diff options
Diffstat (limited to 'drivers/i2c')
-rw-r--r-- | drivers/i2c/busses/i2c-imx-lpi2c.c | 256 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-imx.c | 37 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-qup.c | 4 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-riic.c | 54 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-st.c | 19 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-stm32f7.c | 3 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-tegra.c | 25 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-virtio.c | 15 | ||||
-rw-r--r-- | drivers/i2c/i2c-core-acpi.c | 2 | ||||
-rw-r--r-- | drivers/i2c/i2c-core-base.c | 10 | ||||
-rw-r--r-- | drivers/i2c/i2c-slave-eeprom.c | 4 | ||||
-rw-r--r-- | drivers/i2c/muxes/i2c-mux-pca954x.c | 3 |
12 files changed, 268 insertions, 164 deletions
diff --git a/drivers/i2c/busses/i2c-imx-lpi2c.c b/drivers/i2c/busses/i2c-imx-lpi2c.c index 064bc83840a6..03b5a7e8c361 100644 --- a/drivers/i2c/busses/i2c-imx-lpi2c.c +++ b/drivers/i2c/busses/i2c-imx-lpi2c.c @@ -16,6 +16,7 @@ #include <linux/init.h> #include <linux/interrupt.h> #include <linux/io.h> +#include <linux/iopoll.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/of.h> @@ -187,41 +188,48 @@ struct lpi2c_imx_struct { struct i2c_client *target; }; +#define lpi2c_imx_read_msr_poll_timeout(atomic, val, cond) \ + (atomic ? readl_poll_timeout_atomic(lpi2c_imx->base + LPI2C_MSR, val, \ + cond, 0, 500000) : \ + readl_poll_timeout(lpi2c_imx->base + LPI2C_MSR, val, cond, \ + 0, 500000)) + static void lpi2c_imx_intctrl(struct lpi2c_imx_struct *lpi2c_imx, unsigned int enable) { writel(enable, lpi2c_imx->base + LPI2C_MIER); } -static int lpi2c_imx_bus_busy(struct lpi2c_imx_struct *lpi2c_imx) +static int lpi2c_imx_bus_busy(struct lpi2c_imx_struct *lpi2c_imx, bool atomic) { - unsigned long orig_jiffies = jiffies; unsigned int temp; + int err; - while (1) { - temp = readl(lpi2c_imx->base + LPI2C_MSR); - - /* check for arbitration lost, clear if set */ - if (temp & MSR_ALF) { - writel(temp, lpi2c_imx->base + LPI2C_MSR); - return -EAGAIN; - } + err = lpi2c_imx_read_msr_poll_timeout(atomic, temp, + temp & (MSR_ALF | MSR_BBF | MSR_MBF)); - if (temp & (MSR_BBF | MSR_MBF)) - break; + /* check for arbitration lost, clear if set */ + if (temp & MSR_ALF) { + writel(temp, lpi2c_imx->base + LPI2C_MSR); + return -EAGAIN; + } - if (time_after(jiffies, orig_jiffies + msecs_to_jiffies(500))) { - dev_dbg(&lpi2c_imx->adapter.dev, "bus not work\n"); - if (lpi2c_imx->adapter.bus_recovery_info) - i2c_recover_bus(&lpi2c_imx->adapter); - return -ETIMEDOUT; - } - schedule(); + /* check for bus not busy */ + if (err) { + dev_dbg(&lpi2c_imx->adapter.dev, "bus not work\n"); + if (lpi2c_imx->adapter.bus_recovery_info) + i2c_recover_bus(&lpi2c_imx->adapter); + return -ETIMEDOUT; } return 0; } +static u32 lpi2c_imx_txfifo_cnt(struct lpi2c_imx_struct *lpi2c_imx) +{ + return readl(lpi2c_imx->base + LPI2C_MFSR) & 0xff; +} + static void lpi2c_imx_set_mode(struct lpi2c_imx_struct *lpi2c_imx) { unsigned int bitrate = lpi2c_imx->bitrate; @@ -242,7 +250,7 @@ static void lpi2c_imx_set_mode(struct lpi2c_imx_struct *lpi2c_imx) } static int lpi2c_imx_start(struct lpi2c_imx_struct *lpi2c_imx, - struct i2c_msg *msgs) + struct i2c_msg *msgs, bool atomic) { unsigned int temp; @@ -254,30 +262,23 @@ static int lpi2c_imx_start(struct lpi2c_imx_struct *lpi2c_imx, temp = i2c_8bit_addr_from_msg(msgs) | (GEN_START << 8); writel(temp, lpi2c_imx->base + LPI2C_MTDR); - return lpi2c_imx_bus_busy(lpi2c_imx); + return lpi2c_imx_bus_busy(lpi2c_imx, atomic); } -static void lpi2c_imx_stop(struct lpi2c_imx_struct *lpi2c_imx) +static void lpi2c_imx_stop(struct lpi2c_imx_struct *lpi2c_imx, bool atomic) { - unsigned long orig_jiffies = jiffies; unsigned int temp; + int err; writel(GEN_STOP << 8, lpi2c_imx->base + LPI2C_MTDR); - do { - temp = readl(lpi2c_imx->base + LPI2C_MSR); - if (temp & MSR_SDF) - break; - - if (time_after(jiffies, orig_jiffies + msecs_to_jiffies(500))) { - dev_dbg(&lpi2c_imx->adapter.dev, "stop timeout\n"); - if (lpi2c_imx->adapter.bus_recovery_info) - i2c_recover_bus(&lpi2c_imx->adapter); - break; - } - schedule(); + err = lpi2c_imx_read_msr_poll_timeout(atomic, temp, temp & MSR_SDF); - } while (1); + if (err) { + dev_dbg(&lpi2c_imx->adapter.dev, "stop timeout\n"); + if (lpi2c_imx->adapter.bus_recovery_info) + i2c_recover_bus(&lpi2c_imx->adapter); + } } /* CLKLO = I2C_CLK_RATIO * CLKHI, SETHOLD = CLKHI, DATAVD = CLKHI/2 */ @@ -391,28 +392,25 @@ static int lpi2c_imx_pio_msg_complete(struct lpi2c_imx_struct *lpi2c_imx) return time_left ? 0 : -ETIMEDOUT; } -static int lpi2c_imx_txfifo_empty(struct lpi2c_imx_struct *lpi2c_imx) +static int lpi2c_imx_txfifo_empty(struct lpi2c_imx_struct *lpi2c_imx, bool atomic) { - unsigned long orig_jiffies = jiffies; - u32 txcnt; - - do { - txcnt = readl(lpi2c_imx->base + LPI2C_MFSR) & 0xff; + unsigned int temp; + int err; - if (readl(lpi2c_imx->base + LPI2C_MSR) & MSR_NDF) { - dev_dbg(&lpi2c_imx->adapter.dev, "NDF detected\n"); - return -EIO; - } + err = lpi2c_imx_read_msr_poll_timeout(atomic, temp, + (temp & MSR_NDF) || !lpi2c_imx_txfifo_cnt(lpi2c_imx)); - if (time_after(jiffies, orig_jiffies + msecs_to_jiffies(500))) { - dev_dbg(&lpi2c_imx->adapter.dev, "txfifo empty timeout\n"); - if (lpi2c_imx->adapter.bus_recovery_info) - i2c_recover_bus(&lpi2c_imx->adapter); - return -ETIMEDOUT; - } - schedule(); + if (temp & MSR_NDF) { + dev_dbg(&lpi2c_imx->adapter.dev, "NDF detected\n"); + return -EIO; + } - } while (txcnt); + if (err) { + dev_dbg(&lpi2c_imx->adapter.dev, "txfifo empty timeout\n"); + if (lpi2c_imx->adapter.bus_recovery_info) + i2c_recover_bus(&lpi2c_imx->adapter); + return -ETIMEDOUT; + } return 0; } @@ -436,7 +434,7 @@ static void lpi2c_imx_set_rx_watermark(struct lpi2c_imx_struct *lpi2c_imx) writel(temp << 16, lpi2c_imx->base + LPI2C_MFCR); } -static void lpi2c_imx_write_txfifo(struct lpi2c_imx_struct *lpi2c_imx) +static bool lpi2c_imx_write_txfifo(struct lpi2c_imx_struct *lpi2c_imx, bool atomic) { unsigned int data, txcnt; @@ -451,13 +449,19 @@ static void lpi2c_imx_write_txfifo(struct lpi2c_imx_struct *lpi2c_imx) txcnt++; } - if (lpi2c_imx->delivered < lpi2c_imx->msglen) - lpi2c_imx_intctrl(lpi2c_imx, MIER_TDIE | MIER_NDIE); - else + if (lpi2c_imx->delivered < lpi2c_imx->msglen) { + if (!atomic) + lpi2c_imx_intctrl(lpi2c_imx, MIER_TDIE | MIER_NDIE); + return false; + } + + if (!atomic) complete(&lpi2c_imx->complete); + + return true; } -static void lpi2c_imx_read_rxfifo(struct lpi2c_imx_struct *lpi2c_imx) +static bool lpi2c_imx_read_rxfifo(struct lpi2c_imx_struct *lpi2c_imx, bool atomic) { unsigned int blocklen, remaining; unsigned int temp, data; @@ -482,8 +486,9 @@ static void lpi2c_imx_read_rxfifo(struct lpi2c_imx_struct *lpi2c_imx) remaining = lpi2c_imx->msglen - lpi2c_imx->delivered; if (!remaining) { - complete(&lpi2c_imx->complete); - return; + if (!atomic) + complete(&lpi2c_imx->complete); + return true; } /* not finished, still waiting for rx data */ @@ -501,7 +506,10 @@ static void lpi2c_imx_read_rxfifo(struct lpi2c_imx_struct *lpi2c_imx) writel(temp, lpi2c_imx->base + LPI2C_MTDR); } - lpi2c_imx_intctrl(lpi2c_imx, MIER_RDIE); + if (!atomic) + lpi2c_imx_intctrl(lpi2c_imx, MIER_RDIE); + + return false; } static void lpi2c_imx_write(struct lpi2c_imx_struct *lpi2c_imx, @@ -509,11 +517,29 @@ static void lpi2c_imx_write(struct lpi2c_imx_struct *lpi2c_imx, { lpi2c_imx->tx_buf = msgs->buf; lpi2c_imx_set_tx_watermark(lpi2c_imx); - lpi2c_imx_write_txfifo(lpi2c_imx); + lpi2c_imx_write_txfifo(lpi2c_imx, false); } -static void lpi2c_imx_read(struct lpi2c_imx_struct *lpi2c_imx, - struct i2c_msg *msgs) +static int lpi2c_imx_write_atomic(struct lpi2c_imx_struct *lpi2c_imx, + struct i2c_msg *msgs) +{ + u32 temp; + int err; + + lpi2c_imx->tx_buf = msgs->buf; + + err = lpi2c_imx_read_msr_poll_timeout(true, temp, + (temp & MSR_NDF) || + lpi2c_imx_write_txfifo(lpi2c_imx, true)); + + if (temp & MSR_NDF) + return -EIO; + + return err; +} + +static void lpi2c_imx_read_init(struct lpi2c_imx_struct *lpi2c_imx, + struct i2c_msg *msgs) { unsigned int temp; @@ -524,8 +550,43 @@ static void lpi2c_imx_read(struct lpi2c_imx_struct *lpi2c_imx, temp = msgs->len > CHUNK_DATA ? CHUNK_DATA - 1 : msgs->len - 1; temp |= (RECV_DATA << 8); writel(temp, lpi2c_imx->base + LPI2C_MTDR); +} + +static bool lpi2c_imx_read_chunk_atomic(struct lpi2c_imx_struct *lpi2c_imx) +{ + u32 rxcnt; + + rxcnt = (readl(lpi2c_imx->base + LPI2C_MFSR) >> 16) & 0xFF; + if (!rxcnt) + return false; + + if (!lpi2c_imx_read_rxfifo(lpi2c_imx, true)) + return false; + + return true; +} + +static int lpi2c_imx_read_atomic(struct lpi2c_imx_struct *lpi2c_imx, + struct i2c_msg *msgs) +{ + u32 temp; + int tmo_us; + + tmo_us = 1000000; + do { + if (lpi2c_imx_read_chunk_atomic(lpi2c_imx)) + return 0; + + temp = readl(lpi2c_imx->base + LPI2C_MSR); - lpi2c_imx_intctrl(lpi2c_imx, MIER_RDIE | MIER_NDIE); + if (temp & MSR_NDF) + return -EIO; + + udelay(100); + tmo_us -= 100; + } while (tmo_us > 0); + + return -ETIMEDOUT; } static bool is_use_dma(struct lpi2c_imx_struct *lpi2c_imx, struct i2c_msg *msg) @@ -545,14 +606,27 @@ static int lpi2c_imx_pio_xfer(struct lpi2c_imx_struct *lpi2c_imx, { reinit_completion(&lpi2c_imx->complete); - if (msg->flags & I2C_M_RD) - lpi2c_imx_read(lpi2c_imx, msg); - else + if (msg->flags & I2C_M_RD) { + lpi2c_imx_read_init(lpi2c_imx, msg); + lpi2c_imx_intctrl(lpi2c_imx, MIER_RDIE | MIER_NDIE); + } else { lpi2c_imx_write(lpi2c_imx, msg); + } return lpi2c_imx_pio_msg_complete(lpi2c_imx); } +static int lpi2c_imx_pio_xfer_atomic(struct lpi2c_imx_struct *lpi2c_imx, + struct i2c_msg *msg) +{ + if (msg->flags & I2C_M_RD) { + lpi2c_imx_read_init(lpi2c_imx, msg); + return lpi2c_imx_read_atomic(lpi2c_imx, msg); + } + + return lpi2c_imx_write_atomic(lpi2c_imx, msg); +} + static int lpi2c_imx_dma_timeout_calculate(struct lpi2c_imx_struct *lpi2c_imx) { unsigned long time = 0; @@ -563,7 +637,7 @@ static int lpi2c_imx_dma_timeout_calculate(struct lpi2c_imx_struct *lpi2c_imx) time += 1; /* Double calculated time */ - return msecs_to_jiffies(time * MSEC_PER_SEC); + return secs_to_jiffies(time); } static int lpi2c_imx_alloc_rx_cmd_buf(struct lpi2c_imx_struct *lpi2c_imx) @@ -947,8 +1021,8 @@ disable_dma: return ret; } -static int lpi2c_imx_xfer(struct i2c_adapter *adapter, - struct i2c_msg *msgs, int num) +static int lpi2c_imx_xfer_common(struct i2c_adapter *adapter, + struct i2c_msg *msgs, int num, bool atomic) { struct lpi2c_imx_struct *lpi2c_imx = i2c_get_adapdata(adapter); unsigned int temp; @@ -959,7 +1033,7 @@ static int lpi2c_imx_xfer(struct i2c_adapter *adapter, return result; for (i = 0; i < num; i++) { - result = lpi2c_imx_start(lpi2c_imx, &msgs[i]); + result = lpi2c_imx_start(lpi2c_imx, &msgs[i], atomic); if (result) goto disable; @@ -971,28 +1045,33 @@ static int lpi2c_imx_xfer(struct i2c_adapter *adapter, lpi2c_imx->tx_buf = NULL; lpi2c_imx->delivered = 0; lpi2c_imx->msglen = msgs[i].len; - init_completion(&lpi2c_imx->complete); - if (is_use_dma(lpi2c_imx, &msgs[i])) { - result = lpi2c_imx_dma_xfer(lpi2c_imx, &msgs[i]); - if (result && lpi2c_imx->dma->using_pio_mode) - result = lpi2c_imx_pio_xfer(lpi2c_imx, &msgs[i]); + if (atomic) { + result = lpi2c_imx_pio_xfer_atomic(lpi2c_imx, &msgs[i]); } else { - result = lpi2c_imx_pio_xfer(lpi2c_imx, &msgs[i]); + init_completion(&lpi2c_imx->complete); + + if (is_use_dma(lpi2c_imx, &msgs[i])) { + result = lpi2c_imx_dma_xfer(lpi2c_imx, &msgs[i]); + if (result && lpi2c_imx->dma->using_pio_mode) + result = lpi2c_imx_pio_xfer(lpi2c_imx, &msgs[i]); + } else { + result = lpi2c_imx_pio_xfer(lpi2c_imx, &msgs[i]); + } } if (result) goto stop; if (!(msgs[i].flags & I2C_M_RD)) { - result = lpi2c_imx_txfifo_empty(lpi2c_imx); + result = lpi2c_imx_txfifo_empty(lpi2c_imx, atomic); if (result) goto stop; } } stop: - lpi2c_imx_stop(lpi2c_imx); + lpi2c_imx_stop(lpi2c_imx, atomic); temp = readl(lpi2c_imx->base + LPI2C_MSR); if ((temp & MSR_NDF) && !result) @@ -1008,6 +1087,16 @@ disable: return (result < 0) ? result : num; } +static int lpi2c_imx_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num) +{ + return lpi2c_imx_xfer_common(adapter, msgs, num, false); +} + +static int lpi2c_imx_xfer_atomic(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num) +{ + return lpi2c_imx_xfer_common(adapter, msgs, num, true); +} + static irqreturn_t lpi2c_imx_target_isr(struct lpi2c_imx_struct *lpi2c_imx, u32 ssr, u32 sier_filter) { @@ -1070,9 +1159,9 @@ static irqreturn_t lpi2c_imx_master_isr(struct lpi2c_imx_struct *lpi2c_imx) if (temp & MSR_NDF) complete(&lpi2c_imx->complete); else if (temp & MSR_RDF) - lpi2c_imx_read_rxfifo(lpi2c_imx); + lpi2c_imx_read_rxfifo(lpi2c_imx, false); else if (temp & MSR_TDF) - lpi2c_imx_write_txfifo(lpi2c_imx); + lpi2c_imx_write_txfifo(lpi2c_imx, false); return IRQ_HANDLED; } @@ -1269,6 +1358,7 @@ static u32 lpi2c_imx_func(struct i2c_adapter *adapter) static const struct i2c_algorithm lpi2c_imx_algo = { .xfer = lpi2c_imx_xfer, + .xfer_atomic = lpi2c_imx_xfer_atomic, .functionality = lpi2c_imx_func, .reg_target = lpi2c_imx_register_target, .unreg_target = lpi2c_imx_unregister_target, diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c index 205cc132fdec..60f5c790ad7c 100644 --- a/drivers/i2c/busses/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c @@ -23,6 +23,7 @@ #include <linux/acpi.h> #include <linux/clk.h> +#include <linux/cleanup.h> #include <linux/completion.h> #include <linux/delay.h> #include <linux/dma-mapping.h> @@ -891,13 +892,13 @@ static enum hrtimer_restart i2c_imx_slave_timeout(struct hrtimer *t) struct imx_i2c_struct *i2c_imx = container_of(t, struct imx_i2c_struct, slave_timer); unsigned int ctl, status; - unsigned long flags; - spin_lock_irqsave(&i2c_imx->slave_lock, flags); + guard(spinlock_irqsave)(&i2c_imx->slave_lock); + status = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2SR); ctl = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR); i2c_imx_slave_handle(i2c_imx, status, ctl); - spin_unlock_irqrestore(&i2c_imx->slave_lock, flags); + return HRTIMER_NORESTART; } @@ -1126,32 +1127,26 @@ static irqreturn_t i2c_imx_isr(int irq, void *dev_id) { struct imx_i2c_struct *i2c_imx = dev_id; unsigned int ctl, status; - unsigned long flags; - spin_lock_irqsave(&i2c_imx->slave_lock, flags); - status = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2SR); - ctl = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR); + scoped_guard(spinlock_irqsave, &i2c_imx->slave_lock) { + status = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2SR); + ctl = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR); + + if (!(status & I2SR_IIF)) + return IRQ_NONE; - if (status & I2SR_IIF) { i2c_imx_clear_irq(i2c_imx, I2SR_IIF); + if (i2c_imx->slave) { - if (!(ctl & I2CR_MSTA)) { - irqreturn_t ret; - - ret = i2c_imx_slave_handle(i2c_imx, - status, ctl); - spin_unlock_irqrestore(&i2c_imx->slave_lock, - flags); - return ret; - } + if (!(ctl & I2CR_MSTA)) + return i2c_imx_slave_handle(i2c_imx, + status, ctl); + i2c_imx_slave_finish_op(i2c_imx); } - spin_unlock_irqrestore(&i2c_imx->slave_lock, flags); - return i2c_imx_master_isr(i2c_imx, status); } - spin_unlock_irqrestore(&i2c_imx->slave_lock, flags); - return IRQ_NONE; + return i2c_imx_master_isr(i2c_imx, status); } static int i2c_imx_dma_write(struct imx_i2c_struct *i2c_imx, diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c index 6059f585843e..fc348924d522 100644 --- a/drivers/i2c/busses/i2c-qup.c +++ b/drivers/i2c/busses/i2c-qup.c @@ -452,8 +452,10 @@ static int qup_i2c_bus_active(struct qup_i2c_dev *qup, int len) if (!(status & I2C_STATUS_BUS_ACTIVE)) break; - if (time_after(jiffies, timeout)) + if (time_after(jiffies, timeout)) { ret = -ETIMEDOUT; + break; + } usleep_range(len, len * 2); } diff --git a/drivers/i2c/busses/i2c-riic.c b/drivers/i2c/busses/i2c-riic.c index 23375f7fe3ad..9c164a4b9bb9 100644 --- a/drivers/i2c/busses/i2c-riic.c +++ b/drivers/i2c/busses/i2c-riic.c @@ -79,6 +79,7 @@ #define ICIER_SPIE BIT(3) #define ICSR2_NACKF BIT(4) +#define ICSR2_STOP BIT(3) #define ICBR_RESERVED GENMASK(7, 5) /* Should be 1 on writes */ @@ -102,6 +103,8 @@ enum riic_reg_list { struct riic_of_data { const u8 *regs; + const struct riic_irq_desc *irqs; + u8 num_irqs; bool fast_mode_plus; }; @@ -324,6 +327,19 @@ static irqreturn_t riic_stop_isr(int irq, void *data) return IRQ_HANDLED; } +static irqreturn_t riic_eei_isr(int irq, void *data) +{ + u8 icsr2 = riic_readb(data, RIIC_ICSR2); + + if (icsr2 & ICSR2_NACKF) + return riic_tend_isr(irq, data); + + if (icsr2 & ICSR2_STOP) + return riic_stop_isr(irq, data); + + return IRQ_NONE; +} + static u32 riic_func(struct i2c_adapter *adap) { return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; @@ -495,6 +511,13 @@ static const struct riic_irq_desc riic_irqs[] = { { .res_num = 5, .isr = riic_tend_isr, .name = "riic-nack" }, }; +static const struct riic_irq_desc riic_rzt2h_irqs[] = { + { .res_num = 0, .isr = riic_eei_isr, .name = "riic-eei" }, + { .res_num = 1, .isr = riic_rdrf_isr, .name = "riic-rxi" }, + { .res_num = 2, .isr = riic_tdre_isr, .name = "riic-txi" }, + { .res_num = 3, .isr = riic_tend_isr, .name = "riic-tei" }, +}; + static int riic_i2c_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -520,21 +543,23 @@ static int riic_i2c_probe(struct platform_device *pdev) return dev_err_probe(dev, PTR_ERR(riic->rstc), "failed to acquire deasserted reset\n"); - for (i = 0; i < ARRAY_SIZE(riic_irqs); i++) { + riic->info = of_device_get_match_data(dev); + + for (i = 0; i < riic->info->num_irqs; i++) { + const struct riic_irq_desc *irq_desc; int irq; - irq = platform_get_irq(pdev, riic_irqs[i].res_num); + irq_desc = &riic->info->irqs[i]; + irq = platform_get_irq(pdev, irq_desc->res_num); if (irq < 0) return irq; - ret = devm_request_irq(dev, irq, riic_irqs[i].isr, - 0, riic_irqs[i].name, riic); + ret = devm_request_irq(dev, irq, irq_desc->isr, 0, irq_desc->name, riic); if (ret) return dev_err_probe(dev, ret, "failed to request irq %s\n", - riic_irqs[i].name); + irq_desc->name); } - riic->info = of_device_get_match_data(dev); adap = &riic->adapter; i2c_set_adapdata(adap, riic); @@ -606,11 +631,15 @@ static const u8 riic_rz_a_regs[RIIC_REG_END] = { static const struct riic_of_data riic_rz_a_info = { .regs = riic_rz_a_regs, + .irqs = riic_irqs, + .num_irqs = ARRAY_SIZE(riic_irqs), .fast_mode_plus = true, }; static const struct riic_of_data riic_rz_a1h_info = { .regs = riic_rz_a_regs, + .irqs = riic_irqs, + .num_irqs = ARRAY_SIZE(riic_irqs), }; static const u8 riic_rz_v2h_regs[RIIC_REG_END] = { @@ -630,9 +659,17 @@ static const u8 riic_rz_v2h_regs[RIIC_REG_END] = { static const struct riic_of_data riic_rz_v2h_info = { .regs = riic_rz_v2h_regs, + .irqs = riic_irqs, + .num_irqs = ARRAY_SIZE(riic_irqs), .fast_mode_plus = true, }; +static const struct riic_of_data riic_rz_t2h_info = { + .regs = riic_rz_v2h_regs, + .irqs = riic_rzt2h_irqs, + .num_irqs = ARRAY_SIZE(riic_rzt2h_irqs), +}; + static int riic_i2c_suspend(struct device *dev) { struct riic_dev *riic = dev_get_drvdata(dev); @@ -683,10 +720,11 @@ static const struct dev_pm_ops riic_i2c_pm_ops = { }; static const struct of_device_id riic_i2c_dt_ids[] = { - { .compatible = "renesas,riic-rz", .data = &riic_rz_a_info }, { .compatible = "renesas,riic-r7s72100", .data = &riic_rz_a1h_info, }, { .compatible = "renesas,riic-r9a09g057", .data = &riic_rz_v2h_info }, - { /* Sentinel */ }, + { .compatible = "renesas,riic-r9a09g077", .data = &riic_rz_t2h_info }, + { .compatible = "renesas,riic-rz", .data = &riic_rz_a_info }, + { /* Sentinel */ } }; static struct platform_driver riic_i2c_driver = { diff --git a/drivers/i2c/busses/i2c-st.c b/drivers/i2c/busses/i2c-st.c index 750fff3d2389..bf28f8e3ee6b 100644 --- a/drivers/i2c/busses/i2c-st.c +++ b/drivers/i2c/busses/i2c-st.c @@ -13,6 +13,7 @@ #include <linux/i2c.h> #include <linux/interrupt.h> #include <linux/io.h> +#include <linux/minmax.h> #include <linux/module.h> #include <linux/of_address.h> #include <linux/of_irq.h> @@ -422,12 +423,8 @@ static void st_i2c_wr_fill_tx_fifo(struct st_i2c_dev *i2c_dev) tx_fstat = readl_relaxed(i2c_dev->base + SSC_TX_FSTAT); tx_fstat &= SSC_TX_FSTAT_STATUS; - if (c->count < (SSC_TXFIFO_SIZE - tx_fstat)) - i = c->count; - else - i = SSC_TXFIFO_SIZE - tx_fstat; - - for (; i > 0; i--, c->count--, c->buf++) + for (i = min(c->count, SSC_TXFIFO_SIZE - tx_fstat); + i > 0; i--, c->count--, c->buf++) st_i2c_write_tx_fifo(i2c_dev, *c->buf); } @@ -439,7 +436,7 @@ static void st_i2c_wr_fill_tx_fifo(struct st_i2c_dev *i2c_dev) * This functions fills the Tx FIFO with fixed pattern when * in read mode to trigger clock. */ -static void st_i2c_rd_fill_tx_fifo(struct st_i2c_dev *i2c_dev, int max) +static void st_i2c_rd_fill_tx_fifo(struct st_i2c_dev *i2c_dev, u32 max) { struct st_i2c_client *c = &i2c_dev->client; u32 tx_fstat, sta; @@ -452,12 +449,8 @@ static void st_i2c_rd_fill_tx_fifo(struct st_i2c_dev *i2c_dev, int max) tx_fstat = readl_relaxed(i2c_dev->base + SSC_TX_FSTAT); tx_fstat &= SSC_TX_FSTAT_STATUS; - if (max < (SSC_TXFIFO_SIZE - tx_fstat)) - i = max; - else - i = SSC_TXFIFO_SIZE - tx_fstat; - - for (; i > 0; i--, c->xfered++) + for (i = min(max, SSC_TXFIFO_SIZE - tx_fstat); + i > 0; i--, c->xfered++) st_i2c_write_tx_fifo(i2c_dev, 0xff); } diff --git a/drivers/i2c/busses/i2c-stm32f7.c b/drivers/i2c/busses/i2c-stm32f7.c index 73a7b8894c0d..c8b4b404f6c1 100644 --- a/drivers/i2c/busses/i2c-stm32f7.c +++ b/drivers/i2c/busses/i2c-stm32f7.c @@ -34,6 +34,7 @@ #include <linux/regmap.h> #include <linux/reset.h> #include <linux/slab.h> +#include <linux/string_choices.h> #include "i2c-stm32.h" @@ -722,7 +723,7 @@ static int stm32f7_i2c_setup_timing(struct stm32f7_i2c_dev *i2c_dev, dev_dbg(i2c_dev->dev, "I2C Rise(%i) and Fall(%i) Time\n", setup->rise_time, setup->fall_time); dev_dbg(i2c_dev->dev, "I2C Analog Filter(%s), DNF(%i)\n", - (i2c_dev->analog_filter ? "On" : "Off"), i2c_dev->dnf); + str_on_off(i2c_dev->analog_filter), i2c_dev->dnf); i2c_dev->bus_rate = setup->speed_freq; diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index 0862b98007f5..4f05afab161f 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -253,6 +253,7 @@ struct tegra_i2c_hw_feature { * @dma_phys: handle to DMA resources * @dma_buf: pointer to allocated DMA buffer * @dma_buf_size: DMA buffer size + * @dma_dev: DMA device used for transfers * @dma_mode: indicates active DMA transfer * @dma_complete: DMA completion notifier * @atomic_mode: indicates active atomic transfer @@ -607,7 +608,6 @@ static int tegra_i2c_wait_for_config_load(struct tegra_i2c_dev *i2c_dev) static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev) { u32 val, clk_divisor, clk_multiplier, tsu_thd, tlow, thigh, non_hs_mode; - acpi_handle handle = ACPI_HANDLE(i2c_dev->dev); struct i2c_timings *t = &i2c_dev->timings; int err; @@ -619,11 +619,7 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev) * emit a noisy warning on error, which won't stay unnoticed and * won't hose machine entirely. */ - if (handle) - err = acpi_evaluate_object(handle, "_RST", NULL, NULL); - else - err = reset_control_reset(i2c_dev->rst); - + err = device_reset(i2c_dev->dev); WARN_ON_ONCE(err); if (IS_DVC(i2c_dev)) @@ -1666,19 +1662,6 @@ static void tegra_i2c_parse_dt(struct tegra_i2c_dev *i2c_dev) i2c_dev->is_vi = true; } -static int tegra_i2c_init_reset(struct tegra_i2c_dev *i2c_dev) -{ - if (ACPI_HANDLE(i2c_dev->dev)) - return 0; - - i2c_dev->rst = devm_reset_control_get_exclusive(i2c_dev->dev, "i2c"); - if (IS_ERR(i2c_dev->rst)) - return dev_err_probe(i2c_dev->dev, PTR_ERR(i2c_dev->rst), - "failed to get reset control\n"); - - return 0; -} - static int tegra_i2c_init_clocks(struct tegra_i2c_dev *i2c_dev) { int err; @@ -1788,10 +1771,6 @@ static int tegra_i2c_probe(struct platform_device *pdev) tegra_i2c_parse_dt(i2c_dev); - err = tegra_i2c_init_reset(i2c_dev); - if (err) - return err; - err = tegra_i2c_init_clocks(i2c_dev); if (err) return err; diff --git a/drivers/i2c/busses/i2c-virtio.c b/drivers/i2c/busses/i2c-virtio.c index 9b05ff53d3d7..af1381949f50 100644 --- a/drivers/i2c/busses/i2c-virtio.c +++ b/drivers/i2c/busses/i2c-virtio.c @@ -116,15 +116,16 @@ static int virtio_i2c_complete_reqs(struct virtqueue *vq, for (i = 0; i < num; i++) { struct virtio_i2c_req *req = &reqs[i]; - wait_for_completion(&req->completion); - - if (!failed && req->in_hdr.status != VIRTIO_I2C_MSG_OK) - failed = true; + if (!failed) { + if (wait_for_completion_interruptible(&req->completion)) + failed = true; + else if (req->in_hdr.status != VIRTIO_I2C_MSG_OK) + failed = true; + else + j++; + } i2c_put_dma_safe_msg_buf(reqs[i].buf, &msgs[i], !failed); - - if (!failed) - j++; } return j; diff --git a/drivers/i2c/i2c-core-acpi.c b/drivers/i2c/i2c-core-acpi.c index d2499f302b50..3445cc3b476b 100644 --- a/drivers/i2c/i2c-core-acpi.c +++ b/drivers/i2c/i2c-core-acpi.c @@ -250,7 +250,7 @@ static int i2c_acpi_get_info(struct acpi_device *adev, if (adapter) { /* The adapter must match the one in I2cSerialBus() connector */ - if (ACPI_HANDLE(&adapter->dev) != lookup.adapter_handle) + if (!device_match_acpi_handle(&adapter->dev, lookup.adapter_handle)) return -ENODEV; } else { struct acpi_device *adapter_adev; diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c index 2ad2b1838f0f..ecca8c006b02 100644 --- a/drivers/i2c/i2c-core-base.c +++ b/drivers/i2c/i2c-core-base.c @@ -573,7 +573,7 @@ static int i2c_device_probe(struct device *dev) goto err_clear_wakeup_irq; do_power_on = !i2c_acpi_waive_d0_probe(dev); - status = dev_pm_domain_attach(&client->dev, do_power_on); + status = dev_pm_domain_attach(&client->dev, do_power_on ? PD_FLAG_ATTACH_POWER_ON : 0); if (status) goto err_clear_wakeup_irq; @@ -1066,7 +1066,13 @@ void i2c_unregister_device(struct i2c_client *client) of_node_clear_flag(to_of_node(fwnode), OF_POPULATED); else if (is_acpi_device_node(fwnode)) acpi_device_clear_enumerated(to_acpi_device_node(fwnode)); - fwnode_handle_put(fwnode); + + /* + * If the primary fwnode is a software node it is free-ed by + * device_remove_software_node() below, avoid double-free. + */ + if (!is_software_node(fwnode)) + fwnode_handle_put(fwnode); device_remove_software_node(&client->dev); device_unregister(&client->dev); diff --git a/drivers/i2c/i2c-slave-eeprom.c b/drivers/i2c/i2c-slave-eeprom.c index 275d1d0e910f..6bc2ef650a74 100644 --- a/drivers/i2c/i2c-slave-eeprom.c +++ b/drivers/i2c/i2c-slave-eeprom.c @@ -165,8 +165,8 @@ static int i2c_slave_eeprom_probe(struct i2c_client *client) sysfs_bin_attr_init(&eeprom->bin); eeprom->bin.attr.name = "slave-eeprom"; eeprom->bin.attr.mode = S_IRUSR | S_IWUSR; - eeprom->bin.read_new = i2c_slave_eeprom_bin_read; - eeprom->bin.write_new = i2c_slave_eeprom_bin_write; + eeprom->bin.read = i2c_slave_eeprom_bin_read; + eeprom->bin.write = i2c_slave_eeprom_bin_write; eeprom->bin.size = size; ret = sysfs_create_bin_file(&client->dev.kobj, &eeprom->bin); diff --git a/drivers/i2c/muxes/i2c-mux-pca954x.c b/drivers/i2c/muxes/i2c-mux-pca954x.c index 5bb26af0f532..b9f370c9f018 100644 --- a/drivers/i2c/muxes/i2c-mux-pca954x.c +++ b/drivers/i2c/muxes/i2c-mux-pca954x.c @@ -442,8 +442,7 @@ static int pca954x_irq_setup(struct i2c_mux_core *muxc) raw_spin_lock_init(&data->lock); - data->irq = irq_domain_create_linear(of_fwnode_handle(client->dev.of_node), - data->chip->nchans, + data->irq = irq_domain_create_linear(dev_fwnode(&client->dev), data->chip->nchans, &irq_domain_simple_ops, data); if (!data->irq) return -ENODEV; |