/* * This i2c core has a lot of interrupts, namely 8. We use their chaining as * some kind of state machine. * * 1) The main xfer routine kicks off a transmission by putting the start bit * (or repeated start) on the bus and enabling the transmit interrupt (TIE) * since we need to send the target address + RW bit in every case. * * 2) TIE sends target address + RW bit and selects how to continue. * * 3a) Write case: We keep utilizing TIE as long as we have data to send. If we * are done, we switch over to the transmission done interrupt (TEIE) and mark * the message as completed (includes sending STOP) there. * * 3b) Read case: We switch over to receive interrupt (RIE). One dummy read is * needed to start clocking, then we keep receiving until we are done. Note * that we use the RDRFS mode all the time, i.e. we ACK/NACK every byte by * writing to the ACKBT bit. I tried using the RDRFS mode only at the end of a * message to create the final NACK as sketched in the datasheet. This caused * some subtle races (when byte n was processed and byte n+1 was already * waiting), though, and I started with the safe approach. * * 4) If we got a NACK somewhere, we flag the error and stop the transmission * via NAKIE. * * Also check the comments in the interrupt routines for some gory details.
*/
staticint riic_bus_barrier(struct riic_dev *riic)
{ int ret;
u8 val;
/* * The SDA line can still be low even when BBSY = 0. Therefore, after checking * the BBSY flag, also verify that the SDA and SCL lines are not being held low.
*/
ret = readb_poll_timeout(riic->base + riic->info->regs[RIIC_ICCR2], val,
!(val & ICCR2_BBSY), 10, riic->adapter.timeout); if (ret) return i2c_recover_bus(&riic->adapter);
if (riic->bytes_left == RIIC_INIT_MSG) { if (riic->msg->flags & I2C_M_RD) /* On read, switch over to receive interrupt */
riic_clear_set_bit(riic, ICIER_TIE, ICIER_RIE, RIIC_ICIER); else /* On write, initialize length */
riic->bytes_left = riic->msg->len;
val = i2c_8bit_addr_from_msg(riic->msg);
} else {
val = *riic->buf;
riic->buf++;
riic->bytes_left--;
}
/* * Switch to transmission ended interrupt when done. Do check here * after bytes_left was initialized to support SMBUS_QUICK (new msg has * 0 length then)
*/ if (riic->bytes_left == 0)
riic_clear_set_bit(riic, ICIER_TIE, ICIER_TEIE, RIIC_ICIER);
/* * This acks the TIE interrupt. We get another TIE immediately if our * value could be moved to the shadow shift register right away. So * this must be after updates to ICIER (where we want to disable TIE)!
*/
riic_writeb(riic, val, RIIC_ICDRT);
if (riic->bytes_left == 1) { /* STOP must come before we set ACKBT! */ if (riic->is_last) {
riic_clear_set_bit(riic, 0, ICIER_SPIE, RIIC_ICIER);
riic_writeb(riic, ICCR2_SP, RIIC_ICCR2);
}
/* * Determine reference clock rate. We must be able to get the desired * frequency with only 62 clock ticks max (31 high, 31 low). * Aim for a duty of 60% LOW, 40% HIGH.
*/
total_ticks = DIV_ROUND_UP(rate, t->bus_freq_hz ?: 1);
for (cks = 0; cks <= 7; cks++) { /* * 60% low time must be less than BRL + 2 + 1 * BRL max register value is 0x1F.
*/
brl = ((total_ticks * 6) / 10); if (brl <= (0x1F + 3)) break;
ret = pm_runtime_resume_and_get(dev); if (ret) return ret;
/* Changing the order of accessing IICRST and ICE may break things! */
riic_writeb(riic, ICCR1_IICRST | ICCR1_SOWP, RIIC_ICCR1);
riic_clear_set_bit(riic, 0, ICCR1_ICE, RIIC_ICCR1);
/* Default 0 to save power. Can be overridden via sysfs for lower latency. */
pm_runtime_set_autosuspend_delay(dev, 0);
pm_runtime_use_autosuspend(dev);
pm_runtime_enable(dev);
ret = riic_init_hw(riic); if (ret) goto out;
ret = i2c_add_adapter(adap); if (ret) goto out;
platform_set_drvdata(pdev, riic);
dev_info(dev, "registered with %dHz bus speed\n", riic->i2c_t.bus_freq_hz); return0;
ret = reset_control_deassert(riic->rstc); if (ret) return ret;
ret = riic_init_hw(riic); if (ret) { /* * In case this happens there is no way to recover from this * state. The driver will remain loaded. We want to avoid * keeping the reset line de-asserted for no reason.
*/
reset_control_assert(riic->rstc); return ret;
}
MODULE_DESCRIPTION("Renesas RIIC adapter");
MODULE_AUTHOR("Wolfram Sang <wsa@sang-engineering.com>");
MODULE_LICENSE("GPL v2");
MODULE_DEVICE_TABLE(of, riic_i2c_dt_ids);
Messung V0.5 in Prozent
¤ 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.15Bemerkung:
(vorverarbeitet am 2026-06-08)
¤
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.