diff options
| author | Dinesh Maniyam <[email protected]> | 2025-08-06 12:32:31 +0800 |
|---|---|---|
| committer | Heiko Schocher <[email protected]> | 2025-08-06 08:41:14 +0200 |
| commit | 82cc368cd2b3bc8664d7e12f4f87af49c1783237 (patch) | |
| tree | af7b293fb3d58177222a18076d2fcb8f25a971f6 /drivers/i3c | |
| parent | b5cf7cd1749f13a270e864d9ccd8960e4988941a (diff) | |
i3c: master: dw-i3c-master: Fix OD_TIMING for spike filter
Fix the I3C device with spike filter unable to detect issue by setting
tHIGH_INIT to 200ns for first broadcast address.
This is according to MIPI SPEC 1.1.1 for first broadcast address
which is already part of linux upstreamed patch.
Signed-off-by: Dinesh Maniyam <[email protected]>
Diffstat (limited to 'drivers/i3c')
| -rw-r--r-- | drivers/i3c/master/dw-i3c-master.c | 23 |
1 files changed, 23 insertions, 0 deletions
diff --git a/drivers/i3c/master/dw-i3c-master.c b/drivers/i3c/master/dw-i3c-master.c index 8b3d5531a7f..6d3d2ab5e71 100644 --- a/drivers/i3c/master/dw-i3c-master.c +++ b/drivers/i3c/master/dw-i3c-master.c @@ -334,6 +334,14 @@ static int dw_i3c_clk_cfg(struct dw_i3c_master *master) if (hcnt < SCL_I3C_TIMING_CNT_MIN) hcnt = SCL_I3C_TIMING_CNT_MIN; + /* set back to THIGH_MAX_NS, after disable spike filter */ + if (!master->first_broadcast) { + lcnt = SCL_I3C_TIMING_LCNT(readl(master->regs + SCL_I3C_OD_TIMING)); + scl_timing = SCL_I3C_TIMING_HCNT(hcnt) | lcnt; + writel(scl_timing, master->regs + SCL_I3C_OD_TIMING); + return 0; + } + lcnt = DIV_ROUND_UP(core_rate, master->base.bus.scl_rate.i3c) - hcnt; if (lcnt < SCL_I3C_TIMING_CNT_MIN) lcnt = SCL_I3C_TIMING_CNT_MIN; @@ -351,6 +359,9 @@ static int dw_i3c_clk_cfg(struct dw_i3c_master *master) lcnt = max_t(u8, DIV_ROUND_UP(I3C_BUS_TLOW_OD_MIN_NS, core_period), lcnt); + /* first broadcast thigh to 200ns, to disable spike filter */ + hcnt = DIV_ROUND_UP(I3C_BUS_THIGH_INIT_OD_MIN_NS, core_period); + scl_timing = SCL_I3C_TIMING_HCNT(hcnt) | SCL_I3C_TIMING_LCNT(lcnt); writel(scl_timing, master->regs + SCL_I3C_OD_TIMING); @@ -406,6 +417,9 @@ static int dw_i3c_master_bus_init(struct i3c_master_controller *m) u32 thld_ctrl; int ret; + /* first broadcast to disable spike filter */ + master->first_broadcast = true; + switch (bus->mode) { case I3C_BUS_MODE_MIXED_FAST: case I3C_BUS_MODE_MIXED_LIMITED: @@ -485,6 +499,15 @@ static void dw_i3c_master_irq_handler(struct dw_i3c_master *master) if (status & INTR_TRANSFER_ERR_STAT) writel(INTR_TRANSFER_ERR_STAT, master->regs + INTR_STATUS); + /* set back to THIGH_MAX_NS, after disable spike filter */ + if (master->first_broadcast) { + master->first_broadcast = false; + int ret = dw_i3c_clk_cfg(master); + + if (ret) + pr_err("Failed to set clk cfg\n"); + } + spin_unlock(&master->xferqueue.lock); } |
