static int i2c_imx_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num) { unsigned int i, temp; int result; struct imx_i2c_struct *i2c_imx = i2c_get_adapdata(adapter); dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__); /* Start I2C transfer */ result = i2c_imx_start(i2c_imx); if (result) goto fail0; /* read/write data */ for (i = 0; i < num; i++) { if (i) { dev_dbg(&i2c_imx->adapter.dev, "<%s> repeated start\n", __func__); temp = readb(i2c_imx->base + IMX_I2C_I2CR); temp |= I2CR_RSTA; writeb(temp, i2c_imx->base + IMX_I2C_I2CR); result = i2c_imx_bus_busy(i2c_imx, 1); if (result) goto fail0; } dev_dbg(&i2c_imx->adapter.dev, "<%s> transfer message: %d\n", __func__, i); /* write/read data */ #ifdef CONFIG_I2C_DEBUG_BUS temp = readb(i2c_imx->base + IMX_I2C_I2CR); dev_dbg(&i2c_imx->adapter.dev, "<%s> CONTROL: IEN=%d, IIEN=%d, " "MSTA=%d, MTX=%d, TXAK=%d, RSTA=%d\n", __func__, (temp & I2CR_IEN ? 1 : 0), (temp & I2CR_IIEN ? 1 : 0), (temp & I2CR_MSTA ? 1 : 0), (temp & I2CR_MTX ? 1 : 0), (temp & I2CR_TXAK ? 1 : 0), (temp & I2CR_RSTA ? 1 : 0)); temp = readb(i2c_imx->base + IMX_I2C_I2SR); dev_dbg(&i2c_imx->adapter.dev, "<%s> STATUS: ICF=%d, IAAS=%d, IBB=%d, " "IAL=%d, SRW=%d, IIF=%d, RXAK=%d\n", __func__, (temp & I2SR_ICF ? 1 : 0), (temp & I2SR_IAAS ? 1 : 0), (temp & I2SR_IBB ? 1 : 0), (temp & I2SR_IAL ? 1 : 0), (temp & I2SR_SRW ? 1 : 0), (temp & I2SR_IIF ? 1 : 0), (temp & I2SR_RXAK ? 1 : 0)); #endif if (msgs[i].flags & I2C_M_RD) result = i2c_imx_read(i2c_imx, &msgs[i]); else result = i2c_imx_write(i2c_imx, &msgs[i]); } fail0: /* Stop I2C transfer */ i2c_imx_stop(i2c_imx); dev_dbg(&i2c_imx->adapter.dev, "<%s> exit with: %s: %d\n", __func__, (result < 0) ? "error" : "success msg", (result < 0) ? result : num); return (result < 0) ? result : num; }
static int i2c_imx_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num) { struct imx_i2c_struct *i2c_imx = to_imx_i2c_struct(adapter); void __iomem *base = i2c_imx->base; unsigned int i, temp; int result; /* Start I2C transfer */ result = i2c_imx_start(adapter); if (result) goto fail0; /* read/write data */ for (i = 0; i < num; i++) { if (i && !(msgs[i].flags & I2C_M_DATA_ONLY)) { temp = readb(base + IMX_I2C_I2CR); temp |= I2CR_RSTA; writeb(temp, base + IMX_I2C_I2CR); result = i2c_imx_bus_busy(adapter, 1); if (result) goto fail0; } i2c_imx_dump_reg(adapter); /* write/read data */ if (msgs[i].flags & I2C_M_RD) result = i2c_imx_read(adapter, &msgs[i]); else result = i2c_imx_write(adapter, &msgs[i]); if (result) goto fail0; } fail0: /* Stop I2C transfer */ i2c_imx_stop(adapter); return (result < 0) ? result : num; }
static int i2c_imx_transfer(struct device *dev, struct i2c_msg *msgs, u8_t num_msgs, u16_t addr) { I2C_Type *base = DEV_BASE(dev); struct i2c_imx_data *data = DEV_DATA(dev); struct i2c_master_transfer *transfer = &data->transfer; u8_t *buf, *buf_end; u16_t timeout = UINT16_MAX; int result = -EIO; if (!num_msgs) { return 0; } /* Wait until bus not busy */ while ((I2C_I2SR_REG(base) & i2cStatusBusBusy) && (--timeout)) { } if (timeout == 0) { return result; } /* Make sure we're in a good state so slave recognises the Start */ I2C_SetWorkMode(base, i2cModeSlave); transfer->currentMode = i2cModeSlave; /* Switch back to Rx direction. */ I2C_SetDirMode(base, i2cDirectionReceive); transfer->currentDir = i2cDirectionReceive; /* Start condition */ I2C_SetDirMode(base, i2cDirectionTransmit); transfer->currentDir = i2cDirectionTransmit; I2C_SetWorkMode(base, i2cModeMaster); transfer->currentMode = i2cModeMaster; /* Send address after any Start condition */ if (!i2c_imx_send_addr(dev, addr, msgs->flags)) { goto finish; /* No ACK received */ } do { if (msgs->flags & I2C_MSG_RESTART) { I2C_SendRepeatStart(base); if (!i2c_imx_send_addr(dev, addr, msgs->flags)) { goto finish; /* No ACK received */ } } /* Transfer data */ buf = msgs->buf; buf_end = buf + msgs->len; if ((msgs->flags & I2C_MSG_RW_MASK) == I2C_MSG_READ) { i2c_imx_read(dev, msgs->buf, msgs->len); } else { if (!i2c_imx_write(dev, msgs->buf, msgs->len)) { goto finish; /* No ACK received */ } } if (msgs->flags & I2C_MSG_STOP) { I2C_SetWorkMode(base, i2cModeSlave); transfer->currentMode = i2cModeSlave; I2C_SetDirMode(base, i2cDirectionReceive); transfer->currentDir = i2cDirectionReceive; } /* Next message */ msgs++; num_msgs--; } while (num_msgs); /* Complete without error */ result = 0; return result; finish: I2C_SetWorkMode(base, i2cModeSlave); transfer->currentMode = i2cModeSlave; I2C_SetDirMode(base, i2cDirectionReceive); transfer->currentDir = i2cDirectionReceive; return result; }