+
+ /* Set slave address */
+ omap_i2c_write_reg(i2c_base, ip_rev, chip, OMAP_I2C_SA_REG);
+ /* Read/Write len bytes data */
+ omap_i2c_write_reg(i2c_base, ip_rev, len, OMAP_I2C_CNT_REG);
+ /* Configure the I2C_CON register */
+ omap_i2c_write_reg(i2c_base, ip_rev, i2c_con_reg, OMAP_I2C_CON_REG);
+
+ /* read/write data bytewise */
+ for (i = 0; i < len; i++) {
+ status = wait_for_event(i2c_base, ip_rev, waitdelay);
+ /* Ignore I2C_STAT_RRDY in transmitter mode */
+ if (i2c_con_reg & I2C_CON_TRX)
+ status &= ~I2C_STAT_RRDY;
+ else
+ status &= ~I2C_STAT_XRDY;
+
+ /* Try to identify bus that is not padconf'd for I2C */
+ if (status == I2C_STAT_XRDY) {
+ i2c_error = 2;
+ printf("I2C xfer: pads on bus probably not configured
(status=0x%x)\n",
+ status);
+ goto xfer_exit;
+ }
+ if (status == 0 || (status & I2C_STAT_NACK)) {
+ i2c_error = 1;
+ printf("I2C xfer: error waiting for ACK (status=0x%x)\n",
+ status);
+ goto xfer_exit;
+ }
+ if (status & I2C_STAT_XRDY) {
+ /* Transmit data */
+ omap_i2c_write_reg(i2c_base, ip_rev,
+ buffer[i], OMAP_I2C_DATA_REG);
+ omap_i2c_write_reg(i2c_base, ip_rev,
+ I2C_STAT_XRDY, OMAP_I2C_STAT_REG);
+ }
+ if (status & I2C_STAT_RRDY) {
+ /* Receive data */
+ *buffer++ = omap_i2c_read_reg(i2c_base, ip_rev,
+ OMAP_I2C_DATA_REG);
+ omap_i2c_write_reg(i2c_base, ip_rev,
+ I2C_STAT_RRDY, OMAP_I2C_STAT_REG);
+ }
+ }
+
+ /*
+ * poll ARDY bit for making sure that last byte really has been
+ * transferred on the bus.
+ */
+ do {
+ status = wait_for_event(i2c_base, ip_rev, waitdelay);
+ } while (!(status & I2C_STAT_ARDY) && timeout--);
+ if (timeout <= 0) {
+ puts("I2C xfer: timed out on last byte!\n");
+ i2c_error = 1;
+ goto xfer_exit;
+ } else {
+ omap_i2c_write_reg(i2c_base, ip_rev, I2C_STAT_ARDY,
OMAP_I2C_STAT_REG);
+ }
+
+ /* If Stop bit set, flush FIFO. */
+ if (i2c_con_reg & I2C_CON_STP)
+ goto xfer_exit;
+
+ return 0;
+
+xfer_exit:
+ flush_fifo(i2c_base, ip_rev);
+ omap_i2c_write_reg(i2c_base, ip_rev, 0xFFFF, OMAP_I2C_STAT_REG);
+ return i2c_error;
+}
+
+#if !CONFIG_IS_ENABLED(DM_I2C)
+/*
+ * The legacy I2C functions. These need to get removed once
+ * all users of this driver are converted to DM.
+ */
+
/*
* i2c_read: Function now uses a single I2C read transaction with
bulk transfer
* of the requested number of bytes (note that the 'i2c
md' command
@@ -836,11 +937,6 @@ wr_exit:
return i2c_error;
}
-#if !CONFIG_IS_ENABLED(DM_I2C)
-/*
- * The legacy I2C functions. These need to get removed once
- * all users of this driver are converted to DM.
- */
static void __iomem *omap24_get_base(struct i2c_adapter *adap)
{
switch (adap->hwadapnr) {
@@ -975,23 +1071,30 @@ static int omap_i2c_xfer(struct udevice *bus,
struct i2c_msg *msg, int nmsgs)
{
struct omap_i2c *priv = dev_get_priv(bus);
int ret;
+ u16 i2c_con_reg = 0;
debug("i2c_xfer: %d messages\n", nmsgs);
for (; nmsgs > 0; nmsgs--, msg++) {
- debug("i2c_xfer: chip=0x%x, len=0x%x\n", msg->addr, msg->len);
- if (msg->flags & I2C_M_RD) {
- ret = __omap24_i2c_read(priv->regs, priv->ip_rev,
- priv->waitdelay,
- msg->addr, 0, 0, msg->buf,
- msg->len);
- } else {
- ret = __omap24_i2c_write(priv->regs, priv->ip_rev,
- priv->waitdelay,
- msg->addr, 0, 0, msg->buf,
- msg->len);
- }
+ debug("i2c_xfer: chip=0x%x, len=0x%x, read=0x%x\n",
+ msg->addr, msg->len, (msg->flags & I2C_M_RD));
+
+ /* Wait until bus not busy */
+ if (wait_for_bb(priv->regs, priv->ip_rev, priv->waitdelay))
+ return -EREMOTEIO;
+
+ /* Set Controller mode with Start and Stop bit */
+ i2c_con_reg = I2C_CON_EN | I2C_CON_MST | I2C_CON_STT |
I2C_CON_STP;
+ /* Set Transmitter/Receiver mode if it is a write/read msg */
+ if (msg->flags & I2C_M_RD)
+ i2c_con_reg &= ~I2C_CON_TRX;
+ else
+ i2c_con_reg |= I2C_CON_TRX;
+
+ ret = __omap24_i2c_xfer_msg(priv->regs, priv->ip_rev,
priv->waitdelay,
+ msg->addr, msg->buf, msg->len,
+ i2c_con_reg);
if (ret) {
- debug("i2c_write: error sending\n");
+ debug("i2c_xfer: error sending\n");
return -EREMOTEIO;
}
}