]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
Merge branch 'i2c/for-4.12' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa...
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 3 May 2017 19:18:47 +0000 (12:18 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 3 May 2017 19:18:47 +0000 (12:18 -0700)
Pull i2c updates from Wilfram Sang:
 "I2C has the following updates for you:

   - an immutable cross-subsystem branch fixing PMIC access on Intel
     Baytrail

   - bigger driver updates to the designware, meson, exynos5 drivers

   - new i2c_acpi_new_device() function to create devices from ACPI

   - struct i2c_driver has now a flag 'disable_i2c_core_irq_mapping' to
     allow custom IRQ mapping in case the default does not fit

   - mux subsystem centralized error messages in its core

   - new driver for ltc4306 i2c mux

   - usual set of small updates"

* 'i2c/for-4.12' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux: (44 commits)
  i2c: thunderx: Enable HWMON class probing
  i2c: rcar: clarify PM handling with more comments
  i2c: rcar: fix resume by always initializing registers before transfer
  i2c: tegra: fix spelling mistake: "contoller" -> "controller"
  i2c: exynos5: use core helper to get driver data
  i2c: exynos5: de-duplicate error logs on clock setup
  i2c: exynos5: simplify clock frequency handling
  i2c: exynos5: simplify timings calculation
  i2c: designware-baytrail: fix potential null pointer dereference on dev
  i2c: designware: Get selected speed mode sda-hold-time via ACPI
  [media] cx231xx: stop double error reporting
  i2c: core: Allow drivers to disable i2c-core irq mapping
  i2c: core: Add new i2c_acpi_new_device helper function
  i2c: core: Allow getting ACPI info by index
  i2c: img-scb: use setup_timer
  i2c: i2c-scmi: add a MS HID
  i2c: mux: ltc4306: LTC4306 and LTC4305 I2C multiplexer/switch
  dt-bindings: i2c: mux: ltc4306: Add dt-bindings for I2C multiplexer/switch
  i2c: mux: reg: stop double error reporting
  i2c: mux: pinctrl: stop double error reporting
  ...

31 files changed:
Documentation/devicetree/bindings/i2c/i2c-meson.txt
Documentation/devicetree/bindings/i2c/i2c-mux-ltc4306.txt [new file with mode: 0644]
Documentation/devicetree/bindings/i2c/i2c-rk3x.txt
MAINTAINERS
drivers/i2c/busses/Kconfig
drivers/i2c/busses/i2c-designware-baytrail.c
drivers/i2c/busses/i2c-designware-core.c
drivers/i2c/busses/i2c-designware-core.h
drivers/i2c/busses/i2c-designware-platdrv.c
drivers/i2c/busses/i2c-exynos5.c
drivers/i2c/busses/i2c-img-scb.c
drivers/i2c/busses/i2c-meson.c
drivers/i2c/busses/i2c-mv64xxx.c
drivers/i2c/busses/i2c-rcar.c
drivers/i2c/busses/i2c-scmi.c
drivers/i2c/busses/i2c-tegra-bpmp.c
drivers/i2c/busses/i2c-thunderx-pcidrv.c
drivers/i2c/busses/i2c-xlp9xx.c
drivers/i2c/i2c-core.c
drivers/i2c/i2c-mux.c
drivers/i2c/muxes/Kconfig
drivers/i2c/muxes/Makefile
drivers/i2c/muxes/i2c-arb-gpio-challenge.c
drivers/i2c/muxes/i2c-mux-gpio.c
drivers/i2c/muxes/i2c-mux-ltc4306.c [new file with mode: 0644]
drivers/i2c/muxes/i2c-mux-pca9541.c
drivers/i2c/muxes/i2c-mux-pca954x.c
drivers/i2c/muxes/i2c-mux-pinctrl.c
drivers/i2c/muxes/i2c-mux-reg.c
drivers/media/usb/cx231xx/cx231xx-i2c.c
include/linux/i2c.h

index 386357d1aab05de652675bf6ed19c0dc22b50709..611b934c7e104d4ec0b844bbca59b54c45471009 100644 (file)
@@ -8,6 +8,8 @@ Required properties:
  - #address-cells: should be <1>
  - #size-cells: should be <0>
 
+For details regarding the following core I2C bindings see also i2c.txt.
+
 Optional properties:
 - clock-frequency: the desired I2C bus clock frequency in Hz; in
   absence of this property the default value is used (100 kHz).
diff --git a/Documentation/devicetree/bindings/i2c/i2c-mux-ltc4306.txt b/Documentation/devicetree/bindings/i2c/i2c-mux-ltc4306.txt
new file mode 100644 (file)
index 0000000..1e98c6b
--- /dev/null
@@ -0,0 +1,61 @@
+* Linear Technology / Analog Devices I2C bus switch
+
+Required Properties:
+
+  - compatible: Must contain one of the following.
+    "lltc,ltc4305", "lltc,ltc4306"
+  - reg: The I2C address of the device.
+
+  The following required properties are defined externally:
+
+  - Standard I2C mux properties. See i2c-mux.txt in this directory.
+  - I2C child bus nodes. See i2c-mux.txt in this directory.
+
+Optional Properties:
+
+  - enable-gpios: Reference to the GPIO connected to the enable input.
+  - i2c-mux-idle-disconnect: Boolean; if defined, forces mux to disconnect all
+    children in idle state. This is necessary for example, if there are several
+    multiplexers on the bus and the devices behind them use same I2C addresses.
+  - gpio-controller: Marks the device node as a GPIO Controller.
+  - #gpio-cells: Should be two.  The first cell is the pin number and
+       the second cell is used to specify flags.
+       See ../gpio/gpio.txt for more information.
+  - ltc,downstream-accelerators-enable: Enables the rise time accelerators
+       on the downstream port.
+  - ltc,upstream-accelerators-enable: Enables the rise time accelerators
+       on the upstream port.
+
+Example:
+
+       ltc4306: i2c-mux@4a {
+               compatible = "lltc,ltc4306";
+               #address-cells = <1>;
+               #size-cells = <0>;
+               reg = <0x4a>;
+
+               gpio-controller;
+               #gpio-cells = <2>;
+
+               i2c@0 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <0>;
+
+                       eeprom@50 {
+                               compatible = "at,24c02";
+                               reg = <0x50>;
+                       };
+               };
+
+               i2c@1 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <1>;
+
+                       eeprom@50 {
+                               compatible = "at,24c02";
+                               reg = <0x50>;
+                       };
+               };
+       };
index bbc5a1ed5fa188557a4c45828ea8ba5d65f46893..e18445d0980cc6ab5d2b0d6b3b10fb35e6d3cff3 100644 (file)
@@ -11,6 +11,7 @@ Required properties :
    - "rockchip,rk3188-i2c": for rk3188
    - "rockchip,rk3228-i2c": for rk3228
    - "rockchip,rk3288-i2c": for rk3288
+   - "rockchip,rk3328-i2c", "rockchip,rk3399-i2c": for rk3328
    - "rockchip,rk3399-i2c": for rk3399
  - interrupts : interrupt number
  - clocks: See ../clock/clock-bindings.txt
index 7046de618fdda580dcbef22b4f48010ce77749c7..95803b7b61be292fb59f0372dbf24a62896039b5 100644 (file)
@@ -7775,6 +7775,14 @@ S:       Maintained
 F:     Documentation/hwmon/ltc4261
 F:     drivers/hwmon/ltc4261.c
 
+LTC4306 I2C MULTIPLEXER DRIVER
+M:     Michael Hennerich <michael.hennerich@analog.com>
+W:     http://ez.analog.com/community/linux-device-drivers
+L:     linux-i2c@vger.kernel.org
+S:     Supported
+F:     drivers/i2c/muxes/i2c-mux-ltc4306.c
+F:     Documentation/devicetree/bindings/i2c/i2c-mux-ltc4306.txt
+
 LTP (Linux Test Project)
 M:     Mike Frysinger <vapier@gentoo.org>
 M:     Cyril Hrubis <chrubis@suse.cz>
index 8adc0f1d7ad0ba72240fcae0ff2feb8e7c517456..144cbadc7c728d38661cd231f704751cce6b0227 100644 (file)
@@ -933,6 +933,7 @@ config I2C_TEGRA
 config I2C_TEGRA_BPMP
        tristate "NVIDIA Tegra BPMP I2C controller"
        depends on TEGRA_BPMP
+       default y
        help
          If you say yes to this option, support will be included for the I2C
          controller embedded in NVIDIA Tegra SoCs accessed via the BPMP.
@@ -1021,7 +1022,7 @@ config I2C_XLR
 
 config I2C_XLP9XX
        tristate "XLP9XX I2C support"
-       depends on CPU_XLP || ARCH_VULCAN || COMPILE_TEST
+       depends on CPU_XLP || ARCH_THUNDER2 || COMPILE_TEST
        help
          This driver enables support for the on-chip I2C interface of
          the Broadcom XLP9xx/XLP5xx MIPS and Vulcan ARM64 processors.
index 1749a0f5a9fafada3a19b7bb73c62742a243301a..dbda8c9c8a1ce07e0563182d3dbe01d6380b5ac6 100644 (file)
@@ -22,7 +22,7 @@
 
 #include "i2c-designware-core.h"
 
