Merge branch 'i2c/for-4.15' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git...
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 15 Nov 2017 01:52:21 +0000 (17:52 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 15 Nov 2017 01:52:21 +0000 (17:52 -0800)
Pull i2c updates from Wolfram Sang:
 "This contains two bigger than usual tree-wide changes this time. They
  all have proper acks, caused no merge conflicts in linux-next where
  they have been for a while. They are namely:

   - to-gpiod conversion of the i2c-gpio driver and its users (touching
     arch/* and drivers/mfd/*)

   - adding a sbs-manager based on I2C core updates to SMBus alerts
     (touching drivers/power/*)

  Other notable changes:

   - i2c_boardinfo can now carry a dev_name to be used when the device
     is created. This is because some devices in ACPI world need fixed
     names to find the regulators.

   - the designware driver got a long discussed overhaul of its PM
     handling. img-scb and davinci got PM support, too.

   - at24 driver has way better OF support. And it has a new maintainer.
     Thanks Bartosz for stepping up!

  The rest is regular driver updates and fixes"

* 'i2c/for-4.15' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/wsa/linux: (55 commits)
  ARM: sa1100: simpad: Correct I2C GPIO offsets
  i2c: aspeed: Deassert reset in probe
  eeprom: at24: Add OF device ID table
  MAINTAINERS: new maintainer for AT24 driver
  i2c: nuc900: remove platform_data, too
  i2c: thunderx: Remove duplicate NULL check
  i2c: taos-evm: Remove duplicate NULL check
  i2c: Make i2c_unregister_device() NULL-aware
  i2c: xgene-slimpro: Support v2
  i2c: mpc: remove useless variable initialization
  i2c: omap: Trigger bus recovery in lockup case
  i2c: gpio: Add support for named gpios in DT
  dt-bindings: i2c: i2c-gpio: Add support for named gpios
  i2c: gpio: Local vars in probe
  i2c: gpio: Augment all boardfiles to use open drain
  i2c: gpio: Enforce open drain through gpiolib
  gpio: Make it possible for consumers to enforce open drain
  i2c: gpio: Convert to use descriptors
  power: supply: sbs-message: fix some code style issues
  power: supply: sbs-battery: remove unchecked return var
  ...

70 files changed:
Documentation/devicetree/bindings/eeprom/eeprom.txt
Documentation/devicetree/bindings/i2c/i2c-aspeed.txt
Documentation/devicetree/bindings/i2c/i2c-davinci.txt
Documentation/devicetree/bindings/i2c/i2c-gpio.txt
Documentation/devicetree/bindings/i2c/i2c-mux.txt
Documentation/devicetree/bindings/i2c/i2c-rcar.txt
Documentation/devicetree/bindings/i2c/i2c.txt
Documentation/devicetree/bindings/power/supply/sbs,sbs-manager.txt [new file with mode: 0644]
MAINTAINERS
arch/arm/mach-ep93xx/core.c
arch/arm/mach-ep93xx/edb93xx.c
arch/arm/mach-ep93xx/include/mach/platform.h
arch/arm/mach-ep93xx/simone.c
arch/arm/mach-ep93xx/snappercl15.c
arch/arm/mach-ep93xx/vision_ep9307.c
arch/arm/mach-ixp4xx/avila-setup.c
arch/arm/mach-ixp4xx/dsmg600-setup.c
arch/arm/mach-ixp4xx/fsg-setup.c
arch/arm/mach-ixp4xx/goramo_mlr.c
arch/arm/mach-ixp4xx/ixdp425-setup.c
arch/arm/mach-ixp4xx/nas100d-setup.c
arch/arm/mach-ixp4xx/nslu2-setup.c
arch/arm/mach-ks8695/board-acs5k.c
arch/arm/mach-pxa/palmz72.c
arch/arm/mach-pxa/viper.c
arch/arm/mach-sa1100/simpad.c
arch/blackfin/mach-bf533/boards/blackstamp.c
arch/blackfin/mach-bf533/boards/ezkit.c
arch/blackfin/mach-bf533/boards/stamp.c
arch/blackfin/mach-bf561/boards/ezkit.c
arch/mips/alchemy/board-gpr.c
arch/mips/ath79/mach-pb44.c
drivers/acpi/acpi_apd.c
drivers/gpio/gpiolib.c
drivers/i2c/busses/Kconfig
drivers/i2c/busses/i2c-aspeed.c
drivers/i2c/busses/i2c-cht-wc.c
drivers/i2c/busses/i2c-davinci.c
drivers/i2c/busses/i2c-designware-core.h
drivers/i2c/busses/i2c-designware-platdrv.c
drivers/i2c/busses/i2c-gpio.c
drivers/i2c/busses/i2c-img-scb.c
drivers/i2c/busses/i2c-mpc.c
drivers/i2c/busses/i2c-omap.c
drivers/i2c/busses/i2c-parport-light.c
drivers/i2c/busses/i2c-parport.c
drivers/i2c/busses/i2c-pnx.c
drivers/i2c/busses/i2c-riic.c
drivers/i2c/busses/i2c-sh_mobile.c
drivers/i2c/busses/i2c-taos-evm.c
drivers/i2c/busses/i2c-thunderx-pcidrv.c
drivers/i2c/busses/i2c-xgene-slimpro.c
drivers/i2c/busses/i2c-xlp9xx.c
drivers/i2c/i2c-core-base.c
drivers/i2c/i2c-core-smbus.c
drivers/i2c/i2c-smbus.c
drivers/i2c/muxes/i2c-mux-pca954x.c
drivers/i2c/muxes/i2c-mux-reg.c
drivers/mfd/intel-lpss.h
drivers/mfd/sm501.c
drivers/misc/eeprom/at24.c
drivers/power/supply/Kconfig
drivers/power/supply/Makefile
drivers/power/supply/sbs-battery.c
drivers/power/supply/sbs-manager.c [new file with mode: 0644]
include/linux/gpio/consumer.h
include/linux/i2c-gpio.h
include/linux/i2c-smbus.h
include/linux/i2c.h
include/linux/platform_data/i2c-nuc900.h [deleted file]

index afc0458..27f2bc1 100644 (file)
@@ -36,6 +36,8 @@ Optional properties:
 
   - read-only: this parameterless property disables writes to the eeprom
 
+  - size: total eeprom size in bytes
+
 Example:
 
 eeprom@52 {
index bd6480b..e7106bf 100644 (file)
@@ -7,7 +7,9 @@ Required Properties:
 - compatible           : should be "aspeed,ast2400-i2c-bus"
                          or "aspeed,ast2500-i2c-bus"
 - clocks               : root clock of bus, should reference the APB
-                         clock
+                         clock in the second cell
+- resets               : phandle to reset controller with the reset number in
+                         the second cell
 - interrupts           : interrupt number
 - interrupt-parent     : interrupt controller for bus, should reference a
                          aspeed,ast2400-i2c-ic or aspeed,ast2500-i2c-ic
@@ -40,7 +42,8 @@ i2c {
                #interrupt-cells = <1>;
                reg = <0x40 0x40>;
                compatible = "aspeed,ast2400-i2c-bus";
-               clocks = <&clk_apb>;
+               clocks = <&syscon ASPEED_CLK_APB>;
+               resets = <&syscon ASPEED_RESET_I2C>;
                bus-frequency = <100000>;
                interrupts = <0>;
                interrupt-parent = <&i2c_ic>;
index 5b123e0..64e6e65 100644 (file)
@@ -6,6 +6,18 @@ davinci/keystone i2c interface contains.
 Required properties:
 - compatible: "ti,davinci-i2c" or "ti,keystone-i2c";
 - reg : Offset and length of the register set for the device
+- clocks: I2C functional clock phandle.
+         For 66AK2G this property should be set per binding,
+         Documentation/devicetree/bindings/clock/ti,sci-clk.txt
+
+SoC-specific Required Properties:
+
+The following are mandatory properties for Keystone 2 66AK2G SoCs only:
+
+- power-domains:       Should contain a phandle to a PM domain provider node
+                       and an args specifier containing the I2C device id
+                       value. This property is as per the binding,
+                       Documentation/devicetree/bindings/soc/ti/sci-pm-domain.txt
 
 Recommended properties :
 - interrupts : standard interrupt property.
index 4f8ec94..38a0556 100644 (file)
@@ -2,25 +2,39 @@ Device-Tree bindings for i2c gpio driver
 
 Required properties:
        - compatible = "i2c-gpio";
-       - gpios: sda and scl gpio
-
+       - sda-gpios: gpio used for the sda signal, this should be flagged as
+         active high using open drain with (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)
+         from <dt-bindings/gpio/gpio.h> since the signal is by definition
+         open drain.
+       - scl-gpios: gpio used for the scl signal, this should be flagged as
+         active high using open drain with (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)
+         from <dt-bindings/gpio/gpio.h> since the signal is by definition
+         open drain.
 
 Optional properties:
-       - i2c-gpio,sda-open-drain: sda as open drain
-       - i2c-gpio,scl-open-drain: scl as open drain
        - i2c-gpio,scl-output-only: scl as output only
        - i2c-gpio,delay-us: delay between GPIO operations (may depend on each platform)
        - i2c-gpio,timeout-ms: timeout to get data
 
+Deprecated properties, do not use in new device tree sources:
+       - gpios: sda and scl gpio, alternative for {sda,scl}-gpios
+       - i2c-gpio,sda-open-drain: this means that something outside of our
+         control has put the GPIO line used for SDA into open drain mode, and
+         that something is not the GPIO chip. It is essentially an
+         inconsistency flag.
+       - i2c-gpio,scl-open-drain: this means that something outside of our
+         control has put the GPIO line used for SCL into open drain mode, and
+         that something is not the GPIO chip. It is essentially an
+         inconsistency flag.
+
 Example nodes:
 
+#include <dt-bindings/gpio/gpio.h>
+
 i2c@0 {
        compatible = "i2c-gpio";
-       gpios = <&pioA 23 0 /* sda */
-                &pioA 24 0 /* scl */
-               >;
-       i2c-gpio,sda-open-drain;
-       i2c-gpio,scl-open-drain;
+       sda-gpios = <&pioA 23 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>;
+       scl-gpios = <&pioA 24 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>;
        i2c-gpio,delay-us = <2>;        /* ~100 kHz */
        #address-cells = <1>;
        #size-cells = <0>;
index 212e677..b38f58a 100644 (file)
@@ -6,10 +6,10 @@ multiplexer/switch will have one child node for each child bus.
 
 Optional properties:
 - #address-cells = <1>;
-   This property is required is the i2c-mux child node does not exist.
+   This property is required if the i2c-mux child node does not exist.
 
 - #size-cells = <0>;
-   This property is required is the i2c-mux child node does not exist.
+   This property is required if the i2c-mux child node does not exist.
 
 - i2c-mux
    For i2c multiplexers/switches that have child nodes that are a mixture
index cad39ae..a777477 100644 (file)
@@ -13,6 +13,7 @@ Required properties:
        "renesas,i2c-r8a7794" if the device is a part of a R8A7794 SoC.
        "renesas,i2c-r8a7795" if the device is a part of a R8A7795 SoC.
        "renesas,i2c-r8a7796" if the device is a part of a R8A7796 SoC.
+       "renesas,i2c-r8a77970" if the device is a part of a R8A77970 SoC.
        "renesas,rcar-gen1-i2c" for a generic R-Car Gen1 compatible device.
        "renesas,rcar-gen2-i2c" for a generic R-Car Gen2 or RZ/G1 compatible
                                device.
index cee9d50..1126398 100644 (file)
@@ -59,8 +59,8 @@ wants to support one of the below features, it should adapt the bindings below.
        interrupts used by the device.
 
 - interrupt-names
-       "irq" and "wakeup" names are recognized by I2C core, other names are
-       left to individual drivers.
+       "irq", "wakeup" and "smbus_alert" names are recognized by I2C core,
+       other names are left to individual drivers.
 
 - host-notify
        device uses SMBus host notify protocol instead of interrupt line.
diff --git a/Documentation/devicetree/bindings/power/supply/sbs,sbs-manager.txt b/Documentation/devicetree/bindings/power/supply/sbs,sbs-manager.txt
new file mode 100644 (file)
index 0000000..4b21955
--- /dev/null
@@ -0,0 +1,66 @@
+Binding for sbs-manager
+
+Required properties:
+- compatible: "<vendor>,<part-number>", "sbs,sbs-charger" as fallback. The part
+  number compatible string might be used in order to take care of vendor
+  specific registers.
+- reg: integer, i2c address of the device. Should be <0xa>.
+Optional properties:
+- gpio-controller: Marks the port as GPIO controller.
+  See "gpio-specifier" in .../devicetree/bindings/gpio/gpio.txt.
+- #gpio-cells: Should be <2>. The first cell is the pin number, the second cell
+  is used to specify optional parameters:
+  See "gpio-specifier" in .../devicetree/bindings/gpio/gpio.txt.
+
+From OS view the device is basically an i2c-mux used to communicate with up to
+four smart battery devices at address 0xb. The driver actually implements this
+behaviour. So standard i2c-mux nodes can be used to register up to four slave
+batteries. Channels will be numerated starting from 1 to 4.
+
+Example:
+
+batman@a {
+    compatible = "lltc,ltc1760", "sbs,sbs-manager";
+    reg = <0x0a>;
+    #address-cells = <1>;
+    #size-cells = <0>;
+
+    gpio-controller;
+    #gpio-cells = <2>;
+
+    i2c@1 {
+        #address-cells = <1>;
+        #size-cells = <0>;
+        reg = <1>;
+
+        battery@b {
+            compatible = "ti,bq2060", "sbs,sbs-battery";
+            reg = <0x0b>;
+            sbs,battery-detect-gpios = <&batman 1 1>;
+        };
+    };
+
+    i2c@2 {
+        #address-cells = <1>;
+        #size-cells = <0>;
+        reg = <2>;
+
+        battery@b {
+            compatible = "ti,bq2060", "sbs,sbs-battery";
+            reg = <0x0b>;
+            sbs,battery-detect-gpios = <&batman 2 1>;
+        };
+    };
+
+    i2c@3 {
+        #address-cells = <1>;
+        #size-cells = <0>;
+        reg = <3>;
+
+        battery@b {
+            compatible = "ti,bq2060", "sbs,sbs-battery";
+            reg = <0x0b>;
+            sbs,battery-detect-gpios = <&batman 3 1>;
+        };
+    };
+};
index bb8eba5..a76f02f 100644 (file)
@@ -2249,7 +2249,7 @@ F:        include/linux/dmaengine.h
 F:     include/linux/async_tx.h
 
 AT24 EEPROM DRIVER
-M:     Wolfram Sang <wsa@the-dreams.de>
+M:     Bartosz Golaszewski <brgl@bgdev.pl>
 L:     linux-i2c@vger.kernel.org
 S:     Maintained
 F:     drivers/misc/eeprom/at24.c
index f53c618..e70feec 100644 (file)
@@ -31,7 +31,7 @@
 #include <linux/amba/serial.h>
 #include <linux/mtd/physmap.h>
 #include <linux/i2c.h>
-#include <linux/i2c-gpio.h>
+#include <linux/gpio/machine.h>
 #include <linux/spi/spi.h>
 #include <linux/export.h>
 #include <linux/irqchip/arm-vic.h>
@@ -320,42 +320,47 @@ void __init ep93xx_register_eth(struct ep93xx_eth_data *data, int copy_addr)
 /*************************************************************************
  * EP93xx i2c peripheral handling
  *************************************************************************/
-static struct i2c_gpio_platform_data ep93xx_i2c_data;
+
+/* All EP93xx devices use the same two GPIO pins for I2C bit-banging */
+static struct gpiod_lookup_table ep93xx_i2c_gpiod_table = {
+       .dev_id         = "i2c-gpio",
+       .table          = {
+               /* Use local offsets on gpiochip/port "G" */
+               GPIO_LOOKUP_IDX("G", 1, NULL, 0,
+                               GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
+               GPIO_LOOKUP_IDX("G", 0, NULL, 1,
+                               GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
+       },
+};
 
 static struct platform_device ep93xx_i2c_device = {
        .name           = "i2c-gpio",
        .id             = 0,
        .dev            = {
-               .platform_data  = &ep93xx_i2c_data,
+               .platform_data  = NULL,
        },
 };
 
 /**
  * ep93xx_register_i2c - Register the i2c platform device.
- * @data:      platform specific i2c-gpio configuration (__initdata)
  * @devices:   platform specific i2c bus device information (__initdata)
  * @num:       the number of devices on the i2c bus
  */
-void __init ep93xx_register_i2c(struct i2c_gpio_platform_data *data,
-                               struct i2c_board_info *devices, int num)
+void __init ep93xx_register_i2c(struct i2c_board_info *devices, int num)
 {
        /*
-        * Set the EEPROM interface pin drive type control.
-        * Defines the driver type for the EECLK and EEDAT pins as either
-        * open drain, which will require an external pull-up, or a normal
-        * CMOS driver.
+        * FIXME: this just sets the two pins as non-opendrain, as no
+        * platforms tries to do that anyway. Flag the applicable lines
+        * as open drain in the GPIO_LOOKUP above and the driver or
+        * gpiolib will handle open drain/open drain emulation as need
+        * be. Right now i2c-gpio emulates open drain which is not
+        * optimal.
         */
-       if (data->sda_is_open_drain && data->sda_pin != EP93XX_GPIO_LINE_EEDAT)
-               pr_warning("sda != EEDAT, open drain has no effect\n");
-       if (data->scl_is_open_drain && data->scl_pin != EP93XX_GPIO_LINE_EECLK)
-               pr_warning("scl != EECLK, open drain has no effect\n");
-
-       __raw_writel((data->sda_is_open_drain << 1) |
-                    (data->scl_is_open_drain << 0),
+       __raw_writel((0 << 1) | (0 << 0),
                     EP93XX_GPIO_EEDRIVE);
 
-       ep93xx_i2c_data = *data;
        i2c_register_board_info(0, devices, num);
+       gpiod_add_lookup_table(&ep93xx_i2c_gpiod_table);
        platform_device_register(&ep93xx_i2c_device);
 }
 
index 7a7f280..8e89ec8 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/i2c.h>
-#include <linux/i2c-gpio.h>
 #include <linux/spi/spi.h>
 
 #include <sound/cs4271.h>
@@ -61,14 +60,6 @@ static struct ep93xx_eth_data __initdata edb93xx_eth_data = {
 /*************************************************************************
  * EDB93xx i2c peripheral handling
  *************************************************************************/
-static struct i2c_gpio_platform_data __initdata edb93xx_i2c_gpio_data = {
-       .sda_pin                = EP93XX_GPIO_LINE_EEDAT,
-       .sda_is_open_drain      = 0,
-       .scl_pin                = EP93XX_GPIO_LINE_EECLK,
-       .scl_is_open_drain      = 0,
-       .udelay                 = 0,    /* default to 100 kHz */
-       .timeout                = 0,    /* default to 100 ms */
-};
 
 static struct i2c_board_info __initdata edb93xxa_i2c_board_info[] = {
        {
@@ -86,13 +77,11 @@ static void __init edb93xx_register_i2c(void)
 {
        if (machine_is_edb9302a() || machine_is_edb9307a() ||
            machine_is_edb9315a()) {
-               ep93xx_register_i2c(&edb93xx_i2c_gpio_data,
-                                   edb93xxa_i2c_board_info,
+               ep93xx_register_i2c(edb93xxa_i2c_board_info,
                                    ARRAY_SIZE(edb93xxa_i2c_board_info));
        } else if (machine_is_edb9302() || machine_is_edb9307()
                || machine_is_edb9312() || machine_is_edb9315()) {
-               ep93xx_register_i2c(&edb93xx_i2c_gpio_data,
-                                   edb93xx_i2c_board_info,
+               ep93xx_register_i2c(edb93xx_i2c_board_info,
                                    ARRAY_SIZE(edb93xx_i2c_board_info));
        }
 }
index 3bbe159..6c41c79 100644 (file)
@@ -8,7 +8,6 @@
 #include <linux/reboot.h>
 
 struct device;
-struct i2c_gpio_platform_data;
 struct i2c_board_info;
 struct spi_board_info;
 struct platform_device;
@@ -37,8 +36,7 @@ void ep93xx_register_flash(unsigned int width,
                           resource_size_t start, resource_size_t size);
 
 void ep93xx_register_eth(struct ep93xx_eth_data *data, int copy_addr);
-void ep93xx_register_i2c(struct i2c_gpio_platform_data *data,
-                        struct i2c_board_info *devices, int num);
+void ep93xx_register_i2c(struct i2c_board_info *devices, int num);
 void ep93xx_register_spi(struct ep93xx_spi_info *info,
                         struct spi_board_info *devices, int num);
 void ep93xx_register_fb(struct ep93xxfb_mach_info *data);
index c7a40f2..e61f3de 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/i2c.h>
-#include <linux/i2c-gpio.h>
 #include <linux/mmc/host.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/mmc_spi.h>
@@ -129,15 +128,6 @@ static struct ep93xx_spi_info simone_spi_info __initdata = {
        .use_dma = 1,
 };
 
-static struct i2c_gpio_platform_data __initdata simone_i2c_gpio_data = {
-       .sda_pin                = EP93XX_GPIO_LINE_EEDAT,
-       .sda_is_open_drain      = 0,
-       .scl_pin                = EP93XX_GPIO_LINE_EECLK,
-       .scl_is_open_drain      = 0,
-       .udelay                 = 0,
-       .timeout                = 0,
-};
-
 static struct i2c_board_info __initdata simone_i2c_board_info[] = {
        {
                I2C_BOARD_INFO("ds1337", 0x68),
@@ -161,7 +151,7 @@ static void __init simone_init_machine(void)
        ep93xx_register_flash(2, EP93XX_CS6_PHYS_BASE, SZ_8M);
        ep93xx_register_eth(&simone_eth_data, 1);
        ep93xx_register_fb(&simone_fb_info);
-       ep93xx_register_i2c(&simone_i2c_gpio_data, simone_i2c_board_info,
+       ep93xx_register_i2c(simone_i2c_board_info,
                            ARRAY_SIZE(simone_i2c_board_info));
        ep93xx_register_spi(&simone_spi_info, simone_spi_devices,
                            ARRAY_SIZE(simone_spi_devices));
index 8b29398..45940c1 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/i2c.h>
-#include <linux/i2c-gpio.h>
 #include <linux/fb.h>
 
 #include <linux/mtd/partitions.h>
@@ -127,15 +126,6 @@ static struct ep93xx_eth_data __initdata snappercl15_eth_data = {
        .phy_id                 = 1,
 };
 
-static struct i2c_gpio_platform_data __initdata snappercl15_i2c_gpio_data = {
-       .sda_pin                = EP93XX_GPIO_LINE_EEDAT,
-       .sda_is_open_drain      = 0,
-       .scl_pin                = EP93XX_GPIO_LINE_EECLK,
-       .scl_is_open_drain      = 0,
-       .udelay                 = 0,
-       .timeout                = 0,
-};
-
 static struct i2c_board_info __initdata snappercl15_i2c_data[] = {
        {
                /* Audio codec */
@@ -161,7 +151,7 @@ static void __init snappercl15_init_machine(void)
 {
        ep93xx_init_devices();
        ep93xx_register_eth(&snappercl15_eth_data, 1);
-       ep93xx_register_i2c(&snappercl15_i2c_gpio_data, snappercl15_i2c_data,
+       ep93xx_register_i2c(snappercl15_i2c_data,
                            ARRAY_SIZE(snappercl15_i2c_data));
        ep93xx_register_fb(&snappercl15_fb_info);
        snappercl15_register_audio();
index 1daf944..5a0b618 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/io.h>
 #include <linux/mtd/partitions.h>
 #include <linux/i2c.h>
-#include <linux/i2c-gpio.h>
 #include <linux/platform_data/pca953x.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/flash.h>
@@ -144,10 +143,6 @@ static struct pca953x_platform_data pca953x_77_gpio_data = {
 /*************************************************************************
  * I2C Bus
  *************************************************************************/
-static struct i2c_gpio_platform_data vision_i2c_gpio_data __initdata = {
-       .sda_pin                = EP93XX_GPIO_LINE_EEDAT,
-       .scl_pin                = EP93XX_GPIO_LINE_EECLK,
-};
 
 static struct i2c_board_info vision_i2c_info[] __initdata = {
        {
@@ -289,7 +284,7 @@ static void __init vision_init_machine(void)
 
        vision_i2c_info[1].irq = gpio_to_irq(EP93XX_GPIO_LINE_F(7));
 
-       ep93xx_register_i2c(&vision_i2c_gpio_data, vision_i2c_info,
+       ep93xx_register_i2c(vision_i2c_info,
                                ARRAY_SIZE(vision_i2c_info));
        ep93xx_register_spi(&vision_spi_master, vision_spi_board_info,
                                ARRAY_SIZE(vision_spi_board_info));
index 186df64..77def61 100644 (file)
@@ -18,7 +18,7 @@
 #include <linux/serial.h>
 #include <linux/tty.h>
 #include <linux/serial_8250.h>
-#include <linux/i2c-gpio.h>
+#include <linux/gpio/machine.h>
 #include <asm/types.h>
 #include <asm/setup.h>
 #include <asm/memory.h>
@@ -50,16 +50,21 @@ static struct platform_device avila_flash = {
        .resource       = &avila_flash_resource,
 };
 
-static struct i2c_gpio_platform_data avila_i2c_gpio_data = {
-       .sda_pin        = AVILA_SDA_PIN,
-       .scl_pin        = AVILA_SCL_PIN,
+static struct gpiod_lookup_table avila_i2c_gpiod_table = {
+       .dev_id         = "i2c-gpio",
+       .table          = {
+               GPIO_LOOKUP_IDX("IXP4XX_GPIO_CHIP", AVILA_SDA_PIN,
+                               NULL, 0, GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
+               GPIO_LOOKUP_IDX("IXP4XX_GPIO_CHIP", AVILA_SCL_PIN,
+                               NULL, 1, GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
+       },
 };
 
 static struct platform_device avila_i2c_gpio = {
        .name           = "i2c-gpio",
        .id             = 0,
        .dev     = {
-               .platform_data  = &avila_i2c_gpio_data,
+               .platform_data  = NULL,
        },
 };
 
@@ -148,6 +153,8 @@ static void __init avila_init(void)
        avila_flash_resource.end =
                IXP4XX_EXP_BUS_BASE(0) + ixp4xx_exp_bus_size - 1;
 
+       gpiod_add_lookup_table(&avila_i2c_gpiod_table);
+
        platform_add_devices(avila_devices, ARRAY_SIZE(avila_devices));
 
        avila_pata_resources[0].start = IXP4XX_EXP_BUS_BASE(1);
index 19839bb..ac97a45 100644 (file)
@@ -26,7 +26,7 @@
 #include <linux/leds.h>
 #include <linux/reboot.h>
 #include <linux/i2c.h>
-#include <linux/i2c-gpio.h>
+#include <linux/gpio/machine.h>
 
 #include <mach/hardware.h>
 
@@ -69,16 +69,21 @@ static struct platform_device dsmg600_flash = {
        .resource               = &dsmg600_flash_resource,
 };
 
-static struct i2c_gpio_platform_data dsmg600_i2c_gpio_data = {
-       .sda_pin                = DSMG600_SDA_PIN,
-       .scl_pin                = DSMG600_SCL_PIN,
+static struct gpiod_lookup_table dsmg600_i2c_gpiod_table = {
+       .dev_id         = "i2c-gpio",
+       .table          = {
+               GPIO_LOOKUP_IDX("IXP4XX_GPIO_CHIP", DSMG600_SDA_PIN,
+                               NULL, 0, GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
+               GPIO_LOOKUP_IDX("IXP4XX_GPIO_CHIP", DSMG600_SCL_PIN,
+                               NULL, 1, GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
+       },
 };
 
 static struct platform_device dsmg600_i2c_gpio = {
        .name                   = "i2c-gpio",
        .id                     = 0,
        .dev     = {
-               .platform_data  = &dsmg600_i2c_gpio_data,
+               .platform_data  = NULL,
        },
 };
 
@@ -270,6 +275,7 @@ static void __init dsmg600_init(void)
        dsmg600_flash_resource.end =
                IXP4XX_EXP_BUS_BASE(0) + ixp4xx_exp_bus_size - 1;
 
+       gpiod_add_lookup_table(&dsmg600_i2c_gpiod_table);
        i2c_register_board_info(0, dsmg600_i2c_board_info,
                                ARRAY_SIZE(dsmg600_i2c_board_info));
 
index 6e32cbc..033f79b 100644 (file)
@@ -23,7 +23,7 @@
 #include <linux/leds.h>
 #include <linux/reboot.h>
 #include <linux/i2c.h>
-#include <linux/i2c-gpio.h>
+#include <linux/gpio/machine.h>
 #include <linux/io.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -55,16 +55,21 @@ static struct platform_device fsg_flash = {
        .resource               = &fsg_flash_resource,
 };
 
-static struct i2c_gpio_platform_data fsg_i2c_gpio_data = {
-       .sda_pin                = FSG_SDA_PIN,
-       .scl_pin                = FSG_SCL_PIN,
+static struct gpiod_lookup_table fsg_i2c_gpiod_table = {
+       .dev_id         = "i2c-gpio",
+       .table          = {
+               GPIO_LOOKUP_IDX("IXP4XX_GPIO_CHIP", FSG_SDA_PIN,
+                               NULL, 0, GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
+               GPIO_LOOKUP_IDX("IXP4XX_GPIO_CHIP", FSG_SCL_PIN,
+                               NULL, 1, GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
+       },
 };
 
 static struct platform_device fsg_i2c_gpio = {
        .name                   = "i2c-gpio",
        .id                     = 0,
        .dev = {
-               .platform_data  = &fsg_i2c_gpio_data,
+               .platform_data  = NULL,
        },
 };
 
@@ -197,6 +202,7 @@ static void __init fsg_init(void)
        /* Configure CS2 for operation, 8bit and writable */
        *IXP4XX_EXP_CS2 = 0xbfff0002;
 
+       gpiod_add_lookup_table(&fsg_i2c_gpiod_table);
        i2c_register_board_info(0, fsg_i2c_board_info,
                                ARRAY_SIZE(fsg_i2c_board_info));
 
index 145ec5c..4d80508 100644 (file)
@@ -7,7 +7,6 @@
 #include <linux/delay.h>
 #include <linux/gpio.h>
 #include <linux/hdlc.h>
-#include <linux/i2c-gpio.h>
 #include <linux/io.h>
 #include <linux/irq.h>
 #include <linux/kernel.h>
 static u32 hw_bits = 0xFFFFFFFD;    /* assume all hardware present */;
 static u8 control_value;
 
+/*
+ * FIXME: this is reimplementing I2C bit-bangining. Move this
+ * over to using driver/i2c/busses/i2c-gpio.c like all other boards
+ * and register proper I2C device(s) on the bus for this. (See
+ * other IXP4xx boards for examples.)
+ */
 static void set_scl(u8 value)
 {
        gpio_set_value(GPIO_SCL, !!value);
@@ -217,20 +222,6 @@ static struct platform_device device_flash = {
        .resource       = &flash_resource,
 };
 
-
-/* I^2C interface */
-static struct i2c_gpio_platform_data i2c_data = {
-       .sda_pin        = GPIO_SDA,
-       .scl_pin        = GPIO_SCL,
-};
-
-static struct platform_device device_i2c = {
-       .name           = "i2c-gpio",
-       .id             = 0,
-       .dev            = { .platform_data = &i2c_data },
-};
-
-
 /* IXP425 2 UART ports */
 static struct resource uart_resources[] = {
        {
@@ -412,9 +403,6 @@ static void __init gmlr_init(void)
        if (hw_bits & CFG_HW_HAS_HSS1)
                device_tab[devices++] = &device_hss_tab[1]; /* max index 5 */
 
-       if (hw_bits & CFG_HW_HAS_EEPROM)
-               device_tab[devices++] = &device_i2c; /* max index 6 */
-
        gpio_request(GPIO_SCL, "SCL/clock");
        gpio_request(GPIO_SDA, "SDA/data");
        gpio_request(GPIO_STR, "strobe");
index 8f5e015..b168e2f 100644 (file)
@@ -15,7 +15,7 @@
 #include <linux/serial.h>
 #include <linux/tty.h>
 #include <linux/serial_8250.h>
-#include <linux/i2c-gpio.h>
+#include <linux/gpio/machine.h>
 #include <linux/io.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/rawnand.h>
@@ -123,16 +123,21 @@ static struct platform_device ixdp425_flash_nand = {
 };
 #endif /* CONFIG_MTD_NAND_PLATFORM */
 
-static struct i2c_gpio_platform_data ixdp425_i2c_gpio_data = {
-       .sda_pin        = IXDP425_SDA_PIN,
-       .scl_pin        = IXDP425_SCL_PIN,
+static struct gpiod_lookup_table ixdp425_i2c_gpiod_table = {
+       .dev_id         = "i2c-gpio",
+       .table          = {
+               GPIO_LOOKUP_IDX("IXP4XX_GPIO_CHIP", IXDP425_SDA_PIN,
+                               NULL, 0, GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
+               GPIO_LOOKUP_IDX("IXP4XX_GPIO_CHIP", IXDP425_SCL_PIN,
+                               NULL, 1, GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
+       },
 };
 
 static struct platform_device ixdp425_i2c_gpio = {
        .name           = "i2c-gpio",
        .id             = 0,
        .dev     = {
-               .platform_data  = &ixdp425_i2c_gpio_data,
+               .platform_data  = NULL,
        },
 };
 
@@ -246,6 +251,7 @@ static void __init ixdp425_init(void)
                ixdp425_uart_data[1].flags = 0;
        }
 
+       gpiod_add_lookup_table(&ixdp425_i2c_gpiod_table);
        platform_add_devices(ixdp425_devices, ARRAY_SIZE(ixdp425_devices));
 }
 
index b6d7312..4356020 100644 (file)
@@ -28,7 +28,7 @@
 #include <linux/leds.h>
 #include <linux/reboot.h>
 #include <linux/i2c.h>
-#include <linux/i2c-gpio.h>
+#include <linux/gpio/machine.h>
 #include <linux/io.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -101,16 +101,21 @@ static struct platform_device nas100d_leds = {
        .dev.platform_data      = &nas100d_led_data,
 };
 
-static struct i2c_gpio_platform_data nas100d_i2c_gpio_data = {
-       .sda_pin                = NAS100D_SDA_PIN,
-       .scl_pin                = NAS100D_SCL_PIN,
+static struct gpiod_lookup_table nas100d_i2c_gpiod_table = {
+       .dev_id         = "i2c-gpio",
+       .table          = {
+               GPIO_LOOKUP_IDX("IXP4XX_GPIO_CHIP", NAS100D_SDA_PIN,
+                               NULL, 0, GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
+               GPIO_LOOKUP_IDX("IXP4XX_GPIO_CHIP", NAS100D_SCL_PIN,
+                               NULL, 1, GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
+       },
 };
 
 static struct platform_device nas100d_i2c_gpio = {
        .name                   = "i2c-gpio",
        .id                     = 0,
        .dev     = {
-               .platform_data  = &nas100d_i2c_gpio_data,
+               .platform_data  = NULL,
        },
 };
 
@@ -281,6 +286,7 @@ static void __init nas100d_init(void)
        nas100d_flash_resource.end =
                IXP4XX_EXP_BUS_BASE(0) + ixp4xx_exp_bus_size - 1;
 
+       gpiod_add_lookup_table(&nas100d_i2c_gpiod_table);
        i2c_register_board_info(0, nas100d_i2c_board_info,
                                ARRAY_SIZE(nas100d_i2c_board_info));
 
index bd8dc65..91da63a 100644 (file)
@@ -25,7 +25,7 @@
 #include <linux/leds.h>
 #include <linux/reboot.h>
 #include <linux/i2c.h>
-#include <linux/i2c-gpio.h>
+#include <linux/gpio/machine.h>
 #include <linux/io.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -69,9 +69,14 @@ static struct platform_device nslu2_flash = {
        .resource               = &nslu2_flash_resource,
 };
 
-static struct i2c_gpio_platform_data nslu2_i2c_gpio_data = {
-       .sda_pin                = NSLU2_SDA_PIN,
-       .scl_pin                = NSLU2_SCL_PIN,
+static struct gpiod_lookup_table nslu2_i2c_gpiod_table = {
+       .dev_id         = "i2c-gpio",
+       .table          = {
+               GPIO_LOOKUP_IDX("IXP4XX_GPIO_CHIP", NSLU2_SDA_PIN,
+                               NULL, 0, GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
+               GPIO_LOOKUP_IDX("IXP4XX_GPIO_CHIP", NSLU2_SCL_PIN,
+                               NULL, 1, GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
+       },
 };
 
 static struct i2c_board_info __initdata nslu2_i2c_board_info [] = {
@@ -116,7 +121,7 @@ static struct platform_device nslu2_i2c_gpio = {
        .name                   = "i2c-gpio",
        .id                     = 0,
        .dev     = {
-               .platform_data  = &nslu2_i2c_gpio_data,
+               .platform_data  = NULL,
        },
 };
 
@@ -251,6 +256,7 @@ static void __init nslu2_init(void)
        nslu2_flash_resource.end =
                IXP4XX_EXP_BUS_BASE(0) + ixp4xx_exp_bus_size - 1;
 
+       gpiod_add_lookup_table(&nslu2_i2c_gpiod_table);
        i2c_register_board_info(0, nslu2_i2c_board_info,
                                ARRAY_SIZE(nslu2_i2c_board_info));
 
index e4d709c..937eb1d 100644 (file)
@@ -16,7 +16,7 @@
 #include <linux/interrupt.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
-
+#include <linux/gpio/machine.h>
 #include <linux/i2c.h>
 #include <linux/i2c-algo-bit.h>
 #include <linux/i2c-gpio.h>
 
 #include "generic.h"
 
+static struct gpiod_lookup_table acs5k_i2c_gpiod_table = {
+       .dev_id         = "i2c-gpio",
+       .table          = {
+               GPIO_LOOKUP_IDX("KS8695", 4, NULL, 0,
+                               GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
+               GPIO_LOOKUP_IDX("KS8695", 5, NULL, 1,
+                               GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
+       },
+};
+
 static struct i2c_gpio_platform_data acs5k_i2c_device_platdata = {
-       .sda_pin        = 4,
-       .scl_pin        = 5,
        .udelay         = 10,
 };
 
@@ -95,6 +103,7 @@ static struct i2c_board_info acs5k_i2c_devs[] __initdata = {
 static void acs5k_i2c_init(void)
 {
        /* The gpio interface */
+       gpiod_add_lookup_table(&acs5k_i2c_gpiod_table);
        platform_device_register(&acs5k_i2c_device);
        /* I2C devices */
        i2c_register_board_info(0, acs5k_i2c_devs,
index 2963006..5877e54 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/power_supply.h>
 #include <linux/usb/gpio_vbus.h>
 #include <linux/i2c-gpio.h>
+#include <linux/gpio/machine.h>
 
 #include <asm/mach-types.h>
 #include <asm/suspend.h>
@@ -320,9 +321,17 @@ static struct soc_camera_link palmz72_iclink = {
        .flags          = SOCAM_DATAWIDTH_8,
 };
 
+static struct gpiod_lookup_table palmz72_i2c_gpiod_table = {
+       .dev_id         = "i2c-gpio",
+       .table          = {
+               GPIO_LOOKUP_IDX("gpio-pxa", 118, NULL, 0,
+                               GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
+               GPIO_LOOKUP_IDX("gpio-pxa", 117, NULL, 1,
+                               GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
+       },
+};
+
 static struct i2c_gpio_platform_data palmz72_i2c_bus_data = {
-       .sda_pin        = 118,
-       .scl_pin        = 117,
        .udelay         = 10,
        .timeout        = 100,
 };
@@ -369,6 +378,7 @@ static void __init palmz72_camera_init(void)
 {
        palmz72_cam_gpio_init();
        pxa_set_camera_info(&palmz72_pxacamera_platform_data);
+       gpiod_add_lookup_table(&palmz72_i2c_gpiod_table);
        platform_device_register(&palmz72_i2c_bus_device);
        platform_device_register(&palmz72_camera);
 }
index 8e89d91..4185e7f 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/gpio.h>
 #include <linux/jiffies.h>
 #include <linux/i2c-gpio.h>
+#include <linux/gpio/machine.h>
 #include <linux/i2c/pxa-i2c.h>
 #include <linux/serial_8250.h>
 #include <linux/smc91x.h>
@@ -458,9 +459,17 @@ static struct platform_device smc91x_device = {
 };
 
 /* i2c */
+static struct gpiod_lookup_table viper_i2c_gpiod_table = {
+       .dev_id         = "i2c-gpio",
+       .table          = {
+               GPIO_LOOKUP_IDX("gpio-pxa", VIPER_RTC_I2C_SDA_GPIO,
+                               NULL, 0, GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
+               GPIO_LOOKUP_IDX("gpio-pxa", VIPER_RTC_I2C_SCL_GPIO,
+                               NULL, 1, GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
+       },
+};
+
 static struct i2c_gpio_platform_data i2c_bus_data = {
-       .sda_pin = VIPER_RTC_I2C_SDA_GPIO,
-       .scl_pin = VIPER_RTC_I2C_SCL_GPIO,
        .udelay  = 10,
        .timeout = HZ,
 };
@@ -779,12 +788,20 @@ static int __init viper_tpm_setup(char *str)
 
 __setup("tpm=", viper_tpm_setup);
 
+struct gpiod_lookup_table viper_tpm_i2c_gpiod_table = {
+       .dev_id = "i2c-gpio",
+       .table = {
+               GPIO_LOOKUP_IDX("gpio-pxa", VIPER_TPM_I2C_SDA_GPIO,
+                               NULL, 0, GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
+               GPIO_LOOKUP_IDX("gpio-pxa", VIPER_TPM_I2C_SCL_GPIO,
+                               NULL, 1, GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
+       },
+};
+
 static void __init viper_tpm_init(void)
 {
        struct platform_device *tpm_device;
        struct i2c_gpio_platform_data i2c_tpm_data = {
-               .sda_pin = VIPER_TPM_I2C_SDA_GPIO,
-               .scl_pin = VIPER_TPM_I2C_SCL_GPIO,
                .udelay  = 10,
                .timeout = HZ,
        };
@@ -794,6 +811,7 @@ static void __init viper_tpm_init(void)
        if (!viper_tpm)
                return;
 
+       gpiod_add_lookup_table(&viper_tpm_i2c_gpiod_table);
        tpm_device = platform_device_alloc("i2c-gpio", 2);
        if (tpm_device) {
                if (!platform_device_add_data(tpm_device,
@@ -943,6 +961,7 @@ static void __init viper_init(void)
                smc91x_device.num_resources--;
 
        pxa_set_i2c_info(NULL);
+       gpiod_add_lookup_table(&viper_i2c_gpiod_table);
        pwm_add_table(viper_pwm_lookup, ARRAY_SIZE(viper_pwm_lookup));
        platform_add_devices(viper_devs, ARRAY_SIZE(viper_devs));
 
index e8d25a7..7d4feb8 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/mtd/partitions.h>
 #include <linux/io.h>
 #include <linux/gpio/driver.h>
+#include <linux/gpio/machine.h>
 
 #include <mach/hardware.h>
 #include <asm/setup.h>
@@ -324,9 +325,17 @@ static struct platform_device simpad_gpio_leds = {
 /*
  * i2c
  */
+static struct gpiod_lookup_table simpad_i2c_gpiod_table = {
+       .dev_id = "i2c-gpio",
+       .table = {
+               GPIO_LOOKUP_IDX("gpio", 21, NULL, 0,
+                               GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
+               GPIO_LOOKUP_IDX("gpio", 25, NULL, 1,
+                               GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
+       },
+};
+
 static struct i2c_gpio_platform_data simpad_i2c_data = {
-       .sda_pin = GPIO_GPIO21,
-       .scl_pin = GPIO_GPIO25,
        .udelay = 10,
        .timeout = HZ,
 };
@@ -381,6 +390,7 @@ static int __init simpad_init(void)
                              ARRAY_SIZE(simpad_flash_resources));
        sa11x0_register_mcp(&simpad_mcp_data);
 
+       gpiod_add_lookup_table(&simpad_i2c_gpiod_table);
        ret = platform_add_devices(devices, ARRAY_SIZE(devices));
        if(ret)
                printk(KERN_WARNING "simpad: Unable to register mq200 framebuffer device");
index 0ccf0cf..fab69c7 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/irq.h>
 #include <linux/gpio.h>
 #include <linux/i2c.h>
+#include <linux/gpio/machine.h>
 #include <asm/dma.h>
 #include <asm/bfin5xx_spi.h>
 #include <asm/portmux.h>
@@ -362,11 +363,17 @@ static struct platform_device bfin_device_gpiokeys = {
 #if IS_ENABLED(CONFIG_I2C_GPIO)
 #include <linux/i2c-gpio.h>
 
+static struct gpiod_lookup_table bfin_i2c_gpiod_table = {
+       .dev_id = "i2c-gpio",
+       .table = {
+               GPIO_LOOKUP_IDX("BFIN-GPIO", GPIO_PF8, NULL, 0,
+                               GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
+               GPIO_LOOKUP_IDX("BFIN-GPIO", GPIO_PF9, NULL, 1,
+                               GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
+       },
+};
+
 static struct i2c_gpio_platform_data i2c_gpio_data = {
-       .sda_pin                = GPIO_PF8,
-       .scl_pin                = GPIO_PF9,
-       .sda_is_open_drain      = 0,
-       .scl_is_open_drain      = 0,
        .udelay                 = 40,
 }; /* This hasn't actually been used these pins
     * are (currently) free pins on the expansion connector */
@@ -462,7 +469,9 @@ static int __init blackstamp_init(void)
        int ret;
 
        printk(KERN_INFO "%s(): registering device resources\n", __func__);
-
+#if IS_ENABLED(CONFIG_I2C_GPIO)
+       gpiod_add_lookup_table(&bfin_i2c_gpiod_table);
+#endif
        i2c_register_board_info(0, bfin_i2c_board_info,
                                ARRAY_SIZE(bfin_i2c_board_info));
 
index 3625e9e..d64d270 100644 (file)
@@ -19,6 +19,7 @@
 #endif
 #include <linux/irq.h>
 #include <linux/i2c.h>
+#include <linux/gpio/machine.h>
 #include <asm/dma.h>
 #include <asm/bfin5xx_spi.h>
 #include <asm/portmux.h>
@@ -390,11 +391,17 @@ static struct platform_device bfin_device_gpiokeys = {
 #if IS_ENABLED(CONFIG_I2C_GPIO)
 #include <linux/i2c-gpio.h>
 
+static struct gpiod_lookup_table bfin_i2c_gpiod_table = {
+       .dev_id = "i2c-gpio",
+       .table = {
+               GPIO_LOOKUP_IDX("BFIN-GPIO", GPIO_PF1, NULL, 0,
+                               GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
+               GPIO_LOOKUP_IDX("BFIN-GPIO", GPIO_PF0, NULL, 1,
+                               GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
+       },
+};
+
 static struct i2c_gpio_platform_data i2c_gpio_data = {
-       .sda_pin                = GPIO_PF1,
-       .scl_pin                = GPIO_PF0,
-       .sda_is_open_drain      = 0,
-       .scl_is_open_drain      = 0,
        .udelay                 = 40,
 };
 
@@ -516,6 +523,9 @@ static struct platform_device *ezkit_devices[] __initdata = {
 static int __init ezkit_init(void)
 {
        printk(KERN_INFO "%s(): registering device resources\n", __func__);
+#if IS_ENABLED(CONFIG_I2C_GPIO)
+       gpiod_add_lookup_table(&bfin_i2c_gpiod_table);
+#endif
        platform_add_devices(ezkit_devices, ARRAY_SIZE(ezkit_devices));
        spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info));
        i2c_register_board_info(0, bfin_i2c_board_info,
index 23eada7..27cbf2f 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/gpio.h>
 #include <linux/irq.h>
 #include <linux/i2c.h>
+#include <linux/gpio/machine.h>
 #include <asm/dma.h>
 #include <asm/bfin5xx_spi.h>
 #include <asm/reboot.h>
@@ -512,11 +513,17 @@ static struct platform_device bfin_device_gpiokeys = {
 #if IS_ENABLED(CONFIG_I2C_GPIO)
 #include <linux/i2c-gpio.h>
 
+static struct gpiod_lookup_table bfin_i2c_gpiod_table = {
+       .dev_id = "i2c-gpio",
+       .table = {
+               GPIO_LOOKUP_IDX("BFIN-GPIO", GPIO_PF2, NULL, 0,
+                               GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
+               GPIO_LOOKUP_IDX("BFIN-GPIO", GPIO_PF3, NULL, 1,
+                               GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
+       },
+};
+
 static struct i2c_gpio_platform_data i2c_gpio_data = {
-       .sda_pin                = GPIO_PF2,
-       .scl_pin                = GPIO_PF3,
-       .sda_is_open_drain      = 0,
-       .scl_is_open_drain      = 0,
        .udelay                 = 10,
 };
 
@@ -848,6 +855,9 @@ static int __init stamp_init(void)
 
        printk(KERN_INFO "%s(): registering device resources\n", __func__);
 
+#if IS_ENABLED(CONFIG_I2C_GPIO)
+       gpiod_add_lookup_table(&bfin_i2c_gpiod_table);
+#endif
        i2c_register_board_info(0, bfin_i2c_board_info,
                                ARRAY_SIZE(bfin_i2c_board_info));
 
index 57d1c43..acc5363 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/interrupt.h>
 #include <linux/gpio.h>
 #include <linux/delay.h>
+#include <linux/gpio/machine.h>
 #include <asm/dma.h>
 #include <asm/bfin5xx_spi.h>
 #include <asm/portmux.h>
@@ -379,11 +380,17 @@ static struct platform_device bfin_device_gpiokeys = {
 #if IS_ENABLED(CONFIG_I2C_GPIO)
 #include <linux/i2c-gpio.h>
 
+static struct gpiod_lookup_table bfin_i2c_gpiod_table = {
+       .dev_id = "i2c-gpio",
+       .table = {
+               GPIO_LOOKUP_IDX("BFIN-GPIO", GPIO_PF1, NULL, 0,
+                               GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
+               GPIO_LOOKUP_IDX("BFIN-GPIO", GPIO_PF0, NULL, 1,
+                               GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
+       },
+};
+
 static struct i2c_gpio_platform_data i2c_gpio_data = {
-       .sda_pin                = GPIO_PF1,
-       .scl_pin                = GPIO_PF0,
-       .sda_is_open_drain      = 0,
-       .scl_is_open_drain      = 0,
        .udelay                 = 10,
 };
 
@@ -633,6 +640,9 @@ static int __init ezkit_init(void)
 
        printk(KERN_INFO "%s(): registering device resources\n", __func__);
 
+#if IS_ENABLED(CONFIG_I2C_GPIO)
+       gpiod_add_lookup_table(&bfin_i2c_gpiod_table);
+#endif
        ret = platform_add_devices(ezkit_devices, ARRAY_SIZE(ezkit_devices));
        if (ret < 0)
                return ret;
index 6fb6b3f..328d697 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/gpio.h>
 #include <linux/i2c.h>
 #include <linux/i2c-gpio.h>
+#include <linux/gpio/machine.h>
 #include <asm/bootinfo.h>
 #include <asm/idle.h>
 #include <asm/reboot.h>
@@ -218,10 +219,27 @@ static struct platform_device gpr_led_devices = {
 /*
  * I2C
  */
+static struct gpiod_lookup_table gpr_i2c_gpiod_table = {
+       .dev_id = "i2c-gpio",
+       .table = {
+               /*
+                * This should be on "GPIO2" which has base at 200 so
+                * the global numbers 209 and 210 should correspond to
+                * local offsets 9 and 10.
+                */
+               GPIO_LOOKUP_IDX("alchemy-gpio2", 9, NULL, 0,
+                               GPIO_ACTIVE_HIGH),
+               GPIO_LOOKUP_IDX("alchemy-gpio2", 10, NULL, 1,
+                               GPIO_ACTIVE_HIGH),
+       },
+};
+
 static struct i2c_gpio_platform_data gpr_i2c_data = {
-       .sda_pin                = 209,
+       /*
+        * The open drain mode is hardwired somewhere or an electrical
+        * property of the alchemy GPIO controller.
+        */
        .sda_is_open_drain      = 1,
-       .scl_pin                = 210,
        .scl_is_open_drain      = 1,
        .udelay                 = 2,            /* ~100 kHz */
        .timeout                = HZ,
@@ -295,6 +313,7 @@ arch_initcall(gpr_pci_init);
 
 static int __init gpr_dev_init(void)
 {
+       gpiod_add_lookup_table(&gpr_i2c_gpiod_table);
        i2c_register_board_info(0, gpr_i2c_info, ARRAY_SIZE(gpr_i2c_info));
 
        return platform_add_devices(gpr_devices, ARRAY_SIZE(gpr_devices));
index be78298..6b2c6f3 100644 (file)
@@ -11,7 +11,7 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/i2c.h>
-#include <linux/i2c-gpio.h>
+#include <linux/gpio/machine.h>
 #include <linux/platform_data/pcf857x.h>
 
 #include "machtypes.h"
 #define PB44_KEYS_POLL_INTERVAL                20      /* msecs */
 #define PB44_KEYS_DEBOUNCE_INTERVAL    (3 * PB44_KEYS_POLL_INTERVAL)
 
-static struct i2c_gpio_platform_data pb44_i2c_gpio_data = {
-       .sda_pin        = PB44_GPIO_I2C_SDA,
-       .scl_pin        = PB44_GPIO_I2C_SCL,
+static struct gpiod_lookup_table pb44_i2c_gpiod_table = {
+       .dev_id = "i2c-gpio",
+       .table = {
+               GPIO_LOOKUP_IDX("ath79-gpio", PB44_GPIO_I2C_SDA,
+                               NULL, 0, GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
+               GPIO_LOOKUP_IDX("ath79-gpio", PB44_GPIO_I2C_SCL,
+                               NULL, 1, GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
+       },
 };
 
 static struct platform_device pb44_i2c_gpio_device = {
        .name           = "i2c-gpio",
        .id             = 0,
        .dev = {
-               .platform_data  = &pb44_i2c_gpio_data,
+               .platform_data  = NULL,
        }
 };
 
@@ -103,6 +108,7 @@ static struct ath79_spi_platform_data pb44_spi_data = {
 
 static void __init pb44_init(void)
 {
+       gpiod_add_lookup_table(&pb44_i2c_gpiod_table);
        i2c_register_board_info(0, pb44_i2c_board_info,
                                ARRAY_SIZE(pb44_i2c_board_info));
        platform_device_register(&pb44_i2c_gpio_device);
index d5999eb..d553b00 100644 (file)
@@ -116,6 +116,10 @@ static const struct apd_device_desc hip08_i2c_desc = {
        .setup = acpi_apd_setup,
        .fixed_clk_rate = 250000000,
 };
+static const struct apd_device_desc thunderx2_i2c_desc = {
+       .setup = acpi_apd_setup,
+       .fixed_clk_rate = 125000000,
+};
 #endif
 
 #else
@@ -180,6 +184,7 @@ static const struct acpi_device_id acpi_apd_device_ids[] = {
        { "APMC0D0F", APD_ADDR(xgene_i2c_desc) },
        { "BRCM900D", APD_ADDR(vulcan_spi_desc) },
        { "CAV900D",  APD_ADDR(vulcan_spi_desc) },
+       { "CAV9007",  APD_ADDR(thunderx2_i2c_desc) },
        { "HISI02A1", APD_ADDR(hip07_i2c_desc) },
        { "HISI02A2", APD_ADDR(hip08_i2c_desc) },
 #endif
index 86dcd02..641a5eb 100644 (file)
@@ -3528,8 +3528,21 @@ int gpiod_configure_flags(struct gpio_desc *desc, const char *con_id,
 
        if (lflags & GPIO_ACTIVE_LOW)
                set_bit(FLAG_ACTIVE_LOW, &desc->flags);
+
        if (lflags & GPIO_OPEN_DRAIN)
                set_bit(FLAG_OPEN_DRAIN, &desc->flags);
+       else if (dflags & GPIOD_FLAGS_BIT_OPEN_DRAIN) {
+               /*
+                * This enforces open drain mode from the consumer side.
+                * This is necessary for some busses like I2C, but the lookup
+                * should *REALLY* have specified them as open drain in the
+                * first place, so print a little warning here.
+                */
+               set_bit(FLAG_OPEN_DRAIN, &desc->flags);
+               gpiod_warn(desc,
+                          "enforced open drain please flag it properly in DT/ACPI DSDT/board file\n");
+       }
+
        if (lflags & GPIO_OPEN_SOURCE)
                set_bit(FLAG_OPEN_SOURCE, &desc->flags);
        if (lflags & GPIO_SLEEP_MAY_LOSE_VALUE)
index 45a3f3c..009345d 100644 (file)
@@ -198,6 +198,11 @@ config I2C_CHT_WC
          SMBus controller found in the Intel Cherry Trail Whiskey Cove PMIC
          found on some Intel Cherry Trail systems.
 
+         Note this controller is hooked up to a TI bq24292i charger-IC,
+         combined with a FUSB302 Type-C port-controller as such it is advised
+         to also select CONFIG_CHARGER_BQ24190=m and CONFIG_TYPEC_FUSB302=m
+         (the fusb302 driver currently is in drivers/staging).
+
 config I2C_NFORCE2
        tristate "Nvidia nForce2, nForce3 and nForce4"
        depends on PCI
index 284f867..7d4aeb4 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
 #include <linux/platform_device.h>
+#include <linux/reset.h>
 #include <linux/slab.h>
 
 /* I2C Register */
@@ -132,6 +133,7 @@ struct aspeed_i2c_bus {
        struct i2c_adapter              adap;
        struct device                   *dev;
        void __iomem                    *base;
+       struct reset_control            *rst;
        /* Synchronizes I/O mem access to base. */
        spinlock_t                      lock;
        struct completion               cmd_complete;
@@ -847,6 +849,14 @@ static int aspeed_i2c_probe_bus(struct platform_device *pdev)
        /* We just need the clock rate, we don't actually use the clk object. */
        devm_clk_put(&pdev->dev, parent_clk);
 
+       bus->rst = devm_reset_control_get_shared(&pdev->dev, NULL);
+       if (IS_ERR(bus->rst)) {
+               dev_err(&pdev->dev,
+                       "missing or invalid reset controller device tree entry");
+               return PTR_ERR(bus->rst);
+       }
+       reset_control_deassert(bus->rst);
+
        ret = of_property_read_u32(pdev->dev.of_node,
                                   "bus-frequency", &bus->bus_frequency);
        if (ret < 0) {
@@ -917,6 +927,8 @@ static int aspeed_i2c_remove_bus(struct platform_device *pdev)
 
        spin_unlock_irqrestore(&bus->lock, flags);
 
+       reset_control_assert(bus->rst);
+
        i2c_del_adapter(&bus->adap);
 
        return 0;
index 190bbbc..0d05dad 100644 (file)
@@ -16,6 +16,7 @@
  * GNU General Public License for more details.
  */
 
+#include <linux/acpi.h>
 #include <linux/completion.h>
 #include <linux/delay.h>
 #include <linux/i2c.h>
@@ -25,6 +26,7 @@
 #include <linux/mfd/intel_soc_pmic.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
+#include <linux/power/bq24190_charger.h>
 #include <linux/slab.h>
 
 #define CHT_WC_I2C_CTRL                        0x5e24
@@ -232,13 +234,35 @@ static const struct irq_chip cht_wc_i2c_irq_chip = {
        .name                   = "cht_wc_ext_chrg_irq_chip",
 };
 
+static const char * const bq24190_suppliers[] = { "fusb302-typec-source" };
+
 static const struct property_entry bq24190_props[] = {
-       PROPERTY_ENTRY_STRING("extcon-name", "cht_wcove_pwrsrc"),
+       PROPERTY_ENTRY_STRING_ARRAY("supplied-from", bq24190_suppliers),
        PROPERTY_ENTRY_BOOL("omit-battery-class"),
        PROPERTY_ENTRY_BOOL("disable-reset"),
        { }
 };
 
+static struct regulator_consumer_supply fusb302_consumer = {
+       .supply = "vbus",
+       /* Must match fusb302 dev_name in intel_cht_int33fe.c */
+       .dev_name = "i2c-fusb302",
+};
+
+static const struct regulator_init_data bq24190_vbus_init_data = {
+       .constraints = {
+               /* The name is used in intel_cht_int33fe.c do not change. */
+               .name = "cht_wc_usb_typec_vbus",
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+       },
+       .consumer_supplies = &fusb302_consumer,
+       .num_consumer_supplies = 1,
+};
+
+static struct bq24190_platform_data bq24190_pdata = {
+       .regulator_init_data = &bq24190_vbus_init_data,
+};
+
 static int cht_wc_i2c_adap_i2c_probe(struct platform_device *pdev)
 {
        struct intel_soc_pmic *pmic = dev_get_drvdata(pdev->dev.parent);
@@ -246,7 +270,9 @@ static int cht_wc_i2c_adap_i2c_probe(struct platform_device *pdev)
        struct i2c_board_info board_info = {
                .type = "bq24190",
                .addr = 0x6b,
+               .dev_name = "bq24190",
                .properties = bq24190_props,
+               .platform_data = &bq24190_pdata,
        };
        int ret, reg, irq;
 
@@ -314,11 +340,21 @@ static int cht_wc_i2c_adap_i2c_probe(struct platform_device *pdev)
        if (ret)
                goto remove_irq_domain;
 
-       board_info.irq = adap->client_irq;
-       adap->client = i2c_new_device(&adap->adapter, &board_info);
-       if (!adap->client) {
-               ret = -ENOMEM;
-               goto del_adapter;
+       /*
+        * Normally the Whiskey Cove PMIC is paired with a TI bq24292i charger,
+        * connected to this i2c bus, and a max17047 fuel-gauge and a fusb302
+        * USB Type-C controller connected to another i2c bus. In this setup
+        * the max17047 and fusb302 devices are enumerated through an INT33FE
+        * ACPI device. If this device is present register an i2c-client for
+        * the TI bq24292i charger.
+        */
+       if (acpi_dev_present("INT33FE", NULL, -1)) {
+               board_info.irq = adap->client_irq;
+               adap->client = i2c_new_device(&adap->adapter, &board_info);
+               if (!adap->client) {
+                       ret = -ENOMEM;
+                       goto del_adapter;
+               }
        }
 
        platform_set_drvdata(pdev, adap);
@@ -335,7 +371,8 @@ static int cht_wc_i2c_adap_i2c_remove(struct platform_device *pdev)
 {
        struct cht_wc_i2c_adap *adap = platform_get_drvdata(pdev);
 
-       i2c_unregister_device(adap->client);
+       if (adap->client)
+               i2c_unregister_device(adap->client);
        i2c_del_adapter(&adap->adapter);
        irq_domain_remove(adap->irq_domain);
 
index b8c4353..2ead9b9 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/gpio.h>
 #include <linux/of_device.h>
 #include <linux/platform_data/i2c-davinci.h>
+#include <linux/pm_runtime.h>
 
 /* ----- global defines ----------------------------------------------- */
 
 /* set the SDA GPIO low */
 #define DAVINCI_I2C_DCLR_PDCLR1        BIT(1)
 
+/* timeout for pm runtime autosuspend */
+#define DAVINCI_I2C_PM_TIMEOUT 1000    /* ms */
+
 struct davinci_i2c_dev {
        struct device           *dev;
        void __iomem            *base;
@@ -500,7 +504,7 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop)
                /* This should be 0 if all bytes were transferred
                 * or dev->cmd_err denotes an error.
                 */
-               dev_err(dev->dev, "abnormal termination buf_len=%i\n",
+               dev_err(dev->dev, "abnormal termination buf_len=%zu\n",
                        dev->buf_len);
                dev->terminate = 1;
                wmb();
@@ -541,10 +545,17 @@ i2c_davinci_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
 
        dev_dbg(dev->dev, "%s: msgs: %d\n", __func__, num);
 
+       ret = pm_runtime_get_sync(dev->dev);
+       if (ret < 0) {
+               dev_err(dev->dev, "Failed to runtime_get device: %d\n", ret);
+               pm_runtime_put_noidle(dev->dev);
+               return ret;
+       }
+
        ret = i2c_davinci_wait_bus_not_busy(dev);
        if (ret < 0) {
                dev_warn(dev->dev, "timeout waiting for bus ready\n");
-               return ret;
+               goto out;
        }
 
        for (i = 0; i < num; i++) {
@@ -552,14 +563,19 @@ i2c_davinci_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
                dev_dbg(dev->dev, "%s [%d/%d] ret: %d\n", __func__, i + 1, num,
                        ret);
                if (ret < 0)
-                       return ret;
+                       goto out;
        }
 
+       ret = num;
 #ifdef CONFIG_CPU_FREQ
        complete(&dev->xfr_complete);
 #endif
 
-       return num;
+out:
+       pm_runtime_mark_last_busy(dev->dev);
+       pm_runtime_put_autosuspend(dev->dev);
+
+       return ret;
 }
 
 static u32 i2c_davinci_func(struct i2c_adapter *adap)
@@ -599,6 +615,9 @@ static irqreturn_t i2c_davinci_isr(int this_irq, void *dev_id)
        int count = 0;
        u16 w;
 
+       if (pm_runtime_suspended(dev->dev))
+               return IRQ_NONE;
+
        while ((stat = davinci_i2c_read_reg(dev, DAVINCI_I2C_IVR_REG))) {
                dev_dbg(dev->dev, "%s: stat=0x%x\n", __func__, stat);
                if (count++ == 100) {
@@ -802,13 +821,24 @@ static int davinci_i2c_probe(struct platform_device *pdev)
        dev->clk = devm_clk_get(&pdev->dev, NULL);
        if (IS_ERR(dev->clk))
                return PTR_ERR(dev->clk);
-       clk_prepare_enable(dev->clk);
 
        mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        dev->base = devm_ioremap_resource(&pdev->dev, mem);
        if (IS_ERR(dev->base)) {
-               r = PTR_ERR(dev->base);
-               goto err_unuse_clocks;
+               return PTR_ERR(dev->base);
+       }
+
+       pm_runtime_set_autosuspend_delay(dev->dev,
+                                        DAVINCI_I2C_PM_TIMEOUT);
+       pm_runtime_use_autosuspend(dev->dev);
+
+       pm_runtime_enable(dev->dev);
+
+       r = pm_runtime_get_sync(dev->dev);
+       if (r < 0) {
+               dev_err(dev->dev, "failed to runtime_get device: %d\n", r);
+               pm_runtime_put_noidle(dev->dev);
+               return r;
        }
 
        i2c_davinci_init(dev);
@@ -849,27 +879,40 @@ static int davinci_i2c_probe(struct platform_device *pdev)
        if (r)
                goto err_unuse_clocks;
 
+       pm_runtime_mark_last_busy(dev->dev);
+       pm_runtime_put_autosuspend(dev->dev);
+
        return 0;
 
 err_unuse_clocks:
-       clk_disable_unprepare(dev->clk);
-       dev->clk = NULL;
+       pm_runtime_dont_use_autosuspend(dev->dev);
+       pm_runtime_put_sync(dev->dev);
+       pm_runtime_disable(dev->dev);
+
        return r;
 }
 
 static int davinci_i2c_remove(struct platform_device *pdev)
 {
        struct davinci_i2c_dev *dev = platform_get_drvdata(pdev);
+       int ret;
 
        i2c_davinci_cpufreq_deregister(dev);
 
        i2c_del_adapter(&dev->adapter);
 
-       clk_disable_unprepare(dev->clk);
-       dev->clk = NULL;
+       ret = pm_runtime_get_sync(&pdev->dev);
+       if (ret < 0) {
+               pm_runtime_put_noidle(&pdev->dev);
+               return ret;
+       }
 
        davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, 0);
 
+       pm_runtime_dont_use_autosuspend(dev->dev);
+       pm_runtime_put_sync(dev->dev);
+       pm_runtime_disable(dev->dev);
+
        return 0;
 }
 
@@ -880,7 +923,6 @@ static int davinci_i2c_suspend(struct device *dev)
 
        /* put I2C into reset */
        davinci_i2c_reset_ctrl(i2c_dev, 0);
-       clk_disable_unprepare(i2c_dev->clk);
 
        return 0;
 }
@@ -889,7 +931,6 @@ static int davinci_i2c_resume(struct device *dev)
 {
        struct davinci_i2c_dev *i2c_dev = dev_get_drvdata(dev);
 
-       clk_prepare_enable(i2c_dev->clk);
        /* take I2C out of reset */
        davinci_i2c_reset_ctrl(i2c_dev, 1);
 
@@ -899,6 +940,8 @@ static int davinci_i2c_resume(struct device *dev)
 static const struct dev_pm_ops davinci_i2c_pm = {
        .suspend        = davinci_i2c_suspend,
        .resume         = davinci_i2c_resume,
+       SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+                                     pm_runtime_force_resume)
 };
 
 #define davinci_i2c_pm_ops (&davinci_i2c_pm)
index 9fee4c0..21bf619 100644 (file)
@@ -280,6 +280,8 @@ struct dw_i2c_dev {
        int                     (*acquire_lock)(struct dw_i2c_dev *dev);
        void                    (*release_lock)(struct dw_i2c_dev *dev);
        bool                    pm_disabled;
+       bool                    suspended;
+       bool                    skip_resume;
        void                    (*disable)(struct dw_i2c_dev *dev);
        void                    (*disable_int)(struct dw_i2c_dev *dev);
        int                     (*init)(struct dw_i2c_dev *dev);
index 0e65b97..58add69 100644 (file)
@@ -249,6 +249,14 @@ static void dw_i2c_set_fifo_size(struct dw_i2c_dev *dev, int id)
        }
 }
 
+static void dw_i2c_plat_pm_cleanup(struct dw_i2c_dev *dev)
+{
+       pm_runtime_disable(dev->dev);
+
+       if (dev->pm_disabled)
+               pm_runtime_put_noidle(dev->dev);
+}
+
 static int dw_i2c_plat_probe(struct platform_device *pdev)
 {
        struct dw_i2c_platform_data *pdata = dev_get_platdata(&pdev->dev);
@@ -257,7 +265,9 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
        u32 acpi_speed, ht = 0;
        struct resource *mem;
        int i, irq, ret;
-       const int supported_speeds[] = { 0, 100000, 400000, 1000000, 3400000 };
+       static const int supported_speeds[] = {
+               0, 100000, 400000, 1000000, 3400000
+       };
 
        irq = platform_get_irq(pdev, 0);
        if (irq < 0)
@@ -362,14 +372,17 @@ 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_disabled) {
-               pm_runtime_forbid(&pdev->dev);
-       } else {
-               pm_runtime_set_autosuspend_delay(&pdev->dev, 1000);
-               pm_runtime_use_autosuspend(&pdev->dev);
-               pm_runtime_set_active(&pdev->dev);
-               pm_runtime_enable(&pdev->dev);
-       }
+       /* The code below assumes runtime PM to be disabled. */
+       WARN_ON(pm_runtime_enabled(&pdev->dev));
+
+       pm_runtime_set_autosuspend_delay(&pdev->dev, 1000);
+       pm_runtime_use_autosuspend(&pdev->dev);
+       pm_runtime_set_active(&pdev->dev);
+
+       if (dev->pm_disabled)
+               pm_runtime_get_noresume(&pdev->dev);
+
+       pm_runtime_enable(&pdev->dev);
 
        if (dev->mode == DW_IC_SLAVE)
                ret = i2c_dw_probe_slave(dev);
@@ -382,8 +395,7 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
        return ret;
 
 exit_probe:
-       if (!dev->pm_disabled)
-               pm_runtime_disable(&pdev->dev);
+       dw_i2c_plat_pm_cleanup(dev);
 exit_reset:
        if (!IS_ERR_OR_NULL(dev->rst))
                reset_control_assert(dev->rst);
@@ -402,8 +414,8 @@ 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_disabled)
-               pm_runtime_disable(&pdev->dev);
+       dw_i2c_plat_pm_cleanup(dev);
+
        if (!IS_ERR_OR_NULL(dev->rst))
                reset_control_assert(dev->rst);
 
@@ -437,13 +449,20 @@ static void dw_i2c_plat_complete(struct device *dev)
 #endif
 
 #ifdef CONFIG_PM
-static int dw_i2c_plat_runtime_suspend(struct device *dev)
+static int dw_i2c_plat_suspend(struct device *dev)
 {
        struct dw_i2c_dev *i_dev = dev_get_drvdata(dev);
 
+       if (i_dev->suspended) {
+               i_dev->skip_resume = true;
+               return 0;
+       }
+
        i_dev->disable(i_dev);
        i2c_dw_plat_prepare_clk(i_dev, false);
 
+       i_dev->suspended = true;
+
        return 0;
 }
 
@@ -451,27 +470,27 @@ static int dw_i2c_plat_resume(struct device *dev)
 {
        struct dw_i2c_dev *i_dev = dev_get_drvdata(dev);
 
+       if (!i_dev->suspended)
+               return 0;
+
+       if (i_dev->skip_resume) {
+               i_dev->skip_resume = false;
+               return 0;
+       }
+
        i2c_dw_plat_prepare_clk(i_dev, true);
        i_dev->init(i_dev);
 
-       return 0;
-}
+       i_dev->suspended = false;
 
-#ifdef CONFIG_PM_SLEEP
-static int dw_i2c_plat_suspend(struct device *dev)
-{
-       pm_runtime_resume(dev);
-       return dw_i2c_plat_runtime_suspend(dev);
+       return 0;
 }
-#endif
 
 static const struct dev_pm_ops dw_i2c_dev_pm_ops = {
        .prepare = dw_i2c_plat_prepare,
        .complete = dw_i2c_plat_complete,
-       SET_SYSTEM_SLEEP_PM_OPS(dw_i2c_plat_suspend, dw_i2c_plat_resume)
-       SET_RUNTIME_PM_OPS(dw_i2c_plat_runtime_suspend,
-                          dw_i2c_plat_resume,
-                          NULL)
+       SET_LATE_SYSTEM_SLEEP_PM_OPS(dw_i2c_plat_suspend, dw_i2c_plat_resume)
+       SET_RUNTIME_PM_OPS(dw_i2c_plat_suspend, dw_i2c_plat_resume, NULL)
 };
 
 #define DW_I2C_DEV_PMOPS (&dw_i2c_dev_pm_ops)
index 0ef8fcc..d80ea6c 100644 (file)
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/platform_device.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
 #include <linux/of.h>
-#include <linux/of_gpio.h>
 
 struct i2c_gpio_private_data {
+       struct gpio_desc *sda;
+       struct gpio_desc *scl;
        struct i2c_adapter adap;
        struct i2c_algo_bit_data bit_data;
        struct i2c_gpio_platform_data pdata;
 };
 
-/* Toggle SDA by changing the direction of the pin */
-static void i2c_gpio_setsda_dir(void *data, int state)
-{
-       struct i2c_gpio_platform_data *pdata = data;
-
-       if (state)
-               gpio_direction_input(pdata->sda_pin);
-       else
-               gpio_direction_output(pdata->sda_pin, 0);
-}
-
 /*
  * Toggle SDA by changing the output value of the pin. This is only
  * valid for pins configured as open drain (i.e. setting the value
@@ -42,20 +32,9 @@ static void i2c_gpio_setsda_dir(void *data, int state)
  */
 static void i2c_gpio_setsda_val(void *data, int state)
 {
-       struct i2c_gpio_platform_data *pdata = data;
-
-       gpio_set_value(pdata->sda_pin, state);
-}
-
-/* Toggle SCL by changing the direction of the pin. */
-static void i2c_gpio_setscl_dir(void *data, int state)
-{
-       struct i2c_gpio_platform_data *pdata = data;
+       struct i2c_gpio_private_data *priv = data;
 
-       if (state)
-               gpio_direction_input(pdata->scl_pin);
-       else
-               gpio_direction_output(pdata->scl_pin, 0);
+       gpiod_set_value(priv->sda, state);
 }
 
 /*
@@ -66,44 +45,23 @@ static void i2c_gpio_setscl_dir(void *data, int state)
  */
 static void i2c_gpio_setscl_val(void *data, int state)
 {
-       struct i2c_gpio_platform_data *pdata = data;
+       struct i2c_gpio_private_data *priv = data;
 
-       gpio_set_value(pdata->scl_pin, state);
+       gpiod_set_value(priv->scl, state);
 }
 
 static int i2c_gpio_getsda(void *data)
 {
-       struct i2c_gpio_platform_data *pdata = data;
+       struct i2c_gpio_private_data *priv = data;
 
-       return gpio_get_value(pdata->sda_pin);
+       return gpiod_get_value(priv->sda);
 }
 
 static int i2c_gpio_getscl(void *data)
 {
-       struct i2c_gpio_platform_data *pdata = data;
-
-       return gpio_get_value(pdata->scl_pin);
-}
-
-static int of_i2c_gpio_get_pins(struct device_node *np,
-                               unsigned int *sda_pin, unsigned int *scl_pin)
-{
-       if (of_gpio_count(np) < 2)
-               return -ENODEV;
-
-       *sda_pin = of_get_gpio(np, 0);
-       *scl_pin = of_get_gpio(np, 1);
-
-       if (*sda_pin == -EPROBE_DEFER || *scl_pin == -EPROBE_DEFER)
-               return -EPROBE_DEFER;
-
-       if (!gpio_is_valid(*sda_pin) || !gpio_is_valid(*scl_pin)) {
-               pr_err("%pOF: invalid GPIO pins, sda=%d/scl=%d\n",
-                      np, *sda_pin, *scl_pin);
-               return -ENODEV;
-       }
+       struct i2c_gpio_private_data *priv = data;
 
-       return 0;
+       return gpiod_get_value(priv->scl);
 }
 
 static void of_i2c_gpio_get_props(struct device_node *np,
@@ -124,72 +82,105 @@ static void of_i2c_gpio_get_props(struct device_node *np,
                of_property_read_bool(np, "i2c-gpio,scl-output-only");
 }
 
+static struct gpio_desc *i2c_gpio_get_desc(struct device *dev,
+                                          const char *con_id,
+                                          unsigned int index,
+                                          enum gpiod_flags gflags)
+{
+       struct gpio_desc *retdesc;
+       int ret;
+
+       retdesc = devm_gpiod_get(dev, con_id, gflags);
+       if (!IS_ERR(retdesc)) {
+               dev_dbg(dev, "got GPIO from name %s\n", con_id);
+               return retdesc;
+       }
+
+       retdesc = devm_gpiod_get_index(dev, NULL, index, gflags);
+       if (!IS_ERR(retdesc)) {
+               dev_dbg(dev, "got GPIO from index %u\n", index);
+               return retdesc;
+       }
+
+       ret = PTR_ERR(retdesc);
+
+       /* FIXME: hack in the old code, is this really necessary? */
+       if (ret == -EINVAL)
+               retdesc = ERR_PTR(-EPROBE_DEFER);
+
+       /* This happens if the GPIO driver is not yet probed, let's defer */
+       if (ret == -ENOENT)
+               retdesc = ERR_PTR(-EPROBE_DEFER);
+
+       if (ret != -EPROBE_DEFER)
+               dev_err(dev, "error trying to get descriptor: %d\n", ret);
+
+       return retdesc;
+}
+
 static int i2c_gpio_probe(struct platform_device *pdev)
 {
        struct i2c_gpio_private_data *priv;
        struct i2c_gpio_platform_data *pdata;
        struct i2c_algo_bit_data *bit_data;
        struct i2c_adapter *adap;
-       unsigned int sda_pin, scl_pin;
+       struct device *dev = &pdev->dev;
+       struct device_node *np = dev->of_node;
+       enum gpiod_flags gflags;
        int ret;
 
-       /* First get the GPIO pins; if it fails, we'll defer the probe. */
-       if (pdev->dev.of_node) {
-               ret = of_i2c_gpio_get_pins(pdev->dev.of_node,
-                                          &sda_pin, &scl_pin);
-               if (ret)
-                       return ret;
-       } else {
-               if (!dev_get_platdata(&pdev->dev))
-                       return -ENXIO;
-               pdata = dev_get_platdata(&pdev->dev);
-               sda_pin = pdata->sda_pin;
-               scl_pin = pdata->scl_pin;
-       }
-
-       ret = devm_gpio_request(&pdev->dev, sda_pin, "sda");
-       if (ret) {
-               if (ret == -EINVAL)
-                       ret = -EPROBE_DEFER;    /* Try again later */
-               return ret;
-       }
-       ret = devm_gpio_request(&pdev->dev, scl_pin, "scl");
-       if (ret) {
-               if (ret == -EINVAL)
-                       ret = -EPROBE_DEFER;    /* Try again later */
-               return ret;
-       }
-
-       priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+       priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
        if (!priv)
                return -ENOMEM;
+
        adap = &priv->adap;
        bit_data = &priv->bit_data;
        pdata = &priv->pdata;
 
-       if (pdev->dev.of_node) {
-               pdata->sda_pin = sda_pin;
-               pdata->scl_pin = scl_pin;
-               of_i2c_gpio_get_props(pdev->dev.of_node, pdata);
+       if (np) {
+               of_i2c_gpio_get_props(np, pdata);
        } else {
-               memcpy(pdata, dev_get_platdata(&pdev->dev), sizeof(*pdata));
+               /*
+                * If all platform data settings are zero it is OK
+                * to not provide any platform data from the board.
+                */
+               if (dev_get_platdata(dev))
+                       memcpy(pdata, dev_get_platdata(dev), sizeof(*pdata));
        }
 
-       if (pdata->sda_is_open_drain) {
-               gpio_direction_output(pdata->sda_pin, 1);
-               bit_data->setsda = i2c_gpio_setsda_val;
-       } else {
-               gpio_direction_input(pdata->sda_pin);
-               bit_data->setsda = i2c_gpio_setsda_dir;
-       }
+       /*
+        * First get the GPIO pins; if it fails, we'll defer the probe.
+        * If the SDA line is marked from platform data or device tree as
+        * "open drain" it means something outside of our control is making
+        * this line being handled as open drain, and we should just handle
+        * it as any other output. Else we enforce open drain as this is
+        * required for an I2C bus.
+        */
+       if (pdata->sda_is_open_drain)
+               gflags = GPIOD_OUT_HIGH;
+       else
+               gflags = GPIOD_OUT_HIGH_OPEN_DRAIN;
+       priv->sda = i2c_gpio_get_desc(dev, "sda", 0, gflags);
+       if (IS_ERR(priv->sda))
+               return PTR_ERR(priv->sda);
+
+       /*
+        * If the SCL line is marked from platform data or device tree as
+        * "open drain" it means something outside of our control is making
+        * this line being handled as open drain, and we should just handle
+        * it as any other output. Else we enforce open drain as this is
+        * required for an I2C bus.
+        */
+       if (pdata->scl_is_open_drain)
+               gflags = GPIOD_OUT_LOW;
+       else
+               gflags = GPIOD_OUT_LOW_OPEN_DRAIN;
+       priv->scl = i2c_gpio_get_desc(dev, "scl", 1, gflags);
+       if (IS_ERR(priv->scl))
+               return PTR_ERR(priv->scl);
 
-       if (pdata->scl_is_open_drain || pdata->scl_is_output_only) {
-               gpio_direction_output(pdata->scl_pin, 1);
-               bit_data->setscl = i2c_gpio_setscl_val;
-       } else {
-               gpio_direction_input(pdata->scl_pin);
-               bit_data->setscl = i2c_gpio_setscl_dir;
-       }
+       bit_data->setsda = i2c_gpio_setsda_val;
+       bit_data->setscl = i2c_gpio_setscl_val;
 
        if (!pdata->scl_is_output_only)
                bit_data->getscl = i2c_gpio_getscl;
@@ -207,18 +198,18 @@ static int i2c_gpio_probe(struct platform_device *pdev)
        else
                bit_data->timeout = HZ / 10;            /* 100 ms */
 
-       bit_data->data = pdata;
+       bit_data->data = priv;
 
        adap->owner = THIS_MODULE;
-       if (pdev->dev.of_node)
-               strlcpy(adap->name, dev_name(&pdev->dev), sizeof(adap->name));
+       if (np)
+               strlcpy(adap->name, dev_name(dev), sizeof(adap->name));
        else
                snprintf(adap->name, sizeof(adap->name), "i2c-gpio%d", pdev->id);
 
        adap->algo_data = bit_data;
        adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
-       adap->dev.parent = &pdev->dev;
-       adap->dev.of_node = pdev->dev.of_node;
+       adap->dev.parent = dev;
+       adap->dev.of_node = np;
 
        adap->nr = pdev->id;
        ret = i2c_bit_add_numbered_bus(adap);
@@ -227,8 +218,13 @@ static int i2c_gpio_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, priv);
 
-       dev_info(&pdev->dev, "using pins %u (SDA) and %u (SCL%s)\n",
-                pdata->sda_pin, pdata->scl_pin,
+       /*
+        * FIXME: using global GPIO numbers is not helpful. If/when we
+        * get accessors to get the actual name of the GPIO line,
+        * from the descriptor, then provide that instead.
+        */
+       dev_info(dev, "using lines %u (SDA) and %u (SCL%s)\n",
+                desc_to_gpio(priv->sda), desc_to_gpio(priv->scl),
                 pdata->scl_is_output_only
                 ? ", no clock stretching" : "");
 
index eb1d91b..f038858 100644 (file)
@@ -82,6 +82,7 @@
 #include <linux/module.h>
 #include <linux/of_platform.h>
 #include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
 #include <linux/slab.h>
 #include <linux/timer.h>
 
 #define ISR_COMPLETE(err)      (ISR_COMPLETE_M | (ISR_STATUS_M & (err)))
 #define ISR_FATAL(err)         (ISR_COMPLETE(err) | ISR_FATAL_M)
 
+#define IMG_I2C_PM_TIMEOUT     1000 /* ms */
+
 enum img_i2c_mode {
        MODE_INACTIVE,
        MODE_RAW,
@@ -408,6 +411,9 @@ struct img_i2c {
        unsigned int raw_timeout;
 };
 
+static int img_i2c_runtime_suspend(struct device *dev);
+static int img_i2c_runtime_resume(struct device *dev);
+
 static void img_i2c_writel(struct img_i2c *i2c, u32 offset, u32 value)
 {
        writel(value, i2c->base + offset);
@@ -826,9 +832,9 @@ next_atomic_cmd:
  * Timer function to check if something has gone wrong in automatic mode (so we
  * don't have to handle so many interrupts just to catch an exception).
  */
-static void img_i2c_check_timer(unsigned long arg)
+static void img_i2c_check_timer(struct timer_list *t)
 {
-       struct img_i2c *i2c = (struct img_i2c *)arg;
+       struct img_i2c *i2c = from_timer(i2c, t, check_timer);
        unsigned long flags;
        unsigned int line_status;
 
@@ -1054,8 +1060,8 @@ static int img_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
                        atomic = true;
        }
 
-       ret = clk_prepare_enable(i2c->scb_clk);
-       if (ret)
+       ret = pm_runtime_get_sync(adap->dev.parent);
+       if (ret < 0)
                return ret;
 
        for (i = 0; i < num; i++) {
@@ -1131,7 +1137,8 @@ static int img_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
                        break;
        }
 
-       clk_disable_unprepare(i2c->scb_clk);
+       pm_runtime_mark_last_busy(adap->dev.parent);
+       pm_runtime_put_autosuspend(adap->dev.parent);
 
        return i2c->msg_status ? i2c->msg_status : num;
 }
@@ -1149,12 +1156,13 @@ static const struct i2c_algorithm img_i2c_algo = {
 static int img_i2c_init(struct img_i2c *i2c)
 {
        unsigned int clk_khz, bitrate_khz, clk_period, tckh, tckl, tsdh;
-       unsigned int i, ret, data, prescale, inc, int_bitrate, filt;
+       unsigned int i, data, prescale, inc, int_bitrate, filt;
        struct img_i2c_timings timing;
        u32 rev;
+       int ret;
 
-       ret = clk_prepare_enable(i2c->scb_clk);
-       if (ret)
+       ret = pm_runtime_get_sync(i2c->adap.dev.parent);
+       if (ret < 0)
                return ret;
 
        rev = img_i2c_readl(i2c, SCB_CORE_REV_REG);
@@ -1163,7 +1171,8 @@ static int img_i2c_init(struct img_i2c *i2c)
                         "Unknown hardware revision (%d.%d.%d.%d)\n",
                         (rev >> 24) & 0xff, (rev >> 16) & 0xff,
                         (rev >> 8) & 0xff, rev & 0xff);
-               clk_disable_unprepare(i2c->scb_clk);
+               pm_runtime_mark_last_busy(i2c->adap.dev.parent);
+               pm_runtime_put_autosuspend(i2c->adap.dev.parent);
                return -EINVAL;
        }
 
@@ -1314,7 +1323,8 @@ static int img_i2c_init(struct img_i2c *i2c)
        /* Perform a synchronous sequence to reset the bus */
        ret = img_i2c_reset_bus(i2c);
 
-       clk_disable_unprepare(i2c->scb_clk);
+       pm_runtime_mark_last_busy(i2c->adap.dev.parent);
+       pm_runtime_put_autosuspend(i2c->adap.dev.parent);
 
        return ret;
 }
@@ -1362,8 +1372,7 @@ static int img_i2c_probe(struct platform_device *pdev)
        }
 
        /* Set up the exception check timer */
-       setup_timer(&i2c->check_timer, img_i2c_check_timer,
-                   (unsigned long)i2c);
+       timer_setup(&i2c->check_timer, img_i2c_check_timer, 0);
 
        i2c->bitrate = timings[0].max_bitrate;
        if (!of_property_read_u32(node, "clock-frequency", &val))
@@ -1384,22 +1393,30 @@ static int img_i2c_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, i2c);
 
-       ret = clk_prepare_enable(i2c->sys_clk);
-       if (ret)
-               return ret;
+       pm_runtime_set_autosuspend_delay(&pdev->dev, IMG_I2C_PM_TIMEOUT);
+       pm_runtime_use_autosuspend(&pdev->dev);
+       pm_runtime_enable(&pdev->dev);
+       if (!pm_runtime_enabled(&pdev->dev)) {
+               ret = img_i2c_runtime_resume(&pdev->dev);
+               if (ret)
+                       return ret;
+       }
 
        ret = img_i2c_init(i2c);
        if (ret)
-               goto disable_clk;
+               goto rpm_disable;
 
        ret = i2c_add_numbered_adapter(&i2c->adap);
        if (ret < 0)
-               goto disable_clk;
+               goto rpm_disable;
 
        return 0;
 
-disable_clk:
-       clk_disable_unprepare(i2c->sys_clk);
+rpm_disable:
+       if (!pm_runtime_enabled(&pdev->dev))
+               img_i2c_runtime_suspend(&pdev->dev);
+       pm_runtime_disable(&pdev->dev);
+       pm_runtime_dont_use_autosuspend(&pdev->dev);
        return ret;
 }
 
@@ -1408,19 +1425,55 @@ static int img_i2c_remove(struct platform_device *dev)
        struct img_i2c *i2c = platform_get_drvdata(dev);
 
        i2c_del_adapter(&i2c->adap);
+       pm_runtime_disable(&dev->dev);
+       if (!pm_runtime_status_suspended(&dev->dev))
+               img_i2c_runtime_suspend(&dev->dev);
+
+       return 0;
+}
+
+static int img_i2c_runtime_suspend(struct device *dev)
+{
+       struct img_i2c *i2c = dev_get_drvdata(dev);
+
+       clk_disable_unprepare(i2c->scb_clk);
        clk_disable_unprepare(i2c->sys_clk);
 
        return 0;
 }
 
+static int img_i2c_runtime_resume(struct device *dev)
+{
+       struct img_i2c *i2c = dev_get_drvdata(dev);
+       int ret;
+
+       ret = clk_prepare_enable(i2c->sys_clk);
+       if (ret) {
+               dev_err(dev, "Unable to enable sys clock\n");
+               return ret;
+       }
+
+       ret = clk_prepare_enable(i2c->scb_clk);
+       if (ret) {
+               dev_err(dev, "Unable to enable scb clock\n");
+               clk_disable_unprepare(i2c->sys_clk);
+               return ret;
+       }
+
+       return 0;
+}
+
 #ifdef CONFIG_PM_SLEEP
 static int img_i2c_suspend(struct device *dev)
 {
        struct img_i2c *i2c = dev_get_drvdata(dev);
+       int ret;
 
-       img_i2c_switch_mode(i2c, MODE_SUSPEND);
+       ret = pm_runtime_force_suspend(dev);
+       if (ret)
+               return ret;
 
-       clk_disable_unprepare(i2c->sys_clk);
+       img_i2c_switch_mode(i2c, MODE_SUSPEND);
 
        return 0;
 }
@@ -1430,7 +1483,7 @@ static int img_i2c_resume(struct device *dev)
        struct img_i2c *i2c = dev_get_drvdata(dev);
        int ret;
 
-       ret = clk_prepare_enable(i2c->sys_clk);
+       ret = pm_runtime_force_resume(dev);
        if (ret)
                return ret;
 
@@ -1440,7 +1493,12 @@ static int img_i2c_resume(struct device *dev)
 }
 #endif /* CONFIG_PM_SLEEP */
 
-static SIMPLE_DEV_PM_OPS(img_i2c_pm, img_i2c_suspend, img_i2c_resume);
+static const struct dev_pm_ops img_i2c_pm = {
+       SET_RUNTIME_PM_OPS(img_i2c_runtime_suspend,
+                          img_i2c_runtime_resume,
+                          NULL)
+       SET_SYSTEM_SLEEP_PM_OPS(img_i2c_suspend, img_i2c_resume)
+};
 
 static const struct of_device_id img_scb_i2c_match[] = {
        { .compatible = "img,scb-i2c" },
index 96caf37..950a9d7 100644 (file)
@@ -322,7 +322,7 @@ static const struct mpc_i2c_divider mpc_i2c_dividers_8xxx[] = {
 
 static u32 mpc_i2c_get_sec_cfg_8xxx(void)
 {
-       struct device_node *node = NULL;
+       struct device_node *node;
        u32 __iomem *reg;
        u32 val = 0;
 
@@ -700,7 +700,7 @@ static int fsl_i2c_probe(struct platform_device *op)
                }
        }
 
-       if (of_get_property(op->dev.of_node, "fsl,preserve-clocking", NULL)) {
+       if (of_property_read_bool(op->dev.of_node, "fsl,preserve-clocking")) {
                clock = MPC_I2C_CLOCK_PRESERVE;
        } else {
                prop = of_get_property(op->dev.of_node, "clock-frequency",
index 23c2ea2..b9172f0 100644 (file)
@@ -486,6 +486,22 @@ static int omap_i2c_init(struct omap_i2c_dev *omap)
        return 0;
 }
 
+/*
+ * Try bus recovery, but only if SDA is actually low.
+ */
+static int omap_i2c_recover_bus(struct omap_i2c_dev *omap)
+{
+       u16 systest;
+
+       systest = omap_i2c_read_reg(omap, OMAP_I2C_SYSTEST_REG);
+       if ((systest & OMAP_I2C_SYSTEST_SCL_I_FUNC) &&
+           (systest & OMAP_I2C_SYSTEST_SDA_I_FUNC))
+               return 0; /* bus seems to already be fine */
+       if (!(systest & OMAP_I2C_SYSTEST_SCL_I_FUNC))
+               return -EBUSY; /* recovery would not fix SCL */
+       return i2c_recover_bus(&omap->adapter);
+}
+
 /*
  * Waiting on Bus Busy
  */
@@ -496,7 +512,7 @@ static int omap_i2c_wait_for_bb(struct omap_i2c_dev *omap)
        timeout = jiffies + OMAP_I2C_TIMEOUT;
        while (omap_i2c_read_reg(omap, OMAP_I2C_STAT_REG) & OMAP_I2C_STAT_BB) {
                if (time_after(jiffies, timeout))
-                       return i2c_recover_bus(&omap->adapter);
+                       return omap_i2c_recover_bus(omap);
                msleep(1);
        }
 
@@ -577,8 +593,13 @@ static int omap_i2c_wait_for_bb_valid(struct omap_i2c_dev *omap)
                }
 
                if (time_after(jiffies, timeout)) {
+                       /*
+                        * SDA or SCL were low for the entire timeout without
+                        * any activity detected. Most likely, a slave is
+                        * locking up the bus with no master driving the clock.
+                        */
                        dev_warn(omap->dev, "timeout waiting for bus ready\n");
-                       return -ETIMEDOUT;
+                       return omap_i2c_recover_bus(omap);
                }
 
                msleep(1);
index faa8fb8..fa41ff7 100644 (file)
@@ -123,7 +123,6 @@ static struct i2c_adapter parport_adapter = {
 
 /* SMBus alert support */
 static struct i2c_smbus_alert_setup alert_data = {
-       .alert_edge_triggered   = 1,
 };
 static struct i2c_client *ara;
 static struct lineop parport_ctrl_irq = {
index a8e54df..319209a 100644 (file)
@@ -237,7 +237,6 @@ static void i2c_parport_attach(struct parport *port)
 
        /* Setup SMBus alert if supported */
        if (adapter_parm[type].smbus_alert) {
-               adapter->alert_data.alert_edge_triggered = 1;
                adapter->ara = i2c_setup_smbus_alert(&adapter->adapter,
                                                     &adapter->alert_data);
                if (adapter->ara)
index 42d6b3a..a542041 100644 (file)
@@ -112,7 +112,6 @@ static inline void i2c_pnx_arm_timer(struct i2c_pnx_algo_data *alg_data)
                jiffies, expires);
 
        timer->expires = jiffies + expires;
-       timer->data = (unsigned long)alg_data;
 
        add_timer(timer);
 }
@@ -435,9 +434,9 @@ static irqreturn_t i2c_pnx_interrupt(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-static void i2c_pnx_timeout(unsigned long data)
+static void i2c_pnx_timeout(struct timer_list *t)
 {
-       struct i2c_pnx_algo_data *alg_data = (struct i2c_pnx_algo_data *)data;
+       struct i2c_pnx_algo_data *alg_data = from_timer(alg_data, t, mif.timer);
        u32 ctl;
 
        dev_err(&alg_data->adapter.dev,
@@ -659,8 +658,7 @@ static int i2c_pnx_probe(struct platform_device *pdev)
        if (IS_ERR(alg_data->clk))
                return PTR_ERR(alg_data->clk);
 
-       setup_timer(&alg_data->mif.timer, i2c_pnx_timeout,
-                       (unsigned long)alg_data);
+       timer_setup(&alg_data->mif.timer, i2c_pnx_timeout, 0);
 
        snprintf(alg_data->adapter.name, sizeof(alg_data->adapter.name),
                 "%s", pdev->name);
index c811af4..95c2f1c 100644 (file)
 
 #define ICSR2_NACKF    0x10
 
-/* ICBRx (@ PCLK 33MHz) */
 #define ICBR_RESERVED  0xe0 /* Should be 1 on writes */
-#define ICBRL_SP100K   (19 | ICBR_RESERVED)
-#define ICBRH_SP100K   (16 | ICBR_RESERVED)
-#define ICBRL_SP400K   (21 | ICBR_RESERVED)
-#define ICBRH_SP400K   (9 | ICBR_RESERVED)
 
 #define RIIC_INIT_MSG  -1
 
@@ -288,48 +283,99 @@ static const struct i2c_algorithm riic_algo = {
        .functionality  = riic_func,
 };
 
-static int riic_init_hw(struct riic_dev *riic, u32 spd)
+static int riic_init_hw(struct riic_dev *riic, struct i2c_timings *t)
 {
        int ret;
        unsigned long rate;
+       int total_ticks, cks, brl, brh;
 
        ret = clk_prepare_enable(riic->clk);
        if (ret)
                return ret;
 
+       if (t->bus_freq_hz > 400000) {
+               dev_err(&riic->adapter.dev,
+                       "unsupported bus speed (%dHz). 400000 max\n",
+                       t->bus_freq_hz);
+               clk_disable_unprepare(riic->clk);
+               return -EINVAL;
+       }
+
+       rate = clk_get_rate(riic->clk);
+
        /*
-        * TODO: Implement formula to calculate the timing values depending on
-        * variable parent clock rate and arbitrary bus speed
+        * Assume the default register settings:
+        *  FER.SCLE = 1 (SCL sync circuit enabled, adds 2 or 3 cycles)
+        *  FER.NFE = 1 (noise circuit enabled)
+        *  MR3.NF = 0 (1 cycle of noise filtered out)
+        *
+        * Freq (CKS=000) = (I2CCLK + tr + tf)/ (BRH + 3 + 1) + (BRL + 3 + 1)
+        * Freq (CKS!=000) = (I2CCLK + tr + tf)/ (BRH + 2 + 1) + (BRL + 2 + 1)
         */
-       rate = clk_get_rate(riic->clk);
-       if (rate != 33325000) {
-               dev_err(&riic->adapter.dev,
-                       "invalid parent clk (%lu). Must be 33325000Hz\n", rate);
+
+       /*
+        * Determine reference clock rate. We must be able to get the desired
+        * frequency with only 62 clock ticks max (31 high, 31 low).
+        * Aim for a duty of 60% LOW, 40% HIGH.
+        */
+       total_ticks = DIV_ROUND_UP(rate, t->bus_freq_hz);
+
+       for (cks = 0; cks < 7; cks++) {
+               /*
+                * 60% low time must be less than BRL + 2 + 1
+                * BRL max register value is 0x1F.
+                */
+               brl = ((total_ticks * 6) / 10);
+               if (brl <= (0x1F + 3))
+                       break;
+
+               total_ticks /= 2;
+               rate /= 2;
+       }
+
+       if (brl > (0x1F + 3)) {
+               dev_err(&riic->adapter.dev, "invalid speed (%lu). Too slow.\n",
+                       (unsigned long)t->bus_freq_hz);
                clk_disable_unprepare(riic->clk);
                return -EINVAL;
        }
 
+       brh = total_ticks - brl;
+
+       /* Remove automatic clock ticks for sync circuit and NF */
+       if (cks == 0) {
+               brl -= 4;
+               brh -= 4;
+       } else {
+               brl -= 3;
+               brh -= 3;
+       }
+
+       /*
+        * Remove clock ticks for rise and fall times. Convert ns to clock
+        * ticks.
+        */
+       brl -= t->scl_fall_ns / (1000000000 / rate);
+       brh -= t->scl_rise_ns / (1000000000 / rate);
+
+       /* Adjust for min register values for when SCLE=1 and NFE=1 */
+       if (brl < 1)
+               brl = 1;
+       if (brh < 1)
+               brh = 1;
+
+       pr_debug("i2c-riic: freq=%lu, duty=%d, fall=%lu, rise=%lu, cks=%d, brl=%d, brh=%d\n",
+                rate / total_ticks, ((brl + 3) * 100) / (brl + brh + 6),
+                t->scl_fall_ns / (1000000000 / rate),
+                t->scl_rise_ns / (1000000000 / rate), cks, brl, brh);
+
        /* Changing the order of accessing IICRST and ICE may break things! */
        writeb(ICCR1_IICRST | ICCR1_SOWP, riic->base + RIIC_ICCR1);
        riic_clear_set_bit(riic, 0, ICCR1_ICE, RIIC_ICCR1);
 
-       switch (spd) {
-       case 100000:
-               writeb(ICMR1_CKS(3), riic->base + RIIC_ICMR1);
-               writeb(ICBRH_SP100K, riic->base + RIIC_ICBRH);
-               writeb(ICBRL_SP100K, riic->base + RIIC_ICBRL);
-               break;
-       case 400000:
-               writeb(ICMR1_CKS(1), riic->base + RIIC_ICMR1);
-               writeb(ICBRH_SP400K, riic->base + RIIC_ICBRH);
-               writeb(ICBRL_SP400K, riic->base + RIIC_ICBRL);
-               break;
-       default:
-               dev_err(&riic->adapter.dev,
-                       "unsupported bus speed (%dHz). Use 100000 or 400000\n", spd);
-               clk_disable_unprepare(riic->clk);
-               return -EINVAL;
-       }
+       writeb(ICMR1_CKS(cks), riic->base + RIIC_ICMR1);
+       writeb(brh | ICBR_RESERVED, riic->base + RIIC_ICBRH);
+       writeb(brl | ICBR_RESERVED, riic->base + RIIC_ICBRL);
 
        writeb(0, riic->base + RIIC_ICSER);
        writeb(ICMR3_ACKWP | ICMR3_RDRFS, riic->base + RIIC_ICMR3);
@@ -351,11 +397,10 @@ static struct riic_irq_desc riic_irqs[] = {
 
 static int riic_i2c_probe(struct platform_device *pdev)
 {
-       struct device_node *np = pdev->dev.of_node;
        struct riic_dev *riic;
        struct i2c_adapter *adap;
        struct resource *res;
-       u32 bus_rate = 0;
+       struct i2c_timings i2c_t;
        int i, ret;
 
        riic = devm_kzalloc(&pdev->dev, sizeof(*riic), GFP_KERNEL);
@@ -396,8 +441,9 @@ static int riic_i2c_probe(struct platform_device *pdev)
 
        init_completion(&riic->msg_done);
 
-       of_property_read_u32(np, "clock-frequency", &bus_rate);
-       ret = riic_init_hw(riic, bus_rate);
+       i2c_parse_fw_timings(&pdev->dev, &i2c_t, true);
+
+       ret = riic_init_hw(riic, &i2c_t);
        if (ret)
                return ret;
 
@@ -408,7 +454,8 @@ static int riic_i2c_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, riic);
 
-       dev_info(&pdev->dev, "registered with %dHz bus speed\n", bus_rate);
+       dev_info(&pdev->dev, "registered with %dHz bus speed\n",
+                i2c_t.bus_freq_hz);
        return 0;
 }
 
index 6f2aaeb..c03acdf 100644 (file)
@@ -881,7 +881,7 @@ static int sh_mobile_i2c_probe(struct platform_device *dev)
        struct sh_mobile_i2c_data *pd;
        struct i2c_adapter *adap;
        struct resource *res;
-       const struct of_device_id *match;
+       const struct sh_mobile_dt_config *config;
        int ret;
        u32 bus_speed;
 
@@ -913,10 +913,8 @@ static int sh_mobile_i2c_probe(struct platform_device *dev)
        pd->bus_speed = ret ? STANDARD_MODE : bus_speed;
        pd->clks_per_count = 1;
 
-       match = of_match_device(sh_mobile_i2c_dt_ids, &dev->dev);
-       if (match) {
-               const struct sh_mobile_dt_config *config = match->data;
-
+       config = of_device_get_match_data(&dev->dev);
+       if (config) {
                pd->clks_per_count = config->clks_per_count;
 
                if (config->setup)
index addd90a..7c7fc01 100644 (file)
@@ -282,8 +282,7 @@ static void taos_disconnect(struct serio *serio)
 {
        struct taos_data *taos = serio_get_drvdata(serio);
 
-       if (taos->client)
-               i2c_unregister_device(taos->client);
+       i2c_unregister_device(taos->client);
        i2c_del_adapter(&taos->adapter);
        serio_close(serio);
        kfree(taos);
index df0976f..19f8eec 100644 (file)
@@ -118,8 +118,6 @@ static void thunder_i2c_clock_disable(struct device *dev, struct clk *clk)
 static int thunder_i2c_smbus_setup_of(struct octeon_i2c *i2c,
                                      struct device_node *node)
 {
-       u32 type;
-
        if (!node)
                return -EINVAL;
 
@@ -127,10 +125,6 @@ static int thunder_i2c_smbus_setup_of(struct octeon_i2c *i2c,
        if (!i2c->alert_data.irq)
                return -EINVAL;
 
-       type = irqd_get_trigger_type(irq_get_irq_data(i2c->alert_data.irq));
-       i2c->alert_data.alert_edge_triggered =
-               (type & IRQ_TYPE_LEVEL_MASK) ? 1 : 0;
-
        i2c->ara = i2c_setup_smbus_alert(&i2c->adap, &i2c->alert_data);
        if (!i2c->ara)
                return -ENODEV;
@@ -149,8 +143,7 @@ static int thunder_i2c_smbus_setup(struct octeon_i2c *i2c,
 
 static void thunder_i2c_smbus_remove(struct octeon_i2c *i2c)
 {
-       if (i2c->ara)
-               i2c_unregister_device(i2c->ara);
+       i2c_unregister_device(i2c->ara);
 }
 
 static int thunder_i2c_probe_pci(struct pci_dev *pdev,
index 7e89ba6..a7ac746 100644 (file)
@@ -129,6 +129,11 @@ struct slimpro_i2c_dev {
 #define to_slimpro_i2c_dev(cl) \
                container_of(cl, struct slimpro_i2c_dev, mbox_client)
 
+enum slimpro_i2c_version {
+       XGENE_SLIMPRO_I2C_V1 = 0,
+       XGENE_SLIMPRO_I2C_V2 = 1,
+};
+
 /*
  * This function tests and clears a bitmask then returns its old value
  */
@@ -476,6 +481,15 @@ static int xgene_slimpro_i2c_probe(struct platform_device *pdev)
                }
        } else {
                struct acpi_pcct_hw_reduced *cppc_ss;
+               const struct acpi_device_id *acpi_id;
+               int version = XGENE_SLIMPRO_I2C_V1;
+
+               acpi_id = acpi_match_device(pdev->dev.driver->acpi_match_table,
+                                           &pdev->dev);
+               if (!acpi_id)
+                       return -EINVAL;
+
+               version = (int)acpi_id->driver_data;
 
                if (device_property_read_u32(&pdev->dev, "pcc-channel",
                                             &ctx->mbox_idx))
@@ -514,9 +528,16 @@ static int xgene_slimpro_i2c_probe(struct platform_device *pdev)
                 */
                ctx->comm_base_addr = cppc_ss->base_address;
                if (ctx->comm_base_addr) {
-                       ctx->pcc_comm_addr = memremap(ctx->comm_base_addr,
-                                                     cppc_ss->length,
-                                                     MEMREMAP_WB);
+                       if (version == XGENE_SLIMPRO_I2C_V2)
+                               ctx->pcc_comm_addr = memremap(
+                                                       ctx->comm_base_addr,
+                                                       cppc_ss->length,
+                                                       MEMREMAP_WT);
+                       else
+                               ctx->pcc_comm_addr = memremap(
+                                                       ctx->comm_base_addr,
+                                                       cppc_ss->length,
+                                                       MEMREMAP_WB);
                } else {
                        dev_err(&pdev->dev, "Failed to get PCC comm region\n");
                        rc = -ENOENT;
@@ -581,7 +602,8 @@ MODULE_DEVICE_TABLE(of, xgene_slimpro_i2c_dt_ids);
 
 #ifdef CONFIG_ACPI
 static const struct acpi_device_id xgene_slimpro_i2c_acpi_ids[] = {
-       {"APMC0D40", 0},
+       {"APMC0D40", XGENE_SLIMPRO_I2C_V1},
+       {"APMC0D8B", XGENE_SLIMPRO_I2C_V2},
        {}
 };
 MODULE_DEVICE_TABLE(acpi, xgene_slimpro_i2c_acpi_ids);
index 6b106e9..b970bf8 100644 (file)
@@ -7,6 +7,7 @@
  */
 
 #include <linux/acpi.h>
+#include <linux/clk.h>
 #include <linux/completion.h>
 #include <linux/i2c.h>
 #include <linux/init.h>
@@ -81,9 +82,12 @@ struct xlp9xx_i2c_dev {
        struct completion msg_complete;
        int irq;
        bool msg_read;
+       bool len_recv;
+       bool client_pec;
        u32 __iomem *base;
        u32 msg_buf_remaining;
        u32 msg_len;
+       u32 ip_clk_hz;
        u32 clk_hz;
        u32 msg_err;
        u8 *msg_buf;
@@ -141,10 +145,25 @@ static void xlp9xx_i2c_fill_tx_fifo(struct xlp9xx_i2c_dev *priv)
 static void xlp9xx_i2c_drain_rx_fifo(struct xlp9xx_i2c_dev *priv)
 {
        u32 len, i;
-       u8 *buf = priv->msg_buf;
+       u8 rlen, *buf = priv->msg_buf;
 
        len = xlp9xx_read_i2c_reg(priv, XLP9XX_I2C_FIFOWCNT) &
                                  XLP9XX_I2C_FIFO_WCNT_MASK;
+       if (!len)
+               return;
+       if (priv->len_recv) {
+               /* read length byte */
+               rlen = xlp9xx_read_i2c_reg(priv, XLP9XX_I2C_MRXFIFO);
+               *buf++ = rlen;
+               len--;
+               if (priv->client_pec)
+                       ++rlen;
+               /* update remaining bytes and message length */
+               priv->msg_buf_remaining = rlen;
+               priv->msg_len = rlen + 1;
+               priv->len_recv = false;
+       }
+
        len = min(priv->msg_buf_remaining, len);
        for (i = 0; i < len; i++, buf++)
                *buf = xlp9xx_read_i2c_reg(priv, XLP9XX_I2C_MRXFIFO);
@@ -213,7 +232,7 @@ static int xlp9xx_i2c_init(struct xlp9xx_i2c_dev *priv)
         * The controller uses 5 * SCL clock internally.
         * So prescale value should be divided by 5.
         */
-       prescale = DIV_ROUND_UP(XLP9XX_I2C_IP_CLK_FREQ, priv->clk_hz);
+       prescale = DIV_ROUND_UP(priv->ip_clk_hz, priv->clk_hz);
        prescale = ((prescale - 8) / 5) - 1;
        xlp9xx_write_i2c_reg(priv, XLP9XX_I2C_CTRL, XLP9XX_I2C_CTRL_RST);
        xlp9xx_write_i2c_reg(priv, XLP9XX_I2C_CTRL, XLP9XX_I2C_CTRL_EN |
@@ -228,7 +247,7 @@ static int xlp9xx_i2c_xfer_msg(struct xlp9xx_i2c_dev *priv, struct i2c_msg *msg,
                               int last_msg)
 {
        unsigned long timeleft;
-       u32 intr_mask, cmd, val;
+       u32 intr_mask, cmd, val, len;
 
        priv->msg_buf = msg->buf;
        priv->msg_buf_remaining = priv->msg_len = msg->len;
@@ -261,9 +280,13 @@ static int xlp9xx_i2c_xfer_msg(struct xlp9xx_i2c_dev *priv, struct i2c_msg *msg,
        else
                val &= ~XLP9XX_I2C_CTRL_ADDMODE;
 
+       priv->len_recv = msg->flags & I2C_M_RECV_LEN;
+       len = priv->len_recv ? XLP9XX_I2C_FIFO_SIZE : msg->len;
+       priv->client_pec = msg->flags & I2C_CLIENT_PEC;
+
        /* set data length to be transferred */
        val = (val & ~XLP9XX_I2C_CTRL_MCTLEN_MASK) |
-             (msg->len << XLP9XX_I2C_CTRL_MCTLEN_SHIFT);
+             (len << XLP9XX_I2C_CTRL_MCTLEN_SHIFT);
        xlp9xx_write_i2c_reg(priv, XLP9XX_I2C_CTRL, val);
 
        /* fill fifo during tx */
@@ -310,6 +333,9 @@ static int xlp9xx_i2c_xfer_msg(struct xlp9xx_i2c_dev *priv, struct i2c_msg *msg,
                return -ETIMEDOUT;
        }
 
+       /* update msg->len with actual received length */
+       if (msg->flags & I2C_M_RECV_LEN)
+               msg->len = priv->msg_len;
        return 0;
 }
 
@@ -342,9 +368,19 @@ static const struct i2c_algorithm xlp9xx_i2c_algo = {
 static int xlp9xx_i2c_get_frequency(struct platform_device *pdev,
                                    struct xlp9xx_i2c_dev *priv)
 {
+       struct clk *clk;
        u32 freq;
        int err;
 
+       clk = devm_clk_get(&pdev->dev, NULL);
+       if (IS_ERR(clk)) {
+               priv->ip_clk_hz = XLP9XX_I2C_IP_CLK_FREQ;
+               dev_dbg(&pdev->dev, "using default input frequency %u\n",
+                       priv->ip_clk_hz);
+       } else {
+               priv->ip_clk_hz = clk_get_rate(clk);
+       }
+
        err = device_property_read_u32(&pdev->dev, "clock-frequency", &freq);
        if (err) {
                freq = XLP9XX_I2C_DEFAULT_FREQ;
index 56e4658..706164b 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/errno.h>
 #include <linux/gpio.h>
 #include <linux/i2c.h>
+#include <linux/i2c-smbus.h>
 #include <linux/idr.h>
 #include <linux/init.h>
 #include <linux/irqflags.h>
@@ -205,9 +206,6 @@ static int i2c_generic_recovery(struct i2c_adapter *adap)
         */
        while (i++ < RECOVERY_CLK_CNT * 2) {
                if (val) {
-                       /* Break if SDA is high */
-                       if (bri->get_sda && bri->get_sda(adap))
-                                       break;
                        /* SCL shouldn't be low here */
                        if (!bri->get_scl(adap)) {
                                dev_err(&adap->dev,
@@ -215,6 +213,9 @@ static int i2c_generic_recovery(struct i2c_adapter *adap)
                                ret = -EBUSY;
                                break;
                        }
+                       /* Break if SDA is high */
+                       if (bri->get_sda && bri->get_sda(adap))
+                               break;
                }
 
                val = !val;
@@ -222,6 +223,10 @@ static int i2c_generic_recovery(struct i2c_adapter *adap)
                ndelay(RECOVERY_NDELAY);
        }
 
+       /* check if recovery actually succeeded */
+       if (bri->get_sda && !bri->get_sda(adap))
+               ret = -EBUSY;
+
        if (bri->unprepare_recovery)
                bri->unprepare_recovery(adap);
 
@@ -666,10 +671,16 @@ static void i2c_adapter_unlock_bus(struct i2c_adapter *adapter,
 }
 
 static void i2c_dev_set_name(struct i2c_adapter *adap,
-                            struct i2c_client *client)
+                            struct i2c_client *client,
+                            struct i2c_board_info const *info)
 {
        struct acpi_device *adev = ACPI_COMPANION(&client->dev);
 
+       if (info && info->dev_name) {
+               dev_set_name(&client->dev, "i2c-%s", info->dev_name);
+               return;
+       }
+
        if (adev) {
                dev_set_name(&client->dev, "i2c-%s", acpi_dev_name(adev));
                return;
@@ -766,7 +777,7 @@ i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info)
        client->dev.of_node = info->of_node;
        client->dev.fwnode = info->fwnode;
 
-       i2c_dev_set_name(adap, client);
+       i2c_dev_set_name(adap, client, info);
 
        if (info->properties) {
                status = device_add_properties(&client->dev, info->properties);
@@ -808,6 +819,8 @@ EXPORT_SYMBOL_GPL(i2c_new_device);
  */
 void i2c_unregister_device(struct i2c_client *client)
 {
+       if (!client)
+               return;
        if (client->dev.of_node)
                of_node_clear_flag(client->dev.of_node, OF_POPULATED);
        if (ACPI_COMPANION(&client->dev))
@@ -1259,6 +1272,10 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
                goto out_list;
        }
 
+       res = of_i2c_setup_smbus_alert(adap);
+       if (res)
+               goto out_reg;
+
        dev_dbg(&adap->dev, "adapter [%s] registered\n", adap->name);
 
        pm_runtime_no_callbacks(&adap->dev);
@@ -1290,6 +1307,10 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
 
        return 0;
 
+out_reg:
+       init_completion(&adap->dev_released);
+       device_unregister(&adap->dev);
+       wait_for_completion(&adap->dev_released);
 out_list:
        mutex_lock(&core_lock);
        idr_remove(&i2c_adapter_idr, adap->nr);
@@ -1417,8 +1438,7 @@ static int __unregister_client(struct device *dev, void *dummy)
 static int __unregister_dummy(struct device *dev, void *dummy)
 {
        struct i2c_client *client = i2c_verify_client(dev);
-       if (client)
-               i2c_unregister_device(client);
+       i2c_unregister_device(client);
        return 0;
 }
 
index 10f00a8..4bb9927 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/device.h>
 #include <linux/err.h>
 #include <linux/i2c.h>
+#include <linux/i2c-smbus.h>
 
 #define CREATE_TRACE_POINTS
 #include <trace/events/smbus.h>
@@ -592,3 +593,57 @@ s32 i2c_smbus_read_i2c_block_data_or_emulated(const struct i2c_client *client,
        return i;
 }
 EXPORT_SYMBOL(i2c_smbus_read_i2c_block_data_or_emulated);
+
+/**
+ * i2c_setup_smbus_alert - Setup SMBus alert support
+ * @adapter: the target adapter
+ * @setup: setup data for the SMBus alert handler
+ * Context: can sleep
+ *
+ * Setup handling of the SMBus alert protocol on a given I2C bus segment.
+ *
+ * Handling can be done either through our IRQ handler, or by the
+ * adapter (from its handler, periodic polling, or whatever).
+ *
+ * NOTE that if we manage the IRQ, we *MUST* know if it's level or
+ * edge triggered in order to hand it to the workqueue correctly.
+ * If triggering the alert seems to wedge the system, you probably
+ * should have said it's level triggered.
+ *
+ * This returns the ara client, which should be saved for later use with
+ * i2c_handle_smbus_alert() and ultimately i2c_unregister_device(); or NULL
+ * to indicate an error.
+ */
+struct i2c_client *i2c_setup_smbus_alert(struct i2c_adapter *adapter,
+                                        struct i2c_smbus_alert_setup *setup)
+{
+       struct i2c_board_info ara_board_info = {
+               I2C_BOARD_INFO("smbus_alert", 0x0c),
+               .platform_data = setup,
+       };
+
+       return i2c_new_device(adapter, &ara_board_info);
+}
+EXPORT_SYMBOL_GPL(i2c_setup_smbus_alert);
+
+#if IS_ENABLED(CONFIG_I2C_SMBUS) && IS_ENABLED(CONFIG_OF)
+int of_i2c_setup_smbus_alert(struct i2c_adapter *adapter)
+{
+       struct i2c_client *client;
+       int irq;
+
+       irq = of_property_match_string(adapter->dev.of_node, "interrupt-names",
+                                      "smbus_alert");
+       if (irq == -EINVAL || irq == -ENODATA)
+               return 0;
+       else if (irq < 0)
+               return irq;
+
+       client = i2c_setup_smbus_alert(adapter, NULL);
+       if (!client)
+               return -ENODEV;
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(of_i2c_setup_smbus_alert);
+#endif
index f9271c7..5a1dd7f 100644 (file)
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/of_irq.h>
 #include <linux/slab.h>
 #include <linux/workqueue.h>
 
 struct i2c_smbus_alert {
-       unsigned int            alert_edge_triggered:1;
-       int                     irq;
        struct work_struct      alert;
        struct i2c_client       *ara;           /* Alert response address */
 };
@@ -72,13 +71,12 @@ static int smbus_do_alert(struct device *dev, void *addrp)
  * The alert IRQ handler needs to hand work off to a task which can issue
  * SMBus calls, because those sleeping calls can't be made in IRQ context.
  */
-static void smbus_alert(struct work_struct *work)
+static irqreturn_t smbus_alert(int irq, void *d)
 {
-       struct i2c_smbus_alert *alert;
+       struct i2c_smbus_alert *alert = d;
        struct i2c_client *ara;
        unsigned short prev_addr = 0;   /* Not a valid address */
 
-       alert = container_of(work, struct i2c_smbus_alert, alert);
        ara = alert->ara;
 
        for (;;) {
@@ -115,21 +113,17 @@ static void smbus_alert(struct work_struct *work)
                prev_addr = data.addr;
        }
 
-       /* We handled all alerts; re-enable level-triggered IRQs */
-       if (!alert->alert_edge_triggered)
-               enable_irq(alert->irq);
+       return IRQ_HANDLED;
 }
 
-static irqreturn_t smbalert_irq(int irq, void *d)
+static void smbalert_work(struct work_struct *work)
 {
-       struct i2c_smbus_alert *alert = d;
+       struct i2c_smbus_alert *alert;
 
-       /* Disable level-triggered IRQs until we handle them */
-       if (!alert->alert_edge_triggered)
-               disable_irq_nosync(irq);
+       alert = container_of(work, struct i2c_smbus_alert, alert);
+
+       smbus_alert(0, alert);
 
-       schedule_work(&alert->alert);
-       return IRQ_HANDLED;
 }
 
 /* Setup SMBALERT# infrastructure */
@@ -139,28 +133,35 @@ static int smbalert_probe(struct i2c_client *ara,
        struct i2c_smbus_alert_setup *setup = dev_get_platdata(&ara->dev);
        struct i2c_smbus_alert *alert;
        struct i2c_adapter *adapter = ara->adapter;
-       int res;
+       int res, irq;
 
        alert = devm_kzalloc(&ara->dev, sizeof(struct i2c_smbus_alert),
                             GFP_KERNEL);
        if (!alert)
                return -ENOMEM;
 
-       alert->alert_edge_triggered = setup->alert_edge_triggered;
-       alert->irq = setup->irq;
-       INIT_WORK(&alert->alert, smbus_alert);
+       if (setup) {
+               irq = setup->irq;
+       } else {
+               irq = of_irq_get_byname(adapter->dev.of_node, "smbus_alert");
+               if (irq <= 0)
+                       return irq;
+       }
+
+       INIT_WORK(&alert->alert, smbalert_work);
        alert->ara = ara;
 
-       if (setup->irq > 0) {
-               res = devm_request_irq(&ara->dev, setup->irq, smbalert_irq,
-                                      0, "smbus_alert", alert);
+       if (irq > 0) {
+               res = devm_request_threaded_irq(&ara->dev, irq,
+                                               NULL, smbus_alert,
+                                               IRQF_SHARED | IRQF_ONESHOT,
+                                               "smbus_alert", alert);
                if (res)
                        return res;
        }
 
        i2c_set_clientdata(ara, alert);
-       dev_info(&adapter->dev, "supports SMBALERT#, %s trigger\n",
-                setup->alert_edge_triggered ? "edge" : "level");
+       dev_info(&adapter->dev, "supports SMBALERT#\n");
 
        return 0;
 }
@@ -189,38 +190,6 @@ static struct i2c_driver smbalert_driver = {
        .id_table       = smbalert_ids,
 };
 
-/**
- * i2c_setup_smbus_alert - Setup SMBus alert support
- * @adapter: the target adapter
- * @setup: setup data for the SMBus alert handler
- * Context: can sleep
- *
- * Setup handling of the SMBus alert protocol on a given I2C bus segment.
- *
- * Handling can be done either through our IRQ handler, or by the
- * adapter (from its handler, periodic polling, or whatever).
- *
- * NOTE that if we manage the IRQ, we *MUST* know if it's level or
- * edge triggered in order to hand it to the workqueue correctly.
- * If triggering the alert seems to wedge the system, you probably
- * should have said it's level triggered.
- *
- * This returns the ara client, which should be saved for later use with
- * i2c_handle_smbus_alert() and ultimately i2c_unregister_device(); or NULL
- * to indicate an error.
- */
-struct i2c_client *i2c_setup_smbus_alert(struct i2c_adapter *adapter,
-                                        struct i2c_smbus_alert_setup *setup)
-{
-       struct i2c_board_info ara_board_info = {
-               I2C_BOARD_INFO("smbus_alert", 0x0c),
-               .platform_data = setup,
-       };
-
-       return i2c_new_device(adapter, &ara_board_info);
-}
-EXPORT_SYMBOL_GPL(i2c_setup_smbus_alert);
-
 /**
  * i2c_handle_smbus_alert - Handle an SMBus alert
  * @ara: the ARA client on the relevant adapter
index 7b992db..2ca068d 100644 (file)
@@ -246,36 +246,6 @@ static irqreturn_t pca954x_irq_handler(int irq, void *dev_id)
        return handled ? IRQ_HANDLED : IRQ_NONE;
 }
 
-static void pca954x_irq_mask(struct irq_data *idata)
-{
-       struct pca954x *data = irq_data_get_irq_chip_data(idata);
-       unsigned int pos = idata->hwirq;
-       unsigned long flags;
-
-       raw_spin_lock_irqsave(&data->lock, flags);
-
-       data->irq_mask &= ~BIT(pos);
-       if (!data->irq_mask)
-               disable_irq(data->client->irq);
-
-       raw_spin_unlock_irqrestore(&data->lock, flags);
-}
-
-static void pca954x_irq_unmask(struct irq_data *idata)
-{
-       struct pca954x *data = irq_data_get_irq_chip_data(idata);
-       unsigned int pos = idata->hwirq;
-       unsigned long flags;
-
-       raw_spin_lock_irqsave(&data->lock, flags);
-
-       if (!data->irq_mask)
-               enable_irq(data->client->irq);
-       data->irq_mask |= BIT(pos);
-
-       raw_spin_unlock_irqrestore(&data->lock, flags);
-}
-
 static int pca954x_irq_set_type(struct irq_data *idata, unsigned int type)
 {
        if ((type & IRQ_TYPE_SENSE_MASK) != IRQ_TYPE_LEVEL_LOW)
@@ -285,8 +255,6 @@ static int pca954x_irq_set_type(struct irq_data *idata, unsigned int type)
 
 static struct irq_chip pca954x_irq_chip = {
        .name = "i2c-mux-pca954x",
-       .irq_mask = pca954x_irq_mask,
-       .irq_unmask = pca954x_irq_unmask,
        .irq_set_type = pca954x_irq_set_type,
 };
 
@@ -294,7 +262,7 @@ static int pca954x_irq_setup(struct i2c_mux_core *muxc)
 {
        struct pca954x *data = i2c_mux_priv(muxc);
        struct i2c_client *client = data->client;
-       int c, err, irq;
+       int c, irq;
 
        if (!data->chip->has_irq || client->irq <= 0)
                return 0;
@@ -309,29 +277,31 @@ static int pca954x_irq_setup(struct i2c_mux_core *muxc)
 
        for (c = 0; c < data->chip->nchans; c++) {
                irq = irq_create_mapping(data->irq, c);
+               if (!irq) {
+                       dev_err(&client->dev, "failed irq create map\n");
+                       return -EINVAL;
+               }
                irq_set_chip_data(irq, data);
                irq_set_chip_and_handler(irq, &pca954x_irq_chip,
                        handle_simple_irq);
        }
 
-       err = devm_request_threaded_irq(&client->dev, data->client->irq, NULL,
-                                       pca954x_irq_handler,
-                                       IRQF_ONESHOT | IRQF_SHARED,
-                                       "pca954x", data);
-       if (err)
-               goto err_req_irq;
+       return 0;
+}
 
-       disable_irq(data->client->irq);
+static void pca954x_cleanup(struct i2c_mux_core *muxc)
+{
+       struct pca954x *data = i2c_mux_priv(muxc);
+       int c, irq;
 
-       return 0;
-err_req_irq:
-       for (c = 0; c < data->chip->nchans; c++) {
-               irq = irq_find_mapping(data->irq, c);
-               irq_dispose_mapping(irq);
+       if (data->irq) {
+               for (c = 0; c < data->chip->nchans; c++) {
+                       irq = irq_find_mapping(data->irq, c);
+                       irq_dispose_mapping(irq);
+               }
+               irq_domain_remove(data->irq);
        }
-       irq_domain_remove(data->irq);
-
-       return err;
+       i2c_mux_del_adapters(muxc);
 }
 
 /*
@@ -391,7 +361,7 @@ static int pca954x_probe(struct i2c_client *client,
 
        ret = pca954x_irq_setup(muxc);
        if (ret)
-               goto fail_del_adapters;
+               goto fail_cleanup;
 
        /* Now create an adapter for each channel */
        for (num = 0; num < data->chip->nchans; num++) {
@@ -414,7 +384,16 @@ static int pca954x_probe(struct i2c_client *client,
 
                ret = i2c_mux_add_adapter(muxc, force, num, class);
                if (ret)
-                       goto fail_del_adapters;
+                       goto fail_cleanup;
+       }
+
+       if (data->irq) {
+               ret = devm_request_threaded_irq(&client->dev, data->client->irq,
+                                               NULL, pca954x_irq_handler,
+                                               IRQF_ONESHOT | IRQF_SHARED,
+                                               "pca954x", data);
+               if (ret)
+                       goto fail_cleanup;
        }
 
        dev_info(&client->dev,
@@ -424,26 +403,16 @@ static int pca954x_probe(struct i2c_client *client,
 
        return 0;
 
-fail_del_adapters:
-       i2c_mux_del_adapters(muxc);
+fail_cleanup:
+       pca954x_cleanup(muxc);
        return ret;
 }
 
 static int pca954x_remove(struct i2c_client *client)
 {
        struct i2c_mux_core *muxc = i2c_get_clientdata(client);
-       struct pca954x *data = i2c_mux_priv(muxc);
-       int c, irq;
 
-       if (data->irq) {
-               for (c = 0; c < data->chip->nchans; c++) {
-                       irq = irq_find_mapping(data->irq, c);
-                       irq_dispose_mapping(irq);
-               }
-               irq_domain_remove(data->irq);
-       }
-
-       i2c_mux_del_adapters(muxc);
+       pca954x_cleanup(muxc);
        return 0;
 }
 
index d970318..f6c9c3d 100644 (file)
@@ -107,9 +107,9 @@ static int i2c_mux_reg_probe_dt(struct regmux *mux,
        put_device(&adapter->dev);
 
        mux->data.n_values = of_get_child_count(np);
-       if (of_find_property(np, "little-endian", NULL)) {
+       if (of_property_read_bool(np, "little-endian")) {
                mux->data.little_endian = true;
-       } else if (of_find_property(np, "big-endian", NULL)) {
+       } else if (of_property_read_bool(np, "big-endian")) {
                mux->data.little_endian = false;
        } else {
 #if defined(__BYTE_ORDER) ? __BYTE_ORDER == __LITTLE_ENDIAN : \
@@ -122,10 +122,7 @@ static int i2c_mux_reg_probe_dt(struct regmux *mux,
 #error Endianness not defined?
 #endif
        }
-       if (of_find_property(np, "write-only", NULL))
-               mux->data.write_only = true;
-       else
-               mux->data.write_only = false;
+       mux->data.write_only = of_property_read_bool(np, "write-only");
 
        values = devm_kzalloc(&pdev->dev,
                              sizeof(*mux->data.values) * mux->data.n_values,
index 6941166..865bbea 100644 (file)
@@ -38,12 +38,7 @@ int intel_lpss_resume(struct device *dev);
 #ifdef CONFIG_PM_SLEEP
 #define INTEL_LPSS_SLEEP_PM_OPS                        \
        .prepare = intel_lpss_prepare,          \
-       .suspend = intel_lpss_suspend,          \
-       .resume = intel_lpss_resume,            \
-       .freeze = intel_lpss_suspend,           \
-       .thaw = intel_lpss_resume,              \
-       .poweroff = intel_lpss_suspend,         \
-       .restore = intel_lpss_resume,
+       SET_LATE_SYSTEM_SLEEP_PM_OPS(intel_lpss_suspend, intel_lpss_resume)
 #else
 #define INTEL_LPSS_SLEEP_PM_OPS
 #endif
index 4053435..ad77416 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/platform_device.h>
 #include <linux/pci.h>
 #include <linux/i2c-gpio.h>
+#include <linux/gpio/machine.h>
 #include <linux/slab.h>
 
 #include <linux/sm501.h>
@@ -1107,14 +1108,6 @@ static void sm501_gpio_remove(struct sm501_devdata *sm)
        kfree(gpio->regs_res);
 }
 
-static inline int sm501_gpio_pin2nr(struct sm501_devdata *sm, unsigned int pin)
-{
-       struct sm501_gpio *gpio = &sm->gpio;
-       int base = (pin < 32) ? gpio->low.gpio.base : gpio->high.gpio.base;
-
-       return (pin % 32) + base;
-}
-
 static inline int sm501_gpio_isregistered(struct sm501_devdata *sm)
 {
        return sm->gpio.registered;
@@ -1129,11 +1122,6 @@ static inline void sm501_gpio_remove(struct sm501_devdata *sm)
 {
 }
 
-static inline int sm501_gpio_pin2nr(struct sm501_devdata *sm, unsigned int pin)
-{
-       return -1;
-}
-
 static inline int sm501_gpio_isregistered(struct sm501_devdata *sm)
 {
        return 0;
@@ -1145,20 +1133,37 @@ static int sm501_register_gpio_i2c_instance(struct sm501_devdata *sm,
 {
        struct i2c_gpio_platform_data *icd;
        struct platform_device *pdev;
+       struct gpiod_lookup_table *lookup;
 
        pdev = sm501_create_subdev(sm, "i2c-gpio", 0,
                                   sizeof(struct i2c_gpio_platform_data));
        if (!pdev)
                return -ENOMEM;
 
-       icd = dev_get_platdata(&pdev->dev);
-
-       /* We keep the pin_sda and pin_scl fields relative in case the
-        * same platform data is passed to >1 SM501.
-        */
+       /* Create a gpiod lookup using gpiochip-local offsets */
+       lookup = devm_kzalloc(&pdev->dev,
+                             sizeof(*lookup) + 3 * sizeof(struct gpiod_lookup),
+                             GFP_KERNEL);
+       lookup->dev_id = "i2c-gpio";
+       if (iic->pin_sda < 32)
+               lookup->table[0].chip_label = "SM501-LOW";
+       else
+               lookup->table[0].chip_label = "SM501-HIGH";
+       lookup->table[0].chip_hwnum = iic->pin_sda % 32;
+       lookup->table[0].con_id = NULL;
+       lookup->table[0].idx = 0;
+       lookup->table[0].flags = GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN;
+       if (iic->pin_scl < 32)
+               lookup->table[1].chip_label = "SM501-LOW";
+       else
+               lookup->table[1].chip_label = "SM501-HIGH";
+       lookup->table[1].chip_hwnum = iic->pin_scl % 32;
+       lookup->table[1].con_id = NULL;
+       lookup->table[1].idx = 1;
+       lookup->table[1].flags = GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN;
+       gpiod_add_lookup_table(lookup);
 
-       icd->sda_pin = sm501_gpio_pin2nr(sm, iic->pin_sda);
-       icd->scl_pin = sm501_gpio_pin2nr(sm, iic->pin_scl);
+       icd = dev_get_platdata(&pdev->dev);
        icd->timeout = iic->timeout;
        icd->udelay = iic->udelay;
 
@@ -1170,9 +1175,9 @@ static int sm501_register_gpio_i2c_instance(struct sm501_devdata *sm,
 
        pdev->id = iic->bus_num;
 
-       dev_info(sm->dev, "registering i2c-%d: sda=%d (%d), scl=%d (%d)\n",
+       dev_info(sm->dev, "registering i2c-%d: sda=%d, scl=%d\n",
                 iic->bus_num,
-                icd->sda_pin, iic->pin_sda, icd->scl_pin, iic->pin_scl);
+                iic->pin_sda, iic->pin_scl);
 
        return sm501_register_device(sm, pdev);
 }
index 764ff5d..e0b4b36 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/module.h>
+#include <linux/of_device.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/mutex.h>
@@ -24,6 +25,7 @@
 #include <linux/i2c.h>
 #include <linux/nvmem-provider.h>
 #include <linux/platform_data/at24.h>
+#include <linux/pm_runtime.h>
 
 /*
  * I2C EEPROMs from most vendors are inexpensive and mostly interchangeable.
@@ -175,6 +177,64 @@ static const struct i2c_device_id at24_ids[] = {
 };
 MODULE_DEVICE_TABLE(i2c, at24_ids);
 
+static const struct of_device_id at24_of_match[] = {
+       {
+               .compatible = "atmel,24c00",
+               .data = (void *)AT24_DEVICE_MAGIC(128 / 8, AT24_FLAG_TAKE8ADDR)
+       },
+       {
+               .compatible = "atmel,24c01",
+               .data = (void *)AT24_DEVICE_MAGIC(1024 / 8, 0)
+       },
+       {
+               .compatible = "atmel,24c02",
+               .data = (void *)AT24_DEVICE_MAGIC(2048 / 8, 0)
+       },
+       {
+               .compatible = "atmel,spd",
+               .data = (void *)AT24_DEVICE_MAGIC(2048 / 8,
+                               AT24_FLAG_READONLY | AT24_FLAG_IRUGO)
+       },
+       {
+               .compatible = "atmel,24c04",
+               .data = (void *)AT24_DEVICE_MAGIC(4096 / 8, 0)
+       },
+       {
+               .compatible = "atmel,24c08",
+               .data = (void *)AT24_DEVICE_MAGIC(8192 / 8, 0)
+       },
+       {
+               .compatible = "atmel,24c16",
+               .data = (void *)AT24_DEVICE_MAGIC(16384 / 8, 0)
+       },
+       {
+               .compatible = "atmel,24c32",
+               .data = (void *)AT24_DEVICE_MAGIC(32768 / 8, AT24_FLAG_ADDR16)
+       },
+       {
+               .compatible = "atmel,24c64",
+               .data = (void *)AT24_DEVICE_MAGIC(65536 / 8, AT24_FLAG_ADDR16)
+       },
+       {
+               .compatible = "atmel,24c128",
+               .data = (void *)AT24_DEVICE_MAGIC(131072 / 8, AT24_FLAG_ADDR16)
+       },
+       {
+               .compatible = "atmel,24c256",
+               .data = (void *)AT24_DEVICE_MAGIC(262144 / 8, AT24_FLAG_ADDR16)
+       },
+       {
+               .compatible = "atmel,24c512",
+               .data = (void *)AT24_DEVICE_MAGIC(524288 / 8, AT24_FLAG_ADDR16)
+       },
+       {
+               .compatible = "atmel,24c1024",
+               .data = (void *)AT24_DEVICE_MAGIC(1048576 / 8, AT24_FLAG_ADDR16)
+       },
+       { },
+};
+MODULE_DEVICE_TABLE(of, at24_of_match);
+
 static const struct acpi_device_id at24_acpi_ids[] = {
        { "INT3499", AT24_DEVICE_MAGIC(8192 / 8, 0) },
        { }
@@ -501,11 +561,21 @@ static ssize_t at24_eeprom_write_i2c(struct at24_data *at24, const char *buf,
 static int at24_read(void *priv, unsigned int off, void *val, size_t count)
 {
        struct at24_data *at24 = priv;
+       struct i2c_client *client;
        char *buf = val;
+       int ret;
 
        if (unlikely(!count))
                return count;
 
+       client = at24_translate_offset(at24, &off);
+
+       ret = pm_runtime_get_sync(&client->dev);
+       if (ret < 0) {
+               pm_runtime_put_noidle(&client->dev);
+               return ret;
+       }
+
        /*
         * Read data from chip, protecting against concurrent updates
         * from this host, but not from other I2C masters.
@@ -518,6 +588,7 @@ static int at24_read(void *priv, unsigned int off, void *val, size_t count)
                status = at24->read_func(at24, buf, off, count);
                if (status < 0) {
                        mutex_unlock(&at24->lock);
+                       pm_runtime_put(&client->dev);
                        return status;
                }
                buf += status;
@@ -527,17 +598,29 @@ static int at24_read(void *priv, unsigned int off, void *val, size_t count)
 
        mutex_unlock(&at24->lock);
 
+       pm_runtime_put(&client->dev);
+
        return 0;
 }
 
 static int at24_write(void *priv, unsigned int off, void *val, size_t count)
 {
        struct at24_data *at24 = priv;
+       struct i2c_client *client;
        char *buf = val;
+       int ret;
 
        if (unlikely(!count))
                return -EINVAL;
 
+       client = at24_translate_offset(at24, &off);
+
+       ret = pm_runtime_get_sync(&client->dev);
+       if (ret < 0) {
+               pm_runtime_put_noidle(&client->dev);
+               return ret;
+       }
+
        /*
         * Write data to chip, protecting against concurrent updates
         * from this host, but not from other I2C masters.
@@ -550,6 +633,7 @@ static int at24_write(void *priv, unsigned int off, void *val, size_t count)
                status = at24->write_func(at24, buf, off, count);
                if (status < 0) {
                        mutex_unlock(&at24->lock);
+                       pm_runtime_put(&client->dev);
                        return status;
                }
                buf += status;
@@ -559,6 +643,8 @@ static int at24_write(void *priv, unsigned int off, void *val, size_t count)
 
        mutex_unlock(&at24->lock);
 
+       pm_runtime_put(&client->dev);
+
        return 0;
 }
 
@@ -570,6 +656,10 @@ static void at24_get_pdata(struct device *dev, struct at24_platform_data *chip)
        if (device_property_present(dev, "read-only"))
                chip->flags |= AT24_FLAG_READONLY;
 
+       err = device_property_read_u32(dev, "size", &val);
+       if (!err)
+               chip->byte_len = val;
+
        err = device_property_read_u32(dev, "pagesize", &val);
        if (!err) {
                chip->page_size = val;
@@ -598,7 +688,16 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
        if (client->dev.platform_data) {
                chip = *(struct at24_platform_data *)client->dev.platform_data;
        } else {
-               if (id) {
+               /*
+                * The I2C core allows OF nodes compatibles to match against the
+                * I2C device ID table as a fallback, so check not only if an OF
+                * node is present but also if it matches an OF device ID entry.
+                */
+               if (client->dev.of_node &&
+                   of_match_device(at24_of_match, &client->dev)) {
+                       magic = (kernel_ulong_t)
+                               of_device_get_match_data(&client->dev);
+               } else if (id) {
                        magic = id->driver_data;
                } else {
                        const struct acpi_device_id *aid;
@@ -739,11 +838,16 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
 
        i2c_set_clientdata(client, at24);
 
+       /* enable runtime pm */
+       pm_runtime_set_active(&client->dev);
+       pm_runtime_enable(&client->dev);
+
        /*
         * Perform a one-byte test read to verify that the
         * chip is functional.
         */
        err = at24_read(at24, 0, &test_byte, 1);
+       pm_runtime_idle(&client->dev);
        if (err) {
                err = -ENODEV;
                goto err_clients;
@@ -791,6 +895,8 @@ err_clients:
                if (at24->client[i])
                        i2c_unregister_device(at24->client[i]);
 
+       pm_runtime_disable(&client->dev);
+
        return err;
 }
 
@@ -806,6 +912,9 @@ static int at24_remove(struct i2c_client *client)
        for (i = 1; i < at24->num_addresses; i++)
                i2c_unregister_device(at24->client[i]);
 
+       pm_runtime_disable(&client->dev);
+       pm_runtime_set_suspended(&client->dev);
+
        return 0;
 }
 
@@ -814,6 +923,7 @@ static int at24_remove(struct i2c_client *client)
 static struct i2c_driver at24_driver = {
        .driver = {
                .name = "at24",
+               .of_match_table = at24_of_match,
                .acpi_match_table = ACPI_PTR(at24_acpi_ids),
        },
        .probe = at24_probe,
index 5ab90c1..fbca0ba 100644 (file)
@@ -184,6 +184,20 @@ config CHARGER_SBS
         help
          Say Y to include support for SBS compilant battery chargers.
 
+config MANAGER_SBS
+       tristate "Smart Battery System Manager"
+       depends on I2C && I2C_MUX && GPIOLIB
+       select I2C_SMBUS
+       help
+         Say Y here to include support for Smart Battery System Manager
+         ICs. The driver reports online and charging status via sysfs.
+         It presents itself also as I2C mux which allows to bind
+         smart battery driver to its ports.
+         Supported is for example LTC1760.
+
+         This driver can also be built as a module. If so, the module will be
+         called sbs-manager.
+
 config BATTERY_BQ27XXX
        tristate "BQ27xxx battery driver"
        help
index aae4e4a..e83aa84 100644 (file)
@@ -37,6 +37,7 @@ obj-$(CONFIG_BATTERY_IPAQ_MICRO) += ipaq_micro_battery.o
 obj-$(CONFIG_BATTERY_WM97XX)   += wm97xx_battery.o
 obj-$(CONFIG_BATTERY_SBS)      += sbs-battery.o
 obj-$(CONFIG_CHARGER_SBS)      += sbs-charger.o
+obj-$(CONFIG_MANAGER_SBS)      += sbs-manager.o
 obj-$(CONFIG_BATTERY_BQ27XXX)  += bq27xxx_battery.o
 obj-$(CONFIG_BATTERY_BQ27XXX_I2C) += bq27xxx_battery_i2c.o
 obj-$(CONFIG_BATTERY_BQ27XXX_HDQ) += bq27xxx_battery_hdq.o
index b19a731..83d7b41 100644 (file)
@@ -177,10 +177,8 @@ static bool force_load;
 static int sbs_read_word_data(struct i2c_client *client, u8 address)
 {
        struct sbs_info *chip = i2c_get_clientdata(client);
+       int retries = chip->i2c_retry_count;
        s32 ret = 0;
-       int retries = 1;
-
-       retries = chip->i2c_retry_count;
 
        while (retries > 0) {
                ret = i2c_smbus_read_word_data(client, address);
@@ -204,7 +202,7 @@ static int sbs_read_string_data(struct i2c_client *client, u8 address,
 {
        struct sbs_info *chip = i2c_get_clientdata(client);
        s32 ret = 0, block_length = 0;
-       int retries_length = 1, retries_block = 1;
+       int retries_length, retries_block;
        u8 block_buffer[I2C_SMBUS_BLOCK_MAX + 1];
 
        retries_length = chip->i2c_retry_count;
@@ -269,10 +267,8 @@ static int sbs_write_word_data(struct i2c_client *client, u8 address,
        u16 value)
 {
        struct sbs_info *chip = i2c_get_clientdata(client);
+       int retries = chip->i2c_retry_count;
        s32 ret = 0;
-       int retries = 1;
-
-       retries = chip->i2c_retry_count;
 
        while (retries > 0) {
                ret = i2c_smbus_write_word_data(client, address, value);
@@ -321,16 +317,6 @@ static int sbs_get_battery_presence_and_health(
        union power_supply_propval *val)
 {
        s32 ret;
-       struct sbs_info *chip = i2c_get_clientdata(client);
-
-       if (psp == POWER_SUPPLY_PROP_PRESENT && chip->gpio_detect) {
-               ret = gpiod_get_value_cansleep(chip->gpio_detect);
-               if (ret < 0)
-                       return ret;
-               val->intval = ret;
-               chip->is_present = val->intval;
-               return ret;
-       }
 
        /*
         * Write to ManufacturerAccess with ManufacturerAccess command
@@ -570,7 +556,7 @@ static int sbs_get_battery_serial_number(struct i2c_client *client,
        if (ret < 0)
                return ret;
 
-       ret = sprintf(sbs_serial, "%04x", ret);
+       sprintf(sbs_serial, "%04x", ret);
        val->strval = sbs_serial;
 
        return 0;
@@ -598,6 +584,19 @@ static int sbs_get_property(struct power_supply *psy,
        struct sbs_info *chip = power_supply_get_drvdata(psy);
        struct i2c_client *client = chip->client;
 
+       if (chip->gpio_detect) {
+               ret = gpiod_get_value_cansleep(chip->gpio_detect);
+               if (ret < 0)
+                       return ret;
+               if (psp == POWER_SUPPLY_PROP_PRESENT) {
+                       val->intval = ret;
+                       chip->is_present = val->intval;
+                       return 0;
+               }
+               if (ret == 0)
+                       return -ENODATA;
+       }
+
        switch (psp) {
        case POWER_SUPPLY_PROP_PRESENT:
        case POWER_SUPPLY_PROP_HEALTH:
diff --git a/drivers/power/supply/sbs-manager.c b/drivers/power/supply/sbs-manager.c
new file mode 100644 (file)
index 0000000..ccb4217
--- /dev/null
@@ -0,0 +1,445 @@
+/*
+ * Driver for SBS compliant Smart Battery System Managers
+ *
+ * The device communicates via i2c at address 0x0a and multiplexes access to up
+ * to four smart batteries at address 0x0b.
+ *
+ * Via sysfs interface the online state and charge type are presented.
+ *
+ * Datasheet SBSM:    http://sbs-forum.org/specs/sbsm100b.pdf
+ * Datasheet LTC1760: http://cds.linear.com/docs/en/datasheet/1760fb.pdf
+ *
+ * Karl-Heinz Schneider <karl-heinz@schneider-inet.de>
+ *
+ * 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 <linux/gpio.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/i2c-mux.h>
+#include <linux/power_supply.h>
+#include <linux/property.h>
+
+#define SBSM_MAX_BATS  4
+#define SBSM_RETRY_CNT 3
+
+/* registers addresses */
+#define SBSM_CMD_BATSYSSTATE     0x01
+#define SBSM_CMD_BATSYSSTATECONT 0x02
+#define SBSM_CMD_BATSYSINFO      0x04
+#define SBSM_CMD_LTC             0x3c
+
+#define SBSM_MASK_BAT_SUPPORTED  GENMASK(3, 0)
+#define SBSM_MASK_CHARGE_BAT     GENMASK(7, 4)
+#define SBSM_BIT_AC_PRESENT      BIT(0)
+#define SBSM_BIT_TURBO           BIT(7)
+
+#define SBSM_SMB_BAT_OFFSET      11
+struct sbsm_data {
+       struct i2c_client *client;
+       struct i2c_mux_core *muxc;
+
+       struct power_supply *psy;
+
+       u8 cur_chan;          /* currently selected channel */
+       struct gpio_chip chip;
+       bool is_ltc1760;      /* special capabilities */
+
+       unsigned int supported_bats;
+       unsigned int last_state;
+       unsigned int last_state_cont;
+};
+
+static enum power_supply_property sbsm_props[] = {
+       POWER_SUPPLY_PROP_ONLINE,
+       POWER_SUPPLY_PROP_CHARGE_TYPE,
+};
+
+static int sbsm_read_word(struct i2c_client *client, u8 address)
+{
+       int reg, retries;
+
+       for (retries = SBSM_RETRY_CNT; retries > 0; retries--) {
+               reg = i2c_smbus_read_word_data(client, address);
+               if (reg >= 0)
+                       break;
+       }
+
+       if (reg < 0) {
+               dev_err(&client->dev, "failed to read register 0x%02x\n",
+                       address);
+       }
+
+       return reg;
+}
+
+static int sbsm_write_word(struct i2c_client *client, u8 address, u16 word)
+{
+       int ret, retries;
+
+       for (retries = SBSM_RETRY_CNT; retries > 0; retries--) {
+               ret = i2c_smbus_write_word_data(client, address, word);
+               if (ret >= 0)
+                       break;
+       }
+       if (ret < 0)
+               dev_err(&client->dev, "failed to write to register 0x%02x\n",
+                       address);
+
+       return ret;
+}
+
+static int sbsm_get_property(struct power_supply *psy,
+                            enum power_supply_property psp,
+                            union power_supply_propval *val)
+{
+       struct sbsm_data *data = power_supply_get_drvdata(psy);
+       int regval = 0;
+
+       switch (psp) {
+       case POWER_SUPPLY_PROP_ONLINE:
+               regval = sbsm_read_word(data->client, SBSM_CMD_BATSYSSTATECONT);
+               if (regval < 0)
+                       return regval;
+               val->intval = !!(regval & SBSM_BIT_AC_PRESENT);
+               break;
+
+       case POWER_SUPPLY_PROP_CHARGE_TYPE:
+               regval = sbsm_read_word(data->client, SBSM_CMD_BATSYSSTATE);
+               if (regval < 0)
+                       return regval;
+
+               if ((regval & SBSM_MASK_CHARGE_BAT) == 0) {
+                       val->intval = POWER_SUPPLY_CHARGE_TYPE_NONE;
+                       return 0;
+               }
+               val->intval = POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
+
+               if (data->is_ltc1760) {
+                       /* charge mode fast if turbo is active */
+                       regval = sbsm_read_word(data->client, SBSM_CMD_LTC);
+                       if (regval < 0)
+                               return regval;
+                       else if (regval & SBSM_BIT_TURBO)
+                               val->intval = POWER_SUPPLY_CHARGE_TYPE_FAST;
+               }
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int sbsm_prop_is_writeable(struct power_supply *psy,
+                                 enum power_supply_property psp)
+{
+       struct sbsm_data *data = power_supply_get_drvdata(psy);
+
+       return (psp == POWER_SUPPLY_PROP_CHARGE_TYPE) && data->is_ltc1760;
+}
+
+static int sbsm_set_property(struct power_supply *psy,
+                            enum power_supply_property psp,
+                            const union power_supply_propval *val)
+{
+       struct sbsm_data *data = power_supply_get_drvdata(psy);
+       int ret = -EINVAL;
+       u16 regval;
+
+       switch (psp) {
+       case POWER_SUPPLY_PROP_CHARGE_TYPE:
+               /* write 1 to TURBO if type fast is given */
+               if (!data->is_ltc1760)
+                       break;
+               regval = val->intval ==
+                        POWER_SUPPLY_CHARGE_TYPE_FAST ? SBSM_BIT_TURBO : 0;
+               ret = sbsm_write_word(data->client, SBSM_CMD_LTC, regval);
+               break;
+
+       default:
+               break;
+       }
+
+       return ret;
+}
+
+/*
+ * Switch to battery
+ * Parameter chan is directly the content of SMB_BAT* nibble
+ */
+static int sbsm_select(struct i2c_mux_core *muxc, u32 chan)
+{
+       struct sbsm_data *data = i2c_mux_priv(muxc);
+       struct device *dev = &data->client->dev;
+       int ret = 0;
+       u16 reg;
+
+       if (data->cur_chan == chan)
+               return ret;
+
+       /* chan goes from 1 ... 4 */
+       reg = 1 << BIT(SBSM_SMB_BAT_OFFSET + chan);
+       ret = sbsm_write_word(data->client, SBSM_CMD_BATSYSSTATE, reg);
+       if (ret)
+               dev_err(dev, "Failed to select channel %i\n", chan);
+       else
+               data->cur_chan = chan;
+
+       return ret;
+}
+
+static int sbsm_gpio_get_value(struct gpio_chip *gc, unsigned int off)
+{
+       struct sbsm_data *data = gpiochip_get_data(gc);
+       int ret;
+
+       ret = sbsm_read_word(data->client, SBSM_CMD_BATSYSSTATE);
+       if (ret < 0)
+               return ret;
+
+       return ret & BIT(off);
+}
+
+/*
+ * This needs to be defined or the GPIO lib fails to register the pin.
+ * But the 'gpio' is always an input.
+ */
+static int sbsm_gpio_direction_input(struct gpio_chip *gc, unsigned int off)
+{
+       return 0;
+}
+
+static int sbsm_do_alert(struct device *dev, void *d)
+{
+       struct i2c_client *client = i2c_verify_client(dev);
+       struct i2c_driver *driver;
+
+       if (!client || client->addr != 0x0b)
+               return 0;
+
+       device_lock(dev);
+       if (client->dev.driver) {
+               driver = to_i2c_driver(client->dev.driver);
+               if (driver->alert)
+                       driver->alert(client, I2C_PROTOCOL_SMBUS_ALERT, 0);
+               else
+                       dev_warn(&client->dev, "no driver alert()!\n");
+       } else {
+               dev_dbg(&client->dev, "alert with no driver\n");
+       }
+       device_unlock(dev);
+
+       return -EBUSY;
+}
+
+static void sbsm_alert(struct i2c_client *client, enum i2c_alert_protocol prot,
+                      unsigned int d)
+{
+       struct sbsm_data *sbsm = i2c_get_clientdata(client);
+
+       int ret, i, irq_bat = 0, state = 0;
+
+       ret = sbsm_read_word(sbsm->client, SBSM_CMD_BATSYSSTATE);
+       if (ret >= 0) {
+               irq_bat = ret ^ sbsm->last_state;
+               sbsm->last_state = ret;
+               state = ret;
+       }
+
+       ret = sbsm_read_word(sbsm->client, SBSM_CMD_BATSYSSTATECONT);
+       if ((ret >= 0) &&
+           ((ret ^ sbsm->last_state_cont) & SBSM_BIT_AC_PRESENT)) {
+               irq_bat |= sbsm->supported_bats & state;
+               power_supply_changed(sbsm->psy);
+       }
+       sbsm->last_state_cont = ret;
+
+       for (i = 0; i < SBSM_MAX_BATS; i++) {
+               if (irq_bat & BIT(i)) {
+                       device_for_each_child(&sbsm->muxc->adapter[i]->dev,
+                                             NULL, sbsm_do_alert);
+               }
+       }
+}
+
+static int sbsm_gpio_setup(struct sbsm_data *data)
+{
+       struct gpio_chip *gc = &data->chip;
+       struct i2c_client *client = data->client;
+       struct device *dev = &client->dev;
+       int ret;
+
+       if (!device_property_present(dev, "gpio-controller"))
+               return 0;
+
+       ret  = sbsm_read_word(client, SBSM_CMD_BATSYSSTATE);
+       if (ret < 0)
+               return ret;
+       data->last_state = ret;
+
+       ret  = sbsm_read_word(client, SBSM_CMD_BATSYSSTATECONT);
+       if (ret < 0)
+               return ret;
+       data->last_state_cont = ret;
+
+       gc->get = sbsm_gpio_get_value;
+       gc->direction_input  = sbsm_gpio_direction_input;
+       gc->can_sleep = true;
+       gc->base = -1;
+       gc->ngpio = SBSM_MAX_BATS;
+       gc->label = client->name;
+       gc->parent = dev;
+       gc->owner = THIS_MODULE;
+
+       ret = devm_gpiochip_add_data(dev, gc, data);
+       if (ret) {
+               dev_err(dev, "devm_gpiochip_add_data failed: %d\n", ret);
+               return ret;
+       }
+
+       return ret;
+}
+
+static const struct power_supply_desc sbsm_default_psy_desc = {
+       .type = POWER_SUPPLY_TYPE_MAINS,
+       .properties = sbsm_props,
+       .num_properties = ARRAY_SIZE(sbsm_props),
+       .get_property = &sbsm_get_property,
+       .set_property = &sbsm_set_property,
+       .property_is_writeable = &sbsm_prop_is_writeable,
+};
+
+static int sbsm_probe(struct i2c_client *client,
+                     const struct i2c_device_id *id)
+{
+       struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
+       struct sbsm_data *data;
+       struct device *dev = &client->dev;
+       struct power_supply_desc *psy_desc;
+       struct power_supply_config psy_cfg = {};
+       int ret = 0, i;
+
+       /* Device listens only at address 0x0a */
+       if (client->addr != 0x0a)
+               return -EINVAL;
+
+       if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA))
+               return -EPFNOSUPPORT;
+
+       data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
+
+       i2c_set_clientdata(client, data);
+
+       data->client = client;
+       data->is_ltc1760 = !!strstr(id->name, "ltc1760");
+
+       ret  = sbsm_read_word(client, SBSM_CMD_BATSYSINFO);
+       if (ret < 0)
+               return ret;
+       data->supported_bats = ret & SBSM_MASK_BAT_SUPPORTED;
+       data->muxc = i2c_mux_alloc(adapter, dev, SBSM_MAX_BATS, 0,
+                                  I2C_MUX_LOCKED, &sbsm_select, NULL);
+       if (!data->muxc) {
+               dev_err(dev, "failed to alloc i2c mux\n");
+               ret = -ENOMEM;
+               goto err_mux_alloc;
+       }
+       data->muxc->priv = data;
+
+       /* register muxed i2c channels. One for each supported battery */
+       for (i = 0; i < SBSM_MAX_BATS; ++i) {
+               if (data->supported_bats & BIT(i)) {
+                       ret = i2c_mux_add_adapter(data->muxc, 0, i + 1, 0);
+                       if (ret)
+                               break;
+               }
+       }
+       if (ret) {
+               dev_err(dev, "failed to register i2c mux channel %d\n", i + 1);
+               goto err_mux_register;
+       }
+
+       psy_desc = devm_kmemdup(dev, &sbsm_default_psy_desc,
+                               sizeof(struct power_supply_desc),
+                               GFP_KERNEL);
+       if (!psy_desc) {
+               ret = -ENOMEM;
+               goto err_psy;
+       }
+
+       psy_desc->name = devm_kasprintf(dev, GFP_KERNEL, "sbsm-%s",
+                                       dev_name(&client->dev));
+       if (!psy_desc->name) {
+               ret = -ENOMEM;
+               goto err_psy;
+       }
+       ret = sbsm_gpio_setup(data);
+       if (ret < 0)
+               goto err_psy;
+
+       psy_cfg.drv_data = data;
+       psy_cfg.of_node = dev->of_node;
+       data->psy = devm_power_supply_register(dev, psy_desc, &psy_cfg);
+       if (IS_ERR(data->psy)) {
+               ret = PTR_ERR(data->psy);
+               dev_err(dev, "failed to register power supply %s\n",
+                       psy_desc->name);
+               goto err_psy;
+       }
+
+       return 0;
+
+err_psy:
+err_mux_register:
+       i2c_mux_del_adapters(data->muxc);
+
+err_mux_alloc:
+       return ret;
+}
+
+static int sbsm_remove(struct i2c_client *client)
+{
+       struct sbsm_data *data = i2c_get_clientdata(client);
+
+       i2c_mux_del_adapters(data->muxc);
+       return 0;
+}
+
+static const struct i2c_device_id sbsm_ids[] = {
+       { "sbs-manager", 0 },
+       { "ltc1760",     0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, sbsm_ids);
+
+#ifdef CONFIG_OF
+static const struct of_device_id sbsm_dt_ids[] = {
+       { .compatible = "sbs,sbs-manager" },
+       { .compatible = "lltc,ltc1760" },
+       { }
+};
+MODULE_DEVICE_TABLE(of, sbsm_dt_ids);
+#endif
+
+static struct i2c_driver sbsm_driver = {
+       .driver = {
+               .name = "sbsm",
+               .of_match_table = of_match_ptr(sbsm_dt_ids),
+       },
+       .probe          = sbsm_probe,
+       .remove         = sbsm_remove,
+       .alert          = sbsm_alert,
+       .id_table       = sbsm_ids
+};
+module_i2c_driver(sbsm_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Karl-Heinz Schneider <karl-heinz@schneider-inet.de>");
+MODULE_DESCRIPTION("SBSM Smart Battery System Manager");
index 6d23665..7447d85 100644 (file)
@@ -29,6 +29,7 @@ struct gpio_descs {
 #define GPIOD_FLAGS_BIT_DIR_SET                BIT(0)
 #define GPIOD_FLAGS_BIT_DIR_OUT                BIT(1)
 #define GPIOD_FLAGS_BIT_DIR_VAL                BIT(2)
+#define GPIOD_FLAGS_BIT_OPEN_DRAIN     BIT(3)
 
 /**
  * Optional flags that can be passed to one of gpiod_* to configure direction
@@ -40,6 +41,11 @@ enum gpiod_flags {
        GPIOD_OUT_LOW   = GPIOD_FLAGS_BIT_DIR_SET | GPIOD_FLAGS_BIT_DIR_OUT,
        GPIOD_OUT_HIGH  = GPIOD_FLAGS_BIT_DIR_SET | GPIOD_FLAGS_BIT_DIR_OUT |
                          GPIOD_FLAGS_BIT_DIR_VAL,
+       GPIOD_OUT_LOW_OPEN_DRAIN = GPIOD_FLAGS_BIT_DIR_SET |
+                         GPIOD_FLAGS_BIT_DIR_OUT | GPIOD_FLAGS_BIT_OPEN_DRAIN,
+       GPIOD_OUT_HIGH_OPEN_DRAIN = GPIOD_FLAGS_BIT_DIR_SET |
+                         GPIOD_FLAGS_BIT_DIR_OUT | GPIOD_FLAGS_BIT_DIR_VAL |
+                         GPIOD_FLAGS_BIT_OPEN_DRAIN,
 };
 
 #ifdef CONFIG_GPIOLIB
index c1bcb1f..352c142 100644 (file)
@@ -12,8 +12,6 @@
 
 /**
  * struct i2c_gpio_platform_data - Platform-dependent data for i2c-gpio
- * @sda_pin: GPIO pin ID to use for SDA
- * @scl_pin: GPIO pin ID to use for SCL
  * @udelay: signal toggle delay. SCL frequency is (500 / udelay) kHz
  * @timeout: clock stretching timeout in jiffies. If the slave keeps
  *     SCL low for longer than this, the transfer will time out.
@@ -26,8 +24,6 @@
  * @scl_is_output_only: SCL output drivers cannot be turned off.
  */
 struct i2c_gpio_platform_data {
-       unsigned int    sda_pin;
-       unsigned int    scl_pin;
        int             udelay;
        int             timeout;
        unsigned int    sda_is_open_drain:1;
index a138502..fb0e040 100644 (file)
@@ -42,7 +42,6 @@
  * properly set.
  */
 struct i2c_smbus_alert_setup {
-       unsigned int            alert_edge_triggered:1;
        int                     irq;
 };
 
@@ -50,4 +49,13 @@ struct i2c_client *i2c_setup_smbus_alert(struct i2c_adapter *adapter,
                                         struct i2c_smbus_alert_setup *setup);
 int i2c_handle_smbus_alert(struct i2c_client *ara);
 
+#if IS_ENABLED(CONFIG_I2C_SMBUS) && IS_ENABLED(CONFIG_OF)
+int of_i2c_setup_smbus_alert(struct i2c_adapter *adap);
+#else
+static inline int of_i2c_setup_smbus_alert(struct i2c_adapter *adap)
+{
+       return 0;
+}
+#endif
+
 #endif /* _LINUX_I2C_SMBUS_H */
index d501d39..0f77440 100644 (file)
@@ -304,6 +304,7 @@ static inline bool i2c_detect_slave_mode(struct device *dev) { return false; }
  * @type: chip type, to initialize i2c_client.name
  * @flags: to initialize i2c_client.flags
  * @addr: stored in i2c_client.addr
+ * @dev_name: Overrides the default <busnr>-<addr> dev_name if set
  * @platform_data: stored in i2c_client.dev.platform_data
  * @archdata: copied into i2c_client.dev.archdata
  * @of_node: pointer to OpenFirmware device node
@@ -328,6 +329,7 @@ struct i2c_board_info {
        char            type[I2C_NAME_SIZE];
        unsigned short  flags;
        unsigned short  addr;
+       const char      *dev_name;
        void            *platform_data;
        struct dev_archdata     *archdata;
        struct device_node *of_node;
diff --git a/include/linux/platform_data/i2c-nuc900.h b/include/linux/platform_data/i2c-nuc900.h
deleted file mode 100644 (file)
index 2303627..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef __ASM_ARCH_NUC900_I2C_H
-#define __ASM_ARCH_NUC900_I2C_H
-
-struct nuc900_platform_i2c {
-       int             bus_num;
-       unsigned long   bus_freq;
-};
-
-#endif /* __ASM_ARCH_NUC900_I2C_H */