summaryrefslogtreecommitdiff
path: root/drivers/i3c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/i3c')
-rw-r--r--drivers/i3c/master/ast2600-i3c-master.c21
1 files changed, 21 insertions, 0 deletions
diff --git a/drivers/i3c/master/ast2600-i3c-master.c b/drivers/i3c/master/ast2600-i3c-master.c
index b3f0fe1e63c3..6715d1f044b6 100644
--- a/drivers/i3c/master/ast2600-i3c-master.c
+++ b/drivers/i3c/master/ast2600-i3c-master.c
@@ -36,6 +36,8 @@
#define AST2600_DEFAULT_SDA_PULLUP_OHMS 2000
+#define DEV_ADDR_TABLE_IBI_PEC BIT(11)
+
struct ast2600_i3c {
struct dw_i3c_master dw;
struct regmap *global_regs;
@@ -99,8 +101,26 @@ static int ast2600_i3c_init(struct dw_i3c_master *dw)
return rc;
}
+static void ast2600_i3c_set_dat_ibi(struct dw_i3c_master *i3c,
+ struct i3c_dev_desc *dev,
+ bool enable, u32 *dat)
+{
+ /*
+ * The ast2600 i3c controller will lock up on receiving 4n+1-byte IBIs
+ * if the PEC is disabled. We have no way to restrict the length of
+ * IBIs sent to the controller, so we need to unconditionally enable
+ * PEC checking, which means we drop a byte of payload data
+ */
+ if (enable && dev->info.bcr & I3C_BCR_IBI_PAYLOAD) {
+ dev_warn_once(&i3c->base.dev,
+ "Enabling PEC workaround. IBI payloads will be truncated\n");
+ *dat |= DEV_ADDR_TABLE_IBI_PEC;
+ }
+}
+
const struct dw_i3c_platform_ops ast2600_i3c_ops = {
.init = ast2600_i3c_init,
+ .set_dat_ibi = ast2600_i3c_set_dat_ibi,
};
static int ast2600_i3c_probe(struct platform_device *pdev)
@@ -137,6 +157,7 @@ static int ast2600_i3c_probe(struct platform_device *pdev)
i3c->sda_pullup);
i3c->dw.platform_ops = &ast2600_i3c_ops;
+ i3c->dw.ibi_capable = true;
return dw_i3c_common_probe(&i3c->dw, pdev);
}