-#define SEMAPHORE_TIMEOUT      100
+#define SEMAPHORE_TIMEOUT      500
 #define PUNIT_SEMAPHORE                0x7
 #define PUNIT_SEMAPHORE_CHT    0x10e
 #define PUNIT_SEMAPHORE_BIT    BIT(0)
@@ -70,7 +70,7 @@ static void reset_semaphore(struct dw_i2c_dev *dev)
 
 static int baytrail_i2c_acquire(struct dw_i2c_dev *dev)
 {
-       u32 addr = get_sem_addr(dev);
+       u32 addr;
        u32 sem = PUNIT_SEMAPHORE_ACQUIRE;
        int ret;
        unsigned long start, end;
@@ -94,6 +94,8 @@ static int baytrail_i2c_acquire(struct dw_i2c_dev *dev)
         */
        pm_qos_update_request(&dev->pm_qos, 0);
 
+       addr = get_sem_addr(dev);
+
        /* host driver writes to side band semaphore register */
        ret = iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE, addr, sem);
        if (ret) {
@@ -170,7 +172,7 @@ int i2c_dw_probe_lock_support(struct dw_i2c_dev *dev)
        dev_info(dev->dev, "I2C bus managed by PUNIT\n");
        dev->acquire_lock = baytrail_i2c_acquire;
        dev->release_lock = baytrail_i2c_release;
-       dev->pm_runtime_disabled = true;
+       dev->pm_disabled = true;
 
        pm_qos_add_request(&dev->pm_qos, PM_QOS_CPU_DMA_LATENCY,
                           PM_QOS_DEFAULT_VALUE);
index 15a534818d4f5cf318d57de49ddc42247d8ded26..c453717b753b724a36aa4986aa90a5c16b2619b1 100644 (file)
@@ -960,6 +960,7 @@ EXPORT_SYMBOL_GPL(i2c_dw_read_comp_param);
 int i2c_dw_probe(struct dw_i2c_dev *dev)
 {
        struct i2c_adapter *adap = &dev->adapter;
+       unsigned long irq_flags;
        int r;
 
        init_completion(&dev->cmd_complete);
@@ -975,9 +976,15 @@ int i2c_dw_probe(struct dw_i2c_dev *dev)
        adap->dev.parent = dev->dev;
        i2c_set_adapdata(adap, dev);
 
+       if (dev->pm_disabled) {
+               dev_pm_syscore_device(dev->dev, true);
+               irq_flags = IRQF_NO_SUSPEND;
+       } else {
+               irq_flags = IRQF_SHARED | IRQF_COND_SUSPEND;
+       }
+
        i2c_dw_disable_int(dev);
-       r = devm_request_irq(dev->dev, dev->irq, i2c_dw_isr,
-                            IRQF_SHARED | IRQF_COND_SUSPEND,
+       r = devm_request_irq(dev->dev, dev->irq, i2c_dw_isr, irq_flags,
                             dev_name(dev->dev), dev);
        if (r) {
                dev_err(dev->dev, "failure requesting irq %i: %d\n",
index 846ea57f85af014856d78c2bf62a01cd7b13d800..a7cf429daf60da4f60eb96fdfdfb00c1f2c9d26c 100644 (file)
@@ -79,7 +79,7 @@
  * @pm_qos: pm_qos_request used while holding a hardware lock on the bus
  * @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
+ * @pm_disabled: true if power-management should be disabled for this i2c-bus
  *
  * HCNT and LCNT parameters can be used if the platform knows more accurate
  * values than the one computed based only on the input clock frequency.
@@ -128,7 +128,7 @@ struct dw_i2c_dev {
        struct pm_qos_request   pm_qos;
        int                     (*acquire_lock)(struct dw_i2c_dev *dev);
        void                    (*release_lock)(struct dw_i2c_dev *dev);
-       bool                    pm_runtime_disabled;
+       bool                    pm_disabled;
 };
 
 #define ACCESS_SWAP            0x00000001
index d8665098dce9d0536b0fcb957bea01e590008ece..5a4eb6b6bd9295b0b0acfbd3ace526947d686647 100644 (file)
@@ -85,8 +85,7 @@ static void dw_i2c_acpi_params(struct platform_device *pdev, char method[],
 
                *hcnt = (u16)objs[0].integer.value;
                *lcnt = (u16)objs[1].integer.value;
-               if (sda_hold)
-                       *sda_hold = (u32)objs[2].integer.value;
+               *sda_hold = (u32)objs[2].integer.value;
        }
 
        kfree(buf.pointer);
@@ -95,26 +94,55 @@ static void dw_i2c_acpi_params(struct platform_device *pdev, char method[],
 static int dw_i2c_acpi_configure(struct platform_device *pdev)
 {
        struct dw_i2c_dev *dev = platform_get_drvdata(pdev);
+       acpi_handle handle = ACPI_HANDLE(&pdev->dev);
        const struct acpi_device_id *id;
+       struct acpi_device *adev;
+       const char *uid;
 
        dev->adapter.nr = -1;
        dev->tx_fifo_depth = 32;
        dev->rx_fifo_depth = 32;
 
        /*
-        * Try to get SDA hold time and *CNT values from an ACPI method if
-        * it exists for both supported speed modes.
+        * Try to get SDA hold time and *CNT values from an ACPI method for
+        * selected speed modes.
         */
-       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);
+       switch (dev->clk_freq) {
+       case 100000:
+               dw_i2c_acpi_params(pdev, "SSCN", &dev->ss_hcnt, &dev->ss_lcnt,
+                                  &dev->sda_hold_time);
+               break;
+       case 1000000:
+               dw_i2c_acpi_params(pdev, "FPCN", &dev->fp_hcnt, &dev->fp_lcnt,
+                                  &dev->sda_hold_time);
+               break;
+       case 3400000:
+               dw_i2c_acpi_params(pdev, "HSCN", &dev->hs_hcnt, &dev->hs_lcnt,
+                                  &dev->sda_hold_time);
+               break;
+       case 400000:
+       default:
+               dw_i2c_acpi_params(pdev, "FMCN", &dev->fs_hcnt, &dev->fs_lcnt,
+                                  &dev->sda_hold_time);
+               break;
+       }
 
        id = acpi_match_device(pdev->dev.driver->acpi_match_table, &pdev->dev);
        if (id && id->driver_data)
                dev->flags |= (u32)id->driver_data;
 
+       if (acpi_bus_get_device(handle, &adev))
+               return -ENODEV;
+
+       /*
+        * Cherrytrail I2C7 gets used for the PMIC which gets accessed
+        * through ACPI opregions during late suspend / early resume
+        * disable pm for it.
+        */
+       uid = adev->pnp.unique_id;
+       if ((dev->flags & MODEL_CHERRYTRAIL) && !strcmp(uid, "7"))
+               dev->pm_disabled = true;
+
        return 0;
 }
 
@@ -286,7 +314,7 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
        ACPI_COMPANION_SET(&adap->dev, ACPI_COMPANION(&pdev->dev));
        adap->dev.of_node = pdev->dev.of_node;
 
-       if (dev->pm_runtime_disabled) {
+       if (dev->pm_disabled) {
                pm_runtime_forbid(&pdev->dev);
        } else {
                pm_runtime_set_autosuspend_delay(&pdev->dev, 1000);
@@ -302,7 +330,7 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
        return r;
 
 exit_probe:
-       if (!dev->pm_runtime_disabled)
+       if (!dev->pm_disabled)
                pm_runtime_disable(&pdev->dev);
 exit_reset:
        if (!IS_ERR_OR_NULL(dev->rst))
@@ -322,7 +350,7 @@ static int dw_i2c_plat_remove(struct platform_device *pdev)
 
        pm_runtime_dont_use_autosuspend(&pdev->dev);
        pm_runtime_put_sync(&pdev->dev);
-       if (!dev->pm_runtime_disabled)
+       if (!dev->pm_disabled)
                pm_runtime_disable(&pdev->dev);
        if (!IS_ERR_OR_NULL(dev->rst))
                reset_control_assert(dev->rst);
@@ -374,9 +402,7 @@ static int dw_i2c_plat_resume(struct device *dev)
        struct dw_i2c_dev *i_dev = platform_get_drvdata(pdev);
 
        i2c_dw_plat_prepare_clk(i_dev, true);
-
-       if (!i_dev->pm_runtime_disabled)
-               i2c_dw_init(i_dev);
+       i2c_dw_init(i_dev);
 
        return 0;
 }
index 736a82472101733d7ada08b360c9f159c35371cb..23ed4d67ecad6bff296ffb80607525df03d5f482 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/slab.h>
 #include <linux/io.h>
 #include <linux/of_address.h>
+#include <linux/of_device.h>
 #include <linux/of_irq.h>
 #include <linux/spinlock.h>
 
  */
 #define HSI2C_HS_TX_CLOCK      1000000
 #define HSI2C_FS_TX_CLOCK      100000
-#define HSI2C_HIGH_SPD         1
-#define HSI2C_FAST_SPD         0
 
 #define EXYNOS5_I2C_TIMEOUT (msecs_to_jiffies(1000))
 
@@ -200,18 +199,10 @@ struct exynos5_i2c {
        int                     trans_done;
 
        /* Controller operating frequency */
-       unsigned int            fs_clock;
-       unsigned int            hs_clock;
-
-       /*
-        * HSI2C Controller can operate in
-        * 1. High speed upto 3.4Mbps
-        * 2. Fast speed upto 1Mbps
-        */
-       int                     speed_mode;
+       unsigned int            op_clock;
 
        /* Version of HS-I2C Hardware */
-       struct exynos_hsi2c_variant     *variant;
+       const struct exynos_hsi2c_variant *variant;
 };
 
 /**
@@ -257,15 +248,6 @@ static const struct of_device_id exynos5_i2c_match[] = {
 };
 MODULE_DEVICE_TABLE(of, exynos5_i2c_match);
 
-static inline struct exynos_hsi2c_variant *exynos5_i2c_get_variant
-                                       (struct platform_device *pdev)
-{
-       const struct of_device_id *match;
-
-       match = of_match_node(exynos5_i2c_match, pdev->dev.of_node);
-       return (struct exynos_hsi2c_variant *)match->data;
-}
-
 static void exynos5_i2c_clr_pend_irq(struct exynos5_i2c *i2c)
 {
        writel(readl(i2c->regs + HSI2C_INT_STATUS),
@@ -279,7 +261,7 @@ static void exynos5_i2c_clr_pend_irq(struct exynos5_i2c *i2c)
  * Returns 0 on success, -EINVAL if the cycle length cannot
  * be calculated.
  */
-static int exynos5_i2c_set_timing(struct exynos5_i2c *i2c, int mode)
+static int exynos5_i2c_set_timing(struct exynos5_i2c *i2c, bool hs_timings)
 {
        u32 i2c_timing_s1;
        u32 i2c_timing_s2;
@@ -292,9 +274,10 @@ static int exynos5_i2c_set_timing(struct exynos5_i2c *i2c, int mode)
        unsigned int t_sr_release;
        unsigned int t_ftl_cycle;
        unsigned int clkin = clk_get_rate(i2c->clk);
-       unsigned int div, utemp0 = 0, utemp1 = 0, clk_cycle;
-       unsigned int op_clk = (mode == HSI2C_HIGH_SPD) ?
-                               i2c->hs_clock : i2c->fs_clock;
+       unsigned int op_clk = hs_timings ? i2c->op_clock :
+               (i2c->op_clock >= HSI2C_HS_TX_CLOCK) ? HSI2C_FS_TX_CLOCK :
+               i2c->op_clock;
+       int div, clk_cycle, temp;
 
        /*
         * In case of HSI2C controller in Exynos5 series
@@ -305,33 +288,22 @@ static int exynos5_i2c_set_timing(struct exynos5_i2c *i2c, int mode)
         * FPCLK / FI2C =
         * (CLK_DIV + 1) * (TSCLK_L + TSCLK_H + 2) + 8 + FLT_CYCLE
         *
-        * utemp0 = (CLK_DIV + 1) * (TSCLK_L + TSCLK_H + 2)
-        * utemp1 = (TSCLK_L + TSCLK_H + 2)
+        * clk_cycle := TSCLK_L + TSCLK_H
+        * temp := (CLK_DIV + 1) * (clk_cycle + 2)
+        *
+        * Constraints: 4 <= temp, 0 <= CLK_DIV < 256, 2 <= clk_cycle <= 510
+        *
         */
        t_ftl_cycle = (readl(i2c->regs + HSI2C_CONF) >> 16) & 0x7;
-       utemp0 = (clkin / op_clk) - 8;
-
-       if (i2c->variant->hw == HSI2C_EXYNOS7)
-               utemp0 -= t_ftl_cycle;
-       else
-               utemp0 -= 2 * t_ftl_cycle;
-
-       /* CLK_DIV max is 256 */
-       for (div = 0; div < 256; div++) {
-               utemp1 = utemp0 / (div + 1);
-
-               /*
-                * SCL_L and SCL_H each has max value of 255
-                * Hence, For the clk_cycle to the have right value
-                * utemp1 has to be less then 512 and more than 4.
-                */
-               if ((utemp1 < 512) && (utemp1 > 4)) {
-                       clk_cycle = utemp1 - 2;
-                       break;
-               } else if (div == 255) {
-                       dev_warn(i2c->dev, "Failed to calculate divisor");
-                       return -EINVAL;
-               }
+       temp = clkin / op_clk - 8 - t_ftl_cycle;
+       if (i2c->variant->hw != HSI2C_EXYNOS7)
+               temp -= t_ftl_cycle;
+       div = temp / 512;
+       clk_cycle = temp / (div + 1) - 2;
+       if (temp < 4 || div >= 256 || clk_cycle < 2) {
+               dev_err(i2c->dev, "%s clock set-up failed\n",
+                       hs_timings ? "HS" : "FS");
+               return -EINVAL;
        }
 
        t_scl_l = clk_cycle / 2;
@@ -356,7 +328,7 @@ static int exynos5_i2c_set_timing(struct exynos5_i2c *i2c, int mode)
                div, t_sr_release);
        dev_dbg(i2c->dev, "tDATA_HD: %X\n", t_data_hd);
 
-       if (mode == HSI2C_HIGH_SPD) {
+       if (hs_timings) {
                writel(i2c_timing_s1, i2c->regs + HSI2C_TIMING_HS1);
                writel(i2c_timing_s2, i2c->regs + HSI2C_TIMING_HS2);
                writel(i2c_timing_s3, i2c->regs + HSI2C_TIMING_HS3);
@@ -372,24 +344,13 @@ static int exynos5_i2c_set_timing(struct exynos5_i2c *i2c, int mode)
 
 static int exynos5_hsi2c_clock_setup(struct exynos5_i2c *i2c)
 {
-       /*
-        * Configure the Fast speed timing values
-        * Even the High Speed mode initially starts with Fast mode
-        */
-       if (exynos5_i2c_set_timing(i2c, HSI2C_FAST_SPD)) {
-               dev_err(i2c->dev, "HSI2C FS Clock set up failed\n");
-               return -EINVAL;
-       }
+       /* always set Fast Speed timings */
+       int ret = exynos5_i2c_set_timing(i2c, false);
 
-       /* configure the High speed timing values */
-       if (i2c->speed_mode == HSI2C_HIGH_SPD) {
-               if (exynos5_i2c_set_timing(i2c, HSI2C_HIGH_SPD)) {
-                       dev_err(i2c->dev, "HSI2C HS Clock set up failed\n");
-                       return -EINVAL;
-               }
-       }
+       if (ret < 0 || i2c->op_clock < HSI2C_HS_TX_CLOCK)
+               return ret;
 
-       return 0;
+       return exynos5_i2c_set_timing(i2c, true);
 }
 
 /*
@@ -409,7 +370,7 @@ static void exynos5_i2c_init(struct exynos5_i2c *i2c)
                                        i2c->regs + HSI2C_CTL);
        writel(HSI2C_TRAILING_COUNT, i2c->regs + HSI2C_TRAILIG_CTL);
 
-       if (i2c->speed_mode == HSI2C_HIGH_SPD) {
+       if (i2c->op_clock >= HSI2C_HS_TX_CLOCK) {
                writel(HSI2C_MASTER_ID(MASTER_ID(i2c->adap.nr)),
                                        i2c->regs + HSI2C_ADDR);
                i2c_conf |= HSI2C_HS_MODE;
@@ -747,26 +708,14 @@ static int exynos5_i2c_probe(struct platform_device *pdev)
        struct device_node *np = pdev->dev.of_node;
        struct exynos5_i2c *i2c;
        struct resource *mem;
-       unsigned int op_clock;
        int ret;
 
        i2c = devm_kzalloc(&pdev->dev, sizeof(struct exynos5_i2c), GFP_KERNEL);
        if (!i2c)
                return -ENOMEM;
 
-       if (of_property_read_u32(np, "clock-frequency", &op_clock)) {
-               i2c->speed_mode = HSI2C_FAST_SPD;
-               i2c->fs_clock = HSI2C_FS_TX_CLOCK;
-       } else {
-               if (op_clock >= HSI2C_HS_TX_CLOCK) {
-                       i2c->speed_mode = HSI2C_HIGH_SPD;
-                       i2c->fs_clock = HSI2C_FS_TX_CLOCK;
-                       i2c->hs_clock = op_clock;
-               } else {
-                       i2c->speed_mode = HSI2C_FAST_SPD;
-                       i2c->fs_clock = op_clock;
-               }
-       }
+       if (of_property_read_u32(np, "clock-frequency", &i2c->op_clock))
+               i2c->op_clock = HSI2C_FS_TX_CLOCK;
 
        strlcpy(i2c->adap.name, "exynos5-i2c", sizeof(i2c->adap.name));
        i2c->adap.owner   = THIS_MODULE;
@@ -817,8 +766,7 @@ static int exynos5_i2c_probe(struct platform_device *pdev)
                goto err_clk;
        }
 
-       /* Need to check the variant before setting up. */
-       i2c->variant = exynos5_i2c_get_variant(pdev);
+       i2c->variant = of_device_get_match_data(&pdev->dev);
 
        ret = exynos5_hsi2c_clock_setup(i2c);
        if (ret)
index db8e8b40569d98aa2a4f107eddf574f0e5a31cd2..84fb35f6837f0861e628ecab0527dbc6561db008 100644 (file)
@@ -1362,9 +1362,8 @@ static int img_i2c_probe(struct platform_device *pdev)
        }
 
        /* Set up the exception check timer */
-       init_timer(&i2c->check_timer);
-       i2c->check_timer.function = img_i2c_check_timer;
-       i2c->check_timer.data = (unsigned long)i2c;
+       setup_timer(&i2c->check_timer, img_i2c_check_timer,
+                   (unsigned long)i2c);
 
        i2c->bitrate = timings[0].max_bitrate;
        if (!of_property_read_u32(node, "clock-frequency", &val))
index 73b97c71a484ee186fcb488c1b758cbb04178898..88d15b92ec35e6293747e6ecf553f69a2b6b0cdf 100644 (file)
 #define REG_CTRL_STATUS                BIT(2)
 #define REG_CTRL_ERROR         BIT(3)
 #define REG_CTRL_CLKDIV_SHIFT  12
-#define REG_CTRL_CLKDIV_MASK   ((BIT(10) - 1) << REG_CTRL_CLKDIV_SHIFT)
+#define REG_CTRL_CLKDIV_MASK   GENMASK(21, 12)
+#define REG_CTRL_CLKDIVEXT_SHIFT 28
+#define REG_CTRL_CLKDIVEXT_MASK        GENMASK(29, 28)
 
 #define I2C_TIMEOUT_MS         500
-#define DEFAULT_FREQ           100000
 
 enum {
        TOKEN_END = 0,
@@ -54,7 +55,6 @@ enum {
        STATE_IDLE,
        STATE_READ,
        STATE_WRITE,
-       STATE_STOP,
 };
 
 /**
@@ -73,7 +73,6 @@ enum {
  * @error:     Flag set when an error is received
  * @lock:      To avoid race conditions between irq handler and xfer code
  * @done:      Completion used to wait for transfer termination
- * @frequency: Operating frequency of I2C bus clock
  * @tokens:    Sequence of tokens to be written to the device
  * @num_tokens:        Number of tokens
  */
@@ -82,7 +81,6 @@ struct meson_i2c {
        struct device           *dev;
        void __iomem            *regs;
        struct clk              *clk;
-       int                     irq;
 
        struct i2c_msg          *msg;
        int                     state;
@@ -93,7 +91,6 @@ struct meson_i2c {
 
        spinlock_t              lock;
        struct completion       done;
-       unsigned int            frequency;
        u32                     tokens[2];
        int                     num_tokens;
 };
@@ -126,23 +123,27 @@ static void meson_i2c_add_token(struct meson_i2c *i2c, int token)
        i2c->num_tokens++;
 }
 
-static void meson_i2c_write_tokens(struct meson_i2c *i2c)
-{
-       writel(i2c->tokens[0], i2c->regs + REG_TOK_LIST0);
-       writel(i2c->tokens[1], i2c->regs + REG_TOK_LIST1);
-}
-
-static void meson_i2c_set_clk_div(struct meson_i2c *i2c)
+static void meson_i2c_set_clk_div(struct meson_i2c *i2c, unsigned int freq)
 {
        unsigned long clk_rate = clk_get_rate(i2c->clk);
        unsigned int div;
 
-       div = DIV_ROUND_UP(clk_rate, i2c->frequency * 4);
+       div = DIV_ROUND_UP(clk_rate, freq * 4);
+
+       /* clock divider has 12 bits */
+       if (div >= (1 << 12)) {
+               dev_err(i2c->dev, "requested bus frequency too low\n");
+               div = (1 << 12) - 1;
+       }
+
        meson_i2c_set_mask(i2c, REG_CTRL, REG_CTRL_CLKDIV_MASK,
-                          div << REG_CTRL_CLKDIV_SHIFT);
+                          (div & GENMASK(9, 0)) << REG_CTRL_CLKDIV_SHIFT);
+
+       meson_i2c_set_mask(i2c, REG_CTRL, REG_CTRL_CLKDIVEXT_MASK,
+                          (div >> 10) << REG_CTRL_CLKDIVEXT_SHIFT);
 
        dev_dbg(i2c->dev, "%s: clk %lu, freq %u, div %u\n", __func__,
-               clk_rate, i2c->frequency, div);
+               clk_rate, freq, div);
 }
 
 static void meson_i2c_get_data(struct meson_i2c *i2c, char *buf, int len)
@@ -156,10 +157,10 @@ static void meson_i2c_get_data(struct meson_i2c *i2c, char *buf, int len)
        dev_dbg(i2c->dev, "%s: data %08x %08x len %d\n", __func__,
                rdata0, rdata1, len);
 
-       for (i = 0; i < min_t(int, 4, len); i++)
+       for (i = 0; i < min(4, len); i++)
                *buf++ = (rdata0 >> i * 8) & 0xff;
 
-       for (i = 4; i < min_t(int, 8, len); i++)
+       for (i = 4; i < min(8, len); i++)
                *buf++ = (rdata1 >> (i - 4) * 8) & 0xff;
 }
 
@@ -168,10 +169,10 @@ static void meson_i2c_put_data(struct meson_i2c *i2c, char *buf, int len)
        u32 wdata0 = 0, wdata1 = 0;
        int i;
 
-       for (i = 0; i < min_t(int, 4, len); i++)
+       for (i = 0; i < min(4, len); i++)
                wdata0 |= *buf++ << (i * 8);
 
-       for (i = 4; i < min_t(int, 8, len); i++)
+       for (i = 4; i < min(8, len); i++)
                wdata1 |= *buf++ << ((i - 4) * 8);
 
        writel(wdata0, i2c->regs + REG_TOK_WDATA0);
@@ -186,7 +187,7 @@ static void meson_i2c_prepare_xfer(struct meson_i2c *i2c)
        bool write = !(i2c->msg->flags & I2C_M_RD);
        int i;
 
-       i2c->count = min_t(int, i2c->msg->len - i2c->pos, 8);
+       i2c->count = min(i2c->msg->len - i2c->pos, 8);
 
        for (i = 0; i < i2c->count - 1; i++)
                meson_i2c_add_token(i2c, TOKEN_DATA);
@@ -200,19 +201,12 @@ static void meson_i2c_prepare_xfer(struct meson_i2c *i2c)
 
        if (write)
                meson_i2c_put_data(i2c, i2c->msg->buf + i2c->pos, i2c->count);
-}
-
-static void meson_i2c_stop(struct meson_i2c *i2c)
-{
-       dev_dbg(i2c->dev, "%s: last %d\n", __func__, i2c->last);
 
-       if (i2c->last) {
-               i2c->state = STATE_STOP;
+       if (i2c->last && i2c->pos + i2c->count >= i2c->msg->len)
                meson_i2c_add_token(i2c, TOKEN_STOP);
-       } else {
-               i2c->state = STATE_IDLE;
-               complete(&i2c->done);
-       }
+
+       writel(i2c->tokens[0], i2c->regs + REG_TOK_LIST0);
+       writel(i2c->tokens[1], i2c->regs + REG_TOK_LIST1);
 }
 
 static irqreturn_t meson_i2c_irq(int irqno, void *dev_id)
@@ -223,12 +217,18 @@ static irqreturn_t meson_i2c_irq(int irqno, void *dev_id)
        spin_lock(&i2c->lock);
 
        meson_i2c_reset_tokens(i2c);
+       meson_i2c_set_mask(i2c, REG_CTRL, REG_CTRL_START, 0);
        ctrl = readl(i2c->regs + REG_CTRL);
 
        dev_dbg(i2c->dev, "irq: state %d, pos %d, count %d, ctrl %08x\n",
                i2c->state, i2c->pos, i2c->count, ctrl);
 
-       if (ctrl & REG_CTRL_ERROR && i2c->state != STATE_IDLE) {
+       if (i2c->state == STATE_IDLE) {
+               spin_unlock(&i2c->lock);
+               return IRQ_NONE;
+       }
+
+       if (ctrl & REG_CTRL_ERROR) {
                /*
                 * The bit is set when the IGNORE_NAK bit is cleared
                 * and the device didn't respond. In this case, the
@@ -242,48 +242,21 @@ static irqreturn_t meson_i2c_irq(int irqno, void *dev_id)
                goto out;
        }
 
-       switch (i2c->state) {
-       case STATE_READ:
-               if (i2c->count > 0) {
-                       meson_i2c_get_data(i2c, i2c->msg->buf + i2c->pos,
-                                          i2c->count);
-                       i2c->pos += i2c->count;
-               }
-
-               if (i2c->pos >= i2c->msg->len) {
-                       meson_i2c_stop(i2c);
-                       break;
-               }
-
-               meson_i2c_prepare_xfer(i2c);
-               break;
-       case STATE_WRITE:
-               i2c->pos += i2c->count;
+       if (i2c->state == STATE_READ && i2c->count)
+               meson_i2c_get_data(i2c, i2c->msg->buf + i2c->pos, i2c->count);
 
-               if (i2c->pos >= i2c->msg->len) {
-                       meson_i2c_stop(i2c);
-                       break;
-               }
+       i2c->pos += i2c->count;
 
-               meson_i2c_prepare_xfer(i2c);
-               break;
-       case STATE_STOP:
+       if (i2c->pos >= i2c->msg->len) {
                i2c->state = STATE_IDLE;
                complete(&i2c->done);
-               break;
-       case STATE_IDLE:
-               break;
+               goto out;
        }
 
+       /* Restart the processing */
+       meson_i2c_prepare_xfer(i2c);
+       meson_i2c_set_mask(i2c, REG_CTRL, REG_CTRL_START, REG_CTRL_START);
 out:
-       if (i2c->state != STATE_IDLE) {
-               /* Restart the processing */
-               meson_i2c_write_tokens(i2c);
-               meson_i2c_set_mask(i2c, REG_CTRL, REG_CTRL_START, 0);
-               meson_i2c_set_mask(i2c, REG_CTRL, REG_CTRL_START,
-                                  REG_CTRL_START);
-       }
-
        spin_unlock(&i2c->lock);
 
        return IRQ_HANDLED;
@@ -323,7 +296,6 @@ static int meson_i2c_xfer_msg(struct meson_i2c *i2c, struct i2c_msg *msg,
 
        i2c->state = (msg->flags & I2C_M_RD) ? STATE_READ : STATE_WRITE;
        meson_i2c_prepare_xfer(i2c);
-       meson_i2c_write_tokens(i2c);
        reinit_completion(&i2c->done);
 
        /* Start the transfer */
@@ -359,21 +331,19 @@ static int meson_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
                          int num)
 {
        struct meson_i2c *i2c = adap->algo_data;
-       int i, ret = 0, count = 0;
+       int i, ret = 0;
 
        clk_enable(i2c->clk);
-       meson_i2c_set_clk_div(i2c);
 
        for (i = 0; i < num; i++) {
                ret = meson_i2c_xfer_msg(i2c, msgs + i, i == num - 1);
                if (ret)
                        break;
-               count++;
        }
 
        clk_disable(i2c->clk);
 
-       return ret ? ret : count;
+       return ret ?: i;
 }
 
 static u32 meson_i2c_func(struct i2c_adapter *adap)
@@ -391,15 +361,14 @@ static int meson_i2c_probe(struct platform_device *pdev)
        struct device_node *np = pdev->dev.of_node;
        struct meson_i2c *i2c;
        struct resource *mem;
-       int ret = 0;
+       struct i2c_timings timings;
+       int irq, ret = 0;
 
        i2c = devm_kzalloc(&pdev->dev, sizeof(struct meson_i2c), GFP_KERNEL);
        if (!i2c)
                return -ENOMEM;
 
-       if (of_property_read_u32(pdev->dev.of_node, "clock-frequency",
-                                &i2c->frequency))
-               i2c->frequency = DEFAULT_FREQ;
+       i2c_parse_fw_timings(&pdev->dev, &timings, true);
 
        i2c->dev = &pdev->dev;
        platform_set_drvdata(pdev, i2c);
@@ -418,14 +387,13 @@ static int meson_i2c_probe(struct platform_device *pdev)
        if (IS_ERR(i2c->regs))
                return PTR_ERR(i2c->regs);
 
-       i2c->irq = platform_get_irq(pdev, 0);
-       if (i2c->irq < 0) {
+       irq = platform_get_irq(pdev, 0);
+       if (irq < 0) {
                dev_err(&pdev->dev, "can't find IRQ\n");
-               return i2c->irq;
+               return irq;
        }
 
-       ret = devm_request_irq(&pdev->dev, i2c->irq, meson_i2c_irq,
-                              0, dev_name(&pdev->dev), i2c);
+       ret = devm_request_irq(&pdev->dev, irq, meson_i2c_irq, 0, NULL, i2c);
        if (ret < 0) {
                dev_err(&pdev->dev, "can't request IRQ\n");
                return ret;
@@ -457,6 +425,8 @@ static int meson_i2c_probe(struct platform_device *pdev)
                return ret;
        }
 
+       meson_i2c_set_clk_div(i2c, timings.bus_freq_hz);
+
        return 0;
 }
 
index a50bd6891e27b220e3ddaa93f23dc194b2dd542b..cf737ec8563b873042a519e6f1337e3f095e10dd 100644 (file)
@@ -823,13 +823,10 @@ mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data,
 
        drv_data->rstc = devm_reset_control_get_optional(dev, NULL);
        if (IS_ERR(drv_data->rstc)) {
-               if (PTR_ERR(drv_data->rstc) == -EPROBE_DEFER) {
-                       rc = -EPROBE_DEFER;
-                       goto out;
-               }
-       } else {
-               reset_control_deassert(drv_data->rstc);
+               rc = PTR_ERR(drv_data->rstc);
+               goto out;
        }
+       reset_control_deassert(drv_data->rstc);
 
        /* Its not yet defined how timeouts will be specified in device tree.
         * So hard code the value to 1 second.
@@ -951,8 +948,7 @@ mv64xxx_i2c_probe(struct platform_device *pd)
 exit_free_irq:
        free_irq(drv_data->irq, drv_data);
 exit_reset:
-       if (!IS_ERR_OR_NULL(drv_data->rstc))
-               reset_control_assert(drv_data->rstc);
+       reset_control_assert(drv_data->rstc);
 exit_clk:
        /* Not all platforms have a clk */
        if (!IS_ERR(drv_data->clk))
@@ -968,8 +964,7 @@ mv64xxx_i2c_remove(struct platform_device *dev)
 
        i2c_del_adapter(&drv_data->adapter);
        free_irq(drv_data->irq, drv_data);
-       if (!IS_ERR_OR_NULL(drv_data->rstc))
-               reset_control_assert(drv_data->rstc);
+       reset_control_assert(drv_data->rstc);
        /* Not all platforms have a clk */
        if (!IS_ERR(drv_data->clk))
                clk_disable_unprepare(drv_data->clk);
index 26f2ff22e97e55cadd20e696e6cd0bfeefeecc30..214bf2835d1f95ff176cb0ded24654b20b821944 100644 (file)
@@ -700,6 +700,8 @@ static int rcar_i2c_master_xfer(struct i2c_adapter *adap,
 
        pm_runtime_get_sync(dev);
 
+       rcar_i2c_init(priv);
+
        ret = rcar_i2c_bus_barrier(priv);
        if (ret < 0)
                goto out;
@@ -751,6 +753,7 @@ static int rcar_reg_slave(struct i2c_client *slave)
        if (slave->flags & I2C_CLIENT_TEN)
                return -EAFNOSUPPORT;
 
+       /* Keep device active for slave address detection logic */
        pm_runtime_get_sync(rcar_i2c_priv_to_dev(priv));
 
        priv->slave = slave;
@@ -854,15 +857,14 @@ static int rcar_i2c_probe(struct platform_device *pdev)
        priv->dma_direction = DMA_NONE;
        priv->dma_rx = priv->dma_tx = ERR_PTR(-EPROBE_DEFER);
 
+       /* Activate device for clock calculation */
        pm_runtime_enable(dev);
        pm_runtime_get_sync(dev);
        ret = rcar_i2c_clock_calculate(priv, &i2c_t);
        if (ret < 0)
                goto out_pm_put;
 
-       rcar_i2c_init(priv);
-
-       /* Don't suspend when multi-master to keep arbitration working */
+       /* Stay always active when multi-master to keep arbitration working */
        if (of_property_read_bool(dev->of_node, "multi-master"))
                priv->flags |= ID_P_PM_BLOCKED;
        else
index dfc98df7b1b6a72ccc96e1e1b242bcab9770002e..7aa7b9cb6203f07a705b245ef6fd4a935bf74cab 100644 (file)
@@ -18,6 +18,9 @@
 #define ACPI_SMBUS_HC_CLASS            "smbus"
 #define ACPI_SMBUS_HC_DEVICE_NAME      "cmi"
 
+/* SMBUS HID definition as supported by Microsoft Windows */
+#define ACPI_SMBUS_MS_HID              "SMB0001"
+
 ACPI_MODULE_NAME("smbus_cmi");
 
 struct smbus_methods_t {
@@ -51,6 +54,7 @@ static const struct smbus_methods_t ibm_smbus_methods = {
 static const struct acpi_device_id acpi_smbus_cmi_ids[] = {
        {"SMBUS01", (kernel_ulong_t)&smbus_methods},
        {ACPI_SMBUS_IBM_HID, (kernel_ulong_t)&ibm_smbus_methods},
+       {ACPI_SMBUS_MS_HID, (kernel_ulong_t)&smbus_methods},
        {"", 0}
 };
 MODULE_DEVICE_TABLE(acpi, acpi_smbus_cmi_ids);
index 9eed69d5e17e0993e37943af95ac09cfba95e6b6..f6cd35d0a2ac0e6c37c3e9e982a20a2ee77df2fb 100644 (file)
@@ -340,7 +340,7 @@ static struct platform_driver tegra_bpmp_i2c_driver = {
 };
 module_platform_driver(tegra_bpmp_i2c_driver);
 
-MODULE_DESCRIPTION("NVIDIA Tegra BPMP I2C bus contoller driver");
+MODULE_DESCRIPTION("NVIDIA Tegra BPMP I2C bus controller driver");
 MODULE_AUTHOR("Shardar Shariff Md <smohammed@nvidia.com>");
 MODULE_AUTHOR("Juha-Matti Tilli");
 MODULE_LICENSE("GPL v2");
index 1d4c2beacf2e7044011110593fbeafa2f839bb37..ea35a895b5682a033d377d9896b6525fddfd85fd 100644 (file)
@@ -85,17 +85,23 @@ 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;
+       if (acpi_disabled) {
+               /* DT */
+               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);
+       } else {
+               /* ACPI */
+               device_property_read_u32(dev, "sclk", &i2c->sys_freq);
        }
 
-       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;
@@ -205,6 +211,7 @@ static int thunder_i2c_probe_pci(struct pci_dev *pdev,
 
        i2c->adap = thunderx_i2c_ops;
        i2c->adap.retries = 5;
+       i2c->adap.class = I2C_CLASS_HWMON;
        i2c->adap.bus_recovery_info = &octeon_i2c_recovery_info;
        i2c->adap.dev.parent = dev;
        i2c->adap.dev.of_node = pdev->dev.of_node;
index 66b464d52c9c12623d61786041f75b8ab6b22d52..ae80228104e9f6a613669b431f3807e0281fd175 100644 (file)
@@ -432,6 +432,7 @@ MODULE_DEVICE_TABLE(of, xlp9xx_i2c_of_match);
 #ifdef CONFIG_ACPI
 static const struct acpi_device_id xlp9xx_i2c_acpi_ids[] = {
        {"BRCM9007", 0},
+       {"CAV9007",  0},
        {}
 };
 MODULE_DEVICE_TABLE(acpi, xlp9xx_i2c_acpi_ids);
index d2402bbf6729e55143a9d097aaf455b65c27b1ba..7a065c4260f30be4e4746b3662bba79b6b6a9962 100644 (file)
@@ -112,6 +112,8 @@ struct i2c_acpi_lookup {
        acpi_handle adapter_handle;
        acpi_handle device_handle;
        acpi_handle search_handle;
+       int n;
+       int index;
        u32 speed;
        u32 min_speed;
 };
@@ -130,6 +132,9 @@ static int i2c_acpi_fill_info(struct acpi_resource *ares, void *data)
        if (sb->type != ACPI_RESOURCE_SERIAL_TYPE_I2C)
                return 1;
 
+       if (lookup->index != -1 && lookup->n++ != lookup->index)
+               return 1;
+
        status = acpi_get_handle(lookup->device_handle,
                                 sb->resource_source.string_ptr,
                                 &lookup->adapter_handle);
@@ -182,6 +187,7 @@ static int i2c_acpi_get_info(struct acpi_device *adev,
 
        memset(&lookup, 0, sizeof(lookup));
        lookup.info = info;
+       lookup.index = -1;
 
        ret = i2c_acpi_do_lookup(adev, &lookup);
        if (ret)
@@ -328,6 +334,7 @@ u32 i2c_acpi_find_bus_speed(struct device *dev)
        lookup.search_handle = ACPI_HANDLE(dev);
        lookup.min_speed = UINT_MAX;
        lookup.info = &dummy;
+       lookup.index = -1;
 
        status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
                                     I2C_ACPI_MAX_SCAN_DEPTH,
@@ -414,6 +421,55 @@ static int i2c_acpi_notify(struct notifier_block *nb, unsigned long value,
 static struct notifier_block i2c_acpi_notifier = {
        .notifier_call = i2c_acpi_notify,
 };
+
+/**
+ * i2c_acpi_new_device - Create i2c-client for the Nth I2cSerialBus resource
+ * @dev:     Device owning the ACPI resources to get the client from
+ * @index:   Index of ACPI resource to get
+ * @info:    describes the I2C device; note this is modified (addr gets set)
+ * Context: can sleep
+ *
+ * By default the i2c subsys creates an i2c-client for the first I2cSerialBus
+ * resource of an acpi_device, but some acpi_devices have multiple I2cSerialBus
+ * resources, in that case this function can be used to create an i2c-client
+ * for other I2cSerialBus resources in the Current Resource Settings table.
+ *
+ * Also see i2c_new_device, which this function calls to create the i2c-client.
+ *
+ * Returns a pointer to the new i2c-client, or NULL if the adapter is not found.
+ */
+struct i2c_client *i2c_acpi_new_device(struct device *dev, int index,
+                                      struct i2c_board_info *info)
+{
+       struct i2c_acpi_lookup lookup;
+       struct i2c_adapter *adapter;
+       struct acpi_device *adev;
+       LIST_HEAD(resource_list);
+       int ret;
+
+       adev = ACPI_COMPANION(dev);
+       if (!adev)
+               return NULL;
+
+       memset(&lookup, 0, sizeof(lookup));
+       lookup.info = info;
+       lookup.device_handle = acpi_device_handle(adev);
+       lookup.index = index;
+
+       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 NULL;
+
+       adapter = i2c_acpi_find_adapter_by_handle(lookup.adapter_handle);
+       if (!adapter)
+               return NULL;
+
+       return i2c_new_device(adapter, info);
+}
+EXPORT_SYMBOL_GPL(i2c_acpi_new_device);
 #else /* CONFIG_ACPI */
 static inline void i2c_acpi_register_devices(struct i2c_adapter *adap) { }
 extern struct notifier_block i2c_acpi_notifier;
@@ -929,7 +985,9 @@ static int i2c_device_probe(struct device *dev)
        if (!client)
                return 0;
 
-       if (!client->irq) {
+       driver = to_i2c_driver(dev->driver);
+
+       if (!client->irq && !driver->disable_i2c_core_irq_mapping) {
                int irq = -ENOENT;
 
                if (client->flags & I2C_CLIENT_HOST_NOTIFY) {
@@ -951,8 +1009,6 @@ static int i2c_device_probe(struct device *dev)
                client->irq = irq;
        }
 
-       driver = to_i2c_driver(dev->driver);
-
        /*
         * An I2C ID table is not mandatory, if and only if, a suitable Device
         * Tree match table entry is supplied for the probing device.
index 2178266bca794825e948ce275d48a1b13064056c..26f7237558bad75f8a111037e725a37b519d751e 100644 (file)
@@ -395,13 +395,16 @@ int i2c_mux_add_adapter(struct i2c_mux_core *muxc,
        if (force_nr) {
                priv->adap.nr = force_nr;
                ret = i2c_add_numbered_adapter(&priv->adap);
+               dev_err(&parent->dev,
+                       "failed to add mux-adapter %u as bus %u (error=%d)\n",
+                       chan_id, force_nr, ret);
        } else {
                ret = i2c_add_adapter(&priv->adap);
+               dev_err(&parent->dev,
+                       "failed to add mux-adapter %u (error=%d)\n",
+                       chan_id, ret);
        }
        if (ret < 0) {
-               dev_err(&parent->dev,
-                       "failed to add mux-adapter (error=%d)\n",
-                       ret);
                kfree(priv);
                return ret;
        }
index 10b3d17ae3ea0c4c0fe2287be11820ec5c9fd945..1e160fc37ecc309ed69cf1bbe23f6c81a6a72ee7 100644 (file)
@@ -30,6 +30,17 @@ config I2C_MUX_GPIO
          This driver can also be built as a module.  If so, the module
          will be called i2c-mux-gpio.
 
+config I2C_MUX_LTC4306
+       tristate "LTC LTC4306/5 I2C multiplexer"
+       select GPIOLIB
+       select REGMAP_I2C
+       help
+         If you say yes here you get support for the Analog Devices
+         LTC4306 or LTC4305 I2C mux/switch devices.
+
+         This driver can also be built as a module.  If so, the module
+         will be called i2c-mux-ltc4306.
+
 config I2C_MUX_PCA9541
        tristate "NXP PCA9541 I2C Master Selector"
        help
index 9948fa45037f552d447c5a3720caf03f8920775b..ff7618cd5312392b850566004cacbb0a135f17c4 100644 (file)
@@ -6,6 +6,7 @@ obj-$(CONFIG_I2C_ARB_GPIO_CHALLENGE)    += i2c-arb-gpio-challenge.o
 obj-$(CONFIG_I2C_DEMUX_PINCTRL)                += i2c-demux-pinctrl.o
 
 obj-$(CONFIG_I2C_MUX_GPIO)     += i2c-mux-gpio.o
+obj-$(CONFIG_I2C_MUX_LTC4306)  += i2c-mux-ltc4306.o
 obj-$(CONFIG_I2C_MUX_MLXCPLD)  += i2c-mux-mlxcpld.o
 obj-$(CONFIG_I2C_MUX_PCA9541)  += i2c-mux-pca9541.o
 obj-$(CONFIG_I2C_MUX_PCA954x)  += i2c-mux-pca954x.o
index 86fc2d4c081b2eb4f265d7d69cd485d9ca9ec120..812b8cff265fd1be1694ec25ac0dc1d5a908c705 100644 (file)
@@ -202,10 +202,8 @@ static int i2c_arbitrator_probe(struct platform_device *pdev)
 
        /* Actually add the mux adapter */
        ret = i2c_mux_add_adapter(muxc, 0, 0, 0);
-       if (ret) {
-               dev_err(dev, "Failed to add adapter\n");
+       if (ret)
                i2c_put_adapter(muxc->parent);
-       }
 
        return ret;
 }
index 655684d621a41d9855223ea2e5c463ff61e27ff6..1a9973ede4436d7f583c9c602b5c12e265f680fa 100644 (file)
@@ -245,10 +245,8 @@ static int i2c_mux_gpio_probe(struct platform_device *pdev)
                unsigned int class = mux->data.classes ? mux->data.classes[i] : 0;
 
                ret = i2c_mux_add_adapter(muxc, nr, mux->data.values[i], class);
-               if (ret) {
-                       dev_err(&pdev->dev, "Failed to add adapter %d\n", i);
+               if (ret)
                        goto add_adapter_failed;
-               }
        }
 
        dev_info(&pdev->dev, "%d port mux on %s adapter\n",
diff --git a/drivers/i2c/muxes/i2c-mux-ltc4306.c b/drivers/i2c/muxes/i2c-mux-ltc4306.c
new file mode 100644 (file)
index 0000000..311b1cc
--- /dev/null
@@ -0,0 +1,322 @@
+/*
+ * Linear Technology LTC4306 and LTC4305 I2C multiplexer/switch
+ *
+ * Copyright (C) 2017 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2.
+ *
+ * Based on: i2c-mux-pca954x.c
+ *
+ * Datasheet: http://cds.linear.com/docs/en/datasheet/4306.pdf
+ */
+
+#include <linux/gpio/consumer.h>
+#include <linux/gpio/driver.h>
+#include <linux/i2c-mux.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/property.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+
+#define LTC4305_MAX_NCHANS 2
+#define LTC4306_MAX_NCHANS 4
+
+#define LTC_REG_STATUS 0x0
+#define LTC_REG_CONFIG 0x1
+#define LTC_REG_MODE   0x2
+#define LTC_REG_SWITCH 0x3
+
+#define LTC_DOWNSTREAM_ACCL_EN BIT(6)
+#define LTC_UPSTREAM_ACCL_EN   BIT(7)
+
+#define LTC_GPIO_ALL_INPUT     0xC0
+#define LTC_SWITCH_MASK                0xF0
+
+enum ltc_type {
+       ltc_4305,
+       ltc_4306,
+};
+
+struct chip_desc {
+       u8 nchans;
+       u8 num_gpios;
+};
+
+struct ltc4306 {
+       struct regmap *regmap;
+       struct gpio_chip gpiochip;
+       const struct chip_desc *chip;
+};
+
+static const struct chip_desc chips[] = {
+       [ltc_4305] = {
+               .nchans = LTC4305_MAX_NCHANS,
+       },
+       [ltc_4306] = {
+               .nchans = LTC4306_MAX_NCHANS,
+               .num_gpios = 2,
+       },
+};
+
+static bool ltc4306_is_volatile_reg(struct device *dev, unsigned int reg)
+{
+       return (reg == LTC_REG_CONFIG) ? true : false;
+}
+
+static const struct regmap_config ltc4306_regmap_config = {
+       .reg_bits = 8,
+       .val_bits = 8,
+       .max_register = LTC_REG_SWITCH,
+       .volatile_reg = ltc4306_is_volatile_reg,
+       .cache_type = REGCACHE_FLAT,
+};
+
+static int ltc4306_gpio_get(struct gpio_chip *chip, unsigned int offset)
+{
+       struct ltc4306 *data = gpiochip_get_data(chip);
+       unsigned int val;
+       int ret;
+
+       ret = regmap_read(data->regmap, LTC_REG_CONFIG, &val);
+       if (ret < 0)
+               return ret;
+
+       return !!(val & BIT(1 - offset));
+}
+
+static void ltc4306_gpio_set(struct gpio_chip *chip, unsigned int offset,
+                            int value)
+{
+       struct ltc4306 *data = gpiochip_get_data(chip);
+
+       regmap_update_bits(data->regmap, LTC_REG_CONFIG, BIT(5 - offset),
+                          value ? BIT(5 - offset) : 0);
+}
+
+static int ltc4306_gpio_get_direction(struct gpio_chip *chip,
+                                     unsigned int offset)
+{
+       struct ltc4306 *data = gpiochip_get_data(chip);
+       unsigned int val;
+       int ret;
+
+       ret = regmap_read(data->regmap, LTC_REG_MODE, &val);
+       if (ret < 0)
+               return ret;
+
+       return !!(val & BIT(7 - offset));
+}
+
+static int ltc4306_gpio_direction_input(struct gpio_chip *chip,
+                                       unsigned int offset)
+{
+       struct ltc4306 *data = gpiochip_get_data(chip);
+
+       return regmap_update_bits(data->regmap, LTC_REG_MODE,
+                                 BIT(7 - offset), BIT(7 - offset));
+}
+
+static int ltc4306_gpio_direction_output(struct gpio_chip *chip,
+                                        unsigned int offset, int value)
+{
+       struct ltc4306 *data = gpiochip_get_data(chip);
+
+       ltc4306_gpio_set(chip, offset, value);
+       return regmap_update_bits(data->regmap, LTC_REG_MODE,
+                                 BIT(7 - offset), 0);
+}
+
+static int ltc4306_gpio_set_config(struct gpio_chip *chip,
+                                  unsigned int offset, unsigned long config)
+{
+       struct ltc4306 *data = gpiochip_get_data(chip);
+       unsigned int val;
+
+       switch (pinconf_to_config_param(config)) {
+       case PIN_CONFIG_DRIVE_OPEN_DRAIN:
+               val = 0;
+               break;
+       case PIN_CONFIG_DRIVE_PUSH_PULL:
+               val = BIT(4 - offset);
+               break;
+       default:
+               return -ENOTSUPP;
+       }
+
+       return regmap_update_bits(data->regmap, LTC_REG_MODE,
+                                 BIT(4 - offset), val);
+}
+
+static int ltc4306_gpio_init(struct ltc4306 *data)
+{
+       struct device *dev = regmap_get_device(data->regmap);
+
+       if (!data->chip->num_gpios)
+               return 0;
+
+       data->gpiochip.label = dev_name(dev);
+       data->gpiochip.base = -1;
+       data->gpiochip.ngpio = data->chip->num_gpios;
+       data->gpiochip.parent = dev;
+       data->gpiochip.can_sleep = true;
+       data->gpiochip.get_direction = ltc4306_gpio_get_direction;
+       data->gpiochip.direction_input = ltc4306_gpio_direction_input;
+       data->gpiochip.direction_output = ltc4306_gpio_direction_output;
+       data->gpiochip.get = ltc4306_gpio_get;
+       data->gpiochip.set = ltc4306_gpio_set;
+       data->gpiochip.set_config = ltc4306_gpio_set_config;
+       data->gpiochip.owner = THIS_MODULE;
+
+       /* gpiolib assumes all GPIOs default input */
+       regmap_write(data->regmap, LTC_REG_MODE, LTC_GPIO_ALL_INPUT);
+
+       return devm_gpiochip_add_data(dev, &data->gpiochip, data);
+}
+
+static int ltc4306_select_mux(struct i2c_mux_core *muxc, u32 chan)
+{
+       struct ltc4306 *data = i2c_mux_priv(muxc);
+
+       return regmap_update_bits(data->regmap, LTC_REG_SWITCH,
+                                 LTC_SWITCH_MASK, BIT(7 - chan));
+}
+
+static int ltc4306_deselect_mux(struct i2c_mux_core *muxc, u32 chan)
+{
+       struct ltc4306 *data = i2c_mux_priv(muxc);
+
+       return regmap_update_bits(data->regmap, LTC_REG_SWITCH,
+                                 LTC_SWITCH_MASK, 0);
+}
+
+static const struct i2c_device_id ltc4306_id[] = {
+       { "ltc4305", ltc_4305 },
+       { "ltc4306", ltc_4306 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, ltc4306_id);
+
+static const struct of_device_id ltc4306_of_match[] = {
+       { .compatible = "lltc,ltc4305", .data = &chips[ltc_4305] },
+       { .compatible = "lltc,ltc4306", .data = &chips[ltc_4306] },
+       { }
+};
+MODULE_DEVICE_TABLE(of, ltc4306_of_match);
+
+static int ltc4306_probe(struct i2c_client *client,
+                        const struct i2c_device_id *id)
+{
+       struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent);
+       const struct chip_desc *chip;
+       struct i2c_mux_core *muxc;
+       struct ltc4306 *data;
+       struct gpio_desc *gpio;
+       bool idle_disc;
+       unsigned int val = 0;
+       int num, ret;
+
+       chip = of_device_get_match_data(&client->dev);
+
+       if (!chip)
+               chip = &chips[id->driver_data];
+
+       idle_disc = device_property_read_bool(&client->dev,
+                                             "i2c-mux-idle-disconnect");
+
+       muxc = i2c_mux_alloc(adap, &client->dev,
+                            chip->nchans, sizeof(*data),
+                            I2C_MUX_LOCKED, ltc4306_select_mux,
+                            idle_disc ? ltc4306_deselect_mux : NULL);
+       if (!muxc)
+               return -ENOMEM;
+       data = i2c_mux_priv(muxc);
+       data->chip = chip;
+
+       i2c_set_clientdata(client, muxc);
+
+       data->regmap = devm_regmap_init_i2c(client, &ltc4306_regmap_config);
+       if (IS_ERR(data->regmap)) {
+               ret = PTR_ERR(data->regmap);
+               dev_err(&client->dev, "Failed to allocate register map: %d\n",
+                       ret);
+               return ret;
+       }
+
+       /* Reset and enable the mux if an enable GPIO is specified. */
+       gpio = devm_gpiod_get_optional(&client->dev, "enable", GPIOD_OUT_LOW);
+       if (IS_ERR(gpio))
+               return PTR_ERR(gpio);
+
+       if (gpio) {
+               udelay(1);
+               gpiod_set_value(gpio, 1);
+       }
+
+       /*
+        * Write the mux register at addr to verify
+        * that the mux is in fact present. This also
+        * initializes the mux to disconnected state.
+        */
+       if (regmap_write(data->regmap, LTC_REG_SWITCH, 0) < 0) {
+               dev_warn(&client->dev, "probe failed\n");
+               return -ENODEV;
+       }
+
+       if (device_property_read_bool(&client->dev,
+                                     "ltc,downstream-accelerators-enable"))
+               val |= LTC_DOWNSTREAM_ACCL_EN;
+
+       if (device_property_read_bool(&client->dev,
+                                     "ltc,upstream-accelerators-enable"))
+               val |= LTC_UPSTREAM_ACCL_EN;
+
+       if (regmap_write(data->regmap, LTC_REG_CONFIG, val) < 0)
+               return -ENODEV;
+
+       ret = ltc4306_gpio_init(data);
+       if (ret < 0)
+               return ret;
+
+       /* Now create an adapter for each channel */
+       for (num = 0; num < chip->nchans; num++) {
+               ret = i2c_mux_add_adapter(muxc, 0, num, 0);
+               if (ret) {
+                       i2c_mux_del_adapters(muxc);
+                       return ret;
+               }
+       }
+
+       dev_info(&client->dev,
+                "registered %d multiplexed busses for I2C switch %s\n",
+                num, client->name);
+
+       return 0;
+}
+
+static int ltc4306_remove(struct i2c_client *client)
+{
+       struct i2c_mux_core *muxc = i2c_get_clientdata(client);
+
+       i2c_mux_del_adapters(muxc);
+
+       return 0;
+}
+
+static struct i2c_driver ltc4306_driver = {
+       .driver         = {
+               .name   = "ltc4306",
+               .of_match_table = of_match_ptr(ltc4306_of_match),
+       },
+       .probe          = ltc4306_probe,
+       .remove         = ltc4306_remove,
+       .id_table       = ltc4306_id,
+};
+
+module_i2c_driver(ltc4306_driver);
+
+MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>");
+MODULE_DESCRIPTION("Linear Technology LTC4306, LTC4305 I2C mux/switch driver");
+MODULE_LICENSE("GPL v2");
index 77840f7845a1ba3117f66d815696b4fdce68f2b3..9e318c9516c767b41e872d966d425699c51b0b04 100644 (file)
@@ -369,10 +369,8 @@ static int pca9541_probe(struct i2c_client *client,
        i2c_set_clientdata(client, muxc);
 
        ret = i2c_mux_add_adapter(muxc, force, 0, 0);
-       if (ret) {
-               dev_err(&client->dev, "failed to register master selector\n");
+       if (ret)
                return ret;
-       }
 
        dev_info(&client->dev, "registered master selector for I2C %s\n",
                 client->name);
index ad31d21da3165f73ecc8f7beb1feef4fc186cbe5..f1751c290af67c7dfebde81d2e48951954fe62a5 100644 (file)
@@ -84,7 +84,7 @@ struct pca954x {
 
        struct irq_domain *irq;
        unsigned int irq_mask;
-       spinlock_t lock;
+       raw_spinlock_t lock;
 };
 
 /* Provide specs for the PCA954x types we know about */
@@ -252,13 +252,13 @@ static void pca954x_irq_mask(struct irq_data *idata)
        unsigned int pos = idata->hwirq;
        unsigned long flags;
 
-       spin_lock_irqsave(&data->lock, flags);
+       raw_spin_lock_irqsave(&data->lock, flags);
 
        data->irq_mask &= ~BIT(pos);
        if (!data->irq_mask)
                disable_irq(data->client->irq);
 
-       spin_unlock_irqrestore(&data->lock, flags);
+       raw_spin_unlock_irqrestore(&data->lock, flags);
 }
 
 static void pca954x_irq_unmask(struct irq_data *idata)
@@ -267,13 +267,13 @@ static void pca954x_irq_unmask(struct irq_data *idata)
        unsigned int pos = idata->hwirq;
        unsigned long flags;
 
-       spin_lock_irqsave(&data->lock, flags);
+       raw_spin_lock_irqsave(&data->lock, flags);
 
        if (!data->irq_mask)
                enable_irq(data->client->irq);
        data->irq_mask |= BIT(pos);
 
-       spin_unlock_irqrestore(&data->lock, flags);
+       raw_spin_unlock_irqrestore(&data->lock, flags);
 }
 
 static int pca954x_irq_set_type(struct irq_data *idata, unsigned int type)
@@ -299,7 +299,7 @@ static int pca954x_irq_setup(struct i2c_mux_core *muxc)
        if (!data->chip->has_irq || client->irq <= 0)
                return 0;
 
-       spin_lock_init(&data->lock);
+       raw_spin_lock_init(&data->lock);
 
        data->irq = irq_domain_add_linear(client->dev.of_node,
                                          data->chip->nchans,
@@ -413,13 +413,8 @@ static int pca954x_probe(struct i2c_client *client,
                                   idle_disconnect_dt) << num;
 
                ret = i2c_mux_add_adapter(muxc, force, num, class);
-
-               if (ret) {
-                       dev_err(&client->dev,
-                               "failed to register multiplexed adapter"
-                               " %d as bus %d\n", num, force);
+               if (ret)
                        goto fail_del_adapters;
-               }
        }
 
        dev_info(&client->dev,
index 35bb775e1b7423f77355f670b4959219f44897eb..7c0c264b07bc5c47b8864d7ea9105d91138fef73 100644 (file)
@@ -245,10 +245,8 @@ static int i2c_mux_pinctrl_probe(struct platform_device *pdev)
                                (mux->pdata->base_bus_num + i) : 0;
 
                ret = i2c_mux_add_adapter(muxc, bus, i, 0);
-               if (ret) {
-                       dev_err(&pdev->dev, "Failed to add adapter %d\n", i);
+               if (ret)
                        goto err_del_adapter;
-               }
        }
 
        return 0;
index c6a90b4a9c626dcf4fdf65e51e2f01b5b6ac4968..406d5059072cbe41964105d752a42236e66f7c8d 100644 (file)
@@ -222,10 +222,8 @@ static int i2c_mux_reg_probe(struct platform_device *pdev)
                class = mux->data.classes ? mux->data.classes[i] : 0;
 
                ret = i2c_mux_add_adapter(muxc, nr, mux->data.values[i], class);
-               if (ret) {
-                       dev_err(&pdev->dev, "Failed to add adapter %d\n", i);
+               if (ret)
                        goto add_adapter_failed;
-               }
        }
 
        dev_dbg(&pdev->dev, "%d port mux on %s adapter\n",
index 35e9acfe63d3bff8e9b349740a6ff5bcad95cf24..dff514e147daf98417f45e4cf1b1b86786ee2e55 100644 (file)
@@ -576,17 +576,10 @@ int cx231xx_i2c_mux_create(struct cx231xx *dev)
 
 int cx231xx_i2c_mux_register(struct cx231xx *dev, int mux_no)
 {
-       int rc;
-
-       rc = i2c_mux_add_adapter(dev->muxc,
-                                0,
-                                mux_no /* chan_id */,
-                                0 /* class */);
-       if (rc)
-               dev_warn(dev->dev,
-                        "i2c mux %d register FAILED\n", mux_no);
-
-       return rc;
+       return i2c_mux_add_adapter(dev->muxc,
+                                  0,
+                                  mux_no /* chan_id */,
+                                  0 /* class */);
 }
 
 void cx231xx_i2c_mux_unregister(struct cx231xx *dev)
index 6b183521c61697aa3af56082b830247f960d06fb..3a57e3dc9bec1db9b69155f9d9603ce14c545b16 100644 (file)
@@ -149,6 +149,7 @@ enum i2c_alert_protocol {
  * @detect: Callback for device detection
  * @address_list: The I2C addresses to probe (for detect)
  * @clients: List of detected clients we created (for i2c-core use only)
+ * @disable_i2c_core_irq_mapping: Tell the i2c-core to not do irq-mapping
  *
  * The driver.owner field should be set to the module owner of this driver.
  * The driver.name field should be set to the name of this driver.
@@ -212,6 +213,8 @@ struct i2c_driver {
        int (*detect)(struct i2c_client *, struct i2c_board_info *);
        const unsigned short *address_list;
        struct list_head clients;
+
+       bool disable_i2c_core_irq_mapping;
 };
 #define to_i2c_driver(d) container_of(d, struct i2c_driver, driver)
 
@@ -824,11 +827,18 @@ static inline const struct of_device_id
 
 #if IS_ENABLED(CONFIG_ACPI)
 u32 i2c_acpi_find_bus_speed(struct device *dev);
+struct i2c_client *i2c_acpi_new_device(struct device *dev, int index,
+                                      struct i2c_board_info *info);
 #else
 static inline u32 i2c_acpi_find_bus_speed(struct device *dev)
 {
        return 0;
 }
+static inline struct i2c_client *i2c_acpi_new_device(struct device *dev,
+                                       int index, struct i2c_board_info *info)
+{
+       return NULL;
+}
 #endif /* CONFIG_ACPI */
 
 #endif /* _LINUX_I2C_H */