diff options
Diffstat (limited to 'drivers/i2c')
57 files changed, 2741 insertions, 1036 deletions
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index ceb3ecdf884b..83c88c79afe2 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -503,7 +503,7 @@ config I2C_BRCMSTB tristate "BRCM Settop/DSL I2C controller" depends on ARCH_BCM2835 || ARCH_BCMBCA || ARCH_BRCMSTB || \ BMIPS_GENERIC || COMPILE_TEST - default y + default ARCH_BCM2835 || ARCH_BCMBCA || ARCH_BRCMSTB || BMIPS_GENERIC help If you say yes to this option, support will be included for the I2C interface on the Broadcom Settop/DSL SoCs. @@ -756,6 +756,7 @@ config I2C_IMX config I2C_IMX_LPI2C tristate "IMX Low Power I2C interface" depends on ARCH_MXC || COMPILE_TEST + select I2C_SLAVE help Say Y here if you want to use the Low Power IIC bus controller on the Freescale i.MX processors. @@ -782,6 +783,23 @@ config I2C_JZ4780 If you don't know what to do here, say N. +config I2C_K1 + tristate "SpacemiT K1 I2C adapter" + depends on ARCH_SPACEMIT || COMPILE_TEST + depends on OF + help + This option enables support for the I2C interface on the SpacemiT K1 + platform. + + If you enable this configuration, the kernel will include support for + the I2C adapter specific to the SpacemiT K1 platform. This driver can + be used to manage I2C bus transactions, which are necessary for + interfacing with I2C peripherals such as sensors, EEPROMs, and other + devices. + + This driver can also be built as a module. If so, the + module will be called `i2c-k1`. + config I2C_KEBA tristate "KEBA I2C controller support" depends on HAS_IOMEM @@ -910,7 +928,7 @@ config I2C_MXS config I2C_NOMADIK tristate "ST-Ericsson Nomadik/Ux500 I2C Controller" - depends on ARM_AMBA + depends on ARM_AMBA || COMPILE_TEST help If you say yes to this option, support will be included for the I2C interface from ST-Ericsson's Nomadik and Ux500 architectures, @@ -939,6 +957,7 @@ config I2C_OMAP tristate "OMAP I2C adapter" depends on ARCH_OMAP || ARCH_K3 || COMPILE_TEST default MACH_OMAP_OSK + select MULTIPLEXER help If you say yes to this option, support will be included for the I2C interface on the Texas Instruments OMAP1/2 family of processors. diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index 1c2a4510abe4..c1252e2b779e 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -74,6 +74,7 @@ obj-$(CONFIG_I2C_IMX) += i2c-imx.o obj-$(CONFIG_I2C_IMX_LPI2C) += i2c-imx-lpi2c.o obj-$(CONFIG_I2C_IOP3XX) += i2c-iop3xx.o obj-$(CONFIG_I2C_JZ4780) += i2c-jz4780.o +obj-$(CONFIG_I2C_K1) += i2c-k1.o obj-$(CONFIG_I2C_KEBA) += i2c-keba.o obj-$(CONFIG_I2C_KEMPLD) += i2c-kempld.o obj-$(CONFIG_I2C_LPC2K) += i2c-lpc2k.o diff --git a/drivers/i2c/busses/i2c-ali1535.c b/drivers/i2c/busses/i2c-ali1535.c index 544c94e86b89..1eac35838040 100644 --- a/drivers/i2c/busses/i2c-ali1535.c +++ b/drivers/i2c/busses/i2c-ali1535.c @@ -485,6 +485,8 @@ MODULE_DEVICE_TABLE(pci, ali1535_ids); static int ali1535_probe(struct pci_dev *dev, const struct pci_device_id *id) { + int ret; + if (ali1535_setup(dev)) { dev_warn(&dev->dev, "ALI1535 not detected, module not inserted.\n"); @@ -496,7 +498,15 @@ static int ali1535_probe(struct pci_dev *dev, const struct pci_device_id *id) snprintf(ali1535_adapter.name, sizeof(ali1535_adapter.name), "SMBus ALI1535 adapter at %04x", ali1535_offset); - return i2c_add_adapter(&ali1535_adapter); + ret = i2c_add_adapter(&ali1535_adapter); + if (ret) + goto release_region; + + return 0; + +release_region: + release_region(ali1535_smba, ALI1535_SMB_IOSIZE); + return ret; } static void ali1535_remove(struct pci_dev *dev) diff --git a/drivers/i2c/busses/i2c-ali15x3.c b/drivers/i2c/busses/i2c-ali15x3.c index 4761c7208102..418d11266671 100644 --- a/drivers/i2c/busses/i2c-ali15x3.c +++ b/drivers/i2c/busses/i2c-ali15x3.c @@ -472,6 +472,8 @@ MODULE_DEVICE_TABLE (pci, ali15x3_ids); static int ali15x3_probe(struct pci_dev *dev, const struct pci_device_id *id) { + int ret; + if (ali15x3_setup(dev)) { dev_err(&dev->dev, "ALI15X3 not detected, module not inserted.\n"); @@ -483,7 +485,15 @@ static int ali15x3_probe(struct pci_dev *dev, const struct pci_device_id *id) snprintf(ali15x3_adapter.name, sizeof(ali15x3_adapter.name), "SMBus ALI15X3 adapter at %04x", ali15x3_smba); - return i2c_add_adapter(&ali15x3_adapter); + ret = i2c_add_adapter(&ali15x3_adapter); + if (ret) + goto release_region; + + return 0; + +release_region: + release_region(ali15x3_smba, ALI15X3_SMB_IOSIZE); + return ret; } static void ali15x3_remove(struct pci_dev *dev) diff --git a/drivers/i2c/busses/i2c-amd-asf-plat.c b/drivers/i2c/busses/i2c-amd-asf-plat.c index 93ebec162c6d..ca45f0f23321 100644 --- a/drivers/i2c/busses/i2c-amd-asf-plat.c +++ b/drivers/i2c/busses/i2c-amd-asf-plat.c @@ -69,7 +69,7 @@ static void amd_asf_process_target(struct work_struct *work) /* Check if no error bits are set in target status register */ if (reg & ASF_ERROR_STATUS) { /* Set bank as full */ - cmd = 0; + cmd = 1; reg |= GENMASK(3, 2); outb_p(reg, ASFDATABNKSEL); } else { @@ -272,9 +272,9 @@ static u32 amd_asf_func(struct i2c_adapter *adapter) } static const struct i2c_algorithm amd_asf_smbus_algorithm = { - .master_xfer = amd_asf_xfer, - .reg_slave = amd_asf_reg_target, - .unreg_slave = amd_asf_unreg_target, + .xfer = amd_asf_xfer, + .reg_target = amd_asf_reg_target, + .unreg_target = amd_asf_unreg_target, .functionality = amd_asf_func, }; diff --git a/drivers/i2c/busses/i2c-amd-mp2-pci.c b/drivers/i2c/busses/i2c-amd-mp2-pci.c index 143165300949..ef7370d3dbea 100644 --- a/drivers/i2c/busses/i2c-amd-mp2-pci.c +++ b/drivers/i2c/busses/i2c-amd-mp2-pci.c @@ -327,13 +327,11 @@ static int amd_mp2_pci_init(struct amd_mp2_dev *privdata, amd_mp2_irq_isr, irq_flag, dev_name(&pci_dev->dev), privdata); if (rc) { pci_err(pci_dev, "Failure requesting irq %i: %d\n", privdata->dev_irq, rc); - goto free_irq_vectors; + goto err_dma_mask; } return rc; -free_irq_vectors: - free_irq(privdata->dev_irq, privdata); err_dma_mask: pci_clear_master(pci_dev); err_pci_enable: @@ -376,7 +374,6 @@ static void amd_mp2_pci_remove(struct pci_dev *pci_dev) pm_runtime_forbid(&pci_dev->dev); pm_runtime_get_noresume(&pci_dev->dev); - free_irq(privdata->dev_irq, privdata); pci_clear_master(pci_dev); amd_mp2_clear_reg(privdata); diff --git a/drivers/i2c/busses/i2c-amd756.c b/drivers/i2c/busses/i2c-amd756.c index fa0d5a2c3732..3621c02f1cba 100644 --- a/drivers/i2c/busses/i2c-amd756.c +++ b/drivers/i2c/busses/i2c-amd756.c @@ -211,7 +211,7 @@ static s32 amd756_access(struct i2c_adapter * adap, u16 addr, SMB_HOST_ADDRESS); outb_p(command, SMB_HOST_COMMAND); if (read_write == I2C_SMBUS_WRITE) - outw_p(data->word, SMB_HOST_DATA); /* TODO: endian???? */ + outw_p(data->word, SMB_HOST_DATA); size = AMD756_WORD_DATA; break; case I2C_SMBUS_BLOCK_DATA: @@ -256,7 +256,7 @@ static s32 amd756_access(struct i2c_adapter * adap, u16 addr, data->byte = inw_p(SMB_HOST_DATA); break; case AMD756_WORD_DATA: - data->word = inw_p(SMB_HOST_DATA); /* TODO: endian???? */ + data->word = inw_p(SMB_HOST_DATA); break; case AMD756_BLOCK_DATA: data->block[0] = inw_p(SMB_HOST_DATA) & 0x3f; diff --git a/drivers/i2c/busses/i2c-axxia.c b/drivers/i2c/busses/i2c-axxia.c index 48916cf45ff7..50030256cd85 100644 --- a/drivers/i2c/busses/i2c-axxia.c +++ b/drivers/i2c/busses/i2c-axxia.c @@ -255,11 +255,6 @@ static int i2c_m_rd(const struct i2c_msg *msg) return (msg->flags & I2C_M_RD) != 0; } -static int i2c_m_ten(const struct i2c_msg *msg) -{ - return (msg->flags & I2C_M_TEN) != 0; -} - static int i2c_m_recv_len(const struct i2c_msg *msg) { return (msg->flags & I2C_M_RECV_LEN) != 0; @@ -439,20 +434,10 @@ static void axxia_i2c_set_addr(struct axxia_i2c_dev *idev, struct i2c_msg *msg) { u32 addr_1, addr_2; - if (i2c_m_ten(msg)) { - /* 10-bit address - * addr_1: 5'b11110 | addr[9:8] | (R/nW) - * addr_2: addr[7:0] - */ - addr_1 = 0xF0 | ((msg->addr >> 7) & 0x06); - if (i2c_m_rd(msg)) - addr_1 |= 1; /* Set the R/nW bit of the address */ - addr_2 = msg->addr & 0xFF; + if (msg->flags & I2C_M_TEN) { + addr_1 = i2c_10bit_addr_hi_from_msg(msg); + addr_2 = i2c_10bit_addr_lo_from_msg(msg); } else { - /* 7-bit address - * addr_1: addr[6:0] | (R/nW) - * addr_2: dont care - */ addr_1 = i2c_8bit_addr_from_msg(msg); addr_2 = 0; } diff --git a/drivers/i2c/busses/i2c-bcm-iproc.c b/drivers/i2c/busses/i2c-bcm-iproc.c index 15b632a146e1..332a0fcca28d 100644 --- a/drivers/i2c/busses/i2c-bcm-iproc.c +++ b/drivers/i2c/busses/i2c-bcm-iproc.c @@ -678,7 +678,7 @@ static irqreturn_t bcm_iproc_i2c_isr(int irq, void *data) return IRQ_HANDLED; } -static int bcm_iproc_i2c_init(struct bcm_iproc_i2c_dev *iproc_i2c) +static void bcm_iproc_i2c_init(struct bcm_iproc_i2c_dev *iproc_i2c) { u32 val; @@ -706,8 +706,6 @@ static int bcm_iproc_i2c_init(struct bcm_iproc_i2c_dev *iproc_i2c) /* clear all pending interrupts */ iproc_i2c_wr_reg(iproc_i2c, IS_OFFSET, 0xffffffff); - - return 0; } static void bcm_iproc_i2c_enable_disable(struct bcm_iproc_i2c_dev *iproc_i2c, @@ -1081,9 +1079,7 @@ static int bcm_iproc_i2c_probe(struct platform_device *pdev) bcm_iproc_algo.unreg_slave = NULL; } - ret = bcm_iproc_i2c_init(iproc_i2c); - if (ret) - return ret; + bcm_iproc_i2c_init(iproc_i2c); ret = bcm_iproc_i2c_cfg_speed(iproc_i2c); if (ret) @@ -1162,16 +1158,13 @@ static int bcm_iproc_i2c_suspend(struct device *dev) static int bcm_iproc_i2c_resume(struct device *dev) { struct bcm_iproc_i2c_dev *iproc_i2c = dev_get_drvdata(dev); - int ret; u32 val; /* * Power domain could have been shut off completely in system deep * sleep, so re-initialize the block here */ - ret = bcm_iproc_i2c_init(iproc_i2c); - if (ret) - return ret; + bcm_iproc_i2c_init(iproc_i2c); /* configure to the desired bus speed */ val = iproc_i2c_rd_reg(iproc_i2c, TIM_CFG_OFFSET); diff --git a/drivers/i2c/busses/i2c-bcm-kona.c b/drivers/i2c/busses/i2c-bcm-kona.c index 340fe1305dd9..9d8838bbd938 100644 --- a/drivers/i2c/busses/i2c-bcm-kona.c +++ b/drivers/i2c/busses/i2c-bcm-kona.c @@ -471,12 +471,12 @@ static int bcm_kona_i2c_do_addr(struct bcm_kona_i2c_dev *dev, if (msg->flags & I2C_M_TEN) { /* First byte is 11110XX0 where XX is upper 2 bits */ - addr = 0xF0 | ((msg->addr & 0x300) >> 7); + addr = i2c_10bit_addr_hi_from_msg(msg) & ~I2C_M_RD; if (bcm_kona_i2c_write_byte(dev, addr, 0) < 0) return -EREMOTEIO; /* Second byte is the remaining 8 bits */ - addr = msg->addr & 0xFF; + addr = i2c_10bit_addr_lo_from_msg(msg); if (bcm_kona_i2c_write_byte(dev, addr, 0) < 0) return -EREMOTEIO; @@ -486,7 +486,7 @@ static int bcm_kona_i2c_do_addr(struct bcm_kona_i2c_dev *dev, return -EREMOTEIO; /* Then re-send the first byte with the read bit set */ - addr = 0xF0 | ((msg->addr & 0x300) >> 7) | 0x01; + addr = i2c_10bit_addr_hi_from_msg(msg); if (bcm_kona_i2c_write_byte(dev, addr, 0) < 0) return -EREMOTEIO; } diff --git a/drivers/i2c/busses/i2c-brcmstb.c b/drivers/i2c/busses/i2c-brcmstb.c index 00f1a046e985..5fa30e8926c5 100644 --- a/drivers/i2c/busses/i2c-brcmstb.c +++ b/drivers/i2c/busses/i2c-brcmstb.c @@ -414,23 +414,22 @@ static int brcmstb_i2c_do_addr(struct brcmstb_i2c_dev *dev, if (msg->flags & I2C_M_TEN) { /* First byte is 11110XX0 where XX is upper 2 bits */ - addr = 0xF0 | ((msg->addr & 0x300) >> 7); + addr = i2c_10bit_addr_hi_from_msg(msg) & ~I2C_M_RD; bsc_writel(dev, addr, chip_address); /* Second byte is the remaining 8 bits */ - addr = msg->addr & 0xFF; + addr = i2c_10bit_addr_lo_from_msg(msg); if (brcmstb_i2c_write_data_byte(dev, &addr, 0) < 0) return -EREMOTEIO; if (msg->flags & I2C_M_RD) { /* For read, send restart without stop condition */ - brcmstb_set_i2c_start_stop(dev, COND_RESTART - | COND_NOSTOP); + brcmstb_set_i2c_start_stop(dev, COND_RESTART | COND_NOSTOP); + /* Then re-send the first byte with the read bit set */ - addr = 0xF0 | ((msg->addr & 0x300) >> 7) | 0x01; + addr = i2c_10bit_addr_hi_from_msg(msg); if (brcmstb_i2c_write_data_byte(dev, &addr, 0) < 0) return -EREMOTEIO; - } } else { addr = i2c_8bit_addr_from_msg(msg); diff --git a/drivers/i2c/busses/i2c-cadence.c b/drivers/i2c/busses/i2c-cadence.c index b64026fbca66..8df63aaf2a80 100644 --- a/drivers/i2c/busses/i2c-cadence.c +++ b/drivers/i2c/busses/i2c-cadence.c @@ -1541,7 +1541,7 @@ static int cdns_i2c_probe(struct platform_device *pdev) snprintf(id->adap.name, sizeof(id->adap.name), "Cadence I2C at %08lx", (unsigned long)r_mem->start); - id->clk = devm_clk_get(&pdev->dev, NULL); + id->clk = devm_clk_get_enabled(&pdev->dev, NULL); if (IS_ERR(id->clk)) return dev_err_probe(&pdev->dev, PTR_ERR(id->clk), "input clock not found.\n"); @@ -1551,16 +1551,10 @@ static int cdns_i2c_probe(struct platform_device *pdev) return dev_err_probe(&pdev->dev, PTR_ERR(id->reset), "Failed to request reset.\n"); - ret = clk_prepare_enable(id->clk); - if (ret) - dev_err(&pdev->dev, "Unable to enable clock.\n"); - ret = reset_control_deassert(id->reset); - if (ret) { - dev_err_probe(&pdev->dev, ret, - "Failed to de-assert reset.\n"); - goto err_clk_dis; - } + if (ret) + return dev_err_probe(&pdev->dev, ret, + "Failed to de-assert reset.\n"); pm_runtime_set_autosuspend_delay(id->dev, CNDS_I2C_PM_TIMEOUT); pm_runtime_use_autosuspend(id->dev); @@ -1615,11 +1609,9 @@ static int cdns_i2c_probe(struct platform_device *pdev) err_clk_notifier_unregister: clk_notifier_unregister(id->clk, &id->clk_rate_change_nb); - reset_control_assert(id->reset); -err_clk_dis: - clk_disable_unprepare(id->clk); pm_runtime_disable(&pdev->dev); pm_runtime_set_suspended(&pdev->dev); + reset_control_assert(id->reset); return ret; } @@ -1642,7 +1634,6 @@ static void cdns_i2c_remove(struct platform_device *pdev) i2c_del_adapter(&id->adap); clk_notifier_unregister(id->clk, &id->clk_rate_change_nb); reset_control_assert(id->reset); - clk_disable_unprepare(id->clk); } static struct platform_driver cdns_i2c_drv = { diff --git a/drivers/i2c/busses/i2c-cros-ec-tunnel.c b/drivers/i2c/busses/i2c-cros-ec-tunnel.c index 43bf90d90eeb..208ce4f9e782 100644 --- a/drivers/i2c/busses/i2c-cros-ec-tunnel.c +++ b/drivers/i2c/busses/i2c-cros-ec-tunnel.c @@ -247,6 +247,9 @@ static int ec_i2c_probe(struct platform_device *pdev) u32 remote_bus; int err; + if (!ec) + return dev_err_probe(dev, -EPROBE_DEFER, "couldn't find parent EC device\n"); + if (!ec->cmd_xfer) { dev_err(dev, "Missing sendrecv\n"); return -EINVAL; diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c index 71dc0a6688b7..6a909d339681 100644 --- a/drivers/i2c/busses/i2c-davinci.c +++ b/drivers/i2c/busses/i2c-davinci.c @@ -11,23 +11,23 @@ * * ---------------------------------------------------------------------------- */ -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/delay.h> -#include <linux/i2c.h> + #include <linux/clk.h> -#include <linux/errno.h> -#include <linux/sched.h> +#include <linux/cpufreq.h> +#include <linux/delay.h> #include <linux/err.h> +#include <linux/errno.h> +#include <linux/gpio/consumer.h> +#include <linux/i2c.h> #include <linux/interrupt.h> -#include <linux/platform_device.h> #include <linux/io.h> -#include <linux/slab.h> -#include <linux/cpufreq.h> -#include <linux/gpio/consumer.h> -#include <linux/of.h> -#include <linux/platform_data/i2c-davinci.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/platform_device.h> #include <linux/pm_runtime.h> +#include <linux/property.h> +#include <linux/sched.h> +#include <linux/slab.h> /* ----- global defines ----------------------------------------------- */ @@ -117,6 +117,8 @@ /* timeout for pm runtime autosuspend */ #define DAVINCI_I2C_PM_TIMEOUT 1000 /* ms */ +#define DAVINCI_I2C_DEFAULT_BUS_FREQ 100 + struct davinci_i2c_dev { struct device *dev; void __iomem *base; @@ -132,13 +134,10 @@ struct davinci_i2c_dev { #ifdef CONFIG_CPU_FREQ struct notifier_block freq_transition; #endif - struct davinci_i2c_platform_data *pdata; -}; - -/* default platform data to use if not supplied in the platform_device */ -static struct davinci_i2c_platform_data davinci_i2c_platform_data_default = { - .bus_freq = 100, - .bus_delay = 0, + /* standard bus frequency (kHz) */ + unsigned int bus_freq; + /* Chip has a ICPFUNC register */ + bool has_pfunc; }; static inline void davinci_i2c_write_reg(struct davinci_i2c_dev *i2c_dev, @@ -168,14 +167,12 @@ static inline void davinci_i2c_reset_ctrl(struct davinci_i2c_dev *i2c_dev, static void i2c_davinci_calc_clk_dividers(struct davinci_i2c_dev *dev) { - struct davinci_i2c_platform_data *pdata = dev->pdata; u16 psc; u32 clk; u32 d; u32 clkh; u32 clkl; u32 input_clock = clk_get_rate(dev->clk); - struct device_node *of_node = dev->dev->of_node; /* NOTE: I2C Clock divider programming info * As per I2C specs the following formulas provide prescaler @@ -209,19 +206,19 @@ static void i2c_davinci_calc_clk_dividers(struct davinci_i2c_dev *dev) psc++; /* better to run under spec than over */ d = (psc >= 2) ? 5 : 7 - psc; - if (of_node && of_device_is_compatible(of_node, "ti,keystone-i2c")) + if (device_is_compatible(dev->dev, "ti,keystone-i2c")) d = 6; - clk = ((input_clock / (psc + 1)) / (pdata->bus_freq * 1000)); + clk = ((input_clock / (psc + 1)) / (dev->bus_freq * 1000)); /* Avoid driving the bus too fast because of rounding errors above */ - if (input_clock / (psc + 1) / clk > pdata->bus_freq * 1000) + if (input_clock / (psc + 1) / clk > dev->bus_freq * 1000) clk++; /* * According to I2C-BUS Spec 2.1, in FAST-MODE LOW period should be at * least 1.3uS, which is not the case with 50% duty cycle. Driving HIGH * to LOW ratio as 1 to 2 is more safe. */ - if (pdata->bus_freq > 100) + if (dev->bus_freq > 100) clkl = (clk << 1) / 3; else clkl = (clk >> 1); @@ -255,8 +252,6 @@ static void i2c_davinci_calc_clk_dividers(struct davinci_i2c_dev *dev) */ static int i2c_davinci_init(struct davinci_i2c_dev *dev) { - struct davinci_i2c_platform_data *pdata = dev->pdata; - /* put I2C into reset */ davinci_i2c_reset_ctrl(dev, 0); @@ -274,8 +269,7 @@ static int i2c_davinci_init(struct davinci_i2c_dev *dev) davinci_i2c_read_reg(dev, DAVINCI_I2C_CLKL_REG)); dev_dbg(dev->dev, "CLKH = %d\n", davinci_i2c_read_reg(dev, DAVINCI_I2C_CLKH_REG)); - dev_dbg(dev->dev, "bus_freq = %dkHz, bus_delay = %d\n", - pdata->bus_freq, pdata->bus_delay); + dev_dbg(dev->dev, "bus_freq = %dkHz\n", dev->bus_freq); /* Take the I2C module out of reset: */ @@ -309,12 +303,6 @@ static void davinci_i2c_unprepare_recovery(struct i2c_adapter *adap) i2c_davinci_init(dev); } -static struct i2c_bus_recovery_info davinci_i2c_gpio_recovery_info = { - .recover_bus = i2c_generic_scl_recovery, - .prepare_recovery = davinci_i2c_prepare_recovery, - .unprepare_recovery = davinci_i2c_unprepare_recovery, -}; - static void davinci_i2c_set_scl(struct i2c_adapter *adap, int val) { struct davinci_i2c_dev *dev = i2c_get_adapdata(adap); @@ -414,7 +402,6 @@ static int i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop) { struct davinci_i2c_dev *dev = i2c_get_adapdata(adap); - struct davinci_i2c_platform_data *pdata = dev->pdata; u32 flag; u16 w; unsigned long time_left; @@ -424,10 +411,6 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop) return -EADDRNOTAVAIL; } - /* Introduce a delay, required for some boards (e.g Davinci EVM) */ - if (pdata->bus_delay) - udelay(pdata->bus_delay); - /* set the target address */ davinci_i2c_write_reg(dev, DAVINCI_I2C_SAR_REG, msg->addr); @@ -758,8 +741,8 @@ static int davinci_i2c_probe(struct platform_device *pdev) { struct davinci_i2c_dev *dev; struct i2c_adapter *adap; - struct i2c_bus_recovery_info *rinfo; int r, irq; + u32 prop; irq = platform_get_irq(pdev, 0); if (irq < 0) @@ -773,29 +756,15 @@ static int davinci_i2c_probe(struct platform_device *pdev) dev->dev = &pdev->dev; dev->irq = irq; - dev->pdata = dev_get_platdata(&pdev->dev); platform_set_drvdata(pdev, dev); - if (!dev->pdata && pdev->dev.of_node) { - u32 prop; - - dev->pdata = devm_kzalloc(&pdev->dev, - sizeof(struct davinci_i2c_platform_data), GFP_KERNEL); - if (!dev->pdata) - return -ENOMEM; - - memcpy(dev->pdata, &davinci_i2c_platform_data_default, - sizeof(struct davinci_i2c_platform_data)); - if (!of_property_read_u32(pdev->dev.of_node, "clock-frequency", - &prop)) - dev->pdata->bus_freq = prop / 1000; - - dev->pdata->has_pfunc = - of_property_read_bool(pdev->dev.of_node, - "ti,has-pfunc"); - } else if (!dev->pdata) { - dev->pdata = &davinci_i2c_platform_data_default; - } + r = device_property_read_u32(&pdev->dev, "clock-frequency", &prop); + if (r) + prop = DAVINCI_I2C_DEFAULT_BUS_FREQ; + + dev->bus_freq = prop / 1000; + + dev->has_pfunc = device_property_present(&pdev->dev, "ti,has-pfunc"); dev->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(dev->clk)) @@ -841,25 +810,10 @@ static int davinci_i2c_probe(struct platform_device *pdev) adap->algo = &i2c_davinci_algo; adap->dev.parent = &pdev->dev; adap->timeout = DAVINCI_I2C_TIMEOUT; - adap->dev.of_node = pdev->dev.of_node; + adap->dev.of_node = dev_of_node(&pdev->dev); - if (dev->pdata->has_pfunc) + if (dev->has_pfunc) adap->bus_recovery_info = &davinci_i2c_scl_recovery_info; - else if (dev->pdata->gpio_recovery) { - rinfo = &davinci_i2c_gpio_recovery_info; - adap->bus_recovery_info = rinfo; - rinfo->scl_gpiod = devm_gpiod_get(&pdev->dev, "scl", - GPIOD_OUT_HIGH_OPEN_DRAIN); - if (IS_ERR(rinfo->scl_gpiod)) { - r = PTR_ERR(rinfo->scl_gpiod); - goto err_unuse_clocks; - } - rinfo->sda_gpiod = devm_gpiod_get(&pdev->dev, "sda", GPIOD_IN); - if (IS_ERR(rinfo->sda_gpiod)) { - r = PTR_ERR(rinfo->sda_gpiod); - goto err_unuse_clocks; - } - } adap->nr = pdev->id; r = i2c_add_numbered_adapter(adap); diff --git a/drivers/i2c/busses/i2c-designware-amdpsp.c b/drivers/i2c/busses/i2c-designware-amdpsp.c index 8fbd2a10c31a..404571ad61a8 100644 --- a/drivers/i2c/busses/i2c-designware-amdpsp.c +++ b/drivers/i2c/busses/i2c-designware-amdpsp.c @@ -151,19 +151,16 @@ static void release_bus(void) static void psp_release_i2c_bus_deferred(struct work_struct *work) { - mutex_lock(&psp_i2c_access_mutex); + guard(mutex)(&psp_i2c_access_mutex); /* * If there is any pending transaction, cannot release the bus here. * psp_release_i2c_bus() will take care of this later. */ if (psp_i2c_access_count) - goto cleanup; + return; release_bus(); - -cleanup: - mutex_unlock(&psp_i2c_access_mutex); } static DECLARE_DELAYED_WORK(release_queue, psp_release_i2c_bus_deferred); @@ -171,11 +168,11 @@ static int psp_acquire_i2c_bus(void) { int status; - mutex_lock(&psp_i2c_access_mutex); + guard(mutex)(&psp_i2c_access_mutex); /* Return early if mailbox malfunctioned */ if (psp_i2c_mbox_fail) - goto cleanup; + return 0; psp_i2c_access_count++; @@ -184,11 +181,11 @@ static int psp_acquire_i2c_bus(void) * reservation period. */ if (psp_i2c_sem_acquired) - goto cleanup; + return 0; status = psp_send_i2c_req(PSP_I2C_REQ_ACQUIRE); if (status) - goto cleanup; + return 0; psp_i2c_sem_acquired = jiffies; @@ -201,18 +198,16 @@ static int psp_acquire_i2c_bus(void) * communication with PSP. At any case i2c bus is granted to the caller, * thus always return success. */ -cleanup: - mutex_unlock(&psp_i2c_access_mutex); return 0; } static void psp_release_i2c_bus(void) { - mutex_lock(&psp_i2c_access_mutex); + guard(mutex)(&psp_i2c_access_mutex); /* Return early if mailbox was malfunctioned */ if (psp_i2c_mbox_fail) - goto cleanup; + return; /* * If we are last owner of PSP semaphore, need to release arbitration @@ -220,7 +215,7 @@ static void psp_release_i2c_bus(void) */ psp_i2c_access_count--; if (psp_i2c_access_count) - goto cleanup; + return; /* * Send a release command to PSP if the semaphore reservation timeout @@ -228,9 +223,6 @@ static void psp_release_i2c_bus(void) */ if (!delayed_work_pending(&release_queue)) release_bus(); - -cleanup: - mutex_unlock(&psp_i2c_access_mutex); } /* diff --git a/drivers/i2c/busses/i2c-designware-master.c b/drivers/i2c/busses/i2c-designware-master.c index 2569bf1a72e0..40aa5114bf8c 100644 --- a/drivers/i2c/busses/i2c-designware-master.c +++ b/drivers/i2c/busses/i2c-designware-master.c @@ -363,6 +363,7 @@ static int amd_i2c_dw_xfer_quirk(struct i2c_adapter *adap, struct i2c_msg *msgs, dev->msgs = msgs; dev->msgs_num = num_msgs; + dev->msg_write_idx = 0; i2c_dw_xfer_init(dev); /* Initiate messages read/write transaction */ @@ -907,7 +908,7 @@ done_nolock: } static const struct i2c_algorithm i2c_dw_algo = { - .master_xfer = i2c_dw_xfer, + .xfer = i2c_dw_xfer, .functionality = i2c_dw_func, }; diff --git a/drivers/i2c/busses/i2c-designware-pcidrv.c b/drivers/i2c/busses/i2c-designware-pcidrv.c index 8e0267c7cc29..f21f9877c040 100644 --- a/drivers/i2c/busses/i2c-designware-pcidrv.c +++ b/drivers/i2c/busses/i2c-designware-pcidrv.c @@ -278,9 +278,11 @@ static int i2c_dw_pci_probe(struct pci_dev *pdev, if ((dev->flags & MODEL_MASK) == MODEL_AMD_NAVI_GPU) { dev->slave = i2c_new_ccgx_ucsi(&dev->adapter, dev->irq, &dgpu_node); - if (IS_ERR(dev->slave)) + if (IS_ERR(dev->slave)) { + i2c_del_adapter(&dev->adapter); return dev_err_probe(device, PTR_ERR(dev->slave), "register UCSI failed\n"); + } } pm_runtime_set_autosuspend_delay(device, 1000); diff --git a/drivers/i2c/busses/i2c-designware-slave.c b/drivers/i2c/busses/i2c-designware-slave.c index 5cd4a5f7a472..b936a240db0a 100644 --- a/drivers/i2c/busses/i2c-designware-slave.c +++ b/drivers/i2c/busses/i2c-designware-slave.c @@ -96,7 +96,7 @@ static int i2c_dw_unreg_slave(struct i2c_client *slave) i2c_dw_disable(dev); synchronize_irq(dev->irq); dev->slave = NULL; - pm_runtime_put(dev->dev); + pm_runtime_put_sync_suspend(dev->dev); return 0; } diff --git a/drivers/i2c/busses/i2c-eg20t.c b/drivers/i2c/busses/i2c-eg20t.c index 4914bfbee2a9..efdaddf99f9e 100644 --- a/drivers/i2c/busses/i2c-eg20t.c +++ b/drivers/i2c/busses/i2c-eg20t.c @@ -48,8 +48,6 @@ #define BUS_IDLE_TIMEOUT 20 #define PCH_I2CCTL_I2CMEN 0x0080 -#define TEN_BIT_ADDR_DEFAULT 0xF000 -#define TEN_BIT_ADDR_MASK 0xF0 #define PCH_START 0x0020 #define PCH_RESTART 0x0004 #define PCH_ESR_START 0x0001 @@ -58,7 +56,6 @@ #define PCH_ACK 0x0008 #define PCH_GETACK 0x0001 #define CLR_REG 0x0 -#define I2C_RD 0x1 #define I2CMCF_BIT 0x0080 #define I2CMIF_BIT 0x0002 #define I2CMAL_BIT 0x0010 @@ -76,8 +73,6 @@ #define I2CMBB_BIT 0x0020 #define BUFFER_MODE_MASK (I2CBMFI_BIT | I2CBMAL_BIT | I2CBMNA_BIT | \ I2CBMTO_BIT | I2CBMIS_BIT) -#define I2C_ADDR_MSK 0xFF -#define I2C_MSB_2B_MSK 0x300 #define FAST_MODE_CLK 400 #define FAST_MODE_EN 0x0001 #define SUB_ADDR_LEN_MAX 4 @@ -371,16 +366,12 @@ static s32 pch_i2c_writebytes(struct i2c_adapter *i2c_adap, struct i2c_algo_pch_data *adap = i2c_adap->algo_data; u8 *buf; u32 length; - u32 addr; - u32 addr_2_msb; - u32 addr_8_lsb; s32 wrcount; s32 rtn; void __iomem *p = adap->pch_base_address; length = msgs->len; buf = msgs->buf; - addr = msgs->addr; /* enable master tx */ pch_setbit(adap->pch_base_address, PCH_I2CCTL, I2C_TX_MODE); @@ -394,8 +385,7 @@ static s32 pch_i2c_writebytes(struct i2c_adapter *i2c_adap, } if (msgs->flags & I2C_M_TEN) { - addr_2_msb = ((addr & I2C_MSB_2B_MSK) >> 7) & 0x06; - iowrite32(addr_2_msb | TEN_BIT_ADDR_MASK, p + PCH_I2CDR); + iowrite32(i2c_10bit_addr_hi_from_msg(msgs), p + PCH_I2CDR); if (first) pch_i2c_start(adap); @@ -403,8 +393,7 @@ static s32 pch_i2c_writebytes(struct i2c_adapter *i2c_adap, if (rtn) return rtn; - addr_8_lsb = (addr & I2C_ADDR_MSK); - iowrite32(addr_8_lsb, p + PCH_I2CDR); + iowrite32(i2c_10bit_addr_lo_from_msg(msgs), p + PCH_I2CDR); } else { /* set 7 bit slave address and R/W bit as 0 */ iowrite32(i2c_8bit_addr_from_msg(msgs), p + PCH_I2CDR); @@ -490,15 +479,11 @@ static s32 pch_i2c_readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, u8 *buf; u32 count; u32 length; - u32 addr; - u32 addr_2_msb; - u32 addr_8_lsb; void __iomem *p = adap->pch_base_address; s32 rtn; length = msgs->len; buf = msgs->buf; - addr = msgs->addr; /* enable master reception */ pch_clrbit(adap->pch_base_address, PCH_I2CCTL, I2C_TX_MODE); @@ -509,8 +494,7 @@ static s32 pch_i2c_readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, } if (msgs->flags & I2C_M_TEN) { - addr_2_msb = ((addr & I2C_MSB_2B_MSK) >> 7); - iowrite32(addr_2_msb | TEN_BIT_ADDR_MASK, p + PCH_I2CDR); + iowrite32(i2c_10bit_addr_hi_from_msg(msgs) & ~I2C_M_RD, p + PCH_I2CDR); if (first) pch_i2c_start(adap); @@ -518,8 +502,7 @@ static s32 pch_i2c_readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, if (rtn) return rtn; - addr_8_lsb = (addr & I2C_ADDR_MSK); - iowrite32(addr_8_lsb, p + PCH_I2CDR); + iowrite32(i2c_10bit_addr_lo_from_msg(msgs), p + PCH_I2CDR); pch_i2c_restart(adap); @@ -527,8 +510,7 @@ static s32 pch_i2c_readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, if (rtn) return rtn; - addr_2_msb |= I2C_RD; - iowrite32(addr_2_msb | TEN_BIT_ADDR_MASK, p + PCH_I2CDR); + iowrite32(i2c_10bit_addr_hi_from_msg(msgs), p + PCH_I2CDR); } else { /* 7 address bits + R/W bit */ iowrite32(i2c_8bit_addr_from_msg(msgs), p + PCH_I2CDR); diff --git a/drivers/i2c/busses/i2c-exynos5.c b/drivers/i2c/busses/i2c-exynos5.c index e330015087ab..02f24479aa07 100644 --- a/drivers/i2c/busses/i2c-exynos5.c +++ b/drivers/i2c/busses/i2c-exynos5.c @@ -168,6 +168,7 @@ enum i2c_type_exynos { I2C_TYPE_EXYNOS5, I2C_TYPE_EXYNOS7, I2C_TYPE_EXYNOSAUTOV9, + I2C_TYPE_EXYNOS8895, }; struct exynos5_i2c { @@ -240,6 +241,11 @@ static const struct exynos_hsi2c_variant exynosautov9_hsi2c_data = { .hw = I2C_TYPE_EXYNOSAUTOV9, }; +static const struct exynos_hsi2c_variant exynos8895_hsi2c_data = { + .fifo_depth = 64, + .hw = I2C_TYPE_EXYNOS8895, +}; + static const struct of_device_id exynos5_i2c_match[] = { { .compatible = "samsung,exynos5-hsi2c", @@ -256,6 +262,9 @@ static const struct of_device_id exynos5_i2c_match[] = { }, { .compatible = "samsung,exynosautov9-hsi2c", .data = &exynosautov9_hsi2c_data + }, { + .compatible = "samsung,exynos8895-hsi2c", + .data = &exynos8895_hsi2c_data }, {}, }; MODULE_DEVICE_TABLE(of, exynos5_i2c_match); @@ -331,6 +340,14 @@ static int exynos5_i2c_set_timing(struct exynos5_i2c *i2c, bool hs_timings) * clk_cycle := TSCLK_L + TSCLK_H * temp := (CLK_DIV + 1) * (clk_cycle + 2) * + * In case of HSI2C controllers in Exynos8895 + * FPCLK / FI2C = + * (CLK_DIV + 1) * (TSCLK_L + TSCLK_H + 2) + + * 2 * ((FLT_CYCLE + 3) - (FLT_CYCLE + 3) % (CLK_DIV + 1)) + * + * clk_cycle := TSCLK_L + TSCLK_H + * temp := (FPCLK / FI2C) - (FLT_CYCLE + 3) * 2 + * * Constraints: 4 <= temp, 0 <= CLK_DIV < 256, 2 <= clk_cycle <= 510 * * To split SCL clock into low, high periods appropriately, one @@ -352,11 +369,19 @@ static int exynos5_i2c_set_timing(struct exynos5_i2c *i2c, bool hs_timings) * */ t_ftl_cycle = (readl(i2c->regs + HSI2C_CONF) >> 16) & 0x7; - temp = clkin / op_clk - 8 - t_ftl_cycle; - if (i2c->variant->hw != I2C_TYPE_EXYNOS7) - temp -= t_ftl_cycle; + if (i2c->variant->hw == I2C_TYPE_EXYNOS8895) + temp = clkin / op_clk - (t_ftl_cycle + 3) * 2; + else if (i2c->variant->hw == I2C_TYPE_EXYNOS7) + temp = clkin / op_clk - 8 - t_ftl_cycle; + else + temp = clkin / op_clk - 8 - (t_ftl_cycle * 2); div = temp / 512; - clk_cycle = temp / (div + 1) - 2; + + if (i2c->variant->hw == I2C_TYPE_EXYNOS8895) + clk_cycle = (temp + ((t_ftl_cycle + 3) % (div + 1)) * 2) / + (div + 1) - 2; + else + clk_cycle = temp / (div + 1) - 2; if (temp < 4 || div >= 256 || clk_cycle < 2) { dev_err(i2c->dev, "%s clock set-up failed\n", hs_timings ? "HS" : "FS"); @@ -491,6 +516,8 @@ static irqreturn_t exynos5_i2c_irq(int irqno, void *dev_id) switch (i2c->variant->hw) { case I2C_TYPE_EXYNOSAUTOV9: fallthrough; + case I2C_TYPE_EXYNOS8895: + fallthrough; case I2C_TYPE_EXYNOS7: if (int_status & HSI2C_INT_TRANS_DONE) { i2c->trans_done = 1; @@ -787,7 +814,7 @@ static int exynos5_i2c_xfer_msg(struct exynos5_i2c *i2c, ret = i2c->state; /* - * If this is the last message to be transfered (stop == 1) + * If this is the last message to be transferred (stop == 1) * Then check if the bus can be brought back to idle. */ if (ret == 0 && stop) diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index 75dab01d43a7..48e1af544b75 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -144,6 +144,7 @@ #define SMBNTFDADD(p) (20 + (p)->smba) /* ICH3 and later */ /* PCI Address Constants */ +#define SMBBAR_MMIO 0 #define SMBBAR 4 #define SMBHSTCFG 0x040 #define TCOBASE 0x050 @@ -276,7 +277,7 @@ struct i801_mux_config { struct i801_priv { struct i2c_adapter adapter; - unsigned long smba; + void __iomem *smba; unsigned char original_hstcfg; unsigned char original_hstcnt; unsigned char original_slvcmd; @@ -337,9 +338,43 @@ MODULE_PARM_DESC(disable_features, "Disable selected driver features:\n" "\t\t 0x10 don't use interrupts\n" "\t\t 0x20 disable SMBus Host Notify "); +/* Wait for BUSY being cleared and either INTR or an error flag being set */ +static int i801_wait_intr(struct i801_priv *priv) +{ + unsigned long timeout = jiffies + priv->adapter.timeout; + int status, busy; + + do { + usleep_range(250, 500); + status = ioread8(SMBHSTSTS(priv)); + busy = status & SMBHSTSTS_HOST_BUSY; + status &= STATUS_ERROR_FLAGS | SMBHSTSTS_INTR; + if (!busy && status) + return status & STATUS_ERROR_FLAGS; + } while (time_is_after_eq_jiffies(timeout)); + + return -ETIMEDOUT; +} + +/* Wait for either BYTE_DONE or an error flag being set */ +static int i801_wait_byte_done(struct i801_priv *priv) +{ + unsigned long timeout = jiffies + priv->adapter.timeout; + int status; + + do { + usleep_range(250, 500); + status = ioread8(SMBHSTSTS(priv)); + if (status & (STATUS_ERROR_FLAGS | SMBHSTSTS_BYTE_DONE)) + return status & STATUS_ERROR_FLAGS; + } while (time_is_after_eq_jiffies(timeout)); + + return -ETIMEDOUT; +} + static int i801_get_block_len(struct i801_priv *priv) { - u8 len = inb_p(SMBHSTDAT0(priv)); + u8 len = ioread8(SMBHSTDAT0(priv)); if (len < 1 || len > I2C_SMBUS_BLOCK_MAX) { pci_err(priv->pci_dev, "Illegal SMBus block read size %u\n", len); @@ -356,9 +391,9 @@ static int i801_check_and_clear_pec_error(struct i801_priv *priv) if (!(priv->features & FEATURE_SMBUS_PEC)) return 0; - status = inb_p(SMBAUXSTS(priv)) & SMBAUXSTS_CRCE; + status = ioread8(SMBAUXSTS(priv)) & SMBAUXSTS_CRCE; if (status) { - outb_p(status, SMBAUXSTS(priv)); + iowrite8(status, SMBAUXSTS(priv)); return -EBADMSG; } @@ -371,7 +406,7 @@ static int i801_check_pre(struct i801_priv *priv) { int status, result; - status = inb_p(SMBHSTSTS(priv)); + status = ioread8(SMBHSTSTS(priv)); if (status & SMBHSTSTS_HOST_BUSY) { pci_err(priv->pci_dev, "SMBus is busy, can't use it!\n"); return -EBUSY; @@ -380,7 +415,7 @@ static int i801_check_pre(struct i801_priv *priv) status &= STATUS_FLAGS; if (status) { pci_dbg(priv->pci_dev, "Clearing status flags (%02x)\n", status); - outb_p(status, SMBHSTSTS(priv)); + iowrite8(status, SMBHSTSTS(priv)); } /* @@ -406,22 +441,19 @@ static int i801_check_post(struct i801_priv *priv, int status) */ if (unlikely(status < 0)) { /* try to stop the current command */ - outb_p(SMBHSTCNT_KILL, SMBHSTCNT(priv)); - usleep_range(1000, 2000); - outb_p(0, SMBHSTCNT(priv)); + iowrite8(SMBHSTCNT_KILL, SMBHSTCNT(priv)); + status = i801_wait_intr(priv); + iowrite8(0, SMBHSTCNT(priv)); /* Check if it worked */ - status = inb_p(SMBHSTSTS(priv)); - if ((status & SMBHSTSTS_HOST_BUSY) || - !(status & SMBHSTSTS_FAILED)) - dev_dbg(&priv->pci_dev->dev, - "Failed terminating the transaction\n"); + if (status < 0 || !(status & SMBHSTSTS_FAILED)) + pci_dbg(priv->pci_dev, "Failed terminating the transaction\n"); return -ETIMEDOUT; } if (status & SMBHSTSTS_FAILED) { result = -EIO; - dev_err(&priv->pci_dev->dev, "Transaction failed\n"); + pci_err(priv->pci_dev, "Transaction failed\n"); } if (status & SMBHSTSTS_DEV_ERR) { /* @@ -449,46 +481,12 @@ static int i801_check_post(struct i801_priv *priv, int status) } if (status & SMBHSTSTS_BUS_ERR) { result = -EAGAIN; - dev_dbg(&priv->pci_dev->dev, "Lost arbitration\n"); + pci_dbg(priv->pci_dev, "Lost arbitration\n"); } return result; } -/* Wait for BUSY being cleared and either INTR or an error flag being set */ -static int i801_wait_intr(struct i801_priv *priv) -{ - unsigned long timeout = jiffies + priv->adapter.timeout; - int status, busy; - - do { - usleep_range(250, 500); - status = inb_p(SMBHSTSTS(priv)); - busy = status & SMBHSTSTS_HOST_BUSY; - status &= STATUS_ERROR_FLAGS | SMBHSTSTS_INTR; - if (!busy && status) - return status & STATUS_ERROR_FLAGS; - } while (time_is_after_eq_jiffies(timeout)); - - return -ETIMEDOUT; -} - -/* Wait for either BYTE_DONE or an error flag being set */ -static int i801_wait_byte_done(struct i801_priv *priv) -{ - unsigned long timeout = jiffies + priv->adapter.timeout; - int status; - - do { - usleep_range(250, 500); - status = inb_p(SMBHSTSTS(priv)); - if (status & (STATUS_ERROR_FLAGS | SMBHSTSTS_BYTE_DONE)) - return status & STATUS_ERROR_FLAGS; - } while (time_is_after_eq_jiffies(timeout)); - - return -ETIMEDOUT; -} - static int i801_transaction(struct i801_priv *priv, int xact) { unsigned long result; @@ -496,13 +494,13 @@ static int i801_transaction(struct i801_priv *priv, int xact) if (priv->features & FEATURE_IRQ) { reinit_completion(&priv->done); - outb_p(xact | SMBHSTCNT_INTREN | SMBHSTCNT_START, + iowrite8(xact | SMBHSTCNT_INTREN | SMBHSTCNT_START, SMBHSTCNT(priv)); result = wait_for_completion_timeout(&priv->done, adap->timeout); return result ? priv->status : -ETIMEDOUT; } - outb_p(xact | SMBHSTCNT_START, SMBHSTCNT(priv)); + iowrite8(xact | SMBHSTCNT_START, SMBHSTCNT(priv)); return i801_wait_intr(priv); } @@ -511,7 +509,7 @@ static int i801_block_transaction_by_block(struct i801_priv *priv, union i2c_smbus_data *data, char read_write, int command) { - int i, len, status, xact; + int len, status, xact; switch (command) { case I2C_SMBUS_BLOCK_PROC_CALL: @@ -525,14 +523,13 @@ static int i801_block_transaction_by_block(struct i801_priv *priv, } /* Set block buffer mode */ - outb_p(inb_p(SMBAUXCTL(priv)) | SMBAUXCTL_E32B, SMBAUXCTL(priv)); + iowrite8(ioread8(SMBAUXCTL(priv)) | SMBAUXCTL_E32B, SMBAUXCTL(priv)); if (read_write == I2C_SMBUS_WRITE) { len = data->block[0]; - outb_p(len, SMBHSTDAT0(priv)); - inb_p(SMBHSTCNT(priv)); /* reset the data buffer index */ - for (i = 0; i < len; i++) - outb_p(data->block[i+1], SMBBLKDAT(priv)); + iowrite8(len, SMBHSTDAT0(priv)); + ioread8(SMBHSTCNT(priv)); /* reset the data buffer index */ + iowrite8_rep(SMBBLKDAT(priv), data->block + 1, len); } status = i801_transaction(priv, xact); @@ -548,12 +545,11 @@ static int i801_block_transaction_by_block(struct i801_priv *priv, } data->block[0] = len; - inb_p(SMBHSTCNT(priv)); /* reset the data buffer index */ - for (i = 0; i < len; i++) - data->block[i + 1] = inb_p(SMBBLKDAT(priv)); + ioread8(SMBHSTCNT(priv)); /* reset the data buffer index */ + ioread8_rep(SMBBLKDAT(priv), data->block + 1, len); } out: - outb_p(inb_p(SMBAUXCTL(priv)) & ~SMBAUXCTL_E32B, SMBAUXCTL(priv)); + iowrite8(ioread8(SMBAUXCTL(priv)) & ~SMBAUXCTL_E32B, SMBAUXCTL(priv)); return status; } @@ -576,18 +572,17 @@ static void i801_isr_byte_done(struct i801_priv *priv) /* Read next byte */ if (priv->count < priv->len) - priv->data[priv->count++] = inb(SMBBLKDAT(priv)); + priv->data[priv->count++] = ioread8(SMBBLKDAT(priv)); else - dev_dbg(&priv->pci_dev->dev, - "Discarding extra byte on block read\n"); + pci_dbg(priv->pci_dev, "Discarding extra byte on block read\n"); /* Set LAST_BYTE for last byte of read transaction */ if (priv->count == priv->len - 1) - outb_p(priv->cmd | SMBHSTCNT_LAST_BYTE, + iowrite8(priv->cmd | SMBHSTCNT_LAST_BYTE, SMBHSTCNT(priv)); } else if (priv->count < priv->len - 1) { /* Write next byte, except for IRQ after last byte */ - outb_p(priv->data[++priv->count], SMBBLKDAT(priv)); + iowrite8(priv->data[++priv->count], SMBBLKDAT(priv)); } } @@ -595,7 +590,7 @@ static irqreturn_t i801_host_notify_isr(struct i801_priv *priv) { unsigned short addr; - addr = inb_p(SMBNTFDADD(priv)) >> 1; + addr = ioread8(SMBNTFDADD(priv)) >> 1; /* * With the tested platforms, reading SMBNTFDDAT (22 + (p)->smba) @@ -605,7 +600,7 @@ static irqreturn_t i801_host_notify_isr(struct i801_priv *priv) i2c_handle_smbus_host_notify(&priv->adapter, addr); /* clear Host Notify bit and return */ - outb_p(SMBSLVSTS_HST_NTFY_STS, SMBSLVSTS(priv)); + iowrite8(SMBSLVSTS_HST_NTFY_STS, SMBSLVSTS(priv)); return IRQ_HANDLED; } @@ -636,12 +631,12 @@ static irqreturn_t i801_isr(int irq, void *dev_id) return IRQ_NONE; if (priv->features & FEATURE_HOST_NOTIFY) { - status = inb_p(SMBSLVSTS(priv)); + status = ioread8(SMBSLVSTS(priv)); if (status & SMBSLVSTS_HST_NTFY_STS) return i801_host_notify_isr(priv); } - status = inb_p(SMBHSTSTS(priv)); + status = ioread8(SMBHSTSTS(priv)); if ((status & (SMBHSTSTS_BYTE_DONE | STATUS_ERROR_FLAGS)) == SMBHSTSTS_BYTE_DONE) i801_isr_byte_done(priv); @@ -651,7 +646,7 @@ static irqreturn_t i801_isr(int irq, void *dev_id) * so clear it always when the status is set. */ status &= STATUS_FLAGS | SMBHSTSTS_SMBALERT_STS; - outb_p(status, SMBHSTSTS(priv)); + iowrite8(status, SMBHSTSTS(priv)); status &= STATUS_ERROR_FLAGS | SMBHSTSTS_INTR; if (status) { @@ -683,8 +678,8 @@ static int i801_block_transaction_byte_by_byte(struct i801_priv *priv, len = data->block[0]; if (read_write == I2C_SMBUS_WRITE) { - outb_p(len, SMBHSTDAT0(priv)); - outb_p(data->block[1], SMBBLKDAT(priv)); + iowrite8(len, SMBHSTDAT0(priv)); + iowrite8(data->block[1], SMBBLKDAT(priv)); } if (command == I2C_SMBUS_I2C_BLOCK_DATA && @@ -703,14 +698,14 @@ static int i801_block_transaction_byte_by_byte(struct i801_priv *priv, priv->data = &data->block[1]; reinit_completion(&priv->done); - outb_p(priv->cmd | SMBHSTCNT_START, SMBHSTCNT(priv)); + iowrite8(priv->cmd | SMBHSTCNT_START, SMBHSTCNT(priv)); result = wait_for_completion_timeout(&priv->done, adap->timeout); return result ? priv->status : -ETIMEDOUT; } if (len == 1 && read_write == I2C_SMBUS_READ) smbcmd |= SMBHSTCNT_LAST_BYTE; - outb_p(smbcmd | SMBHSTCNT_START, SMBHSTCNT(priv)); + iowrite8(smbcmd | SMBHSTCNT_START, SMBHSTCNT(priv)); for (i = 1; i <= len; i++) { status = i801_wait_byte_done(priv); @@ -726,27 +721,27 @@ static int i801_block_transaction_byte_by_byte(struct i801_priv *priv, len = i801_get_block_len(priv); if (len < 0) { /* Recover */ - while (inb_p(SMBHSTSTS(priv)) & + while (ioread8(SMBHSTSTS(priv)) & SMBHSTSTS_HOST_BUSY) - outb_p(SMBHSTSTS_BYTE_DONE, + iowrite8(SMBHSTSTS_BYTE_DONE, SMBHSTSTS(priv)); - outb_p(SMBHSTSTS_INTR, SMBHSTSTS(priv)); + iowrite8(SMBHSTSTS_INTR, SMBHSTSTS(priv)); return -EPROTO; } data->block[0] = len; } if (read_write == I2C_SMBUS_READ) { - data->block[i] = inb_p(SMBBLKDAT(priv)); + data->block[i] = ioread8(SMBBLKDAT(priv)); if (i == len - 1) - outb_p(smbcmd | SMBHSTCNT_LAST_BYTE, SMBHSTCNT(priv)); + iowrite8(smbcmd | SMBHSTCNT_LAST_BYTE, SMBHSTCNT(priv)); } if (read_write == I2C_SMBUS_WRITE && i+1 <= len) - outb_p(data->block[i+1], SMBBLKDAT(priv)); + iowrite8(data->block[i+1], SMBBLKDAT(priv)); /* signals SMBBLKDAT ready */ - outb_p(SMBHSTSTS_BYTE_DONE, SMBHSTSTS(priv)); + iowrite8(SMBHSTSTS_BYTE_DONE, SMBHSTSTS(priv)); } return i801_wait_intr(priv); @@ -754,7 +749,7 @@ static int i801_block_transaction_byte_by_byte(struct i801_priv *priv, static void i801_set_hstadd(struct i801_priv *priv, u8 addr, char read_write) { - outb_p((addr << 1) | (read_write & 0x01), SMBHSTADD(priv)); + iowrite8((addr << 1) | (read_write & 0x01), SMBHSTADD(priv)); } /* Single value transaction function */ @@ -771,30 +766,30 @@ static int i801_simple_transaction(struct i801_priv *priv, union i2c_smbus_data case I2C_SMBUS_BYTE: i801_set_hstadd(priv, addr, read_write); if (read_write == I2C_SMBUS_WRITE) - outb_p(hstcmd, SMBHSTCMD(priv)); + iowrite8(hstcmd, SMBHSTCMD(priv)); xact = I801_BYTE; break; case I2C_SMBUS_BYTE_DATA: i801_set_hstadd(priv, addr, read_write); if (read_write == I2C_SMBUS_WRITE) - outb_p(data->byte, SMBHSTDAT0(priv)); - outb_p(hstcmd, SMBHSTCMD(priv)); + iowrite8(data->byte, SMBHSTDAT0(priv)); + iowrite8(hstcmd, SMBHSTCMD(priv)); xact = I801_BYTE_DATA; break; case I2C_SMBUS_WORD_DATA: i801_set_hstadd(priv, addr, read_write); if (read_write == I2C_SMBUS_WRITE) { - outb_p(data->word & 0xff, SMBHSTDAT0(priv)); - outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1(priv)); + iowrite8(data->word & 0xff, SMBHSTDAT0(priv)); + iowrite8((data->word & 0xff00) >> 8, SMBHSTDAT1(priv)); } - outb_p(hstcmd, SMBHSTCMD(priv)); + iowrite8(hstcmd, SMBHSTCMD(priv)); xact = I801_WORD_DATA; break; case I2C_SMBUS_PROC_CALL: i801_set_hstadd(priv, addr, I2C_SMBUS_WRITE); - outb_p(data->word & 0xff, SMBHSTDAT0(priv)); - outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1(priv)); - outb_p(hstcmd, SMBHSTCMD(priv)); + iowrite8(data->word & 0xff, SMBHSTDAT0(priv)); + iowrite8((data->word & 0xff00) >> 8, SMBHSTDAT1(priv)); + iowrite8(hstcmd, SMBHSTCMD(priv)); read_write = I2C_SMBUS_READ; xact = I801_PROC_CALL; break; @@ -810,12 +805,12 @@ static int i801_simple_transaction(struct i801_priv *priv, union i2c_smbus_data switch (command) { case I2C_SMBUS_BYTE: case I2C_SMBUS_BYTE_DATA: - data->byte = inb_p(SMBHSTDAT0(priv)); + data->byte = ioread8(SMBHSTDAT0(priv)); break; case I2C_SMBUS_WORD_DATA: case I2C_SMBUS_PROC_CALL: - data->word = inb_p(SMBHSTDAT0(priv)) + - (inb_p(SMBHSTDAT1(priv)) << 8); + data->word = ioread8(SMBHSTDAT0(priv)) + + (ioread8(SMBHSTDAT1(priv)) << 8); break; } @@ -836,7 +831,7 @@ static int i801_smbus_block_transaction(struct i801_priv *priv, union i2c_smbus_ i801_set_hstadd(priv, addr, I2C_SMBUS_WRITE); else i801_set_hstadd(priv, addr, read_write); - outb_p(hstcmd, SMBHSTCMD(priv)); + iowrite8(hstcmd, SMBHSTCMD(priv)); if (priv->features & FEATURE_BLOCK_BUFFER) return i801_block_transaction_by_block(priv, data, read_write, command); @@ -862,9 +857,9 @@ static int i801_i2c_block_transaction(struct i801_priv *priv, union i2c_smbus_da /* NB: page 240 of ICH5 datasheet shows that DATA1 is the cmd field when reading */ if (read_write == I2C_SMBUS_READ) - outb_p(hstcmd, SMBHSTDAT1(priv)); + iowrite8(hstcmd, SMBHSTDAT1(priv)); else - outb_p(hstcmd, SMBHSTCMD(priv)); + iowrite8(hstcmd, SMBHSTCMD(priv)); if (read_write == I2C_SMBUS_WRITE) { /* set I2C_EN bit in configuration register */ @@ -907,9 +902,9 @@ static s32 i801_access(struct i2c_adapter *adap, u16 addr, && size != I2C_SMBUS_I2C_BLOCK_DATA; if (hwpec) /* enable/disable hardware PEC */ - outb_p(inb_p(SMBAUXCTL(priv)) | SMBAUXCTL_CRC, SMBAUXCTL(priv)); + iowrite8(ioread8(SMBAUXCTL(priv)) | SMBAUXCTL_CRC, SMBAUXCTL(priv)); else - outb_p(inb_p(SMBAUXCTL(priv)) & (~SMBAUXCTL_CRC), + iowrite8(ioread8(SMBAUXCTL(priv)) & (~SMBAUXCTL_CRC), SMBAUXCTL(priv)); if (size == I2C_SMBUS_BLOCK_DATA || size == I2C_SMBUS_BLOCK_PROC_CALL) @@ -925,13 +920,13 @@ static s32 i801_access(struct i2c_adapter *adap, u16 addr, * time, so we forcibly disable it after every transaction. */ if (hwpec) - outb_p(inb_p(SMBAUXCTL(priv)) & ~SMBAUXCTL_CRC, SMBAUXCTL(priv)); + iowrite8(ioread8(SMBAUXCTL(priv)) & ~SMBAUXCTL_CRC, SMBAUXCTL(priv)); out: /* * Unlock the SMBus device for use by BIOS/ACPI, * and clear status flags if not done already. */ - outb_p(SMBHSTSTS_INUSE_STS | STATUS_FLAGS, SMBHSTSTS(priv)); + iowrite8(SMBHSTSTS_INUSE_STS | STATUS_FLAGS, SMBHSTSTS(priv)); pm_runtime_mark_last_busy(&priv->pci_dev->dev); pm_runtime_put_autosuspend(&priv->pci_dev->dev); @@ -968,11 +963,11 @@ static void i801_enable_host_notify(struct i2c_adapter *adapter) * from the SMB_ALERT signal because the driver does not support * SMBus Alert. */ - outb_p(SMBSLVCMD_HST_NTFY_INTREN | SMBSLVCMD_SMBALERT_DISABLE | + iowrite8(SMBSLVCMD_HST_NTFY_INTREN | SMBSLVCMD_SMBALERT_DISABLE | priv->original_slvcmd, SMBSLVCMD(priv)); /* clear Host Notify bit to allow a new notification */ - outb_p(SMBSLVSTS_HST_NTFY_STS, SMBSLVSTS(priv)); + iowrite8(SMBSLVSTS_HST_NTFY_STS, SMBSLVSTS(priv)); } static void i801_disable_host_notify(struct i801_priv *priv) @@ -980,7 +975,7 @@ static void i801_disable_host_notify(struct i801_priv *priv) if (!(priv->features & FEATURE_HOST_NOTIFY)) return; - outb_p(priv->original_slvcmd, SMBSLVCMD(priv)); + iowrite8(priv->original_slvcmd, SMBSLVCMD(priv)); } static const struct i2c_algorithm smbus_algorithm = { @@ -1162,127 +1157,6 @@ static void dmi_check_onboard_devices(const struct dmi_header *dm, void *adap) } } -/* NOTE: Keep this list in sync with drivers/platform/x86/dell-smo8800.c */ -static const char *const acpi_smo8800_ids[] = { - "SMO8800", - "SMO8801", - "SMO8810", - "SMO8811", - "SMO8820", - "SMO8821", - "SMO8830", - "SMO8831", -}; - -static acpi_status check_acpi_smo88xx_device(acpi_handle obj_handle, - u32 nesting_level, - void *context, - void **return_value) -{ - struct acpi_device_info *info; - acpi_status status; - char *hid; - int i; - - status = acpi_get_object_info(obj_handle, &info); - if (ACPI_FAILURE(status)) - return AE_OK; - - if (!(info->valid & ACPI_VALID_HID)) - goto smo88xx_not_found; - - hid = info->hardware_id.string; - if (!hid) - goto smo88xx_not_found; - - i = match_string(acpi_smo8800_ids, ARRAY_SIZE(acpi_smo8800_ids), hid); - if (i < 0) - goto smo88xx_not_found; - - kfree(info); - - *return_value = NULL; - return AE_CTRL_TERMINATE; - -smo88xx_not_found: - kfree(info); - return AE_OK; -} - -static bool is_dell_system_with_lis3lv02d(void) -{ - void *err = ERR_PTR(-ENOENT); - - if (!dmi_match(DMI_SYS_VENDOR, "Dell Inc.")) - return false; - - /* - * Check that ACPI device SMO88xx is present and is functioning. - * Function acpi_get_devices() already filters all ACPI devices - * which are not present or are not functioning. - * ACPI device SMO88xx represents our ST microelectronics lis3lv02d - * accelerometer but unfortunately ACPI does not provide any other - * information (like I2C address). - */ - acpi_get_devices(NULL, check_acpi_smo88xx_device, NULL, &err); - - return !IS_ERR(err); -} - -/* - * Accelerometer's I2C address is not specified in DMI nor ACPI, - * so it is needed to define mapping table based on DMI product names. - */ -static const struct { - const char *dmi_product_name; - unsigned short i2c_addr; -} dell_lis3lv02d_devices[] = { - /* - * Dell platform team told us that these Latitude devices have - * ST microelectronics accelerometer at I2C address 0x29. - */ - { "Latitude E5250", 0x29 }, - { "Latitude E5450", 0x29 }, - { "Latitude E5550", 0x29 }, - { "Latitude E6440", 0x29 }, - { "Latitude E6440 ATG", 0x29 }, - { "Latitude E6540", 0x29 }, - /* - * Additional individual entries were added after verification. - */ - { "Latitude 5480", 0x29 }, - { "Precision 3540", 0x29 }, - { "Vostro V131", 0x1d }, - { "Vostro 5568", 0x29 }, - { "XPS 15 7590", 0x29 }, -}; - -static void register_dell_lis3lv02d_i2c_device(struct i801_priv *priv) -{ - struct i2c_board_info info; - const char *dmi_product_name; - int i; - - dmi_product_name = dmi_get_system_info(DMI_PRODUCT_NAME); - for (i = 0; i < ARRAY_SIZE(dell_lis3lv02d_devices); ++i) { - if (strcmp(dmi_product_name, - dell_lis3lv02d_devices[i].dmi_product_name) == 0) - break; - } - - if (i == ARRAY_SIZE(dell_lis3lv02d_devices)) { - dev_warn(&priv->pci_dev->dev, - "Accelerometer lis3lv02d is present on SMBus but its" - " address is unknown, skipping registration\n"); - return; - } - - memset(&info, 0, sizeof(struct i2c_board_info)); - info.addr = dell_lis3lv02d_devices[i].i2c_addr; - strscpy(info.type, "lis3lv02d", I2C_NAME_SIZE); - i2c_new_client_device(&priv->adapter, &info); -} - /* Register optional targets */ static void i801_probe_optional_targets(struct i801_priv *priv) { @@ -1302,9 +1176,6 @@ static void i801_probe_optional_targets(struct i801_priv *priv) if (dmi_name_in_vendors("FUJITSU")) dmi_walk(dmi_check_onboard_devices, &priv->adapter); - if (is_dell_system_with_lis3lv02d()) - register_dell_lis3lv02d_i2c_device(priv); - /* Instantiate SPD EEPROMs unless the SMBus is multiplexed */ #ifdef CONFIG_I2C_I801_MUX if (!priv->mux_pdev) @@ -1562,14 +1433,14 @@ static void i801_add_tco(struct i801_priv *priv) priv->tco_pdev = i801_add_tco_spt(pci_dev, tco_res); if (IS_ERR(priv->tco_pdev)) - dev_warn(&pci_dev->dev, "failed to create iTCO device\n"); + pci_warn(pci_dev, "failed to create iTCO device\n"); } #ifdef CONFIG_ACPI static bool i801_acpi_is_smbus_ioport(const struct i801_priv *priv, acpi_physical_address address) { - return address >= priv->smba && + return address >= pci_resource_start(priv->pci_dev, SMBBAR) && address <= pci_resource_end(priv->pci_dev, SMBBAR); } @@ -1591,8 +1462,8 @@ i801_acpi_io_handler(u32 function, acpi_physical_address address, u32 bits, if (!priv->acpi_reserved && i801_acpi_is_smbus_ioport(priv, address)) { priv->acpi_reserved = true; - dev_warn(&pdev->dev, "BIOS is accessing SMBus registers\n"); - dev_warn(&pdev->dev, "Driver SMBus register access inhibited\n"); + pci_warn(pdev, "BIOS is accessing SMBus registers\n"); + pci_warn(pdev, "Driver SMBus register access inhibited\n"); /* * BIOS is accessing the host controller so prevent it from @@ -1646,13 +1517,13 @@ static void i801_setup_hstcfg(struct i801_priv *priv) static void i801_restore_regs(struct i801_priv *priv) { - outb_p(priv->original_hstcnt, SMBHSTCNT(priv)); + iowrite8(priv->original_hstcnt, SMBHSTCNT(priv)); pci_write_config_byte(priv->pci_dev, SMBHSTCFG, priv->original_hstcfg); } static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id) { - int err, i; + int err, i, bar = SMBBAR; struct i801_priv *priv; priv = devm_kzalloc(&dev->dev, sizeof(*priv), GFP_KERNEL); @@ -1673,8 +1544,7 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id) /* Disable features on user request */ for (i = 0; i < ARRAY_SIZE(i801_feature_names); i++) { if (priv->features & disable_features & (1 << i)) - dev_notice(&dev->dev, "%s disabled by user\n", - i801_feature_names[i]); + pci_notice(dev, "%s disabled by user\n", i801_feature_names[i]); } priv->features &= ~disable_features; @@ -1682,51 +1552,52 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id) if (!(priv->features & FEATURE_BLOCK_BUFFER)) priv->features &= ~FEATURE_BLOCK_PROC; - err = pcim_enable_device(dev); + /* + * Do not call pcim_enable_device(), because the device has to remain + * enabled on driver detach. See i801_remove() for the reasoning. + */ + err = pci_enable_device(dev); if (err) { - dev_err(&dev->dev, "Failed to enable SMBus PCI device (%d)\n", - err); + pci_err(dev, "Failed to enable SMBus PCI device (%d)\n", err); return err; } - pcim_pin_device(dev); /* Determine the address of the SMBus area */ - priv->smba = pci_resource_start(dev, SMBBAR); - if (!priv->smba) { - dev_err(&dev->dev, - "SMBus base address uninitialized, upgrade BIOS\n"); + if (!pci_resource_start(dev, SMBBAR)) { + pci_err(dev, "SMBus base address uninitialized, upgrade BIOS\n"); return -ENODEV; } if (i801_acpi_probe(priv)) return -ENODEV; - err = pcim_iomap_regions(dev, 1 << SMBBAR, DRV_NAME); - if (err) { - dev_err(&dev->dev, - "Failed to request SMBus region 0x%lx-0x%Lx\n", - priv->smba, - (unsigned long long)pci_resource_end(dev, SMBBAR)); + if (pci_resource_flags(dev, SMBBAR_MMIO) & IORESOURCE_MEM) + bar = SMBBAR_MMIO; + + priv->smba = pcim_iomap_region(dev, bar, DRV_NAME); + if (IS_ERR(priv->smba)) { + pci_err(dev, "Failed to request SMBus region %pr\n", + pci_resource_n(dev, bar)); i801_acpi_remove(priv); - return err; + return PTR_ERR(priv->smba); } - pci_read_config_byte(priv->pci_dev, SMBHSTCFG, &priv->original_hstcfg); + pci_read_config_byte(dev, SMBHSTCFG, &priv->original_hstcfg); i801_setup_hstcfg(priv); if (!(priv->original_hstcfg & SMBHSTCFG_HST_EN)) - dev_info(&dev->dev, "Enabling SMBus device\n"); + pci_info(dev, "Enabling SMBus device\n"); if (priv->original_hstcfg & SMBHSTCFG_SMB_SMI_EN) { - dev_dbg(&dev->dev, "SMBus using interrupt SMI#\n"); + pci_dbg(dev, "SMBus using interrupt SMI#\n"); /* Disable SMBus interrupt feature if SMBus using SMI# */ priv->features &= ~FEATURE_IRQ; } if (priv->original_hstcfg & SMBHSTCFG_SPD_WD) - dev_info(&dev->dev, "SPD Write Disable is set\n"); + pci_info(dev, "SPD Write Disable is set\n"); /* Clear special mode bits */ if (priv->features & (FEATURE_SMBUS_PEC | FEATURE_BLOCK_BUFFER)) - outb_p(inb_p(SMBAUXCTL(priv)) & + iowrite8(ioread8(SMBAUXCTL(priv)) & ~(SMBAUXCTL_CRC | SMBAUXCTL_E32B), SMBAUXCTL(priv)); /* Default timeout in interrupt mode: 200 ms */ @@ -1741,7 +1612,7 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id) /* Complain if an interrupt is already pending */ pci_read_config_word(priv->pci_dev, PCI_STATUS, &pcists); if (pcists & PCI_STATUS_INTERRUPT) - dev_warn(&dev->dev, "An interrupt is pending!\n"); + pci_warn(dev, "An interrupt is pending!\n"); } if (priv->features & FEATURE_IRQ) { @@ -1750,12 +1621,11 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id) err = devm_request_irq(&dev->dev, dev->irq, i801_isr, IRQF_SHARED, DRV_NAME, priv); if (err) { - dev_err(&dev->dev, "Failed to allocate irq %d: %d\n", - dev->irq, err); + pci_err(dev, "Failed to allocate irq %d: %d\n", dev->irq, err); priv->features &= ~FEATURE_IRQ; } } - dev_info(&dev->dev, "SMBus using %s\n", + pci_info(dev, "SMBus using %s\n", priv->features & FEATURE_IRQ ? "PCI interrupt" : "polling"); /* Host notification uses an interrupt */ @@ -1763,9 +1633,9 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id) priv->features &= ~FEATURE_HOST_NOTIFY; /* Remember original Interrupt and Host Notify settings */ - priv->original_hstcnt = inb_p(SMBHSTCNT(priv)) & ~SMBHSTCNT_KILL; + priv->original_hstcnt = ioread8(SMBHSTCNT(priv)) & ~SMBHSTCNT_KILL; if (priv->features & FEATURE_HOST_NOTIFY) - priv->original_slvcmd = inb_p(SMBSLVCMD(priv)); + priv->original_slvcmd = ioread8(SMBSLVCMD(priv)); i801_add_tco(priv); @@ -1774,9 +1644,9 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id) * to instantiante i2c_clients, do not change. */ snprintf(priv->adapter.name, sizeof(priv->adapter.name), - "SMBus %s adapter at %04lx", + "SMBus %s adapter at %s", (priv->features & FEATURE_IDF) ? "I801 IDF" : "I801", - priv->smba); + pci_name(dev)); err = i2c_add_adapter(&priv->adapter); if (err) { diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c index c76c4116ddc7..6bf45d752ff9 100644 --- a/drivers/i2c/busses/i2c-ibm_iic.c +++ b/drivers/i2c/busses/i2c-ibm_iic.c @@ -512,19 +512,17 @@ static int iic_xfer_bytes(struct ibm_iic_private* dev, struct i2c_msg* pm, static inline void iic_address(struct ibm_iic_private* dev, struct i2c_msg* msg) { volatile struct iic_regs __iomem *iic = dev->vaddr; - u16 addr = msg->addr; DBG2("%d: iic_address, 0x%03x (%d-bit)\n", dev->idx, - addr, msg->flags & I2C_M_TEN ? 10 : 7); + msg->addr, msg->flags & I2C_M_TEN ? 10 : 7); - if (msg->flags & I2C_M_TEN){ + if (msg->flags & I2C_M_TEN) { out_8(&iic->cntl, CNTL_AMD); - out_8(&iic->lmadr, addr); - out_8(&iic->hmadr, 0xf0 | ((addr >> 7) & 0x06)); - } - else { + out_8(&iic->lmadr, i2c_10bit_addr_lo_from_msg(msg)); + out_8(&iic->hmadr, i2c_10bit_addr_hi_from_msg(msg) & ~I2C_M_RD); + } else { out_8(&iic->cntl, 0); - out_8(&iic->lmadr, addr << 1); + out_8(&iic->lmadr, i2c_8bit_addr_from_msg(msg) & ~I2C_M_RD); } } diff --git a/drivers/i2c/busses/i2c-img-scb.c b/drivers/i2c/busses/i2c-img-scb.c index 02f75cf310aa..5d8b82ae6fd6 100644 --- a/drivers/i2c/busses/i2c-img-scb.c +++ b/drivers/i2c/busses/i2c-img-scb.c @@ -1122,7 +1122,7 @@ static int img_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, time_left = wait_for_completion_timeout(&i2c->msg_complete, IMG_I2C_TIMEOUT); - del_timer_sync(&i2c->check_timer); + timer_delete_sync(&i2c->check_timer); if (time_left == 0) i2c->msg_status = -ETIMEDOUT; diff --git a/drivers/i2c/busses/i2c-imx-lpi2c.c b/drivers/i2c/busses/i2c-imx-lpi2c.c index 8adf2963d764..342d47e67586 100644 --- a/drivers/i2c/busses/i2c-imx-lpi2c.c +++ b/drivers/i2c/busses/i2c-imx-lpi2c.c @@ -8,6 +8,8 @@ #include <linux/clk.h> #include <linux/completion.h> #include <linux/delay.h> +#include <linux/dma-mapping.h> +#include <linux/dmaengine.h> #include <linux/err.h> #include <linux/errno.h> #include <linux/i2c.h> @@ -29,6 +31,7 @@ #define LPI2C_MCR 0x10 /* i2c contrl register */ #define LPI2C_MSR 0x14 /* i2c status register */ #define LPI2C_MIER 0x18 /* i2c interrupt enable */ +#define LPI2C_MDER 0x1C /* i2c DMA enable */ #define LPI2C_MCFGR0 0x20 /* i2c master configuration */ #define LPI2C_MCFGR1 0x24 /* i2c master configuration */ #define LPI2C_MCFGR2 0x28 /* i2c master configuration */ @@ -40,6 +43,20 @@ #define LPI2C_MTDR 0x60 /* i2c master TX data register */ #define LPI2C_MRDR 0x70 /* i2c master RX data register */ +#define LPI2C_SCR 0x110 /* i2c target control register */ +#define LPI2C_SSR 0x114 /* i2c target status register */ +#define LPI2C_SIER 0x118 /* i2c target interrupt enable */ +#define LPI2C_SDER 0x11C /* i2c target DMA enable */ +#define LPI2C_SCFGR0 0x120 /* i2c target configuration */ +#define LPI2C_SCFGR1 0x124 /* i2c target configuration */ +#define LPI2C_SCFGR2 0x128 /* i2c target configuration */ +#define LPI2C_SAMR 0x140 /* i2c target address match */ +#define LPI2C_SASR 0x150 /* i2c target address status */ +#define LPI2C_STAR 0x154 /* i2c target transmit ACK */ +#define LPI2C_STDR 0x160 /* i2c target transmit data */ +#define LPI2C_SRDR 0x170 /* i2c target receive data */ +#define LPI2C_SRDROR 0x178 /* i2c target receive data read only */ + /* i2c command */ #define TRAN_DATA 0X00 #define RECV_DATA 0X01 @@ -70,11 +87,50 @@ #define MCFGR1_AUTOSTOP BIT(8) #define MCFGR1_IGNACK BIT(9) #define MRDR_RXEMPTY BIT(14) +#define MDER_TDDE BIT(0) +#define MDER_RDDE BIT(1) + +#define SCR_SEN BIT(0) +#define SCR_RST BIT(1) +#define SCR_FILTEN BIT(4) +#define SCR_RTF BIT(8) +#define SCR_RRF BIT(9) +#define SSR_TDF BIT(0) +#define SSR_RDF BIT(1) +#define SSR_AVF BIT(2) +#define SSR_TAF BIT(3) +#define SSR_RSF BIT(8) +#define SSR_SDF BIT(9) +#define SSR_BEF BIT(10) +#define SSR_FEF BIT(11) +#define SSR_SBF BIT(24) +#define SSR_BBF BIT(25) +#define SSR_CLEAR_BITS (SSR_RSF | SSR_SDF | SSR_BEF | SSR_FEF) +#define SIER_TDIE BIT(0) +#define SIER_RDIE BIT(1) +#define SIER_AVIE BIT(2) +#define SIER_TAIE BIT(3) +#define SIER_RSIE BIT(8) +#define SIER_SDIE BIT(9) +#define SIER_BEIE BIT(10) +#define SIER_FEIE BIT(11) +#define SIER_AM0F BIT(12) +#define SCFGR1_RXSTALL BIT(1) +#define SCFGR1_TXDSTALL BIT(2) +#define SCFGR2_FILTSDA_SHIFT 24 +#define SCFGR2_FILTSCL_SHIFT 16 +#define SCFGR2_CLKHOLD(x) (x) +#define SCFGR2_FILTSDA(x) ((x) << SCFGR2_FILTSDA_SHIFT) +#define SCFGR2_FILTSCL(x) ((x) << SCFGR2_FILTSCL_SHIFT) +#define SASR_READ_REQ 0x1 +#define SLAVE_INT_FLAG (SIER_TDIE | SIER_RDIE | SIER_AVIE | \ + SIER_SDIE | SIER_BEIE) #define I2C_CLK_RATIO 2 #define CHUNK_DATA 256 #define I2C_PM_TIMEOUT 10 /* ms */ +#define I2C_DMA_THRESHOLD 8 /* bytes */ enum lpi2c_imx_mode { STANDARD, /* 100+Kbps */ @@ -91,6 +147,24 @@ enum lpi2c_imx_pincfg { FOUR_PIN_PP, }; +struct lpi2c_imx_dma { + bool using_pio_mode; + u8 rx_cmd_buf_len; + u8 *dma_buf; + u16 *rx_cmd_buf; + unsigned int dma_len; + unsigned int tx_burst_num; + unsigned int rx_burst_num; + unsigned long dma_msg_flag; + resource_size_t phy_addr; + dma_addr_t dma_tx_addr; + dma_addr_t dma_addr; + enum dma_data_direction dma_data_dir; + enum dma_transfer_direction dma_transfer_dir; + struct dma_chan *chan_tx; + struct dma_chan *chan_rx; +}; + struct lpi2c_imx_struct { struct i2c_adapter adapter; int num_clks; @@ -108,6 +182,9 @@ struct lpi2c_imx_struct { unsigned int rxfifosize; enum lpi2c_imx_mode mode; struct i2c_bus_recovery_info rinfo; + bool can_use_dma; + struct lpi2c_imx_dma *dma; + struct i2c_client *target; }; static void lpi2c_imx_intctrl(struct lpi2c_imx_struct *lpi2c_imx, @@ -305,7 +382,7 @@ static int lpi2c_imx_master_disable(struct lpi2c_imx_struct *lpi2c_imx) return 0; } -static int lpi2c_imx_msg_complete(struct lpi2c_imx_struct *lpi2c_imx) +static int lpi2c_imx_pio_msg_complete(struct lpi2c_imx_struct *lpi2c_imx) { unsigned long time_left; @@ -451,6 +528,425 @@ static void lpi2c_imx_read(struct lpi2c_imx_struct *lpi2c_imx, lpi2c_imx_intctrl(lpi2c_imx, MIER_RDIE | MIER_NDIE); } +static bool is_use_dma(struct lpi2c_imx_struct *lpi2c_imx, struct i2c_msg *msg) +{ + if (!lpi2c_imx->can_use_dma) + return false; + + /* + * When the length of data is less than I2C_DMA_THRESHOLD, + * cpu mode is used directly to avoid low performance. + */ + return !(msg->len < I2C_DMA_THRESHOLD); +} + +static int lpi2c_imx_pio_xfer(struct lpi2c_imx_struct *lpi2c_imx, + struct i2c_msg *msg) +{ + reinit_completion(&lpi2c_imx->complete); + + if (msg->flags & I2C_M_RD) + lpi2c_imx_read(lpi2c_imx, msg); + else + lpi2c_imx_write(lpi2c_imx, msg); + + return lpi2c_imx_pio_msg_complete(lpi2c_imx); +} + +static int lpi2c_imx_dma_timeout_calculate(struct lpi2c_imx_struct *lpi2c_imx) +{ + unsigned long time = 0; + + time = 8 * lpi2c_imx->dma->dma_len * 1000 / lpi2c_imx->bitrate; + + /* Add extra second for scheduler related activities */ + time += 1; + + /* Double calculated time */ + return msecs_to_jiffies(time * MSEC_PER_SEC); +} + +static int lpi2c_imx_alloc_rx_cmd_buf(struct lpi2c_imx_struct *lpi2c_imx) +{ + struct lpi2c_imx_dma *dma = lpi2c_imx->dma; + u16 rx_remain = dma->dma_len; + int cmd_num; + u16 temp; + + /* + * Calculate the number of rx command words via the DMA TX channel + * writing into command register based on the i2c msg len, and build + * the rx command words buffer. + */ + cmd_num = DIV_ROUND_UP(rx_remain, CHUNK_DATA); + dma->rx_cmd_buf = kcalloc(cmd_num, sizeof(u16), GFP_KERNEL); + dma->rx_cmd_buf_len = cmd_num * sizeof(u16); + + if (!dma->rx_cmd_buf) { + dev_err(&lpi2c_imx->adapter.dev, "Alloc RX cmd buffer failed\n"); + return -ENOMEM; + } + + for (int i = 0; i < cmd_num ; i++) { + temp = rx_remain > CHUNK_DATA ? CHUNK_DATA - 1 : rx_remain - 1; + temp |= (RECV_DATA << 8); + rx_remain -= CHUNK_DATA; + dma->rx_cmd_buf[i] = temp; + } + + return 0; +} + +static int lpi2c_imx_dma_msg_complete(struct lpi2c_imx_struct *lpi2c_imx) +{ + unsigned long time_left, time; + + time = lpi2c_imx_dma_timeout_calculate(lpi2c_imx); + time_left = wait_for_completion_timeout(&lpi2c_imx->complete, time); + if (time_left == 0) { + dev_err(&lpi2c_imx->adapter.dev, "I/O Error in DMA Data Transfer\n"); + return -ETIMEDOUT; + } + + return 0; +} + +static void lpi2c_dma_unmap(struct lpi2c_imx_dma *dma) +{ + struct dma_chan *chan = dma->dma_data_dir == DMA_FROM_DEVICE + ? dma->chan_rx : dma->chan_tx; + + dma_unmap_single(chan->device->dev, dma->dma_addr, + dma->dma_len, dma->dma_data_dir); + + dma->dma_data_dir = DMA_NONE; +} + +static void lpi2c_cleanup_rx_cmd_dma(struct lpi2c_imx_dma *dma) +{ + dmaengine_terminate_sync(dma->chan_tx); + dma_unmap_single(dma->chan_tx->device->dev, dma->dma_tx_addr, + dma->rx_cmd_buf_len, DMA_TO_DEVICE); +} + +static void lpi2c_cleanup_dma(struct lpi2c_imx_dma *dma) +{ + if (dma->dma_data_dir == DMA_FROM_DEVICE) + dmaengine_terminate_sync(dma->chan_rx); + else if (dma->dma_data_dir == DMA_TO_DEVICE) + dmaengine_terminate_sync(dma->chan_tx); + + lpi2c_dma_unmap(dma); +} + +static void lpi2c_dma_callback(void *data) +{ + struct lpi2c_imx_struct *lpi2c_imx = (struct lpi2c_imx_struct *)data; + + complete(&lpi2c_imx->complete); +} + +static int lpi2c_dma_rx_cmd_submit(struct lpi2c_imx_struct *lpi2c_imx) +{ + struct dma_async_tx_descriptor *rx_cmd_desc; + struct lpi2c_imx_dma *dma = lpi2c_imx->dma; + struct dma_chan *txchan = dma->chan_tx; + dma_cookie_t cookie; + + dma->dma_tx_addr = dma_map_single(txchan->device->dev, + dma->rx_cmd_buf, dma->rx_cmd_buf_len, + DMA_TO_DEVICE); + if (dma_mapping_error(txchan->device->dev, dma->dma_tx_addr)) { + dev_err(&lpi2c_imx->adapter.dev, "DMA map failed, use pio\n"); + return -EINVAL; + } + + rx_cmd_desc = dmaengine_prep_slave_single(txchan, dma->dma_tx_addr, + dma->rx_cmd_buf_len, DMA_MEM_TO_DEV, + DMA_PREP_INTERRUPT | DMA_CTRL_ACK); + if (!rx_cmd_desc) { + dev_err(&lpi2c_imx->adapter.dev, "DMA prep slave sg failed, use pio\n"); + goto desc_prepare_err_exit; + } + + cookie = dmaengine_submit(rx_cmd_desc); + if (dma_submit_error(cookie)) { + dev_err(&lpi2c_imx->adapter.dev, "submitting DMA failed, use pio\n"); + goto submit_err_exit; + } + + dma_async_issue_pending(txchan); + + return 0; + +desc_prepare_err_exit: + dma_unmap_single(txchan->device->dev, dma->dma_tx_addr, + dma->rx_cmd_buf_len, DMA_TO_DEVICE); + return -EINVAL; + +submit_err_exit: + dma_unmap_single(txchan->device->dev, dma->dma_tx_addr, + dma->rx_cmd_buf_len, DMA_TO_DEVICE); + dmaengine_desc_free(rx_cmd_desc); + return -EINVAL; +} + +static int lpi2c_dma_submit(struct lpi2c_imx_struct *lpi2c_imx) +{ + struct lpi2c_imx_dma *dma = lpi2c_imx->dma; + struct dma_async_tx_descriptor *desc; + struct dma_chan *chan; + dma_cookie_t cookie; + + if (dma->dma_msg_flag & I2C_M_RD) { + chan = dma->chan_rx; + dma->dma_data_dir = DMA_FROM_DEVICE; + dma->dma_transfer_dir = DMA_DEV_TO_MEM; + } else { + chan = dma->chan_tx; + dma->dma_data_dir = DMA_TO_DEVICE; + dma->dma_transfer_dir = DMA_MEM_TO_DEV; + } + + dma->dma_addr = dma_map_single(chan->device->dev, + dma->dma_buf, dma->dma_len, dma->dma_data_dir); + if (dma_mapping_error(chan->device->dev, dma->dma_addr)) { + dev_err(&lpi2c_imx->adapter.dev, "DMA map failed, use pio\n"); + return -EINVAL; + } + + desc = dmaengine_prep_slave_single(chan, dma->dma_addr, + dma->dma_len, dma->dma_transfer_dir, + DMA_PREP_INTERRUPT | DMA_CTRL_ACK); + if (!desc) { + dev_err(&lpi2c_imx->adapter.dev, "DMA prep slave sg failed, use pio\n"); + goto desc_prepare_err_exit; + } + + reinit_completion(&lpi2c_imx->complete); + desc->callback = lpi2c_dma_callback; + desc->callback_param = lpi2c_imx; + + cookie = dmaengine_submit(desc); + if (dma_submit_error(cookie)) { + dev_err(&lpi2c_imx->adapter.dev, "submitting DMA failed, use pio\n"); + goto submit_err_exit; + } + + /* Can't switch to PIO mode when DMA have started transfer */ + dma->using_pio_mode = false; + + dma_async_issue_pending(chan); + + return 0; + +desc_prepare_err_exit: + lpi2c_dma_unmap(dma); + return -EINVAL; + +submit_err_exit: + lpi2c_dma_unmap(dma); + dmaengine_desc_free(desc); + return -EINVAL; +} + +static int lpi2c_imx_find_max_burst_num(unsigned int fifosize, unsigned int len) +{ + unsigned int i; + + for (i = fifosize / 2; i > 0; i--) + if (!(len % i)) + break; + + return i; +} + +/* + * For a highest DMA efficiency, tx/rx burst number should be calculated according + * to the FIFO depth. + */ +static void lpi2c_imx_dma_burst_num_calculate(struct lpi2c_imx_struct *lpi2c_imx) +{ + struct lpi2c_imx_dma *dma = lpi2c_imx->dma; + unsigned int cmd_num; + + if (dma->dma_msg_flag & I2C_M_RD) { + /* + * One RX cmd word can trigger DMA receive no more than 256 bytes. + * The number of RX cmd words should be calculated based on the data + * length. + */ + cmd_num = DIV_ROUND_UP(dma->dma_len, CHUNK_DATA); + dma->tx_burst_num = lpi2c_imx_find_max_burst_num(lpi2c_imx->txfifosize, + cmd_num); + dma->rx_burst_num = lpi2c_imx_find_max_burst_num(lpi2c_imx->rxfifosize, + dma->dma_len); + } else { + dma->tx_burst_num = lpi2c_imx_find_max_burst_num(lpi2c_imx->txfifosize, + dma->dma_len); + } +} + +static int lpi2c_dma_config(struct lpi2c_imx_struct *lpi2c_imx) +{ + struct lpi2c_imx_dma *dma = lpi2c_imx->dma; + struct dma_slave_config rx = {}, tx = {}; + int ret; + + lpi2c_imx_dma_burst_num_calculate(lpi2c_imx); + + if (dma->dma_msg_flag & I2C_M_RD) { + tx.dst_addr = dma->phy_addr + LPI2C_MTDR; + tx.dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; + tx.dst_maxburst = dma->tx_burst_num; + tx.direction = DMA_MEM_TO_DEV; + ret = dmaengine_slave_config(dma->chan_tx, &tx); + if (ret < 0) + return ret; + + rx.src_addr = dma->phy_addr + LPI2C_MRDR; + rx.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; + rx.src_maxburst = dma->rx_burst_num; + rx.direction = DMA_DEV_TO_MEM; + ret = dmaengine_slave_config(dma->chan_rx, &rx); + if (ret < 0) + return ret; + } else { + tx.dst_addr = dma->phy_addr + LPI2C_MTDR; + tx.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; + tx.dst_maxburst = dma->tx_burst_num; + tx.direction = DMA_MEM_TO_DEV; + ret = dmaengine_slave_config(dma->chan_tx, &tx); + if (ret < 0) + return ret; + } + + return 0; +} + +static void lpi2c_dma_enable(struct lpi2c_imx_struct *lpi2c_imx) +{ + struct lpi2c_imx_dma *dma = lpi2c_imx->dma; + /* + * TX interrupt will be triggered when the number of words in + * the transmit FIFO is equal or less than TX watermark. + * RX interrupt will be triggered when the number of words in + * the receive FIFO is greater than RX watermark. + * In order to trigger the DMA interrupt, TX watermark should be + * set equal to the DMA TX burst number but RX watermark should + * be set less than the DMA RX burst number. + */ + if (dma->dma_msg_flag & I2C_M_RD) { + /* Set I2C TX/RX watermark */ + writel(dma->tx_burst_num | (dma->rx_burst_num - 1) << 16, + lpi2c_imx->base + LPI2C_MFCR); + /* Enable I2C DMA TX/RX function */ + writel(MDER_TDDE | MDER_RDDE, lpi2c_imx->base + LPI2C_MDER); + } else { + /* Set I2C TX watermark */ + writel(dma->tx_burst_num, lpi2c_imx->base + LPI2C_MFCR); + /* Enable I2C DMA TX function */ + writel(MDER_TDDE, lpi2c_imx->base + LPI2C_MDER); + } + + /* Enable NACK detected */ + lpi2c_imx_intctrl(lpi2c_imx, MIER_NDIE); +}; + +/* + * When lpi2c is in TX DMA mode we can use one DMA TX channel to write + * data word into TXFIFO, but in RX DMA mode it is different. + * + * The LPI2C MTDR register is a command data and transmit data register. + * Bits 8-10 are the command data field and Bits 0-7 are the transmit + * data field. When the LPI2C master needs to read data, the number of + * bytes to read should be set in the command field and RECV_DATA should + * be set into the command data field to receive (DATA[7:0] + 1) bytes. + * The recv data command word is made of RECV_DATA in the command data + * field and the number of bytes to read in transmit data field. When the + * length of data to be read exceeds 256 bytes, recv data command word + * needs to be written to TXFIFO multiple times. + * + * So when in RX DMA mode, the TX channel also must to be configured to + * send RX command words and the RX command word must be set in advance + * before transmitting. + */ +static int lpi2c_imx_dma_xfer(struct lpi2c_imx_struct *lpi2c_imx, + struct i2c_msg *msg) +{ + struct lpi2c_imx_dma *dma = lpi2c_imx->dma; + int ret; + + /* When DMA mode fails before transferring, CPU mode can be used. */ + dma->using_pio_mode = true; + + dma->dma_len = msg->len; + dma->dma_msg_flag = msg->flags; + dma->dma_buf = i2c_get_dma_safe_msg_buf(msg, I2C_DMA_THRESHOLD); + if (!dma->dma_buf) + return -ENOMEM; + + ret = lpi2c_dma_config(lpi2c_imx); + if (ret) { + dev_err(&lpi2c_imx->adapter.dev, "Failed to configure DMA (%d)\n", ret); + goto disable_dma; + } + + lpi2c_dma_enable(lpi2c_imx); + + ret = lpi2c_dma_submit(lpi2c_imx); + if (ret) { + dev_err(&lpi2c_imx->adapter.dev, "DMA submission failed (%d)\n", ret); + goto disable_dma; + } + + if (dma->dma_msg_flag & I2C_M_RD) { + ret = lpi2c_imx_alloc_rx_cmd_buf(lpi2c_imx); + if (ret) + goto disable_cleanup_data_dma; + + ret = lpi2c_dma_rx_cmd_submit(lpi2c_imx); + if (ret) + goto disable_cleanup_data_dma; + } + + ret = lpi2c_imx_dma_msg_complete(lpi2c_imx); + if (ret) + goto disable_cleanup_all_dma; + + /* When encountering NACK in transfer, clean up all DMA transfers */ + if ((readl(lpi2c_imx->base + LPI2C_MSR) & MSR_NDF) && !ret) { + ret = -EIO; + goto disable_cleanup_all_dma; + } + + if (dma->dma_msg_flag & I2C_M_RD) + dma_unmap_single(dma->chan_tx->device->dev, dma->dma_tx_addr, + dma->rx_cmd_buf_len, DMA_TO_DEVICE); + lpi2c_dma_unmap(dma); + + goto disable_dma; + +disable_cleanup_all_dma: + if (dma->dma_msg_flag & I2C_M_RD) + lpi2c_cleanup_rx_cmd_dma(dma); +disable_cleanup_data_dma: + lpi2c_cleanup_dma(dma); +disable_dma: + /* Disable I2C DMA function */ + writel(0, lpi2c_imx->base + LPI2C_MDER); + + if (dma->dma_msg_flag & I2C_M_RD) + kfree(dma->rx_cmd_buf); + + if (ret) + i2c_put_dma_safe_msg_buf(dma->dma_buf, msg, false); + else + i2c_put_dma_safe_msg_buf(dma->dma_buf, msg, true); + + return ret; +} + static int lpi2c_imx_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num) { @@ -477,12 +973,14 @@ static int lpi2c_imx_xfer(struct i2c_adapter *adapter, lpi2c_imx->msglen = msgs[i].len; init_completion(&lpi2c_imx->complete); - if (msgs[i].flags & I2C_M_RD) - lpi2c_imx_read(lpi2c_imx, &msgs[i]); - else - lpi2c_imx_write(lpi2c_imx, &msgs[i]); + if (is_use_dma(lpi2c_imx, &msgs[i])) { + result = lpi2c_imx_dma_xfer(lpi2c_imx, &msgs[i]); + if (result && lpi2c_imx->dma->using_pio_mode) + result = lpi2c_imx_pio_xfer(lpi2c_imx, &msgs[i]); + } else { + result = lpi2c_imx_pio_xfer(lpi2c_imx, &msgs[i]); + } - result = lpi2c_imx_msg_complete(lpi2c_imx); if (result) goto stop; @@ -510,9 +1008,56 @@ disable: return (result < 0) ? result : num; } -static irqreturn_t lpi2c_imx_isr(int irq, void *dev_id) +static irqreturn_t lpi2c_imx_target_isr(struct lpi2c_imx_struct *lpi2c_imx, + u32 ssr, u32 sier_filter) +{ + u8 value; + u32 sasr; + + /* Arbitration lost */ + if (sier_filter & SSR_BEF) { + writel(0, lpi2c_imx->base + LPI2C_SIER); + return IRQ_HANDLED; + } + + /* Address detected */ + if (sier_filter & SSR_AVF) { + sasr = readl(lpi2c_imx->base + LPI2C_SASR); + if (SASR_READ_REQ & sasr) { + /* Read request */ + i2c_slave_event(lpi2c_imx->target, I2C_SLAVE_READ_REQUESTED, &value); + writel(value, lpi2c_imx->base + LPI2C_STDR); + goto ret; + } else { + /* Write request */ + i2c_slave_event(lpi2c_imx->target, I2C_SLAVE_WRITE_REQUESTED, &value); + } + } + + if (sier_filter & SSR_SDF) + /* STOP */ + i2c_slave_event(lpi2c_imx->target, I2C_SLAVE_STOP, &value); + + if (sier_filter & SSR_TDF) { + /* Target send data */ + i2c_slave_event(lpi2c_imx->target, I2C_SLAVE_READ_PROCESSED, &value); + writel(value, lpi2c_imx->base + LPI2C_STDR); + } + + if (sier_filter & SSR_RDF) { + /* Target receive data */ + value = readl(lpi2c_imx->base + LPI2C_SRDR); + i2c_slave_event(lpi2c_imx->target, I2C_SLAVE_WRITE_RECEIVED, &value); + } + +ret: + /* Clear SSR */ + writel(ssr & SSR_CLEAR_BITS, lpi2c_imx->base + LPI2C_SSR); + return IRQ_HANDLED; +} + +static irqreturn_t lpi2c_imx_master_isr(struct lpi2c_imx_struct *lpi2c_imx) { - struct lpi2c_imx_struct *lpi2c_imx = dev_id; unsigned int enabled; unsigned int temp; @@ -532,6 +1077,124 @@ static irqreturn_t lpi2c_imx_isr(int irq, void *dev_id) return IRQ_HANDLED; } +static irqreturn_t lpi2c_imx_isr(int irq, void *dev_id) +{ + struct lpi2c_imx_struct *lpi2c_imx = dev_id; + + if (lpi2c_imx->target) { + u32 scr = readl(lpi2c_imx->base + LPI2C_SCR); + u32 ssr = readl(lpi2c_imx->base + LPI2C_SSR); + u32 sier_filter = ssr & readl(lpi2c_imx->base + LPI2C_SIER); + + /* + * The target is enabled and an interrupt has been triggered. + * Enter the target's irq handler. + */ + if ((scr & SCR_SEN) && sier_filter) + return lpi2c_imx_target_isr(lpi2c_imx, ssr, sier_filter); + } + + /* + * Otherwise the interrupt has been triggered by the master. + * Enter the master's irq handler. + */ + return lpi2c_imx_master_isr(lpi2c_imx); +} + +static void lpi2c_imx_target_init(struct lpi2c_imx_struct *lpi2c_imx) +{ + u32 temp; + + /* reset target module */ + writel(SCR_RST, lpi2c_imx->base + LPI2C_SCR); + writel(0, lpi2c_imx->base + LPI2C_SCR); + + /* Set target address */ + writel((lpi2c_imx->target->addr << 1), lpi2c_imx->base + LPI2C_SAMR); + + writel(SCFGR1_RXSTALL | SCFGR1_TXDSTALL, lpi2c_imx->base + LPI2C_SCFGR1); + + /* + * set SCFGR2: FILTSDA, FILTSCL and CLKHOLD + * + * FILTSCL/FILTSDA can eliminate signal skew. It should generally be + * set to the same value and should be set >= 50ns. + * + * CLKHOLD is only used when clock stretching is enabled, but it will + * extend the clock stretching to ensure there is an additional delay + * between the target driving SDA and the target releasing the SCL pin. + * + * CLKHOLD setting is crucial for lpi2c target. When master read data + * from target, if there is a delay caused by cpu idle, excessive load, + * or other delays between two bytes in one message transmission, it + * will cause a short interval time between the driving SDA signal and + * releasing SCL signal. The lpi2c master will mistakenly think it is a stop + * signal resulting in an arbitration failure. This issue can be avoided + * by setting CLKHOLD. + * + * In order to ensure lpi2c function normally when the lpi2c speed is as + * low as 100kHz, CLKHOLD should be set to 3 and it is also compatible with + * higher clock frequency like 400kHz and 1MHz. + */ + temp = SCFGR2_FILTSDA(2) | SCFGR2_FILTSCL(2) | SCFGR2_CLKHOLD(3); + writel(temp, lpi2c_imx->base + LPI2C_SCFGR2); + + /* + * Enable module: + * SCR_FILTEN can enable digital filter and output delay counter for LPI2C + * target mode. So SCR_FILTEN need be asserted when enable SDA/SCL FILTER + * and CLKHOLD. + */ + writel(SCR_SEN | SCR_FILTEN, lpi2c_imx->base + LPI2C_SCR); + + /* Enable interrupt from i2c module */ + writel(SLAVE_INT_FLAG, lpi2c_imx->base + LPI2C_SIER); +} + +static int lpi2c_imx_register_target(struct i2c_client *client) +{ + struct lpi2c_imx_struct *lpi2c_imx = i2c_get_adapdata(client->adapter); + int ret; + + if (lpi2c_imx->target) + return -EBUSY; + + lpi2c_imx->target = client; + + ret = pm_runtime_resume_and_get(lpi2c_imx->adapter.dev.parent); + if (ret < 0) { + dev_err(&lpi2c_imx->adapter.dev, "failed to resume i2c controller"); + return ret; + } + + lpi2c_imx_target_init(lpi2c_imx); + + return 0; +} + +static int lpi2c_imx_unregister_target(struct i2c_client *client) +{ + struct lpi2c_imx_struct *lpi2c_imx = i2c_get_adapdata(client->adapter); + int ret; + + if (!lpi2c_imx->target) + return -EINVAL; + + /* Reset target address. */ + writel(0, lpi2c_imx->base + LPI2C_SAMR); + + writel(SCR_RST, lpi2c_imx->base + LPI2C_SCR); + writel(0, lpi2c_imx->base + LPI2C_SCR); + + lpi2c_imx->target = NULL; + + ret = pm_runtime_put_sync(lpi2c_imx->adapter.dev.parent); + if (ret < 0) + dev_err(&lpi2c_imx->adapter.dev, "failed to suspend i2c controller"); + + return ret; +} + static int lpi2c_imx_init_recovery_info(struct lpi2c_imx_struct *lpi2c_imx, struct platform_device *pdev) { @@ -546,6 +1209,58 @@ static int lpi2c_imx_init_recovery_info(struct lpi2c_imx_struct *lpi2c_imx, return 0; } +static void dma_exit(struct device *dev, struct lpi2c_imx_dma *dma) +{ + if (dma->chan_rx) + dma_release_channel(dma->chan_rx); + + if (dma->chan_tx) + dma_release_channel(dma->chan_tx); + + devm_kfree(dev, dma); +} + +static int lpi2c_dma_init(struct device *dev, dma_addr_t phy_addr) +{ + struct lpi2c_imx_struct *lpi2c_imx = dev_get_drvdata(dev); + struct lpi2c_imx_dma *dma; + int ret; + + dma = devm_kzalloc(dev, sizeof(*dma), GFP_KERNEL); + if (!dma) + return -ENOMEM; + + dma->phy_addr = phy_addr; + + /* Prepare for TX DMA: */ + dma->chan_tx = dma_request_chan(dev, "tx"); + if (IS_ERR(dma->chan_tx)) { + ret = PTR_ERR(dma->chan_tx); + if (ret != -ENODEV && ret != -EPROBE_DEFER) + dev_err(dev, "can't request DMA tx channel (%d)\n", ret); + dma->chan_tx = NULL; + goto dma_exit; + } + + /* Prepare for RX DMA: */ + dma->chan_rx = dma_request_chan(dev, "rx"); + if (IS_ERR(dma->chan_rx)) { + ret = PTR_ERR(dma->chan_rx); + if (ret != -ENODEV && ret != -EPROBE_DEFER) + dev_err(dev, "can't request DMA rx channel (%d)\n", ret); + dma->chan_rx = NULL; + goto dma_exit; + } + + lpi2c_imx->can_use_dma = true; + lpi2c_imx->dma = dma; + return 0; + +dma_exit: + dma_exit(dev, dma); + return ret; +} + static u32 lpi2c_imx_func(struct i2c_adapter *adapter) { return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | @@ -555,6 +1270,8 @@ static u32 lpi2c_imx_func(struct i2c_adapter *adapter) static const struct i2c_algorithm lpi2c_imx_algo = { .master_xfer = lpi2c_imx_xfer, .functionality = lpi2c_imx_func, + .reg_target = lpi2c_imx_register_target, + .unreg_target = lpi2c_imx_unregister_target, }; static const struct of_device_id lpi2c_imx_of_match[] = { @@ -566,6 +1283,8 @@ MODULE_DEVICE_TABLE(of, lpi2c_imx_of_match); static int lpi2c_imx_probe(struct platform_device *pdev) { struct lpi2c_imx_struct *lpi2c_imx; + struct resource *res; + dma_addr_t phy_addr; unsigned int temp; int irq, ret; @@ -573,7 +1292,7 @@ static int lpi2c_imx_probe(struct platform_device *pdev) if (!lpi2c_imx) return -ENOMEM; - lpi2c_imx->base = devm_platform_ioremap_resource(pdev, 0); + lpi2c_imx->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); if (IS_ERR(lpi2c_imx->base)) return PTR_ERR(lpi2c_imx->base); @@ -587,6 +1306,7 @@ static int lpi2c_imx_probe(struct platform_device *pdev) lpi2c_imx->adapter.dev.of_node = pdev->dev.of_node; strscpy(lpi2c_imx->adapter.name, pdev->name, sizeof(lpi2c_imx->adapter.name)); + phy_addr = (dma_addr_t)res->start; ret = devm_clk_bulk_get_all(&pdev->dev, &lpi2c_imx->clks); if (ret < 0) @@ -598,7 +1318,7 @@ static int lpi2c_imx_probe(struct platform_device *pdev) if (ret) lpi2c_imx->bitrate = I2C_MAX_STANDARD_MODE_FREQ; - ret = devm_request_irq(&pdev->dev, irq, lpi2c_imx_isr, 0, + ret = devm_request_irq(&pdev->dev, irq, lpi2c_imx_isr, IRQF_NO_SUSPEND, pdev->name, lpi2c_imx); if (ret) return dev_err_probe(&pdev->dev, ret, "can't claim irq %d\n", irq); @@ -640,6 +1360,14 @@ static int lpi2c_imx_probe(struct platform_device *pdev) if (ret == -EPROBE_DEFER) goto rpm_disable; + /* Init DMA */ + ret = lpi2c_dma_init(&pdev->dev, phy_addr); + if (ret) { + if (ret == -EPROBE_DEFER) + goto rpm_disable; + dev_info(&pdev->dev, "use pio mode\n"); + } + ret = i2c_add_adapter(&lpi2c_imx->adapter); if (ret) goto rpm_disable; @@ -652,9 +1380,9 @@ static int lpi2c_imx_probe(struct platform_device *pdev) return 0; rpm_disable: - pm_runtime_put(&pdev->dev); - pm_runtime_disable(&pdev->dev); pm_runtime_dont_use_autosuspend(&pdev->dev); + pm_runtime_put_sync(&pdev->dev); + pm_runtime_disable(&pdev->dev); return ret; } @@ -694,9 +1422,68 @@ static int __maybe_unused lpi2c_runtime_resume(struct device *dev) return 0; } +static int __maybe_unused lpi2c_suspend_noirq(struct device *dev) +{ + return pm_runtime_force_suspend(dev); +} + +static int __maybe_unused lpi2c_resume_noirq(struct device *dev) +{ + struct lpi2c_imx_struct *lpi2c_imx = dev_get_drvdata(dev); + int ret; + + ret = pm_runtime_force_resume(dev); + if (ret) + return ret; + + /* + * If the I2C module powers down during system suspend, + * the register values will be lost. Therefore, reinitialize + * the target when the system resumes. + */ + if (lpi2c_imx->target) + lpi2c_imx_target_init(lpi2c_imx); + + return 0; +} + +static int lpi2c_suspend(struct device *dev) +{ + /* + * Some I2C devices may need the I2C controller to remain active + * during resume_noirq() or suspend_noirq(). If the controller is + * autosuspended, there is no way to wake it up once runtime PM is + * disabled (in suspend_late()). + * + * During system resume, the I2C controller will be available only + * after runtime PM is re-enabled (in resume_early()). However, this + * may be too late for some devices. + * + * Wake up the controller in the suspend() callback while runtime PM + * is still enabled. The I2C controller will remain available until + * the suspend_noirq() callback (pm_runtime_force_suspend()) is + * called. During resume, the I2C controller can be restored by the + * resume_noirq() callback (pm_runtime_force_resume()). + * + * Finally, the resume() callback re-enables autosuspend, ensuring + * the I2C controller remains available until the system enters + * suspend_noirq() and from resume_noirq(). + */ + return pm_runtime_resume_and_get(dev); +} + +static int lpi2c_resume(struct device *dev) +{ + pm_runtime_mark_last_busy(dev); + pm_runtime_put_autosuspend(dev); + + return 0; +} + static const struct dev_pm_ops lpi2c_pm_ops = { - SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, - pm_runtime_force_resume) + SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(lpi2c_suspend_noirq, + lpi2c_resume_noirq) + SYSTEM_SLEEP_PM_OPS(lpi2c_suspend, lpi2c_resume) SET_RUNTIME_PM_OPS(lpi2c_runtime_suspend, lpi2c_runtime_resume, NULL) }; diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c index 5c9a8dfbc4a0..2f6945e02a4b 100644 --- a/drivers/i2c/busses/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c @@ -397,17 +397,16 @@ static void i2c_imx_reset_regs(struct imx_i2c_struct *i2c_imx) } /* Functions for DMA support */ -static void i2c_imx_dma_request(struct imx_i2c_struct *i2c_imx, - dma_addr_t phy_addr) +static int i2c_imx_dma_request(struct imx_i2c_struct *i2c_imx, dma_addr_t phy_addr) { struct imx_i2c_dma *dma; struct dma_slave_config dma_sconfig; - struct device *dev = &i2c_imx->adapter.dev; + struct device *dev = i2c_imx->adapter.dev.parent; int ret; dma = devm_kzalloc(dev, sizeof(*dma), GFP_KERNEL); if (!dma) - return; + return -ENOMEM; dma->chan_tx = dma_request_chan(dev, "tx"); if (IS_ERR(dma->chan_tx)) { @@ -452,7 +451,7 @@ static void i2c_imx_dma_request(struct imx_i2c_struct *i2c_imx, dev_info(dev, "using %s (tx) and %s (rx) for DMA transfers\n", dma_chan_name(dma->chan_tx), dma_chan_name(dma->chan_rx)); - return; + return 0; fail_rx: dma_release_channel(dma->chan_rx); @@ -460,6 +459,8 @@ fail_tx: dma_release_channel(dma->chan_tx); fail_al: devm_kfree(dev, dma); + + return ret; } static void i2c_imx_dma_callback(void *arg) @@ -621,8 +622,8 @@ static int i2c_imx_acked(struct imx_i2c_struct *i2c_imx) return 0; } -static void i2c_imx_set_clk(struct imx_i2c_struct *i2c_imx, - unsigned int i2c_clk_rate) +static int i2c_imx_set_clk(struct imx_i2c_struct *i2c_imx, + unsigned int i2c_clk_rate) { struct imx_i2c_clk_pair *i2c_clk_div = i2c_imx->hwdata->clk_div; unsigned int div; @@ -637,7 +638,11 @@ static void i2c_imx_set_clk(struct imx_i2c_struct *i2c_imx, /* Divider value calculation */ if (i2c_imx->cur_clk == i2c_clk_rate) - return; + return 0; + + /* Keep the denominator of the following program always NOT equal to 0. */ + if (!(i2c_clk_rate / 2)) + return -EINVAL; i2c_imx->cur_clk = i2c_clk_rate; @@ -668,6 +673,8 @@ static void i2c_imx_set_clk(struct imx_i2c_struct *i2c_imx, dev_dbg(&i2c_imx->adapter.dev, "IFDR[IC]=0x%x, REAL DIV=%d\n", i2c_clk_div[i].val, i2c_clk_div[i].div); #endif + + return 0; } static int i2c_imx_clk_notifier_call(struct notifier_block *nb, @@ -677,11 +684,12 @@ static int i2c_imx_clk_notifier_call(struct notifier_block *nb, struct imx_i2c_struct *i2c_imx = container_of(nb, struct imx_i2c_struct, clk_change_nb); + int ret = 0; if (action & POST_RATE_CHANGE) - i2c_imx_set_clk(i2c_imx, ndata->new_rate); + ret = i2c_imx_set_clk(i2c_imx, ndata->new_rate); - return NOTIFY_OK; + return notifier_from_errno(ret); } static int i2c_imx_start(struct imx_i2c_struct *i2c_imx, bool atomic) @@ -1000,7 +1008,7 @@ static inline int i2c_imx_isr_read(struct imx_i2c_struct *i2c_imx) /* setup bus to read data */ temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR); temp &= ~I2CR_MTX; - if (i2c_imx->msg->len - 1) + if ((i2c_imx->msg->len - 1) || (i2c_imx->msg->flags & I2C_M_RECV_LEN)) temp &= ~I2CR_TXAK; imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR); @@ -1055,6 +1063,7 @@ static inline void i2c_imx_isr_read_block_data_len(struct imx_i2c_struct *i2c_im wake_up(&i2c_imx->queue); } i2c_imx->msg->len += len; + i2c_imx->msg->buf[i2c_imx->msg_buf_idx++] = len; } static irqreturn_t i2c_imx_master_isr(struct imx_i2c_struct *i2c_imx, unsigned int status) @@ -1715,8 +1724,8 @@ static int i2c_imx_probe(struct platform_device *pdev) return -ENOMEM; spin_lock_init(&i2c_imx->slave_lock); - hrtimer_init(&i2c_imx->slave_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS); - i2c_imx->slave_timer.function = i2c_imx_slave_timeout; + hrtimer_setup(&i2c_imx->slave_timer, i2c_imx_slave_timeout, CLOCK_MONOTONIC, + HRTIMER_MODE_ABS); match = device_get_match_data(&pdev->dev); if (match) @@ -1760,7 +1769,8 @@ static int i2c_imx_probe(struct platform_device *pdev) goto rpm_disable; /* Request IRQ */ - ret = request_irq(irq, i2c_imx_isr, IRQF_SHARED, pdev->name, i2c_imx); + ret = request_irq(irq, i2c_imx_isr, IRQF_SHARED | IRQF_NO_SUSPEND, + pdev->name, i2c_imx); if (ret) { dev_err(&pdev->dev, "can't claim irq %d\n", irq); goto rpm_disable; @@ -1780,7 +1790,11 @@ static int i2c_imx_probe(struct platform_device *pdev) i2c_imx->bitrate = pdata->bitrate; i2c_imx->clk_change_nb.notifier_call = i2c_imx_clk_notifier_call; clk_notifier_register(i2c_imx->clk, &i2c_imx->clk_change_nb); - i2c_imx_set_clk(i2c_imx, clk_get_rate(i2c_imx->clk)); + ret = i2c_imx_set_clk(i2c_imx, clk_get_rate(i2c_imx->clk)); + if (ret < 0) { + dev_err(&pdev->dev, "can't get I2C clock\n"); + goto clk_notifier_unregister; + } i2c_imx_reset_regs(i2c_imx); @@ -1790,6 +1804,22 @@ static int i2c_imx_probe(struct platform_device *pdev) if (ret == -EPROBE_DEFER) goto clk_notifier_unregister; + /* + * DMA mode should be optional for I2C, when encountering DMA errors, + * no need to exit I2C probe. Only print warning to show DMA error and + * use PIO mode directly to ensure I2C bus available as much as possible. + */ + ret = i2c_imx_dma_request(i2c_imx, phy_addr); + if (ret) { + if (ret == -EPROBE_DEFER) + goto clk_notifier_unregister; + else if (ret == -ENODEV) + dev_dbg(&pdev->dev, "Only use PIO mode\n"); + else + dev_warn(&pdev->dev, "Failed to setup DMA (%pe), only use PIO mode\n", + ERR_PTR(ret)); + } + /* Add I2C adapter */ ret = i2c_add_numbered_adapter(&i2c_imx->adapter); if (ret < 0) @@ -1804,9 +1834,6 @@ static int i2c_imx_probe(struct platform_device *pdev) i2c_imx->adapter.name); dev_info(&i2c_imx->adapter.dev, "IMX I2C adapter registered\n"); - /* Init DMA config if supported */ - i2c_imx_dma_request(i2c_imx, phy_addr); - return 0; /* Return OK */ clk_notifier_unregister: @@ -1858,8 +1885,7 @@ static int i2c_imx_runtime_suspend(struct device *dev) struct imx_i2c_struct *i2c_imx = dev_get_drvdata(dev); clk_disable(i2c_imx->clk); - - return 0; + return pinctrl_pm_select_sleep_state(dev); } static int i2c_imx_runtime_resume(struct device *dev) @@ -1867,6 +1893,10 @@ static int i2c_imx_runtime_resume(struct device *dev) struct imx_i2c_struct *i2c_imx = dev_get_drvdata(dev); int ret; + ret = pinctrl_pm_select_default_state(dev); + if (ret) + return ret; + ret = clk_enable(i2c_imx->clk); if (ret) dev_err(dev, "can't enable I2C clock, ret=%d\n", ret); @@ -1874,7 +1904,43 @@ static int i2c_imx_runtime_resume(struct device *dev) return ret; } +static int i2c_imx_suspend(struct device *dev) +{ + /* + * Some I2C devices may need the I2C controller to remain active + * during resume_noirq() or suspend_noirq(). If the controller is + * autosuspended, there is no way to wake it up once runtime PM is + * disabled (in suspend_late()). + * + * During system resume, the I2C controller will be available only + * after runtime PM is re-enabled (in resume_early()). However, this + * may be too late for some devices. + * + * Wake up the controller in the suspend() callback while runtime PM + * is still enabled. The I2C controller will remain available until + * the suspend_noirq() callback (pm_runtime_force_suspend()) is + * called. During resume, the I2C controller can be restored by the + * resume_noirq() callback (pm_runtime_force_resume()). + * + * Finally, the resume() callback re-enables autosuspend, ensuring + * the I2C controller remains available until the system enters + * suspend_noirq() and from resume_noirq(). + */ + return pm_runtime_resume_and_get(dev); +} + +static int i2c_imx_resume(struct device *dev) +{ + pm_runtime_mark_last_busy(dev); + pm_runtime_put_autosuspend(dev); + + return 0; +} + static const struct dev_pm_ops i2c_imx_pm_ops = { + NOIRQ_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, + pm_runtime_force_resume) + SYSTEM_SLEEP_PM_OPS(i2c_imx_suspend, i2c_imx_resume) RUNTIME_PM_OPS(i2c_imx_runtime_suspend, i2c_imx_runtime_resume, NULL) }; diff --git a/drivers/i2c/busses/i2c-isch.c b/drivers/i2c/busses/i2c-isch.c index 2b3b65ef2900..a2ac992f9cb0 100644 --- a/drivers/i2c/busses/i2c-isch.c +++ b/drivers/i2c/busses/i2c-isch.c @@ -291,9 +291,9 @@ static int smbus_sch_probe(struct platform_device *pdev) /* Set up the sysfs linkage to our parent device */ priv->adapter.dev.parent = dev; - priv->adapter.owner = THIS_MODULE, - priv->adapter.class = I2C_CLASS_HWMON, - priv->adapter.algo = &smbus_algorithm, + priv->adapter.owner = THIS_MODULE; + priv->adapter.class = I2C_CLASS_HWMON; + priv->adapter.algo = &smbus_algorithm; snprintf(priv->adapter.name, sizeof(priv->adapter.name), "SMBus SCH adapter at %04x", (unsigned short)res->start); diff --git a/drivers/i2c/busses/i2c-k1.c b/drivers/i2c/busses/i2c-k1.c new file mode 100644 index 000000000000..b68a21fff0b5 --- /dev/null +++ b/drivers/i2c/busses/i2c-k1.c @@ -0,0 +1,602 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2024-2025 Troy Mitchell <troymitchell988@gmail.com> + */ + + #include <linux/clk.h> + #include <linux/i2c.h> + #include <linux/iopoll.h> + #include <linux/module.h> + #include <linux/of_address.h> + #include <linux/platform_device.h> + +/* spacemit i2c registers */ +#define SPACEMIT_ICR 0x0 /* Control register */ +#define SPACEMIT_ISR 0x4 /* Status register */ +#define SPACEMIT_IDBR 0xc /* Data buffer register */ +#define SPACEMIT_IBMR 0x1c /* Bus monitor register */ + +/* SPACEMIT_ICR register fields */ +#define SPACEMIT_CR_START BIT(0) /* start bit */ +#define SPACEMIT_CR_STOP BIT(1) /* stop bit */ +#define SPACEMIT_CR_ACKNAK BIT(2) /* send ACK(0) or NAK(1) */ +#define SPACEMIT_CR_TB BIT(3) /* transfer byte bit */ +/* Bits 4-7 are reserved */ +#define SPACEMIT_CR_MODE_FAST BIT(8) /* bus mode (master operation) */ +/* Bit 9 is reserved */ +#define SPACEMIT_CR_UR BIT(10) /* unit reset */ +/* Bits 11-12 are reserved */ +#define SPACEMIT_CR_SCLE BIT(13) /* master clock enable */ +#define SPACEMIT_CR_IUE BIT(14) /* unit enable */ +/* Bits 15-17 are reserved */ +#define SPACEMIT_CR_ALDIE BIT(18) /* enable arbitration interrupt */ +#define SPACEMIT_CR_DTEIE BIT(19) /* enable TX interrupts */ +#define SPACEMIT_CR_DRFIE BIT(20) /* enable RX interrupts */ +#define SPACEMIT_CR_GCD BIT(21) /* general call disable */ +#define SPACEMIT_CR_BEIE BIT(22) /* enable bus error ints */ +/* Bits 23-24 are reserved */ +#define SPACEMIT_CR_MSDIE BIT(25) /* master STOP detected int enable */ +#define SPACEMIT_CR_MSDE BIT(26) /* master STOP detected enable */ +#define SPACEMIT_CR_TXDONEIE BIT(27) /* transaction done int enable */ +#define SPACEMIT_CR_TXEIE BIT(28) /* transmit FIFO empty int enable */ +#define SPACEMIT_CR_RXHFIE BIT(29) /* receive FIFO half-full int enable */ +#define SPACEMIT_CR_RXFIE BIT(30) /* receive FIFO full int enable */ +#define SPACEMIT_CR_RXOVIE BIT(31) /* receive FIFO overrun int enable */ + +#define SPACEMIT_I2C_INT_CTRL_MASK (SPACEMIT_CR_ALDIE | SPACEMIT_CR_DTEIE | \ + SPACEMIT_CR_DRFIE | SPACEMIT_CR_BEIE | \ + SPACEMIT_CR_TXDONEIE | SPACEMIT_CR_TXEIE | \ + SPACEMIT_CR_RXHFIE | SPACEMIT_CR_RXFIE | \ + SPACEMIT_CR_RXOVIE | SPACEMIT_CR_MSDIE) + +/* SPACEMIT_ISR register fields */ +/* Bits 0-13 are reserved */ +#define SPACEMIT_SR_ACKNAK BIT(14) /* ACK/NACK status */ +#define SPACEMIT_SR_UB BIT(15) /* unit busy */ +#define SPACEMIT_SR_IBB BIT(16) /* i2c bus busy */ +#define SPACEMIT_SR_EBB BIT(17) /* early bus busy */ +#define SPACEMIT_SR_ALD BIT(18) /* arbitration loss detected */ +#define SPACEMIT_SR_ITE BIT(19) /* TX buffer empty */ +#define SPACEMIT_SR_IRF BIT(20) /* RX buffer full */ +#define SPACEMIT_SR_GCAD BIT(21) /* general call address detected */ +#define SPACEMIT_SR_BED BIT(22) /* bus error no ACK/NAK */ +#define SPACEMIT_SR_SAD BIT(23) /* slave address detected */ +#define SPACEMIT_SR_SSD BIT(24) /* slave stop detected */ +/* Bit 25 is reserved */ +#define SPACEMIT_SR_MSD BIT(26) /* master stop detected */ +#define SPACEMIT_SR_TXDONE BIT(27) /* transaction done */ +#define SPACEMIT_SR_TXE BIT(28) /* TX FIFO empty */ +#define SPACEMIT_SR_RXHF BIT(29) /* RX FIFO half-full */ +#define SPACEMIT_SR_RXF BIT(30) /* RX FIFO full */ +#define SPACEMIT_SR_RXOV BIT(31) /* RX FIFO overrun */ + +#define SPACEMIT_I2C_INT_STATUS_MASK (SPACEMIT_SR_RXOV | SPACEMIT_SR_RXF | SPACEMIT_SR_RXHF | \ + SPACEMIT_SR_TXE | SPACEMIT_SR_TXDONE | SPACEMIT_SR_MSD | \ + SPACEMIT_SR_SSD | SPACEMIT_SR_SAD | SPACEMIT_SR_BED | \ + SPACEMIT_SR_GCAD | SPACEMIT_SR_IRF | SPACEMIT_SR_ITE | \ + SPACEMIT_SR_ALD) + +/* SPACEMIT_IBMR register fields */ +#define SPACEMIT_BMR_SDA BIT(0) /* SDA line level */ +#define SPACEMIT_BMR_SCL BIT(1) /* SCL line level */ + +/* i2c bus recover timeout: us */ +#define SPACEMIT_I2C_BUS_BUSY_TIMEOUT 100000 + +#define SPACEMIT_I2C_MAX_STANDARD_MODE_FREQ 100000 /* Hz */ +#define SPACEMIT_I2C_MAX_FAST_MODE_FREQ 400000 /* Hz */ + +#define SPACEMIT_SR_ERR (SPACEMIT_SR_BED | SPACEMIT_SR_RXOV | SPACEMIT_SR_ALD) + +enum spacemit_i2c_state { + SPACEMIT_STATE_IDLE, + SPACEMIT_STATE_START, + SPACEMIT_STATE_READ, + SPACEMIT_STATE_WRITE, +}; + +/* i2c-spacemit driver's main struct */ +struct spacemit_i2c_dev { + struct device *dev; + struct i2c_adapter adapt; + + /* hardware resources */ + void __iomem *base; + int irq; + u32 clock_freq; + + struct i2c_msg *msgs; + u32 msg_num; + + /* index of the current message being processed */ + u32 msg_idx; + u8 *msg_buf; + /* the number of unprocessed bytes remaining in the current message */ + u32 unprocessed; + + enum spacemit_i2c_state state; + bool read; + struct completion complete; + u32 status; +}; + +static void spacemit_i2c_enable(struct spacemit_i2c_dev *i2c) +{ + u32 val; + + val = readl(i2c->base + SPACEMIT_ICR); + val |= SPACEMIT_CR_IUE; + writel(val, i2c->base + SPACEMIT_ICR); +} + +static void spacemit_i2c_disable(struct spacemit_i2c_dev *i2c) +{ + u32 val; + + val = readl(i2c->base + SPACEMIT_ICR); + val &= ~SPACEMIT_CR_IUE; + writel(val, i2c->base + SPACEMIT_ICR); +} + +static void spacemit_i2c_reset(struct spacemit_i2c_dev *i2c) +{ + writel(SPACEMIT_CR_UR, i2c->base + SPACEMIT_ICR); + udelay(5); + writel(0, i2c->base + SPACEMIT_ICR); +} + +static int spacemit_i2c_handle_err(struct spacemit_i2c_dev *i2c) +{ + dev_dbg(i2c->dev, "i2c error status: 0x%08x\n", i2c->status); + + if (i2c->status & (SPACEMIT_SR_BED | SPACEMIT_SR_ALD)) { + spacemit_i2c_reset(i2c); + return -EAGAIN; + } + + return i2c->status & SPACEMIT_SR_ACKNAK ? -ENXIO : -EIO; +} + +static void spacemit_i2c_conditionally_reset_bus(struct spacemit_i2c_dev *i2c) +{ + u32 status; + + /* if bus is locked, reset unit. 0: locked */ + status = readl(i2c->base + SPACEMIT_IBMR); + if ((status & SPACEMIT_BMR_SDA) && (status & SPACEMIT_BMR_SCL)) + return; + + spacemit_i2c_reset(i2c); + usleep_range(10, 20); + + /* check scl status again */ + status = readl(i2c->base + SPACEMIT_IBMR); + if (!(status & SPACEMIT_BMR_SCL)) + dev_warn_ratelimited(i2c->dev, "unit reset failed\n"); +} + +static int spacemit_i2c_wait_bus_idle(struct spacemit_i2c_dev *i2c) +{ + int ret; + u32 val; + + val = readl(i2c->base + SPACEMIT_ISR); + if (!(val & (SPACEMIT_SR_UB | SPACEMIT_SR_IBB))) + return 0; + + ret = readl_poll_timeout(i2c->base + SPACEMIT_ISR, + val, !(val & (SPACEMIT_SR_UB | SPACEMIT_SR_IBB)), + 1500, SPACEMIT_I2C_BUS_BUSY_TIMEOUT); + if (ret) + spacemit_i2c_reset(i2c); + + return ret; +} + +static void spacemit_i2c_check_bus_release(struct spacemit_i2c_dev *i2c) +{ + /* in case bus is not released after transfer completes */ + if (readl(i2c->base + SPACEMIT_ISR) & SPACEMIT_SR_EBB) { + spacemit_i2c_conditionally_reset_bus(i2c); + usleep_range(90, 150); + } +} + +static void spacemit_i2c_init(struct spacemit_i2c_dev *i2c) +{ + u32 val; + + /* + * Unmask interrupt bits for all xfer mode: + * bus error, arbitration loss detected. + * For transaction complete signal, we use master stop + * interrupt, so we don't need to unmask SPACEMIT_CR_TXDONEIE. + */ + val = SPACEMIT_CR_BEIE | SPACEMIT_CR_ALDIE; + + /* + * Unmask interrupt bits for interrupt xfer mode: + * When IDBR receives a byte, an interrupt is triggered. + * + * For the tx empty interrupt, it will be enabled in the + * i2c_start function. + * Otherwise, it will cause an erroneous empty interrupt before i2c_start. + */ + val |= SPACEMIT_CR_DRFIE; + + if (i2c->clock_freq == SPACEMIT_I2C_MAX_FAST_MODE_FREQ) + val |= SPACEMIT_CR_MODE_FAST; + + /* disable response to general call */ + val |= SPACEMIT_CR_GCD; + + /* enable SCL clock output */ + val |= SPACEMIT_CR_SCLE; + + /* enable master stop detected */ + val |= SPACEMIT_CR_MSDE | SPACEMIT_CR_MSDIE; + + writel(val, i2c->base + SPACEMIT_ICR); +} + +static inline void +spacemit_i2c_clear_int_status(struct spacemit_i2c_dev *i2c, u32 mask) +{ + writel(mask & SPACEMIT_I2C_INT_STATUS_MASK, i2c->base + SPACEMIT_ISR); +} + +static void spacemit_i2c_start(struct spacemit_i2c_dev *i2c) +{ + u32 target_addr_rw, val; + struct i2c_msg *cur_msg = i2c->msgs + i2c->msg_idx; + + i2c->read = !!(cur_msg->flags & I2C_M_RD); + + i2c->state = SPACEMIT_STATE_START; + + target_addr_rw = (cur_msg->addr & 0x7f) << 1; + if (cur_msg->flags & I2C_M_RD) + target_addr_rw |= 1; + + writel(target_addr_rw, i2c->base + SPACEMIT_IDBR); + + /* send start pulse */ + val = readl(i2c->base + SPACEMIT_ICR); + val &= ~SPACEMIT_CR_STOP; + val |= SPACEMIT_CR_START | SPACEMIT_CR_TB | SPACEMIT_CR_DTEIE; + writel(val, i2c->base + SPACEMIT_ICR); +} + +static void spacemit_i2c_stop(struct spacemit_i2c_dev *i2c) +{ + u32 val; + + val = readl(i2c->base + SPACEMIT_ICR); + val |= SPACEMIT_CR_STOP | SPACEMIT_CR_ALDIE | SPACEMIT_CR_TB; + + if (i2c->read) + val |= SPACEMIT_CR_ACKNAK; + + writel(val, i2c->base + SPACEMIT_ICR); +} + +static int spacemit_i2c_xfer_msg(struct spacemit_i2c_dev *i2c) +{ + unsigned long time_left; + struct i2c_msg *msg; + + for (i2c->msg_idx = 0; i2c->msg_idx < i2c->msg_num; i2c->msg_idx++) { + msg = &i2c->msgs[i2c->msg_idx]; + i2c->msg_buf = msg->buf; + i2c->unprocessed = msg->len; + i2c->status = 0; + + reinit_completion(&i2c->complete); + + spacemit_i2c_start(i2c); + + time_left = wait_for_completion_timeout(&i2c->complete, + i2c->adapt.timeout); + if (!time_left) { + dev_err(i2c->dev, "msg completion timeout\n"); + spacemit_i2c_conditionally_reset_bus(i2c); + spacemit_i2c_reset(i2c); + return -ETIMEDOUT; + } + + if (i2c->status & SPACEMIT_SR_ERR) + return spacemit_i2c_handle_err(i2c); + } + + return 0; +} + +static bool spacemit_i2c_is_last_msg(struct spacemit_i2c_dev *i2c) +{ + if (i2c->msg_idx != i2c->msg_num - 1) + return false; + + if (i2c->read) + return i2c->unprocessed == 1; + + return !i2c->unprocessed; +} + +static void spacemit_i2c_handle_write(struct spacemit_i2c_dev *i2c) +{ + /* if transfer completes, SPACEMIT_ISR will handle it */ + if (i2c->status & SPACEMIT_SR_MSD) + return; + + if (i2c->unprocessed) { + writel(*i2c->msg_buf++, i2c->base + SPACEMIT_IDBR); + i2c->unprocessed--; + return; + } + + /* SPACEMIT_STATE_IDLE avoids trigger next byte */ + i2c->state = SPACEMIT_STATE_IDLE; + complete(&i2c->complete); +} + +static void spacemit_i2c_handle_read(struct spacemit_i2c_dev *i2c) +{ + if (i2c->unprocessed) { + *i2c->msg_buf++ = readl(i2c->base + SPACEMIT_IDBR); + i2c->unprocessed--; + } + + /* if transfer completes, SPACEMIT_ISR will handle it */ + if (i2c->status & (SPACEMIT_SR_MSD | SPACEMIT_SR_ACKNAK)) + return; + + /* it has to append stop bit in icr that read last byte */ + if (i2c->unprocessed) + return; + + /* SPACEMIT_STATE_IDLE avoids trigger next byte */ + i2c->state = SPACEMIT_STATE_IDLE; + complete(&i2c->complete); +} + +static void spacemit_i2c_handle_start(struct spacemit_i2c_dev *i2c) +{ + i2c->state = i2c->read ? SPACEMIT_STATE_READ : SPACEMIT_STATE_WRITE; + if (i2c->state == SPACEMIT_STATE_WRITE) + spacemit_i2c_handle_write(i2c); +} + +static void spacemit_i2c_err_check(struct spacemit_i2c_dev *i2c) +{ + u32 val; + + /* + * Send transaction complete signal: + * error happens, detect master stop + */ + if (!(i2c->status & (SPACEMIT_SR_ERR | SPACEMIT_SR_MSD))) + return; + + /* + * Here the transaction is already done, we don't need any + * other interrupt signals from now, in case any interrupt + * happens before spacemit_i2c_xfer to disable irq and i2c unit, + * we mask all the interrupt signals and clear the interrupt + * status. + */ + val = readl(i2c->base + SPACEMIT_ICR); + val &= ~SPACEMIT_I2C_INT_CTRL_MASK; + writel(val, i2c->base + SPACEMIT_ICR); + + spacemit_i2c_clear_int_status(i2c, SPACEMIT_I2C_INT_STATUS_MASK); + + i2c->state = SPACEMIT_STATE_IDLE; + complete(&i2c->complete); +} + +static irqreturn_t spacemit_i2c_irq_handler(int irq, void *devid) +{ + struct spacemit_i2c_dev *i2c = devid; + u32 status, val; + + status = readl(i2c->base + SPACEMIT_ISR); + if (!status) + return IRQ_HANDLED; + + i2c->status = status; + + spacemit_i2c_clear_int_status(i2c, status); + + if (i2c->status & SPACEMIT_SR_ERR) + goto err_out; + + val = readl(i2c->base + SPACEMIT_ICR); + val &= ~(SPACEMIT_CR_TB | SPACEMIT_CR_ACKNAK | SPACEMIT_CR_STOP | SPACEMIT_CR_START); + writel(val, i2c->base + SPACEMIT_ICR); + + switch (i2c->state) { + case SPACEMIT_STATE_START: + spacemit_i2c_handle_start(i2c); + break; + case SPACEMIT_STATE_READ: + spacemit_i2c_handle_read(i2c); + break; + case SPACEMIT_STATE_WRITE: + spacemit_i2c_handle_write(i2c); + break; + default: + break; + } + + if (i2c->state != SPACEMIT_STATE_IDLE) { + if (spacemit_i2c_is_last_msg(i2c)) { + /* trigger next byte with stop */ + spacemit_i2c_stop(i2c); + } else { + /* trigger next byte */ + val |= SPACEMIT_CR_ALDIE | SPACEMIT_CR_TB; + writel(val, i2c->base + SPACEMIT_ICR); + } + } + +err_out: + spacemit_i2c_err_check(i2c); + return IRQ_HANDLED; +} + +static void spacemit_i2c_calc_timeout(struct spacemit_i2c_dev *i2c) +{ + unsigned long timeout; + int idx = 0, cnt = 0; + + for (; idx < i2c->msg_num; idx++) + cnt += (i2c->msgs + idx)->len + 1; + + /* + * Multiply by 9 because each byte in I2C transmission requires + * 9 clock cycles: 8 bits of data plus 1 ACK/NACK bit. + */ + timeout = cnt * 9 * USEC_PER_SEC / i2c->clock_freq; + + i2c->adapt.timeout = usecs_to_jiffies(timeout + USEC_PER_SEC / 10) / i2c->msg_num; +} + +static int spacemit_i2c_xfer(struct i2c_adapter *adapt, struct i2c_msg *msgs, int num) +{ + struct spacemit_i2c_dev *i2c = i2c_get_adapdata(adapt); + int ret; + + i2c->msgs = msgs; + i2c->msg_num = num; + + spacemit_i2c_calc_timeout(i2c); + + spacemit_i2c_init(i2c); + + spacemit_i2c_enable(i2c); + + ret = spacemit_i2c_wait_bus_idle(i2c); + if (!ret) + ret = spacemit_i2c_xfer_msg(i2c); + else if (ret < 0) + dev_dbg(i2c->dev, "i2c transfer error: %d\n", ret); + else + spacemit_i2c_check_bus_release(i2c); + + spacemit_i2c_disable(i2c); + + if (ret == -ETIMEDOUT || ret == -EAGAIN) + dev_err(i2c->dev, "i2c transfer failed, ret %d err 0x%lx\n", + ret, i2c->status & SPACEMIT_SR_ERR); + + return ret < 0 ? ret : num; +} + +static u32 spacemit_i2c_func(struct i2c_adapter *adap) +{ + return I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK); +} + +static const struct i2c_algorithm spacemit_i2c_algo = { + .xfer = spacemit_i2c_xfer, + .functionality = spacemit_i2c_func, +}; + +static int spacemit_i2c_probe(struct platform_device *pdev) +{ + struct clk *clk; + struct device *dev = &pdev->dev; + struct device_node *of_node = pdev->dev.of_node; + struct spacemit_i2c_dev *i2c; + int ret; + + i2c = devm_kzalloc(dev, sizeof(*i2c), GFP_KERNEL); + if (!i2c) + return -ENOMEM; + + ret = of_property_read_u32(of_node, "clock-frequency", &i2c->clock_freq); + if (ret && ret != -EINVAL) + dev_warn(dev, "failed to read clock-frequency property: %d\n", ret); + + /* For now, this driver doesn't support high-speed. */ + if (!i2c->clock_freq || i2c->clock_freq > SPACEMIT_I2C_MAX_FAST_MODE_FREQ) { + dev_warn(dev, "unsupported clock frequency %u; using %u\n", + i2c->clock_freq, SPACEMIT_I2C_MAX_FAST_MODE_FREQ); + i2c->clock_freq = SPACEMIT_I2C_MAX_FAST_MODE_FREQ; + } else if (i2c->clock_freq < SPACEMIT_I2C_MAX_STANDARD_MODE_FREQ) { + dev_warn(dev, "unsupported clock frequency %u; using %u\n", + i2c->clock_freq, SPACEMIT_I2C_MAX_STANDARD_MODE_FREQ); + i2c->clock_freq = SPACEMIT_I2C_MAX_STANDARD_MODE_FREQ; + } + + i2c->dev = &pdev->dev; + + i2c->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(i2c->base)) + return dev_err_probe(dev, PTR_ERR(i2c->base), "failed to do ioremap"); + + i2c->irq = platform_get_irq(pdev, 0); + if (i2c->irq < 0) + return dev_err_probe(dev, i2c->irq, "failed to get irq resource"); + + ret = devm_request_irq(i2c->dev, i2c->irq, spacemit_i2c_irq_handler, + IRQF_NO_SUSPEND | IRQF_ONESHOT, dev_name(i2c->dev), i2c); + if (ret) + return dev_err_probe(dev, ret, "failed to request irq"); + + clk = devm_clk_get_enabled(dev, "func"); + if (IS_ERR(clk)) + return dev_err_probe(dev, PTR_ERR(clk), "failed to enable func clock"); + + clk = devm_clk_get_enabled(dev, "bus"); + if (IS_ERR(clk)) + return dev_err_probe(dev, PTR_ERR(clk), "failed to enable bus clock"); + + spacemit_i2c_reset(i2c); + + i2c_set_adapdata(&i2c->adapt, i2c); + i2c->adapt.owner = THIS_MODULE; + i2c->adapt.algo = &spacemit_i2c_algo; + i2c->adapt.dev.parent = i2c->dev; + i2c->adapt.nr = pdev->id; + + i2c->adapt.dev.of_node = of_node; + + strscpy(i2c->adapt.name, "spacemit-i2c-adapter", sizeof(i2c->adapt.name)); + + init_completion(&i2c->complete); + + platform_set_drvdata(pdev, i2c); + + ret = i2c_add_numbered_adapter(&i2c->adapt); + if (ret) + return dev_err_probe(&pdev->dev, ret, "failed to add i2c adapter"); + + return 0; +} + +static void spacemit_i2c_remove(struct platform_device *pdev) +{ + struct spacemit_i2c_dev *i2c = platform_get_drvdata(pdev); + + i2c_del_adapter(&i2c->adapt); +} + +static const struct of_device_id spacemit_i2c_of_match[] = { + { .compatible = "spacemit,k1-i2c", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, spacemit_i2c_of_match); + +static struct platform_driver spacemit_i2c_driver = { + .probe = spacemit_i2c_probe, + .remove = spacemit_i2c_remove, + .driver = { + .name = "i2c-k1", + .of_match_table = spacemit_i2c_of_match, + }, +}; +module_platform_driver(spacemit_i2c_driver); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("I2C bus driver for SpacemiT K1 SoC"); diff --git a/drivers/i2c/busses/i2c-keba.c b/drivers/i2c/busses/i2c-keba.c index 759732a07ef0..7b9ed2592f5b 100644 --- a/drivers/i2c/busses/i2c-keba.c +++ b/drivers/i2c/busses/i2c-keba.c @@ -464,12 +464,8 @@ static void ki2c_unregister_devices(struct ki2c *ki2c) { int i; - for (i = 0; i < ki2c->client_size; i++) { - struct i2c_client *client = ki2c->client[i]; - - if (client) - i2c_unregister_device(client); - } + for (i = 0; i < ki2c->client_size; i++) + i2c_unregister_device(ki2c->client[i]); } static int ki2c_register_devices(struct ki2c *ki2c) diff --git a/drivers/i2c/busses/i2c-kempld.c b/drivers/i2c/busses/i2c-kempld.c index 212196af68ba..9b4c7cba62b6 100644 --- a/drivers/i2c/busses/i2c-kempld.c +++ b/drivers/i2c/busses/i2c-kempld.c @@ -115,9 +115,7 @@ static int kempld_i2c_process(struct kempld_i2c_data *i2c) if (i2c->state == STATE_ADDR) { /* 10 bit address? */ if (i2c->msg->flags & I2C_M_TEN) { - addr = 0xf0 | ((i2c->msg->addr >> 7) & 0x6); - /* Set read bit if necessary */ - addr |= (i2c->msg->flags & I2C_M_RD) ? 1 : 0; + addr = i2c_10bit_addr_hi_from_msg(msg); i2c->state = STATE_ADDR10; } else { addr = i2c_8bit_addr_from_msg(i2c->msg); @@ -132,10 +130,12 @@ static int kempld_i2c_process(struct kempld_i2c_data *i2c) /* Second part of 10 bit addressing */ if (i2c->state == STATE_ADDR10) { - kempld_write8(pld, KEMPLD_I2C_DATA, i2c->msg->addr & 0xff); + addr = i2c_10bit_addr_lo_from_msg(msg); + i2c->state = STATE_START; + + kempld_write8(pld, KEMPLD_I2C_DATA, addr); kempld_write8(pld, KEMPLD_I2C_CMD, I2C_CMD_WRITE); - i2c->state = STATE_START; return 0; } diff --git a/drivers/i2c/busses/i2c-mlxbf.c b/drivers/i2c/busses/i2c-mlxbf.c index 21f67f3b65b6..280dde53d7f3 100644 --- a/drivers/i2c/busses/i2c-mlxbf.c +++ b/drivers/i2c/busses/i2c-mlxbf.c @@ -12,6 +12,7 @@ #include <linux/interrupt.h> #include <linux/i2c.h> #include <linux/io.h> +#include <linux/iopoll.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/mutex.h> @@ -495,65 +496,6 @@ static u8 mlxbf_i2c_bus_count; static struct mutex mlxbf_i2c_bus_lock; -/* - * Function to poll a set of bits at a specific address; it checks whether - * the bits are equal to zero when eq_zero is set to 'true', and not equal - * to zero when eq_zero is set to 'false'. - * Note that the timeout is given in microseconds. - */ -static u32 mlxbf_i2c_poll(void __iomem *io, u32 addr, u32 mask, - bool eq_zero, u32 timeout) -{ - u32 bits; - - timeout = (timeout / MLXBF_I2C_POLL_FREQ_IN_USEC) + 1; - - do { - bits = readl(io + addr) & mask; - if (eq_zero ? bits == 0 : bits != 0) - return eq_zero ? 1 : bits; - udelay(MLXBF_I2C_POLL_FREQ_IN_USEC); - } while (timeout-- != 0); - - return 0; -} - -/* - * SW must make sure that the SMBus Master GW is idle before starting - * a transaction. Accordingly, this function polls the Master FSM stop - * bit; it returns false when the bit is asserted, true if not. - */ -static bool mlxbf_i2c_smbus_master_wait_for_idle(struct mlxbf_i2c_priv *priv) -{ - u32 mask = MLXBF_I2C_SMBUS_MASTER_FSM_STOP_MASK; - u32 addr = priv->chip->smbus_master_fsm_off; - u32 timeout = MLXBF_I2C_SMBUS_TIMEOUT; - - if (mlxbf_i2c_poll(priv->mst->io, addr, mask, true, timeout)) - return true; - - return false; -} - -/* - * wait for the lock to be released before acquiring it. - */ -static bool mlxbf_i2c_smbus_master_lock(struct mlxbf_i2c_priv *priv) -{ - if (mlxbf_i2c_poll(priv->mst->io, MLXBF_I2C_SMBUS_MASTER_GW, - MLXBF_I2C_MASTER_LOCK_BIT, true, - MLXBF_I2C_SMBUS_LOCK_POLL_TIMEOUT)) - return true; - - return false; -} - -static void mlxbf_i2c_smbus_master_unlock(struct mlxbf_i2c_priv *priv) -{ - /* Clear the gw to clear the lock */ - writel(0, priv->mst->io + MLXBF_I2C_SMBUS_MASTER_GW); -} - static bool mlxbf_i2c_smbus_transaction_success(u32 master_status, u32 cause_status) { @@ -583,6 +525,7 @@ static int mlxbf_i2c_smbus_check_status(struct mlxbf_i2c_priv *priv) { u32 master_status_bits; u32 cause_status_bits; + u32 bits; /* * GW busy bit is raised by the driver and cleared by the HW @@ -591,9 +534,9 @@ static int mlxbf_i2c_smbus_check_status(struct mlxbf_i2c_priv *priv) * then read the cause and master status bits to determine if * errors occurred during the transaction. */ - mlxbf_i2c_poll(priv->mst->io, MLXBF_I2C_SMBUS_MASTER_GW, - MLXBF_I2C_MASTER_BUSY_BIT, true, - MLXBF_I2C_SMBUS_TIMEOUT); + readl_poll_timeout_atomic(priv->mst->io + MLXBF_I2C_SMBUS_MASTER_GW, + bits, !(bits & MLXBF_I2C_MASTER_BUSY_BIT), + MLXBF_I2C_POLL_FREQ_IN_USEC, MLXBF_I2C_SMBUS_TIMEOUT); /* Read cause status bits. */ cause_status_bits = readl(priv->mst_cause->io + @@ -740,7 +683,8 @@ mlxbf_i2c_smbus_start_transaction(struct mlxbf_i2c_priv *priv, u8 read_en, write_en, block_en, pec_en; u8 slave, flags, addr; u8 *read_buf; - int ret = 0; + u32 bits; + int ret; if (request->operation_cnt > MLXBF_I2C_SMBUS_MAX_OP_CNT) return -EINVAL; @@ -760,11 +704,22 @@ mlxbf_i2c_smbus_start_transaction(struct mlxbf_i2c_priv *priv, * Try to acquire the smbus gw lock before any reads of the GW register since * a read sets the lock. */ - if (WARN_ON(!mlxbf_i2c_smbus_master_lock(priv))) + ret = readl_poll_timeout_atomic(priv->mst->io + MLXBF_I2C_SMBUS_MASTER_GW, + bits, !(bits & MLXBF_I2C_MASTER_LOCK_BIT), + MLXBF_I2C_POLL_FREQ_IN_USEC, + MLXBF_I2C_SMBUS_LOCK_POLL_TIMEOUT); + if (WARN_ON(ret)) return -EBUSY; - /* Check whether the HW is idle */ - if (WARN_ON(!mlxbf_i2c_smbus_master_wait_for_idle(priv))) { + /* + * SW must make sure that the SMBus Master GW is idle before starting + * a transaction. Accordingly, this call polls the Master FSM stop bit; + * it returns -ETIMEDOUT when the bit is asserted, 0 if not. + */ + ret = readl_poll_timeout_atomic(priv->mst->io + priv->chip->smbus_master_fsm_off, + bits, !(bits & MLXBF_I2C_SMBUS_MASTER_FSM_STOP_MASK), + MLXBF_I2C_POLL_FREQ_IN_USEC, MLXBF_I2C_SMBUS_TIMEOUT); + if (WARN_ON(ret)) { ret = -EBUSY; goto out_unlock; } @@ -855,7 +810,8 @@ mlxbf_i2c_smbus_start_transaction(struct mlxbf_i2c_priv *priv, } out_unlock: - mlxbf_i2c_smbus_master_unlock(priv); + /* Clear the gw to clear the lock */ + writel(0, priv->mst->io + MLXBF_I2C_SMBUS_MASTER_GW); return ret; } @@ -1829,18 +1785,6 @@ static bool mlxbf_i2c_has_coalesce(struct mlxbf_i2c_priv *priv, bool *read, return true; } -static bool mlxbf_i2c_slave_wait_for_idle(struct mlxbf_i2c_priv *priv, - u32 timeout) -{ - u32 mask = MLXBF_I2C_CAUSE_S_GW_BUSY_FALL; - u32 addr = MLXBF_I2C_CAUSE_ARBITER; - - if (mlxbf_i2c_poll(priv->slv_cause->io, addr, mask, false, timeout)) - return true; - - return false; -} - static struct i2c_client *mlxbf_i2c_get_slave_from_addr( struct mlxbf_i2c_priv *priv, u8 addr) { @@ -1943,7 +1887,9 @@ static int mlxbf_i2c_irq_send(struct mlxbf_i2c_priv *priv, u8 recv_bytes) * Wait until the transfer is completed; the driver will wait * until the GW is idle, a cause will rise on fall of GW busy. */ - mlxbf_i2c_slave_wait_for_idle(priv, MLXBF_I2C_SMBUS_TIMEOUT); + readl_poll_timeout_atomic(priv->slv_cause->io + MLXBF_I2C_CAUSE_ARBITER, + data32, data32 & MLXBF_I2C_CAUSE_S_GW_BUSY_FALL, + MLXBF_I2C_POLL_FREQ_IN_USEC, MLXBF_I2C_SMBUS_TIMEOUT); clear_csr: /* Release the Slave GW. */ diff --git a/drivers/i2c/busses/i2c-mt7621.c b/drivers/i2c/busses/i2c-mt7621.c index 2103f21f9ddd..0a288c998419 100644 --- a/drivers/i2c/busses/i2c-mt7621.c +++ b/drivers/i2c/busses/i2c-mt7621.c @@ -164,22 +164,18 @@ static int mtk_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, /* write address */ if (pmsg->flags & I2C_M_TEN) { /* 10 bits address */ - addr = 0xf0 | ((pmsg->addr >> 7) & 0x06); - addr |= (pmsg->addr & 0xff) << 8; - if (pmsg->flags & I2C_M_RD) - addr |= 1; - iowrite32(addr, i2c->base + REG_SM0D0_REG); - ret = mtk_i2c_cmd(i2c, SM0CTL1_WRITE, 2); - if (ret) - goto err_timeout; + addr = i2c_10bit_addr_hi_from_msg(pmsg); + addr |= i2c_10bit_addr_lo_from_msg(pmsg) << 8; + len = 2; } else { /* 7 bits address */ addr = i2c_8bit_addr_from_msg(pmsg); - iowrite32(addr, i2c->base + REG_SM0D0_REG); - ret = mtk_i2c_cmd(i2c, SM0CTL1_WRITE, 1); - if (ret) - goto err_timeout; + len = 1; } + iowrite32(addr, i2c->base + REG_SM0D0_REG); + ret = mtk_i2c_cmd(i2c, SM0CTL1_WRITE, len); + if (ret) + goto err_timeout; /* check address ACK */ if (!(pmsg->flags & I2C_M_IGNORE_NAK)) { diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c index 874309580c33..8fc26a511320 100644 --- a/drivers/i2c/busses/i2c-mv64xxx.c +++ b/drivers/i2c/busses/i2c-mv64xxx.c @@ -27,7 +27,6 @@ #include <linux/err.h> #include <linux/delay.h> -#define MV64XXX_I2C_ADDR_ADDR(val) ((val & 0x7f) << 1) #define MV64XXX_I2C_BAUD_DIV_N(val) (val & 0x7) #define MV64XXX_I2C_BAUD_DIV_M(val) ((val & 0xf) << 3) @@ -176,22 +175,17 @@ static void mv64xxx_i2c_prepare_for_io(struct mv64xxx_i2c_data *drv_data, struct i2c_msg *msg) { - u32 dir = 0; - drv_data->cntl_bits = MV64XXX_I2C_REG_CONTROL_ACK | MV64XXX_I2C_REG_CONTROL_TWSIEN; if (!drv_data->atomic) drv_data->cntl_bits |= MV64XXX_I2C_REG_CONTROL_INTEN; - if (msg->flags & I2C_M_RD) - dir = 1; - if (msg->flags & I2C_M_TEN) { - drv_data->addr1 = 0xf0 | (((u32)msg->addr & 0x300) >> 7) | dir; - drv_data->addr2 = (u32)msg->addr & 0xff; + drv_data->addr1 = i2c_10bit_addr_hi_from_msg(msg); + drv_data->addr2 = i2c_10bit_addr_lo_from_msg(msg); } else { - drv_data->addr1 = MV64XXX_I2C_ADDR_ADDR((u32)msg->addr) | dir; + drv_data->addr1 = i2c_8bit_addr_from_msg(msg); drv_data->addr2 = 0; } } diff --git a/drivers/i2c/busses/i2c-npcm7xx.c b/drivers/i2c/busses/i2c-npcm7xx.c index da12e5af9064..05a140ec2b64 100644 --- a/drivers/i2c/busses/i2c-npcm7xx.c +++ b/drivers/i2c/busses/i2c-npcm7xx.c @@ -263,6 +263,265 @@ static const int npcm_i2caddr[I2C_NUM_OWN_ADDR] = { #define I2C_FREQ_MIN_HZ 10000 #define I2C_FREQ_MAX_HZ I2C_MAX_FAST_MODE_PLUS_FREQ +struct smb_timing_t { + u32 core_clk; + u8 hldt; + u8 dbcnt; + u16 sclfrq; + u8 scllt; + u8 sclht; + bool fast_mode; +}; + +static struct smb_timing_t smb_timing_100khz[] = { + { + .core_clk = 100000000, .hldt = 0x2A, .dbcnt = 0x4, + .sclfrq = 0xFB, .scllt = 0x0, .sclht = 0x0, + .fast_mode = false, + }, + { + .core_clk = 62500000, .hldt = 0x2A, .dbcnt = 0x1, + .sclfrq = 0x9D, .scllt = 0x0, .sclht = 0x0, + .fast_mode = false, + }, + { + .core_clk = 50000000, .hldt = 0x2A, .dbcnt = 0x1, + .sclfrq = 0x7E, .scllt = 0x0, .sclht = 0x0, + .fast_mode = false, + }, + { + .core_clk = 48000000, .hldt = 0x2A, .dbcnt = 0x1, + .sclfrq = 0x79, .scllt = 0x0, .sclht = 0x0, + .fast_mode = false, + }, + { + .core_clk = 40000000, .hldt = 0x2A, .dbcnt = 0x1, + .sclfrq = 0x65, .scllt = 0x0, .sclht = 0x0, + .fast_mode = false, + }, + { + .core_clk = 30000000, .hldt = 0x2A, .dbcnt = 0x1, + .sclfrq = 0x4C, .scllt = 0x0, .sclht = 0x0, + .fast_mode = false, + }, + { + .core_clk = 29000000, .hldt = 0x2A, .dbcnt = 0x1, + .sclfrq = 0x49, .scllt = 0x0, .sclht = 0x0, + .fast_mode = false, + }, + { + .core_clk = 26000000, .hldt = 0x2A, .dbcnt = 0x1, + .sclfrq = 0x42, .scllt = 0x0, .sclht = 0x0, + .fast_mode = false, + }, + { + .core_clk = 25000000, .hldt = 0x2A, .dbcnt = 0x1, + .sclfrq = 0x3F, .scllt = 0x0, .sclht = 0x0, + .fast_mode = false, + }, + { + .core_clk = 24000000, .hldt = 0x2A, .dbcnt = 0x1, + .sclfrq = 0x3D, .scllt = 0x0, .sclht = 0x0, + .fast_mode = false, + }, + { + .core_clk = 20000000, .hldt = 0x2A, .dbcnt = 0x1, + .sclfrq = 0x33, .scllt = 0x0, .sclht = 0x0, + .fast_mode = false, + }, + { + .core_clk = 16180000, .hldt = 0x2A, .dbcnt = 0x1, + .sclfrq = 0x29, .scllt = 0x0, .sclht = 0x0, + .fast_mode = false, + }, + { + .core_clk = 15000000, .hldt = 0x23, .dbcnt = 0x1, + .sclfrq = 0x26, .scllt = 0x0, .sclht = 0x0, + .fast_mode = false, + }, + { + .core_clk = 13000000, .hldt = 0x1D, .dbcnt = 0x1, + .sclfrq = 0x21, .scllt = 0x0, .sclht = 0x0, + .fast_mode = false, + }, + { + .core_clk = 12000000, .hldt = 0x1B, .dbcnt = 0x1, + .sclfrq = 0x1F, .scllt = 0x0, .sclht = 0x0, + .fast_mode = false, + }, + { + .core_clk = 10000000, .hldt = 0x18, .dbcnt = 0x1, + .sclfrq = 0x1A, .scllt = 0x0, .sclht = 0x0, + .fast_mode = false, + }, + { + .core_clk = 9000000, .hldt = 0x16, .dbcnt = 0x1, + .sclfrq = 0x17, .scllt = 0x0, .sclht = 0x0, + .fast_mode = false, + }, + { + .core_clk = 8090000, .hldt = 0x14, .dbcnt = 0x1, + .sclfrq = 0x15, .scllt = 0x0, .sclht = 0x0, + .fast_mode = false, + }, + { + .core_clk = 7500000, .hldt = 0x7, .dbcnt = 0x1, + .sclfrq = 0x13, .scllt = 0x0, .sclht = 0x0, + .fast_mode = false, + }, + { + .core_clk = 6500000, .hldt = 0xE, .dbcnt = 0x1, + .sclfrq = 0x11, .scllt = 0x0, .sclht = 0x0, + .fast_mode = false, + }, + { + .core_clk = 4000000, .hldt = 0x9, .dbcnt = 0x1, + .sclfrq = 0xB, .scllt = 0x0, .sclht = 0x0, + .fast_mode = false, + }, +}; + +static struct smb_timing_t smb_timing_400khz[] = { + { + .core_clk = 100000000, .hldt = 0x2A, .dbcnt = 0x3, + .sclfrq = 0x0, .scllt = 0x47, .sclht = 0x35, + .fast_mode = true, + }, + { + .core_clk = 62500000, .hldt = 0x2A, .dbcnt = 0x2, + .sclfrq = 0x0, .scllt = 0x2C, .sclht = 0x22, + .fast_mode = true, + }, + { + .core_clk = 50000000, .hldt = 0x21, .dbcnt = 0x1, + .sclfrq = 0x0, .scllt = 0x24, .sclht = 0x1B, + .fast_mode = true, + }, + { + .core_clk = 48000000, .hldt = 0x1E, .dbcnt = 0x1, + .sclfrq = 0x0, .scllt = 0x24, .sclht = 0x19, + .fast_mode = true, + }, + { + .core_clk = 40000000, .hldt = 0x1B, .dbcnt = 0x1, + .sclfrq = 0x0, .scllt = 0x1E, .sclht = 0x14, + .fast_mode = true, + }, + { + .core_clk = 33000000, .hldt = 0x15, .dbcnt = 0x1, + .sclfrq = 0x0, .scllt = 0x19, .sclht = 0x11, + .fast_mode = true, + }, + { + .core_clk = 30000000, .hldt = 0x15, .dbcnt = 0x1, + .sclfrq = 0x0, .scllt = 0x19, .sclht = 0xD, + .fast_mode = true, + }, + { + .core_clk = 29000000, .hldt = 0x11, .dbcnt = 0x1, + .sclfrq = 0x0, .scllt = 0x15, .sclht = 0x10, + .fast_mode = true, + }, + { + .core_clk = 26000000, .hldt = 0x10, .dbcnt = 0x1, + .sclfrq = 0x0, .scllt = 0x13, .sclht = 0xE, + .fast_mode = true, + }, + { + .core_clk = 25000000, .hldt = 0xF, .dbcnt = 0x1, + .sclfrq = 0x0, .scllt = 0x13, .sclht = 0xD, + .fast_mode = true, + }, + { + .core_clk = 24000000, .hldt = 0xD, .dbcnt = 0x1, + .sclfrq = 0x0, .scllt = 0x12, .sclht = 0xD, + .fast_mode = true, + }, + { + .core_clk = 20000000, .hldt = 0xB, .dbcnt = 0x1, + .sclfrq = 0x0, .scllt = 0xF, .sclht = 0xA, + .fast_mode = true, + }, + { + .core_clk = 16180000, .hldt = 0xA, .dbcnt = 0x1, + .sclfrq = 0x0, .scllt = 0xC, .sclht = 0x9, + .fast_mode = true, + }, + { + .core_clk = 15000000, .hldt = 0x9, .dbcnt = 0x1, + .sclfrq = 0x0, .scllt = 0xB, .sclht = 0x8, + .fast_mode = true, + }, + { + .core_clk = 13000000, .hldt = 0x7, .dbcnt = 0x1, + .sclfrq = 0x0, .scllt = 0xA, .sclht = 0x7, + .fast_mode = true, + }, + { + .core_clk = 12000000, .hldt = 0x7, .dbcnt = 0x1, + .sclfrq = 0x0, .scllt = 0xA, .sclht = 0x6, + .fast_mode = true, + }, + { + .core_clk = 10000000, .hldt = 0x6, .dbcnt = 0x1, + .sclfrq = 0x0, .scllt = 0x8, .sclht = 0x5, + .fast_mode = true, + }, +}; + +static struct smb_timing_t smb_timing_1000khz[] = { + { + .core_clk = 100000000, .hldt = 0x15, .dbcnt = 0x4, + .sclfrq = 0x0, .scllt = 0x1C, .sclht = 0x15, + .fast_mode = true, + }, + { + .core_clk = 62500000, .hldt = 0xF, .dbcnt = 0x3, + .sclfrq = 0x0, .scllt = 0x11, .sclht = 0xE, + .fast_mode = true, + }, + { + .core_clk = 50000000, .hldt = 0xA, .dbcnt = 0x2, + .sclfrq = 0x0, .scllt = 0xE, .sclht = 0xB, + .fast_mode = true, + }, + { + .core_clk = 48000000, .hldt = 0x9, .dbcnt = 0x2, + .sclfrq = 0x0, .scllt = 0xD, .sclht = 0xB, + .fast_mode = true, + }, + { + .core_clk = 41000000, .hldt = 0x9, .dbcnt = 0x2, + .sclfrq = 0x0, .scllt = 0xC, .sclht = 0x9, + .fast_mode = true, + }, + { + .core_clk = 40000000, .hldt = 0x8, .dbcnt = 0x2, + .sclfrq = 0x0, .scllt = 0xB, .sclht = 0x9, + .fast_mode = true, + }, + { + .core_clk = 33000000, .hldt = 0x7, .dbcnt = 0x1, + .sclfrq = 0x0, .scllt = 0xA, .sclht = 0x7, + .fast_mode = true, + }, + { + .core_clk = 25000000, .hldt = 0x4, .dbcnt = 0x1, + .sclfrq = 0x0, .scllt = 0x7, .sclht = 0x6, + .fast_mode = true, + }, + { + .core_clk = 24000000, .hldt = 0x7, .dbcnt = 0x1, + .sclfrq = 0x0, .scllt = 0x8, .sclht = 0x5, + .fast_mode = true, + }, + { + .core_clk = 20000000, .hldt = 0x4, .dbcnt = 0x1, + .sclfrq = 0x0, .scllt = 0x6, .sclht = 0x4, + .fast_mode = true, + }, +}; + struct npcm_i2c_data { u8 fifo_size; u32 segctl_init_val; @@ -1666,6 +1925,12 @@ static int npcm_i2c_int_master_handler(struct npcm_i2c *bus) (FIELD_GET(NPCM_I2CCST3_EO_BUSY, ioread8(bus->reg + NPCM_I2CCST3)))) { npcm_i2c_irq_handle_eob(bus); +#if IS_ENABLED(CONFIG_I2C_SLAVE) + /* reenable slave if it was enabled */ + if (bus->slave) + iowrite8(bus->slave->addr | NPCM_I2CADDR_SAEN, + bus->reg + NPCM_I2CADDR1); +#endif return 0; } @@ -1805,102 +2070,45 @@ static void npcm_i2c_recovery_init(struct i2c_adapter *_adap) */ static int npcm_i2c_init_clk(struct npcm_i2c *bus, u32 bus_freq_hz) { - u32 k1 = 0; - u32 k2 = 0; - u8 dbnct = 0; - u32 sclfrq = 0; - u8 hldt = 7; + struct smb_timing_t *smb_timing; + u8 scl_table_cnt = 0, table_size = 0; u8 fast_mode = 0; - u32 src_clk_khz; - u32 bus_freq_khz; - src_clk_khz = bus->apb_clk / 1000; - bus_freq_khz = bus_freq_hz / 1000; bus->bus_freq = bus_freq_hz; - /* 100KHz and below: */ - if (bus_freq_hz <= I2C_MAX_STANDARD_MODE_FREQ) { - sclfrq = src_clk_khz / (bus_freq_khz * 4); - - if (sclfrq < SCLFRQ_MIN || sclfrq > SCLFRQ_MAX) - return -EDOM; - - if (src_clk_khz >= 40000) - hldt = 17; - else if (src_clk_khz >= 12500) - hldt = 15; - else - hldt = 7; - } - - /* 400KHz: */ - else if (bus_freq_hz <= I2C_MAX_FAST_MODE_FREQ) { - sclfrq = 0; + switch (bus_freq_hz) { + case I2C_MAX_STANDARD_MODE_FREQ: + smb_timing = smb_timing_100khz; + table_size = ARRAY_SIZE(smb_timing_100khz); + break; + case I2C_MAX_FAST_MODE_FREQ: + smb_timing = smb_timing_400khz; + table_size = ARRAY_SIZE(smb_timing_400khz); fast_mode = I2CCTL3_400K_MODE; - - if (src_clk_khz < 7500) - /* 400KHZ cannot be supported for core clock < 7.5MHz */ - return -EDOM; - - else if (src_clk_khz >= 50000) { - k1 = 80; - k2 = 48; - hldt = 12; - dbnct = 7; - } - - /* Master or Slave with frequency > 25MHz */ - else if (src_clk_khz > 25000) { - hldt = clk_coef(src_clk_khz, 300) + 7; - k1 = clk_coef(src_clk_khz, 1600); - k2 = clk_coef(src_clk_khz, 900); - } - } - - /* 1MHz: */ - else if (bus_freq_hz <= I2C_MAX_FAST_MODE_PLUS_FREQ) { - sclfrq = 0; + break; + case I2C_MAX_FAST_MODE_PLUS_FREQ: + smb_timing = smb_timing_1000khz; + table_size = ARRAY_SIZE(smb_timing_1000khz); fast_mode = I2CCTL3_400K_MODE; - - /* 1MHZ cannot be supported for core clock < 24 MHz */ - if (src_clk_khz < 24000) - return -EDOM; - - k1 = clk_coef(src_clk_khz, 620); - k2 = clk_coef(src_clk_khz, 380); - - /* Core clk > 40 MHz */ - if (src_clk_khz > 40000) { - /* - * Set HLDT: - * SDA hold time: (HLDT-7) * T(CLK) >= 120 - * HLDT = 120/T(CLK) + 7 = 120 * FREQ(CLK) + 7 - */ - hldt = clk_coef(src_clk_khz, 120) + 7; - } else { - hldt = 7; - dbnct = 2; - } + break; + default: + return -EINVAL; } - /* Frequency larger than 1 MHz is not supported */ - else - return -EINVAL; + for (scl_table_cnt = 0; scl_table_cnt < table_size; scl_table_cnt++) + if (bus->apb_clk >= smb_timing[scl_table_cnt].core_clk) + break; - if (bus_freq_hz >= I2C_MAX_FAST_MODE_FREQ) { - k1 = round_up(k1, 2); - k2 = round_up(k2 + 1, 2); - if (k1 < SCLFRQ_MIN || k1 > SCLFRQ_MAX || - k2 < SCLFRQ_MIN || k2 > SCLFRQ_MAX) - return -EDOM; - } + if (scl_table_cnt == table_size) + return -EINVAL; /* write sclfrq value. bits [6:0] are in I2CCTL2 reg */ - iowrite8(FIELD_PREP(I2CCTL2_SCLFRQ6_0, sclfrq & 0x7F), + iowrite8(FIELD_PREP(I2CCTL2_SCLFRQ6_0, smb_timing[scl_table_cnt].sclfrq & 0x7F), bus->reg + NPCM_I2CCTL2); /* bits [8:7] are in I2CCTL3 reg */ - iowrite8(fast_mode | FIELD_PREP(I2CCTL3_SCLFRQ8_7, (sclfrq >> 7) & 0x3), + iowrite8(FIELD_PREP(I2CCTL3_SCLFRQ8_7, (smb_timing[scl_table_cnt].sclfrq >> 7) & 0x3) | + fast_mode, bus->reg + NPCM_I2CCTL3); /* Select Bank 0 to access NPCM_I2CCTL4/NPCM_I2CCTL5 */ @@ -1912,13 +2120,13 @@ static int npcm_i2c_init_clk(struct npcm_i2c *bus, u32 bus_freq_hz) * k1 = 2 * SCLLT7-0 -> Low Time = k1 / 2 * k2 = 2 * SCLLT7-0 -> High Time = k2 / 2 */ - iowrite8(k1 / 2, bus->reg + NPCM_I2CSCLLT); - iowrite8(k2 / 2, bus->reg + NPCM_I2CSCLHT); + iowrite8(smb_timing[scl_table_cnt].scllt, bus->reg + NPCM_I2CSCLLT); + iowrite8(smb_timing[scl_table_cnt].sclht, bus->reg + NPCM_I2CSCLHT); - iowrite8(dbnct, bus->reg + NPCM_I2CCTL5); + iowrite8(smb_timing[scl_table_cnt].dbcnt, bus->reg + NPCM_I2CCTL5); } - iowrite8(hldt, bus->reg + NPCM_I2CCTL4); + iowrite8(smb_timing[scl_table_cnt].hldt, bus->reg + NPCM_I2CCTL4); /* Return to Bank 1, and stay there by default: */ npcm_i2c_select_bank(bus, I2C_BANK_1); @@ -1970,10 +2178,14 @@ static int npcm_i2c_init_module(struct npcm_i2c *bus, enum i2c_mode mode, /* Check HW is OK: SDA and SCL should be high at this point. */ if ((npcm_i2c_get_SDA(&bus->adap) == 0) || (npcm_i2c_get_SCL(&bus->adap) == 0)) { - dev_err(bus->dev, "I2C%d init fail: lines are low\n", bus->num); - dev_err(bus->dev, "SDA=%d SCL=%d\n", npcm_i2c_get_SDA(&bus->adap), - npcm_i2c_get_SCL(&bus->adap)); - return -ENXIO; + dev_warn(bus->dev, " I2C%d SDA=%d SCL=%d, attempting to recover\n", bus->num, + npcm_i2c_get_SDA(&bus->adap), npcm_i2c_get_SCL(&bus->adap)); + if (npcm_i2c_recovery_tgclk(&bus->adap)) { + dev_err(bus->dev, "I2C%d init fail: SDA=%d SCL=%d\n", + bus->num, npcm_i2c_get_SDA(&bus->adap), + npcm_i2c_get_SCL(&bus->adap)); + return -ENXIO; + } } npcm_i2c_int_enable(bus, true); @@ -2035,7 +2247,7 @@ static irqreturn_t npcm_i2c_bus_irq(int irq, void *dev_id) } static bool npcm_i2c_master_start_xmit(struct npcm_i2c *bus, - u8 slave_addr, u16 nwrite, u16 nread, + u16 nwrite, u16 nread, u8 *write_data, u8 *read_data, bool use_PEC, bool use_read_block) { @@ -2043,7 +2255,6 @@ static bool npcm_i2c_master_start_xmit(struct npcm_i2c *bus, bus->cmd_err = -EBUSY; return false; } - bus->dest_addr = slave_addr << 1; bus->wr_buf = write_data; bus->wr_size = nwrite; bus->wr_ind = 0; @@ -2086,7 +2297,6 @@ static int npcm_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, unsigned long time_left, flags; u16 nwrite, nread; u8 *write_data, *read_data; - u8 slave_addr; unsigned long timeout; bool read_block = false; bool read_PEC = false; @@ -2099,7 +2309,6 @@ static int npcm_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, } msg0 = &msgs[0]; - slave_addr = msg0->addr; if (msg0->flags & I2C_M_RD) { /* read */ nwrite = 0; write_data = NULL; @@ -2132,19 +2341,12 @@ static int npcm_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, } } - /* - * Adaptive TimeOut: estimated time in usec + 100% margin: - * 2: double the timeout for clock stretching case - * 9: bits per transaction (including the ack/nack) - */ - timeout_usec = (2 * 9 * USEC_PER_SEC / bus->bus_freq) * (2 + nread + nwrite); - timeout = max_t(unsigned long, bus->adap.timeout, usecs_to_jiffies(timeout_usec)); if (nwrite >= 32 * 1024 || nread >= 32 * 1024) { dev_err(bus->dev, "i2c%d buffer too big\n", bus->num); return -EINVAL; } - time_left = jiffies + timeout + 1; + time_left = jiffies + bus->adap.timeout / bus->adap.retries + 1; do { /* * we must clear slave address immediately when the bus is not @@ -2163,6 +2365,21 @@ static int npcm_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, } while (time_is_after_jiffies(time_left) && bus_busy); /* + * Store the address early in a global position to ensure it is + * accessible for a potential call to i2c_recover_bus(). + * + * Since the transfer might be a read operation, remove the I2C_M_RD flag + * from the bus->dest_addr for the i2c_recover_bus() call later. + * + * The i2c_recover_bus() uses the address in a write direction to recover + * the i2c bus if some error condition occurs. + * + * Remove the I2C_M_RD flag from the address since npcm_i2c_master_start_xmit() + * handles the read/write operation internally. + */ + bus->dest_addr = i2c_8bit_addr_from_msg(msg0) & ~I2C_M_RD; + + /* * Check the BER (bus error) state, when ber_state is true, it means that the module * detects the bus error which is caused by some factor like that the electricity * noise occurs on the bus. Under this condition, the module is reset and the bus @@ -2179,7 +2396,6 @@ static int npcm_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, } npcm_i2c_init_params(bus); - bus->dest_addr = slave_addr; bus->msgs = msgs; bus->msgs_num = num; bus->cmd_err = 0; @@ -2189,9 +2405,17 @@ static int npcm_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, npcm_i2c_int_enable(bus, true); - if (npcm_i2c_master_start_xmit(bus, slave_addr, nwrite, nread, + if (npcm_i2c_master_start_xmit(bus, nwrite, nread, write_data, read_data, read_PEC, read_block)) { + /* + * Adaptive TimeOut: estimated time in usec + 100% margin: + * 2: double the timeout for clock stretching case + * 9: bits per transaction (including the ack/nack) + */ + timeout_usec = (2 * 9 * USEC_PER_SEC / bus->bus_freq) * (2 + nread + nwrite); + timeout = max_t(unsigned long, bus->adap.timeout / bus->adap.retries, + usecs_to_jiffies(timeout_usec)); time_left = wait_for_completion_timeout(&bus->cmd_complete, timeout); @@ -2317,7 +2541,12 @@ static int npcm_i2c_probe_bus(struct platform_device *pdev) adap = &bus->adap; adap->owner = THIS_MODULE; adap->retries = 3; - adap->timeout = msecs_to_jiffies(35); + /* + * The users want to connect a lot of masters on the same bus. + * This timeout is used to determine the time it takes to take bus ownership. + * The transactions are very long, so waiting 35ms is not enough. + */ + adap->timeout = 2 * HZ; adap->algo = &npcm_i2c_algo; adap->quirks = &npcm_i2c_quirks; adap->algo_data = bus; diff --git a/drivers/i2c/busses/i2c-octeon-core.c b/drivers/i2c/busses/i2c-octeon-core.c index 16cc34a0526e..baf6b27f3752 100644 --- a/drivers/i2c/busses/i2c-octeon-core.c +++ b/drivers/i2c/busses/i2c-octeon-core.c @@ -45,7 +45,7 @@ static bool octeon_i2c_test_iflg(struct octeon_i2c *i2c) * octeon_i2c_wait - wait for the IFLG to be set * @i2c: The struct octeon_i2c * - * Returns 0 on success, otherwise a negative errno. + * Returns: 0 on success, otherwise a negative errno. */ static int octeon_i2c_wait(struct octeon_i2c *i2c) { @@ -139,7 +139,7 @@ static void octeon_i2c_hlc_disable(struct octeon_i2c *i2c) * octeon_i2c_hlc_wait - wait for an HLC operation to complete * @i2c: The struct octeon_i2c * - * Returns 0 on success, otherwise -ETIMEDOUT. + * Returns: 0 on success, otherwise -ETIMEDOUT. */ static int octeon_i2c_hlc_wait(struct octeon_i2c *i2c) { @@ -273,7 +273,7 @@ static int octeon_i2c_recovery(struct octeon_i2c *i2c) * octeon_i2c_start - send START to the bus * @i2c: The struct octeon_i2c * - * Returns 0 on success, otherwise a negative errno. + * Returns: 0 on success, otherwise a negative errno. */ static int octeon_i2c_start(struct octeon_i2c *i2c) { @@ -314,7 +314,7 @@ static void octeon_i2c_stop(struct octeon_i2c *i2c) * * The address is sent over the bus, then the data is read. * - * Returns 0 on success, otherwise a negative errno. + * Returns: 0 on success, otherwise a negative errno. */ static int octeon_i2c_read(struct octeon_i2c *i2c, int target, u8 *data, u16 *rlength, bool recv_len) @@ -382,7 +382,7 @@ static int octeon_i2c_read(struct octeon_i2c *i2c, int target, * * The address is sent over the bus, then the data. * - * Returns 0 on success, otherwise a negative errno. + * Returns: 0 on success, otherwise a negative errno. */ static int octeon_i2c_write(struct octeon_i2c *i2c, int target, const u8 *data, int length) @@ -421,17 +421,12 @@ static int octeon_i2c_hlc_read(struct octeon_i2c *i2c, struct i2c_msg *msgs) octeon_i2c_hlc_enable(i2c); octeon_i2c_hlc_int_clear(i2c); - cmd = SW_TWSI_V | SW_TWSI_R | SW_TWSI_SOVR; + cmd = SW_TWSI_V | SW_TWSI_R | SW_TWSI_SOVR | SW_TWSI_OP_7; /* SIZE */ cmd |= (u64)(msgs[0].len - 1) << SW_TWSI_SIZE_SHIFT; /* A */ cmd |= (u64)(msgs[0].addr & 0x7full) << SW_TWSI_ADDR_SHIFT; - if (msgs[0].flags & I2C_M_TEN) - cmd |= SW_TWSI_OP_10; - else - cmd |= SW_TWSI_OP_7; - octeon_i2c_writeq_flush(cmd, i2c->twsi_base + OCTEON_REG_SW_TWSI(i2c)); ret = octeon_i2c_hlc_wait(i2c); if (ret) @@ -463,17 +458,12 @@ static int octeon_i2c_hlc_write(struct octeon_i2c *i2c, struct i2c_msg *msgs) octeon_i2c_hlc_enable(i2c); octeon_i2c_hlc_int_clear(i2c); - cmd = SW_TWSI_V | SW_TWSI_SOVR; + cmd = SW_TWSI_V | SW_TWSI_SOVR | SW_TWSI_OP_7; /* SIZE */ cmd |= (u64)(msgs[0].len - 1) << SW_TWSI_SIZE_SHIFT; /* A */ cmd |= (u64)(msgs[0].addr & 0x7full) << SW_TWSI_ADDR_SHIFT; - if (msgs[0].flags & I2C_M_TEN) - cmd |= SW_TWSI_OP_10; - else - cmd |= SW_TWSI_OP_7; - for (i = 0, j = msgs[0].len - 1; i < msgs[0].len && i < 4; i++, j--) cmd |= (u64)msgs[0].buf[j] << (8 * i); @@ -498,6 +488,45 @@ err: return ret; } +/* Process hlc transaction */ +static int octeon_i2c_hlc_cmd_send(struct octeon_i2c *i2c, u64 cmd) +{ + octeon_i2c_hlc_int_clear(i2c); + octeon_i2c_writeq_flush(cmd, i2c->twsi_base + OCTEON_REG_SW_TWSI(i2c)); + + return octeon_i2c_hlc_wait(i2c); +} + +/* Generic consideration for extended internal addresses in i2c hlc r/w ops */ +static bool octeon_i2c_hlc_ext(struct octeon_i2c *i2c, struct i2c_msg msg, u64 *cmd_in, u64 *ext) +{ + bool set_ext = false; + u64 cmd = 0; + + if (msg.len == 2) { + cmd |= SW_TWSI_EIA; + *ext = (u64)msg.buf[0] << SW_TWSI_IA_SHIFT; + cmd |= (u64)msg.buf[1] << SW_TWSI_IA_SHIFT; + set_ext = true; + } else { + cmd |= (u64)msg.buf[0] << SW_TWSI_IA_SHIFT; + } + + *cmd_in |= cmd; + return set_ext; +} + +/* Construct and send i2c transaction core cmd for read ops */ +static int octeon_i2c_hlc_read_cmd(struct octeon_i2c *i2c, struct i2c_msg msg, u64 cmd) +{ + u64 ext = 0; + + if (octeon_i2c_hlc_ext(i2c, msg, &cmd, &ext)) + octeon_i2c_writeq_flush(ext, i2c->twsi_base + OCTEON_REG_SW_TWSI_EXT(i2c)); + + return octeon_i2c_hlc_cmd_send(i2c, cmd); +} + /* high-level-controller composite write+read, msg0=addr, msg1=data */ static int octeon_i2c_hlc_comp_read(struct octeon_i2c *i2c, struct i2c_msg *msgs) { @@ -506,32 +535,14 @@ static int octeon_i2c_hlc_comp_read(struct octeon_i2c *i2c, struct i2c_msg *msgs octeon_i2c_hlc_enable(i2c); - cmd = SW_TWSI_V | SW_TWSI_R | SW_TWSI_SOVR; + cmd = SW_TWSI_V | SW_TWSI_R | SW_TWSI_SOVR | SW_TWSI_OP_7_IA; /* SIZE */ cmd |= (u64)(msgs[1].len - 1) << SW_TWSI_SIZE_SHIFT; /* A */ cmd |= (u64)(msgs[0].addr & 0x7full) << SW_TWSI_ADDR_SHIFT; - if (msgs[0].flags & I2C_M_TEN) - cmd |= SW_TWSI_OP_10_IA; - else - cmd |= SW_TWSI_OP_7_IA; - - if (msgs[0].len == 2) { - u64 ext = 0; - - cmd |= SW_TWSI_EIA; - ext = (u64)msgs[0].buf[0] << SW_TWSI_IA_SHIFT; - cmd |= (u64)msgs[0].buf[1] << SW_TWSI_IA_SHIFT; - octeon_i2c_writeq_flush(ext, i2c->twsi_base + OCTEON_REG_SW_TWSI_EXT(i2c)); - } else { - cmd |= (u64)msgs[0].buf[0] << SW_TWSI_IA_SHIFT; - } - - octeon_i2c_hlc_int_clear(i2c); - octeon_i2c_writeq_flush(cmd, i2c->twsi_base + OCTEON_REG_SW_TWSI(i2c)); - - ret = octeon_i2c_hlc_wait(i2c); + /* Send core command */ + ret = octeon_i2c_hlc_read_cmd(i2c, msgs[0], cmd); if (ret) goto err; @@ -561,25 +572,14 @@ static int octeon_i2c_hlc_comp_write(struct octeon_i2c *i2c, struct i2c_msg *msg octeon_i2c_hlc_enable(i2c); - cmd = SW_TWSI_V | SW_TWSI_SOVR; + cmd = SW_TWSI_V | SW_TWSI_SOVR | SW_TWSI_OP_7_IA; /* SIZE */ cmd |= (u64)(msgs[1].len - 1) << SW_TWSI_SIZE_SHIFT; /* A */ cmd |= (u64)(msgs[0].addr & 0x7full) << SW_TWSI_ADDR_SHIFT; - if (msgs[0].flags & I2C_M_TEN) - cmd |= SW_TWSI_OP_10_IA; - else - cmd |= SW_TWSI_OP_7_IA; - - if (msgs[0].len == 2) { - cmd |= SW_TWSI_EIA; - ext |= (u64)msgs[0].buf[0] << SW_TWSI_IA_SHIFT; - set_ext = true; - cmd |= (u64)msgs[0].buf[1] << SW_TWSI_IA_SHIFT; - } else { - cmd |= (u64)msgs[0].buf[0] << SW_TWSI_IA_SHIFT; - } + /* Set parameters for extended message (if required) */ + set_ext = octeon_i2c_hlc_ext(i2c, msgs[0], &cmd, &ext); for (i = 0, j = msgs[1].len - 1; i < msgs[1].len && i < 4; i++, j--) cmd |= (u64)msgs[1].buf[j] << (8 * i); @@ -592,10 +592,7 @@ static int octeon_i2c_hlc_comp_write(struct octeon_i2c *i2c, struct i2c_msg *msg if (set_ext) octeon_i2c_writeq_flush(ext, i2c->twsi_base + OCTEON_REG_SW_TWSI_EXT(i2c)); - octeon_i2c_hlc_int_clear(i2c); - octeon_i2c_writeq_flush(cmd, i2c->twsi_base + OCTEON_REG_SW_TWSI(i2c)); - - ret = octeon_i2c_hlc_wait(i2c); + ret = octeon_i2c_hlc_cmd_send(i2c, cmd); if (ret) goto err; @@ -613,7 +610,7 @@ err: * @msgs: Pointer to the messages to be processed * @num: Length of the MSGS array * - * Returns the number of messages processed, or a negative errno on failure. + * Returns: the number of messages processed, or a negative errno on failure. */ int octeon_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) { diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index 92faf03d64cf..60e70b25c87f 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -24,6 +24,7 @@ #include <linux/platform_device.h> #include <linux/clk.h> #include <linux/io.h> +#include <linux/mux/consumer.h> #include <linux/of.h> #include <linux/slab.h> #include <linux/platform_data/i2c-omap.h> @@ -211,6 +212,7 @@ struct omap_i2c_dev { u16 syscstate; u16 westate; u16 errata; + struct mux_state *mux_state; }; static const u8 reg_map_ip_v1[] = { @@ -1048,23 +1050,6 @@ static int omap_i2c_transmit_data(struct omap_i2c_dev *omap, u8 num_bytes, return 0; } -static irqreturn_t -omap_i2c_isr(int irq, void *dev_id) -{ - struct omap_i2c_dev *omap = dev_id; - irqreturn_t ret = IRQ_HANDLED; - u16 mask; - u16 stat; - - stat = omap_i2c_read_reg(omap, OMAP_I2C_STAT_REG); - mask = omap_i2c_read_reg(omap, OMAP_I2C_IE_REG) & ~OMAP_I2C_STAT_NACK; - - if (stat & mask) - ret = IRQ_WAKE_THREAD; - - return ret; -} - static int omap_i2c_xfer_data(struct omap_i2c_dev *omap) { u16 bits; @@ -1095,8 +1080,13 @@ static int omap_i2c_xfer_data(struct omap_i2c_dev *omap) } if (stat & OMAP_I2C_STAT_NACK) { - err |= OMAP_I2C_STAT_NACK; + omap->cmd_err |= OMAP_I2C_STAT_NACK; omap_i2c_ack_stat(omap, OMAP_I2C_STAT_NACK); + + if (!(stat & ~OMAP_I2C_STAT_NACK)) { + err = -EAGAIN; + break; + } } if (stat & OMAP_I2C_STAT_AL) { @@ -1464,15 +1454,34 @@ omap_i2c_probe(struct platform_device *pdev) (1000 * omap->speed / 8); } + if (of_property_present(node, "mux-states")) { + struct mux_state *mux_state; + + mux_state = devm_mux_state_get(&pdev->dev, NULL); + if (IS_ERR(mux_state)) { + r = PTR_ERR(mux_state); + dev_dbg(&pdev->dev, "failed to get I2C mux: %d\n", r); + goto err_put_pm; + } + omap->mux_state = mux_state; + r = mux_state_select(omap->mux_state); + if (r) { + dev_err(&pdev->dev, "failed to select I2C mux: %d\n", r); + goto err_put_pm; + } + } + /* reset ASAP, clearing any IRQs */ - omap_i2c_init(omap); + r = omap_i2c_init(omap); + if (r) + goto err_mux_state_deselect; if (omap->rev < OMAP_I2C_OMAP1_REV_2) r = devm_request_irq(&pdev->dev, omap->irq, omap_i2c_omap1_isr, IRQF_NO_SUSPEND, pdev->name, omap); else r = devm_request_threaded_irq(&pdev->dev, omap->irq, - omap_i2c_isr, omap_i2c_isr_thread, + NULL, omap_i2c_isr_thread, IRQF_NO_SUSPEND | IRQF_ONESHOT, pdev->name, omap); @@ -1508,9 +1517,13 @@ omap_i2c_probe(struct platform_device *pdev) err_unuse_clocks: omap_i2c_write_reg(omap, OMAP_I2C_CON_REG, 0); - pm_runtime_dont_use_autosuspend(omap->dev); +err_mux_state_deselect: + if (omap->mux_state) + mux_state_deselect(omap->mux_state); +err_put_pm: pm_runtime_put_sync(omap->dev); err_disable_pm: + pm_runtime_dont_use_autosuspend(omap->dev); pm_runtime_disable(&pdev->dev); return r; @@ -1523,6 +1536,9 @@ static void omap_i2c_remove(struct platform_device *pdev) i2c_del_adapter(&omap->adapter); + if (omap->mux_state) + mux_state_deselect(omap->mux_state); + ret = pm_runtime_get_sync(&pdev->dev); if (ret < 0) dev_err(omap->dev, "Failed to resume hardware, skip disable\n"); diff --git a/drivers/i2c/busses/i2c-pasemi-core.c b/drivers/i2c/busses/i2c-pasemi-core.c index dac694a9d781..27ab09854c92 100644 --- a/drivers/i2c/busses/i2c-pasemi-core.c +++ b/drivers/i2c/busses/i2c-pasemi-core.c @@ -5,6 +5,7 @@ * SMBus host driver for PA Semi PWRficient */ +#include <linux/bitfield.h> #include <linux/module.h> #include <linux/pci.h> #include <linux/kernel.h> @@ -26,21 +27,30 @@ #define REG_REV 0x28 /* Register defs */ -#define MTXFIFO_READ 0x00000400 -#define MTXFIFO_STOP 0x00000200 -#define MTXFIFO_START 0x00000100 -#define MTXFIFO_DATA_M 0x000000ff - -#define MRXFIFO_EMPTY 0x00000100 -#define MRXFIFO_DATA_M 0x000000ff - -#define SMSTA_XEN 0x08000000 -#define SMSTA_MTN 0x00200000 - -#define CTL_MRR 0x00000400 -#define CTL_MTR 0x00000200 -#define CTL_EN 0x00000800 -#define CTL_CLK_M 0x000000ff +#define MTXFIFO_READ BIT(10) +#define MTXFIFO_STOP BIT(9) +#define MTXFIFO_START BIT(8) +#define MTXFIFO_DATA_M GENMASK(7, 0) + +#define MRXFIFO_EMPTY BIT(8) +#define MRXFIFO_DATA_M GENMASK(7, 0) + +#define SMSTA_XIP BIT(28) +#define SMSTA_XEN BIT(27) +#define SMSTA_JMD BIT(25) +#define SMSTA_JAM BIT(24) +#define SMSTA_MTO BIT(23) +#define SMSTA_MTA BIT(22) +#define SMSTA_MTN BIT(21) +#define SMSTA_MRNE BIT(19) +#define SMSTA_MTE BIT(16) +#define SMSTA_TOM BIT(6) + +#define CTL_EN BIT(11) +#define CTL_MRR BIT(10) +#define CTL_MTR BIT(9) +#define CTL_UJM BIT(8) +#define CTL_CLK_M GENMASK(7, 0) static inline void reg_write(struct pasemi_smbus *smbus, int reg, int val) { @@ -61,7 +71,7 @@ static inline int reg_read(struct pasemi_smbus *smbus, int reg) static void pasemi_reset(struct pasemi_smbus *smbus) { - u32 val = (CTL_MTR | CTL_MRR | (smbus->clk_div & CTL_CLK_M)); + u32 val = (CTL_MTR | CTL_MRR | CTL_UJM | (smbus->clk_div & CTL_CLK_M)); if (smbus->hw_rev >= 6) val |= CTL_EN; diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c index cb6988482673..4415a29f749b 100644 --- a/drivers/i2c/busses/i2c-pxa.c +++ b/drivers/i2c/busses/i2c-pxa.c @@ -1503,7 +1503,10 @@ static int i2c_pxa_probe(struct platform_device *dev) i2c->adap.name); } - clk_prepare_enable(i2c->clk); + ret = clk_prepare_enable(i2c->clk); + if (ret) + return dev_err_probe(&dev->dev, ret, + "failed to enable clock\n"); if (i2c->use_pio) { i2c->adap.algo = &i2c_pxa_pio_algorithm; diff --git a/drivers/i2c/busses/i2c-qcom-geni.c b/drivers/i2c/busses/i2c-qcom-geni.c index 7a22e1f46e60..515a784c951c 100644 --- a/drivers/i2c/busses/i2c-qcom-geni.c +++ b/drivers/i2c/busses/i2c-qcom-geni.c @@ -148,9 +148,9 @@ struct geni_i2c_clk_fld { * source_clock = 19.2 MHz */ static const struct geni_i2c_clk_fld geni_i2c_clk_map_19p2mhz[] = { - {KHZ(100), 7, 10, 11, 26}, - {KHZ(400), 2, 5, 12, 24}, - {KHZ(1000), 1, 3, 9, 18}, + {KHZ(100), 7, 10, 12, 26}, + {KHZ(400), 2, 5, 11, 22}, + {KHZ(1000), 1, 2, 8, 18}, {}, }; @@ -823,11 +823,9 @@ static int geni_i2c_probe(struct platform_device *pdev) return gi2c->irq; ret = geni_i2c_clk_map_idx(gi2c); - if (ret) { - dev_err(dev, "Invalid clk frequency %d Hz: %d\n", - gi2c->clk_freq_out, ret); - return ret; - } + if (ret) + return dev_err_probe(dev, ret, "Invalid clk frequency %d Hz\n", + gi2c->clk_freq_out); gi2c->adap.algo = &geni_i2c_algo; init_completion(&gi2c->done); @@ -837,11 +835,10 @@ static int geni_i2c_probe(struct platform_device *pdev) /* Keep interrupts disabled initially to allow for low-power modes */ ret = devm_request_irq(dev, gi2c->irq, geni_i2c_irq, IRQF_NO_AUTOEN, dev_name(dev), gi2c); - if (ret) { - dev_err(dev, "Request_irq failed:%d: err:%d\n", - gi2c->irq, ret); - return ret; - } + if (ret) + return dev_err_probe(dev, ret, + "Request_irq failed: %d\n", gi2c->irq); + i2c_set_adapdata(&gi2c->adap, gi2c); gi2c->adap.dev.parent = dev; gi2c->adap.dev.of_node = dev->of_node; @@ -870,16 +867,13 @@ static int geni_i2c_probe(struct platform_device *pdev) ret = geni_se_resources_on(&gi2c->se); if (ret) { - dev_err(dev, "Error turning on resources %d\n", ret); - clk_disable_unprepare(gi2c->core_clk); - return ret; + dev_err_probe(dev, ret, "Error turning on resources\n"); + goto err_clk; } proto = geni_se_read_proto(&gi2c->se); if (proto != GENI_SE_I2C) { - dev_err(dev, "Invalid proto %d\n", proto); - geni_se_resources_off(&gi2c->se); - clk_disable_unprepare(gi2c->core_clk); - return -ENXIO; + ret = dev_err_probe(dev, -ENXIO, "Invalid proto %d\n", proto); + goto err_resources; } if (desc && desc->no_dma_support) @@ -891,11 +885,8 @@ static int geni_i2c_probe(struct platform_device *pdev) /* FIFO is disabled, so we can only use GPI DMA */ gi2c->gpi_mode = true; ret = setup_gpi_dma(gi2c); - if (ret) { - geni_se_resources_off(&gi2c->se); - clk_disable_unprepare(gi2c->core_clk); - return dev_err_probe(dev, ret, "Failed to setup GPI DMA mode\n"); - } + if (ret) + goto err_resources; dev_dbg(dev, "Using GPI DMA mode for I2C\n"); } else { @@ -907,10 +898,9 @@ static int geni_i2c_probe(struct platform_device *pdev) tx_depth = desc->tx_fifo_depth; if (!tx_depth) { - dev_err(dev, "Invalid TX FIFO depth\n"); - geni_se_resources_off(&gi2c->se); - clk_disable_unprepare(gi2c->core_clk); - return -EINVAL; + ret = dev_err_probe(dev, -EINVAL, + "Invalid TX FIFO depth\n"); + goto err_resources; } gi2c->tx_wm = tx_depth - 1; @@ -924,7 +914,7 @@ static int geni_i2c_probe(struct platform_device *pdev) clk_disable_unprepare(gi2c->core_clk); ret = geni_se_resources_off(&gi2c->se); if (ret) { - dev_err(dev, "Error turning off resources %d\n", ret); + dev_err_probe(dev, ret, "Error turning off resources\n"); goto err_dma; } @@ -940,17 +930,25 @@ static int geni_i2c_probe(struct platform_device *pdev) ret = i2c_add_adapter(&gi2c->adap); if (ret) { - dev_err(dev, "Error adding i2c adapter %d\n", ret); + dev_err_probe(dev, ret, "Error adding i2c adapter\n"); pm_runtime_disable(gi2c->se.dev); goto err_dma; } dev_dbg(dev, "Geni-I2C adaptor successfully added\n"); - return 0; + return ret; + +err_resources: + geni_se_resources_off(&gi2c->se); +err_clk: + clk_disable_unprepare(gi2c->core_clk); + + return ret; err_dma: release_gpi_dma(gi2c); + return ret; } diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c index da20b4487c9a..5b053e51f4c9 100644 --- a/drivers/i2c/busses/i2c-qup.c +++ b/drivers/i2c/busses/i2c-qup.c @@ -14,6 +14,7 @@ #include <linux/dma-mapping.h> #include <linux/err.h> #include <linux/i2c.h> +#include <linux/interconnect.h> #include <linux/interrupt.h> #include <linux/io.h> #include <linux/module.h> @@ -150,6 +151,8 @@ /* TAG length for DATA READ in RX FIFO */ #define READ_RX_TAGS_LEN 2 +#define QUP_BUS_WIDTH 8 + static unsigned int scl_freq; module_param_named(scl_freq, scl_freq, uint, 0444); MODULE_PARM_DESC(scl_freq, "SCL frequency override"); @@ -227,6 +230,7 @@ struct qup_i2c_dev { int irq; struct clk *clk; struct clk *pclk; + struct icc_path *icc_path; struct i2c_adapter adap; int clk_ctl; @@ -255,6 +259,10 @@ struct qup_i2c_dev { /* To configure when bus is in run state */ u32 config_run; + /* bandwidth votes */ + u32 src_clk_freq; + u32 cur_bw_clk_freq; + /* dma parameters */ bool is_dma; /* To check if the current transfer is using DMA */ @@ -444,8 +452,10 @@ static int qup_i2c_bus_active(struct qup_i2c_dev *qup, int len) if (!(status & I2C_STATUS_BUS_ACTIVE)) break; - if (time_after(jiffies, timeout)) + if (time_after(jiffies, timeout)) { ret = -ETIMEDOUT; + break; + } usleep_range(len, len * 2); } @@ -453,6 +463,23 @@ static int qup_i2c_bus_active(struct qup_i2c_dev *qup, int len) return ret; } +static int qup_i2c_vote_bw(struct qup_i2c_dev *qup, u32 clk_freq) +{ + u32 needed_peak_bw; + int ret; + + if (qup->cur_bw_clk_freq == clk_freq) + return 0; + + needed_peak_bw = Bps_to_icc(clk_freq * QUP_BUS_WIDTH); + ret = icc_set_bw(qup->icc_path, 0, needed_peak_bw); + if (ret) + return ret; + + qup->cur_bw_clk_freq = clk_freq; + return 0; +} + static void qup_i2c_write_tx_fifo_v1(struct qup_i2c_dev *qup) { struct qup_i2c_block *blk = &qup->blk; @@ -838,6 +865,10 @@ static int qup_i2c_bam_xfer(struct i2c_adapter *adap, struct i2c_msg *msg, int ret = 0; int idx = 0; + ret = qup_i2c_vote_bw(qup, qup->src_clk_freq); + if (ret) + return ret; + enable_irq(qup->irq); ret = qup_i2c_req_dma(qup); @@ -1643,6 +1674,7 @@ static void qup_i2c_disable_clocks(struct qup_i2c_dev *qup) config = readl(qup->base + QUP_CONFIG); config |= QUP_CLOCK_AUTO_GATE; writel(config, qup->base + QUP_CONFIG); + qup_i2c_vote_bw(qup, 0); clk_disable_unprepare(qup->pclk); } @@ -1743,6 +1775,11 @@ static int qup_i2c_probe(struct platform_device *pdev) goto fail_dma; } qup->is_dma = true; + + qup->icc_path = devm_of_icc_get(&pdev->dev, NULL); + if (IS_ERR(qup->icc_path)) + return dev_err_probe(&pdev->dev, PTR_ERR(qup->icc_path), + "failed to get interconnect path\n"); } nodma: @@ -1791,6 +1828,7 @@ nodma: qup_i2c_enable_clocks(qup); src_clk_freq = clk_get_rate(qup->clk); } + qup->src_clk_freq = src_clk_freq; /* * Bootloaders might leave a pending interrupt on certain QUP's, diff --git a/drivers/i2c/busses/i2c-riic.c b/drivers/i2c/busses/i2c-riic.c index 9264adc97ca9..d7dddd6c296a 100644 --- a/drivers/i2c/busses/i2c-riic.c +++ b/drivers/i2c/busses/i2c-riic.c @@ -34,46 +34,51 @@ * Also check the comments in the interrupt routines for some gory details. */ +#include <linux/bits.h> #include <linux/clk.h> #include <linux/completion.h> #include <linux/err.h> #include <linux/i2c.h> #include <linux/interrupt.h> #include <linux/io.h> +#include <linux/iopoll.h> #include <linux/module.h> #include <linux/of.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/reset.h> +#include <linux/time.h> -#define ICCR1_ICE 0x80 -#define ICCR1_IICRST 0x40 -#define ICCR1_SOWP 0x10 +#define ICCR1_ICE BIT(7) +#define ICCR1_IICRST BIT(6) +#define ICCR1_SOWP BIT(4) +#define ICCR1_SCLI BIT(1) +#define ICCR1_SDAI BIT(0) -#define ICCR2_BBSY 0x80 -#define ICCR2_SP 0x08 -#define ICCR2_RS 0x04 -#define ICCR2_ST 0x02 +#define ICCR2_BBSY BIT(7) +#define ICCR2_SP BIT(3) +#define ICCR2_RS BIT(2) +#define ICCR2_ST BIT(1) -#define ICMR1_CKS_MASK 0x70 -#define ICMR1_BCWP 0x08 +#define ICMR1_CKS_MASK GENMASK(6, 4) +#define ICMR1_BCWP BIT(3) #define ICMR1_CKS(_x) ((((_x) << 4) & ICMR1_CKS_MASK) | ICMR1_BCWP) -#define ICMR3_RDRFS 0x20 -#define ICMR3_ACKWP 0x10 -#define ICMR3_ACKBT 0x08 +#define ICMR3_RDRFS BIT(5) +#define ICMR3_ACKWP BIT(4) +#define ICMR3_ACKBT BIT(3) -#define ICFER_FMPE 0x80 +#define ICFER_FMPE BIT(7) -#define ICIER_TIE 0x80 -#define ICIER_TEIE 0x40 -#define ICIER_RIE 0x20 -#define ICIER_NAKIE 0x10 -#define ICIER_SPIE 0x08 +#define ICIER_TIE BIT(7) +#define ICIER_TEIE BIT(6) +#define ICIER_RIE BIT(5) +#define ICIER_NAKIE BIT(4) +#define ICIER_SPIE BIT(3) -#define ICSR2_NACKF 0x10 +#define ICSR2_NACKF BIT(4) -#define ICBR_RESERVED 0xe0 /* Should be 1 on writes */ +#define ICBR_RESERVED GENMASK(7, 5) /* Should be 1 on writes */ #define RIIC_INIT_MSG -1 @@ -134,6 +139,27 @@ static inline void riic_clear_set_bit(struct riic_dev *riic, u8 clear, u8 set, u riic_writeb(riic, (riic_readb(riic, reg) & ~clear) | set, reg); } +static int riic_bus_barrier(struct riic_dev *riic) +{ + int ret; + u8 val; + + /* + * The SDA line can still be low even when BBSY = 0. Therefore, after checking + * the BBSY flag, also verify that the SDA and SCL lines are not being held low. + */ + ret = readb_poll_timeout(riic->base + riic->info->regs[RIIC_ICCR2], val, + !(val & ICCR2_BBSY), 10, riic->adapter.timeout); + if (ret) + return ret; + + if ((riic_readb(riic, RIIC_ICCR1) & (ICCR1_SDAI | ICCR1_SCLI)) != + (ICCR1_SDAI | ICCR1_SCLI)) + return -EBUSY; + + return 0; +} + static int riic_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) { struct riic_dev *riic = i2c_get_adapdata(adap); @@ -146,13 +172,11 @@ static int riic_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) if (ret) return ret; - if (riic_readb(riic, RIIC_ICCR2) & ICCR2_BBSY) { - riic->err = -EBUSY; + riic->err = riic_bus_barrier(riic); + if (riic->err) goto out; - } reinit_completion(&riic->msg_done); - riic->err = 0; riic_writeb(riic, 0, RIIC_ICSR2); @@ -312,6 +336,7 @@ static int riic_init_hw(struct riic_dev *riic) { int ret; unsigned long rate; + unsigned long ns_per_tick; int total_ticks, cks, brl, brh; struct i2c_timings *t = &riic->i2c_t; struct device *dev = riic->adapter.dev.parent; @@ -320,7 +345,7 @@ static int riic_init_hw(struct riic_dev *riic) : I2C_MAX_FAST_MODE_FREQ; if (t->bus_freq_hz > max_freq) - return dev_err_probe(&riic->adapter.dev, -EINVAL, + return dev_err_probe(dev, -EINVAL, "unsupported bus speed %uHz (%u max)\n", t->bus_freq_hz, max_freq); @@ -356,11 +381,9 @@ static int riic_init_hw(struct riic_dev *riic) rate /= 2; } - if (brl > (0x1F + 3)) { - dev_err(&riic->adapter.dev, "invalid speed (%lu). Too slow.\n", - (unsigned long)t->bus_freq_hz); - return -EINVAL; - } + if (brl > (0x1F + 3)) + return dev_err_probe(dev, -EINVAL, "invalid speed (%uHz). Too slow.\n", + t->bus_freq_hz); brh = total_ticks - brl; @@ -377,8 +400,9 @@ static int riic_init_hw(struct riic_dev *riic) * Remove clock ticks for rise and fall times. Convert ns to clock * ticks. */ - brl -= t->scl_fall_ns / (1000000000 / rate); - brh -= t->scl_rise_ns / (1000000000 / rate); + ns_per_tick = NSEC_PER_SEC / rate; + brl -= t->scl_fall_ns / ns_per_tick; + brh -= t->scl_rise_ns / ns_per_tick; /* Adjust for min register values for when SCLE=1 and NFE=1 */ if (brl < 1) @@ -388,8 +412,7 @@ static int riic_init_hw(struct riic_dev *riic) pr_debug("i2c-riic: freq=%lu, duty=%d, fall=%lu, rise=%lu, cks=%d, brl=%d, brh=%d\n", rate / total_ticks, ((brl + 3) * 100) / (brl + brh + 6), - t->scl_fall_ns / (1000000000 / rate), - t->scl_rise_ns / (1000000000 / rate), cks, brl, brh); + t->scl_fall_ns / ns_per_tick, t->scl_rise_ns / ns_per_tick, cks, brl, brh); ret = pm_runtime_resume_and_get(dev); if (ret) @@ -416,7 +439,7 @@ static int riic_init_hw(struct riic_dev *riic) return 0; } -static struct riic_irq_desc riic_irqs[] = { +static const struct riic_irq_desc riic_irqs[] = { { .res_num = 0, .isr = riic_tend_isr, .name = "riic-tend" }, { .res_num = 1, .isr = riic_rdrf_isr, .name = "riic-rdrf" }, { .res_num = 2, .isr = riic_tdre_isr, .name = "riic-tdre" }, @@ -424,11 +447,6 @@ static struct riic_irq_desc riic_irqs[] = { { .res_num = 5, .isr = riic_tend_isr, .name = "riic-nack" }, }; -static void riic_reset_control_assert(void *data) -{ - reset_control_assert(data); -} - static int riic_i2c_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -445,35 +463,27 @@ static int riic_i2c_probe(struct platform_device *pdev) return PTR_ERR(riic->base); riic->clk = devm_clk_get(dev, NULL); - if (IS_ERR(riic->clk)) { - dev_err(dev, "missing controller clock"); - return PTR_ERR(riic->clk); - } + if (IS_ERR(riic->clk)) + return dev_err_probe(dev, PTR_ERR(riic->clk), + "missing controller clock"); - riic->rstc = devm_reset_control_get_optional_exclusive(dev, NULL); + riic->rstc = devm_reset_control_get_optional_exclusive_deasserted(dev, NULL); if (IS_ERR(riic->rstc)) return dev_err_probe(dev, PTR_ERR(riic->rstc), - "Error: missing reset ctrl\n"); - - ret = reset_control_deassert(riic->rstc); - if (ret) - return ret; - - ret = devm_add_action_or_reset(dev, riic_reset_control_assert, riic->rstc); - if (ret) - return ret; + "failed to acquire deasserted reset\n"); for (i = 0; i < ARRAY_SIZE(riic_irqs); i++) { - ret = platform_get_irq(pdev, riic_irqs[i].res_num); - if (ret < 0) - return ret; + int irq; + + irq = platform_get_irq(pdev, riic_irqs[i].res_num); + if (irq < 0) + return irq; - ret = devm_request_irq(dev, ret, riic_irqs[i].isr, + ret = devm_request_irq(dev, irq, riic_irqs[i].isr, 0, riic_irqs[i].name, riic); - if (ret) { - dev_err(dev, "failed to request irq %s\n", riic_irqs[i].name); - return ret; - } + if (ret) + return dev_err_probe(dev, ret, "failed to request irq %s\n", + riic_irqs[i].name); } riic->info = of_device_get_match_data(dev); diff --git a/drivers/i2c/busses/i2c-robotfuzz-osif.c b/drivers/i2c/busses/i2c-robotfuzz-osif.c index 80d45079b763..e0a76fb5bc31 100644 --- a/drivers/i2c/busses/i2c-robotfuzz-osif.c +++ b/drivers/i2c/busses/i2c-robotfuzz-osif.c @@ -111,6 +111,11 @@ static u32 osif_func(struct i2c_adapter *adapter) return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; } +/* prevent invalid 0-length usb_control_msg */ +static const struct i2c_adapter_quirks osif_quirks = { + .flags = I2C_AQ_NO_ZERO_LEN_READ, +}; + static const struct i2c_algorithm osif_algorithm = { .xfer = osif_xfer, .functionality = osif_func, @@ -143,6 +148,7 @@ static int osif_probe(struct usb_interface *interface, priv->adapter.owner = THIS_MODULE; priv->adapter.class = I2C_CLASS_HWMON; + priv->adapter.quirks = &osif_quirks; priv->adapter.algo = &osif_algorithm; priv->adapter.algo_data = priv; snprintf(priv->adapter.name, sizeof(priv->adapter.name), diff --git a/drivers/i2c/busses/i2c-rzv2m.c b/drivers/i2c/busses/i2c-rzv2m.c index 02b76e24a476..53762cc56d28 100644 --- a/drivers/i2c/busses/i2c-rzv2m.c +++ b/drivers/i2c/busses/i2c-rzv2m.c @@ -287,20 +287,15 @@ static int rzv2m_i2c_send_address(struct rzv2m_i2c_priv *priv, int ret; if (msg->flags & I2C_M_TEN) { - /* - * 10-bit address - * addr_1: 5'b11110 | addr[9:8] | (R/nW) - * addr_2: addr[7:0] - */ - addr = 0xf0 | ((msg->addr & GENMASK(9, 8)) >> 7); - addr |= !!(msg->flags & I2C_M_RD); - /* Send 1st address(extend code) */ + /* 10-bit address: Send 1st address(extend code) */ + addr = i2c_10bit_addr_hi_from_msg(msg); ret = rzv2m_i2c_write_with_ack(priv, addr); if (ret) return ret; - /* Send 2nd address */ - ret = rzv2m_i2c_write_with_ack(priv, msg->addr & 0xff); + /* 10-bit address: Send 2nd address */ + addr = i2c_10bit_addr_lo_from_msg(msg); + ret = rzv2m_i2c_write_with_ack(priv, addr); } else { /* 7-bit address */ addr = i2c_8bit_addr_from_msg(msg); diff --git a/drivers/i2c/busses/i2c-sis630.c b/drivers/i2c/busses/i2c-sis630.c index 3505cf29cedd..a19c3d251804 100644 --- a/drivers/i2c/busses/i2c-sis630.c +++ b/drivers/i2c/busses/i2c-sis630.c @@ -509,6 +509,8 @@ MODULE_DEVICE_TABLE(pci, sis630_ids); static int sis630_probe(struct pci_dev *dev, const struct pci_device_id *id) { + int ret; + if (sis630_setup(dev)) { dev_err(&dev->dev, "SIS630 compatible bus not detected, " @@ -522,7 +524,15 @@ static int sis630_probe(struct pci_dev *dev, const struct pci_device_id *id) snprintf(sis630_adapter.name, sizeof(sis630_adapter.name), "SMBus SIS630 adapter at %04x", smbus_base + SMB_STS); - return i2c_add_adapter(&sis630_adapter); + ret = i2c_add_adapter(&sis630_adapter); + if (ret) + goto release_region; + + return 0; + +release_region: + release_region(smbus_base + SMB_STS, SIS630_SMB_IOREGION); + return ret; } static void sis630_remove(struct pci_dev *dev) diff --git a/drivers/i2c/busses/i2c-stm32.c b/drivers/i2c/busses/i2c-stm32.c index 157c64e27d0b..f84ec056e36d 100644 --- a/drivers/i2c/busses/i2c-stm32.c +++ b/drivers/i2c/busses/i2c-stm32.c @@ -102,7 +102,6 @@ int stm32_i2c_prep_dma_xfer(struct device *dev, struct stm32_i2c_dma *dma, void *dma_async_param) { struct dma_async_tx_descriptor *txdesc; - struct device *chan_dev; int ret; if (rd_wr) { @@ -116,11 +115,10 @@ int stm32_i2c_prep_dma_xfer(struct device *dev, struct stm32_i2c_dma *dma, } dma->dma_len = len; - chan_dev = dma->chan_using->device->dev; - dma->dma_buf = dma_map_single(chan_dev, buf, dma->dma_len, + dma->dma_buf = dma_map_single(dev, buf, dma->dma_len, dma->dma_data_dir); - if (dma_mapping_error(chan_dev, dma->dma_buf)) { + if (dma_mapping_error(dev, dma->dma_buf)) { dev_err(dev, "DMA mapping failed\n"); return -EINVAL; } @@ -150,7 +148,7 @@ int stm32_i2c_prep_dma_xfer(struct device *dev, struct stm32_i2c_dma *dma, return 0; err: - dma_unmap_single(chan_dev, dma->dma_buf, dma->dma_len, + dma_unmap_single(dev, dma->dma_buf, dma->dma_len, dma->dma_data_dir); return ret; } diff --git a/drivers/i2c/busses/i2c-stm32f7.c b/drivers/i2c/busses/i2c-stm32f7.c index 973a3a8c6d4a..1f8c6593e99a 100644 --- a/drivers/i2c/busses/i2c-stm32f7.c +++ b/drivers/i2c/busses/i2c-stm32f7.c @@ -739,12 +739,13 @@ static void stm32f7_i2c_disable_dma_req(struct stm32f7_i2c_dev *i2c_dev) static void stm32f7_i2c_dma_callback(void *arg) { - struct stm32f7_i2c_dev *i2c_dev = (struct stm32f7_i2c_dev *)arg; + struct stm32f7_i2c_dev *i2c_dev = arg; struct stm32_i2c_dma *dma = i2c_dev->dma; - struct device *dev = dma->chan_using->device->dev; stm32f7_i2c_disable_dma_req(i2c_dev); - dma_unmap_single(dev, dma->dma_buf, dma->dma_len, dma->dma_data_dir); + dmaengine_terminate_async(dma->chan_using); + dma_unmap_single(i2c_dev->dev, dma->dma_buf, dma->dma_len, + dma->dma_data_dir); complete(&dma->dma_complete); } @@ -1510,7 +1511,6 @@ static irqreturn_t stm32f7_i2c_handle_isr_errs(struct stm32f7_i2c_dev *i2c_dev, u16 addr = f7_msg->addr; void __iomem *base = i2c_dev->base; struct device *dev = i2c_dev->dev; - struct stm32_i2c_dma *dma = i2c_dev->dma; /* Bus error */ if (status & STM32F7_I2C_ISR_BERR) { @@ -1551,10 +1551,8 @@ static irqreturn_t stm32f7_i2c_handle_isr_errs(struct stm32f7_i2c_dev *i2c_dev, } /* Disable dma */ - if (i2c_dev->use_dma) { - stm32f7_i2c_disable_dma_req(i2c_dev); - dmaengine_terminate_async(dma->chan_using); - } + if (i2c_dev->use_dma) + stm32f7_i2c_dma_callback(i2c_dev); i2c_dev->master_mode = false; complete(&i2c_dev->complete); @@ -1600,7 +1598,6 @@ static irqreturn_t stm32f7_i2c_isr_event_thread(int irq, void *data) { struct stm32f7_i2c_dev *i2c_dev = data; struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg; - struct stm32_i2c_dma *dma = i2c_dev->dma; void __iomem *base = i2c_dev->base; u32 status, mask; int ret; @@ -1619,10 +1616,8 @@ static irqreturn_t stm32f7_i2c_isr_event_thread(int irq, void *data) dev_dbg(i2c_dev->dev, "<%s>: Receive NACK (addr %x)\n", __func__, f7_msg->addr); writel_relaxed(STM32F7_I2C_ICR_NACKCF, base + STM32F7_I2C_ICR); - if (i2c_dev->use_dma) { - stm32f7_i2c_disable_dma_req(i2c_dev); - dmaengine_terminate_async(dma->chan_using); - } + if (i2c_dev->use_dma) + stm32f7_i2c_dma_callback(i2c_dev); f7_msg->result = -ENXIO; } @@ -1640,8 +1635,7 @@ static irqreturn_t stm32f7_i2c_isr_event_thread(int irq, void *data) ret = wait_for_completion_timeout(&i2c_dev->dma->dma_complete, HZ); if (!ret) { dev_dbg(i2c_dev->dev, "<%s>: Timed out\n", __func__); - stm32f7_i2c_disable_dma_req(i2c_dev); - dmaengine_terminate_async(dma->chan_using); + stm32f7_i2c_dma_callback(i2c_dev); f7_msg->result = -ETIMEDOUT; } } diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index 87976e99e6d0..687d1e608abc 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -607,7 +607,6 @@ static int tegra_i2c_wait_for_config_load(struct tegra_i2c_dev *i2c_dev) static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev) { u32 val, clk_divisor, clk_multiplier, tsu_thd, tlow, thigh, non_hs_mode; - acpi_handle handle = ACPI_HANDLE(i2c_dev->dev); struct i2c_timings *t = &i2c_dev->timings; int err; @@ -619,11 +618,7 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev) * emit a noisy warning on error, which won't stay unnoticed and * won't hose machine entirely. */ - if (handle) - err = acpi_evaluate_object(handle, "_RST", NULL, NULL); - else - err = reset_control_reset(i2c_dev->rst); - + err = device_reset(i2c_dev->dev); WARN_ON_ONCE(err); if (IS_DVC(i2c_dev)) @@ -1395,6 +1390,11 @@ static int tegra_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], ret = tegra_i2c_xfer_msg(i2c_dev, &msgs[i], MSG_END_CONTINUE); if (ret) break; + + /* Validate message length before proceeding */ + if (msgs[i].buf[0] == 0 || msgs[i].buf[0] > I2C_SMBUS_BLOCK_MAX) + break; + /* Set the msg length from first byte */ msgs[i].len += msgs[i].buf[0]; dev_dbg(i2c_dev->dev, "reading %d bytes\n", msgs[i].len); @@ -1661,19 +1661,6 @@ static void tegra_i2c_parse_dt(struct tegra_i2c_dev *i2c_dev) i2c_dev->is_vi = true; } -static int tegra_i2c_init_reset(struct tegra_i2c_dev *i2c_dev) -{ - if (ACPI_HANDLE(i2c_dev->dev)) - return 0; - - i2c_dev->rst = devm_reset_control_get_exclusive(i2c_dev->dev, "i2c"); - if (IS_ERR(i2c_dev->rst)) - return dev_err_probe(i2c_dev->dev, PTR_ERR(i2c_dev->rst), - "failed to get reset control\n"); - - return 0; -} - static int tegra_i2c_init_clocks(struct tegra_i2c_dev *i2c_dev) { int err; @@ -1783,10 +1770,6 @@ static int tegra_i2c_probe(struct platform_device *pdev) tegra_i2c_parse_dt(i2c_dev); - err = tegra_i2c_init_reset(i2c_dev); - if (err) - return err; - err = tegra_i2c_init_clocks(i2c_dev); if (err) return err; diff --git a/drivers/i2c/busses/i2c-tiny-usb.c b/drivers/i2c/busses/i2c-tiny-usb.c index 0f2ed181b266..0cc7c0a816fc 100644 --- a/drivers/i2c/busses/i2c-tiny-usb.c +++ b/drivers/i2c/busses/i2c-tiny-usb.c @@ -138,6 +138,11 @@ out: return ret; } +/* prevent invalid 0-length usb_control_msg */ +static const struct i2c_adapter_quirks usb_quirks = { + .flags = I2C_AQ_NO_ZERO_LEN_READ, +}; + /* This is the actual algorithm we define */ static const struct i2c_algorithm usb_algorithm = { .xfer = usb_xfer, @@ -246,6 +251,7 @@ static int i2c_tiny_usb_probe(struct usb_interface *interface, /* setup i2c adapter description */ dev->adapter.owner = THIS_MODULE; dev->adapter.class = I2C_CLASS_HWMON; + dev->adapter.quirks = &usb_quirks; dev->adapter.algo = &usb_algorithm; dev->adapter.algo_data = dev; snprintf(dev->adapter.name, sizeof(dev->adapter.name), diff --git a/drivers/i2c/busses/i2c-virtio.c b/drivers/i2c/busses/i2c-virtio.c index 2a351f961b89..c8c40ff9765d 100644 --- a/drivers/i2c/busses/i2c-virtio.c +++ b/drivers/i2c/busses/i2c-virtio.c @@ -116,15 +116,16 @@ static int virtio_i2c_complete_reqs(struct virtqueue *vq, for (i = 0; i < num; i++) { struct virtio_i2c_req *req = &reqs[i]; - wait_for_completion(&req->completion); - - if (!failed && req->in_hdr.status != VIRTIO_I2C_MSG_OK) - failed = true; + if (!failed) { + if (wait_for_completion_interruptible(&req->completion)) + failed = true; + else if (req->in_hdr.status != VIRTIO_I2C_MSG_OK) + failed = true; + else + j++; + } i2c_put_dma_safe_msg_buf(reqs[i].buf, &msgs[i], !failed); - - if (!failed) - j++; } return j; diff --git a/drivers/i2c/busses/i2c-xiic.c b/drivers/i2c/busses/i2c-xiic.c index c4d3eb02da09..dc1e46d834dc 100644 --- a/drivers/i2c/busses/i2c-xiic.c +++ b/drivers/i2c/busses/i2c-xiic.c @@ -30,6 +30,8 @@ #include <linux/of.h> #include <linux/clk.h> #include <linux/pm_runtime.h> +#include <linux/iopoll.h> +#include <linux/spinlock.h> #define DRIVER_NAME "xiic-i2c" #define DYNAMIC_MODE_READ_BROKEN_BIT BIT(0) @@ -74,6 +76,9 @@ enum i2c_scl_freq { * @smbus_block_read: Flag to handle block read * @input_clk: Input clock to I2C controller * @i2c_clk: I2C SCL frequency + * @atomic: Mode of transfer + * @atomic_lock: Lock for atomic transfer mode + * @atomic_xfer_state: See STATE_ */ struct xiic_i2c { struct device *dev; @@ -96,6 +101,9 @@ struct xiic_i2c { bool smbus_block_read; unsigned long input_clk; unsigned int i2c_clk; + bool atomic; + spinlock_t atomic_lock; /* Lock for atomic transfer mode */ + enum xilinx_i2c_state atomic_xfer_state; }; struct xiic_version_data { @@ -224,6 +232,8 @@ static const struct timing_regs timing_reg_values[] = { #define XIIC_I2C_TIMEOUT (msecs_to_jiffies(1000)) /* timeout waiting for the controller finish transfers */ #define XIIC_XFER_TIMEOUT (msecs_to_jiffies(10000)) +/* timeout waiting for the controller finish transfers in micro seconds */ +#define XIIC_XFER_TIMEOUT_US 10000000 /* * The following constant is used for the device global interrupt enable @@ -238,6 +248,29 @@ static const struct timing_regs timing_reg_values[] = { static int xiic_start_xfer(struct xiic_i2c *i2c, struct i2c_msg *msgs, int num); static void __xiic_start_xfer(struct xiic_i2c *i2c); +static int xiic_i2c_runtime_suspend(struct device *dev) +{ + struct xiic_i2c *i2c = dev_get_drvdata(dev); + + clk_disable(i2c->clk); + + return 0; +} + +static int xiic_i2c_runtime_resume(struct device *dev) +{ + struct xiic_i2c *i2c = dev_get_drvdata(dev); + int ret; + + ret = clk_enable(i2c->clk); + if (ret) { + dev_err(dev, "Cannot enable clock.\n"); + return ret; + } + + return 0; +} + /* * For the register read and write functions, a little-endian and big-endian * version are necessary. Endianness is detected during the probe function. @@ -374,9 +407,10 @@ static int xiic_setclk(struct xiic_i2c *i2c) unsigned int index = 0; u32 reg_val; - dev_dbg(i2c->adap.dev.parent, - "%s entry, i2c->input_clk: %ld, i2c->i2c_clk: %d\n", - __func__, i2c->input_clk, i2c->i2c_clk); + if (!i2c->atomic) + dev_dbg(i2c->adap.dev.parent, + "%s entry, i2c->input_clk: %ld, i2c->i2c_clk: %d\n", + __func__, i2c->input_clk, i2c->i2c_clk); /* If not specified in DT, do not configure in SW. Rely only on Vivado design */ if (!i2c->i2c_clk || !i2c->input_clk) @@ -467,7 +501,8 @@ static int xiic_reinit(struct xiic_i2c *i2c) return ret; /* Enable interrupts */ - xiic_setreg32(i2c, XIIC_DGIER_OFFSET, XIIC_GINTR_ENABLE_MASK); + if (!i2c->atomic) + xiic_setreg32(i2c, XIIC_DGIER_OFFSET, XIIC_GINTR_ENABLE_MASK); xiic_irq_clr_en(i2c, XIIC_INTR_ARB_LOST_MASK); @@ -549,11 +584,12 @@ static void xiic_read_rx(struct xiic_i2c *i2c) bytes_in_fifo = xiic_getreg8(i2c, XIIC_RFO_REG_OFFSET) + 1; - dev_dbg(i2c->adap.dev.parent, - "%s entry, bytes in fifo: %d, rem: %d, SR: 0x%x, CR: 0x%x\n", - __func__, bytes_in_fifo, xiic_rx_space(i2c), - xiic_getreg8(i2c, XIIC_SR_REG_OFFSET), - xiic_getreg8(i2c, XIIC_CR_REG_OFFSET)); + if (!i2c->atomic) + dev_dbg(i2c->adap.dev.parent, + "%s entry, bytes in fifo: %d, rem: %d, SR: 0x%x, CR: 0x%x\n", + __func__, bytes_in_fifo, xiic_rx_space(i2c), + xiic_getreg8(i2c, XIIC_SR_REG_OFFSET), + xiic_getreg8(i2c, XIIC_CR_REG_OFFSET)); if (bytes_in_fifo > xiic_rx_space(i2c)) bytes_in_fifo = xiic_rx_space(i2c); @@ -612,6 +648,26 @@ static void xiic_read_rx(struct xiic_i2c *i2c) } } +static bool xiic_error_check(struct xiic_i2c *i2c) +{ + bool status = false; + u32 pend, isr, ier; + + isr = xiic_getreg32(i2c, XIIC_IISR_OFFSET); + ier = xiic_getreg32(i2c, XIIC_IIER_OFFSET); + pend = isr & ier; + + if ((pend & XIIC_INTR_ARB_LOST_MASK) || + ((pend & XIIC_INTR_TX_ERROR_MASK) && + !(pend & XIIC_INTR_RX_FULL_MASK))) { + xiic_reinit(i2c); + status = true; + if (i2c->tx_msg || i2c->rx_msg) + i2c->atomic_xfer_state = STATE_ERROR; + } + return status; +} + static int xiic_tx_fifo_space(struct xiic_i2c *i2c) { /* return the actual space left in the FIFO */ @@ -625,8 +681,9 @@ static void xiic_fill_tx_fifo(struct xiic_i2c *i2c) len = (len > fifo_space) ? fifo_space : len; - dev_dbg(i2c->adap.dev.parent, "%s entry, len: %d, fifo space: %d\n", - __func__, len, fifo_space); + if (!i2c->atomic) + dev_dbg(i2c->adap.dev.parent, "%s entry, len: %d, fifo space: %d\n", + __func__, len, fifo_space); while (len--) { u16 data = i2c->tx_msg->buf[i2c->tx_pos++]; @@ -649,9 +706,13 @@ static void xiic_fill_tx_fifo(struct xiic_i2c *i2c) xiic_setreg8(i2c, XIIC_CR_REG_OFFSET, cr & ~XIIC_CR_MSMS_MASK); } - dev_dbg(i2c->adap.dev.parent, "%s TX STOP\n", __func__); + if (!i2c->atomic) + dev_dbg(i2c->adap.dev.parent, "%s TX STOP\n", __func__); } xiic_setreg16(i2c, XIIC_DTR_REG_OFFSET, data); + + if (i2c->atomic && xiic_error_check(i2c)) + return; } } @@ -854,22 +915,51 @@ static int xiic_wait_not_busy(struct xiic_i2c *i2c) */ err = xiic_bus_busy(i2c); while (err && tries--) { - msleep(1); + if (i2c->atomic) + udelay(1000); + else + usleep_range(1000, 1100); err = xiic_bus_busy(i2c); } return err; } +static void xiic_recv_atomic(struct xiic_i2c *i2c) +{ + while (xiic_rx_space(i2c)) { + if (xiic_getreg32(i2c, XIIC_IISR_OFFSET) & XIIC_INTR_RX_FULL_MASK) { + xiic_read_rx(i2c); + + /* Clear Rx full and Tx error interrupts. */ + xiic_irq_clr_en(i2c, XIIC_INTR_RX_FULL_MASK | + XIIC_INTR_TX_ERROR_MASK); + } + if (xiic_error_check(i2c)) + return; + } + + i2c->rx_msg = NULL; + xiic_irq_clr_en(i2c, XIIC_INTR_TX_ERROR_MASK); + + /* send next message if this wasn't the last. */ + if (i2c->nmsgs > 1) { + i2c->nmsgs--; + i2c->tx_msg++; + __xiic_start_xfer(i2c); + } +} + static void xiic_start_recv(struct xiic_i2c *i2c) { u16 rx_watermark; u8 cr = 0, rfd_set = 0; struct i2c_msg *msg = i2c->rx_msg = i2c->tx_msg; - dev_dbg(i2c->adap.dev.parent, "%s entry, ISR: 0x%x, CR: 0x%x\n", - __func__, xiic_getreg32(i2c, XIIC_IISR_OFFSET), - xiic_getreg8(i2c, XIIC_CR_REG_OFFSET)); + if (!i2c->atomic) + dev_dbg(i2c->adap.dev.parent, "%s entry, ISR: 0x%x, CR: 0x%x\n", + __func__, xiic_getreg32(i2c, XIIC_IISR_OFFSET), + xiic_getreg8(i2c, XIIC_CR_REG_OFFSET)); /* Disable Tx interrupts */ xiic_irq_dis(i2c, XIIC_INTR_TX_HALF_MASK | XIIC_INTR_TX_EMPTY_MASK); @@ -967,9 +1057,10 @@ static void xiic_start_recv(struct xiic_i2c *i2c) XIIC_CR_MSMS_MASK) & ~(XIIC_CR_DIR_IS_TX_MASK)); } - dev_dbg(i2c->adap.dev.parent, "%s end, ISR: 0x%x, CR: 0x%x\n", - __func__, xiic_getreg32(i2c, XIIC_IISR_OFFSET), - xiic_getreg8(i2c, XIIC_CR_REG_OFFSET)); + if (!i2c->atomic) + dev_dbg(i2c->adap.dev.parent, "%s end, ISR: 0x%x, CR: 0x%x\n", + __func__, xiic_getreg32(i2c, XIIC_IISR_OFFSET), + xiic_getreg8(i2c, XIIC_CR_REG_OFFSET)); } if (i2c->nmsgs == 1) @@ -979,10 +1070,55 @@ static void xiic_start_recv(struct xiic_i2c *i2c) /* the message is tx:ed */ i2c->tx_pos = msg->len; + i2c->prev_msg_tx = false; + /* Enable interrupts */ - xiic_setreg32(i2c, XIIC_DGIER_OFFSET, XIIC_GINTR_ENABLE_MASK); + if (!i2c->atomic) + xiic_setreg32(i2c, XIIC_DGIER_OFFSET, XIIC_GINTR_ENABLE_MASK); + else + xiic_recv_atomic(i2c); +} - i2c->prev_msg_tx = false; +static void xiic_send_rem_atomic(struct xiic_i2c *i2c) +{ + while (xiic_tx_space(i2c)) { + if (xiic_tx_fifo_space(i2c)) { + u16 data; + + data = i2c->tx_msg->buf[i2c->tx_pos]; + i2c->tx_pos++; + if (!xiic_tx_space(i2c) && i2c->nmsgs == 1) { + /* last message in transfer -> STOP */ + if (i2c->dynamic) { + data |= XIIC_TX_DYN_STOP_MASK; + } else { + u8 cr; + int status; + + /* Wait till FIFO is empty so STOP is sent last */ + status = xiic_wait_tx_empty(i2c); + if (status) + return; + + /* Write to CR to stop */ + cr = xiic_getreg8(i2c, XIIC_CR_REG_OFFSET); + xiic_setreg8(i2c, XIIC_CR_REG_OFFSET, cr & + ~XIIC_CR_MSMS_MASK); + } + } + xiic_setreg16(i2c, XIIC_DTR_REG_OFFSET, data); + } + if (xiic_error_check(i2c)) + return; + } + + if (i2c->nmsgs > 1) { + i2c->nmsgs--; + i2c->tx_msg++; + __xiic_start_xfer(i2c); + } else { + xiic_irq_dis(i2c, XIIC_INTR_TX_HALF_MASK); + } } static void xiic_start_send(struct xiic_i2c *i2c) @@ -991,11 +1127,13 @@ static void xiic_start_send(struct xiic_i2c *i2c) u16 data; struct i2c_msg *msg = i2c->tx_msg; - dev_dbg(i2c->adap.dev.parent, "%s entry, msg: %p, len: %d", - __func__, msg, msg->len); - dev_dbg(i2c->adap.dev.parent, "%s entry, ISR: 0x%x, CR: 0x%x\n", - __func__, xiic_getreg32(i2c, XIIC_IISR_OFFSET), - xiic_getreg8(i2c, XIIC_CR_REG_OFFSET)); + if (!i2c->atomic) { + dev_dbg(i2c->adap.dev.parent, "%s entry, msg: %p, len: %d", + __func__, msg, msg->len); + dev_dbg(i2c->adap.dev.parent, "%s entry, ISR: 0x%x, CR: 0x%x\n", + __func__, xiic_getreg32(i2c, XIIC_IISR_OFFSET), + xiic_getreg8(i2c, XIIC_CR_REG_OFFSET)); + } if (i2c->dynamic) { /* write the address */ @@ -1060,19 +1198,27 @@ static void xiic_start_send(struct xiic_i2c *i2c) XIIC_INTR_TX_ERROR_MASK | XIIC_INTR_BNB_MASK); } + i2c->prev_msg_tx = true; + + if (i2c->atomic && !i2c->atomic_xfer_state) + xiic_send_rem_atomic(i2c); } static void __xiic_start_xfer(struct xiic_i2c *i2c) { int fifo_space = xiic_tx_fifo_space(i2c); - dev_dbg(i2c->adap.dev.parent, "%s entry, msg: %p, fifos space: %d\n", - __func__, i2c->tx_msg, fifo_space); + if (!i2c->atomic) + dev_dbg(i2c->adap.dev.parent, "%s entry, msg: %p, fifos space: %d\n", + __func__, i2c->tx_msg, fifo_space); if (!i2c->tx_msg) return; + if (i2c->atomic && xiic_error_check(i2c)) + return; + i2c->rx_pos = 0; i2c->tx_pos = 0; i2c->state = STATE_START; @@ -1089,7 +1235,10 @@ static int xiic_start_xfer(struct xiic_i2c *i2c, struct i2c_msg *msgs, int num) bool broken_read, max_read_len, smbus_blk_read; int ret, count; - mutex_lock(&i2c->lock); + if (i2c->atomic) + spin_lock(&i2c->atomic_lock); + else + mutex_lock(&i2c->lock); if (i2c->tx_msg || i2c->rx_msg) { dev_err(i2c->adap.dev.parent, @@ -1098,6 +1247,8 @@ static int xiic_start_xfer(struct xiic_i2c *i2c, struct i2c_msg *msgs, int num) goto out; } + i2c->atomic_xfer_state = STATE_DONE; + /* In single master mode bus can only be busy, when in use by this * driver. If the register indicates bus being busy for some reason we * should ignore it, since bus will never be released and i2c will be @@ -1124,7 +1275,9 @@ static int xiic_start_xfer(struct xiic_i2c *i2c, struct i2c_msg *msgs, int num) i2c->tx_msg = msgs; i2c->rx_msg = NULL; i2c->nmsgs = num; - init_completion(&i2c->completion); + + if (!i2c->atomic) + init_completion(&i2c->completion); /* Decide standard mode or Dynamic mode */ i2c->dynamic = true; @@ -1159,7 +1312,10 @@ static int xiic_start_xfer(struct xiic_i2c *i2c, struct i2c_msg *msgs, int num) __xiic_start_xfer(i2c); out: - mutex_unlock(&i2c->lock); + if (i2c->atomic) + spin_unlock(&i2c->atomic_lock); + else + mutex_unlock(&i2c->lock); return ret; } @@ -1198,6 +1354,44 @@ out: return err; } +static int xiic_xfer_atomic(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) +{ + struct xiic_i2c *i2c = i2c_get_adapdata(adap); + u32 status_reg; + int err; + + err = xiic_i2c_runtime_resume(i2c->dev); + if (err) + return err; + + i2c->atomic = true; + err = xiic_start_xfer(i2c, msgs, num); + if (err < 0) + return err; + + err = readl_poll_timeout_atomic(i2c->base + XIIC_SR_REG_OFFSET, + status_reg, !(status_reg & XIIC_SR_BUS_BUSY_MASK), + 1, XIIC_XFER_TIMEOUT_US); + + if (err) /* Timeout */ + err = -ETIMEDOUT; + + spin_lock(&i2c->atomic_lock); + if (err || i2c->state) { + i2c->tx_msg = NULL; + i2c->rx_msg = NULL; + i2c->nmsgs = 0; + } + + err = (i2c->atomic_xfer_state == STATE_DONE) ? num : -EIO; + spin_unlock(&i2c->atomic_lock); + + i2c->atomic = false; + xiic_i2c_runtime_suspend(i2c->dev); + + return err; +} + static u32 xiic_func(struct i2c_adapter *adap) { return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_SMBUS_BLOCK_DATA; @@ -1205,6 +1399,7 @@ static u32 xiic_func(struct i2c_adapter *adap) static const struct i2c_algorithm xiic_algorithm = { .master_xfer = xiic_xfer, + .master_xfer_atomic = xiic_xfer_atomic, .functionality = xiic_func, }; @@ -1268,6 +1463,7 @@ static int xiic_i2c_probe(struct platform_device *pdev) DRIVER_NAME " %s", pdev->name); mutex_init(&i2c->lock); + spin_lock_init(&i2c->atomic_lock); i2c->clk = devm_clk_get_enabled(&pdev->dev, NULL); if (IS_ERR(i2c->clk)) @@ -1365,29 +1561,6 @@ static void xiic_i2c_remove(struct platform_device *pdev) pm_runtime_dont_use_autosuspend(&pdev->dev); } -static int __maybe_unused xiic_i2c_runtime_suspend(struct device *dev) -{ - struct xiic_i2c *i2c = dev_get_drvdata(dev); - - clk_disable(i2c->clk); - - return 0; -} - -static int __maybe_unused xiic_i2c_runtime_resume(struct device *dev) -{ - struct xiic_i2c *i2c = dev_get_drvdata(dev); - int ret; - - ret = clk_enable(i2c->clk); - if (ret) { - dev_err(dev, "Cannot enable clock.\n"); - return ret; - } - - return 0; -} - static const struct dev_pm_ops xiic_dev_pm_ops = { SET_RUNTIME_PM_OPS(xiic_i2c_runtime_suspend, xiic_i2c_runtime_resume, NULL) diff --git a/drivers/i2c/i2c-atr.c b/drivers/i2c/i2c-atr.c index 8fe9ddff8e96..783fb8df2ebe 100644 --- a/drivers/i2c/i2c-atr.c +++ b/drivers/i2c/i2c-atr.c @@ -8,12 +8,12 @@ * Originally based on i2c-mux.c */ -#include <linux/fwnode.h> #include <linux/i2c-atr.h> #include <linux/i2c.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/mutex.h> +#include <linux/property.h> #include <linux/slab.h> #include <linux/spinlock.h> diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c index 75d30861ffe2..7ad1ad5c8c3f 100644 --- a/drivers/i2c/i2c-core-base.c +++ b/drivers/i2c/i2c-core-base.c @@ -583,6 +583,9 @@ static int i2c_device_probe(struct device *dev) goto err_detach_pm_domain; } + client->debugfs = debugfs_create_dir(dev_name(&client->dev), + client->adapter->debugfs); + if (driver->probe) status = driver->probe(client); else @@ -602,6 +605,7 @@ static int i2c_device_probe(struct device *dev) return 0; err_release_driver_resources: + debugfs_remove_recursive(client->debugfs); devres_release_group(&client->dev, client->devres_group_id); err_detach_pm_domain: dev_pm_domain_detach(&client->dev, do_power_on); @@ -627,6 +631,8 @@ static void i2c_device_remove(struct device *dev) driver->remove(client); } + debugfs_remove_recursive(client->debugfs); + devres_release_group(&client->dev, client->devres_group_id); dev_pm_domain_detach(&client->dev, true); @@ -1058,6 +1064,7 @@ void i2c_unregister_device(struct i2c_client *client) if (ACPI_COMPANION(&client->dev)) acpi_device_clear_enumerated(ACPI_COMPANION(&client->dev)); + device_remove_software_node(&client->dev); device_unregister(&client->dev); } @@ -2520,9 +2527,10 @@ static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver) return 0; /* Set up a temporary client to help detect callback */ - temp_client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); + temp_client = kzalloc(sizeof(*temp_client), GFP_KERNEL); if (!temp_client) return -ENOMEM; + temp_client->adapter = adapter; for (i = 0; address_list[i] != I2C_CLIENT_END; i += 1) { @@ -2536,6 +2544,7 @@ static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver) } kfree(temp_client); + return err; } diff --git a/drivers/i2c/i2c-core-of.c b/drivers/i2c/i2c-core-of.c index a6c407d36800..02feee6c9ba9 100644 --- a/drivers/i2c/i2c-core-of.c +++ b/drivers/i2c/i2c-core-of.c @@ -157,7 +157,6 @@ const struct of_device_id return i2c_of_match_device_sysfs(matches, client); } -EXPORT_SYMBOL_GPL(i2c_of_match_device); #if IS_ENABLED(CONFIG_OF_DYNAMIC) static int of_i2c_notify(struct notifier_block *nb, unsigned long action, diff --git a/drivers/i2c/i2c-core.h b/drivers/i2c/i2c-core.h index 36587f38dff3..4797ba88331c 100644 --- a/drivers/i2c/i2c-core.h +++ b/drivers/i2c/i2c-core.h @@ -84,8 +84,17 @@ static inline void i2c_acpi_remove_space_handler(struct i2c_adapter *adapter) { #ifdef CONFIG_OF void of_i2c_register_devices(struct i2c_adapter *adap); +const struct of_device_id *i2c_of_match_device(const struct of_device_id *matches, + struct i2c_client *client); + #else static inline void of_i2c_register_devices(struct i2c_adapter *adap) { } +static inline +const struct of_device_id *i2c_of_match_device(const struct of_device_id *matches, + struct i2c_client *client) +{ + return NULL; +} #endif extern struct notifier_block i2c_of_notifier; diff --git a/drivers/i2c/i2c-slave-eeprom.c b/drivers/i2c/i2c-slave-eeprom.c index 5946c0d0aef9..275d1d0e910f 100644 --- a/drivers/i2c/i2c-slave-eeprom.c +++ b/drivers/i2c/i2c-slave-eeprom.c @@ -91,7 +91,7 @@ static int i2c_slave_eeprom_slave_cb(struct i2c_client *client, } static ssize_t i2c_slave_eeprom_bin_read(struct file *filp, struct kobject *kobj, - struct bin_attribute *attr, char *buf, loff_t off, size_t count) + const struct bin_attribute *attr, char *buf, loff_t off, size_t count) { struct eeprom_data *eeprom; unsigned long flags; @@ -106,7 +106,7 @@ static ssize_t i2c_slave_eeprom_bin_read(struct file *filp, struct kobject *kobj } static ssize_t i2c_slave_eeprom_bin_write(struct file *filp, struct kobject *kobj, - struct bin_attribute *attr, char *buf, loff_t off, size_t count) + const struct bin_attribute *attr, char *buf, loff_t off, size_t count) { struct eeprom_data *eeprom; unsigned long flags; @@ -165,8 +165,8 @@ static int i2c_slave_eeprom_probe(struct i2c_client *client) sysfs_bin_attr_init(&eeprom->bin); eeprom->bin.attr.name = "slave-eeprom"; eeprom->bin.attr.mode = S_IRUSR | S_IWUSR; - eeprom->bin.read = i2c_slave_eeprom_bin_read; - eeprom->bin.write = i2c_slave_eeprom_bin_write; + eeprom->bin.read_new = i2c_slave_eeprom_bin_read; + eeprom->bin.write_new = i2c_slave_eeprom_bin_write; eeprom->bin.size = size; ret = sysfs_create_bin_file(&client->dev.kobj, &eeprom->bin); diff --git a/drivers/i2c/muxes/i2c-mux-ltc4306.c b/drivers/i2c/muxes/i2c-mux-ltc4306.c index 19a7c370946d..8a87f19bf5d5 100644 --- a/drivers/i2c/muxes/i2c-mux-ltc4306.c +++ b/drivers/i2c/muxes/i2c-mux-ltc4306.c @@ -303,7 +303,7 @@ static void ltc4306_remove(struct i2c_client *client) static struct i2c_driver ltc4306_driver = { .driver = { .name = "ltc4306", - .of_match_table = of_match_ptr(ltc4306_of_match), + .of_match_table = ltc4306_of_match, }, .probe = ltc4306_probe, .remove = ltc4306_remove, diff --git a/drivers/i2c/muxes/i2c-mux-pca954x.c b/drivers/i2c/muxes/i2c-mux-pca954x.c index 6f84018258c4..db95113a5b49 100644 --- a/drivers/i2c/muxes/i2c-mux-pca954x.c +++ b/drivers/i2c/muxes/i2c-mux-pca954x.c @@ -414,7 +414,7 @@ static irqreturn_t pca954x_irq_handler(int irq, void *dev_id) pending = (ret >> PCA954X_IRQ_OFFSET) & (BIT(data->chip->nchans) - 1); for_each_set_bit(i, &pending, data->chip->nchans) - handle_nested_irq(irq_linear_revmap(data->irq, i)); + handle_nested_irq(irq_find_mapping(data->irq, i)); return IRQ_RETVAL(pending); } diff --git a/drivers/i2c/muxes/i2c-mux-reg.c b/drivers/i2c/muxes/i2c-mux-reg.c index dfa472d514cc..1e566ea92bc9 100644 --- a/drivers/i2c/muxes/i2c-mux-reg.c +++ b/drivers/i2c/muxes/i2c-mux-reg.c @@ -250,7 +250,7 @@ static struct platform_driver i2c_mux_reg_driver = { .remove = i2c_mux_reg_remove, .driver = { .name = "i2c-mux-reg", - .of_match_table = of_match_ptr(i2c_mux_reg_of_match), + .of_match_table = i2c_mux_reg_of_match, }, }; |