/* SCL low and high time values */
omap_i2c_write_reg(omap, OMAP_I2C_SCLL_REG, omap->scllstate);
omap_i2c_write_reg(omap, OMAP_I2C_SCLH_REG, omap->sclhstate); if (omap->rev >= OMAP_I2C_REV_ON_3430_3530)
omap_i2c_write_reg(omap, OMAP_I2C_WE_REG, omap->westate);
/* Take the I2C module out of reset: */
omap_i2c_write_reg(omap, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN);
/* * NOTE: right after setting CON_EN, STAT_BB could be 0 while the * bus is busy. It will be changed to 1 on the next IP FCLK clock. * udelay(1) will be enough to fix that.
*/
/* * Don't write to this register if the IE state is 0 as it can * cause deadlock.
*/ if (omap->iestate)
omap_i2c_write_reg(omap, OMAP_I2C_IE_REG, omap->iestate);
}
omap_i2c_write_reg(omap, OMAP_I2C_SYSC_REG, SYSC_SOFTRESET_MASK); /* For some reason we need to set the EN bit before the
* reset done bit gets set. */
timeout = jiffies + OMAP_I2C_TIMEOUT;
omap_i2c_write_reg(omap, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN); while (!(omap_i2c_read_reg(omap, OMAP_I2C_SYSS_REG) &
SYSS_RESETDONE_MASK)) { if (time_after(jiffies, timeout)) {
dev_warn(omap->dev, "timeout waiting " "for controller reset\n"); return -ETIMEDOUT;
}
msleep(1);
}
/* SYSC register is cleared by the reset; rewrite it */
omap_i2c_write_reg(omap, OMAP_I2C_SYSC_REG, sysc);
if (omap->rev > OMAP_I2C_REV_ON_3430_3530) { /* Schedule I2C-bus monitoring on the next transfer */
omap->bb_valid = 0;
}
}
if (omap->rev >= OMAP_I2C_REV_ON_3430_3530) { /* * Enabling all wakup sources to stop I2C freezing on * WFI instruction. * REVISIT: Some wkup sources might not be needed.
*/
omap->westate = OMAP_I2C_WE_ALL;
}
if (omap->flags & OMAP_I2C_FLAG_ALWAYS_ARMXOR_CLK) { /* * The I2C functional clock is the armxor_ck, so there's * no need to get "armxor_ck" separately. Now, if OMAP2420 * always returns 12MHz for the functional clock, we can * do this bit unconditionally.
*/
fclk = clk_get(omap->dev, "fck"); if (IS_ERR(fclk)) {
error = PTR_ERR(fclk);
dev_err(omap->dev, "could not get fck: %i\n", error);
return error;
}
fclk_rate = clk_get_rate(fclk);
clk_put(fclk);
/* TRM for 5912 says the I2C clock must be prescaled to be * between 7 - 12 MHz. The XOR input clock is typically * 12, 13 or 19.2 MHz. So we should have code that produces: * * XOR MHz Divider Prescaler * 12 1 0 * 13 2 1 * 19.2 2 1
*/ if (fclk_rate > 12000000)
psc = fclk_rate / 12000000;
}
if (!(omap->flags & OMAP_I2C_FLAG_SIMPLE_CLOCK)) {
/* * HSI2C controller internal clk rate should be 19.2 Mhz for * HS and for all modes on 2430. On 34xx we can use lower rate * to get longer filter period for better noise suppression. * The filter is iclk (fclk for HS) period.
*/ if (omap->speed > 400 ||
omap->flags & OMAP_I2C_FLAG_FORCE_19200_INT_CLK)
internal_clk = 19200; elseif (omap->speed > 100)
internal_clk = 9600; else
internal_clk = 4000;
fclk = clk_get(omap->dev, "fck"); if (IS_ERR(fclk)) {
error = PTR_ERR(fclk);
dev_err(omap->dev, "could not get fck: %i\n", error);
if (omap->rev <= OMAP_I2C_REV_ON_3430_3530) { /* Not implemented */
omap->bb_valid = 1;
}
__omap_i2c_init(omap);
return 0;
}
/* * Try bus recovery, but only if SDA is actually low.
*/ staticint omap_i2c_recover_bus(struct omap_i2c_dev *omap)
{
u16 systest;
systest = omap_i2c_read_reg(omap, OMAP_I2C_SYSTEST_REG); if ((systest & OMAP_I2C_SYSTEST_SCL_I_FUNC) &&
(systest & OMAP_I2C_SYSTEST_SDA_I_FUNC)) return 0; /* bus seems to already be fine */ if (!(systest & OMAP_I2C_SYSTEST_SCL_I_FUNC)) return -EBUSY; /* recovery would not fix SCL */ return i2c_recover_bus(&omap->adapter);
}
/* * Waiting on Bus Busy
*/ staticint omap_i2c_wait_for_bb(struct omap_i2c_dev *omap)
{ unsignedlong timeout;
timeout = jiffies + OMAP_I2C_TIMEOUT; while (omap_i2c_read_reg(omap, OMAP_I2C_STAT_REG) & OMAP_I2C_STAT_BB) { if (time_after(jiffies, timeout)) return omap_i2c_recover_bus(omap);
msleep(1);
}
return 0;
}
/* * Wait while BB-bit doesn't reflect the I2C bus state * * In a multimaster environment, after IP software reset, BB-bit value doesn't * correspond to the current bus state. It may happen what BB-bit will be 0, * while the bus is busy due to another I2C master activity. * Here are BB-bit values after reset: * SDA SCL BB NOTES * 0 0 0 1, 2 * 1 0 0 1, 2 * 0 1 1 * 1 1 0 3 * Later, if IP detect SDA=0 and SCL=1 (ACK) or SDA 1->0 while SCL=1 (START) * combinations on the bus, it set BB-bit to 1. * If IP detect SDA 0->1 while SCL=1 (STOP) combination on the bus, * it set BB-bit to 0 and BF to 1. * BB and BF bits correctly tracks the bus state while IP is suspended * BB bit became valid on the next FCLK clock after CON_EN bit set * * NOTES: * 1. Any transfer started when BB=0 and bus is busy wouldn't be * completed by IP and results in controller timeout. * 2. Any transfer started when BB=0 and SCL=0 results in IP * starting to drive SDA low. In that case IP corrupt data * on the bus. * 3. Any transfer started in the middle of another master's transfer * results in unpredictable results and data corruption
*/ staticint omap_i2c_wait_for_bb_valid(struct omap_i2c_dev *omap)
{ unsignedlong bus_free_timeout = 0; unsignedlong timeout; int bus_free = 0;
u16 stat, systest;
if (omap->bb_valid) return 0;
timeout = jiffies + OMAP_I2C_TIMEOUT; while (1) {
stat = omap_i2c_read_reg(omap, OMAP_I2C_STAT_REG); /* * We will see BB or BF event in a case IP had detected any * activity on the I2C bus. Now IP correctly tracks the bus * state. BB-bit value is valid.
*/ if (stat & (OMAP_I2C_STAT_BB | OMAP_I2C_STAT_BF)) break;
/* * Otherwise, we must look signals on the bus to make * the right decision.
*/
systest = omap_i2c_read_reg(omap, OMAP_I2C_SYSTEST_REG); if ((systest & OMAP_I2C_SYSTEST_SCL_I_FUNC) &&
(systest & OMAP_I2C_SYSTEST_SDA_I_FUNC)) { if (!bus_free) {
bus_free_timeout = jiffies +
OMAP_I2C_BUS_FREE_TIMEOUT;
bus_free = 1;
}
/* * SDA and SCL lines was high for 10 ms without bus * activity detected. The bus is free. Consider * BB-bit value is valid.
*/ if (time_after(jiffies, bus_free_timeout)) break;
} else {
bus_free = 0;
}
if (time_after(jiffies, timeout)) { /* * SDA or SCL were low for the entire timeout without * any activity detected. Most likely, a slave is * locking up the bus with no master driving the clock.
*/
dev_warn(omap->dev, "timeout waiting for bus ready\n"); return omap_i2c_recover_bus(omap);
}
/* * Set up notification threshold based on message size. We're doing * this to try and avoid draining feature as much as possible. Whenever * we have big messages to transfer (bigger than our total fifo size) * then we might use draining feature to transfer the remaining bytes.
*/
/* Clear the FIFO Buffers */
w = omap_i2c_read_reg(omap, OMAP_I2C_BUF_REG);
w |= OMAP_I2C_BUF_RXFIF_CLR | OMAP_I2C_BUF_TXFIF_CLR;
omap_i2c_write_reg(omap, OMAP_I2C_BUF_REG, w);
if (!polling)
reinit_completion(&omap->cmd_complete);
omap->cmd_err = 0;
w = OMAP_I2C_CON_EN | OMAP_I2C_CON_MST | OMAP_I2C_CON_STT;
/* High speed configuration */ if (omap->speed > 400)
w |= OMAP_I2C_CON_OPMODE_HS;
if (msg->flags & I2C_M_STOP)
stop = 1; if (msg->flags & I2C_M_TEN)
w |= OMAP_I2C_CON_XA; if (!(msg->flags & I2C_M_RD))
w |= OMAP_I2C_CON_TRX;
if (!omap->b_hw && stop)
w |= OMAP_I2C_CON_STP; /* * NOTE: STAT_BB bit could became 1 here if another master occupy * the bus. IP successfully complete transfer when the bus will be * free again (BB reset to 0).
*/
omap_i2c_write_reg(omap, OMAP_I2C_CON_REG, w);
/* * Don't write stt and stp together on some hardware.
*/ if (omap->b_hw && stop) { unsignedlong delay = jiffies + OMAP_I2C_TIMEOUT;
u16 con = omap_i2c_read_reg(omap, OMAP_I2C_CON_REG); while (con & OMAP_I2C_CON_STT) {
con = omap_i2c_read_reg(omap, OMAP_I2C_CON_REG);
/* Let the user know if i2c is in a bad state */ if (time_after(jiffies, delay)) {
dev_err(omap->dev, "controller timed out " "waiting for start condition to finish\n"); return -ETIMEDOUT;
}
cpu_relax();
}
w |= OMAP_I2C_CON_STP;
w &= ~OMAP_I2C_CON_STT;
omap_i2c_write_reg(omap, OMAP_I2C_CON_REG, w);
}
/* * REVISIT: We should abort the transfer on signals, but the bus goes * into arbitration and we're currently unable to recover from it.
*/ if (!polling) {
time_left = wait_for_completion_timeout(&omap->cmd_complete,
OMAP_I2C_TIMEOUT);
} else { do {
omap_i2c_wait(omap);
ret = omap_i2c_xfer_data(omap);
} while (ret == -EAGAIN);
time_left = !ret;
}
if (time_left == 0) {
omap_i2c_reset(omap);
__omap_i2c_init(omap); return -ETIMEDOUT;
}
if (likely(!omap->cmd_err)) return 0;
/* We have an error */ if (omap->cmd_err & (OMAP_I2C_STAT_ROVR | OMAP_I2C_STAT_XUDF)) {
omap_i2c_reset(omap);
__omap_i2c_init(omap); return -EIO;
}
if (omap->cmd_err & OMAP_I2C_STAT_AL) return -EAGAIN;
if (omap->cmd_err & OMAP_I2C_STAT_NACK) { if (msg->flags & I2C_M_IGNORE_NAK) return 0;
w = omap_i2c_read_reg(omap, OMAP_I2C_CON_REG);
w |= OMAP_I2C_CON_STP;
omap_i2c_write_reg(omap, OMAP_I2C_CON_REG, w); return -EREMOTEIO;
} return -EIO;
}
/* * Prepare controller for a transaction and call omap_i2c_xfer_msg * to do the work during IRQ processing.
*/ staticint
omap_i2c_xfer_common(struct i2c_adapter *adap, struct i2c_msg msgs[], int num, bool polling)
{ struct omap_i2c_dev *omap = i2c_get_adapdata(adap); int i; int r;
r = pm_runtime_get_sync(omap->dev); if (r < 0) goto out;
r = omap_i2c_wait_for_bb_valid(omap); if (r < 0) goto out;
r = omap_i2c_wait_for_bb(omap); if (r < 0) goto out;
if (omap->set_mpu_wkup_lat != NULL)
omap->set_mpu_wkup_lat(omap->dev, omap->latency);
for (i = 0; i < num; i++) {
r = omap_i2c_xfer_msg(adap, &msgs[i], (i == (num - 1)),
polling); if (r != 0) break;
}
if (r == 0)
r = num;
omap_i2c_wait_for_bb(omap);
if (omap->set_mpu_wkup_lat != NULL)
omap->set_mpu_wkup_lat(omap->dev, -1);
staticinlinevoid i2c_omap_errata_i207(struct omap_i2c_dev *omap, u16 stat)
{ /* * I2C Errata(Errata Nos. OMAP2: 1.67, OMAP3: 1.8) * Not applicable for OMAP4. * Under certain rare conditions, RDR could be set again * when the bus is busy, then ignore the interrupt and * clear the interrupt.
*/ if (stat & OMAP_I2C_STAT_RDR) { /* Step 1: If RDR is set, clear it */
omap_i2c_ack_stat(omap, OMAP_I2C_STAT_RDR);
/* Step 2: */ if (!(omap_i2c_read_reg(omap, OMAP_I2C_STAT_REG)
& OMAP_I2C_STAT_BB)) {
/* Step 3: */ if (omap_i2c_read_reg(omap, OMAP_I2C_STAT_REG)
& OMAP_I2C_STAT_RDR) {
omap_i2c_ack_stat(omap, OMAP_I2C_STAT_RDR);
dev_dbg(omap->dev, "RDR when bus is busy.\n");
}
}
}
}
/* rev1 devices are apparently only on some 15xx */ #ifdef CONFIG_ARCH_OMAP15XX
if (pm_runtime_suspended(omap->dev)) return IRQ_NONE;
iv = omap_i2c_read_reg(omap, OMAP_I2C_IV_REG); switch (iv) { case 0x00: /* None */ break; case 0x01: /* Arbitration lost */
dev_err(omap->dev, "Arbitration lost\n");
omap_i2c_complete_cmd(omap, OMAP_I2C_STAT_AL); break; case 0x02: /* No acknowledgement */
omap_i2c_complete_cmd(omap, OMAP_I2C_STAT_NACK);
omap_i2c_write_reg(omap, OMAP_I2C_CON_REG, OMAP_I2C_CON_STP); break; case 0x03: /* Register access ready */
omap_i2c_complete_cmd(omap, 0); break; case 0x04: /* Receive data ready */ if (omap->buf_len) {
w = omap_i2c_read_reg(omap, OMAP_I2C_DATA_REG);
*omap->buf++ = w;
omap->buf_len--; if (omap->buf_len) {
*omap->buf++ = w >> 8;
omap->buf_len--;
}
} else
dev_err(omap->dev, "RRDY IRQ while no data requested\n"); break; case 0x05: /* Transmit data ready */ if (omap->buf_len) {
w = *omap->buf++;
omap->buf_len--; if (omap->buf_len) {
w |= *omap->buf++ << 8;
omap->buf_len--;
}
omap_i2c_write_reg(omap, OMAP_I2C_DATA_REG, w);
} else
dev_err(omap->dev, "XRDY IRQ while no data to send\n"); break; default: return IRQ_NONE;
}
/* * OMAP3430 Errata i462: When an XRDY/XDR is hit, wait for XUDF before writing * data to DATA_REG. Otherwise some data bytes can be lost while transferring * them from the memory to the I2C interface.
*/ staticint errata_omap3_i462(struct omap_i2c_dev *omap)
{ unsignedlong timeout = 10000;
u16 stat;
do {
stat = omap_i2c_read_reg(omap, OMAP_I2C_STAT_REG); if (stat & OMAP_I2C_STAT_XUDF) break;
while (num_bytes--) {
w = omap_i2c_read_reg(omap, OMAP_I2C_DATA_REG);
*omap->buf++ = w;
omap->buf_len--;
/* * Data reg in 2430, omap3 and * omap4 is 8 bit wide
*/ if (omap->flags & OMAP_I2C_FLAG_16BIT_DATA_REG) {
*omap->buf++ = w >> 8;
omap->buf_len--;
}
}
}
do {
bits = omap_i2c_read_reg(omap, OMAP_I2C_IE_REG);
stat = omap_i2c_read_reg(omap, OMAP_I2C_STAT_REG);
stat &= bits;
/* If we're in receiver mode, ignore XDR/XRDY */ if (omap->receiver)
stat &= ~(OMAP_I2C_STAT_XDR | OMAP_I2C_STAT_XRDY); else
stat &= ~(OMAP_I2C_STAT_RDR | OMAP_I2C_STAT_RRDY);
if (!stat) { /* my work here is done */
err = -EAGAIN; break;
}
dev_dbg(omap->dev, "IRQ (ISR = 0x%04x)\n", stat); if (count++ == 100) {
dev_warn(omap->dev, "Too much work in one IRQ\n"); break;
}
if (stat & OMAP_I2C_STAT_NACK) {
omap->cmd_err |= OMAP_I2C_STAT_NACK;
omap_i2c_ack_stat(omap, OMAP_I2C_STAT_NACK);
reg = omap_i2c_read_reg(dev, OMAP_I2C_SYSTEST_REG); /* enable test mode */
reg |= OMAP_I2C_SYSTEST_ST_EN; /* select SDA/SCL IO mode */
reg |= 3 << OMAP_I2C_SYSTEST_TMODE_SHIFT; /* set SCL to high-impedance state (reset value is 0) */
reg |= OMAP_I2C_SYSTEST_SCL_O; /* set SDA to high-impedance state (reset value is 0) */
reg |= OMAP_I2C_SYSTEST_SDA_O;
omap_i2c_write_reg(dev, OMAP_I2C_SYSTEST_REG, reg);
}
r = pm_runtime_resume_and_get(omap->dev); if (r < 0) goto err_disable_pm;
/* * Read the Rev hi bit-[15:14] ie scheme this is 1 indicates ver2. * On omap1/3/2 Offset 4 is IE Reg the bit [15:14] is 0 at reset. * Also since the omap_i2c_read_reg uses reg_map_ip_* a * readw_relaxed is done.
*/
rev = readw_relaxed(omap->base + 0x04);
omap->scheme = OMAP_I2C_SCHEME(rev); switch (omap->scheme) { case OMAP_I2C_SCHEME_0:
omap->regs = (u8 *)reg_map_ip_v1;
omap->rev = omap_i2c_read_reg(omap, OMAP_I2C_REV_REG);
minor = OMAP_I2C_REV_SCHEME_0_MAJOR(omap->rev);
major = OMAP_I2C_REV_SCHEME_0_MAJOR(omap->rev); break; case OMAP_I2C_SCHEME_1: default:
omap->regs = (u8 *)reg_map_ip_v2;
rev = (rev << 16) |
omap_i2c_read_reg(omap, OMAP_I2C_IP_V2_REVNB_LO);
minor = OMAP_I2C_REV_SCHEME_1_MINOR(rev);
major = OMAP_I2C_REV_SCHEME_1_MAJOR(rev);
omap->rev = rev;
}
if (omap->rev <= OMAP_I2C_REV_ON_3430_3530)
omap->errata |= I2C_OMAP_ERRATA_I462;
if (!(omap->flags & OMAP_I2C_FLAG_NO_FIFO)) {
u16 s;
/* Set up the fifo size - Get total size */
s = (omap_i2c_read_reg(omap, OMAP_I2C_BUFSTAT_REG) >> 14) & 0x3;
omap->fifo_size = 0x8 << s;
/* * Set up notification threshold as half the total available * size. This is to ensure that we can handle the status on int * call back latencies.
*/
/* i2c device drivers may be active on return from add_adapter() */
adap->nr = pdev->id;
r = i2c_add_numbered_adapter(adap); if (r) goto err_unuse_clocks;
staticint omap_i2c_suspend(struct device *dev)
{ /* * If the controller is autosuspended, there is no way to wakeup it once * runtime pm is disabled (in suspend_late()). * But a device may need the controller up during suspend_noirq() or * resume_noirq(). * Wakeup the controller while runtime pm is enabled, so it is available * until its suspend_noirq(), and from resume_noirq().
*/ return pm_runtime_resume_and_get(dev);
}
/* I2C may be needed to bring up other drivers */ staticint __init
omap_i2c_init_driver(void)
{ return platform_driver_register(&omap_i2c_driver);
}
subsys_initcall(omap_i2c_init_driver);
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.