diff options
Diffstat (limited to 'drivers/i3c/master/svc-i3c-master.c')
-rw-r--r-- | drivers/i3c/master/svc-i3c-master.c | 594 |
1 files changed, 436 insertions, 158 deletions
diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c index 5ee4db68988e..7e1a7cb94b43 100644 --- a/drivers/i3c/master/svc-i3c-master.c +++ b/drivers/i3c/master/svc-i3c-master.c @@ -32,6 +32,7 @@ #define SVC_I3C_MCONFIG_ODBAUD(x) FIELD_PREP(GENMASK(23, 16), (x)) #define SVC_I3C_MCONFIG_ODHPP(x) FIELD_PREP(BIT(24), (x)) #define SVC_I3C_MCONFIG_SKEW(x) FIELD_PREP(GENMASK(27, 25), (x)) +#define SVC_I3C_MCONFIG_SKEW_MASK GENMASK(27, 25) #define SVC_I3C_MCONFIG_I2CBAUD(x) FIELD_PREP(GENMASK(31, 28), (x)) #define SVC_I3C_MCTRL 0x084 @@ -58,6 +59,7 @@ #define SVC_I3C_MSTATUS 0x088 #define SVC_I3C_MSTATUS_STATE(x) FIELD_GET(GENMASK(2, 0), (x)) #define SVC_I3C_MSTATUS_STATE_DAA(x) (SVC_I3C_MSTATUS_STATE(x) == 5) +#define SVC_I3C_MSTATUS_STATE_SLVREQ(x) (SVC_I3C_MSTATUS_STATE(x) == 1) #define SVC_I3C_MSTATUS_STATE_IDLE(x) (SVC_I3C_MSTATUS_STATE(x) == 0) #define SVC_I3C_MSTATUS_BETWEEN(x) FIELD_GET(BIT(4), (x)) #define SVC_I3C_MSTATUS_NACKED(x) FIELD_GET(BIT(5), (x)) @@ -113,6 +115,7 @@ #define SVC_I3C_MWDATAHE 0x0BC #define SVC_I3C_MRDATAB 0x0C0 #define SVC_I3C_MRDATAH 0x0C8 +#define SVC_I3C_MWDATAB1 0x0CC #define SVC_I3C_MWMSG_SDR 0x0D0 #define SVC_I3C_MRMSG_SDR 0x0D4 #define SVC_I3C_MWMSG_DDR 0x0D8 @@ -127,9 +130,37 @@ /* This parameter depends on the implementation and may be tuned */ #define SVC_I3C_FIFO_SIZE 16 +#define SVC_I3C_PPBAUD_MAX 15 +#define SVC_I3C_QUICK_I2C_CLK 4170000 -#define SVC_I3C_EVENT_IBI BIT(0) -#define SVC_I3C_EVENT_HOTJOIN BIT(1) +#define SVC_I3C_EVENT_IBI GENMASK(7, 0) +#define SVC_I3C_EVENT_HOTJOIN BIT(31) + +/* + * SVC_I3C_QUIRK_FIFO_EMPTY: + * I3C HW stalls the write transfer if the transmit FIFO becomes empty, + * when new data is written to FIFO, I3C HW resumes the transfer but + * the first transmitted data bit may have the wrong value. + * Workaround: + * Fill the FIFO in advance to prevent FIFO from becoming empty. + */ +#define SVC_I3C_QUIRK_FIFO_EMPTY BIT(0) +/* + * SVC_I3C_QUIRK_FLASE_SLVSTART: + * I3C HW may generate an invalid SlvStart event when emitting a STOP. + * If it is a true SlvStart, the MSTATUS state is SLVREQ. + */ +#define SVC_I3C_QUIRK_FALSE_SLVSTART BIT(1) +/* + * SVC_I3C_QUIRK_DAA_CORRUPT: + * When MCONFIG.SKEW=0 and MCONFIG.ODHPP=0, the ENTDAA transaction gets + * corrupted and results in a no repeated-start condition at the end of + * address assignment. + * Workaround: + * Set MCONFIG.SKEW to 1 before initiating the DAA process. After the DAA + * process is completed, return MCONFIG.SKEW to its previous value. + */ +#define SVC_I3C_QUIRK_DAA_CORRUPT BIT(2) struct svc_i3c_cmd { u8 addr; @@ -156,6 +187,10 @@ struct svc_i3c_regs_save { u32 mdynaddr; }; +struct svc_i3c_drvdata { + u32 quirks; +}; + /** * struct svc_i3c_master - Silvaco I3C Master structure * @base: I3C master controller @@ -166,11 +201,10 @@ struct svc_i3c_regs_save { * @addrs: Array containing the dynamic addresses of each attached device * @descs: Array of descriptors, one per attached device * @hj_work: Hot-join work - * @ibi_work: IBI work * @irq: Main interrupt - * @pclk: System clock + * @num_clks: I3C clock number * @fclk: Fast clock (bus) - * @sclk: Slow clock (other events) + * @clks: I3C clock array * @xferqueue: Transfer queue structure * @xferqueue.list: List member * @xferqueue.cur: Current ongoing transfer @@ -181,7 +215,9 @@ struct svc_i3c_regs_save { * @ibi.tbq_slot: To be queued IBI slot * @ibi.lock: IBI lock * @lock: Transfer lock, protect between IBI work thread and callbacks from master + * @drvdata: Driver data * @enabled_events: Bit masks for enable events (IBI, HotJoin). + * @mctrl_config: Configuration value in SVC_I3C_MCTRL for setting speed back. */ struct svc_i3c_master { struct i3c_master_controller base; @@ -192,11 +228,10 @@ struct svc_i3c_master { u8 addrs[SVC_I3C_MAX_DEVS]; struct i3c_dev_desc *descs[SVC_I3C_MAX_DEVS]; struct work_struct hj_work; - struct work_struct ibi_work; int irq; - struct clk *pclk; + int num_clks; struct clk *fclk; - struct clk *sclk; + struct clk_bulk_data *clks; struct { struct list_head list; struct svc_i3c_xfer *cur; @@ -211,7 +246,9 @@ struct svc_i3c_master { spinlock_t lock; } ibi; struct mutex lock; - int enabled_events; + const struct svc_i3c_drvdata *drvdata; + u32 enabled_events; + u32 mctrl_config; }; /** @@ -226,6 +263,18 @@ struct svc_i3c_i2c_dev_data { struct i3c_generic_ibi_pool *ibi_pool; }; +static inline bool svc_has_quirk(struct svc_i3c_master *master, u32 quirk) +{ + return (master->drvdata->quirks & quirk); +} + +static inline bool svc_has_daa_corrupt(struct svc_i3c_master *master) +{ + return ((master->drvdata->quirks & SVC_I3C_QUIRK_DAA_CORRUPT) && + !(master->mctrl_config & + (SVC_I3C_MCONFIG_SKEW_MASK | SVC_I3C_MCONFIG_ODHPP(1)))); +} + static inline bool is_events_enabled(struct svc_i3c_master *master, u32 mask) { return !!(master->enabled_events & mask); @@ -374,7 +423,7 @@ static int svc_i3c_master_handle_ibi(struct svc_i3c_master *master, slot->len < SVC_I3C_FIFO_SIZE) { mdatactrl = readl(master->regs + SVC_I3C_MDATACTRL); count = SVC_I3C_MDATACTRL_RXCOUNT(mdatactrl); - readsl(master->regs + SVC_I3C_MRDATAB, buf, count); + readsb(master->regs + SVC_I3C_MRDATAB, buf, count); slot->len += count; buf += count; } @@ -384,10 +433,11 @@ static int svc_i3c_master_handle_ibi(struct svc_i3c_master *master, return 0; } -static void svc_i3c_master_ack_ibi(struct svc_i3c_master *master, +static int svc_i3c_master_ack_ibi(struct svc_i3c_master *master, bool mandatory_byte) { unsigned int ibi_ack_nack; + u32 reg; ibi_ack_nack = SVC_I3C_MCTRL_REQUEST_IBI_ACKNACK; if (mandatory_byte) @@ -396,42 +446,90 @@ static void svc_i3c_master_ack_ibi(struct svc_i3c_master *master, ibi_ack_nack |= SVC_I3C_MCTRL_IBIRESP_ACK_WITHOUT_BYTE; writel(ibi_ack_nack, master->regs + SVC_I3C_MCTRL); + + return readl_poll_timeout_atomic(master->regs + SVC_I3C_MSTATUS, reg, + SVC_I3C_MSTATUS_MCTRLDONE(reg), 1, 1000); + } -static void svc_i3c_master_nack_ibi(struct svc_i3c_master *master) +static int svc_i3c_master_nack_ibi(struct svc_i3c_master *master) { + int ret; + u32 reg; + writel(SVC_I3C_MCTRL_REQUEST_IBI_ACKNACK | SVC_I3C_MCTRL_IBIRESP_NACK, master->regs + SVC_I3C_MCTRL); + + ret = readl_poll_timeout_atomic(master->regs + SVC_I3C_MSTATUS, reg, + SVC_I3C_MSTATUS_MCTRLDONE(reg), 1, 1000); + return ret; +} + +static int svc_i3c_master_handle_ibi_won(struct svc_i3c_master *master, u32 mstatus) +{ + u32 ibitype; + int ret = 0; + + ibitype = SVC_I3C_MSTATUS_IBITYPE(mstatus); + + writel(SVC_I3C_MINT_IBIWON, master->regs + SVC_I3C_MSTATUS); + + /* Hardware can't auto emit NACK for hot join and master request */ + switch (ibitype) { + case SVC_I3C_MSTATUS_IBITYPE_HOT_JOIN: + case SVC_I3C_MSTATUS_IBITYPE_MASTER_REQUEST: + ret = svc_i3c_master_nack_ibi(master); + } + + return ret; } -static void svc_i3c_master_ibi_work(struct work_struct *work) +static void svc_i3c_master_ibi_isr(struct svc_i3c_master *master) { - struct svc_i3c_master *master = container_of(work, struct svc_i3c_master, ibi_work); struct svc_i3c_i2c_dev_data *data; unsigned int ibitype, ibiaddr; struct i3c_dev_desc *dev; u32 status, val; int ret; - mutex_lock(&master->lock); + /* + * According to I3C spec ver 1.1, 09-Jun-2021, section 5.1.2.5: + * + * The I3C Controller shall hold SCL low while the Bus is in ACK/NACK Phase of I3C/I2C + * transfer. But maximum stall time is 100us. The IRQs have to be disabled to prevent + * schedule during the whole I3C transaction, otherwise, the I3C bus timeout may happen if + * any irq or schedule happen during transaction. + */ + guard(spinlock)(&master->xferqueue.lock); + + /* + * IBIWON may be set before SVC_I3C_MCTRL_REQUEST_AUTO_IBI, causing + * readl_relaxed_poll_timeout() to return immediately. Consequently, + * ibitype will be 0 since it was last updated only after the 8th SCL + * cycle, leading to missed client IBI handlers. + * + * A typical scenario is when IBIWON occurs and bus arbitration is lost + * at svc_i3c_master_priv_xfers(). + * + * Clear SVC_I3C_MINT_IBIWON before sending SVC_I3C_MCTRL_REQUEST_AUTO_IBI. + */ + writel(SVC_I3C_MINT_IBIWON, master->regs + SVC_I3C_MSTATUS); + /* Acknowledge the incoming interrupt with the AUTOIBI mechanism */ writel(SVC_I3C_MCTRL_REQUEST_AUTO_IBI | SVC_I3C_MCTRL_IBIRESP_AUTO, master->regs + SVC_I3C_MCTRL); /* Wait for IBIWON, should take approximately 100us */ - ret = readl_relaxed_poll_timeout(master->regs + SVC_I3C_MSTATUS, val, - SVC_I3C_MSTATUS_IBIWON(val), 0, 1000); + ret = readl_relaxed_poll_timeout_atomic(master->regs + SVC_I3C_MSTATUS, val, + SVC_I3C_MSTATUS_IBIWON(val), 0, 100); if (ret) { dev_err(master->dev, "Timeout when polling for IBIWON\n"); svc_i3c_master_emit_stop(master); - goto reenable_ibis; + return; } - /* Clear the interrupt status */ - writel(SVC_I3C_MINT_IBIWON, master->regs + SVC_I3C_MSTATUS); - status = readl(master->regs + SVC_I3C_MSTATUS); ibitype = SVC_I3C_MSTATUS_IBITYPE(status); ibiaddr = SVC_I3C_MSTATUS_IBIADDR(status); @@ -473,17 +571,17 @@ static void svc_i3c_master_ibi_work(struct work_struct *work) svc_i3c_master_emit_stop(master); - goto reenable_ibis; + return; } /* Handle the non critical tasks */ switch (ibitype) { case SVC_I3C_MSTATUS_IBITYPE_IBI: + svc_i3c_master_emit_stop(master); if (dev) { i3c_master_queue_ibi(dev, master->ibi.tbq_slot); master->ibi.tbq_slot = NULL; } - svc_i3c_master_emit_stop(master); break; case SVC_I3C_MSTATUS_IBITYPE_HOT_JOIN: svc_i3c_master_emit_stop(master); @@ -491,13 +589,11 @@ static void svc_i3c_master_ibi_work(struct work_struct *work) queue_work(master->base.wq, &master->hj_work); break; case SVC_I3C_MSTATUS_IBITYPE_MASTER_REQUEST: + svc_i3c_master_emit_stop(master); + break; default: break; } - -reenable_ibis: - svc_i3c_master_enable_interrupts(master, SVC_I3C_MINT_SLVSTART); - mutex_unlock(&master->lock); } static irqreturn_t svc_i3c_master_irq_handler(int irq, void *dev_id) @@ -511,20 +607,76 @@ static irqreturn_t svc_i3c_master_irq_handler(int irq, void *dev_id) /* Clear the interrupt status */ writel(SVC_I3C_MINT_SLVSTART, master->regs + SVC_I3C_MSTATUS); - svc_i3c_master_disable_interrupts(master); + /* Ignore the false event */ + if (svc_has_quirk(master, SVC_I3C_QUIRK_FALSE_SLVSTART) && + !SVC_I3C_MSTATUS_STATE_SLVREQ(active)) + return IRQ_HANDLED; - /* Handle the interrupt in a non atomic context */ - queue_work(master->base.wq, &master->ibi_work); + /* + * The SDA line remains low until the request is processed. + * Receive the request in the interrupt context to respond promptly + * and restore the bus to idle state. + */ + svc_i3c_master_ibi_isr(master); return IRQ_HANDLED; } +static int svc_i3c_master_set_speed(struct i3c_master_controller *m, + enum i3c_open_drain_speed speed) +{ + struct svc_i3c_master *master = to_svc_i3c_master(m); + struct i3c_bus *bus = i3c_master_get_bus(&master->base); + u32 ppbaud, odbaud, odhpp, mconfig; + unsigned long fclk_rate; + int ret; + + ret = pm_runtime_resume_and_get(master->dev); + if (ret < 0) { + dev_err(master->dev, "<%s> Cannot get runtime PM.\n", __func__); + return ret; + } + + switch (speed) { + case I3C_OPEN_DRAIN_SLOW_SPEED: + fclk_rate = clk_get_rate(master->fclk); + if (!fclk_rate) { + ret = -EINVAL; + goto rpm_out; + } + /* + * Set 50% duty-cycle I2C speed to I3C OPEN-DRAIN mode, so the first + * broadcast address is visible to all I2C/I3C devices on the I3C bus. + * I3C device working as a I2C device will turn off its 50ns Spike + * Filter to change to I3C mode. + */ + mconfig = master->mctrl_config; + ppbaud = FIELD_GET(GENMASK(11, 8), mconfig); + odhpp = 0; + odbaud = DIV_ROUND_UP(fclk_rate, bus->scl_rate.i2c * (2 + 2 * ppbaud)) - 1; + mconfig &= ~GENMASK(24, 16); + mconfig |= SVC_I3C_MCONFIG_ODBAUD(odbaud) | SVC_I3C_MCONFIG_ODHPP(odhpp); + writel(mconfig, master->regs + SVC_I3C_MCONFIG); + break; + case I3C_OPEN_DRAIN_NORMAL_SPEED: + writel(master->mctrl_config, master->regs + SVC_I3C_MCONFIG); + break; + } + +rpm_out: + pm_runtime_mark_last_busy(master->dev); + pm_runtime_put_autosuspend(master->dev); + + return ret; +} + static int svc_i3c_master_bus_init(struct i3c_master_controller *m) { struct svc_i3c_master *master = to_svc_i3c_master(m); struct i3c_bus *bus = i3c_master_get_bus(m); struct i3c_device_info info = {}; unsigned long fclk_rate, fclk_period_ns; + unsigned long i2c_period_ns, i2c_scl_rate, i3c_scl_rate; unsigned int high_period_ns, od_low_period_ns; u32 ppbaud, pplow, odhpp, odbaud, odstop, i2cbaud, reg; int ret; @@ -545,12 +697,15 @@ static int svc_i3c_master_bus_init(struct i3c_master_controller *m) } fclk_period_ns = DIV_ROUND_UP(1000000000, fclk_rate); + i2c_period_ns = DIV_ROUND_UP(1000000000, bus->scl_rate.i2c); + i2c_scl_rate = bus->scl_rate.i2c; + i3c_scl_rate = bus->scl_rate.i3c; /* * Using I3C Push-Pull mode, target is 12.5MHz/80ns period. * Simplest configuration is using a 50% duty-cycle of 40ns. */ - ppbaud = DIV_ROUND_UP(40, fclk_period_ns) - 1; + ppbaud = DIV_ROUND_UP(fclk_rate / 2, i3c_scl_rate) - 1; pplow = 0; /* @@ -560,7 +715,7 @@ static int svc_i3c_master_bus_init(struct i3c_master_controller *m) */ odhpp = 1; high_period_ns = (ppbaud + 1) * fclk_period_ns; - odbaud = DIV_ROUND_UP(240 - high_period_ns, high_period_ns) - 1; + odbaud = DIV_ROUND_UP(fclk_rate, SVC_I3C_QUICK_I2C_CLK * (1 + ppbaud)) - 2; od_low_period_ns = (odbaud + 1) * high_period_ns; switch (bus->mode) { @@ -569,20 +724,27 @@ static int svc_i3c_master_bus_init(struct i3c_master_controller *m) odstop = 0; break; case I3C_BUS_MODE_MIXED_FAST: - case I3C_BUS_MODE_MIXED_LIMITED: /* * Using I2C Fm+ mode, target is 1MHz/1000ns, the difference * between the high and low period does not really matter. */ - i2cbaud = DIV_ROUND_UP(1000, od_low_period_ns) - 2; + i2cbaud = DIV_ROUND_UP(i2c_period_ns, od_low_period_ns) - 2; odstop = 1; break; + case I3C_BUS_MODE_MIXED_LIMITED: case I3C_BUS_MODE_MIXED_SLOW: - /* - * Using I2C Fm mode, target is 0.4MHz/2500ns, with the same - * constraints as the FM+ mode. - */ - i2cbaud = DIV_ROUND_UP(2500, od_low_period_ns) - 2; + /* I3C PP + I3C OP + I2C OP both use i2c clk rate */ + if (ppbaud > SVC_I3C_PPBAUD_MAX) { + ppbaud = SVC_I3C_PPBAUD_MAX; + pplow = DIV_ROUND_UP(fclk_rate, i3c_scl_rate) - (2 + 2 * ppbaud); + } + + high_period_ns = (ppbaud + 1) * fclk_period_ns; + odhpp = 0; + odbaud = DIV_ROUND_UP(fclk_rate, i2c_scl_rate * (2 + 2 * ppbaud)) - 1; + + od_low_period_ns = (odbaud + 1) * high_period_ns; + i2cbaud = DIV_ROUND_UP(i2c_period_ns, od_low_period_ns) - 2; odstop = 1; break; default: @@ -601,6 +763,7 @@ static int svc_i3c_master_bus_init(struct i3c_master_controller *m) SVC_I3C_MCONFIG_I2CBAUD(i2cbaud); writel(reg, master->regs + SVC_I3C_MCONFIG); + master->mctrl_config = reg; /* Master core's registration */ ret = i3c_master_get_free_addr(m, 0); if (ret < 0) @@ -775,12 +938,30 @@ static int svc_i3c_master_do_daa_locked(struct svc_i3c_master *master, u8 *addrs, unsigned int *count) { u64 prov_id[SVC_I3C_MAX_DEVS] = {}, nacking_prov_id = 0; - unsigned int dev_nb = 0, last_addr = 0; + unsigned int dev_nb = 0, last_addr = 0, dyn_addr = 0; u32 reg; int ret, i; + svc_i3c_master_flush_fifo(master); + while (true) { - /* Enter/proceed with DAA */ + /* clean SVC_I3C_MINT_IBIWON w1c bits */ + writel(SVC_I3C_MINT_IBIWON, master->regs + SVC_I3C_MSTATUS); + + /* SVC_I3C_MCTRL_REQUEST_PROC_DAA have two mode, ENTER DAA or PROCESS DAA. + * + * ENTER DAA: + * 1 will issue START, 7E, ENTDAA, and then emits 7E/R to process first target. + * 2 Stops just before the new Dynamic Address (DA) is to be emitted. + * + * PROCESS DAA: + * 1 The DA is written using MWDATAB or ADDR bits 6:0. + * 2 ProcessDAA is requested again to write the new address, and then starts the + * next (START, 7E, ENTDAA) unless marked to STOP; an MSTATUS indicating NACK + * means DA was not accepted (e.g. parity error). If PROCESSDAA is NACKed on the + * 7E/R, which means no more Slaves need a DA, then a COMPLETE will be signaled + * (along with DONE), and a STOP issued automatically. + */ writel(SVC_I3C_MCTRL_REQUEST_PROC_DAA | SVC_I3C_MCTRL_TYPE_I3C | SVC_I3C_MCTRL_IBIRESP_NACK | @@ -797,19 +978,39 @@ static int svc_i3c_master_do_daa_locked(struct svc_i3c_master *master, SVC_I3C_MSTATUS_MCTRLDONE(reg), 1, 1000); if (ret) - return ret; + break; if (SVC_I3C_MSTATUS_RXPEND(reg)) { u8 data[6]; /* + * One slave sends its ID to request for address assignment, + * prefilling the dynamic address can reduce SCL clock stalls + * and also fix the SVC_I3C_QUIRK_FIFO_EMPTY quirk. + * + * Ideally, prefilling before the processDAA command is better. + * However, it requires an additional check to write the dyn_addr + * at the right time because the driver needs to write the processDAA + * command twice for one assignment. + * Prefilling here is safe and efficient because the FIFO starts + * filling within a few hundred nanoseconds, which is significantly + * faster compared to the 64 SCL clock cycles. + */ + ret = i3c_master_get_free_addr(&master->base, last_addr + 1); + if (ret < 0) + break; + + dyn_addr = ret; + writel(dyn_addr, master->regs + SVC_I3C_MWDATAB); + + /* * We only care about the 48-bit provisioned ID yet to * be sure a device does not nack an address twice. * Otherwise, we would just need to flush the RX FIFO. */ ret = svc_i3c_master_readb(master, data, 6); if (ret) - return ret; + break; for (i = 0; i < 6; i++) prov_id[dev_nb] |= (u64)(data[i]) << (8 * (5 - i)); @@ -817,7 +1018,12 @@ static int svc_i3c_master_do_daa_locked(struct svc_i3c_master *master, /* We do not care about the BCR and DCR yet */ ret = svc_i3c_master_readb(master, data, 2); if (ret) - return ret; + break; + } else if (SVC_I3C_MSTATUS_IBIWON(reg)) { + ret = svc_i3c_master_handle_ibi_won(master, reg); + if (ret) + break; + continue; } else if (SVC_I3C_MSTATUS_MCTRLDONE(reg)) { if (SVC_I3C_MSTATUS_STATE_IDLE(reg) && SVC_I3C_MSTATUS_COMPLETE(reg)) { @@ -825,12 +1031,23 @@ static int svc_i3c_master_do_daa_locked(struct svc_i3c_master *master, * All devices received and acked they dynamic * address, this is the natural end of the DAA * procedure. + * + * Hardware will auto emit STOP at this case. */ - break; + *count = dev_nb; + return 0; + } else if (SVC_I3C_MSTATUS_NACKED(reg)) { /* No I3C devices attached */ - if (dev_nb == 0) + if (dev_nb == 0) { + /* + * Hardware can't treat first NACK for ENTAA as normal + * COMPLETE. So need manual emit STOP. + */ + ret = 0; + *count = 0; break; + } /* * A slave device nacked the address, this is @@ -839,8 +1056,10 @@ static int svc_i3c_master_do_daa_locked(struct svc_i3c_master *master, * answer again immediately and shall ack the * address this time. */ - if (prov_id[dev_nb] == nacking_prov_id) - return -EIO; + if (prov_id[dev_nb] == nacking_prov_id) { + ret = -EIO; + break; + } dev_nb--; nacking_prov_id = prov_id[dev_nb]; @@ -848,7 +1067,7 @@ static int svc_i3c_master_do_daa_locked(struct svc_i3c_master *master, continue; } else { - return -EIO; + break; } } @@ -860,24 +1079,19 @@ static int svc_i3c_master_do_daa_locked(struct svc_i3c_master *master, SVC_I3C_MSTATUS_BETWEEN(reg), 0, 1000); if (ret) - return ret; - - /* Give the slave device a suitable dynamic address */ - ret = i3c_master_get_free_addr(&master->base, last_addr + 1); - if (ret < 0) - return ret; + break; - addrs[dev_nb] = ret; + addrs[dev_nb] = dyn_addr; dev_dbg(master->dev, "DAA: device %d assigned to 0x%02x\n", dev_nb, addrs[dev_nb]); - - writel(addrs[dev_nb], master->regs + SVC_I3C_MWDATAB); last_addr = addrs[dev_nb++]; } - *count = dev_nb; + /* Need manual issue STOP except for Complete condition */ + svc_i3c_master_emit_stop(master); + svc_i3c_master_flush_fifo(master); - return 0; + return ret; } static int svc_i3c_update_ibirules(struct svc_i3c_master *master) @@ -890,7 +1104,7 @@ static int svc_i3c_update_ibirules(struct svc_i3c_master *master) /* Create the IBIRULES register for both cases */ i3c_bus_for_each_i3cdev(&master->base.bus, dev) { - if (I3C_BCR_DEVICE_ROLE(dev->info.bcr) == I3C_BCR_I3C_MASTER) + if (!(dev->info.bcr & I3C_BCR_IBI_REQ_CAP)) continue; if (dev->info.bcr & I3C_BCR_IBI_PAYLOAD) { @@ -949,20 +1163,43 @@ static int svc_i3c_master_do_daa(struct i3c_master_controller *m) } spin_lock_irqsave(&master->xferqueue.lock, flags); + + if (svc_has_daa_corrupt(master)) + writel(master->mctrl_config | SVC_I3C_MCONFIG_SKEW(1), + master->regs + SVC_I3C_MCONFIG); + ret = svc_i3c_master_do_daa_locked(master, addrs, &dev_nb); + + if (svc_has_daa_corrupt(master)) + writel(master->mctrl_config, master->regs + SVC_I3C_MCONFIG); + spin_unlock_irqrestore(&master->xferqueue.lock, flags); - if (ret) { - svc_i3c_master_emit_stop(master); - svc_i3c_master_clear_merrwarn(master); + + svc_i3c_master_clear_merrwarn(master); + if (ret) goto rpm_out; - } - /* Register all devices who participated to the core */ - for (i = 0; i < dev_nb; i++) { - ret = i3c_master_add_i3c_dev_locked(m, addrs[i]); - if (ret) - goto rpm_out; - } + /* + * Register all devices who participated to the core + * + * If two devices (A and B) are detected in DAA and address 0xa is assigned to + * device A and 0xb to device B, a failure in i3c_master_add_i3c_dev_locked() + * for device A (addr: 0xa) could prevent device B (addr: 0xb) from being + * registered on the bus. The I3C stack might still consider 0xb a free + * address. If a subsequent Hotjoin occurs, 0xb might be assigned to Device A, + * causing both devices A and B to use the same address 0xb, violating the I3C + * specification. + * + * The return value for i3c_master_add_i3c_dev_locked() should not be checked + * because subsequent steps will scan the entire I3C bus, independent of + * whether i3c_master_add_i3c_dev_locked() returns success. + * + * If device A registration fails, there is still a chance to register device + * B. i3c_master_add_i3c_dev_locked() can reset DAA if a failure occurs while + * retrieving device information. + */ + for (i = 0; i < dev_nb; i++) + i3c_master_add_i3c_dev_locked(m, addrs[i]); /* Configure IBI auto-rules */ ret = svc_i3c_update_ibirules(master); @@ -1040,49 +1277,99 @@ static int svc_i3c_master_write(struct svc_i3c_master *master, static int svc_i3c_master_xfer(struct svc_i3c_master *master, bool rnw, unsigned int xfer_type, u8 addr, u8 *in, const u8 *out, unsigned int xfer_len, - unsigned int *actual_len, bool continued) + unsigned int *actual_len, bool continued, bool repeat_start) { + int retry = repeat_start ? 1 : 2; u32 reg; int ret; /* clean SVC_I3C_MINT_IBIWON w1c bits */ writel(SVC_I3C_MINT_IBIWON, master->regs + SVC_I3C_MSTATUS); - writel(SVC_I3C_MCTRL_REQUEST_START_ADDR | - xfer_type | - SVC_I3C_MCTRL_IBIRESP_NACK | - SVC_I3C_MCTRL_DIR(rnw) | - SVC_I3C_MCTRL_ADDR(addr) | - SVC_I3C_MCTRL_RDTERM(*actual_len), - master->regs + SVC_I3C_MCTRL); - ret = readl_poll_timeout(master->regs + SVC_I3C_MSTATUS, reg, + while (retry--) { + writel(SVC_I3C_MCTRL_REQUEST_START_ADDR | + xfer_type | + SVC_I3C_MCTRL_IBIRESP_NACK | + SVC_I3C_MCTRL_DIR(rnw) | + SVC_I3C_MCTRL_ADDR(addr) | + SVC_I3C_MCTRL_RDTERM(*actual_len), + master->regs + SVC_I3C_MCTRL); + + /* + * The entire transaction can consist of multiple write transfers. + * Prefilling before EmitStartAddr causes the data to be emitted + * immediately, becoming part of the previous transfer. + * The only way to work around this hardware issue is to let the + * FIFO start filling as soon as possible after EmitStartAddr. + */ + if (svc_has_quirk(master, SVC_I3C_QUIRK_FIFO_EMPTY) && !rnw && xfer_len) { + u32 end = xfer_len > SVC_I3C_FIFO_SIZE ? 0 : SVC_I3C_MWDATAB_END; + u32 len = min_t(u32, xfer_len, SVC_I3C_FIFO_SIZE); + + writesb(master->regs + SVC_I3C_MWDATAB1, out, len - 1); + /* Mark END bit if this is the last byte */ + writel(out[len - 1] | end, master->regs + SVC_I3C_MWDATAB); + xfer_len -= len; + out += len; + } + + ret = readl_poll_timeout(master->regs + SVC_I3C_MSTATUS, reg, SVC_I3C_MSTATUS_MCTRLDONE(reg), 0, 1000); - if (ret) - goto emit_stop; + if (ret) + goto emit_stop; - if (readl(master->regs + SVC_I3C_MERRWARN) & SVC_I3C_MERRWARN_NACK) { - ret = -ENXIO; - *actual_len = 0; - goto emit_stop; - } + /* + * According to I3C spec ver 1.1.1, 5.1.2.2.3 Consequence of Controller Starting a + * Frame with I3C Target Address. + * + * The I3C Controller normally should start a Frame, the Address may be arbitrated, + * and so the Controller shall monitor to see whether an In-Band Interrupt request, + * a Controller Role Request (i.e., Secondary Controller requests to become the + * Active Controller), or a Hot-Join Request has been made. + * + * If missed IBIWON check, the wrong data will be return. When IBIWON happen, issue + * repeat start. Address arbitrate only happen at START, never happen at REPEAT + * start. + */ + if (SVC_I3C_MSTATUS_IBIWON(reg)) { + ret = svc_i3c_master_handle_ibi_won(master, reg); + if (ret) + goto emit_stop; + continue; + } - /* - * According to I3C spec ver 1.1.1, 5.1.2.2.3 Consequence of Controller Starting a Frame - * with I3C Target Address. - * - * The I3C Controller normally should start a Frame, the Address may be arbitrated, and so - * the Controller shall monitor to see whether an In-Band Interrupt request, a Controller - * Role Request (i.e., Secondary Controller requests to become the Active Controller), or - * a Hot-Join Request has been made. - * - * If missed IBIWON check, the wrong data will be return. When IBIWON happen, return failure - * and yield the above events handler. - */ - if (SVC_I3C_MSTATUS_IBIWON(reg)) { - ret = -ENXIO; - *actual_len = 0; - goto emit_stop; + if (readl(master->regs + SVC_I3C_MERRWARN) & SVC_I3C_MERRWARN_NACK) { + /* + * According to I3C Spec 1.1.1, 11-Jun-2021, section: 5.1.2.2.3. + * If the Controller chooses to start an I3C Message with an I3C Dynamic + * Address, then special provisions shall be made because that same I3C + * Target may be initiating an IBI or a Controller Role Request. So, one of + * three things may happen: (skip 1, 2) + * + * 3. The Addresses match and the RnW bits also match, and so neither + * Controller nor Target will ACK since both are expecting the other side to + * provide ACK. As a result, each side might think it had "won" arbitration, + * but neither side would continue, as each would subsequently see that the + * other did not provide ACK. + * ... + * For either value of RnW: Due to the NACK, the Controller shall defer the + * Private Write or Private Read, and should typically transmit the Target + * Address again after a Repeated START (i.e., the next one or any one prior + * to a STOP in the Frame). Since the Address Header following a Repeated + * START is not arbitrated, the Controller will always win (see Section + * 5.1.2.2.4). + */ + if (retry && addr != 0x7e) { + writel(SVC_I3C_MERRWARN_NACK, master->regs + SVC_I3C_MERRWARN); + } else { + ret = -ENXIO; + *actual_len = 0; + goto emit_stop; + } + } else { + break; + } } if (rnw) @@ -1115,6 +1402,7 @@ static int svc_i3c_master_xfer(struct svc_i3c_master *master, emit_stop: svc_i3c_master_emit_stop(master); svc_i3c_master_clear_merrwarn(master); + svc_i3c_master_flush_fifo(master); return ret; } @@ -1176,7 +1464,7 @@ static void svc_i3c_master_start_xfer_locked(struct svc_i3c_master *master) ret = svc_i3c_master_xfer(master, cmd->rnw, xfer->type, cmd->addr, cmd->in, cmd->out, cmd->len, &cmd->actual_len, - cmd->continued); + cmd->continued, i > 0); /* cmd->xfer is NULL if I2C or CCC transfer */ if (cmd->xfer) cmd->xfer->actual_len = cmd->actual_len; @@ -1311,7 +1599,7 @@ static int svc_i3c_master_send_direct_ccc_cmd(struct svc_i3c_master *master, cmd->addr = ccc->dests[0].addr; cmd->rnw = ccc->rnw; cmd->in = ccc->rnw ? ccc->dests[0].payload.data : NULL; - cmd->out = ccc->rnw ? NULL : ccc->dests[0].payload.data, + cmd->out = ccc->rnw ? NULL : ccc->dests[0].payload.data; cmd->len = xfer_len; cmd->actual_len = actual_len; cmd->continued = false; @@ -1391,7 +1679,7 @@ static int svc_i3c_master_priv_xfers(struct i3c_dev_desc *dev, } static int svc_i3c_master_i2c_xfers(struct i2c_dev_desc *dev, - const struct i2c_msg *xfers, + struct i2c_msg *xfers, int nxfers) { struct i3c_master_controller *m = i2c_dev_get_master(dev); @@ -1495,7 +1783,7 @@ static int svc_i3c_master_enable_ibi(struct i3c_dev_desc *dev) return ret; } - master->enabled_events |= SVC_I3C_EVENT_IBI; + master->enabled_events++; svc_i3c_master_enable_interrupts(master, SVC_I3C_MINT_SLVSTART); return i3c_master_enec_locked(m, dev->info.dyn_addr, I3C_CCC_EVENT_SIR); @@ -1507,7 +1795,7 @@ static int svc_i3c_master_disable_ibi(struct i3c_dev_desc *dev) struct svc_i3c_master *master = to_svc_i3c_master(m); int ret; - master->enabled_events &= ~SVC_I3C_EVENT_IBI; + master->enabled_events--; if (!master->enabled_events) svc_i3c_master_disable_interrupts(master); @@ -1580,77 +1868,54 @@ static const struct i3c_master_controller_ops svc_i3c_master_ops = { .disable_ibi = svc_i3c_master_disable_ibi, .enable_hotjoin = svc_i3c_master_enable_hotjoin, .disable_hotjoin = svc_i3c_master_disable_hotjoin, + .set_speed = svc_i3c_master_set_speed, }; -static int svc_i3c_master_prepare_clks(struct svc_i3c_master *master) -{ - int ret = 0; - - ret = clk_prepare_enable(master->pclk); - if (ret) - return ret; - - ret = clk_prepare_enable(master->fclk); - if (ret) { - clk_disable_unprepare(master->pclk); - return ret; - } - - ret = clk_prepare_enable(master->sclk); - if (ret) { - clk_disable_unprepare(master->pclk); - clk_disable_unprepare(master->fclk); - return ret; - } - - return 0; -} - -static void svc_i3c_master_unprepare_clks(struct svc_i3c_master *master) -{ - clk_disable_unprepare(master->pclk); - clk_disable_unprepare(master->fclk); - clk_disable_unprepare(master->sclk); -} - static int svc_i3c_master_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct svc_i3c_master *master; - int ret; + int ret, i; master = devm_kzalloc(dev, sizeof(*master), GFP_KERNEL); if (!master) return -ENOMEM; + master->drvdata = of_device_get_match_data(dev); + if (!master->drvdata) + return -EINVAL; + master->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(master->regs)) return PTR_ERR(master->regs); - master->pclk = devm_clk_get(dev, "pclk"); - if (IS_ERR(master->pclk)) - return PTR_ERR(master->pclk); + master->num_clks = devm_clk_bulk_get_all(dev, &master->clks); + if (master->num_clks < 0) + return dev_err_probe(dev, -EINVAL, "can't get I3C clocks\n"); + + for (i = 0; i < master->num_clks; i++) { + if (!strcmp(master->clks[i].id, "fast_clk")) + break; + } + + if (i == master->num_clks) + return dev_err_probe(dev, -EINVAL, + "can't get I3C peripheral clock\n"); - master->fclk = devm_clk_get(dev, "fast_clk"); + master->fclk = master->clks[i].clk; if (IS_ERR(master->fclk)) return PTR_ERR(master->fclk); - master->sclk = devm_clk_get(dev, "slow_clk"); - if (IS_ERR(master->sclk)) - return PTR_ERR(master->sclk); - master->irq = platform_get_irq(pdev, 0); if (master->irq < 0) return master->irq; master->dev = dev; - - ret = svc_i3c_master_prepare_clks(master); + ret = clk_bulk_prepare_enable(master->num_clks, master->clks); if (ret) - return ret; + return dev_err_probe(dev, ret, "can't enable I3C clocks\n"); INIT_WORK(&master->hj_work, svc_i3c_master_hj_work); - INIT_WORK(&master->ibi_work, svc_i3c_master_ibi_work); mutex_init(&master->lock); ret = devm_request_irq(dev, master->irq, svc_i3c_master_irq_handler, @@ -1697,11 +1962,11 @@ static int svc_i3c_master_probe(struct platform_device *pdev) rpm_disable: pm_runtime_dont_use_autosuspend(&pdev->dev); pm_runtime_put_noidle(&pdev->dev); - pm_runtime_set_suspended(&pdev->dev); pm_runtime_disable(&pdev->dev); + pm_runtime_set_suspended(&pdev->dev); err_disable_clks: - svc_i3c_master_unprepare_clks(master); + clk_bulk_disable_unprepare(master->num_clks, master->clks); return ret; } @@ -1710,6 +1975,7 @@ static void svc_i3c_master_remove(struct platform_device *pdev) { struct svc_i3c_master *master = platform_get_drvdata(pdev); + cancel_work_sync(&master->hj_work); i3c_master_unregister(&master->base); pm_runtime_dont_use_autosuspend(&pdev->dev); @@ -1738,7 +2004,7 @@ static int __maybe_unused svc_i3c_runtime_suspend(struct device *dev) struct svc_i3c_master *master = dev_get_drvdata(dev); svc_i3c_save_regs(master); - svc_i3c_master_unprepare_clks(master); + clk_bulk_disable_unprepare(master->num_clks, master->clks); pinctrl_pm_select_sleep_state(dev); return 0; @@ -1747,9 +2013,12 @@ static int __maybe_unused svc_i3c_runtime_suspend(struct device *dev) static int __maybe_unused svc_i3c_runtime_resume(struct device *dev) { struct svc_i3c_master *master = dev_get_drvdata(dev); + int ret; pinctrl_pm_select_default_state(dev); - svc_i3c_master_prepare_clks(master); + ret = clk_bulk_prepare_enable(master->num_clks, master->clks); + if (ret) + return ret; svc_i3c_restore_regs(master); @@ -1763,15 +2032,24 @@ static const struct dev_pm_ops svc_i3c_pm_ops = { svc_i3c_runtime_resume, NULL) }; +static const struct svc_i3c_drvdata npcm845_drvdata = { + .quirks = SVC_I3C_QUIRK_FIFO_EMPTY | + SVC_I3C_QUIRK_FALSE_SLVSTART | + SVC_I3C_QUIRK_DAA_CORRUPT, +}; + +static const struct svc_i3c_drvdata svc_default_drvdata = {}; + static const struct of_device_id svc_i3c_master_of_match_tbl[] = { - { .compatible = "silvaco,i3c-master-v1"}, + { .compatible = "nuvoton,npcm845-i3c", .data = &npcm845_drvdata }, + { .compatible = "silvaco,i3c-master-v1", .data = &svc_default_drvdata }, { /* sentinel */ }, }; MODULE_DEVICE_TABLE(of, svc_i3c_master_of_match_tbl); static struct platform_driver svc_i3c_master = { .probe = svc_i3c_master_probe, - .remove_new = svc_i3c_master_remove, + .remove = svc_i3c_master_remove, .driver = { .name = "silvaco-i3c-master", .of_match_table = svc_i3c_master_of_match_tbl, |