From ea734404f3daf1f6b5103171d848c9d4641fd96b Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Tue, 9 Aug 2016 13:36:17 +0200 Subject: [PATCH 01/71] i2c: don't print error when adding adapter fails The core will do this for us now. Signed-off-by: Wolfram Sang Reviewed-by: Grygorii Strashko Acked-by: Peter Korsgaard Acked-by: Heiko Stuebner Acked-by: Neil Horman Acked-by: Thierry Reding Acked-by: Ray Jui Acked-by: Vladimir Zapolskiy Acked-by: Ludovic Desroches Acked-by: Krzysztof Kozlowski Acked-by: Laxman Dewangan Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-amd756.c | 5 +---- drivers/i2c/busses/i2c-at91.c | 2 -- drivers/i2c/busses/i2c-axxia.c | 8 +------- drivers/i2c/busses/i2c-bcm-iproc.c | 8 +------- drivers/i2c/busses/i2c-bcm-kona.c | 4 +--- drivers/i2c/busses/i2c-bfin-twi.c | 4 +--- drivers/i2c/busses/i2c-brcmstb.c | 4 +--- drivers/i2c/busses/i2c-cadence.c | 4 +--- drivers/i2c/busses/i2c-cpm.c | 4 +--- drivers/i2c/busses/i2c-cros-ec-tunnel.c | 4 +--- drivers/i2c/busses/i2c-davinci.c | 4 +--- drivers/i2c/busses/i2c-diolan-u2c.c | 4 +--- drivers/i2c/busses/i2c-dln2.c | 4 +--- drivers/i2c/busses/i2c-efm32.c | 1 - drivers/i2c/busses/i2c-exynos5.c | 4 +--- drivers/i2c/busses/i2c-hix5hd2.c | 4 +--- drivers/i2c/busses/i2c-i801.c | 1 - drivers/i2c/busses/i2c-ibm_iic.c | 4 +--- drivers/i2c/busses/i2c-img-scb.c | 4 +--- drivers/i2c/busses/i2c-imx.c | 4 +--- drivers/i2c/busses/i2c-isch.c | 4 +--- drivers/i2c/busses/i2c-ismt.c | 4 +--- drivers/i2c/busses/i2c-jz4780.c | 4 +--- drivers/i2c/busses/i2c-lpc2k.c | 4 +--- drivers/i2c/busses/i2c-meson.c | 1 - drivers/i2c/busses/i2c-mpc.c | 4 +--- drivers/i2c/busses/i2c-mt65xx.c | 4 +--- drivers/i2c/busses/i2c-mxs.c | 1 - drivers/i2c/busses/i2c-nforce2.c | 1 - drivers/i2c/busses/i2c-nomadik.c | 4 +--- drivers/i2c/busses/i2c-ocores.c | 4 +--- drivers/i2c/busses/i2c-octeon.c | 4 +--- drivers/i2c/busses/i2c-omap.c | 4 +--- drivers/i2c/busses/i2c-piix4.c | 1 - drivers/i2c/busses/i2c-pmcmsp.c | 4 +--- drivers/i2c/busses/i2c-pnx.c | 4 +--- drivers/i2c/busses/i2c-puv3.c | 5 +---- drivers/i2c/busses/i2c-pxa.c | 4 +--- drivers/i2c/busses/i2c-rcar.c | 4 +--- drivers/i2c/busses/i2c-riic.c | 4 +--- drivers/i2c/busses/i2c-rk3x.c | 4 +--- drivers/i2c/busses/i2c-s3c2410.c | 1 - drivers/i2c/busses/i2c-sh7760.c | 4 +--- drivers/i2c/busses/i2c-sh_mobile.c | 1 - drivers/i2c/busses/i2c-sirf.c | 4 +--- drivers/i2c/busses/i2c-st.c | 4 +--- drivers/i2c/busses/i2c-stu300.c | 5 +---- drivers/i2c/busses/i2c-tegra.c | 4 +--- drivers/i2c/busses/i2c-wmt.c | 4 +--- drivers/i2c/busses/i2c-xgene-slimpro.c | 1 - drivers/i2c/busses/i2c-xiic.c | 1 - drivers/i2c/busses/i2c-xlp9xx.c | 4 +--- drivers/i2c/busses/i2c-xlr.c | 4 +--- 53 files changed, 42 insertions(+), 149 deletions(-) diff --git a/drivers/i2c/busses/i2c-amd756.c b/drivers/i2c/busses/i2c-amd756.c index 6c7113d990f8..274908cd1fde 100644 --- a/drivers/i2c/busses/i2c-amd756.c +++ b/drivers/i2c/busses/i2c-amd756.c @@ -378,11 +378,8 @@ static int amd756_probe(struct pci_dev *pdev, const struct pci_device_id *id) amd756_ioport); error = i2c_add_adapter(&amd756_smbus); - if (error) { - dev_err(&pdev->dev, - "Adapter registration failed, module not inserted\n"); + if (error) goto out_err; - } return 0; diff --git a/drivers/i2c/busses/i2c-at91.c b/drivers/i2c/busses/i2c-at91.c index 1bb97f658b47..0b86c6173e07 100644 --- a/drivers/i2c/busses/i2c-at91.c +++ b/drivers/i2c/busses/i2c-at91.c @@ -1122,8 +1122,6 @@ static int at91_twi_probe(struct platform_device *pdev) rc = i2c_add_numbered_adapter(&dev->adapter); if (rc) { - dev_err(dev->dev, "Adapter %s registration failed\n", - dev->adapter.name); clk_disable_unprepare(dev->clk); pm_runtime_disable(dev->dev); diff --git a/drivers/i2c/busses/i2c-axxia.c b/drivers/i2c/busses/i2c-axxia.c index c335cc7852f9..d3bcaf4ab095 100644 --- a/drivers/i2c/busses/i2c-axxia.c +++ b/drivers/i2c/busses/i2c-axxia.c @@ -558,13 +558,7 @@ static int axxia_i2c_probe(struct platform_device *pdev) platform_set_drvdata(pdev, idev); - ret = i2c_add_adapter(&idev->adapter); - if (ret) { - dev_err(&pdev->dev, "failed to add adapter\n"); - return ret; - } - - return 0; + return i2c_add_adapter(&idev->adapter); } static int axxia_i2c_remove(struct platform_device *pdev) diff --git a/drivers/i2c/busses/i2c-bcm-iproc.c b/drivers/i2c/busses/i2c-bcm-iproc.c index 95f7cac76f89..326b3db02c48 100644 --- a/drivers/i2c/busses/i2c-bcm-iproc.c +++ b/drivers/i2c/busses/i2c-bcm-iproc.c @@ -488,13 +488,7 @@ static int bcm_iproc_i2c_probe(struct platform_device *pdev) adap->dev.parent = &pdev->dev; adap->dev.of_node = pdev->dev.of_node; - ret = i2c_add_adapter(adap); - if (ret) { - dev_err(iproc_i2c->device, "failed to add adapter\n"); - return ret; - } - - return 0; + return i2c_add_adapter(adap); } static int bcm_iproc_i2c_remove(struct platform_device *pdev) diff --git a/drivers/i2c/busses/i2c-bcm-kona.c b/drivers/i2c/busses/i2c-bcm-kona.c index f98743277e3c..d8494f8c9bd4 100644 --- a/drivers/i2c/busses/i2c-bcm-kona.c +++ b/drivers/i2c/busses/i2c-bcm-kona.c @@ -858,10 +858,8 @@ static int bcm_kona_i2c_probe(struct platform_device *pdev) adap->dev.of_node = pdev->dev.of_node; rc = i2c_add_adapter(adap); - if (rc) { - dev_err(dev->device, "failed to add adapter\n"); + if (rc) return rc; - } dev_info(dev->device, "device registered successfully\n"); diff --git a/drivers/i2c/busses/i2c-bfin-twi.c b/drivers/i2c/busses/i2c-bfin-twi.c index 025686d41640..29d00c4f7824 100644 --- a/drivers/i2c/busses/i2c-bfin-twi.c +++ b/drivers/i2c/busses/i2c-bfin-twi.c @@ -685,10 +685,8 @@ static int i2c_bfin_twi_probe(struct platform_device *pdev) write_CONTROL(iface, read_CONTROL(iface) | TWI_ENA); rc = i2c_add_numbered_adapter(p_adap); - if (rc < 0) { - dev_err(&pdev->dev, "Can't add i2c adapter!\n"); + if (rc < 0) goto out_error; - } platform_set_drvdata(pdev, iface); diff --git a/drivers/i2c/busses/i2c-brcmstb.c b/drivers/i2c/busses/i2c-brcmstb.c index 385b57bfcb38..0652281662a8 100644 --- a/drivers/i2c/busses/i2c-brcmstb.c +++ b/drivers/i2c/busses/i2c-brcmstb.c @@ -648,10 +648,8 @@ static int brcmstb_i2c_probe(struct platform_device *pdev) adap->dev.parent = &pdev->dev; adap->dev.of_node = pdev->dev.of_node; rc = i2c_add_adapter(adap); - if (rc) { - dev_err(dev->device, "failed to add adapter\n"); + if (rc) goto probe_errorout; - } dev_info(dev->device, "%s@%dhz registered in %s mode\n", int_name ? int_name : " ", dev->clk_freq_hz, diff --git a/drivers/i2c/busses/i2c-cadence.c b/drivers/i2c/busses/i2c-cadence.c index 90bbd9f9dd8f..1cc1e79e958d 100644 --- a/drivers/i2c/busses/i2c-cadence.c +++ b/drivers/i2c/busses/i2c-cadence.c @@ -963,10 +963,8 @@ static int cdns_i2c_probe(struct platform_device *pdev) } ret = i2c_add_adapter(&id->adap); - if (ret < 0) { - dev_err(&pdev->dev, "reg adap failed: %d\n", ret); + if (ret < 0) goto err_clk_dis; - } /* * Cadence I2C controller has a bug wherein it generates diff --git a/drivers/i2c/busses/i2c-cpm.c b/drivers/i2c/busses/i2c-cpm.c index ee57c1e865e2..d89bde2c5da2 100644 --- a/drivers/i2c/busses/i2c-cpm.c +++ b/drivers/i2c/busses/i2c-cpm.c @@ -665,10 +665,8 @@ static int cpm_i2c_probe(struct platform_device *ofdev) cpm->adap.nr = (data && len == 4) ? be32_to_cpup(data) : -1; result = i2c_add_numbered_adapter(&cpm->adap); - if (result < 0) { - dev_err(&ofdev->dev, "Unable to register with I2C\n"); + if (result < 0) goto out_shut; - } dev_dbg(&ofdev->dev, "hw routines for %s registered.\n", cpm->adap.name); diff --git a/drivers/i2c/busses/i2c-cros-ec-tunnel.c b/drivers/i2c/busses/i2c-cros-ec-tunnel.c index 2d5ff86398d0..9b36a7b3befd 100644 --- a/drivers/i2c/busses/i2c-cros-ec-tunnel.c +++ b/drivers/i2c/busses/i2c-cros-ec-tunnel.c @@ -281,10 +281,8 @@ static int ec_i2c_probe(struct platform_device *pdev) bus->adap.retries = I2C_MAX_RETRIES; err = i2c_add_adapter(&bus->adap); - if (err) { - dev_err(dev, "cannot register i2c adapter\n"); + if (err) return err; - } platform_set_drvdata(pdev, bus); return err; diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c index a8bdcb5292f5..9e7ef5cf5d49 100644 --- a/drivers/i2c/busses/i2c-davinci.c +++ b/drivers/i2c/busses/i2c-davinci.c @@ -846,10 +846,8 @@ static int davinci_i2c_probe(struct platform_device *pdev) adap->nr = pdev->id; r = i2c_add_numbered_adapter(adap); - if (r) { - dev_err(&pdev->dev, "failure adding adapter\n"); + if (r) goto err_unuse_clocks; - } return 0; diff --git a/drivers/i2c/busses/i2c-diolan-u2c.c b/drivers/i2c/busses/i2c-diolan-u2c.c index b19a310bf9b3..f718ee4e3332 100644 --- a/drivers/i2c/busses/i2c-diolan-u2c.c +++ b/drivers/i2c/busses/i2c-diolan-u2c.c @@ -487,10 +487,8 @@ static int diolan_u2c_probe(struct usb_interface *interface, /* and finally attach to i2c layer */ ret = i2c_add_adapter(&dev->adapter); - if (ret < 0) { - dev_err(&interface->dev, "failed to add I2C adapter\n"); + if (ret < 0) goto error_free; - } dev_dbg(&interface->dev, "connected " DRIVER_NAME "\n"); diff --git a/drivers/i2c/busses/i2c-dln2.c b/drivers/i2c/busses/i2c-dln2.c index f2eb4f76591f..8acda2aa1558 100644 --- a/drivers/i2c/busses/i2c-dln2.c +++ b/drivers/i2c/busses/i2c-dln2.c @@ -228,10 +228,8 @@ static int dln2_i2c_probe(struct platform_device *pdev) /* and finally attach to i2c layer */ ret = i2c_add_adapter(&dln2->adapter); - if (ret < 0) { - dev_err(dev, "failed to add I2C adapter: %d\n", ret); + if (ret < 0) goto out_disable; - } return 0; diff --git a/drivers/i2c/busses/i2c-efm32.c b/drivers/i2c/busses/i2c-efm32.c index e253598d764c..aa336ba89aa3 100644 --- a/drivers/i2c/busses/i2c-efm32.c +++ b/drivers/i2c/busses/i2c-efm32.c @@ -438,7 +438,6 @@ static int efm32_i2c_probe(struct platform_device *pdev) ret = i2c_add_adapter(&ddata->adapter); if (ret) { - dev_err(&pdev->dev, "failed to add i2c adapter (%d)\n", ret); free_irq(ddata->irq, ddata); err_disable_clk: diff --git a/drivers/i2c/busses/i2c-exynos5.c b/drivers/i2c/busses/i2c-exynos5.c index c0e3ada02876..bea607149972 100644 --- a/drivers/i2c/busses/i2c-exynos5.c +++ b/drivers/i2c/busses/i2c-exynos5.c @@ -796,10 +796,8 @@ static int exynos5_i2c_probe(struct platform_device *pdev) exynos5_i2c_reset(i2c); ret = i2c_add_adapter(&i2c->adap); - if (ret < 0) { - dev_err(&pdev->dev, "failed to add bus to i2c core\n"); + if (ret < 0) goto err_clk; - } platform_set_drvdata(pdev, i2c); diff --git a/drivers/i2c/busses/i2c-hix5hd2.c b/drivers/i2c/busses/i2c-hix5hd2.c index 7c6966434ee7..ae7f3180f7e8 100644 --- a/drivers/i2c/busses/i2c-hix5hd2.c +++ b/drivers/i2c/busses/i2c-hix5hd2.c @@ -478,10 +478,8 @@ static int hix5hd2_i2c_probe(struct platform_device *pdev) pm_runtime_enable(priv->dev); ret = i2c_add_adapter(&priv->adap); - if (ret < 0) { - dev_err(&pdev->dev, "failed to add bus to i2c core\n"); + if (ret < 0) goto err_runtime; - } return ret; diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index 5ef9b733d153..22a0ed4de80d 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -1613,7 +1613,6 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id) "SMBus I801 adapter at %04lx", priv->smba); err = i2c_add_adapter(&priv->adapter); if (err) { - dev_err(&dev->dev, "Failed to add SMBus adapter\n"); i801_acpi_remove(priv); return err; } diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c index cdaa7be2cd1b..412b91d255ad 100644 --- a/drivers/i2c/busses/i2c-ibm_iic.c +++ b/drivers/i2c/busses/i2c-ibm_iic.c @@ -751,10 +751,8 @@ static int iic_probe(struct platform_device *ofdev) adap->timeout = HZ; ret = i2c_add_adapter(adap); - if (ret < 0) { - dev_err(&ofdev->dev, "failed to register i2c adapter\n"); + if (ret < 0) goto error_cleanup; - } dev_info(&ofdev->dev, "using %s mode\n", dev->fast_mode ? "fast (400 kHz)" : "standard (100 kHz)"); diff --git a/drivers/i2c/busses/i2c-img-scb.c b/drivers/i2c/busses/i2c-img-scb.c index ea20425b6972..db8e8b40569d 100644 --- a/drivers/i2c/busses/i2c-img-scb.c +++ b/drivers/i2c/busses/i2c-img-scb.c @@ -1394,10 +1394,8 @@ static int img_i2c_probe(struct platform_device *pdev) goto disable_clk; ret = i2c_add_numbered_adapter(&i2c->adap); - if (ret < 0) { - dev_err(&pdev->dev, "failed to add adapter\n"); + if (ret < 0) goto disable_clk; - } return 0; diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c index 1844bc9f7cd5..cb11eee95673 100644 --- a/drivers/i2c/busses/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c @@ -1129,10 +1129,8 @@ static int i2c_imx_probe(struct platform_device *pdev) /* Add I2C adapter */ ret = i2c_add_numbered_adapter(&i2c_imx->adapter); - if (ret < 0) { - dev_err(&pdev->dev, "registration failed\n"); + if (ret < 0) goto rpm_disable; - } pm_runtime_mark_last_busy(&pdev->dev); pm_runtime_put_autosuspend(&pdev->dev); diff --git a/drivers/i2c/busses/i2c-isch.c b/drivers/i2c/busses/i2c-isch.c index c2f25f19d76f..0cf1379f4e80 100644 --- a/drivers/i2c/busses/i2c-isch.c +++ b/drivers/i2c/busses/i2c-isch.c @@ -288,10 +288,8 @@ static int smbus_sch_probe(struct platform_device *dev) "SMBus SCH adapter at %04x", sch_smba); retval = i2c_add_adapter(&sch_adapter); - if (retval) { - dev_err(&dev->dev, "Couldn't register adapter!\n"); + if (retval) sch_smba = 0; - } return retval; } diff --git a/drivers/i2c/busses/i2c-ismt.c b/drivers/i2c/busses/i2c-ismt.c index 1c8707710098..f573448d2132 100644 --- a/drivers/i2c/busses/i2c-ismt.c +++ b/drivers/i2c/busses/i2c-ismt.c @@ -922,10 +922,8 @@ ismt_probe(struct pci_dev *pdev, const struct pci_device_id *id) return err; err = i2c_add_adapter(&priv->adapter); - if (err) { - dev_err(&pdev->dev, "Failed to add SMBus iSMT adapter\n"); + if (err) return -ENODEV; - } return 0; } diff --git a/drivers/i2c/busses/i2c-jz4780.c b/drivers/i2c/busses/i2c-jz4780.c index cd9872594fe2..b8ea62105f42 100644 --- a/drivers/i2c/busses/i2c-jz4780.c +++ b/drivers/i2c/busses/i2c-jz4780.c @@ -798,10 +798,8 @@ static int jz4780_i2c_probe(struct platform_device *pdev) goto err; ret = i2c_add_adapter(&i2c->adap); - if (ret < 0) { - dev_err(&pdev->dev, "Failed to add bus\n"); + if (ret < 0) goto err; - } return 0; diff --git a/drivers/i2c/busses/i2c-lpc2k.c b/drivers/i2c/busses/i2c-lpc2k.c index 586a15205e61..9b1fef455a89 100644 --- a/drivers/i2c/busses/i2c-lpc2k.c +++ b/drivers/i2c/busses/i2c-lpc2k.c @@ -432,10 +432,8 @@ static int i2c_lpc2k_probe(struct platform_device *pdev) i2c->adap.dev.of_node = pdev->dev.of_node; ret = i2c_add_adapter(&i2c->adap); - if (ret < 0) { - dev_err(&pdev->dev, "failed to add adapter!\n"); + if (ret < 0) goto fail_clk; - } dev_info(&pdev->dev, "LPC2K I2C adapter\n"); diff --git a/drivers/i2c/busses/i2c-meson.c b/drivers/i2c/busses/i2c-meson.c index 76e28980904f..8570e6dbd0db 100644 --- a/drivers/i2c/busses/i2c-meson.c +++ b/drivers/i2c/busses/i2c-meson.c @@ -453,7 +453,6 @@ static int meson_i2c_probe(struct platform_device *pdev) ret = i2c_add_adapter(&i2c->adap); if (ret < 0) { - dev_err(&pdev->dev, "can't register adapter\n"); clk_unprepare(i2c->clk); return ret; } diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c index 48ecffecc0ed..565a49a0c564 100644 --- a/drivers/i2c/busses/i2c-mpc.c +++ b/drivers/i2c/busses/i2c-mpc.c @@ -737,10 +737,8 @@ static int fsl_i2c_probe(struct platform_device *op) i2c->adap.dev.of_node = of_node_get(op->dev.of_node); result = i2c_add_adapter(&i2c->adap); - if (result < 0) { - dev_err(i2c->dev, "failed to add adapter\n"); + if (result < 0) goto fail_add; - } return result; diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c index d9373e60be8a..4a7d9bc2142b 100644 --- a/drivers/i2c/busses/i2c-mt65xx.c +++ b/drivers/i2c/busses/i2c-mt65xx.c @@ -786,10 +786,8 @@ static int mtk_i2c_probe(struct platform_device *pdev) i2c_set_adapdata(&i2c->adap, i2c); ret = i2c_add_adapter(&i2c->adap); - if (ret) { - dev_err(&pdev->dev, "Failed to add i2c bus to i2c core\n"); + if (ret) return ret; - } platform_set_drvdata(pdev, i2c); diff --git a/drivers/i2c/busses/i2c-mxs.c b/drivers/i2c/busses/i2c-mxs.c index 033846cdf266..5738556b6aac 100644 --- a/drivers/i2c/busses/i2c-mxs.c +++ b/drivers/i2c/busses/i2c-mxs.c @@ -868,7 +868,6 @@ static int mxs_i2c_probe(struct platform_device *pdev) i2c_set_adapdata(adap, i2c); err = i2c_add_numbered_adapter(adap); if (err) { - dev_err(dev, "Failed to add adapter (%d)\n", err); writel(MXS_I2C_CTRL0_SFTRST, i2c->regs + MXS_I2C_CTRL0_SET); return err; diff --git a/drivers/i2c/busses/i2c-nforce2.c b/drivers/i2c/busses/i2c-nforce2.c index 42fcc9458432..374b35e7e450 100644 --- a/drivers/i2c/busses/i2c-nforce2.c +++ b/drivers/i2c/busses/i2c-nforce2.c @@ -366,7 +366,6 @@ static int nforce2_probe_smb(struct pci_dev *dev, int bar, int alt_reg, error = i2c_add_adapter(&smbus->adapter); if (error) { - dev_err(&smbus->adapter.dev, "Failed to register adapter.\n"); release_region(smbus->base, smbus->size); return error; } diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c index bcd17e8cbcb4..da6609d62848 100644 --- a/drivers/i2c/busses/i2c-nomadik.c +++ b/drivers/i2c/busses/i2c-nomadik.c @@ -1046,10 +1046,8 @@ static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id) adap->name, dev->virtbase); ret = i2c_add_adapter(adap); - if (ret) { - dev_err(&adev->dev, "failed to add adapter\n"); + if (ret) goto err_no_adap; - } pm_runtime_put(&adev->dev); diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c index ac88a524143e..34f1889a4073 100644 --- a/drivers/i2c/busses/i2c-ocores.c +++ b/drivers/i2c/busses/i2c-ocores.c @@ -494,10 +494,8 @@ static int ocores_i2c_probe(struct platform_device *pdev) /* add i2c adapter to i2c tree */ ret = i2c_add_adapter(&i2c->adap); - if (ret) { - dev_err(&pdev->dev, "Failed to add adapter\n"); + if (ret) goto err_clk; - } /* add in known devices to the bus */ if (pdata) { diff --git a/drivers/i2c/busses/i2c-octeon.c b/drivers/i2c/busses/i2c-octeon.c index 30ae35146723..b75d2da79b27 100644 --- a/drivers/i2c/busses/i2c-octeon.c +++ b/drivers/i2c/busses/i2c-octeon.c @@ -1213,10 +1213,8 @@ static int octeon_i2c_probe(struct platform_device *pdev) platform_set_drvdata(pdev, i2c); result = i2c_add_adapter(&i2c->adap); - if (result < 0) { - dev_err(i2c->dev, "failed to add adapter\n"); + if (result < 0) goto out; - } dev_info(i2c->dev, "probed\n"); return 0; diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index ab1279b8e240..c7da0c42baee 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -1425,10 +1425,8 @@ omap_i2c_probe(struct platform_device *pdev) /* i2c device drivers may be active on return from add_adapter() */ adap->nr = pdev->id; r = i2c_add_numbered_adapter(adap); - if (r) { - dev_err(omap->dev, "failure adding adapter\n"); + if (r) goto err_unuse_clocks; - } dev_info(omap->dev, "bus %d rev%d.%d at %d kHz\n", adap->nr, major, minor, omap->speed); diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c index 23d1c167b5d7..c2268cdf38e8 100644 --- a/drivers/i2c/busses/i2c-piix4.c +++ b/drivers/i2c/busses/i2c-piix4.c @@ -694,7 +694,6 @@ static int piix4_add_adapter(struct pci_dev *dev, unsigned short smba, retval = i2c_add_adapter(adap); if (retval) { - dev_err(&dev->dev, "Couldn't register adapter!\n"); kfree(adapdata); kfree(adap); release_region(smba, SMBIOSIZE); diff --git a/drivers/i2c/busses/i2c-pmcmsp.c b/drivers/i2c/busses/i2c-pmcmsp.c index 2c40edbf6224..217c78711d65 100644 --- a/drivers/i2c/busses/i2c-pmcmsp.c +++ b/drivers/i2c/busses/i2c-pmcmsp.c @@ -329,10 +329,8 @@ static int pmcmsptwi_probe(struct platform_device *pldev) i2c_set_adapdata(&pmcmsptwi_adapter, &pmcmsptwi_data); rc = i2c_add_adapter(&pmcmsptwi_adapter); - if (rc) { - dev_err(&pldev->dev, "Unable to register I2C adapter\n"); + if (rc) goto ret_unmap; - } return 0; diff --git a/drivers/i2c/busses/i2c-pnx.c b/drivers/i2c/busses/i2c-pnx.c index 7ea67aa46fb7..fd5f9d2bf6d9 100644 --- a/drivers/i2c/busses/i2c-pnx.c +++ b/drivers/i2c/busses/i2c-pnx.c @@ -714,10 +714,8 @@ static int i2c_pnx_probe(struct platform_device *pdev) /* Register this adapter with the I2C subsystem */ ret = i2c_add_numbered_adapter(&alg_data->adapter); - if (ret < 0) { - dev_err(&pdev->dev, "I2C: Failed to add bus\n"); + if (ret < 0) goto out_clock; - } dev_dbg(&pdev->dev, "%s: Master at %#8x, irq %d.\n", alg_data->adapter.name, res->start, alg_data->irq); diff --git a/drivers/i2c/busses/i2c-puv3.c b/drivers/i2c/busses/i2c-puv3.c index 82b6f02544da..0c8b1571886d 100644 --- a/drivers/i2c/busses/i2c-puv3.c +++ b/drivers/i2c/busses/i2c-puv3.c @@ -212,11 +212,8 @@ static int puv3_i2c_probe(struct platform_device *pdev) adapter->nr = pdev->id; rc = i2c_add_numbered_adapter(adapter); - if (rc) { - dev_err(&pdev->dev, "Adapter '%s' registration failed\n", - adapter->name); + if (rc) goto fail_add_adapter; - } dev_info(&pdev->dev, "PKUnity v3 i2c bus adapter.\n"); return 0; diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c index 0d351954db02..e28b825b0433 100644 --- a/drivers/i2c/busses/i2c-pxa.c +++ b/drivers/i2c/busses/i2c-pxa.c @@ -1292,10 +1292,8 @@ static int i2c_pxa_probe(struct platform_device *dev) #endif ret = i2c_add_numbered_adapter(&i2c->adap); - if (ret < 0) { - dev_err(&dev->dev, "failed to add bus: %d\n", ret); + if (ret < 0) goto ereqirq; - } platform_set_drvdata(dev, i2c); diff --git a/drivers/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c index 52407f3c9e1c..400e344704d2 100644 --- a/drivers/i2c/busses/i2c-rcar.c +++ b/drivers/i2c/busses/i2c-rcar.c @@ -875,10 +875,8 @@ static int rcar_i2c_probe(struct platform_device *pdev) platform_set_drvdata(pdev, priv); ret = i2c_add_numbered_adapter(adap); - if (ret < 0) { - dev_err(dev, "reg adap failed: %d\n", ret); + if (ret < 0) goto out_pm_disable; - } dev_info(dev, "probed\n"); diff --git a/drivers/i2c/busses/i2c-riic.c b/drivers/i2c/busses/i2c-riic.c index d7e3af671543..6263ea82d6ac 100644 --- a/drivers/i2c/busses/i2c-riic.c +++ b/drivers/i2c/busses/i2c-riic.c @@ -383,10 +383,8 @@ static int riic_i2c_probe(struct platform_device *pdev) ret = i2c_add_adapter(adap); - if (ret) { - dev_err(&pdev->dev, "failed to add adapter\n"); + if (ret) return ret; - } platform_set_drvdata(pdev, riic); diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c index 2bc8b01153d6..3b87afe82f63 100644 --- a/drivers/i2c/busses/i2c-rk3x.c +++ b/drivers/i2c/busses/i2c-rk3x.c @@ -1303,10 +1303,8 @@ static int rk3x_i2c_probe(struct platform_device *pdev) rk3x_i2c_adapt_div(i2c, clk_rate); ret = i2c_add_adapter(&i2c->adap); - if (ret < 0) { - dev_err(&pdev->dev, "Could not register adapter\n"); + if (ret < 0) goto err_clk_notifier; - } dev_info(&pdev->dev, "Initialized RK3xxx I2C bus at %p\n", i2c->regs); diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c index 38dc1cacfd8b..499af26e736e 100644 --- a/drivers/i2c/busses/i2c-s3c2410.c +++ b/drivers/i2c/busses/i2c-s3c2410.c @@ -1215,7 +1215,6 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) ret = i2c_add_numbered_adapter(&i2c->adap); if (ret < 0) { - dev_err(&pdev->dev, "failed to add bus to i2c core\n"); pm_runtime_disable(&pdev->dev); s3c24xx_i2c_deregister_cpufreq(i2c); clk_unprepare(i2c->clk); diff --git a/drivers/i2c/busses/i2c-sh7760.c b/drivers/i2c/busses/i2c-sh7760.c index 24968384b401..c2005c789d2b 100644 --- a/drivers/i2c/busses/i2c-sh7760.c +++ b/drivers/i2c/busses/i2c-sh7760.c @@ -510,10 +510,8 @@ static int sh7760_i2c_probe(struct platform_device *pdev) } ret = i2c_add_numbered_adapter(&id->adap); - if (ret < 0) { - dev_err(&pdev->dev, "reg adap failed: %d\n", ret); + if (ret < 0) goto out4; - } platform_set_drvdata(pdev, id); diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c index 6fb3e2645992..50f276e8d179 100644 --- a/drivers/i2c/busses/i2c-sh_mobile.c +++ b/drivers/i2c/busses/i2c-sh_mobile.c @@ -981,7 +981,6 @@ static int sh_mobile_i2c_probe(struct platform_device *dev) ret = i2c_add_numbered_adapter(adap); if (ret < 0) { sh_mobile_i2c_release_dma(pd); - dev_err(&dev->dev, "cannot add numbered adapter\n"); return ret; } diff --git a/drivers/i2c/busses/i2c-sirf.c b/drivers/i2c/busses/i2c-sirf.c index 792a42bdd335..95e81d0f72b4 100644 --- a/drivers/i2c/busses/i2c-sirf.c +++ b/drivers/i2c/busses/i2c-sirf.c @@ -387,10 +387,8 @@ static int i2c_sirfsoc_probe(struct platform_device *pdev) writel(regval, siic->base + SIRFSOC_I2C_SDA_DELAY); err = i2c_add_numbered_adapter(adap); - if (err < 0) { - dev_err(&pdev->dev, "Can't add new i2c adapter\n"); + if (err < 0) goto out; - } clk_disable(clk); diff --git a/drivers/i2c/busses/i2c-st.c b/drivers/i2c/busses/i2c-st.c index 944ec4205084..1371547ce1a3 100644 --- a/drivers/i2c/busses/i2c-st.c +++ b/drivers/i2c/busses/i2c-st.c @@ -874,10 +874,8 @@ static int st_i2c_probe(struct platform_device *pdev) init_completion(&i2c_dev->complete); ret = i2c_add_adapter(adap); - if (ret) { - dev_err(&pdev->dev, "Failed to add adapter\n"); + if (ret) return ret; - } platform_set_drvdata(pdev, i2c_dev); diff --git a/drivers/i2c/busses/i2c-stu300.c b/drivers/i2c/busses/i2c-stu300.c index 460c134832ac..dc63236b45b2 100644 --- a/drivers/i2c/busses/i2c-stu300.c +++ b/drivers/i2c/busses/i2c-stu300.c @@ -920,11 +920,8 @@ static int stu300_probe(struct platform_device *pdev) /* i2c device drivers may be active on return from add_adapter() */ ret = i2c_add_numbered_adapter(adap); - if (ret) { - dev_err(&pdev->dev, "failure adding ST Micro DDC " - "I2C adapter\n"); + if (ret) return ret; - } platform_set_drvdata(pdev, dev); dev_info(&pdev->dev, "ST DDC I2C @ %p, irq %d\n", diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index b126dbaa47e3..d9979da11485 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -932,10 +932,8 @@ static int tegra_i2c_probe(struct platform_device *pdev) i2c_dev->adapter.dev.of_node = pdev->dev.of_node; ret = i2c_add_numbered_adapter(&i2c_dev->adapter); - if (ret) { - dev_err(&pdev->dev, "Failed to add I2C adapter\n"); + if (ret) goto disable_div_clk; - } return 0; diff --git a/drivers/i2c/busses/i2c-wmt.c b/drivers/i2c/busses/i2c-wmt.c index e1e3a85596c5..fbd0fd59f312 100644 --- a/drivers/i2c/busses/i2c-wmt.c +++ b/drivers/i2c/busses/i2c-wmt.c @@ -432,10 +432,8 @@ static int wmt_i2c_probe(struct platform_device *pdev) } err = i2c_add_adapter(adap); - if (err) { - dev_err(&pdev->dev, "failed to add adapter\n"); + if (err) return err; - } platform_set_drvdata(pdev, i2c_dev); diff --git a/drivers/i2c/busses/i2c-xgene-slimpro.c b/drivers/i2c/busses/i2c-xgene-slimpro.c index 4233f5695352..263685c7a512 100644 --- a/drivers/i2c/busses/i2c-xgene-slimpro.c +++ b/drivers/i2c/busses/i2c-xgene-slimpro.c @@ -418,7 +418,6 @@ static int xgene_slimpro_i2c_probe(struct platform_device *pdev) i2c_set_adapdata(adapter, ctx); rc = i2c_add_adapter(adapter); if (rc) { - dev_err(&pdev->dev, "Adapter registeration failed\n"); mbox_free_channel(ctx->mbox_chan); return rc; } diff --git a/drivers/i2c/busses/i2c-xiic.c b/drivers/i2c/busses/i2c-xiic.c index 74f54f2f471f..66bce3b311a1 100644 --- a/drivers/i2c/busses/i2c-xiic.c +++ b/drivers/i2c/busses/i2c-xiic.c @@ -804,7 +804,6 @@ static int xiic_i2c_probe(struct platform_device *pdev) /* add i2c adapter to i2c tree */ ret = i2c_add_adapter(&i2c->adap); if (ret) { - dev_err(&pdev->dev, "Failed to add adapter\n"); xiic_deinit(i2c); goto err_clk_dis; } diff --git a/drivers/i2c/busses/i2c-xlp9xx.c b/drivers/i2c/busses/i2c-xlp9xx.c index 55a7bef1b2e1..2a972ed7aa0d 100644 --- a/drivers/i2c/busses/i2c-xlp9xx.c +++ b/drivers/i2c/busses/i2c-xlp9xx.c @@ -400,10 +400,8 @@ static int xlp9xx_i2c_probe(struct platform_device *pdev) i2c_set_adapdata(&priv->adapter, priv); err = i2c_add_adapter(&priv->adapter); - if (err) { - dev_err(&pdev->dev, "failed to add I2C adapter!\n"); + if (err) return err; - } platform_set_drvdata(pdev, priv); dev_dbg(&pdev->dev, "I2C bus:%d added\n", priv->adapter.nr); diff --git a/drivers/i2c/busses/i2c-xlr.c b/drivers/i2c/busses/i2c-xlr.c index 613c3a4f2c51..0968f59b6df5 100644 --- a/drivers/i2c/busses/i2c-xlr.c +++ b/drivers/i2c/busses/i2c-xlr.c @@ -432,10 +432,8 @@ static int xlr_i2c_probe(struct platform_device *pdev) i2c_set_adapdata(&priv->adap, priv); ret = i2c_add_numbered_adapter(&priv->adap); - if (ret < 0) { - dev_err(&priv->adap.dev, "Failed to add i2c bus.\n"); + if (ret < 0) return ret; - } platform_set_drvdata(pdev, priv); dev_info(&priv->adap.dev, "Added I2C Bus.\n"); From 56025e7bc2079cda92643b43bf26991d3d09717d Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Tue, 9 Aug 2016 22:11:40 +0200 Subject: [PATCH 02/71] i2c: uniphier{-f}: don't print error when adding adapter fails The core will do this for us now. Signed-off-by: Wolfram Sang Acked-by: Masahiro Yamada Acked-by: Guenter Roeck Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-uniphier-f.c | 5 ----- drivers/i2c/busses/i2c-uniphier.c | 5 ----- 2 files changed, 10 deletions(-) diff --git a/drivers/i2c/busses/i2c-uniphier-f.c b/drivers/i2c/busses/i2c-uniphier-f.c index aeead0d27d10..35608531fe07 100644 --- a/drivers/i2c/busses/i2c-uniphier-f.c +++ b/drivers/i2c/busses/i2c-uniphier-f.c @@ -550,11 +550,6 @@ static int uniphier_fi2c_probe(struct platform_device *pdev) } ret = i2c_add_adapter(&priv->adap); - if (ret) { - dev_err(dev, "failed to add I2C adapter\n"); - goto err; - } - err: if (ret) clk_disable_unprepare(priv->clk); diff --git a/drivers/i2c/busses/i2c-uniphier.c b/drivers/i2c/busses/i2c-uniphier.c index 475a5eb514e2..d6e612a0e02a 100644 --- a/drivers/i2c/busses/i2c-uniphier.c +++ b/drivers/i2c/busses/i2c-uniphier.c @@ -407,11 +407,6 @@ static int uniphier_i2c_probe(struct platform_device *pdev) } ret = i2c_add_adapter(&priv->adap); - if (ret) { - dev_err(dev, "failed to add I2C adapter\n"); - goto err; - } - err: if (ret) clk_disable_unprepare(priv->clk); From 00f0ea70d2b82b7d7afeb1bdedc9169eb8ea6675 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Fri, 12 Aug 2016 13:32:57 +0200 Subject: [PATCH 03/71] eeprom: at24: check if the chip is functional in probe() The at24 driver doesn't check if the chip is functional in its probe function. This leads to instantiating devices that are not physically present. For example the cape EEPROMs for BeagleBone Black are defined in the device tree at four addresses on i2c2, but normally only one of them is present. If the userspace doesn't know the location in advance, it will need to check if reading the nvmem attributes fails to determine which EEPROM is actually there. Try to read a single byte in probe() and bail-out with -ENODEV if the read fails. Signed-off-by: Bartosz Golaszewski Signed-off-by: Wolfram Sang --- drivers/misc/eeprom/at24.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c index 3cdf8e1ca0ad..051b14766ef9 100644 --- a/drivers/misc/eeprom/at24.c +++ b/drivers/misc/eeprom/at24.c @@ -593,6 +593,7 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id) struct at24_data *at24; int err; unsigned i, num_addresses; + u8 test_byte; if (client->dev.platform_data) { chip = *(struct at24_platform_data *)client->dev.platform_data; @@ -743,6 +744,18 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id) } } + i2c_set_clientdata(client, at24); + + /* + * Perform a one-byte test read to verify that the + * chip is functional. + */ + err = at24_read(at24, 0, &test_byte, 1); + if (err) { + err = -ENODEV; + goto err_clients; + } + at24->nvmem_config.name = dev_name(&client->dev); at24->nvmem_config.dev = &client->dev; at24->nvmem_config.read_only = !writable; @@ -764,8 +777,6 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id) goto err_clients; } - i2c_set_clientdata(client, at24); - dev_info(&client->dev, "%u byte %s EEPROM, %s, %u bytes/write\n", chip.byte_len, client->name, writable ? "writable" : "read-only", at24->write_max); From fb79e09a74faf39fbeee975e0ead442b7b7f6aac Mon Sep 17 00:00:00 2001 From: Peter Rosin Date: Wed, 29 Jun 2016 15:04:03 +0200 Subject: [PATCH 04/71] i2c: add i2c_trylock_bus wrapper, use it This unifies usage with i2c_lock_bus and i2c_unlock_bus, and paves the way for the next patch which looks a bit saner with this preparatory work taken care of beforehand. Signed-off-by: Peter Rosin Signed-off-by: Wolfram Sang --- drivers/i2c/i2c-core.c | 2 +- drivers/i2c/i2c-mux.c | 4 ++-- include/linux/i2c.h | 14 ++++++++++++++ 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index da3a02ef4a31..56e50ca905ba 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -2459,7 +2459,7 @@ int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) #endif if (in_atomic() || irqs_disabled()) { - ret = adap->trylock_bus(adap, I2C_LOCK_SEGMENT); + ret = i2c_trylock_bus(adap, I2C_LOCK_SEGMENT); if (!ret) /* I2C activity is ongoing. */ return -EAGAIN; diff --git a/drivers/i2c/i2c-mux.c b/drivers/i2c/i2c-mux.c index 8eee98634cda..764f195795e4 100644 --- a/drivers/i2c/i2c-mux.c +++ b/drivers/i2c/i2c-mux.c @@ -159,7 +159,7 @@ static int i2c_mux_trylock_bus(struct i2c_adapter *adapter, unsigned int flags) return 0; /* mux_lock not locked, failure */ if (!(flags & I2C_LOCK_ROOT_ADAPTER)) return 1; /* we only want mux_lock, success */ - if (parent->trylock_bus(parent, flags)) + if (i2c_trylock_bus(parent, flags)) return 1; /* parent locked too, success */ rt_mutex_unlock(&parent->mux_lock); return 0; /* parent not locked, failure */ @@ -193,7 +193,7 @@ static int i2c_parent_trylock_bus(struct i2c_adapter *adapter, if (!rt_mutex_trylock(&parent->mux_lock)) return 0; /* mux_lock not locked, failure */ - if (parent->trylock_bus(parent, flags)) + if (i2c_trylock_bus(parent, flags)) return 1; /* parent locked too, success */ rt_mutex_unlock(&parent->mux_lock); return 0; /* parent not locked, failure */ diff --git a/include/linux/i2c.h b/include/linux/i2c.h index fffdc270ca18..c1f60a345db7 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -600,6 +600,20 @@ i2c_lock_bus(struct i2c_adapter *adapter, unsigned int flags) adapter->lock_bus(adapter, flags); } +/** + * i2c_trylock_bus - Try to get exclusive access to an I2C bus segment + * @adapter: Target I2C bus segment + * @flags: I2C_LOCK_ROOT_ADAPTER tries to locks the root i2c adapter, + * I2C_LOCK_SEGMENT tries to lock only this branch in the adapter tree + * + * Return: true if the I2C bus segment is locked, false otherwise + */ +static inline int +i2c_trylock_bus(struct i2c_adapter *adapter, unsigned int flags) +{ + return adapter->trylock_bus(adapter, flags); +} + /** * i2c_unlock_bus - Release exclusive access to an I2C bus segment * @adapter: Target I2C bus segment From 374f8436ff3a450a2f95a0c1910a0b17212cede1 Mon Sep 17 00:00:00 2001 From: Peter Rosin Date: Fri, 8 Jul 2016 12:13:12 +0200 Subject: [PATCH 05/71] dt-bindings: i2c: add support for 'i2c-mux' subnode Similar to the new optional 'i2c-bus' subnode from Jon Hunter, this adds an optional 'i2c-mux' subnode, for similar reasons. I.e. it is bad of the i2c mux core to assume that any subnode of an i2c mux device is a potential (when the 'reg' property matches) i2c-mux child bus, given that i2c mux devices might do more than mux i2c traffic. So, if an 'i2c-mux' subnode is present, dictate that all i2c-mux child buses exist beneath that subnode. Acked-by: Rob Herring Reviewed-by: Wolfram Sang Signed-off-by: Peter Rosin --- .../devicetree/bindings/i2c/i2c-mux.txt | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/Documentation/devicetree/bindings/i2c/i2c-mux.txt b/Documentation/devicetree/bindings/i2c/i2c-mux.txt index af84cce5cd7b..212e6779dc5c 100644 --- a/Documentation/devicetree/bindings/i2c/i2c-mux.txt +++ b/Documentation/devicetree/bindings/i2c/i2c-mux.txt @@ -2,19 +2,32 @@ Common i2c bus multiplexer/switch properties. An i2c bus multiplexer/switch will have several child busses that are numbered uniquely in a device dependent manner. The nodes for an i2c bus -multiplexer/switch will have one child node for each child -bus. +multiplexer/switch will have one child node for each child bus. -Required properties: +Optional properties: +- #address-cells = <1>; + This property is required is the i2c-mux child node does not exist. + +- #size-cells = <0>; + This property is required is the i2c-mux child node does not exist. + +- i2c-mux + For i2c multiplexers/switches that have child nodes that are a mixture + of both i2c child busses and other child nodes, the 'i2c-mux' subnode + can be used for populating the i2c child busses. If an 'i2c-mux' + subnode is present, only subnodes of this will be considered as i2c + child busses. + +Required properties for the i2c-mux child node: - #address-cells = <1>; - #size-cells = <0>; -Required properties for child nodes: +Required properties for i2c child bus nodes: - #address-cells = <1>; - #size-cells = <0>; - reg : The sub-bus number. -Optional properties for child nodes: +Optional properties for i2c child bus nodes: - Other properties specific to the multiplexer/switch hardware. - Child nodes conforming to i2c bus binding From e8813c15be0a9e7f2c79c58d3329d92bcf056ecc Mon Sep 17 00:00:00 2001 From: Peter Rosin Date: Fri, 8 Jul 2016 12:12:17 +0200 Subject: [PATCH 06/71] dt-bindings: i2c: add support for 'i2c-arb' subnode This gets rid of the need for a pointless 'reg' property for i2c arbitrators. I.e. this new and more compact style some-arbitrator { i2c-arb { #address-cells = <1>; #size-cells = <0>; some-i2c-device@50 { reg = <0x50>; }; }; }; instead of the old some-arbitrator { #address-cells = <1>; #size-cells = <0>; i2c@0 { reg = <0>; #address-cells = <1>; #size-cells = <0>; some-i2c-device@50 { reg = <0x50>; }; }; }; Acked-by: Rob Herring Reviewed-by: Wolfram Sang Signed-off-by: Peter Rosin --- .../bindings/i2c/i2c-arb-gpio-challenge.txt | 8 ++--- .../devicetree/bindings/i2c/i2c-arb.txt | 35 +++++++++++++++++++ MAINTAINERS | 1 + 3 files changed, 38 insertions(+), 6 deletions(-) create mode 100644 Documentation/devicetree/bindings/i2c/i2c-arb.txt diff --git a/Documentation/devicetree/bindings/i2c/i2c-arb-gpio-challenge.txt b/Documentation/devicetree/bindings/i2c/i2c-arb-gpio-challenge.txt index 71191ff0e781..248a155414c2 100644 --- a/Documentation/devicetree/bindings/i2c/i2c-arb-gpio-challenge.txt +++ b/Documentation/devicetree/bindings/i2c/i2c-arb-gpio-challenge.txt @@ -44,8 +44,7 @@ Required properties: - our-claim-gpio: The GPIO that we use to claim the bus. - their-claim-gpios: The GPIOs that the other sides use to claim the bus. Note that some implementations may only support a single other master. -- Standard I2C mux properties. See i2c-mux.txt in this directory. -- Single I2C child bus node at reg 0. See i2c-mux.txt in this directory. +- I2C arbitration bus node. See i2c-arb.txt in this directory. Optional properties: - slew-delay-us: microseconds to wait for a GPIO to go high. Default is 10 us. @@ -63,8 +62,6 @@ Example: i2c-arbitrator { compatible = "i2c-arb-gpio-challenge"; - #address-cells = <1>; - #size-cells = <0>; i2c-parent = <&{/i2c@12CA0000}>; @@ -74,8 +71,7 @@ Example: wait-retry-us = <3000>; wait-free-us = <50000>; - i2c@0 { - reg = <0>; + i2c-arb { #address-cells = <1>; #size-cells = <0>; diff --git a/Documentation/devicetree/bindings/i2c/i2c-arb.txt b/Documentation/devicetree/bindings/i2c/i2c-arb.txt new file mode 100644 index 000000000000..59abf9277bdc --- /dev/null +++ b/Documentation/devicetree/bindings/i2c/i2c-arb.txt @@ -0,0 +1,35 @@ +Common i2c arbitration bus properties. + +- i2c-arb child node + +Required properties for the i2c-arb child node: +- #address-cells = <1>; +- #size-cells = <0>; + +Optional properties for i2c-arb child node: +- Child nodes conforming to i2c bus binding + + +Example : + + /* + An NXP pca9541 I2C bus master selector at address 0x74 + with a NXP pca8574 GPIO expander attached. + */ + + arb@74 { + compatible = "nxp,pca9541"; + reg = <0x74>; + + i2c-arb { + #address-cells = <1>; + #size-cells = <0>; + + gpio@38 { + compatible = "nxp,pca8574"; + reg = <0x38>; + #gpio-cells = <2>; + gpio-controller; + }; + }; + }; diff --git a/MAINTAINERS b/MAINTAINERS index 0bbe4b105c34..cde3e729df2c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5667,6 +5667,7 @@ S: Maintained F: Documentation/i2c/i2c-topology F: Documentation/i2c/muxes/ F: Documentation/devicetree/bindings/i2c/i2c-mux* +F: Documentation/devicetree/bindings/i2c/i2c-arb* F: drivers/i2c/i2c-mux.c F: drivers/i2c/muxes/ F: include/linux/i2c-mux.h From 0ac8eb6452e128abd7af08e5d4a38768833da0ca Mon Sep 17 00:00:00 2001 From: Peter Rosin Date: Fri, 8 Jul 2016 12:13:49 +0200 Subject: [PATCH 07/71] dt-bindings: i2c: add support for 'i2c-gate' subnode Handle i2c gates similarly to how i2c arbitrators are handled. This gets rid of a pointless 'reg' property for i2c gates. I.e. this new and more compact style some-gate { i2c-gate { #address-cells = <1>; #size-cells = <0>; some-i2c-device@50 { reg = <0x50>; }; }; }; instead of the old some-gate { #address-cells = <1>; #size-cells = <0>; i2c@0 { reg = <0>; #address-cells = <1>; #size-cells = <0>; some-i2c-device@50 { reg = <0x50>; }; }; }; Acked-by: Rob Herring Reviewed-by: Wolfram Sang Signed-off-by: Peter Rosin --- .../devicetree/bindings/i2c/i2c-gate.txt | 41 +++++++++++++++++++ MAINTAINERS | 1 + 2 files changed, 42 insertions(+) create mode 100644 Documentation/devicetree/bindings/i2c/i2c-gate.txt diff --git a/Documentation/devicetree/bindings/i2c/i2c-gate.txt b/Documentation/devicetree/bindings/i2c/i2c-gate.txt new file mode 100644 index 000000000000..1846d236e656 --- /dev/null +++ b/Documentation/devicetree/bindings/i2c/i2c-gate.txt @@ -0,0 +1,41 @@ +An i2c gate is useful to e.g. reduce the digital noise for RF tuners connected +to the i2c bus. Gates are similar to arbitrators in that you need to perform +some kind of operation to access the i2c bus past the arbitrator/gate, but +there are no competing masters to consider for gates and therefore there is +no arbitration happening for gates. + +Common i2c gate properties. + +- i2c-gate child node + +Required properties for the i2c-gate child node: +- #address-cells = <1>; +- #size-cells = <0>; + +Optional properties for i2c-gate child node: +- Child nodes conforming to i2c bus binding + + +Example : + + /* + An Invensense mpu9150 at address 0x68 featuring an on-chip Asahi + Kasei ak8975 compass behind a gate. + */ + + mpu9150@68 { + compatible = "invensense,mpu9150"; + reg = <0x68>; + interrupt-parent = <&gpio1>; + interrupts = <18 1>; + + i2c-gate { + #address-cells = <1>; + #size-cells = <0>; + + ax8975@c { + compatible = "ak,ak8975"; + reg = <0x0c>; + }; + }; + }; diff --git a/MAINTAINERS b/MAINTAINERS index cde3e729df2c..353bfe6bbaca 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5668,6 +5668,7 @@ F: Documentation/i2c/i2c-topology F: Documentation/i2c/muxes/ F: Documentation/devicetree/bindings/i2c/i2c-mux* F: Documentation/devicetree/bindings/i2c/i2c-arb* +F: Documentation/devicetree/bindings/i2c/i2c-gate* F: drivers/i2c/i2c-mux.c F: drivers/i2c/muxes/ F: include/linux/i2c-mux.h From 8f7720b950cf42d316fe5b625867e163a260a83c Mon Sep 17 00:00:00 2001 From: Peter Rosin Date: Mon, 27 Jun 2016 12:01:30 +0200 Subject: [PATCH 08/71] dt-bindings: i2c: add bindings for nxp,pca9541 Fill the gap for this pre-existing driver. Acked-by: Rob Herring Reviewed-by: Wolfram Sang Signed-off-by: Peter Rosin --- .../devicetree/bindings/i2c/nxp,pca9541.txt | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 Documentation/devicetree/bindings/i2c/nxp,pca9541.txt diff --git a/Documentation/devicetree/bindings/i2c/nxp,pca9541.txt b/Documentation/devicetree/bindings/i2c/nxp,pca9541.txt new file mode 100644 index 000000000000..0fbbc6970ec5 --- /dev/null +++ b/Documentation/devicetree/bindings/i2c/nxp,pca9541.txt @@ -0,0 +1,29 @@ +* NXP PCA9541 I2C bus master selector + +Required Properties: + + - compatible: Must be "nxp,pca9541" + + - reg: The I2C address of the device. + + The following required properties are defined externally: + + - I2C arbitration bus node. See i2c-arb.txt in this directory. + + +Example: + + i2c-arbitrator@74 { + compatible = "nxp,pca9541"; + reg = <0x74>; + + i2c-arb { + #address-cells = <1>; + #size-cells = <0>; + + eeprom@54 { + compatible = "at,24c08"; + reg = <0x54>; + }; + }; + }; From b2d57b56047b99f2992fc958d7ac5ead283e9088 Mon Sep 17 00:00:00 2001 From: Peter Rosin Date: Sat, 9 Jul 2016 21:53:42 +0200 Subject: [PATCH 09/71] i2c: mux: add support for 'i2c-mux', 'i2c-arb' and 'i2c-gate' DT subnodes Backwards compatibility is preserved; the subnodes are in practice optional. However, the mux core needs to know what subnode it should examine, so add a couple of new flags for i2c_mux_alloc for this purpose. The rule is that if the mux core finds a 'reg' property in the appropriate subnode, e.g. if 'reg' exists in the 'i2c-mux' subnode, then the mux core will assume that this is an old style entry and not an i2c-mux subnode (correspondingly for arbitrators and gates with 'i2c-arb' and 'i2c-gate'). Reviewed-by: Wolfram Sang Signed-off-by: Peter Rosin --- drivers/i2c/i2c-mux.c | 44 +++++++++++++++++++++++++++++++++-------- include/linux/i2c-mux.h | 8 ++++++-- 2 files changed, 42 insertions(+), 10 deletions(-) diff --git a/drivers/i2c/i2c-mux.c b/drivers/i2c/i2c-mux.c index 8eee98634cda..c1ae719d1a7a 100644 --- a/drivers/i2c/i2c-mux.c +++ b/drivers/i2c/i2c-mux.c @@ -255,6 +255,10 @@ struct i2c_mux_core *i2c_mux_alloc(struct i2c_adapter *parent, muxc->dev = dev; if (flags & I2C_MUX_LOCKED) muxc->mux_locked = true; + if (flags & I2C_MUX_ARBITRATOR) + muxc->arbitrator = true; + if (flags & I2C_MUX_GATE) + muxc->gate = true; muxc->select = select; muxc->deselect = deselect; muxc->max_adapters = max_adapters; @@ -335,18 +339,42 @@ int i2c_mux_add_adapter(struct i2c_mux_core *muxc, * nothing if !CONFIG_OF. */ if (muxc->dev->of_node) { - struct device_node *child; + struct device_node *dev_node = muxc->dev->of_node; + struct device_node *mux_node, *child = NULL; u32 reg; - for_each_child_of_node(muxc->dev->of_node, child) { - ret = of_property_read_u32(child, "reg", ®); - if (ret) - continue; - if (chan_id == reg) { - priv->adap.dev.of_node = child; - break; + if (muxc->arbitrator) + mux_node = of_get_child_by_name(dev_node, "i2c-arb"); + else if (muxc->gate) + mux_node = of_get_child_by_name(dev_node, "i2c-gate"); + else + mux_node = of_get_child_by_name(dev_node, "i2c-mux"); + + if (mux_node) { + /* A "reg" property indicates an old-style DT entry */ + if (!of_property_read_u32(mux_node, "reg", ®)) { + of_node_put(mux_node); + mux_node = NULL; } } + + if (!mux_node) + mux_node = of_node_get(dev_node); + else if (muxc->arbitrator || muxc->gate) + child = of_node_get(mux_node); + + if (!child) { + for_each_child_of_node(mux_node, child) { + ret = of_property_read_u32(child, "reg", ®); + if (ret) + continue; + if (chan_id == reg) + break; + } + } + + priv->adap.dev.of_node = child; + of_node_put(mux_node); } /* diff --git a/include/linux/i2c-mux.h b/include/linux/i2c-mux.h index d4c1d12f900d..bd74d5706f3b 100644 --- a/include/linux/i2c-mux.h +++ b/include/linux/i2c-mux.h @@ -32,7 +32,9 @@ struct i2c_mux_core { struct i2c_adapter *parent; struct device *dev; - bool mux_locked; + unsigned int mux_locked:1; + unsigned int arbitrator:1; + unsigned int gate:1; void *priv; @@ -51,7 +53,9 @@ struct i2c_mux_core *i2c_mux_alloc(struct i2c_adapter *parent, int (*deselect)(struct i2c_mux_core *, u32)); /* flags for i2c_mux_alloc */ -#define I2C_MUX_LOCKED BIT(0) +#define I2C_MUX_LOCKED BIT(0) +#define I2C_MUX_ARBITRATOR BIT(1) +#define I2C_MUX_GATE BIT(2) static inline void *i2c_mux_priv(struct i2c_mux_core *muxc) { From 40839590f868d77ab8f84ac6e1b1297f553e3dea Mon Sep 17 00:00:00 2001 From: Peter Rosin Date: Thu, 11 Aug 2016 16:49:54 +0200 Subject: [PATCH 10/71] i2c: mux: inform the i2c mux core about how it is used The i2c mux core can then take appropriate action depending on if it is used for an actual i2c mux, for a gate or for an arbitrator (the last is the case for these drivers). This adds support for the new clearer and more compact devicetree bindings that was added recently. Reviewed-by: Wolfram Sang Signed-off-by: Peter Rosin --- drivers/i2c/muxes/i2c-arb-gpio-challenge.c | 2 +- drivers/i2c/muxes/i2c-mux-pca9541.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/i2c/muxes/i2c-arb-gpio-challenge.c b/drivers/i2c/muxes/i2c-arb-gpio-challenge.c index a90bbc4037dd..86fc2d4c081b 100644 --- a/drivers/i2c/muxes/i2c-arb-gpio-challenge.c +++ b/drivers/i2c/muxes/i2c-arb-gpio-challenge.c @@ -130,7 +130,7 @@ static int i2c_arbitrator_probe(struct platform_device *pdev) return -EINVAL; } - muxc = i2c_mux_alloc(NULL, dev, 1, sizeof(*arb), 0, + muxc = i2c_mux_alloc(NULL, dev, 1, sizeof(*arb), I2C_MUX_ARBITRATOR, i2c_arbitrator_select, i2c_arbitrator_deselect); if (!muxc) return -ENOMEM; diff --git a/drivers/i2c/muxes/i2c-mux-pca9541.c b/drivers/i2c/muxes/i2c-mux-pca9541.c index 3cb8af635db5..f052c3067791 100644 --- a/drivers/i2c/muxes/i2c-mux-pca9541.c +++ b/drivers/i2c/muxes/i2c-mux-pca9541.c @@ -349,7 +349,8 @@ static int pca9541_probe(struct i2c_client *client, force = 0; if (pdata) force = pdata->modes[0].adap_id; - muxc = i2c_mux_alloc(adap, &client->dev, 1, sizeof(*data), 0, + muxc = i2c_mux_alloc(adap, &client->dev, 1, sizeof(*data), + I2C_MUX_ARBITRATOR, pca9541_select_chan, pca9541_release_chan); if (!muxc) return -ENOMEM; From a1cbf338abaf4d340b7aee1d8255e20462d11e70 Mon Sep 17 00:00:00 2001 From: Peter Rosin Date: Sat, 9 Jul 2016 20:30:58 +0200 Subject: [PATCH 11/71] i2c: pca9541: add device tree binding No longer rely on the implicit matching with the i2c device name, use an explicit compatible string instead. Reviewed-by: Wolfram Sang Signed-off-by: Peter Rosin --- drivers/i2c/muxes/i2c-mux-pca9541.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/i2c/muxes/i2c-mux-pca9541.c b/drivers/i2c/muxes/i2c-mux-pca9541.c index f052c3067791..4ea7e691afc7 100644 --- a/drivers/i2c/muxes/i2c-mux-pca9541.c +++ b/drivers/i2c/muxes/i2c-mux-pca9541.c @@ -85,6 +85,13 @@ static const struct i2c_device_id pca9541_id[] = { MODULE_DEVICE_TABLE(i2c, pca9541_id); +#ifdef CONFIG_OF +static const struct of_device_id pca9541_of_match[] = { + { .compatible = "nxp,pca9541" }, + {} +}; +#endif + /* * Write to chip register. Don't use i2c_transfer()/i2c_smbus_xfer() * as they will try to lock the adapter a second time. @@ -383,6 +390,7 @@ static int pca9541_remove(struct i2c_client *client) static struct i2c_driver pca9541_driver = { .driver = { .name = "pca9541", + .of_match_table = of_match_ptr(pca9541_of_match), }, .probe = pca9541_probe, .remove = pca9541_remove, From 8a191a7ad4ca9022bb838387b20d3de6acc88b72 Mon Sep 17 00:00:00 2001 From: Peter Rosin Date: Sat, 9 Jul 2016 21:21:15 +0200 Subject: [PATCH 12/71] i2c: pca954x: add device tree binding No longer rely on the implicit matching with the i2c device name, use an explicit compatible string instead. Keep a direct pointer to the chip description instead of an index into the chip description array. Reviewed-by: Wolfram Sang Signed-off-by: Peter Rosin --- drivers/i2c/muxes/i2c-mux-pca954x.c | 46 +++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 12 deletions(-) diff --git a/drivers/i2c/muxes/i2c-mux-pca954x.c b/drivers/i2c/muxes/i2c-mux-pca954x.c index 528e755c468f..6dfd31ba29a0 100644 --- a/drivers/i2c/muxes/i2c-mux-pca954x.c +++ b/drivers/i2c/muxes/i2c-mux-pca954x.c @@ -42,6 +42,7 @@ #include #include #include +#include #include #include @@ -58,14 +59,6 @@ enum pca_type { pca_9548, }; -struct pca954x { - enum pca_type type; - - u8 last_chan; /* last register value */ - u8 deselect; - struct i2c_client *client; -}; - struct chip_desc { u8 nchans; u8 enable; /* used for muxes only */ @@ -75,6 +68,14 @@ struct chip_desc { } muxtype; }; +struct pca954x { + const struct chip_desc *chip; + + u8 last_chan; /* last register value */ + u8 deselect; + struct i2c_client *client; +}; + /* Provide specs for the PCA954x types we know about */ static const struct chip_desc chips[] = { [pca_9540] = { @@ -119,6 +120,20 @@ static const struct i2c_device_id pca954x_id[] = { }; MODULE_DEVICE_TABLE(i2c, pca954x_id); +#ifdef CONFIG_OF +static const struct of_device_id pca954x_of_match[] = { + { .compatible = "nxp,pca9540", .data = &chips[pca_9540] }, + { .compatible = "nxp,pca9542", .data = &chips[pca_9542] }, + { .compatible = "nxp,pca9543", .data = &chips[pca_9543] }, + { .compatible = "nxp,pca9544", .data = &chips[pca_9544] }, + { .compatible = "nxp,pca9545", .data = &chips[pca_9545] }, + { .compatible = "nxp,pca9546", .data = &chips[pca_9546] }, + { .compatible = "nxp,pca9547", .data = &chips[pca_9547] }, + { .compatible = "nxp,pca9548", .data = &chips[pca_9548] }, + {} +}; +#endif + /* Write to mux register. Don't use i2c_transfer()/i2c_smbus_xfer() for this as they will try to lock adapter a second time */ static int pca954x_reg_write(struct i2c_adapter *adap, @@ -151,7 +166,7 @@ static int pca954x_select_chan(struct i2c_mux_core *muxc, u32 chan) { struct pca954x *data = i2c_mux_priv(muxc); struct i2c_client *client = data->client; - const struct chip_desc *chip = &chips[data->type]; + const struct chip_desc *chip = data->chip; u8 regval; int ret = 0; @@ -197,6 +212,7 @@ static int pca954x_probe(struct i2c_client *client, int num, force, class; struct i2c_mux_core *muxc; struct pca954x *data; + const struct of_device_id *match; int ret; if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE)) @@ -226,14 +242,19 @@ static int pca954x_probe(struct i2c_client *client, return -ENODEV; } - data->type = id->driver_data; + match = of_match_device(of_match_ptr(pca954x_of_match), &client->dev); + if (match) + data->chip = of_device_get_match_data(&client->dev); + else + data->chip = &chips[id->driver_data]; + data->last_chan = 0; /* force the first selection */ idle_disconnect_dt = of_node && of_property_read_bool(of_node, "i2c-mux-idle-disconnect"); /* Now create an adapter for each channel */ - for (num = 0; num < chips[data->type].nchans; num++) { + for (num = 0; num < data->chip->nchans; num++) { bool idle_disconnect_pd = false; force = 0; /* dynamic adap number */ @@ -263,7 +284,7 @@ static int pca954x_probe(struct i2c_client *client, dev_info(&client->dev, "registered %d multiplexed busses for I2C %s %s\n", - num, chips[data->type].muxtype == pca954x_ismux + num, data->chip->muxtype == pca954x_ismux ? "mux" : "switch", client->name); return 0; @@ -299,6 +320,7 @@ static struct i2c_driver pca954x_driver = { .driver = { .name = "pca954x", .pm = &pca954x_pm, + .of_match_table = of_match_ptr(pca954x_of_match), }, .probe = pca954x_probe, .remove = pca954x_remove, From 68af512a74481d579443f3c81e7a017d06f677c2 Mon Sep 17 00:00:00 2001 From: Jan Glauber Date: Wed, 24 Aug 2016 23:25:42 +0200 Subject: [PATCH 13/71] i2c: octeon: Rename driver to prepare for split This is an intermediate commit in preparation of the driver split. The module rename in this commit will be reverted in the next patch, this is just done to make the series bisectible. Signed-off-by: Jan Glauber Signed-off-by: Wolfram Sang --- drivers/i2c/busses/Makefile | 2 +- drivers/i2c/busses/{i2c-octeon.c => i2c-octeon-platdrv.c} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename drivers/i2c/busses/{i2c-octeon.c => i2c-octeon-platdrv.c} (100%) diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index 37f2819b4560..f2c9c6f9b89d 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -91,7 +91,7 @@ obj-$(CONFIG_I2C_UNIPHIER) += i2c-uniphier.o obj-$(CONFIG_I2C_UNIPHIER_F) += i2c-uniphier-f.o obj-$(CONFIG_I2C_VERSATILE) += i2c-versatile.o obj-$(CONFIG_I2C_WMT) += i2c-wmt.o -obj-$(CONFIG_I2C_OCTEON) += i2c-octeon.o +obj-$(CONFIG_I2C_OCTEON) += i2c-octeon-platdrv.o obj-$(CONFIG_I2C_XILINX) += i2c-xiic.o obj-$(CONFIG_I2C_XLR) += i2c-xlr.o obj-$(CONFIG_I2C_XLP9XX) += i2c-xlp9xx.o diff --git a/drivers/i2c/busses/i2c-octeon.c b/drivers/i2c/busses/i2c-octeon-platdrv.c similarity index 100% rename from drivers/i2c/busses/i2c-octeon.c rename to drivers/i2c/busses/i2c-octeon-platdrv.c From ad83665b4687f5a4456009487af1ea640b9b1b1b Mon Sep 17 00:00:00 2001 From: Jan Glauber Date: Wed, 24 Aug 2016 23:25:43 +0200 Subject: [PATCH 14/71] i2c: octeon: Split the driver into two parts Move common functionality into a separate file in preparation of the re-use from the ThunderX i2c driver. Functions are slightly re-ordered but no other changes are included. Signed-off-by: Jan Glauber Signed-off-by: Wolfram Sang --- drivers/i2c/busses/Makefile | 3 +- drivers/i2c/busses/i2c-octeon-core.c | 810 ++++++++++++++++++++ drivers/i2c/busses/i2c-octeon-core.h | 197 +++++ drivers/i2c/busses/i2c-octeon-platdrv.c | 973 +----------------------- 4 files changed, 1010 insertions(+), 973 deletions(-) create mode 100644 drivers/i2c/busses/i2c-octeon-core.c create mode 100644 drivers/i2c/busses/i2c-octeon-core.h diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index f2c9c6f9b89d..f975263a5da3 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -91,7 +91,8 @@ obj-$(CONFIG_I2C_UNIPHIER) += i2c-uniphier.o obj-$(CONFIG_I2C_UNIPHIER_F) += i2c-uniphier-f.o obj-$(CONFIG_I2C_VERSATILE) += i2c-versatile.o obj-$(CONFIG_I2C_WMT) += i2c-wmt.o -obj-$(CONFIG_I2C_OCTEON) += i2c-octeon-platdrv.o +i2c-octeon-objs := i2c-octeon-core.o i2c-octeon-platdrv.o +obj-$(CONFIG_I2C_OCTEON) += i2c-octeon.o obj-$(CONFIG_I2C_XILINX) += i2c-xiic.o obj-$(CONFIG_I2C_XLR) += i2c-xlr.o obj-$(CONFIG_I2C_XLP9XX) += i2c-xlp9xx.o diff --git a/drivers/i2c/busses/i2c-octeon-core.c b/drivers/i2c/busses/i2c-octeon-core.c new file mode 100644 index 000000000000..23384efc101a --- /dev/null +++ b/drivers/i2c/busses/i2c-octeon-core.c @@ -0,0 +1,810 @@ +/* + * (C) Copyright 2009-2010 + * Nokia Siemens Networks, michael.lawnick.ext@nsn.com + * + * Portions Copyright (C) 2010 - 2016 Cavium, Inc. + * + * This file contains the shared part of the driver for the i2c adapter in + * Cavium Networks' OCTEON processors and ThunderX SOCs. + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include + +#include "i2c-octeon-core.h" + +/* interrupt service routine */ +irqreturn_t octeon_i2c_isr(int irq, void *dev_id) +{ + struct octeon_i2c *i2c = dev_id; + + i2c->int_disable(i2c); + wake_up(&i2c->queue); + + return IRQ_HANDLED; +} + +static bool octeon_i2c_test_iflg(struct octeon_i2c *i2c) +{ + return (octeon_i2c_ctl_read(i2c) & TWSI_CTL_IFLG); +} + +static bool octeon_i2c_test_ready(struct octeon_i2c *i2c, bool *first) +{ + if (octeon_i2c_test_iflg(i2c)) + return true; + + if (*first) { + *first = false; + return false; + } + + /* + * IRQ has signaled an event but IFLG hasn't changed. + * Sleep and retry once. + */ + usleep_range(I2C_OCTEON_EVENT_WAIT, 2 * I2C_OCTEON_EVENT_WAIT); + return octeon_i2c_test_iflg(i2c); +} + +/** + * octeon_i2c_wait - wait for the IFLG to be set + * @i2c: The struct octeon_i2c + * + * Returns 0 on success, otherwise a negative errno. + */ +static int octeon_i2c_wait(struct octeon_i2c *i2c) +{ + long time_left; + bool first = 1; + + /* + * Some chip revisions don't assert the irq in the interrupt + * controller. So we must poll for the IFLG change. + */ + if (i2c->broken_irq_mode) { + u64 end = get_jiffies_64() + i2c->adap.timeout; + + while (!octeon_i2c_test_iflg(i2c) && + time_before64(get_jiffies_64(), end)) + usleep_range(I2C_OCTEON_EVENT_WAIT / 2, I2C_OCTEON_EVENT_WAIT); + + return octeon_i2c_test_iflg(i2c) ? 0 : -ETIMEDOUT; + } + + i2c->int_enable(i2c); + time_left = wait_event_timeout(i2c->queue, octeon_i2c_test_ready(i2c, &first), + i2c->adap.timeout); + i2c->int_disable(i2c); + + if (i2c->broken_irq_check && !time_left && + octeon_i2c_test_iflg(i2c)) { + dev_err(i2c->dev, "broken irq connection detected, switching to polling mode.\n"); + i2c->broken_irq_mode = true; + return 0; + } + + if (!time_left) + return -ETIMEDOUT; + + return 0; +} + +static bool octeon_i2c_hlc_test_valid(struct octeon_i2c *i2c) +{ + return (__raw_readq(i2c->twsi_base + SW_TWSI) & SW_TWSI_V) == 0; +} + +static bool octeon_i2c_hlc_test_ready(struct octeon_i2c *i2c, bool *first) +{ + /* check if valid bit is cleared */ + if (octeon_i2c_hlc_test_valid(i2c)) + return true; + + if (*first) { + *first = false; + return false; + } + + /* + * IRQ has signaled an event but valid bit isn't cleared. + * Sleep and retry once. + */ + usleep_range(I2C_OCTEON_EVENT_WAIT, 2 * I2C_OCTEON_EVENT_WAIT); + return octeon_i2c_hlc_test_valid(i2c); +} + +static void octeon_i2c_hlc_int_clear(struct octeon_i2c *i2c) +{ + /* clear ST/TS events, listen for neither */ + octeon_i2c_write_int(i2c, TWSI_INT_ST_INT | TWSI_INT_TS_INT); +} + +/* + * Cleanup low-level state & enable high-level controller. + */ +static void octeon_i2c_hlc_enable(struct octeon_i2c *i2c) +{ + int try = 0; + u64 val; + + if (i2c->hlc_enabled) + return; + i2c->hlc_enabled = true; + + while (1) { + val = octeon_i2c_ctl_read(i2c); + if (!(val & (TWSI_CTL_STA | TWSI_CTL_STP))) + break; + + /* clear IFLG event */ + if (val & TWSI_CTL_IFLG) + octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB); + + if (try++ > 100) { + pr_err("%s: giving up\n", __func__); + break; + } + + /* spin until any start/stop has finished */ + udelay(10); + } + octeon_i2c_ctl_write(i2c, TWSI_CTL_CE | TWSI_CTL_AAK | TWSI_CTL_ENAB); +} + +static void octeon_i2c_hlc_disable(struct octeon_i2c *i2c) +{ + if (!i2c->hlc_enabled) + return; + + i2c->hlc_enabled = false; + octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB); +} + +/** + * octeon_i2c_hlc_wait - wait for an HLC operation to complete + * @i2c: The struct octeon_i2c + * + * Returns 0 on success, otherwise -ETIMEDOUT. + */ +static int octeon_i2c_hlc_wait(struct octeon_i2c *i2c) +{ + bool first = 1; + int time_left; + + /* + * Some cn38xx boards don't assert the irq in the interrupt + * controller. So we must poll for the valid bit change. + */ + if (i2c->broken_irq_mode) { + u64 end = get_jiffies_64() + i2c->adap.timeout; + + while (!octeon_i2c_hlc_test_valid(i2c) && + time_before64(get_jiffies_64(), end)) + usleep_range(I2C_OCTEON_EVENT_WAIT / 2, I2C_OCTEON_EVENT_WAIT); + + return octeon_i2c_hlc_test_valid(i2c) ? 0 : -ETIMEDOUT; + } + + i2c->hlc_int_enable(i2c); + time_left = wait_event_timeout(i2c->queue, + octeon_i2c_hlc_test_ready(i2c, &first), + i2c->adap.timeout); + i2c->hlc_int_disable(i2c); + if (!time_left) + octeon_i2c_hlc_int_clear(i2c); + + if (i2c->broken_irq_check && !time_left && + octeon_i2c_hlc_test_valid(i2c)) { + dev_err(i2c->dev, "broken irq connection detected, switching to polling mode.\n"); + i2c->broken_irq_mode = true; + return 0; + } + + if (!time_left) + return -ETIMEDOUT; + return 0; +} + +static int octeon_i2c_check_status(struct octeon_i2c *i2c, int final_read) +{ + u8 stat = octeon_i2c_stat_read(i2c); + + switch (stat) { + /* Everything is fine */ + case STAT_IDLE: + case STAT_AD2W_ACK: + case STAT_RXADDR_ACK: + case STAT_TXADDR_ACK: + case STAT_TXDATA_ACK: + return 0; + + /* ACK allowed on pre-terminal bytes only */ + case STAT_RXDATA_ACK: + if (!final_read) + return 0; + return -EIO; + + /* NAK allowed on terminal byte only */ + case STAT_RXDATA_NAK: + if (final_read) + return 0; + return -EIO; + + /* Arbitration lost */ + case STAT_LOST_ARB_38: + case STAT_LOST_ARB_68: + case STAT_LOST_ARB_78: + case STAT_LOST_ARB_B0: + return -EAGAIN; + + /* Being addressed as slave, should back off & listen */ + case STAT_SLAVE_60: + case STAT_SLAVE_70: + case STAT_GENDATA_ACK: + case STAT_GENDATA_NAK: + return -EOPNOTSUPP; + + /* Core busy as slave */ + case STAT_SLAVE_80: + case STAT_SLAVE_88: + case STAT_SLAVE_A0: + case STAT_SLAVE_A8: + case STAT_SLAVE_LOST: + case STAT_SLAVE_NAK: + case STAT_SLAVE_ACK: + return -EOPNOTSUPP; + + case STAT_TXDATA_NAK: + return -EIO; + case STAT_TXADDR_NAK: + case STAT_RXADDR_NAK: + case STAT_AD2W_NAK: + return -ENXIO; + default: + dev_err(i2c->dev, "unhandled state: %d\n", stat); + return -EIO; + } +} + +static int octeon_i2c_recovery(struct octeon_i2c *i2c) +{ + int ret; + + ret = i2c_recover_bus(&i2c->adap); + if (ret) + /* recover failed, try hardware re-init */ + ret = octeon_i2c_init_lowlevel(i2c); + return ret; +} + +/** + * octeon_i2c_start - send START to the bus + * @i2c: The struct octeon_i2c + * + * Returns 0 on success, otherwise a negative errno. + */ +static int octeon_i2c_start(struct octeon_i2c *i2c) +{ + int ret; + u8 stat; + + octeon_i2c_hlc_disable(i2c); + + octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB | TWSI_CTL_STA); + ret = octeon_i2c_wait(i2c); + if (ret) + goto error; + + stat = octeon_i2c_stat_read(i2c); + if (stat == STAT_START || stat == STAT_REP_START) + /* START successful, bail out */ + return 0; + +error: + /* START failed, try to recover */ + ret = octeon_i2c_recovery(i2c); + return (ret) ? ret : -EAGAIN; +} + +/* send STOP to the bus */ +static void octeon_i2c_stop(struct octeon_i2c *i2c) +{ + octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB | TWSI_CTL_STP); +} + +/** + * octeon_i2c_read - receive data from the bus via low-level controller + * @i2c: The struct octeon_i2c + * @target: Target address + * @data: Pointer to the location to store the data + * @rlength: Length of the data + * @recv_len: flag for length byte + * + * The address is sent over the bus, then the data is read. + * + * Returns 0 on success, otherwise a negative errno. + */ +static int octeon_i2c_read(struct octeon_i2c *i2c, int target, + u8 *data, u16 *rlength, bool recv_len) +{ + int i, result, length = *rlength; + bool final_read = false; + + octeon_i2c_data_write(i2c, (target << 1) | 1); + octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB); + + result = octeon_i2c_wait(i2c); + if (result) + return result; + + /* address OK ? */ + result = octeon_i2c_check_status(i2c, false); + if (result) + return result; + + for (i = 0; i < length; i++) { + /* + * For the last byte to receive TWSI_CTL_AAK must not be set. + * + * A special case is I2C_M_RECV_LEN where we don't know the + * additional length yet. If recv_len is set we assume we're + * not reading the final byte and therefore need to set + * TWSI_CTL_AAK. + */ + if ((i + 1 == length) && !(recv_len && i == 0)) + final_read = true; + + /* clear iflg to allow next event */ + if (final_read) + octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB); + else + octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB | TWSI_CTL_AAK); + + result = octeon_i2c_wait(i2c); + if (result) + return result; + + data[i] = octeon_i2c_data_read(i2c); + if (recv_len && i == 0) { + if (data[i] > I2C_SMBUS_BLOCK_MAX + 1) + return -EPROTO; + length += data[i]; + } + + result = octeon_i2c_check_status(i2c, final_read); + if (result) + return result; + } + *rlength = length; + return 0; +} + +/** + * octeon_i2c_write - send data to the bus via low-level controller + * @i2c: The struct octeon_i2c + * @target: Target address + * @data: Pointer to the data to be sent + * @length: Length of the data + * + * The address is sent over the bus, then the data. + * + * Returns 0 on success, otherwise a negative errno. + */ +static int octeon_i2c_write(struct octeon_i2c *i2c, int target, + const u8 *data, int length) +{ + int i, result; + + octeon_i2c_data_write(i2c, target << 1); + octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB); + + result = octeon_i2c_wait(i2c); + if (result) + return result; + + for (i = 0; i < length; i++) { + result = octeon_i2c_check_status(i2c, false); + if (result) + return result; + + octeon_i2c_data_write(i2c, data[i]); + octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB); + + result = octeon_i2c_wait(i2c); + if (result) + return result; + } + + return 0; +} + +/* high-level-controller pure read of up to 8 bytes */ +static int octeon_i2c_hlc_read(struct octeon_i2c *i2c, struct i2c_msg *msgs) +{ + int i, j, ret = 0; + u64 cmd; + + octeon_i2c_hlc_enable(i2c); + octeon_i2c_hlc_int_clear(i2c); + + cmd = SW_TWSI_V | SW_TWSI_R | SW_TWSI_SOVR; + /* SIZE */ + cmd |= (u64)(msgs[0].len - 1) << SW_TWSI_SIZE_SHIFT; + /* A */ + cmd |= (u64)(msgs[0].addr & 0x7full) << SW_TWSI_ADDR_SHIFT; + + if (msgs[0].flags & I2C_M_TEN) + cmd |= SW_TWSI_OP_10; + else + cmd |= SW_TWSI_OP_7; + + octeon_i2c_writeq_flush(cmd, i2c->twsi_base + SW_TWSI); + ret = octeon_i2c_hlc_wait(i2c); + if (ret) + goto err; + + cmd = __raw_readq(i2c->twsi_base + SW_TWSI); + if ((cmd & SW_TWSI_R) == 0) + return -EAGAIN; + + for (i = 0, j = msgs[0].len - 1; i < msgs[0].len && i < 4; i++, j--) + msgs[0].buf[j] = (cmd >> (8 * i)) & 0xff; + + if (msgs[0].len > 4) { + cmd = __raw_readq(i2c->twsi_base + SW_TWSI_EXT); + for (i = 0; i < msgs[0].len - 4 && i < 4; i++, j--) + msgs[0].buf[j] = (cmd >> (8 * i)) & 0xff; + } + +err: + return ret; +} + +/* high-level-controller pure write of up to 8 bytes */ +static int octeon_i2c_hlc_write(struct octeon_i2c *i2c, struct i2c_msg *msgs) +{ + int i, j, ret = 0; + u64 cmd; + + octeon_i2c_hlc_enable(i2c); + octeon_i2c_hlc_int_clear(i2c); + + cmd = SW_TWSI_V | SW_TWSI_SOVR; + /* SIZE */ + cmd |= (u64)(msgs[0].len - 1) << SW_TWSI_SIZE_SHIFT; + /* A */ + cmd |= (u64)(msgs[0].addr & 0x7full) << SW_TWSI_ADDR_SHIFT; + + if (msgs[0].flags & I2C_M_TEN) + cmd |= SW_TWSI_OP_10; + else + cmd |= SW_TWSI_OP_7; + + for (i = 0, j = msgs[0].len - 1; i < msgs[0].len && i < 4; i++, j--) + cmd |= (u64)msgs[0].buf[j] << (8 * i); + + if (msgs[0].len > 4) { + u64 ext = 0; + + for (i = 0; i < msgs[0].len - 4 && i < 4; i++, j--) + ext |= (u64)msgs[0].buf[j] << (8 * i); + octeon_i2c_writeq_flush(ext, i2c->twsi_base + SW_TWSI_EXT); + } + + octeon_i2c_writeq_flush(cmd, i2c->twsi_base + SW_TWSI); + ret = octeon_i2c_hlc_wait(i2c); + if (ret) + goto err; + + cmd = __raw_readq(i2c->twsi_base + SW_TWSI); + if ((cmd & SW_TWSI_R) == 0) + return -EAGAIN; + + ret = octeon_i2c_check_status(i2c, false); + +err: + return ret; +} + +/* high-level-controller composite write+read, msg0=addr, msg1=data */ +static int octeon_i2c_hlc_comp_read(struct octeon_i2c *i2c, struct i2c_msg *msgs) +{ + int i, j, ret = 0; + u64 cmd; + + octeon_i2c_hlc_enable(i2c); + + cmd = SW_TWSI_V | SW_TWSI_R | SW_TWSI_SOVR; + /* SIZE */ + cmd |= (u64)(msgs[1].len - 1) << SW_TWSI_SIZE_SHIFT; + /* A */ + cmd |= (u64)(msgs[0].addr & 0x7full) << SW_TWSI_ADDR_SHIFT; + + if (msgs[0].flags & I2C_M_TEN) + cmd |= SW_TWSI_OP_10_IA; + else + cmd |= SW_TWSI_OP_7_IA; + + if (msgs[0].len == 2) { + u64 ext = 0; + + cmd |= SW_TWSI_EIA; + ext = (u64)msgs[0].buf[0] << SW_TWSI_IA_SHIFT; + cmd |= (u64)msgs[0].buf[1] << SW_TWSI_IA_SHIFT; + octeon_i2c_writeq_flush(ext, i2c->twsi_base + SW_TWSI_EXT); + } else { + cmd |= (u64)msgs[0].buf[0] << SW_TWSI_IA_SHIFT; + } + + octeon_i2c_hlc_int_clear(i2c); + octeon_i2c_writeq_flush(cmd, i2c->twsi_base + SW_TWSI); + + ret = octeon_i2c_hlc_wait(i2c); + if (ret) + goto err; + + cmd = __raw_readq(i2c->twsi_base + SW_TWSI); + if ((cmd & SW_TWSI_R) == 0) + return -EAGAIN; + + for (i = 0, j = msgs[1].len - 1; i < msgs[1].len && i < 4; i++, j--) + msgs[1].buf[j] = (cmd >> (8 * i)) & 0xff; + + if (msgs[1].len > 4) { + cmd = __raw_readq(i2c->twsi_base + SW_TWSI_EXT); + for (i = 0; i < msgs[1].len - 4 && i < 4; i++, j--) + msgs[1].buf[j] = (cmd >> (8 * i)) & 0xff; + } + +err: + return ret; +} + +/* high-level-controller composite write+write, m[0]len<=2, m[1]len<=8 */ +static int octeon_i2c_hlc_comp_write(struct octeon_i2c *i2c, struct i2c_msg *msgs) +{ + bool set_ext = false; + int i, j, ret = 0; + u64 cmd, ext = 0; + + octeon_i2c_hlc_enable(i2c); + + cmd = SW_TWSI_V | SW_TWSI_SOVR; + /* SIZE */ + cmd |= (u64)(msgs[1].len - 1) << SW_TWSI_SIZE_SHIFT; + /* A */ + cmd |= (u64)(msgs[0].addr & 0x7full) << SW_TWSI_ADDR_SHIFT; + + if (msgs[0].flags & I2C_M_TEN) + cmd |= SW_TWSI_OP_10_IA; + else + cmd |= SW_TWSI_OP_7_IA; + + if (msgs[0].len == 2) { + cmd |= SW_TWSI_EIA; + ext |= (u64)msgs[0].buf[0] << SW_TWSI_IA_SHIFT; + set_ext = true; + cmd |= (u64)msgs[0].buf[1] << SW_TWSI_IA_SHIFT; + } else { + cmd |= (u64)msgs[0].buf[0] << SW_TWSI_IA_SHIFT; + } + + for (i = 0, j = msgs[1].len - 1; i < msgs[1].len && i < 4; i++, j--) + cmd |= (u64)msgs[1].buf[j] << (8 * i); + + if (msgs[1].len > 4) { + for (i = 0; i < msgs[1].len - 4 && i < 4; i++, j--) + ext |= (u64)msgs[1].buf[j] << (8 * i); + set_ext = true; + } + if (set_ext) + octeon_i2c_writeq_flush(ext, i2c->twsi_base + SW_TWSI_EXT); + + octeon_i2c_hlc_int_clear(i2c); + octeon_i2c_writeq_flush(cmd, i2c->twsi_base + SW_TWSI); + + ret = octeon_i2c_hlc_wait(i2c); + if (ret) + goto err; + + cmd = __raw_readq(i2c->twsi_base + SW_TWSI); + if ((cmd & SW_TWSI_R) == 0) + return -EAGAIN; + + ret = octeon_i2c_check_status(i2c, false); + +err: + return ret; +} + +/** + * octeon_i2c_xfer - The driver's master_xfer function + * @adap: Pointer to the i2c_adapter structure + * @msgs: Pointer to the messages to be processed + * @num: Length of the MSGS array + * + * Returns the number of messages processed, or a negative errno on failure. + */ +int octeon_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) +{ + struct octeon_i2c *i2c = i2c_get_adapdata(adap); + int i, ret = 0; + + if (num == 1) { + if (msgs[0].len > 0 && msgs[0].len <= 8) { + if (msgs[0].flags & I2C_M_RD) + ret = octeon_i2c_hlc_read(i2c, msgs); + else + ret = octeon_i2c_hlc_write(i2c, msgs); + goto out; + } + } else if (num == 2) { + if ((msgs[0].flags & I2C_M_RD) == 0 && + (msgs[1].flags & I2C_M_RECV_LEN) == 0 && + msgs[0].len > 0 && msgs[0].len <= 2 && + msgs[1].len > 0 && msgs[1].len <= 8 && + msgs[0].addr == msgs[1].addr) { + if (msgs[1].flags & I2C_M_RD) + ret = octeon_i2c_hlc_comp_read(i2c, msgs); + else + ret = octeon_i2c_hlc_comp_write(i2c, msgs); + goto out; + } + } + + for (i = 0; ret == 0 && i < num; i++) { + struct i2c_msg *pmsg = &msgs[i]; + + /* zero-length messages are not supported */ + if (!pmsg->len) { + ret = -EOPNOTSUPP; + break; + } + + ret = octeon_i2c_start(i2c); + if (ret) + return ret; + + if (pmsg->flags & I2C_M_RD) + ret = octeon_i2c_read(i2c, pmsg->addr, pmsg->buf, + &pmsg->len, pmsg->flags & I2C_M_RECV_LEN); + else + ret = octeon_i2c_write(i2c, pmsg->addr, pmsg->buf, + pmsg->len); + } + octeon_i2c_stop(i2c); +out: + return (ret != 0) ? ret : num; +} + +/* calculate and set clock divisors */ +void octeon_i2c_set_clock(struct octeon_i2c *i2c) +{ + int tclk, thp_base, inc, thp_idx, mdiv_idx, ndiv_idx, foscl, diff; + int thp = 0x18, mdiv = 2, ndiv = 0, delta_hz = 1000000; + + for (ndiv_idx = 0; ndiv_idx < 8 && delta_hz != 0; ndiv_idx++) { + /* + * An mdiv value of less than 2 seems to not work well + * with ds1337 RTCs, so we constrain it to larger values. + */ + for (mdiv_idx = 15; mdiv_idx >= 2 && delta_hz != 0; mdiv_idx--) { + /* + * For given ndiv and mdiv values check the + * two closest thp values. + */ + tclk = i2c->twsi_freq * (mdiv_idx + 1) * 10; + tclk *= (1 << ndiv_idx); + thp_base = (i2c->sys_freq / (tclk * 2)) - 1; + + for (inc = 0; inc <= 1; inc++) { + thp_idx = thp_base + inc; + if (thp_idx < 5 || thp_idx > 0xff) + continue; + + foscl = i2c->sys_freq / (2 * (thp_idx + 1)); + foscl = foscl / (1 << ndiv_idx); + foscl = foscl / (mdiv_idx + 1) / 10; + diff = abs(foscl - i2c->twsi_freq); + if (diff < delta_hz) { + delta_hz = diff; + thp = thp_idx; + mdiv = mdiv_idx; + ndiv = ndiv_idx; + } + } + } + } + octeon_i2c_reg_write(i2c, SW_TWSI_OP_TWSI_CLK, thp); + octeon_i2c_reg_write(i2c, SW_TWSI_EOP_TWSI_CLKCTL, (mdiv << 3) | ndiv); +} + +int octeon_i2c_init_lowlevel(struct octeon_i2c *i2c) +{ + u8 status = 0; + int tries; + + /* reset controller */ + octeon_i2c_reg_write(i2c, SW_TWSI_EOP_TWSI_RST, 0); + + for (tries = 10; tries && status != STAT_IDLE; tries--) { + udelay(1); + status = octeon_i2c_stat_read(i2c); + if (status == STAT_IDLE) + break; + } + + if (status != STAT_IDLE) { + dev_err(i2c->dev, "%s: TWSI_RST failed! (0x%x)\n", + __func__, status); + return -EIO; + } + + /* toggle twice to force both teardowns */ + octeon_i2c_hlc_enable(i2c); + octeon_i2c_hlc_disable(i2c); + return 0; +} + +static int octeon_i2c_get_scl(struct i2c_adapter *adap) +{ + struct octeon_i2c *i2c = i2c_get_adapdata(adap); + u64 state; + + state = octeon_i2c_read_int(i2c); + return state & TWSI_INT_SCL; +} + +static void octeon_i2c_set_scl(struct i2c_adapter *adap, int val) +{ + struct octeon_i2c *i2c = i2c_get_adapdata(adap); + + octeon_i2c_write_int(i2c, TWSI_INT_SCL_OVR); +} + +static int octeon_i2c_get_sda(struct i2c_adapter *adap) +{ + struct octeon_i2c *i2c = i2c_get_adapdata(adap); + u64 state; + + state = octeon_i2c_read_int(i2c); + return state & TWSI_INT_SDA; +} + +static void octeon_i2c_prepare_recovery(struct i2c_adapter *adap) +{ + struct octeon_i2c *i2c = i2c_get_adapdata(adap); + + /* + * The stop resets the state machine, does not _transmit_ STOP unless + * engine was active. + */ + octeon_i2c_stop(i2c); + + octeon_i2c_hlc_disable(i2c); + octeon_i2c_write_int(i2c, 0); +} + +static void octeon_i2c_unprepare_recovery(struct i2c_adapter *adap) +{ + struct octeon_i2c *i2c = i2c_get_adapdata(adap); + + octeon_i2c_write_int(i2c, 0); +} + +struct i2c_bus_recovery_info octeon_i2c_recovery_info = { + .recover_bus = i2c_generic_scl_recovery, + .get_scl = octeon_i2c_get_scl, + .set_scl = octeon_i2c_set_scl, + .get_sda = octeon_i2c_get_sda, + .prepare_recovery = octeon_i2c_prepare_recovery, + .unprepare_recovery = octeon_i2c_unprepare_recovery, +}; diff --git a/drivers/i2c/busses/i2c-octeon-core.h b/drivers/i2c/busses/i2c-octeon-core.h new file mode 100644 index 000000000000..81c6a81cd308 --- /dev/null +++ b/drivers/i2c/busses/i2c-octeon-core.h @@ -0,0 +1,197 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +/* Register offsets */ +#define SW_TWSI 0x00 +#define TWSI_INT 0x10 +#define SW_TWSI_EXT 0x18 + +/* Controller command patterns */ +#define SW_TWSI_V BIT_ULL(63) /* Valid bit */ +#define SW_TWSI_EIA BIT_ULL(61) /* Extended internal address */ +#define SW_TWSI_R BIT_ULL(56) /* Result or read bit */ +#define SW_TWSI_SOVR BIT_ULL(55) /* Size override */ +#define SW_TWSI_SIZE_SHIFT 52 +#define SW_TWSI_ADDR_SHIFT 40 +#define SW_TWSI_IA_SHIFT 32 /* Internal address */ + +/* Controller opcode word (bits 60:57) */ +#define SW_TWSI_OP_SHIFT 57 +#define SW_TWSI_OP_7 (0ULL << SW_TWSI_OP_SHIFT) +#define SW_TWSI_OP_7_IA (1ULL << SW_TWSI_OP_SHIFT) +#define SW_TWSI_OP_10 (2ULL << SW_TWSI_OP_SHIFT) +#define SW_TWSI_OP_10_IA (3ULL << SW_TWSI_OP_SHIFT) +#define SW_TWSI_OP_TWSI_CLK (4ULL << SW_TWSI_OP_SHIFT) +#define SW_TWSI_OP_EOP (6ULL << SW_TWSI_OP_SHIFT) /* Extended opcode */ + +/* Controller extended opcode word (bits 34:32) */ +#define SW_TWSI_EOP_SHIFT 32 +#define SW_TWSI_EOP_TWSI_DATA (SW_TWSI_OP_EOP | 1ULL << SW_TWSI_EOP_SHIFT) +#define SW_TWSI_EOP_TWSI_CTL (SW_TWSI_OP_EOP | 2ULL << SW_TWSI_EOP_SHIFT) +#define SW_TWSI_EOP_TWSI_CLKCTL (SW_TWSI_OP_EOP | 3ULL << SW_TWSI_EOP_SHIFT) +#define SW_TWSI_EOP_TWSI_STAT (SW_TWSI_OP_EOP | 3ULL << SW_TWSI_EOP_SHIFT) +#define SW_TWSI_EOP_TWSI_RST (SW_TWSI_OP_EOP | 7ULL << SW_TWSI_EOP_SHIFT) + +/* Controller command and status bits */ +#define TWSI_CTL_CE 0x80 /* High level controller enable */ +#define TWSI_CTL_ENAB 0x40 /* Bus enable */ +#define TWSI_CTL_STA 0x20 /* Master-mode start, HW clears when done */ +#define TWSI_CTL_STP 0x10 /* Master-mode stop, HW clears when done */ +#define TWSI_CTL_IFLG 0x08 /* HW event, SW writes 0 to ACK */ +#define TWSI_CTL_AAK 0x04 /* Assert ACK */ + +/* Status values */ +#define STAT_ERROR 0x00 +#define STAT_START 0x08 +#define STAT_REP_START 0x10 +#define STAT_TXADDR_ACK 0x18 +#define STAT_TXADDR_NAK 0x20 +#define STAT_TXDATA_ACK 0x28 +#define STAT_TXDATA_NAK 0x30 +#define STAT_LOST_ARB_38 0x38 +#define STAT_RXADDR_ACK 0x40 +#define STAT_RXADDR_NAK 0x48 +#define STAT_RXDATA_ACK 0x50 +#define STAT_RXDATA_NAK 0x58 +#define STAT_SLAVE_60 0x60 +#define STAT_LOST_ARB_68 0x68 +#define STAT_SLAVE_70 0x70 +#define STAT_LOST_ARB_78 0x78 +#define STAT_SLAVE_80 0x80 +#define STAT_SLAVE_88 0x88 +#define STAT_GENDATA_ACK 0x90 +#define STAT_GENDATA_NAK 0x98 +#define STAT_SLAVE_A0 0xA0 +#define STAT_SLAVE_A8 0xA8 +#define STAT_LOST_ARB_B0 0xB0 +#define STAT_SLAVE_LOST 0xB8 +#define STAT_SLAVE_NAK 0xC0 +#define STAT_SLAVE_ACK 0xC8 +#define STAT_AD2W_ACK 0xD0 +#define STAT_AD2W_NAK 0xD8 +#define STAT_IDLE 0xF8 + +/* TWSI_INT values */ +#define TWSI_INT_ST_INT BIT_ULL(0) +#define TWSI_INT_TS_INT BIT_ULL(1) +#define TWSI_INT_CORE_INT BIT_ULL(2) +#define TWSI_INT_ST_EN BIT_ULL(4) +#define TWSI_INT_TS_EN BIT_ULL(5) +#define TWSI_INT_CORE_EN BIT_ULL(6) +#define TWSI_INT_SDA_OVR BIT_ULL(8) +#define TWSI_INT_SCL_OVR BIT_ULL(9) +#define TWSI_INT_SDA BIT_ULL(10) +#define TWSI_INT_SCL BIT_ULL(11) + +#define I2C_OCTEON_EVENT_WAIT 80 /* microseconds */ + +struct octeon_i2c { + wait_queue_head_t queue; + struct i2c_adapter adap; + int irq; + int hlc_irq; /* For cn7890 only */ + u32 twsi_freq; + int sys_freq; + void __iomem *twsi_base; + struct device *dev; + bool hlc_enabled; + bool broken_irq_mode; + bool broken_irq_check; + void (*int_enable)(struct octeon_i2c *); + void (*int_disable)(struct octeon_i2c *); + void (*hlc_int_enable)(struct octeon_i2c *); + void (*hlc_int_disable)(struct octeon_i2c *); + atomic_t int_enable_cnt; + atomic_t hlc_int_enable_cnt; +}; + +static inline void octeon_i2c_writeq_flush(u64 val, void __iomem *addr) +{ + __raw_writeq(val, addr); + __raw_readq(addr); /* wait for write to land */ +} + +/** + * octeon_i2c_reg_write - write an I2C core register + * @i2c: The struct octeon_i2c + * @eop_reg: Register selector + * @data: Value to be written + * + * The I2C core registers are accessed indirectly via the SW_TWSI CSR. + */ +static inline void octeon_i2c_reg_write(struct octeon_i2c *i2c, u64 eop_reg, u8 data) +{ + u64 tmp; + + __raw_writeq(SW_TWSI_V | eop_reg | data, i2c->twsi_base + SW_TWSI); + do { + tmp = __raw_readq(i2c->twsi_base + SW_TWSI); + } while ((tmp & SW_TWSI_V) != 0); +} + +#define octeon_i2c_ctl_write(i2c, val) \ + octeon_i2c_reg_write(i2c, SW_TWSI_EOP_TWSI_CTL, val) +#define octeon_i2c_data_write(i2c, val) \ + octeon_i2c_reg_write(i2c, SW_TWSI_EOP_TWSI_DATA, val) + +/** + * octeon_i2c_reg_read - read lower bits of an I2C core register + * @i2c: The struct octeon_i2c + * @eop_reg: Register selector + * + * Returns the data. + * + * The I2C core registers are accessed indirectly via the SW_TWSI CSR. + */ +static inline u8 octeon_i2c_reg_read(struct octeon_i2c *i2c, u64 eop_reg) +{ + u64 tmp; + + __raw_writeq(SW_TWSI_V | eop_reg | SW_TWSI_R, i2c->twsi_base + SW_TWSI); + do { + tmp = __raw_readq(i2c->twsi_base + SW_TWSI); + } while ((tmp & SW_TWSI_V) != 0); + + return tmp & 0xFF; +} + +#define octeon_i2c_ctl_read(i2c) \ + octeon_i2c_reg_read(i2c, SW_TWSI_EOP_TWSI_CTL) +#define octeon_i2c_data_read(i2c) \ + octeon_i2c_reg_read(i2c, SW_TWSI_EOP_TWSI_DATA) +#define octeon_i2c_stat_read(i2c) \ + octeon_i2c_reg_read(i2c, SW_TWSI_EOP_TWSI_STAT) + +/** + * octeon_i2c_read_int - read the TWSI_INT register + * @i2c: The struct octeon_i2c + * + * Returns the value of the register. + */ +static inline u64 octeon_i2c_read_int(struct octeon_i2c *i2c) +{ + return __raw_readq(i2c->twsi_base + TWSI_INT); +} + +/** + * octeon_i2c_write_int - write the TWSI_INT register + * @i2c: The struct octeon_i2c + * @data: Value to be written + */ +static inline void octeon_i2c_write_int(struct octeon_i2c *i2c, u64 data) +{ + octeon_i2c_writeq_flush(data, i2c->twsi_base + TWSI_INT); +} + +/* Prototypes */ +irqreturn_t octeon_i2c_isr(int irq, void *dev_id); +int octeon_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num); +int octeon_i2c_init_lowlevel(struct octeon_i2c *i2c); +void octeon_i2c_set_clock(struct octeon_i2c *i2c); +extern struct i2c_bus_recovery_info octeon_i2c_recovery_info; diff --git a/drivers/i2c/busses/i2c-octeon-platdrv.c b/drivers/i2c/busses/i2c-octeon-platdrv.c index b75d2da79b27..53fa9a0d96bb 100644 --- a/drivers/i2c/busses/i2c-octeon-platdrv.c +++ b/drivers/i2c/busses/i2c-octeon-platdrv.c @@ -24,191 +24,10 @@ #include #include +#include "i2c-octeon-core.h" #define DRV_NAME "i2c-octeon" -/* Register offsets */ -#define SW_TWSI 0x00 -#define TWSI_INT 0x10 -#define SW_TWSI_EXT 0x18 - -/* Controller command patterns */ -#define SW_TWSI_V BIT_ULL(63) /* Valid bit */ -#define SW_TWSI_EIA BIT_ULL(61) /* Extended internal address */ -#define SW_TWSI_R BIT_ULL(56) /* Result or read bit */ -#define SW_TWSI_SOVR BIT_ULL(55) /* Size override */ -#define SW_TWSI_SIZE_SHIFT 52 -#define SW_TWSI_ADDR_SHIFT 40 -#define SW_TWSI_IA_SHIFT 32 /* Internal address */ - -/* Controller opcode word (bits 60:57) */ -#define SW_TWSI_OP_SHIFT 57 -#define SW_TWSI_OP_7 (0ULL << SW_TWSI_OP_SHIFT) -#define SW_TWSI_OP_7_IA (1ULL << SW_TWSI_OP_SHIFT) -#define SW_TWSI_OP_10 (2ULL << SW_TWSI_OP_SHIFT) -#define SW_TWSI_OP_10_IA (3ULL << SW_TWSI_OP_SHIFT) -#define SW_TWSI_OP_TWSI_CLK (4ULL << SW_TWSI_OP_SHIFT) -#define SW_TWSI_OP_EOP (6ULL << SW_TWSI_OP_SHIFT) /* Extended opcode */ - -/* Controller extended opcode word (bits 34:32) */ -#define SW_TWSI_EOP_SHIFT 32 -#define SW_TWSI_EOP_TWSI_DATA (SW_TWSI_OP_EOP | 1ULL << SW_TWSI_EOP_SHIFT) -#define SW_TWSI_EOP_TWSI_CTL (SW_TWSI_OP_EOP | 2ULL << SW_TWSI_EOP_SHIFT) -#define SW_TWSI_EOP_TWSI_CLKCTL (SW_TWSI_OP_EOP | 3ULL << SW_TWSI_EOP_SHIFT) -#define SW_TWSI_EOP_TWSI_STAT (SW_TWSI_OP_EOP | 3ULL << SW_TWSI_EOP_SHIFT) -#define SW_TWSI_EOP_TWSI_RST (SW_TWSI_OP_EOP | 7ULL << SW_TWSI_EOP_SHIFT) - -/* Controller command and status bits */ -#define TWSI_CTL_CE 0x80 /* High level controller enable */ -#define TWSI_CTL_ENAB 0x40 /* Bus enable */ -#define TWSI_CTL_STA 0x20 /* Master-mode start, HW clears when done */ -#define TWSI_CTL_STP 0x10 /* Master-mode stop, HW clears when done */ -#define TWSI_CTL_IFLG 0x08 /* HW event, SW writes 0 to ACK */ -#define TWSI_CTL_AAK 0x04 /* Assert ACK */ - -/* Status values */ -#define STAT_ERROR 0x00 -#define STAT_START 0x08 -#define STAT_REP_START 0x10 -#define STAT_TXADDR_ACK 0x18 -#define STAT_TXADDR_NAK 0x20 -#define STAT_TXDATA_ACK 0x28 -#define STAT_TXDATA_NAK 0x30 -#define STAT_LOST_ARB_38 0x38 -#define STAT_RXADDR_ACK 0x40 -#define STAT_RXADDR_NAK 0x48 -#define STAT_RXDATA_ACK 0x50 -#define STAT_RXDATA_NAK 0x58 -#define STAT_SLAVE_60 0x60 -#define STAT_LOST_ARB_68 0x68 -#define STAT_SLAVE_70 0x70 -#define STAT_LOST_ARB_78 0x78 -#define STAT_SLAVE_80 0x80 -#define STAT_SLAVE_88 0x88 -#define STAT_GENDATA_ACK 0x90 -#define STAT_GENDATA_NAK 0x98 -#define STAT_SLAVE_A0 0xA0 -#define STAT_SLAVE_A8 0xA8 -#define STAT_LOST_ARB_B0 0xB0 -#define STAT_SLAVE_LOST 0xB8 -#define STAT_SLAVE_NAK 0xC0 -#define STAT_SLAVE_ACK 0xC8 -#define STAT_AD2W_ACK 0xD0 -#define STAT_AD2W_NAK 0xD8 -#define STAT_IDLE 0xF8 - -/* TWSI_INT values */ -#define TWSI_INT_ST_INT BIT_ULL(0) -#define TWSI_INT_TS_INT BIT_ULL(1) -#define TWSI_INT_CORE_INT BIT_ULL(2) -#define TWSI_INT_ST_EN BIT_ULL(4) -#define TWSI_INT_TS_EN BIT_ULL(5) -#define TWSI_INT_CORE_EN BIT_ULL(6) -#define TWSI_INT_SDA_OVR BIT_ULL(8) -#define TWSI_INT_SCL_OVR BIT_ULL(9) -#define TWSI_INT_SDA BIT_ULL(10) -#define TWSI_INT_SCL BIT_ULL(11) - -#define I2C_OCTEON_EVENT_WAIT 80 /* microseconds */ - -struct octeon_i2c { - wait_queue_head_t queue; - struct i2c_adapter adap; - int irq; - int hlc_irq; /* For cn7890 only */ - u32 twsi_freq; - int sys_freq; - void __iomem *twsi_base; - struct device *dev; - bool hlc_enabled; - bool broken_irq_mode; - bool broken_irq_check; - void (*int_enable)(struct octeon_i2c *); - void (*int_disable)(struct octeon_i2c *); - void (*hlc_int_enable)(struct octeon_i2c *); - void (*hlc_int_disable)(struct octeon_i2c *); - atomic_t int_enable_cnt; - atomic_t hlc_int_enable_cnt; -}; - -static void octeon_i2c_writeq_flush(u64 val, void __iomem *addr) -{ - __raw_writeq(val, addr); - __raw_readq(addr); /* wait for write to land */ -} - -/** - * octeon_i2c_reg_write - write an I2C core register - * @i2c: The struct octeon_i2c - * @eop_reg: Register selector - * @data: Value to be written - * - * The I2C core registers are accessed indirectly via the SW_TWSI CSR. - */ -static void octeon_i2c_reg_write(struct octeon_i2c *i2c, u64 eop_reg, u8 data) -{ - u64 tmp; - - __raw_writeq(SW_TWSI_V | eop_reg | data, i2c->twsi_base + SW_TWSI); - do { - tmp = __raw_readq(i2c->twsi_base + SW_TWSI); - } while ((tmp & SW_TWSI_V) != 0); -} - -#define octeon_i2c_ctl_write(i2c, val) \ - octeon_i2c_reg_write(i2c, SW_TWSI_EOP_TWSI_CTL, val) -#define octeon_i2c_data_write(i2c, val) \ - octeon_i2c_reg_write(i2c, SW_TWSI_EOP_TWSI_DATA, val) - -/** - * octeon_i2c_reg_read - read lower bits of an I2C core register - * @i2c: The struct octeon_i2c - * @eop_reg: Register selector - * - * Returns the data. - * - * The I2C core registers are accessed indirectly via the SW_TWSI CSR. - */ -static u8 octeon_i2c_reg_read(struct octeon_i2c *i2c, u64 eop_reg) -{ - u64 tmp; - - __raw_writeq(SW_TWSI_V | eop_reg | SW_TWSI_R, i2c->twsi_base + SW_TWSI); - do { - tmp = __raw_readq(i2c->twsi_base + SW_TWSI); - } while ((tmp & SW_TWSI_V) != 0); - - return tmp & 0xFF; -} - -#define octeon_i2c_ctl_read(i2c) \ - octeon_i2c_reg_read(i2c, SW_TWSI_EOP_TWSI_CTL) -#define octeon_i2c_data_read(i2c) \ - octeon_i2c_reg_read(i2c, SW_TWSI_EOP_TWSI_DATA) -#define octeon_i2c_stat_read(i2c) \ - octeon_i2c_reg_read(i2c, SW_TWSI_EOP_TWSI_STAT) - -/** - * octeon_i2c_read_int - read the TWSI_INT register - * @i2c: The struct octeon_i2c - * - * Returns the value of the register. - */ -static u64 octeon_i2c_read_int(struct octeon_i2c *i2c) -{ - return __raw_readq(i2c->twsi_base + TWSI_INT); -} - -/** - * octeon_i2c_write_int - write the TWSI_INT register - * @i2c: The struct octeon_i2c - * @data: Value to be written - */ -static void octeon_i2c_write_int(struct octeon_i2c *i2c, u64 data) -{ - octeon_i2c_writeq_flush(data, i2c->twsi_base + TWSI_INT); -} - /** * octeon_i2c_int_enable - enable the CORE interrupt * @i2c: The struct octeon_i2c @@ -280,58 +99,6 @@ static void octeon_i2c_hlc_int_disable78(struct octeon_i2c *i2c) __octeon_i2c_irq_disable(&i2c->hlc_int_enable_cnt, i2c->hlc_irq); } -/* - * Cleanup low-level state & enable high-level controller. - */ -static void octeon_i2c_hlc_enable(struct octeon_i2c *i2c) -{ - int try = 0; - u64 val; - - if (i2c->hlc_enabled) - return; - i2c->hlc_enabled = true; - - while (1) { - val = octeon_i2c_ctl_read(i2c); - if (!(val & (TWSI_CTL_STA | TWSI_CTL_STP))) - break; - - /* clear IFLG event */ - if (val & TWSI_CTL_IFLG) - octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB); - - if (try++ > 100) { - pr_err("%s: giving up\n", __func__); - break; - } - - /* spin until any start/stop has finished */ - udelay(10); - } - octeon_i2c_ctl_write(i2c, TWSI_CTL_CE | TWSI_CTL_AAK | TWSI_CTL_ENAB); -} - -static void octeon_i2c_hlc_disable(struct octeon_i2c *i2c) -{ - if (!i2c->hlc_enabled) - return; - - i2c->hlc_enabled = false; - octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB); -} - -/* interrupt service routine */ -static irqreturn_t octeon_i2c_isr(int irq, void *dev_id) -{ - struct octeon_i2c *i2c = dev_id; - - i2c->int_disable(i2c); - wake_up(&i2c->queue); - - return IRQ_HANDLED; -} - /* HLC interrupt service routine */ static irqreturn_t octeon_i2c_hlc_isr78(int irq, void *dev_id) { @@ -343,749 +110,11 @@ static irqreturn_t octeon_i2c_hlc_isr78(int irq, void *dev_id) return IRQ_HANDLED; } -static bool octeon_i2c_test_iflg(struct octeon_i2c *i2c) -{ - return (octeon_i2c_ctl_read(i2c) & TWSI_CTL_IFLG); -} - -static bool octeon_i2c_test_ready(struct octeon_i2c *i2c, bool *first) -{ - if (octeon_i2c_test_iflg(i2c)) - return true; - - if (*first) { - *first = false; - return false; - } - - /* - * IRQ has signaled an event but IFLG hasn't changed. - * Sleep and retry once. - */ - usleep_range(I2C_OCTEON_EVENT_WAIT, 2 * I2C_OCTEON_EVENT_WAIT); - return octeon_i2c_test_iflg(i2c); -} - -/** - * octeon_i2c_wait - wait for the IFLG to be set - * @i2c: The struct octeon_i2c - * - * Returns 0 on success, otherwise a negative errno. - */ -static int octeon_i2c_wait(struct octeon_i2c *i2c) -{ - long time_left; - bool first = 1; - - /* - * Some chip revisions don't assert the irq in the interrupt - * controller. So we must poll for the IFLG change. - */ - if (i2c->broken_irq_mode) { - u64 end = get_jiffies_64() + i2c->adap.timeout; - - while (!octeon_i2c_test_iflg(i2c) && - time_before64(get_jiffies_64(), end)) - usleep_range(I2C_OCTEON_EVENT_WAIT / 2, I2C_OCTEON_EVENT_WAIT); - - return octeon_i2c_test_iflg(i2c) ? 0 : -ETIMEDOUT; - } - - i2c->int_enable(i2c); - time_left = wait_event_timeout(i2c->queue, octeon_i2c_test_ready(i2c, &first), - i2c->adap.timeout); - i2c->int_disable(i2c); - - if (i2c->broken_irq_check && !time_left && - octeon_i2c_test_iflg(i2c)) { - dev_err(i2c->dev, "broken irq connection detected, switching to polling mode.\n"); - i2c->broken_irq_mode = true; - return 0; - } - - if (!time_left) - return -ETIMEDOUT; - - return 0; -} - -static int octeon_i2c_check_status(struct octeon_i2c *i2c, int final_read) -{ - u8 stat = octeon_i2c_stat_read(i2c); - - switch (stat) { - /* Everything is fine */ - case STAT_IDLE: - case STAT_AD2W_ACK: - case STAT_RXADDR_ACK: - case STAT_TXADDR_ACK: - case STAT_TXDATA_ACK: - return 0; - - /* ACK allowed on pre-terminal bytes only */ - case STAT_RXDATA_ACK: - if (!final_read) - return 0; - return -EIO; - - /* NAK allowed on terminal byte only */ - case STAT_RXDATA_NAK: - if (final_read) - return 0; - return -EIO; - - /* Arbitration lost */ - case STAT_LOST_ARB_38: - case STAT_LOST_ARB_68: - case STAT_LOST_ARB_78: - case STAT_LOST_ARB_B0: - return -EAGAIN; - - /* Being addressed as slave, should back off & listen */ - case STAT_SLAVE_60: - case STAT_SLAVE_70: - case STAT_GENDATA_ACK: - case STAT_GENDATA_NAK: - return -EOPNOTSUPP; - - /* Core busy as slave */ - case STAT_SLAVE_80: - case STAT_SLAVE_88: - case STAT_SLAVE_A0: - case STAT_SLAVE_A8: - case STAT_SLAVE_LOST: - case STAT_SLAVE_NAK: - case STAT_SLAVE_ACK: - return -EOPNOTSUPP; - - case STAT_TXDATA_NAK: - return -EIO; - case STAT_TXADDR_NAK: - case STAT_RXADDR_NAK: - case STAT_AD2W_NAK: - return -ENXIO; - default: - dev_err(i2c->dev, "unhandled state: %d\n", stat); - return -EIO; - } -} - -static bool octeon_i2c_hlc_test_valid(struct octeon_i2c *i2c) -{ - return (__raw_readq(i2c->twsi_base + SW_TWSI) & SW_TWSI_V) == 0; -} - -static bool octeon_i2c_hlc_test_ready(struct octeon_i2c *i2c, bool *first) -{ - /* check if valid bit is cleared */ - if (octeon_i2c_hlc_test_valid(i2c)) - return true; - - if (*first) { - *first = false; - return false; - } - - /* - * IRQ has signaled an event but valid bit isn't cleared. - * Sleep and retry once. - */ - usleep_range(I2C_OCTEON_EVENT_WAIT, 2 * I2C_OCTEON_EVENT_WAIT); - return octeon_i2c_hlc_test_valid(i2c); -} - static void octeon_i2c_hlc_int_enable(struct octeon_i2c *i2c) { octeon_i2c_write_int(i2c, TWSI_INT_ST_EN); } -static void octeon_i2c_hlc_int_clear(struct octeon_i2c *i2c) -{ - /* clear ST/TS events, listen for neither */ - octeon_i2c_write_int(i2c, TWSI_INT_ST_INT | TWSI_INT_TS_INT); -} - -/** - * octeon_i2c_hlc_wait - wait for an HLC operation to complete - * @i2c: The struct octeon_i2c - * - * Returns 0 on success, otherwise -ETIMEDOUT. - */ -static int octeon_i2c_hlc_wait(struct octeon_i2c *i2c) -{ - bool first = 1; - int time_left; - - /* - * Some cn38xx boards don't assert the irq in the interrupt - * controller. So we must poll for the valid bit change. - */ - if (i2c->broken_irq_mode) { - u64 end = get_jiffies_64() + i2c->adap.timeout; - - while (!octeon_i2c_hlc_test_valid(i2c) && - time_before64(get_jiffies_64(), end)) - usleep_range(I2C_OCTEON_EVENT_WAIT / 2, I2C_OCTEON_EVENT_WAIT); - - return octeon_i2c_hlc_test_valid(i2c) ? 0 : -ETIMEDOUT; - } - - i2c->hlc_int_enable(i2c); - time_left = wait_event_timeout(i2c->queue, - octeon_i2c_hlc_test_ready(i2c, &first), - i2c->adap.timeout); - i2c->hlc_int_disable(i2c); - if (!time_left) - octeon_i2c_hlc_int_clear(i2c); - - if (i2c->broken_irq_check && !time_left && - octeon_i2c_hlc_test_valid(i2c)) { - dev_err(i2c->dev, "broken irq connection detected, switching to polling mode.\n"); - i2c->broken_irq_mode = true; - return 0; - } - - if (!time_left) - return -ETIMEDOUT; - return 0; -} - -/* high-level-controller pure read of up to 8 bytes */ -static int octeon_i2c_hlc_read(struct octeon_i2c *i2c, struct i2c_msg *msgs) -{ - int i, j, ret = 0; - u64 cmd; - - octeon_i2c_hlc_enable(i2c); - octeon_i2c_hlc_int_clear(i2c); - - cmd = SW_TWSI_V | SW_TWSI_R | SW_TWSI_SOVR; - /* SIZE */ - cmd |= (u64)(msgs[0].len - 1) << SW_TWSI_SIZE_SHIFT; - /* A */ - cmd |= (u64)(msgs[0].addr & 0x7full) << SW_TWSI_ADDR_SHIFT; - - if (msgs[0].flags & I2C_M_TEN) - cmd |= SW_TWSI_OP_10; - else - cmd |= SW_TWSI_OP_7; - - octeon_i2c_writeq_flush(cmd, i2c->twsi_base + SW_TWSI); - ret = octeon_i2c_hlc_wait(i2c); - if (ret) - goto err; - - cmd = __raw_readq(i2c->twsi_base + SW_TWSI); - if ((cmd & SW_TWSI_R) == 0) - return -EAGAIN; - - for (i = 0, j = msgs[0].len - 1; i < msgs[0].len && i < 4; i++, j--) - msgs[0].buf[j] = (cmd >> (8 * i)) & 0xff; - - if (msgs[0].len > 4) { - cmd = __raw_readq(i2c->twsi_base + SW_TWSI_EXT); - for (i = 0; i < msgs[0].len - 4 && i < 4; i++, j--) - msgs[0].buf[j] = (cmd >> (8 * i)) & 0xff; - } - -err: - return ret; -} - -/* high-level-controller pure write of up to 8 bytes */ -static int octeon_i2c_hlc_write(struct octeon_i2c *i2c, struct i2c_msg *msgs) -{ - int i, j, ret = 0; - u64 cmd; - - octeon_i2c_hlc_enable(i2c); - octeon_i2c_hlc_int_clear(i2c); - - cmd = SW_TWSI_V | SW_TWSI_SOVR; - /* SIZE */ - cmd |= (u64)(msgs[0].len - 1) << SW_TWSI_SIZE_SHIFT; - /* A */ - cmd |= (u64)(msgs[0].addr & 0x7full) << SW_TWSI_ADDR_SHIFT; - - if (msgs[0].flags & I2C_M_TEN) - cmd |= SW_TWSI_OP_10; - else - cmd |= SW_TWSI_OP_7; - - for (i = 0, j = msgs[0].len - 1; i < msgs[0].len && i < 4; i++, j--) - cmd |= (u64)msgs[0].buf[j] << (8 * i); - - if (msgs[0].len > 4) { - u64 ext = 0; - - for (i = 0; i < msgs[0].len - 4 && i < 4; i++, j--) - ext |= (u64)msgs[0].buf[j] << (8 * i); - octeon_i2c_writeq_flush(ext, i2c->twsi_base + SW_TWSI_EXT); - } - - octeon_i2c_writeq_flush(cmd, i2c->twsi_base + SW_TWSI); - ret = octeon_i2c_hlc_wait(i2c); - if (ret) - goto err; - - cmd = __raw_readq(i2c->twsi_base + SW_TWSI); - if ((cmd & SW_TWSI_R) == 0) - return -EAGAIN; - - ret = octeon_i2c_check_status(i2c, false); - -err: - return ret; -} - -/* high-level-controller composite write+read, msg0=addr, msg1=data */ -static int octeon_i2c_hlc_comp_read(struct octeon_i2c *i2c, struct i2c_msg *msgs) -{ - int i, j, ret = 0; - u64 cmd; - - octeon_i2c_hlc_enable(i2c); - - cmd = SW_TWSI_V | SW_TWSI_R | SW_TWSI_SOVR; - /* SIZE */ - cmd |= (u64)(msgs[1].len - 1) << SW_TWSI_SIZE_SHIFT; - /* A */ - cmd |= (u64)(msgs[0].addr & 0x7full) << SW_TWSI_ADDR_SHIFT; - - if (msgs[0].flags & I2C_M_TEN) - cmd |= SW_TWSI_OP_10_IA; - else - cmd |= SW_TWSI_OP_7_IA; - - if (msgs[0].len == 2) { - u64 ext = 0; - - cmd |= SW_TWSI_EIA; - ext = (u64)msgs[0].buf[0] << SW_TWSI_IA_SHIFT; - cmd |= (u64)msgs[0].buf[1] << SW_TWSI_IA_SHIFT; - octeon_i2c_writeq_flush(ext, i2c->twsi_base + SW_TWSI_EXT); - } else { - cmd |= (u64)msgs[0].buf[0] << SW_TWSI_IA_SHIFT; - } - - octeon_i2c_hlc_int_clear(i2c); - octeon_i2c_writeq_flush(cmd, i2c->twsi_base + SW_TWSI); - - ret = octeon_i2c_hlc_wait(i2c); - if (ret) - goto err; - - cmd = __raw_readq(i2c->twsi_base + SW_TWSI); - if ((cmd & SW_TWSI_R) == 0) - return -EAGAIN; - - for (i = 0, j = msgs[1].len - 1; i < msgs[1].len && i < 4; i++, j--) - msgs[1].buf[j] = (cmd >> (8 * i)) & 0xff; - - if (msgs[1].len > 4) { - cmd = __raw_readq(i2c->twsi_base + SW_TWSI_EXT); - for (i = 0; i < msgs[1].len - 4 && i < 4; i++, j--) - msgs[1].buf[j] = (cmd >> (8 * i)) & 0xff; - } - -err: - return ret; -} - -/* high-level-controller composite write+write, m[0]len<=2, m[1]len<=8 */ -static int octeon_i2c_hlc_comp_write(struct octeon_i2c *i2c, struct i2c_msg *msgs) -{ - bool set_ext = false; - int i, j, ret = 0; - u64 cmd, ext = 0; - - octeon_i2c_hlc_enable(i2c); - - cmd = SW_TWSI_V | SW_TWSI_SOVR; - /* SIZE */ - cmd |= (u64)(msgs[1].len - 1) << SW_TWSI_SIZE_SHIFT; - /* A */ - cmd |= (u64)(msgs[0].addr & 0x7full) << SW_TWSI_ADDR_SHIFT; - - if (msgs[0].flags & I2C_M_TEN) - cmd |= SW_TWSI_OP_10_IA; - else - cmd |= SW_TWSI_OP_7_IA; - - if (msgs[0].len == 2) { - cmd |= SW_TWSI_EIA; - ext |= (u64)msgs[0].buf[0] << SW_TWSI_IA_SHIFT; - set_ext = true; - cmd |= (u64)msgs[0].buf[1] << SW_TWSI_IA_SHIFT; - } else { - cmd |= (u64)msgs[0].buf[0] << SW_TWSI_IA_SHIFT; - } - - for (i = 0, j = msgs[1].len - 1; i < msgs[1].len && i < 4; i++, j--) - cmd |= (u64)msgs[1].buf[j] << (8 * i); - - if (msgs[1].len > 4) { - for (i = 0; i < msgs[1].len - 4 && i < 4; i++, j--) - ext |= (u64)msgs[1].buf[j] << (8 * i); - set_ext = true; - } - if (set_ext) - octeon_i2c_writeq_flush(ext, i2c->twsi_base + SW_TWSI_EXT); - - octeon_i2c_hlc_int_clear(i2c); - octeon_i2c_writeq_flush(cmd, i2c->twsi_base + SW_TWSI); - - ret = octeon_i2c_hlc_wait(i2c); - if (ret) - goto err; - - cmd = __raw_readq(i2c->twsi_base + SW_TWSI); - if ((cmd & SW_TWSI_R) == 0) - return -EAGAIN; - - ret = octeon_i2c_check_status(i2c, false); - -err: - return ret; -} - -/* calculate and set clock divisors */ -static void octeon_i2c_set_clock(struct octeon_i2c *i2c) -{ - int tclk, thp_base, inc, thp_idx, mdiv_idx, ndiv_idx, foscl, diff; - int thp = 0x18, mdiv = 2, ndiv = 0, delta_hz = 1000000; - - for (ndiv_idx = 0; ndiv_idx < 8 && delta_hz != 0; ndiv_idx++) { - /* - * An mdiv value of less than 2 seems to not work well - * with ds1337 RTCs, so we constrain it to larger values. - */ - for (mdiv_idx = 15; mdiv_idx >= 2 && delta_hz != 0; mdiv_idx--) { - /* - * For given ndiv and mdiv values check the - * two closest thp values. - */ - tclk = i2c->twsi_freq * (mdiv_idx + 1) * 10; - tclk *= (1 << ndiv_idx); - thp_base = (i2c->sys_freq / (tclk * 2)) - 1; - - for (inc = 0; inc <= 1; inc++) { - thp_idx = thp_base + inc; - if (thp_idx < 5 || thp_idx > 0xff) - continue; - - foscl = i2c->sys_freq / (2 * (thp_idx + 1)); - foscl = foscl / (1 << ndiv_idx); - foscl = foscl / (mdiv_idx + 1) / 10; - diff = abs(foscl - i2c->twsi_freq); - if (diff < delta_hz) { - delta_hz = diff; - thp = thp_idx; - mdiv = mdiv_idx; - ndiv = ndiv_idx; - } - } - } - } - octeon_i2c_reg_write(i2c, SW_TWSI_OP_TWSI_CLK, thp); - octeon_i2c_reg_write(i2c, SW_TWSI_EOP_TWSI_CLKCTL, (mdiv << 3) | ndiv); -} - -static int octeon_i2c_init_lowlevel(struct octeon_i2c *i2c) -{ - u8 status = 0; - int tries; - - /* reset controller */ - octeon_i2c_reg_write(i2c, SW_TWSI_EOP_TWSI_RST, 0); - - for (tries = 10; tries && status != STAT_IDLE; tries--) { - udelay(1); - status = octeon_i2c_stat_read(i2c); - if (status == STAT_IDLE) - break; - } - - if (status != STAT_IDLE) { - dev_err(i2c->dev, "%s: TWSI_RST failed! (0x%x)\n", - __func__, status); - return -EIO; - } - - /* toggle twice to force both teardowns */ - octeon_i2c_hlc_enable(i2c); - octeon_i2c_hlc_disable(i2c); - return 0; -} - -static int octeon_i2c_recovery(struct octeon_i2c *i2c) -{ - int ret; - - ret = i2c_recover_bus(&i2c->adap); - if (ret) - /* recover failed, try hardware re-init */ - ret = octeon_i2c_init_lowlevel(i2c); - return ret; -} - -/** - * octeon_i2c_start - send START to the bus - * @i2c: The struct octeon_i2c - * - * Returns 0 on success, otherwise a negative errno. - */ -static int octeon_i2c_start(struct octeon_i2c *i2c) -{ - int ret; - u8 stat; - - octeon_i2c_hlc_disable(i2c); - - octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB | TWSI_CTL_STA); - ret = octeon_i2c_wait(i2c); - if (ret) - goto error; - - stat = octeon_i2c_stat_read(i2c); - if (stat == STAT_START || stat == STAT_REP_START) - /* START successful, bail out */ - return 0; - -error: - /* START failed, try to recover */ - ret = octeon_i2c_recovery(i2c); - return (ret) ? ret : -EAGAIN; -} - -/* send STOP to the bus */ -static void octeon_i2c_stop(struct octeon_i2c *i2c) -{ - octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB | TWSI_CTL_STP); -} - -/** - * octeon_i2c_write - send data to the bus via low-level controller - * @i2c: The struct octeon_i2c - * @target: Target address - * @data: Pointer to the data to be sent - * @length: Length of the data - * - * The address is sent over the bus, then the data. - * - * Returns 0 on success, otherwise a negative errno. - */ -static int octeon_i2c_write(struct octeon_i2c *i2c, int target, - const u8 *data, int length) -{ - int i, result; - - octeon_i2c_data_write(i2c, target << 1); - octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB); - - result = octeon_i2c_wait(i2c); - if (result) - return result; - - for (i = 0; i < length; i++) { - result = octeon_i2c_check_status(i2c, false); - if (result) - return result; - - octeon_i2c_data_write(i2c, data[i]); - octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB); - - result = octeon_i2c_wait(i2c); - if (result) - return result; - } - - return 0; -} - -/** - * octeon_i2c_read - receive data from the bus via low-level controller - * @i2c: The struct octeon_i2c - * @target: Target address - * @data: Pointer to the location to store the data - * @rlength: Length of the data - * @recv_len: flag for length byte - * - * The address is sent over the bus, then the data is read. - * - * Returns 0 on success, otherwise a negative errno. - */ -static int octeon_i2c_read(struct octeon_i2c *i2c, int target, - u8 *data, u16 *rlength, bool recv_len) -{ - int i, result, length = *rlength; - bool final_read = false; - - octeon_i2c_data_write(i2c, (target << 1) | 1); - octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB); - - result = octeon_i2c_wait(i2c); - if (result) - return result; - - /* address OK ? */ - result = octeon_i2c_check_status(i2c, false); - if (result) - return result; - - for (i = 0; i < length; i++) { - /* - * For the last byte to receive TWSI_CTL_AAK must not be set. - * - * A special case is I2C_M_RECV_LEN where we don't know the - * additional length yet. If recv_len is set we assume we're - * not reading the final byte and therefore need to set - * TWSI_CTL_AAK. - */ - if ((i + 1 == length) && !(recv_len && i == 0)) - final_read = true; - - /* clear iflg to allow next event */ - if (final_read) - octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB); - else - octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB | TWSI_CTL_AAK); - - result = octeon_i2c_wait(i2c); - if (result) - return result; - - data[i] = octeon_i2c_data_read(i2c); - if (recv_len && i == 0) { - if (data[i] > I2C_SMBUS_BLOCK_MAX + 1) - return -EPROTO; - length += data[i]; - } - - result = octeon_i2c_check_status(i2c, final_read); - if (result) - return result; - } - *rlength = length; - return 0; -} - -/** - * octeon_i2c_xfer - The driver's master_xfer function - * @adap: Pointer to the i2c_adapter structure - * @msgs: Pointer to the messages to be processed - * @num: Length of the MSGS array - * - * Returns the number of messages processed, or a negative errno on failure. - */ -static int octeon_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, - int num) -{ - struct octeon_i2c *i2c = i2c_get_adapdata(adap); - int i, ret = 0; - - if (num == 1) { - if (msgs[0].len > 0 && msgs[0].len <= 8) { - if (msgs[0].flags & I2C_M_RD) - ret = octeon_i2c_hlc_read(i2c, msgs); - else - ret = octeon_i2c_hlc_write(i2c, msgs); - goto out; - } - } else if (num == 2) { - if ((msgs[0].flags & I2C_M_RD) == 0 && - (msgs[1].flags & I2C_M_RECV_LEN) == 0 && - msgs[0].len > 0 && msgs[0].len <= 2 && - msgs[1].len > 0 && msgs[1].len <= 8 && - msgs[0].addr == msgs[1].addr) { - if (msgs[1].flags & I2C_M_RD) - ret = octeon_i2c_hlc_comp_read(i2c, msgs); - else - ret = octeon_i2c_hlc_comp_write(i2c, msgs); - goto out; - } - } - - for (i = 0; ret == 0 && i < num; i++) { - struct i2c_msg *pmsg = &msgs[i]; - - /* zero-length messages are not supported */ - if (!pmsg->len) { - ret = -EOPNOTSUPP; - break; - } - - ret = octeon_i2c_start(i2c); - if (ret) - return ret; - - if (pmsg->flags & I2C_M_RD) - ret = octeon_i2c_read(i2c, pmsg->addr, pmsg->buf, - &pmsg->len, pmsg->flags & I2C_M_RECV_LEN); - else - ret = octeon_i2c_write(i2c, pmsg->addr, pmsg->buf, - pmsg->len); - } - octeon_i2c_stop(i2c); -out: - return (ret != 0) ? ret : num; -} - -static int octeon_i2c_get_scl(struct i2c_adapter *adap) -{ - struct octeon_i2c *i2c = i2c_get_adapdata(adap); - u64 state; - - state = octeon_i2c_read_int(i2c); - return state & TWSI_INT_SCL; -} - -static void octeon_i2c_set_scl(struct i2c_adapter *adap, int val) -{ - struct octeon_i2c *i2c = i2c_get_adapdata(adap); - - octeon_i2c_write_int(i2c, TWSI_INT_SCL_OVR); -} - -static int octeon_i2c_get_sda(struct i2c_adapter *adap) -{ - struct octeon_i2c *i2c = i2c_get_adapdata(adap); - u64 state; - - state = octeon_i2c_read_int(i2c); - return state & TWSI_INT_SDA; -} - -static void octeon_i2c_prepare_recovery(struct i2c_adapter *adap) -{ - struct octeon_i2c *i2c = i2c_get_adapdata(adap); - - /* - * The stop resets the state machine, does not _transmit_ STOP unless - * engine was active. - */ - octeon_i2c_stop(i2c); - - octeon_i2c_hlc_disable(i2c); - octeon_i2c_write_int(i2c, 0); -} - -static void octeon_i2c_unprepare_recovery(struct i2c_adapter *adap) -{ - struct octeon_i2c *i2c = i2c_get_adapdata(adap); - - octeon_i2c_write_int(i2c, 0); -} - -static struct i2c_bus_recovery_info octeon_i2c_recovery_info = { - .recover_bus = i2c_generic_scl_recovery, - .get_scl = octeon_i2c_get_scl, - .set_scl = octeon_i2c_set_scl, - .get_sda = octeon_i2c_get_sda, - .prepare_recovery = octeon_i2c_prepare_recovery, - .unprepare_recovery = octeon_i2c_unprepare_recovery, -}; - static u32 octeon_i2c_functionality(struct i2c_adapter *adap) { return I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK) | From 22d40209de3bb50cbffcc6b79f2f7c5d689d185f Mon Sep 17 00:00:00 2001 From: Jan Glauber Date: Wed, 24 Aug 2016 23:25:44 +0200 Subject: [PATCH 15/71] i2c: thunderx: Add i2c driver for ThunderX SOC The ThunderX SOC uses the same i2c block as the Octeon SOC. The main difference is that on ThunderX the device is a PCI device so device probing is done via PCI, interrupts are MSI-X. The clock rates can be set via device tree or ACPI. Signed-off-by: Jan Glauber Signed-off-by: Wolfram Sang --- drivers/i2c/busses/Kconfig | 10 ++ drivers/i2c/busses/Makefile | 2 + drivers/i2c/busses/i2c-octeon-core.h | 16 +- drivers/i2c/busses/i2c-thunderx-pcidrv.c | 209 +++++++++++++++++++++++ 4 files changed, 234 insertions(+), 3 deletions(-) create mode 100644 drivers/i2c/busses/i2c-thunderx-pcidrv.c diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 5c3993b26129..d69a3420c8dc 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -956,6 +956,16 @@ config I2C_OCTEON This driver can also be built as a module. If so, the module will be called i2c-octeon. +config I2C_THUNDERX + tristate "Cavium ThunderX I2C bus support" + depends on 64BIT && PCI && (ARM64 || COMPILE_TEST) + help + Say yes if you want to support the I2C serial bus on Cavium + ThunderX SOC. + + This driver can also be built as a module. If so, the module + will be called i2c-thunderx. + config I2C_XILINX tristate "Xilinx I2C Controller" depends on HAS_IOMEM diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index f975263a5da3..29764cc20a44 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -93,6 +93,8 @@ obj-$(CONFIG_I2C_VERSATILE) += i2c-versatile.o obj-$(CONFIG_I2C_WMT) += i2c-wmt.o i2c-octeon-objs := i2c-octeon-core.o i2c-octeon-platdrv.o obj-$(CONFIG_I2C_OCTEON) += i2c-octeon.o +i2c-thunderx-objs := i2c-octeon-core.o i2c-thunderx-pcidrv.o +obj-$(CONFIG_I2C_THUNDERX) += i2c-thunderx.o obj-$(CONFIG_I2C_XILINX) += i2c-xiic.o obj-$(CONFIG_I2C_XLR) += i2c-xlr.o obj-$(CONFIG_I2C_XLP9XX) += i2c-xlp9xx.o diff --git a/drivers/i2c/busses/i2c-octeon-core.h b/drivers/i2c/busses/i2c-octeon-core.h index 81c6a81cd308..33c7e1fb178c 100644 --- a/drivers/i2c/busses/i2c-octeon-core.h +++ b/drivers/i2c/busses/i2c-octeon-core.h @@ -8,9 +8,15 @@ #include /* Register offsets */ -#define SW_TWSI 0x00 -#define TWSI_INT 0x10 -#define SW_TWSI_EXT 0x18 +#if IS_ENABLED(CONFIG_I2C_THUNDERX) + #define SW_TWSI 0x1000 + #define TWSI_INT 0x1010 + #define SW_TWSI_EXT 0x1018 +#else + #define SW_TWSI 0x00 + #define TWSI_INT 0x10 + #define SW_TWSI_EXT 0x18 +#endif /* Controller command patterns */ #define SW_TWSI_V BIT_ULL(63) /* Valid bit */ @@ -94,6 +100,7 @@ struct octeon_i2c { wait_queue_head_t queue; struct i2c_adapter adap; + struct clk *clk; int irq; int hlc_irq; /* For cn7890 only */ u32 twsi_freq; @@ -109,6 +116,9 @@ struct octeon_i2c { void (*hlc_int_disable)(struct octeon_i2c *); atomic_t int_enable_cnt; atomic_t hlc_int_enable_cnt; +#if IS_ENABLED(CONFIG_I2C_THUNDERX) + struct msix_entry i2c_msix; +#endif }; static inline void octeon_i2c_writeq_flush(u64 val, void __iomem *addr) diff --git a/drivers/i2c/busses/i2c-thunderx-pcidrv.c b/drivers/i2c/busses/i2c-thunderx-pcidrv.c new file mode 100644 index 000000000000..0dcebe2a5c4f --- /dev/null +++ b/drivers/i2c/busses/i2c-thunderx-pcidrv.c @@ -0,0 +1,209 @@ +/* + * Cavium ThunderX i2c driver. + * + * Copyright (C) 2015,2016 Cavium Inc. + * Authors: Fred Martin + * Jan Glauber + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "i2c-octeon-core.h" + +#define DRV_NAME "i2c-thunderx" + +#define PCI_DEVICE_ID_THUNDER_TWSI 0xa012 + +#define SYS_FREQ_DEFAULT 700000000 + +#define TWSI_INT_ENA_W1C 0x1028 +#define TWSI_INT_ENA_W1S 0x1030 + +/* + * Enable the CORE interrupt. + * The interrupt will be asserted when there is non-STAT_IDLE state in the + * SW_TWSI_EOP_TWSI_STAT register. + */ +static void thunder_i2c_int_enable(struct octeon_i2c *i2c) +{ + octeon_i2c_writeq_flush(TWSI_INT_CORE_INT, + i2c->twsi_base + TWSI_INT_ENA_W1S); +} + +/* + * Disable the CORE interrupt. + */ +static void thunder_i2c_int_disable(struct octeon_i2c *i2c) +{ + octeon_i2c_writeq_flush(TWSI_INT_CORE_INT, + i2c->twsi_base + TWSI_INT_ENA_W1C); +} + +static void thunder_i2c_hlc_int_enable(struct octeon_i2c *i2c) +{ + octeon_i2c_writeq_flush(TWSI_INT_ST_INT | TWSI_INT_TS_INT, + i2c->twsi_base + TWSI_INT_ENA_W1S); +} + +static void thunder_i2c_hlc_int_disable(struct octeon_i2c *i2c) +{ + octeon_i2c_writeq_flush(TWSI_INT_ST_INT | TWSI_INT_TS_INT, + i2c->twsi_base + TWSI_INT_ENA_W1C); +} + +static u32 thunderx_i2c_functionality(struct i2c_adapter *adap) +{ + return I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK) | + I2C_FUNC_SMBUS_READ_BLOCK_DATA | I2C_SMBUS_BLOCK_PROC_CALL; +} + +static const struct i2c_algorithm thunderx_i2c_algo = { + .master_xfer = octeon_i2c_xfer, + .functionality = thunderx_i2c_functionality, +}; + +static struct i2c_adapter thunderx_i2c_ops = { + .owner = THIS_MODULE, + .name = "ThunderX adapter", + .algo = &thunderx_i2c_algo, +}; + +static void thunder_i2c_clock_enable(struct device *dev, struct octeon_i2c *i2c) +{ + int ret; + + i2c->clk = clk_get(dev, NULL); + if (IS_ERR(i2c->clk)) { + i2c->clk = NULL; + goto skip; + } + + ret = clk_prepare_enable(i2c->clk); + if (ret) + goto skip; + i2c->sys_freq = clk_get_rate(i2c->clk); + +skip: + if (!i2c->sys_freq) + i2c->sys_freq = SYS_FREQ_DEFAULT; +} + +static void thunder_i2c_clock_disable(struct device *dev, struct clk *clk) +{ + if (!clk) + return; + clk_disable_unprepare(clk); + clk_put(clk); +} + +static int thunder_i2c_probe_pci(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + struct device *dev = &pdev->dev; + struct octeon_i2c *i2c; + int ret; + + i2c = devm_kzalloc(dev, sizeof(*i2c), GFP_KERNEL); + if (!i2c) + return -ENOMEM; + + i2c->dev = dev; + pci_set_drvdata(pdev, i2c); + ret = pcim_enable_device(pdev); + if (ret) + return ret; + + ret = pci_request_regions(pdev, DRV_NAME); + if (ret) + return ret; + + i2c->twsi_base = pcim_iomap(pdev, 0, pci_resource_len(pdev, 0)); + if (!i2c->twsi_base) + return -EINVAL; + + thunder_i2c_clock_enable(dev, i2c); + ret = device_property_read_u32(dev, "clock-frequency", &i2c->twsi_freq); + if (ret) + i2c->twsi_freq = 100000; + + init_waitqueue_head(&i2c->queue); + + i2c->int_enable = thunder_i2c_int_enable; + i2c->int_disable = thunder_i2c_int_disable; + i2c->hlc_int_enable = thunder_i2c_hlc_int_enable; + i2c->hlc_int_disable = thunder_i2c_hlc_int_disable; + + ret = pci_enable_msix(pdev, &i2c->i2c_msix, 1); + if (ret) + goto error; + + ret = devm_request_irq(dev, i2c->i2c_msix.vector, octeon_i2c_isr, 0, + DRV_NAME, i2c); + if (ret) + goto error; + + ret = octeon_i2c_init_lowlevel(i2c); + if (ret) + goto error; + + octeon_i2c_set_clock(i2c); + + i2c->adap = thunderx_i2c_ops; + i2c->adap.retries = 5; + i2c->adap.bus_recovery_info = &octeon_i2c_recovery_info; + i2c->adap.dev.parent = dev; + i2c->adap.dev.of_node = pdev->dev.of_node; + snprintf(i2c->adap.name, sizeof(i2c->adap.name), + "Cavium ThunderX i2c adapter at %s", dev_name(dev)); + i2c_set_adapdata(&i2c->adap, i2c); + + ret = i2c_add_adapter(&i2c->adap); + if (ret) + goto error; + + dev_info(i2c->dev, "Probed. Set system clock to %u\n", i2c->sys_freq); + return 0; + +error: + thunder_i2c_clock_disable(dev, i2c->clk); + return ret; +} + +static void thunder_i2c_remove_pci(struct pci_dev *pdev) +{ + struct octeon_i2c *i2c = pci_get_drvdata(pdev); + + thunder_i2c_clock_disable(&pdev->dev, i2c->clk); + i2c_del_adapter(&i2c->adap); +} + +static const struct pci_device_id thunder_i2c_pci_id_table[] = { + { PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, PCI_DEVICE_ID_THUNDER_TWSI) }, + { 0, } +}; + +MODULE_DEVICE_TABLE(pci, thunder_i2c_pci_id_table); + +static struct pci_driver thunder_i2c_pci_driver = { + .name = DRV_NAME, + .id_table = thunder_i2c_pci_id_table, + .probe = thunder_i2c_probe_pci, + .remove = thunder_i2c_remove_pci, +}; + +module_pci_driver(thunder_i2c_pci_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Fred Martin "); +MODULE_DESCRIPTION("I2C-Bus adapter for Cavium ThunderX SOC"); From 1e5866711accf16e931c4f8174cf898b554e9f4a Mon Sep 17 00:00:00 2001 From: Jan Glauber Date: Wed, 24 Aug 2016 23:25:45 +0200 Subject: [PATCH 16/71] i2c: thunderx: Add SMBUS alert support Add SMBUS alert interrupt support. For now only device tree is supported for specifying the alert. In case of ACPI an error is returned. Signed-off-by: Jan Glauber Signed-off-by: Wolfram Sang --- drivers/i2c/busses/Kconfig | 1 + drivers/i2c/busses/i2c-octeon-core.h | 3 ++ drivers/i2c/busses/i2c-thunderx-pcidrv.c | 46 ++++++++++++++++++++++++ 3 files changed, 50 insertions(+) diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index d69a3420c8dc..1f3239ead037 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -959,6 +959,7 @@ config I2C_OCTEON config I2C_THUNDERX tristate "Cavium ThunderX I2C bus support" depends on 64BIT && PCI && (ARM64 || COMPILE_TEST) + select I2C_SMBUS help Say yes if you want to support the I2C serial bus on Cavium ThunderX SOC. diff --git a/drivers/i2c/busses/i2c-octeon-core.h b/drivers/i2c/busses/i2c-octeon-core.h index 33c7e1fb178c..2ed6f7a36b88 100644 --- a/drivers/i2c/busses/i2c-octeon-core.h +++ b/drivers/i2c/busses/i2c-octeon-core.h @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -119,6 +120,8 @@ struct octeon_i2c { #if IS_ENABLED(CONFIG_I2C_THUNDERX) struct msix_entry i2c_msix; #endif + struct i2c_smbus_alert_setup alert_data; + struct i2c_client *ara; }; static inline void octeon_i2c_writeq_flush(u64 val, void __iomem *addr) diff --git a/drivers/i2c/busses/i2c-thunderx-pcidrv.c b/drivers/i2c/busses/i2c-thunderx-pcidrv.c index 0dcebe2a5c4f..e8c3ce0eaf4d 100644 --- a/drivers/i2c/busses/i2c-thunderx-pcidrv.c +++ b/drivers/i2c/busses/i2c-thunderx-pcidrv.c @@ -14,9 +14,11 @@ #include #include #include +#include #include #include #include +#include #include #include "i2c-octeon-core.h" @@ -107,6 +109,44 @@ static void thunder_i2c_clock_disable(struct device *dev, struct clk *clk) clk_put(clk); } +static int thunder_i2c_smbus_setup_of(struct octeon_i2c *i2c, + struct device_node *node) +{ + u32 type; + + if (!node) + return -EINVAL; + + i2c->alert_data.irq = irq_of_parse_and_map(node, 0); + if (!i2c->alert_data.irq) + return -EINVAL; + + type = irqd_get_trigger_type(irq_get_irq_data(i2c->alert_data.irq)); + i2c->alert_data.alert_edge_triggered = + (type & IRQ_TYPE_LEVEL_MASK) ? 1 : 0; + + i2c->ara = i2c_setup_smbus_alert(&i2c->adap, &i2c->alert_data); + if (!i2c->ara) + return -ENODEV; + return 0; +} + +static int thunder_i2c_smbus_setup(struct octeon_i2c *i2c, + struct device_node *node) +{ + /* TODO: ACPI support */ + if (!acpi_disabled) + return -EOPNOTSUPP; + + return thunder_i2c_smbus_setup_of(i2c, node); +} + +static void thunder_i2c_smbus_remove(struct octeon_i2c *i2c) +{ + if (i2c->ara) + i2c_unregister_device(i2c->ara); +} + static int thunder_i2c_probe_pci(struct pci_dev *pdev, const struct pci_device_id *ent) { @@ -173,6 +213,11 @@ static int thunder_i2c_probe_pci(struct pci_dev *pdev, goto error; dev_info(i2c->dev, "Probed. Set system clock to %u\n", i2c->sys_freq); + + ret = thunder_i2c_smbus_setup(i2c, pdev->dev.of_node); + if (ret) + dev_info(dev, "SMBUS alert not active on this bus\n"); + return 0; error: @@ -184,6 +229,7 @@ static void thunder_i2c_remove_pci(struct pci_dev *pdev) { struct octeon_i2c *i2c = pci_get_drvdata(pdev); + thunder_i2c_smbus_remove(i2c); thunder_i2c_clock_disable(&pdev->dev, i2c->clk); i2c_del_adapter(&i2c->adap); } From 97d970046a15bf5baac849dbeac56310c8ee3966 Mon Sep 17 00:00:00 2001 From: Jan Glauber Date: Wed, 24 Aug 2016 23:25:46 +0200 Subject: [PATCH 17/71] i2c: octeon,thunderx: Move register offsets to struct The register offsets are different between Octeon and ThunderX so move them into the algorithm struct and get rid of the define. Signed-off-by: Jan Glauber Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-octeon-core.c | 28 +++++++++---------- drivers/i2c/busses/i2c-octeon-core.h | 35 ++++++++++++------------ drivers/i2c/busses/i2c-octeon-platdrv.c | 4 +++ drivers/i2c/busses/i2c-thunderx-pcidrv.c | 4 +++ 4 files changed, 40 insertions(+), 31 deletions(-) diff --git a/drivers/i2c/busses/i2c-octeon-core.c b/drivers/i2c/busses/i2c-octeon-core.c index 23384efc101a..a327a5fa453e 100644 --- a/drivers/i2c/busses/i2c-octeon-core.c +++ b/drivers/i2c/busses/i2c-octeon-core.c @@ -99,7 +99,7 @@ static int octeon_i2c_wait(struct octeon_i2c *i2c) static bool octeon_i2c_hlc_test_valid(struct octeon_i2c *i2c) { - return (__raw_readq(i2c->twsi_base + SW_TWSI) & SW_TWSI_V) == 0; + return (__raw_readq(i2c->twsi_base + SW_TWSI(i2c)) & SW_TWSI_V) == 0; } static bool octeon_i2c_hlc_test_ready(struct octeon_i2c *i2c, bool *first) @@ -446,12 +446,12 @@ static int octeon_i2c_hlc_read(struct octeon_i2c *i2c, struct i2c_msg *msgs) else cmd |= SW_TWSI_OP_7; - octeon_i2c_writeq_flush(cmd, i2c->twsi_base + SW_TWSI); + octeon_i2c_writeq_flush(cmd, i2c->twsi_base + SW_TWSI(i2c)); ret = octeon_i2c_hlc_wait(i2c); if (ret) goto err; - cmd = __raw_readq(i2c->twsi_base + SW_TWSI); + cmd = __raw_readq(i2c->twsi_base + SW_TWSI(i2c)); if ((cmd & SW_TWSI_R) == 0) return -EAGAIN; @@ -459,7 +459,7 @@ static int octeon_i2c_hlc_read(struct octeon_i2c *i2c, struct i2c_msg *msgs) msgs[0].buf[j] = (cmd >> (8 * i)) & 0xff; if (msgs[0].len > 4) { - cmd = __raw_readq(i2c->twsi_base + SW_TWSI_EXT); + cmd = __raw_readq(i2c->twsi_base + SW_TWSI_EXT(i2c)); for (i = 0; i < msgs[0].len - 4 && i < 4; i++, j--) msgs[0].buf[j] = (cmd >> (8 * i)) & 0xff; } @@ -496,15 +496,15 @@ static int octeon_i2c_hlc_write(struct octeon_i2c *i2c, struct i2c_msg *msgs) for (i = 0; i < msgs[0].len - 4 && i < 4; i++, j--) ext |= (u64)msgs[0].buf[j] << (8 * i); - octeon_i2c_writeq_flush(ext, i2c->twsi_base + SW_TWSI_EXT); + octeon_i2c_writeq_flush(ext, i2c->twsi_base + SW_TWSI_EXT(i2c)); } - octeon_i2c_writeq_flush(cmd, i2c->twsi_base + SW_TWSI); + octeon_i2c_writeq_flush(cmd, i2c->twsi_base + SW_TWSI(i2c)); ret = octeon_i2c_hlc_wait(i2c); if (ret) goto err; - cmd = __raw_readq(i2c->twsi_base + SW_TWSI); + cmd = __raw_readq(i2c->twsi_base + SW_TWSI(i2c)); if ((cmd & SW_TWSI_R) == 0) return -EAGAIN; @@ -539,19 +539,19 @@ static int octeon_i2c_hlc_comp_read(struct octeon_i2c *i2c, struct i2c_msg *msgs cmd |= SW_TWSI_EIA; ext = (u64)msgs[0].buf[0] << SW_TWSI_IA_SHIFT; cmd |= (u64)msgs[0].buf[1] << SW_TWSI_IA_SHIFT; - octeon_i2c_writeq_flush(ext, i2c->twsi_base + SW_TWSI_EXT); + octeon_i2c_writeq_flush(ext, i2c->twsi_base + SW_TWSI_EXT(i2c)); } else { cmd |= (u64)msgs[0].buf[0] << SW_TWSI_IA_SHIFT; } octeon_i2c_hlc_int_clear(i2c); - octeon_i2c_writeq_flush(cmd, i2c->twsi_base + SW_TWSI); + octeon_i2c_writeq_flush(cmd, i2c->twsi_base + SW_TWSI(i2c)); ret = octeon_i2c_hlc_wait(i2c); if (ret) goto err; - cmd = __raw_readq(i2c->twsi_base + SW_TWSI); + cmd = __raw_readq(i2c->twsi_base + SW_TWSI(i2c)); if ((cmd & SW_TWSI_R) == 0) return -EAGAIN; @@ -559,7 +559,7 @@ static int octeon_i2c_hlc_comp_read(struct octeon_i2c *i2c, struct i2c_msg *msgs msgs[1].buf[j] = (cmd >> (8 * i)) & 0xff; if (msgs[1].len > 4) { - cmd = __raw_readq(i2c->twsi_base + SW_TWSI_EXT); + cmd = __raw_readq(i2c->twsi_base + SW_TWSI_EXT(i2c)); for (i = 0; i < msgs[1].len - 4 && i < 4; i++, j--) msgs[1].buf[j] = (cmd >> (8 * i)) & 0xff; } @@ -606,16 +606,16 @@ static int octeon_i2c_hlc_comp_write(struct octeon_i2c *i2c, struct i2c_msg *msg set_ext = true; } if (set_ext) - octeon_i2c_writeq_flush(ext, i2c->twsi_base + SW_TWSI_EXT); + octeon_i2c_writeq_flush(ext, i2c->twsi_base + SW_TWSI_EXT(i2c)); octeon_i2c_hlc_int_clear(i2c); - octeon_i2c_writeq_flush(cmd, i2c->twsi_base + SW_TWSI); + octeon_i2c_writeq_flush(cmd, i2c->twsi_base + SW_TWSI(i2c)); ret = octeon_i2c_hlc_wait(i2c); if (ret) goto err; - cmd = __raw_readq(i2c->twsi_base + SW_TWSI); + cmd = __raw_readq(i2c->twsi_base + SW_TWSI(i2c)); if ((cmd & SW_TWSI_R) == 0) return -EAGAIN; diff --git a/drivers/i2c/busses/i2c-octeon-core.h b/drivers/i2c/busses/i2c-octeon-core.h index 2ed6f7a36b88..87151ea74acd 100644 --- a/drivers/i2c/busses/i2c-octeon-core.h +++ b/drivers/i2c/busses/i2c-octeon-core.h @@ -8,17 +8,6 @@ #include #include -/* Register offsets */ -#if IS_ENABLED(CONFIG_I2C_THUNDERX) - #define SW_TWSI 0x1000 - #define TWSI_INT 0x1010 - #define SW_TWSI_EXT 0x1018 -#else - #define SW_TWSI 0x00 - #define TWSI_INT 0x10 - #define SW_TWSI_EXT 0x18 -#endif - /* Controller command patterns */ #define SW_TWSI_V BIT_ULL(63) /* Valid bit */ #define SW_TWSI_EIA BIT_ULL(61) /* Extended internal address */ @@ -98,9 +87,21 @@ #define I2C_OCTEON_EVENT_WAIT 80 /* microseconds */ +/* Register offsets */ +struct octeon_i2c_reg_offset { + unsigned int sw_twsi; + unsigned int twsi_int; + unsigned int sw_twsi_ext; +}; + +#define SW_TWSI(x) (x->roff.sw_twsi) +#define TWSI_INT(x) (x->roff.twsi_int) +#define SW_TWSI_EXT(x) (x->roff.sw_twsi_ext) + struct octeon_i2c { wait_queue_head_t queue; struct i2c_adapter adap; + struct octeon_i2c_reg_offset roff; struct clk *clk; int irq; int hlc_irq; /* For cn7890 only */ @@ -142,9 +143,9 @@ static inline void octeon_i2c_reg_write(struct octeon_i2c *i2c, u64 eop_reg, u8 { u64 tmp; - __raw_writeq(SW_TWSI_V | eop_reg | data, i2c->twsi_base + SW_TWSI); + __raw_writeq(SW_TWSI_V | eop_reg | data, i2c->twsi_base + SW_TWSI(i2c)); do { - tmp = __raw_readq(i2c->twsi_base + SW_TWSI); + tmp = __raw_readq(i2c->twsi_base + SW_TWSI(i2c)); } while ((tmp & SW_TWSI_V) != 0); } @@ -166,9 +167,9 @@ static inline u8 octeon_i2c_reg_read(struct octeon_i2c *i2c, u64 eop_reg) { u64 tmp; - __raw_writeq(SW_TWSI_V | eop_reg | SW_TWSI_R, i2c->twsi_base + SW_TWSI); + __raw_writeq(SW_TWSI_V | eop_reg | SW_TWSI_R, i2c->twsi_base + SW_TWSI(i2c)); do { - tmp = __raw_readq(i2c->twsi_base + SW_TWSI); + tmp = __raw_readq(i2c->twsi_base + SW_TWSI(i2c)); } while ((tmp & SW_TWSI_V) != 0); return tmp & 0xFF; @@ -189,7 +190,7 @@ static inline u8 octeon_i2c_reg_read(struct octeon_i2c *i2c, u64 eop_reg) */ static inline u64 octeon_i2c_read_int(struct octeon_i2c *i2c) { - return __raw_readq(i2c->twsi_base + TWSI_INT); + return __raw_readq(i2c->twsi_base + TWSI_INT(i2c)); } /** @@ -199,7 +200,7 @@ static inline u64 octeon_i2c_read_int(struct octeon_i2c *i2c) */ static inline void octeon_i2c_write_int(struct octeon_i2c *i2c, u64 data) { - octeon_i2c_writeq_flush(data, i2c->twsi_base + TWSI_INT); + octeon_i2c_writeq_flush(data, i2c->twsi_base + TWSI_INT(i2c)); } /* Prototypes */ diff --git a/drivers/i2c/busses/i2c-octeon-platdrv.c b/drivers/i2c/busses/i2c-octeon-platdrv.c index 53fa9a0d96bb..2861821bbd60 100644 --- a/drivers/i2c/busses/i2c-octeon-platdrv.c +++ b/drivers/i2c/busses/i2c-octeon-platdrv.c @@ -163,6 +163,10 @@ static int octeon_i2c_probe(struct platform_device *pdev) } i2c->dev = &pdev->dev; + i2c->roff.sw_twsi = 0x00; + i2c->roff.twsi_int = 0x10; + i2c->roff.sw_twsi_ext = 0x18; + res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); i2c->twsi_base = devm_ioremap_resource(&pdev->dev, res_mem); if (IS_ERR(i2c->twsi_base)) { diff --git a/drivers/i2c/busses/i2c-thunderx-pcidrv.c b/drivers/i2c/busses/i2c-thunderx-pcidrv.c index e8c3ce0eaf4d..bba5b429f69c 100644 --- a/drivers/i2c/busses/i2c-thunderx-pcidrv.c +++ b/drivers/i2c/busses/i2c-thunderx-pcidrv.c @@ -158,6 +158,10 @@ static int thunder_i2c_probe_pci(struct pci_dev *pdev, if (!i2c) return -ENOMEM; + i2c->roff.sw_twsi = 0x1000; + i2c->roff.twsi_int = 0x1010; + i2c->roff.sw_twsi_ext = 0x1018; + i2c->dev = dev; pci_set_drvdata(pdev, i2c); ret = pcim_enable_device(pdev); From caa505f20df01b326ca99dcace0c4656298d94f3 Mon Sep 17 00:00:00 2001 From: Jan Glauber Date: Wed, 24 Aug 2016 23:25:47 +0200 Subject: [PATCH 18/71] i2c: octeon: Sort include files alphabetically Sort include files alphabetically to reduce probability of merge conflicts. Signed-off-by: Jan Glauber Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-octeon-platdrv.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/i2c/busses/i2c-octeon-platdrv.c b/drivers/i2c/busses/i2c-octeon-platdrv.c index 2861821bbd60..917524ce6890 100644 --- a/drivers/i2c/busses/i2c-octeon-platdrv.c +++ b/drivers/i2c/busses/i2c-octeon-platdrv.c @@ -12,16 +12,16 @@ */ #include -#include +#include +#include #include +#include #include #include -#include +#include +#include #include #include -#include -#include -#include #include #include "i2c-octeon-core.h" From eefbfe011f68a6efcdeb244bf9f917499069daab Mon Sep 17 00:00:00 2001 From: Jan Glauber Date: Wed, 24 Aug 2016 23:25:48 +0200 Subject: [PATCH 19/71] i2c: octeon: Use booleon values for booleon variables Initialize booleon values with true instead of 1. Signed-off-by: Jan Glauber Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-octeon-core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/i2c/busses/i2c-octeon-core.c b/drivers/i2c/busses/i2c-octeon-core.c index a327a5fa453e..f45ea5eef513 100644 --- a/drivers/i2c/busses/i2c-octeon-core.c +++ b/drivers/i2c/busses/i2c-octeon-core.c @@ -63,7 +63,7 @@ static bool octeon_i2c_test_ready(struct octeon_i2c *i2c, bool *first) static int octeon_i2c_wait(struct octeon_i2c *i2c) { long time_left; - bool first = 1; + bool first = true; /* * Some chip revisions don't assert the irq in the interrupt @@ -176,7 +176,7 @@ static void octeon_i2c_hlc_disable(struct octeon_i2c *i2c) */ static int octeon_i2c_hlc_wait(struct octeon_i2c *i2c) { - bool first = 1; + bool first = true; int time_left; /* From f9484852567987158545523d6d6325d9cdf482b1 Mon Sep 17 00:00:00 2001 From: Jan Glauber Date: Wed, 24 Aug 2016 23:25:49 +0200 Subject: [PATCH 20/71] i2c: octeon: thunderx: Add MAINTAINERS entry The i2c Octeon and ThunderX drivers are maintained by Cavium. While at it fix the whitespace errors of the next entry. Signed-off-by: Jan Glauber Acked-by: David Daney Signed-off-by: Wolfram Sang --- MAINTAINERS | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 0bbe4b105c34..4b9a6ae6aaf9 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2878,6 +2878,14 @@ S: Maintained F: drivers/iio/light/cm* F: Documentation/devicetree/bindings/i2c/trivial-devices.txt +CAVIUM I2C DRIVER +M: Jan Glauber +M: David Daney +W: http://www.cavium.com +S: Supported +F: drivers/i2c/busses/i2c-octeon* +F: drivers/i2c/busses/i2c-thunderx* + CAVIUM LIQUIDIO NETWORK DRIVER M: Derek Chickles M: Satanand Burla From 19c0a5399fe46218c2b5a5c17a01cf60f91ff5ae Mon Sep 17 00:00:00 2001 From: Weifeng Voon Date: Fri, 12 Aug 2016 17:02:47 +0300 Subject: [PATCH 21/71] i2c: designware: Move clk_freq into struct dw_i2c_dev I2c designware controller operate speed is configured in the register IC_CON. Previously the operate speed is determined by a local variable clk_freq. This patch will move the local variable clk_freq into struct dw_i2c_dev. This change will ease the set and get of the clk_freq. Signed-off-by: Weifeng Voon Signed-off-by: Jarkko Nikula Reviewed-by: Andy Shevchenko Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-designware-core.h | 2 ++ drivers/i2c/busses/i2c-designware-platdrv.c | 12 ++++++------ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/i2c/busses/i2c-designware-core.h b/drivers/i2c/busses/i2c-designware-core.h index 38493a7142ad..63f6d4acee39 100644 --- a/drivers/i2c/busses/i2c-designware-core.h +++ b/drivers/i2c/busses/i2c-designware-core.h @@ -57,6 +57,7 @@ * @tx_fifo_depth: depth of the hardware tx fifo * @rx_fifo_depth: depth of the hardware rx fifo * @rx_outstanding: current master-rx elements in tx fifo + * @clk_freq: bus clock frequency * @ss_hcnt: standard speed HCNT value * @ss_lcnt: standard speed LCNT value * @fs_hcnt: fast speed HCNT value @@ -96,6 +97,7 @@ struct dw_i2c_dev { unsigned int tx_fifo_depth; unsigned int rx_fifo_depth; int rx_outstanding; + u32 clk_freq; u32 sda_hold_time; u32 sda_falling_time; u32 scl_falling_time; diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c index d656657b805c..1608cf4d3263 100644 --- a/drivers/i2c/busses/i2c-designware-platdrv.c +++ b/drivers/i2c/busses/i2c-designware-platdrv.c @@ -155,7 +155,7 @@ static int dw_i2c_plat_probe(struct platform_device *pdev) struct i2c_adapter *adap; struct resource *mem; int irq, r; - u32 clk_freq, ht = 0; + u32 ht = 0; irq = platform_get_irq(pdev, 0); if (irq < 0) @@ -175,10 +175,10 @@ static int dw_i2c_plat_probe(struct platform_device *pdev) platform_set_drvdata(pdev, dev); /* fast mode by default because of legacy reasons */ - clk_freq = 400000; + dev->clk_freq = 400000; if (pdata) { - clk_freq = pdata->i2c_scl_freq; + dev->clk_freq = pdata->i2c_scl_freq; } else { device_property_read_u32(&pdev->dev, "i2c-sda-hold-time-ns", &ht); @@ -187,7 +187,7 @@ static int dw_i2c_plat_probe(struct platform_device *pdev) device_property_read_u32(&pdev->dev, "i2c-scl-falling-time-ns", &dev->scl_falling_time); device_property_read_u32(&pdev->dev, "clock-frequency", - &clk_freq); + &dev->clk_freq); } if (has_acpi_companion(&pdev->dev)) @@ -196,7 +196,7 @@ static int dw_i2c_plat_probe(struct platform_device *pdev) /* * Only standard mode at 100kHz and fast mode at 400kHz are supported. */ - if (clk_freq != 100000 && clk_freq != 400000) { + if (dev->clk_freq != 100000 && dev->clk_freq != 400000) { dev_err(&pdev->dev, "Only 100kHz and 400kHz supported"); return -EINVAL; } @@ -212,7 +212,7 @@ static int dw_i2c_plat_probe(struct platform_device *pdev) I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_I2C_BLOCK; - if (clk_freq == 100000) + if (dev->clk_freq == 100000) dev->master_cfg = DW_IC_CON_MASTER | DW_IC_CON_SLAVE_DISABLE | DW_IC_CON_RESTART_EN | DW_IC_CON_SPEED_STD; else From a92ec1746f10e339220bf186c4f6cce531b8a7ee Mon Sep 17 00:00:00 2001 From: Weifeng Voon Date: Fri, 12 Aug 2016 17:02:48 +0300 Subject: [PATCH 22/71] i2c: designware: get fast plus and high speed *CNT configuration I2C designware controller can run at fast mode plus and high speed. This patch adds the capability to get the HCNT, LCNT configuration via FPCN (fast plus) and HSCN (high speed) ACPI method. Signed-off-by: Weifeng Voon Signed-off-by: Jarkko Nikula Reviewed-by: Andy Shevchenko Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-designware-core.h | 8 ++++++++ drivers/i2c/busses/i2c-designware-platdrv.c | 2 ++ 2 files changed, 10 insertions(+) diff --git a/drivers/i2c/busses/i2c-designware-core.h b/drivers/i2c/busses/i2c-designware-core.h index 63f6d4acee39..84866db2d04f 100644 --- a/drivers/i2c/busses/i2c-designware-core.h +++ b/drivers/i2c/busses/i2c-designware-core.h @@ -62,6 +62,10 @@ * @ss_lcnt: standard speed LCNT value * @fs_hcnt: fast speed HCNT value * @fs_lcnt: fast speed LCNT value + * @fp_hcnt: fast plus HCNT value + * @fp_lcnt: fast plus LCNT value + * @hs_hcnt: high speed HCNT value + * @hs_lcnt: high speed LCNT value * @acquire_lock: function to acquire a hardware lock on the bus * @release_lock: function to release a hardware lock on the bus * @pm_runtime_disabled: true if pm runtime is disabled @@ -105,6 +109,10 @@ struct dw_i2c_dev { u16 ss_lcnt; u16 fs_hcnt; u16 fs_lcnt; + u16 fp_hcnt; + u16 fp_lcnt; + u16 hs_hcnt; + u16 hs_lcnt; int (*acquire_lock)(struct dw_i2c_dev *dev); void (*release_lock)(struct dw_i2c_dev *dev); bool pm_runtime_disabled; diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c index 1608cf4d3263..cbe4fb31cb4b 100644 --- a/drivers/i2c/busses/i2c-designware-platdrv.c +++ b/drivers/i2c/busses/i2c-designware-platdrv.c @@ -107,6 +107,8 @@ static int dw_i2c_acpi_configure(struct platform_device *pdev) dw_i2c_acpi_params(pdev, "SSCN", &dev->ss_hcnt, &dev->ss_lcnt, NULL); dw_i2c_acpi_params(pdev, "FMCN", &dev->fs_hcnt, &dev->fs_lcnt, &dev->sda_hold_time); + dw_i2c_acpi_params(pdev, "FPCN", &dev->fp_hcnt, &dev->fp_lcnt, NULL); + dw_i2c_acpi_params(pdev, "HSCN", &dev->hs_hcnt, &dev->hs_lcnt, NULL); id = acpi_match_device(pdev->dev.driver->acpi_match_table, &pdev->dev); if (id && id->driver_data) From d608c3d9ac818fc0addc884144c7550e03b0fc6f Mon Sep 17 00:00:00 2001 From: Weifeng Voon Date: Fri, 12 Aug 2016 17:02:49 +0300 Subject: [PATCH 23/71] i2c: designware: Enable fast mode plus This patch enabled fast mode plus. The fast mode plus and fast speed share the same HCNT and LCNT register. So, the fast mode plus will only run when the HCNT and LCNT value is provided. Else, it will run at fast speed as default. Signed-off-by: Weifeng Voon Signed-off-by: Jarkko Nikula Reviewed-by: Andy Shevchenko Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-designware-core.c | 7 +++++-- drivers/i2c/busses/i2c-designware-platdrv.c | 9 ++++++--- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/drivers/i2c/busses/i2c-designware-core.c b/drivers/i2c/busses/i2c-designware-core.c index c6922b806fb7..07edff7a62e3 100644 --- a/drivers/i2c/busses/i2c-designware-core.c +++ b/drivers/i2c/busses/i2c-designware-core.c @@ -347,8 +347,11 @@ int i2c_dw_init(struct dw_i2c_dev *dev) dw_writel(dev, lcnt, DW_IC_SS_SCL_LCNT); dev_dbg(dev->dev, "Standard-mode HCNT:LCNT = %d:%d\n", hcnt, lcnt); - /* Set SCL timing parameters for fast-mode */ - if (dev->fs_hcnt && dev->fs_lcnt) { + /* Set SCL timing parameters for fast-mode or fast-mode plus */ + if ((dev->clk_freq == 1000000) && dev->fp_hcnt && dev->fp_lcnt) { + hcnt = dev->fp_hcnt; + lcnt = dev->fp_lcnt; + } else if (dev->fs_hcnt && dev->fs_lcnt) { hcnt = dev->fs_hcnt; lcnt = dev->fs_lcnt; } else { diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c index cbe4fb31cb4b..ea92e9f3fba1 100644 --- a/drivers/i2c/busses/i2c-designware-platdrv.c +++ b/drivers/i2c/busses/i2c-designware-platdrv.c @@ -196,10 +196,13 @@ static int dw_i2c_plat_probe(struct platform_device *pdev) dw_i2c_acpi_configure(pdev); /* - * Only standard mode at 100kHz and fast mode at 400kHz are supported. + * Only standard mode at 100kHz, fast mode at 400kHz, + * and fast mode plus at 1MHz are supported. */ - if (dev->clk_freq != 100000 && dev->clk_freq != 400000) { - dev_err(&pdev->dev, "Only 100kHz and 400kHz supported"); + if (dev->clk_freq != 100000 && dev->clk_freq != 400000 + && dev->clk_freq != 1000000) { + dev_err(&pdev->dev, + "Only 100kHz, 400kHz and 1MHz are supported"); return -EINVAL; } From 548e6695d16d201f390f7554ae7d0b5bb8690166 Mon Sep 17 00:00:00 2001 From: Weifeng Voon Date: Fri, 12 Aug 2016 17:02:50 +0300 Subject: [PATCH 24/71] i2c: designware: set the common config before the if else DW_IC_CON_MASTER, DW_IC_CON_SLAVE_DISABLE and DW_IC_CON_RESTART_EN are common config that need to be set for i2c designware master. So, configure it first without having to repeat inside the if else. Signed-off-by: Weifeng Voon Signed-off-by: Jarkko Nikula Reviewed-by: Andy Shevchenko Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-designware-platdrv.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c index ea92e9f3fba1..d45481ee1b56 100644 --- a/drivers/i2c/busses/i2c-designware-platdrv.c +++ b/drivers/i2c/busses/i2c-designware-platdrv.c @@ -217,12 +217,14 @@ static int dw_i2c_plat_probe(struct platform_device *pdev) I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_I2C_BLOCK; + + dev->master_cfg = DW_IC_CON_MASTER | DW_IC_CON_SLAVE_DISABLE | + DW_IC_CON_RESTART_EN; + if (dev->clk_freq == 100000) - dev->master_cfg = DW_IC_CON_MASTER | DW_IC_CON_SLAVE_DISABLE | - DW_IC_CON_RESTART_EN | DW_IC_CON_SPEED_STD; + dev->master_cfg |= DW_IC_CON_SPEED_STD; else - dev->master_cfg = DW_IC_CON_MASTER | DW_IC_CON_SLAVE_DISABLE | - DW_IC_CON_RESTART_EN | DW_IC_CON_SPEED_FAST; + dev->master_cfg |= DW_IC_CON_SPEED_FAST; dev->clk = devm_clk_get(&pdev->dev, NULL); if (!i2c_dw_plat_prepare_clk(dev, true)) { From b6e67145f14903ca430e011db3b771d8de4c3d8a Mon Sep 17 00:00:00 2001 From: Weifeng Voon Date: Fri, 12 Aug 2016 17:02:51 +0300 Subject: [PATCH 25/71] i2c: designware: Enable high speed mode This patch enabled high speed mode. High speed mode can be turn on by setting the clk_freq to 3400000. High speed HCNT and LCNT are needed as there is no default value provided. Signed-off-by: Weifeng Voon Signed-off-by: Jarkko Nikula Reviewed-by: Andy Shevchenko Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-designware-core.c | 26 ++++++++++++++++++++- drivers/i2c/busses/i2c-designware-core.h | 1 + drivers/i2c/busses/i2c-designware-platdrv.c | 16 +++++++++---- 3 files changed, 37 insertions(+), 6 deletions(-) diff --git a/drivers/i2c/busses/i2c-designware-core.c b/drivers/i2c/busses/i2c-designware-core.c index 07edff7a62e3..c5783ed9388d 100644 --- a/drivers/i2c/busses/i2c-designware-core.c +++ b/drivers/i2c/busses/i2c-designware-core.c @@ -42,6 +42,8 @@ #define DW_IC_SS_SCL_LCNT 0x18 #define DW_IC_FS_SCL_HCNT 0x1c #define DW_IC_FS_SCL_LCNT 0x20 +#define DW_IC_HS_SCL_HCNT 0x24 +#define DW_IC_HS_SCL_LCNT 0x28 #define DW_IC_INTR_STAT 0x2c #define DW_IC_INTR_MASK 0x30 #define DW_IC_RAW_INTR_STAT 0x34 @@ -95,6 +97,9 @@ #define DW_IC_TAR_10BITADDR_MASTER BIT(12) +#define DW_IC_COMP_PARAM_1_SPEED_MODE_HIGH (BIT(2) | BIT(3)) +#define DW_IC_COMP_PARAM_1_SPEED_MODE_MASK GENMASK(3, 2) + /* * status codes */ @@ -293,7 +298,7 @@ static unsigned long i2c_dw_clk_rate(struct dw_i2c_dev *dev) int i2c_dw_init(struct dw_i2c_dev *dev) { u32 hcnt, lcnt; - u32 reg; + u32 reg, comp_param1; u32 sda_falling_time, scl_falling_time; int ret; @@ -320,6 +325,8 @@ int i2c_dw_init(struct dw_i2c_dev *dev) return -ENODEV; } + comp_param1 = dw_readl(dev, DW_IC_COMP_PARAM_1); + /* Disable the adapter */ __i2c_dw_enable(dev, false); @@ -369,6 +376,23 @@ int i2c_dw_init(struct dw_i2c_dev *dev) dw_writel(dev, lcnt, DW_IC_FS_SCL_LCNT); dev_dbg(dev->dev, "Fast-mode HCNT:LCNT = %d:%d\n", hcnt, lcnt); + if ((dev->master_cfg & DW_IC_CON_SPEED_MASK) == + DW_IC_CON_SPEED_HIGH) { + if ((comp_param1 & DW_IC_COMP_PARAM_1_SPEED_MODE_MASK) + != DW_IC_COMP_PARAM_1_SPEED_MODE_HIGH) { + dev_err(dev->dev, "High Speed not supported!\n"); + dev->master_cfg &= ~DW_IC_CON_SPEED_MASK; + dev->master_cfg |= DW_IC_CON_SPEED_FAST; + } else if (dev->hs_hcnt && dev->hs_lcnt) { + hcnt = dev->hs_hcnt; + lcnt = dev->hs_lcnt; + dw_writel(dev, hcnt, DW_IC_HS_SCL_HCNT); + dw_writel(dev, lcnt, DW_IC_HS_SCL_LCNT); + dev_dbg(dev->dev, "HighSpeed-mode HCNT:LCNT = %d:%d\n", + hcnt, lcnt); + } + } + /* Configure SDA Hold Time if required */ if (dev->sda_hold_time) { reg = dw_readl(dev, DW_IC_COMP_VERSION); diff --git a/drivers/i2c/busses/i2c-designware-core.h b/drivers/i2c/busses/i2c-designware-core.h index 84866db2d04f..22bfbe147870 100644 --- a/drivers/i2c/busses/i2c-designware-core.h +++ b/drivers/i2c/busses/i2c-designware-core.h @@ -26,6 +26,7 @@ #define DW_IC_CON_MASTER 0x1 #define DW_IC_CON_SPEED_STD 0x2 #define DW_IC_CON_SPEED_FAST 0x4 +#define DW_IC_CON_SPEED_HIGH 0x6 #define DW_IC_CON_SPEED_MASK 0x6 #define DW_IC_CON_10BITADDR_MASTER 0x10 #define DW_IC_CON_RESTART_EN 0x20 diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c index d45481ee1b56..cb846cb50512 100644 --- a/drivers/i2c/busses/i2c-designware-platdrv.c +++ b/drivers/i2c/busses/i2c-designware-platdrv.c @@ -197,12 +197,12 @@ static int dw_i2c_plat_probe(struct platform_device *pdev) /* * Only standard mode at 100kHz, fast mode at 400kHz, - * and fast mode plus at 1MHz are supported. + * fast mode plus at 1MHz and high speed mode at 3.4MHz are supported. */ if (dev->clk_freq != 100000 && dev->clk_freq != 400000 - && dev->clk_freq != 1000000) { + && dev->clk_freq != 1000000 && dev->clk_freq != 3400000) { dev_err(&pdev->dev, - "Only 100kHz, 400kHz and 1MHz are supported"); + "Only 100kHz, 400kHz, 1MHz and 3.4MHz supported"); return -EINVAL; } @@ -221,10 +221,16 @@ static int dw_i2c_plat_probe(struct platform_device *pdev) dev->master_cfg = DW_IC_CON_MASTER | DW_IC_CON_SLAVE_DISABLE | DW_IC_CON_RESTART_EN; - if (dev->clk_freq == 100000) + switch (dev->clk_freq) { + case 100000: dev->master_cfg |= DW_IC_CON_SPEED_STD; - else + break; + case 3400000: + dev->master_cfg |= DW_IC_CON_SPEED_HIGH; + break; + default: dev->master_cfg |= DW_IC_CON_SPEED_FAST; + } dev->clk = devm_clk_get(&pdev->dev, NULL); if (!i2c_dw_plat_prepare_clk(dev, true)) { From aec809fc63f61a85e4300bb70081fbe6b492171c Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Fri, 12 Aug 2016 17:02:52 +0300 Subject: [PATCH 26/71] i2c: core: Cleanup I2C ACPI namespace, take 2 I2C ACPI enumeration was originally implemented in another module under drivers/acpi/ but was later moved into i2c-core with added support for I2C ACPI operation region. Rename these acpi_i2c_ prefixed functions, structures and defines in i2c-core to i2c_acpi_ in order to have more consistent name space. This is updated version from commit a7003b65801e ("i2c: core: Cleanup I2C ACPI namespace") that got reverted due merge conflicts from commit 525e6fabeae2 ("i2c / ACPI: add support for ACPI reconfigure notifications"). Signed-off-by: Jarkko Nikula Reviewed-by: Andy Shevchenko Signed-off-by: Wolfram Sang --- drivers/i2c/i2c-core.c | 86 +++++++++++++++++++++--------------------- 1 file changed, 43 insertions(+), 43 deletions(-) diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 56e50ca905ba..d4b2f66d8994 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -88,7 +88,7 @@ void i2c_transfer_trace_unreg(void) } #if defined(CONFIG_ACPI) -struct acpi_i2c_handler_data { +struct i2c_acpi_handler_data { struct acpi_connection_info info; struct i2c_adapter *adapter; }; @@ -103,15 +103,15 @@ struct gsb_buffer { }; } __packed; -struct acpi_i2c_lookup { +struct i2c_acpi_lookup { struct i2c_board_info *info; acpi_handle adapter_handle; acpi_handle device_handle; }; -static int acpi_i2c_fill_info(struct acpi_resource *ares, void *data) +static int i2c_acpi_fill_info(struct acpi_resource *ares, void *data) { - struct acpi_i2c_lookup *lookup = data; + struct i2c_acpi_lookup *lookup = data; struct i2c_board_info *info = lookup->info; struct acpi_resource_i2c_serialbus *sb; acpi_status status; @@ -136,13 +136,13 @@ static int acpi_i2c_fill_info(struct acpi_resource *ares, void *data) return 1; } -static int acpi_i2c_get_info(struct acpi_device *adev, +static int i2c_acpi_get_info(struct acpi_device *adev, struct i2c_board_info *info, acpi_handle *adapter_handle) { struct list_head resource_list; struct resource_entry *entry; - struct acpi_i2c_lookup lookup; + struct i2c_acpi_lookup lookup; int ret; if (acpi_bus_get_status(adev) || !adev->status.present || @@ -159,7 +159,7 @@ static int acpi_i2c_get_info(struct acpi_device *adev, /* Look up for I2cSerialBus resource */ INIT_LIST_HEAD(&resource_list); ret = acpi_dev_get_resources(adev, &resource_list, - acpi_i2c_fill_info, &lookup); + i2c_acpi_fill_info, &lookup); acpi_dev_free_resource_list(&resource_list); if (ret < 0 || !info->addr) @@ -186,7 +186,7 @@ static int acpi_i2c_get_info(struct acpi_device *adev, return 0; } -static void acpi_i2c_register_device(struct i2c_adapter *adapter, +static void i2c_acpi_register_device(struct i2c_adapter *adapter, struct acpi_device *adev, struct i2c_board_info *info) { @@ -201,7 +201,7 @@ static void acpi_i2c_register_device(struct i2c_adapter *adapter, } } -static acpi_status acpi_i2c_add_device(acpi_handle handle, u32 level, +static acpi_status i2c_acpi_add_device(acpi_handle handle, u32 level, void *data, void **return_value) { struct i2c_adapter *adapter = data; @@ -212,28 +212,28 @@ static acpi_status acpi_i2c_add_device(acpi_handle handle, u32 level, if (acpi_bus_get_device(handle, &adev)) return AE_OK; - if (acpi_i2c_get_info(adev, &info, &adapter_handle)) + if (i2c_acpi_get_info(adev, &info, &adapter_handle)) return AE_OK; if (adapter_handle != ACPI_HANDLE(&adapter->dev)) return AE_OK; - acpi_i2c_register_device(adapter, adev, &info); + i2c_acpi_register_device(adapter, adev, &info); return AE_OK; } -#define ACPI_I2C_MAX_SCAN_DEPTH 32 +#define I2C_ACPI_MAX_SCAN_DEPTH 32 /** - * acpi_i2c_register_devices - enumerate I2C slave devices behind adapter + * i2c_acpi_register_devices - enumerate I2C slave devices behind adapter * @adap: pointer to adapter * * Enumerate all I2C slave devices behind this adapter by walking the ACPI * namespace. When a device is found it will be added to the Linux device * model and bound to the corresponding ACPI handle. */ -static void acpi_i2c_register_devices(struct i2c_adapter *adap) +static void i2c_acpi_register_devices(struct i2c_adapter *adap) { acpi_status status; @@ -241,14 +241,14 @@ static void acpi_i2c_register_devices(struct i2c_adapter *adap) return; status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, - ACPI_I2C_MAX_SCAN_DEPTH, - acpi_i2c_add_device, NULL, + I2C_ACPI_MAX_SCAN_DEPTH, + i2c_acpi_add_device, NULL, adap, NULL); if (ACPI_FAILURE(status)) dev_warn(&adap->dev, "failed to enumerate I2C slaves\n"); } -static int acpi_i2c_match_adapter(struct device *dev, void *data) +static int i2c_acpi_match_adapter(struct device *dev, void *data) { struct i2c_adapter *adapter = i2c_verify_adapter(dev); @@ -258,29 +258,29 @@ static int acpi_i2c_match_adapter(struct device *dev, void *data) return ACPI_HANDLE(dev) == (acpi_handle)data; } -static int acpi_i2c_match_device(struct device *dev, void *data) +static int i2c_acpi_match_device(struct device *dev, void *data) { return ACPI_COMPANION(dev) == data; } -static struct i2c_adapter *acpi_i2c_find_adapter_by_handle(acpi_handle handle) +static struct i2c_adapter *i2c_acpi_find_adapter_by_handle(acpi_handle handle) { struct device *dev; dev = bus_find_device(&i2c_bus_type, NULL, handle, - acpi_i2c_match_adapter); + i2c_acpi_match_adapter); return dev ? i2c_verify_adapter(dev) : NULL; } -static struct i2c_client *acpi_i2c_find_client_by_adev(struct acpi_device *adev) +static struct i2c_client *i2c_acpi_find_client_by_adev(struct acpi_device *adev) { struct device *dev; - dev = bus_find_device(&i2c_bus_type, NULL, adev, acpi_i2c_match_device); + dev = bus_find_device(&i2c_bus_type, NULL, adev, i2c_acpi_match_device); return dev ? i2c_verify_client(dev) : NULL; } -static int acpi_i2c_notify(struct notifier_block *nb, unsigned long value, +static int i2c_acpi_notify(struct notifier_block *nb, unsigned long value, void *arg) { struct acpi_device *adev = arg; @@ -291,20 +291,20 @@ static int acpi_i2c_notify(struct notifier_block *nb, unsigned long value, switch (value) { case ACPI_RECONFIG_DEVICE_ADD: - if (acpi_i2c_get_info(adev, &info, &adapter_handle)) + if (i2c_acpi_get_info(adev, &info, &adapter_handle)) break; - adapter = acpi_i2c_find_adapter_by_handle(adapter_handle); + adapter = i2c_acpi_find_adapter_by_handle(adapter_handle); if (!adapter) break; - acpi_i2c_register_device(adapter, adev, &info); + i2c_acpi_register_device(adapter, adev, &info); break; case ACPI_RECONFIG_DEVICE_REMOVE: if (!acpi_device_enumerated(adev)) break; - client = acpi_i2c_find_client_by_adev(adev); + client = i2c_acpi_find_client_by_adev(adev); if (!client) break; @@ -317,10 +317,10 @@ static int acpi_i2c_notify(struct notifier_block *nb, unsigned long value, } static struct notifier_block i2c_acpi_notifier = { - .notifier_call = acpi_i2c_notify, + .notifier_call = i2c_acpi_notify, }; #else /* CONFIG_ACPI */ -static inline void acpi_i2c_register_devices(struct i2c_adapter *adap) { } +static inline void i2c_acpi_register_devices(struct i2c_adapter *adap) { } extern struct notifier_block i2c_acpi_notifier; #endif /* CONFIG_ACPI */ @@ -386,12 +386,12 @@ static int acpi_gsb_i2c_write_bytes(struct i2c_client *client, } static acpi_status -acpi_i2c_space_handler(u32 function, acpi_physical_address command, +i2c_acpi_space_handler(u32 function, acpi_physical_address command, u32 bits, u64 *value64, void *handler_context, void *region_context) { struct gsb_buffer *gsb = (struct gsb_buffer *)value64; - struct acpi_i2c_handler_data *data = handler_context; + struct i2c_acpi_handler_data *data = handler_context; struct acpi_connection_info *info = &data->info; struct acpi_resource_i2c_serialbus *sb; struct i2c_adapter *adapter = data->adapter; @@ -510,10 +510,10 @@ acpi_i2c_space_handler(u32 function, acpi_physical_address command, } -static int acpi_i2c_install_space_handler(struct i2c_adapter *adapter) +static int i2c_acpi_install_space_handler(struct i2c_adapter *adapter) { acpi_handle handle; - struct acpi_i2c_handler_data *data; + struct i2c_acpi_handler_data *data; acpi_status status; if (!adapter->dev.parent) @@ -524,7 +524,7 @@ static int acpi_i2c_install_space_handler(struct i2c_adapter *adapter) if (!handle) return -ENODEV; - data = kzalloc(sizeof(struct acpi_i2c_handler_data), + data = kzalloc(sizeof(struct i2c_acpi_handler_data), GFP_KERNEL); if (!data) return -ENOMEM; @@ -538,7 +538,7 @@ static int acpi_i2c_install_space_handler(struct i2c_adapter *adapter) status = acpi_install_address_space_handler(handle, ACPI_ADR_SPACE_GSBUS, - &acpi_i2c_space_handler, + &i2c_acpi_space_handler, NULL, data); if (ACPI_FAILURE(status)) { @@ -552,10 +552,10 @@ static int acpi_i2c_install_space_handler(struct i2c_adapter *adapter) return 0; } -static void acpi_i2c_remove_space_handler(struct i2c_adapter *adapter) +static void i2c_acpi_remove_space_handler(struct i2c_adapter *adapter) { acpi_handle handle; - struct acpi_i2c_handler_data *data; + struct i2c_acpi_handler_data *data; acpi_status status; if (!adapter->dev.parent) @@ -568,7 +568,7 @@ static void acpi_i2c_remove_space_handler(struct i2c_adapter *adapter) acpi_remove_address_space_handler(handle, ACPI_ADR_SPACE_GSBUS, - &acpi_i2c_space_handler); + &i2c_acpi_space_handler); status = acpi_bus_get_private_data(handle, (void **)&data); if (ACPI_SUCCESS(status)) @@ -577,10 +577,10 @@ static void acpi_i2c_remove_space_handler(struct i2c_adapter *adapter) acpi_bus_detach_private_data(handle); } #else /* CONFIG_ACPI_I2C_OPREGION */ -static inline void acpi_i2c_remove_space_handler(struct i2c_adapter *adapter) +static inline void i2c_acpi_remove_space_handler(struct i2c_adapter *adapter) { } -static inline int acpi_i2c_install_space_handler(struct i2c_adapter *adapter) +static inline int i2c_acpi_install_space_handler(struct i2c_adapter *adapter) { return 0; } #endif /* CONFIG_ACPI_I2C_OPREGION */ @@ -1752,8 +1752,8 @@ static int i2c_register_adapter(struct i2c_adapter *adap) /* create pre-declared device nodes */ of_i2c_register_devices(adap); - acpi_i2c_register_devices(adap); - acpi_i2c_install_space_handler(adap); + i2c_acpi_register_devices(adap); + i2c_acpi_install_space_handler(adap); if (adap->nr < __i2c_first_dynamic_bus_num) i2c_scan_static_board_info(adap); @@ -1925,7 +1925,7 @@ void i2c_del_adapter(struct i2c_adapter *adap) return; } - acpi_i2c_remove_space_handler(adap); + i2c_acpi_remove_space_handler(adap); /* Tell drivers about this removal */ mutex_lock(&core_lock); bus_for_each_drv(&i2c_bus_type, NULL, adap, From 5853b22d96fa786365ff11fe9f008a68a533f043 Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Fri, 12 Aug 2016 17:02:53 +0300 Subject: [PATCH 27/71] i2c: core: Add function for finding the bus speed from ACPI, take 2 ACPI 5 specification doesn't have property for the I2C bus speed but I2cSerialBus resource descriptor which define each controller-slave connection define the maximum speed supported by that connection. Thus finding the maximum safe speed for the bus is to walk through all I2cSerialBus resources that are associated to I2C controller and use the speed of slowest connection. Add function i2c_acpi_find_bus_speed() to the i2c-core that adapter drivers can call prior registering itself to core. This implies two-step walk through the I2cSerialBus resources: call to i2c_acpi_find_bus_speed() does the first scan and finds the safe bus speed that adapter drivers can set up. Adapter driver registration does the second scan when i2c-core creates the I2C slaves by calling the i2c_acpi_register_devices(). In that way the bus speed is set in case slave device probe gets called during registration and does communication. Previous version commit 55d38d060e99 ("i2c: core: Add function for finding the bus speed from ACPI") got reverted due merge conflicts from commit 525e6fabeae2 ("i2c / ACPI: add support for ACPI reconfigure notifications"). This version is a bit bigger than previous version but is still sharing the lowest and complicated part of I2cSerialBus lookup routines with the existing code. Signed-off-by: Jarkko Nikula Reviewed-by: Andy Shevchenko Signed-off-by: Wolfram Sang --- drivers/i2c/i2c-core.c | 109 +++++++++++++++++++++++++++++++++++------ include/linux/i2c.h | 9 ++++ 2 files changed, 102 insertions(+), 16 deletions(-) diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index d4b2f66d8994..05794423e01f 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -107,6 +107,9 @@ struct i2c_acpi_lookup { struct i2c_board_info *info; acpi_handle adapter_handle; acpi_handle device_handle; + acpi_handle search_handle; + u32 speed; + u32 min_speed; }; static int i2c_acpi_fill_info(struct acpi_resource *ares, void *data) @@ -130,12 +133,39 @@ static int i2c_acpi_fill_info(struct acpi_resource *ares, void *data) return 1; info->addr = sb->slave_address; + lookup->speed = sb->connection_speed; if (sb->access_mode == ACPI_I2C_10BIT_MODE) info->flags |= I2C_CLIENT_TEN; return 1; } +static int i2c_acpi_do_lookup(struct acpi_device *adev, + struct i2c_acpi_lookup *lookup) +{ + struct i2c_board_info *info = lookup->info; + struct list_head resource_list; + int ret; + + if (acpi_bus_get_status(adev) || !adev->status.present || + acpi_device_enumerated(adev)) + return -EINVAL; + + memset(info, 0, sizeof(*info)); + lookup->device_handle = acpi_device_handle(adev); + + /* Look up for I2cSerialBus resource */ + INIT_LIST_HEAD(&resource_list); + ret = acpi_dev_get_resources(adev, &resource_list, + i2c_acpi_fill_info, lookup); + acpi_dev_free_resource_list(&resource_list); + + if (ret < 0 || !info->addr) + return -EINVAL; + + return 0; +} + static int i2c_acpi_get_info(struct acpi_device *adev, struct i2c_board_info *info, acpi_handle *adapter_handle) @@ -145,29 +175,18 @@ static int i2c_acpi_get_info(struct acpi_device *adev, struct i2c_acpi_lookup lookup; int ret; - if (acpi_bus_get_status(adev) || !adev->status.present || - acpi_device_enumerated(adev)) - return -EINVAL; - - memset(info, 0, sizeof(*info)); - info->fwnode = acpi_fwnode_handle(adev); - memset(&lookup, 0, sizeof(lookup)); - lookup.device_handle = acpi_device_handle(adev); lookup.info = info; - /* Look up for I2cSerialBus resource */ - INIT_LIST_HEAD(&resource_list); - ret = acpi_dev_get_resources(adev, &resource_list, - i2c_acpi_fill_info, &lookup); - acpi_dev_free_resource_list(&resource_list); - - if (ret < 0 || !info->addr) - return -EINVAL; + ret = i2c_acpi_do_lookup(adev, &lookup); + if (ret) + return ret; + info->fwnode = acpi_fwnode_handle(adev); *adapter_handle = lookup.adapter_handle; /* Then fill IRQ number if any */ + INIT_LIST_HEAD(&resource_list); ret = acpi_dev_get_resources(adev, &resource_list, NULL, NULL); if (ret < 0) return -EINVAL; @@ -248,6 +267,64 @@ static void i2c_acpi_register_devices(struct i2c_adapter *adap) dev_warn(&adap->dev, "failed to enumerate I2C slaves\n"); } +static acpi_status i2c_acpi_lookup_speed(acpi_handle handle, u32 level, + void *data, void **return_value) +{ + struct i2c_acpi_lookup *lookup = data; + struct acpi_device *adev; + + if (acpi_bus_get_device(handle, &adev)) + return AE_OK; + + if (i2c_acpi_do_lookup(adev, lookup)) + return AE_OK; + + if (lookup->search_handle != lookup->adapter_handle) + return AE_OK; + + if (lookup->speed <= lookup->min_speed) + lookup->min_speed = lookup->speed; + + return AE_OK; +} + +/** + * i2c_acpi_find_bus_speed - find I2C bus speed from ACPI + * @dev: The device owning the bus + * + * Find the I2C bus speed by walking the ACPI namespace for all I2C slaves + * devices connected to this bus and use the speed of slowest device. + * + * Returns the speed in Hz or zero + */ +u32 i2c_acpi_find_bus_speed(struct device *dev) +{ + struct i2c_acpi_lookup lookup; + struct i2c_board_info dummy; + acpi_status status; + + if (!has_acpi_companion(dev)) + return 0; + + memset(&lookup, 0, sizeof(lookup)); + lookup.search_handle = ACPI_HANDLE(dev); + lookup.min_speed = UINT_MAX; + lookup.info = &dummy; + + status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, + I2C_ACPI_MAX_SCAN_DEPTH, + i2c_acpi_lookup_speed, NULL, + &lookup, NULL); + + if (ACPI_FAILURE(status)) { + dev_warn(dev, "unable to find I2C bus speed from ACPI\n"); + return 0; + } + + return lookup.min_speed != UINT_MAX ? lookup.min_speed : 0; +} +EXPORT_SYMBOL_GPL(i2c_acpi_find_bus_speed); + static int i2c_acpi_match_adapter(struct device *dev, void *data) { struct i2c_adapter *adapter = i2c_verify_adapter(dev); diff --git a/include/linux/i2c.h b/include/linux/i2c.h index c1f60a345db7..5b4a3cbe5d7d 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -780,4 +780,13 @@ static inline struct i2c_adapter *of_get_i2c_adapter_by_node(struct device_node } #endif /* CONFIG_OF */ +#if IS_ENABLED(CONFIG_ACPI) +u32 i2c_acpi_find_bus_speed(struct device *dev); +#else +static inline u32 i2c_acpi_find_bus_speed(struct device *dev) +{ + return 0; +} +#endif /* CONFIG_ACPI */ + #endif /* _LINUX_I2C_H */ From 10f8e7fb371c9e575e772bc6fcc385dc973f6e87 Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Fri, 12 Aug 2016 17:02:54 +0300 Subject: [PATCH 28/71] i2c: designware: Find bus speed from ACPI Fast mode is the default speed of i2c-designware which can be overridden by platform data or by "clock-frequency" device property. Even though the ACPI 5.1 can pass device properties via _DSD method, shipping systems define the connection speed between I2C host and each slave in their I2cSerialBus resources. Which means speed is not defined per bus but per slave. As there is now support in i2c-core to find the bus speed from ACPI use that to set up the bus speed prior registering the I2C adapter. Signed-off-by: Jarkko Nikula Reviewed-by: Andy Shevchenko Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-designware-platdrv.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c index cb846cb50512..0b42a12171f3 100644 --- a/drivers/i2c/busses/i2c-designware-platdrv.c +++ b/drivers/i2c/busses/i2c-designware-platdrv.c @@ -157,7 +157,7 @@ static int dw_i2c_plat_probe(struct platform_device *pdev) struct i2c_adapter *adap; struct resource *mem; int irq, r; - u32 ht = 0; + u32 acpi_speed, ht = 0; irq = platform_get_irq(pdev, 0); if (irq < 0) @@ -192,6 +192,10 @@ static int dw_i2c_plat_probe(struct platform_device *pdev) &dev->clk_freq); } + acpi_speed = i2c_acpi_find_bus_speed(&pdev->dev); + if (acpi_speed) + dev->clk_freq = acpi_speed; + if (has_acpi_companion(&pdev->dev)) dw_i2c_acpi_configure(pdev); From 2702ea7dbec55db62fa3016c7275fea7b508033f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Roberto=20de=20Souza?= Date: Tue, 23 Aug 2016 19:18:53 -0300 Subject: [PATCH 29/71] i2c: designware: wait for disable/enable only if necessary MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If we aren't going to continue using the controller we can just disable it instead of waiting for it to complete. The biggest improvement here is when a I2C transaction is completed and it doesn't block until the adapter is disabled. When a new transfer is needed we will disable and wait for its completion. This way the adapter will continue changing its state in parallel to the execution of the thread that requested the I2C transaction saving most of the time 25~250 usec per I2C transaction. A simple program doing a register read (1 byte write, 1 byte read) alternating on 2 different slaves repeated 25k times for each and measurements taken 4 times we get: perf stat -r4 chrt -f 10 ./i2c-test /dev/i2c-1 25000 0x40 0x6 0x1e 0x00 Before: 30.879317977 seconds time elapsed ( +- 14.83% ) After: 8.638705161 seconds time elapsed ( +- 5.90% ) Signed-off-by: José Roberto de Souza Signed-off-by: Lucas De Marchi Acked-by: Jarkko Nikula Tested-by: Christian Ruppert Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-designware-core.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/i2c/busses/i2c-designware-core.c b/drivers/i2c/busses/i2c-designware-core.c index c5783ed9388d..24e8445f5a70 100644 --- a/drivers/i2c/busses/i2c-designware-core.c +++ b/drivers/i2c/busses/i2c-designware-core.c @@ -256,11 +256,16 @@ static u32 i2c_dw_scl_lcnt(u32 ic_clk, u32 tLOW, u32 tf, int offset) } static void __i2c_dw_enable(struct dw_i2c_dev *dev, bool enable) +{ + dw_writel(dev, enable, DW_IC_ENABLE); +} + +static void __i2c_dw_enable_and_wait(struct dw_i2c_dev *dev, bool enable) { int timeout = 100; do { - dw_writel(dev, enable, DW_IC_ENABLE); + __i2c_dw_enable(dev, enable); if ((dw_readl(dev, DW_IC_ENABLE_STATUS) & 1) == enable) return; @@ -328,7 +333,7 @@ int i2c_dw_init(struct dw_i2c_dev *dev) comp_param1 = dw_readl(dev, DW_IC_COMP_PARAM_1); /* Disable the adapter */ - __i2c_dw_enable(dev, false); + __i2c_dw_enable_and_wait(dev, false); /* set standard and fast speed deviders for high/low periods */ @@ -441,7 +446,7 @@ static void i2c_dw_xfer_init(struct dw_i2c_dev *dev) u32 ic_con, ic_tar = 0; /* Disable the adapter */ - __i2c_dw_enable(dev, false); + __i2c_dw_enable_and_wait(dev, false); /* if the slave address is ten bit address, enable 10BITADDR */ ic_con = dw_readl(dev, DW_IC_CON); @@ -860,7 +865,7 @@ tx_aborted: void i2c_dw_disable(struct dw_i2c_dev *dev) { /* Disable controller */ - __i2c_dw_enable(dev, false); + __i2c_dw_enable_and_wait(dev, false); /* Disable all interupts */ dw_writel(dev, 0, DW_IC_INTR_MASK); From 8c5660bb299a9350857e1e5800b7db8214e3f75c Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Tue, 23 Aug 2016 19:18:54 -0300 Subject: [PATCH 30/71] i2c: designware: add common functions for locking These are used in 2 places and will be needed in more. Signed-off-by: Lucas De Marchi Acked-by: Jarkko Nikula Tested-by: Christian Ruppert Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-designware-core.c | 52 +++++++++++++++--------- 1 file changed, 32 insertions(+), 20 deletions(-) diff --git a/drivers/i2c/busses/i2c-designware-core.c b/drivers/i2c/busses/i2c-designware-core.c index 24e8445f5a70..2bf4f60a9ac2 100644 --- a/drivers/i2c/busses/i2c-designware-core.c +++ b/drivers/i2c/busses/i2c-designware-core.c @@ -292,6 +292,28 @@ static unsigned long i2c_dw_clk_rate(struct dw_i2c_dev *dev) return dev->get_clk_rate_khz(dev); } +static int i2c_dw_acquire_lock(struct dw_i2c_dev *dev) +{ + int ret; + + if (!dev->acquire_lock) + return 0; + + ret = dev->acquire_lock(dev); + if (!ret) + return 0; + + dev_err(dev->dev, "couldn't acquire bus ownership\n"); + + return ret; +} + +static void i2c_dw_release_lock(struct dw_i2c_dev *dev) +{ + if (dev->release_lock) + dev->release_lock(dev); +} + /** * i2c_dw_init() - initialize the designware i2c master hardware * @dev: device private data @@ -307,13 +329,9 @@ int i2c_dw_init(struct dw_i2c_dev *dev) u32 sda_falling_time, scl_falling_time; int ret; - if (dev->acquire_lock) { - ret = dev->acquire_lock(dev); - if (ret) { - dev_err(dev->dev, "couldn't acquire bus ownership\n"); - return ret; - } - } + ret = i2c_dw_acquire_lock(dev); + if (ret) + return ret; reg = dw_readl(dev, DW_IC_COMP_TYPE); if (reg == ___constant_swab32(DW_IC_COMP_TYPE_VALUE)) { @@ -325,8 +343,7 @@ int i2c_dw_init(struct dw_i2c_dev *dev) } else if (reg != DW_IC_COMP_TYPE_VALUE) { dev_err(dev->dev, "Unknown Synopsys component type: " "0x%08x\n", reg); - if (dev->release_lock) - dev->release_lock(dev); + i2c_dw_release_lock(dev); return -ENODEV; } @@ -415,8 +432,8 @@ int i2c_dw_init(struct dw_i2c_dev *dev) /* configure the i2c master */ dw_writel(dev, dev->master_cfg , DW_IC_CON); - if (dev->release_lock) - dev->release_lock(dev); + i2c_dw_release_lock(dev); + return 0; } EXPORT_SYMBOL_GPL(i2c_dw_init); @@ -679,13 +696,9 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) dev->abort_source = 0; dev->rx_outstanding = 0; - if (dev->acquire_lock) { - ret = dev->acquire_lock(dev); - if (ret) { - dev_err(dev->dev, "couldn't acquire bus ownership\n"); - goto done_nolock; - } - } + ret = i2c_dw_acquire_lock(dev); + if (ret) + goto done_nolock; ret = i2c_dw_wait_bus_not_busy(dev); if (ret < 0) @@ -732,8 +745,7 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) ret = -EIO; done: - if (dev->release_lock) - dev->release_lock(dev); + i2c_dw_release_lock(dev); done_nolock: pm_runtime_mark_last_busy(dev->dev); From 63d0f0a6952a1a02bc4f116b7da7c7887e46efa3 Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Tue, 23 Aug 2016 19:18:55 -0300 Subject: [PATCH 31/71] i2c: designware: detect when dynamic tar update is possible MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adapter can be synthesized with dynamic tar update enabled or disabled. When enabled it is not necessary to disable the adapter to change the slave address in some situations, which saves some time per transaction. There is no direct register to know if this feature is enabled but we can do it indirectly by writing to the 10BIT_ADDR field in IC_CON: this field is read only when dynamic tar update is enabled. Signed-off-by: Lucas De Marchi Signed-off-by: José Roberto de Souza Acked-by: Jarkko Nikula Tested-by: Christian Ruppert Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-designware-core.c | 45 ++++++++++++++++++------ drivers/i2c/busses/i2c-designware-core.h | 1 + 2 files changed, 35 insertions(+), 11 deletions(-) diff --git a/drivers/i2c/busses/i2c-designware-core.c b/drivers/i2c/busses/i2c-designware-core.c index 2bf4f60a9ac2..e1f1b7519771 100644 --- a/drivers/i2c/busses/i2c-designware-core.c +++ b/drivers/i2c/busses/i2c-designware-core.c @@ -460,27 +460,29 @@ static int i2c_dw_wait_bus_not_busy(struct dw_i2c_dev *dev) static void i2c_dw_xfer_init(struct dw_i2c_dev *dev) { struct i2c_msg *msgs = dev->msgs; - u32 ic_con, ic_tar = 0; + u32 ic_tar = 0; /* Disable the adapter */ __i2c_dw_enable_and_wait(dev, false); /* if the slave address is ten bit address, enable 10BITADDR */ - ic_con = dw_readl(dev, DW_IC_CON); - if (msgs[dev->msg_write_idx].flags & I2C_M_TEN) { - ic_con |= DW_IC_CON_10BITADDR_MASTER; + if (dev->dynamic_tar_update_enabled) { /* * If I2C_DYNAMIC_TAR_UPDATE is set, the 10-bit addressing - * mode has to be enabled via bit 12 of IC_TAR register. - * We set it always as I2C_DYNAMIC_TAR_UPDATE can't be - * detected from registers. + * mode has to be enabled via bit 12 of IC_TAR register, + * otherwise bit 4 of IC_CON is used. */ - ic_tar = DW_IC_TAR_10BITADDR_MASTER; + if (msgs[dev->msg_write_idx].flags & I2C_M_TEN) + ic_tar = DW_IC_TAR_10BITADDR_MASTER; } else { - ic_con &= ~DW_IC_CON_10BITADDR_MASTER; - } + u32 ic_con = dw_readl(dev, DW_IC_CON); - dw_writel(dev, ic_con, DW_IC_CON); + if (msgs[dev->msg_write_idx].flags & I2C_M_TEN) + ic_con |= DW_IC_CON_10BITADDR_MASTER; + else + ic_con &= ~DW_IC_CON_10BITADDR_MASTER; + dw_writel(dev, ic_con, DW_IC_CON); + } /* * Set the slave (target) address and enable 10-bit addressing mode @@ -901,6 +903,7 @@ int i2c_dw_probe(struct dw_i2c_dev *dev) { struct i2c_adapter *adap = &dev->adapter; int r; + u32 reg; init_completion(&dev->cmd_complete); @@ -908,6 +911,26 @@ int i2c_dw_probe(struct dw_i2c_dev *dev) if (r) return r; + r = i2c_dw_acquire_lock(dev); + if (r) + return r; + + /* + * Test if dynamic TAR update is enabled in this controller by writing + * to IC_10BITADDR_MASTER field in IC_CON: when it is enabled this + * field is read-only so it should not succeed + */ + reg = dw_readl(dev, DW_IC_CON); + dw_writel(dev, reg ^ DW_IC_CON_10BITADDR_MASTER, DW_IC_CON); + + if ((dw_readl(dev, DW_IC_CON) & DW_IC_CON_10BITADDR_MASTER) == + (reg & DW_IC_CON_10BITADDR_MASTER)) { + dev->dynamic_tar_update_enabled = true; + dev_dbg(dev->dev, "Dynamic TAR update enabled"); + } + + i2c_dw_release_lock(dev); + snprintf(adap->name, sizeof(adap->name), "Synopsys DesignWare I2C adapter"); adap->retries = 3; diff --git a/drivers/i2c/busses/i2c-designware-core.h b/drivers/i2c/busses/i2c-designware-core.h index 22bfbe147870..0d44d2ae7d4c 100644 --- a/drivers/i2c/busses/i2c-designware-core.h +++ b/drivers/i2c/busses/i2c-designware-core.h @@ -117,6 +117,7 @@ struct dw_i2c_dev { int (*acquire_lock)(struct dw_i2c_dev *dev); void (*release_lock)(struct dw_i2c_dev *dev); bool pm_runtime_disabled; + bool dynamic_tar_update_enabled; }; #define ACCESS_SWAP 0x00000001 From 0317e6c0f1dc1ba86b8d9dccc010c5e77b8355fa Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Tue, 23 Aug 2016 19:18:56 -0300 Subject: [PATCH 32/71] i2c: designware: do not disable adapter after transfer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Disabling the adapter after each transfer adds additional delays for each I2C transfer. Even if we don't wait for it to be disabled anymore, on next transfer we will need to if we have several transfers in a row. Now during the transfer init we check if IC_TAR can be changed dynamically, the status register for no activity and TX buffer being empty. In this case we don't need to disable it When a transfer fails the adapter will still be disabled - this is a conservative approach. When transfers succeed, the adapter is left enabled and it's configured so to disable interrupts. Alternating register reads on 2 slaves: perf stat -r4 chrt -f 10 ./i2c-test /dev/i2c-1 25000 0x40 0x6 0x1e 0x00 Before: 8.638705161 seconds time elapsed ( +- 5.90% ) After: 7.516821591 seconds time elapsed ( +- 0.11% ) Signed-off-by: Lucas De Marchi Signed-off-by: José Roberto de Souza Acked-by: Jarkko Nikula Tested-by: Christian Ruppert Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-designware-core.c | 55 ++++++++++++++++-------- 1 file changed, 37 insertions(+), 18 deletions(-) diff --git a/drivers/i2c/busses/i2c-designware-core.c b/drivers/i2c/busses/i2c-designware-core.c index e1f1b7519771..52a603a01ddd 100644 --- a/drivers/i2c/busses/i2c-designware-core.c +++ b/drivers/i2c/busses/i2c-designware-core.c @@ -91,7 +91,9 @@ DW_IC_INTR_TX_ABRT | \ DW_IC_INTR_STOP_DET) -#define DW_IC_STATUS_ACTIVITY 0x1 +#define DW_IC_STATUS_ACTIVITY 0x1 +#define DW_IC_STATUS_TFE BIT(2) +#define DW_IC_STATUS_MST_ACTIVITY BIT(5) #define DW_IC_ERR_TX_ABRT 0x1 @@ -461,9 +463,25 @@ static void i2c_dw_xfer_init(struct dw_i2c_dev *dev) { struct i2c_msg *msgs = dev->msgs; u32 ic_tar = 0; + bool enabled; - /* Disable the adapter */ - __i2c_dw_enable_and_wait(dev, false); + enabled = dw_readl(dev, DW_IC_ENABLE_STATUS) & 1; + + if (enabled) { + u32 ic_status; + + /* + * Only disable adapter if ic_tar and ic_con can't be + * dynamically updated + */ + ic_status = dw_readl(dev, DW_IC_STATUS); + if (!dev->dynamic_tar_update_enabled || + (ic_status & DW_IC_STATUS_MST_ACTIVITY) || + !(ic_status & DW_IC_STATUS_TFE)) { + __i2c_dw_enable_and_wait(dev, false); + enabled = false; + } + } /* if the slave address is ten bit address, enable 10BITADDR */ if (dev->dynamic_tar_update_enabled) { @@ -493,8 +511,8 @@ static void i2c_dw_xfer_init(struct dw_i2c_dev *dev) /* enforce disabled interrupts (due to HW issues) */ i2c_dw_disable_int(dev); - /* Enable the adapter */ - __i2c_dw_enable(dev, true); + if (!enabled) + __i2c_dw_enable(dev, true); /* Clear and enable interrupts */ dw_readl(dev, DW_IC_CLR_INTR); @@ -675,7 +693,8 @@ static int i2c_dw_handle_tx_abort(struct dw_i2c_dev *dev) } /* - * Prepare controller for a transaction and call i2c_dw_xfer_msg + * Prepare controller for a transaction and start transfer by calling + * i2c_dw_xfer_init() */ static int i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) @@ -718,16 +737,6 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) goto done; } - /* - * We must disable the adapter before returning and signaling the end - * of the current transfer. Otherwise the hardware might continue - * generating interrupts which in turn causes a race condition with - * the following transfer. Needs some more investigation if the - * additional interrupts are a hardware bug or this driver doesn't - * handle them correctly yet. - */ - __i2c_dw_enable(dev, false); - if (dev->msg_err) { ret = dev->msg_err; goto done; @@ -864,9 +873,19 @@ static irqreturn_t i2c_dw_isr(int this_irq, void *dev_id) */ tx_aborted: - if ((stat & (DW_IC_INTR_TX_ABRT | DW_IC_INTR_STOP_DET)) || dev->msg_err) + if ((stat & (DW_IC_INTR_TX_ABRT | DW_IC_INTR_STOP_DET)) + || dev->msg_err) { + /* + * We must disable interruts before returning and signaling + * the end of the current transfer. Otherwise the hardware + * might continue generating interrupts for non-existent + * transfers. + */ + i2c_dw_disable_int(dev); + dw_readl(dev, DW_IC_CLR_INTR); + complete(&dev->cmd_complete); - else if (unlikely(dev->accessor_flags & ACCESS_INTR_MASK)) { + } else if (unlikely(dev->accessor_flags & ACCESS_INTR_MASK)) { /* workaround to trigger pending interrupt */ stat = dw_readl(dev, DW_IC_INTR_MASK); i2c_dw_disable_int(dev); From c7ae44e8aadafec41eb7a5dcdeebc9022bf6c1ce Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Fri, 26 Aug 2016 14:08:57 +0100 Subject: [PATCH 33/71] i2c: tegra: Fix lines over 80 characters Checkpatch warns about some lines over 80 characters in the Tegra I2C driver and so fix these. While we are at it, prefix the second instance of "STOP condition" in the comment with a "the". Signed-off-by: Jon Hunter Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-tegra.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index d9979da11485..b90bc326907d 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -193,7 +193,8 @@ struct tegra_i2c_dev { bool is_multimaster_mode; }; -static void dvc_writel(struct tegra_i2c_dev *i2c_dev, u32 val, unsigned long reg) +static void dvc_writel(struct tegra_i2c_dev *i2c_dev, u32 val, + unsigned long reg) { writel(val, i2c_dev->base + reg); } @@ -643,9 +644,10 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev, return 0; /* - * NACK interrupt is generated before the I2C controller generates the - * STOP condition on the bus. So wait for 2 clock periods before resetting - * the controller so that STOP condition has been delivered properly. + * NACK interrupt is generated before the I2C controller generates + * the STOP condition on the bus. So wait for 2 clock periods + * before resetting the controller so that the STOP condition has + * been delivered properly. */ if (i2c_dev->msg_err == I2C_ERR_NO_ACK) udelay(DIV_ROUND_UP(2 * 1000000, i2c_dev->bus_clk_rate)); From 2929be29e09b789f0e6c61549e3426c439d78c58 Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Fri, 26 Aug 2016 14:08:58 +0100 Subject: [PATCH 34/71] i2c: tegra: Use BIT macro Checkpatch warns about spacing around the '<<' operator in the Tegra I2C driver and so fix these by converting the bit definitions that are using this operator to use the BIT macro. Signed-off-by: Jon Hunter Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-tegra.c | 64 +++++++++++++++++----------------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index b90bc326907d..98d13437eb42 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -36,21 +36,21 @@ #define I2C_CNFG 0x000 #define I2C_CNFG_DEBOUNCE_CNT_SHIFT 12 -#define I2C_CNFG_PACKET_MODE_EN (1<<10) -#define I2C_CNFG_NEW_MASTER_FSM (1<<11) -#define I2C_CNFG_MULTI_MASTER_MODE (1<<17) +#define I2C_CNFG_PACKET_MODE_EN BIT(10) +#define I2C_CNFG_NEW_MASTER_FSM BIT(11) +#define I2C_CNFG_MULTI_MASTER_MODE BIT(17) #define I2C_STATUS 0x01C #define I2C_SL_CNFG 0x020 -#define I2C_SL_CNFG_NACK (1<<1) -#define I2C_SL_CNFG_NEWSL (1<<2) +#define I2C_SL_CNFG_NACK BIT(1) +#define I2C_SL_CNFG_NEWSL BIT(2) #define I2C_SL_ADDR1 0x02c #define I2C_SL_ADDR2 0x030 #define I2C_TX_FIFO 0x050 #define I2C_RX_FIFO 0x054 #define I2C_PACKET_TRANSFER_STATUS 0x058 #define I2C_FIFO_CONTROL 0x05c -#define I2C_FIFO_CONTROL_TX_FLUSH (1<<1) -#define I2C_FIFO_CONTROL_RX_FLUSH (1<<0) +#define I2C_FIFO_CONTROL_TX_FLUSH BIT(1) +#define I2C_FIFO_CONTROL_RX_FLUSH BIT(0) #define I2C_FIFO_CONTROL_TX_TRIG_SHIFT 5 #define I2C_FIFO_CONTROL_RX_TRIG_SHIFT 2 #define I2C_FIFO_STATUS 0x060 @@ -60,26 +60,26 @@ #define I2C_FIFO_STATUS_RX_SHIFT 0 #define I2C_INT_MASK 0x064 #define I2C_INT_STATUS 0x068 -#define I2C_INT_PACKET_XFER_COMPLETE (1<<7) -#define I2C_INT_ALL_PACKETS_XFER_COMPLETE (1<<6) -#define I2C_INT_TX_FIFO_OVERFLOW (1<<5) -#define I2C_INT_RX_FIFO_UNDERFLOW (1<<4) -#define I2C_INT_NO_ACK (1<<3) -#define I2C_INT_ARBITRATION_LOST (1<<2) -#define I2C_INT_TX_FIFO_DATA_REQ (1<<1) -#define I2C_INT_RX_FIFO_DATA_REQ (1<<0) +#define I2C_INT_PACKET_XFER_COMPLETE BIT(7) +#define I2C_INT_ALL_PACKETS_XFER_COMPLETE BIT(6) +#define I2C_INT_TX_FIFO_OVERFLOW BIT(5) +#define I2C_INT_RX_FIFO_UNDERFLOW BIT(4) +#define I2C_INT_NO_ACK BIT(3) +#define I2C_INT_ARBITRATION_LOST BIT(2) +#define I2C_INT_TX_FIFO_DATA_REQ BIT(1) +#define I2C_INT_RX_FIFO_DATA_REQ BIT(0) #define I2C_CLK_DIVISOR 0x06c #define I2C_CLK_DIVISOR_STD_FAST_MODE_SHIFT 16 #define I2C_CLK_MULTIPLIER_STD_FAST_MODE 8 #define DVC_CTRL_REG1 0x000 -#define DVC_CTRL_REG1_INTR_EN (1<<10) +#define DVC_CTRL_REG1_INTR_EN BIT(10) #define DVC_CTRL_REG2 0x004 #define DVC_CTRL_REG3 0x008 -#define DVC_CTRL_REG3_SW_PROG (1<<26) -#define DVC_CTRL_REG3_I2C_DONE_INTR_EN (1<<30) +#define DVC_CTRL_REG3_SW_PROG BIT(26) +#define DVC_CTRL_REG3_I2C_DONE_INTR_EN BIT(30) #define DVC_STATUS 0x00c -#define DVC_STATUS_I2C_DONE_INTR (1<<30) +#define DVC_STATUS_I2C_DONE_INTR BIT(30) #define I2C_ERR_NONE 0x00 #define I2C_ERR_NO_ACK 0x01 @@ -89,26 +89,26 @@ #define PACKET_HEADER0_HEADER_SIZE_SHIFT 28 #define PACKET_HEADER0_PACKET_ID_SHIFT 16 #define PACKET_HEADER0_CONT_ID_SHIFT 12 -#define PACKET_HEADER0_PROTOCOL_I2C (1<<4) +#define PACKET_HEADER0_PROTOCOL_I2C BIT(4) -#define I2C_HEADER_HIGHSPEED_MODE (1<<22) -#define I2C_HEADER_CONT_ON_NAK (1<<21) -#define I2C_HEADER_SEND_START_BYTE (1<<20) -#define I2C_HEADER_READ (1<<19) -#define I2C_HEADER_10BIT_ADDR (1<<18) -#define I2C_HEADER_IE_ENABLE (1<<17) -#define I2C_HEADER_REPEAT_START (1<<16) -#define I2C_HEADER_CONTINUE_XFER (1<<15) +#define I2C_HEADER_HIGHSPEED_MODE BIT(22) +#define I2C_HEADER_CONT_ON_NAK BIT(21) +#define I2C_HEADER_SEND_START_BYTE BIT(20) +#define I2C_HEADER_READ BIT(19) +#define I2C_HEADER_10BIT_ADDR BIT(18) +#define I2C_HEADER_IE_ENABLE BIT(17) +#define I2C_HEADER_REPEAT_START BIT(16) +#define I2C_HEADER_CONTINUE_XFER BIT(15) #define I2C_HEADER_MASTER_ADDR_SHIFT 12 #define I2C_HEADER_SLAVE_ADDR_SHIFT 1 #define I2C_CONFIG_LOAD 0x08C -#define I2C_MSTR_CONFIG_LOAD (1 << 0) -#define I2C_SLV_CONFIG_LOAD (1 << 1) -#define I2C_TIMEOUT_CONFIG_LOAD (1 << 2) +#define I2C_MSTR_CONFIG_LOAD BIT(0) +#define I2C_SLV_CONFIG_LOAD BIT(1) +#define I2C_TIMEOUT_CONFIG_LOAD BIT(2) #define I2C_CLKEN_OVERRIDE 0x090 -#define I2C_MST_CORE_CLKEN_OVR (1 << 0) +#define I2C_MST_CORE_CLKEN_OVR BIT(0) /* * msg_end_type: The bus control which need to be send at end of transfer. From f5076685b3aa4f292ca322404886fee8d3d4f03d Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Fri, 26 Aug 2016 14:08:59 +0100 Subject: [PATCH 35/71] i2c: tegra: Fix missing blank lines after declarations Checkpatch warns about missing blank lines after declarations in the Tegra I2C driver and so fix these. Note that the initialisation of 'val' to zero in tegra_dvc_init() is unnecessary and so remove this. Signed-off-by: Jon Hunter Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-tegra.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index 98d13437eb42..7a7f899936a3 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -245,15 +245,17 @@ static void i2c_readsl(struct tegra_i2c_dev *i2c_dev, void *data, static void tegra_i2c_mask_irq(struct tegra_i2c_dev *i2c_dev, u32 mask) { - u32 int_mask = i2c_readl(i2c_dev, I2C_INT_MASK); - int_mask &= ~mask; + u32 int_mask; + + int_mask = i2c_readl(i2c_dev, I2C_INT_MASK) & ~mask; i2c_writel(i2c_dev, int_mask, I2C_INT_MASK); } static void tegra_i2c_unmask_irq(struct tegra_i2c_dev *i2c_dev, u32 mask) { - u32 int_mask = i2c_readl(i2c_dev, I2C_INT_MASK); - int_mask |= mask; + u32 int_mask; + + int_mask = i2c_readl(i2c_dev, I2C_INT_MASK) | mask; i2c_writel(i2c_dev, int_mask, I2C_INT_MASK); } @@ -261,6 +263,7 @@ static int tegra_i2c_flush_fifos(struct tegra_i2c_dev *i2c_dev) { unsigned long timeout = jiffies + HZ; u32 val = i2c_readl(i2c_dev, I2C_FIFO_CONTROL); + val |= I2C_FIFO_CONTROL_TX_FLUSH | I2C_FIFO_CONTROL_RX_FLUSH; i2c_writel(i2c_dev, val, I2C_FIFO_CONTROL); @@ -386,7 +389,8 @@ static int tegra_i2c_fill_tx_fifo(struct tegra_i2c_dev *i2c_dev) */ static void tegra_dvc_init(struct tegra_i2c_dev *i2c_dev) { - u32 val = 0; + u32 val; + val = dvc_readl(i2c_dev, DVC_CTRL_REG3); val |= DVC_CTRL_REG3_SW_PROG; val |= DVC_CTRL_REG3_I2C_DONE_INTR_EN; @@ -400,6 +404,7 @@ static void tegra_dvc_init(struct tegra_i2c_dev *i2c_dev) static inline int tegra_i2c_clock_enable(struct tegra_i2c_dev *i2c_dev) { int ret; + if (!i2c_dev->hw->has_single_clk_source) { ret = clk_enable(i2c_dev->fast_clk); if (ret < 0) { @@ -461,11 +466,11 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev) if (!i2c_dev->is_dvc) { u32 sl_cfg = i2c_readl(i2c_dev, I2C_SL_CNFG); + sl_cfg |= I2C_SL_CNFG_NACK | I2C_SL_CNFG_NEWSL; i2c_writel(i2c_dev, sl_cfg, I2C_SL_CNFG); i2c_writel(i2c_dev, 0xfc, I2C_SL_ADDR1); i2c_writel(i2c_dev, 0x00, I2C_SL_ADDR2); - } val = 7 << I2C_FIFO_CONTROL_TX_TRIG_SHIFT | @@ -680,6 +685,7 @@ static int tegra_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], for (i = 0; i < num; i++) { enum msg_end_type end_type = MSG_END_STOP; + if (i < (num - 1)) { if (msgs[i + 1].flags & I2C_M_NOSTART) end_type = MSG_END_CONTINUE; @@ -956,6 +962,7 @@ unprepare_fast_clk: static int tegra_i2c_remove(struct platform_device *pdev) { struct tegra_i2c_dev *i2c_dev = platform_get_drvdata(pdev); + i2c_del_adapter(&i2c_dev->adapter); if (i2c_dev->is_multimaster_mode) From e8e999cbe725a4403ac771b1e4c8a5de7e0031f3 Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Fri, 26 Aug 2016 14:09:00 +0100 Subject: [PATCH 36/71] i2c: tegra: Add missing new line characters Add missing new line characters for the various error messages. Signed-off-by: Jon Hunter Acked-by: Laxman Dewangan Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-tegra.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index 7a7f899936a3..7f31a103c04a 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -833,7 +833,7 @@ static int tegra_i2c_probe(struct platform_device *pdev) div_clk = devm_clk_get(&pdev->dev, "div-clk"); if (IS_ERR(div_clk)) { - dev_err(&pdev->dev, "missing controller clock"); + dev_err(&pdev->dev, "missing controller clock\n"); return PTR_ERR(div_clk); } @@ -851,7 +851,7 @@ static int tegra_i2c_probe(struct platform_device *pdev) i2c_dev->rst = devm_reset_control_get(&pdev->dev, "i2c"); if (IS_ERR(i2c_dev->rst)) { - dev_err(&pdev->dev, "missing controller reset"); + dev_err(&pdev->dev, "missing controller reset\n"); return PTR_ERR(i2c_dev->rst); } @@ -871,7 +871,7 @@ static int tegra_i2c_probe(struct platform_device *pdev) if (!i2c_dev->hw->has_single_clk_source) { fast_clk = devm_clk_get(&pdev->dev, "fast-clk"); if (IS_ERR(fast_clk)) { - dev_err(&pdev->dev, "missing fast clock"); + dev_err(&pdev->dev, "missing fast clock\n"); return PTR_ERR(fast_clk); } i2c_dev->fast_clk = fast_clk; @@ -919,7 +919,7 @@ static int tegra_i2c_probe(struct platform_device *pdev) ret = tegra_i2c_init(i2c_dev); if (ret) { - dev_err(&pdev->dev, "Failed to initialize i2c controller"); + dev_err(&pdev->dev, "Failed to initialize i2c controller\n"); goto disable_div_clk; } From a9e32cd81624faf4deb7c850f846efc00a3d36b4 Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Fri, 26 Aug 2016 14:09:01 +0100 Subject: [PATCH 37/71] i2c: tegra: Remove non device-tree support Tegra has only supported device-tree for platform/board configuration for quite some time now and so simplify the Tegra I2C driver by dropping code for non device-tree platforms/boards. Signed-off-by: Jon Hunter Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-tegra.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index 7f31a103c04a..e5c8c67a2491 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -857,15 +857,9 @@ static int tegra_i2c_probe(struct platform_device *pdev) tegra_i2c_parse_dt(i2c_dev); - i2c_dev->hw = &tegra20_i2c_hw; - - if (pdev->dev.of_node) { - i2c_dev->hw = of_device_get_match_data(&pdev->dev); - i2c_dev->is_dvc = of_device_is_compatible(pdev->dev.of_node, - "nvidia,tegra20-i2c-dvc"); - } else if (pdev->id == 3) { - i2c_dev->is_dvc = 1; - } + i2c_dev->hw = of_device_get_match_data(&pdev->dev); + i2c_dev->is_dvc = of_device_is_compatible(pdev->dev.of_node, + "nvidia,tegra20-i2c-dvc"); init_completion(&i2c_dev->msg_complete); if (!i2c_dev->hw->has_single_clk_source) { From 0da9ab89aba975d2b27b829636e253c5b2771c13 Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Fri, 26 Aug 2016 14:09:02 +0100 Subject: [PATCH 38/71] i2c: tegra: Use device name for adapter name All Tegra I2C devices have the name "Tegra I2C adapter" which is not very useful when viewing the I2C adapter names via the sysfs. Therefore, use the device name, which is unique for each I2C device, instead. Signed-off-by: Jon Hunter Acked-by: Laxman Dewangan Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-tegra.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index e5c8c67a2491..bdb50258a9a8 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -927,7 +927,7 @@ static int tegra_i2c_probe(struct platform_device *pdev) i2c_set_adapdata(&i2c_dev->adapter, i2c_dev); i2c_dev->adapter.owner = THIS_MODULE; i2c_dev->adapter.class = I2C_CLASS_DEPRECATED; - strlcpy(i2c_dev->adapter.name, "Tegra I2C adapter", + strlcpy(i2c_dev->adapter.name, dev_name(&pdev->dev), sizeof(i2c_dev->adapter.name)); i2c_dev->adapter.dev.parent = &pdev->dev; i2c_dev->adapter.nr = pdev->id; From f4c2d89bd4b13ec448f6c5dc07f445883685ea4b Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Fri, 26 Aug 2016 14:09:03 +0100 Subject: [PATCH 39/71] i2c: tegra: Simplify I2C resume The I2C adapter is unlocked regardless of whether the tegra_i2c_init() called during the resume is successful or not. However, if the tegra_i2c_init() is not successful, then ->is_suspended is not set to false. Simplify the resume code by only setting ->is_suspended to false if tegra_i2c_init() is successful and return the error code from tegra_i2c_init(). Signed-off-by: Jon Hunter Acked-by: Laxman Dewangan Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-tegra.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index bdb50258a9a8..3c27012fa96c 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -989,17 +989,12 @@ static int tegra_i2c_resume(struct device *dev) i2c_lock_adapter(&i2c_dev->adapter); ret = tegra_i2c_init(i2c_dev); - - if (ret) { - i2c_unlock_adapter(&i2c_dev->adapter); - return ret; - } - - i2c_dev->is_suspended = false; + if (!ret) + i2c_dev->is_suspended = false; i2c_unlock_adapter(&i2c_dev->adapter); - return 0; + return ret; } static SIMPLE_DEV_PM_OPS(tegra_i2c_pm, tegra_i2c_suspend, tegra_i2c_resume); From 1f50ad2c86cdecc223e4098adfc5aa3a4e8d7e49 Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Fri, 26 Aug 2016 14:09:04 +0100 Subject: [PATCH 40/71] i2c: tegra: Add runtime power-management support Update the Tegra I2C driver to use runtime PM and move the code in the tegra_i2c_clock_enable/disable() functions to the PM runtime resume and suspend callbacks, respectively. Note that given that CONFIG_PM is not mandatory for Tegra, if CONFIG_PM is not enabled and so runtime PM is not enabled, ensure that the I2C clocks are turned on during probe and kept on by calling the resume callback directly. In the function tegra_i2c_init(), the variable 'err' does not need to be initialised to zero in tegra_i2c_init() because it is initialised when pm_runtime_get_sync() is called. Furthermore, to ensure we only return 0 from tegra_i2c_init(), it is necessary to re-initialise 'err' to 0 after a successful call to pm_runtime_get_sync() because it can return a positive value on success. However, alternatively re-initialise 'err' by using the return value of the function tegra_i2c_flush_fifos() because it can only be 0 or -ETIMEDOUT. Signed-off-by: Jon Hunter Acked-by: Laxman Dewangan Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-tegra.c | 60 ++++++++++++++++++++++++++-------- 1 file changed, 46 insertions(+), 14 deletions(-) diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index 3c27012fa96c..05e34dc29d5a 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -28,6 +28,7 @@ #include #include #include +#include #include @@ -401,8 +402,9 @@ static void tegra_dvc_init(struct tegra_i2c_dev *i2c_dev) dvc_writel(i2c_dev, val, DVC_CTRL_REG1); } -static inline int tegra_i2c_clock_enable(struct tegra_i2c_dev *i2c_dev) +static int tegra_i2c_runtime_resume(struct device *dev) { + struct tegra_i2c_dev *i2c_dev = dev_get_drvdata(dev); int ret; if (!i2c_dev->hw->has_single_clk_source) { @@ -413,32 +415,39 @@ static inline int tegra_i2c_clock_enable(struct tegra_i2c_dev *i2c_dev) return ret; } } + ret = clk_enable(i2c_dev->div_clk); if (ret < 0) { dev_err(i2c_dev->dev, "Enabling div clk failed, err %d\n", ret); clk_disable(i2c_dev->fast_clk); + return ret; } - return ret; + + return 0; } -static inline void tegra_i2c_clock_disable(struct tegra_i2c_dev *i2c_dev) +static int tegra_i2c_runtime_suspend(struct device *dev) { + struct tegra_i2c_dev *i2c_dev = dev_get_drvdata(dev); + clk_disable(i2c_dev->div_clk); if (!i2c_dev->hw->has_single_clk_source) clk_disable(i2c_dev->fast_clk); + + return 0; } static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev) { u32 val; - int err = 0; + int err; u32 clk_divisor; unsigned long timeout = jiffies + HZ; - err = tegra_i2c_clock_enable(i2c_dev); + err = pm_runtime_get_sync(i2c_dev->dev); if (err < 0) { - dev_err(i2c_dev->dev, "Clock enable failed %d\n", err); + dev_err(i2c_dev->dev, "runtime resume failed %d\n", err); return err; } @@ -477,8 +486,7 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev) 0 << I2C_FIFO_CONTROL_RX_TRIG_SHIFT; i2c_writel(i2c_dev, val, I2C_FIFO_CONTROL); - if (tegra_i2c_flush_fifos(i2c_dev)) - err = -ETIMEDOUT; + err = tegra_i2c_flush_fifos(i2c_dev); 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); @@ -502,7 +510,7 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev) } err: - tegra_i2c_clock_disable(i2c_dev); + pm_runtime_put(i2c_dev->dev); return err; } @@ -677,9 +685,9 @@ static int tegra_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], if (i2c_dev->is_suspended) return -EBUSY; - ret = tegra_i2c_clock_enable(i2c_dev); + ret = pm_runtime_get_sync(i2c_dev->dev); if (ret < 0) { - dev_err(i2c_dev->dev, "Clock enable failed %d\n", ret); + dev_err(i2c_dev->dev, "runtime resume failed %d\n", ret); return ret; } @@ -696,7 +704,9 @@ static int tegra_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], if (ret) break; } - tegra_i2c_clock_disable(i2c_dev); + + pm_runtime_put(i2c_dev->dev); + return ret ?: i; } @@ -902,12 +912,21 @@ static int tegra_i2c_probe(struct platform_device *pdev) goto unprepare_fast_clk; } + pm_runtime_enable(&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; + } + } + if (i2c_dev->is_multimaster_mode) { ret = clk_enable(i2c_dev->div_clk); if (ret < 0) { dev_err(i2c_dev->dev, "div_clk enable failed %d\n", ret); - goto unprepare_div_clk; + goto disable_rpm; } } @@ -943,6 +962,11 @@ disable_div_clk: if (i2c_dev->is_multimaster_mode) clk_disable(i2c_dev->div_clk); +disable_rpm: + pm_runtime_disable(&pdev->dev); + if (!pm_runtime_status_suspended(&pdev->dev)) + tegra_i2c_runtime_suspend(&pdev->dev); + unprepare_div_clk: clk_unprepare(i2c_dev->div_clk); @@ -962,6 +986,10 @@ static int tegra_i2c_remove(struct platform_device *pdev) if (i2c_dev->is_multimaster_mode) clk_disable(i2c_dev->div_clk); + pm_runtime_disable(&pdev->dev); + if (!pm_runtime_status_suspended(&pdev->dev)) + tegra_i2c_runtime_suspend(&pdev->dev); + clk_unprepare(i2c_dev->div_clk); if (!i2c_dev->hw->has_single_clk_source) clk_unprepare(i2c_dev->fast_clk); @@ -997,7 +1025,11 @@ static int tegra_i2c_resume(struct device *dev) return ret; } -static SIMPLE_DEV_PM_OPS(tegra_i2c_pm, tegra_i2c_suspend, tegra_i2c_resume); +static const struct dev_pm_ops tegra_i2c_pm = { + SET_RUNTIME_PM_OPS(tegra_i2c_runtime_suspend, tegra_i2c_runtime_resume, + NULL) + SET_SYSTEM_SLEEP_PM_OPS(tegra_i2c_suspend, tegra_i2c_resume) +}; #define TEGRA_I2C_PM (&tegra_i2c_pm) #else #define TEGRA_I2C_PM NULL From 718917b9875fcfa6450e7274d2727c4680c3591a Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Fri, 26 Aug 2016 14:09:05 +0100 Subject: [PATCH 41/71] i2c: tegra: Add pinctrl support On Tegra124/132 the pins for I2C6 are shared with the Display Port AUX (DPAUX) channel and on Tegra210 the pins for I2C4 and I2C6 are shared with DPAUX1 and DPAUX0, respectively. The multiplexing of the pins is handled by a register in the DPAUX and so the Tegra DPAUX driver has been updated to register a pinctrl device for managing these pins. The pins for these particular I2C devices are bound to the I2C device prior to probing. However, these I2C devices are in a different power partition to the DPAUX devices that own the pins. Hence, it is desirable to place the pins in the 'idle' state and allow the DPAUX power partition to switch off, when these I2C devices is not in use. Therefore, add calls to place the I2C pins in the 'default' and 'idle' states when the I2C device is runtime resumed and suspended, respectively. Please note that the pinctrl functions that set the state of the pins check to see if the devices has pins associated and will return zero if they do not. Therefore, it is safe to call these pinctrl functions even for I2C devices that do not have any pins associated. Signed-off-by: Jon Hunter Acked-by: Laxman Dewangan Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-tegra.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index 05e34dc29d5a..d86a993b75d6 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -407,6 +408,10 @@ static int tegra_i2c_runtime_resume(struct device *dev) struct tegra_i2c_dev *i2c_dev = dev_get_drvdata(dev); int ret; + ret = pinctrl_pm_select_default_state(i2c_dev->dev); + if (ret) + return ret; + if (!i2c_dev->hw->has_single_clk_source) { ret = clk_enable(i2c_dev->fast_clk); if (ret < 0) { @@ -435,7 +440,7 @@ static int tegra_i2c_runtime_suspend(struct device *dev) if (!i2c_dev->hw->has_single_clk_source) clk_disable(i2c_dev->fast_clk); - return 0; + return pinctrl_pm_select_idle_state(i2c_dev->dev); } static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev) From d1ed7985b9a6b85ea38a330108c51ec83381c01b Mon Sep 17 00:00:00 2001 From: Peter Rosin Date: Thu, 25 Aug 2016 23:07:01 +0200 Subject: [PATCH 42/71] i2c: move locking operations to their own struct This makes it trivial to constify them, so do that. Signed-off-by: Peter Rosin Acked-by: Daniel Vetter Signed-off-by: Wolfram Sang --- drivers/gpu/drm/drm_dp_helper.c | 10 +++++++--- drivers/i2c/i2c-core.c | 13 ++++++++----- drivers/i2c/i2c-mux.c | 25 ++++++++++++++++--------- include/linux/i2c.h | 25 ++++++++++++++++++------- 4 files changed, 49 insertions(+), 24 deletions(-) diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index eae5ef963cb7..2bd064493ae7 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c @@ -790,6 +790,12 @@ static void unlock_bus(struct i2c_adapter *i2c, unsigned int flags) mutex_unlock(&i2c_to_aux(i2c)->hw_mutex); } +static const struct i2c_lock_operations drm_dp_i2c_lock_ops = { + .lock_bus = lock_bus, + .trylock_bus = trylock_bus, + .unlock_bus = unlock_bus, +}; + /** * drm_dp_aux_init() - minimally initialise an aux channel * @aux: DisplayPort AUX channel @@ -807,9 +813,7 @@ void drm_dp_aux_init(struct drm_dp_aux *aux) aux->ddc.algo_data = aux; aux->ddc.retries = 3; - aux->ddc.lock_bus = lock_bus; - aux->ddc.trylock_bus = trylock_bus; - aux->ddc.unlock_bus = unlock_bus; + aux->ddc.lock_ops = &drm_dp_i2c_lock_ops; } EXPORT_SYMBOL(drm_dp_aux_init); diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 05794423e01f..0722713e5910 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -1768,6 +1768,12 @@ static int __process_new_adapter(struct device_driver *d, void *data) return i2c_do_add_adapter(to_i2c_driver(d), data); } +static const struct i2c_lock_operations i2c_adapter_lock_ops = { + .lock_bus = i2c_adapter_lock_bus, + .trylock_bus = i2c_adapter_trylock_bus, + .unlock_bus = i2c_adapter_unlock_bus, +}; + static int i2c_register_adapter(struct i2c_adapter *adap) { int res = -EINVAL; @@ -1787,11 +1793,8 @@ static int i2c_register_adapter(struct i2c_adapter *adap) goto out_list; } - if (!adap->lock_bus) { - adap->lock_bus = i2c_adapter_lock_bus; - adap->trylock_bus = i2c_adapter_trylock_bus; - adap->unlock_bus = i2c_adapter_unlock_bus; - } + if (!adap->lock_ops) + adap->lock_ops = &i2c_adapter_lock_ops; rt_mutex_init(&adap->bus_lock); rt_mutex_init(&adap->mux_lock); diff --git a/drivers/i2c/i2c-mux.c b/drivers/i2c/i2c-mux.c index 90f59c088750..83768e85a919 100644 --- a/drivers/i2c/i2c-mux.c +++ b/drivers/i2c/i2c-mux.c @@ -267,6 +267,18 @@ struct i2c_mux_core *i2c_mux_alloc(struct i2c_adapter *parent, } EXPORT_SYMBOL_GPL(i2c_mux_alloc); +static const struct i2c_lock_operations i2c_mux_lock_ops = { + .lock_bus = i2c_mux_lock_bus, + .trylock_bus = i2c_mux_trylock_bus, + .unlock_bus = i2c_mux_unlock_bus, +}; + +static const struct i2c_lock_operations i2c_parent_lock_ops = { + .lock_bus = i2c_parent_lock_bus, + .trylock_bus = i2c_parent_trylock_bus, + .unlock_bus = i2c_parent_unlock_bus, +}; + int i2c_mux_add_adapter(struct i2c_mux_core *muxc, u32 force_nr, u32 chan_id, unsigned int class) @@ -316,15 +328,10 @@ int i2c_mux_add_adapter(struct i2c_mux_core *muxc, priv->adap.retries = parent->retries; priv->adap.timeout = parent->timeout; priv->adap.quirks = parent->quirks; - if (muxc->mux_locked) { - priv->adap.lock_bus = i2c_mux_lock_bus; - priv->adap.trylock_bus = i2c_mux_trylock_bus; - priv->adap.unlock_bus = i2c_mux_unlock_bus; - } else { - priv->adap.lock_bus = i2c_parent_lock_bus; - priv->adap.trylock_bus = i2c_parent_trylock_bus; - priv->adap.unlock_bus = i2c_parent_unlock_bus; - } + if (muxc->mux_locked) + priv->adap.lock_ops = &i2c_mux_lock_ops; + else + priv->adap.lock_ops = &i2c_parent_lock_ops; /* Sanity check on class */ if (i2c_mux_parent_classes(parent) & class) diff --git a/include/linux/i2c.h b/include/linux/i2c.h index 5b4a3cbe5d7d..4a4099d3a4b9 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -426,6 +426,20 @@ struct i2c_algorithm { #endif }; +/** + * struct i2c_lock_operations - represent I2C locking operations + * @lock_bus: Get exclusive access to an I2C bus segment + * @trylock_bus: Try to get exclusive access to an I2C bus segment + * @unlock_bus: Release exclusive access to an I2C bus segment + * + * The main operations are wrapped by i2c_lock_bus and i2c_unlock_bus. + */ +struct i2c_lock_operations { + void (*lock_bus)(struct i2c_adapter *, unsigned int flags); + int (*trylock_bus)(struct i2c_adapter *, unsigned int flags); + void (*unlock_bus)(struct i2c_adapter *, unsigned int flags); +}; + /** * struct i2c_timings - I2C timing information * @bus_freq_hz: the bus frequency in Hz @@ -536,6 +550,7 @@ struct i2c_adapter { void *algo_data; /* data fields that are valid for all devices */ + const struct i2c_lock_operations *lock_ops; struct rt_mutex bus_lock; struct rt_mutex mux_lock; @@ -552,10 +567,6 @@ struct i2c_adapter { struct i2c_bus_recovery_info *bus_recovery_info; const struct i2c_adapter_quirks *quirks; - - void (*lock_bus)(struct i2c_adapter *, unsigned int flags); - int (*trylock_bus)(struct i2c_adapter *, unsigned int flags); - void (*unlock_bus)(struct i2c_adapter *, unsigned int flags); }; #define to_i2c_adapter(d) container_of(d, struct i2c_adapter, dev) @@ -597,7 +608,7 @@ int i2c_for_each_dev(void *data, int (*fn)(struct device *, void *)); static inline void i2c_lock_bus(struct i2c_adapter *adapter, unsigned int flags) { - adapter->lock_bus(adapter, flags); + adapter->lock_ops->lock_bus(adapter, flags); } /** @@ -611,7 +622,7 @@ i2c_lock_bus(struct i2c_adapter *adapter, unsigned int flags) static inline int i2c_trylock_bus(struct i2c_adapter *adapter, unsigned int flags) { - return adapter->trylock_bus(adapter, flags); + return adapter->lock_ops->trylock_bus(adapter, flags); } /** @@ -623,7 +634,7 @@ i2c_trylock_bus(struct i2c_adapter *adapter, unsigned int flags) static inline void i2c_unlock_bus(struct i2c_adapter *adapter, unsigned int flags) { - adapter->unlock_bus(adapter, flags); + adapter->lock_ops->unlock_bus(adapter, flags); } static inline void From b93d3d3739246705dfcebce815b319542cd7fbfb Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 25 Aug 2016 17:42:10 +0300 Subject: [PATCH 43/71] i2c: core: put literals on one line in dev_*() calls It's better to have strings in the code like they appeared in the output. Signed-off-by: Andy Shevchenko Signed-off-by: Wolfram Sang --- drivers/i2c/i2c-core.c | 43 ++++++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 0722713e5910..65242666901e 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -930,7 +930,7 @@ static int i2c_device_probe(struct device *dev) status = 0; if (status) - dev_warn(&client->dev, "failed to set up wakeup irq"); + dev_warn(&client->dev, "failed to set up wakeup irq\n"); } dev_dbg(dev, "probe\n"); @@ -1285,8 +1285,9 @@ i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info) return client; out_err: - dev_err(&adap->dev, "Failed to register i2c client %s at 0x%02x " - "(%d)\n", client->name, client->addr, status); + dev_err(&adap->dev, + "Failed to register i2c client %s at 0x%02x (%d)\n", + client->name, client->addr, status); out_err_silent: kfree(client); return NULL; @@ -1755,8 +1756,8 @@ static int i2c_do_add_adapter(struct i2c_driver *driver, if (driver->attach_adapter) { dev_warn(&adap->dev, "%s: attach_adapter method is deprecated\n", driver->driver.name); - dev_warn(&adap->dev, "Please use another way to instantiate " - "your i2c_client\n"); + dev_warn(&adap->dev, + "Please use another way to instantiate your i2c_client\n"); /* We ignore the return code; if it fails, too bad */ driver->attach_adapter(adap); } @@ -2531,9 +2532,10 @@ int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) if (adap->algo->master_xfer) { #ifdef DEBUG for (ret = 0; ret < num; ret++) { - dev_dbg(&adap->dev, "master_xfer[%d] %c, addr=0x%02x, " - "len=%d%s\n", ret, (msgs[ret].flags & I2C_M_RD) - ? 'R' : 'W', msgs[ret].addr, msgs[ret].len, + dev_dbg(&adap->dev, + "master_xfer[%d] %c, addr=0x%02x, len=%d%s\n", + ret, (msgs[ret].flags & I2C_M_RD) ? 'R' : 'W', + msgs[ret].addr, msgs[ret].len, (msgs[ret].flags & I2C_M_RECV_LEN) ? "+" : ""); } #endif @@ -2699,9 +2701,9 @@ static int i2c_detect_address(struct i2c_client *temp_client, /* Consistency check */ if (info.type[0] == '\0') { - dev_err(&adapter->dev, "%s detection function provided " - "no name for 0x%x\n", driver->driver.name, - addr); + dev_err(&adapter->dev, + "%s detection function provided no name for 0x%x\n", + driver->driver.name, addr); } else { struct i2c_client *client; @@ -2739,9 +2741,8 @@ static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver) /* Warn that the adapter lost class based instantiation */ if (adapter->class == I2C_CLASS_DEPRECATED) { dev_dbg(&adapter->dev, - "This adapter dropped support for I2C classes and " - "won't auto-detect %s devices anymore. If you need it, check " - "'Documentation/i2c/instantiating-devices' for alternatives.\n", + "This adapter dropped support for I2C classes and won't auto-detect %s devices anymore. " + "If you need it, check 'Documentation/i2c/instantiating-devices' for alternatives.\n", driver->driver.name); return 0; } @@ -2757,8 +2758,9 @@ static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver) temp_client->adapter = adapter; for (i = 0; address_list[i] != I2C_CLIENT_END; i += 1) { - dev_dbg(&adapter->dev, "found normal entry for adapter %d, " - "addr 0x%02x\n", adap_id, address_list[i]); + dev_dbg(&adapter->dev, + "found normal entry for adapter %d, addr 0x%02x\n", + adap_id, address_list[i]); temp_client->addr = address_list[i]; err = i2c_detect_address(temp_client, driver); if (unlikely(err)) @@ -2790,15 +2792,16 @@ i2c_new_probed_device(struct i2c_adapter *adap, for (i = 0; addr_list[i] != I2C_CLIENT_END; i++) { /* Check address validity */ if (i2c_check_7bit_addr_validity_strict(addr_list[i]) < 0) { - dev_warn(&adap->dev, "Invalid 7-bit address " - "0x%02x\n", addr_list[i]); + dev_warn(&adap->dev, "Invalid 7-bit address 0x%02x\n", + addr_list[i]); continue; } /* Check address availability (7 bit, no need to encode flags) */ if (i2c_check_addr_busy(adap, addr_list[i])) { - dev_dbg(&adap->dev, "Address 0x%02x already in " - "use, not probing\n", addr_list[i]); + dev_dbg(&adap->dev, + "Address 0x%02x already in use, not probing\n", + addr_list[i]); continue; } From 17f80487f653dfcc6cc3a8b64891442dc4182f62 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 31 Aug 2016 11:35:13 +0200 Subject: [PATCH 44/71] i2c: shmobile: Use ARCH_SHMOBILE instead of SUPERH "i2c-sh_mobile" is used on sh7343, sh7366, sh7722, sh7723, and sh7724 only. As all of the above select ARCH_SHMOBILE, restrict its driver dependencies from SUPERH to ARCH_SHMOBILE. Signed-off-by: Geert Uytterhoeven Reviewed-by: Simon Horman Signed-off-by: Wolfram Sang --- drivers/i2c/busses/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 1f3239ead037..6d94e2ec5b4f 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -836,7 +836,7 @@ config I2C_SH7760 config I2C_SH_MOBILE tristate "SuperH Mobile I2C Controller" depends on HAS_DMA - depends on SUPERH || ARCH_RENESAS || COMPILE_TEST + depends on ARCH_SHMOBILE || ARCH_RENESAS || COMPILE_TEST help If you say yes to this option, support will be included for the built-in I2C interface on the Renesas SH-Mobile processor. From 685143a1598b36227250f6c0a90ec234218f58ff Mon Sep 17 00:00:00 2001 From: Shardar Shariff Md Date: Wed, 31 Aug 2016 18:58:40 +0530 Subject: [PATCH 45/71] i2c: tegra: use readl_poll_timeout after config_load reg programmed After CONFIG_LOAD register is programmed instead of explicitly waiting for timeout, use readl_poll_timeout() to check for register value to get updated or wait till timeout. Signed-off-by: Shardar Shariff Md Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-tegra.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index d86a993b75d6..e93c72aec555 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -30,6 +30,7 @@ #include #include #include +#include #include @@ -112,6 +113,8 @@ #define I2C_CLKEN_OVERRIDE 0x090 #define I2C_MST_CORE_CLKEN_OVR BIT(0) +#define I2C_CONFIG_LOAD_TIMEOUT 1000000 + /* * msg_end_type: The bus control which need to be send at end of transfer. * @MSG_END_STOP: Send stop pulse at end of transfer. @@ -448,7 +451,6 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev) u32 val; int err; u32 clk_divisor; - unsigned long timeout = jiffies + HZ; err = pm_runtime_get_sync(i2c_dev->dev); if (err < 0) { @@ -497,15 +499,18 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev) i2c_writel(i2c_dev, I2C_MST_CORE_CLKEN_OVR, I2C_CLKEN_OVERRIDE); if (i2c_dev->hw->has_config_load_reg) { + unsigned long reg_offset; + void __iomem *addr; + + reg_offset = tegra_i2c_reg_addr(i2c_dev, I2C_CONFIG_LOAD); + addr = i2c_dev->base + reg_offset; i2c_writel(i2c_dev, I2C_MSTR_CONFIG_LOAD, I2C_CONFIG_LOAD); - while (i2c_readl(i2c_dev, I2C_CONFIG_LOAD) != 0) { - if (time_after(jiffies, timeout)) { - dev_warn(i2c_dev->dev, - "timeout waiting for config load\n"); - err = -ETIMEDOUT; - goto err; - } - msleep(1); + err = readl_poll_timeout(addr, val, val == 0, 1000, + I2C_CONFIG_LOAD_TIMEOUT); + if (err) { + dev_warn(i2c_dev->dev, + "timeout waiting for config load\n"); + goto err; } } From 2148c01ccea9203a153eadadf068c1be5a935495 Mon Sep 17 00:00:00 2001 From: Shardar Shariff Md Date: Wed, 31 Aug 2016 18:58:41 +0530 Subject: [PATCH 46/71] i2c: tegra: If fifo flush fails return error During i2c controller initialization, when fifo flush fails return error instead of returning the error during exit. Signed-off-by: Shardar Shariff Md Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-tegra.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index e93c72aec555..07a39b7c293a 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -494,6 +494,8 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev) i2c_writel(i2c_dev, val, I2C_FIFO_CONTROL); err = tegra_i2c_flush_fifos(i2c_dev); + if (err) + goto 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); From 89120d66fce9b6df4b9300fab373676648994cb8 Mon Sep 17 00:00:00 2001 From: Shardar Shariff Md Date: Wed, 31 Aug 2016 18:58:42 +0530 Subject: [PATCH 47/71] i2c: tegra: add separate function for config_load programing Define separate function for configuration load register handling to make it use by different functions later. Signed-off-by: Shardar Shariff Md Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-tegra.c | 41 +++++++++++++++++++++------------- 1 file changed, 26 insertions(+), 15 deletions(-) diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index 07a39b7c293a..daab0cea20b4 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -446,6 +446,29 @@ static int tegra_i2c_runtime_suspend(struct device *dev) return pinctrl_pm_select_idle_state(i2c_dev->dev); } +static int tegra_i2c_wait_for_config_load(struct tegra_i2c_dev *i2c_dev) +{ + unsigned long reg_offset; + void __iomem *addr; + u32 val; + int err; + + if (i2c_dev->hw->has_config_load_reg) { + reg_offset = tegra_i2c_reg_addr(i2c_dev, I2C_CONFIG_LOAD); + addr = i2c_dev->base + reg_offset; + i2c_writel(i2c_dev, I2C_MSTR_CONFIG_LOAD, I2C_CONFIG_LOAD); + err = readl_poll_timeout(addr, val, val == 0, 1000, + I2C_CONFIG_LOAD_TIMEOUT); + if (err) { + dev_warn(i2c_dev->dev, + "timeout waiting for config load\n"); + return err; + } + } + + return 0; +} + static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev) { u32 val; @@ -500,21 +523,9 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev) 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); - if (i2c_dev->hw->has_config_load_reg) { - unsigned long reg_offset; - void __iomem *addr; - - reg_offset = tegra_i2c_reg_addr(i2c_dev, I2C_CONFIG_LOAD); - addr = i2c_dev->base + reg_offset; - i2c_writel(i2c_dev, I2C_MSTR_CONFIG_LOAD, I2C_CONFIG_LOAD); - err = readl_poll_timeout(addr, val, val == 0, 1000, - I2C_CONFIG_LOAD_TIMEOUT); - if (err) { - dev_warn(i2c_dev->dev, - "timeout waiting for config load\n"); - goto err; - } - } + err = tegra_i2c_wait_for_config_load(i2c_dev); + if (err) + goto err; if (i2c_dev->irq_disabled) { i2c_dev->irq_disabled = 0; From 2bc445e2253f963412083c3eb1fc92a276086389 Mon Sep 17 00:00:00 2001 From: Shardar Shariff Md Date: Wed, 31 Aug 2016 18:58:43 +0530 Subject: [PATCH 48/71] i2c: tegra: use atomic poll function during configuration Use readl_poll_timeout_atomic() function as *wait_for_config_load() function can be called from interrupt context. Signed-off-by: Shardar Shariff Md Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-tegra.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index daab0cea20b4..243753564110 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -457,8 +457,13 @@ static int tegra_i2c_wait_for_config_load(struct tegra_i2c_dev *i2c_dev) reg_offset = tegra_i2c_reg_addr(i2c_dev, I2C_CONFIG_LOAD); addr = i2c_dev->base + reg_offset; i2c_writel(i2c_dev, I2C_MSTR_CONFIG_LOAD, I2C_CONFIG_LOAD); - err = readl_poll_timeout(addr, val, val == 0, 1000, - I2C_CONFIG_LOAD_TIMEOUT); + if (in_interrupt()) + err = readl_poll_timeout_atomic(addr, val, val == 0, + 1000, I2C_CONFIG_LOAD_TIMEOUT); + else + err = readl_poll_timeout(addr, val, val == 0, + 1000, I2C_CONFIG_LOAD_TIMEOUT); + if (err) { dev_warn(i2c_dev->dev, "timeout waiting for config load\n"); From 77821b4678f93b0b45870c04b7c06c364ed090de Mon Sep 17 00:00:00 2001 From: Shardar Shariff Md Date: Wed, 31 Aug 2016 18:58:44 +0530 Subject: [PATCH 49/71] i2c: tegra: proper handling of error cases To summarize the issue observed in error cases: SW Flow: For i2c message transfer, packet header and data payload is posted and then required error/packet completion interrupts are enabled later. HW flow: HW process the packet just after packet header is posted, if ARB lost/NACK error occurs (SW will not handle immediately when error happens as error interrupts are not enabled at this point). HW assumes error is acknowledged and clears current data in FIFO, But SW here posts the remaining data payload which still stays in FIFO as stale data (data without packet header). Now once the interrupts are enabled, SW handles ARB lost/NACK error by clearing the ARB lost/NACK interrupt. Now HW assumes that SW attended the error and will parse/process stale data (data without packet header) present in FIFO which causes invalid NACK errors. Fix: Enable the error interrupts before posting the packet into FIFO which make sure HW to not clear the fifo. Also disable the packet mode before acknowledging errors (ARB lost/NACK error) to not process any stale data. As error interrupts are enabled before posting the packet header use spinlock to avoid preempting. Signed-off-by: Shardar Shariff Md Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-tegra.c | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index 243753564110..c15d5755bccc 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -196,6 +196,7 @@ struct tegra_i2c_dev { u16 clk_divisor_non_hs_mode; bool is_suspended; bool is_multimaster_mode; + spinlock_t xfer_lock; }; static void dvc_writel(struct tegra_i2c_dev *i2c_dev, u32 val, @@ -542,14 +543,27 @@ err: return err; } +static int tegra_i2c_disable_packet_mode(struct tegra_i2c_dev *i2c_dev) +{ + u32 cnfg; + + cnfg = i2c_readl(i2c_dev, I2C_CNFG); + if (cnfg & I2C_CNFG_PACKET_MODE_EN) + i2c_writel(i2c_dev, cnfg & ~I2C_CNFG_PACKET_MODE_EN, I2C_CNFG); + + return tegra_i2c_wait_for_config_load(i2c_dev); +} + static irqreturn_t tegra_i2c_isr(int irq, void *dev_id) { u32 status; const u32 status_err = I2C_INT_NO_ACK | I2C_INT_ARBITRATION_LOST; struct tegra_i2c_dev *i2c_dev = dev_id; + unsigned long flags; status = i2c_readl(i2c_dev, I2C_INT_STATUS); + spin_lock_irqsave(&i2c_dev->xfer_lock, flags); if (status == 0) { dev_warn(i2c_dev->dev, "irq status 0 %08x %08x %08x\n", i2c_readl(i2c_dev, I2C_PACKET_TRANSFER_STATUS), @@ -565,6 +579,7 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id) } if (unlikely(status & status_err)) { + tegra_i2c_disable_packet_mode(i2c_dev); if (status & I2C_INT_NO_ACK) i2c_dev->msg_err |= I2C_ERR_NO_ACK; if (status & I2C_INT_ARBITRATION_LOST) @@ -594,7 +609,7 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id) BUG_ON(i2c_dev->msg_buf_remaining); complete(&i2c_dev->msg_complete); } - return IRQ_HANDLED; + goto done; err: /* An error occurred, mask all interrupts */ tegra_i2c_mask_irq(i2c_dev, I2C_INT_NO_ACK | I2C_INT_ARBITRATION_LOST | @@ -605,6 +620,8 @@ err: dvc_writel(i2c_dev, DVC_STATUS_I2C_DONE_INTR, DVC_STATUS); complete(&i2c_dev->msg_complete); +done: + spin_unlock_irqrestore(&i2c_dev->xfer_lock, flags); return IRQ_HANDLED; } @@ -614,6 +631,7 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev, u32 packet_header; u32 int_mask; unsigned long time_left; + unsigned long flags; tegra_i2c_flush_fifos(i2c_dev); @@ -626,6 +644,11 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev, i2c_dev->msg_read = (msg->flags & I2C_M_RD); reinit_completion(&i2c_dev->msg_complete); + spin_lock_irqsave(&i2c_dev->xfer_lock, flags); + + int_mask = I2C_INT_NO_ACK | I2C_INT_ARBITRATION_LOST; + tegra_i2c_unmask_irq(i2c_dev, int_mask); + packet_header = (0 << PACKET_HEADER0_HEADER_SIZE_SHIFT) | PACKET_HEADER0_PROTOCOL_I2C | (i2c_dev->cont_id << PACKET_HEADER0_CONT_ID_SHIFT) | @@ -655,14 +678,15 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev, if (!(msg->flags & I2C_M_RD)) tegra_i2c_fill_tx_fifo(i2c_dev); - int_mask = I2C_INT_NO_ACK | I2C_INT_ARBITRATION_LOST; if (i2c_dev->hw->has_per_pkt_xfer_complete_irq) int_mask |= I2C_INT_PACKET_XFER_COMPLETE; if (msg->flags & I2C_M_RD) int_mask |= I2C_INT_RX_FIFO_DATA_REQ; else if (i2c_dev->msg_buf_remaining) int_mask |= I2C_INT_TX_FIFO_DATA_REQ; + tegra_i2c_unmask_irq(i2c_dev, int_mask); + spin_unlock_irqrestore(&i2c_dev->xfer_lock, flags); dev_dbg(i2c_dev->dev, "unmasked irq: %02x\n", i2c_readl(i2c_dev, I2C_INT_MASK)); @@ -899,6 +923,7 @@ static int tegra_i2c_probe(struct platform_device *pdev) i2c_dev->is_dvc = of_device_is_compatible(pdev->dev.of_node, "nvidia,tegra20-i2c-dvc"); init_completion(&i2c_dev->msg_complete); + spin_lock_init(&i2c_dev->xfer_lock); if (!i2c_dev->hw->has_single_clk_source) { fast_clk = devm_clk_get(&pdev->dev, "fast-clk"); From fbf8090b723d4df3cfe18c9491a8bc21ec15a5c0 Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Tue, 6 Sep 2016 10:50:45 +0100 Subject: [PATCH 50/71] i2c: tegra: Fix assignment of boolean variables Fix the following warnings reported by coccinelle for the Tegra I2C driver. drivers/i2c/busses/i2c-tegra.c:513:2-23: WARNING: Assignment of bool to 0/1 drivers/i2c/busses/i2c-tegra.c:539:3-24: WARNING: Assignment of bool to 0/1 Reported-by: Wolfram Sang Signed-off-by: Jon Hunter Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-tegra.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index c15d5755bccc..4af9bbae20df 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -534,7 +534,7 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev) goto err; if (i2c_dev->irq_disabled) { - i2c_dev->irq_disabled = 0; + i2c_dev->irq_disabled = false; enable_irq(i2c_dev->irq); } @@ -573,7 +573,7 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id) if (!i2c_dev->irq_disabled) { disable_irq_nosync(i2c_dev->irq); - i2c_dev->irq_disabled = 1; + i2c_dev->irq_disabled = true; } goto err; } From 4c91307ce9387519836e17482906ef0f698ea7d9 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Thu, 1 Sep 2016 20:46:28 +0900 Subject: [PATCH 51/71] i2c: uniphier: avoid WARN_ON() of clk_disable() in failure path If clk_prepare_enable() fails, clk_disable_unprepare() is called in the failure path, where the enable_count is still zero, so it hits WARN_ON(core->enable_count == 0) in the clk_core_disable(). To fix this, make the clock setting more linear in the probe function so that it can exploit "goto err" in case of error. Signed-off-by: Masahiro Yamada Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-uniphier.c | 73 +++++++++++++------------------ 1 file changed, 31 insertions(+), 42 deletions(-) diff --git a/drivers/i2c/busses/i2c-uniphier.c b/drivers/i2c/busses/i2c-uniphier.c index d6e612a0e02a..56e92af46ddc 100644 --- a/drivers/i2c/busses/i2c-uniphier.c +++ b/drivers/i2c/busses/i2c-uniphier.c @@ -316,50 +316,15 @@ static struct i2c_bus_recovery_info uniphier_i2c_bus_recovery_info = { .unprepare_recovery = uniphier_i2c_unprepare_recovery, }; -static int uniphier_i2c_clk_init(struct device *dev, - struct uniphier_i2c_priv *priv) +static void uniphier_i2c_hw_init(struct uniphier_i2c_priv *priv, + u32 bus_speed, unsigned long clk_rate) { - struct device_node *np = dev->of_node; - unsigned long clk_rate; - u32 bus_speed; - int ret; - - if (of_property_read_u32(np, "clock-frequency", &bus_speed)) - bus_speed = UNIPHIER_I2C_DEFAULT_SPEED; - - if (!bus_speed) { - dev_err(dev, "clock-frequency should not be zero\n"); - return -EINVAL; - } - - if (bus_speed > UNIPHIER_I2C_MAX_SPEED) - bus_speed = UNIPHIER_I2C_MAX_SPEED; - - /* Get input clk rate through clk driver */ - priv->clk = devm_clk_get(dev, NULL); - if (IS_ERR(priv->clk)) { - dev_err(dev, "failed to get clock\n"); - return PTR_ERR(priv->clk); - } - - ret = clk_prepare_enable(priv->clk); - if (ret) - return ret; - - clk_rate = clk_get_rate(priv->clk); - if (!clk_rate) { - dev_err(dev, "input clock rate should not be zero\n"); - return -EINVAL; - } - uniphier_i2c_reset(priv, true); writel((clk_rate / bus_speed / 2 << 16) | (clk_rate / bus_speed), priv->membase + UNIPHIER_I2C_CLK); uniphier_i2c_reset(priv, false); - - return 0; } static int uniphier_i2c_probe(struct platform_device *pdev) @@ -367,8 +332,9 @@ static int uniphier_i2c_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct uniphier_i2c_priv *priv; struct resource *regs; - int irq; - int ret; + u32 bus_speed; + unsigned long clk_rate; + int irq, ret; priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); if (!priv) @@ -385,6 +351,31 @@ static int uniphier_i2c_probe(struct platform_device *pdev) return irq; } + if (of_property_read_u32(dev->of_node, "clock-frequency", &bus_speed)) + bus_speed = UNIPHIER_I2C_DEFAULT_SPEED; + + if (!bus_speed || bus_speed > UNIPHIER_I2C_MAX_SPEED) { + dev_err(dev, "invalid clock-frequency %d\n", bus_speed); + return -EINVAL; + } + + priv->clk = devm_clk_get(dev, NULL); + if (IS_ERR(priv->clk)) { + dev_err(dev, "failed to get clock\n"); + return PTR_ERR(priv->clk); + } + + ret = clk_prepare_enable(priv->clk); + if (ret) + return ret; + + clk_rate = clk_get_rate(priv->clk); + if (!clk_rate) { + dev_err(dev, "input clock rate should not be zero\n"); + ret = -EINVAL; + goto err; + } + init_completion(&priv->comp); priv->adap.owner = THIS_MODULE; priv->adap.algo = &uniphier_i2c_algo; @@ -395,9 +386,7 @@ static int uniphier_i2c_probe(struct platform_device *pdev) i2c_set_adapdata(&priv->adap, priv); platform_set_drvdata(pdev, priv); - ret = uniphier_i2c_clk_init(dev, priv); - if (ret) - goto err; + uniphier_i2c_hw_init(priv, bus_speed, clk_rate); ret = devm_request_irq(dev, irq, uniphier_i2c_interrupt, 0, pdev->name, priv); From 405188e86a4acb732f94f6d7a00b7fbb89cf5309 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Thu, 1 Sep 2016 20:46:29 +0900 Subject: [PATCH 52/71] i2c: uniphier-f: avoid WARN_ON() of clk_disable() in failure path If clk_prepare_enable() fails, clk_disable_unprepare() is called in the failure path, where the enable_count is still zero, so it hits WARN_ON(core->enable_count == 0) in the clk_core_disable(). To fix this, make the clock setting more linear in the probe function so that it can exploit "goto err" in case of error. Signed-off-by: Masahiro Yamada Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-uniphier-f.c | 73 +++++++++++++---------------- 1 file changed, 32 insertions(+), 41 deletions(-) diff --git a/drivers/i2c/busses/i2c-uniphier-f.c b/drivers/i2c/busses/i2c-uniphier-f.c index 35608531fe07..28866854950e 100644 --- a/drivers/i2c/busses/i2c-uniphier-f.c +++ b/drivers/i2c/busses/i2c-uniphier-f.c @@ -455,41 +455,10 @@ static struct i2c_bus_recovery_info uniphier_fi2c_bus_recovery_info = { .unprepare_recovery = uniphier_fi2c_unprepare_recovery, }; -static int uniphier_fi2c_clk_init(struct device *dev, - struct uniphier_fi2c_priv *priv) +static void uniphier_fi2c_hw_init(struct uniphier_fi2c_priv *priv, + u32 bus_speed, unsigned long clk_rate) { - struct device_node *np = dev->of_node; - unsigned long clk_rate; - u32 bus_speed, clk_count; - int ret; - - if (of_property_read_u32(np, "clock-frequency", &bus_speed)) - bus_speed = UNIPHIER_FI2C_DEFAULT_SPEED; - - if (!bus_speed) { - dev_err(dev, "clock-frequency should not be zero\n"); - return -EINVAL; - } - - if (bus_speed > UNIPHIER_FI2C_MAX_SPEED) - bus_speed = UNIPHIER_FI2C_MAX_SPEED; - - /* Get input clk rate through clk driver */ - priv->clk = devm_clk_get(dev, NULL); - if (IS_ERR(priv->clk)) { - dev_err(dev, "failed to get clock\n"); - return PTR_ERR(priv->clk); - } - - ret = clk_prepare_enable(priv->clk); - if (ret) - return ret; - - clk_rate = clk_get_rate(priv->clk); - if (!clk_rate) { - dev_err(dev, "input clock rate should not be zero\n"); - return -EINVAL; - } + u32 clk_count; uniphier_fi2c_reset(priv); @@ -501,8 +470,6 @@ static int uniphier_fi2c_clk_init(struct device *dev, writel(clk_count / 16, priv->membase + UNIPHIER_FI2C_DSUT); uniphier_fi2c_prepare_operation(priv); - - return 0; } static int uniphier_fi2c_probe(struct platform_device *pdev) @@ -510,8 +477,9 @@ static int uniphier_fi2c_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct uniphier_fi2c_priv *priv; struct resource *regs; - int irq; - int ret; + u32 bus_speed; + unsigned long clk_rate; + int irq, ret; priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); if (!priv) @@ -528,6 +496,31 @@ static int uniphier_fi2c_probe(struct platform_device *pdev) return irq; } + if (of_property_read_u32(dev->of_node, "clock-frequency", &bus_speed)) + bus_speed = UNIPHIER_FI2C_DEFAULT_SPEED; + + if (!bus_speed || bus_speed > UNIPHIER_FI2C_MAX_SPEED) { + dev_err(dev, "invalid clock-frequency %d\n", bus_speed); + return -EINVAL; + } + + priv->clk = devm_clk_get(dev, NULL); + if (IS_ERR(priv->clk)) { + dev_err(dev, "failed to get clock\n"); + return PTR_ERR(priv->clk); + } + + ret = clk_prepare_enable(priv->clk); + if (ret) + return ret; + + clk_rate = clk_get_rate(priv->clk); + if (!clk_rate) { + dev_err(dev, "input clock rate should not be zero\n"); + ret = -EINVAL; + goto err; + } + init_completion(&priv->comp); priv->adap.owner = THIS_MODULE; priv->adap.algo = &uniphier_fi2c_algo; @@ -538,9 +531,7 @@ static int uniphier_fi2c_probe(struct platform_device *pdev) i2c_set_adapdata(&priv->adap, priv); platform_set_drvdata(pdev, priv); - ret = uniphier_fi2c_clk_init(dev, priv); - if (ret) - goto err; + uniphier_fi2c_hw_init(priv, bus_speed, clk_rate); ret = devm_request_irq(dev, irq, uniphier_fi2c_interrupt, 0, pdev->name, priv); From 0b1c7716fd871eaa6cb4a9a1df5396302411255a Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Thu, 1 Sep 2016 20:46:30 +0900 Subject: [PATCH 53/71] i2c: uniphier-f: set the adapter to master mode when probing Currently, the adapter is set to the master mode at the first use. Since then, it is kept in the slave mode, so unexpected glitch signals on the I2C lines may cause the adapter into insane state. Setting it to the master mode along with initialization solves the problem. Signed-off-by: Masahiro Yamada Reported-by: Akio Noda Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-uniphier-f.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/drivers/i2c/busses/i2c-uniphier-f.c b/drivers/i2c/busses/i2c-uniphier-f.c index 28866854950e..829df91cc759 100644 --- a/drivers/i2c/busses/i2c-uniphier-f.c +++ b/drivers/i2c/busses/i2c-uniphier-f.c @@ -458,16 +458,20 @@ static struct i2c_bus_recovery_info uniphier_fi2c_bus_recovery_info = { static void uniphier_fi2c_hw_init(struct uniphier_fi2c_priv *priv, u32 bus_speed, unsigned long clk_rate) { - u32 clk_count; + u32 tmp; + + tmp = readl(priv->membase + UNIPHIER_FI2C_CR); + tmp |= UNIPHIER_FI2C_CR_MST; + writel(tmp, priv->membase + UNIPHIER_FI2C_CR); uniphier_fi2c_reset(priv); - clk_count = clk_rate / bus_speed; + tmp = clk_rate / bus_speed; - writel(clk_count, priv->membase + UNIPHIER_FI2C_CYC); - writel(clk_count / 2, priv->membase + UNIPHIER_FI2C_LCTL); - writel(clk_count / 2, priv->membase + UNIPHIER_FI2C_SSUT); - writel(clk_count / 16, priv->membase + UNIPHIER_FI2C_DSUT); + writel(tmp, priv->membase + UNIPHIER_FI2C_CYC); + writel(tmp / 2, priv->membase + UNIPHIER_FI2C_LCTL); + writel(tmp / 2, priv->membase + UNIPHIER_FI2C_SSUT); + writel(tmp / 16, priv->membase + UNIPHIER_FI2C_DSUT); uniphier_fi2c_prepare_operation(priv); } From d1050caea4f0a7abd72e5feb01ee175828a69fd4 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Wed, 14 Sep 2016 11:49:16 +0200 Subject: [PATCH 54/71] i2c: meson: add gxbb compatible string Signed-off-by: Neil Armstrong Signed-off-by: Jerome Brunet Acked-by: Kevin Hilman Signed-off-by: Wolfram Sang --- Documentation/devicetree/bindings/i2c/i2c-meson.txt | 2 +- drivers/i2c/busses/i2c-meson.c | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/i2c/i2c-meson.txt b/Documentation/devicetree/bindings/i2c/i2c-meson.txt index 682f9a6f766e..386357d1aab0 100644 --- a/Documentation/devicetree/bindings/i2c/i2c-meson.txt +++ b/Documentation/devicetree/bindings/i2c/i2c-meson.txt @@ -1,7 +1,7 @@ Amlogic Meson I2C controller Required properties: - - compatible: must be "amlogic,meson6-i2c" + - compatible: must be "amlogic,meson6-i2c" or "amlogic,meson-gxbb-i2c" - reg: physical address and length of the device registers - interrupts: a single interrupt specifier - clocks: clock for the device diff --git a/drivers/i2c/busses/i2c-meson.c b/drivers/i2c/busses/i2c-meson.c index 8570e6dbd0db..2aa61bbbd307 100644 --- a/drivers/i2c/busses/i2c-meson.c +++ b/drivers/i2c/busses/i2c-meson.c @@ -472,6 +472,7 @@ static int meson_i2c_remove(struct platform_device *pdev) static const struct of_device_id meson_i2c_match[] = { { .compatible = "amlogic,meson6-i2c" }, + { .compatible = "amlogic,meson-gxbb-i2c" }, { }, }; MODULE_DEVICE_TABLE(of, meson_i2c_match); From fd8961c5ba9e6c841cdf4cc00903316e5bd35180 Mon Sep 17 00:00:00 2001 From: Yang Li Date: Mon, 12 Sep 2016 17:22:30 -0500 Subject: [PATCH 55/71] i2c: imx: make bus recovery through pinctrl optional MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since commit 1c4b6c3bcf30 ("i2c: imx: implement bus recovery") the driver starts to use gpio/pinctrl to support optional bus recovery feature. But pinctrl is not always usable. There are platforms such as ls1021a and ls1043a that don't support pinctrl, and it could just be broken due to old/broken device tree. The patch makes it really optional that the probe function won't bailout on pinctrl problems instead it just disables bus recovery and prints out notification when there is problem with pinctrl. Since pinctrl is only used by bus recovery in this driver, move pinctrl initialization into bus recovery init function to prevent confusion. Signed-off-by: Li Yang Acked-by: Linus Walleij Acked-by: Uwe Kleine-König Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-imx.c | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c index cb11eee95673..592a8f26a708 100644 --- a/drivers/i2c/busses/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c @@ -984,11 +984,24 @@ static void i2c_imx_unprepare_recovery(struct i2c_adapter *adap) pinctrl_select_state(i2c_imx->pinctrl, i2c_imx->pinctrl_pins_default); } -static void i2c_imx_init_recovery_info(struct imx_i2c_struct *i2c_imx, +/* + * We switch SCL and SDA to their GPIO function and do some bitbanging + * for bus recovery. These alternative pinmux settings can be + * described in the device tree by a separate pinctrl state "gpio". If + * this is missing this is not a big problem, the only implication is + * that we can't do bus recovery. + */ +static int i2c_imx_init_recovery_info(struct imx_i2c_struct *i2c_imx, struct platform_device *pdev) { struct i2c_bus_recovery_info *rinfo = &i2c_imx->rinfo; + i2c_imx->pinctrl = devm_pinctrl_get(&pdev->dev); + if (!i2c_imx->pinctrl || IS_ERR(i2c_imx->pinctrl)) { + dev_info(&pdev->dev, "can't get pinctrl, bus recovery not supported\n"); + return PTR_ERR(i2c_imx->pinctrl); + } + i2c_imx->pinctrl_pins_default = pinctrl_lookup_state(i2c_imx->pinctrl, PINCTRL_STATE_DEFAULT); i2c_imx->pinctrl_pins_gpio = pinctrl_lookup_state(i2c_imx->pinctrl, @@ -1001,7 +1014,7 @@ static void i2c_imx_init_recovery_info(struct imx_i2c_struct *i2c_imx, IS_ERR(i2c_imx->pinctrl_pins_default) || IS_ERR(i2c_imx->pinctrl_pins_gpio)) { dev_dbg(&pdev->dev, "recovery information incomplete\n"); - return; + return 0; } dev_dbg(&pdev->dev, "using scl-gpio %d and sda-gpio %d for recovery\n", @@ -1011,6 +1024,8 @@ static void i2c_imx_init_recovery_info(struct imx_i2c_struct *i2c_imx, rinfo->unprepare_recovery = i2c_imx_unprepare_recovery; rinfo->recover_bus = i2c_generic_gpio_recovery; i2c_imx->adapter.bus_recovery_info = rinfo; + + return 0; } static u32 i2c_imx_func(struct i2c_adapter *adapter) @@ -1081,12 +1096,6 @@ static int i2c_imx_probe(struct platform_device *pdev) return ret; } - i2c_imx->pinctrl = devm_pinctrl_get(&pdev->dev); - if (IS_ERR(i2c_imx->pinctrl)) { - ret = PTR_ERR(i2c_imx->pinctrl); - goto clk_disable; - } - /* Request IRQ */ ret = devm_request_irq(&pdev->dev, irq, i2c_imx_isr, 0, pdev->name, i2c_imx); @@ -1125,7 +1134,11 @@ static int i2c_imx_probe(struct platform_device *pdev) i2c_imx, IMX_I2C_I2CR); imx_i2c_write_reg(i2c_imx->hwdata->i2sr_clr_opcode, i2c_imx, IMX_I2C_I2SR); - i2c_imx_init_recovery_info(i2c_imx, pdev); + /* Init optional bus recovery function */ + ret = i2c_imx_init_recovery_info(i2c_imx, pdev); + /* Give it another chance if pinctrl used is not ready yet */ + if (ret == -EPROBE_DEFER) + goto rpm_disable; /* Add I2C adapter */ ret = i2c_add_numbered_adapter(&i2c_imx->adapter); From c13f743aee4a84a380a8cc0745d20e832bab8ed2 Mon Sep 17 00:00:00 2001 From: Ulrich Hecht Date: Wed, 14 Sep 2016 18:46:06 +0200 Subject: [PATCH 56/71] i2c: rcar: add support for r8a7796 (R-Car M3-W) Same as r8a7795. Signed-off-by: Ulrich Hecht Signed-off-by: Wolfram Sang --- Documentation/devicetree/bindings/i2c/i2c-rcar.txt | 1 + drivers/i2c/busses/i2c-rcar.c | 1 + 2 files changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/i2c/i2c-rcar.txt b/Documentation/devicetree/bindings/i2c/i2c-rcar.txt index 5f0cb502b1db..239632a0d709 100644 --- a/Documentation/devicetree/bindings/i2c/i2c-rcar.txt +++ b/Documentation/devicetree/bindings/i2c/i2c-rcar.txt @@ -11,6 +11,7 @@ Required properties: "renesas,i2c-r8a7793" "renesas,i2c-r8a7794" "renesas,i2c-r8a7795" + "renesas,i2c-r8a7796" - reg: physical base address of the controller and length of memory mapped region. - interrupts: interrupt specifier. diff --git a/drivers/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c index 400e344704d2..7f284121e964 100644 --- a/drivers/i2c/busses/i2c-rcar.c +++ b/drivers/i2c/busses/i2c-rcar.c @@ -802,6 +802,7 @@ static const struct of_device_id rcar_i2c_dt_ids[] = { { .compatible = "renesas,i2c-r8a7793", .data = (void *)I2C_RCAR_GEN2 }, { .compatible = "renesas,i2c-r8a7794", .data = (void *)I2C_RCAR_GEN2 }, { .compatible = "renesas,i2c-r8a7795", .data = (void *)I2C_RCAR_GEN3 }, + { .compatible = "renesas,i2c-r8a7796", .data = (void *)I2C_RCAR_GEN3 }, {}, }; MODULE_DEVICE_TABLE(of, rcar_i2c_dt_ids); From e7051556b63dac163a82db6e6f324196c0c81e5b Mon Sep 17 00:00:00 2001 From: Dmitry Bazhenov Date: Wed, 21 Sep 2016 08:51:02 +0200 Subject: [PATCH 57/71] i2c: octeon: Fix set SCL recovery function The set SCL recovery function unconditionally pulls the SCL line low. Only pull SCL line low according to val parameter. Signed-off-by: Dmitry Bazhenov Signed-off-by: Jan Glauber [Changed commit message] Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-octeon-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-octeon-core.c b/drivers/i2c/busses/i2c-octeon-core.c index f45ea5eef513..f322242cdbf8 100644 --- a/drivers/i2c/busses/i2c-octeon-core.c +++ b/drivers/i2c/busses/i2c-octeon-core.c @@ -767,7 +767,7 @@ static void octeon_i2c_set_scl(struct i2c_adapter *adap, int val) { struct octeon_i2c *i2c = i2c_get_adapdata(adap); - octeon_i2c_write_int(i2c, TWSI_INT_SCL_OVR); + octeon_i2c_write_int(i2c, val ? 0 : TWSI_INT_SCL_OVR); } static int octeon_i2c_get_sda(struct i2c_adapter *adap) From de919ff6a0060510b099405d9b8f9413aba9ae14 Mon Sep 17 00:00:00 2001 From: Dmitry Bazhenov Date: Wed, 21 Sep 2016 08:51:03 +0200 Subject: [PATCH 58/71] i2c: octeon: Avoid sending STOP during recovery Due to a bug in the ThunderX I2C hardware sending STOP during a recovery attempt could lock up the hardware. To work around this problem do not send STOP at the beginning of the recovery but use the override registers to bring the TWSI including the high-level controller out of the bad state. Signed-off-by: Dmitry Bazhenov Signed-off-by: Jan Glauber [Changed commit message] Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-octeon-core.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/drivers/i2c/busses/i2c-octeon-core.c b/drivers/i2c/busses/i2c-octeon-core.c index f322242cdbf8..7d4df8383b38 100644 --- a/drivers/i2c/busses/i2c-octeon-core.c +++ b/drivers/i2c/busses/i2c-octeon-core.c @@ -783,13 +783,14 @@ static void octeon_i2c_prepare_recovery(struct i2c_adapter *adap) { struct octeon_i2c *i2c = i2c_get_adapdata(adap); - /* - * The stop resets the state machine, does not _transmit_ STOP unless - * engine was active. - */ - octeon_i2c_stop(i2c); - octeon_i2c_hlc_disable(i2c); + + /* + * Bring control register to a good state regardless + * of HLC state. + */ + octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB); + octeon_i2c_write_int(i2c, 0); } @@ -797,6 +798,15 @@ static void octeon_i2c_unprepare_recovery(struct i2c_adapter *adap) { struct octeon_i2c *i2c = i2c_get_adapdata(adap); + /* + * Generate STOP to finish the unfinished transaction. + * Can't generate STOP via the TWSI CTL register + * since it could bring the TWSI controller into an inoperable state. + */ + octeon_i2c_write_int(i2c, TWSI_INT_SDA_OVR | TWSI_INT_SCL_OVR); + udelay(5); + octeon_i2c_write_int(i2c, TWSI_INT_SDA_OVR); + udelay(5); octeon_i2c_write_int(i2c, 0); } From 38caa925ee67d2359f45a4a9cd1afa2e23a9eece Mon Sep 17 00:00:00 2001 From: Jan Glauber Date: Wed, 21 Sep 2016 08:51:04 +0200 Subject: [PATCH 59/71] i2c: octeon: Fix high-level controller status check In case the high-level controller (HLC) is used the status code is reported at a different location. Check that location after HLC write operations if the ready bit is not set and return an appropriate error code instead of always returning -EAGAIN. Signed-off-by: Jan Glauber Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-octeon-core.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/drivers/i2c/busses/i2c-octeon-core.c b/drivers/i2c/busses/i2c-octeon-core.c index 7d4df8383b38..5e63b17f935d 100644 --- a/drivers/i2c/busses/i2c-octeon-core.c +++ b/drivers/i2c/busses/i2c-octeon-core.c @@ -215,7 +215,16 @@ static int octeon_i2c_hlc_wait(struct octeon_i2c *i2c) static int octeon_i2c_check_status(struct octeon_i2c *i2c, int final_read) { - u8 stat = octeon_i2c_stat_read(i2c); + u8 stat; + + /* + * This is ugly... in HLC mode the status is not in the status register + * but in the lower 8 bits of SW_TWSI. + */ + if (i2c->hlc_enabled) + stat = __raw_readq(i2c->twsi_base + SW_TWSI(i2c)); + else + stat = octeon_i2c_stat_read(i2c); switch (stat) { /* Everything is fine */ @@ -453,7 +462,7 @@ static int octeon_i2c_hlc_read(struct octeon_i2c *i2c, struct i2c_msg *msgs) cmd = __raw_readq(i2c->twsi_base + SW_TWSI(i2c)); if ((cmd & SW_TWSI_R) == 0) - return -EAGAIN; + return octeon_i2c_check_status(i2c, false); for (i = 0, j = msgs[0].len - 1; i < msgs[0].len && i < 4; i++, j--) msgs[0].buf[j] = (cmd >> (8 * i)) & 0xff; @@ -506,9 +515,7 @@ static int octeon_i2c_hlc_write(struct octeon_i2c *i2c, struct i2c_msg *msgs) cmd = __raw_readq(i2c->twsi_base + SW_TWSI(i2c)); if ((cmd & SW_TWSI_R) == 0) - return -EAGAIN; - - ret = octeon_i2c_check_status(i2c, false); + return octeon_i2c_check_status(i2c, false); err: return ret; @@ -553,7 +560,7 @@ static int octeon_i2c_hlc_comp_read(struct octeon_i2c *i2c, struct i2c_msg *msgs cmd = __raw_readq(i2c->twsi_base + SW_TWSI(i2c)); if ((cmd & SW_TWSI_R) == 0) - return -EAGAIN; + return octeon_i2c_check_status(i2c, false); for (i = 0, j = msgs[1].len - 1; i < msgs[1].len && i < 4; i++, j--) msgs[1].buf[j] = (cmd >> (8 * i)) & 0xff; @@ -617,9 +624,7 @@ static int octeon_i2c_hlc_comp_write(struct octeon_i2c *i2c, struct i2c_msg *msg cmd = __raw_readq(i2c->twsi_base + SW_TWSI(i2c)); if ((cmd & SW_TWSI_R) == 0) - return -EAGAIN; - - ret = octeon_i2c_check_status(i2c, false); + return octeon_i2c_check_status(i2c, false); err: return ret; From 318ce2782a2732cadb422c6a76ebeb973ecd63cb Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Tue, 20 Sep 2016 16:59:25 +0300 Subject: [PATCH 60/71] i2c / ACPI: Do not touch an I2C device if it belongs to another adapter When enumerating I2C devices connected to an I2C adapter we scan the whole namespace (as it is possible to have devices anywhere in that namespace, not just below the I2C adapter device) and add each found device to the I2C bus in question. Now after commit 525e6fabeae2 ("i2c / ACPI: add support for ACPI reconfigure notifications") checking of the adapter handle to the one found in the I2cSerialBus() resource was moved to happen after resources of the I2C device has been parsed. This means that if the I2cSerialBus() resource points to an adapter that does not exists in the system we still parse those resources. This is problematic in particular because acpi_dev_resource_interrupt() tries to configure GSI if the device also has an Interrupt() resource. Failing to do that results errrors like this to be printed on the console: [ 10.409490] ERROR: Unable to locate IOAPIC for GSI 37 To fix this we pass the I2C adapter to i2c_acpi_get_info() and make sure the handle matches the one in the I2cSerialBus() resource before doing anything else to the device. Reported-by: Nicolai Stange Signed-off-by: Mika Westerberg Reviewed-by: Nicolai Stange Signed-off-by: Wolfram Sang --- drivers/i2c/i2c-core.c | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 65242666901e..cdbbd9bdb7b4 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -168,6 +168,7 @@ static int i2c_acpi_do_lookup(struct acpi_device *adev, static int i2c_acpi_get_info(struct acpi_device *adev, struct i2c_board_info *info, + struct i2c_adapter *adapter, acpi_handle *adapter_handle) { struct list_head resource_list; @@ -182,8 +183,24 @@ static int i2c_acpi_get_info(struct acpi_device *adev, if (ret) return ret; + if (adapter) { + /* The adapter must match the one in I2cSerialBus() connector */ + if (ACPI_HANDLE(&adapter->dev) != lookup.adapter_handle) + return -ENODEV; + } else { + struct acpi_device *adapter_adev; + + /* The adapter must be present */ + if (acpi_bus_get_device(lookup.adapter_handle, &adapter_adev)) + return -ENODEV; + if (acpi_bus_get_status(adapter_adev) || + !adapter_adev->status.present) + return -ENODEV; + } + info->fwnode = acpi_fwnode_handle(adev); - *adapter_handle = lookup.adapter_handle; + if (adapter_handle) + *adapter_handle = lookup.adapter_handle; /* Then fill IRQ number if any */ INIT_LIST_HEAD(&resource_list); @@ -225,16 +242,12 @@ static acpi_status i2c_acpi_add_device(acpi_handle handle, u32 level, { struct i2c_adapter *adapter = data; struct acpi_device *adev; - acpi_handle adapter_handle; struct i2c_board_info info; if (acpi_bus_get_device(handle, &adev)) return AE_OK; - if (i2c_acpi_get_info(adev, &info, &adapter_handle)) - return AE_OK; - - if (adapter_handle != ACPI_HANDLE(&adapter->dev)) + if (i2c_acpi_get_info(adev, &info, adapter, NULL)) return AE_OK; i2c_acpi_register_device(adapter, adev, &info); @@ -368,7 +381,7 @@ static int i2c_acpi_notify(struct notifier_block *nb, unsigned long value, switch (value) { case ACPI_RECONFIG_DEVICE_ADD: - if (i2c_acpi_get_info(adev, &info, &adapter_handle)) + if (i2c_acpi_get_info(adev, &info, NULL, &adapter_handle)) break; adapter = i2c_acpi_find_adapter_by_handle(adapter_handle); From a8a7d09e7304b107957e8c45882cdbb5b51bd111 Mon Sep 17 00:00:00 2001 From: David Wu Date: Thu, 22 Sep 2016 19:29:23 +0800 Subject: [PATCH 61/71] i2c: rk3x: Fix sparse warning This patch fixes the following sparse warning: drivers/i2c/busses/i2c-rk3x.c:888:17: warning: cast truncates bits from constant value (ffffffffff00 becomes ffffff00) Reported-by: Wolfram Sang Signed-off-by: David Wu Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-rk3x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c index 3b87afe82f63..dbbdbece778a 100644 --- a/drivers/i2c/busses/i2c-rk3x.c +++ b/drivers/i2c/busses/i2c-rk3x.c @@ -58,7 +58,7 @@ enum { #define REG_CON_LASTACK BIT(5) /* 1: send NACK after last received byte */ #define REG_CON_ACTACK BIT(6) /* 1: stop if NACK is received */ -#define REG_CON_TUNING_MASK GENMASK(15, 8) +#define REG_CON_TUNING_MASK GENMASK_ULL(15, 8) #define REG_CON_SDA_CFG(cfg) ((cfg) << 8) #define REG_CON_STA_CFG(cfg) ((cfg) << 12) From 72cf8c565cf4e25312fb9fa65d306ae736104ade Mon Sep 17 00:00:00 2001 From: David Wu Date: Thu, 22 Sep 2016 19:29:24 +0800 Subject: [PATCH 62/71] i2c: rk3x: Fix variable 'min_total_ns' unused warning This patch fixs the following warning: drivers/i2c/busses/i2c-rk3x.c: In function 'rk3x_i2c_v1_calc_timings': drivers/i2c/busses/i2c-rk3x.c:745:41: warning: variable 'min_total_ns' set but not used [-Wunused-but-set-variable] Reported-by: Wolfram Sang Signed-off-by: David Wu Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-rk3x.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c index dbbdbece778a..c528e191f069 100644 --- a/drivers/i2c/busses/i2c-rk3x.c +++ b/drivers/i2c/busses/i2c-rk3x.c @@ -742,7 +742,7 @@ static int rk3x_i2c_v1_calc_timings(unsigned long clk_rate, struct i2c_timings *t, struct rk3x_i2c_calced_timings *t_calc) { - unsigned long min_low_ns, min_high_ns, min_total_ns; + unsigned long min_low_ns, min_high_ns; unsigned long min_setup_start_ns, min_setup_data_ns; unsigned long min_setup_stop_ns, max_hold_data_ns; @@ -793,7 +793,6 @@ static int rk3x_i2c_v1_calc_timings(unsigned long clk_rate, /* These are the min dividers needed for min hold times. */ min_div_for_hold = (min_low_div + min_high_div); - min_total_ns = min_low_ns + min_high_ns; /* * This is the maximum divider so we don't go over the maximum. From 8dd1fe1594a712eb326e1607c694fbd1baf85f4b Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Fri, 16 Sep 2016 18:02:42 +0200 Subject: [PATCH 63/71] i2c: export i2c_adapter_depth() For crazy setups in which an i2c gpio expander is behind an i2c gpio multiplexer controlled by a gpio provided a second expander using the same device driver we need to explicitly tell lockdep how to handle nested locking. Export i2c_adapter_depth() as public API to be reused outside of i2c core code. Signed-off-by: Bartosz Golaszewski Acked-by: Peter Rosin Acked-by: Peter Zijlstra (Intel) Signed-off-by: Wolfram Sang --- drivers/i2c/i2c-core.c | 9 ++------- include/linux/i2c.h | 1 + 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index cdbbd9bdb7b4..981de21ab814 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -1426,13 +1426,7 @@ static void i2c_adapter_dev_release(struct device *dev) complete(&adap->dev_released); } -/* - * This function is only needed for mutex_lock_nested, so it is never - * called unless locking correctness checking is enabled. Thus we - * make it inline to avoid a compiler warning. That's what gcc ends up - * doing anyway. - */ -static inline unsigned int i2c_adapter_depth(struct i2c_adapter *adapter) +unsigned int i2c_adapter_depth(struct i2c_adapter *adapter) { unsigned int depth = 0; @@ -1441,6 +1435,7 @@ static inline unsigned int i2c_adapter_depth(struct i2c_adapter *adapter) return depth; } +EXPORT_SYMBOL_GPL(i2c_adapter_depth); /* * Let users instantiate I2C devices through sysfs. This can be used when diff --git a/include/linux/i2c.h b/include/linux/i2c.h index 4a4099d3a4b9..6422eef428c4 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -698,6 +698,7 @@ extern void i2c_clients_command(struct i2c_adapter *adap, extern struct i2c_adapter *i2c_get_adapter(int nr); extern void i2c_put_adapter(struct i2c_adapter *adap); +extern unsigned int i2c_adapter_depth(struct i2c_adapter *adapter); void i2c_parse_fw_timings(struct device *dev, struct i2c_timings *t, bool use_defaults); From a5ecddfe0bf82c92cc2e47385e287b21361a8d70 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Fri, 16 Sep 2016 18:02:43 +0200 Subject: [PATCH 64/71] lockdep: make MAX_LOCKDEP_SUBCLASSES unconditionally visible This define is needed by i2c_adapter_depth() to detect if we don't exceed the maximum number of lock subclasses. Make it visible even if lockdep is disabled. Signed-off-by: Bartosz Golaszewski Acked-by: Peter Rosin Acked-by: Peter Zijlstra (Intel) Signed-off-by: Wolfram Sang --- include/linux/lockdep.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h index eabe0138eb06..c1458fede1f9 100644 --- a/include/linux/lockdep.h +++ b/include/linux/lockdep.h @@ -16,6 +16,8 @@ struct lockdep_map; extern int prove_locking; extern int lock_stat; +#define MAX_LOCKDEP_SUBCLASSES 8UL + #ifdef CONFIG_LOCKDEP #include @@ -29,8 +31,6 @@ extern int lock_stat; */ #define XXX_LOCK_USAGE_STATES (1+3*4) -#define MAX_LOCKDEP_SUBCLASSES 8UL - /* * NR_LOCKDEP_CACHING_CLASSES ... Number of classes * cached in the instance of lockdep_map From 2771dc34ddaa313127d6431f23ae4cea26b869b0 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Fri, 16 Sep 2016 18:02:44 +0200 Subject: [PATCH 65/71] i2c: add a warning to i2c_adapter_depth() This routine is only used together with lockdep for nested locking. The number of lock subclasses is limited to 8 as defined in lockdep.h Emit a warning if the adapter depth exceeds the maximum number of lockdep subclasses. Signed-off-by: Bartosz Golaszewski Acked-by: Peter Rosin Acked-by: Peter Zijlstra (Intel) Signed-off-by: Wolfram Sang --- drivers/i2c/i2c-core.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 981de21ab814..98fffa3a09f7 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -1433,6 +1433,9 @@ unsigned int i2c_adapter_depth(struct i2c_adapter *adapter) while ((adapter = i2c_parent_is_i2c_adapter(adapter))) depth++; + WARN_ONCE(depth >= MAX_LOCKDEP_SUBCLASSES, + "adapter depth exceeds lockdep subclass limit\n"); + return depth; } EXPORT_SYMBOL_GPL(i2c_adapter_depth); From 559b46990e7635758d7350a4385d63682b181ed1 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Fri, 16 Sep 2016 18:02:45 +0200 Subject: [PATCH 66/71] gpio: pca953x: fix an incorrect lockdep warning If an I2C GPIO multiplexer is driven by a GPIO provided by an expander when there's a second expander using the same device driver on one of the I2C bus segments, lockdep prints a deadlock warning when trying to set the direction or the value of the GPIOs provided by the second expander. The below diagram presents the setup: - - - - - ------- --------- Bus segment 1 | | | | | |--------------- Devices | | SCL/SDA | | | | | Linux |-----------| I2C MUX | - - - - - | | | | | Bus segment 2 | | | | |------------------- ------- | --------- | | | - - - - - ------------ | MUX GPIO | | | | | Devices | GPIO | | | | | Expander 1 |---- - - - - - | | | ------------ | SCL/SDA | ------------ | | | GPIO | | Expander 2 | | | ------------ The reason for lockdep warning is that we take the chip->i2c_lock in pca953x_gpio_set_value() or pca953x_gpio_direction_output() and then come right back to pca953x_gpio_set_value() when the GPIO mux kicks in. The locks actually protect different expanders, but for lockdep both are of the same class, so it says: Possible unsafe locking scenario: CPU0 ---- lock(&chip->i2c_lock); lock(&chip->i2c_lock); *** DEADLOCK *** May be due to missing lock nesting notation In order to get rid of the warning, retrieve the adapter nesting depth and use it as lockdep subclass for chip->i2c_lock. Signed-off-by: Bartosz Golaszewski Acked-by: Peter Rosin Acked-by: Peter Zijlstra (Intel) Acked-by: Linus Walleij Signed-off-by: Wolfram Sang --- drivers/gpio/gpio-pca953x.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index 02f2a5621bb0..892dc043f40b 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -786,6 +786,8 @@ static int pca953x_probe(struct i2c_client *client, chip->chip_type = PCA_CHIP_TYPE(chip->driver_data); mutex_init(&chip->i2c_lock); + lockdep_set_subclass(&chip->i2c_lock, + i2c_adapter_depth(client->adapter)); /* initialize cached registers from their original values. * we can't share this chip with another i2c master. From 31158763ef2dba9393ddd205248b9c95d2b5b87c Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 23 Sep 2016 11:56:01 +0300 Subject: [PATCH 67/71] i2c: i801: Add support for Kaby Lake PCH-H Intel Kaby Lake PCH-H has the same legacy SMBus host controller than Intel Sunrisepoint PCH. It also has same iTCO watchdog on the bus. Add Kaby Lake PCH-H PCI ID to the list of supported devices. Signed-off-by: Andy Shevchenko Signed-off-by: Mika Westerberg Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-i801.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index 22a0ed4de80d..426fdbad6dae 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -64,6 +64,7 @@ * Broxton (SOC) 0x5ad4 32 hard yes yes yes * Lewisburg (PCH) 0xa1a3 32 hard yes yes yes * Lewisburg Supersku (PCH) 0xa223 32 hard yes yes yes + * Kaby Lake PCH-H (PCH) 0xa2a3 32 hard yes yes yes * * Features supported by this driver: * Software PEC no @@ -226,6 +227,7 @@ #define PCI_DEVICE_ID_INTEL_SUNRISEPOINT_H_SMBUS 0xa123 #define PCI_DEVICE_ID_INTEL_LEWISBURG_SMBUS 0xa1a3 #define PCI_DEVICE_ID_INTEL_LEWISBURG_SSKU_SMBUS 0xa223 +#define PCI_DEVICE_ID_INTEL_KABYLAKE_PCH_H_SMBUS 0xa2a3 struct i801_mux_config { char *gpio_chip; @@ -1006,6 +1008,7 @@ static const struct pci_device_id i801_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BROXTON_SMBUS) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LEWISBURG_SMBUS) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LEWISBURG_SSKU_SMBUS) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_KABYLAKE_PCH_H_SMBUS) }, { 0, } }; @@ -1482,6 +1485,7 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id) case PCI_DEVICE_ID_INTEL_LEWISBURG_SMBUS: case PCI_DEVICE_ID_INTEL_LEWISBURG_SSKU_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; From 6212e1d6ed4018ae3d3e6079ea0c45df346c97a6 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Sat, 24 Sep 2016 11:06:29 +0200 Subject: [PATCH 68/71] gpio: pca953x: variable 'id' was used twice sparse rightfully said: drivers/gpio/gpio-pca953x.c:771:45: warning: symbol 'id' shadows an earlier one drivers/gpio/gpio-pca953x.c:742:36: originally declared here So, name them explicitly 'i2c_id' and 'acpi_id' to avoid any confusion. Signed-off-by: Wolfram Sang --- drivers/gpio/gpio-pca953x.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index 892dc043f40b..018f39cc19c8 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -739,7 +739,7 @@ out: static const struct of_device_id pca953x_dt_ids[]; static int pca953x_probe(struct i2c_client *client, - const struct i2c_device_id *id) + const struct i2c_device_id *i2c_id) { struct pca953x_platform_data *pdata; struct pca953x_chip *chip; @@ -765,21 +765,21 @@ static int pca953x_probe(struct i2c_client *client, chip->client = client; - if (id) { - chip->driver_data = id->driver_data; + if (i2c_id) { + chip->driver_data = i2c_id->driver_data; } else { - const struct acpi_device_id *id; + const struct acpi_device_id *acpi_id; const struct of_device_id *match; match = of_match_device(pca953x_dt_ids, &client->dev); if (match) { chip->driver_data = (int)(uintptr_t)match->data; } else { - id = acpi_match_device(pca953x_acpi_ids, &client->dev); - if (!id) + acpi_id = acpi_match_device(pca953x_acpi_ids, &client->dev); + if (!acpi_id) return -ENODEV; - chip->driver_data = id->driver_data; + chip->driver_data = acpi_id->driver_data; } } From fcbd4bddb314346a35295701f385b9627bb3a137 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 23 Sep 2016 22:34:41 +0900 Subject: [PATCH 69/71] i2c: uniphier-f: fix misdetection of incomplete STOP condition Currently, the status register FI2C_SR is checked immediately after a STOP condition is issued in case of the deferred STOP condition. It takes typically 5-10 usec until the corresponding bits in the register are set, so the error check for "stop condition was not completed" is very likely to be false positive. Add wait code to relax the status register check. Signed-off-by: Masahiro Yamada Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-uniphier-f.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/i2c/busses/i2c-uniphier-f.c b/drivers/i2c/busses/i2c-uniphier-f.c index 829df91cc759..db9105e52c79 100644 --- a/drivers/i2c/busses/i2c-uniphier-f.c +++ b/drivers/i2c/busses/i2c-uniphier-f.c @@ -14,6 +14,7 @@ #include #include +#include #include #include #include @@ -348,14 +349,19 @@ static int uniphier_fi2c_master_xfer_one(struct i2c_adapter *adap, dev_dbg(&adap->dev, "complete\n"); if (unlikely(priv->flags & UNIPHIER_FI2C_DEFER_STOP_COMP)) { - u32 status = readl(priv->membase + UNIPHIER_FI2C_SR); + u32 status; + int ret; - if (!(status & UNIPHIER_FI2C_SR_STS) || - status & UNIPHIER_FI2C_SR_BB) { + ret = readl_poll_timeout(priv->membase + UNIPHIER_FI2C_SR, + status, + (status & UNIPHIER_FI2C_SR_STS) && + !(status & UNIPHIER_FI2C_SR_BB), + 1, 20); + if (ret) { dev_err(&adap->dev, "stop condition was not completed.\n"); uniphier_fi2c_recover(priv); - return -EBUSY; + return ret; } } From 70121f7f3725c82e8927a4e03ca1d50c98bbc6d2 Mon Sep 17 00:00:00 2001 From: Jan Glauber Date: Fri, 23 Sep 2016 11:40:39 +0200 Subject: [PATCH 70/71] i2c: octeon: thunderx: Limit register access retries Do not infinitely retry register readq and writeq operations in order to not lock up the CPU in case the TWSI gets stuck. Return -ETIMEDOUT in case of a failed data read. For all other cases just return so subsequent operations will fail. Signed-off-by: Jan Glauber Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-octeon-core.c | 4 +++- drivers/i2c/busses/i2c-octeon-core.h | 27 ++++++++++++++++----------- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/drivers/i2c/busses/i2c-octeon-core.c b/drivers/i2c/busses/i2c-octeon-core.c index 5e63b17f935d..419b54bfc7c7 100644 --- a/drivers/i2c/busses/i2c-octeon-core.c +++ b/drivers/i2c/busses/i2c-octeon-core.c @@ -381,7 +381,9 @@ static int octeon_i2c_read(struct octeon_i2c *i2c, int target, if (result) return result; - data[i] = octeon_i2c_data_read(i2c); + data[i] = octeon_i2c_data_read(i2c, &result); + if (result) + return result; if (recv_len && i == 0) { if (data[i] > I2C_SMBUS_BLOCK_MAX + 1) return -EPROTO; diff --git a/drivers/i2c/busses/i2c-octeon-core.h b/drivers/i2c/busses/i2c-octeon-core.h index 87151ea74acd..1db7c835a454 100644 --- a/drivers/i2c/busses/i2c-octeon-core.h +++ b/drivers/i2c/busses/i2c-octeon-core.h @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -144,9 +145,9 @@ static inline void octeon_i2c_reg_write(struct octeon_i2c *i2c, u64 eop_reg, u8 u64 tmp; __raw_writeq(SW_TWSI_V | eop_reg | data, i2c->twsi_base + SW_TWSI(i2c)); - do { - tmp = __raw_readq(i2c->twsi_base + SW_TWSI(i2c)); - } while ((tmp & SW_TWSI_V) != 0); + + readq_poll_timeout(i2c->twsi_base + SW_TWSI(i2c), tmp, tmp & SW_TWSI_V, + I2C_OCTEON_EVENT_WAIT, i2c->adap.timeout); } #define octeon_i2c_ctl_write(i2c, val) \ @@ -163,24 +164,28 @@ static inline void octeon_i2c_reg_write(struct octeon_i2c *i2c, u64 eop_reg, u8 * * The I2C core registers are accessed indirectly via the SW_TWSI CSR. */ -static inline u8 octeon_i2c_reg_read(struct octeon_i2c *i2c, u64 eop_reg) +static inline int octeon_i2c_reg_read(struct octeon_i2c *i2c, u64 eop_reg, + int *error) { u64 tmp; + int ret; __raw_writeq(SW_TWSI_V | eop_reg | SW_TWSI_R, i2c->twsi_base + SW_TWSI(i2c)); - do { - tmp = __raw_readq(i2c->twsi_base + SW_TWSI(i2c)); - } while ((tmp & SW_TWSI_V) != 0); + ret = readq_poll_timeout(i2c->twsi_base + SW_TWSI(i2c), tmp, + tmp & SW_TWSI_V, I2C_OCTEON_EVENT_WAIT, + i2c->adap.timeout); + if (error) + *error = ret; return tmp & 0xFF; } #define octeon_i2c_ctl_read(i2c) \ - octeon_i2c_reg_read(i2c, SW_TWSI_EOP_TWSI_CTL) -#define octeon_i2c_data_read(i2c) \ - octeon_i2c_reg_read(i2c, SW_TWSI_EOP_TWSI_DATA) + octeon_i2c_reg_read(i2c, SW_TWSI_EOP_TWSI_CTL, NULL) +#define octeon_i2c_data_read(i2c, error) \ + octeon_i2c_reg_read(i2c, SW_TWSI_EOP_TWSI_DATA, error) #define octeon_i2c_stat_read(i2c) \ - octeon_i2c_reg_read(i2c, SW_TWSI_EOP_TWSI_STAT) + octeon_i2c_reg_read(i2c, SW_TWSI_EOP_TWSI_STAT, NULL) /** * octeon_i2c_read_int - read the TWSI_INT register From 662786a5429c3a992c6f884a647ee32424822358 Mon Sep 17 00:00:00 2001 From: Alexey Khoroshilov Date: Fri, 23 Sep 2016 11:15:26 +0200 Subject: [PATCH 71/71] i2c: axxia: disable clks in case of failure in probe axxia_i2c_probe() does not disable clock in case of failure in i2c_add_adapter(). Also it ignores returned value from clk_prepare_enable(). Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-axxia.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/i2c/busses/i2c-axxia.c b/drivers/i2c/busses/i2c-axxia.c index d3bcaf4ab095..4351a9343058 100644 --- a/drivers/i2c/busses/i2c-axxia.c +++ b/drivers/i2c/busses/i2c-axxia.c @@ -545,7 +545,11 @@ static int axxia_i2c_probe(struct platform_device *pdev) return ret; } - clk_prepare_enable(idev->i2c_clk); + ret = clk_prepare_enable(idev->i2c_clk); + if (ret) { + dev_err(&pdev->dev, "failed to enable clock\n"); + return ret; + } i2c_set_adapdata(&idev->adapter, idev); strlcpy(idev->adapter.name, pdev->name, sizeof(idev->adapter.name)); @@ -558,7 +562,13 @@ static int axxia_i2c_probe(struct platform_device *pdev) platform_set_drvdata(pdev, idev); - return i2c_add_adapter(&idev->adapter); + ret = i2c_add_adapter(&idev->adapter); + if (ret) { + clk_disable_unprepare(idev->i2c_clk); + return ret; + } + + return 0; } static int axxia_i2c_remove(struct platform_device *pdev)