diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2021-02-22 09:02:24 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2021-02-22 09:02:24 -0800 |
commit | 32c080c4b5cfadeb1d1d5952840d696d5cda8bb8 (patch) | |
tree | 77dfaa7d04c77fb389b4382303b7b3c3b4e8417b /drivers/i2c | |
parent | a26a9d8ab4f9edbdfb087a563b6613e9970ef0b0 (diff) | |
parent | 0b16cfd9e660f59e396ab5f3af7d49e3677e3f9c (diff) | |
download | linux-stable-32c080c4b5cfadeb1d1d5952840d696d5cda8bb8.tar.gz linux-stable-32c080c4b5cfadeb1d1d5952840d696d5cda8bb8.tar.bz2 linux-stable-32c080c4b5cfadeb1d1d5952840d696d5cda8bb8.zip |
Merge branch 'i2c/for-5.12' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux
Pull i2c updates from Wolfram Sang:
- mostly driver updates. Bigger ones for mlxcpld and iproc. But most of
them are all over the place.
- removal of the efm32, sirf, u300, and zte zx bus drivers because of
platform removal. So, we have a pleasant diffstat this time.
- first set of cleanups in the I2C core as preparation to increase
maximum length of SMBus transfers to 255 (as specified in the new
standard). Better documentation of struct i2c_msg and its flags stand
out here.
- the testunit can now respond to SMBus block process calls which is
the testcase when implementing the above new maximum length.
* 'i2c/for-5.12' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux: (62 commits)
i2c: remove redundant error print in stm32f7_i2c_probe
i2c: testunit: add support for block process calls
i2c: busses: Replace spin_lock_irqsave with spin_lock in hard IRQ
dt-bindings: eeprom: at24: Document ROHM BR24G01
i2c: i801: Add support for Intel Alder Lake PCH-P
i2c: mv64xxx: Fix check for missing clock after adding RPM
i2c: mux: mlxcpld: Add callback to notify mux creation completion
i2c: mux: mlxcpld: Extend supported mux number
i2c: mux: mlxcpld: Extend driver to support word address space devices
i2c: mux: mlxcpld: Get rid of adapter numbers enforcement
i2c: mux: mlxcpld: Prepare mux selection infrastructure for two-byte support
i2c: mux: mlxcpld: Convert driver to platform driver
i2c: imx: Synthesize end of transaction events without idle interrupts
i2c: i2c-qcom-geni: Add shutdown callback for i2c
i2c: mv64xxx: Add runtime PM support
i2c: amd-mp2: Remove unused macro
i2c: amd-mp2: convert to PCI logging functions
i2c: mux: mlxcpld: Move header file out of x86 realm
platform/x86: mlxcpld: Update module license
i2c: mux: mlxcpld: Update module license
...
Diffstat (limited to 'drivers/i2c')
32 files changed, 764 insertions, 2993 deletions
diff --git a/drivers/i2c/algos/i2c-algo-bit.c b/drivers/i2c/algos/i2c-algo-bit.c index 913db013fe90..fc90293afcbf 100644 --- a/drivers/i2c/algos/i2c-algo-bit.c +++ b/drivers/i2c/algos/i2c-algo-bit.c @@ -622,9 +622,7 @@ static int bit_xfer_atomic(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], static u32 bit_func(struct i2c_adapter *adap) { - return I2C_FUNC_I2C | I2C_FUNC_NOSTART | I2C_FUNC_SMBUS_EMUL | - I2C_FUNC_SMBUS_READ_BLOCK_DATA | - I2C_FUNC_SMBUS_BLOCK_PROC_CALL | + return I2C_FUNC_I2C | I2C_FUNC_NOSTART | I2C_FUNC_SMBUS_EMUL_ALL | I2C_FUNC_10BIT_ADDR | I2C_FUNC_PROTOCOL_MANGLING; } diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 8c55faaea0e7..05ebf7546e3f 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -586,13 +586,6 @@ config I2C_DIGICOLOR This driver can also be built as a module. If so, the module will be called i2c-digicolor. -config I2C_EFM32 - tristate "EFM32 I2C controller" - depends on ARCH_EFM32 || COMPILE_TEST - help - This driver supports the i2c block found in Energy Micro's EFM32 - SoCs. - config I2C_EG20T tristate "Intel EG20T PCH/LAPIS Semicon IOH(ML7213/ML7223/ML7831) I2C" depends on PCI && (X86_32 || MIPS || COMPILE_TEST) @@ -1000,16 +993,6 @@ config I2C_SIMTEC This driver can also be built as a module. If so, the module will be called i2c-simtec. -config I2C_SIRF - tristate "CSR SiRFprimaII I2C interface" - depends on ARCH_SIRF || COMPILE_TEST - help - If you say yes to this option, support will be included for the - CSR SiRFprimaII I2C interface. - - This driver can also be built as a module. If so, the module - will be called i2c-sirf. - config I2C_SPRD tristate "Spreadtrum I2C interface" depends on I2C=y && (ARCH_SPRD || COMPILE_TEST) @@ -1050,19 +1033,6 @@ config I2C_STM32F7 This driver can also be built as module. If so, the module will be called i2c-stm32f7. -config I2C_STU300 - tristate "ST Microelectronics DDC I2C interface" - depends on MACH_U300 || COMPILE_TEST - default y if MACH_U300 - help - If you say yes to this option, support will be included for the - I2C interface from ST Microelectronics simply called "DDC I2C" - supporting both I2C and DDC, used in e.g. the U300 series - mobile platforms. - - This driver can also be built as a module. If so, the module - will be called i2c-stu300. - config I2C_SUN6I_P2WI tristate "Allwinner sun6i internal P2WI controller" depends on RESET_CONTROLLER @@ -1401,15 +1371,6 @@ config I2C_OPAL This driver can also be built as a module. If so, the module will be called as i2c-opal. -config I2C_ZX2967 - tristate "ZTE ZX2967 I2C support" - depends on ARCH_ZX - default y - help - Selecting this option will add ZX2967 I2C driver. - This driver can also be built as a module. If so, the module will be - called i2c-zx2967. - config I2C_FSI tristate "FSI I2C driver" depends on FSI diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index 683c49faca05..615f35e3e31f 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -58,7 +58,6 @@ i2c-designware-platform-$(CONFIG_I2C_DESIGNWARE_BAYTRAIL) += i2c-designware-bayt obj-$(CONFIG_I2C_DESIGNWARE_PCI) += i2c-designware-pci.o i2c-designware-pci-y := i2c-designware-pcidrv.o obj-$(CONFIG_I2C_DIGICOLOR) += i2c-digicolor.o -obj-$(CONFIG_I2C_EFM32) += i2c-efm32.o obj-$(CONFIG_I2C_EG20T) += i2c-eg20t.o obj-$(CONFIG_I2C_EMEV2) += i2c-emev2.o obj-$(CONFIG_I2C_EXYNOS5) += i2c-exynos5.o @@ -99,13 +98,11 @@ obj-$(CONFIG_I2C_S3C2410) += i2c-s3c2410.o obj-$(CONFIG_I2C_SH7760) += i2c-sh7760.o obj-$(CONFIG_I2C_SH_MOBILE) += i2c-sh_mobile.o obj-$(CONFIG_I2C_SIMTEC) += i2c-simtec.o -obj-$(CONFIG_I2C_SIRF) += i2c-sirf.o obj-$(CONFIG_I2C_SPRD) += i2c-sprd.o obj-$(CONFIG_I2C_ST) += i2c-st.o obj-$(CONFIG_I2C_STM32F4) += i2c-stm32f4.o i2c-stm32f7-drv-objs := i2c-stm32f7.o i2c-stm32.o obj-$(CONFIG_I2C_STM32F7) += i2c-stm32f7-drv.o -obj-$(CONFIG_I2C_STU300) += i2c-stu300.o obj-$(CONFIG_I2C_SUN6I_P2WI) += i2c-sun6i-p2wi.o obj-$(CONFIG_I2C_SYNQUACER) += i2c-synquacer.o obj-$(CONFIG_I2C_TEGRA) += i2c-tegra.o @@ -122,7 +119,6 @@ obj-$(CONFIG_I2C_XILINX) += i2c-xiic.o obj-$(CONFIG_I2C_XLR) += i2c-xlr.o obj-$(CONFIG_I2C_XLP9XX) += i2c-xlp9xx.o obj-$(CONFIG_I2C_RCAR) += i2c-rcar.o -obj-$(CONFIG_I2C_ZX2967) += i2c-zx2967.o # External I2C/SMBus adapter drivers obj-$(CONFIG_I2C_DIOLAN_U2C) += i2c-diolan-u2c.o diff --git a/drivers/i2c/busses/i2c-amd-mp2-pci.c b/drivers/i2c/busses/i2c-amd-mp2-pci.c index cd3fd5ee5f65..ce130a821ea5 100644 --- a/drivers/i2c/busses/i2c-amd-mp2-pci.c +++ b/drivers/i2c/busses/i2c-amd-mp2-pci.c @@ -30,7 +30,7 @@ static void amd_mp2_c2p_mutex_unlock(struct amd_i2c_common *i2c_common) struct amd_mp2_dev *privdata = i2c_common->mp2_dev; if (unlikely(privdata->c2p_lock_busid != i2c_common->bus_id)) { - dev_warn(ndev_dev(privdata), + pci_warn(privdata->pci_dev, "bus %d attempting to unlock C2P locked by bus %d\n", i2c_common->bus_id, privdata->c2p_lock_busid); return; @@ -59,8 +59,7 @@ int amd_mp2_bus_enable_set(struct amd_i2c_common *i2c_common, bool enable) struct amd_mp2_dev *privdata = i2c_common->mp2_dev; union i2c_cmd_base i2c_cmd_base; - dev_dbg(ndev_dev(privdata), "%s id: %d\n", __func__, - i2c_common->bus_id); + pci_dbg(privdata->pci_dev, "id: %d\n", i2c_common->bus_id); i2c_cmd_base.ul = 0; i2c_cmd_base.s.i2c_cmd = enable ? i2c_enable : i2c_disable; @@ -111,20 +110,19 @@ EXPORT_SYMBOL_GPL(amd_mp2_rw); static void amd_mp2_pci_check_rw_event(struct amd_i2c_common *i2c_common) { struct amd_mp2_dev *privdata = i2c_common->mp2_dev; + struct pci_dev *pdev = privdata->pci_dev; int len = i2c_common->eventval.r.length; u32 slave_addr = i2c_common->eventval.r.slave_addr; bool err = false; if (unlikely(len != i2c_common->msg->len)) { - dev_err(ndev_dev(privdata), - "length %d in event doesn't match buffer length %d!\n", + pci_err(pdev, "length %d in event doesn't match buffer length %d!\n", len, i2c_common->msg->len); err = true; } if (unlikely(slave_addr != i2c_common->msg->addr)) { - dev_err(ndev_dev(privdata), - "unexpected slave address %x (expected: %x)!\n", + pci_err(pdev, "unexpected slave address %x (expected: %x)!\n", slave_addr, i2c_common->msg->addr); err = true; } @@ -136,13 +134,14 @@ static void amd_mp2_pci_check_rw_event(struct amd_i2c_common *i2c_common) static void __amd_mp2_process_event(struct amd_i2c_common *i2c_common) { struct amd_mp2_dev *privdata = i2c_common->mp2_dev; + struct pci_dev *pdev = privdata->pci_dev; enum status_type sts = i2c_common->eventval.r.status; enum response_type res = i2c_common->eventval.r.response; int len = i2c_common->eventval.r.length; if (res != command_success) { if (res != command_failed) - dev_err(ndev_dev(privdata), "invalid response to i2c command!\n"); + pci_err(pdev, "invalid response to i2c command!\n"); return; } @@ -155,32 +154,26 @@ static void __amd_mp2_process_event(struct amd_i2c_common *i2c_common) privdata->mmio + AMD_C2P_MSG2, len); } else if (sts != i2c_readfail_event) { - dev_err(ndev_dev(privdata), - "invalid i2c status after read (%d)!\n", sts); + pci_err(pdev, "invalid i2c status after read (%d)!\n", sts); } break; case i2c_write: if (sts == i2c_writecomplete_event) amd_mp2_pci_check_rw_event(i2c_common); else if (sts != i2c_writefail_event) - dev_err(ndev_dev(privdata), - "invalid i2c status after write (%d)!\n", sts); + pci_err(pdev, "invalid i2c status after write (%d)!\n", sts); break; case i2c_enable: if (sts == i2c_busenable_complete) i2c_common->cmd_success = true; else if (sts != i2c_busenable_failed) - dev_err(ndev_dev(privdata), - "invalid i2c status after bus enable (%d)!\n", - sts); + pci_err(pdev, "invalid i2c status after bus enable (%d)!\n", sts); break; case i2c_disable: if (sts == i2c_busdisable_complete) i2c_common->cmd_success = true; else if (sts != i2c_busdisable_failed) - dev_err(ndev_dev(privdata), - "invalid i2c status after bus disable (%d)!\n", - sts); + pci_err(pdev, "invalid i2c status after bus disable (%d)!\n", sts); break; default: break; @@ -190,10 +183,10 @@ static void __amd_mp2_process_event(struct amd_i2c_common *i2c_common) void amd_mp2_process_event(struct amd_i2c_common *i2c_common) { struct amd_mp2_dev *privdata = i2c_common->mp2_dev; + struct pci_dev *pdev = privdata->pci_dev; if (unlikely(i2c_common->reqcmd == i2c_none)) { - dev_warn(ndev_dev(privdata), - "received msg but no cmd was sent (bus = %d)!\n", + pci_warn(pdev, "received msg but no cmd was sent (bus = %d)!\n", i2c_common->bus_id); return; } @@ -208,6 +201,7 @@ EXPORT_SYMBOL_GPL(amd_mp2_process_event); static irqreturn_t amd_mp2_irq_isr(int irq, void *dev) { struct amd_mp2_dev *privdata = dev; + struct pci_dev *pdev = privdata->pci_dev; struct amd_i2c_common *i2c_common; u32 val; unsigned int bus_id; @@ -236,8 +230,7 @@ static irqreturn_t amd_mp2_irq_isr(int irq, void *dev) val = readl(privdata->mmio + AMD_P2C_MSG_INTEN); if (val != 0) { writel(0, privdata->mmio + AMD_P2C_MSG_INTEN); - dev_warn(ndev_dev(privdata), - "received irq without message\n"); + pci_warn(pdev, "received irq without message\n"); ret = IRQ_HANDLED; } } @@ -255,13 +248,13 @@ EXPORT_SYMBOL_GPL(amd_mp2_rw_timeout); int amd_mp2_register_cb(struct amd_i2c_common *i2c_common) { struct amd_mp2_dev *privdata = i2c_common->mp2_dev; + struct pci_dev *pdev = privdata->pci_dev; if (i2c_common->bus_id > 1) return -EINVAL; if (privdata->busses[i2c_common->bus_id]) { - dev_err(ndev_dev(privdata), - "Bus %d already taken!\n", i2c_common->bus_id); + pci_err(pdev, "Bus %d already taken!\n", i2c_common->bus_id); return -EINVAL; } @@ -301,13 +294,13 @@ static int amd_mp2_pci_init(struct amd_mp2_dev *privdata, rc = pcim_enable_device(pci_dev); if (rc) { - dev_err(ndev_dev(privdata), "Failed to enable MP2 PCI device\n"); + pci_err(pci_dev, "Failed to enable MP2 PCI device\n"); goto err_pci_enable; } rc = pcim_iomap_regions(pci_dev, 1 << 2, pci_name(pci_dev)); if (rc) { - dev_err(ndev_dev(privdata), "I/O memory remapping failed\n"); + pci_err(pci_dev, "I/O memory remapping failed\n"); goto err_pci_enable; } privdata->mmio = pcim_iomap_table(pci_dev)[2]; @@ -327,7 +320,7 @@ static int amd_mp2_pci_init(struct amd_mp2_dev *privdata, rc = devm_request_irq(&pci_dev->dev, pci_dev->irq, amd_mp2_irq_isr, IRQF_SHARED, dev_name(&pci_dev->dev), privdata); if (rc) - dev_err(&pci_dev->dev, "Failure requesting irq %i: %d\n", + pci_err(pci_dev, "Failure requesting irq %i: %d\n", pci_dev->irq, rc); return rc; @@ -363,7 +356,7 @@ static int amd_mp2_pci_probe(struct pci_dev *pci_dev, privdata->probed = true; - dev_info(&pci_dev->dev, "MP2 device registered.\n"); + pci_info(pci_dev, "MP2 device registered.\n"); return 0; } @@ -397,8 +390,7 @@ static int amd_mp2_pci_suspend(struct device *dev) ret = pci_save_state(pci_dev); if (ret) { - dev_err(ndev_dev(privdata), - "pci_save_state failed = %d\n", ret); + pci_err(pci_dev, "pci_save_state failed = %d\n", ret); return ret; } @@ -417,8 +409,7 @@ static int amd_mp2_pci_resume(struct device *dev) pci_restore_state(pci_dev); ret = pci_enable_device(pci_dev); if (ret < 0) { - dev_err(ndev_dev(privdata), - "pci_enable_device failed = %d\n", ret); + pci_err(pci_dev, "pci_enable_device failed = %d\n", ret); return ret; } diff --git a/drivers/i2c/busses/i2c-amd-mp2-plat.c b/drivers/i2c/busses/i2c-amd-mp2-plat.c index 506433bc0ff2..de058671f9b8 100644 --- a/drivers/i2c/busses/i2c-amd-mp2-plat.c +++ b/drivers/i2c/busses/i2c-amd-mp2-plat.c @@ -88,8 +88,7 @@ static void i2c_amd_cmd_completion(struct amd_i2c_common *i2c_common) union i2c_event *event = &i2c_common->eventval; if (event->r.status == i2c_readcomplete_event) - dev_dbg(&i2c_dev->pdev->dev, "%s readdata:%*ph\n", - __func__, event->r.length, + dev_dbg(&i2c_dev->pdev->dev, "readdata:%*ph\n", event->r.length, i2c_common->msg->buf); complete(&i2c_dev->cmd_complete); diff --git a/drivers/i2c/busses/i2c-amd-mp2.h b/drivers/i2c/busses/i2c-amd-mp2.h index 058362edebaa..ddecd0c88656 100644 --- a/drivers/i2c/busses/i2c-amd-mp2.h +++ b/drivers/i2c/busses/i2c-amd-mp2.h @@ -185,12 +185,6 @@ struct amd_mp2_dev { unsigned int probed; }; -#define ndev_pdev(ndev) ((ndev)->pci_dev) -#define ndev_name(ndev) pci_name(ndev_pdev(ndev)) -#define ndev_dev(ndev) (&ndev_pdev(ndev)->dev) -#define work_amd_i2c_common(__work) \ - container_of(__work, struct amd_i2c_common, work.work) - /* PCIe communication driver */ int amd_mp2_rw(struct amd_i2c_common *i2c_common, enum i2c_cmd reqcmd); diff --git a/drivers/i2c/busses/i2c-bcm-iproc.c b/drivers/i2c/busses/i2c-bcm-iproc.c index d8295b1c379d..cceaf69279a9 100644 --- a/drivers/i2c/busses/i2c-bcm-iproc.c +++ b/drivers/i2c/busses/i2c-bcm-iproc.c @@ -93,6 +93,7 @@ #define S_CMD_STATUS_MASK 0x07 #define S_CMD_STATUS_SUCCESS 0x0 #define S_CMD_STATUS_TIMEOUT 0x5 +#define S_CMD_STATUS_MASTER_ABORT 0x7 #define IE_OFFSET 0x38 #define IE_M_RX_FIFO_FULL_SHIFT 31 @@ -159,6 +160,11 @@ #define IE_S_ALL_INTERRUPT_SHIFT 21 #define IE_S_ALL_INTERRUPT_MASK 0x3f +/* + * It takes ~18us to reading 10bytes of data, hence to keep tasklet + * running for less time, max slave read per tasklet is set to 10 bytes. + */ +#define MAX_SLAVE_RX_PER_INT 10 enum i2c_slave_read_status { I2C_SLAVE_RX_FIFO_EMPTY = 0, @@ -205,8 +211,18 @@ struct bcm_iproc_i2c_dev { /* bytes that have been read */ unsigned int rx_bytes; unsigned int thld_bytes; + + bool slave_rx_only; + bool rx_start_rcvd; + bool slave_read_complete; + u32 tx_underrun; + u32 slave_int_mask; + struct tasklet_struct slave_rx_tasklet; }; +/* tasklet to process slave rx data */ +static void slave_rx_tasklet_fn(unsigned long); + /* * Can be expanded in the future if more interrupt status bits are utilized */ @@ -215,7 +231,8 @@ struct bcm_iproc_i2c_dev { #define ISR_MASK_SLAVE (BIT(IS_S_START_BUSY_SHIFT)\ | BIT(IS_S_RX_EVENT_SHIFT) | BIT(IS_S_RD_EVENT_SHIFT)\ - | BIT(IS_S_TX_UNDERRUN_SHIFT)) + | BIT(IS_S_TX_UNDERRUN_SHIFT) | BIT(IS_S_RX_FIFO_FULL_SHIFT)\ + | BIT(IS_S_RX_THLD_SHIFT)) static int bcm_iproc_i2c_reg_slave(struct i2c_client *slave); static int bcm_iproc_i2c_unreg_slave(struct i2c_client *slave); @@ -259,6 +276,7 @@ static void bcm_iproc_i2c_slave_init( { u32 val; + iproc_i2c->tx_underrun = 0; if (need_reset) { /* put controller in reset */ val = iproc_i2c_rd_reg(iproc_i2c, CFG_OFFSET); @@ -295,8 +313,13 @@ static void bcm_iproc_i2c_slave_init( /* Enable interrupt register to indicate a valid byte in receive fifo */ val = BIT(IE_S_RX_EVENT_SHIFT); + /* Enable interrupt register to indicate Slave Rx FIFO Full */ + val |= BIT(IE_S_RX_FIFO_FULL_SHIFT); + /* Enable interrupt register to indicate a Master read transaction */ + val |= BIT(IE_S_RD_EVENT_SHIFT); /* Enable interrupt register for the Slave BUSY command */ val |= BIT(IE_S_START_BUSY_SHIFT); + iproc_i2c->slave_int_mask = val; iproc_i2c_wr_reg(iproc_i2c, IE_OFFSET, val); } @@ -311,9 +334,10 @@ static void bcm_iproc_i2c_check_slave_status( return; val = (val >> S_CMD_STATUS_SHIFT) & S_CMD_STATUS_MASK; - if (val == S_CMD_STATUS_TIMEOUT) { - dev_err(iproc_i2c->device, "slave random stretch time timeout\n"); - + if (val == S_CMD_STATUS_TIMEOUT || val == S_CMD_STATUS_MASTER_ABORT) { + dev_err(iproc_i2c->device, (val == S_CMD_STATUS_TIMEOUT) ? + "slave random stretch time timeout\n" : + "Master aborted read transaction\n"); /* re-initialize i2c for recovery */ bcm_iproc_i2c_enable_disable(iproc_i2c, false); bcm_iproc_i2c_slave_init(iproc_i2c, true); @@ -321,76 +345,187 @@ static void bcm_iproc_i2c_check_slave_status( } } -static bool bcm_iproc_i2c_slave_isr(struct bcm_iproc_i2c_dev *iproc_i2c, - u32 status) +static void bcm_iproc_i2c_slave_read(struct bcm_iproc_i2c_dev *iproc_i2c) { + u8 rx_data, rx_status; + u32 rx_bytes = 0; u32 val; - u8 value, rx_status; - /* Slave RX byte receive */ - if (status & BIT(IS_S_RX_EVENT_SHIFT)) { + while (rx_bytes < MAX_SLAVE_RX_PER_INT) { val = iproc_i2c_rd_reg(iproc_i2c, S_RX_OFFSET); rx_status = (val >> S_RX_STATUS_SHIFT) & S_RX_STATUS_MASK; - if (rx_status == I2C_SLAVE_RX_START) { - /* Start of SMBUS for Master write */ - i2c_slave_event(iproc_i2c->slave, - I2C_SLAVE_WRITE_REQUESTED, &value); + rx_data = ((val >> S_RX_DATA_SHIFT) & S_RX_DATA_MASK); - val = iproc_i2c_rd_reg(iproc_i2c, S_RX_OFFSET); - value = (u8)((val >> S_RX_DATA_SHIFT) & S_RX_DATA_MASK); + if (rx_status == I2C_SLAVE_RX_START) { + /* Start of SMBUS Master write */ i2c_slave_event(iproc_i2c->slave, - I2C_SLAVE_WRITE_RECEIVED, &value); - } else if (status & BIT(IS_S_RD_EVENT_SHIFT)) { - /* Start of SMBUS for Master Read */ + I2C_SLAVE_WRITE_REQUESTED, &rx_data); + iproc_i2c->rx_start_rcvd = true; + iproc_i2c->slave_read_complete = false; + } else if (rx_status == I2C_SLAVE_RX_DATA && + iproc_i2c->rx_start_rcvd) { + /* Middle of SMBUS Master write */ i2c_slave_event(iproc_i2c->slave, - I2C_SLAVE_READ_REQUESTED, &value); - iproc_i2c_wr_reg(iproc_i2c, S_TX_OFFSET, value); + I2C_SLAVE_WRITE_RECEIVED, &rx_data); + } else if (rx_status == I2C_SLAVE_RX_END && + iproc_i2c->rx_start_rcvd) { + /* End of SMBUS Master write */ + if (iproc_i2c->slave_rx_only) + i2c_slave_event(iproc_i2c->slave, + I2C_SLAVE_WRITE_RECEIVED, + &rx_data); + + i2c_slave_event(iproc_i2c->slave, I2C_SLAVE_STOP, + &rx_data); + } else if (rx_status == I2C_SLAVE_RX_FIFO_EMPTY) { + iproc_i2c->rx_start_rcvd = false; + iproc_i2c->slave_read_complete = true; + break; + } - val = BIT(S_CMD_START_BUSY_SHIFT); - iproc_i2c_wr_reg(iproc_i2c, S_CMD_OFFSET, val); + rx_bytes++; + } +} - /* - * Enable interrupt for TX FIFO becomes empty and - * less than PKT_LENGTH bytes were output on the SMBUS - */ - val = iproc_i2c_rd_reg(iproc_i2c, IE_OFFSET); - val |= BIT(IE_S_TX_UNDERRUN_SHIFT); - iproc_i2c_wr_reg(iproc_i2c, IE_OFFSET, val); - } else { - /* Master write other than start */ - value = (u8)((val >> S_RX_DATA_SHIFT) & S_RX_DATA_MASK); +static void slave_rx_tasklet_fn(unsigned long data) +{ + struct bcm_iproc_i2c_dev *iproc_i2c = (struct bcm_iproc_i2c_dev *)data; + u32 int_clr; + + bcm_iproc_i2c_slave_read(iproc_i2c); + + /* clear pending IS_S_RX_EVENT_SHIFT interrupt */ + int_clr = BIT(IS_S_RX_EVENT_SHIFT); + + if (!iproc_i2c->slave_rx_only && iproc_i2c->slave_read_complete) { + /* + * In case of single byte master-read request, + * IS_S_TX_UNDERRUN_SHIFT event is generated before + * IS_S_START_BUSY_SHIFT event. Hence start slave data send + * from first IS_S_TX_UNDERRUN_SHIFT event. + * + * This means don't send any data from slave when + * IS_S_RD_EVENT_SHIFT event is generated else it will increment + * eeprom or other backend slave driver read pointer twice. + */ + iproc_i2c->tx_underrun = 0; + iproc_i2c->slave_int_mask |= BIT(IE_S_TX_UNDERRUN_SHIFT); + + /* clear IS_S_RD_EVENT_SHIFT interrupt */ + int_clr |= BIT(IS_S_RD_EVENT_SHIFT); + } + + /* clear slave interrupt */ + iproc_i2c_wr_reg(iproc_i2c, IS_OFFSET, int_clr); + /* enable slave interrupts */ + iproc_i2c_wr_reg(iproc_i2c, IE_OFFSET, iproc_i2c->slave_int_mask); +} + +static bool bcm_iproc_i2c_slave_isr(struct bcm_iproc_i2c_dev *iproc_i2c, + u32 status) +{ + u32 val; + u8 value; + + /* + * Slave events in case of master-write, master-write-read and, + * master-read + * + * Master-write : only IS_S_RX_EVENT_SHIFT event + * Master-write-read: both IS_S_RX_EVENT_SHIFT and IS_S_RD_EVENT_SHIFT + * events + * Master-read : both IS_S_RX_EVENT_SHIFT and IS_S_RD_EVENT_SHIFT + * events or only IS_S_RD_EVENT_SHIFT + * + * iproc has a slave rx fifo size of 64 bytes. Rx fifo full interrupt + * (IS_S_RX_FIFO_FULL_SHIFT) will be generated when RX fifo becomes + * full. This can happen if Master issues write requests of more than + * 64 bytes. + */ + if (status & BIT(IS_S_RX_EVENT_SHIFT) || + status & BIT(IS_S_RD_EVENT_SHIFT) || + status & BIT(IS_S_RX_FIFO_FULL_SHIFT)) { + /* disable slave interrupts */ + val = iproc_i2c_rd_reg(iproc_i2c, IE_OFFSET); + val &= ~iproc_i2c->slave_int_mask; + iproc_i2c_wr_reg(iproc_i2c, IE_OFFSET, val); + + if (status & BIT(IS_S_RD_EVENT_SHIFT)) + /* Master-write-read request */ + iproc_i2c->slave_rx_only = false; + else + /* Master-write request only */ + iproc_i2c->slave_rx_only = true; + + /* schedule tasklet to read data later */ + tasklet_schedule(&iproc_i2c->slave_rx_tasklet); + + /* + * clear only IS_S_RX_EVENT_SHIFT and + * IS_S_RX_FIFO_FULL_SHIFT interrupt. + */ + val = BIT(IS_S_RX_EVENT_SHIFT); + if (status & BIT(IS_S_RX_FIFO_FULL_SHIFT)) + val |= BIT(IS_S_RX_FIFO_FULL_SHIFT); + iproc_i2c_wr_reg(iproc_i2c, IS_OFFSET, val); + } + + if (status & BIT(IS_S_TX_UNDERRUN_SHIFT)) { + iproc_i2c->tx_underrun++; + if (iproc_i2c->tx_underrun == 1) + /* Start of SMBUS for Master Read */ i2c_slave_event(iproc_i2c->slave, - I2C_SLAVE_WRITE_RECEIVED, &value); - if (rx_status == I2C_SLAVE_RX_END) - i2c_slave_event(iproc_i2c->slave, - I2C_SLAVE_STOP, &value); - } - } else if (status & BIT(IS_S_TX_UNDERRUN_SHIFT)) { - /* Master read other than start */ - i2c_slave_event(iproc_i2c->slave, - I2C_SLAVE_READ_PROCESSED, &value); + I2C_SLAVE_READ_REQUESTED, + &value); + else + /* Master read other than start */ + i2c_slave_event(iproc_i2c->slave, + I2C_SLAVE_READ_PROCESSED, + &value); iproc_i2c_wr_reg(iproc_i2c, S_TX_OFFSET, value); + /* start transfer */ val = BIT(S_CMD_START_BUSY_SHIFT); iproc_i2c_wr_reg(iproc_i2c, S_CMD_OFFSET, val); + + /* clear interrupt */ + iproc_i2c_wr_reg(iproc_i2c, IS_OFFSET, + BIT(IS_S_TX_UNDERRUN_SHIFT)); } - /* Stop */ + /* Stop received from master in case of master read transaction */ if (status & BIT(IS_S_START_BUSY_SHIFT)) { - i2c_slave_event(iproc_i2c->slave, I2C_SLAVE_STOP, &value); /* - * Enable interrupt for TX FIFO becomes empty and + * Disable interrupt for TX FIFO becomes empty and * less than PKT_LENGTH bytes were output on the SMBUS */ - val = iproc_i2c_rd_reg(iproc_i2c, IE_OFFSET); - val &= ~BIT(IE_S_TX_UNDERRUN_SHIFT); - iproc_i2c_wr_reg(iproc_i2c, IE_OFFSET, val); + iproc_i2c->slave_int_mask &= ~BIT(IE_S_TX_UNDERRUN_SHIFT); + iproc_i2c_wr_reg(iproc_i2c, IE_OFFSET, + iproc_i2c->slave_int_mask); + + /* End of SMBUS for Master Read */ + val = BIT(S_TX_WR_STATUS_SHIFT); + iproc_i2c_wr_reg(iproc_i2c, S_TX_OFFSET, val); + + val = BIT(S_CMD_START_BUSY_SHIFT); + iproc_i2c_wr_reg(iproc_i2c, S_CMD_OFFSET, val); + + /* flush TX FIFOs */ + val = iproc_i2c_rd_reg(iproc_i2c, S_FIFO_CTRL_OFFSET); + val |= (BIT(S_FIFO_TX_FLUSH_SHIFT)); + iproc_i2c_wr_reg(iproc_i2c, S_FIFO_CTRL_OFFSET, val); + + i2c_slave_event(iproc_i2c->slave, I2C_SLAVE_STOP, &value); + + /* clear interrupt */ + iproc_i2c_wr_reg(iproc_i2c, IS_OFFSET, + BIT(IS_S_START_BUSY_SHIFT)); } - /* clear interrupt status */ - iproc_i2c_wr_reg(iproc_i2c, IS_OFFSET, status); + /* check slave transmit status only if slave is transmitting */ + if (!iproc_i2c->slave_rx_only) + bcm_iproc_i2c_check_slave_status(iproc_i2c); - bcm_iproc_i2c_check_slave_status(iproc_i2c); return true; } @@ -505,12 +640,17 @@ static void bcm_iproc_i2c_process_m_event(struct bcm_iproc_i2c_dev *iproc_i2c, static irqreturn_t bcm_iproc_i2c_isr(int irq, void *data) { struct bcm_iproc_i2c_dev *iproc_i2c = data; - u32 status = iproc_i2c_rd_reg(iproc_i2c, IS_OFFSET); + u32 slave_status; + u32 status; bool ret; - u32 sl_status = status & ISR_MASK_SLAVE; - if (sl_status) { - ret = bcm_iproc_i2c_slave_isr(iproc_i2c, sl_status); + status = iproc_i2c_rd_reg(iproc_i2c, IS_OFFSET); + /* process only slave interrupt which are enabled */ + slave_status = status & iproc_i2c_rd_reg(iproc_i2c, IE_OFFSET) & + ISR_MASK_SLAVE; + + if (slave_status) { + ret = bcm_iproc_i2c_slave_isr(iproc_i2c, slave_status); if (ret) return IRQ_HANDLED; else @@ -1066,6 +1206,10 @@ static int bcm_iproc_i2c_reg_slave(struct i2c_client *slave) return -EAFNOSUPPORT; iproc_i2c->slave = slave; + + tasklet_init(&iproc_i2c->slave_rx_tasklet, slave_rx_tasklet_fn, + (unsigned long)iproc_i2c); + bcm_iproc_i2c_slave_init(iproc_i2c, false); return 0; } @@ -1086,6 +1230,8 @@ static int bcm_iproc_i2c_unreg_slave(struct i2c_client *slave) IE_S_ALL_INTERRUPT_SHIFT); iproc_i2c_wr_reg(iproc_i2c, IE_OFFSET, tmp); + tasklet_kill(&iproc_i2c->slave_rx_tasklet); + /* Erase the slave address programmed */ tmp = iproc_i2c_rd_reg(iproc_i2c, S_CFG_SMBUS_ADDR_OFFSET); tmp &= ~BIT(S_CFG_EN_NIC_SMB_ADDR3_SHIFT); diff --git a/drivers/i2c/busses/i2c-digicolor.c b/drivers/i2c/busses/i2c-digicolor.c index f67639dc74b7..60c838c7c454 100644 --- a/drivers/i2c/busses/i2c-digicolor.c +++ b/drivers/i2c/busses/i2c-digicolor.c @@ -160,12 +160,11 @@ static irqreturn_t dc_i2c_irq(int irq, void *dev_id) { struct dc_i2c *i2c = dev_id; int cmd_status = dc_i2c_cmd_status(i2c); - unsigned long flags; u8 addr_cmd; writeb_relaxed(1, i2c->regs + II_INTFLAG_CLEAR); - spin_lock_irqsave(&i2c->lock, flags); + spin_lock(&i2c->lock); if (cmd_status == II_CMD_STATUS_ACK_BAD || cmd_status == II_CMD_STATUS_ABORT) { @@ -207,7 +206,7 @@ static irqreturn_t dc_i2c_irq(int irq, void *dev_id) } out: - spin_unlock_irqrestore(&i2c->lock, flags); + spin_unlock(&i2c->lock); return IRQ_HANDLED; } diff --git a/drivers/i2c/busses/i2c-efm32.c b/drivers/i2c/busses/i2c-efm32.c deleted file mode 100644 index f6e13ceeb2b3..000000000000 --- a/drivers/i2c/busses/i2c-efm32.c +++ /dev/null @@ -1,469 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (C) 2014 Uwe Kleine-Koenig for Pengutronix - */ -#include <linux/module.h> -#include <linux/platform_device.h> -#include <linux/i2c.h> -#include <linux/io.h> -#include <linux/interrupt.h> -#include <linux/err.h> -#include <linux/clk.h> - -#define DRIVER_NAME "efm32-i2c" - -#define MASK_VAL(mask, val) ((val << __ffs(mask)) & mask) - -#define REG_CTRL 0x00 -#define REG_CTRL_EN 0x00001 -#define REG_CTRL_SLAVE 0x00002 -#define REG_CTRL_AUTOACK 0x00004 -#define REG_CTRL_AUTOSE 0x00008 -#define REG_CTRL_AUTOSN 0x00010 -#define REG_CTRL_ARBDIS 0x00020 -#define REG_CTRL_GCAMEN 0x00040 -#define REG_CTRL_CLHR__MASK 0x00300 -#define REG_CTRL_BITO__MASK 0x03000 -#define REG_CTRL_BITO_OFF 0x00000 -#define REG_CTRL_BITO_40PCC 0x01000 -#define REG_CTRL_BITO_80PCC 0x02000 -#define REG_CTRL_BITO_160PCC 0x03000 -#define REG_CTRL_GIBITO 0x08000 -#define REG_CTRL_CLTO__MASK 0x70000 -#define REG_CTRL_CLTO_OFF 0x00000 - -#define REG_CMD 0x04 -#define REG_CMD_START 0x00001 -#define REG_CMD_STOP 0x00002 -#define REG_CMD_ACK 0x00004 -#define REG_CMD_NACK 0x00008 -#define REG_CMD_CONT 0x00010 -#define REG_CMD_ABORT 0x00020 -#define REG_CMD_CLEARTX 0x00040 -#define REG_CMD_CLEARPC 0x00080 - -#define REG_STATE 0x08 -#define REG_STATE_BUSY 0x00001 -#define REG_STATE_MASTER 0x00002 -#define REG_STATE_TRANSMITTER 0x00004 -#define REG_STATE_NACKED 0x00008 -#define REG_STATE_BUSHOLD 0x00010 -#define REG_STATE_STATE__MASK 0x000e0 -#define REG_STATE_STATE_IDLE 0x00000 -#define REG_STATE_STATE_WAIT 0x00020 -#define REG_STATE_STATE_START 0x00040 -#define REG_STATE_STATE_ADDR 0x00060 -#define REG_STATE_STATE_ADDRACK 0x00080 -#define REG_STATE_STATE_DATA 0x000a0 -#define REG_STATE_STATE_DATAACK 0x000c0 - -#define REG_STATUS 0x0c -#define REG_STATUS_PSTART 0x00001 -#define REG_STATUS_PSTOP 0x00002 -#define REG_STATUS_PACK 0x00004 -#define REG_STATUS_PNACK 0x00008 -#define REG_STATUS_PCONT 0x00010 -#define REG_STATUS_PABORT 0x00020 -#define REG_STATUS_TXC 0x00040 -#define REG_STATUS_TXBL 0x00080 -#define REG_STATUS_RXDATAV 0x00100 - -#define REG_CLKDIV 0x10 -#define REG_CLKDIV_DIV__MASK 0x001ff -#define REG_CLKDIV_DIV(div) MASK_VAL(REG_CLKDIV_DIV__MASK, (div)) - -#define REG_SADDR 0x14 -#define REG_SADDRMASK 0x18 -#define REG_RXDATA 0x1c -#define REG_RXDATAP 0x20 -#define REG_TXDATA 0x24 -#define REG_IF 0x28 -#define REG_IF_START 0x00001 -#define REG_IF_RSTART 0x00002 -#define REG_IF_ADDR 0x00004 -#define REG_IF_TXC 0x00008 -#define REG_IF_TXBL 0x00010 -#define REG_IF_RXDATAV 0x00020 -#define REG_IF_ACK 0x00040 -#define REG_IF_NACK 0x00080 -#define REG_IF_MSTOP 0x00100 -#define REG_IF_ARBLOST 0x00200 -#define REG_IF_BUSERR 0x00400 -#define REG_IF_BUSHOLD 0x00800 -#define REG_IF_TXOF 0x01000 -#define REG_IF_RXUF 0x02000 -#define REG_IF_BITO 0x04000 -#define REG_IF_CLTO 0x08000 -#define REG_IF_SSTOP 0x10000 - -#define REG_IFS 0x2c -#define REG_IFC 0x30 -#define REG_IFC__MASK 0x1ffcf - -#define REG_IEN 0x34 - -#define REG_ROUTE 0x38 -#define REG_ROUTE_SDAPEN 0x00001 -#define REG_ROUTE_SCLPEN 0x00002 -#define REG_ROUTE_LOCATION__MASK 0x00700 -#define REG_ROUTE_LOCATION(n) MASK_VAL(REG_ROUTE_LOCATION__MASK, (n)) - -struct efm32_i2c_ddata { - struct i2c_adapter adapter; - - struct clk *clk; - void __iomem *base; - unsigned int irq; - u8 location; - unsigned long frequency; - - /* transfer data */ - struct completion done; - struct i2c_msg *msgs; - size_t num_msgs; - size_t current_word, current_msg; - int retval; -}; - -static u32 efm32_i2c_read32(struct efm32_i2c_ddata *ddata, unsigned offset) -{ - return readl(ddata->base + offset); -} - -static void efm32_i2c_write32(struct efm32_i2c_ddata *ddata, - unsigned offset, u32 value) -{ - writel(value, ddata->base + offset); -} - -static void efm32_i2c_send_next_msg(struct efm32_i2c_ddata *ddata) -{ - struct i2c_msg *cur_msg = &ddata->msgs[ddata->current_msg]; - - efm32_i2c_write32(ddata, REG_CMD, REG_CMD_START); - efm32_i2c_write32(ddata, REG_TXDATA, i2c_8bit_addr_from_msg(cur_msg)); -} - -static void efm32_i2c_send_next_byte(struct efm32_i2c_ddata *ddata) -{ - struct i2c_msg *cur_msg = &ddata->msgs[ddata->current_msg]; - - if (ddata->current_word >= cur_msg->len) { - /* cur_msg completely transferred */ - ddata->current_word = 0; - ddata->current_msg += 1; - - if (ddata->current_msg >= ddata->num_msgs) { - efm32_i2c_write32(ddata, REG_CMD, REG_CMD_STOP); - complete(&ddata->done); - } else { - efm32_i2c_send_next_msg(ddata); - } - } else { - efm32_i2c_write32(ddata, REG_TXDATA, - cur_msg->buf[ddata->current_word++]); - } -} - -static void efm32_i2c_recv_next_byte(struct efm32_i2c_ddata *ddata) -{ - struct i2c_msg *cur_msg = &ddata->msgs[ddata->current_msg]; - - cur_msg->buf[ddata->current_word] = efm32_i2c_read32(ddata, REG_RXDATA); - ddata->current_word += 1; - if (ddata->current_word >= cur_msg->len) { - /* cur_msg completely transferred */ - ddata->current_word = 0; - ddata->current_msg += 1; - - efm32_i2c_write32(ddata, REG_CMD, REG_CMD_NACK); - - if (ddata->current_msg >= ddata->num_msgs) { - efm32_i2c_write32(ddata, REG_CMD, REG_CMD_STOP); - complete(&ddata->done); - } else { - efm32_i2c_send_next_msg(ddata); - } - } else { - efm32_i2c_write32(ddata, REG_CMD, REG_CMD_ACK); - } -} - -static irqreturn_t efm32_i2c_irq(int irq, void *dev_id) -{ - struct efm32_i2c_ddata *ddata = dev_id; - struct i2c_msg *cur_msg = &ddata->msgs[ddata->current_msg]; - u32 irqflag = efm32_i2c_read32(ddata, REG_IF); - u32 state = efm32_i2c_read32(ddata, REG_STATE); - - efm32_i2c_write32(ddata, REG_IFC, irqflag & REG_IFC__MASK); - - switch (state & REG_STATE_STATE__MASK) { - case REG_STATE_STATE_IDLE: - /* arbitration lost? */ - ddata->retval = -EAGAIN; - complete(&ddata->done); - break; - case REG_STATE_STATE_WAIT: - /* - * huh, this shouldn't happen. - * Reset hardware state and get out - */ - ddata->retval = -EIO; - efm32_i2c_write32(ddata, REG_CMD, - REG_CMD_STOP | REG_CMD_ABORT | - REG_CMD_CLEARTX | REG_CMD_CLEARPC); - complete(&ddata->done); - break; - case REG_STATE_STATE_START: - /* "caller" is expected to send an address */ - break; - case REG_STATE_STATE_ADDR: - /* wait for Ack or NAck of slave */ - break; - case REG_STATE_STATE_ADDRACK: - if (state & REG_STATE_NACKED) { - efm32_i2c_write32(ddata, REG_CMD, REG_CMD_STOP); - ddata->retval = -ENXIO; - complete(&ddata->done); - } else if (cur_msg->flags & I2C_M_RD) { - /* wait for slave to send first data byte */ - } else { - efm32_i2c_send_next_byte(ddata); - } - break; - case REG_STATE_STATE_DATA: - if (cur_msg->flags & I2C_M_RD) { - efm32_i2c_recv_next_byte(ddata); - } else { - /* wait for Ack or Nack of slave */ - } - break; - case REG_STATE_STATE_DATAACK: - if (state & REG_STATE_NACKED) { - efm32_i2c_write32(ddata, REG_CMD, REG_CMD_STOP); - complete(&ddata->done); - } else { - efm32_i2c_send_next_byte(ddata); - } - } - - return IRQ_HANDLED; -} - -static int efm32_i2c_master_xfer(struct i2c_adapter *adap, - struct i2c_msg *msgs, int num) -{ - struct efm32_i2c_ddata *ddata = i2c_get_adapdata(adap); - int ret; - - if (ddata->msgs) - return -EBUSY; - - ddata->msgs = msgs; - ddata->num_msgs = num; - ddata->current_word = 0; - ddata->current_msg = 0; - ddata->retval = -EIO; - - reinit_completion(&ddata->done); - - dev_dbg(&ddata->adapter.dev, "state: %08x, status: %08x\n", - efm32_i2c_read32(ddata, REG_STATE), - efm32_i2c_read32(ddata, REG_STATUS)); - - efm32_i2c_send_next_msg(ddata); - - wait_for_completion(&ddata->done); - - if (ddata->current_msg >= ddata->num_msgs) - ret = ddata->num_msgs; - else - ret = ddata->retval; - - return ret; -} - -static u32 efm32_i2c_functionality(struct i2c_adapter *adap) -{ - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; -} - -static const struct i2c_algorithm efm32_i2c_algo = { - .master_xfer = efm32_i2c_master_xfer, - .functionality = efm32_i2c_functionality, -}; - -static u32 efm32_i2c_get_configured_location(struct efm32_i2c_ddata *ddata) -{ - u32 reg = efm32_i2c_read32(ddata, REG_ROUTE); - - return (reg & REG_ROUTE_LOCATION__MASK) >> - __ffs(REG_ROUTE_LOCATION__MASK); -} - -static int efm32_i2c_probe(struct platform_device *pdev) -{ - struct efm32_i2c_ddata *ddata; - struct resource *res; - unsigned long rate; - struct device_node *np = pdev->dev.of_node; - u32 location, frequency; - int ret; - u32 clkdiv; - - ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL); - if (!ddata) - return -ENOMEM; - platform_set_drvdata(pdev, ddata); - - init_completion(&ddata->done); - strlcpy(ddata->adapter.name, pdev->name, sizeof(ddata->adapter.name)); - ddata->adapter.owner = THIS_MODULE; - ddata->adapter.algo = &efm32_i2c_algo; - ddata->adapter.dev.parent = &pdev->dev; - ddata->adapter.dev.of_node = pdev->dev.of_node; - i2c_set_adapdata(&ddata->adapter, ddata); - - ddata->clk = devm_clk_get(&pdev->dev, NULL); - if (IS_ERR(ddata->clk)) { - ret = PTR_ERR(ddata->clk); - dev_err(&pdev->dev, "failed to get clock: %d\n", ret); - return ret; - } - - ddata->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); - if (IS_ERR(ddata->base)) - return PTR_ERR(ddata->base); - - if (resource_size(res) < 0x42) { - dev_err(&pdev->dev, "memory resource too small\n"); - return -EINVAL; - } - - ret = platform_get_irq(pdev, 0); - if (ret <= 0) { - if (!ret) - ret = -EINVAL; - return ret; - } - - ddata->irq = ret; - - ret = clk_prepare_enable(ddata->clk); - if (ret < 0) { - dev_err(&pdev->dev, "failed to enable clock (%d)\n", ret); - return ret; - } - - - ret = of_property_read_u32(np, "energymicro,location", &location); - - if (ret) - /* fall back to wrongly namespaced property */ - ret = of_property_read_u32(np, "efm32,location", &location); - - if (!ret) { - dev_dbg(&pdev->dev, "using location %u\n", location); - } else { - /* default to location configured in hardware */ - location = efm32_i2c_get_configured_location(ddata); - - dev_info(&pdev->dev, "fall back to location %u\n", location); - } - - ddata->location = location; - - ret = of_property_read_u32(np, "clock-frequency", &frequency); - if (!ret) { - dev_dbg(&pdev->dev, "using frequency %u\n", frequency); - } else { - frequency = I2C_MAX_STANDARD_MODE_FREQ; - dev_info(&pdev->dev, "defaulting to 100 kHz\n"); - } - ddata->frequency = frequency; - - rate = clk_get_rate(ddata->clk); - if (!rate) { - dev_err(&pdev->dev, "there is no input clock available\n"); - ret = -EINVAL; - goto err_disable_clk; - } - clkdiv = DIV_ROUND_UP(rate, 8 * ddata->frequency) - 1; - if (clkdiv >= 0x200) { - dev_err(&pdev->dev, - "input clock too fast (%lu) to divide down to bus freq (%lu)", - rate, ddata->frequency); - ret = -EINVAL; - goto err_disable_clk; - } - - dev_dbg(&pdev->dev, "input clock = %lu, bus freq = %lu, clkdiv = %lu\n", - rate, ddata->frequency, (unsigned long)clkdiv); - efm32_i2c_write32(ddata, REG_CLKDIV, REG_CLKDIV_DIV(clkdiv)); - - efm32_i2c_write32(ddata, REG_ROUTE, REG_ROUTE_SDAPEN | - REG_ROUTE_SCLPEN | - REG_ROUTE_LOCATION(ddata->location)); - - efm32_i2c_write32(ddata, REG_CTRL, REG_CTRL_EN | - REG_CTRL_BITO_160PCC | 0 * REG_CTRL_GIBITO); - - efm32_i2c_write32(ddata, REG_IFC, REG_IFC__MASK); - efm32_i2c_write32(ddata, REG_IEN, REG_IF_TXC | REG_IF_ACK | REG_IF_NACK - | REG_IF_ARBLOST | REG_IF_BUSERR | REG_IF_RXDATAV); - - /* to make bus idle */ - efm32_i2c_write32(ddata, REG_CMD, REG_CMD_ABORT); - - ret = request_irq(ddata->irq, efm32_i2c_irq, 0, DRIVER_NAME, ddata); - if (ret < 0) { - dev_err(&pdev->dev, "failed to request irq (%d)\n", ret); - goto err_disable_clk; - } - - ret = i2c_add_adapter(&ddata->adapter); - if (ret) { - free_irq(ddata->irq, ddata); - -err_disable_clk: - clk_disable_unprepare(ddata->clk); - } - return ret; -} - -static int efm32_i2c_remove(struct platform_device *pdev) -{ - struct efm32_i2c_ddata *ddata = platform_get_drvdata(pdev); - - i2c_del_adapter(&ddata->adapter); - free_irq(ddata->irq, ddata); - clk_disable_unprepare(ddata->clk); - - return 0; -} - -static const struct of_device_id efm32_i2c_dt_ids[] = { - { - .compatible = "energymicro,efm32-i2c", - }, { - /* sentinel */ - } -}; -MODULE_DEVICE_TABLE(of, efm32_i2c_dt_ids); - -static struct platform_driver efm32_i2c_driver = { - .probe = efm32_i2c_probe, - .remove = efm32_i2c_remove, - - .driver = { - .name = DRIVER_NAME, - .of_match_table = efm32_i2c_dt_ids, - }, -}; -module_platform_driver(efm32_i2c_driver); - -MODULE_AUTHOR("Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>"); -MODULE_DESCRIPTION("EFM32 i2c driver"); -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("platform:" DRIVER_NAME); diff --git a/drivers/i2c/busses/i2c-elektor.c b/drivers/i2c/busses/i2c-elektor.c index b72a3c3ef2ab..b0f50dce9d0f 100644 --- a/drivers/i2c/busses/i2c-elektor.c +++ b/drivers/i2c/busses/i2c-elektor.c @@ -49,7 +49,7 @@ static int mmapped; static wait_queue_head_t pcf_wait; static int pcf_pending; -static spinlock_t lock; +static DEFINE_SPINLOCK(lock); static struct i2c_adapter pcf_isa_ops; @@ -132,7 +132,6 @@ static irqreturn_t pcf_isa_handler(int this_irq, void *dev_id) { static int pcf_isa_init(void) { - spin_lock_init(&lock); if (!mmapped) { if (!request_region(base, 2, pcf_isa_ops.name)) { printk(KERN_ERR "%s: requested I/O region (%#x:2) is " diff --git a/drivers/i2c/busses/i2c-gpio.c b/drivers/i2c/busses/i2c-gpio.c index a4a6825c8758..7a048abbf92b 100644 --- a/drivers/i2c/busses/i2c-gpio.c +++ b/drivers/i2c/busses/i2c-gpio.c @@ -520,5 +520,5 @@ module_exit(i2c_gpio_exit); MODULE_AUTHOR("Haavard Skinnemoen (Atmel)"); MODULE_DESCRIPTION("Platform-independent bitbanging I2C driver"); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL v2"); MODULE_ALIAS("platform:i2c-gpio"); diff --git a/drivers/i2c/busses/i2c-hix5hd2.c b/drivers/i2c/busses/i2c-hix5hd2.c index ab15b1ec2ab3..c45f226c2b85 100644 --- a/drivers/i2c/busses/i2c-hix5hd2.c +++ b/drivers/i2c/busses/i2c-hix5hd2.c @@ -413,10 +413,8 @@ static int hix5hd2_i2c_probe(struct platform_device *pdev) return PTR_ERR(priv->regs); irq = platform_get_irq(pdev, 0); - if (irq <= 0) { - dev_err(&pdev->dev, "cannot find HS-I2C IRQ\n"); + if (irq <= 0) return irq; - } priv->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(priv->clk)) { diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index 877fe3733a42..4acee6f9e5a3 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -72,6 +72,7 @@ * Jasper Lake (SOC) 0x4da3 32 hard yes yes yes * Comet Lake-V (PCH) 0xa3a3 32 hard yes yes yes * Alder Lake-S (PCH) 0x7aa3 32 hard yes yes yes + * Alder Lake-P (PCH) 0x51a3 32 hard yes yes yes * * Features supported by this driver: * Software PEC no @@ -228,6 +229,7 @@ #define PCI_DEVICE_ID_INTEL_TIGERLAKE_H_SMBUS 0x43a3 #define PCI_DEVICE_ID_INTEL_ELKHART_LAKE_SMBUS 0x4b23 #define PCI_DEVICE_ID_INTEL_JASPER_LAKE_SMBUS 0x4da3 +#define PCI_DEVICE_ID_INTEL_ALDER_LAKE_P_SMBUS 0x51a3 #define PCI_DEVICE_ID_INTEL_BROXTON_SMBUS 0x5ad4 #define PCI_DEVICE_ID_INTEL_ALDER_LAKE_S_SMBUS 0x7aa3 #define PCI_DEVICE_ID_INTEL_LYNXPOINT_SMBUS 0x8c22 @@ -1084,6 +1086,7 @@ static const struct pci_device_id i801_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_TIGERLAKE_H_SMBUS) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_JASPER_LAKE_SMBUS) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ALDER_LAKE_S_SMBUS) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ALDER_LAKE_P_SMBUS) }, { 0, } }; @@ -1433,7 +1436,7 @@ static int i801_add_mux(struct i801_priv *priv) const struct i801_mux_config *mux_config; struct i2c_mux_gpio_platform_data gpio_data; struct gpiod_lookup_table *lookup; - int err, i; + int i; if (!priv->mux_drvdata) return 0; @@ -1473,22 +1476,17 @@ static int i801_add_mux(struct i801_priv *priv) PLATFORM_DEVID_NONE, &gpio_data, sizeof(struct i2c_mux_gpio_platform_data)); if (IS_ERR(priv->mux_pdev)) { - err = PTR_ERR(priv->mux_pdev); gpiod_remove_lookup_table(lookup); - priv->mux_pdev = NULL; dev_err(dev, "Failed to register i2c-mux-gpio device\n"); - return err; } - return 0; + return PTR_ERR_OR_ZERO(priv->mux_pdev); } static void i801_del_mux(struct i801_priv *priv) { - if (priv->mux_pdev) - platform_device_unregister(priv->mux_pdev); - if (priv->lookup) - gpiod_remove_lookup_table(priv->lookup); + platform_device_unregister(priv->mux_pdev); + gpiod_remove_lookup_table(priv->lookup); } static unsigned int i801_get_adapter_class(struct i801_priv *priv) @@ -1772,6 +1770,7 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id) case PCI_DEVICE_ID_INTEL_JASPER_LAKE_SMBUS: case PCI_DEVICE_ID_INTEL_EBG_SMBUS: case PCI_DEVICE_ID_INTEL_ALDER_LAKE_S_SMBUS: + case PCI_DEVICE_ID_INTEL_ALDER_LAKE_P_SMBUS: priv->features |= FEATURE_BLOCK_PROC; priv->features |= FEATURE_I2C_BLOCK_READ; priv->features |= FEATURE_IRQ; diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c index a8e8af57e33f..b80fdc1f0092 100644 --- a/drivers/i2c/busses/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c @@ -209,6 +209,7 @@ struct imx_i2c_struct { struct imx_i2c_dma *dma; struct i2c_client *slave; + enum i2c_slave_event last_slave_event; }; static const struct imx_i2c_hwdata imx1_i2c_hwdata = { @@ -550,7 +551,7 @@ static void i2c_imx_set_clk(struct imx_i2c_struct *i2c_imx, i2c_imx->cur_clk = i2c_clk_rate; - div = (i2c_clk_rate + i2c_imx->bitrate - 1) / i2c_imx->bitrate; + div = DIV_ROUND_UP(i2c_clk_rate, i2c_imx->bitrate); if (div < i2c_clk_div[0].div) i = 0; else if (div > i2c_clk_div[i2c_imx->hwdata->ndivs - 1].div) @@ -568,8 +569,8 @@ static void i2c_imx_set_clk(struct imx_i2c_struct *i2c_imx, * This delay is used in I2C bus disable function * to fix chip hardware bug. */ - i2c_imx->disable_delay = (500000U * i2c_clk_div[i].div - + (i2c_clk_rate / 2) - 1) / (i2c_clk_rate / 2); + i2c_imx->disable_delay = DIV_ROUND_UP(500000U * i2c_clk_div[i].div, + i2c_clk_rate / 2); #ifdef CONFIG_I2C_DEBUG_BUS dev_dbg(&i2c_imx->adapter.dev, "I2C_CLK=%d, REQ DIV=%d\n", @@ -675,6 +676,36 @@ static void i2c_imx_enable_bus_idle(struct imx_i2c_struct *i2c_imx) } } +static void i2c_imx_slave_event(struct imx_i2c_struct *i2c_imx, + enum i2c_slave_event event, u8 *val) +{ + i2c_slave_event(i2c_imx->slave, event, val); + i2c_imx->last_slave_event = event; +} + +static void i2c_imx_slave_finish_op(struct imx_i2c_struct *i2c_imx) +{ + u8 val; + + while (i2c_imx->last_slave_event != I2C_SLAVE_STOP) { + switch (i2c_imx->last_slave_event) { + case I2C_SLAVE_READ_REQUESTED: + i2c_imx_slave_event(i2c_imx, I2C_SLAVE_READ_PROCESSED, + &val); + break; + + case I2C_SLAVE_WRITE_REQUESTED: + case I2C_SLAVE_READ_PROCESSED: + case I2C_SLAVE_WRITE_RECEIVED: + i2c_imx_slave_event(i2c_imx, I2C_SLAVE_STOP, &val); + break; + + case I2C_SLAVE_STOP: + break; + } + } +} + static irqreturn_t i2c_imx_slave_isr(struct imx_i2c_struct *i2c_imx, unsigned int status, unsigned int ctl) { @@ -687,9 +718,11 @@ static irqreturn_t i2c_imx_slave_isr(struct imx_i2c_struct *i2c_imx, } if (status & I2SR_IAAS) { /* Addressed as a slave */ + i2c_imx_slave_finish_op(i2c_imx); if (status & I2SR_SRW) { /* Master wants to read from us*/ dev_dbg(&i2c_imx->adapter.dev, "read requested"); - i2c_slave_event(i2c_imx->slave, I2C_SLAVE_READ_REQUESTED, &value); + i2c_imx_slave_event(i2c_imx, + I2C_SLAVE_READ_REQUESTED, &value); /* Slave transmit */ ctl |= I2CR_MTX; @@ -699,7 +732,8 @@ static irqreturn_t i2c_imx_slave_isr(struct imx_i2c_struct *i2c_imx, imx_i2c_write_reg(value, i2c_imx, IMX_I2C_I2DR); } else { /* Master wants to write to us */ dev_dbg(&i2c_imx->adapter.dev, "write requested"); - i2c_slave_event(i2c_imx->slave, I2C_SLAVE_WRITE_REQUESTED, &value); + i2c_imx_slave_event(i2c_imx, + I2C_SLAVE_WRITE_REQUESTED, &value); /* Slave receive */ ctl &= ~I2CR_MTX; @@ -710,17 +744,20 @@ static irqreturn_t i2c_imx_slave_isr(struct imx_i2c_struct *i2c_imx, } else if (!(ctl & I2CR_MTX)) { /* Receive mode */ if (status & I2SR_IBB) { /* No STOP signal detected */ value = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR); - i2c_slave_event(i2c_imx->slave, I2C_SLAVE_WRITE_RECEIVED, &value); + i2c_imx_slave_event(i2c_imx, + I2C_SLAVE_WRITE_RECEIVED, &value); } else { /* STOP signal is detected */ dev_dbg(&i2c_imx->adapter.dev, "STOP signal detected"); - i2c_slave_event(i2c_imx->slave, I2C_SLAVE_STOP, &value); + i2c_imx_slave_event(i2c_imx, + I2C_SLAVE_STOP, &value); } } else if (!(status & I2SR_RXAK)) { /* Transmit mode received ACK */ ctl |= I2CR_MTX; imx_i2c_write_reg(ctl, i2c_imx, IMX_I2C_I2CR); - i2c_slave_event(i2c_imx->slave, I2C_SLAVE_READ_PROCESSED, &value); + i2c_imx_slave_event(i2c_imx, + I2C_SLAVE_READ_PROCESSED, &value); imx_i2c_write_reg(value, i2c_imx, IMX_I2C_I2DR); } else { /* Transmit mode received NAK */ @@ -761,6 +798,7 @@ static int i2c_imx_reg_slave(struct i2c_client *client) return -EBUSY; i2c_imx->slave = client; + i2c_imx->last_slave_event = I2C_SLAVE_STOP; /* Resume */ ret = pm_runtime_get_sync(i2c_imx->adapter.dev.parent); @@ -813,10 +851,17 @@ static irqreturn_t i2c_imx_isr(int irq, void *dev_id) status = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2SR); ctl = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR); + if (status & I2SR_IIF) { i2c_imx_clear_irq(i2c_imx, I2SR_IIF); - if (i2c_imx->slave && !(ctl & I2CR_MSTA)) - return i2c_imx_slave_isr(i2c_imx, status, ctl); + if (i2c_imx->slave) { + if (!(ctl & I2CR_MSTA)) { + return i2c_imx_slave_isr(i2c_imx, status, ctl); + } else if (i2c_imx->last_slave_event != + I2C_SLAVE_STOP) { + i2c_imx_slave_finish_op(i2c_imx); + } + } return i2c_imx_master_isr(i2c_imx, status); } diff --git a/drivers/i2c/busses/i2c-jz4780.c b/drivers/i2c/busses/i2c-jz4780.c index cb4a25ebb890..8509c5f11356 100644 --- a/drivers/i2c/busses/i2c-jz4780.c +++ b/drivers/i2c/busses/i2c-jz4780.c @@ -437,9 +437,8 @@ static irqreturn_t jz4780_i2c_irq(int irqno, void *dev_id) unsigned short intst; unsigned short intmsk; struct jz4780_i2c *i2c = dev_id; - unsigned long flags; - spin_lock_irqsave(&i2c->lock, flags); + spin_lock(&i2c->lock); intmsk = jz4780_i2c_readw(i2c, JZ4780_I2C_INTM); intst = jz4780_i2c_readw(i2c, JZ4780_I2C_INTST); @@ -551,7 +550,7 @@ static irqreturn_t jz4780_i2c_irq(int irqno, void *dev_id) } done: - spin_unlock_irqrestore(&i2c->lock, flags); + spin_unlock(&i2c->lock); return IRQ_HANDLED; } diff --git a/drivers/i2c/busses/i2c-mlxcpld.c b/drivers/i2c/busses/i2c-mlxcpld.c index 71d7bae2cbca..4e0b7c2882ce 100644 --- a/drivers/i2c/busses/i2c-mlxcpld.c +++ b/drivers/i2c/busses/i2c-mlxcpld.c @@ -1,34 +1,8 @@ +// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 /* - * Copyright (c) 2016 Mellanox Technologies. All rights reserved. - * Copyright (c) 2016 Michael Shych <michaels@mellanox.com> + * Mellanox i2c driver * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the names of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. + * Copyright (C) 2016-2020 Mellanox Technologies */ #include <linux/delay.h> @@ -37,7 +11,9 @@ #include <linux/io.h> #include <linux/kernel.h> #include <linux/module.h> +#include <linux/platform_data/mlxreg.h> #include <linux/platform_device.h> +#include <linux/regmap.h> /* General defines */ #define MLXPLAT_CPLD_LPC_I2C_BASE_ADDR 0x2000 @@ -51,7 +27,7 @@ #define MLXCPLD_I2C_MAX_ADDR_LEN 4 #define MLXCPLD_I2C_RETR_NUM 2 #define MLXCPLD_I2C_XFER_TO 500000 /* usec */ -#define MLXCPLD_I2C_POLL_TIME 2000 /* usec */ +#define MLXCPLD_I2C_POLL_TIME 400 /* usec */ /* LPC I2C registers */ #define MLXCPLD_LPCI2C_CPBLTY_REG 0x0 @@ -72,6 +48,16 @@ #define MLXCPLD_LPCI2C_ACK_IND 1 #define MLXCPLD_LPCI2C_NACK_IND 2 +#define MLXCPLD_I2C_FREQ_1000KHZ_SET 0x04 +#define MLXCPLD_I2C_FREQ_400KHZ_SET 0x0f +#define MLXCPLD_I2C_FREQ_100KHZ_SET 0x42 + +enum mlxcpld_i2c_frequency { + MLXCPLD_I2C_FREQ_1000KHZ = 1, + MLXCPLD_I2C_FREQ_400KHZ = 2, + MLXCPLD_I2C_FREQ_100KHZ = 3, +}; + struct mlxcpld_i2c_curr_xfer { u8 cmd; u8 addr_width; @@ -489,8 +475,45 @@ static struct i2c_adapter mlxcpld_i2c_adapter = { .nr = MLXCPLD_I2C_BUS_NUM, }; +static int +mlxcpld_i2c_set_frequency(struct mlxcpld_i2c_priv *priv, + struct mlxreg_core_hotplug_platform_data *pdata) +{ + struct mlxreg_core_item *item = pdata->items; + struct mlxreg_core_data *data; + u32 regval; + u8 freq; + int err; + + if (!item) + return 0; + + /* Read frequency setting. */ + data = item->data; + err = regmap_read(pdata->regmap, data->reg, ®val); + if (err) + return err; + + /* Set frequency only if it is not 100KHz, which is default. */ + switch ((data->reg & data->mask) >> data->bit) { + case MLXCPLD_I2C_FREQ_1000KHZ: + freq = MLXCPLD_I2C_FREQ_1000KHZ_SET; + break; + case MLXCPLD_I2C_FREQ_400KHZ: + freq = MLXCPLD_I2C_FREQ_400KHZ_SET; + break; + default: + return 0; + } + + mlxcpld_i2c_write_comm(priv, MLXCPLD_LPCI2C_HALF_CYC_REG, &freq, 1); + + return 0; +} + static int mlxcpld_i2c_probe(struct platform_device *pdev) { + struct mlxreg_core_hotplug_platform_data *pdata; struct mlxcpld_i2c_priv *priv; int err; u8 val; @@ -505,6 +528,14 @@ static int mlxcpld_i2c_probe(struct platform_device *pdev) priv->dev = &pdev->dev; priv->base_addr = MLXPLAT_CPLD_LPC_I2C_BASE_ADDR; + /* Set I2C bus frequency if platform data provides this info. */ + pdata = dev_get_platdata(&pdev->dev); + if (pdata) { + err = mlxcpld_i2c_set_frequency(priv, pdata); + if (err) + goto mlxcpld_i2_probe_failed; + } + /* Register with i2c layer */ mlxcpld_i2c_adapter.timeout = usecs_to_jiffies(MLXCPLD_I2C_XFER_TO); /* Read capability register */ @@ -523,8 +554,12 @@ static int mlxcpld_i2c_probe(struct platform_device *pdev) err = i2c_add_numbered_adapter(&priv->adap); if (err) - mutex_destroy(&priv->lock); + goto mlxcpld_i2_probe_failed; + return 0; + +mlxcpld_i2_probe_failed: + mutex_destroy(&priv->lock); return err; } diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c index 5cfe70aedced..c590d36b5fd1 100644 --- a/drivers/i2c/busses/i2c-mv64xxx.c +++ b/drivers/i2c/busses/i2c-mv64xxx.c @@ -18,6 +18,7 @@ #include <linux/mv643xx_i2c.h> #include <linux/platform_device.h> #include <linux/pinctrl/consumer.h> +#include <linux/pm_runtime.h> #include <linux/reset.h> #include <linux/io.h> #include <linux/of.h> @@ -717,6 +718,10 @@ mv64xxx_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) struct mv64xxx_i2c_data *drv_data = i2c_get_adapdata(adap); int rc, ret = num; + rc = pm_runtime_resume_and_get(&adap->dev); + if (rc) + return rc; + BUG_ON(drv_data->msgs != NULL); drv_data->msgs = msgs; drv_data->num_msgs = num; @@ -732,6 +737,9 @@ mv64xxx_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) drv_data->num_msgs = 0; drv_data->msgs = NULL; + pm_runtime_mark_last_busy(&adap->dev); + pm_runtime_put_autosuspend(&adap->dev); + return ret; } @@ -805,7 +813,7 @@ mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data, * need to know tclk in order to calculate bus clock * factors. */ - if (IS_ERR(drv_data->clk)) { + if (!drv_data->clk) { rc = -ENODEV; goto out; } @@ -828,7 +836,6 @@ mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data, rc = PTR_ERR(drv_data->rstc); goto out; } - reset_control_deassert(drv_data->rstc); /* Its not yet defined how timeouts will be specified in device tree. * So hard code the value to 1 second. @@ -894,6 +901,32 @@ static int mv64xxx_i2c_init_recovery_info(struct mv64xxx_i2c_data *drv_data, } static int +mv64xxx_i2c_runtime_suspend(struct device *dev) +{ + struct mv64xxx_i2c_data *drv_data = dev_get_drvdata(dev); + + reset_control_assert(drv_data->rstc); + clk_disable_unprepare(drv_data->reg_clk); + clk_disable_unprepare(drv_data->clk); + + return 0; +} + +static int +mv64xxx_i2c_runtime_resume(struct device *dev) +{ + struct mv64xxx_i2c_data *drv_data = dev_get_drvdata(dev); + + clk_prepare_enable(drv_data->clk); + clk_prepare_enable(drv_data->reg_clk); + reset_control_reset(drv_data->rstc); + + mv64xxx_i2c_hw_init(drv_data); + + return 0; +} + +static int mv64xxx_i2c_probe(struct platform_device *pd) { struct mv64xxx_i2c_data *drv_data; @@ -920,18 +953,22 @@ mv64xxx_i2c_probe(struct platform_device *pd) /* Not all platforms have clocks */ drv_data->clk = devm_clk_get(&pd->dev, NULL); - if (PTR_ERR(drv_data->clk) == -EPROBE_DEFER) - return -EPROBE_DEFER; - if (!IS_ERR(drv_data->clk)) - clk_prepare_enable(drv_data->clk); + if (IS_ERR(drv_data->clk)) { + if (PTR_ERR(drv_data->clk) == -EPROBE_DEFER) + return -EPROBE_DEFER; + drv_data->clk = NULL; + } drv_data->reg_clk = devm_clk_get(&pd->dev, "reg"); - if (PTR_ERR(drv_data->reg_clk) == -EPROBE_DEFER) - return -EPROBE_DEFER; - if (!IS_ERR(drv_data->reg_clk)) - clk_prepare_enable(drv_data->reg_clk); + if (IS_ERR(drv_data->reg_clk)) { + if (PTR_ERR(drv_data->reg_clk) == -EPROBE_DEFER) + return -EPROBE_DEFER; + drv_data->reg_clk = NULL; + } drv_data->irq = platform_get_irq(pd, 0); + if (drv_data->irq < 0) + return drv_data->irq; if (pdata) { drv_data->freq_m = pdata->freq_m; @@ -942,16 +979,12 @@ mv64xxx_i2c_probe(struct platform_device *pd) } else if (pd->dev.of_node) { rc = mv64xxx_of_config(drv_data, &pd->dev); if (rc) - goto exit_clk; - } - if (drv_data->irq < 0) { - rc = drv_data->irq; - goto exit_reset; + return rc; } rc = mv64xxx_i2c_init_recovery_info(drv_data, &pd->dev); if (rc == -EPROBE_DEFER) - goto exit_reset; + return rc; drv_data->adapter.dev.parent = &pd->dev; drv_data->adapter.algo = &mv64xxx_i2c_algo; @@ -962,7 +995,14 @@ mv64xxx_i2c_probe(struct platform_device *pd) platform_set_drvdata(pd, drv_data); i2c_set_adapdata(&drv_data->adapter, drv_data); - mv64xxx_i2c_hw_init(drv_data); + pm_runtime_set_autosuspend_delay(&pd->dev, MSEC_PER_SEC); + pm_runtime_use_autosuspend(&pd->dev); + pm_runtime_enable(&pd->dev); + if (!pm_runtime_enabled(&pd->dev)) { + rc = mv64xxx_i2c_runtime_resume(&pd->dev); + if (rc) + goto exit_disable_pm; + } rc = request_irq(drv_data->irq, mv64xxx_i2c_intr, 0, MV64XXX_I2C_CTLR_NAME, drv_data); @@ -970,7 +1010,7 @@ mv64xxx_i2c_probe(struct platform_device *pd) dev_err(&drv_data->adapter.dev, "mv64xxx: Can't register intr handler irq%d: %d\n", drv_data->irq, rc); - goto exit_reset; + goto exit_disable_pm; } else if ((rc = i2c_add_numbered_adapter(&drv_data->adapter)) != 0) { dev_err(&drv_data->adapter.dev, "mv64xxx: Can't add i2c adapter, rc: %d\n", -rc); @@ -981,54 +1021,50 @@ mv64xxx_i2c_probe(struct platform_device *pd) exit_free_irq: free_irq(drv_data->irq, drv_data); -exit_reset: - reset_control_assert(drv_data->rstc); -exit_clk: - clk_disable_unprepare(drv_data->reg_clk); - clk_disable_unprepare(drv_data->clk); +exit_disable_pm: + pm_runtime_disable(&pd->dev); + if (!pm_runtime_status_suspended(&pd->dev)) + mv64xxx_i2c_runtime_suspend(&pd->dev); return rc; } static int -mv64xxx_i2c_remove(struct platform_device *dev) +mv64xxx_i2c_remove(struct platform_device *pd) { - struct mv64xxx_i2c_data *drv_data = platform_get_drvdata(dev); + struct mv64xxx_i2c_data *drv_data = platform_get_drvdata(pd); i2c_del_adapter(&drv_data->adapter); free_irq(drv_data->irq, drv_data); - reset_control_assert(drv_data->rstc); - clk_disable_unprepare(drv_data->reg_clk); - clk_disable_unprepare(drv_data->clk); + pm_runtime_disable(&pd->dev); + if (!pm_runtime_status_suspended(&pd->dev)) + mv64xxx_i2c_runtime_suspend(&pd->dev); return 0; } -#ifdef CONFIG_PM -static int mv64xxx_i2c_resume(struct device *dev) +static void +mv64xxx_i2c_shutdown(struct platform_device *pd) { - struct mv64xxx_i2c_data *drv_data = dev_get_drvdata(dev); - - mv64xxx_i2c_hw_init(drv_data); - - return 0; + pm_runtime_disable(&pd->dev); + if (!pm_runtime_status_suspended(&pd->dev)) + mv64xxx_i2c_runtime_suspend(&pd->dev); } -static const struct dev_pm_ops mv64xxx_i2c_pm = { - .resume = mv64xxx_i2c_resume, +static const struct dev_pm_ops mv64xxx_i2c_pm_ops = { + SET_RUNTIME_PM_OPS(mv64xxx_i2c_runtime_suspend, + mv64xxx_i2c_runtime_resume, NULL) + SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, + pm_runtime_force_resume) }; -#define mv64xxx_i2c_pm_ops (&mv64xxx_i2c_pm) -#else -#define mv64xxx_i2c_pm_ops NULL -#endif - static struct platform_driver mv64xxx_i2c_driver = { .probe = mv64xxx_i2c_probe, .remove = mv64xxx_i2c_remove, + .shutdown = mv64xxx_i2c_shutdown, .driver = { .name = MV64XXX_I2C_CTLR_NAME, - .pm = mv64xxx_i2c_pm_ops, + .pm = &mv64xxx_i2c_pm_ops, .of_match_table = mv64xxx_i2c_of_match_table, }, }; diff --git a/drivers/i2c/busses/i2c-qcom-geni.c b/drivers/i2c/busses/i2c-qcom-geni.c index 046d241183c5..c3f584795911 100644 --- a/drivers/i2c/busses/i2c-qcom-geni.c +++ b/drivers/i2c/busses/i2c-qcom-geni.c @@ -86,6 +86,9 @@ struct geni_i2c_dev { u32 clk_freq_out; const struct geni_i2c_clk_fld *clk_fld; int suspended; + void *dma_buf; + size_t xfer_len; + dma_addr_t dma_addr; }; struct geni_i2c_err_log { @@ -348,14 +351,65 @@ static void geni_i2c_tx_fsm_rst(struct geni_i2c_dev *gi2c) dev_err(gi2c->se.dev, "Timeout resetting TX_FSM\n"); } +static void geni_i2c_rx_msg_cleanup(struct geni_i2c_dev *gi2c, + struct i2c_msg *cur) +{ + gi2c->cur_rd = 0; + if (gi2c->dma_buf) { + if (gi2c->err) + geni_i2c_rx_fsm_rst(gi2c); + geni_se_rx_dma_unprep(&gi2c->se, gi2c->dma_addr, gi2c->xfer_len); + i2c_put_dma_safe_msg_buf(gi2c->dma_buf, cur, !gi2c->err); + } +} + +static void geni_i2c_tx_msg_cleanup(struct geni_i2c_dev *gi2c, + struct i2c_msg *cur) +{ + gi2c->cur_wr = 0; + if (gi2c->dma_buf) { + if (gi2c->err) + geni_i2c_tx_fsm_rst(gi2c); + geni_se_tx_dma_unprep(&gi2c->se, gi2c->dma_addr, gi2c->xfer_len); + i2c_put_dma_safe_msg_buf(gi2c->dma_buf, cur, !gi2c->err); + } +} + +static void geni_i2c_stop_xfer(struct geni_i2c_dev *gi2c) +{ + int ret; + u32 geni_status; + struct i2c_msg *cur; + + /* Resume device, as runtime suspend can happen anytime during transfer */ + ret = pm_runtime_get_sync(gi2c->se.dev); + if (ret < 0) { + dev_err(gi2c->se.dev, "Failed to resume device: %d\n", ret); + return; + } + + geni_status = readl_relaxed(gi2c->se.base + SE_GENI_STATUS); + if (geni_status & M_GENI_CMD_ACTIVE) { + cur = gi2c->cur; + geni_i2c_abort_xfer(gi2c); + if (cur->flags & I2C_M_RD) + geni_i2c_rx_msg_cleanup(gi2c, cur); + else + geni_i2c_tx_msg_cleanup(gi2c, cur); + } + + pm_runtime_put_sync_suspend(gi2c->se.dev); +} + static int geni_i2c_rx_one_msg(struct geni_i2c_dev *gi2c, struct i2c_msg *msg, u32 m_param) { - dma_addr_t rx_dma; + dma_addr_t rx_dma = 0; unsigned long time_left; void *dma_buf; struct geni_se *se = &gi2c->se; size_t len = msg->len; + struct i2c_msg *cur; dma_buf = i2c_get_dma_safe_msg_buf(msg, 32); if (dma_buf) @@ -370,19 +424,18 @@ static int geni_i2c_rx_one_msg(struct geni_i2c_dev *gi2c, struct i2c_msg *msg, geni_se_select_mode(se, GENI_SE_FIFO); i2c_put_dma_safe_msg_buf(dma_buf, msg, false); dma_buf = NULL; + } else { + gi2c->xfer_len = len; + gi2c->dma_addr = rx_dma; + gi2c->dma_buf = dma_buf; } + cur = gi2c->cur; time_left = wait_for_completion_timeout(&gi2c->done, XFER_TIMEOUT); if (!time_left) geni_i2c_abort_xfer(gi2c); - gi2c->cur_rd = 0; - if (dma_buf) { - if (gi2c->err) - geni_i2c_rx_fsm_rst(gi2c); - geni_se_rx_dma_unprep(se, rx_dma, len); - i2c_put_dma_safe_msg_buf(dma_buf, msg, !gi2c->err); - } + geni_i2c_rx_msg_cleanup(gi2c, cur); return gi2c->err; } @@ -390,11 +443,12 @@ static int geni_i2c_rx_one_msg(struct geni_i2c_dev *gi2c, struct i2c_msg *msg, static int geni_i2c_tx_one_msg(struct geni_i2c_dev *gi2c, struct i2c_msg *msg, u32 m_param) { - dma_addr_t tx_dma; + dma_addr_t tx_dma = 0; unsigned long time_left; void *dma_buf; struct geni_se *se = &gi2c->se; size_t len = msg->len; + struct i2c_msg *cur; dma_buf = i2c_get_dma_safe_msg_buf(msg, 32); if (dma_buf) @@ -409,22 +463,21 @@ static int geni_i2c_tx_one_msg(struct geni_i2c_dev *gi2c, struct i2c_msg *msg, geni_se_select_mode(se, GENI_SE_FIFO); i2c_put_dma_safe_msg_buf(dma_buf, msg, false); dma_buf = NULL; + } else { + gi2c->xfer_len = len; + gi2c->dma_addr = tx_dma; + gi2c->dma_buf = dma_buf; } if (!dma_buf) /* Get FIFO IRQ */ writel_relaxed(1, se->base + SE_GENI_TX_WATERMARK_REG); + cur = gi2c->cur; time_left = wait_for_completion_timeout(&gi2c->done, XFER_TIMEOUT); if (!time_left) geni_i2c_abort_xfer(gi2c); - gi2c->cur_wr = 0; - if (dma_buf) { - if (gi2c->err) - geni_i2c_tx_fsm_rst(gi2c); - geni_se_tx_dma_unprep(se, tx_dma, len); - i2c_put_dma_safe_msg_buf(dma_buf, msg, !gi2c->err); - } + geni_i2c_tx_msg_cleanup(gi2c, cur); return gi2c->err; } @@ -623,6 +676,13 @@ static int geni_i2c_remove(struct platform_device *pdev) return 0; } +static void geni_i2c_shutdown(struct platform_device *pdev) +{ + struct geni_i2c_dev *gi2c = platform_get_drvdata(pdev); + + geni_i2c_stop_xfer(gi2c); +} + static int __maybe_unused geni_i2c_runtime_suspend(struct device *dev) { int ret; @@ -687,6 +747,7 @@ MODULE_DEVICE_TABLE(of, geni_i2c_dt_match); static struct platform_driver geni_i2c_driver = { .probe = geni_i2c_probe, .remove = geni_i2c_remove, + .shutdown = geni_i2c_shutdown, .driver = { .name = "geni_i2c", .pm = &geni_i2c_pm_ops, diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c index 5a47915869ae..61dc20fd1191 100644 --- a/drivers/i2c/busses/i2c-qup.c +++ b/drivers/i2c/busses/i2c-qup.c @@ -1603,7 +1603,7 @@ out: static u32 qup_i2c_func(struct i2c_adapter *adap) { - return I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK); + return I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL_ALL & ~I2C_FUNC_SMBUS_QUICK); } static const struct i2c_algorithm qup_i2c_algo = { diff --git a/drivers/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c index 217def2d7cb4..12f6d452c0f7 100644 --- a/drivers/i2c/busses/i2c-rcar.c +++ b/drivers/i2c/busses/i2c-rcar.c @@ -91,7 +91,6 @@ #define RCAR_BUS_PHASE_START (MDBS | MIE | ESG) #define RCAR_BUS_PHASE_DATA (MDBS | MIE) -#define RCAR_BUS_MASK_DATA (~(ESG | FSB) & 0xFF) #define RCAR_BUS_PHASE_STOP (MDBS | MIE | FSB) #define RCAR_IRQ_SEND (MNR | MAL | MST | MAT | MDE) @@ -120,6 +119,7 @@ enum rcar_i2c_type { }; struct rcar_i2c_priv { + u32 flags; void __iomem *io; struct i2c_adapter adap; struct i2c_msg *msg; @@ -130,7 +130,6 @@ struct rcar_i2c_priv { int pos; u32 icccr; - u32 flags; u8 recovery_icmcr; /* protected by adapter lock */ enum rcar_i2c_type devtype; struct i2c_client *slave; @@ -621,27 +620,16 @@ static bool rcar_i2c_slave_irq(struct rcar_i2c_priv *priv) /* * This driver has a lock-free design because there are IP cores (at least * R-Car Gen2) which have an inherent race condition in their hardware design. - * There, we need to clear RCAR_BUS_MASK_DATA bits as soon as possible after + * There, we need to switch to RCAR_BUS_PHASE_DATA as soon as possible after * the interrupt was generated, otherwise an unwanted repeated message gets * generated. It turned out that taking a spinlock at the beginning of the ISR * was already causing repeated messages. Thus, this driver was converted to * the now lockless behaviour. Please keep this in mind when hacking the driver. + * R-Car Gen3 seems to have this fixed but earlier versions than R-Car Gen2 are + * likely affected. Therefore, we have different interrupt handler entries. */ -static irqreturn_t rcar_i2c_irq(int irq, void *ptr) +static irqreturn_t rcar_i2c_irq(int irq, struct rcar_i2c_priv *priv, u32 msr) { - struct rcar_i2c_priv *priv = ptr; - u32 msr, val; - - /* Clear START or STOP immediately, except for REPSTART after read */ - if (likely(!(priv->flags & ID_P_REP_AFTER_RD))) { - val = rcar_i2c_read(priv, ICMCR); - rcar_i2c_write(priv, ICMCR, val & RCAR_BUS_MASK_DATA); - } - - msr = rcar_i2c_read(priv, ICMSR); - - /* Only handle interrupts that are currently enabled */ - msr &= rcar_i2c_read(priv, ICMIER); if (!msr) { if (rcar_i2c_slave_irq(priv)) return IRQ_HANDLED; @@ -685,6 +673,41 @@ out: return IRQ_HANDLED; } +static irqreturn_t rcar_i2c_gen2_irq(int irq, void *ptr) +{ + struct rcar_i2c_priv *priv = ptr; + u32 msr; + + /* Clear START or STOP immediately, except for REPSTART after read */ + if (likely(!(priv->flags & ID_P_REP_AFTER_RD))) + rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_DATA); + + /* Only handle interrupts that are currently enabled */ + msr = rcar_i2c_read(priv, ICMSR); + msr &= rcar_i2c_read(priv, ICMIER); + + return rcar_i2c_irq(irq, priv, msr); +} + +static irqreturn_t rcar_i2c_gen3_irq(int irq, void *ptr) +{ + struct rcar_i2c_priv *priv = ptr; + u32 msr; + + /* Only handle interrupts that are currently enabled */ + msr = rcar_i2c_read(priv, ICMSR); + msr &= rcar_i2c_read(priv, ICMIER); + + /* + * Clear START or STOP immediately, except for REPSTART after read or + * if a spurious interrupt was detected. + */ + if (likely(!(priv->flags & ID_P_REP_AFTER_RD) && msr)) + rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_DATA); + + return rcar_i2c_irq(irq, priv, msr); +} + static struct dma_chan *rcar_i2c_request_dma_chan(struct device *dev, enum dma_transfer_direction dir, dma_addr_t port_addr) @@ -931,6 +954,8 @@ static int rcar_i2c_probe(struct platform_device *pdev) struct rcar_i2c_priv *priv; struct i2c_adapter *adap; struct device *dev = &pdev->dev; + unsigned long irqflags = 0; + irqreturn_t (*irqhandler)(int irq, void *ptr) = rcar_i2c_gen3_irq; int ret; /* Otherwise logic will break because some bytes must always use PIO */ @@ -979,6 +1004,11 @@ static int rcar_i2c_probe(struct platform_device *pdev) rcar_i2c_write(priv, ICSAR, 0); /* Gen2: must be 0 if not using slave */ + if (priv->devtype < I2C_RCAR_GEN3) { + irqflags |= IRQF_NO_THREAD; + irqhandler = rcar_i2c_gen2_irq; + } + if (priv->devtype == I2C_RCAR_GEN3) { priv->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL); if (!IS_ERR(priv->rstc)) { @@ -998,7 +1028,7 @@ static int rcar_i2c_probe(struct platform_device *pdev) priv->flags |= ID_P_HOST_NOTIFY; priv->irq = platform_get_irq(pdev, 0); - ret = devm_request_irq(dev, priv->irq, rcar_i2c_irq, 0, dev_name(dev), priv); + ret = devm_request_irq(dev, priv->irq, irqhandler, irqflags, dev_name(dev), priv); if (ret < 0) { dev_err(dev, "cannot get irq %d\n", priv->irq); goto out_pm_disable; diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c index 3eafe0eb3e4c..62a903fbe912 100644 --- a/drivers/i2c/busses/i2c-s3c2410.c +++ b/drivers/i2c/busses/i2c-s3c2410.c @@ -781,7 +781,7 @@ static int s3c24xx_i2c_xfer(struct i2c_adapter *adap, /* declare our i2c functionality */ static u32 s3c24xx_i2c_func(struct i2c_adapter *adap) { - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_NOSTART | + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL_ALL | I2C_FUNC_NOSTART | I2C_FUNC_PROTOCOL_MANGLING; } diff --git a/drivers/i2c/busses/i2c-sirf.c b/drivers/i2c/busses/i2c-sirf.c deleted file mode 100644 index 30db8fafe078..000000000000 --- a/drivers/i2c/busses/i2c-sirf.c +++ /dev/null @@ -1,475 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * I2C bus driver for CSR SiRFprimaII - * - * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company. - */ - -#include <linux/interrupt.h> -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/platform_device.h> -#include <linux/i2c.h> -#include <linux/clk.h> -#include <linux/err.h> -#include <linux/io.h> - -#define SIRFSOC_I2C_CLK_CTRL 0x00 -#define SIRFSOC_I2C_STATUS 0x0C -#define SIRFSOC_I2C_CTRL 0x10 -#define SIRFSOC_I2C_IO_CTRL 0x14 -#define SIRFSOC_I2C_SDA_DELAY 0x18 -#define SIRFSOC_I2C_CMD_START 0x1C -#define SIRFSOC_I2C_CMD_BUF 0x30 -#define SIRFSOC_I2C_DATA_BUF 0x80 - -#define SIRFSOC_I2C_CMD_BUF_MAX 16 -#define SIRFSOC_I2C_DATA_BUF_MAX 16 - -#define SIRFSOC_I2C_CMD(x) (SIRFSOC_I2C_CMD_BUF + (x)*0x04) -#define SIRFSOC_I2C_DATA_MASK(x) (0xFF<<(((x)&3)*8)) -#define SIRFSOC_I2C_DATA_SHIFT(x) (((x)&3)*8) - -#define SIRFSOC_I2C_DIV_MASK (0xFFFF) - -/* I2C status flags */ -#define SIRFSOC_I2C_STAT_BUSY BIT(0) -#define SIRFSOC_I2C_STAT_TIP BIT(1) -#define SIRFSOC_I2C_STAT_NACK BIT(2) -#define SIRFSOC_I2C_STAT_TR_INT BIT(4) -#define SIRFSOC_I2C_STAT_STOP BIT(6) -#define SIRFSOC_I2C_STAT_CMD_DONE BIT(8) -#define SIRFSOC_I2C_STAT_ERR BIT(9) -#define SIRFSOC_I2C_CMD_INDEX (0x1F<<16) - -/* I2C control flags */ -#define SIRFSOC_I2C_RESET BIT(0) -#define SIRFSOC_I2C_CORE_EN BIT(1) -#define SIRFSOC_I2C_MASTER_MODE BIT(2) -#define SIRFSOC_I2C_CMD_DONE_EN BIT(11) -#define SIRFSOC_I2C_ERR_INT_EN BIT(12) - -#define SIRFSOC_I2C_SDA_DELAY_MASK (0xFF) -#define SIRFSOC_I2C_SCLF_FILTER (3<<8) - -#define SIRFSOC_I2C_START_CMD BIT(0) - -#define SIRFSOC_I2C_CMD_RP(x) ((x)&0x7) -#define SIRFSOC_I2C_NACK BIT(3) -#define SIRFSOC_I2C_WRITE BIT(4) -#define SIRFSOC_I2C_READ BIT(5) -#define SIRFSOC_I2C_STOP BIT(6) -#define SIRFSOC_I2C_START BIT(7) - -#define SIRFSOC_I2C_ERR_NOACK 1 -#define SIRFSOC_I2C_ERR_TIMEOUT 2 - -struct sirfsoc_i2c { - void __iomem *base; - struct clk *clk; - u32 cmd_ptr; /* Current position in CMD buffer */ - u8 *buf; /* Buffer passed by user */ - u32 msg_len; /* Message length */ - u32 finished_len; /* number of bytes read/written */ - u32 read_cmd_len; /* number of read cmd sent */ - int msg_read; /* 1 indicates a read message */ - int err_status; /* 1 indicates an error on bus */ - - u32 sda_delay; /* For suspend/resume */ - u32 clk_div; - int last; /* Last message in transfer, STOP cmd can be sent */ - - struct completion done; /* indicates completion of message transfer */ - struct i2c_adapter adapter; -}; - -static void i2c_sirfsoc_read_data(struct sirfsoc_i2c *siic) -{ - u32 data = 0; - int i; - - for (i = 0; i < siic->read_cmd_len; i++) { - if (!(i & 0x3)) - data = readl(siic->base + SIRFSOC_I2C_DATA_BUF + i); - siic->buf[siic->finished_len++] = - (u8)((data & SIRFSOC_I2C_DATA_MASK(i)) >> - SIRFSOC_I2C_DATA_SHIFT(i)); - } -} - -static void i2c_sirfsoc_queue_cmd(struct sirfsoc_i2c *siic) -{ - u32 regval; - int i = 0; - - if (siic->msg_read) { - while (((siic->finished_len + i) < siic->msg_len) - && (siic->cmd_ptr < SIRFSOC_I2C_CMD_BUF_MAX)) { - regval = SIRFSOC_I2C_READ | SIRFSOC_I2C_CMD_RP(0); - if (((siic->finished_len + i) == - (siic->msg_len - 1)) && siic->last) - regval |= SIRFSOC_I2C_STOP | SIRFSOC_I2C_NACK; - writel(regval, - siic->base + SIRFSOC_I2C_CMD(siic->cmd_ptr++)); - i++; - } - - siic->read_cmd_len = i; - } else { - while ((siic->cmd_ptr < SIRFSOC_I2C_CMD_BUF_MAX - 1) - && (siic->finished_len < siic->msg_len)) { - regval = SIRFSOC_I2C_WRITE | SIRFSOC_I2C_CMD_RP(0); - if ((siic->finished_len == (siic->msg_len - 1)) - && siic->last) - regval |= SIRFSOC_I2C_STOP; - writel(regval, - siic->base + SIRFSOC_I2C_CMD(siic->cmd_ptr++)); - writel(siic->buf[siic->finished_len++], - siic->base + SIRFSOC_I2C_CMD(siic->cmd_ptr++)); - } - } - siic->cmd_ptr = 0; - - /* Trigger the transfer */ - writel(SIRFSOC_I2C_START_CMD, siic->base + SIRFSOC_I2C_CMD_START); -} - -static irqreturn_t i2c_sirfsoc_irq(int irq, void *dev_id) -{ - struct sirfsoc_i2c *siic = (struct sirfsoc_i2c *)dev_id; - u32 i2c_stat = readl(siic->base + SIRFSOC_I2C_STATUS); - - if (i2c_stat & SIRFSOC_I2C_STAT_ERR) { - /* Error conditions */ - siic->err_status = SIRFSOC_I2C_ERR_NOACK; - writel(SIRFSOC_I2C_STAT_ERR, siic->base + SIRFSOC_I2C_STATUS); - - if (i2c_stat & SIRFSOC_I2C_STAT_NACK) - dev_dbg(&siic->adapter.dev, "ACK not received\n"); - else - dev_err(&siic->adapter.dev, "I2C error\n"); - - /* - * Due to hardware ANOMALY, we need to reset I2C earlier after - * we get NOACK while accessing non-existing clients, otherwise - * we will get errors even we access existing clients later - */ - writel(readl(siic->base + SIRFSOC_I2C_CTRL) | SIRFSOC_I2C_RESET, - siic->base + SIRFSOC_I2C_CTRL); - while (readl(siic->base + SIRFSOC_I2C_CTRL) & SIRFSOC_I2C_RESET) - cpu_relax(); - - complete(&siic->done); - } else if (i2c_stat & SIRFSOC_I2C_STAT_CMD_DONE) { - /* CMD buffer execution complete */ - if (siic->msg_read) - i2c_sirfsoc_read_data(siic); - if (siic->finished_len == siic->msg_len) - complete(&siic->done); - else /* Fill a new CMD buffer for left data */ - i2c_sirfsoc_queue_cmd(siic); - - writel(SIRFSOC_I2C_STAT_CMD_DONE, siic->base + SIRFSOC_I2C_STATUS); - } - - return IRQ_HANDLED; -} - -static void i2c_sirfsoc_set_address(struct sirfsoc_i2c *siic, - struct i2c_msg *msg) -{ - unsigned char addr; - u32 regval = SIRFSOC_I2C_START | SIRFSOC_I2C_CMD_RP(0) | SIRFSOC_I2C_WRITE; - - /* no data and last message -> add STOP */ - if (siic->last && (msg->len == 0)) - regval |= SIRFSOC_I2C_STOP; - - writel(regval, siic->base + SIRFSOC_I2C_CMD(siic->cmd_ptr++)); - - addr = i2c_8bit_addr_from_msg(msg); - - /* Reverse direction bit */ - if (msg->flags & I2C_M_REV_DIR_ADDR) - addr ^= 1; - - writel(addr, siic->base + SIRFSOC_I2C_CMD(siic->cmd_ptr++)); -} - -static int i2c_sirfsoc_xfer_msg(struct sirfsoc_i2c *siic, struct i2c_msg *msg) -{ - u32 regval = readl(siic->base + SIRFSOC_I2C_CTRL); - /* timeout waiting for the xfer to finish or fail */ - int timeout = msecs_to_jiffies((msg->len + 1) * 50); - - i2c_sirfsoc_set_address(siic, msg); - - writel(regval | SIRFSOC_I2C_CMD_DONE_EN | SIRFSOC_I2C_ERR_INT_EN, - siic->base + SIRFSOC_I2C_CTRL); - i2c_sirfsoc_queue_cmd(siic); - - if (wait_for_completion_timeout(&siic->done, timeout) == 0) { - siic->err_status = SIRFSOC_I2C_ERR_TIMEOUT; - dev_err(&siic->adapter.dev, "Transfer timeout\n"); - } - - writel(regval & ~(SIRFSOC_I2C_CMD_DONE_EN | SIRFSOC_I2C_ERR_INT_EN), - siic->base + SIRFSOC_I2C_CTRL); - writel(0, siic->base + SIRFSOC_I2C_CMD_START); - - /* i2c control doesn't response, reset it */ - if (siic->err_status == SIRFSOC_I2C_ERR_TIMEOUT) { - writel(readl(siic->base + SIRFSOC_I2C_CTRL) | SIRFSOC_I2C_RESET, - siic->base + SIRFSOC_I2C_CTRL); - while (readl(siic->base + SIRFSOC_I2C_CTRL) & SIRFSOC_I2C_RESET) - cpu_relax(); - } - return siic->err_status ? -EAGAIN : 0; -} - -static u32 i2c_sirfsoc_func(struct i2c_adapter *adap) -{ - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; -} - -static int i2c_sirfsoc_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, - int num) -{ - struct sirfsoc_i2c *siic = adap->algo_data; - int i, ret; - - clk_enable(siic->clk); - - for (i = 0; i < num; i++) { - siic->buf = msgs[i].buf; - siic->msg_len = msgs[i].len; - siic->msg_read = !!(msgs[i].flags & I2C_M_RD); - siic->err_status = 0; - siic->cmd_ptr = 0; - siic->finished_len = 0; - siic->last = (i == (num - 1)); - - ret = i2c_sirfsoc_xfer_msg(siic, &msgs[i]); - if (ret) { - clk_disable(siic->clk); - return ret; - } - } - - clk_disable(siic->clk); - return num; -} - -/* I2C algorithms associated with this master controller driver */ -static const struct i2c_algorithm i2c_sirfsoc_algo = { - .master_xfer = i2c_sirfsoc_xfer, - .functionality = i2c_sirfsoc_func, -}; - -static int i2c_sirfsoc_probe(struct platform_device *pdev) -{ - struct sirfsoc_i2c *siic; - struct i2c_adapter *adap; - struct clk *clk; - int bitrate; - int ctrl_speed; - int irq; - - int err; - u32 regval; - - clk = clk_get(&pdev->dev, NULL); - if (IS_ERR(clk)) { - err = PTR_ERR(clk); - dev_err(&pdev->dev, "Clock get failed\n"); - goto err_get_clk; - } - - err = clk_prepare(clk); - if (err) { - dev_err(&pdev->dev, "Clock prepare failed\n"); - goto err_clk_prep; - } - - err = clk_enable(clk); - if (err) { - dev_err(&pdev->dev, "Clock enable failed\n"); - goto err_clk_en; - } - - ctrl_speed = clk_get_rate(clk); - - siic = devm_kzalloc(&pdev->dev, sizeof(*siic), GFP_KERNEL); - if (!siic) { - err = -ENOMEM; - goto out; - } - adap = &siic->adapter; - adap->class = I2C_CLASS_DEPRECATED; - - siic->base = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(siic->base)) { - err = PTR_ERR(siic->base); - goto out; - } - - irq = platform_get_irq(pdev, 0); - if (irq < 0) { - err = irq; - goto out; - } - err = devm_request_irq(&pdev->dev, irq, i2c_sirfsoc_irq, 0, - dev_name(&pdev->dev), siic); - if (err) - goto out; - - adap->algo = &i2c_sirfsoc_algo; - adap->algo_data = siic; - adap->retries = 3; - - adap->dev.of_node = pdev->dev.of_node; - adap->dev.parent = &pdev->dev; - adap->nr = pdev->id; - - strlcpy(adap->name, "sirfsoc-i2c", sizeof(adap->name)); - - platform_set_drvdata(pdev, adap); - init_completion(&siic->done); - - /* Controller initialisation */ - - writel(SIRFSOC_I2C_RESET, siic->base + SIRFSOC_I2C_CTRL); - while (readl(siic->base + SIRFSOC_I2C_CTRL) & SIRFSOC_I2C_RESET) - cpu_relax(); - writel(SIRFSOC_I2C_CORE_EN | SIRFSOC_I2C_MASTER_MODE, - siic->base + SIRFSOC_I2C_CTRL); - - siic->clk = clk; - - err = of_property_read_u32(pdev->dev.of_node, - "clock-frequency", &bitrate); - if (err < 0) - bitrate = I2C_MAX_STANDARD_MODE_FREQ; - - /* - * Due to some hardware design issues, we need to tune the formula. - * Since i2c is open drain interface that allows the slave to - * stall the transaction by holding the SCL line at '0', the RTL - * implementation is waiting for SCL feedback from the pin after - * setting it to High-Z ('1'). This wait adds to the high-time - * interval counter few cycles of the input synchronization - * (depending on the SCL_FILTER_REG field), and also the time it - * takes for the board pull-up resistor to rise the SCL line. - * For slow SCL settings these additions are negligible, - * but they start to affect the speed when clock is set to faster - * frequencies. - * Through the actual tests, use the different user_div value(which - * in the divider formula 'Fio / (Fi2c * user_div)') to adapt - * the different ranges of i2c bus clock frequency, to make the SCL - * more accurate. - */ - if (bitrate <= 30000) - regval = ctrl_speed / (bitrate * 5); - else if (bitrate > 30000 && bitrate <= 280000) - regval = (2 * ctrl_speed) / (bitrate * 11); - else - regval = ctrl_speed / (bitrate * 6); - - writel(regval, siic->base + SIRFSOC_I2C_CLK_CTRL); - if (regval > 0xFF) - writel(0xFF, siic->base + SIRFSOC_I2C_SDA_DELAY); - else - writel(regval, siic->base + SIRFSOC_I2C_SDA_DELAY); - - err = i2c_add_numbered_adapter(adap); - if (err < 0) - goto out; - - clk_disable(clk); - - dev_info(&pdev->dev, " I2C adapter ready to operate\n"); - - return 0; - -out: - clk_disable(clk); -err_clk_en: - clk_unprepare(clk); -err_clk_prep: - clk_put(clk); -err_get_clk: - return err; -} - -static int i2c_sirfsoc_remove(struct platform_device *pdev) -{ - struct i2c_adapter *adapter = platform_get_drvdata(pdev); - struct sirfsoc_i2c *siic = adapter->algo_data; - - writel(SIRFSOC_I2C_RESET, siic->base + SIRFSOC_I2C_CTRL); - i2c_del_adapter(adapter); - clk_unprepare(siic->clk); - clk_put(siic->clk); - return 0; -} - -#ifdef CONFIG_PM -static int i2c_sirfsoc_suspend(struct device *dev) -{ - struct i2c_adapter *adapter = dev_get_drvdata(dev); - struct sirfsoc_i2c *siic = adapter->algo_data; - - clk_enable(siic->clk); - siic->sda_delay = readl(siic->base + SIRFSOC_I2C_SDA_DELAY); - siic->clk_div = readl(siic->base + SIRFSOC_I2C_CLK_CTRL); - clk_disable(siic->clk); - return 0; -} - -static int i2c_sirfsoc_resume(struct device *dev) -{ - struct i2c_adapter *adapter = dev_get_drvdata(dev); - struct sirfsoc_i2c *siic = adapter->algo_data; - - clk_enable(siic->clk); - writel(SIRFSOC_I2C_RESET, siic->base + SIRFSOC_I2C_CTRL); - while (readl(siic->base + SIRFSOC_I2C_CTRL) & SIRFSOC_I2C_RESET) - cpu_relax(); - writel(SIRFSOC_I2C_CORE_EN | SIRFSOC_I2C_MASTER_MODE, - siic->base + SIRFSOC_I2C_CTRL); - writel(siic->clk_div, siic->base + SIRFSOC_I2C_CLK_CTRL); - writel(siic->sda_delay, siic->base + SIRFSOC_I2C_SDA_DELAY); - clk_disable(siic->clk); - return 0; -} - -static const struct dev_pm_ops i2c_sirfsoc_pm_ops = { - .suspend = i2c_sirfsoc_suspend, - .resume = i2c_sirfsoc_resume, -}; -#endif - -static const struct of_device_id sirfsoc_i2c_of_match[] = { - { .compatible = "sirf,prima2-i2c", }, - {}, -}; -MODULE_DEVICE_TABLE(of, sirfsoc_i2c_of_match); - -static struct platform_driver i2c_sirfsoc_driver = { - .driver = { - .name = "sirfsoc_i2c", -#ifdef CONFIG_PM - .pm = &i2c_sirfsoc_pm_ops, -#endif - .of_match_table = sirfsoc_i2c_of_match, - }, - .probe = i2c_sirfsoc_probe, - .remove = i2c_sirfsoc_remove, -}; -module_platform_driver(i2c_sirfsoc_driver); - -MODULE_DESCRIPTION("SiRF SoC I2C master controller driver"); -MODULE_AUTHOR("Zhiwu Song <Zhiwu.Song@csr.com>"); -MODULE_AUTHOR("Xiangzhen Ye <Xiangzhen.Ye@csr.com>"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/i2c/busses/i2c-stm32f7.c b/drivers/i2c/busses/i2c-stm32f7.c index 473fbe144b7e..c62c815b88eb 100644 --- a/drivers/i2c/busses/i2c-stm32f7.c +++ b/drivers/i2c/busses/i2c-stm32f7.c @@ -2035,12 +2035,8 @@ static int stm32f7_i2c_probe(struct platform_device *pdev) } irq_error = platform_get_irq(pdev, 1); - if (irq_error <= 0) { - if (irq_error != -EPROBE_DEFER) - dev_err(&pdev->dev, "Failed to get IRQ error: %d\n", - irq_error); + if (irq_error <= 0) return irq_error ? : -ENOENT; - } i2c_dev->wakeup_src = of_property_read_bool(pdev->dev.of_node, "wakeup-source"); diff --git a/drivers/i2c/busses/i2c-stu300.c b/drivers/i2c/busses/i2c-stu300.c deleted file mode 100644 index 64d739baf480..000000000000 --- a/drivers/i2c/busses/i2c-stu300.c +++ /dev/null @@ -1,1008 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (C) 2007-2012 ST-Ericsson AB - * ST DDC I2C master mode driver, used in e.g. U300 series platforms. - * Author: Linus Walleij <linus.walleij@stericsson.com> - * Author: Jonas Aaberg <jonas.aberg@stericsson.com> - */ -#include <linux/init.h> -#include <linux/module.h> -#include <linux/platform_device.h> -#include <linux/delay.h> -#include <linux/i2c.h> -#include <linux/spinlock.h> -#include <linux/completion.h> -#include <linux/err.h> -#include <linux/interrupt.h> -#include <linux/clk.h> -#include <linux/io.h> -#include <linux/slab.h> - -/* the name of this kernel module */ -#define NAME "stu300" - -/* CR (Control Register) 8bit (R/W) */ -#define I2C_CR (0x00000000) -#define I2C_CR_RESET_VALUE (0x00) -#define I2C_CR_RESET_UMASK (0x00) -#define I2C_CR_DDC1_ENABLE (0x80) -#define I2C_CR_TRANS_ENABLE (0x40) -#define I2C_CR_PERIPHERAL_ENABLE (0x20) -#define I2C_CR_DDC2B_ENABLE (0x10) -#define I2C_CR_START_ENABLE (0x08) -#define I2C_CR_ACK_ENABLE (0x04) -#define I2C_CR_STOP_ENABLE (0x02) -#define I2C_CR_INTERRUPT_ENABLE (0x01) -/* SR1 (Status Register 1) 8bit (R/-) */ -#define I2C_SR1 (0x00000004) -#define I2C_SR1_RESET_VALUE (0x00) -#define I2C_SR1_RESET_UMASK (0x00) -#define I2C_SR1_EVF_IND (0x80) -#define I2C_SR1_ADD10_IND (0x40) -#define I2C_SR1_TRA_IND (0x20) -#define I2C_SR1_BUSY_IND (0x10) -#define I2C_SR1_BTF_IND (0x08) -#define I2C_SR1_ADSL_IND (0x04) -#define I2C_SR1_MSL_IND (0x02) -#define I2C_SR1_SB_IND (0x01) -/* SR2 (Status Register 2) 8bit (R/-) */ -#define I2C_SR2 (0x00000008) -#define I2C_SR2_RESET_VALUE (0x00) -#define I2C_SR2_RESET_UMASK (0x40) -#define I2C_SR2_MASK (0xBF) -#define I2C_SR2_SCLFAL_IND (0x80) -#define I2C_SR2_ENDAD_IND (0x20) -#define I2C_SR2_AF_IND (0x10) -#define I2C_SR2_STOPF_IND (0x08) -#define I2C_SR2_ARLO_IND (0x04) -#define I2C_SR2_BERR_IND (0x02) -#define I2C_SR2_DDC2BF_IND (0x01) -/* CCR (Clock Control Register) 8bit (R/W) */ -#define I2C_CCR (0x0000000C) -#define I2C_CCR_RESET_VALUE (0x00) -#define I2C_CCR_RESET_UMASK (0x00) -#define I2C_CCR_MASK (0xFF) -#define I2C_CCR_FMSM (0x80) -#define I2C_CCR_CC_MASK (0x7F) -/* OAR1 (Own Address Register 1) 8bit (R/W) */ -#define I2C_OAR1 (0x00000010) -#define I2C_OAR1_RESET_VALUE (0x00) -#define I2C_OAR1_RESET_UMASK (0x00) -#define I2C_OAR1_ADD_MASK (0xFF) -/* OAR2 (Own Address Register 2) 8bit (R/W) */ -#define I2C_OAR2 (0x00000014) -#define I2C_OAR2_RESET_VALUE (0x40) -#define I2C_OAR2_RESET_UMASK (0x19) -#define I2C_OAR2_MASK (0xE6) -#define I2C_OAR2_FR_25_10MHZ (0x00) -#define I2C_OAR2_FR_10_1667MHZ (0x20) -#define I2C_OAR2_FR_1667_2667MHZ (0x40) -#define I2C_OAR2_FR_2667_40MHZ (0x60) -#define I2C_OAR2_FR_40_5333MHZ (0x80) -#define I2C_OAR2_FR_5333_66MHZ (0xA0) -#define I2C_OAR2_FR_66_80MHZ (0xC0) -#define I2C_OAR2_FR_80_100MHZ (0xE0) -#define I2C_OAR2_FR_MASK (0xE0) -#define I2C_OAR2_ADD_MASK (0x06) -/* DR (Data Register) 8bit (R/W) */ -#define I2C_DR (0x00000018) -#define I2C_DR_RESET_VALUE (0x00) -#define I2C_DR_RESET_UMASK (0xFF) -#define I2C_DR_D_MASK (0xFF) -/* ECCR (Extended Clock Control Register) 8bit (R/W) */ -#define I2C_ECCR (0x0000001C) -#define I2C_ECCR_RESET_VALUE (0x00) -#define I2C_ECCR_RESET_UMASK (0xE0) -#define I2C_ECCR_MASK (0x1F) -#define I2C_ECCR_CC_MASK (0x1F) - -/* - * These events are more or less responses to commands - * sent into the hardware, presumably reflecting the state - * of an internal state machine. - */ -enum stu300_event { - STU300_EVENT_NONE = 0, - STU300_EVENT_1, - STU300_EVENT_2, - STU300_EVENT_3, - STU300_EVENT_4, - STU300_EVENT_5, - STU300_EVENT_6, - STU300_EVENT_7, - STU300_EVENT_8, - STU300_EVENT_9 -}; - -enum stu300_error { - STU300_ERROR_NONE = 0, - STU300_ERROR_ACKNOWLEDGE_FAILURE, - STU300_ERROR_BUS_ERROR, - STU300_ERROR_ARBITRATION_LOST, - STU300_ERROR_UNKNOWN -}; - -/* timeout waiting for the controller to respond */ -#define STU300_TIMEOUT (msecs_to_jiffies(1000)) - -/* - * The number of address send athemps tried before giving up. - * If the first one fails it seems like 5 to 8 attempts are required. - */ -#define NUM_ADDR_RESEND_ATTEMPTS 12 - -/* I2C clock speed, in Hz 0-400kHz*/ -static unsigned int scl_frequency = I2C_MAX_STANDARD_MODE_FREQ; -module_param(scl_frequency, uint, 0644); - -/** - * struct stu300_dev - the stu300 driver state holder - * @pdev: parent platform device - * @adapter: corresponding I2C adapter - * @clk: hardware block clock - * @irq: assigned interrupt line - * @cmd_issue_lock: this locks the following cmd_ variables - * @cmd_complete: acknowledge completion for an I2C command - * @cmd_event: expected event coming in as a response to a command - * @cmd_err: error code as response to a command - * @speed: current bus speed in Hz - * @msg_index: index of current message - * @msg_len: length of current message - */ - -struct stu300_dev { - struct platform_device *pdev; - struct i2c_adapter adapter; - void __iomem *virtbase; - struct clk *clk; - int irq; - spinlock_t cmd_issue_lock; - struct completion cmd_complete; - enum stu300_event cmd_event; - enum stu300_error cmd_err; - unsigned int speed; - int msg_index; - int msg_len; -}; - -/* Local forward function declarations */ -static int stu300_init_hw(struct stu300_dev *dev); - -/* - * The block needs writes in both MSW and LSW in order - * for all data lines to reach their destination. - */ -static inline void stu300_wr8(u32 value, void __iomem *address) -{ - writel((value << 16) | value, address); -} - -/* - * This merely masks off the duplicates which appear - * in bytes 1-3. You _MUST_ use 32-bit bus access on this - * device, else it will not work. - */ -static inline u32 stu300_r8(void __iomem *address) -{ - return readl(address) & 0x000000FFU; -} - -static void stu300_irq_enable(struct stu300_dev *dev) -{ - u32 val; - val = stu300_r8(dev->virtbase + I2C_CR); - val |= I2C_CR_INTERRUPT_ENABLE; - /* Twice paranoia (possible HW glitch) */ - stu300_wr8(val, dev->virtbase + I2C_CR); - stu300_wr8(val, dev->virtbase + I2C_CR); -} - -static void stu300_irq_disable(struct stu300_dev *dev) -{ - u32 val; - val = stu300_r8(dev->virtbase + I2C_CR); - val &= ~I2C_CR_INTERRUPT_ENABLE; - /* Twice paranoia (possible HW glitch) */ - stu300_wr8(val, dev->virtbase + I2C_CR); - stu300_wr8(val, dev->virtbase + I2C_CR); -} - - -/* - * Tells whether a certain event or events occurred in - * response to a command. The events represent states in - * the internal state machine of the hardware. The events - * are not very well described in the hardware - * documentation and can only be treated as abstract state - * machine states. - * - * @ret 0 = event has not occurred or unknown error, any - * other value means the correct event occurred or an error. - */ - -static int stu300_event_occurred(struct stu300_dev *dev, - enum stu300_event mr_event) { - u32 status1; - u32 status2; - - /* What event happened? */ - status1 = stu300_r8(dev->virtbase + I2C_SR1); - - if (!(status1 & I2C_SR1_EVF_IND)) - /* No event at all */ - return 0; - - status2 = stu300_r8(dev->virtbase + I2C_SR2); - - /* Block any multiple interrupts */ - stu300_irq_disable(dev); - - /* Check for errors first */ - if (status2 & I2C_SR2_AF_IND) { - dev->cmd_err = STU300_ERROR_ACKNOWLEDGE_FAILURE; - return 1; - } else if (status2 & I2C_SR2_BERR_IND) { - dev->cmd_err = STU300_ERROR_BUS_ERROR; - return 1; - } else if (status2 & I2C_SR2_ARLO_IND) { - dev->cmd_err = STU300_ERROR_ARBITRATION_LOST; - return 1; - } - - switch (mr_event) { - case STU300_EVENT_1: - if (status1 & I2C_SR1_ADSL_IND) - return 1; - break; - case STU300_EVENT_2: - case STU300_EVENT_3: - case STU300_EVENT_7: - case STU300_EVENT_8: - if (status1 & I2C_SR1_BTF_IND) { - return 1; - } - break; - case STU300_EVENT_4: - if (status2 & I2C_SR2_STOPF_IND) - return 1; - break; - case STU300_EVENT_5: - if (status1 & I2C_SR1_SB_IND) - /* Clear start bit */ - return 1; - break; - case STU300_EVENT_6: - if (status2 & I2C_SR2_ENDAD_IND) { - /* First check for any errors */ - return 1; - } - break; - case STU300_EVENT_9: - if (status1 & I2C_SR1_ADD10_IND) - return 1; - break; - default: - break; - } - /* If we get here, we're on thin ice. - * Here we are in a status where we have - * gotten a response that does not match - * what we requested. - */ - dev->cmd_err = STU300_ERROR_UNKNOWN; - dev_err(&dev->pdev->dev, - "Unhandled interrupt! %d sr1: 0x%x sr2: 0x%x\n", - mr_event, status1, status2); - return 0; -} - -static irqreturn_t stu300_irh(int irq, void *data) -{ - struct stu300_dev *dev = data; - int res; - - /* Just make sure that the block is clocked */ - clk_enable(dev->clk); - - /* See if this was what we were waiting for */ - spin_lock(&dev->cmd_issue_lock); - - res = stu300_event_occurred(dev, dev->cmd_event); - if (res || dev->cmd_err != STU300_ERROR_NONE) - complete(&dev->cmd_complete); - - spin_unlock(&dev->cmd_issue_lock); - - clk_disable(dev->clk); - - return IRQ_HANDLED; -} - -/* - * Sends a command and then waits for the bits masked by *flagmask* - * to go high or low by IRQ awaiting. - */ -static int stu300_start_and_await_event(struct stu300_dev *dev, - u8 cr_value, - enum stu300_event mr_event) -{ - int ret; - - /* Lock command issue, fill in an event we wait for */ - spin_lock_irq(&dev->cmd_issue_lock); - init_completion(&dev->cmd_complete); - dev->cmd_err = STU300_ERROR_NONE; - dev->cmd_event = mr_event; - spin_unlock_irq(&dev->cmd_issue_lock); - - /* Turn on interrupt, send command and wait. */ - cr_value |= I2C_CR_INTERRUPT_ENABLE; - stu300_wr8(cr_value, dev->virtbase + I2C_CR); - ret = wait_for_completion_interruptible_timeout(&dev->cmd_complete, - STU300_TIMEOUT); - if (ret < 0) { - dev_err(&dev->pdev->dev, - "wait_for_completion_interruptible_timeout() " - "returned %d waiting for event %04x\n", ret, mr_event); - return ret; - } - - if (ret == 0) { - dev_err(&dev->pdev->dev, "controller timed out " - "waiting for event %d, reinit hardware\n", mr_event); - (void) stu300_init_hw(dev); - return -ETIMEDOUT; - } - - if (dev->cmd_err != STU300_ERROR_NONE) { - dev_err(&dev->pdev->dev, "controller (start) " - "error %d waiting for event %d, reinit hardware\n", - dev->cmd_err, mr_event); - (void) stu300_init_hw(dev); - return -EIO; - } - - return 0; -} - -/* - * This waits for a flag to be set, if it is not set on entry, an interrupt is - * configured to wait for the flag using a completion. - */ -static int stu300_await_event(struct stu300_dev *dev, - enum stu300_event mr_event) -{ - int ret; - - /* Is it already here? */ - spin_lock_irq(&dev->cmd_issue_lock); - dev->cmd_err = STU300_ERROR_NONE; - dev->cmd_event = mr_event; - - init_completion(&dev->cmd_complete); - - /* Turn on the I2C interrupt for current operation */ - stu300_irq_enable(dev); - - /* Unlock the command block and wait for the event to occur */ - spin_unlock_irq(&dev->cmd_issue_lock); - - ret = wait_for_completion_interruptible_timeout(&dev->cmd_complete, - STU300_TIMEOUT); - if (ret < 0) { - dev_err(&dev->pdev->dev, - "wait_for_completion_interruptible_timeout()" - "returned %d waiting for event %04x\n", ret, mr_event); - return ret; - } - - if (ret == 0) { - if (mr_event != STU300_EVENT_6) { - dev_err(&dev->pdev->dev, "controller " - "timed out waiting for event %d, reinit " - "hardware\n", mr_event); - (void) stu300_init_hw(dev); - } - return -ETIMEDOUT; - } - - if (dev->cmd_err != STU300_ERROR_NONE) { - if (mr_event != STU300_EVENT_6) { - dev_err(&dev->pdev->dev, "controller " - "error (await_event) %d waiting for event %d, " - "reinit hardware\n", dev->cmd_err, mr_event); - (void) stu300_init_hw(dev); - } - return -EIO; - } - - return 0; -} - -/* - * Waits for the busy bit to go low by repeated polling. - */ -#define BUSY_RELEASE_ATTEMPTS 10 -static int stu300_wait_while_busy(struct stu300_dev *dev) -{ - unsigned long timeout; - int i; - - for (i = 0; i < BUSY_RELEASE_ATTEMPTS; i++) { - timeout = jiffies + STU300_TIMEOUT; - - while (!time_after(jiffies, timeout)) { - /* Is not busy? */ - if ((stu300_r8(dev->virtbase + I2C_SR1) & - I2C_SR1_BUSY_IND) == 0) - return 0; - msleep(1); - } - - dev_err(&dev->pdev->dev, "transaction timed out " - "waiting for device to be free (not busy). " - "Attempt: %d\n", i+1); - - dev_err(&dev->pdev->dev, "base address = " - "0x%p, reinit hardware\n", dev->virtbase); - - (void) stu300_init_hw(dev); - } - - dev_err(&dev->pdev->dev, "giving up after %d attempts " - "to reset the bus.\n", BUSY_RELEASE_ATTEMPTS); - - return -ETIMEDOUT; -} - -struct stu300_clkset { - unsigned long rate; - u32 setting; -}; - -static const struct stu300_clkset stu300_clktable[] = { - { 0, 0xFFU }, - { 2500000, I2C_OAR2_FR_25_10MHZ }, - { 10000000, I2C_OAR2_FR_10_1667MHZ }, - { 16670000, I2C_OAR2_FR_1667_2667MHZ }, - { 26670000, I2C_OAR2_FR_2667_40MHZ }, - { 40000000, I2C_OAR2_FR_40_5333MHZ }, - { 53330000, I2C_OAR2_FR_5333_66MHZ }, - { 66000000, I2C_OAR2_FR_66_80MHZ }, - { 80000000, I2C_OAR2_FR_80_100MHZ }, - { 100000000, 0xFFU }, -}; - - -static int stu300_set_clk(struct stu300_dev *dev, unsigned long clkrate) -{ - - u32 val; - int i = 0; - - /* Locate the appropriate clock setting */ - while (i < ARRAY_SIZE(stu300_clktable) - 1 && - stu300_clktable[i].rate < clkrate) - i++; - - if (stu300_clktable[i].setting == 0xFFU) { - dev_err(&dev->pdev->dev, "too %s clock rate requested " - "(%lu Hz).\n", i ? "high" : "low", clkrate); - return -EINVAL; - } - - stu300_wr8(stu300_clktable[i].setting, - dev->virtbase + I2C_OAR2); - - dev_dbg(&dev->pdev->dev, "Clock rate %lu Hz, I2C bus speed %d Hz " - "virtbase %p\n", clkrate, dev->speed, dev->virtbase); - - if (dev->speed > I2C_MAX_STANDARD_MODE_FREQ) - /* Fast Mode I2C */ - val = ((clkrate/dev->speed) - 9)/3 + 1; - else - /* Standard Mode I2C */ - val = ((clkrate/dev->speed) - 7)/2 + 1; - - /* According to spec the divider must be > 2 */ - if (val < 0x002) { - dev_err(&dev->pdev->dev, "too low clock rate (%lu Hz).\n", - clkrate); - return -EINVAL; - } - - /* We have 12 bits clock divider only! */ - if (val & 0xFFFFF000U) { - dev_err(&dev->pdev->dev, "too high clock rate (%lu Hz).\n", - clkrate); - return -EINVAL; - } - - if (dev->speed > I2C_MAX_STANDARD_MODE_FREQ) { - /* CC6..CC0 */ - stu300_wr8((val & I2C_CCR_CC_MASK) | I2C_CCR_FMSM, - dev->virtbase + I2C_CCR); - dev_dbg(&dev->pdev->dev, "set clock divider to 0x%08x, " - "Fast Mode I2C\n", val); - } else { - /* CC6..CC0 */ - stu300_wr8((val & I2C_CCR_CC_MASK), - dev->virtbase + I2C_CCR); - dev_dbg(&dev->pdev->dev, "set clock divider to " - "0x%08x, Standard Mode I2C\n", val); - } - - /* CC11..CC7 */ - stu300_wr8(((val >> 7) & 0x1F), - dev->virtbase + I2C_ECCR); - - return 0; -} - - -static int stu300_init_hw(struct stu300_dev *dev) -{ - u32 dummy; - unsigned long clkrate; - int ret; - - /* Disable controller */ - stu300_wr8(0x00, dev->virtbase + I2C_CR); - /* - * Set own address to some default value (0x00). - * We do not support slave mode anyway. - */ - stu300_wr8(0x00, dev->virtbase + I2C_OAR1); - /* - * The I2C controller only operates properly in 26 MHz but we - * program this driver as if we didn't know. This will also set the two - * high bits of the own address to zero as well. - * There is no known hardware issue with running in 13 MHz - * However, speeds over 200 kHz are not used. - */ - clkrate = clk_get_rate(dev->clk); - ret = stu300_set_clk(dev, clkrate); - - if (ret) - return ret; - /* - * Enable block, do it TWICE (hardware glitch) - * Setting bit 7 can enable DDC mode. (Not used currently.) - */ - stu300_wr8(I2C_CR_PERIPHERAL_ENABLE, - dev->virtbase + I2C_CR); - stu300_wr8(I2C_CR_PERIPHERAL_ENABLE, - dev->virtbase + I2C_CR); - /* Make a dummy read of the status register SR1 & SR2 */ - dummy = stu300_r8(dev->virtbase + I2C_SR2); - dummy = stu300_r8(dev->virtbase + I2C_SR1); - - return 0; -} - - - -/* Send slave address. */ -static int stu300_send_address(struct stu300_dev *dev, - struct i2c_msg *msg, int resend) -{ - u32 val; - int ret; - - if (msg->flags & I2C_M_TEN) { - /* This is probably how 10 bit addresses look */ - val = (0xf0 | (((u32) msg->addr & 0x300) >> 7)) & - I2C_DR_D_MASK; - if (msg->flags & I2C_M_RD) - /* This is the direction bit */ - val |= 0x01; - } else { - val = i2c_8bit_addr_from_msg(msg); - } - - if (resend) { - if (msg->flags & I2C_M_RD) - dev_dbg(&dev->pdev->dev, "read resend\n"); - else - dev_dbg(&dev->pdev->dev, "write resend\n"); - } - - stu300_wr8(val, dev->virtbase + I2C_DR); - - /* For 10bit addressing, await 10bit request (EVENT 9) */ - if (msg->flags & I2C_M_TEN) { - ret = stu300_await_event(dev, STU300_EVENT_9); - /* - * The slave device wants a 10bit address, send the rest - * of the bits (the LSBits) - */ - val = msg->addr & I2C_DR_D_MASK; - /* This clears "event 9" */ - stu300_wr8(val, dev->virtbase + I2C_DR); - if (ret != 0) - return ret; - } - /* FIXME: Why no else here? two events for 10bit? - * Await event 6 (normal) or event 9 (10bit) - */ - - if (resend) - dev_dbg(&dev->pdev->dev, "await event 6\n"); - ret = stu300_await_event(dev, STU300_EVENT_6); - - /* - * Clear any pending EVENT 6 no matter what happened during - * await_event. - */ - val = stu300_r8(dev->virtbase + I2C_CR); - val |= I2C_CR_PERIPHERAL_ENABLE; - stu300_wr8(val, dev->virtbase + I2C_CR); - - return ret; -} - -static int stu300_xfer_msg(struct i2c_adapter *adap, - struct i2c_msg *msg, int stop) -{ - u32 cr; - u32 val; - u32 i; - int ret; - int attempts = 0; - struct stu300_dev *dev = i2c_get_adapdata(adap); - - clk_enable(dev->clk); - - /* Remove this if (0) to trace each and every message. */ - if (0) { - dev_dbg(&dev->pdev->dev, "I2C message to: 0x%04x, len: %d, " - "flags: 0x%04x, stop: %d\n", - msg->addr, msg->len, msg->flags, stop); - } - - /* - * For some reason, sending the address sometimes fails when running - * on the 13 MHz clock. No interrupt arrives. This is a work around, - * which tries to restart and send the address up to 10 times before - * really giving up. Usually 5 to 8 attempts are enough. - */ - do { - if (attempts) - dev_dbg(&dev->pdev->dev, "wait while busy\n"); - /* Check that the bus is free, or wait until some timeout */ - ret = stu300_wait_while_busy(dev); - if (ret != 0) - goto exit_disable; - - if (attempts) - dev_dbg(&dev->pdev->dev, "re-int hw\n"); - /* - * According to ST, there is no problem if the clock is - * changed between 13 and 26 MHz during a transfer. - */ - ret = stu300_init_hw(dev); - if (ret) - goto exit_disable; - - /* Send a start condition */ - cr = I2C_CR_PERIPHERAL_ENABLE; - /* Setting the START bit puts the block in master mode */ - if (!(msg->flags & I2C_M_NOSTART)) - cr |= I2C_CR_START_ENABLE; - if ((msg->flags & I2C_M_RD) && (msg->len > 1)) - /* On read more than 1 byte, we need ack. */ - cr |= I2C_CR_ACK_ENABLE; - /* Check that it gets through */ - if (!(msg->flags & I2C_M_NOSTART)) { - if (attempts) - dev_dbg(&dev->pdev->dev, "send start event\n"); - ret = stu300_start_and_await_event(dev, cr, - STU300_EVENT_5); - } - - if (attempts) - dev_dbg(&dev->pdev->dev, "send address\n"); - - if (ret == 0) - /* Send address */ - ret = stu300_send_address(dev, msg, attempts != 0); - - if (ret != 0) { - attempts++; - dev_dbg(&dev->pdev->dev, "failed sending address, " - "retrying. Attempt: %d msg_index: %d/%d\n", - attempts, dev->msg_index, dev->msg_len); - } - - } while (ret != 0 && attempts < NUM_ADDR_RESEND_ATTEMPTS); - - if (attempts < NUM_ADDR_RESEND_ATTEMPTS && attempts > 0) { - dev_dbg(&dev->pdev->dev, "managed to get address " - "through after %d attempts\n", attempts); - } else if (attempts == NUM_ADDR_RESEND_ATTEMPTS) { - dev_dbg(&dev->pdev->dev, "I give up, tried %d times " - "to resend address.\n", - NUM_ADDR_RESEND_ATTEMPTS); - goto exit_disable; - } - - - if (msg->flags & I2C_M_RD) { - /* READ: we read the actual bytes one at a time */ - for (i = 0; i < msg->len; i++) { - if (i == msg->len-1) { - /* - * Disable ACK and set STOP condition before - * reading last byte - */ - val = I2C_CR_PERIPHERAL_ENABLE; - - if (stop) - val |= I2C_CR_STOP_ENABLE; - - stu300_wr8(val, - dev->virtbase + I2C_CR); - } - /* Wait for this byte... */ - ret = stu300_await_event(dev, STU300_EVENT_7); - if (ret != 0) - goto exit_disable; - /* This clears event 7 */ - msg->buf[i] = (u8) stu300_r8(dev->virtbase + I2C_DR); - } - } else { - /* WRITE: we send the actual bytes one at a time */ - for (i = 0; i < msg->len; i++) { - /* Write the byte */ - stu300_wr8(msg->buf[i], - dev->virtbase + I2C_DR); - /* Check status */ - ret = stu300_await_event(dev, STU300_EVENT_8); - /* Next write to DR will clear event 8 */ - if (ret != 0) { - dev_err(&dev->pdev->dev, "error awaiting " - "event 8 (%d)\n", ret); - goto exit_disable; - } - } - /* Check NAK */ - if (!(msg->flags & I2C_M_IGNORE_NAK)) { - if (stu300_r8(dev->virtbase + I2C_SR2) & - I2C_SR2_AF_IND) { - dev_err(&dev->pdev->dev, "I2C payload " - "send returned NAK!\n"); - ret = -EIO; - goto exit_disable; - } - } - if (stop) { - /* Send stop condition */ - val = I2C_CR_PERIPHERAL_ENABLE; - val |= I2C_CR_STOP_ENABLE; - stu300_wr8(val, dev->virtbase + I2C_CR); - } - } - - /* Check that the bus is free, or wait until some timeout occurs */ - ret = stu300_wait_while_busy(dev); - if (ret != 0) { - dev_err(&dev->pdev->dev, "timeout waiting for transfer " - "to commence.\n"); - goto exit_disable; - } - - /* Dummy read status registers */ - val = stu300_r8(dev->virtbase + I2C_SR2); - val = stu300_r8(dev->virtbase + I2C_SR1); - ret = 0; - - exit_disable: - /* Disable controller */ - stu300_wr8(0x00, dev->virtbase + I2C_CR); - clk_disable(dev->clk); - return ret; -} - -static int stu300_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, - int num) -{ - int ret = -1; - int i; - - struct stu300_dev *dev = i2c_get_adapdata(adap); - dev->msg_len = num; - - for (i = 0; i < num; i++) { - /* - * Another driver appears to send stop for each message, - * here we only do that for the last message. Possibly some - * peripherals require this behaviour, then their drivers - * have to send single messages in order to get "stop" for - * each message. - */ - dev->msg_index = i; - - ret = stu300_xfer_msg(adap, &msgs[i], (i == (num - 1))); - - if (ret != 0) { - num = ret; - break; - } - } - - return num; -} - -static int stu300_xfer_todo(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) -{ - /* TODO: implement polling for this case if need be. */ - WARN(1, "%s: atomic transfers not implemented\n", dev_name(&adap->dev)); - return -EOPNOTSUPP; -} - -static u32 stu300_func(struct i2c_adapter *adap) -{ - /* This is the simplest thing you can think of... */ - return I2C_FUNC_I2C | I2C_FUNC_10BIT_ADDR; -} - -static const struct i2c_algorithm stu300_algo = { - .master_xfer = stu300_xfer, - .master_xfer_atomic = stu300_xfer_todo, - .functionality = stu300_func, -}; - -static const struct i2c_adapter_quirks stu300_quirks = { - .flags = I2C_AQ_NO_ZERO_LEN, -}; - -static int stu300_probe(struct platform_device *pdev) -{ - struct stu300_dev *dev; - struct i2c_adapter *adap; - int bus_nr; - int ret = 0; - - dev = devm_kzalloc(&pdev->dev, sizeof(struct stu300_dev), GFP_KERNEL); - if (!dev) - return -ENOMEM; - - bus_nr = pdev->id; - dev->clk = devm_clk_get(&pdev->dev, NULL); - if (IS_ERR(dev->clk)) { - dev_err(&pdev->dev, "could not retrieve i2c bus clock\n"); - return PTR_ERR(dev->clk); - } - - dev->pdev = pdev; - dev->virtbase = devm_platform_ioremap_resource(pdev, 0); - dev_dbg(&pdev->dev, "initialize bus device I2C%d on virtual " - "base %p\n", bus_nr, dev->virtbase); - if (IS_ERR(dev->virtbase)) - return PTR_ERR(dev->virtbase); - - dev->irq = platform_get_irq(pdev, 0); - ret = devm_request_irq(&pdev->dev, dev->irq, stu300_irh, 0, NAME, dev); - if (ret < 0) - return ret; - - dev->speed = scl_frequency; - - clk_prepare_enable(dev->clk); - ret = stu300_init_hw(dev); - clk_disable(dev->clk); - if (ret != 0) { - dev_err(&dev->pdev->dev, "error initializing hardware.\n"); - return -EIO; - } - - /* IRQ event handling initialization */ - spin_lock_init(&dev->cmd_issue_lock); - dev->cmd_event = STU300_EVENT_NONE; - dev->cmd_err = STU300_ERROR_NONE; - - adap = &dev->adapter; - adap->owner = THIS_MODULE; - /* DDC class but actually often used for more generic I2C */ - adap->class = I2C_CLASS_DEPRECATED; - strlcpy(adap->name, "ST Microelectronics DDC I2C adapter", - sizeof(adap->name)); - adap->nr = bus_nr; - adap->algo = &stu300_algo; - adap->dev.parent = &pdev->dev; - adap->dev.of_node = pdev->dev.of_node; - adap->quirks = &stu300_quirks; - - i2c_set_adapdata(adap, dev); - - /* i2c device drivers may be active on return from add_adapter() */ - ret = i2c_add_numbered_adapter(adap); - if (ret) - return ret; - - platform_set_drvdata(pdev, dev); - dev_info(&pdev->dev, "ST DDC I2C @ %p, irq %d\n", - dev->virtbase, dev->irq); - - return 0; -} - -#ifdef CONFIG_PM_SLEEP -static int stu300_suspend(struct device *device) -{ - struct stu300_dev *dev = dev_get_drvdata(device); - - /* Turn off everything */ - stu300_wr8(0x00, dev->virtbase + I2C_CR); - return 0; -} - -static int stu300_resume(struct device *device) -{ - int ret = 0; - struct stu300_dev *dev = dev_get_drvdata(device); - - clk_enable(dev->clk); - ret = stu300_init_hw(dev); - clk_disable(dev->clk); - - if (ret != 0) - dev_err(device, "error re-initializing hardware.\n"); - return ret; -} - -static SIMPLE_DEV_PM_OPS(stu300_pm, stu300_suspend, stu300_resume); -#define STU300_I2C_PM (&stu300_pm) -#else -#define STU300_I2C_PM NULL -#endif - -static int stu300_remove(struct platform_device *pdev) -{ - struct stu300_dev *dev = platform_get_drvdata(pdev); - - i2c_del_adapter(&dev->adapter); - /* Turn off everything */ - stu300_wr8(0x00, dev->virtbase + I2C_CR); - return 0; -} - -static const struct of_device_id stu300_dt_match[] = { - { .compatible = "st,ddci2c" }, - {}, -}; -MODULE_DEVICE_TABLE(of, stu300_dt_match); - -static struct platform_driver stu300_i2c_driver = { - .driver = { - .name = NAME, - .pm = STU300_I2C_PM, - .of_match_table = stu300_dt_match, - }, - .probe = stu300_probe, - .remove = stu300_remove, - -}; - -static int __init stu300_init(void) -{ - return platform_driver_register(&stu300_i2c_driver); -} - -static void __exit stu300_exit(void) -{ - platform_driver_unregister(&stu300_i2c_driver); -} - -/* - * The systems using this bus often have very basic devices such - * as regulators on the I2C bus, so this needs to be loaded early. - * Therefore it is registered in the subsys_initcall(). - */ -subsys_initcall(stu300_init); -module_exit(stu300_exit); - -MODULE_AUTHOR("Linus Walleij <linus.walleij@stericsson.com>"); -MODULE_DESCRIPTION("ST Micro DDC I2C adapter (" NAME ")"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:" NAME); diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index 8b113ae32dc7..c883044715f3 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -550,7 +550,7 @@ static int tegra_i2c_poll_register(struct tegra_i2c_dev *i2c_dev, void __iomem *addr = i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg); u32 val; - if (!i2c_dev->atomic_mode && !in_irq()) + if (!i2c_dev->atomic_mode) return readl_relaxed_poll_timeout(addr, val, !(val & mask), delay_us, timeout_us); @@ -1739,9 +1739,10 @@ static int tegra_i2c_probe(struct platform_device *pdev) /* interrupt will be enabled during of transfer time */ irq_set_status_flags(i2c_dev->irq, IRQ_NOAUTOEN); - err = devm_request_irq(i2c_dev->dev, i2c_dev->irq, tegra_i2c_isr, - IRQF_NO_SUSPEND, dev_name(i2c_dev->dev), - i2c_dev); + err = devm_request_threaded_irq(i2c_dev->dev, i2c_dev->irq, + NULL, tegra_i2c_isr, + IRQF_NO_SUSPEND | IRQF_ONESHOT, + dev_name(i2c_dev->dev), i2c_dev); if (err) return err; diff --git a/drivers/i2c/busses/i2c-zx2967.c b/drivers/i2c/busses/i2c-zx2967.c deleted file mode 100644 index 8db9519695a6..000000000000 --- a/drivers/i2c/busses/i2c-zx2967.c +++ /dev/null @@ -1,602 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (C) 2017 Sanechips Technology Co., Ltd. - * Copyright 2017 Linaro Ltd. - * - * Author: Baoyou Xie <baoyou.xie@linaro.org> - */ - -#include <linux/clk.h> -#include <linux/i2c.h> -#include <linux/interrupt.h> -#include <linux/io.h> -#include <linux/module.h> -#include <linux/platform_device.h> - -#define REG_CMD 0x04 -#define REG_DEVADDR_H 0x0C -#define REG_DEVADDR_L 0x10 -#define REG_CLK_DIV_FS 0x14 -#define REG_CLK_DIV_HS 0x18 -#define REG_WRCONF 0x1C -#define REG_RDCONF 0x20 -#define REG_DATA 0x24 -#define REG_STAT 0x28 - -#define I2C_STOP 0 -#define I2C_MASTER BIT(0) -#define I2C_ADDR_MODE_TEN BIT(1) -#define I2C_IRQ_MSK_ENABLE BIT(3) -#define I2C_RW_READ BIT(4) -#define I2C_CMB_RW_EN BIT(5) -#define I2C_START BIT(6) - -#define I2C_ADDR_LOW_MASK GENMASK(6, 0) -#define I2C_ADDR_LOW_SHIFT 0 -#define I2C_ADDR_HI_MASK GENMASK(2, 0) -#define I2C_ADDR_HI_SHIFT 7 - -#define I2C_WFIFO_RESET BIT(7) -#define I2C_RFIFO_RESET BIT(7) - -#define I2C_IRQ_ACK_CLEAR BIT(7) -#define I2C_INT_MASK GENMASK(6, 0) - -#define I2C_TRANS_DONE BIT(0) -#define I2C_SR_EDEVICE BIT(1) -#define I2C_SR_EDATA BIT(2) - -#define I2C_FIFO_MAX 16 - -#define I2C_TIMEOUT msecs_to_jiffies(1000) - -#define DEV(i2c) ((i2c)->adap.dev.parent) - -struct zx2967_i2c { - struct i2c_adapter adap; - struct clk *clk; - struct completion complete; - u32 clk_freq; - void __iomem *reg_base; - size_t residue; - int irq; - int msg_rd; - u8 *cur_trans; - u8 access_cnt; - int error; -}; - -static void zx2967_i2c_writel(struct zx2967_i2c *i2c, - u32 val, unsigned long reg) -{ - writel_relaxed(val, i2c->reg_base + reg); -} - -static u32 zx2967_i2c_readl(struct zx2967_i2c *i2c, unsigned long reg) -{ - return readl_relaxed(i2c->reg_base + reg); -} - -static void zx2967_i2c_writesb(struct zx2967_i2c *i2c, - void *data, unsigned long reg, int len) -{ - writesb(i2c->reg_base + reg, data, len); -} - -static void zx2967_i2c_readsb(struct zx2967_i2c *i2c, - void *data, unsigned long reg, int len) -{ - readsb(i2c->reg_base + reg, data, len); -} - -static void zx2967_i2c_start_ctrl(struct zx2967_i2c *i2c) -{ - u32 status; - u32 ctl; - - status = zx2967_i2c_readl(i2c, REG_STAT); - status |= I2C_IRQ_ACK_CLEAR; - zx2967_i2c_writel(i2c, status, REG_STAT); - - ctl = zx2967_i2c_readl(i2c, REG_CMD); - if (i2c->msg_rd) - ctl |= I2C_RW_READ; - else - ctl &= ~I2C_RW_READ; - ctl &= ~I2C_CMB_RW_EN; - ctl |= I2C_START; - zx2967_i2c_writel(i2c, ctl, REG_CMD); -} - -static void zx2967_i2c_flush_fifos(struct zx2967_i2c *i2c) -{ - u32 offset; - u32 val; - - if (i2c->msg_rd) { - offset = REG_RDCONF; - val = I2C_RFIFO_RESET; - } else { - offset = REG_WRCONF; - val = I2C_WFIFO_RESET; - } - - val |= zx2967_i2c_readl(i2c, offset); - zx2967_i2c_writel(i2c, val, offset); -} - -static int zx2967_i2c_empty_rx_fifo(struct zx2967_i2c *i2c, u32 size) -{ - u8 val[I2C_FIFO_MAX] = {0}; - int i; - - if (size > I2C_FIFO_MAX) { - dev_err(DEV(i2c), "fifo size %d over the max value %d\n", - size, I2C_FIFO_MAX); - return -EINVAL; - } - - zx2967_i2c_readsb(i2c, val, REG_DATA, size); - for (i = 0; i < size; i++) { - *i2c->cur_trans++ = val[i]; - i2c->residue--; - } - - barrier(); - - return 0; -} - -static int zx2967_i2c_fill_tx_fifo(struct zx2967_i2c *i2c) -{ - size_t residue = i2c->residue; - u8 *buf = i2c->cur_trans; - - if (residue == 0) { - dev_err(DEV(i2c), "residue is %d\n", (int)residue); - return -EINVAL; - } - - if (residue <= I2C_FIFO_MAX) { - zx2967_i2c_writesb(i2c, buf, REG_DATA, residue); - - /* Again update before writing to FIFO to make sure isr sees. */ - i2c->residue = 0; - i2c->cur_trans = NULL; - } else { - zx2967_i2c_writesb(i2c, buf, REG_DATA, I2C_FIFO_MAX); - i2c->residue -= I2C_FIFO_MAX; - i2c->cur_trans += I2C_FIFO_MAX; - } - - barrier(); - - return 0; -} - -static int zx2967_i2c_reset_hardware(struct zx2967_i2c *i2c) -{ - u32 val; - u32 clk_div; - - val = I2C_MASTER | I2C_IRQ_MSK_ENABLE; - zx2967_i2c_writel(i2c, val, REG_CMD); - - clk_div = clk_get_rate(i2c->clk) / i2c->clk_freq - 1; - zx2967_i2c_writel(i2c, clk_div, REG_CLK_DIV_FS); - zx2967_i2c_writel(i2c, clk_div, REG_CLK_DIV_HS); - - zx2967_i2c_writel(i2c, I2C_FIFO_MAX - 1, REG_WRCONF); - zx2967_i2c_writel(i2c, I2C_FIFO_MAX - 1, REG_RDCONF); - zx2967_i2c_writel(i2c, 1, REG_RDCONF); - - zx2967_i2c_flush_fifos(i2c); - - return 0; -} - -static void zx2967_i2c_isr_clr(struct zx2967_i2c *i2c) -{ - u32 status; - - status = zx2967_i2c_readl(i2c, REG_STAT); - status |= I2C_IRQ_ACK_CLEAR; - zx2967_i2c_writel(i2c, status, REG_STAT); -} - -static irqreturn_t zx2967_i2c_isr(int irq, void *dev_id) -{ - u32 status; - struct zx2967_i2c *i2c = (struct zx2967_i2c *)dev_id; - - status = zx2967_i2c_readl(i2c, REG_STAT) & I2C_INT_MASK; - zx2967_i2c_isr_clr(i2c); - - if (status & I2C_SR_EDEVICE) - i2c->error = -ENXIO; - else if (status & I2C_SR_EDATA) - i2c->error = -EIO; - else if (status & I2C_TRANS_DONE) - i2c->error = 0; - else - goto done; - - complete(&i2c->complete); -done: - return IRQ_HANDLED; -} - -static void zx2967_set_addr(struct zx2967_i2c *i2c, u16 addr) -{ - u16 val; - - val = (addr >> I2C_ADDR_LOW_SHIFT) & I2C_ADDR_LOW_MASK; - zx2967_i2c_writel(i2c, val, REG_DEVADDR_L); - - val = (addr >> I2C_ADDR_HI_SHIFT) & I2C_ADDR_HI_MASK; - zx2967_i2c_writel(i2c, val, REG_DEVADDR_H); - if (val) - val = zx2967_i2c_readl(i2c, REG_CMD) | I2C_ADDR_MODE_TEN; - else - val = zx2967_i2c_readl(i2c, REG_CMD) & ~I2C_ADDR_MODE_TEN; - zx2967_i2c_writel(i2c, val, REG_CMD); -} - -static int zx2967_i2c_xfer_bytes(struct zx2967_i2c *i2c, u32 bytes) -{ - unsigned long time_left; - int rd = i2c->msg_rd; - int ret; - - reinit_completion(&i2c->complete); - - if (rd) { - zx2967_i2c_writel(i2c, bytes - 1, REG_RDCONF); - } else { - ret = zx2967_i2c_fill_tx_fifo(i2c); - if (ret) - return ret; - } - - zx2967_i2c_start_ctrl(i2c); - - time_left = wait_for_completion_timeout(&i2c->complete, - I2C_TIMEOUT); - if (time_left == 0) - return -ETIMEDOUT; - - if (i2c->error) - return i2c->error; - - return rd ? zx2967_i2c_empty_rx_fifo(i2c, bytes) : 0; -} - -static int zx2967_i2c_xfer_msg(struct zx2967_i2c *i2c, - struct i2c_msg *msg) -{ - int ret; - int i; - - zx2967_i2c_flush_fifos(i2c); - - i2c->cur_trans = msg->buf; - i2c->residue = msg->len; - i2c->access_cnt = msg->len / I2C_FIFO_MAX; - i2c->msg_rd = msg->flags & I2C_M_RD; - - for (i = 0; i < i2c->access_cnt; i++) { - ret = zx2967_i2c_xfer_bytes(i2c, I2C_FIFO_MAX); - if (ret) - return ret; - } - - if (i2c->residue > 0) { - ret = zx2967_i2c_xfer_bytes(i2c, i2c->residue); - if (ret) - return ret; - } - - i2c->residue = 0; - i2c->access_cnt = 0; - - return 0; -} - -static int zx2967_i2c_xfer(struct i2c_adapter *adap, - struct i2c_msg *msgs, int num) -{ - struct zx2967_i2c *i2c = i2c_get_adapdata(adap); - int ret; - int i; - - zx2967_set_addr(i2c, msgs->addr); - - for (i = 0; i < num; i++) { - ret = zx2967_i2c_xfer_msg(i2c, &msgs[i]); - if (ret) - return ret; - } - - return num; -} - -static void -zx2967_smbus_xfer_prepare(struct zx2967_i2c *i2c, u16 addr, - char read_write, u8 command, int size, - union i2c_smbus_data *data) -{ - u32 val; - - val = zx2967_i2c_readl(i2c, REG_RDCONF); - val |= I2C_RFIFO_RESET; - zx2967_i2c_writel(i2c, val, REG_RDCONF); - zx2967_set_addr(i2c, addr); - val = zx2967_i2c_readl(i2c, REG_CMD); - val &= ~I2C_RW_READ; - zx2967_i2c_writel(i2c, val, REG_CMD); - - switch (size) { - case I2C_SMBUS_BYTE: - zx2967_i2c_writel(i2c, command, REG_DATA); - break; - case I2C_SMBUS_BYTE_DATA: - zx2967_i2c_writel(i2c, command, REG_DATA); - if (read_write == I2C_SMBUS_WRITE) - zx2967_i2c_writel(i2c, data->byte, REG_DATA); - break; - case I2C_SMBUS_WORD_DATA: - zx2967_i2c_writel(i2c, command, REG_DATA); - if (read_write == I2C_SMBUS_WRITE) { - zx2967_i2c_writel(i2c, (data->word >> 8), REG_DATA); - zx2967_i2c_writel(i2c, (data->word & 0xff), - REG_DATA); - } - break; - } -} - -static int zx2967_smbus_xfer_read(struct zx2967_i2c *i2c, int size, - union i2c_smbus_data *data) -{ - unsigned long time_left; - u8 buf[2]; - u32 val; - - reinit_completion(&i2c->complete); - - val = zx2967_i2c_readl(i2c, REG_CMD); - val |= I2C_CMB_RW_EN; - zx2967_i2c_writel(i2c, val, REG_CMD); - - val = zx2967_i2c_readl(i2c, REG_CMD); - val |= I2C_START; - zx2967_i2c_writel(i2c, val, REG_CMD); - - time_left = wait_for_completion_timeout(&i2c->complete, - I2C_TIMEOUT); - if (time_left == 0) - return -ETIMEDOUT; - - if (i2c->error) - return i2c->error; - - switch (size) { - case I2C_SMBUS_BYTE: - case I2C_SMBUS_BYTE_DATA: - val = zx2967_i2c_readl(i2c, REG_DATA); - data->byte = val; - break; - case I2C_SMBUS_WORD_DATA: - case I2C_SMBUS_PROC_CALL: - buf[0] = zx2967_i2c_readl(i2c, REG_DATA); - buf[1] = zx2967_i2c_readl(i2c, REG_DATA); - data->word = (buf[0] << 8) | buf[1]; - break; - default: - return -EOPNOTSUPP; - } - - return 0; -} - -static int zx2967_smbus_xfer_write(struct zx2967_i2c *i2c) -{ - unsigned long time_left; - u32 val; - - reinit_completion(&i2c->complete); - val = zx2967_i2c_readl(i2c, REG_CMD); - val |= I2C_START; - zx2967_i2c_writel(i2c, val, REG_CMD); - - time_left = wait_for_completion_timeout(&i2c->complete, - I2C_TIMEOUT); - if (time_left == 0) - return -ETIMEDOUT; - - if (i2c->error) - return i2c->error; - - return 0; -} - -static int zx2967_smbus_xfer(struct i2c_adapter *adap, u16 addr, - unsigned short flags, char read_write, - u8 command, int size, union i2c_smbus_data *data) -{ - struct zx2967_i2c *i2c = i2c_get_adapdata(adap); - - if (size == I2C_SMBUS_QUICK) - read_write = I2C_SMBUS_WRITE; - - switch (size) { - case I2C_SMBUS_QUICK: - case I2C_SMBUS_BYTE: - case I2C_SMBUS_BYTE_DATA: - case I2C_SMBUS_WORD_DATA: - zx2967_smbus_xfer_prepare(i2c, addr, read_write, - command, size, data); - break; - default: - return -EOPNOTSUPP; - } - - if (read_write == I2C_SMBUS_READ) - return zx2967_smbus_xfer_read(i2c, size, data); - - return zx2967_smbus_xfer_write(i2c); -} - -static u32 zx2967_i2c_func(struct i2c_adapter *adap) -{ - return I2C_FUNC_I2C | - I2C_FUNC_SMBUS_QUICK | - I2C_FUNC_SMBUS_BYTE | - I2C_FUNC_SMBUS_BYTE_DATA | - I2C_FUNC_SMBUS_WORD_DATA | - I2C_FUNC_SMBUS_BLOCK_DATA | - I2C_FUNC_SMBUS_PROC_CALL | - I2C_FUNC_SMBUS_I2C_BLOCK; -} - -static int __maybe_unused zx2967_i2c_suspend(struct device *dev) -{ - struct zx2967_i2c *i2c = dev_get_drvdata(dev); - - i2c_mark_adapter_suspended(&i2c->adap); - clk_disable_unprepare(i2c->clk); - - return 0; -} - -static int __maybe_unused zx2967_i2c_resume(struct device *dev) -{ - struct zx2967_i2c *i2c = dev_get_drvdata(dev); - - clk_prepare_enable(i2c->clk); - i2c_mark_adapter_resumed(&i2c->adap); - - return 0; -} - -static SIMPLE_DEV_PM_OPS(zx2967_i2c_dev_pm_ops, - zx2967_i2c_suspend, zx2967_i2c_resume); - -static const struct i2c_algorithm zx2967_i2c_algo = { - .master_xfer = zx2967_i2c_xfer, - .smbus_xfer = zx2967_smbus_xfer, - .functionality = zx2967_i2c_func, -}; - -static const struct i2c_adapter_quirks zx2967_i2c_quirks = { - .flags = I2C_AQ_NO_ZERO_LEN, -}; - -static const struct of_device_id zx2967_i2c_of_match[] = { - { .compatible = "zte,zx296718-i2c", }, - { }, -}; -MODULE_DEVICE_TABLE(of, zx2967_i2c_of_match); - -static int zx2967_i2c_probe(struct platform_device *pdev) -{ - struct zx2967_i2c *i2c; - void __iomem *reg_base; - struct clk *clk; - int ret; - - i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL); - if (!i2c) - return -ENOMEM; - - reg_base = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(reg_base)) - return PTR_ERR(reg_base); - - clk = devm_clk_get(&pdev->dev, NULL); - if (IS_ERR(clk)) { - dev_err(&pdev->dev, "missing controller clock"); - return PTR_ERR(clk); - } - - ret = clk_prepare_enable(clk); - if (ret) { - dev_err(&pdev->dev, "failed to enable i2c_clk\n"); - return ret; - } - - ret = device_property_read_u32(&pdev->dev, "clock-frequency", - &i2c->clk_freq); - if (ret) { - dev_err(&pdev->dev, "missing clock-frequency"); - return ret; - } - - ret = platform_get_irq(pdev, 0); - if (ret < 0) - return ret; - - i2c->irq = ret; - i2c->reg_base = reg_base; - i2c->clk = clk; - - init_completion(&i2c->complete); - platform_set_drvdata(pdev, i2c); - - ret = zx2967_i2c_reset_hardware(i2c); - if (ret) { - dev_err(&pdev->dev, "failed to initialize i2c controller\n"); - goto err_clk_unprepare; - } - - ret = devm_request_irq(&pdev->dev, i2c->irq, - zx2967_i2c_isr, 0, dev_name(&pdev->dev), i2c); - if (ret) { - dev_err(&pdev->dev, "failed to request irq %i\n", i2c->irq); - goto err_clk_unprepare; - } - - i2c_set_adapdata(&i2c->adap, i2c); - strlcpy(i2c->adap.name, "zx2967 i2c adapter", - sizeof(i2c->adap.name)); - i2c->adap.algo = &zx2967_i2c_algo; - i2c->adap.quirks = &zx2967_i2c_quirks; - i2c->adap.nr = pdev->id; - i2c->adap.dev.parent = &pdev->dev; - i2c->adap.dev.of_node = pdev->dev.of_node; - - ret = i2c_add_numbered_adapter(&i2c->adap); - if (ret) - goto err_clk_unprepare; - - return 0; - -err_clk_unprepare: - clk_disable_unprepare(i2c->clk); - return ret; -} - -static int zx2967_i2c_remove(struct platform_device *pdev) -{ - struct zx2967_i2c *i2c = platform_get_drvdata(pdev); - - i2c_del_adapter(&i2c->adap); - clk_disable_unprepare(i2c->clk); - - return 0; -} - -static struct platform_driver zx2967_i2c_driver = { - .probe = zx2967_i2c_probe, - .remove = zx2967_i2c_remove, - .driver = { - .name = "zx2967_i2c", - .of_match_table = zx2967_i2c_of_match, - .pm = &zx2967_i2c_dev_pm_ops, - }, -}; -module_platform_driver(zx2967_i2c_driver); - -MODULE_AUTHOR("Baoyou Xie <baoyou.xie@linaro.org>"); -MODULE_DESCRIPTION("ZTE ZX2967 I2C Bus Controller driver"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/i2c/i2c-core-acpi.c b/drivers/i2c/i2c-core-acpi.c index 37c510d9347a..8ceaa88dd78f 100644 --- a/drivers/i2c/i2c-core-acpi.c +++ b/drivers/i2c/i2c-core-acpi.c @@ -225,12 +225,8 @@ static void i2c_acpi_register_device(struct i2c_adapter *adapter, adev->power.flags.ignore_parent = true; acpi_device_set_enumerated(adev); - if (IS_ERR(i2c_new_client_device(adapter, info))) { + if (IS_ERR(i2c_new_client_device(adapter, info))) adev->power.flags.ignore_parent = false; - dev_err(&adapter->dev, - "failed to add I2C device %s from ACPI\n", - dev_name(&adev->dev)); - } } static acpi_status i2c_acpi_add_device(acpi_handle handle, u32 level, diff --git a/drivers/i2c/i2c-core-smbus.c b/drivers/i2c/i2c-core-smbus.c index f5c9787992e9..d2d32c0fd8c3 100644 --- a/drivers/i2c/i2c-core-smbus.c +++ b/drivers/i2c/i2c-core-smbus.c @@ -323,8 +323,7 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter *adapter, u16 addr, */ unsigned char msgbuf0[I2C_SMBUS_BLOCK_MAX+3]; unsigned char msgbuf1[I2C_SMBUS_BLOCK_MAX+2]; - int num = read_write == I2C_SMBUS_READ ? 2 : 1; - int i; + int nmsgs = read_write == I2C_SMBUS_READ ? 2 : 1; u8 partial_pec = 0; int status; struct i2c_msg msg[2] = { @@ -340,6 +339,8 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter *adapter, u16 addr, .buf = msgbuf1, }, }; + bool wants_pec = ((flags & I2C_CLIENT_PEC) && size != I2C_SMBUS_QUICK + && size != I2C_SMBUS_I2C_BLOCK_DATA); msgbuf0[0] = command; switch (size) { @@ -348,13 +349,13 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter *adapter, u16 addr, /* Special case: The read/write field is used as data */ msg[0].flags = flags | (read_write == I2C_SMBUS_READ ? I2C_M_RD : 0); - num = 1; + nmsgs = 1; break; case I2C_SMBUS_BYTE: if (read_write == I2C_SMBUS_READ) { /* Special case: only a read! */ msg[0].flags = I2C_M_RD | flags; - num = 1; + nmsgs = 1; } break; case I2C_SMBUS_BYTE_DATA: @@ -375,7 +376,7 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter *adapter, u16 addr, } break; case I2C_SMBUS_PROC_CALL: - num = 2; /* Special case */ + nmsgs = 2; /* Special case */ read_write = I2C_SMBUS_READ; msg[0].len = 3; msg[1].len = 2; @@ -398,12 +399,11 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter *adapter, u16 addr, } i2c_smbus_try_get_dmabuf(&msg[0], command); - for (i = 1; i < msg[0].len; i++) - msg[0].buf[i] = data->block[i - 1]; + memcpy(msg[0].buf + 1, data->block, msg[0].len - 1); } break; case I2C_SMBUS_BLOCK_PROC_CALL: - num = 2; /* Another special case */ + nmsgs = 2; /* Another special case */ read_write = I2C_SMBUS_READ; if (data->block[0] > I2C_SMBUS_BLOCK_MAX) { dev_err(&adapter->dev, @@ -414,8 +414,7 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter *adapter, u16 addr, msg[0].len = data->block[0] + 2; i2c_smbus_try_get_dmabuf(&msg[0], command); - for (i = 1; i < msg[0].len; i++) - msg[0].buf[i] = data->block[i - 1]; + memcpy(msg[0].buf + 1, data->block, msg[0].len - 1); msg[1].flags |= I2C_M_RECV_LEN; msg[1].len = 1; /* block length will be added by @@ -437,8 +436,7 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter *adapter, u16 addr, msg[0].len = data->block[0] + 1; i2c_smbus_try_get_dmabuf(&msg[0], command); - for (i = 1; i <= data->block[0]; i++) - msg[0].buf[i] = data->block[i]; + memcpy(msg[0].buf + 1, data->block + 1, data->block[0]); } break; default: @@ -446,33 +444,31 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter *adapter, u16 addr, return -EOPNOTSUPP; } - i = ((flags & I2C_CLIENT_PEC) && size != I2C_SMBUS_QUICK - && size != I2C_SMBUS_I2C_BLOCK_DATA); - if (i) { + if (wants_pec) { /* Compute PEC if first message is a write */ if (!(msg[0].flags & I2C_M_RD)) { - if (num == 1) /* Write only */ + if (nmsgs == 1) /* Write only */ i2c_smbus_add_pec(&msg[0]); else /* Write followed by read */ partial_pec = i2c_smbus_msg_pec(0, &msg[0]); } /* Ask for PEC if last message is a read */ - if (msg[num-1].flags & I2C_M_RD) - msg[num-1].len++; + if (msg[nmsgs - 1].flags & I2C_M_RD) + msg[nmsgs - 1].len++; } - status = __i2c_transfer(adapter, msg, num); + status = __i2c_transfer(adapter, msg, nmsgs); if (status < 0) goto cleanup; - if (status != num) { + if (status != nmsgs) { status = -EIO; goto cleanup; } status = 0; /* Check PEC if last message is a read */ - if (i && (msg[num-1].flags & I2C_M_RD)) { - status = i2c_smbus_check_pec(partial_pec, &msg[num-1]); + if (wants_pec && (msg[nmsgs - 1].flags & I2C_M_RD)) { + status = i2c_smbus_check_pec(partial_pec, &msg[nmsgs - 1]); if (status < 0) goto cleanup; } @@ -490,8 +486,7 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter *adapter, u16 addr, data->word = msgbuf1[0] | (msgbuf1[1] << 8); break; case I2C_SMBUS_I2C_BLOCK_DATA: - for (i = 0; i < data->block[0]; i++) - data->block[i + 1] = msg[1].buf[i]; + memcpy(data->block + 1, msg[1].buf, data->block[0]); break; case I2C_SMBUS_BLOCK_DATA: case I2C_SMBUS_BLOCK_PROC_CALL: @@ -502,8 +497,7 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter *adapter, u16 addr, status = -EPROTO; goto cleanup; } - for (i = 0; i < msg[1].buf[0] + 1; i++) - data->block[i] = msg[1].buf[i]; + memcpy(data->block, msg[1].buf, msg[1].buf[0] + 1); break; } diff --git a/drivers/i2c/i2c-slave-testunit.c b/drivers/i2c/i2c-slave-testunit.c index c288102de324..56dae08dfd48 100644 --- a/drivers/i2c/i2c-slave-testunit.c +++ b/drivers/i2c/i2c-slave-testunit.c @@ -19,6 +19,7 @@ enum testunit_cmds { TU_CMD_READ_BYTES = 1, /* save 0 for ABORT, RESET or similar */ TU_CMD_HOST_NOTIFY, + TU_CMD_SMBUS_BLOCK_PROC_CALL, TU_NUM_CMDS }; @@ -88,6 +89,8 @@ static int i2c_slave_testunit_slave_cb(struct i2c_client *client, enum i2c_slave_event event, u8 *val) { struct testunit_data *tu = i2c_get_clientdata(client); + bool is_proc_call = tu->reg_idx == 3 && tu->regs[TU_REG_DATAL] == 1 && + tu->regs[TU_REG_CMD] == TU_CMD_SMBUS_BLOCK_PROC_CALL; int ret = 0; switch (event) { @@ -118,12 +121,17 @@ static int i2c_slave_testunit_slave_cb(struct i2c_client *client, fallthrough; case I2C_SLAVE_WRITE_REQUESTED: + memset(tu->regs, 0, TU_NUM_REGS); tu->reg_idx = 0; break; - case I2C_SLAVE_READ_REQUESTED: case I2C_SLAVE_READ_PROCESSED: - *val = TU_CUR_VERSION; + if (is_proc_call && tu->regs[TU_REG_DATAH]) + tu->regs[TU_REG_DATAH]--; + fallthrough; + + case I2C_SLAVE_READ_REQUESTED: + *val = is_proc_call ? tu->regs[TU_REG_DATAH] : TU_CUR_VERSION; break; } diff --git a/drivers/i2c/i2c-stub.c b/drivers/i2c/i2c-stub.c index 537a598e22db..d642cad219d9 100644 --- a/drivers/i2c/i2c-stub.c +++ b/drivers/i2c/i2c-stub.c @@ -7,7 +7,6 @@ */ -#define DEBUG 1 #define pr_fmt(fmt) "i2c-stub: " fmt #include <linux/errno.h> diff --git a/drivers/i2c/muxes/i2c-mux-gpio.c b/drivers/i2c/muxes/i2c-mux-gpio.c index 4effe563e9e8..bac415a52b78 100644 --- a/drivers/i2c/muxes/i2c-mux-gpio.c +++ b/drivers/i2c/muxes/i2c-mux-gpio.c @@ -49,60 +49,112 @@ static int i2c_mux_gpio_deselect(struct i2c_mux_core *muxc, u32 chan) return 0; } -#ifdef CONFIG_OF -static int i2c_mux_gpio_probe_dt(struct gpiomux *mux, - struct platform_device *pdev) +#ifdef CONFIG_ACPI + +static int i2c_mux_gpio_get_acpi_adr(struct device *dev, + struct fwnode_handle *fwdev, + unsigned int *adr) + +{ + unsigned long long adr64; + acpi_status status; + + status = acpi_evaluate_integer(ACPI_HANDLE_FWNODE(fwdev), + METHOD_NAME__ADR, + NULL, &adr64); + + if (!ACPI_SUCCESS(status)) { + dev_err(dev, "Cannot get address\n"); + return -EINVAL; + } + + *adr = adr64; + if (*adr != adr64) { + dev_err(dev, "Address out of range\n"); + return -ERANGE; + } + + return 0; +} + +#else + +static int i2c_mux_gpio_get_acpi_adr(struct device *dev, + struct fwnode_handle *fwdev, + unsigned int *adr) +{ + return -EINVAL; +} + +#endif + +static int i2c_mux_gpio_probe_fw(struct gpiomux *mux, + struct platform_device *pdev) { - struct device_node *np = pdev->dev.of_node; - struct device_node *adapter_np, *child; - struct i2c_adapter *adapter; + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + struct device_node *adapter_np; + struct i2c_adapter *adapter = NULL; + struct fwnode_handle *child; unsigned *values; - int i = 0; + int rc, i = 0; + + if (is_of_node(dev->fwnode)) { + if (!np) + return -ENODEV; - if (!np) - return -ENODEV; + adapter_np = of_parse_phandle(np, "i2c-parent", 0); + if (!adapter_np) { + dev_err(&pdev->dev, "Cannot parse i2c-parent\n"); + return -ENODEV; + } + adapter = of_find_i2c_adapter_by_node(adapter_np); + of_node_put(adapter_np); + + } else if (is_acpi_node(dev->fwnode)) { + /* + * In ACPI land the mux should be a direct child of the i2c + * bus it muxes. + */ + acpi_handle dev_handle = ACPI_HANDLE(dev->parent); - adapter_np = of_parse_phandle(np, "i2c-parent", 0); - if (!adapter_np) { - dev_err(&pdev->dev, "Cannot parse i2c-parent\n"); - return -ENODEV; + adapter = i2c_acpi_find_adapter_by_handle(dev_handle); } - adapter = of_find_i2c_adapter_by_node(adapter_np); - of_node_put(adapter_np); + if (!adapter) return -EPROBE_DEFER; mux->data.parent = i2c_adapter_id(adapter); put_device(&adapter->dev); - mux->data.n_values = of_get_child_count(np); - - values = devm_kcalloc(&pdev->dev, + mux->data.n_values = device_get_child_node_count(dev); + values = devm_kcalloc(dev, mux->data.n_values, sizeof(*mux->data.values), GFP_KERNEL); if (!values) { - dev_err(&pdev->dev, "Cannot allocate values array"); + dev_err(dev, "Cannot allocate values array"); return -ENOMEM; } - for_each_child_of_node(np, child) { - of_property_read_u32(child, "reg", values + i); + device_for_each_child_node(dev, child) { + if (is_of_node(child)) { + fwnode_property_read_u32(child, "reg", values + i); + + } else if (is_acpi_node(child)) { + rc = i2c_mux_gpio_get_acpi_adr(dev, child, values + i); + if (rc) + return rc; + } + i++; } mux->data.values = values; - if (of_property_read_u32(np, "idle-state", &mux->data.idle)) + if (fwnode_property_read_u32(dev->fwnode, "idle-state", &mux->data.idle)) mux->data.idle = I2C_MUX_GPIO_NO_IDLE; return 0; } -#else -static int i2c_mux_gpio_probe_dt(struct gpiomux *mux, - struct platform_device *pdev) -{ - return 0; -} -#endif static int i2c_mux_gpio_probe(struct platform_device *pdev) { @@ -118,7 +170,7 @@ static int i2c_mux_gpio_probe(struct platform_device *pdev) return -ENOMEM; if (!dev_get_platdata(&pdev->dev)) { - ret = i2c_mux_gpio_probe_dt(mux, pdev); + ret = i2c_mux_gpio_probe_fw(mux, pdev); if (ret < 0) return ret; } else { diff --git a/drivers/i2c/muxes/i2c-mux-mlxcpld.c b/drivers/i2c/muxes/i2c-mux-mlxcpld.c index 5ed55ca4fe93..1a879f6a31ef 100644 --- a/drivers/i2c/muxes/i2c-mux-mlxcpld.c +++ b/drivers/i2c/muxes/i2c-mux-mlxcpld.c @@ -1,35 +1,8 @@ +// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 /* - * drivers/i2c/muxes/i2c-mux-mlxcpld.c - * Copyright (c) 2016 Mellanox Technologies. All rights reserved. - * Copyright (c) 2016 Michael Shych <michaels@mellanox.com> + * Mellanox i2c mux driver * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the names of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. + * Copyright (C) 2016-2020 Mellanox Technologies */ #include <linux/device.h> @@ -38,19 +11,19 @@ #include <linux/io.h> #include <linux/init.h> #include <linux/module.h> -#include <linux/platform_data/x86/mlxcpld.h> +#include <linux/platform_data/mlxcpld.h> #include <linux/platform_device.h> #include <linux/slab.h> -#define CPLD_MUX_MAX_NCHANS 8 - /* mlxcpld_mux - mux control structure: - * @last_chan - last register value + * @last_val - last selected register value or -1 if mux deselected * @client - I2C device client + * @pdata: platform data */ struct mlxcpld_mux { - u8 last_chan; + int last_val; struct i2c_client *client; + struct mlxcpld_mux_plat_data pdata; }; /* MUX logic description. @@ -81,37 +54,50 @@ struct mlxcpld_mux { * */ -static const struct i2c_device_id mlxcpld_mux_id[] = { - { "mlxcpld_mux_module", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, mlxcpld_mux_id); - /* Write to mux register. Don't use i2c_transfer() and i2c_smbus_xfer() * for this as they will try to lock adapter a second time. */ static int mlxcpld_mux_reg_write(struct i2c_adapter *adap, - struct i2c_client *client, u8 val) + struct mlxcpld_mux *mux, u32 val) { - struct mlxcpld_mux_plat_data *pdata = dev_get_platdata(&client->dev); - union i2c_smbus_data data = { .byte = val }; - - return __i2c_smbus_xfer(adap, client->addr, client->flags, - I2C_SMBUS_WRITE, pdata->sel_reg_addr, - I2C_SMBUS_BYTE_DATA, &data); + struct i2c_client *client = mux->client; + union i2c_smbus_data data; + struct i2c_msg msg; + u8 buf[3]; + + switch (mux->pdata.reg_size) { + case 1: + data.byte = val; + return __i2c_smbus_xfer(adap, client->addr, client->flags, + I2C_SMBUS_WRITE, mux->pdata.sel_reg_addr, + I2C_SMBUS_BYTE_DATA, &data); + case 2: + buf[0] = mux->pdata.sel_reg_addr >> 8; + buf[1] = mux->pdata.sel_reg_addr; + buf[2] = val; + msg.addr = client->addr; + msg.buf = buf; + msg.len = mux->pdata.reg_size + 1; + msg.flags = 0; + return __i2c_transfer(adap, &msg, 1); + default: + return -EINVAL; + } } static int mlxcpld_mux_select_chan(struct i2c_mux_core *muxc, u32 chan) { - struct mlxcpld_mux *data = i2c_mux_priv(muxc); - struct i2c_client *client = data->client; - u8 regval = chan + 1; + struct mlxcpld_mux *mux = i2c_mux_priv(muxc); + u32 regval = chan; int err = 0; + if (mux->pdata.reg_size == 1) + regval += 1; + /* Only select the channel if its different from the last channel */ - if (data->last_chan != regval) { - err = mlxcpld_mux_reg_write(muxc->parent, client, regval); - data->last_chan = err < 0 ? 0 : regval; + if (mux->last_val != regval) { + err = mlxcpld_mux_reg_write(muxc->parent, mux, regval); + mux->last_val = err < 0 ? -1 : regval; } return err; @@ -119,56 +105,64 @@ static int mlxcpld_mux_select_chan(struct i2c_mux_core *muxc, u32 chan) static int mlxcpld_mux_deselect(struct i2c_mux_core *muxc, u32 chan) { - struct mlxcpld_mux *data = i2c_mux_priv(muxc); - struct i2c_client *client = data->client; + struct mlxcpld_mux *mux = i2c_mux_priv(muxc); /* Deselect active channel */ - data->last_chan = 0; + mux->last_val = -1; - return mlxcpld_mux_reg_write(muxc->parent, client, data->last_chan); + return mlxcpld_mux_reg_write(muxc->parent, mux, 0); } /* Probe/reomove functions */ -static int mlxcpld_mux_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int mlxcpld_mux_probe(struct platform_device *pdev) { - struct i2c_adapter *adap = client->adapter; - struct mlxcpld_mux_plat_data *pdata = dev_get_platdata(&client->dev); + struct mlxcpld_mux_plat_data *pdata = dev_get_platdata(&pdev->dev); + struct i2c_client *client = to_i2c_client(pdev->dev.parent); struct i2c_mux_core *muxc; - int num, force; struct mlxcpld_mux *data; - int err; + int num, err; + u32 func; if (!pdata) return -EINVAL; - if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) + switch (pdata->reg_size) { + case 1: + func = I2C_FUNC_SMBUS_WRITE_BYTE_DATA; + break; + case 2: + func = I2C_FUNC_I2C; + break; + default: + return -EINVAL; + } + + if (!i2c_check_functionality(client->adapter, func)) return -ENODEV; - muxc = i2c_mux_alloc(adap, &client->dev, CPLD_MUX_MAX_NCHANS, + muxc = i2c_mux_alloc(client->adapter, &pdev->dev, pdata->num_adaps, sizeof(*data), 0, mlxcpld_mux_select_chan, mlxcpld_mux_deselect); if (!muxc) return -ENOMEM; + platform_set_drvdata(pdev, muxc); data = i2c_mux_priv(muxc); - i2c_set_clientdata(client, muxc); data->client = client; - data->last_chan = 0; /* force the first selection */ + memcpy(&data->pdata, pdata, sizeof(*pdata)); + data->last_val = -1; /* force the first selection */ /* Create an adapter for each channel. */ - for (num = 0; num < CPLD_MUX_MAX_NCHANS; num++) { - if (num >= pdata->num_adaps) - /* discard unconfigured channels */ - break; - - force = pdata->adap_ids[num]; - - err = i2c_mux_add_adapter(muxc, force, num, 0); + for (num = 0; num < pdata->num_adaps; num++) { + err = i2c_mux_add_adapter(muxc, 0, pdata->chan_ids[num], 0); if (err) goto virt_reg_failed; } + /* Notify caller when all channels' adapters are created. */ + if (pdata->completion_notify) + pdata->completion_notify(pdata->handle, muxc->parent, muxc->adapter); + return 0; virt_reg_failed: @@ -176,24 +170,23 @@ virt_reg_failed: return err; } -static int mlxcpld_mux_remove(struct i2c_client *client) +static int mlxcpld_mux_remove(struct platform_device *pdev) { - struct i2c_mux_core *muxc = i2c_get_clientdata(client); + struct i2c_mux_core *muxc = platform_get_drvdata(pdev); i2c_mux_del_adapters(muxc); return 0; } -static struct i2c_driver mlxcpld_mux_driver = { - .driver = { - .name = "mlxcpld-mux", +static struct platform_driver mlxcpld_mux_driver = { + .driver = { + .name = "i2c-mux-mlxcpld", }, - .probe = mlxcpld_mux_probe, - .remove = mlxcpld_mux_remove, - .id_table = mlxcpld_mux_id, + .probe = mlxcpld_mux_probe, + .remove = mlxcpld_mux_remove, }; -module_i2c_driver(mlxcpld_mux_driver); +module_platform_driver(mlxcpld_mux_driver); MODULE_AUTHOR("Michael Shych (michaels@mellanox.com)"); MODULE_DESCRIPTION("Mellanox I2C-CPLD-MUX driver"); |