diff options
Diffstat (limited to 'drivers/i2c/busses')
31 files changed, 726 insertions, 240 deletions
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 09367fc014c3..146ce40d8e0a 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -429,6 +429,7 @@ config I2C_AXXIA tristate "Axxia I2C controller" depends on ARCH_AXXIA || COMPILE_TEST default ARCH_AXXIA + select I2C_SLAVE help Say yes if you want to support the I2C bus on Axxia platforms. @@ -684,7 +685,7 @@ config I2C_IMX_LPI2C config I2C_IOP3XX tristate "Intel IOPx3xx and IXP4xx on-chip I2C interface" - depends on ARCH_IOP32X || ARCH_IOP33X || ARCH_IXP4XX || ARCH_IOP13XX + depends on ARCH_IOP32X || ARCH_IXP4XX help Say Y here if you want to use the IIC bus controller on the Intel IOPx3xx I/O Processors or IXP4xx Network Processors. @@ -977,7 +978,7 @@ config I2C_SIRF will be called i2c-sirf. config I2C_SPRD - bool "Spreadtrum I2C interface" + tristate "Spreadtrum I2C interface" depends on I2C=y && ARCH_SPRD help If you say yes to this option, support will be included for the @@ -1206,7 +1207,7 @@ config I2C_PARPORT and makes it easier to add support for new devices. An adapter type parameter is now mandatory. Please read the file - Documentation/i2c/busses/i2c-parport for details. + Documentation/i2c/busses/i2c-parport.rst for details. Another driver exists, named i2c-parport-light, which doesn't depend on the parport driver. This is meant for embedded systems. Don't say @@ -1309,6 +1310,20 @@ config I2C_ELEKTOR This support is also available as a module. If so, the module will be called i2c-elektor. +config I2C_ICY + tristate "ICY Zorro card" + depends on ZORRO + select I2C_ALGOPCF + help + This supports the PCF8584 Zorro bus I2C adapter, known as ICY. + Say Y if you own such an adapter. + + This support is also available as a module. If so, the module + will be called i2c-icy. + + If you have a 2019 edition board with an LTC2990 sensor at address + 0x4c, loading the module 'ltc2990' is sufficient to enable it. + config I2C_MLXCPLD tristate "Mellanox I2C driver" depends on X86_64 @@ -1345,7 +1360,7 @@ config I2C_SIBYTE config I2C_CROS_EC_TUNNEL tristate "ChromeOS EC tunnel I2C bus" - depends on MFD_CROS_EC + depends on CROS_EC help If you say yes here you get an I2C bus that will tunnel i2c commands through to the other side of the ChromeOS EC to the i2c bus diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index 80c23895eaaf..3ab8aebc39c9 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -140,6 +140,7 @@ obj-$(CONFIG_I2C_BCM_KONA) += i2c-bcm-kona.o obj-$(CONFIG_I2C_BRCMSTB) += i2c-brcmstb.o obj-$(CONFIG_I2C_CROS_EC_TUNNEL) += i2c-cros-ec-tunnel.o obj-$(CONFIG_I2C_ELEKTOR) += i2c-elektor.o +obj-$(CONFIG_I2C_ICY) += i2c-icy.o obj-$(CONFIG_I2C_MLXCPLD) += i2c-mlxcpld.o obj-$(CONFIG_I2C_OPAL) += i2c-opal.o obj-$(CONFIG_I2C_PCA_ISA) += i2c-pca-isa.o diff --git a/drivers/i2c/busses/i2c-amd-mp2-pci.c b/drivers/i2c/busses/i2c-amd-mp2-pci.c index c7fe3b44a860..5e4800d72e00 100644 --- a/drivers/i2c/busses/i2c-amd-mp2-pci.c +++ b/drivers/i2c/busses/i2c-amd-mp2-pci.c @@ -457,18 +457,12 @@ static struct pci_driver amd_mp2_pci_driver = { }; module_pci_driver(amd_mp2_pci_driver); -static int amd_mp2_device_match(struct device *dev, const void *data) -{ - return 1; -} - struct amd_mp2_dev *amd_mp2_find_device(void) { struct device *dev; struct pci_dev *pci_dev; - dev = driver_find_device(&amd_mp2_pci_driver.driver, NULL, NULL, - amd_mp2_device_match); + dev = driver_find_next_device(&amd_mp2_pci_driver.driver, NULL); if (!dev) return NULL; diff --git a/drivers/i2c/busses/i2c-axxia.c b/drivers/i2c/busses/i2c-axxia.c index ff3142b15cab..0214daa913ff 100644 --- a/drivers/i2c/busses/i2c-axxia.c +++ b/drivers/i2c/busses/i2c-axxia.c @@ -77,6 +77,40 @@ MST_STATUS_IP) #define MST_TX_BYTES_XFRD 0x50 #define MST_RX_BYTES_XFRD 0x54 +#define SLV_ADDR_DEC_CTL 0x58 +#define SLV_ADDR_DEC_GCE BIT(0) /* ACK to General Call Address from own master (loopback) */ +#define SLV_ADDR_DEC_OGCE BIT(1) /* ACK to General Call Address from external masters */ +#define SLV_ADDR_DEC_SA1E BIT(2) /* ACK to addr_1 enabled */ +#define SLV_ADDR_DEC_SA1M BIT(3) /* 10-bit addressing for addr_1 enabled */ +#define SLV_ADDR_DEC_SA2E BIT(4) /* ACK to addr_2 enabled */ +#define SLV_ADDR_DEC_SA2M BIT(5) /* 10-bit addressing for addr_2 enabled */ +#define SLV_ADDR_1 0x5c +#define SLV_ADDR_2 0x60 +#define SLV_RX_CTL 0x64 +#define SLV_RX_ACSA1 BIT(0) /* Generate ACK for writes to addr_1 */ +#define SLV_RX_ACSA2 BIT(1) /* Generate ACK for writes to addr_2 */ +#define SLV_RX_ACGCA BIT(2) /* ACK data phase transfers to General Call Address */ +#define SLV_DATA 0x68 +#define SLV_RX_FIFO 0x6c +#define SLV_FIFO_DV1 BIT(0) /* Data Valid for addr_1 */ +#define SLV_FIFO_DV2 BIT(1) /* Data Valid for addr_2 */ +#define SLV_FIFO_AS BIT(2) /* (N)ACK Sent */ +#define SLV_FIFO_TNAK BIT(3) /* Timeout NACK */ +#define SLV_FIFO_STRC BIT(4) /* First byte after start condition received */ +#define SLV_FIFO_RSC BIT(5) /* Repeated Start Condition */ +#define SLV_FIFO_STPC BIT(6) /* Stop Condition */ +#define SLV_FIFO_DV (SLV_FIFO_DV1 | SLV_FIFO_DV2) +#define SLV_INT_ENABLE 0x70 +#define SLV_INT_STATUS 0x74 +#define SLV_STATUS_RFH BIT(0) /* FIFO service */ +#define SLV_STATUS_WTC BIT(1) /* Write transfer complete */ +#define SLV_STATUS_SRS1 BIT(2) /* Slave read from addr 1 */ +#define SLV_STATUS_SRRS1 BIT(3) /* Repeated start from addr 1 */ +#define SLV_STATUS_SRND1 BIT(4) /* Read request not following start condition */ +#define SLV_STATUS_SRC1 BIT(5) /* Read canceled */ +#define SLV_STATUS_SRAT1 BIT(6) /* Slave Read timed out */ +#define SLV_STATUS_SRDRE1 BIT(7) /* Data written after timed out */ +#define SLV_READ_DUMMY 0x78 #define SCL_HIGH_PERIOD 0x80 #define SCL_LOW_PERIOD 0x84 #define SPIKE_FLTR_LEN 0x88 @@ -111,6 +145,8 @@ struct axxia_i2c_dev { struct clk *i2c_clk; u32 bus_clk_rate; bool last; + struct i2c_client *slave; + int irq; }; static void i2c_int_disable(struct axxia_i2c_dev *idev, u32 mask) @@ -276,13 +312,65 @@ static int axxia_i2c_fill_tx_fifo(struct axxia_i2c_dev *idev) return ret; } +static void axxia_i2c_slv_fifo_event(struct axxia_i2c_dev *idev) +{ + u32 fifo_status = readl(idev->base + SLV_RX_FIFO); + u8 val; + + dev_dbg(idev->dev, "slave irq fifo_status=0x%x\n", fifo_status); + + if (fifo_status & SLV_FIFO_DV1) { + if (fifo_status & SLV_FIFO_STRC) + i2c_slave_event(idev->slave, + I2C_SLAVE_WRITE_REQUESTED, &val); + + val = readl(idev->base + SLV_DATA); + i2c_slave_event(idev->slave, I2C_SLAVE_WRITE_RECEIVED, &val); + } + if (fifo_status & SLV_FIFO_STPC) { + readl(idev->base + SLV_DATA); /* dummy read */ + i2c_slave_event(idev->slave, I2C_SLAVE_STOP, &val); + } + if (fifo_status & SLV_FIFO_RSC) + readl(idev->base + SLV_DATA); /* dummy read */ +} + +static irqreturn_t axxia_i2c_slv_isr(struct axxia_i2c_dev *idev) +{ + u32 status = readl(idev->base + SLV_INT_STATUS); + u8 val; + + dev_dbg(idev->dev, "slave irq status=0x%x\n", status); + + if (status & SLV_STATUS_RFH) + axxia_i2c_slv_fifo_event(idev); + if (status & SLV_STATUS_SRS1) { + i2c_slave_event(idev->slave, I2C_SLAVE_READ_REQUESTED, &val); + writel(val, idev->base + SLV_DATA); + } + if (status & SLV_STATUS_SRND1) { + i2c_slave_event(idev->slave, I2C_SLAVE_READ_PROCESSED, &val); + writel(val, idev->base + SLV_DATA); + } + if (status & SLV_STATUS_SRC1) + i2c_slave_event(idev->slave, I2C_SLAVE_STOP, &val); + + writel(INT_SLV, idev->base + INTERRUPT_STATUS); + return IRQ_HANDLED; +} + static irqreturn_t axxia_i2c_isr(int irq, void *_dev) { struct axxia_i2c_dev *idev = _dev; + irqreturn_t ret = IRQ_NONE; u32 status; - if (!(readl(idev->base + INTERRUPT_STATUS) & INT_MST)) - return IRQ_NONE; + status = readl(idev->base + INTERRUPT_STATUS); + + if (status & INT_SLV) + ret = axxia_i2c_slv_isr(idev); + if (!(status & INT_MST)) + return ret; /* Read interrupt status bits */ status = readl(idev->base + MST_INT_STATUS); @@ -583,9 +671,58 @@ static u32 axxia_i2c_func(struct i2c_adapter *adap) return caps; } +static int axxia_i2c_reg_slave(struct i2c_client *slave) +{ + struct axxia_i2c_dev *idev = i2c_get_adapdata(slave->adapter); + u32 slv_int_mask = SLV_STATUS_RFH; + u32 dec_ctl; + + if (idev->slave) + return -EBUSY; + + idev->slave = slave; + + /* Enable slave mode as well */ + writel(GLOBAL_MST_EN | GLOBAL_SLV_EN, idev->base + GLOBAL_CONTROL); + writel(INT_MST | INT_SLV, idev->base + INTERRUPT_ENABLE); + + /* Set slave address */ + dec_ctl = SLV_ADDR_DEC_SA1E; + if (slave->flags & I2C_CLIENT_TEN) + dec_ctl |= SLV_ADDR_DEC_SA1M; + + writel(SLV_RX_ACSA1, idev->base + SLV_RX_CTL); + writel(dec_ctl, idev->base + SLV_ADDR_DEC_CTL); + writel(slave->addr, idev->base + SLV_ADDR_1); + + /* Enable interrupts */ + slv_int_mask |= SLV_STATUS_SRS1 | SLV_STATUS_SRRS1 | SLV_STATUS_SRND1; + slv_int_mask |= SLV_STATUS_SRC1; + writel(slv_int_mask, idev->base + SLV_INT_ENABLE); + + return 0; +} + +static int axxia_i2c_unreg_slave(struct i2c_client *slave) +{ + struct axxia_i2c_dev *idev = i2c_get_adapdata(slave->adapter); + + /* Disable slave mode */ + writel(GLOBAL_MST_EN, idev->base + GLOBAL_CONTROL); + writel(INT_MST, idev->base + INTERRUPT_ENABLE); + + synchronize_irq(idev->irq); + + idev->slave = NULL; + + return 0; +} + static const struct i2c_algorithm axxia_i2c_algo = { .master_xfer = axxia_i2c_xfer, .functionality = axxia_i2c_func, + .reg_slave = axxia_i2c_reg_slave, + .unreg_slave = axxia_i2c_unreg_slave, }; static const struct i2c_adapter_quirks axxia_i2c_quirks = { @@ -599,7 +736,6 @@ static int axxia_i2c_probe(struct platform_device *pdev) struct axxia_i2c_dev *idev = NULL; struct resource *res; void __iomem *base; - int irq; int ret = 0; idev = devm_kzalloc(&pdev->dev, sizeof(*idev), GFP_KERNEL); @@ -611,10 +747,10 @@ static int axxia_i2c_probe(struct platform_device *pdev) if (IS_ERR(base)) return PTR_ERR(base); - irq = platform_get_irq(pdev, 0); - if (irq < 0) { + idev->irq = platform_get_irq(pdev, 0); + if (idev->irq < 0) { dev_err(&pdev->dev, "missing interrupt resource\n"); - return irq; + return idev->irq; } idev->i2c_clk = devm_clk_get(&pdev->dev, "i2c"); @@ -643,10 +779,10 @@ static int axxia_i2c_probe(struct platform_device *pdev) goto error_disable_clk; } - ret = devm_request_irq(&pdev->dev, irq, axxia_i2c_isr, 0, + ret = devm_request_irq(&pdev->dev, idev->irq, axxia_i2c_isr, 0, pdev->name, idev); if (ret) { - dev_err(&pdev->dev, "failed to claim IRQ%d\n", irq); + dev_err(&pdev->dev, "failed to claim IRQ%d\n", idev->irq); goto error_disable_clk; } diff --git a/drivers/i2c/busses/i2c-bcm-iproc.c b/drivers/i2c/busses/i2c-bcm-iproc.c index d7fd76baec92..9ffdffaf6141 100644 --- a/drivers/i2c/busses/i2c-bcm-iproc.c +++ b/drivers/i2c/busses/i2c-bcm-iproc.c @@ -790,7 +790,10 @@ static int bcm_iproc_i2c_xfer(struct i2c_adapter *adapter, static uint32_t bcm_iproc_i2c_functionality(struct i2c_adapter *adap) { - u32 val = I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; + u32 val; + + /* We do not support the SMBUS Quick command */ + val = I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK); if (adap->algo->reg_slave) val |= I2C_FUNC_SLAVE; @@ -805,7 +808,7 @@ static struct i2c_algorithm bcm_iproc_algo = { .unreg_slave = bcm_iproc_i2c_unreg_slave, }; -static struct i2c_adapter_quirks bcm_iproc_i2c_quirks = { +static const struct i2c_adapter_quirks bcm_iproc_i2c_quirks = { .max_read_len = M_RX_MAX_READ_LEN, }; @@ -919,7 +922,9 @@ static int bcm_iproc_i2c_probe(struct platform_device *pdev) adap = &iproc_i2c->adapter; i2c_set_adapdata(adap, iproc_i2c); - strlcpy(adap->name, "Broadcom iProc I2C adapter", sizeof(adap->name)); + snprintf(adap->name, sizeof(adap->name), + "Broadcom iProc (%s)", + of_node_full_name(iproc_i2c->device->of_node)); adap->algo = &bcm_iproc_algo; adap->quirks = &bcm_iproc_i2c_quirks; adap->dev.parent = &pdev->dev; diff --git a/drivers/i2c/busses/i2c-bcm2835.c b/drivers/i2c/busses/i2c-bcm2835.c index 67752f7b0371..e01b2b57e724 100644 --- a/drivers/i2c/busses/i2c-bcm2835.c +++ b/drivers/i2c/busses/i2c-bcm2835.c @@ -12,6 +12,7 @@ #include <linux/interrupt.h> #include <linux/io.h> #include <linux/module.h> +#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/slab.h> @@ -389,7 +390,7 @@ static const struct i2c_algorithm bcm2835_i2c_algo = { }; /* - * This HW was reported to have problems with clock stretching: + * The BCM2835 was reported to have problems with clock stretching: * http://www.advamation.com/knowhow/raspberrypi/rpi-i2c-bug.html * https://www.raspberrypi.org/forums/viewtopic.php?p=146272 */ @@ -471,11 +472,12 @@ static int bcm2835_i2c_probe(struct platform_device *pdev) i2c_set_adapdata(adap, i2c_dev); adap->owner = THIS_MODULE; adap->class = I2C_CLASS_DEPRECATED; - strlcpy(adap->name, "bcm2835 I2C adapter", sizeof(adap->name)); + snprintf(adap->name, sizeof(adap->name), "bcm2835 (%s)", + of_node_full_name(pdev->dev.of_node)); adap->algo = &bcm2835_i2c_algo; adap->dev.parent = &pdev->dev; adap->dev.of_node = pdev->dev.of_node; - adap->quirks = &bcm2835_i2c_quirks; + adap->quirks = of_device_get_match_data(&pdev->dev); bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, 0); @@ -501,7 +503,8 @@ static int bcm2835_i2c_remove(struct platform_device *pdev) } static const struct of_device_id bcm2835_i2c_of_match[] = { - { .compatible = "brcm,bcm2835-i2c" }, + { .compatible = "brcm,bcm2711-i2c" }, + { .compatible = "brcm,bcm2835-i2c", .data = &bcm2835_i2c_quirks }, {}, }; MODULE_DEVICE_TABLE(of, bcm2835_i2c_of_match); diff --git a/drivers/i2c/busses/i2c-cht-wc.c b/drivers/i2c/busses/i2c-cht-wc.c index 66af44bfa67d..b8fde61bb5d8 100644 --- a/drivers/i2c/busses/i2c-cht-wc.c +++ b/drivers/i2c/busses/i2c-cht-wc.c @@ -178,6 +178,51 @@ static const struct i2c_algorithm cht_wc_i2c_adap_algo = { .smbus_xfer = cht_wc_i2c_adap_smbus_xfer, }; +/* + * We are an i2c-adapter which itself is part of an i2c-client. This means that + * transfers done through us take adapter->bus_lock twice, once for our parent + * i2c-adapter and once to take our own bus_lock. Lockdep does not like this + * nested locking, to make lockdep happy in the case of busses with muxes, the + * i2c-core's i2c_adapter_lock_bus function calls: + * rt_mutex_lock_nested(&adapter->bus_lock, i2c_adapter_depth(adapter)); + * + * But i2c_adapter_depth only works when the direct parent of the adapter is + * another adapter, as it is only meant for muxes. In our case there is an + * i2c-client and MFD instantiated platform_device in the parent->child chain + * between the 2 devices. + * + * So we override the default i2c_lock_operations and pass a hardcoded + * depth of 1 to rt_mutex_lock_nested, to make lockdep happy. + * + * Note that if there were to be a mux attached to our adapter, this would + * break things again since the i2c-mux code expects the root-adapter to have + * a locking depth of 0. But we always have only 1 client directly attached + * in the form of the Charger IC paired with the CHT Whiskey Cove PMIC. + */ +static void cht_wc_i2c_adap_lock_bus(struct i2c_adapter *adapter, + unsigned int flags) +{ + rt_mutex_lock_nested(&adapter->bus_lock, 1); +} + +static int cht_wc_i2c_adap_trylock_bus(struct i2c_adapter *adapter, + unsigned int flags) +{ + return rt_mutex_trylock(&adapter->bus_lock); +} + +static void cht_wc_i2c_adap_unlock_bus(struct i2c_adapter *adapter, + unsigned int flags) +{ + rt_mutex_unlock(&adapter->bus_lock); +} + +static const struct i2c_lock_operations cht_wc_i2c_adap_lock_ops = { + .lock_bus = cht_wc_i2c_adap_lock_bus, + .trylock_bus = cht_wc_i2c_adap_trylock_bus, + .unlock_bus = cht_wc_i2c_adap_unlock_bus, +}; + /**** irqchip for the client connected to the extchgr i2c adapter ****/ static void cht_wc_i2c_irq_lock(struct irq_data *data) { @@ -286,6 +331,7 @@ static int cht_wc_i2c_adap_i2c_probe(struct platform_device *pdev) adap->adapter.owner = THIS_MODULE; adap->adapter.class = I2C_CLASS_HWMON; adap->adapter.algo = &cht_wc_i2c_adap_algo; + adap->adapter.lock_ops = &cht_wc_i2c_adap_lock_ops; strlcpy(adap->adapter.name, "PMIC I2C Adapter", sizeof(adap->adapter.name)); adap->adapter.dev.parent = &pdev->dev; @@ -363,8 +409,7 @@ static int cht_wc_i2c_adap_i2c_remove(struct platform_device *pdev) { struct cht_wc_i2c_adap *adap = platform_get_drvdata(pdev); - if (adap->client) - i2c_unregister_device(adap->client); + i2c_unregister_device(adap->client); i2c_del_adapter(&adap->adapter); irq_domain_remove(adap->irq_domain); diff --git a/drivers/i2c/busses/i2c-cros-ec-tunnel.c b/drivers/i2c/busses/i2c-cros-ec-tunnel.c index 82bcd9a78759..c551aa96a2e3 100644 --- a/drivers/i2c/busses/i2c-cros-ec-tunnel.c +++ b/drivers/i2c/busses/i2c-cros-ec-tunnel.c @@ -5,8 +5,8 @@ #include <linux/module.h> #include <linux/i2c.h> -#include <linux/mfd/cros_ec.h> -#include <linux/mfd/cros_ec_commands.h> +#include <linux/platform_data/cros_ec_commands.h> +#include <linux/platform_data/cros_ec_proto.h> #include <linux/platform_device.h> #include <linux/slab.h> diff --git a/drivers/i2c/busses/i2c-designware-master.c b/drivers/i2c/busses/i2c-designware-master.c index d464799e40a3..e8b328242256 100644 --- a/drivers/i2c/busses/i2c-designware-master.c +++ b/drivers/i2c/busses/i2c-designware-master.c @@ -655,15 +655,11 @@ static int i2c_dw_init_recovery_info(struct dw_i2c_dev *dev) struct i2c_bus_recovery_info *rinfo = &dev->rinfo; struct i2c_adapter *adap = &dev->adapter; struct gpio_desc *gpio; - int r; - - gpio = devm_gpiod_get(dev->dev, "scl", GPIOD_OUT_HIGH); - if (IS_ERR(gpio)) { - r = PTR_ERR(gpio); - if (r == -ENOENT || r == -ENOSYS) - return 0; - return r; - } + + gpio = devm_gpiod_get_optional(dev->dev, "scl", GPIOD_OUT_HIGH); + if (IS_ERR_OR_NULL(gpio)) + return PTR_ERR_OR_ZERO(gpio); + rinfo->scl_gpiod = gpio; gpio = devm_gpiod_get_optional(dev->dev, "sda", GPIOD_IN); diff --git a/drivers/i2c/busses/i2c-designware-pcidrv.c b/drivers/i2c/busses/i2c-designware-pcidrv.c index 76810deb2de6..050adda7c1bd 100644 --- a/drivers/i2c/busses/i2c-designware-pcidrv.c +++ b/drivers/i2c/busses/i2c-designware-pcidrv.c @@ -33,6 +33,7 @@ enum dw_pci_ctl_id_t { baytrail, cherrytrail, haswell, + elkhartlake, }; struct dw_scl_sda_cfg { @@ -168,13 +169,20 @@ static struct dw_pci_controller dw_pci_controllers[] = { .flags = MODEL_CHERRYTRAIL, .scl_sda_cfg = &byt_config, }, + [elkhartlake] = { + .bus_num = -1, + .bus_cfg = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST, + .tx_fifo_depth = 32, + .rx_fifo_depth = 32, + .functionality = I2C_FUNC_10BIT_ADDR, + .clk_khz = 100000, + }, }; #ifdef CONFIG_PM static int i2c_dw_pci_suspend(struct device *dev) { - struct pci_dev *pdev = to_pci_dev(dev); - struct dw_i2c_dev *i_dev = pci_get_drvdata(pdev); + struct dw_i2c_dev *i_dev = dev_get_drvdata(dev); i_dev->suspended = true; i_dev->disable(i_dev); @@ -184,8 +192,7 @@ static int i2c_dw_pci_suspend(struct device *dev) static int i2c_dw_pci_resume(struct device *dev) { - struct pci_dev *pdev = to_pci_dev(dev); - struct dw_i2c_dev *i_dev = pci_get_drvdata(pdev); + struct dw_i2c_dev *i_dev = dev_get_drvdata(dev); int ret; ret = i_dev->init(i_dev); @@ -227,6 +234,8 @@ static int i2c_dw_pci_probe(struct pci_dev *pdev, return r; } + pci_set_master(pdev); + r = pcim_iomap_regions(pdev, 1 << 0, pci_name(pdev)); if (r) { dev_err(&pdev->dev, "I/O memory remapping failed\n"); @@ -237,18 +246,24 @@ static int i2c_dw_pci_probe(struct pci_dev *pdev, if (!dev) return -ENOMEM; + r = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES); + if (r < 0) + return r; + dev->clk = NULL; dev->controller = controller; dev->get_clk_rate_khz = i2c_dw_get_clk_rate_khz; dev->base = pcim_iomap_table(pdev)[0]; dev->dev = &pdev->dev; - dev->irq = pdev->irq; + dev->irq = pci_irq_vector(pdev, 0); dev->flags |= controller->flags; if (controller->setup) { r = controller->setup(pdev, controller); - if (r) + if (r) { + pci_free_irq_vectors(pdev); return r; + } } dev->functionality = controller->functionality | @@ -276,8 +291,10 @@ static int i2c_dw_pci_probe(struct pci_dev *pdev, adap->nr = controller->bus_num; r = i2c_dw_probe(dev); - if (r) + if (r) { + pci_free_irq_vectors(pdev); return r; + } pm_runtime_set_autosuspend_delay(&pdev->dev, 1000); pm_runtime_use_autosuspend(&pdev->dev); @@ -296,6 +313,7 @@ static void i2c_dw_pci_remove(struct pci_dev *pdev) pm_runtime_get_noresume(&pdev->dev); i2c_del_adapter(&dev->adapter); + pci_free_irq_vectors(pdev); } /* work with hotplug and coldplug */ @@ -331,6 +349,15 @@ static const struct pci_device_id i2_designware_pci_ids[] = { { PCI_VDEVICE(INTEL, 0x22C5), cherrytrail }, { PCI_VDEVICE(INTEL, 0x22C6), cherrytrail }, { PCI_VDEVICE(INTEL, 0x22C7), cherrytrail }, + /* Elkhart Lake (PSE I2C) */ + { PCI_VDEVICE(INTEL, 0x4bb9), elkhartlake }, + { PCI_VDEVICE(INTEL, 0x4bba), elkhartlake }, + { PCI_VDEVICE(INTEL, 0x4bbb), elkhartlake }, + { PCI_VDEVICE(INTEL, 0x4bbc), elkhartlake }, + { PCI_VDEVICE(INTEL, 0x4bbd), elkhartlake }, + { PCI_VDEVICE(INTEL, 0x4bbe), elkhartlake }, + { PCI_VDEVICE(INTEL, 0x4bbf), elkhartlake }, + { PCI_VDEVICE(INTEL, 0x4bc0), elkhartlake }, { 0,} }; MODULE_DEVICE_TABLE(pci, i2_designware_pci_ids); diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c index ddfb81872906..16dd338877d0 100644 --- a/drivers/i2c/busses/i2c-designware-platdrv.c +++ b/drivers/i2c/busses/i2c-designware-platdrv.c @@ -279,12 +279,10 @@ static int dw_i2c_plat_probe(struct platform_device *pdev) platform_set_drvdata(pdev, dev); dev->rst = devm_reset_control_get_optional_exclusive(&pdev->dev, NULL); - if (IS_ERR(dev->rst)) { - if (PTR_ERR(dev->rst) == -EPROBE_DEFER) - return -EPROBE_DEFER; - } else { - reset_control_deassert(dev->rst); - } + if (IS_ERR(dev->rst)) + return PTR_ERR(dev->rst); + + reset_control_deassert(dev->rst); t = &dev->timings; if (pdata) @@ -346,8 +344,10 @@ static int dw_i2c_plat_probe(struct platform_device *pdev) /* Optional interface clock */ dev->pclk = devm_clk_get_optional(&pdev->dev, "pclk"); - if (IS_ERR(dev->pclk)) - return PTR_ERR(dev->pclk); + if (IS_ERR(dev->pclk)) { + ret = PTR_ERR(dev->pclk); + goto exit_reset; + } dev->clk = devm_clk_get(&pdev->dev, NULL); if (!i2c_dw_prepare_clk(dev, true)) { @@ -400,8 +400,7 @@ static int dw_i2c_plat_probe(struct platform_device *pdev) exit_probe: dw_i2c_plat_pm_cleanup(dev); exit_reset: - if (!IS_ERR_OR_NULL(dev->rst)) - reset_control_assert(dev->rst); + reset_control_assert(dev->rst); return ret; } @@ -419,8 +418,7 @@ static int dw_i2c_plat_remove(struct platform_device *pdev) pm_runtime_put_sync(&pdev->dev); dw_i2c_plat_pm_cleanup(dev); - if (!IS_ERR_OR_NULL(dev->rst)) - reset_control_assert(dev->rst); + reset_control_assert(dev->rst); return 0; } diff --git a/drivers/i2c/busses/i2c-designware-slave.c b/drivers/i2c/busses/i2c-designware-slave.c index e7f9305b2dd9..f5f001738df5 100644 --- a/drivers/i2c/busses/i2c-designware-slave.c +++ b/drivers/i2c/busses/i2c-designware-slave.c @@ -94,6 +94,7 @@ static int i2c_dw_unreg_slave(struct i2c_client *slave) dev->disable_int(dev); dev->disable(dev); + synchronize_irq(dev->irq); dev->slave = NULL; pm_runtime_put(dev->dev); diff --git a/drivers/i2c/busses/i2c-exynos5.c b/drivers/i2c/busses/i2c-exynos5.c index e4e7932f7800..e7514c16b756 100644 --- a/drivers/i2c/busses/i2c-exynos5.c +++ b/drivers/i2c/busses/i2c-exynos5.c @@ -791,9 +791,7 @@ static int exynos5_i2c_probe(struct platform_device *pdev) } ret = devm_request_irq(&pdev->dev, i2c->irq, exynos5_i2c_irq, - IRQF_NO_SUSPEND | IRQF_ONESHOT, - dev_name(&pdev->dev), i2c); - + IRQF_NO_SUSPEND, dev_name(&pdev->dev), i2c); if (ret != 0) { dev_err(&pdev->dev, "cannot request HS-I2C IRQ %d\n", i2c->irq); goto err_clk; diff --git a/drivers/i2c/busses/i2c-fsi.c b/drivers/i2c/busses/i2c-fsi.c index da5eb3960def..e0c256922d4f 100644 --- a/drivers/i2c/busses/i2c-fsi.c +++ b/drivers/i2c/busses/i2c-fsi.c @@ -707,8 +707,10 @@ static int fsi_i2c_probe(struct device *dev) continue; port = kzalloc(sizeof(*port), GFP_KERNEL); - if (!port) + if (!port) { + of_node_put(np); break; + } port->master = i2c; port->port = port_no; diff --git a/drivers/i2c/busses/i2c-hix5hd2.c b/drivers/i2c/busses/i2c-hix5hd2.c index 4df1434b3597..8497c7a95dd4 100644 --- a/drivers/i2c/busses/i2c-hix5hd2.c +++ b/drivers/i2c/busses/i2c-hix5hd2.c @@ -445,8 +445,7 @@ static int hix5hd2_i2c_probe(struct platform_device *pdev) hix5hd2_i2c_init(priv); ret = devm_request_irq(&pdev->dev, irq, hix5hd2_i2c_irq, - IRQF_NO_SUSPEND | IRQF_ONESHOT, - dev_name(&pdev->dev), priv); + IRQF_NO_SUSPEND, dev_name(&pdev->dev), priv); if (ret != 0) { dev_err(&pdev->dev, "cannot request HS-I2C IRQ %d\n", irq); goto err_clk; diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index f2956936c3f2..c09791fb4929 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -77,7 +77,7 @@ * SMBus Host Notify yes * Interrupt processing yes * - * See the file Documentation/i2c/busses/i2c-i801 for details. + * See the file Documentation/i2c/busses/i2c-i801.rst for details. */ #include <linux/interrupt.h> @@ -292,7 +292,8 @@ struct i801_priv { #define FEATURE_HOST_NOTIFY BIT(5) /* Not really a feature, but it's convenient to handle it as such */ #define FEATURE_IDF BIT(15) -#define FEATURE_TCO BIT(16) +#define FEATURE_TCO_SPT BIT(16) +#define FEATURE_TCO_CNL BIT(17) static const char *i801_feature_names[] = { "SMBus PEC", @@ -1194,19 +1195,28 @@ static acpi_status check_acpi_smo88xx_device(acpi_handle obj_handle, int i; status = acpi_get_object_info(obj_handle, &info); - if (!ACPI_SUCCESS(status) || !(info->valid & ACPI_VALID_HID)) + if (ACPI_FAILURE(status)) return AE_OK; + if (!(info->valid & ACPI_VALID_HID)) + goto smo88xx_not_found; + hid = info->hardware_id.string; if (!hid) - return AE_OK; + goto smo88xx_not_found; i = match_string(acpi_smo8800_ids, ARRAY_SIZE(acpi_smo8800_ids), hid); if (i < 0) - return AE_OK; + goto smo88xx_not_found; + + kfree(info); *((bool *)return_value) = true; return AE_CTRL_TERMINATE; + +smo88xx_not_found: + kfree(info); + return AE_OK; } static bool is_dell_system_with_lis3lv02d(void) @@ -1491,57 +1501,23 @@ static inline unsigned int i801_get_adapter_class(struct i801_priv *priv) } #endif -static const struct itco_wdt_platform_data tco_platform_data = { +static const struct itco_wdt_platform_data spt_tco_platform_data = { .name = "Intel PCH", .version = 4, }; static DEFINE_SPINLOCK(p2sb_spinlock); -static void i801_add_tco(struct i801_priv *priv) +static struct platform_device * +i801_add_tco_spt(struct i801_priv *priv, struct pci_dev *pci_dev, + struct resource *tco_res) { - struct pci_dev *pci_dev = priv->pci_dev; - struct resource tco_res[3], *res; - struct platform_device *pdev; + struct resource *res; unsigned int devfn; - u32 tco_base, tco_ctl; - u32 base_addr, ctrl_val; u64 base64_addr; + u32 base_addr; u8 hidden; - if (!(priv->features & FEATURE_TCO)) - return; - - pci_read_config_dword(pci_dev, TCOBASE, &tco_base); - pci_read_config_dword(pci_dev, TCOCTL, &tco_ctl); - if (!(tco_ctl & TCOCTL_EN)) - return; - - memset(tco_res, 0, sizeof(tco_res)); - - res = &tco_res[ICH_RES_IO_TCO]; - res->start = tco_base & ~1; - res->end = res->start + 32 - 1; - res->flags = IORESOURCE_IO; - - /* - * Power Management registers. - */ - devfn = PCI_DEVFN(PCI_SLOT(pci_dev->devfn), 2); - pci_bus_read_config_dword(pci_dev->bus, devfn, ACPIBASE, &base_addr); - - res = &tco_res[ICH_RES_IO_SMI]; - res->start = (base_addr & ~1) + ACPIBASE_SMI_OFF; - res->end = res->start + 3; - res->flags = IORESOURCE_IO; - - /* - * Enable the ACPI I/O space. - */ - pci_bus_read_config_dword(pci_dev->bus, devfn, ACPICTRL, &ctrl_val); - ctrl_val |= ACPICTRL_EN; - pci_bus_write_config_dword(pci_dev->bus, devfn, ACPICTRL, ctrl_val); - /* * We must access the NO_REBOOT bit over the Primary to Sideband * bridge (P2SB). The BIOS prevents the P2SB device from being @@ -1577,15 +1553,76 @@ static void i801_add_tco(struct i801_priv *priv) res->end = res->start + 3; res->flags = IORESOURCE_MEM; - pdev = platform_device_register_resndata(&pci_dev->dev, "iTCO_wdt", -1, - tco_res, 3, &tco_platform_data, - sizeof(tco_platform_data)); - if (IS_ERR(pdev)) { - dev_warn(&pci_dev->dev, "failed to create iTCO device\n"); + return platform_device_register_resndata(&pci_dev->dev, "iTCO_wdt", -1, + tco_res, 3, &spt_tco_platform_data, + sizeof(spt_tco_platform_data)); +} + +static const struct itco_wdt_platform_data cnl_tco_platform_data = { + .name = "Intel PCH", + .version = 6, +}; + +static struct platform_device * +i801_add_tco_cnl(struct i801_priv *priv, struct pci_dev *pci_dev, + struct resource *tco_res) +{ + return platform_device_register_resndata(&pci_dev->dev, "iTCO_wdt", -1, + tco_res, 2, &cnl_tco_platform_data, + sizeof(cnl_tco_platform_data)); +} + +static void i801_add_tco(struct i801_priv *priv) +{ + u32 base_addr, tco_base, tco_ctl, ctrl_val; + struct pci_dev *pci_dev = priv->pci_dev; + struct resource tco_res[3], *res; + unsigned int devfn; + + /* If we have ACPI based watchdog use that instead */ + if (acpi_has_watchdog()) + return; + + if (!(priv->features & (FEATURE_TCO_SPT | FEATURE_TCO_CNL))) + return; + + pci_read_config_dword(pci_dev, TCOBASE, &tco_base); + pci_read_config_dword(pci_dev, TCOCTL, &tco_ctl); + if (!(tco_ctl & TCOCTL_EN)) return; - } - priv->tco_pdev = pdev; + memset(tco_res, 0, sizeof(tco_res)); + + res = &tco_res[ICH_RES_IO_TCO]; + res->start = tco_base & ~1; + res->end = res->start + 32 - 1; + res->flags = IORESOURCE_IO; + + /* + * Power Management registers. + */ + devfn = PCI_DEVFN(PCI_SLOT(pci_dev->devfn), 2); + pci_bus_read_config_dword(pci_dev->bus, devfn, ACPIBASE, &base_addr); + + res = &tco_res[ICH_RES_IO_SMI]; + res->start = (base_addr & ~1) + ACPIBASE_SMI_OFF; + res->end = res->start + 3; + res->flags = IORESOURCE_IO; + + /* + * Enable the ACPI I/O space. + */ + pci_bus_read_config_dword(pci_dev->bus, devfn, ACPICTRL, &ctrl_val); + ctrl_val |= ACPICTRL_EN; + pci_bus_write_config_dword(pci_dev->bus, devfn, ACPICTRL, ctrl_val); + + if (priv->features & FEATURE_TCO_CNL) + priv->tco_pdev = i801_add_tco_cnl(priv, pci_dev, tco_res); + else + priv->tco_pdev = i801_add_tco_spt(priv, pci_dev, tco_res); + + if (IS_ERR(priv->tco_pdev)) + dev_warn(&pci_dev->dev, "failed to create iTCO device\n"); } #ifdef CONFIG_ACPI @@ -1695,13 +1732,21 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id) switch (dev->device) { case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_H_SMBUS: case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_SMBUS: - case PCI_DEVICE_ID_INTEL_CANNONLAKE_H_SMBUS: - case PCI_DEVICE_ID_INTEL_CANNONLAKE_LP_SMBUS: case PCI_DEVICE_ID_INTEL_LEWISBURG_SMBUS: case PCI_DEVICE_ID_INTEL_LEWISBURG_SSKU_SMBUS: - case PCI_DEVICE_ID_INTEL_CDF_SMBUS: case PCI_DEVICE_ID_INTEL_DNV_SMBUS: case PCI_DEVICE_ID_INTEL_KABYLAKE_PCH_H_SMBUS: + priv->features |= FEATURE_I2C_BLOCK_READ; + priv->features |= FEATURE_IRQ; + priv->features |= FEATURE_SMBUS_PEC; + priv->features |= FEATURE_BLOCK_BUFFER; + priv->features |= FEATURE_TCO_SPT; + priv->features |= FEATURE_HOST_NOTIFY; + break; + + case PCI_DEVICE_ID_INTEL_CANNONLAKE_H_SMBUS: + case PCI_DEVICE_ID_INTEL_CANNONLAKE_LP_SMBUS: + case PCI_DEVICE_ID_INTEL_CDF_SMBUS: case PCI_DEVICE_ID_INTEL_ICELAKE_LP_SMBUS: case PCI_DEVICE_ID_INTEL_COMETLAKE_SMBUS: case PCI_DEVICE_ID_INTEL_ELKHART_LAKE_SMBUS: @@ -1711,9 +1756,7 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id) priv->features |= FEATURE_IRQ; priv->features |= FEATURE_SMBUS_PEC; priv->features |= FEATURE_BLOCK_BUFFER; - /* If we have ACPI based watchdog use that instead */ - if (!acpi_has_watchdog()) - priv->features |= FEATURE_TCO; + priv->features |= FEATURE_TCO_CNL; priv->features |= FEATURE_HOST_NOTIFY; break; @@ -1912,8 +1955,7 @@ static int i801_suspend(struct device *dev) static int i801_resume(struct device *dev) { - struct pci_dev *pci_dev = to_pci_dev(dev); - struct i801_priv *priv = pci_get_drvdata(pci_dev); + struct i801_priv *priv = dev_get_drvdata(dev); i801_enable_host_notify(&priv->adapter); diff --git a/drivers/i2c/busses/i2c-icy.c b/drivers/i2c/busses/i2c-icy.c new file mode 100644 index 000000000000..8382eb64b424 --- /dev/null +++ b/drivers/i2c/busses/i2c-icy.c @@ -0,0 +1,230 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * I2C driver for stand-alone PCF8584 style adapters on Zorro cards + * + * Original ICY documentation can be found on Aminet: + * https://aminet.net/package/docs/hard/icy + * + * There has been a modern community re-print of this design in 2019: + * https://www.a1k.org/forum/index.php?threads/70106/ + * + * The card is basically a Philips PCF8584 connected straight to the + * beginning of the AutoConfig'd address space (register S1 on base+2), + * with /INT on /INT2 on the Zorro bus. + * + * Copyright (c) 2019 Max Staudt <max@enpas.org> + * + * This started as a fork of i2c-elektor.c and has evolved since. + * Thanks go to its authors for providing a base to grow on. + * + * + * IRQ support is currently not implemented. + * + * As it turns out, i2c-algo-pcf is really written with i2c-elektor's + * edge-triggered ISA interrupts in mind, while the Amiga's Zorro bus has + * level-triggered interrupts. This means that once an interrupt occurs, we + * have to tell the PCF8584 to shut up immediately, or it will keep the + * interrupt line busy and cause an IRQ storm. + + * However, because of the PCF8584's host-side protocol, there is no good + * way to just quieten it without side effects. Rather, we have to perform + * the next read/write operation straight away, which will reset the /INT + * pin. This entails re-designing the core of i2c-algo-pcf in the future. + * For now, we never request an IRQ from the PCF8584, and poll it instead. + */ + +#include <linux/delay.h> +#include <linux/init.h> +#include <linux/io.h> +#include <linux/ioport.h> +#include <linux/kernel.h> +#include <linux/module.h> + +#include <linux/i2c.h> +#include <linux/i2c-algo-pcf.h> + +#include <asm/amigaints.h> +#include <linux/zorro.h> + +#include "../algos/i2c-algo-pcf.h" + +struct icy_i2c { + struct i2c_adapter adapter; + + void __iomem *reg_s0; + void __iomem *reg_s1; + struct fwnode_handle *ltc2990_fwnode; + struct i2c_client *ltc2990_client; +}; + +/* + * Functions called by i2c-algo-pcf + */ +static void icy_pcf_setpcf(void *data, int ctl, int val) +{ + struct icy_i2c *i2c = (struct icy_i2c *)data; + + u8 __iomem *address = ctl ? i2c->reg_s1 : i2c->reg_s0; + + z_writeb(val, address); +} + +static int icy_pcf_getpcf(void *data, int ctl) +{ + struct icy_i2c *i2c = (struct icy_i2c *)data; + + u8 __iomem *address = ctl ? i2c->reg_s1 : i2c->reg_s0; + + return z_readb(address); +} + +static int icy_pcf_getown(void *data) +{ + return 0x55; +} + +static int icy_pcf_getclock(void *data) +{ + return 0x1c; +} + +static void icy_pcf_waitforpin(void *data) +{ + usleep_range(50, 150); +} + +/* + * Main i2c-icy part + */ +static unsigned short const icy_ltc2990_addresses[] = { + 0x4c, 0x4d, 0x4e, 0x4f, I2C_CLIENT_END +}; + +/* + * Additional sensors exposed once this property is applied: + * + * in1 will be the voltage of the 5V rail, divided by 2. + * in2 will be the voltage of the 12V rail, divided by 4. + * temp3 will be measured using a PCB loop next the chip. + */ +static const u32 icy_ltc2990_meas_mode[] = {0, 3}; + +static const struct property_entry icy_ltc2990_props[] = { + PROPERTY_ENTRY_U32_ARRAY("lltc,meas-mode", icy_ltc2990_meas_mode), + { } +}; + +static int icy_probe(struct zorro_dev *z, + const struct zorro_device_id *ent) +{ + struct icy_i2c *i2c; + struct i2c_algo_pcf_data *algo_data; + struct fwnode_handle *new_fwnode; + struct i2c_board_info ltc2990_info = { + .type = "ltc2990", + .addr = 0x4c, + }; + + i2c = devm_kzalloc(&z->dev, sizeof(*i2c), GFP_KERNEL); + if (!i2c) + return -ENOMEM; + + algo_data = devm_kzalloc(&z->dev, sizeof(*algo_data), GFP_KERNEL); + if (!algo_data) + return -ENOMEM; + + dev_set_drvdata(&z->dev, i2c); + i2c->adapter.dev.parent = &z->dev; + i2c->adapter.owner = THIS_MODULE; + /* i2c->adapter.algo assigned by i2c_pcf_add_bus() */ + i2c->adapter.algo_data = algo_data; + strlcpy(i2c->adapter.name, "ICY I2C Zorro adapter", + sizeof(i2c->adapter.name)); + + if (!devm_request_mem_region(&z->dev, + z->resource.start, + 4, i2c->adapter.name)) + return -ENXIO; + + /* Driver private data */ + i2c->reg_s0 = ZTWO_VADDR(z->resource.start); + i2c->reg_s1 = ZTWO_VADDR(z->resource.start + 2); + + algo_data->data = i2c; + algo_data->setpcf = icy_pcf_setpcf; + algo_data->getpcf = icy_pcf_getpcf; + algo_data->getown = icy_pcf_getown; + algo_data->getclock = icy_pcf_getclock; + algo_data->waitforpin = icy_pcf_waitforpin; + + if (i2c_pcf_add_bus(&i2c->adapter)) { + dev_err(&z->dev, "i2c_pcf_add_bus() failed\n"); + return -ENXIO; + } + + dev_info(&z->dev, "ICY I2C controller at %pa, IRQ not implemented\n", + &z->resource.start); + + /* + * The 2019 a1k.org PCBs have an LTC2990 at 0x4c, so start + * it automatically once ltc2990 is modprobed. + * + * in0 is the voltage of the internal 5V power supply. + * temp1 is the temperature inside the chip. + * + * See property_entry above for in1, in2, temp3. + */ + new_fwnode = fwnode_create_software_node(icy_ltc2990_props, NULL); + if (IS_ERR(new_fwnode)) { + dev_info(&z->dev, "Failed to create fwnode for LTC2990, error: %ld\n", + PTR_ERR(new_fwnode)); + } else { + /* + * Store the fwnode so we can destroy it on .remove(). + * Only store it on success, as fwnode_remove_software_node() + * is NULL safe, but not PTR_ERR safe. + */ + i2c->ltc2990_fwnode = new_fwnode; + ltc2990_info.fwnode = new_fwnode; + + i2c->ltc2990_client = + i2c_new_probed_device(&i2c->adapter, + <c2990_info, + icy_ltc2990_addresses, + NULL); + } + + return 0; +} + +static void icy_remove(struct zorro_dev *z) +{ + struct icy_i2c *i2c = dev_get_drvdata(&z->dev); + + i2c_unregister_device(i2c->ltc2990_client); + fwnode_remove_software_node(i2c->ltc2990_fwnode); + + i2c_del_adapter(&i2c->adapter); +} + +static const struct zorro_device_id icy_zorro_tbl[] = { + { ZORRO_ID(VMC, 15, 0), }, + { 0 } +}; + +MODULE_DEVICE_TABLE(zorro, icy_zorro_tbl); + +static struct zorro_driver icy_driver = { + .name = "i2c-icy", + .id_table = icy_zorro_tbl, + .probe = icy_probe, + .remove = icy_remove, +}; + +module_driver(icy_driver, + zorro_register_driver, + zorro_unregister_driver); + +MODULE_AUTHOR("Max Staudt <max@enpas.org>"); +MODULE_DESCRIPTION("I2C bus via PCF8584 on ICY Zorro card"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/i2c/busses/i2c-imx-lpi2c.c b/drivers/i2c/busses/i2c-imx-lpi2c.c index dc00fabc919a..c92b56485fa6 100644 --- a/drivers/i2c/busses/i2c-imx-lpi2c.c +++ b/drivers/i2c/busses/i2c-imx-lpi2c.c @@ -545,7 +545,6 @@ 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; unsigned int temp; int irq, ret; @@ -553,8 +552,7 @@ static int lpi2c_imx_probe(struct platform_device *pdev) if (!lpi2c_imx) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - lpi2c_imx->base = devm_ioremap_resource(&pdev->dev, res); + lpi2c_imx->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(lpi2c_imx->base)) return PTR_ERR(lpi2c_imx->base); diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c index 15f6cde6452f..a3b61336fe55 100644 --- a/drivers/i2c/busses/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c @@ -20,6 +20,7 @@ * */ +#include <linux/acpi.h> #include <linux/clk.h> #include <linux/completion.h> #include <linux/delay.h> @@ -255,6 +256,12 @@ static const struct of_device_id i2c_imx_dt_ids[] = { }; MODULE_DEVICE_TABLE(of, i2c_imx_dt_ids); +static const struct acpi_device_id i2c_imx_acpi_ids[] = { + {"NXP0001", .driver_data = (kernel_ulong_t)&vf610_i2c_hwdata}, + { } +}; +MODULE_DEVICE_TABLE(acpi, i2c_imx_acpi_ids); + static inline int is_imx1_i2c(struct imx_i2c_struct *i2c_imx) { return i2c_imx->hwdata->devtype == IMX1_I2C; @@ -1048,14 +1055,13 @@ static const struct i2c_algorithm i2c_imx_algo = { static int i2c_imx_probe(struct platform_device *pdev) { - const struct of_device_id *of_id = of_match_device(i2c_imx_dt_ids, - &pdev->dev); struct imx_i2c_struct *i2c_imx; struct resource *res; struct imxi2c_platform_data *pdata = dev_get_platdata(&pdev->dev); void __iomem *base; int irq, ret; dma_addr_t phy_addr; + const struct imx_i2c_hwdata *match; dev_dbg(&pdev->dev, "<%s>\n", __func__); @@ -1075,8 +1081,9 @@ static int i2c_imx_probe(struct platform_device *pdev) if (!i2c_imx) return -ENOMEM; - if (of_id) - i2c_imx->hwdata = of_id->data; + match = device_get_match_data(&pdev->dev); + if (match) + i2c_imx->hwdata = match; else i2c_imx->hwdata = (struct imx_i2c_hwdata *) platform_get_device_id(pdev)->driver_data; @@ -1089,6 +1096,7 @@ static int i2c_imx_probe(struct platform_device *pdev) i2c_imx->adapter.nr = pdev->id; i2c_imx->adapter.dev.of_node = pdev->dev.of_node; i2c_imx->base = base; + ACPI_COMPANION_SET(&i2c_imx->adapter.dev, ACPI_COMPANION(&pdev->dev)); /* Get I2C clock */ i2c_imx->clk = devm_clk_get(&pdev->dev, NULL); @@ -1247,6 +1255,7 @@ static struct platform_driver i2c_imx_driver = { .name = DRIVER_NAME, .pm = &i2c_imx_pm_ops, .of_match_table = i2c_imx_dt_ids, + .acpi_match_table = i2c_imx_acpi_ids, }, .id_table = imx_i2c_devtype, }; diff --git a/drivers/i2c/busses/i2c-ismt.c b/drivers/i2c/busses/i2c-ismt.c index 02d23edb2fb1..2f95e25a10f7 100644 --- a/drivers/i2c/busses/i2c-ismt.c +++ b/drivers/i2c/busses/i2c-ismt.c @@ -781,8 +781,6 @@ static int ismt_dev_init(struct ismt_priv *priv) if (!priv->hw) return -ENOMEM; - memset(priv->hw, 0, (ISMT_DESC_ENTRIES * sizeof(struct ismt_desc))); - priv->head = 0; init_completion(&priv->cmp); diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c index 252edb433fdf..29eae1bf4f86 100644 --- a/drivers/i2c/busses/i2c-mt65xx.c +++ b/drivers/i2c/busses/i2c-mt65xx.c @@ -234,6 +234,10 @@ static const struct i2c_adapter_quirks mt7622_i2c_quirks = { .max_num_msgs = 255, }; +static const struct i2c_adapter_quirks mt8183_i2c_quirks = { + .flags = I2C_AQ_NO_ZERO_LEN, +}; + static const struct mtk_i2c_compatible mt2712_compat = { .regs = mt_i2c_regs_v1, .pmic_i2c = 0, @@ -298,6 +302,7 @@ static const struct mtk_i2c_compatible mt8173_compat = { }; static const struct mtk_i2c_compatible mt8183_compat = { + .quirks = &mt8183_i2c_quirks, .regs = mt_i2c_regs_v2, .pmic_i2c = 0, .dcm = 0, @@ -870,7 +875,11 @@ static irqreturn_t mtk_i2c_irq(int irqno, void *dev_id) static u32 mtk_i2c_functionality(struct i2c_adapter *adap) { - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; + if (adap->quirks->flags & I2C_AQ_NO_ZERO_LEN) + return I2C_FUNC_I2C | + (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK); + else + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; } static const struct i2c_algorithm mtk_i2c_algorithm = { diff --git a/drivers/i2c/busses/i2c-mxs.c b/drivers/i2c/busses/i2c-mxs.c index 7d79317a1046..89224913f578 100644 --- a/drivers/i2c/busses/i2c-mxs.c +++ b/drivers/i2c/busses/i2c-mxs.c @@ -802,7 +802,6 @@ static int mxs_i2c_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct mxs_i2c_dev *i2c; struct i2c_adapter *adap; - struct resource *res; int err, irq; i2c = devm_kzalloc(dev, sizeof(*i2c), GFP_KERNEL); @@ -814,8 +813,7 @@ static int mxs_i2c_probe(struct platform_device *pdev) i2c->dev_type = device_id->driver_data; } - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - i2c->regs = devm_ioremap_resource(&pdev->dev, res); + i2c->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(i2c->regs)) return PTR_ERR(i2c->regs); diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c index 4117f1abc7c6..ca8b3ecfa93d 100644 --- a/drivers/i2c/busses/i2c-ocores.c +++ b/drivers/i2c/busses/i2c-ocores.c @@ -703,8 +703,9 @@ static int ocores_i2c_probe(struct platform_device *pdev) } if (ocores_algorithm.master_xfer != ocores_xfer_polling) { - ret = devm_request_irq(&pdev->dev, irq, ocores_isr, 0, - pdev->name, i2c); + ret = devm_request_any_context_irq(&pdev->dev, irq, + ocores_isr, 0, + pdev->name, i2c); if (ret) { dev_err(&pdev->dev, "Cannot claim IRQ\n"); goto err_clk; diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c index c46c4bddc7ca..30ded6422e7b 100644 --- a/drivers/i2c/busses/i2c-piix4.c +++ b/drivers/i2c/busses/i2c-piix4.c @@ -72,7 +72,8 @@ #define PIIX4_BLOCK_DATA 0x14 /* Multi-port constants */ -#define PIIX4_MAX_ADAPTERS 4 +#define PIIX4_MAX_ADAPTERS 4 +#define HUDSON2_MAIN_PORTS 2 /* HUDSON2, KERNCZ reserves ports 3, 4 */ /* SB800 constants */ #define SB800_PIIX4_SMB_IDX 0xcd6 @@ -91,7 +92,7 @@ #define SB800_PIIX4_PORT_IDX_MASK 0x06 #define SB800_PIIX4_PORT_IDX_SHIFT 1 -/* On kerncz, SmBus0Sel is at bit 20:19 of PMx00 DecodeEn */ +/* On kerncz and Hudson2, SmBus0Sel is at bit 20:19 of PMx00 DecodeEn */ #define SB800_PIIX4_PORT_IDX_KERNCZ 0x02 #define SB800_PIIX4_PORT_IDX_MASK_KERNCZ 0x18 #define SB800_PIIX4_PORT_IDX_SHIFT_KERNCZ 3 @@ -358,18 +359,16 @@ static int piix4_setup_sb800(struct pci_dev *PIIX4_dev, /* Find which register is used for port selection */ if (PIIX4_dev->vendor == PCI_VENDOR_ID_AMD || PIIX4_dev->vendor == PCI_VENDOR_ID_HYGON) { - switch (PIIX4_dev->device) { - case PCI_DEVICE_ID_AMD_KERNCZ_SMBUS: + if (PIIX4_dev->device == PCI_DEVICE_ID_AMD_KERNCZ_SMBUS || + (PIIX4_dev->device == PCI_DEVICE_ID_AMD_HUDSON2_SMBUS && + PIIX4_dev->revision >= 0x1F)) { piix4_port_sel_sb800 = SB800_PIIX4_PORT_IDX_KERNCZ; piix4_port_mask_sb800 = SB800_PIIX4_PORT_IDX_MASK_KERNCZ; piix4_port_shift_sb800 = SB800_PIIX4_PORT_IDX_SHIFT_KERNCZ; - break; - case PCI_DEVICE_ID_AMD_HUDSON2_SMBUS: - default: + } else { piix4_port_sel_sb800 = SB800_PIIX4_PORT_IDX_ALT; piix4_port_mask_sb800 = SB800_PIIX4_PORT_IDX_MASK; piix4_port_shift_sb800 = SB800_PIIX4_PORT_IDX_SHIFT; - break; } } else { if (!request_muxed_region(SB800_PIIX4_SMB_IDX, 2, @@ -808,10 +807,12 @@ MODULE_DEVICE_TABLE (pci, piix4_ids); static struct i2c_adapter *piix4_main_adapters[PIIX4_MAX_ADAPTERS]; static struct i2c_adapter *piix4_aux_adapter; +static int piix4_adapter_count; static int piix4_add_adapter(struct pci_dev *dev, unsigned short smba, bool sb800_main, u8 port, bool notify_imc, - const char *name, struct i2c_adapter **padap) + u8 hw_port_nr, const char *name, + struct i2c_adapter **padap) { struct i2c_adapter *adap; struct i2c_piix4_adapdata *adapdata; @@ -843,6 +844,12 @@ static int piix4_add_adapter(struct pci_dev *dev, unsigned short smba, /* set up the sysfs linkage to our parent device */ adap->dev.parent = &dev->dev; + if (has_acpi_companion(&dev->dev)) { + acpi_preset_companion(&adap->dev, + ACPI_COMPANION(&dev->dev), + hw_port_nr); + } + snprintf(adap->name, sizeof(adap->name), "SMBus PIIX4 adapter%s at %04x", name, smba); @@ -867,8 +874,19 @@ static int piix4_add_adapters_sb800(struct pci_dev *dev, unsigned short smba, int port; int retval; - for (port = 0; port < PIIX4_MAX_ADAPTERS; port++) { + if (dev->device == PCI_DEVICE_ID_AMD_KERNCZ_SMBUS || + (dev->device == PCI_DEVICE_ID_AMD_HUDSON2_SMBUS && + dev->revision >= 0x1F)) { + piix4_adapter_count = HUDSON2_MAIN_PORTS; + } else { + piix4_adapter_count = PIIX4_MAX_ADAPTERS; + } + + for (port = 0; port < piix4_adapter_count; port++) { + u8 hw_port_nr = port == 0 ? 0 : port + 1; + retval = piix4_add_adapter(dev, smba, true, port, notify_imc, + hw_port_nr, piix4_main_port_names_sb800[port], &piix4_main_adapters[port]); if (retval < 0) @@ -939,8 +957,8 @@ static int piix4_probe(struct pci_dev *dev, const struct pci_device_id *id) return retval; /* Try to register main SMBus adapter, give up if we can't */ - retval = piix4_add_adapter(dev, retval, false, 0, false, "", - &piix4_main_adapters[0]); + retval = piix4_add_adapter(dev, retval, false, 0, false, 0, + "", &piix4_main_adapters[0]); if (retval < 0) return retval; } @@ -966,7 +984,7 @@ static int piix4_probe(struct pci_dev *dev, const struct pci_device_id *id) if (retval > 0) { /* Try to add the aux adapter if it exists, * piix4_add_adapter will clean up if this fails */ - piix4_add_adapter(dev, retval, false, 0, false, + piix4_add_adapter(dev, retval, false, 0, false, 1, is_sb800 ? piix4_aux_port_name_sb800 : "", &piix4_aux_adapter); } @@ -989,7 +1007,7 @@ static void piix4_adap_remove(struct i2c_adapter *adap) static void piix4_remove(struct pci_dev *dev) { - int port = PIIX4_MAX_ADAPTERS; + int port = piix4_adapter_count; while (--port >= 0) { if (piix4_main_adapters[port]) { diff --git a/drivers/i2c/busses/i2c-sprd.c b/drivers/i2c/busses/i2c-sprd.c index 961123529678..b432e7580458 100644 --- a/drivers/i2c/busses/i2c-sprd.c +++ b/drivers/i2c/busses/i2c-sprd.c @@ -12,6 +12,7 @@ #include <linux/init.h> #include <linux/interrupt.h> #include <linux/kernel.h> +#include <linux/module.h> #include <linux/of.h> #include <linux/of_device.h> #include <linux/platform_device.h> @@ -465,9 +466,9 @@ static int sprd_i2c_clk_init(struct sprd_i2c *i2c_dev) i2c_dev->clk = devm_clk_get(i2c_dev->dev, "enable"); if (IS_ERR(i2c_dev->clk)) { - dev_warn(i2c_dev->dev, "i2c%d can't get the enable clock\n", - i2c_dev->adap.nr); - i2c_dev->clk = NULL; + dev_err(i2c_dev->dev, "i2c%d can't get the enable clock\n", + i2c_dev->adap.nr); + return PTR_ERR(i2c_dev->clk); } return 0; @@ -477,7 +478,6 @@ static int sprd_i2c_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct sprd_i2c *i2c_dev; - struct resource *res; u32 prop; int ret; @@ -487,8 +487,7 @@ static int sprd_i2c_probe(struct platform_device *pdev) if (!i2c_dev) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - i2c_dev->base = devm_ioremap_resource(dev, res); + i2c_dev->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(i2c_dev->base)) return PTR_ERR(i2c_dev->base); @@ -520,7 +519,10 @@ static int sprd_i2c_probe(struct platform_device *pdev) if (i2c_dev->bus_freq != 100000 && i2c_dev->bus_freq != 400000) return -EINVAL; - sprd_i2c_clk_init(i2c_dev); + ret = sprd_i2c_clk_init(i2c_dev); + if (ret) + return ret; + platform_set_drvdata(pdev, i2c_dev); ret = clk_prepare_enable(i2c_dev->clk); @@ -644,8 +646,7 @@ static struct platform_driver sprd_i2c_driver = { }, }; -static int sprd_i2c_init(void) -{ - return platform_driver_register(&sprd_i2c_driver); -} -arch_initcall_sync(sprd_i2c_init); +module_platform_driver(sprd_i2c_driver); + +MODULE_DESCRIPTION("Spreadtrum I2C master controller driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/i2c/busses/i2c-stm32f7.c b/drivers/i2c/busses/i2c-stm32f7.c index 266d1c269b83..d36cf08461f7 100644 --- a/drivers/i2c/busses/i2c-stm32f7.c +++ b/drivers/i2c/busses/i2c-stm32f7.c @@ -1809,7 +1809,7 @@ static u32 stm32f7_i2c_func(struct i2c_adapter *adap) I2C_FUNC_SMBUS_I2C_BLOCK; } -static struct i2c_algorithm stm32f7_i2c_algo = { +static const struct i2c_algorithm stm32f7_i2c_algo = { .master_xfer = stm32f7_i2c_xfer, .smbus_xfer = stm32f7_i2c_smbus_xfer, .functionality = stm32f7_i2c_func, diff --git a/drivers/i2c/busses/i2c-synquacer.c b/drivers/i2c/busses/i2c-synquacer.c index f724c8e6b360..39762f0611b1 100644 --- a/drivers/i2c/busses/i2c-synquacer.c +++ b/drivers/i2c/busses/i2c-synquacer.c @@ -526,7 +526,7 @@ static const struct i2c_algorithm synquacer_i2c_algo = { .functionality = synquacer_i2c_functionality, }; -static struct i2c_adapter synquacer_i2c_ops = { +static const struct i2c_adapter synquacer_i2c_ops = { .owner = THIS_MODULE, .name = "synquacer_i2c-adapter", .algo = &synquacer_i2c_algo, diff --git a/drivers/i2c/busses/i2c-taos-evm.c b/drivers/i2c/busses/i2c-taos-evm.c index c82e78f57386..0bff3f3a8779 100644 --- a/drivers/i2c/busses/i2c-taos-evm.c +++ b/drivers/i2c/busses/i2c-taos-evm.c @@ -39,7 +39,7 @@ struct taos_data { }; /* TAOS TSL2550 EVM */ -static struct i2c_board_info tsl2550_info = { +static const struct i2c_board_info tsl2550_info = { I2C_BOARD_INFO("tsl2550", 0x39), }; @@ -125,7 +125,7 @@ static int taos_smbus_xfer(struct i2c_adapter *adapter, u16 addr, /* * Voluntarily dropping error code of kstrtou8 since all * error code that it could return are invalid according - * to Documentation/i2c/fault-codes. + * to Documentation/i2c/fault-codes.rst. */ if (kstrtou8(p + 1, 16, &data->byte)) return -EPROTO; diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index 9fcb13beeb8f..c1683f9338b4 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -636,7 +636,7 @@ static void tegra_dvc_init(struct tegra_i2c_dev *i2c_dev) dvc_writel(i2c_dev, val, DVC_CTRL_REG1); } -static int tegra_i2c_runtime_resume(struct device *dev) +static int __maybe_unused tegra_i2c_runtime_resume(struct device *dev) { struct tegra_i2c_dev *i2c_dev = dev_get_drvdata(dev); int ret; @@ -665,7 +665,7 @@ static int tegra_i2c_runtime_resume(struct device *dev) return 0; } -static int tegra_i2c_runtime_suspend(struct device *dev) +static int __maybe_unused tegra_i2c_runtime_suspend(struct device *dev) { struct tegra_i2c_dev *i2c_dev = dev_get_drvdata(dev); @@ -713,12 +713,6 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev, bool clk_reinit) u32 tsu_thd; u8 tlow, thigh; - err = pm_runtime_get_sync(i2c_dev->dev); - if (err < 0) { - dev_err(i2c_dev->dev, "runtime resume failed %d\n", err); - return err; - } - reset_control_assert(i2c_dev->rst); udelay(2); reset_control_deassert(i2c_dev->rst); @@ -772,7 +766,7 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev, bool clk_reinit) if (err) { dev_err(i2c_dev->dev, "failed changing clock rate: %d\n", err); - goto err; + return err; } } @@ -787,23 +781,21 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev, bool clk_reinit) err = tegra_i2c_flush_fifos(i2c_dev); if (err) - goto err; + return err; if (i2c_dev->is_multimaster_mode && i2c_dev->hw->has_slcg_override_reg) i2c_writel(i2c_dev, I2C_MST_CORE_CLKEN_OVR, I2C_CLKEN_OVERRIDE); err = tegra_i2c_wait_for_config_load(i2c_dev); if (err) - goto err; + return err; if (i2c_dev->irq_disabled) { i2c_dev->irq_disabled = false; enable_irq(i2c_dev->irq); } -err: - pm_runtime_put(i2c_dev->dev); - return err; + return 0; } static int tegra_i2c_disable_packet_mode(struct tegra_i2c_dev *i2c_dev) @@ -1616,12 +1608,14 @@ static int tegra_i2c_probe(struct platform_device *pdev) } pm_runtime_enable(&pdev->dev); - if (!pm_runtime_enabled(&pdev->dev)) { + if (!pm_runtime_enabled(&pdev->dev)) ret = tegra_i2c_runtime_resume(&pdev->dev); - if (ret < 0) { - dev_err(&pdev->dev, "runtime resume failed\n"); - goto unprepare_div_clk; - } + else + ret = pm_runtime_get_sync(i2c_dev->dev); + + if (ret < 0) { + dev_err(&pdev->dev, "runtime resume failed\n"); + goto unprepare_div_clk; } if (i2c_dev->is_multimaster_mode) { @@ -1666,6 +1660,8 @@ static int tegra_i2c_probe(struct platform_device *pdev) if (ret) goto release_dma; + pm_runtime_put(&pdev->dev); + return 0; release_dma: @@ -1711,8 +1707,7 @@ static int tegra_i2c_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM_SLEEP -static int tegra_i2c_suspend(struct device *dev) +static int __maybe_unused tegra_i2c_suspend(struct device *dev) { struct tegra_i2c_dev *i2c_dev = dev_get_drvdata(dev); @@ -1721,38 +1716,41 @@ static int tegra_i2c_suspend(struct device *dev) return 0; } -static int tegra_i2c_resume(struct device *dev) +static int __maybe_unused tegra_i2c_resume(struct device *dev) { struct tegra_i2c_dev *i2c_dev = dev_get_drvdata(dev); int err; + err = tegra_i2c_runtime_resume(dev); + if (err) + return err; + err = tegra_i2c_init(i2c_dev, false); if (err) return err; + err = tegra_i2c_runtime_suspend(dev); + if (err) + return err; + i2c_mark_adapter_resumed(&i2c_dev->adapter); return 0; } static const struct dev_pm_ops tegra_i2c_pm = { - SET_SYSTEM_SLEEP_PM_OPS(tegra_i2c_suspend, tegra_i2c_resume) + SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(tegra_i2c_suspend, tegra_i2c_resume) SET_RUNTIME_PM_OPS(tegra_i2c_runtime_suspend, tegra_i2c_runtime_resume, NULL) }; -#define TEGRA_I2C_PM (&tegra_i2c_pm) -#else -#define TEGRA_I2C_PM NULL -#endif - static struct platform_driver tegra_i2c_driver = { .probe = tegra_i2c_probe, .remove = tegra_i2c_remove, .driver = { .name = "tegra-i2c", .of_match_table = tegra_i2c_of_match, - .pm = TEGRA_I2C_PM, + .pm = &tegra_i2c_pm, }, }; diff --git a/drivers/i2c/busses/i2c-uniphier-f.c b/drivers/i2c/busses/i2c-uniphier-f.c index 7acca2599f04..4241aac79e7e 100644 --- a/drivers/i2c/busses/i2c-uniphier-f.c +++ b/drivers/i2c/busses/i2c-uniphier-f.c @@ -108,7 +108,6 @@ static void uniphier_fi2c_fill_txfifo(struct uniphier_fi2c_priv *priv, if (fifo_space-- <= 0) break; - dev_dbg(&priv->adap.dev, "write data: %02x\n", *priv->buf); writel(*priv->buf++, priv->membase + UNIPHIER_FI2C_DTTX); priv->len--; } @@ -124,7 +123,6 @@ static void uniphier_fi2c_drain_rxfifo(struct uniphier_fi2c_priv *priv) break; *priv->buf++ = readl(priv->membase + UNIPHIER_FI2C_DTRX); - dev_dbg(&priv->adap.dev, "read data: %02x\n", priv->buf[-1]); priv->len--; } } @@ -142,8 +140,6 @@ static void uniphier_fi2c_clear_irqs(struct uniphier_fi2c_priv *priv, static void uniphier_fi2c_stop(struct uniphier_fi2c_priv *priv) { - dev_dbg(&priv->adap.dev, "stop condition\n"); - priv->enabled_irqs |= UNIPHIER_FI2C_INT_STOP; uniphier_fi2c_set_irqs(priv); writel(UNIPHIER_FI2C_CR_MST | UNIPHIER_FI2C_CR_STO, @@ -160,21 +156,15 @@ static irqreturn_t uniphier_fi2c_interrupt(int irq, void *dev_id) irq_status = readl(priv->membase + UNIPHIER_FI2C_INT); irq_status &= priv->enabled_irqs; - dev_dbg(&priv->adap.dev, - "interrupt: enabled_irqs=%04x, irq_status=%04x\n", - priv->enabled_irqs, irq_status); - if (irq_status & UNIPHIER_FI2C_INT_STOP) goto complete; if (unlikely(irq_status & UNIPHIER_FI2C_INT_AL)) { - dev_dbg(&priv->adap.dev, "arbitration lost\n"); priv->error = -EAGAIN; goto complete; } if (unlikely(irq_status & UNIPHIER_FI2C_INT_NA)) { - dev_dbg(&priv->adap.dev, "could not get ACK\n"); priv->error = -ENXIO; if (priv->flags & UNIPHIER_FI2C_RD) { /* @@ -215,18 +205,14 @@ static irqreturn_t uniphier_fi2c_interrupt(int irq, void *dev_id) if (unlikely(priv->flags & UNIPHIER_FI2C_MANUAL_NACK)) { if (priv->len <= UNIPHIER_FI2C_FIFO_SIZE && !(priv->flags & UNIPHIER_FI2C_BYTE_WISE)) { - dev_dbg(&priv->adap.dev, - "enable read byte count IRQ\n"); priv->enabled_irqs |= UNIPHIER_FI2C_INT_RB; uniphier_fi2c_set_irqs(priv); priv->flags |= UNIPHIER_FI2C_BYTE_WISE; } - if (priv->len <= 1) { - dev_dbg(&priv->adap.dev, "set NACK\n"); + if (priv->len <= 1) writel(UNIPHIER_FI2C_CR_MST | UNIPHIER_FI2C_CR_NACK, priv->membase + UNIPHIER_FI2C_CR); - } } goto handled; @@ -334,10 +320,6 @@ static int uniphier_fi2c_master_xfer_one(struct i2c_adapter *adap, bool is_read = msg->flags & I2C_M_RD; unsigned long time_left, flags; - dev_dbg(&adap->dev, "%s: addr=0x%02x, len=%d, repeat=%d, stop=%d\n", - is_read ? "receive" : "transmit", msg->addr, msg->len, - repeat, stop); - priv->len = msg->len; priv->buf = msg->buf; priv->enabled_irqs = UNIPHIER_FI2C_INT_FAULTS; @@ -359,7 +341,6 @@ static int uniphier_fi2c_master_xfer_one(struct i2c_adapter *adap, else uniphier_fi2c_tx_init(priv, msg->addr, repeat); - dev_dbg(&adap->dev, "start condition\n"); /* * For a repeated START condition, writing a slave address to the FIFO * kicks the controller. So, the UNIPHIER_FI2C_CR register should be @@ -383,7 +364,6 @@ static int uniphier_fi2c_master_xfer_one(struct i2c_adapter *adap, uniphier_fi2c_recover(priv); return -ETIMEDOUT; } - dev_dbg(&adap->dev, "complete\n"); if (unlikely(priv->flags & UNIPHIER_FI2C_DEFER_STOP_COMP)) { u32 status; @@ -538,7 +518,6 @@ static int uniphier_fi2c_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct uniphier_fi2c_priv *priv; - struct resource *regs; u32 bus_speed; unsigned long clk_rate; int irq, ret; @@ -547,8 +526,7 @@ static int uniphier_fi2c_probe(struct platform_device *pdev) if (!priv) return -ENOMEM; - regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); - priv->membase = devm_ioremap_resource(dev, regs); + priv->membase = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(priv->membase)) return PTR_ERR(priv->membase); diff --git a/drivers/i2c/busses/i2c-uniphier.c b/drivers/i2c/busses/i2c-uniphier.c index 0173840c32af..0270090c0360 100644 --- a/drivers/i2c/busses/i2c-uniphier.c +++ b/drivers/i2c/busses/i2c-uniphier.c @@ -71,7 +71,6 @@ static int uniphier_i2c_xfer_byte(struct i2c_adapter *adap, u32 txdata, reinit_completion(&priv->comp); txdata |= UNIPHIER_I2C_DTRM_IRQEN; - dev_dbg(&adap->dev, "write data: 0x%04x\n", txdata); writel(txdata, priv->membase + UNIPHIER_I2C_DTRM); time_left = wait_for_completion_timeout(&priv->comp, adap->timeout); @@ -81,8 +80,6 @@ static int uniphier_i2c_xfer_byte(struct i2c_adapter *adap, u32 txdata, } rxdata = readl(priv->membase + UNIPHIER_I2C_DREC); - dev_dbg(&adap->dev, "read data: 0x%04x\n", rxdata); - if (rxdatap) *rxdatap = rxdata; @@ -98,14 +95,11 @@ static int uniphier_i2c_send_byte(struct i2c_adapter *adap, u32 txdata) if (ret) return ret; - if (unlikely(rxdata & UNIPHIER_I2C_DREC_LAB)) { - dev_dbg(&adap->dev, "arbitration lost\n"); + if (unlikely(rxdata & UNIPHIER_I2C_DREC_LAB)) return -EAGAIN; - } - if (unlikely(rxdata & UNIPHIER_I2C_DREC_LRB)) { - dev_dbg(&adap->dev, "could not get ACK\n"); + + if (unlikely(rxdata & UNIPHIER_I2C_DREC_LRB)) return -ENXIO; - } return 0; } @@ -115,7 +109,6 @@ static int uniphier_i2c_tx(struct i2c_adapter *adap, u16 addr, u16 len, { int ret; - dev_dbg(&adap->dev, "start condition\n"); ret = uniphier_i2c_send_byte(adap, addr << 1 | UNIPHIER_I2C_DTRM_STA | UNIPHIER_I2C_DTRM_NACK); @@ -137,7 +130,6 @@ static int uniphier_i2c_rx(struct i2c_adapter *adap, u16 addr, u16 len, { int ret; - dev_dbg(&adap->dev, "start condition\n"); ret = uniphier_i2c_send_byte(adap, addr << 1 | UNIPHIER_I2C_DTRM_STA | UNIPHIER_I2C_DTRM_NACK | @@ -161,7 +153,6 @@ static int uniphier_i2c_rx(struct i2c_adapter *adap, u16 addr, u16 len, static int uniphier_i2c_stop(struct i2c_adapter *adap) { - dev_dbg(&adap->dev, "stop condition\n"); return uniphier_i2c_send_byte(adap, UNIPHIER_I2C_DTRM_STO | UNIPHIER_I2C_DTRM_NACK); } @@ -173,9 +164,6 @@ static int uniphier_i2c_master_xfer_one(struct i2c_adapter *adap, bool recovery = false; int ret; - dev_dbg(&adap->dev, "%s: addr=0x%02x, len=%d, stop=%d\n", - is_read ? "receive" : "transmit", msg->addr, msg->len, stop); - if (is_read) ret = uniphier_i2c_rx(adap, msg->addr, msg->len, msg->buf); else @@ -326,7 +314,6 @@ static int uniphier_i2c_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct uniphier_i2c_priv *priv; - struct resource *regs; u32 bus_speed; unsigned long clk_rate; int irq, ret; @@ -335,8 +322,7 @@ static int uniphier_i2c_probe(struct platform_device *pdev) if (!priv) return -ENOMEM; - regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); - priv->membase = devm_ioremap_resource(dev, regs); + priv->membase = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(priv->membase)) return PTR_ERR(priv->membase); |