From e5738bc46d49642dc4804bad3656b23016f8e1f1 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Mon, 8 Jul 2019 02:12:34 +0300 Subject: i2c: tegra: Compile PM functions unconditionally The I2C driver fails to probe if CONFIG_PM_SLEEP=n because runtime PM doesn't depend on the PM sleep and in this case the runtime PM ops are not included in the driver, resulting in I2C clock not being enabled. It's much cleaner to simply allow compiler to remove the dead code instead of messing with the #ifdefs. This patch fixes such errors when CONFIG_PM_SLEEP=n: tegra-i2c 7000c400.i2c: timeout waiting for fifo flush tegra-i2c 7000c400.i2c: Failed to initialize i2c controller Signed-off-by: Dmitry Osipenko Acked-by: Jon Hunter Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-tegra.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) (limited to 'drivers/i2c') diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index 9fcb13beeb8f..18f0ceed9f1b 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); @@ -1711,8 +1711,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,7 +1720,7 @@ 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; @@ -1741,18 +1740,13 @@ static const struct dev_pm_ops tegra_i2c_pm = { 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, }, }; -- cgit 1.4.1 From 34de3513e668d5ad46bd32ebee63f9e3dc57e1db Mon Sep 17 00:00:00 2001 From: Fuqian Huang Date: Mon, 15 Jul 2019 11:17:39 +0800 Subject: i2c: ismt: Remove call to memset after dmam_alloc_coherent In commit 518a2f1925c3 ("dma-mapping: zero memory returned from dma_alloc_*"), dma_alloc_coherent has already zeroed the memory. So memset is not needed. Acked-by: Neil Horman Signed-off-by: Fuqian Huang Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-ismt.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/i2c') 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); -- cgit 1.4.1 From b17e6d19dcd3fcb2b93166034e739e82b49d2a51 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Wed, 17 Jul 2019 16:40:16 +0800 Subject: i2c: mxs: use devm_platform_ioremap_resource() to simplify code Use the new helper devm_platform_ioremap_resource() which wraps the platform_get_resource() and devm_ioremap_resource() together, to simplify the code. Signed-off-by: Anson Huang Reviewed-by: Dong Aisheng Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-mxs.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/i2c') 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); -- cgit 1.4.1 From 5667b5b59f45bd0bebadfae9ed55745b4cff2198 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Wed, 17 Jul 2019 16:40:17 +0800 Subject: i2c: imx-lpi2c: use devm_platform_ioremap_resource() to simplify code Use the new helper devm_platform_ioremap_resource() which wraps the platform_get_resource() and devm_ioremap_resource() together, to simplify the code. Signed-off-by: Anson Huang Acked-by: Dong Aisheng Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-imx-lpi2c.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/i2c') 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); -- cgit 1.4.1 From 7735eeebd2be26d6d3fa151c85d839d62d710d93 Mon Sep 17 00:00:00 2001 From: Chuhong Yuan Date: Tue, 23 Jul 2019 19:11:10 +0800 Subject: i2c: busses: Use dev_get_drvdata where possible Instead of using to_pci_dev + pci_get_drvdata, use dev_get_drvdata to make code simpler. Signed-off-by: Chuhong Yuan Reviewed-by: Jean Delvare Acked-by: Jarkko Nikula Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-designware-pcidrv.c | 6 ++---- drivers/i2c/busses/i2c-i801.c | 3 +-- 2 files changed, 3 insertions(+), 6 deletions(-) (limited to 'drivers/i2c') diff --git a/drivers/i2c/busses/i2c-designware-pcidrv.c b/drivers/i2c/busses/i2c-designware-pcidrv.c index 76810deb2de6..7d2e6959679c 100644 --- a/drivers/i2c/busses/i2c-designware-pcidrv.c +++ b/drivers/i2c/busses/i2c-designware-pcidrv.c @@ -173,8 +173,7 @@ static struct dw_pci_controller dw_pci_controllers[] = { #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 +183,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); diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index f2956936c3f2..a6469978e735 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -1912,8 +1912,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); -- cgit 1.4.1 From 33eb09a02e8d8fad976019694196eec2cc210d62 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Thu, 25 Jul 2019 22:21:36 +0200 Subject: i2c: designware: make use of devm_gpiod_get_optional MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There is a semantical change: if devm_gpiod_get_optional returns -ENOSYS this is passed as error to the caller. This effectively reverts commit d1fa74520dcd ("i2c: designware: Consider SCL GPIO optional") which shouldn't be necessary any more since gpiod_get_optional doesn't return -ENOSYS any more with GPIOLIB=n. Signed-off-by: Uwe Kleine-König Reviewed-by: Andy Shevchenko Acked-by: Jarkko Nikula Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-designware-master.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'drivers/i2c') diff --git a/drivers/i2c/busses/i2c-designware-master.c b/drivers/i2c/busses/i2c-designware-master.c index d464799e40a3..867787dade43 100644 --- a/drivers/i2c/busses/i2c-designware-master.c +++ b/drivers/i2c/busses/i2c-designware-master.c @@ -657,13 +657,10 @@ static int i2c_dw_init_recovery_info(struct dw_i2c_dev *dev) 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); -- cgit 1.4.1 From f91b2ab0e0c5f7cb4b11012748a184b91a396f0f Mon Sep 17 00:00:00 2001 From: Shaokun Zhang Date: Mon, 5 Aug 2019 17:31:08 +0800 Subject: i2c: designware: Fix unused variable warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drivers/i2c/busses/i2c-designware-master.c: In function ‘i2c_dw_init_recovery_info’: drivers/i2c/busses/i2c-designware-master.c:658:6: warning: unused variable ‘r’ [-Wunused-variable] int r; ^ Fixes: 33eb09a02e8d ("i2c: designware: make use of devm_gpiod_get_optional") Signed-off-by: Shaokun Zhang Acked-by: Jarkko Nikula Reviewed-by: Andy Shevchenko Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-designware-master.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/i2c') diff --git a/drivers/i2c/busses/i2c-designware-master.c b/drivers/i2c/busses/i2c-designware-master.c index 867787dade43..e8b328242256 100644 --- a/drivers/i2c/busses/i2c-designware-master.c +++ b/drivers/i2c/busses/i2c-designware-master.c @@ -655,7 +655,6 @@ 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_optional(dev->dev, "scl", GPIOD_OUT_HIGH); if (IS_ERR_OR_NULL(gpio)) -- cgit 1.4.1 From 3e99834cc0c7f0612dc790ad7342f18c375d285b Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 26 Jul 2019 16:14:21 +0300 Subject: i2c: Drop unneeded check for of_node of_find_property() will return NULL if of_node is NULL, thus of_irq_get_by_name() returns -EINVAL which we ignore, so no need to double check. Signed-off-by: Andy Shevchenko Signed-off-by: Wolfram Sang --- drivers/i2c/i2c-core-base.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers/i2c') diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c index f26ed495d384..b4d84bd475da 100644 --- a/drivers/i2c/i2c-core-base.c +++ b/drivers/i2c/i2c-core-base.c @@ -350,13 +350,11 @@ static int i2c_device_probe(struct device *dev) return -ENODEV; if (client->flags & I2C_CLIENT_WAKE) { - int wakeirq = -ENOENT; + int wakeirq; - if (dev->of_node) { - wakeirq = of_irq_get_byname(dev->of_node, "wakeup"); - if (wakeirq == -EPROBE_DEFER) - return wakeirq; - } + wakeirq = of_irq_get_byname(dev->of_node, "wakeup"); + if (wakeirq == -EPROBE_DEFER) + return wakeirq; device_init_wakeup(&client->dev, true); -- cgit 1.4.1 From 4d7802aa434a39921c699683c4ca2ad9068b0033 Mon Sep 17 00:00:00 2001 From: Baolin Wang Date: Thu, 25 Jul 2019 15:56:16 +0800 Subject: i2c: sprd: Make I2C driver can be built as a module Now there is no need to keep our I2C driver to be initialized so early, thus changing to module level and let it can be built as a module, meanwhile adding some module information. Signed-off-by: Baolin Wang Signed-off-by: Wolfram Sang --- drivers/i2c/busses/Kconfig | 2 +- drivers/i2c/busses/i2c-sprd.c | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/i2c') diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 09367fc014c3..69f19312a574 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -977,7 +977,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 diff --git a/drivers/i2c/busses/i2c-sprd.c b/drivers/i2c/busses/i2c-sprd.c index 961123529678..8002835d1543 100644 --- a/drivers/i2c/busses/i2c-sprd.c +++ b/drivers/i2c/busses/i2c-sprd.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -644,8 +645,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"); -- cgit 1.4.1 From 3c2588fab65fb083873c6c1e74a1be54345615eb Mon Sep 17 00:00:00 2001 From: Baolin Wang Date: Thu, 25 Jul 2019 15:56:17 +0800 Subject: i2c: sprd: Change to use devm_platform_ioremap_resource() Use the new helper that wraps the calls to platform_get_resource() and devm_ioremap_resource() together. Signed-off-by: Baolin Wang Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-sprd.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/i2c') diff --git a/drivers/i2c/busses/i2c-sprd.c b/drivers/i2c/busses/i2c-sprd.c index 8002835d1543..bbcb0569522d 100644 --- a/drivers/i2c/busses/i2c-sprd.c +++ b/drivers/i2c/busses/i2c-sprd.c @@ -478,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; @@ -488,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); -- cgit 1.4.1 From bbeb6b6c07960b8d33bed5352ef462228110c5ab Mon Sep 17 00:00:00 2001 From: Baolin Wang Date: Thu, 25 Jul 2019 15:56:18 +0800 Subject: i2c: sprd: Validate the return value of clock initialization The 'enable' clock of I2C master is required, we should return an error if failed to get the 'enable' clock, to make sure the I2C driver can be defer probe if the clock resource is not ready. Signed-off-by: Baolin Wang Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-sprd.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'drivers/i2c') diff --git a/drivers/i2c/busses/i2c-sprd.c b/drivers/i2c/busses/i2c-sprd.c index bbcb0569522d..b432e7580458 100644 --- a/drivers/i2c/busses/i2c-sprd.c +++ b/drivers/i2c/busses/i2c-sprd.c @@ -466,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; @@ -519,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); -- cgit 1.4.1 From af80559b4d9cd481c63505edbe425ff6bad4ab8d Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Fri, 9 Aug 2019 17:40:47 +0200 Subject: i2c: replace i2c_new_secondary_device with an ERR_PTR variant In the general move to have i2c_new_*_device functions which return ERR_PTR instead of NULL, this patch converts i2c_new_secondary_device(). There are only few users, so this patch converts the I2C core and all users in one go. The function gets renamed to i2c_new_ancillary_device() so out-of-tree users will get a build failure to understand they need to adapt their error checking code. Signed-off-by: Wolfram Sang Reviewed-by: Kieran Bingham # adv748x Reviewed-by: Laurent Pinchart # adv7511 + adv7604 Reviewed-by: Hans Verkuil # adv7604 Signed-off-by: Wolfram Sang --- drivers/gpu/drm/bridge/adv7511/adv7511_drv.c | 18 +++++++++--------- drivers/i2c/i2c-core-base.c | 10 +++++----- drivers/media/i2c/adv748x/adv748x-core.c | 6 +++--- drivers/media/i2c/adv7604.c | 22 ++++++++++++---------- include/linux/i2c.h | 2 +- 5 files changed, 30 insertions(+), 28 deletions(-) (limited to 'drivers/i2c') diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c index f6d2681f6927..9e13e466e72c 100644 --- a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +++ b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c @@ -981,10 +981,10 @@ static int adv7511_init_cec_regmap(struct adv7511 *adv) { int ret; - adv->i2c_cec = i2c_new_secondary_device(adv->i2c_main, "cec", + adv->i2c_cec = i2c_new_ancillary_device(adv->i2c_main, "cec", ADV7511_CEC_I2C_ADDR_DEFAULT); - if (!adv->i2c_cec) - return -EINVAL; + if (IS_ERR(adv->i2c_cec)) + return PTR_ERR(adv->i2c_cec); i2c_set_clientdata(adv->i2c_cec, adv); adv->regmap_cec = devm_regmap_init_i2c(adv->i2c_cec, @@ -1165,20 +1165,20 @@ static int adv7511_probe(struct i2c_client *i2c, const struct i2c_device_id *id) adv7511_packet_disable(adv7511, 0xffff); - adv7511->i2c_edid = i2c_new_secondary_device(i2c, "edid", + adv7511->i2c_edid = i2c_new_ancillary_device(i2c, "edid", ADV7511_EDID_I2C_ADDR_DEFAULT); - if (!adv7511->i2c_edid) { - ret = -EINVAL; + if (IS_ERR(adv7511->i2c_edid)) { + ret = PTR_ERR(adv7511->i2c_edid); goto uninit_regulators; } regmap_write(adv7511->regmap, ADV7511_REG_EDID_I2C_ADDR, adv7511->i2c_edid->addr << 1); - adv7511->i2c_packet = i2c_new_secondary_device(i2c, "packet", + adv7511->i2c_packet = i2c_new_ancillary_device(i2c, "packet", ADV7511_PACKET_I2C_ADDR_DEFAULT); - if (!adv7511->i2c_packet) { - ret = -EINVAL; + if (IS_ERR(adv7511->i2c_packet)) { + ret = PTR_ERR(adv7511->i2c_packet); goto err_i2c_unregister_edid; } diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c index b4d84bd475da..ca10525e6d94 100644 --- a/drivers/i2c/i2c-core-base.c +++ b/drivers/i2c/i2c-core-base.c @@ -964,7 +964,7 @@ struct i2c_client *devm_i2c_new_dummy_device(struct device *dev, EXPORT_SYMBOL_GPL(devm_i2c_new_dummy_device); /** - * i2c_new_secondary_device - Helper to get the instantiated secondary address + * i2c_new_ancillary_device - Helper to get the instantiated secondary address * and create the associated device * @client: Handle to the primary client * @name: Handle to specify which secondary address to get @@ -983,9 +983,9 @@ EXPORT_SYMBOL_GPL(devm_i2c_new_dummy_device); * cell whose "reg-names" value matches the slave name. * * This returns the new i2c client, which should be saved for later use with - * i2c_unregister_device(); or NULL to indicate an error. + * i2c_unregister_device(); or an ERR_PTR to describe the error. */ -struct i2c_client *i2c_new_secondary_device(struct i2c_client *client, +struct i2c_client *i2c_new_ancillary_device(struct i2c_client *client, const char *name, u16 default_addr) { @@ -1000,9 +1000,9 @@ struct i2c_client *i2c_new_secondary_device(struct i2c_client *client, } dev_dbg(&client->adapter->dev, "Address for %s : 0x%x\n", name, addr); - return i2c_new_dummy(client->adapter, addr); + return i2c_new_dummy_device(client->adapter, addr); } -EXPORT_SYMBOL_GPL(i2c_new_secondary_device); +EXPORT_SYMBOL_GPL(i2c_new_ancillary_device); /* ------------------------------------------------------------------------- */ diff --git a/drivers/media/i2c/adv748x/adv748x-core.c b/drivers/media/i2c/adv748x/adv748x-core.c index f57cd77a32fa..2567de2b0037 100644 --- a/drivers/media/i2c/adv748x/adv748x-core.c +++ b/drivers/media/i2c/adv748x/adv748x-core.c @@ -183,14 +183,14 @@ static int adv748x_initialise_clients(struct adv748x_state *state) int ret; for (i = ADV748X_PAGE_DPLL; i < ADV748X_PAGE_MAX; ++i) { - state->i2c_clients[i] = i2c_new_secondary_device( + state->i2c_clients[i] = i2c_new_ancillary_device( state->client, adv748x_default_addresses[i].name, adv748x_default_addresses[i].default_addr); - if (state->i2c_clients[i] == NULL) { + if (IS_ERR(state->i2c_clients[i])) { adv_err(state, "failed to create i2c client %u\n", i); - return -ENOMEM; + return PTR_ERR(state->i2c_clients[i]); } ret = adv748x_configure_regmap(state, i); diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c index 28a84bf9f8a9..2dedd6ebb236 100644 --- a/drivers/media/i2c/adv7604.c +++ b/drivers/media/i2c/adv7604.c @@ -2862,10 +2862,8 @@ static void adv76xx_unregister_clients(struct adv76xx_state *state) { unsigned int i; - for (i = 1; i < ARRAY_SIZE(state->i2c_clients); ++i) { - if (state->i2c_clients[i]) - i2c_unregister_device(state->i2c_clients[i]); - } + for (i = 1; i < ARRAY_SIZE(state->i2c_clients); ++i) + i2c_unregister_device(state->i2c_clients[i]); } static struct i2c_client *adv76xx_dummy_client(struct v4l2_subdev *sd, @@ -2878,14 +2876,14 @@ static struct i2c_client *adv76xx_dummy_client(struct v4l2_subdev *sd, struct i2c_client *new_client; if (pdata && pdata->i2c_addresses[page]) - new_client = i2c_new_dummy(client->adapter, + new_client = i2c_new_dummy_device(client->adapter, pdata->i2c_addresses[page]); else - new_client = i2c_new_secondary_device(client, + new_client = i2c_new_ancillary_device(client, adv76xx_default_addresses[page].name, adv76xx_default_addresses[page].default_addr); - if (new_client) + if (!IS_ERR(new_client)) io_write(sd, io_reg, new_client->addr << 1); return new_client; @@ -3516,15 +3514,19 @@ static int adv76xx_probe(struct i2c_client *client, } for (i = 1; i < ADV76XX_PAGE_MAX; ++i) { + struct i2c_client *dummy_client; + if (!(BIT(i) & state->info->page_mask)) continue; - state->i2c_clients[i] = adv76xx_dummy_client(sd, i); - if (!state->i2c_clients[i]) { - err = -EINVAL; + dummy_client = adv76xx_dummy_client(sd, i); + if (IS_ERR(dummy_client)) { + err = PTR_ERR(dummy_client); v4l2_err(sd, "failed to create i2c client %u\n", i); goto err_i2c; } + + state->i2c_clients[i] = dummy_client; } INIT_DELAYED_WORK(&state->delayed_work_enable_hotplug, diff --git a/include/linux/i2c.h b/include/linux/i2c.h index fa5552c2307b..ebbe024dd9e0 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -473,7 +473,7 @@ extern struct i2c_client * devm_i2c_new_dummy_device(struct device *dev, struct i2c_adapter *adap, u16 address); extern struct i2c_client * -i2c_new_secondary_device(struct i2c_client *client, +i2c_new_ancillary_device(struct i2c_client *client, const char *name, u16 default_addr); -- cgit 1.4.1 From 232219b9a464c2479c98aa589acb1bd3383ae9d6 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 13 Aug 2019 12:03:01 +0200 Subject: i2c-cht-wc: Fix lockdep warning When the kernel is build with lockdep support and the i2c-cht-wc driver is used, the following warning is shown: [ 66.674334] ====================================================== [ 66.674337] WARNING: possible circular locking dependency detected [ 66.674340] 5.3.0-rc4+ #83 Not tainted [ 66.674342] ------------------------------------------------------ [ 66.674345] systemd-udevd/1232 is trying to acquire lock: [ 66.674349] 00000000a74dab07 (intel_soc_pmic_chtwc:167:(&cht_wc_regmap_cfg)->lock){+.+.}, at: regmap_write+0x31/0x70 [ 66.674360] but task is already holding lock: [ 66.674362] 00000000d44a85b7 (i2c_register_adapter){+.+.}, at: i2c_smbus_xfer+0x49/0xf0 [ 66.674370] which lock already depends on the new lock. [ 66.674371] the existing dependency chain (in reverse order) is: [ 66.674374] -> #1 (i2c_register_adapter){+.+.}: [ 66.674381] rt_mutex_lock_nested+0x46/0x60 [ 66.674384] i2c_smbus_xfer+0x49/0xf0 [ 66.674387] i2c_smbus_read_byte_data+0x45/0x70 [ 66.674391] cht_wc_byte_reg_read+0x35/0x50 [ 66.674394] _regmap_read+0x63/0x1a0 [ 66.674396] _regmap_update_bits+0xa8/0xe0 [ 66.674399] regmap_update_bits_base+0x63/0xa0 [ 66.674403] regmap_irq_update_bits.isra.0+0x3b/0x50 [ 66.674406] regmap_add_irq_chip+0x592/0x7a0 [ 66.674409] devm_regmap_add_irq_chip+0x89/0xed [ 66.674412] cht_wc_probe+0x102/0x158 [ 66.674415] i2c_device_probe+0x95/0x250 [ 66.674419] really_probe+0xf3/0x380 [ 66.674422] driver_probe_device+0x59/0xd0 [ 66.674425] device_driver_attach+0x53/0x60 [ 66.674428] __driver_attach+0x92/0x150 [ 66.674431] bus_for_each_dev+0x7d/0xc0 [ 66.674434] bus_add_driver+0x14d/0x1f0 [ 66.674437] driver_register+0x6d/0xb0 [ 66.674440] i2c_register_driver+0x45/0x80 [ 66.674445] do_one_initcall+0x60/0x2f4 [ 66.674450] kernel_init_freeable+0x20d/0x2b4 [ 66.674453] kernel_init+0xa/0x10c [ 66.674457] ret_from_fork+0x3a/0x50 [ 66.674459] -> #0 (intel_soc_pmic_chtwc:167:(&cht_wc_regmap_cfg)->lock){+.+.}: [ 66.674465] __lock_acquire+0xe07/0x1930 [ 66.674468] lock_acquire+0x9d/0x1a0 [ 66.674472] __mutex_lock+0xa8/0x9a0 [ 66.674474] regmap_write+0x31/0x70 [ 66.674480] cht_wc_i2c_adap_smbus_xfer+0x72/0x240 [i2c_cht_wc] [ 66.674483] __i2c_smbus_xfer+0x1a3/0x640 [ 66.674486] i2c_smbus_xfer+0x67/0xf0 [ 66.674489] i2c_smbus_read_byte_data+0x45/0x70 [ 66.674494] bq24190_probe+0x26b/0x410 [bq24190_charger] [ 66.674497] i2c_device_probe+0x189/0x250 [ 66.674500] really_probe+0xf3/0x380 [ 66.674503] driver_probe_device+0x59/0xd0 [ 66.674506] device_driver_attach+0x53/0x60 [ 66.674509] __driver_attach+0x92/0x150 [ 66.674512] bus_for_each_dev+0x7d/0xc0 [ 66.674515] bus_add_driver+0x14d/0x1f0 [ 66.674518] driver_register+0x6d/0xb0 [ 66.674521] i2c_register_driver+0x45/0x80 [ 66.674524] do_one_initcall+0x60/0x2f4 [ 66.674528] do_init_module+0x5c/0x230 [ 66.674531] load_module+0x2707/0x2a20 [ 66.674534] __do_sys_init_module+0x188/0x1b0 [ 66.674537] do_syscall_64+0x5c/0xb0 [ 66.674541] entry_SYSCALL_64_after_hwframe+0x49/0xbe [ 66.674543] other info that might help us debug this: [ 66.674545] Possible unsafe locking scenario: [ 66.674547] CPU0 CPU1 [ 66.674548] ---- ---- [ 66.674550] lock(i2c_register_adapter); [ 66.674553] lock(intel_soc_pmic_chtwc:167:(&cht_wc_regmap_cfg)->lock); [ 66.674556] lock(i2c_register_adapter); [ 66.674559] lock(intel_soc_pmic_chtwc:167:(&cht_wc_regmap_cfg)->lock); [ 66.674561] *** DEADLOCK *** The problem is that the CHT Whiskey Cove PMIC's builtin i2c-adapter is itself a part of an i2c-client (the PMIC). This means that transfers done through it take adapter->bus_lock twice, once for the parent i2c-adapter and once for its 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 this case there is an i2c-client and MFD instantiated platform_device in the parent->child chain between the 2 devices. This commit overrides the default i2c_lock_operations, passing a hardcoded depth of 1 to rt_mutex_lock_nested, making lockdep happy. Note that if there were to be a mux attached to the i2c-wc-cht adapter, this would break things again since the i2c-mux code expects the root-adapter to have a locking depth of 0. But the i2c-wc-cht adapter always has only 1 client directly attached in the form of the charger IC paired with the CHT Whiskey Cove PMIC. Signed-off-by: Hans de Goede Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-cht-wc.c | 46 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) (limited to 'drivers/i2c') diff --git a/drivers/i2c/busses/i2c-cht-wc.c b/drivers/i2c/busses/i2c-cht-wc.c index 66af44bfa67d..f6546de66fbc 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; -- cgit 1.4.1 From 67de10fbaa12dc7d46412c5ab80f784ea8b4d7f8 Mon Sep 17 00:00:00 2001 From: Stefan Wahren Date: Tue, 27 Aug 2019 19:04:15 +0200 Subject: i2c: bcm2835: Avoid clk stretch quirk for BCM2711 The I2C block on the BCM2711 isn't affected by the clk stretching bug. So there is no need to apply the corresponding quirk. Signed-off-by: Stefan Wahren Reviewed-by: Eric Anholt Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-bcm2835.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers/i2c') diff --git a/drivers/i2c/busses/i2c-bcm2835.c b/drivers/i2c/busses/i2c-bcm2835.c index 67752f7b0371..ab5502f11109 100644 --- a/drivers/i2c/busses/i2c-bcm2835.c +++ b/drivers/i2c/busses/i2c-bcm2835.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -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 */ @@ -475,7 +476,7 @@ static int bcm2835_i2c_probe(struct platform_device *pdev) 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 +502,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); -- cgit 1.4.1 From 250212b59a8e33f1b47f15ad9afa3db19ba0fc8d Mon Sep 17 00:00:00 2001 From: Stefan Wahren Date: Tue, 27 Aug 2019 19:04:16 +0200 Subject: i2c: bcm2835: Add full name of devicetree node to adapter name Inspired by Lori Hikichi's patch for iproc, this adds the full name of the devicetree node to the adapter name. With the introduction of BCM2711 it's very difficult to distinguish between the multiple instances. Signed-off-by: Stefan Wahren Acked-by: Scott Branden Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-bcm2835.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/i2c') diff --git a/drivers/i2c/busses/i2c-bcm2835.c b/drivers/i2c/busses/i2c-bcm2835.c index ab5502f11109..e01b2b57e724 100644 --- a/drivers/i2c/busses/i2c-bcm2835.c +++ b/drivers/i2c/busses/i2c-bcm2835.c @@ -472,7 +472,8 @@ 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; -- cgit 1.4.1 From 4768e90ecaec6b503ff64229bda5d91186d2edd3 Mon Sep 17 00:00:00 2001 From: Max Staudt Date: Tue, 20 Aug 2019 11:27:39 +0200 Subject: i2c: Add i2c-icy for I2C on m68k/Amiga This is the i2c-icy driver for the ICY board for Amiga computers. It connects a PCF8584 I2C controller to the Zorro bus, providing I2C connectivity. The original documentation can be found on Aminet: https://aminet.net/package/docs/hard/icy IRQ support is currently not implemented, as i2c-algo-pcf is built for the ISA bus and a straight implementation of the same stack locks up a Zorro machine. Signed-off-by: Max Staudt Reviewed-by: Geert Uytterhoeven [wsa: added a missing newline reported by checkpatch] Signed-off-by: Wolfram Sang --- MAINTAINERS | 6 ++ drivers/i2c/busses/Kconfig | 11 +++ drivers/i2c/busses/Makefile | 1 + drivers/i2c/busses/i2c-icy.c | 173 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 191 insertions(+) create mode 100644 drivers/i2c/busses/i2c-icy.c (limited to 'drivers/i2c') diff --git a/MAINTAINERS b/MAINTAINERS index f89f27a2d09a..97d35f4e2068 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7750,6 +7750,12 @@ S: Maintained F: drivers/mfd/lpc_ich.c F: drivers/gpio/gpio-ich.c +ICY I2C DRIVER +M: Max Staudt +L: linux-i2c@vger.kernel.org +S: Maintained +F: drivers/i2c/busses/i2c-icy.c + IDE SUBSYSTEM M: "David S. Miller" L: linux-ide@vger.kernel.org diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 69f19312a574..8b97ba4a2c0c 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -1309,6 +1309,17 @@ 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. + config I2C_MLXCPLD tristate "Mellanox I2C driver" depends on X86_64 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-icy.c b/drivers/i2c/busses/i2c-icy.c new file mode 100644 index 000000000000..0d61936dfc0b --- /dev/null +++ b/drivers/i2c/busses/i2c-icy.c @@ -0,0 +1,173 @@ +// 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 + * + * 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 +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include "../algos/i2c-algo-pcf.h" + +struct icy_i2c { + struct i2c_adapter adapter; + + void __iomem *reg_s0; + void __iomem *reg_s1; +}; + +/* + * 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 int icy_probe(struct zorro_dev *z, + const struct zorro_device_id *ent) +{ + struct icy_i2c *i2c; + struct i2c_algo_pcf_data *algo_data; + + 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); + + return 0; +} + +static void icy_remove(struct zorro_dev *z) +{ + struct icy_i2c *i2c = dev_get_drvdata(&z->dev); + + 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 "); +MODULE_DESCRIPTION("I2C bus via PCF8584 on ICY Zorro card"); +MODULE_LICENSE("GPL v2"); -- cgit 1.4.1 From 724041ae15ed9639b72bb54dabfac3279c6b4e55 Mon Sep 17 00:00:00 2001 From: Max Staudt Date: Mon, 19 Aug 2019 14:16:18 +0200 Subject: i2c: icy: Add LTC2990 present on 2019 board revision Since the 2019 a1k.org community re-print of these PCBs sports an LTC2990 hwmon chip as an example use case, let this driver autoprobe for that as well. If it is present, modprobing ltc2990 is sufficient. The property_entry enables the three additional inputs available on this particular board: 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. Signed-off-by: Max Staudt Reviewed-by: Geert Uytterhoeven Signed-off-by: Wolfram Sang --- drivers/i2c/busses/Kconfig | 3 +++ drivers/i2c/busses/i2c-icy.c | 57 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) (limited to 'drivers/i2c') diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 8b97ba4a2c0c..ee7f415a625a 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -1320,6 +1320,9 @@ config I2C_ICY 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 diff --git a/drivers/i2c/busses/i2c-icy.c b/drivers/i2c/busses/i2c-icy.c index 0d61936dfc0b..8382eb64b424 100644 --- a/drivers/i2c/busses/i2c-icy.c +++ b/drivers/i2c/busses/i2c-icy.c @@ -53,6 +53,8 @@ struct icy_i2c { void __iomem *reg_s0; void __iomem *reg_s1; + struct fwnode_handle *ltc2990_fwnode; + struct i2c_client *ltc2990_client; }; /* @@ -94,11 +96,34 @@ static void icy_pcf_waitforpin(void *data) /* * 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) @@ -140,6 +165,35 @@ static int icy_probe(struct zorro_dev *z, 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; } @@ -147,6 +201,9 @@ 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); } -- cgit 1.4.1 From f0b576801d83cecab29888010017333babd61ede Mon Sep 17 00:00:00 2001 From: "Adamski, Krzysztof (Nokia - PL/Wroclaw)" Date: Mon, 19 Aug 2019 09:07:07 +0000 Subject: i2c: axxia: support slave mode This device contains both master and slave controllers which can be enabled simultaneously. Both controllers share the same SDA/SCL lines and interrupt source but has separate control and status registers. Controllers also works in loopback mode - slave device can communicate with its own master controller internally. The controller can handle up to two addresses, both of which may be 10 bit. Most of the logic (sending (N)ACK, handling repeated start or switching between write/read) is handled automatically which makes working with this controller quite easy. For simplicity, this patch adds basic support, limiting to only one slave address. Support for the 2nd device may be added in the future. Note that synchronize_irq() is used to ensure any running slave interrupt is finished to make sure slave i2c_client structure can be safely used by i2c_slave_event. Signed-off-by: Krzysztof Adamski Reviewed-by: Alexander Sverdlin Signed-off-by: Wolfram Sang --- drivers/i2c/busses/Kconfig | 1 + drivers/i2c/busses/i2c-axxia.c | 152 ++++++++++++++++++++++++++++++++++++++--- 2 files changed, 145 insertions(+), 8 deletions(-) (limited to 'drivers/i2c') diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index ee7f415a625a..d3023e5379ea 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. 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; } -- cgit 1.4.1 From 21aa3983d619055cc3ecd0f0ceea4981dc8ee751 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 15 Aug 2019 17:29:43 +0300 Subject: i2c: designware-pci: Switch over to MSI interrupts Some devices support MSI interrupts. Let's at least try to use them in platforms that provide MSI capability. Signed-off-by: Felipe Balbi Signed-off-by: Jarkko Nikula Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-designware-pcidrv.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) (limited to 'drivers/i2c') diff --git a/drivers/i2c/busses/i2c-designware-pcidrv.c b/drivers/i2c/busses/i2c-designware-pcidrv.c index 7d2e6959679c..249ee3ee2a09 100644 --- a/drivers/i2c/busses/i2c-designware-pcidrv.c +++ b/drivers/i2c/busses/i2c-designware-pcidrv.c @@ -225,6 +225,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"); @@ -235,18 +237,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 | @@ -274,8 +282,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); @@ -294,6 +304,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 */ -- cgit 1.4.1 From 70fb95e213147a88417eaae5b93ba6e59be087c0 Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Thu, 15 Aug 2019 17:29:44 +0300 Subject: i2c: designware-pci: Add support for Elkhart Lake PSE I2C Add support for Intel(R) Programmable Services Engine (Intel(R) PSE) I2C controller in Intel Elkhart Lake when interface is assigned to the host processor. Signed-off-by: Jarkko Nikula Reviewed-by: Andy Shevchenko Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-designware-pcidrv.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'drivers/i2c') diff --git a/drivers/i2c/busses/i2c-designware-pcidrv.c b/drivers/i2c/busses/i2c-designware-pcidrv.c index 249ee3ee2a09..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,6 +169,14 @@ 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 @@ -340,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); -- cgit 1.4.1 From f9bf7a899412b5f8c96b084343bde4168dc12efa Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Mon, 19 Aug 2019 13:16:01 +0530 Subject: i2c: taos-evm: Make structure tsl2550_info constant Static structure tsl2550_info, of type i2c_board_info, is referenced only twice: the first time in arguments to dev_info() (which does not modify it) and the second time as the last argument to function i2c_new_device() (where the corresponding parameter is declared as const). As tsl2550_info is therefore never modified, make it const to protect it from unintended modifications. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Reviewed-by: Jean Delvare Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-taos-evm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/i2c') diff --git a/drivers/i2c/busses/i2c-taos-evm.c b/drivers/i2c/busses/i2c-taos-evm.c index c82e78f57386..056df6b2538a 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), }; -- cgit 1.4.1 From 71dc297ca9ab6311e7d39fc53811fd871d51854f Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 19 Aug 2019 13:24:23 +0300 Subject: i2c: designware: assert reset when error happen at ->probe() The commit c62ebb3d5f0d ("i2c: designware: Add support for an interface clock") introduced an optional clock while missed correct error handling. assert reset line back if error happen at ->probe(). Fixes: c62ebb3d5f0d ("i2c: designware: Add support for an interface clock") Signed-off-by: Andy Shevchenko Acked-by: Jarkko Nikula Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-designware-platdrv.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/i2c') diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c index ddfb81872906..4624ef8fbae8 100644 --- a/drivers/i2c/busses/i2c-designware-platdrv.c +++ b/drivers/i2c/busses/i2c-designware-platdrv.c @@ -346,8 +346,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)) { -- cgit 1.4.1 From a6af48ec0712a0c98d8abe6b47c655b26026fceb Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 19 Aug 2019 13:31:30 +0300 Subject: i2c: designware: Fix optional reset error handling The commit bb475230b8e5 ("reset: make optional functions really optional") brought a missed part of the support for an optional reset handlers. Since that we don't need to have special error handling in the driver. Signed-off-by: Andy Shevchenko Acked-by: Jarkko Nikula Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-designware-platdrv.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) (limited to 'drivers/i2c') diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c index 4624ef8fbae8..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) @@ -402,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; } @@ -421,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; } -- cgit 1.4.1 From ba919403566dba52bf074851896ba0ca7f72c1e2 Mon Sep 17 00:00:00 2001 From: Federico Vaga Date: Thu, 22 Aug 2019 15:21:32 +0200 Subject: i2c: ocores: use request_any_context_irq() to register IRQ handler The i2c-ocores device is an HDL component that get instantiated in FPGA. The software stack used to drive an FPGA can be very different, and the i2c-ocore ip-core must work in different context. With respect to this patch the IRQ controller behind this device, and its driver, can have different implementations (nested threads). For this reason, it is safer to use `request_any_context_irq()` to avoid errors at probe time. Signed-off-by: Federico Vaga Reviewed-by: Andrew Lunn Reviewed-by: Peter Korsgaard Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-ocores.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/i2c') 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; -- cgit 1.4.1 From 528d53a1592b0e27c423f7cafc1df85f77fc1163 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Fri, 2 Aug 2019 14:54:38 +0200 Subject: i2c: piix4: Fix probing of reserved ports on AMD Family 16h Model 30h Prevent bus timeouts and resets on Family 16h Model 30h by not probing reserved Ports 3 and 4. According to the AMD BIOS and Kernel Developer's Guides (BKDG), Port 3 and Port 4 are reserved on the following devices: - Family 15h Model 60h-6Fh - Family 15h Model 70h-7Fh - Family 16h Model 30h-3Fh Based on earlier work by Andrew Cooks. Reported-by: Andrew Cooks Signed-off-by: Jean Delvare Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-piix4.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'drivers/i2c') diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c index c46c4bddc7ca..d9f7e771f6ad 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 @@ -808,6 +809,7 @@ 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, @@ -867,7 +869,15 @@ 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++) { retval = piix4_add_adapter(dev, smba, true, port, notify_imc, piix4_main_port_names_sb800[port], &piix4_main_adapters[port]); @@ -989,7 +999,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]) { -- cgit 1.4.1 From 0183eb8bb59d45f26ec4fc73aaa416067fe6c0be Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Fri, 2 Aug 2019 14:55:26 +0200 Subject: i2c: piix4: Add ACPI support Enable the i2c-piix4 SMBus controller driver to enumerate I2C slave devices using ACPI. It builds on the related I2C mux device work in commit 8eb5c87a92c0 ("i2c: add ACPI support for I2C mux ports") In the i2c-piix4 driver the adapters are enumerated as: Main SMBus adapter Port 0, Port 2, ..., aux port (i.e., ASF adapter) However, in the AMD BKDG documentation[1], the implied order of ports is: Main SMBus adapter Port 0, ASF adapter, Port 2, Port 3, ... This ordering difference is unfortunate. We assume that ACPI developers will use the AMD documentation ordering, so we have to pass an extra parameter to piix4_add_adapter(). [1] 52740 BIOS and Kernel Developer's Guide (BKDG) for AMD Family 16h Models 30h-3Fh Processors Based on earlier work by Andrew Cooks. Reported-by: Andrew Cooks Signed-off-by: Jean Delvare Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-piix4.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) (limited to 'drivers/i2c') diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c index d9f7e771f6ad..890b8d029b28 100644 --- a/drivers/i2c/busses/i2c-piix4.c +++ b/drivers/i2c/busses/i2c-piix4.c @@ -813,7 +813,8 @@ 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; @@ -845,6 +846,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); @@ -878,7 +885,10 @@ static int piix4_add_adapters_sb800(struct pci_dev *dev, unsigned short smba, } 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) @@ -949,8 +959,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; } @@ -976,7 +986,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); } -- cgit 1.4.1 From 539005ffc6260fcb3bb4171138be5f66a41185a9 Mon Sep 17 00:00:00 2001 From: Lori Hikichi Date: Thu, 8 Aug 2019 09:07:53 +0530 Subject: i2c: iproc: Add full name of devicetree node to adapter name Add the full name of the devicetree node to the adapter name. Without this change, all adapters have the same name making it difficult to distinguish between multiple instances. The most obvious way to see this is to use the utility i2c_detect. e.g. "i2c-detect -l" Before i2c-1 i2c Broadcom iProc I2C adapter I2C adapter i2c-0 i2c Broadcom iProc I2C adapter I2C adapter After i2c-1 i2c Broadcom iProc (i2c@e0000) I2C adapter i2c-0 i2c Broadcom iProc (i2c@b0000) I2C adapter Now it is easy to figure out which adapter maps to a which DT node. Signed-off-by: Lori Hikichi Signed-off-by: Rayagonda Kokatanur Reviewed-by: Ray Jui Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-bcm-iproc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/i2c') diff --git a/drivers/i2c/busses/i2c-bcm-iproc.c b/drivers/i2c/busses/i2c-bcm-iproc.c index 2c7f145a036e..ee5578173fb1 100644 --- a/drivers/i2c/busses/i2c-bcm-iproc.c +++ b/drivers/i2c/busses/i2c-bcm-iproc.c @@ -917,7 +917,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; -- cgit 1.4.1 From 67a53081e655d41a77f510377364600e5e9bf89c Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Thu, 15 Aug 2019 11:25:50 +0530 Subject: i2c: iproc: Make bcm_iproc_i2c_quirks constant Static structure bcm_iproc_i2c_quirks, of type i2c_adapter_quirks, is only used when being assigned to constant field quirks of a variable having type i2c_adapter. Hence make bcm_iproc_i2c_quirks constant as well to prevent it from unintended modification. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Reviewed-by: Ray Jui Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-bcm-iproc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/i2c') diff --git a/drivers/i2c/busses/i2c-bcm-iproc.c b/drivers/i2c/busses/i2c-bcm-iproc.c index ee5578173fb1..24269a5e3af6 100644 --- a/drivers/i2c/busses/i2c-bcm-iproc.c +++ b/drivers/i2c/busses/i2c-bcm-iproc.c @@ -803,7 +803,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, }; -- cgit 1.4.1 From b84398d6d7f900805662b1619223fd644d862d7c Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Sat, 31 Aug 2019 17:24:02 +0300 Subject: i2c: i801: Use iTCO version 6 in Cannon Lake PCH and beyond Intel Cannon Lake PCH moved the NO_REBOOT bit to reside as part of the TCO registers instead so update the i2c-i801 driver so that for Cannon Lake and beyond register platform device for iTCO using version 6. The affected PCHs are Cannon Lake, Cedar Fork, Comet Lake, Elkhart Lake and Ice Lake. Signed-off-by: Mika Westerberg Reviewed-by: Jean Delvare Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-i801.c | 142 ++++++++++++++++++++++++++---------------- 1 file changed, 88 insertions(+), 54 deletions(-) (limited to 'drivers/i2c') diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index a6469978e735..38afd16c857a 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -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", @@ -1491,57 +1492,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 +1544,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; - } - priv->tco_pdev = pdev; + 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); + + 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 +1723,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 +1747,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; -- cgit 1.4.1 From f8c274e4a70e7cdc43db56e2391c485c580b5a43 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Tue, 13 Aug 2019 13:55:55 +0200 Subject: i2c: hix5hd2: Remove IRQF_ONESHOT The drivers sets IRQF_ONESHOT and passes only a primary handler. The IRQ is masked while the primary is handler is invoked independently of IRQF_ONESHOT. With IRQF_ONESHOT the core code will not force-thread the interrupt and this is probably not intended. I *assume* that the original author copied the IRQ registration from another driver which passed a primary and secondary handler and removed the secondary handler but keeping the ONESHOT flag. Remove IRQF_ONESHOT. Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-hix5hd2.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/i2c') 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; -- cgit 1.4.1 From 7077ad2ee316551b4ba9602838d09b67683e20b6 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Mon, 19 Aug 2019 13:28:54 +0530 Subject: i2c: synquacer: Make synquacer_i2c_ops constant Static structure synquacer_i2c_ops, of type i2c_adapter, is only used when it is copied into a field of another structure. It is not itself modified. Hence make it const to protect it from unintended modification. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Acked-by: Ard Biesheuvel Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-synquacer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/i2c') 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, -- cgit 1.4.1 From 0a321b97368aa0567f238207eeb19cc8cbb6a7e2 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Sat, 6 Jul 2019 18:49:11 +0530 Subject: i2c: fsi: Add of_put_node() before break Each iteration of for_each_available_childe_of_node puts the previous node, but in the case of a break from the middle of the loop, there is no put, thus causing a memory leak. Add an of_node_put before the break. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Reviewed-by: Eddie James Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-fsi.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/i2c') 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; -- cgit 1.4.1 From 82d51481544146db2e9c9fb90c8fed92a5d0f93b Mon Sep 17 00:00:00 2001 From: Björn Ardö Date: Wed, 4 Sep 2019 11:29:53 +0200 Subject: i2c-eeprom_slave: Add support for more eeprom models MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a 32 and a 64 kbit memory. These needs 16 bit address so added support for that as well. Signed-off-by: Björn Ardö Signed-off-by: Wolfram Sang --- drivers/i2c/i2c-slave-eeprom.c | 36 +++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-) (limited to 'drivers/i2c') diff --git a/drivers/i2c/i2c-slave-eeprom.c b/drivers/i2c/i2c-slave-eeprom.c index be65d3842878..773afaabfb61 100644 --- a/drivers/i2c/i2c-slave-eeprom.c +++ b/drivers/i2c/i2c-slave-eeprom.c @@ -11,6 +11,7 @@ * pointer, yet implementation is deferred until the need actually arises. */ +#include #include #include #include @@ -21,12 +22,18 @@ struct eeprom_data { struct bin_attribute bin; - bool first_write; spinlock_t buffer_lock; - u8 buffer_idx; + u16 buffer_idx; + u16 address_mask; + u8 num_address_bytes; + u8 idx_write_cnt; u8 buffer[]; }; +#define I2C_SLAVE_BYTELEN GENMASK(15, 0) +#define I2C_SLAVE_FLAG_ADDR16 BIT(16) +#define I2C_SLAVE_DEVICE_MAGIC(_len, _flags) ((_flags) | (_len)) + static int i2c_slave_eeprom_slave_cb(struct i2c_client *client, enum i2c_slave_event event, u8 *val) { @@ -34,12 +41,14 @@ static int i2c_slave_eeprom_slave_cb(struct i2c_client *client, switch (event) { case I2C_SLAVE_WRITE_RECEIVED: - if (eeprom->first_write) { - eeprom->buffer_idx = *val; - eeprom->first_write = false; + if (eeprom->idx_write_cnt < eeprom->num_address_bytes) { + if (eeprom->idx_write_cnt == 0) + eeprom->buffer_idx = 0; + eeprom->buffer_idx = *val | (eeprom->buffer_idx << 8); + eeprom->idx_write_cnt++; } else { spin_lock(&eeprom->buffer_lock); - eeprom->buffer[eeprom->buffer_idx++] = *val; + eeprom->buffer[eeprom->buffer_idx++ & eeprom->address_mask] = *val; spin_unlock(&eeprom->buffer_lock); } break; @@ -50,7 +59,7 @@ static int i2c_slave_eeprom_slave_cb(struct i2c_client *client, /* fallthrough */ case I2C_SLAVE_READ_REQUESTED: spin_lock(&eeprom->buffer_lock); - *val = eeprom->buffer[eeprom->buffer_idx]; + *val = eeprom->buffer[eeprom->buffer_idx & eeprom->address_mask]; spin_unlock(&eeprom->buffer_lock); /* * Do not increment buffer_idx here, because we don't know if @@ -61,7 +70,7 @@ static int i2c_slave_eeprom_slave_cb(struct i2c_client *client, case I2C_SLAVE_STOP: case I2C_SLAVE_WRITE_REQUESTED: - eeprom->first_write = true; + eeprom->idx_write_cnt = 0; break; default: @@ -105,13 +114,16 @@ static int i2c_slave_eeprom_probe(struct i2c_client *client, const struct i2c_de { struct eeprom_data *eeprom; int ret; - unsigned size = id->driver_data; + unsigned int size = FIELD_GET(I2C_SLAVE_BYTELEN, id->driver_data); + unsigned int flag_addr16 = FIELD_GET(I2C_SLAVE_FLAG_ADDR16, id->driver_data); eeprom = devm_kzalloc(&client->dev, sizeof(struct eeprom_data) + size, GFP_KERNEL); if (!eeprom) return -ENOMEM; - eeprom->first_write = true; + eeprom->idx_write_cnt = 0; + eeprom->num_address_bytes = flag_addr16 ? 2 : 1; + eeprom->address_mask = size - 1; spin_lock_init(&eeprom->buffer_lock); i2c_set_clientdata(client, eeprom); @@ -146,7 +158,9 @@ static int i2c_slave_eeprom_remove(struct i2c_client *client) } static const struct i2c_device_id i2c_slave_eeprom_id[] = { - { "slave-24c02", 2048 / 8 }, + { "slave-24c02", I2C_SLAVE_DEVICE_MAGIC(2048 / 8, 0) }, + { "slave-24c32", I2C_SLAVE_DEVICE_MAGIC(32768 / 8, I2C_SLAVE_FLAG_ADDR16) }, + { "slave-24c64", I2C_SLAVE_DEVICE_MAGIC(65536 / 8, I2C_SLAVE_FLAG_ADDR16) }, { } }; MODULE_DEVICE_TABLE(i2c, i2c_slave_eeprom_id); -- cgit 1.4.1 From 539b7569c56523486db95214d62a108532c7960f Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Tue, 20 Aug 2019 17:34:40 +0200 Subject: i2c: cht-wc: drop check because i2c_unregister_device() is NULL safe No need to check the argument of i2c_unregister_device() because the function itself does it. Signed-off-by: Wolfram Sang Acked-by: Hans de Goede Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-cht-wc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/i2c') diff --git a/drivers/i2c/busses/i2c-cht-wc.c b/drivers/i2c/busses/i2c-cht-wc.c index f6546de66fbc..b8fde61bb5d8 100644 --- a/drivers/i2c/busses/i2c-cht-wc.c +++ b/drivers/i2c/busses/i2c-cht-wc.c @@ -409,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); -- cgit 1.4.1 From 2252c3172cc5ecfab5aef1057f7c57b39e485f21 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Thu, 15 Aug 2019 11:28:57 +0530 Subject: i2c: stm32f7: Make structure stm32f7_i2c_algo constant Static structure stm32f7_i2c_algo, of type i2c_algorithm, is used only when it is assigned to constant field algo of a variable having type i2c_adapter. As stm32f7_i2c_algo is therefore never modified, make it const as well to protect it from unintended modification. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Acked-by: Pierre-Yves MORDRET Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-stm32f7.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/i2c') 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, -- cgit 1.4.1 From 41d529d6227c443a5827cb8b8f040402dedcf3d2 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Tue, 13 Aug 2019 13:55:54 +0200 Subject: i2c: exynos5: Remove IRQF_ONESHOT The drivers sets IRQF_ONESHOT and passes only a primary handler. The IRQ is masked while the primary is handler is invoked independently of IRQF_ONESHOT. With IRQF_ONESHOT the core code will not force-thread the interrupt and this is probably not intended. I *assume* that the original author copied the IRQ registration from another driver which passed a primary and secondary handler and removed the secondary handler but keeping the ONESHOT flag. Remove IRQF_ONESHOT. Reported-by: Benjamin Rouxel Tested-by: Benjamin Rouxel Signed-off-by: Sebastian Andrzej Siewior Tested-by: Krzysztof Kozlowski Acked-by: Krzysztof Kozlowski Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-exynos5.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/i2c') 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; -- cgit 1.4.1 From fe050f99072d6b5175c35427a6f72846790441ec Mon Sep 17 00:00:00 2001 From: Björn Ardö Date: Thu, 5 Sep 2019 16:50:26 +0200 Subject: i2c: slave-eeprom: Add comment about address handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The behaviour of the EEPROM in the case where we only send an 8bit address to a 16bit address EEPROM is not defined. Added comment about that the slave-eeprom might behave differently from how an actual device does (only one model measured). Reported-by: Wolfram Sang Signed-off-by: Björn Ardö Signed-off-by: Wolfram Sang --- drivers/i2c/i2c-slave-eeprom.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/i2c') diff --git a/drivers/i2c/i2c-slave-eeprom.c b/drivers/i2c/i2c-slave-eeprom.c index 773afaabfb61..92ff9991bae8 100644 --- a/drivers/i2c/i2c-slave-eeprom.c +++ b/drivers/i2c/i2c-slave-eeprom.c @@ -11,6 +11,12 @@ * pointer, yet implementation is deferred until the need actually arises. */ +/* + * FIXME: What to do if only 8 bits of a 16 bit address are sent? + * The ST-M24C64 sends only 0xff then. Needs verification with other + * EEPROMs, though. We currently use the 8 bit as a valid address. + */ + #include #include #include -- cgit 1.4.1 From 22ac74a6194798ce131c55ff0dfbb9697650e626 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Thu, 5 Sep 2019 12:45:32 +0900 Subject: i2c: uniphier(-f): use devm_platform_ioremap_resource() Replace the chain of platform_get_resource() and devm_ioremap_resource() with devm_platform_ioremap_resource(). This allows to remove the local variable for (struct resource *), and have one function call less. Signed-off-by: Masahiro Yamada Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-uniphier-f.c | 4 +--- drivers/i2c/busses/i2c-uniphier.c | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) (limited to 'drivers/i2c') diff --git a/drivers/i2c/busses/i2c-uniphier-f.c b/drivers/i2c/busses/i2c-uniphier-f.c index 7acca2599f04..fc5354845ffa 100644 --- a/drivers/i2c/busses/i2c-uniphier-f.c +++ b/drivers/i2c/busses/i2c-uniphier-f.c @@ -538,7 +538,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 +546,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..a6d7a3709051 100644 --- a/drivers/i2c/busses/i2c-uniphier.c +++ b/drivers/i2c/busses/i2c-uniphier.c @@ -326,7 +326,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 +334,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); -- cgit 1.4.1 From 9ee7e72fbbb835ba92b2cbf4349997adf065eab0 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Thu, 5 Sep 2019 13:46:48 +0900 Subject: i2c: uniphier(-f): remove all dev_dbg() I have fixed various bugs, and these drivers are (I hope) pretty stable now. Remove all dev_dbg() for code clean-up. If I end up with debugging the drivers again, I will locally revert this commit. I no longer need the debug code in upstream. Signed-off-by: Masahiro Yamada Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-uniphier-f.c | 22 +--------------------- drivers/i2c/busses/i2c-uniphier.c | 18 +++--------------- 2 files changed, 4 insertions(+), 36 deletions(-) (limited to 'drivers/i2c') diff --git a/drivers/i2c/busses/i2c-uniphier-f.c b/drivers/i2c/busses/i2c-uniphier-f.c index fc5354845ffa..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; diff --git a/drivers/i2c/busses/i2c-uniphier.c b/drivers/i2c/busses/i2c-uniphier.c index a6d7a3709051..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 -- cgit 1.4.1 From 11330a9fef049db195f50300627dd972e19e0f8e Mon Sep 17 00:00:00 2001 From: Chuanhua Han Date: Fri, 6 Sep 2019 15:53:19 +0800 Subject: i2c: imx: ACPI support for NXP i2c controller Enable NXP i2c controller to boot with ACPI. Signed-off-by: Meenakshi Aggarwal Signed-off-by: Udit Kumar Signed-off-by: Chuanhua Han Signed-off-by: Biwen Li Reviewed-by: Andy Shevchenko Acked-by: Oleksij Rempel Tested-by: Oleksij Rempel Acked-by: Rafael J. Wysocki Signed-off-by: Wolfram Sang --- drivers/acpi/acpi_apd.c | 7 +++++++ drivers/i2c/busses/i2c-imx.c | 17 +++++++++++++---- 2 files changed, 20 insertions(+), 4 deletions(-) (limited to 'drivers/i2c') diff --git a/drivers/acpi/acpi_apd.c b/drivers/acpi/acpi_apd.c index 7cd0c9ac71ea..71511ae2dfcd 100644 --- a/drivers/acpi/acpi_apd.c +++ b/drivers/acpi/acpi_apd.c @@ -160,11 +160,17 @@ static const struct apd_device_desc hip08_i2c_desc = { .setup = acpi_apd_setup, .fixed_clk_rate = 250000000, }; + static const struct apd_device_desc thunderx2_i2c_desc = { .setup = acpi_apd_setup, .fixed_clk_rate = 125000000, }; +static const struct apd_device_desc nxp_i2c_desc = { + .setup = acpi_apd_setup, + .fixed_clk_rate = 350000000, +}; + static const struct apd_device_desc hip08_spi_desc = { .setup = acpi_apd_setup, .fixed_clk_rate = 250000000, @@ -238,6 +244,7 @@ static const struct acpi_device_id acpi_apd_device_ids[] = { { "HISI02A1", APD_ADDR(hip07_i2c_desc) }, { "HISI02A2", APD_ADDR(hip08_i2c_desc) }, { "HISI0173", APD_ADDR(hip08_spi_desc) }, + { "NXP0001", APD_ADDR(nxp_i2c_desc) }, #endif { } }; diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c index b1b8b938d7f4..40692fc70d92 100644 --- a/drivers/i2c/busses/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c @@ -20,6 +20,7 @@ * */ +#include #include #include #include @@ -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; @@ -1050,14 +1057,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__); @@ -1077,8 +1083,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; @@ -1091,6 +1098,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); @@ -1253,6 +1261,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, }; -- cgit 1.4.1 From 8ebf15e9c869e764b3aab4928938ee68c0e2bd6d Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Tue, 10 Sep 2019 10:29:17 +0100 Subject: i2c: tegra: Move suspend handling to NOIRQ phase Commit acc8abcb2a9c ("i2c: tegra: Add suspend-resume support") added suspend support for the Tegra I2C driver and following this change on Tegra30 the following WARNING is seen on entering suspend ... WARNING: CPU: 2 PID: 689 at /dvs/git/dirty/git-master_l4t-upstream/kernel/drivers/i2c/i2c-core.h:54 __i2c_transfer+0x35c/0x70c i2c i2c-4: Transfer while suspended Modules linked in: brcmfmac brcmutil CPU: 2 PID: 689 Comm: rtcwake Not tainted 5.3.0-rc7-g089cf7f6ecb2 #1 Hardware name: NVIDIA Tegra SoC (Flattened Device Tree) [] (unwind_backtrace) from [] (show_stack+0x10/0x14) [] (show_stack) from [] (dump_stack+0xb4/0xc8) [] (dump_stack) from [] (__warn+0xe0/0xf8) [] (__warn) from [] (warn_slowpath_fmt+0x48/0x6c) [] (warn_slowpath_fmt) from [] (__i2c_transfer+0x35c/0x70c) [] (__i2c_transfer) from [] (i2c_transfer+0x58/0xf4) [] (i2c_transfer) from [] (i2c_transfer_buffer_flags+0x4c/0x70) [] (i2c_transfer_buffer_flags) from [] (regmap_i2c_write+0x14/0x30) [] (regmap_i2c_write) from [] (_regmap_raw_write_impl+0x35c/0x868) [] (_regmap_raw_write_impl) from [] (_regmap_update_bits+0xe4/0xec) [] (_regmap_update_bits) from [] (regmap_update_bits_base+0x50/0x74) [] (regmap_update_bits_base) from [] (regulator_disable_regmap+0x44/0x54) [] (regulator_disable_regmap) from [] (_regulator_do_disable+0xf8/0x268) [] (_regulator_do_disable) from [] (_regulator_disable+0xf4/0x19c) [] (_regulator_disable) from [] (regulator_disable+0x34/0x64) [] (regulator_disable) from [] (regulator_bulk_disable+0x28/0xb4) [] (regulator_bulk_disable) from [] (tegra_pcie_power_off+0x64/0xa8) [] (tegra_pcie_power_off) from [] (tegra_pcie_pm_suspend+0x25c/0x3f4) [] (tegra_pcie_pm_suspend) from [] (dpm_run_callback+0x38/0x1d4) [] (dpm_run_callback) from [] (__device_suspend_noirq+0xc0/0x2b8) [] (__device_suspend_noirq) from [] (dpm_noirq_suspend_devices+0x100/0x37c) [] (dpm_noirq_suspend_devices) from [] (dpm_suspend_noirq+0x1c/0x48) [] (dpm_suspend_noirq) from [] (suspend_devices_and_enter+0x1d0/0xa00) [] (suspend_devices_and_enter) from [] (pm_suspend+0x220/0x74c) [] (pm_suspend) from [] (state_store+0x6c/0xc8) [] (state_store) from [] (kernfs_fop_write+0xe8/0x1c4) [] (kernfs_fop_write) from [] (__vfs_write+0x2c/0x1c4) [] (__vfs_write) from [] (vfs_write+0xa4/0x184) [] (vfs_write) from [] (ksys_write+0x9c/0xdc) [] (ksys_write) from [] (ret_fast_syscall+0x0/0x54) Exception stack(0xe9f21fa8 to 0xe9f21ff0) 1fa0: 0000006c 004b2438 00000004 004b2438 00000004 00000000 1fc0: 0000006c 004b2438 004b1228 00000004 00000004 00000004 0049e78c 004b1228 1fe0: 00000004 be9809b8 b6f0bc0b b6e96206 The problem is that the Tegra PCIe driver indirectly uses I2C for controlling some regulators and the I2C driver is now being suspended before the PCIe driver causing the PCIe suspend to fail. The Tegra PCIe driver is suspended during the NOIRQ phase and this cannot be changed due to other dependencies. Therefore, we also need to move the suspend handling for the Tegra I2C driver to the NOIRQ phase as well. In order to move the I2C suspend handling to the NOIRQ phase we also need to avoid calling pm_runtime_get/put() because per commit 1e2ef05bb8cf ("PM: Limit race conditions between runtime PM and system sleep (v2)") these cannot be called early in resume. The function tegra_i2c_init(), called during resume, calls pm_runtime_get/put() and so move these calls outside of tegra_i2c_init(), so this function can be used during the NOIRQ resume phase. Fixes: acc8abcb2a9c ("i2c: tegra: Add suspend-resume support") Signed-off-by: Jon Hunter Acked-by: Thierry Reding Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-tegra.c | 40 ++++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 18 deletions(-) (limited to 'drivers/i2c') diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index 18f0ceed9f1b..c1683f9338b4 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -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: @@ -1725,17 +1721,25 @@ 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) }; -- cgit 1.4.1