/* 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
/* * 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_master - Silvaco I3C Master structure * @base: I3C master controller * @dev: Corresponding device * @regs: Memory mapping * @saved_regs: Volatile values for PM operations * @free_slots: Bit array of available slots * @addrs: Array containing the dynamic addresses of each attached device * @descs: Array of descriptors, one per attached device * @hj_work: Hot-join work * @irq: Main interrupt * @num_clks: I3C clock number * @fclk: Fast clock (bus) * @clks: I3C clock array * @xferqueue: Transfer queue structure * @xferqueue.list: List member * @xferqueue.cur: Current ongoing transfer * @xferqueue.lock: Queue lock * @ibi: IBI structure * @ibi.num_slots: Number of slots available in @ibi.slots * @ibi.slots: Available IBI slots * @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; struct device *dev; void __iomem *regs; struct svc_i3c_regs_save saved_regs;
u32 free_slots;
u8 addrs[SVC_I3C_MAX_DEVS]; struct i3c_dev_desc *descs[SVC_I3C_MAX_DEVS]; struct work_struct hj_work; int irq; int num_clks; struct clk *fclk; struct clk_bulk_data *clks; struct { struct list_head list; struct svc_i3c_xfer *cur; /* Prevent races between transfers */
spinlock_t lock;
} xferqueue; struct { unsignedint num_slots; struct i3c_dev_desc **slots; struct i3c_ibi_slot *tbq_slot; /* Prevent races within IBI handlers */
spinlock_t lock;
} ibi; struct mutex lock; conststruct svc_i3c_drvdata *drvdata;
u32 enabled_events;
u32 mctrl_config;
};
/** * struct svc_i3c_i2c_dev_data - Device specific data * @index: Index in the master tables corresponding to this device * @ibi: IBI slot index in the master structure * @ibi_pool: IBI pool associated to this device
*/ struct svc_i3c_i2c_dev_data {
u8 index; int ibi; struct i3c_generic_ibi_pool *ibi_pool;
};
/* * This delay is necessary after the emission of a stop, otherwise eg. * repeating IBIs do not get detected. There is a note in the manual * about it, stating that the stop condition might not be settled * correctly if a start condition follows too rapidly.
*/
udelay(1);
}
/* 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);
}
/* * 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);
/* * Write REQUEST_START_ADDR request to emit broadcast address for arbitration, * instend of using AUTO_IBI. * * Using AutoIBI request may cause controller to remain in AutoIBI state when * there is a glitch on SDA line (high->low->high). * 1. SDA high->low, raising an interrupt to execute IBI isr. * 2. SDA low->high. * 3. IBI isr writes an AutoIBI request. * 4. The controller will not start AutoIBI process because SDA is not low. * 5. IBIWON polling times out. * 6. Controller reamins in AutoIBI state and doesn't accept EmitStop request.
*/
writel(SVC_I3C_MCTRL_REQUEST_START_ADDR |
SVC_I3C_MCTRL_TYPE_I3C |
SVC_I3C_MCTRL_IBIRESP_MANUAL |
SVC_I3C_MCTRL_DIR(SVC_I3C_MCTRL_DIR_WRITE) |
SVC_I3C_MCTRL_ADDR(I3C_BROADCAST_ADDR),
master->regs + SVC_I3C_MCTRL);
/* Wait for IBIWON, should take approximately 100us */
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); return;
}
/* Handle the critical responses to IBI's */ switch (ibitype) { case SVC_I3C_MSTATUS_IBITYPE_IBI:
dev = svc_i3c_master_dev_from_addr(master, ibiaddr); if (!dev || !is_events_enabled(master, SVC_I3C_EVENT_IBI)) {
svc_i3c_master_nack_ibi(master);
} else { if (dev->info.bcr & I3C_BCR_IBI_PAYLOAD)
svc_i3c_master_ack_ibi(master, true); else
svc_i3c_master_ack_ibi(master, false);
svc_i3c_master_handle_ibi(master, dev);
} break; case SVC_I3C_MSTATUS_IBITYPE_HOT_JOIN: if (is_events_enabled(master, SVC_I3C_EVENT_HOTJOIN))
svc_i3c_master_ack_ibi(master, false); else
svc_i3c_master_nack_ibi(master); break; case SVC_I3C_MSTATUS_IBITYPE_MASTER_REQUEST:
svc_i3c_master_nack_ibi(master); break; default: break;
}
/* * If an error happened, we probably got interrupted and the exchange * timedout. In this case we just drop everything, emit a stop and wait * for the slave to interrupt again.
*/ if (svc_i3c_master_error(master)) { if (master->ibi.tbq_slot) {
data = i3c_dev_get_master_data(dev);
i3c_generic_ibi_recycle_slot(data->ibi_pool,
master->ibi.tbq_slot);
master->ibi.tbq_slot = NULL;
}
svc_i3c_master_emit_stop(master);
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;
} break; case SVC_I3C_MSTATUS_IBITYPE_HOT_JOIN:
svc_i3c_master_emit_stop(master); if (is_events_enabled(master, SVC_I3C_EVENT_HOTJOIN))
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;
}
}
if (!SVC_I3C_MSTATUS_SLVSTART(active)) return IRQ_NONE;
/* Clear the interrupt status */
writel(SVC_I3C_MINT_SLVSTART, master->regs + SVC_I3C_MSTATUS);
/* Ignore the false event */ if (svc_has_quirk(master, SVC_I3C_QUIRK_FALSE_SLVSTART) &&
!SVC_I3C_MSTATUS_STATE_SLVREQ(active)) return IRQ_HANDLED;
/* * 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);
/* * 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(fclk_rate / 2, i3c_scl_rate) - 1;
pplow = 0;
/* * Using I3C Open-Drain mode, target is 4.17MHz/240ns with a * duty-cycle tuned so that high levels are filetered out by * the 50ns filter (target being 40ns).
*/
odhpp = 1;
high_period_ns = (ppbaud + 1) * fclk_period_ns;
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) { case I3C_BUS_MODE_PURE:
i2cbaud = 0;
odstop = 0; break; case I3C_BUS_MODE_MIXED_FAST: /* * Using I2C Fm+ mode, target is 1MHz/1000ns, the difference * between the high and low period does not really matter.
*/
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: /* 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);
}
for (i = 0; i < len; i++) {
ret = readl_poll_timeout_atomic(master->regs + SVC_I3C_MSTATUS,
reg,
SVC_I3C_MSTATUS_RXPEND(reg),
0, 1000); if (ret) return ret;
/* 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 |
SVC_I3C_MCTRL_DIR(SVC_I3C_MCTRL_DIR_WRITE),
master->regs + SVC_I3C_MCTRL);
/* * Either one slave will send its ID, or the assignment process * is done.
*/
ret = readl_poll_timeout_atomic(master->regs + SVC_I3C_MSTATUS,
reg,
SVC_I3C_MSTATUS_RXPEND(reg) |
SVC_I3C_MSTATUS_MCTRLDONE(reg),
1, 1000); if (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;
/* * 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) break;
for (i = 0; i < 6; i++)
prov_id[dev_nb] |= (u64)(data[i]) << (8 * (5 - i));
/* We do not care about the BCR and DCR yet */
ret = svc_i3c_master_readb(master, data, 2); if (ret) break;
} elseif (SVC_I3C_MSTATUS_IBIWON(reg)) {
ret = svc_i3c_master_handle_ibi_won(master, reg); if (ret) break; continue;
} elseif (SVC_I3C_MSTATUS_MCTRLDONE(reg)) { if (SVC_I3C_MSTATUS_STATE_IDLE(reg) &&
SVC_I3C_MSTATUS_COMPLETE(reg)) { /* * 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.
*/
*count = dev_nb; return 0;
} elseif (SVC_I3C_MSTATUS_NACKED(reg)) { /* No I3C devices attached */ 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 * allowed only once, DAA will be stopped and * then resumed. The same device is supposed to * answer again immediately and shall ack the * address this time.
*/ if (prov_id[dev_nb] == nacking_prov_id) {
ret = -EIO; break;
}
/* Wait for the slave to be ready to receive its address */
ret = readl_poll_timeout_atomic(master->regs + SVC_I3C_MSTATUS,
reg,
SVC_I3C_MSTATUS_MCTRLDONE(reg) &&
SVC_I3C_MSTATUS_STATE_DAA(reg) &&
SVC_I3C_MSTATUS_BETWEEN(reg),
0, 1000); if (ret) break;
/* Create the IBIRULES register for both cases */
i3c_bus_for_each_i3cdev(&master->base.bus, dev) { if (!(dev->info.bcr & I3C_BCR_IBI_REQ_CAP)) continue;
if (dev->info.bcr & I3C_BCR_IBI_PAYLOAD) {
reg_mbyte |= SVC_I3C_IBIRULES_ADDR(mbyte_addr_ok,
dev->info.dyn_addr);
/* IBI rules cannot be applied to devices with MSb=1 */ if (dev->info.dyn_addr & BIT(7))
mbyte_addr_ko++; else
mbyte_addr_ok++;
} else {
reg_nobyte |= SVC_I3C_IBIRULES_ADDR(nobyte_addr_ok,
dev->info.dyn_addr);
/* IBI rules cannot be applied to devices with MSb=1 */ if (dev->info.dyn_addr & BIT(7))
nobyte_addr_ko++; else
nobyte_addr_ok++;
}
}
/* Device list cannot be handled by hardware */ if (!mbyte_addr_ko && mbyte_addr_ok <= SVC_I3C_IBIRULES_ADDRS)
list_mbyte = true;
if (!nobyte_addr_ko && nobyte_addr_ok <= SVC_I3C_IBIRULES_ADDRS)
list_nobyte = true;
/* No list can be properly handled, return an error */ if (!list_mbyte && !list_nobyte) return -ERANGE;
/* Pick the first list that can be handled by hardware, randomly */ if (list_mbyte)
writel(reg_mbyte, master->regs + SVC_I3C_IBIRULES); else
writel(reg_nobyte, master->regs + SVC_I3C_IBIRULES);
svc_i3c_master_clear_merrwarn(master); 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); if (ret)
dev_err(master->dev, "Cannot handle such a list of devices");
while (offset < len) {
ret = readl_poll_timeout(master->regs + SVC_I3C_MDATACTRL,
mdctrl,
!(mdctrl & SVC_I3C_MDATACTRL_TXFULL),
0, 1000); if (ret) return ret;
/* * The last byte to be sent over the bus must either have the * "end" bit set or be written in MWDATABE.
*/ if (likely(offset < (len - 1)))
writel(out[offset++], master->regs + SVC_I3C_MWDATAB); else
writel(out[offset++], master->regs + SVC_I3C_MWDATABE);
}
/* * 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 space, end, len;
reg = readl(master->regs + SVC_I3C_MDATACTRL);
space = SVC_I3C_FIFO_SIZE - SVC_I3C_MDATACTRL_TXCOUNT(reg); if (space) {
end = xfer_len > space ? 0 : SVC_I3C_MWDATAB_END;
len = min_t(u32, xfer_len, space);
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;
/* * 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;
}
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)
ret = svc_i3c_master_read(master, in, xfer_len); else
ret = svc_i3c_master_write(master, out, xfer_len); if (ret < 0) goto emit_stop;
if (rnw)
*actual_len = ret;
ret = readl_poll_timeout(master->regs + SVC_I3C_MSTATUS, reg,
SVC_I3C_MSTATUS_COMPLETE(reg), 0, 1000); if (ret) goto emit_stop;
for (i = 0; i < xfer->ncmds; i++) { struct svc_i3c_cmd *cmd = &xfer->cmds[i];
ret = svc_i3c_master_xfer(master, cmd->rnw, xfer->type,
cmd->addr, cmd->in, cmd->out,
cmd->len, &cmd->actual_len,
cmd->continued, i > 0); /* cmd->xfer is NULL if I2C or CCC transfer */ if (cmd->xfer)
cmd->xfer->actual_len = cmd->actual_len;
if (ret) break;
}
xfer->ret = ret;
complete(&xfer->comp);
if (ret < 0)
svc_i3c_master_dequeue_xfer_locked(master, xfer);
xfer = list_first_entry_or_null(&master->xferqueue.list, struct svc_i3c_xfer,
node); if (xfer)
list_del_init(&xfer->node);
staticbool
svc_i3c_master_supports_ccc_cmd(struct i3c_master_controller *master, conststruct i3c_ccc_cmd *cmd)
{ /* No software support for CCC commands targeting more than one slave */ return (cmd->ndests == 1);
}
if (dev->ibi->max_payload_len > SVC_I3C_FIFO_SIZE) {
dev_err(master->dev, "IBI max payload %d should be < %d\n",
dev->ibi->max_payload_len, SVC_I3C_FIFO_SIZE); return -ERANGE;
}
data->ibi_pool = i3c_generic_ibi_alloc_pool(dev, req); if (IS_ERR(data->ibi_pool)) return PTR_ERR(data->ibi_pool);
spin_lock_irqsave(&master->ibi.lock, flags); for (i = 0; i < master->ibi.num_slots; i++) { if (!master->ibi.slots[i]) {
data->ibi = i;
master->ibi.slots[i] = dev; break;
}
}
spin_unlock_irqrestore(&master->ibi.lock, flags);
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.41Bemerkung:
Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.