From 9d3dda5c0d092d6bc9911bf24de81350d47c6be6 Mon Sep 17 00:00:00 2001 From: Leilei Shang Date: Fri, 7 Jun 2013 14:38:17 +0800 Subject: i2c: pxa: enable high speed mode for i2c bus To enter high speed mode, following steps should be done: 1. When running in high speed mode, i2c clock rate is different from standard mode. Clock rate must be set according to specification first. 2. When i2c controller sends a master code and wins arbitration, high speed mode is entered. If you want to enable high speed mode, the following members of platform data should be set to proper value: 1. "high_mode" should be set to "1". 2. "master_code" should be set to "8'b 0000_1xxx"(x is 0 or 1). If no master_code is set, set to default value 0xe. 3. "rate" should be set according to specification. Signed-off-by: Leilei Shang Signed-off-by: Wolfram Sang --- include/linux/i2c/pxa-i2c.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'include') diff --git a/include/linux/i2c/pxa-i2c.h b/include/linux/i2c/pxa-i2c.h index 1a9f65e6ec0..53aab243cbd 100644 --- a/include/linux/i2c/pxa-i2c.h +++ b/include/linux/i2c/pxa-i2c.h @@ -67,6 +67,9 @@ struct i2c_pxa_platform_data { unsigned int class; unsigned int use_pio :1; unsigned int fast_mode :1; + unsigned int high_mode:1; + unsigned char master_code; + unsigned long rate; }; extern void pxa_set_i2c_info(struct i2c_pxa_platform_data *info); -- cgit v1.2.3-70-g09d2 From 3923172b3d700486c1ca24df9c4c5405a83e2309 Mon Sep 17 00:00:00 2001 From: Phil Carmody Date: Wed, 26 Jun 2013 10:56:35 +0300 Subject: i2c: reduce parent checking to a NOOP in non-I2C_MUX case In 0826374 - i2c: Multiplexed I2C bus core support core i2c code increased in size and complexity even when I2C_MUX wasn't selected. Turning this check into a constant NULL in the n case lets the client functions in be simplified too, not needing to include never-called calls to the mux-specific helpers. Signed-off-by: Phil Carmody Signed-off-by: Wolfram Sang --- include/linux/i2c.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include') diff --git a/include/linux/i2c.h b/include/linux/i2c.h index e988fa935b3..b3c4b8dac1c 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -447,11 +447,13 @@ static inline void i2c_set_adapdata(struct i2c_adapter *dev, void *data) static inline struct i2c_adapter * i2c_parent_is_i2c_adapter(const struct i2c_adapter *adapter) { +#if IS_ENABLED(I2C_MUX) struct device *parent = adapter->dev.parent; if (parent != NULL && parent->type == &i2c_adapter_type) return to_i2c_adapter(parent); else +#endif return NULL; } -- cgit v1.2.3-70-g09d2 From 687b81d083c082bc1e853032e3a2a54f8c251d27 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Thu, 11 Jul 2013 12:56:15 +0100 Subject: i2c: move OF helpers into the core I2C of helpers used to live in of_i2c.c but experience (from SPI) shows that it is much cleaner to have this in the core. This also removes a circular dependency between the helpers and the core, and so we can finally register child nodes in the core instead of doing this manually in each driver. So, fix the drivers and documentation, too. Signed-off-by: Wolfram Sang --- Documentation/acpi/enumeration.txt | 1 - arch/powerpc/platforms/44x/warp.c | 1 - drivers/gpu/drm/tilcdc/tilcdc_slave.c | 1 - drivers/gpu/drm/tilcdc/tilcdc_tfp410.c | 1 - drivers/gpu/host1x/drm/output.c | 2 +- drivers/i2c/busses/i2c-at91.c | 3 - drivers/i2c/busses/i2c-cpm.c | 6 -- drivers/i2c/busses/i2c-davinci.c | 2 - drivers/i2c/busses/i2c-designware-platdrv.c | 2 - drivers/i2c/busses/i2c-gpio.c | 3 - drivers/i2c/busses/i2c-i801.c | 2 - drivers/i2c/busses/i2c-ibm_iic.c | 4 - drivers/i2c/busses/i2c-imx.c | 3 - drivers/i2c/busses/i2c-mpc.c | 2 - drivers/i2c/busses/i2c-mv64xxx.c | 3 - drivers/i2c/busses/i2c-mxs.c | 3 - drivers/i2c/busses/i2c-nomadik.c | 3 - drivers/i2c/busses/i2c-ocores.c | 3 - drivers/i2c/busses/i2c-octeon.c | 3 - drivers/i2c/busses/i2c-omap.c | 3 - drivers/i2c/busses/i2c-pnx.c | 3 - drivers/i2c/busses/i2c-powermac.c | 9 +- drivers/i2c/busses/i2c-pxa.c | 2 - drivers/i2c/busses/i2c-s3c2410.c | 2 - drivers/i2c/busses/i2c-sh_mobile.c | 2 - drivers/i2c/busses/i2c-sirf.c | 3 - drivers/i2c/busses/i2c-stu300.c | 2 - drivers/i2c/busses/i2c-tegra.c | 3 - drivers/i2c/busses/i2c-versatile.c | 2 - drivers/i2c/busses/i2c-wmt.c | 3 - drivers/i2c/busses/i2c-xiic.c | 3 - drivers/i2c/i2c-core.c | 109 +++++++++++++++++++++- drivers/i2c/i2c-mux.c | 3 - drivers/i2c/muxes/i2c-arb-gpio-challenge.c | 1 - drivers/i2c/muxes/i2c-mux-gpio.c | 1 - drivers/i2c/muxes/i2c-mux-pinctrl.c | 1 - drivers/media/platform/exynos4-is/fimc-is-i2c.c | 4 +- drivers/media/platform/exynos4-is/fimc-is.c | 2 +- drivers/media/platform/exynos4-is/media-dev.c | 1 - drivers/of/Kconfig | 6 -- drivers/of/Makefile | 1 - drivers/of/of_i2c.c | 114 ------------------------ drivers/staging/imx-drm/imx-tve.c | 2 +- include/linux/i2c.h | 20 +++++ include/linux/of_i2c.h | 46 ---------- sound/soc/fsl/imx-sgtl5000.c | 2 +- sound/soc/fsl/imx-wm8962.c | 2 +- 47 files changed, 138 insertions(+), 262 deletions(-) delete mode 100644 drivers/of/of_i2c.c delete mode 100644 include/linux/of_i2c.h (limited to 'include') diff --git a/Documentation/acpi/enumeration.txt b/Documentation/acpi/enumeration.txt index d9be7a97dff..958266efcc2 100644 --- a/Documentation/acpi/enumeration.txt +++ b/Documentation/acpi/enumeration.txt @@ -238,7 +238,6 @@ An I2C bus (controller) driver does: if (ret) /* handle error */ - of_i2c_register_devices(adapter); /* Enumerate the slave devices behind this bus via ACPI */ acpi_i2c_register_devices(adapter); diff --git a/arch/powerpc/platforms/44x/warp.c b/arch/powerpc/platforms/44x/warp.c index 4cfa49901c0..534574a97ec 100644 --- a/arch/powerpc/platforms/44x/warp.c +++ b/arch/powerpc/platforms/44x/warp.c @@ -16,7 +16,6 @@ #include #include #include -#include #include #include diff --git a/drivers/gpu/drm/tilcdc/tilcdc_slave.c b/drivers/gpu/drm/tilcdc/tilcdc_slave.c index dfffaf01402..a19f657dfa5 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_slave.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_slave.c @@ -16,7 +16,6 @@ */ #include -#include #include #include #include diff --git a/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c b/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c index 925c7cddeff..c38b56b268a 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c @@ -16,7 +16,6 @@ */ #include -#include #include #include #include diff --git a/drivers/gpu/host1x/drm/output.c b/drivers/gpu/host1x/drm/output.c index 8140fc6c34d..137ae81ab80 100644 --- a/drivers/gpu/host1x/drm/output.c +++ b/drivers/gpu/host1x/drm/output.c @@ -9,7 +9,7 @@ #include #include -#include +#include #include "drm.h" diff --git a/drivers/i2c/busses/i2c-at91.c b/drivers/i2c/busses/i2c-at91.c index 6bb839b688b..fd059308aff 100644 --- a/drivers/i2c/busses/i2c-at91.c +++ b/drivers/i2c/busses/i2c-at91.c @@ -28,7 +28,6 @@ #include #include #include -#include #include #include #include @@ -775,8 +774,6 @@ static int at91_twi_probe(struct platform_device *pdev) return rc; } - of_i2c_register_devices(&dev->adapter); - dev_info(dev->dev, "AT91 i2c bus driver.\n"); return 0; } diff --git a/drivers/i2c/busses/i2c-cpm.c b/drivers/i2c/busses/i2c-cpm.c index 2e1f7eb55bf..b2b8aa9adc0 100644 --- a/drivers/i2c/busses/i2c-cpm.c +++ b/drivers/i2c/busses/i2c-cpm.c @@ -42,7 +42,6 @@ #include #include #include -#include #include #include @@ -681,11 +680,6 @@ static int cpm_i2c_probe(struct platform_device *ofdev) dev_dbg(&ofdev->dev, "hw routines for %s registered.\n", cpm->adap.name); - /* - * register OF I2C devices - */ - of_i2c_register_devices(&cpm->adap); - return 0; out_shut: cpm_i2c_shutdown(cpm); diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c index cf90bfff967..57473415be1 100644 --- a/drivers/i2c/busses/i2c-davinci.c +++ b/drivers/i2c/busses/i2c-davinci.c @@ -38,7 +38,6 @@ #include #include #include -#include #include #include @@ -726,7 +725,6 @@ static int davinci_i2c_probe(struct platform_device *pdev) dev_err(&pdev->dev, "failure adding adapter\n"); goto err_unuse_clocks; } - of_i2c_register_devices(adap); return 0; diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c index 64ffb908641..ded77c3bd59 100644 --- a/drivers/i2c/busses/i2c-designware-platdrv.c +++ b/drivers/i2c/busses/i2c-designware-platdrv.c @@ -35,7 +35,6 @@ #include #include #include -#include #include #include #include @@ -172,7 +171,6 @@ static int dw_i2c_probe(struct platform_device *pdev) dev_err(&pdev->dev, "failure adding adapter\n"); return r; } - of_i2c_register_devices(adap); acpi_i2c_register_devices(adap); pm_runtime_set_autosuspend_delay(&pdev->dev, 1000); diff --git a/drivers/i2c/busses/i2c-gpio.c b/drivers/i2c/busses/i2c-gpio.c index 8cdb4f743e1..bfa02c6c2dd 100644 --- a/drivers/i2c/busses/i2c-gpio.c +++ b/drivers/i2c/busses/i2c-gpio.c @@ -16,7 +16,6 @@ #include #include #include -#include struct i2c_gpio_private_data { struct i2c_adapter adap; @@ -224,8 +223,6 @@ static int i2c_gpio_probe(struct platform_device *pdev) if (ret) goto err_add_bus; - of_i2c_register_devices(adap); - platform_set_drvdata(pdev, priv); dev_info(&pdev->dev, "using pins %u (SDA) and %u (SCL%s)\n", diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index 4ebceed6bc6..4296d172127 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -87,7 +87,6 @@ #include #include #include -#include #if (defined CONFIG_I2C_MUX_GPIO || defined CONFIG_I2C_MUX_GPIO_MODULE) && \ defined CONFIG_DMI @@ -1230,7 +1229,6 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id) goto exit_free_irq; } - of_i2c_register_devices(&priv->adapter); i801_probe_optional_slaves(priv); /* We ignore errors - multiplexing is optional */ i801_add_mux(priv); diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c index 973f5168827..ff3caa0c28c 100644 --- a/drivers/i2c/busses/i2c-ibm_iic.c +++ b/drivers/i2c/busses/i2c-ibm_iic.c @@ -42,7 +42,6 @@ #include #include #include -#include #include "i2c-ibm_iic.h" @@ -759,9 +758,6 @@ static int iic_probe(struct platform_device *ofdev) dev_info(&ofdev->dev, "using %s mode\n", dev->fast_mode ? "fast (400 kHz)" : "standard (100 kHz)"); - /* Now register all the child nodes */ - of_i2c_register_devices(adap); - return 0; error_cleanup: diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c index a231d2fd91c..ccf46656bda 100644 --- a/drivers/i2c/busses/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c @@ -52,7 +52,6 @@ #include #include #include -#include #include /** Defines ******************************************************************** @@ -682,8 +681,6 @@ static int __init i2c_imx_probe(struct platform_device *pdev) return ret; } - of_i2c_register_devices(&i2c_imx->adapter); - /* Set up platform driver data */ platform_set_drvdata(pdev, i2c_imx); clk_disable_unprepare(i2c_imx->clk); diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c index ffac2145b94..f4060939e95 100644 --- a/drivers/i2c/busses/i2c-mpc.c +++ b/drivers/i2c/busses/i2c-mpc.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #include @@ -694,7 +693,6 @@ static int fsl_i2c_probe(struct platform_device *op) dev_err(i2c->dev, "failed to add adapter\n"); goto fail_add; } - of_i2c_register_devices(&i2c->adap); return result; diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c index bc60f9ac7c0..7f3a4744349 100644 --- a/drivers/i2c/busses/i2c-mv64xxx.c +++ b/drivers/i2c/busses/i2c-mv64xxx.c @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include @@ -871,8 +870,6 @@ mv64xxx_i2c_probe(struct platform_device *pd) goto exit_free_irq; } - of_i2c_register_devices(&drv_data->adapter); - return 0; exit_free_irq: diff --git a/drivers/i2c/busses/i2c-mxs.c b/drivers/i2c/busses/i2c-mxs.c index 46cda0b02fd..f4a01675fa7 100644 --- a/drivers/i2c/busses/i2c-mxs.c +++ b/drivers/i2c/busses/i2c-mxs.c @@ -27,7 +27,6 @@ #include #include #include -#include #include #include @@ -752,8 +751,6 @@ static int mxs_i2c_probe(struct platform_device *pdev) return err; } - of_i2c_register_devices(adap); - return 0; } diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c index 1909e807354..8bf9ac01301 100644 --- a/drivers/i2c/busses/i2c-nomadik.c +++ b/drivers/i2c/busses/i2c-nomadik.c @@ -24,7 +24,6 @@ #include #include #include -#include #include #define DRIVER_NAME "nmk-i2c" @@ -1045,8 +1044,6 @@ static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id) goto err_add_adap; } - of_i2c_register_devices(adap); - pm_runtime_put(&adev->dev); return 0; diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c index e14182cd87f..c61f37a10a0 100644 --- a/drivers/i2c/busses/i2c-ocores.c +++ b/drivers/i2c/busses/i2c-ocores.c @@ -24,7 +24,6 @@ #include #include #include -#include #include struct ocores_i2c { @@ -432,8 +431,6 @@ static int ocores_i2c_probe(struct platform_device *pdev) if (pdata) { for (i = 0; i < pdata->num_devices; i++) i2c_new_device(&i2c->adap, pdata->devices + i); - } else { - of_i2c_register_devices(&i2c->adap); } return 0; diff --git a/drivers/i2c/busses/i2c-octeon.c b/drivers/i2c/busses/i2c-octeon.c index 956fe320f31..b929ba271b4 100644 --- a/drivers/i2c/busses/i2c-octeon.c +++ b/drivers/i2c/busses/i2c-octeon.c @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include @@ -599,8 +598,6 @@ static int octeon_i2c_probe(struct platform_device *pdev) } dev_info(i2c->dev, "version %s\n", DRV_VERSION); - of_i2c_register_devices(&i2c->adap); - return 0; out: diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index 9ccb7b9cb6f..6d8308d5dc4 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -38,7 +38,6 @@ #include #include #include -#include #include #include #include @@ -1231,8 +1230,6 @@ omap_i2c_probe(struct platform_device *pdev) dev_info(dev->dev, "bus %d rev%d.%d at %d kHz\n", adap->nr, major, minor, dev->speed); - of_i2c_register_devices(adap); - pm_runtime_mark_last_busy(dev->dev); pm_runtime_put_autosuspend(dev->dev); diff --git a/drivers/i2c/busses/i2c-pnx.c b/drivers/i2c/busses/i2c-pnx.c index 1713b3ee61f..d09577a05d0 100644 --- a/drivers/i2c/busses/i2c-pnx.c +++ b/drivers/i2c/busses/i2c-pnx.c @@ -23,7 +23,6 @@ #include #include #include -#include #define I2C_PNX_TIMEOUT_DEFAULT 10 /* msec */ #define I2C_PNX_SPEED_KHZ_DEFAULT 100 @@ -741,8 +740,6 @@ static int i2c_pnx_probe(struct platform_device *pdev) goto out_irq; } - of_i2c_register_devices(&alg_data->adapter); - 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-powermac.c b/drivers/i2c/busses/i2c-powermac.c index 06858d57655..37e8cfad625 100644 --- a/drivers/i2c/busses/i2c-powermac.c +++ b/drivers/i2c/busses/i2c-powermac.c @@ -440,7 +440,9 @@ static int i2c_powermac_probe(struct platform_device *dev) adapter->algo = &i2c_powermac_algorithm; i2c_set_adapdata(adapter, bus); adapter->dev.parent = &dev->dev; - adapter->dev.of_node = dev->dev.of_node; + + /* Clear of_node to skip automatic registration of i2c child nodes */ + adapter->dev.of_node = NULL; rc = i2c_add_adapter(adapter); if (rc) { printk(KERN_ERR "i2c-powermac: Adapter %s registration " @@ -451,9 +453,8 @@ static int i2c_powermac_probe(struct platform_device *dev) printk(KERN_INFO "PowerMac i2c bus %s registered\n", adapter->name); - /* Cannot use of_i2c_register_devices() due to Apple device-tree - * funkyness - */ + /* Use custom child registration due to Apple device-tree funkyness */ + adapter->dev.of_node = dev->dev.of_node; i2c_powermac_register_devices(adapter, bus); return 0; diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c index 3dbc1acdc28..bbe6dfbc5c0 100644 --- a/drivers/i2c/busses/i2c-pxa.c +++ b/drivers/i2c/busses/i2c-pxa.c @@ -31,7 +31,6 @@ #include #include #include -#include #include #include #include @@ -1247,7 +1246,6 @@ static int i2c_pxa_probe(struct platform_device *dev) printk(KERN_INFO "I2C: Failed to add bus\n"); goto eadapt; } - of_i2c_register_devices(&i2c->adap); platform_set_drvdata(dev, i2c); diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c index 0a077b1ef94..3535f3c0f7b 100644 --- a/drivers/i2c/busses/i2c-s3c2410.c +++ b/drivers/i2c/busses/i2c-s3c2410.c @@ -36,7 +36,6 @@ #include #include #include -#include #include #include @@ -1154,7 +1153,6 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) return ret; } - of_i2c_register_devices(&i2c->adap); platform_set_drvdata(pdev, i2c); pm_runtime_enable(&pdev->dev); diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c index 4e86a3190d4..55110ddbed1 100644 --- a/drivers/i2c/busses/i2c-sh_mobile.c +++ b/drivers/i2c/busses/i2c-sh_mobile.c @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include @@ -758,7 +757,6 @@ static int sh_mobile_i2c_probe(struct platform_device *dev) "I2C adapter %d with bus speed %lu Hz (L/H=%x/%x)\n", adap->nr, pd->bus_speed, pd->iccl, pd->icch); - of_i2c_register_devices(adap); return 0; err_all: diff --git a/drivers/i2c/busses/i2c-sirf.c b/drivers/i2c/busses/i2c-sirf.c index a63c7d50683..0ff22e29e7d 100644 --- a/drivers/i2c/busses/i2c-sirf.c +++ b/drivers/i2c/busses/i2c-sirf.c @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include @@ -366,8 +365,6 @@ static int i2c_sirfsoc_probe(struct platform_device *pdev) clk_disable(clk); - of_i2c_register_devices(adap); - dev_info(&pdev->dev, " I2C adapter ready to operate\n"); return 0; diff --git a/drivers/i2c/busses/i2c-stu300.c b/drivers/i2c/busses/i2c-stu300.c index 19a40afaf17..f8f6f2e552d 100644 --- a/drivers/i2c/busses/i2c-stu300.c +++ b/drivers/i2c/busses/i2c-stu300.c @@ -17,7 +17,6 @@ #include #include #include -#include /* the name of this kernel module */ #define NAME "stu300" @@ -933,7 +932,6 @@ stu300_probe(struct platform_device *pdev) platform_set_drvdata(pdev, dev); dev_info(&pdev->dev, "ST DDC I2C @ %p, irq %d\n", dev->virtbase, dev->irq); - of_i2c_register_devices(adap); return 0; } diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index 9aa1b60f7fd..c457cb447c6 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include @@ -802,8 +801,6 @@ static int tegra_i2c_probe(struct platform_device *pdev) return ret; } - of_i2c_register_devices(&i2c_dev->adapter); - return 0; } diff --git a/drivers/i2c/busses/i2c-versatile.c b/drivers/i2c/busses/i2c-versatile.c index f3a8790a07e..6bb3a89a440 100644 --- a/drivers/i2c/busses/i2c-versatile.c +++ b/drivers/i2c/busses/i2c-versatile.c @@ -16,7 +16,6 @@ #include #include #include -#include #define I2C_CONTROL 0x00 #define I2C_CONTROLS 0x00 @@ -108,7 +107,6 @@ static int i2c_versatile_probe(struct platform_device *dev) ret = i2c_bit_add_numbered_bus(&i2c->adap); if (ret >= 0) { platform_set_drvdata(dev, i2c); - of_i2c_register_devices(&i2c->adap); return 0; } diff --git a/drivers/i2c/busses/i2c-wmt.c b/drivers/i2c/busses/i2c-wmt.c index baaa7d15b73..c65da3d913a 100644 --- a/drivers/i2c/busses/i2c-wmt.c +++ b/drivers/i2c/busses/i2c-wmt.c @@ -21,7 +21,6 @@ #include #include #include -#include #include #include @@ -439,8 +438,6 @@ static int wmt_i2c_probe(struct platform_device *pdev) platform_set_drvdata(pdev, i2c_dev); - of_i2c_register_devices(adap); - return 0; } diff --git a/drivers/i2c/busses/i2c-xiic.c b/drivers/i2c/busses/i2c-xiic.c index 433f377b386..4c8b368d463 100644 --- a/drivers/i2c/busses/i2c-xiic.c +++ b/drivers/i2c/busses/i2c-xiic.c @@ -40,7 +40,6 @@ #include #include #include -#include #define DRIVER_NAME "xiic-i2c" @@ -752,8 +751,6 @@ static int xiic_i2c_probe(struct platform_device *pdev) i2c_new_device(&i2c->adap, pdata->devices + i); } - of_i2c_register_devices(&i2c->adap); - return 0; add_adapter_failed: diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 3d9ca2d3d77..e874b052b4f 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -23,7 +23,11 @@ SMBus 2.0 support by Mark Studebaker and Jean Delvare Mux support by Rodolfo Giometti and - Michael Lawnick */ + Michael Lawnick + OF support is copyright (c) 2008 Jochen Friedrich + (based on a previous patch from Jon Smirl ) and + (c) 2013 Wolfram Sang + */ #include #include @@ -35,7 +39,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -954,6 +960,104 @@ static void i2c_scan_static_board_info(struct i2c_adapter *adapter) up_read(&__i2c_board_lock); } +/* OF support code */ + +#if IS_ENABLED(CONFIG_OF) +static void of_i2c_register_devices(struct i2c_adapter *adap) +{ + void *result; + struct device_node *node; + + /* Only register child devices if the adapter has a node pointer set */ + if (!adap->dev.of_node) + return; + + dev_dbg(&adap->dev, "of_i2c: walking child nodes\n"); + + for_each_available_child_of_node(adap->dev.of_node, node) { + struct i2c_board_info info = {}; + struct dev_archdata dev_ad = {}; + const __be32 *addr; + int len; + + dev_dbg(&adap->dev, "of_i2c: register %s\n", node->full_name); + + if (of_modalias_node(node, info.type, sizeof(info.type)) < 0) { + dev_err(&adap->dev, "of_i2c: modalias failure on %s\n", + node->full_name); + continue; + } + + addr = of_get_property(node, "reg", &len); + if (!addr || (len < sizeof(int))) { + dev_err(&adap->dev, "of_i2c: invalid reg on %s\n", + node->full_name); + continue; + } + + info.addr = be32_to_cpup(addr); + if (info.addr > (1 << 10) - 1) { + dev_err(&adap->dev, "of_i2c: invalid addr=%x on %s\n", + info.addr, node->full_name); + continue; + } + + info.irq = irq_of_parse_and_map(node, 0); + info.of_node = of_node_get(node); + info.archdata = &dev_ad; + + if (of_get_property(node, "wakeup-source", NULL)) + info.flags |= I2C_CLIENT_WAKE; + + request_module("%s%s", I2C_MODULE_PREFIX, info.type); + + result = i2c_new_device(adap, &info); + if (result == NULL) { + dev_err(&adap->dev, "of_i2c: Failure registering %s\n", + node->full_name); + of_node_put(node); + irq_dispose_mapping(info.irq); + continue; + } + } +} + +static int of_dev_node_match(struct device *dev, void *data) +{ + return dev->of_node == data; +} + +/* must call put_device() when done with returned i2c_client device */ +struct i2c_client *of_find_i2c_device_by_node(struct device_node *node) +{ + struct device *dev; + + dev = bus_find_device(&i2c_bus_type, NULL, node, + of_dev_node_match); + if (!dev) + return NULL; + + return i2c_verify_client(dev); +} +EXPORT_SYMBOL(of_find_i2c_device_by_node); + +/* must call put_device() when done with returned i2c_adapter device */ +struct i2c_adapter *of_find_i2c_adapter_by_node(struct device_node *node) +{ + struct device *dev; + + dev = bus_find_device(&i2c_bus_type, NULL, node, + of_dev_node_match); + if (!dev) + return NULL; + + return i2c_verify_adapter(dev); +} +EXPORT_SYMBOL(of_find_i2c_adapter_by_node); +#else +static void of_i2c_register_devices(struct i2c_adapter *adap) { } +#endif /* CONFIG_OF */ + static int i2c_do_add_adapter(struct i2c_driver *driver, struct i2c_adapter *adap) { @@ -1058,6 +1162,8 @@ static int i2c_register_adapter(struct i2c_adapter *adap) exit_recovery: /* create pre-declared device nodes */ + of_i2c_register_devices(adap); + if (adap->nr < __i2c_first_dynamic_bus_num) i2c_scan_static_board_info(adap); @@ -1282,7 +1388,6 @@ void i2c_del_adapter(struct i2c_adapter *adap) } EXPORT_SYMBOL(i2c_del_adapter); - /* ------------------------------------------------------------------------- */ int i2c_for_each_dev(void *data, int (*fn)(struct device *, void *)) diff --git a/drivers/i2c/i2c-mux.c b/drivers/i2c/i2c-mux.c index 7409ebb33c4..797e3117bef 100644 --- a/drivers/i2c/i2c-mux.c +++ b/drivers/i2c/i2c-mux.c @@ -25,7 +25,6 @@ #include #include #include -#include /* multiplexer per channel data */ struct i2c_mux_priv { @@ -185,8 +184,6 @@ struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent, dev_info(&parent->dev, "Added multiplexed i2c bus %d\n", i2c_adapter_id(&priv->adap)); - of_i2c_register_devices(&priv->adap); - return &priv->adap; } EXPORT_SYMBOL_GPL(i2c_add_mux_adapter); diff --git a/drivers/i2c/muxes/i2c-arb-gpio-challenge.c b/drivers/i2c/muxes/i2c-arb-gpio-challenge.c index f7bf24375f8..74b41ae690f 100644 --- a/drivers/i2c/muxes/i2c-arb-gpio-challenge.c +++ b/drivers/i2c/muxes/i2c-arb-gpio-challenge.c @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/i2c/muxes/i2c-mux-gpio.c b/drivers/i2c/muxes/i2c-mux-gpio.c index 6a206e8d58f..5d4a99ba743 100644 --- a/drivers/i2c/muxes/i2c-mux-gpio.c +++ b/drivers/i2c/muxes/i2c-mux-gpio.c @@ -16,7 +16,6 @@ #include #include #include -#include #include struct gpiomux { diff --git a/drivers/i2c/muxes/i2c-mux-pinctrl.c b/drivers/i2c/muxes/i2c-mux-pinctrl.c index 0d082027c29..69a91732ae6 100644 --- a/drivers/i2c/muxes/i2c-mux-pinctrl.c +++ b/drivers/i2c/muxes/i2c-mux-pinctrl.c @@ -20,7 +20,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/media/platform/exynos4-is/fimc-is-i2c.c b/drivers/media/platform/exynos4-is/fimc-is-i2c.c index 617a798d923..99305560521 100644 --- a/drivers/media/platform/exynos4-is/fimc-is-i2c.c +++ b/drivers/media/platform/exynos4-is/fimc-is-i2c.c @@ -12,7 +12,7 @@ #include #include -#include +#include #include #include #include @@ -67,8 +67,6 @@ static int fimc_is_i2c_probe(struct platform_device *pdev) pm_runtime_enable(&pdev->dev); pm_runtime_enable(&i2c_adap->dev); - of_i2c_register_devices(i2c_adap); - return 0; } diff --git a/drivers/media/platform/exynos4-is/fimc-is.c b/drivers/media/platform/exynos4-is/fimc-is.c index 967f6a93934..2276fdc213c 100644 --- a/drivers/media/platform/exynos4-is/fimc-is.c +++ b/drivers/media/platform/exynos4-is/fimc-is.c @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/drivers/media/platform/exynos4-is/media-dev.c b/drivers/media/platform/exynos4-is/media-dev.c index 19f556c5957..f8c66b434fd 100644 --- a/drivers/media/platform/exynos4-is/media-dev.c +++ b/drivers/media/platform/exynos4-is/media-dev.c @@ -20,7 +20,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig index 80e5c13b930..78cc7605332 100644 --- a/drivers/of/Kconfig +++ b/drivers/of/Kconfig @@ -48,12 +48,6 @@ config OF_IRQ def_bool y depends on !SPARC -config OF_I2C - def_tristate I2C - depends on I2C - help - OpenFirmware I2C accessors - config OF_NET depends on NETDEVICES def_bool y diff --git a/drivers/of/Makefile b/drivers/of/Makefile index 1f9c0c492ef..efd05102c40 100644 --- a/drivers/of/Makefile +++ b/drivers/of/Makefile @@ -3,7 +3,6 @@ obj-$(CONFIG_OF_FLATTREE) += fdt.o obj-$(CONFIG_OF_PROMTREE) += pdt.o obj-$(CONFIG_OF_ADDRESS) += address.o obj-$(CONFIG_OF_IRQ) += irq.o -obj-$(CONFIG_OF_I2C) += of_i2c.o obj-$(CONFIG_OF_NET) += of_net.o obj-$(CONFIG_OF_SELFTEST) += selftest.o obj-$(CONFIG_OF_MDIO) += of_mdio.o diff --git a/drivers/of/of_i2c.c b/drivers/of/of_i2c.c deleted file mode 100644 index b667264222c..00000000000 --- a/drivers/of/of_i2c.c +++ /dev/null @@ -1,114 +0,0 @@ -/* - * OF helpers for the I2C API - * - * Copyright (c) 2008 Jochen Friedrich - * - * Based on a previous patch from Jon Smirl - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include -#include -#include -#include -#include -#include - -void of_i2c_register_devices(struct i2c_adapter *adap) -{ - void *result; - struct device_node *node; - - /* Only register child devices if the adapter has a node pointer set */ - if (!adap->dev.of_node) - return; - - dev_dbg(&adap->dev, "of_i2c: walking child nodes\n"); - - for_each_available_child_of_node(adap->dev.of_node, node) { - struct i2c_board_info info = {}; - struct dev_archdata dev_ad = {}; - const __be32 *addr; - int len; - - dev_dbg(&adap->dev, "of_i2c: register %s\n", node->full_name); - - if (of_modalias_node(node, info.type, sizeof(info.type)) < 0) { - dev_err(&adap->dev, "of_i2c: modalias failure on %s\n", - node->full_name); - continue; - } - - addr = of_get_property(node, "reg", &len); - if (!addr || (len < sizeof(int))) { - dev_err(&adap->dev, "of_i2c: invalid reg on %s\n", - node->full_name); - continue; - } - - info.addr = be32_to_cpup(addr); - if (info.addr > (1 << 10) - 1) { - dev_err(&adap->dev, "of_i2c: invalid addr=%x on %s\n", - info.addr, node->full_name); - continue; - } - - info.irq = irq_of_parse_and_map(node, 0); - info.of_node = of_node_get(node); - info.archdata = &dev_ad; - - if (of_get_property(node, "wakeup-source", NULL)) - info.flags |= I2C_CLIENT_WAKE; - - request_module("%s%s", I2C_MODULE_PREFIX, info.type); - - result = i2c_new_device(adap, &info); - if (result == NULL) { - dev_err(&adap->dev, "of_i2c: Failure registering %s\n", - node->full_name); - of_node_put(node); - irq_dispose_mapping(info.irq); - continue; - } - } -} -EXPORT_SYMBOL(of_i2c_register_devices); - -static int of_dev_node_match(struct device *dev, void *data) -{ - return dev->of_node == data; -} - -/* must call put_device() when done with returned i2c_client device */ -struct i2c_client *of_find_i2c_device_by_node(struct device_node *node) -{ - struct device *dev; - - dev = bus_find_device(&i2c_bus_type, NULL, node, - of_dev_node_match); - if (!dev) - return NULL; - - return i2c_verify_client(dev); -} -EXPORT_SYMBOL(of_find_i2c_device_by_node); - -/* must call put_device() when done with returned i2c_adapter device */ -struct i2c_adapter *of_find_i2c_adapter_by_node(struct device_node *node) -{ - struct device *dev; - - dev = bus_find_device(&i2c_bus_type, NULL, node, - of_dev_node_match); - if (!dev) - return NULL; - - return i2c_verify_adapter(dev); -} -EXPORT_SYMBOL(of_find_i2c_adapter_by_node); - -MODULE_LICENSE("GPL"); diff --git a/drivers/staging/imx-drm/imx-tve.c b/drivers/staging/imx-drm/imx-tve.c index a56797d88ed..2d76fd47c3d 100644 --- a/drivers/staging/imx-drm/imx-tve.c +++ b/drivers/staging/imx-drm/imx-tve.c @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/include/linux/i2c.h b/include/linux/i2c.h index b3c4b8dac1c..ed53696e31a 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -544,6 +544,26 @@ static inline int i2c_adapter_id(struct i2c_adapter *adap) #endif /* I2C */ +#if IS_ENABLED(CONFIG_OF) +/* must call put_device() when done with returned i2c_client device */ +extern struct i2c_client *of_find_i2c_device_by_node(struct device_node *node); + +/* must call put_device() when done with returned i2c_adapter device */ +extern struct i2c_adapter *of_find_i2c_adapter_by_node(struct device_node *node); + +#else + +static inline struct i2c_client *of_find_i2c_device_by_node(struct device_node *node) +{ + return NULL; +} + +static inline struct i2c_adapter *of_find_i2c_adapter_by_node(struct device_node *node) +{ + return NULL; +} +#endif /* CONFIG_OF */ + #if IS_ENABLED(CONFIG_ACPI_I2C) extern void acpi_i2c_register_devices(struct i2c_adapter *adap); #else diff --git a/include/linux/of_i2c.h b/include/linux/of_i2c.h deleted file mode 100644 index cfb545cd86b..00000000000 --- a/include/linux/of_i2c.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Generic I2C API implementation for PowerPC. - * - * Copyright (c) 2008 Jochen Friedrich - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#ifndef __LINUX_OF_I2C_H -#define __LINUX_OF_I2C_H - -#if defined(CONFIG_OF_I2C) || defined(CONFIG_OF_I2C_MODULE) -#include - -extern void of_i2c_register_devices(struct i2c_adapter *adap); - -/* must call put_device() when done with returned i2c_client device */ -extern struct i2c_client *of_find_i2c_device_by_node(struct device_node *node); - -/* must call put_device() when done with returned i2c_adapter device */ -extern struct i2c_adapter *of_find_i2c_adapter_by_node( - struct device_node *node); - -#else -static inline void of_i2c_register_devices(struct i2c_adapter *adap) -{ - return; -} - -static inline struct i2c_client *of_find_i2c_device_by_node(struct device_node *node) -{ - return NULL; -} - -/* must call put_device() when done with returned i2c_adapter device */ -static inline struct i2c_adapter *of_find_i2c_adapter_by_node( - struct device_node *node) -{ - return NULL; -} -#endif /* CONFIG_OF_I2C */ - -#endif /* __LINUX_OF_I2C_H */ diff --git a/sound/soc/fsl/imx-sgtl5000.c b/sound/soc/fsl/imx-sgtl5000.c index 3f726e4f88d..f2fbde9c3d4 100644 --- a/sound/soc/fsl/imx-sgtl5000.c +++ b/sound/soc/fsl/imx-sgtl5000.c @@ -13,7 +13,7 @@ #include #include #include -#include +#include #include #include diff --git a/sound/soc/fsl/imx-wm8962.c b/sound/soc/fsl/imx-wm8962.c index 52a36a90f4f..9fd7a65ae83 100644 --- a/sound/soc/fsl/imx-wm8962.c +++ b/sound/soc/fsl/imx-wm8962.c @@ -15,7 +15,7 @@ #include #include -#include +#include #include #include #include -- cgit v1.2.3-70-g09d2 From 55e71edb81b2b45273e7b284cce13ff24bde846f Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Wed, 21 Aug 2013 17:28:23 +0300 Subject: i2c: move ACPI helpers into the core This follows what has already been done for the DeviceTree helpers. Move the ACPI helpers from drivers/acpi/acpi_i2c.c to the I2C core and update documentation accordingly. This also solves a problem reported by Jerry Snitselaar that we can't build the ACPI I2C helpers as a module. Signed-off-by: Mika Westerberg Acked-by: Rafael J. Wysocki Signed-off-by: Wolfram Sang --- Documentation/acpi/enumeration.txt | 15 +--- drivers/acpi/Kconfig | 6 -- drivers/acpi/Makefile | 1 - drivers/acpi/acpi_i2c.c | 103 ---------------------------- drivers/i2c/busses/i2c-designware-platdrv.c | 1 - drivers/i2c/i2c-core.c | 91 ++++++++++++++++++++++++ include/linux/i2c.h | 6 -- 7 files changed, 94 insertions(+), 129 deletions(-) delete mode 100644 drivers/acpi/acpi_i2c.c (limited to 'include') diff --git a/Documentation/acpi/enumeration.txt b/Documentation/acpi/enumeration.txt index 958266efcc2..d977778b5e6 100644 --- a/Documentation/acpi/enumeration.txt +++ b/Documentation/acpi/enumeration.txt @@ -228,18 +228,9 @@ ACPI handle like: I2C serial bus support ~~~~~~~~~~~~~~~~~~~~~~ The slaves behind I2C bus controller only need to add the ACPI IDs like -with the platform and SPI drivers. However the I2C bus controller driver -needs to call acpi_i2c_register_devices() after it has added the adapter. - -An I2C bus (controller) driver does: - - ... - ret = i2c_add_numbered_adapter(adapter); - if (ret) - /* handle error */ - - /* Enumerate the slave devices behind this bus via ACPI */ - acpi_i2c_register_devices(adapter); +with the platform and SPI drivers. The I2C core automatically enumerates +any slave devices behind the controller device once the adapter is +registered. Below is an example of how to add ACPI support to the existing mpu3050 input driver: diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 100bd724f64..4e0162fa5d3 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -180,12 +180,6 @@ config ACPI_DOCK This driver supports ACPI-controlled docking stations and removable drive bays such as the IBM Ultrabay and the Dell Module Bay. -config ACPI_I2C - def_tristate I2C - depends on I2C - help - ACPI I2C enumeration support. - config ACPI_PROCESSOR tristate "Processor" select THERMAL diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index 81dbeb83bb4..cdaf68b58b0 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -73,7 +73,6 @@ obj-$(CONFIG_ACPI_HED) += hed.o obj-$(CONFIG_ACPI_EC_DEBUGFS) += ec_sys.o obj-$(CONFIG_ACPI_CUSTOM_METHOD)+= custom_method.o obj-$(CONFIG_ACPI_BGRT) += bgrt.o -obj-$(CONFIG_ACPI_I2C) += acpi_i2c.o # processor has its own "processor." module_param namespace processor-y := processor_driver.o processor_throttling.o diff --git a/drivers/acpi/acpi_i2c.c b/drivers/acpi/acpi_i2c.c deleted file mode 100644 index a82c7626aa9..00000000000 --- a/drivers/acpi/acpi_i2c.c +++ /dev/null @@ -1,103 +0,0 @@ -/* - * ACPI I2C enumeration support - * - * Copyright (C) 2012, Intel Corporation - * Author: Mika Westerberg - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include - -ACPI_MODULE_NAME("i2c"); - -static int acpi_i2c_add_resource(struct acpi_resource *ares, void *data) -{ - struct i2c_board_info *info = data; - - if (ares->type == ACPI_RESOURCE_TYPE_SERIAL_BUS) { - struct acpi_resource_i2c_serialbus *sb; - - sb = &ares->data.i2c_serial_bus; - if (sb->type == ACPI_RESOURCE_SERIAL_TYPE_I2C) { - info->addr = sb->slave_address; - if (sb->access_mode == ACPI_I2C_10BIT_MODE) - info->flags |= I2C_CLIENT_TEN; - } - } else if (info->irq < 0) { - struct resource r; - - if (acpi_dev_resource_interrupt(ares, 0, &r)) - info->irq = r.start; - } - - /* Tell the ACPI core to skip this resource */ - return 1; -} - -static acpi_status acpi_i2c_add_device(acpi_handle handle, u32 level, - void *data, void **return_value) -{ - struct i2c_adapter *adapter = data; - struct list_head resource_list; - struct i2c_board_info info; - struct acpi_device *adev; - int ret; - - if (acpi_bus_get_device(handle, &adev)) - return AE_OK; - if (acpi_bus_get_status(adev) || !adev->status.present) - return AE_OK; - - memset(&info, 0, sizeof(info)); - info.acpi_node.handle = handle; - info.irq = -1; - - INIT_LIST_HEAD(&resource_list); - ret = acpi_dev_get_resources(adev, &resource_list, - acpi_i2c_add_resource, &info); - acpi_dev_free_resource_list(&resource_list); - - if (ret < 0 || !info.addr) - return AE_OK; - - strlcpy(info.type, dev_name(&adev->dev), sizeof(info.type)); - if (!i2c_new_device(adapter, &info)) { - dev_err(&adapter->dev, - "failed to add I2C device %s from ACPI\n", - dev_name(&adev->dev)); - } - - return AE_OK; -} - -/** - * acpi_i2c_register_devices - enumerate I2C slave devices behind adapter - * @adapter: 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. - */ -void acpi_i2c_register_devices(struct i2c_adapter *adapter) -{ - acpi_handle handle; - acpi_status status; - - handle = ACPI_HANDLE(adapter->dev.parent); - if (!handle) - return; - - status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1, - acpi_i2c_add_device, NULL, - adapter, NULL); - if (ACPI_FAILURE(status)) - dev_warn(&adapter->dev, "failed to enumerate I2C slaves\n"); -} -EXPORT_SYMBOL_GPL(acpi_i2c_register_devices); diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c index ded77c3bd59..6e99d9f56de 100644 --- a/drivers/i2c/busses/i2c-designware-platdrv.c +++ b/drivers/i2c/busses/i2c-designware-platdrv.c @@ -171,7 +171,6 @@ static int dw_i2c_probe(struct platform_device *pdev) dev_err(&pdev->dev, "failure adding adapter\n"); return r; } - acpi_i2c_register_devices(adap); pm_runtime_set_autosuspend_delay(&pdev->dev, 1000); pm_runtime_use_autosuspend(&pdev->dev); diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index e874b052b4f..29d3f045a2b 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -1058,6 +1058,96 @@ EXPORT_SYMBOL(of_find_i2c_adapter_by_node); static void of_i2c_register_devices(struct i2c_adapter *adap) { } #endif /* CONFIG_OF */ +/* ACPI support code */ + +#if IS_ENABLED(CONFIG_ACPI) +static int acpi_i2c_add_resource(struct acpi_resource *ares, void *data) +{ + struct i2c_board_info *info = data; + + if (ares->type == ACPI_RESOURCE_TYPE_SERIAL_BUS) { + struct acpi_resource_i2c_serialbus *sb; + + sb = &ares->data.i2c_serial_bus; + if (sb->type == ACPI_RESOURCE_SERIAL_TYPE_I2C) { + info->addr = sb->slave_address; + if (sb->access_mode == ACPI_I2C_10BIT_MODE) + info->flags |= I2C_CLIENT_TEN; + } + } else if (info->irq < 0) { + struct resource r; + + if (acpi_dev_resource_interrupt(ares, 0, &r)) + info->irq = r.start; + } + + /* Tell the ACPI core to skip this resource */ + return 1; +} + +static acpi_status acpi_i2c_add_device(acpi_handle handle, u32 level, + void *data, void **return_value) +{ + struct i2c_adapter *adapter = data; + struct list_head resource_list; + struct i2c_board_info info; + struct acpi_device *adev; + int ret; + + if (acpi_bus_get_device(handle, &adev)) + return AE_OK; + if (acpi_bus_get_status(adev) || !adev->status.present) + return AE_OK; + + memset(&info, 0, sizeof(info)); + info.acpi_node.handle = handle; + info.irq = -1; + + INIT_LIST_HEAD(&resource_list); + ret = acpi_dev_get_resources(adev, &resource_list, + acpi_i2c_add_resource, &info); + acpi_dev_free_resource_list(&resource_list); + + if (ret < 0 || !info.addr) + return AE_OK; + + strlcpy(info.type, dev_name(&adev->dev), sizeof(info.type)); + if (!i2c_new_device(adapter, &info)) { + dev_err(&adapter->dev, + "failed to add I2C device %s from ACPI\n", + dev_name(&adev->dev)); + } + + return AE_OK; +} + +/** + * acpi_i2c_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) +{ + acpi_handle handle; + acpi_status status; + + handle = ACPI_HANDLE(adap->dev.parent); + if (!handle) + return; + + status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1, + acpi_i2c_add_device, NULL, + adap, NULL); + if (ACPI_FAILURE(status)) + dev_warn(&adap->dev, "failed to enumerate I2C slaves\n"); +} +#else +static inline void acpi_i2c_register_devices(struct i2c_adapter *adap) {} +#endif /* CONFIG_ACPI */ + static int i2c_do_add_adapter(struct i2c_driver *driver, struct i2c_adapter *adap) { @@ -1163,6 +1253,7 @@ static int i2c_register_adapter(struct i2c_adapter *adap) exit_recovery: /* create pre-declared device nodes */ of_i2c_register_devices(adap); + acpi_i2c_register_devices(adap); if (adap->nr < __i2c_first_dynamic_bus_num) i2c_scan_static_board_info(adap); diff --git a/include/linux/i2c.h b/include/linux/i2c.h index ed53696e31a..2ab11dc3807 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -564,10 +564,4 @@ static inline struct i2c_adapter *of_find_i2c_adapter_by_node(struct device_node } #endif /* CONFIG_OF */ -#if IS_ENABLED(CONFIG_ACPI_I2C) -extern void acpi_i2c_register_devices(struct i2c_adapter *adap); -#else -static inline void acpi_i2c_register_devices(struct i2c_adapter *adap) {} -#endif - #endif /* _LINUX_I2C_H */ -- cgit v1.2.3-70-g09d2