summaryrefslogtreecommitdiff
path: root/drivers/i3c
diff options
context:
space:
mode:
authorJeremy Kerr <jk@codeconstruct.com.au>2023-03-30 10:50:36 +0300
committerAlexandre Belloni <alexandre.belloni@bootlin.com>2023-04-28 09:49:50 +0300
commitf2539c20791eb474ae083f60a572f207ffbc3a67 (patch)
tree45363ac6ff022476bfe5cf886b264afca932bf02 /drivers/i3c
parentf3a3553a51e64379dbb2e980f0024f7a28b74977 (diff)
downloadlinux-f2539c20791eb474ae083f60a572f207ffbc3a67.tar.xz
i3c: ast2600: enable IBI support
The ast2600 i3c hardware is capable of IBIs, but we need a workaround for a hardware issue with the I3C state machine handling IBI payloads of specific lengths when PEC is not enabled. To avoid this, we need to unconditionally enable PECs, at the consquence of losing a byte of data when the device does not send a PEC. Enable IBIs on the ast2600 platform, including an implementation of the PEC workaround, which prints a warning when triggered. Signed-off-by: Jeremy Kerr <jk@codeconstruct.com.au> Reviewed-by: Joel Stanley <joel@jms.id.au> Link: https://lore.kernel.org/r/ba923b96d6d129024c975e8a0472c5b2fcb3af32.1680161823.git.jk@codeconstruct.com.au Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
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);
}