summaryrefslogtreecommitdiff
path: root/drivers/i2c/busses/i2c-imx.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/i2c/busses/i2c-imx.c')
-rw-r--r--drivers/i2c/busses/i2c-imx.c409
1 files changed, 357 insertions, 52 deletions
diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
index 98539313cbc9..f751d231ded8 100644
--- a/drivers/i2c/busses/i2c-imx.c
+++ b/drivers/i2c/busses/i2c-imx.c
@@ -17,7 +17,7 @@
* Copyright (C) 2008 Darius Augulis <darius.augulis at teltonika.lt>
*
* Copyright 2013 Freescale Semiconductor, Inc.
- * Copyright 2020 NXP
+ * Copyright 2020, 2024 NXP
*
*/
@@ -84,6 +84,7 @@
#define IMX_I2C_REGSHIFT 2
#define VF610_I2C_REGSHIFT 0
+#define S32G_I2C_REGSHIFT 0
/* Bits of IMX I2C registers */
#define I2SR_RXAK 0x01
@@ -165,9 +166,34 @@ static struct imx_i2c_clk_pair vf610_i2c_clk_div[] = {
{ 3840, 0x3F }, { 4096, 0x7B }, { 5120, 0x7D }, { 6144, 0x7E },
};
+/* S32G2/S32G3 clock divider, register value pairs */
+static struct imx_i2c_clk_pair s32g2_i2c_clk_div[] = {
+ { 34, 0x00 }, { 36, 0x01 }, { 38, 0x02 }, { 40, 0x03 },
+ { 42, 0x04 }, { 44, 0x05 }, { 46, 0x06 }, { 48, 0x09 },
+ { 52, 0x0A }, { 54, 0x07 }, { 56, 0x0B }, { 60, 0x0C },
+ { 64, 0x0D }, { 68, 0x40 }, { 72, 0x0E }, { 76, 0x42 },
+ { 80, 0x12 }, { 84, 0x0F }, { 88, 0x13 }, { 96, 0x14 },
+ { 104, 0x15 }, { 108, 0x47 }, { 112, 0x19 }, { 120, 0x16 },
+ { 128, 0x1A }, { 136, 0x80 }, { 144, 0x17 }, { 152, 0x82 },
+ { 160, 0x1C }, { 168, 0x84 }, { 176, 0x1D }, { 192, 0x21 },
+ { 208, 0x1E }, { 216, 0x87 }, { 224, 0x22 }, { 240, 0x56 },
+ { 256, 0x1F }, { 288, 0x24 }, { 320, 0x25 }, { 336, 0x8F },
+ { 352, 0x93 }, { 356, 0x5D }, { 358, 0x98 }, { 384, 0x26 },
+ { 416, 0x56 }, { 448, 0x2A }, { 480, 0x27 }, { 512, 0x2B },
+ { 576, 0x2C }, { 640, 0x2D }, { 704, 0x9D }, { 768, 0x2E },
+ { 832, 0x9D }, { 896, 0x32 }, { 960, 0x2F }, { 1024, 0x33 },
+ { 1152, 0x34 }, { 1280, 0x35 }, { 1536, 0x36 }, { 1792, 0x3A },
+ { 1920, 0x37 }, { 2048, 0x3B }, { 2304, 0x74 }, { 2560, 0x3D },
+ { 3072, 0x3E }, { 3584, 0x7A }, { 3840, 0x3F }, { 4096, 0x7B },
+ { 4608, 0x7C }, { 5120, 0x7D }, { 6144, 0x7E }, { 7168, 0xBA },
+ { 7680, 0x7F }, { 8192, 0xBB }, { 9216, 0xBC }, { 10240, 0xBD },
+ { 12288, 0xBE }, { 15360, 0xBF },
+};
+
enum imx_i2c_type {
IMX1_I2C,
IMX21_I2C,
+ S32G_I2C,
VF610_I2C,
};
@@ -197,6 +223,17 @@ struct imx_i2c_dma {
enum dma_data_direction dma_data_dir;
};
+enum imx_i2c_state {
+ IMX_I2C_STATE_DONE,
+ IMX_I2C_STATE_FAILED,
+ IMX_I2C_STATE_WRITE,
+ IMX_I2C_STATE_DMA,
+ IMX_I2C_STATE_READ,
+ IMX_I2C_STATE_READ_CONTINUE,
+ IMX_I2C_STATE_READ_BLOCK_DATA,
+ IMX_I2C_STATE_READ_BLOCK_DATA_LEN,
+};
+
struct imx_i2c_struct {
struct i2c_adapter adapter;
struct clk *clk;
@@ -216,6 +253,14 @@ struct imx_i2c_struct {
struct i2c_client *slave;
enum i2c_slave_event last_slave_event;
+ struct i2c_msg *msg;
+ unsigned int msg_buf_idx;
+ int isr_result;
+ bool is_lastmsg;
+ enum imx_i2c_state state;
+
+ bool multi_master;
+
/* For checking slave events. */
spinlock_t slave_lock;
struct hrtimer slave_timer;
@@ -258,7 +303,15 @@ static struct imx_i2c_hwdata vf610_i2c_hwdata = {
.ndivs = ARRAY_SIZE(vf610_i2c_clk_div),
.i2sr_clr_opcode = I2SR_CLR_OPCODE_W1C,
.i2cr_ien_opcode = I2CR_IEN_OPCODE_0,
+};
+static const struct imx_i2c_hwdata s32g2_i2c_hwdata = {
+ .devtype = S32G_I2C,
+ .regshift = S32G_I2C_REGSHIFT,
+ .clk_div = s32g2_i2c_clk_div,
+ .ndivs = ARRAY_SIZE(s32g2_i2c_clk_div),
+ .i2sr_clr_opcode = I2SR_CLR_OPCODE_W1C,
+ .i2cr_ien_opcode = I2CR_IEN_OPCODE_0,
};
static const struct platform_device_id imx_i2c_devtype[] = {
@@ -288,6 +341,7 @@ static const struct of_device_id i2c_imx_dt_ids[] = {
{ .compatible = "fsl,imx8mp-i2c", .data = &imx6_i2c_hwdata, },
{ .compatible = "fsl,imx8mq-i2c", .data = &imx6_i2c_hwdata, },
{ .compatible = "fsl,vf610-i2c", .data = &vf610_i2c_hwdata, },
+ { .compatible = "nxp,s32g2-i2c", .data = &s32g2_i2c_hwdata, },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, i2c_imx_dt_ids);
@@ -481,6 +535,9 @@ static int i2c_imx_bus_busy(struct imx_i2c_struct *i2c_imx, int for_busy, bool a
unsigned long orig_jiffies = jiffies;
unsigned int temp;
+ if (!i2c_imx->multi_master)
+ return 0;
+
while (1) {
temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2SR);
@@ -540,8 +597,8 @@ static int i2c_imx_trx_complete(struct imx_i2c_struct *i2c_imx, bool atomic)
return -ETIMEDOUT;
}
- /* check for arbitration lost */
- if (i2c_imx->i2csr & I2SR_IAL) {
+ /* In multi-master mode check for arbitration lost */
+ if (i2c_imx->multi_master && (i2c_imx->i2csr & I2SR_IAL)) {
dev_dbg(&i2c_imx->adapter.dev, "<%s> Arbitration lost\n", __func__);
i2c_imx_clear_irq(i2c_imx, I2SR_IAL);
@@ -903,11 +960,156 @@ static int i2c_imx_unreg_slave(struct i2c_client *client)
return ret;
}
+static inline int i2c_imx_isr_acked(struct imx_i2c_struct *i2c_imx)
+{
+ i2c_imx->isr_result = 0;
+
+ if (imx_i2c_read_reg(i2c_imx, IMX_I2C_I2SR) & I2SR_RXAK) {
+ i2c_imx->state = IMX_I2C_STATE_FAILED;
+ i2c_imx->isr_result = -ENXIO;
+ wake_up(&i2c_imx->queue);
+ }
+
+ return i2c_imx->isr_result;
+}
+
+static inline int i2c_imx_isr_write(struct imx_i2c_struct *i2c_imx)
+{
+ int result;
+
+ result = i2c_imx_isr_acked(i2c_imx);
+ if (result)
+ return result;
+
+ if (i2c_imx->msg->len == i2c_imx->msg_buf_idx)
+ return 0;
+
+ imx_i2c_write_reg(i2c_imx->msg->buf[i2c_imx->msg_buf_idx++], i2c_imx, IMX_I2C_I2DR);
+
+ return 1;
+}
+
+static inline int i2c_imx_isr_read(struct imx_i2c_struct *i2c_imx)
+{
+ int result;
+ unsigned int temp;
+
+ result = i2c_imx_isr_acked(i2c_imx);
+ if (result)
+ return result;
+
+ /* setup bus to read data */
+ temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
+ temp &= ~I2CR_MTX;
+ if (i2c_imx->msg->len - 1)
+ temp &= ~I2CR_TXAK;
+
+ imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
+ imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR); /* dummy read */
+
+ return 0;
+}
+
+static inline void i2c_imx_isr_read_continue(struct imx_i2c_struct *i2c_imx)
+{
+ unsigned int temp;
+
+ if ((i2c_imx->msg->len - 1) == i2c_imx->msg_buf_idx) {
+ if (i2c_imx->is_lastmsg) {
+ /*
+ * It must generate STOP before read I2DR to prevent
+ * controller from generating another clock cycle
+ */
+ temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
+ if (!(temp & I2CR_MSTA))
+ i2c_imx->stopped = 1;
+ temp &= ~(I2CR_MSTA | I2CR_MTX);
+ imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
+ } else {
+ /*
+ * For i2c master receiver repeat restart operation like:
+ * read -> repeat MSTA -> read/write
+ * The controller must set MTX before read the last byte in
+ * the first read operation, otherwise the first read cost
+ * one extra clock cycle.
+ */
+ temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
+ temp |= I2CR_MTX;
+ imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
+ }
+ } else if (i2c_imx->msg_buf_idx == (i2c_imx->msg->len - 2)) {
+ temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
+ temp |= I2CR_TXAK;
+ imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
+ }
+
+ i2c_imx->msg->buf[i2c_imx->msg_buf_idx++] = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR);
+}
+
+static inline void i2c_imx_isr_read_block_data_len(struct imx_i2c_struct *i2c_imx)
+{
+ u8 len = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR);
+
+ if (len == 0 || len > I2C_SMBUS_BLOCK_MAX) {
+ i2c_imx->isr_result = -EPROTO;
+ i2c_imx->state = IMX_I2C_STATE_FAILED;
+ wake_up(&i2c_imx->queue);
+ }
+ i2c_imx->msg->len += len;
+}
+
static irqreturn_t i2c_imx_master_isr(struct imx_i2c_struct *i2c_imx, unsigned int status)
{
- /* save status register */
- i2c_imx->i2csr = status;
- wake_up(&i2c_imx->queue);
+ /*
+ * This state machine handles I2C reception and transmission in non-DMA
+ * mode. We must process all the data in the ISR to reduce the delay
+ * between two consecutive messages. If the data is not processed in
+ * the ISR, SMBus devices may timeout, leading to a bus error.
+ */
+ switch (i2c_imx->state) {
+ case IMX_I2C_STATE_DMA:
+ i2c_imx->i2csr = status;
+ wake_up(&i2c_imx->queue);
+ break;
+
+ case IMX_I2C_STATE_READ:
+ if (i2c_imx_isr_read(i2c_imx))
+ break;
+ i2c_imx->state = IMX_I2C_STATE_READ_CONTINUE;
+ break;
+
+ case IMX_I2C_STATE_READ_CONTINUE:
+ i2c_imx_isr_read_continue(i2c_imx);
+ if (i2c_imx->msg_buf_idx == i2c_imx->msg->len) {
+ i2c_imx->state = IMX_I2C_STATE_DONE;
+ wake_up(&i2c_imx->queue);
+ }
+ break;
+
+ case IMX_I2C_STATE_READ_BLOCK_DATA:
+ if (i2c_imx_isr_read(i2c_imx))
+ break;
+ i2c_imx->state = IMX_I2C_STATE_READ_BLOCK_DATA_LEN;
+ break;
+
+ case IMX_I2C_STATE_READ_BLOCK_DATA_LEN:
+ i2c_imx_isr_read_block_data_len(i2c_imx);
+ i2c_imx->state = IMX_I2C_STATE_READ_CONTINUE;
+ break;
+
+ case IMX_I2C_STATE_WRITE:
+ if (i2c_imx_isr_write(i2c_imx))
+ break;
+ i2c_imx->state = IMX_I2C_STATE_DONE;
+ wake_up(&i2c_imx->queue);
+ break;
+
+ default:
+ i2c_imx->i2csr = status;
+ i2c_imx->state = IMX_I2C_STATE_FAILED;
+ i2c_imx->isr_result = -EINVAL;
+ wake_up(&i2c_imx->queue);
+ }
return IRQ_HANDLED;
}
@@ -954,6 +1156,8 @@ static int i2c_imx_dma_write(struct imx_i2c_struct *i2c_imx,
struct imx_i2c_dma *dma = i2c_imx->dma;
struct device *dev = &i2c_imx->adapter.dev;
+ i2c_imx->state = IMX_I2C_STATE_DMA;
+
dma->chan_using = dma->chan_tx;
dma->dma_transfer_dir = DMA_MEM_TO_DEV;
dma->dma_data_dir = DMA_TO_DEVICE;
@@ -1006,6 +1210,42 @@ static int i2c_imx_dma_write(struct imx_i2c_struct *i2c_imx,
return i2c_imx_acked(i2c_imx);
}
+static int i2c_imx_prepare_read(struct imx_i2c_struct *i2c_imx,
+ struct i2c_msg *msgs, bool use_dma)
+{
+ int result;
+ unsigned int temp = 0;
+
+ /* write slave address */
+ imx_i2c_write_reg(i2c_8bit_addr_from_msg(msgs), i2c_imx, IMX_I2C_I2DR);
+ result = i2c_imx_trx_complete(i2c_imx, !use_dma);
+ if (result)
+ return result;
+ result = i2c_imx_acked(i2c_imx);
+ if (result)
+ return result;
+
+ dev_dbg(&i2c_imx->adapter.dev, "<%s> setup bus\n", __func__);
+
+ /* setup bus to read data */
+ temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
+ temp &= ~I2CR_MTX;
+
+ /*
+ * Reset the I2CR_TXAK flag initially for SMBus block read since the
+ * length is unknown
+ */
+ if (msgs->len - 1)
+ temp &= ~I2CR_TXAK;
+ if (use_dma)
+ temp |= I2CR_DMAEN;
+
+ imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
+ imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR); /* dummy read */
+
+ return 0;
+}
+
static int i2c_imx_dma_read(struct imx_i2c_struct *i2c_imx,
struct i2c_msg *msgs, bool is_lastmsg)
{
@@ -1016,6 +1256,13 @@ static int i2c_imx_dma_read(struct imx_i2c_struct *i2c_imx,
struct imx_i2c_dma *dma = i2c_imx->dma;
struct device *dev = &i2c_imx->adapter.dev;
+ i2c_imx->state = IMX_I2C_STATE_DMA;
+
+ result = i2c_imx_prepare_read(i2c_imx, msgs, true);
+ if (result)
+ return result;
+
+ dev_dbg(&i2c_imx->adapter.dev, "<%s> read data\n", __func__);
dma->chan_using = dma->chan_rx;
dma->dma_transfer_dir = DMA_DEV_TO_MEM;
@@ -1092,8 +1339,8 @@ static int i2c_imx_dma_read(struct imx_i2c_struct *i2c_imx,
return 0;
}
-static int i2c_imx_write(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs,
- bool atomic)
+static int i2c_imx_atomic_write(struct imx_i2c_struct *i2c_imx,
+ struct i2c_msg *msgs)
{
int i, result;
@@ -1102,7 +1349,7 @@ static int i2c_imx_write(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs,
/* write slave address */
imx_i2c_write_reg(i2c_8bit_addr_from_msg(msgs), i2c_imx, IMX_I2C_I2DR);
- result = i2c_imx_trx_complete(i2c_imx, atomic);
+ result = i2c_imx_trx_complete(i2c_imx, true);
if (result)
return result;
result = i2c_imx_acked(i2c_imx);
@@ -1116,7 +1363,7 @@ static int i2c_imx_write(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs,
"<%s> write byte: B%d=0x%X\n",
__func__, i, msgs->buf[i]);
imx_i2c_write_reg(msgs->buf[i], i2c_imx, IMX_I2C_I2DR);
- result = i2c_imx_trx_complete(i2c_imx, atomic);
+ result = i2c_imx_trx_complete(i2c_imx, true);
if (result)
return result;
result = i2c_imx_acked(i2c_imx);
@@ -1126,55 +1373,54 @@ static int i2c_imx_write(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs,
return 0;
}
-static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs,
- bool is_lastmsg, bool atomic)
+static int i2c_imx_write(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs)
+{
+ dev_dbg(&i2c_imx->adapter.dev, "<%s> write slave address: addr=0x%x\n",
+ __func__, i2c_8bit_addr_from_msg(msgs));
+
+ i2c_imx->state = IMX_I2C_STATE_WRITE;
+ i2c_imx->msg = msgs;
+ i2c_imx->msg_buf_idx = 0;
+
+ /*
+ * By writing the device address we start the state machine in the ISR.
+ * The ISR will report when it is done or when it fails.
+ */
+ imx_i2c_write_reg(i2c_8bit_addr_from_msg(msgs), i2c_imx, IMX_I2C_I2DR);
+ wait_event_timeout(i2c_imx->queue,
+ i2c_imx->state == IMX_I2C_STATE_DONE ||
+ i2c_imx->state == IMX_I2C_STATE_FAILED,
+ (msgs->len + 1) * HZ / 10);
+ if (i2c_imx->state == IMX_I2C_STATE_FAILED) {
+ dev_dbg(&i2c_imx->adapter.dev, "<%s> write failed with %d\n",
+ __func__, i2c_imx->isr_result);
+ return i2c_imx->isr_result;
+ }
+ if (i2c_imx->state != IMX_I2C_STATE_DONE) {
+ dev_err(&i2c_imx->adapter.dev, "<%s> write timedout\n", __func__);
+ return -ETIMEDOUT;
+ }
+ return 0;
+}
+
+static int i2c_imx_atomic_read(struct imx_i2c_struct *i2c_imx,
+ struct i2c_msg *msgs, bool is_lastmsg)
{
int i, result;
unsigned int temp;
int block_data = msgs->flags & I2C_M_RECV_LEN;
- int use_dma = i2c_imx->dma && msgs->flags & I2C_M_DMA_SAFE &&
- msgs->len >= DMA_THRESHOLD && !block_data;
-
- dev_dbg(&i2c_imx->adapter.dev,
- "<%s> write slave address: addr=0x%x\n",
- __func__, i2c_8bit_addr_from_msg(msgs));
- /* write slave address */
- imx_i2c_write_reg(i2c_8bit_addr_from_msg(msgs), i2c_imx, IMX_I2C_I2DR);
- result = i2c_imx_trx_complete(i2c_imx, atomic);
- if (result)
- return result;
- result = i2c_imx_acked(i2c_imx);
+ result = i2c_imx_prepare_read(i2c_imx, msgs, false);
if (result)
return result;
- dev_dbg(&i2c_imx->adapter.dev, "<%s> setup bus\n", __func__);
-
- /* setup bus to read data */
- temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
- temp &= ~I2CR_MTX;
-
- /*
- * Reset the I2CR_TXAK flag initially for SMBus block read since the
- * length is unknown
- */
- if ((msgs->len - 1) || block_data)
- temp &= ~I2CR_TXAK;
- if (use_dma)
- temp |= I2CR_DMAEN;
- imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
- imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR); /* dummy read */
-
dev_dbg(&i2c_imx->adapter.dev, "<%s> read data\n", __func__);
- if (use_dma)
- return i2c_imx_dma_read(i2c_imx, msgs, is_lastmsg);
-
/* read data */
for (i = 0; i < msgs->len; i++) {
u8 len = 0;
- result = i2c_imx_trx_complete(i2c_imx, atomic);
+ result = i2c_imx_trx_complete(i2c_imx, true);
if (result)
return result;
/*
@@ -1205,7 +1451,7 @@ static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs,
temp &= ~(I2CR_MSTA | I2CR_MTX);
imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
if (!i2c_imx->stopped)
- i2c_imx_bus_busy(i2c_imx, 0, atomic);
+ i2c_imx_bus_busy(i2c_imx, 0, true);
} else {
/*
* For i2c master receiver repeat restart operation like:
@@ -1236,6 +1482,48 @@ static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs,
return 0;
}
+static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs,
+ bool is_lastmsg)
+{
+ int block_data = msgs->flags & I2C_M_RECV_LEN;
+
+ dev_dbg(&i2c_imx->adapter.dev,
+ "<%s> write slave address: addr=0x%x\n",
+ __func__, i2c_8bit_addr_from_msg(msgs));
+
+ i2c_imx->is_lastmsg = is_lastmsg;
+
+ if (block_data)
+ i2c_imx->state = IMX_I2C_STATE_READ_BLOCK_DATA;
+ else
+ i2c_imx->state = IMX_I2C_STATE_READ;
+ i2c_imx->msg = msgs;
+ i2c_imx->msg_buf_idx = 0;
+
+ /*
+ * By writing the device address we start the state machine in the ISR.
+ * The ISR will report when it is done or when it fails.
+ */
+ imx_i2c_write_reg(i2c_8bit_addr_from_msg(msgs), i2c_imx, IMX_I2C_I2DR);
+ wait_event_timeout(i2c_imx->queue,
+ i2c_imx->state == IMX_I2C_STATE_DONE ||
+ i2c_imx->state == IMX_I2C_STATE_FAILED,
+ (msgs->len + 1) * HZ / 10);
+ if (i2c_imx->state == IMX_I2C_STATE_FAILED) {
+ dev_dbg(&i2c_imx->adapter.dev, "<%s> read failed with %d\n",
+ __func__, i2c_imx->isr_result);
+ return i2c_imx->isr_result;
+ }
+ if (i2c_imx->state != IMX_I2C_STATE_DONE) {
+ dev_err(&i2c_imx->adapter.dev, "<%s> read timedout\n", __func__);
+ return -ETIMEDOUT;
+ }
+ if (!i2c_imx->stopped)
+ return i2c_imx_bus_busy(i2c_imx, 0, false);
+
+ return 0;
+}
+
static int i2c_imx_xfer_common(struct i2c_adapter *adapter,
struct i2c_msg *msgs, int num, bool atomic)
{
@@ -1243,6 +1531,7 @@ static int i2c_imx_xfer_common(struct i2c_adapter *adapter,
int result;
bool is_lastmsg = false;
struct imx_i2c_struct *i2c_imx = i2c_get_adapdata(adapter);
+ int use_dma = 0;
/* Start I2C transfer */
result = i2c_imx_start(i2c_imx, atomic);
@@ -1295,15 +1584,25 @@ static int i2c_imx_xfer_common(struct i2c_adapter *adapter,
(temp & I2SR_SRW ? 1 : 0), (temp & I2SR_IIF ? 1 : 0),
(temp & I2SR_RXAK ? 1 : 0));
#endif
+
+ use_dma = i2c_imx->dma && msgs[i].len >= DMA_THRESHOLD &&
+ msgs[i].flags & I2C_M_DMA_SAFE;
if (msgs[i].flags & I2C_M_RD) {
- result = i2c_imx_read(i2c_imx, &msgs[i], is_lastmsg, atomic);
+ int block_data = msgs->flags & I2C_M_RECV_LEN;
+
+ if (atomic)
+ result = i2c_imx_atomic_read(i2c_imx, &msgs[i], is_lastmsg);
+ else if (use_dma && !block_data)
+ result = i2c_imx_dma_read(i2c_imx, &msgs[i], is_lastmsg);
+ else
+ result = i2c_imx_read(i2c_imx, &msgs[i], is_lastmsg);
} else {
- if (!atomic &&
- i2c_imx->dma && msgs[i].len >= DMA_THRESHOLD &&
- msgs[i].flags & I2C_M_DMA_SAFE)
+ if (atomic)
+ result = i2c_imx_atomic_write(i2c_imx, &msgs[i]);
+ else if (use_dma)
result = i2c_imx_dma_write(i2c_imx, &msgs[i]);
else
- result = i2c_imx_write(i2c_imx, &msgs[i], atomic);
+ result = i2c_imx_write(i2c_imx, &msgs[i]);
}
if (result)
goto fail0;
@@ -1468,6 +1767,12 @@ static int i2c_imx_probe(struct platform_device *pdev)
goto rpm_disable;
}
+ /*
+ * We use the single-master property for backward compatibility.
+ * By default multi master mode is enabled.
+ */
+ i2c_imx->multi_master = !of_property_read_bool(pdev->dev.of_node, "single-master");
+
/* Set up clock divider */
i2c_imx->bitrate = I2C_MAX_STANDARD_MODE_FREQ;
ret = of_property_read_u32(pdev->dev.of_node,
@@ -1576,7 +1881,7 @@ static const struct dev_pm_ops i2c_imx_pm_ops = {
static struct platform_driver i2c_imx_driver = {
.probe = i2c_imx_probe,
- .remove_new = i2c_imx_remove,
+ .remove = i2c_imx_remove,
.driver = {
.name = DRIVER_NAME,
.pm = pm_ptr(&i2c_imx_pm_ops),