diff options
Diffstat (limited to 'drivers/i2c')
24 files changed, 957 insertions, 424 deletions
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 7cb6b9b864a7..8c935f867a37 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -1211,8 +1211,7 @@ config I2C_SYNQUACER config I2C_TEGRA tristate "NVIDIA Tegra internal I2C controller" - depends on ARCH_TEGRA || (COMPILE_TEST && (ARC || ARM || ARM64 || M68K || RISCV || SUPERH || SPARC)) - # COMPILE_TEST needs architectures with readsX()/writesX() primitives + depends on ARCH_TEGRA || COMPILE_TEST depends on PINCTRL # ARCH_TEGRA implies PINCTRL, but the COMPILE_TEST side doesn't. help diff --git a/drivers/i2c/busses/i2c-cp2615.c b/drivers/i2c/busses/i2c-cp2615.c index 8212875700e1..951de6249834 100644 --- a/drivers/i2c/busses/i2c-cp2615.c +++ b/drivers/i2c/busses/i2c-cp2615.c @@ -270,8 +270,7 @@ static struct i2c_adapter_quirks cp2615_i2c_quirks = { .max_comb_2nd_msg_len = MAX_I2C_SIZE }; -static void -cp2615_i2c_remove(struct usb_interface *usbif) +static void cp2615_i2c_disconnect(struct usb_interface *usbif) { struct i2c_adapter *adap = usb_get_intfdata(usbif); @@ -328,7 +327,7 @@ MODULE_DEVICE_TABLE(usb, id_table); static struct usb_driver cp2615_i2c_driver = { .name = "i2c-cp2615", .probe = cp2615_i2c_probe, - .disconnect = cp2615_i2c_remove, + .disconnect = cp2615_i2c_disconnect, .id_table = id_table, }; diff --git a/drivers/i2c/busses/i2c-designware-amdisp.c b/drivers/i2c/busses/i2c-designware-amdisp.c index c48728ad9f6f..9f0ec0fae6f2 100644 --- a/drivers/i2c/busses/i2c-designware-amdisp.c +++ b/drivers/i2c/busses/i2c-designware-amdisp.c @@ -7,6 +7,7 @@ #include <linux/module.h> #include <linux/platform_device.h> +#include <linux/pm_domain.h> #include <linux/pm_runtime.h> #include <linux/soc/amd/isp4_misc.h> @@ -76,22 +77,20 @@ static int amd_isp_dw_i2c_plat_probe(struct platform_device *pdev) device_enable_async_suspend(&pdev->dev); - pm_runtime_enable(&pdev->dev); - pm_runtime_get_sync(&pdev->dev); - + dev_pm_genpd_resume(&pdev->dev); ret = i2c_dw_probe(isp_i2c_dev); if (ret) { dev_err_probe(&pdev->dev, ret, "i2c_dw_probe failed\n"); goto error_release_rpm; } - - pm_runtime_put_sync(&pdev->dev); + dev_pm_genpd_suspend(&pdev->dev); + pm_runtime_set_suspended(&pdev->dev); + pm_runtime_enable(&pdev->dev); return 0; error_release_rpm: amd_isp_dw_i2c_plat_pm_cleanup(isp_i2c_dev); - pm_runtime_put_sync(&pdev->dev); return ret; } diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c index 426ffec06e22..3351c4a9ef11 100644 --- a/drivers/i2c/busses/i2c-designware-platdrv.c +++ b/drivers/i2c/busses/i2c-designware-platdrv.c @@ -268,6 +268,7 @@ static const struct acpi_device_id dw_i2c_acpi_match[] = { { "AMDI0510", 0 }, { "APMC0D0F", 0 }, { "FUJI200B", 0 }, + { "GOOG5000", 0 }, { "HISI02A1", 0 }, { "HISI02A2", 0 }, { "HISI02A3", 0 }, diff --git a/drivers/i2c/busses/i2c-diolan-u2c.c b/drivers/i2c/busses/i2c-diolan-u2c.c index 077b093ba834..d502f6e4732f 100644 --- a/drivers/i2c/busses/i2c-diolan-u2c.c +++ b/drivers/i2c/busses/i2c-diolan-u2c.c @@ -427,12 +427,6 @@ static const struct usb_device_id diolan_u2c_table[] = { MODULE_DEVICE_TABLE(usb, diolan_u2c_table); -static void diolan_u2c_free(struct i2c_diolan_u2c *dev) -{ - usb_put_dev(dev->usb_dev); - kfree(dev); -} - static int diolan_u2c_probe(struct usb_interface *interface, const struct usb_device_id *id) { @@ -453,7 +447,7 @@ static int diolan_u2c_probe(struct usb_interface *interface, dev->ep_out = hostif->endpoint[0].desc.bEndpointAddress; dev->ep_in = hostif->endpoint[1].desc.bEndpointAddress; - dev->usb_dev = usb_get_dev(interface_to_usbdev(interface)); + dev->usb_dev = interface_to_usbdev(interface); dev->interface = interface; /* save our data pointer in this interface device */ @@ -488,7 +482,7 @@ static int diolan_u2c_probe(struct usb_interface *interface, error_free: usb_set_intfdata(interface, NULL); - diolan_u2c_free(dev); + kfree(dev); error: return ret; } @@ -499,7 +493,7 @@ static void diolan_u2c_disconnect(struct usb_interface *interface) i2c_del_adapter(&dev->adapter); usb_set_intfdata(interface, NULL); - diolan_u2c_free(dev); + kfree(dev); dev_dbg(&interface->dev, "disconnected\n"); } diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c index 85f554044cf1..a208fefd3c3b 100644 --- a/drivers/i2c/busses/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c @@ -401,7 +401,7 @@ static void i2c_imx_reset_regs(struct imx_i2c_struct *i2c_imx) static int i2c_imx_dma_request(struct imx_i2c_struct *i2c_imx, dma_addr_t phy_addr) { struct imx_i2c_dma *dma; - struct dma_slave_config dma_sconfig; + struct dma_slave_config dma_sconfig = {}; struct device *dev = i2c_imx->adapter.dev.parent; int ret; @@ -1018,8 +1018,9 @@ static inline int i2c_imx_isr_read(struct imx_i2c_struct *i2c_imx) return 0; } -static inline void i2c_imx_isr_read_continue(struct imx_i2c_struct *i2c_imx) +static inline enum imx_i2c_state i2c_imx_isr_read_continue(struct imx_i2c_struct *i2c_imx) { + enum imx_i2c_state next_state = IMX_I2C_STATE_READ_CONTINUE; unsigned int temp; if ((i2c_imx->msg->len - 1) == i2c_imx->msg_buf_idx) { @@ -1033,18 +1034,20 @@ static inline void i2c_imx_isr_read_continue(struct imx_i2c_struct *i2c_imx) 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); + + return IMX_I2C_STATE_DONE; } + /* + * 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); + next_state = IMX_I2C_STATE_DONE; } 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; @@ -1052,6 +1055,7 @@ static inline void i2c_imx_isr_read_continue(struct imx_i2c_struct *i2c_imx) } i2c_imx->msg->buf[i2c_imx->msg_buf_idx++] = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR); + return next_state; } static inline void i2c_imx_isr_read_block_data_len(struct imx_i2c_struct *i2c_imx) @@ -1088,11 +1092,9 @@ static irqreturn_t i2c_imx_master_isr(struct imx_i2c_struct *i2c_imx, unsigned i 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; + i2c_imx->state = i2c_imx_isr_read_continue(i2c_imx); + if (i2c_imx->state == IMX_I2C_STATE_DONE) wake_up(&i2c_imx->queue); - } break; case IMX_I2C_STATE_READ_BLOCK_DATA: @@ -1490,6 +1492,7 @@ 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; + int ret = 0; dev_dbg(&i2c_imx->adapter.dev, "<%s> write slave address: addr=0x%x\n", @@ -1522,10 +1525,20 @@ static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs, 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); + if (i2c_imx->is_lastmsg) { + if (!i2c_imx->stopped) + ret = i2c_imx_bus_busy(i2c_imx, 0, false); + /* + * Only read the last byte of the last message after the bus is + * not busy. Else the controller generates another clock which + * might confuse devices. + */ + if (!ret) + i2c_imx->msg->buf[i2c_imx->msg_buf_idx++] = imx_i2c_read_reg(i2c_imx, + IMX_I2C_I2DR); + } - return 0; + return ret; } static int i2c_imx_xfer_common(struct i2c_adapter *adapter, diff --git a/drivers/i2c/busses/i2c-k1.c b/drivers/i2c/busses/i2c-k1.c index 6e93da576bbd..9152cf436bea 100644 --- a/drivers/i2c/busses/i2c-k1.c +++ b/drivers/i2c/busses/i2c-k1.c @@ -98,6 +98,10 @@ #define SPACEMIT_BUS_RESET_CLK_CNT_MAX 9 +#define SPACEMIT_WAIT_TIMEOUT 1000 /* ms */ +#define SPACEMIT_POLL_TIMEOUT 1000 /* us */ +#define SPACEMIT_POLL_INTERVAL 30 /* us */ + enum spacemit_i2c_state { SPACEMIT_STATE_IDLE, SPACEMIT_STATE_START, @@ -126,6 +130,7 @@ struct spacemit_i2c_dev { enum spacemit_i2c_state state; bool read; + bool use_pio; struct completion complete; u32 status; }; @@ -172,6 +177,14 @@ static int spacemit_i2c_handle_err(struct spacemit_i2c_dev *i2c) return i2c->status & SPACEMIT_SR_ACKNAK ? -ENXIO : -EIO; } +static inline void spacemit_i2c_delay(struct spacemit_i2c_dev *i2c, unsigned int us) +{ + if (i2c->use_pio) + udelay(us); + else + fsleep(us); +} + static void spacemit_i2c_conditionally_reset_bus(struct spacemit_i2c_dev *i2c) { u32 status; @@ -183,7 +196,8 @@ static void spacemit_i2c_conditionally_reset_bus(struct spacemit_i2c_dev *i2c) return; spacemit_i2c_reset(i2c); - usleep_range(10, 20); + + spacemit_i2c_delay(i2c, 10); for (clk_cnt = 0; clk_cnt < SPACEMIT_BUS_RESET_CLK_CNT_MAX; clk_cnt++) { status = readl(i2c->base + SPACEMIT_IBMR); @@ -212,9 +226,15 @@ static int spacemit_i2c_wait_bus_idle(struct spacemit_i2c_dev *i2c) if (!(val & (SPACEMIT_SR_UB | SPACEMIT_SR_IBB))) return 0; - ret = readl_poll_timeout(i2c->base + SPACEMIT_ISR, - val, !(val & (SPACEMIT_SR_UB | SPACEMIT_SR_IBB)), - 1500, SPACEMIT_I2C_BUS_BUSY_TIMEOUT); + if (i2c->use_pio) + ret = readl_poll_timeout_atomic(i2c->base + SPACEMIT_ISR, + val, !(val & (SPACEMIT_SR_UB | SPACEMIT_SR_IBB)), + 1500, SPACEMIT_I2C_BUS_BUSY_TIMEOUT); + else + ret = readl_poll_timeout(i2c->base + SPACEMIT_ISR, + val, !(val & (SPACEMIT_SR_UB | SPACEMIT_SR_IBB)), + 1500, SPACEMIT_I2C_BUS_BUSY_TIMEOUT); + if (ret) spacemit_i2c_reset(i2c); @@ -226,7 +246,7 @@ static void spacemit_i2c_check_bus_release(struct spacemit_i2c_dev *i2c) /* in case bus is not released after transfer completes */ if (readl(i2c->base + SPACEMIT_ISR) & SPACEMIT_SR_EBB) { spacemit_i2c_conditionally_reset_bus(i2c); - usleep_range(90, 150); + spacemit_i2c_delay(i2c, 90); } } @@ -238,25 +258,33 @@ spacemit_i2c_clear_int_status(struct spacemit_i2c_dev *i2c, u32 mask) static void spacemit_i2c_init(struct spacemit_i2c_dev *i2c) { - u32 val; - - /* - * Unmask interrupt bits for all xfer mode: - * bus error, arbitration loss detected. - * For transaction complete signal, we use master stop - * interrupt, so we don't need to unmask SPACEMIT_CR_TXDONEIE. - */ - val = SPACEMIT_CR_BEIE | SPACEMIT_CR_ALDIE; - - /* - * Unmask interrupt bits for interrupt xfer mode: - * When IDBR receives a byte, an interrupt is triggered. - * - * For the tx empty interrupt, it will be enabled in the - * i2c_start function. - * Otherwise, it will cause an erroneous empty interrupt before i2c_start. - */ - val |= SPACEMIT_CR_DRFIE; + u32 val = 0; + + if (!i2c->use_pio) { + /* + * Enable interrupt bits for all xfer mode: + * bus error, arbitration loss detected. + */ + val |= SPACEMIT_CR_BEIE | SPACEMIT_CR_ALDIE; + + /* + * Unmask interrupt bits for interrupt xfer mode: + * When IDBR receives a byte, an interrupt is triggered. + * + * For the tx empty interrupt, it will be enabled in the + * i2c_start(). + * We don't want a TX empty interrupt until we start + * a transfer in i2c_start(). + */ + val |= SPACEMIT_CR_DRFIE; + + /* + * Enable master stop interrupt bit. + * For transaction complete signal, we use master stop + * interrupt, so we don't need to unmask SPACEMIT_CR_TXDONEIE. + */ + val |= SPACEMIT_CR_MSDIE; + } if (i2c->clock_freq == SPACEMIT_I2C_MAX_FAST_MODE_FREQ) val |= SPACEMIT_CR_MODE_FAST; @@ -268,7 +296,7 @@ static void spacemit_i2c_init(struct spacemit_i2c_dev *i2c) val |= SPACEMIT_CR_SCLE; /* enable master stop detected */ - val |= SPACEMIT_CR_MSDE | SPACEMIT_CR_MSDIE; + val |= SPACEMIT_CR_MSDE; writel(val, i2c->base + SPACEMIT_ICR); @@ -301,39 +329,13 @@ static void spacemit_i2c_start(struct spacemit_i2c_dev *i2c) /* send start pulse */ val = readl(i2c->base + SPACEMIT_ICR); val &= ~SPACEMIT_CR_STOP; - val |= SPACEMIT_CR_START | SPACEMIT_CR_TB | SPACEMIT_CR_DTEIE; - writel(val, i2c->base + SPACEMIT_ICR); -} - -static int spacemit_i2c_xfer_msg(struct spacemit_i2c_dev *i2c) -{ - unsigned long time_left; - struct i2c_msg *msg; + val |= SPACEMIT_CR_START | SPACEMIT_CR_TB; - for (i2c->msg_idx = 0; i2c->msg_idx < i2c->msg_num; i2c->msg_idx++) { - msg = &i2c->msgs[i2c->msg_idx]; - i2c->msg_buf = msg->buf; - i2c->unprocessed = msg->len; - i2c->status = 0; - - reinit_completion(&i2c->complete); - - spacemit_i2c_start(i2c); - - time_left = wait_for_completion_timeout(&i2c->complete, - i2c->adapt.timeout); - if (!time_left) { - dev_err(i2c->dev, "msg completion timeout\n"); - spacemit_i2c_conditionally_reset_bus(i2c); - spacemit_i2c_reset(i2c); - return -ETIMEDOUT; - } - - if (i2c->status & SPACEMIT_SR_ERR) - return spacemit_i2c_handle_err(i2c); - } + /* Enable the TX empty interrupt */ + if (!i2c->use_pio) + val |= SPACEMIT_CR_DTEIE; - return 0; + writel(val, i2c->base + SPACEMIT_ICR); } static bool spacemit_i2c_is_last_msg(struct spacemit_i2c_dev *i2c) @@ -347,8 +349,23 @@ static bool spacemit_i2c_is_last_msg(struct spacemit_i2c_dev *i2c) return !i2c->unprocessed; } +static inline void spacemit_i2c_complete(struct spacemit_i2c_dev *i2c) +{ + /* SPACEMIT_STATE_IDLE avoids triggering the next byte */ + i2c->state = SPACEMIT_STATE_IDLE; + + if (i2c->use_pio) + return; + + complete(&i2c->complete); +} + static void spacemit_i2c_handle_write(struct spacemit_i2c_dev *i2c) { + /* If there's no space in the IDBR, we're done */ + if (!(i2c->status & SPACEMIT_SR_ITE)) + return; + /* if transfer completes, SPACEMIT_ISR will handle it */ if (i2c->status & SPACEMIT_SR_MSD) return; @@ -359,16 +376,19 @@ static void spacemit_i2c_handle_write(struct spacemit_i2c_dev *i2c) return; } - /* SPACEMIT_STATE_IDLE avoids trigger next byte */ - i2c->state = SPACEMIT_STATE_IDLE; - complete(&i2c->complete); + spacemit_i2c_complete(i2c); } static void spacemit_i2c_handle_read(struct spacemit_i2c_dev *i2c) { + /* If there's nothing in the IDBR, we're done */ + if (!(i2c->status & SPACEMIT_SR_IRF)) + return; + if (i2c->unprocessed) { *i2c->msg_buf++ = readl(i2c->base + SPACEMIT_IDBR); i2c->unprocessed--; + return; } /* if transfer completes, SPACEMIT_ISR will handle it */ @@ -379,9 +399,7 @@ static void spacemit_i2c_handle_read(struct spacemit_i2c_dev *i2c) if (i2c->unprocessed) return; - /* SPACEMIT_STATE_IDLE avoids trigger next byte */ - i2c->state = SPACEMIT_STATE_IDLE; - complete(&i2c->complete); + spacemit_i2c_complete(i2c); } static void spacemit_i2c_handle_start(struct spacemit_i2c_dev *i2c) @@ -415,29 +433,16 @@ static void spacemit_i2c_err_check(struct spacemit_i2c_dev *i2c) spacemit_i2c_clear_int_status(i2c, SPACEMIT_I2C_INT_STATUS_MASK); - i2c->state = SPACEMIT_STATE_IDLE; - complete(&i2c->complete); + spacemit_i2c_complete(i2c); } -static irqreturn_t spacemit_i2c_irq_handler(int irq, void *devid) +static void spacemit_i2c_handle_state(struct spacemit_i2c_dev *i2c) { - struct spacemit_i2c_dev *i2c = devid; - u32 status, val; - - status = readl(i2c->base + SPACEMIT_ISR); - if (!status) - return IRQ_HANDLED; - - i2c->status = status; - - spacemit_i2c_clear_int_status(i2c, status); + u32 val; if (i2c->status & SPACEMIT_SR_ERR) goto err_out; - val = readl(i2c->base + SPACEMIT_ICR); - val &= ~(SPACEMIT_CR_TB | SPACEMIT_CR_ACKNAK | SPACEMIT_CR_STOP | SPACEMIT_CR_START); - switch (i2c->state) { case SPACEMIT_STATE_START: spacemit_i2c_handle_start(i2c); @@ -453,7 +458,12 @@ static irqreturn_t spacemit_i2c_irq_handler(int irq, void *devid) } if (i2c->state != SPACEMIT_STATE_IDLE) { - val |= SPACEMIT_CR_TB | SPACEMIT_CR_ALDIE; + val = readl(i2c->base + SPACEMIT_ICR); + val &= ~(SPACEMIT_CR_TB | SPACEMIT_CR_ACKNAK | + SPACEMIT_CR_STOP | SPACEMIT_CR_START); + val |= SPACEMIT_CR_TB; + if (!i2c->use_pio) + val |= SPACEMIT_CR_ALDIE; if (spacemit_i2c_is_last_msg(i2c)) { /* trigger next byte with stop */ @@ -467,6 +477,133 @@ static irqreturn_t spacemit_i2c_irq_handler(int irq, void *devid) err_out: spacemit_i2c_err_check(i2c); +} + +/* + * In PIO mode, this function is used as a replacement for + * wait_for_completion_timeout(), whose return value indicates + * the remaining time. + * + * We do not have a meaningful remaining-time value here, so + * return a non-zero value on success to indicate "not timed out". + * Returning 1 ensures callers treating the return value as + * time_left will not incorrectly report a timeout. + */ +static int spacemit_i2c_wait_pio_xfer(struct spacemit_i2c_dev *i2c) +{ + u32 mask, msec = jiffies_to_msecs(i2c->adapt.timeout); + ktime_t timeout = ktime_add_ms(ktime_get(), msec); + int ret; + + mask = SPACEMIT_SR_IRF | SPACEMIT_SR_ITE; + + do { + i2c->status = readl(i2c->base + SPACEMIT_ISR); + + spacemit_i2c_clear_int_status(i2c, i2c->status); + + if (i2c->status & mask) + spacemit_i2c_handle_state(i2c); + else + udelay(SPACEMIT_POLL_INTERVAL); + } while (i2c->unprocessed && ktime_compare(ktime_get(), timeout) < 0); + + if (i2c->unprocessed) + return 0; + + if (i2c->read) + return 1; + + /* + * If this is the last byte to write of the current message, + * we have to wait here. Otherwise, control will proceed directly + * to start(), which would overwrite the current data. + */ + ret = readl_poll_timeout_atomic(i2c->base + SPACEMIT_ISR, + i2c->status, i2c->status & SPACEMIT_SR_ITE, + SPACEMIT_POLL_INTERVAL, SPACEMIT_POLL_TIMEOUT); + if (ret) + return 0; + + /* + * For writes: in interrupt mode, an ITE (write-empty) interrupt is triggered + * after the last byte, and the MSD-related handling takes place there. + * In PIO mode, however, we need to explicitly call err_check() to emulate this + * step, otherwise the next transfer will fail. + */ + if (i2c->msg_idx == i2c->msg_num - 1) { + mask = SPACEMIT_SR_MSD | SPACEMIT_SR_ERR; + /* + * In some cases, MSD may not arrive immediately; + * wait here to handle that. + */ + ret = readl_poll_timeout_atomic(i2c->base + SPACEMIT_ISR, + i2c->status, i2c->status & mask, + SPACEMIT_POLL_INTERVAL, SPACEMIT_POLL_TIMEOUT); + if (ret) + return 0; + + spacemit_i2c_err_check(i2c); + } + + return 1; +} + +static int spacemit_i2c_wait_xfer_complete(struct spacemit_i2c_dev *i2c) +{ + if (i2c->use_pio) + return spacemit_i2c_wait_pio_xfer(i2c); + + return wait_for_completion_timeout(&i2c->complete, + i2c->adapt.timeout); +} + +static int spacemit_i2c_xfer_msg(struct spacemit_i2c_dev *i2c) +{ + unsigned long time_left; + struct i2c_msg *msg; + + for (i2c->msg_idx = 0; i2c->msg_idx < i2c->msg_num; i2c->msg_idx++) { + msg = &i2c->msgs[i2c->msg_idx]; + i2c->msg_buf = msg->buf; + i2c->unprocessed = msg->len; + i2c->status = 0; + + reinit_completion(&i2c->complete); + + spacemit_i2c_start(i2c); + + time_left = spacemit_i2c_wait_xfer_complete(i2c); + + if (!time_left) { + dev_err(i2c->dev, "msg completion timeout\n"); + spacemit_i2c_conditionally_reset_bus(i2c); + spacemit_i2c_reset(i2c); + return -ETIMEDOUT; + } + + if (i2c->status & SPACEMIT_SR_ERR) + return spacemit_i2c_handle_err(i2c); + } + + return 0; +} + +static irqreturn_t spacemit_i2c_irq_handler(int irq, void *devid) +{ + struct spacemit_i2c_dev *i2c = devid; + u32 status; + + status = readl(i2c->base + SPACEMIT_ISR); + if (!status) + return IRQ_HANDLED; + + i2c->status = status; + + spacemit_i2c_clear_int_status(i2c, status); + + spacemit_i2c_handle_state(i2c); + return IRQ_HANDLED; } @@ -475,6 +612,11 @@ static void spacemit_i2c_calc_timeout(struct spacemit_i2c_dev *i2c) unsigned long timeout; int idx = 0, cnt = 0; + if (i2c->use_pio) { + i2c->adapt.timeout = msecs_to_jiffies(SPACEMIT_WAIT_TIMEOUT); + return; + } + for (; idx < i2c->msg_num; idx++) cnt += (i2c->msgs + idx)->len + 1; @@ -487,11 +629,14 @@ static void spacemit_i2c_calc_timeout(struct spacemit_i2c_dev *i2c) i2c->adapt.timeout = usecs_to_jiffies(timeout + USEC_PER_SEC / 10) / i2c->msg_num; } -static int spacemit_i2c_xfer(struct i2c_adapter *adapt, struct i2c_msg *msgs, int num) +static inline int +spacemit_i2c_xfer_common(struct i2c_adapter *adapt, struct i2c_msg *msgs, int num, bool use_pio) { struct spacemit_i2c_dev *i2c = i2c_get_adapdata(adapt); int ret; + i2c->use_pio = use_pio; + i2c->msgs = msgs; i2c->msg_num = num; @@ -519,6 +664,16 @@ static int spacemit_i2c_xfer(struct i2c_adapter *adapt, struct i2c_msg *msgs, in return ret < 0 ? ret : num; } +static int spacemit_i2c_xfer(struct i2c_adapter *adapt, struct i2c_msg *msgs, int num) +{ + return spacemit_i2c_xfer_common(adapt, msgs, num, false); +} + +static int spacemit_i2c_pio_xfer_atomic(struct i2c_adapter *adapt, struct i2c_msg *msgs, int num) +{ + return spacemit_i2c_xfer_common(adapt, msgs, num, true); +} + static u32 spacemit_i2c_func(struct i2c_adapter *adap) { return I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK); @@ -526,6 +681,7 @@ static u32 spacemit_i2c_func(struct i2c_adapter *adap) static const struct i2c_algorithm spacemit_i2c_algo = { .xfer = spacemit_i2c_xfer, + .xfer_atomic = spacemit_i2c_pio_xfer_atomic, .functionality = spacemit_i2c_func, }; diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c index cb4d3aa709d0..126040ca05f1 100644 --- a/drivers/i2c/busses/i2c-mt65xx.c +++ b/drivers/i2c/busses/i2c-mt65xx.c @@ -21,6 +21,7 @@ #include <linux/module.h> #include <linux/of.h> #include <linux/platform_device.h> +#include <linux/regulator/consumer.h> #include <linux/scatterlist.h> #include <linux/sched.h> #include <linux/slab.h> @@ -1244,9 +1245,15 @@ static int mtk_i2c_transfer(struct i2c_adapter *adap, bool write_then_read_en = false; struct mtk_i2c *i2c = i2c_get_adapdata(adap); + if (i2c->adap.bus_regulator) { + ret = regulator_enable(i2c->adap.bus_regulator); + if (ret) + return ret; + } + ret = clk_bulk_enable(I2C_MT65XX_CLK_MAX, i2c->clocks); if (ret) - return ret; + goto err_regulator; i2c->auto_restart = i2c->dev_comp->auto_restart; @@ -1301,6 +1308,10 @@ static int mtk_i2c_transfer(struct i2c_adapter *adap, err_exit: clk_bulk_disable(I2C_MT65XX_CLK_MAX, i2c->clocks); +err_regulator: + if (i2c->adap.bus_regulator) + regulator_disable(i2c->adap.bus_regulator); + return ret; } diff --git a/drivers/i2c/busses/i2c-npcm7xx.c b/drivers/i2c/busses/i2c-npcm7xx.c index 8b7e15240fb0..f667a873b81e 100644 --- a/drivers/i2c/busses/i2c-npcm7xx.c +++ b/drivers/i2c/busses/i2c-npcm7xx.c @@ -1384,7 +1384,7 @@ static irqreturn_t npcm_i2c_int_slave_handler(struct npcm_i2c *bus) */ bus->operation = I2C_NO_OPER; bus->own_slave_addr = 0xFF; - i2c_slave_event(bus->slave, I2C_SLAVE_STOP, 0); + i2c_slave_event(bus->slave, I2C_SLAVE_STOP, NULL); iowrite8(NPCM_I2CST_SLVSTP, bus->reg + NPCM_I2CST); if (bus->fifo_use) { npcm_i2c_clear_fifo_int(bus); diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c index 0f67e57cdeff..df6ebf32d6e8 100644 --- a/drivers/i2c/busses/i2c-ocores.c +++ b/drivers/i2c/busses/i2c-ocores.c @@ -24,6 +24,7 @@ #include <linux/io.h> #include <linux/log2.h> #include <linux/spinlock.h> +#include <linux/iopoll.h> #include <linux/jiffies.h> /* @@ -258,7 +259,7 @@ static void ocores_process_timeout(struct ocores_i2c *i2c) * @reg: register to query * @mask: bitmask to apply on register value * @val: expected result - * @timeout: timeout in jiffies + * @timeout_us: timeout in microseconds * * Timeout is necessary to avoid to stay here forever when the chip * does not answer correctly. @@ -267,21 +268,14 @@ static void ocores_process_timeout(struct ocores_i2c *i2c) */ static int ocores_wait(struct ocores_i2c *i2c, int reg, u8 mask, u8 val, - const unsigned long timeout) + unsigned long timeout_us) { - unsigned long j; + u8 status; - j = jiffies + timeout; - while (1) { - u8 status = oc_getreg(i2c, reg); - - if ((status & mask) == val) - break; - - if (time_after(jiffies, j)) - return -ETIMEDOUT; - } - return 0; + return read_poll_timeout_atomic(oc_getreg, status, + (status & mask) == val, + 0, timeout_us, false, + i2c, reg); } /** @@ -314,7 +308,7 @@ static int ocores_poll_wait(struct ocores_i2c *i2c) * once we are here we expect to get the expected result immediately * so if after 1ms we timeout then something is broken. */ - err = ocores_wait(i2c, OCI2C_STATUS, mask, 0, msecs_to_jiffies(1)); + err = ocores_wait(i2c, OCI2C_STATUS, mask, 0, 1000); if (err) dev_warn(i2c->adap.dev.parent, "%s: STATUS timeout, bit 0x%x did not clear in 1ms\n", diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index d9f590f0c384..f02d294db42a 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -1453,27 +1453,16 @@ omap_i2c_probe(struct platform_device *pdev) (1000 * omap->speed / 8); } - if (of_property_present(node, "mux-states")) { - struct mux_state *mux_state; - - mux_state = devm_mux_state_get(&pdev->dev, NULL); - if (IS_ERR(mux_state)) { - r = PTR_ERR(mux_state); - dev_dbg(&pdev->dev, "failed to get I2C mux: %d\n", r); - goto err_put_pm; - } - omap->mux_state = mux_state; - r = mux_state_select(omap->mux_state); - if (r) { - dev_err(&pdev->dev, "failed to select I2C mux: %d\n", r); - goto err_put_pm; - } + omap->mux_state = devm_mux_state_get_optional_selected(&pdev->dev, NULL); + if (IS_ERR(omap->mux_state)) { + r = PTR_ERR(omap->mux_state); + goto err_put_pm; } /* reset ASAP, clearing any IRQs */ r = omap_i2c_init(omap); if (r) - goto err_mux_state_deselect; + goto err_put_pm; if (omap->rev < OMAP_I2C_OMAP1_REV_2) r = devm_request_irq(&pdev->dev, omap->irq, omap_i2c_omap1_isr, @@ -1515,9 +1504,6 @@ omap_i2c_probe(struct platform_device *pdev) err_unuse_clocks: omap_i2c_write_reg(omap, OMAP_I2C_CON_REG, 0); -err_mux_state_deselect: - if (omap->mux_state) - mux_state_deselect(omap->mux_state); err_put_pm: pm_runtime_put_sync(omap->dev); err_disable_pm: diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c index f55840b2eb9a..9a8b154ab69e 100644 --- a/drivers/i2c/busses/i2c-pxa.c +++ b/drivers/i2c/busses/i2c-pxa.c @@ -71,6 +71,7 @@ #define ISR_GCAD (1 << 8) /* general call address detected */ #define ISR_SAD (1 << 9) /* slave address detected */ #define ISR_BED (1 << 10) /* bus error no ACK/NAK */ +#define ISR_A3700_EBB (1 << 11) /* early bus busy for armada 3700 */ #define ILCR_SLV_SHIFT 0 #define ILCR_SLV_MASK (0x1FF << ILCR_SLV_SHIFT) @@ -263,6 +264,7 @@ struct pxa_i2c { bool highmode_enter; u32 fm_mask; u32 hs_mask; + u32 busy_mask; struct i2c_bus_recovery_info recovery; struct pinctrl *pinctrl; @@ -430,7 +432,7 @@ static int i2c_pxa_wait_bus_not_busy(struct pxa_i2c *i2c) while (1) { isr = readl(_ISR(i2c)); - if (!(isr & (ISR_IBB | ISR_UB))) + if (!(isr & i2c->busy_mask)) return 0; if (isr & ISR_SAD) @@ -467,7 +469,7 @@ static int i2c_pxa_wait_master(struct pxa_i2c *i2c) * quick check of the i2c lines themselves to ensure they've * gone high... */ - if ((readl(_ISR(i2c)) & (ISR_UB | ISR_IBB)) == 0 && + if ((readl(_ISR(i2c)) & i2c->busy_mask) == 0 && readl(_IBMR(i2c)) == (IBMR_SCLS | IBMR_SDAS)) { if (i2c_debug > 0) dev_dbg(&i2c->adap.dev, "%s: done\n", __func__); @@ -488,7 +490,7 @@ static int i2c_pxa_set_master(struct pxa_i2c *i2c) if (i2c_debug) dev_dbg(&i2c->adap.dev, "setting to bus master\n"); - if ((readl(_ISR(i2c)) & (ISR_UB | ISR_IBB)) != 0) { + if ((readl(_ISR(i2c)) & i2c->busy_mask) != 0) { dev_dbg(&i2c->adap.dev, "%s: unit is busy\n", __func__); if (!i2c_pxa_wait_master(i2c)) { dev_dbg(&i2c->adap.dev, "%s: error: unit busy\n", __func__); @@ -514,7 +516,7 @@ static int i2c_pxa_wait_slave(struct pxa_i2c *i2c) dev_dbg(&i2c->adap.dev, "%s: %ld: ISR=%08x, ICR=%08x, IBMR=%02x\n", __func__, (long)jiffies, readl(_ISR(i2c)), readl(_ICR(i2c)), readl(_IBMR(i2c))); - if ((readl(_ISR(i2c)) & (ISR_UB|ISR_IBB)) == 0 || + if ((readl(_ISR(i2c)) & i2c->busy_mask) == 0 || (readl(_ISR(i2c)) & ISR_SAD) != 0 || (readl(_ICR(i2c)) & ICR_SCLE) == 0) { if (i2c_debug > 1) @@ -1177,7 +1179,7 @@ static int i2c_pxa_pio_set_master(struct pxa_i2c *i2c) /* * Wait for the bus to become free. */ - while (timeout-- && readl(_ISR(i2c)) & (ISR_IBB | ISR_UB)) + while (timeout-- && readl(_ISR(i2c)) & i2c->busy_mask) udelay(1000); if (timeout < 0) { @@ -1322,7 +1324,7 @@ static void i2c_pxa_unprepare_recovery(struct i2c_adapter *adap) * handing control of the bus back to avoid the bus changing state. */ isr = readl(_ISR(i2c)); - if (isr & (ISR_UB | ISR_IBB)) { + if (isr & i2c->busy_mask) { dev_dbg(&i2c->adap.dev, "recovery: resetting controller, ISR=0x%08x\n", isr); i2c_pxa_do_reset(i2c); @@ -1479,6 +1481,10 @@ static int i2c_pxa_probe(struct platform_device *dev) i2c->fm_mask = pxa_reg_layout[i2c_type].fm; i2c->hs_mask = pxa_reg_layout[i2c_type].hs; + i2c->busy_mask = ISR_UB | ISR_IBB; + if (i2c_type == REGS_A3700) + i2c->busy_mask |= ISR_A3700_EBB; + if (i2c_type != REGS_CE4100) i2c->reg_isar = i2c->reg_base + pxa_reg_layout[i2c_type].isar; diff --git a/drivers/i2c/busses/i2c-qcom-cci.c b/drivers/i2c/busses/i2c-qcom-cci.c index 884055df1560..f3ccfbbc4bea 100644 --- a/drivers/i2c/busses/i2c-qcom-cci.c +++ b/drivers/i2c/busses/i2c-qcom-cci.c @@ -71,9 +71,6 @@ #define NUM_MASTERS 2 #define NUM_QUEUES 2 -/* Max number of resources + 1 for a NULL terminator */ -#define CCI_RES_MAX 6 - #define CCI_I2C_SET_PARAM 1 #define CCI_I2C_REPORT 8 #define CCI_I2C_WRITE 9 diff --git a/drivers/i2c/busses/i2c-qcom-geni.c b/drivers/i2c/busses/i2c-qcom-geni.c index a4acb78fafb6..a482a4c60744 100644 --- a/drivers/i2c/busses/i2c-qcom-geni.c +++ b/drivers/i2c/busses/i2c-qcom-geni.c @@ -625,8 +625,8 @@ static int geni_i2c_gpi(struct geni_i2c_dev *gi2c, struct i2c_msg msgs[], { struct gpi_i2c_config *peripheral; unsigned int flags; - void *dma_buf; - dma_addr_t addr; + void *dma_buf = NULL; + dma_addr_t addr = 0; enum dma_data_direction map_dirn; enum dma_transfer_direction dma_dirn; struct dma_async_tx_descriptor *desc; @@ -639,6 +639,16 @@ static int geni_i2c_gpi(struct geni_i2c_dev *gi2c, struct i2c_msg msgs[], gi2c_gpi_xfer = &gi2c->i2c_multi_desc_config; msg_idx = gi2c_gpi_xfer->msg_idx_cnt; + /* + * Skip TX DMA mapping for a read message (I2C_M_RD) to avoid + * programming an extra TX DMA TRE that would cause an unintended + * write cycle on the I2C bus before the actual read operation. + */ + if (op == I2C_WRITE && msgs[msg_idx].flags & I2C_M_RD) { + peripheral->multi_msg = true; + goto skip_tx_dma_map; + } + dma_buf = i2c_get_dma_safe_msg_buf(&msgs[msg_idx], 1); if (!dma_buf) { ret = -ENOMEM; @@ -658,6 +668,7 @@ static int geni_i2c_gpi(struct geni_i2c_dev *gi2c, struct i2c_msg msgs[], goto out; } +skip_tx_dma_map: if (gi2c->is_tx_multi_desc_xfer) { flags = DMA_CTRL_ACK; @@ -740,9 +751,12 @@ static int geni_i2c_gpi(struct geni_i2c_dev *gi2c, struct i2c_msg msgs[], return 0; err_config: - dma_unmap_single(gi2c->se.dev->parent, addr, - msgs[msg_idx].len, map_dirn); - i2c_put_dma_safe_msg_buf(dma_buf, &msgs[msg_idx], false); + /* Avoid DMA unmap as the write operation skipped DMA mapping */ + if (dma_buf) { + dma_unmap_single(gi2c->se.dev->parent, addr, + msgs[msg_idx].len, map_dirn); + i2c_put_dma_safe_msg_buf(dma_buf, &msgs[msg_idx], false); + } out: gi2c->err = ret; diff --git a/drivers/i2c/busses/i2c-robotfuzz-osif.c b/drivers/i2c/busses/i2c-robotfuzz-osif.c index e0a76fb5bc31..412fa8e37f69 100644 --- a/drivers/i2c/busses/i2c-robotfuzz-osif.c +++ b/drivers/i2c/busses/i2c-robotfuzz-osif.c @@ -141,7 +141,7 @@ static int osif_probe(struct usb_interface *interface, if (!priv) return -ENOMEM; - priv->usb_dev = usb_get_dev(interface_to_usbdev(interface)); + priv->usb_dev = interface_to_usbdev(interface); priv->interface = interface; usb_set_intfdata(interface, priv); @@ -163,7 +163,6 @@ static int osif_probe(struct usb_interface *interface, NULL, 0); if (ret) { dev_err(&interface->dev, "failure sending bit rate"); - usb_put_dev(priv->usb_dev); return ret; } @@ -184,7 +183,6 @@ static void osif_disconnect(struct usb_interface *interface) i2c_del_adapter(&(priv->adapter)); usb_set_intfdata(interface, NULL); - usb_put_dev(priv->usb_dev); } static struct usb_driver osif_driver = { diff --git a/drivers/i2c/busses/i2c-rtl9300.c b/drivers/i2c/busses/i2c-rtl9300.c index 672cb978066d..8cedffbb2964 100644 --- a/drivers/i2c/busses/i2c-rtl9300.c +++ b/drivers/i2c/busses/i2c-rtl9300.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only #include <linux/bits.h> +#include <linux/clk.h> #include <linux/i2c.h> #include <linux/i2c-mux.h> #include <linux/mod_devicetable.h> @@ -11,10 +12,16 @@ #include <linux/unaligned.h> enum rtl9300_bus_freq { - RTL9300_I2C_STD_FREQ, - RTL9300_I2C_FAST_FREQ, + RTL9300_I2C_STD_FREQ, // 100kHz + RTL9300_I2C_FAST_FREQ, // 400kHz + RTL9300_I2C_SUPER_FAST_FREQ, // 2.5MHz + RTL9300_I2C_SLOW_FREQ, // 50kHz }; +#define RTL9300_I2C_MAX_SUPER_FAST_FREQ 2500000 +#define RTL9300_I2C_MAX_SLOW_FREQ 50000 + + struct rtl9300_i2c; struct rtl9300_i2c_chan { @@ -22,6 +29,7 @@ struct rtl9300_i2c_chan { struct rtl9300_i2c *i2c; enum rtl9300_bus_freq bus_freq; u8 sda_num; + u32 clk_div; }; enum rtl9300_i2c_reg_scope { @@ -47,6 +55,9 @@ enum rtl9300_i2c_reg_fields { F_SCL_SEL, F_SDA_OUT_SEL, F_SDA_SEL, + F_BUSY, + F_CLK_DIV, + F_EXT_SCK_5MS, /* keep last */ F_NUM_FIELDS @@ -55,12 +66,22 @@ enum rtl9300_i2c_reg_fields { struct rtl9300_i2c_drv_data { struct rtl9300_i2c_reg_field field_desc[F_NUM_FIELDS]; int (*select_scl)(struct rtl9300_i2c *i2c, u8 scl); - u32 data_reg; + int (*config_chan)(struct rtl9300_i2c *i2c, struct rtl9300_i2c_chan *chan); + void (*config_clock)(u32 clock_freq, struct rtl9300_i2c_chan *chan); + int (*misc_init)(struct rtl9300_i2c *i2c); + u32 rd_reg; + u32 wd_reg; u8 max_nchan; + u8 max_data_len; + u8 reg_addr_8bit_len; }; #define RTL9300_I2C_MUX_NCHAN 8 #define RTL9310_I2C_MUX_NCHAN 12 +#define RTL9607_I2C_MUX_NCHAN 1 + +#define RTL9300_I2C_MAX_DATA_LEN 16 +#define RTL9607_I2C_MAX_DATA_LEN 4 struct rtl9300_i2c { struct regmap *regmap; @@ -68,10 +89,12 @@ struct rtl9300_i2c { struct rtl9300_i2c_chan chans[RTL9310_I2C_MUX_NCHAN]; struct regmap_field *fields[F_NUM_FIELDS]; u32 reg_base; - u32 data_reg; + u32 rd_reg; + u32 wd_reg; u8 scl_num; u8 sda_num; struct mutex lock; + struct clk *clk; }; DEFINE_GUARD(rtl9300_i2c, struct rtl9300_i2c *, mutex_lock(&_T->lock), mutex_unlock(&_T->lock)) @@ -99,6 +122,7 @@ struct rtl9300_i2c_xfer { #define RTL9300_I2C_MST_DATA_WORD2 0x10 #define RTL9300_I2C_MST_DATA_WORD3 0x14 #define RTL9300_I2C_MST_GLB_CTRL 0x384 +#define RTL9300_REG_ADDR_8BIT_LEN 1 #define RTL9310_I2C_MST_IF_CTRL 0x1004 #define RTL9310_I2C_MST_IF_SEL 0x1008 @@ -106,6 +130,14 @@ struct rtl9300_i2c_xfer { #define RTL9310_I2C_MST_MEMADDR_CTRL 0x4 #define RTL9310_I2C_MST_DATA_CTRL 0x8 +#define RTL9607_I2C_CONFIG 0x22f50 +#define RTL9607_IO_MODE_EN 0x23014 +#define RTL9607_I2C_IND_WD 0x0 +#define RTL9607_I2C_IND_ADR 0x8 +#define RTL9607_I2C_IND_CMD 0x10 +#define RTL9607_I2C_IND_RD 0x18 +#define RTL9607_REG_ADDR_8BIT_LEN 0 + static int rtl9300_i2c_reg_addr_set(struct rtl9300_i2c *i2c, u32 reg, u16 len) { int ret; @@ -157,6 +189,58 @@ static int rtl9300_i2c_config_chan(struct rtl9300_i2c *i2c, struct rtl9300_i2c_c return 0; } +static int rtl9607_i2c_config_chan(struct rtl9300_i2c *i2c, struct rtl9300_i2c_chan *chan) +{ + const struct rtl9300_i2c_drv_data *drv_data; + int ret; + + if (i2c->sda_num == chan->sda_num) + return 0; + + ret = regmap_field_write(i2c->fields[F_CLK_DIV], chan->clk_div); + if (ret) + return ret; + + drv_data = device_get_match_data(i2c->dev); + ret = drv_data->select_scl(i2c, i2c->scl_num); + if (ret) + return ret; + + i2c->sda_num = chan->sda_num; + return 0; +} + +static void rtl9300_i2c_config_clock(u32 clock_freq, struct rtl9300_i2c_chan *chan) +{ + struct rtl9300_i2c *i2c = chan->i2c; + + switch (clock_freq) { + case I2C_MAX_STANDARD_MODE_FREQ: + chan->bus_freq = RTL9300_I2C_STD_FREQ; + break; + case I2C_MAX_FAST_MODE_FREQ: + chan->bus_freq = RTL9300_I2C_FAST_FREQ; + break; + case RTL9300_I2C_MAX_SUPER_FAST_FREQ: + chan->bus_freq = RTL9300_I2C_SUPER_FAST_FREQ; + break; + case RTL9300_I2C_MAX_SLOW_FREQ: + chan->bus_freq = RTL9300_I2C_SLOW_FREQ; + break; + default: + dev_warn(i2c->dev, "SDA%d clock-frequency %d not supported using default\n", + chan->sda_num, clock_freq); + break; + } +} + +static void rtl9607_i2c_config_clock(u32 clock_freq, struct rtl9300_i2c_chan *chan) +{ + struct rtl9300_i2c *i2c = chan->i2c; + + chan->clk_div = clk_get_rate(i2c->clk) / clock_freq - 1; +} + static int rtl9300_i2c_read(struct rtl9300_i2c *i2c, u8 *buf, u8 len) { u32 vals[4] = {}; @@ -165,7 +249,7 @@ static int rtl9300_i2c_read(struct rtl9300_i2c *i2c, u8 *buf, u8 len) if (len > 16) return -EIO; - ret = regmap_bulk_read(i2c->regmap, i2c->data_reg, vals, ARRAY_SIZE(vals)); + ret = regmap_bulk_read(i2c->regmap, i2c->rd_reg, vals, ARRAY_SIZE(vals)); if (ret) return ret; @@ -192,19 +276,21 @@ static int rtl9300_i2c_write(struct rtl9300_i2c *i2c, u8 *buf, u8 len) vals[reg] |= buf[i] << shift; } - return regmap_bulk_write(i2c->regmap, i2c->data_reg, vals, ARRAY_SIZE(vals)); + return regmap_bulk_write(i2c->regmap, i2c->wd_reg, vals, ARRAY_SIZE(vals)); } static int rtl9300_i2c_writel(struct rtl9300_i2c *i2c, u32 data) { - return regmap_write(i2c->regmap, i2c->data_reg, data); + return regmap_write(i2c->regmap, i2c->wd_reg, data); } static int rtl9300_i2c_prepare_xfer(struct rtl9300_i2c *i2c, struct rtl9300_i2c_xfer *xfer) { + const struct rtl9300_i2c_drv_data *drv_data; int ret; - if (xfer->data_len < 1 || xfer->data_len > 16) + drv_data = device_get_match_data(i2c->dev); + if (xfer->data_len < 1 || xfer->data_len > drv_data->max_data_len) return -EINVAL; ret = regmap_field_write(i2c->fields[F_DEV_ADDR], xfer->dev_addr); @@ -249,7 +335,7 @@ static int rtl9300_i2c_do_xfer(struct rtl9300_i2c *i2c, struct rtl9300_i2c_xfer if (ret) return ret; - ret = regmap_field_read_poll_timeout(i2c->fields[F_I2C_TRIG], val, !val, 100, 100000); + ret = regmap_field_read_poll_timeout(i2c->fields[F_BUSY], val, !val, 100, 100000); if (ret) return ret; @@ -262,14 +348,14 @@ static int rtl9300_i2c_do_xfer(struct rtl9300_i2c *i2c, struct rtl9300_i2c_xfer if (!xfer->write) { switch (xfer->type) { case RTL9300_I2C_XFER_BYTE: - ret = regmap_read(i2c->regmap, i2c->data_reg, &val); + ret = regmap_read(i2c->regmap, i2c->rd_reg, &val); if (ret) return ret; *xfer->data = val & 0xff; break; case RTL9300_I2C_XFER_WORD: - ret = regmap_read(i2c->regmap, i2c->data_reg, &val); + ret = regmap_read(i2c->regmap, i2c->rd_reg, &val); if (ret) return ret; @@ -291,6 +377,7 @@ static int rtl9300_i2c_smbus_xfer(struct i2c_adapter *adap, u16 addr, unsigned s union i2c_smbus_data *data) { struct rtl9300_i2c_chan *chan = i2c_get_adapdata(adap); + const struct rtl9300_i2c_drv_data *drv_data; struct rtl9300_i2c *i2c = chan->i2c; struct rtl9300_i2c_xfer xfer = {0}; int ret; @@ -300,14 +387,15 @@ static int rtl9300_i2c_smbus_xfer(struct i2c_adapter *adap, u16 addr, unsigned s guard(rtl9300_i2c)(i2c); - ret = rtl9300_i2c_config_chan(i2c, chan); + drv_data = device_get_match_data(i2c->dev); + ret = drv_data->config_chan(i2c, chan); if (ret) return ret; xfer.dev_addr = addr & 0x7f; xfer.write = (read_write == I2C_SMBUS_WRITE); xfer.reg_addr = command; - xfer.reg_addr_len = 1; + xfer.reg_addr_len = drv_data->reg_addr_8bit_len; switch (size) { case I2C_SMBUS_BYTE: @@ -367,6 +455,17 @@ static struct i2c_adapter_quirks rtl9300_i2c_quirks = { .max_write_len = 16, }; +static int rtl9300_i2c_init(struct rtl9300_i2c *i2c) +{ + /* only use standard read format */ + return regmap_field_write(i2c->fields[F_RD_MODE], 0); +} + +static int rtl9607_i2c_init(struct rtl9300_i2c *i2c) +{ + return regmap_field_write(i2c->fields[F_EXT_SCK_5MS], 1); +} + static int rtl9300_i2c_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -402,7 +501,8 @@ static int rtl9300_i2c_probe(struct platform_device *pdev) if (device_get_child_node_count(dev) > drv_data->max_nchan) return dev_err_probe(dev, -EINVAL, "Too many channels\n"); - i2c->data_reg = i2c->reg_base + drv_data->data_reg; + i2c->rd_reg = i2c->reg_base + drv_data->rd_reg; + i2c->wd_reg = i2c->reg_base + drv_data->wd_reg; for (i = 0; i < F_NUM_FIELDS; i++) { fields[i] = drv_data->field_desc[i].field; if (drv_data->field_desc[i].scope == REG_SCOPE_MASTER) @@ -413,6 +513,10 @@ static int rtl9300_i2c_probe(struct platform_device *pdev) if (ret) return ret; + i2c->clk = devm_clk_get_optional_enabled(dev, NULL); + if (IS_ERR(i2c->clk)) + return dev_err_probe(dev, PTR_ERR(i2c->clk), "Failed to enable i2c clock\n"); + i = 0; for_each_child_of_node_scoped(dev->of_node, child) { struct rtl9300_i2c_chan *chan = &i2c->chans[i]; @@ -426,21 +530,11 @@ static int rtl9300_i2c_probe(struct platform_device *pdev) if (ret) clock_freq = I2C_MAX_STANDARD_MODE_FREQ; - switch (clock_freq) { - case I2C_MAX_STANDARD_MODE_FREQ: - chan->bus_freq = RTL9300_I2C_STD_FREQ; - break; - case I2C_MAX_FAST_MODE_FREQ: - chan->bus_freq = RTL9300_I2C_FAST_FREQ; - break; - default: - dev_warn(i2c->dev, "SDA%d clock-frequency %d not supported using default\n", - sda_num, clock_freq); - break; - } - chan->sda_num = sda_num; chan->i2c = i2c; + + drv_data->config_clock(clock_freq, chan); + adap = &i2c->chans[i].adap; adap->owner = THIS_MODULE; adap->algo = &rtl9300_i2c_algo; @@ -458,8 +552,7 @@ static int rtl9300_i2c_probe(struct platform_device *pdev) } i2c->sda_num = 0xff; - /* only use standard read format */ - ret = regmap_field_write(i2c->fields[F_RD_MODE], 0); + ret = drv_data->misc_init(i2c); if (ret) return ret; @@ -485,10 +578,17 @@ static const struct rtl9300_i2c_drv_data rtl9300_i2c_drv_data = { [F_MEM_ADDR_WIDTH] = MST_REG_FIELD(RTL9300_I2C_MST_CTRL2, 2, 3), [F_SCL_FREQ] = MST_REG_FIELD(RTL9300_I2C_MST_CTRL2, 0, 1), [F_SDA_SEL] = GLB_REG_FIELD(RTL9300_I2C_MST_GLB_CTRL, 0, 7), + [F_BUSY] = MST_REG_FIELD(RTL9300_I2C_MST_CTRL1, 0, 0), }, .select_scl = rtl9300_i2c_select_scl, - .data_reg = RTL9300_I2C_MST_DATA_WORD0, + .config_chan = rtl9300_i2c_config_chan, + .config_clock = rtl9300_i2c_config_clock, + .misc_init = rtl9300_i2c_init, + .rd_reg = RTL9300_I2C_MST_DATA_WORD0, + .wd_reg = RTL9300_I2C_MST_DATA_WORD0, .max_nchan = RTL9300_I2C_MUX_NCHAN, + .max_data_len = RTL9300_I2C_MAX_DATA_LEN, + .reg_addr_8bit_len = RTL9300_REG_ADDR_8BIT_LEN, }; static const struct rtl9300_i2c_drv_data rtl9310_i2c_drv_data = { @@ -505,10 +605,42 @@ static const struct rtl9300_i2c_drv_data rtl9310_i2c_drv_data = { [F_I2C_FAIL] = MST_REG_FIELD(RTL9310_I2C_MST_CTRL, 1, 1), [F_I2C_TRIG] = MST_REG_FIELD(RTL9310_I2C_MST_CTRL, 0, 0), [F_MEM_ADDR] = MST_REG_FIELD(RTL9310_I2C_MST_MEMADDR_CTRL, 0, 23), + [F_BUSY] = MST_REG_FIELD(RTL9310_I2C_MST_CTRL, 0, 0), }, .select_scl = rtl9310_i2c_select_scl, - .data_reg = RTL9310_I2C_MST_DATA_CTRL, + .config_chan = rtl9300_i2c_config_chan, + .config_clock = rtl9300_i2c_config_clock, + .misc_init = rtl9300_i2c_init, + .rd_reg = RTL9310_I2C_MST_DATA_CTRL, + .wd_reg = RTL9310_I2C_MST_DATA_CTRL, .max_nchan = RTL9310_I2C_MUX_NCHAN, + .max_data_len = RTL9300_I2C_MAX_DATA_LEN, + .reg_addr_8bit_len = RTL9300_REG_ADDR_8BIT_LEN, +}; + +static const struct rtl9300_i2c_drv_data rtl9607_i2c_drv_data = { + .field_desc = { + [F_SCL_SEL] = GLB_REG_FIELD(RTL9607_IO_MODE_EN, 13, 14), + [F_EXT_SCK_5MS] = MST_REG_FIELD(RTL9607_I2C_CONFIG, 26, 26), + [F_DEV_ADDR] = MST_REG_FIELD(RTL9607_I2C_CONFIG, 14, 20), + [F_MEM_ADDR_WIDTH] = MST_REG_FIELD(RTL9607_I2C_CONFIG, 12, 13), + [F_DATA_WIDTH] = MST_REG_FIELD(RTL9607_I2C_CONFIG, 10, 11), + [F_CLK_DIV] = MST_REG_FIELD(RTL9607_I2C_CONFIG, 0, 9), + [F_I2C_FAIL] = MST_REG_FIELD(RTL9607_I2C_IND_CMD, 3, 3), + [F_BUSY] = MST_REG_FIELD(RTL9607_I2C_IND_CMD, 2, 2), + [F_RWOP] = MST_REG_FIELD(RTL9607_I2C_IND_CMD, 1, 1), + [F_I2C_TRIG] = MST_REG_FIELD(RTL9607_I2C_IND_CMD, 0, 0), + [F_MEM_ADDR] = MST_REG_FIELD(RTL9607_I2C_IND_ADR, 0, 31), + }, + .select_scl = rtl9310_i2c_select_scl, + .config_chan = rtl9607_i2c_config_chan, + .config_clock = rtl9607_i2c_config_clock, + .misc_init = rtl9607_i2c_init, + .rd_reg = RTL9607_I2C_IND_RD, + .wd_reg = RTL9607_I2C_IND_WD, + .max_nchan = RTL9607_I2C_MUX_NCHAN, + .max_data_len = RTL9607_I2C_MAX_DATA_LEN, + .reg_addr_8bit_len = RTL9607_REG_ADDR_8BIT_LEN, }; static const struct of_device_id i2c_rtl9300_dt_ids[] = { @@ -520,6 +652,7 @@ static const struct of_device_id i2c_rtl9300_dt_ids[] = { { .compatible = "realtek,rtl9311-i2c", .data = (void *) &rtl9310_i2c_drv_data }, { .compatible = "realtek,rtl9312-i2c", .data = (void *) &rtl9310_i2c_drv_data }, { .compatible = "realtek,rtl9313-i2c", .data = (void *) &rtl9310_i2c_drv_data }, + { .compatible = "realtek,rtl9607-i2c", .data = (void *) &rtl9607_i2c_drv_data }, {} }; MODULE_DEVICE_TABLE(of, i2c_rtl9300_dt_ids); diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c index 8138f5ef40f0..15e14a6fe6dc 100644 --- a/drivers/i2c/busses/i2c-s3c2410.c +++ b/drivers/i2c/busses/i2c-s3c2410.c @@ -503,8 +503,13 @@ static void i2c_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat) i2c->msg->buf[i2c->msg_ptr++] = byte; /* Add actual length to read for smbus block read */ - if (i2c->msg->flags & I2C_M_RECV_LEN && i2c->msg->len == 1) + if (i2c->msg->flags & I2C_M_RECV_LEN && i2c->msg->len == 1) { + if (byte == 0 || byte > I2C_SMBUS_BLOCK_MAX) { + s3c24xx_i2c_stop(i2c, -EPROTO); + break; + } i2c->msg->len += byte; + } prepare_read: if (is_msglast(i2c)) { /* last byte of buffer */ diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index 4eaeb395d5db..9fd5ade774a0 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -30,38 +30,29 @@ #define BYTES_PER_FIFO_WORD 4 -#define I2C_CNFG 0x000 #define I2C_CNFG_DEBOUNCE_CNT GENMASK(14, 12) #define I2C_CNFG_PACKET_MODE_EN BIT(10) #define I2C_CNFG_NEW_MASTER_FSM BIT(11) #define I2C_CNFG_MULTI_MASTER_MODE BIT(17) -#define I2C_STATUS 0x01c -#define I2C_SL_CNFG 0x020 + #define I2C_SL_CNFG_NACK BIT(1) #define I2C_SL_CNFG_NEWSL BIT(2) -#define I2C_SL_ADDR1 0x02c -#define I2C_SL_ADDR2 0x030 -#define I2C_TLOW_SEXT 0x034 -#define I2C_TX_FIFO 0x050 -#define I2C_RX_FIFO 0x054 -#define I2C_PACKET_TRANSFER_STATUS 0x058 -#define I2C_FIFO_CONTROL 0x05c + #define I2C_FIFO_CONTROL_TX_FLUSH BIT(1) #define I2C_FIFO_CONTROL_RX_FLUSH BIT(0) #define I2C_FIFO_CONTROL_TX_TRIG(x) (((x) - 1) << 5) #define I2C_FIFO_CONTROL_RX_TRIG(x) (((x) - 1) << 2) -#define I2C_FIFO_STATUS 0x060 + #define I2C_FIFO_STATUS_TX GENMASK(7, 4) #define I2C_FIFO_STATUS_RX GENMASK(3, 0) -#define I2C_INT_MASK 0x064 -#define I2C_INT_STATUS 0x068 + #define I2C_INT_BUS_CLR_DONE BIT(11) #define I2C_INT_PACKET_XFER_COMPLETE BIT(7) #define I2C_INT_NO_ACK BIT(3) #define I2C_INT_ARBITRATION_LOST BIT(2) #define I2C_INT_TX_FIFO_DATA_REQ BIT(1) #define I2C_INT_RX_FIFO_DATA_REQ BIT(0) -#define I2C_CLK_DIVISOR 0x06c + #define I2C_CLK_DIVISOR_STD_FAST_MODE GENMASK(31, 16) #define I2C_CLK_DIVISOR_HSMODE GENMASK(15, 0) @@ -94,50 +85,38 @@ #define I2C_HEADER_CONTINUE_XFER BIT(15) #define I2C_HEADER_SLAVE_ADDR_SHIFT 1 -#define I2C_BUS_CLEAR_CNFG 0x084 #define I2C_BC_SCLK_THRESHOLD GENMASK(23, 16) #define I2C_BC_STOP_COND BIT(2) #define I2C_BC_TERMINATE BIT(1) #define I2C_BC_ENABLE BIT(0) -#define I2C_BUS_CLEAR_STATUS 0x088 + #define I2C_BC_STATUS BIT(0) -#define I2C_CONFIG_LOAD 0x08c #define I2C_MSTR_CONFIG_LOAD BIT(0) -#define I2C_CLKEN_OVERRIDE 0x090 #define I2C_MST_CORE_CLKEN_OVR BIT(0) -#define I2C_INTERFACE_TIMING_0 0x094 -#define I2C_INTERFACE_TIMING_THIGH GENMASK(13, 8) -#define I2C_INTERFACE_TIMING_TLOW GENMASK(5, 0) -#define I2C_INTERFACE_TIMING_1 0x098 -#define I2C_INTERFACE_TIMING_TBUF GENMASK(29, 24) -#define I2C_INTERFACE_TIMING_TSU_STO GENMASK(21, 16) -#define I2C_INTERFACE_TIMING_THD_STA GENMASK(13, 8) -#define I2C_INTERFACE_TIMING_TSU_STA GENMASK(5, 0) - -#define I2C_HS_INTERFACE_TIMING_0 0x09c -#define I2C_HS_INTERFACE_TIMING_THIGH GENMASK(13, 8) -#define I2C_HS_INTERFACE_TIMING_TLOW GENMASK(5, 0) -#define I2C_HS_INTERFACE_TIMING_1 0x0a0 -#define I2C_HS_INTERFACE_TIMING_TSU_STO GENMASK(21, 16) -#define I2C_HS_INTERFACE_TIMING_THD_STA GENMASK(13, 8) -#define I2C_HS_INTERFACE_TIMING_TSU_STA GENMASK(5, 0) - -#define I2C_MST_FIFO_CONTROL 0x0b4 +#define I2C_INTERFACE_TIMING_THIGH GENMASK(13, 8) +#define I2C_INTERFACE_TIMING_TLOW GENMASK(5, 0) +#define I2C_INTERFACE_TIMING_TBUF GENMASK(29, 24) +#define I2C_INTERFACE_TIMING_TSU_STO GENMASK(21, 16) +#define I2C_INTERFACE_TIMING_THD_STA GENMASK(13, 8) +#define I2C_INTERFACE_TIMING_TSU_STA GENMASK(5, 0) + +#define I2C_HS_INTERFACE_TIMING_THIGH GENMASK(13, 8) +#define I2C_HS_INTERFACE_TIMING_TLOW GENMASK(5, 0) +#define I2C_HS_INTERFACE_TIMING_TSU_STO GENMASK(21, 16) +#define I2C_HS_INTERFACE_TIMING_THD_STA GENMASK(13, 8) +#define I2C_HS_INTERFACE_TIMING_TSU_STA GENMASK(5, 0) + #define I2C_MST_FIFO_CONTROL_RX_FLUSH BIT(0) #define I2C_MST_FIFO_CONTROL_TX_FLUSH BIT(1) #define I2C_MST_FIFO_CONTROL_RX_TRIG(x) (((x) - 1) << 4) #define I2C_MST_FIFO_CONTROL_TX_TRIG(x) (((x) - 1) << 16) -#define I2C_MST_FIFO_STATUS 0x0b8 #define I2C_MST_FIFO_STATUS_TX GENMASK(23, 16) #define I2C_MST_FIFO_STATUS_RX GENMASK(7, 0) -#define I2C_MASTER_RESET_CNTRL 0x0a8 - -#define I2C_SW_MUTEX 0x0ec #define I2C_SW_MUTEX_REQUEST GENMASK(3, 0) #define I2C_SW_MUTEX_GRANT GENMASK(7, 4) #define I2C_SW_MUTEX_ID_CCPLEX 9 @@ -159,6 +138,171 @@ */ #define I2C_PIO_MODE_PREFERRED_LEN 32 +struct tegra_i2c_regs { + unsigned int cnfg; + unsigned int status; + unsigned int sl_cnfg; + unsigned int sl_addr1; + unsigned int sl_addr2; + unsigned int tlow_sext; + unsigned int tx_fifo; + unsigned int rx_fifo; + unsigned int packet_transfer_status; + unsigned int fifo_control; + unsigned int fifo_status; + unsigned int int_mask; + unsigned int int_status; + unsigned int clk_divisor; + unsigned int bus_clear_cnfg; + unsigned int bus_clear_status; + unsigned int config_load; + unsigned int clken_override; + unsigned int interface_timing_0; + unsigned int interface_timing_1; + unsigned int hs_interface_timing_0; + unsigned int hs_interface_timing_1; + unsigned int master_reset_cntrl; + unsigned int mst_fifo_control; + unsigned int mst_fifo_status; + unsigned int sw_mutex; +}; + +static const struct tegra_i2c_regs tegra20_i2c_regs = { + .cnfg = 0x000, + .status = 0x01c, + .sl_cnfg = 0x020, + .sl_addr1 = 0x02c, + .sl_addr2 = 0x030, + .tx_fifo = 0x050, + .rx_fifo = 0x054, + .packet_transfer_status = 0x058, + .fifo_control = 0x05c, + .fifo_status = 0x060, + .int_mask = 0x064, + .int_status = 0x068, + .clk_divisor = 0x06c, + .bus_clear_cnfg = 0x084, + .bus_clear_status = 0x088, + .config_load = 0x08c, + .clken_override = 0x090, + .interface_timing_0 = 0x094, + .interface_timing_1 = 0x098, + .hs_interface_timing_0 = 0x09c, + .hs_interface_timing_1 = 0x0a0, + .master_reset_cntrl = 0x0a8, + .mst_fifo_control = 0x0b4, + .mst_fifo_status = 0x0b8, +}; + +#if IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC) +static const struct tegra_i2c_regs tegra20_dvc_i2c_regs = { + .cnfg = 0x040, + .status = 0x05c, + .tx_fifo = 0x060, + .rx_fifo = 0x064, + .packet_transfer_status = 0x068, + .fifo_control = 0x06c, + .fifo_status = 0x070, + .int_mask = 0x074, + .int_status = 0x078, + .clk_divisor = 0x07c, + .bus_clear_cnfg = 0x094, + .bus_clear_status = 0x098, + .config_load = 0x09c, + .clken_override = 0x0a0, + .interface_timing_0 = 0x0a4, + .interface_timing_1 = 0x0a8, + .hs_interface_timing_0 = 0x0ac, + .hs_interface_timing_1 = 0x0b0, + .master_reset_cntrl = 0x0b8, + .mst_fifo_control = 0x0c4, + .mst_fifo_status = 0x0c8, +}; +#endif + +#if IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC) +static const struct tegra_i2c_regs tegra210_vi_i2c_regs = { + .cnfg = 0x0c00, + .status = 0x0c70, + .tlow_sext = 0x0cd0, + .tx_fifo = 0x0d40, + .rx_fifo = 0x0d50, + .packet_transfer_status = 0x0d60, + .fifo_control = 0x0d70, + .fifo_status = 0x0d80, + .int_mask = 0x0d90, + .int_status = 0x0da0, + .clk_divisor = 0x0db0, + .bus_clear_cnfg = 0x0e10, + .bus_clear_status = 0x0e20, + .config_load = 0x0e30, + .clken_override = 0x0e40, + .interface_timing_0 = 0x0e50, + .interface_timing_1 = 0x0e60, + .hs_interface_timing_0 = 0x0e70, + .hs_interface_timing_1 = 0x0e80, + .master_reset_cntrl = 0x0ea0, + .mst_fifo_control = 0x0ed0, + .mst_fifo_status = 0x0ee0, +}; +#endif + +static const struct tegra_i2c_regs tegra264_i2c_regs = { + .cnfg = 0x000, + .status = 0x01c, + .sl_cnfg = 0x020, + .sl_addr1 = 0x02c, + .sl_addr2 = 0x030, + .tx_fifo = 0x050, + .rx_fifo = 0x054, + .packet_transfer_status = 0x058, + .fifo_control = 0x05c, + .fifo_status = 0x060, + .int_mask = 0x064, + .int_status = 0x068, + .clk_divisor = 0x06c, + .bus_clear_cnfg = 0x084, + .bus_clear_status = 0x088, + .config_load = 0x08c, + .clken_override = 0x090, + .interface_timing_0 = 0x094, + .interface_timing_1 = 0x098, + .hs_interface_timing_0 = 0x09c, + .hs_interface_timing_1 = 0x0a0, + .master_reset_cntrl = 0x0a8, + .mst_fifo_control = 0x0b4, + .mst_fifo_status = 0x0b8, + .sw_mutex = 0x0ec, +}; + +static const struct tegra_i2c_regs tegra410_i2c_regs = { + .cnfg = 0x000, + .status = 0x01c, + .sl_cnfg = 0x020, + .sl_addr1 = 0x02c, + .sl_addr2 = 0x030, + .tx_fifo = 0x054, + .rx_fifo = 0x058, + .packet_transfer_status = 0x05c, + .fifo_control = 0x060, + .fifo_status = 0x064, + .int_mask = 0x068, + .int_status = 0x06c, + .clk_divisor = 0x070, + .bus_clear_cnfg = 0x088, + .bus_clear_status = 0x08c, + .config_load = 0x090, + .clken_override = 0x094, + .interface_timing_0 = 0x098, + .interface_timing_1 = 0x09c, + .hs_interface_timing_0 = 0x0a0, + .hs_interface_timing_1 = 0x0a4, + .master_reset_cntrl = 0x0ac, + .mst_fifo_control = 0x0b8, + .mst_fifo_status = 0x0bc, + .sw_mutex = 0x0f0, +}; + /* * msg_end_type: The bus control which needs to be sent at end of transfer. * @MSG_END_STOP: Send stop pulse. @@ -171,6 +315,18 @@ enum msg_end_type { MSG_END_CONTINUE, }; +/* + * tegra_i2c_variant: Identifies the variant of I2C controller. + * @TEGRA_I2C_VARIANT_DEFAULT: Identifies the default I2C controller. + * @TEGRA_I2C_VARIANT_DVC: Identifies the DVC I2C controller, has a different register layout. + * @TEGRA_I2C_VARIANT_VI: Identifies the VI I2C controller, has a different register layout. + */ +enum tegra_i2c_variant { + TEGRA_I2C_VARIANT_DEFAULT, + TEGRA_I2C_VARIANT_DVC, + TEGRA_I2C_VARIANT_VI, +}; + /** * struct tegra_i2c_hw_feature : per hardware generation features * @has_continue_xfer_support: continue-transfer supported @@ -223,6 +379,8 @@ enum msg_end_type { * timing settings. * @enable_hs_mode_support: Enable support for high speed (HS) mode transfers. * @has_mutex: Has mutex register for mutual exclusion with other firmwares or VMs. + * @variant: This represents the I2C controller variant. + * @regs: Register offsets for the specific SoC variant. */ struct tegra_i2c_hw_feature { bool has_continue_xfer_support; @@ -254,6 +412,8 @@ struct tegra_i2c_hw_feature { bool has_interface_timing_reg; bool enable_hs_mode_support; bool has_mutex; + enum tegra_i2c_variant variant; + const struct tegra_i2c_regs *regs; }; /** @@ -268,8 +428,6 @@ struct tegra_i2c_hw_feature { * @base_phys: physical base address of the I2C controller * @cont_id: I2C controller ID, used for packet header * @irq: IRQ number of transfer complete interrupt - * @is_dvc: identifies the DVC I2C controller, has a different register layout - * @is_vi: identifies the VI I2C controller, has a different register layout * @msg_complete: transfer completion notifier * @msg_buf_remaining: size of unsent data in the message buffer * @msg_len: length of message in current transfer @@ -321,12 +479,12 @@ struct tegra_i2c_dev { bool atomic_mode; bool dma_mode; bool msg_read; - bool is_dvc; - bool is_vi; }; -#define IS_DVC(dev) (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC) && (dev)->is_dvc) -#define IS_VI(dev) (IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC) && (dev)->is_vi) +#define IS_DVC(dev) (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC) && \ + (dev)->hw->variant == TEGRA_I2C_VARIANT_DVC) +#define IS_VI(dev) (IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC) && \ + (dev)->hw->variant == TEGRA_I2C_VARIANT_VI) static void dvc_writel(struct tegra_i2c_dev *i2c_dev, u32 val, unsigned int reg) @@ -339,40 +497,26 @@ static u32 dvc_readl(struct tegra_i2c_dev *i2c_dev, unsigned int reg) return readl_relaxed(i2c_dev->base + reg); } -/* - * If necessary, i2c_writel() and i2c_readl() will offset the register - * in order to talk to the I2C block inside the DVC block. - */ -static u32 tegra_i2c_reg_addr(struct tegra_i2c_dev *i2c_dev, unsigned int reg) -{ - if (IS_DVC(i2c_dev)) - reg += (reg >= I2C_TX_FIFO) ? 0x10 : 0x40; - else if (IS_VI(i2c_dev)) - reg = 0xc00 + (reg << 2); - - return reg; -} - static void i2c_writel(struct tegra_i2c_dev *i2c_dev, u32 val, unsigned int reg) { - writel_relaxed(val, i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg)); + writel_relaxed(val, i2c_dev->base + reg); /* read back register to make sure that register writes completed */ - if (reg != I2C_TX_FIFO) - readl_relaxed(i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg)); + if (reg != i2c_dev->hw->regs->tx_fifo) + readl_relaxed(i2c_dev->base + reg); else if (IS_VI(i2c_dev)) - readl_relaxed(i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, I2C_INT_STATUS)); + readl_relaxed(i2c_dev->base + i2c_dev->hw->regs->int_status); } static u32 i2c_readl(struct tegra_i2c_dev *i2c_dev, unsigned int reg) { - return readl_relaxed(i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg)); + return readl_relaxed(i2c_dev->base + reg); } static void i2c_writesl(struct tegra_i2c_dev *i2c_dev, void *data, unsigned int reg, unsigned int len) { - writesl(i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg), data, len); + writesl(i2c_dev->base + reg, data, len); } static void i2c_writesl_vi(struct tegra_i2c_dev *i2c_dev, void *data, @@ -393,12 +537,12 @@ static void i2c_writesl_vi(struct tegra_i2c_dev *i2c_dev, void *data, static void i2c_readsl(struct tegra_i2c_dev *i2c_dev, void *data, unsigned int reg, unsigned int len) { - readsl(i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg), data, len); + readsl(i2c_dev->base + reg, data, len); } static bool tegra_i2c_mutex_acquired(struct tegra_i2c_dev *i2c_dev) { - unsigned int reg = tegra_i2c_reg_addr(i2c_dev, I2C_SW_MUTEX); + unsigned int reg = i2c_dev->hw->regs->sw_mutex; u32 val, id; val = readl(i2c_dev->base + reg); @@ -409,7 +553,7 @@ static bool tegra_i2c_mutex_acquired(struct tegra_i2c_dev *i2c_dev) static bool tegra_i2c_mutex_trylock(struct tegra_i2c_dev *i2c_dev) { - unsigned int reg = tegra_i2c_reg_addr(i2c_dev, I2C_SW_MUTEX); + unsigned int reg = i2c_dev->hw->regs->sw_mutex; u32 val, id; val = readl(i2c_dev->base + reg); @@ -447,7 +591,7 @@ static int tegra_i2c_mutex_lock(struct tegra_i2c_dev *i2c_dev) static int tegra_i2c_mutex_unlock(struct tegra_i2c_dev *i2c_dev) { - unsigned int reg = tegra_i2c_reg_addr(i2c_dev, I2C_SW_MUTEX); + unsigned int reg = i2c_dev->hw->regs->sw_mutex; u32 val, id; if (!i2c_dev->hw->has_mutex) @@ -470,16 +614,16 @@ static void tegra_i2c_mask_irq(struct tegra_i2c_dev *i2c_dev, u32 mask) { u32 int_mask; - int_mask = i2c_readl(i2c_dev, I2C_INT_MASK) & ~mask; - i2c_writel(i2c_dev, int_mask, I2C_INT_MASK); + int_mask = i2c_readl(i2c_dev, i2c_dev->hw->regs->int_mask) & ~mask; + i2c_writel(i2c_dev, int_mask, i2c_dev->hw->regs->int_mask); } static void tegra_i2c_unmask_irq(struct tegra_i2c_dev *i2c_dev, u32 mask) { u32 int_mask; - int_mask = i2c_readl(i2c_dev, I2C_INT_MASK) | mask; - i2c_writel(i2c_dev, int_mask, I2C_INT_MASK); + int_mask = i2c_readl(i2c_dev, i2c_dev->hw->regs->int_mask) | mask; + i2c_writel(i2c_dev, int_mask, i2c_dev->hw->regs->int_mask); } static void tegra_i2c_dma_complete(void *args) @@ -623,34 +767,34 @@ static void tegra_i2c_vi_init(struct tegra_i2c_dev *i2c_dev) value = FIELD_PREP(I2C_INTERFACE_TIMING_THIGH, 2) | FIELD_PREP(I2C_INTERFACE_TIMING_TLOW, 4); - i2c_writel(i2c_dev, value, I2C_INTERFACE_TIMING_0); + i2c_writel(i2c_dev, value, i2c_dev->hw->regs->interface_timing_0); value = FIELD_PREP(I2C_INTERFACE_TIMING_TBUF, 4) | FIELD_PREP(I2C_INTERFACE_TIMING_TSU_STO, 7) | FIELD_PREP(I2C_INTERFACE_TIMING_THD_STA, 4) | FIELD_PREP(I2C_INTERFACE_TIMING_TSU_STA, 4); - i2c_writel(i2c_dev, value, I2C_INTERFACE_TIMING_1); + i2c_writel(i2c_dev, value, i2c_dev->hw->regs->interface_timing_1); value = FIELD_PREP(I2C_HS_INTERFACE_TIMING_THIGH, 3) | FIELD_PREP(I2C_HS_INTERFACE_TIMING_TLOW, 8); - i2c_writel(i2c_dev, value, I2C_HS_INTERFACE_TIMING_0); + i2c_writel(i2c_dev, value, i2c_dev->hw->regs->hs_interface_timing_0); value = FIELD_PREP(I2C_HS_INTERFACE_TIMING_TSU_STO, 11) | FIELD_PREP(I2C_HS_INTERFACE_TIMING_THD_STA, 11) | FIELD_PREP(I2C_HS_INTERFACE_TIMING_TSU_STA, 11); - i2c_writel(i2c_dev, value, I2C_HS_INTERFACE_TIMING_1); + i2c_writel(i2c_dev, value, i2c_dev->hw->regs->hs_interface_timing_1); value = FIELD_PREP(I2C_BC_SCLK_THRESHOLD, 9) | I2C_BC_STOP_COND; - i2c_writel(i2c_dev, value, I2C_BUS_CLEAR_CNFG); + i2c_writel(i2c_dev, value, i2c_dev->hw->regs->bus_clear_cnfg); - i2c_writel(i2c_dev, 0x0, I2C_TLOW_SEXT); + i2c_writel(i2c_dev, 0x0, i2c_dev->hw->regs->tlow_sext); } static int tegra_i2c_poll_register(struct tegra_i2c_dev *i2c_dev, u32 reg, u32 mask, u32 delay_us, u32 timeout_us) { - void __iomem *addr = i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg); + void __iomem *addr = i2c_dev->base + reg; u32 val; if (!i2c_dev->atomic_mode) @@ -669,11 +813,11 @@ static int tegra_i2c_flush_fifos(struct tegra_i2c_dev *i2c_dev) if (i2c_dev->hw->has_mst_fifo) { mask = I2C_MST_FIFO_CONTROL_TX_FLUSH | I2C_MST_FIFO_CONTROL_RX_FLUSH; - offset = I2C_MST_FIFO_CONTROL; + offset = i2c_dev->hw->regs->mst_fifo_control; } else { mask = I2C_FIFO_CONTROL_TX_FLUSH | I2C_FIFO_CONTROL_RX_FLUSH; - offset = I2C_FIFO_CONTROL; + offset = i2c_dev->hw->regs->fifo_control; } val = i2c_readl(i2c_dev, offset); @@ -696,9 +840,9 @@ static int tegra_i2c_wait_for_config_load(struct tegra_i2c_dev *i2c_dev) if (!i2c_dev->hw->has_config_load_reg) return 0; - i2c_writel(i2c_dev, I2C_MSTR_CONFIG_LOAD, I2C_CONFIG_LOAD); + i2c_writel(i2c_dev, I2C_MSTR_CONFIG_LOAD, i2c_dev->hw->regs->config_load); - err = tegra_i2c_poll_register(i2c_dev, I2C_CONFIG_LOAD, 0xffffffff, + err = tegra_i2c_poll_register(i2c_dev, i2c_dev->hw->regs->config_load, 0xffffffff, 1000, I2C_CONFIG_LOAD_TIMEOUT); if (err) { dev_err(i2c_dev->dev, "failed to load config\n"); @@ -719,10 +863,10 @@ static int tegra_i2c_master_reset(struct tegra_i2c_dev *i2c_dev) * SW needs to wait for 2us after assertion and de-assertion of this soft * reset. */ - i2c_writel(i2c_dev, 0x1, I2C_MASTER_RESET_CNTRL); + i2c_writel(i2c_dev, 0x1, i2c_dev->hw->regs->master_reset_cntrl); fsleep(2); - i2c_writel(i2c_dev, 0x0, I2C_MASTER_RESET_CNTRL); + i2c_writel(i2c_dev, 0x0, i2c_dev->hw->regs->master_reset_cntrl); fsleep(2); return 0; @@ -764,8 +908,8 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev) if (i2c_dev->hw->has_multi_master_mode) val |= I2C_CNFG_MULTI_MASTER_MODE; - i2c_writel(i2c_dev, val, I2C_CNFG); - i2c_writel(i2c_dev, 0, I2C_INT_MASK); + i2c_writel(i2c_dev, val, i2c_dev->hw->regs->cnfg); + i2c_writel(i2c_dev, 0, i2c_dev->hw->regs->int_mask); if (IS_VI(i2c_dev)) tegra_i2c_vi_init(i2c_dev); @@ -810,12 +954,12 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev) clk_divisor = FIELD_PREP(I2C_CLK_DIVISOR_HSMODE, i2c_dev->hw->clk_divisor_hs_mode) | FIELD_PREP(I2C_CLK_DIVISOR_STD_FAST_MODE, non_hs_mode); - i2c_writel(i2c_dev, clk_divisor, I2C_CLK_DIVISOR); + i2c_writel(i2c_dev, clk_divisor, i2c_dev->hw->regs->clk_divisor); if (i2c_dev->hw->has_interface_timing_reg) { val = FIELD_PREP(I2C_INTERFACE_TIMING_THIGH, thigh) | FIELD_PREP(I2C_INTERFACE_TIMING_TLOW, tlow); - i2c_writel(i2c_dev, val, I2C_INTERFACE_TIMING_0); + i2c_writel(i2c_dev, val, i2c_dev->hw->regs->interface_timing_0); } /* @@ -823,7 +967,7 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev) * Otherwise, preserve the chip default values. */ if (i2c_dev->hw->has_interface_timing_reg && tsu_thd) - i2c_writel(i2c_dev, tsu_thd, I2C_INTERFACE_TIMING_1); + i2c_writel(i2c_dev, tsu_thd, i2c_dev->hw->regs->interface_timing_1); /* Write HS mode registers. These will get used only for HS mode*/ if (i2c_dev->hw->enable_hs_mode_support) { @@ -833,8 +977,8 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev) val = FIELD_PREP(I2C_HS_INTERFACE_TIMING_THIGH, thigh) | FIELD_PREP(I2C_HS_INTERFACE_TIMING_TLOW, tlow); - i2c_writel(i2c_dev, val, I2C_HS_INTERFACE_TIMING_0); - i2c_writel(i2c_dev, tsu_thd, I2C_HS_INTERFACE_TIMING_1); + i2c_writel(i2c_dev, val, i2c_dev->hw->regs->hs_interface_timing_0); + i2c_writel(i2c_dev, tsu_thd, i2c_dev->hw->regs->hs_interface_timing_1); } clk_multiplier = (tlow + thigh + 2) * (non_hs_mode + 1); @@ -847,12 +991,12 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev) } if (!IS_DVC(i2c_dev) && !IS_VI(i2c_dev)) { - u32 sl_cfg = i2c_readl(i2c_dev, I2C_SL_CNFG); + u32 sl_cfg = i2c_readl(i2c_dev, i2c_dev->hw->regs->sl_cnfg); sl_cfg |= I2C_SL_CNFG_NACK | I2C_SL_CNFG_NEWSL; - i2c_writel(i2c_dev, sl_cfg, I2C_SL_CNFG); - i2c_writel(i2c_dev, 0xfc, I2C_SL_ADDR1); - i2c_writel(i2c_dev, 0x00, I2C_SL_ADDR2); + i2c_writel(i2c_dev, sl_cfg, i2c_dev->hw->regs->sl_cnfg); + i2c_writel(i2c_dev, 0xfc, i2c_dev->hw->regs->sl_addr1); + i2c_writel(i2c_dev, 0x00, i2c_dev->hw->regs->sl_addr2); } err = tegra_i2c_flush_fifos(i2c_dev); @@ -860,7 +1004,7 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev) return err; if (i2c_dev->multimaster_mode && i2c_dev->hw->has_slcg_override_reg) - i2c_writel(i2c_dev, I2C_MST_CORE_CLKEN_OVR, I2C_CLKEN_OVERRIDE); + i2c_writel(i2c_dev, I2C_MST_CORE_CLKEN_OVR, i2c_dev->hw->regs->clken_override); err = tegra_i2c_wait_for_config_load(i2c_dev); if (err) @@ -881,9 +1025,9 @@ static int tegra_i2c_disable_packet_mode(struct tegra_i2c_dev *i2c_dev) */ udelay(DIV_ROUND_UP(2 * 1000000, i2c_dev->timings.bus_freq_hz)); - cnfg = i2c_readl(i2c_dev, I2C_CNFG); + cnfg = i2c_readl(i2c_dev, i2c_dev->hw->regs->cnfg); if (cnfg & I2C_CNFG_PACKET_MODE_EN) - i2c_writel(i2c_dev, cnfg & ~I2C_CNFG_PACKET_MODE_EN, I2C_CNFG); + i2c_writel(i2c_dev, cnfg & ~I2C_CNFG_PACKET_MODE_EN, i2c_dev->hw->regs->cnfg); return tegra_i2c_wait_for_config_load(i2c_dev); } @@ -903,10 +1047,10 @@ static int tegra_i2c_empty_rx_fifo(struct tegra_i2c_dev *i2c_dev) return -EINVAL; if (i2c_dev->hw->has_mst_fifo) { - val = i2c_readl(i2c_dev, I2C_MST_FIFO_STATUS); + val = i2c_readl(i2c_dev, i2c_dev->hw->regs->mst_fifo_status); rx_fifo_avail = FIELD_GET(I2C_MST_FIFO_STATUS_RX, val); } else { - val = i2c_readl(i2c_dev, I2C_FIFO_STATUS); + val = i2c_readl(i2c_dev, i2c_dev->hw->regs->fifo_status); rx_fifo_avail = FIELD_GET(I2C_FIFO_STATUS_RX, val); } @@ -915,7 +1059,7 @@ static int tegra_i2c_empty_rx_fifo(struct tegra_i2c_dev *i2c_dev) if (words_to_transfer > rx_fifo_avail) words_to_transfer = rx_fifo_avail; - i2c_readsl(i2c_dev, buf, I2C_RX_FIFO, words_to_transfer); + i2c_readsl(i2c_dev, buf, i2c_dev->hw->regs->rx_fifo, words_to_transfer); buf += words_to_transfer * BYTES_PER_FIFO_WORD; buf_remaining -= words_to_transfer * BYTES_PER_FIFO_WORD; @@ -931,7 +1075,7 @@ static int tegra_i2c_empty_rx_fifo(struct tegra_i2c_dev *i2c_dev) * when (words_to_transfer was > rx_fifo_avail) earlier * in this function. */ - val = i2c_readl(i2c_dev, I2C_RX_FIFO); + val = i2c_readl(i2c_dev, i2c_dev->hw->regs->rx_fifo); val = cpu_to_le32(val); memcpy(buf, &val, buf_remaining); buf_remaining = 0; @@ -956,10 +1100,10 @@ static int tegra_i2c_fill_tx_fifo(struct tegra_i2c_dev *i2c_dev) u32 val; if (i2c_dev->hw->has_mst_fifo) { - val = i2c_readl(i2c_dev, I2C_MST_FIFO_STATUS); + val = i2c_readl(i2c_dev, i2c_dev->hw->regs->mst_fifo_status); tx_fifo_avail = FIELD_GET(I2C_MST_FIFO_STATUS_TX, val); } else { - val = i2c_readl(i2c_dev, I2C_FIFO_STATUS); + val = i2c_readl(i2c_dev, i2c_dev->hw->regs->fifo_status); tx_fifo_avail = FIELD_GET(I2C_FIFO_STATUS_TX, val); } @@ -990,9 +1134,9 @@ static int tegra_i2c_fill_tx_fifo(struct tegra_i2c_dev *i2c_dev) i2c_dev->msg_buf = buf + words_to_transfer * BYTES_PER_FIFO_WORD; if (IS_VI(i2c_dev)) - i2c_writesl_vi(i2c_dev, buf, I2C_TX_FIFO, words_to_transfer); + i2c_writesl_vi(i2c_dev, buf, i2c_dev->hw->regs->tx_fifo, words_to_transfer); else - i2c_writesl(i2c_dev, buf, I2C_TX_FIFO, words_to_transfer); + i2c_writesl(i2c_dev, buf, i2c_dev->hw->regs->tx_fifo, words_to_transfer); buf += words_to_transfer * BYTES_PER_FIFO_WORD; } @@ -1014,7 +1158,7 @@ static int tegra_i2c_fill_tx_fifo(struct tegra_i2c_dev *i2c_dev) i2c_dev->msg_buf_remaining = 0; i2c_dev->msg_buf = NULL; - i2c_writel(i2c_dev, val, I2C_TX_FIFO); + i2c_writel(i2c_dev, val, i2c_dev->hw->regs->tx_fifo); } return 0; @@ -1026,13 +1170,13 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id) struct tegra_i2c_dev *i2c_dev = dev_id; u32 status; - status = i2c_readl(i2c_dev, I2C_INT_STATUS); + status = i2c_readl(i2c_dev, i2c_dev->hw->regs->int_status); if (status == 0) { dev_warn(i2c_dev->dev, "IRQ status 0 %08x %08x %08x\n", - i2c_readl(i2c_dev, I2C_PACKET_TRANSFER_STATUS), - i2c_readl(i2c_dev, I2C_STATUS), - i2c_readl(i2c_dev, I2C_CNFG)); + i2c_readl(i2c_dev, i2c_dev->hw->regs->packet_transfer_status), + i2c_readl(i2c_dev, i2c_dev->hw->regs->status), + i2c_readl(i2c_dev, i2c_dev->hw->regs->cnfg)); i2c_dev->msg_err |= I2C_ERR_UNKNOWN_INTERRUPT; goto err; } @@ -1075,7 +1219,7 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id) } } - i2c_writel(i2c_dev, status, I2C_INT_STATUS); + i2c_writel(i2c_dev, status, i2c_dev->hw->regs->int_status); if (IS_DVC(i2c_dev)) dvc_writel(i2c_dev, DVC_STATUS_I2C_DONE_INTR, DVC_STATUS); @@ -1113,7 +1257,7 @@ err: if (i2c_dev->hw->supports_bus_clear) tegra_i2c_mask_irq(i2c_dev, I2C_INT_BUS_CLR_DONE); - i2c_writel(i2c_dev, status, I2C_INT_STATUS); + i2c_writel(i2c_dev, status, i2c_dev->hw->regs->int_status); if (IS_DVC(i2c_dev)) dvc_writel(i2c_dev, DVC_STATUS_I2C_DONE_INTR, DVC_STATUS); @@ -1136,9 +1280,9 @@ static void tegra_i2c_config_fifo_trig(struct tegra_i2c_dev *i2c_dev, int err; if (i2c_dev->hw->has_mst_fifo) - reg = I2C_MST_FIFO_CONTROL; + reg = i2c_dev->hw->regs->mst_fifo_control; else - reg = I2C_FIFO_CONTROL; + reg = i2c_dev->hw->regs->fifo_control; if (i2c_dev->dma_mode) { if (len & 0xF) @@ -1149,7 +1293,7 @@ static void tegra_i2c_config_fifo_trig(struct tegra_i2c_dev *i2c_dev, dma_burst = 8; if (i2c_dev->msg_read) { - reg_offset = tegra_i2c_reg_addr(i2c_dev, I2C_RX_FIFO); + reg_offset = i2c_dev->hw->regs->rx_fifo; slv_config.src_addr = i2c_dev->base_phys + reg_offset; slv_config.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; @@ -1160,7 +1304,7 @@ static void tegra_i2c_config_fifo_trig(struct tegra_i2c_dev *i2c_dev, else val = I2C_FIFO_CONTROL_RX_TRIG(dma_burst); } else { - reg_offset = tegra_i2c_reg_addr(i2c_dev, I2C_TX_FIFO); + reg_offset = i2c_dev->hw->regs->tx_fifo; slv_config.dst_addr = i2c_dev->base_phys + reg_offset; slv_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; @@ -1203,7 +1347,7 @@ static unsigned long tegra_i2c_poll_completion(struct tegra_i2c_dev *i2c_dev, ktime_t ktimeout = ktime_add_ms(ktime, timeout_ms); do { - u32 status = i2c_readl(i2c_dev, I2C_INT_STATUS); + u32 status = i2c_readl(i2c_dev, i2c_dev->hw->regs->int_status); if (status) tegra_i2c_isr(i2c_dev->irq, i2c_dev); @@ -1262,14 +1406,14 @@ static int tegra_i2c_issue_bus_clear(struct i2c_adapter *adap) val = FIELD_PREP(I2C_BC_SCLK_THRESHOLD, 9) | I2C_BC_STOP_COND | I2C_BC_TERMINATE; - i2c_writel(i2c_dev, val, I2C_BUS_CLEAR_CNFG); + i2c_writel(i2c_dev, val, i2c_dev->hw->regs->bus_clear_cnfg); err = tegra_i2c_wait_for_config_load(i2c_dev); if (err) return err; val |= I2C_BC_ENABLE; - i2c_writel(i2c_dev, val, I2C_BUS_CLEAR_CNFG); + i2c_writel(i2c_dev, val, i2c_dev->hw->regs->bus_clear_cnfg); tegra_i2c_unmask_irq(i2c_dev, I2C_INT_BUS_CLR_DONE); time_left = tegra_i2c_wait_completion(i2c_dev, &i2c_dev->msg_complete, 50); @@ -1280,7 +1424,7 @@ static int tegra_i2c_issue_bus_clear(struct i2c_adapter *adap) return -ETIMEDOUT; } - val = i2c_readl(i2c_dev, I2C_BUS_CLEAR_STATUS); + val = i2c_readl(i2c_dev, i2c_dev->hw->regs->bus_clear_status); if (!(val & I2C_BC_STATUS)) { dev_err(i2c_dev->dev, "un-recovered arbitration lost\n"); return -EIO; @@ -1305,14 +1449,14 @@ static void tegra_i2c_push_packet_header(struct tegra_i2c_dev *i2c_dev, if (i2c_dev->dma_mode && !i2c_dev->msg_read) *dma_buf++ = packet_header; else - i2c_writel(i2c_dev, packet_header, I2C_TX_FIFO); + i2c_writel(i2c_dev, packet_header, i2c_dev->hw->regs->tx_fifo); packet_header = i2c_dev->msg_len - 1; if (i2c_dev->dma_mode && !i2c_dev->msg_read) *dma_buf++ = packet_header; else - i2c_writel(i2c_dev, packet_header, I2C_TX_FIFO); + i2c_writel(i2c_dev, packet_header, i2c_dev->hw->regs->tx_fifo); packet_header = I2C_HEADER_IE_ENABLE; @@ -1340,7 +1484,7 @@ static void tegra_i2c_push_packet_header(struct tegra_i2c_dev *i2c_dev, if (i2c_dev->dma_mode && !i2c_dev->msg_read) *dma_buf++ = packet_header; else - i2c_writel(i2c_dev, packet_header, I2C_TX_FIFO); + i2c_writel(i2c_dev, packet_header, i2c_dev->hw->regs->tx_fifo); } static int tegra_i2c_error_recover(struct tegra_i2c_dev *i2c_dev, @@ -1461,7 +1605,7 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev, tegra_i2c_unmask_irq(i2c_dev, int_mask); dev_dbg(i2c_dev->dev, "unmasked IRQ: %02x\n", - i2c_readl(i2c_dev, I2C_INT_MASK)); + i2c_readl(i2c_dev, i2c_dev->hw->regs->int_mask)); if (i2c_dev->dma_mode) { time_left = tegra_i2c_wait_completion(i2c_dev, @@ -1635,8 +1779,44 @@ static const struct tegra_i2c_hw_feature tegra20_i2c_hw = { .has_interface_timing_reg = false, .enable_hs_mode_support = false, .has_mutex = false, + .variant = TEGRA_I2C_VARIANT_DEFAULT, + .regs = &tegra20_i2c_regs, }; +#if IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC) +static const struct tegra_i2c_hw_feature tegra20_dvc_i2c_hw = { + .has_continue_xfer_support = false, + .has_per_pkt_xfer_complete_irq = false, + .clk_divisor_hs_mode = 3, + .clk_divisor_std_mode = 0, + .clk_divisor_fast_mode = 0, + .clk_divisor_fast_plus_mode = 0, + .has_config_load_reg = false, + .has_multi_master_mode = false, + .has_slcg_override_reg = false, + .has_mst_fifo = false, + .has_mst_reset = false, + .quirks = &tegra_i2c_quirks, + .supports_bus_clear = false, + .has_apb_dma = true, + .tlow_std_mode = 0x4, + .thigh_std_mode = 0x2, + .tlow_fast_mode = 0x4, + .thigh_fast_mode = 0x2, + .tlow_fastplus_mode = 0x4, + .thigh_fastplus_mode = 0x2, + .setup_hold_time_std_mode = 0x0, + .setup_hold_time_fast_mode = 0x0, + .setup_hold_time_fastplus_mode = 0x0, + .setup_hold_time_hs_mode = 0x0, + .has_interface_timing_reg = false, + .enable_hs_mode_support = false, + .has_mutex = false, + .variant = TEGRA_I2C_VARIANT_DVC, + .regs = &tegra20_dvc_i2c_regs, +}; +#endif + static const struct tegra_i2c_hw_feature tegra30_i2c_hw = { .has_continue_xfer_support = true, .has_per_pkt_xfer_complete_irq = false, @@ -1665,6 +1845,8 @@ static const struct tegra_i2c_hw_feature tegra30_i2c_hw = { .has_interface_timing_reg = false, .enable_hs_mode_support = false, .has_mutex = false, + .variant = TEGRA_I2C_VARIANT_DEFAULT, + .regs = &tegra20_i2c_regs, }; static const struct tegra_i2c_hw_feature tegra114_i2c_hw = { @@ -1695,6 +1877,8 @@ static const struct tegra_i2c_hw_feature tegra114_i2c_hw = { .has_interface_timing_reg = false, .enable_hs_mode_support = false, .has_mutex = false, + .variant = TEGRA_I2C_VARIANT_DEFAULT, + .regs = &tegra20_i2c_regs, }; static const struct tegra_i2c_hw_feature tegra124_i2c_hw = { @@ -1725,6 +1909,8 @@ static const struct tegra_i2c_hw_feature tegra124_i2c_hw = { .has_interface_timing_reg = true, .enable_hs_mode_support = false, .has_mutex = false, + .variant = TEGRA_I2C_VARIANT_DEFAULT, + .regs = &tegra20_i2c_regs, }; static const struct tegra_i2c_hw_feature tegra210_i2c_hw = { @@ -1755,7 +1941,43 @@ static const struct tegra_i2c_hw_feature tegra210_i2c_hw = { .has_interface_timing_reg = true, .enable_hs_mode_support = false, .has_mutex = false, + .variant = TEGRA_I2C_VARIANT_DEFAULT, + .regs = &tegra20_i2c_regs, +}; + +#if IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC) +static const struct tegra_i2c_hw_feature tegra210_vi_i2c_hw = { + .has_continue_xfer_support = true, + .has_per_pkt_xfer_complete_irq = true, + .clk_divisor_hs_mode = 1, + .clk_divisor_std_mode = 0x19, + .clk_divisor_fast_mode = 0x19, + .clk_divisor_fast_plus_mode = 0x10, + .has_config_load_reg = true, + .has_multi_master_mode = false, + .has_slcg_override_reg = true, + .has_mst_fifo = false, + .has_mst_reset = false, + .quirks = &tegra_i2c_quirks, + .supports_bus_clear = true, + .has_apb_dma = true, + .tlow_std_mode = 0x4, + .thigh_std_mode = 0x2, + .tlow_fast_mode = 0x4, + .thigh_fast_mode = 0x2, + .tlow_fastplus_mode = 0x4, + .thigh_fastplus_mode = 0x2, + .setup_hold_time_std_mode = 0, + .setup_hold_time_fast_mode = 0, + .setup_hold_time_fastplus_mode = 0, + .setup_hold_time_hs_mode = 0, + .has_interface_timing_reg = true, + .enable_hs_mode_support = false, + .has_mutex = false, + .variant = TEGRA_I2C_VARIANT_VI, + .regs = &tegra210_vi_i2c_regs, }; +#endif static const struct tegra_i2c_hw_feature tegra186_i2c_hw = { .has_continue_xfer_support = true, @@ -1785,6 +2007,8 @@ static const struct tegra_i2c_hw_feature tegra186_i2c_hw = { .has_interface_timing_reg = true, .enable_hs_mode_support = false, .has_mutex = false, + .variant = TEGRA_I2C_VARIANT_DEFAULT, + .regs = &tegra20_i2c_regs, }; static const struct tegra_i2c_hw_feature tegra194_i2c_hw = { @@ -1817,6 +2041,8 @@ static const struct tegra_i2c_hw_feature tegra194_i2c_hw = { .has_interface_timing_reg = true, .enable_hs_mode_support = true, .has_mutex = false, + .variant = TEGRA_I2C_VARIANT_DEFAULT, + .regs = &tegra20_i2c_regs, }; static const struct tegra_i2c_hw_feature tegra256_i2c_hw = { @@ -1849,6 +2075,8 @@ static const struct tegra_i2c_hw_feature tegra256_i2c_hw = { .has_interface_timing_reg = true, .enable_hs_mode_support = true, .has_mutex = true, + .variant = TEGRA_I2C_VARIANT_DEFAULT, + .regs = &tegra264_i2c_regs, }; static const struct tegra_i2c_hw_feature tegra264_i2c_hw = { @@ -1881,6 +2109,42 @@ static const struct tegra_i2c_hw_feature tegra264_i2c_hw = { .has_interface_timing_reg = true, .enable_hs_mode_support = true, .has_mutex = true, + .variant = TEGRA_I2C_VARIANT_DEFAULT, + .regs = &tegra264_i2c_regs, +}; + +static const struct tegra_i2c_hw_feature tegra410_i2c_hw = { + .has_continue_xfer_support = true, + .has_per_pkt_xfer_complete_irq = true, + .clk_divisor_hs_mode = 1, + .clk_divisor_std_mode = 0x3f, + .clk_divisor_fast_mode = 0x2c, + .clk_divisor_fast_plus_mode = 0x11, + .has_config_load_reg = true, + .has_multi_master_mode = true, + .has_slcg_override_reg = true, + .has_mst_fifo = true, + .has_mst_reset = true, + .quirks = &tegra194_i2c_quirks, + .supports_bus_clear = true, + .has_apb_dma = false, + .tlow_std_mode = 0x8, + .thigh_std_mode = 0x7, + .tlow_fast_mode = 0x2, + .thigh_fast_mode = 0x2, + .tlow_fastplus_mode = 0x2, + .thigh_fastplus_mode = 0x2, + .tlow_hs_mode = 0x8, + .thigh_hs_mode = 0x6, + .setup_hold_time_std_mode = 0x08080808, + .setup_hold_time_fast_mode = 0x02020202, + .setup_hold_time_fastplus_mode = 0x02020202, + .setup_hold_time_hs_mode = 0x0b0b0b, + .has_interface_timing_reg = true, + .enable_hs_mode_support = true, + .has_mutex = true, + .variant = TEGRA_I2C_VARIANT_DEFAULT, + .regs = &tegra410_i2c_regs, }; static const struct of_device_id tegra_i2c_of_match[] = { @@ -1889,7 +2153,7 @@ static const struct of_device_id tegra_i2c_of_match[] = { { .compatible = "nvidia,tegra194-i2c", .data = &tegra194_i2c_hw, }, { .compatible = "nvidia,tegra186-i2c", .data = &tegra186_i2c_hw, }, #if IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC) - { .compatible = "nvidia,tegra210-i2c-vi", .data = &tegra210_i2c_hw, }, + { .compatible = "nvidia,tegra210-i2c-vi", .data = &tegra210_vi_i2c_hw, }, #endif { .compatible = "nvidia,tegra210-i2c", .data = &tegra210_i2c_hw, }, { .compatible = "nvidia,tegra124-i2c", .data = &tegra124_i2c_hw, }, @@ -1897,7 +2161,7 @@ static const struct of_device_id tegra_i2c_of_match[] = { { .compatible = "nvidia,tegra30-i2c", .data = &tegra30_i2c_hw, }, { .compatible = "nvidia,tegra20-i2c", .data = &tegra20_i2c_hw, }, #if IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC) - { .compatible = "nvidia,tegra20-i2c-dvc", .data = &tegra20_i2c_hw, }, + { .compatible = "nvidia,tegra20-i2c-dvc", .data = &tegra20_dvc_i2c_hw, }, #endif {}, }; @@ -1905,21 +2169,12 @@ MODULE_DEVICE_TABLE(of, tegra_i2c_of_match); static void tegra_i2c_parse_dt(struct tegra_i2c_dev *i2c_dev) { - struct device_node *np = i2c_dev->dev->of_node; bool multi_mode; i2c_parse_fw_timings(i2c_dev->dev, &i2c_dev->timings, true); multi_mode = device_property_read_bool(i2c_dev->dev, "multi-master"); i2c_dev->multimaster_mode = multi_mode; - - if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC) && - of_device_is_compatible(np, "nvidia,tegra20-i2c-dvc")) - i2c_dev->is_dvc = true; - - if (IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC) && - of_device_is_compatible(np, "nvidia,tegra210-i2c-vi")) - i2c_dev->is_vi = true; } static int tegra_i2c_init_clocks(struct tegra_i2c_dev *i2c_dev) @@ -2205,6 +2460,7 @@ static const struct acpi_device_id tegra_i2c_acpi_match[] = { {.id = "NVDA0101", .driver_data = (kernel_ulong_t)&tegra210_i2c_hw}, {.id = "NVDA0201", .driver_data = (kernel_ulong_t)&tegra186_i2c_hw}, {.id = "NVDA0301", .driver_data = (kernel_ulong_t)&tegra194_i2c_hw}, + {.id = "NVDA2017", .driver_data = (kernel_ulong_t)&tegra410_i2c_hw}, { } }; MODULE_DEVICE_TABLE(acpi, tegra_i2c_acpi_match); diff --git a/drivers/i2c/busses/i2c-tiny-usb.c b/drivers/i2c/busses/i2c-tiny-usb.c index 9ef495f88ef2..88d66593d9fc 100644 --- a/drivers/i2c/busses/i2c-tiny-usb.c +++ b/drivers/i2c/busses/i2c-tiny-usb.c @@ -213,12 +213,6 @@ static int usb_write(struct i2c_adapter *adapter, int cmd, return ret; } -static void i2c_tiny_usb_free(struct i2c_tiny_usb *dev) -{ - usb_put_dev(dev->usb_dev); - kfree(dev); -} - static int i2c_tiny_usb_probe(struct usb_interface *interface, const struct usb_device_id *id) { @@ -237,7 +231,7 @@ static int i2c_tiny_usb_probe(struct usb_interface *interface, if (!dev) goto error; - dev->usb_dev = usb_get_dev(interface_to_usbdev(interface)); + dev->usb_dev = interface_to_usbdev(interface); dev->interface = interface; /* save our data pointer in this interface device */ @@ -277,8 +271,7 @@ static int i2c_tiny_usb_probe(struct usb_interface *interface, return 0; error: - if (dev) - i2c_tiny_usb_free(dev); + kfree(dev); return retval; } @@ -289,7 +282,7 @@ static void i2c_tiny_usb_disconnect(struct usb_interface *interface) i2c_del_adapter(&dev->adapter); usb_set_intfdata(interface, NULL); - i2c_tiny_usb_free(dev); + kfree(dev); dev_dbg(&interface->dev, "disconnected\n"); } diff --git a/drivers/i2c/busses/i2c-usbio.c b/drivers/i2c/busses/i2c-usbio.c index e7799abf6787..259754e5fd05 100644 --- a/drivers/i2c/busses/i2c-usbio.c +++ b/drivers/i2c/busses/i2c-usbio.c @@ -29,6 +29,7 @@ static const struct acpi_device_id usbio_i2c_acpi_hids[] = { { "INTC10B6" }, /* LNL */ { "INTC10D2" }, /* MTL-CVF */ { "INTC10E3" }, /* PTL */ + { "INTC1118" }, /* NVL */ { } }; diff --git a/drivers/i2c/busses/i2c-xiic.c b/drivers/i2c/busses/i2c-xiic.c index 28015d77599d..3e7735e1dae0 100644 --- a/drivers/i2c/busses/i2c-xiic.c +++ b/drivers/i2c/busses/i2c-xiic.c @@ -27,7 +27,6 @@ #include <linux/platform_data/i2c-xiic.h> #include <linux/io.h> #include <linux/slab.h> -#include <linux/of.h> #include <linux/clk.h> #include <linux/pm_runtime.h> #include <linux/iopoll.h> @@ -1408,7 +1407,6 @@ static const struct i2c_adapter xiic_adapter = { .algo = &xiic_algorithm, }; -#if defined(CONFIG_OF) static const struct xiic_version_data xiic_2_00 = { .quirks = DYNAMIC_MODE_READ_BROKEN_BIT, }; @@ -1419,28 +1417,26 @@ static const struct of_device_id xiic_of_match[] = { {}, }; MODULE_DEVICE_TABLE(of, xiic_of_match); -#endif static int xiic_i2c_probe(struct platform_device *pdev) { + struct device *dev = &pdev->dev; + struct fwnode_handle *fwnode = dev_fwnode(dev); struct xiic_i2c *i2c; struct xiic_i2c_platform_data *pdata; - const struct of_device_id *match; + const struct xiic_version_data *data; struct resource *res; int ret, irq; u8 i; u32 sr; - i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL); + i2c = devm_kzalloc(dev, sizeof(*i2c), GFP_KERNEL); if (!i2c) return -ENOMEM; - match = of_match_node(xiic_of_match, pdev->dev.of_node); - if (match && match->data) { - const struct xiic_version_data *data = match->data; - + data = device_get_match_data(dev); + if (data) i2c->quirks = data->quirks; - } i2c->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); if (IS_ERR(i2c->base)) @@ -1450,50 +1446,52 @@ static int xiic_i2c_probe(struct platform_device *pdev) if (irq < 0) return irq; - pdata = dev_get_platdata(&pdev->dev); + pdata = dev_get_platdata(dev); /* hook up driver to tree */ platform_set_drvdata(pdev, i2c); i2c->adap = xiic_adapter; + i2c->adap.nr = pdev->id; i2c_set_adapdata(&i2c->adap, i2c); i2c->adap.dev.parent = &pdev->dev; - i2c->adap.dev.of_node = pdev->dev.of_node; + device_set_node(&i2c->adap.dev, fwnode); snprintf(i2c->adap.name, sizeof(i2c->adap.name), DRIVER_NAME " %s", pdev->name); - mutex_init(&i2c->lock); + ret = devm_mutex_init(dev, &i2c->lock); + if (ret) + return ret; + spin_lock_init(&i2c->atomic_lock); - i2c->clk = devm_clk_get_enabled(&pdev->dev, NULL); - if (IS_ERR(i2c->clk)) - return dev_err_probe(&pdev->dev, PTR_ERR(i2c->clk), - "failed to enable input clock.\n"); + if (is_of_node(fwnode)) { + i2c->clk = devm_clk_get_enabled(dev, NULL); + if (IS_ERR(i2c->clk)) + return dev_err_probe(dev, PTR_ERR(i2c->clk), + "failed to enable input clock.\n"); + } - i2c->dev = &pdev->dev; - pm_runtime_set_autosuspend_delay(i2c->dev, XIIC_PM_TIMEOUT); - pm_runtime_use_autosuspend(i2c->dev); - pm_runtime_set_active(i2c->dev); - pm_runtime_enable(i2c->dev); + i2c->dev = dev; + + pm_runtime_set_autosuspend_delay(dev, XIIC_PM_TIMEOUT); + pm_runtime_use_autosuspend(dev); + ret = devm_pm_runtime_set_active_enabled(dev); + if (ret) + return ret; /* SCL frequency configuration */ i2c->input_clk = clk_get_rate(i2c->clk); - ret = of_property_read_u32(pdev->dev.of_node, "clock-frequency", - &i2c->i2c_clk); + ret = device_property_read_u32(dev, "clock-frequency", &i2c->i2c_clk); /* If clock-frequency not specified in DT, do not configure in SW */ if (ret || i2c->i2c_clk > I2C_MAX_FAST_MODE_PLUS_FREQ) i2c->i2c_clk = 0; - ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, - xiic_process, IRQF_ONESHOT, - pdev->name, i2c); - - if (ret < 0) { - dev_err_probe(&pdev->dev, ret, "Cannot claim IRQ\n"); - goto err_pm_disable; - } + ret = devm_request_threaded_irq(dev, irq, NULL, xiic_process, + IRQF_ONESHOT, pdev->name, i2c); + if (ret) + return ret; - i2c->singlemaster = - of_property_read_bool(pdev->dev.of_node, "single-master"); + i2c->singlemaster = device_property_read_bool(dev, "single-master"); /* * Detect endianness @@ -1508,16 +1506,14 @@ static int xiic_i2c_probe(struct platform_device *pdev) i2c->endianness = BIG; ret = xiic_reinit(i2c); - if (ret < 0) { - dev_err_probe(&pdev->dev, ret, "Cannot xiic_reinit\n"); - goto err_pm_disable; - } + if (ret) + return dev_err_probe(dev, ret, "Cannot xiic_reinit\n"); /* add i2c adapter to i2c tree */ - ret = i2c_add_adapter(&i2c->adap); + ret = i2c_add_numbered_adapter(&i2c->adap); if (ret) { xiic_deinit(i2c); - goto err_pm_disable; + return ret; } if (pdata) { @@ -1526,38 +1522,29 @@ static int xiic_i2c_probe(struct platform_device *pdev) i2c_new_client_device(&i2c->adap, pdata->devices + i); } - dev_dbg(&pdev->dev, "mmio %08lx irq %d scl clock frequency %d\n", - (unsigned long)res->start, irq, i2c->i2c_clk); + dev_dbg(dev, "mmio %pR irq %d scl clock frequency %d\n", + res, irq, i2c->i2c_clk); return 0; - -err_pm_disable: - pm_runtime_disable(&pdev->dev); - pm_runtime_set_suspended(&pdev->dev); - - return ret; } static void xiic_i2c_remove(struct platform_device *pdev) { + struct device *dev = &pdev->dev; struct xiic_i2c *i2c = platform_get_drvdata(pdev); int ret; /* remove adapter & data */ i2c_del_adapter(&i2c->adap); - ret = pm_runtime_get_sync(i2c->dev); - + ret = pm_runtime_get_sync(dev); if (ret < 0) - dev_warn(&pdev->dev, "Failed to activate device for removal (%pe)\n", + dev_warn(dev, "Failed to activate device for removal (%pe)\n", ERR_PTR(ret)); else xiic_deinit(i2c); - pm_runtime_put_sync(i2c->dev); - pm_runtime_disable(&pdev->dev); - pm_runtime_set_suspended(&pdev->dev); - pm_runtime_dont_use_autosuspend(&pdev->dev); + pm_runtime_put_sync(dev); } static const struct dev_pm_ops xiic_dev_pm_ops = { diff --git a/drivers/i2c/i2c-atr.c b/drivers/i2c/i2c-atr.c index f9fcb4793aaf..e6d2af659d81 100644 --- a/drivers/i2c/i2c-atr.c +++ b/drivers/i2c/i2c-atr.c @@ -49,8 +49,8 @@ struct i2c_atr_alias_pair { * @shared: Indicates if this alias pool is shared by multiple channels * * @lock: Lock protecting @aliases and @use_mask - * @aliases: Array of aliases, must hold exactly @size elements * @use_mask: Mask of used aliases + * @aliases: Array of aliases, must hold exactly @size elements */ struct i2c_atr_alias_pool { size_t size; @@ -58,8 +58,8 @@ struct i2c_atr_alias_pool { /* Protects aliases and use_mask */ spinlock_t lock; - u16 *aliases; unsigned long *use_mask; + u16 aliases[] __counted_by(size); }; /** @@ -137,22 +137,16 @@ static struct i2c_atr_alias_pool *i2c_atr_alloc_alias_pool(size_t num_aliases, b struct i2c_atr_alias_pool *alias_pool; int ret; - alias_pool = kzalloc_obj(*alias_pool); + alias_pool = kzalloc_flex(*alias_pool, aliases, num_aliases); if (!alias_pool) return ERR_PTR(-ENOMEM); alias_pool->size = num_aliases; - alias_pool->aliases = kcalloc(num_aliases, sizeof(*alias_pool->aliases), GFP_KERNEL); - if (!alias_pool->aliases) { - ret = -ENOMEM; - goto err_free_alias_pool; - } - alias_pool->use_mask = bitmap_zalloc(num_aliases, GFP_KERNEL); if (!alias_pool->use_mask) { ret = -ENOMEM; - goto err_free_aliases; + goto err_free_alias_pool; } alias_pool->shared = shared; @@ -161,8 +155,6 @@ static struct i2c_atr_alias_pool *i2c_atr_alloc_alias_pool(size_t num_aliases, b return alias_pool; -err_free_aliases: - kfree(alias_pool->aliases); err_free_alias_pool: kfree(alias_pool); return ERR_PTR(ret); @@ -171,7 +163,6 @@ err_free_alias_pool: static void i2c_atr_free_alias_pool(struct i2c_atr_alias_pool *alias_pool) { bitmap_free(alias_pool->use_mask); - kfree(alias_pool->aliases); kfree(alias_pool); } diff --git a/drivers/i2c/i2c-core-of.c b/drivers/i2c/i2c-core-of.c index eb7fb202355f..354a88d0599e 100644 --- a/drivers/i2c/i2c-core-of.c +++ b/drivers/i2c/i2c-core-of.c @@ -180,7 +180,7 @@ static int of_i2c_notify(struct notifier_block *nb, unsigned long action, * Clear the flag before adding the device so that fw_devlink * doesn't skip adding consumers to this device. */ - rd->dn->fwnode.flags &= ~FWNODE_FLAG_NOT_DEVICE; + fwnode_clear_flag(&rd->dn->fwnode, FWNODE_FLAG_NOT_DEVICE); client = of_i2c_register_device(adap, rd->dn); if (IS_ERR(client)) { dev_err(&adap->dev, "failed to create client for '%pOF'\n", diff --git a/drivers/i2c/i2c-core-slave.c b/drivers/i2c/i2c-core-slave.c index 02ca55c2246b..bebb7ba67e30 100644 --- a/drivers/i2c/i2c-core-slave.c +++ b/drivers/i2c/i2c-core-slave.c @@ -89,7 +89,7 @@ int i2c_slave_event(struct i2c_client *client, int ret = client->slave_cb(client, event, val); if (trace_i2c_slave_enabled()) - trace_i2c_slave(client, event, val, ret); + trace_call__i2c_slave(client, event, val, ret); return ret; } |
