Merge tag 'gpio-v3.12-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw...
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 7 Sep 2013 17:53:00 +0000 (10:53 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 7 Sep 2013 17:53:00 +0000 (10:53 -0700)
Pull GPIO updates from Linus Walleij:
 "This is the bulk of GPIO changes for the v3.12 series:

   - A new driver for the TZ1090 PDC which is used on the metag
     architecture.

   - A new driver for the Kontron ETX or COMexpress GPIO block.  This is
     found on some ETX x86 devices.

   - A new driver for the Fintek Super-I/O chips, used on some x86
     boards.

   - Added device tree probing on a few select GPIO blocks.

   - Drop the Exynos support from the Samsung GPIO driver.

     The Samsung maintainers have moved over to use the modernized pin
     control driver to provide GPIO for the modern platforms instead.

   - The usual bunch of non-critical fixes and cleanups"

* tag 'gpio-v3.12-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio: (36 commits)
  gpio: return -ENOTSUPP if debounce cannot be set
  gpio: improve error path in gpiolib
  gpio: add GPIO support for F71882FG and F71889F
  of: add vendor prefix for Microchip Technology Inc
  gpio: mcp23s08: rename the device tree property
  gpio: samsung: Drop support for Exynos SoCs
  gpio: pcf857x: Remove pdata argument to pcf857x_irq_domain_init()
  gpio: pcf857x: Sort headers alphabetically
  gpio: max7301: Reverting "Do not force SPI speed when using OF Platform"
  gpio: Fix bit masking in Kontron PLD GPIO driver
  gpio: pca953x: fix gpio input on gpio offsets >= 8
  drivers/gpio: simplify use of devm_ioremap_resource
  drivers/gpio/gpio-omap.c: convert comma to semicolon
  gpio-lynxpoint: Fix warning about unbalanced pm_runtime_enable
  gpio: Fix platform driver name in Kontron PLD GPIO driver
  gpio: adnp: Fix segfault if request_threaded_irq fails
  gpio: msm: Staticize local variable 'msm_gpio'
  gpio: gpiolib-of.c: make error message more meaningful by adding the node name and index
  gpio: use dev_get_platdata()
  gpio/mxc: add chained_irq_enter/exit() to mx2_gpio_irq_handler
  ...

58 files changed:
Documentation/devicetree/bindings/gpio/gpio-mcp23s08.txt
Documentation/devicetree/bindings/gpio/gpio-palmas.txt [new file with mode: 0644]
Documentation/devicetree/bindings/gpio/gpio-tz1090-pdc.txt [new file with mode: 0644]
Documentation/devicetree/bindings/gpio/gpio-tz1090.txt [new file with mode: 0644]
Documentation/devicetree/bindings/gpio/mrvl-gpio.txt
Documentation/devicetree/bindings/gpio/renesas,gpio-rcar.txt
Documentation/devicetree/bindings/vendor-prefixes.txt
MAINTAINERS
drivers/gpio/Kconfig
drivers/gpio/Makefile
drivers/gpio/gpio-74x164.c
drivers/gpio/gpio-adnp.c
drivers/gpio/gpio-adp5520.c
drivers/gpio/gpio-adp5588.c
drivers/gpio/gpio-arizona.c
drivers/gpio/gpio-da9052.c
drivers/gpio/gpio-da9055.c
drivers/gpio/gpio-em.c
drivers/gpio/gpio-f7188x.c [new file with mode: 0644]
drivers/gpio/gpio-ich.c
drivers/gpio/gpio-janz-ttl.c
drivers/gpio/gpio-kempld.c [new file with mode: 0644]
drivers/gpio/gpio-lynxpoint.c
drivers/gpio/gpio-max7301.c
drivers/gpio/gpio-max730x.c
drivers/gpio/gpio-max732x.c
drivers/gpio/gpio-mc33880.c
drivers/gpio/gpio-mcp23s08.c
drivers/gpio/gpio-msic.c
drivers/gpio/gpio-msm-v2.c
drivers/gpio/gpio-mvebu.c
drivers/gpio/gpio-mxc.c
drivers/gpio/gpio-omap.c
drivers/gpio/gpio-palmas.c
drivers/gpio/gpio-pca953x.c
drivers/gpio/gpio-pcf857x.c
drivers/gpio/gpio-pl061.c
drivers/gpio/gpio-pxa.c
drivers/gpio/gpio-rcar.c
drivers/gpio/gpio-rdc321x.c
drivers/gpio/gpio-samsung.c
drivers/gpio/gpio-spear-spics.c
drivers/gpio/gpio-sta2x11.c
drivers/gpio/gpio-sx150x.c
drivers/gpio/gpio-timberdale.c
drivers/gpio/gpio-tps65912.c
drivers/gpio/gpio-ts5500.c
drivers/gpio/gpio-twl4030.c
drivers/gpio/gpio-twl6040.c
drivers/gpio/gpio-tz1090-pdc.c [new file with mode: 0644]
drivers/gpio/gpio-tz1090.c [new file with mode: 0644]
drivers/gpio/gpio-ucb1400.c
drivers/gpio/gpio-wm831x.c
drivers/gpio/gpio-wm8350.c
drivers/gpio/gpio-wm8994.c
drivers/gpio/gpiolib-of.c
drivers/gpio/gpiolib.c
include/linux/platform_data/gpio-em.h

index 629d0ef17308a73c4f06e108218de8b7e7b4cb16..daa30174bcc13941e7454772dc2827c377a02a4b 100644 (file)
@@ -3,10 +3,17 @@ Microchip MCP2308/MCP23S08/MCP23017/MCP23S17 driver for
 
 Required properties:
 - compatible : Should be
-    - "mcp,mcp23s08" for  8 GPIO SPI version
-    - "mcp,mcp23s17" for 16 GPIO SPI version
-    - "mcp,mcp23008" for  8 GPIO I2C version or
-    - "mcp,mcp23017" for 16 GPIO I2C version of the chip
+    - "mcp,mcp23s08" (DEPRECATED) for  8 GPIO SPI version
+    - "mcp,mcp23s17" (DEPRECATED) for 16 GPIO SPI version
+    - "mcp,mcp23008" (DEPRECATED) for  8 GPIO I2C version or
+    - "mcp,mcp23017" (DEPRECATED) for 16 GPIO I2C version of the chip
+
+    - "microchip,mcp23s08" for  8 GPIO SPI version
+    - "microchip,mcp23s17" for 16 GPIO SPI version
+    - "microchip,mcp23008" for  8 GPIO I2C version or
+    - "microchip,mcp23017" for 16 GPIO I2C version of the chip
+    NOTE: Do not use the old mcp prefix any more. It is deprecated and will be
+    removed.
 - #gpio-cells : Should be two.
   - first cell is the pin number
   - second cell is used to specify flags. Flags are currently unused.
@@ -15,10 +22,11 @@ Required properties:
         SPI uses this to specify the chipselect line which the chip is
         connected to. The driver and the SPI variant of the chip support
         multiple chips on the same chipselect. Have a look at
-        mcp,spi-present-mask below.
+        microchip,spi-present-mask below.
 
 Required device specific properties (only for SPI chips):
-- mcp,spi-present-mask : This is a present flag, that makes only sense for SPI
+- mcp,spi-present-mask (DEPRECATED)
+- microchip,spi-present-mask : This is a present flag, that makes only sense for SPI
         chips - as the name suggests. Multiple SPI chips can share the same
         SPI chipselect. Set a bit in bit0-7 in this mask to 1 if there is a
         chip connected with the corresponding spi address set. For example if
@@ -26,11 +34,13 @@ Required device specific properties (only for SPI chips):
         which is 0x08. mcp23s08 chip variant only supports bits 0-3. It is not
         possible to mix mcp23s08 and mcp23s17 on the same chipselect. Set at
         least one bit to 1 for SPI chips.
+    NOTE: Do not use the old mcp prefix any more. It is deprecated and will be
+    removed.
 - spi-max-frequency = The maximum frequency this chip is able to handle
 
 Example I2C:
 gpiom1: gpio@20 {
-        compatible = "mcp,mcp23017";
+        compatible = "microchip,mcp23017";
         gpio-controller;
         #gpio-cells = <2>;
         reg = <0x20>;
@@ -38,7 +48,7 @@ gpiom1: gpio@20 {
 
 Example SPI:
 gpiom1: gpio@0 {
-        compatible = "mcp,mcp23s17";
+        compatible = "microchip,mcp23s17";
         gpio-controller;
         #gpio-cells = <2>;
         spi-present-mask = <0x01>;
diff --git a/Documentation/devicetree/bindings/gpio/gpio-palmas.txt b/Documentation/devicetree/bindings/gpio/gpio-palmas.txt
new file mode 100644 (file)
index 0000000..08b5b52
--- /dev/null
@@ -0,0 +1,27 @@
+Palmas GPIO controller bindings
+
+Required properties:
+- compatible:
+  - "ti,palams-gpio" for palma series of the GPIO controller
+  - "ti,tps80036-gpio" for Palma series device TPS80036.
+  - "ti,tps65913-gpio" for palma series device TPS65913.
+  - "ti,tps65914-gpio" for palma series device TPS65914.
+- #gpio-cells : Should be two.
+  - first cell is the gpio pin number
+  - second cell is used to specify the gpio polarity:
+      0 = active high
+      1 = active low
+- gpio-controller : Marks the device node as a GPIO controller.
+
+Note: This gpio node will be sub node of palmas node.
+
+Example:
+       palmas: tps65913@58 {
+               :::::::::::
+               palmas_gpio: palmas_gpio {
+                       compatible = "ti,palmas-gpio";
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+               :::::::::::
+       };
diff --git a/Documentation/devicetree/bindings/gpio/gpio-tz1090-pdc.txt b/Documentation/devicetree/bindings/gpio/gpio-tz1090-pdc.txt
new file mode 100644 (file)
index 0000000..1fd98ff
--- /dev/null
@@ -0,0 +1,45 @@
+ImgTec TZ1090 PDC GPIO Controller
+
+Required properties:
+- compatible: Compatible property value should be "img,tz1090-pdc-gpio".
+
+- reg: Physical base address of the controller and length of memory mapped
+  region. This starts at and cover the SOC_GPIO_CONTROL registers.
+
+- gpio-controller: Specifies that the node is a gpio controller.
+
+- #gpio-cells: Should be 2. The syntax of the gpio specifier used by client
+  nodes should have the following values.
+     <[phandle of the gpio controller node]
+      [PDC gpio number]
+      [gpio flags]>
+
+  Values for gpio specifier:
+  - GPIO number: a value in the range 0 to 6.
+  - GPIO flags: bit field of flags, as defined in <dt-bindings/gpio/gpio.h>.
+    Only the following flags are supported:
+      GPIO_ACTIVE_HIGH
+      GPIO_ACTIVE_LOW
+
+Optional properties:
+- gpio-ranges: Mapping to pin controller pins (as described in
+  Documentation/devicetree/bindings/gpio/gpio.txt)
+
+- interrupts: Individual syswake interrupts (other GPIOs cannot interrupt)
+
+
+Example:
+
+       pdc_gpios: gpio-controller@02006500 {
+               gpio-controller;
+               #gpio-cells = <2>;
+
+               compatible = "img,tz1090-pdc-gpio";
+               reg = <0x02006500 0x100>;
+
+               interrupt-parent = <&pdc>;
+               interrupts =    <8  IRQ_TYPE_NONE>,     /* Syswake 0 */
+                               <9  IRQ_TYPE_NONE>,     /* Syswake 1 */
+                               <10 IRQ_TYPE_NONE>;     /* Syswake 2 */
+               gpio-ranges = <&pdc_pinctrl 0 0 7>;
+       };
diff --git a/Documentation/devicetree/bindings/gpio/gpio-tz1090.txt b/Documentation/devicetree/bindings/gpio/gpio-tz1090.txt
new file mode 100644 (file)
index 0000000..174cdf3
--- /dev/null
@@ -0,0 +1,88 @@
+ImgTec TZ1090 GPIO Controller
+
+Required properties:
+- compatible: Compatible property value should be "img,tz1090-gpio".
+
+- reg: Physical base address of the controller and length of memory mapped
+  region.
+
+- #address-cells: Should be 1 (for bank subnodes)
+
+- #size-cells: Should be 0 (for bank subnodes)
+
+- Each bank of GPIOs should have a subnode to represent it.
+
+  Bank subnode required properties:
+  - reg: Index of bank in the range 0 to 2.
+
+  - gpio-controller: Specifies that the node is a gpio controller.
+
+  - #gpio-cells: Should be 2. The syntax of the gpio specifier used by client
+    nodes should have the following values.
+       <[phandle of the gpio controller node]
+        [gpio number within the gpio bank]
+        [gpio flags]>
+
+    Values for gpio specifier:
+    - GPIO number: a value in the range 0 to 29.
+    - GPIO flags: bit field of flags, as defined in <dt-bindings/gpio/gpio.h>.
+      Only the following flags are supported:
+        GPIO_ACTIVE_HIGH
+        GPIO_ACTIVE_LOW
+
+  Bank subnode optional properties:
+  - gpio-ranges: Mapping to pin controller pins (as described in
+    Documentation/devicetree/bindings/gpio/gpio.txt)
+
+  - interrupts: Interrupt for the entire bank
+
+  - interrupt-controller: Specifies that the node is an interrupt controller
+
+  - #interrupt-cells: Should be 2. The syntax of the interrupt specifier used by
+    client nodes should have the following values.
+       <[phandle of the interurupt controller]
+        [gpio number within the gpio bank]
+        [irq flags]>
+
+    Values for irq specifier:
+    - GPIO number: a value in the range 0 to 29
+    - IRQ flags: value to describe edge and level triggering, as defined in
+      <dt-bindings/interrupt-controller/irq.h>. Only the following flags are
+      supported:
+        IRQ_TYPE_EDGE_RISING
+        IRQ_TYPE_EDGE_FALLING
+        IRQ_TYPE_EDGE_BOTH
+        IRQ_TYPE_LEVEL_HIGH
+        IRQ_TYPE_LEVEL_LOW
+
+
+
+Example:
+
+       gpios: gpio-controller@02005800 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               compatible = "img,tz1090-gpio";
+               reg = <0x02005800 0x90>;
+
+               /* bank 0 with an interrupt */
+               gpios0: bank@0 {
+                       #gpio-cells = <2>;
+                       #interrupt-cells = <2>;
+                       reg = <0>;
+                       interrupts = <13 IRQ_TYPE_LEVEL_HIGH>;
+                       gpio-controller;
+                       gpio-ranges = <&pinctrl 0 0 30>;
+                       interrupt-controller;
+               };
+
+               /* bank 2 without interrupt */
+               gpios2: bank@2 {
+                       #gpio-cells = <2>;
+                       reg = <2>;
+                       gpio-controller;
+                       gpio-ranges = <&pinctrl 0 60 30>;
+               };
+       };
+
+
index 9b3f1d4a88d69fa931ca819c4776727435512104..66416261e14df5a0b621a52ead96e4ef52482472 100644 (file)
@@ -10,8 +10,9 @@ Required properties:
   There're three gpio interrupts in arch-pxa, and they're gpio0,
   gpio1 and gpio_mux. There're only one gpio interrupt in arch-mmp,
   gpio_mux.
-- interrupt-name : Should be the name of irq resource. Each interrupt
-  binds its interrupt-name.
+- interrupt-names : Should be the names of irq resources. Each interrupt
+  uses its own interrupt name, so there should be as many interrupt names
+  as referenced interrups.
 - interrupt-controller : Identifies the node as an interrupt controller.
 - #interrupt-cells: Specifies the number of cells needed to encode an
   interrupt source.
@@ -24,7 +25,7 @@ Example:
                compatible = "marvell,mmp-gpio";
                reg = <0xd4019000 0x1000>;
                interrupts = <49>;
-               interrupt-name = "gpio_mux";
+               interrupt-names = "gpio_mux";
                gpio-controller;
                #gpio-cells = <1>;
                interrupt-controller;
index cb3dc7bcd8e69f975279e2d91d8d87101f909672..8655df9440d506986225dad0594d045054a96728 100644 (file)
@@ -23,6 +23,10 @@ Required Properties:
 Please refer to gpio.txt in this directory for details of gpio-ranges property
 and the common GPIO bindings used by client devices.
 
+The GPIO controller also acts as an interrupt controller. It uses the default
+two cells specifier as described in Documentation/devicetree/bindings/
+interrupt-controller/interrupts.txt.
+
 Example: R8A7779 (R-Car H1) GPIO controller nodes
 
        gpio0: gpio@ffc40000 {
@@ -33,6 +37,8 @@ Example: R8A7779 (R-Car H1) GPIO controller nodes
                #gpio-cells = <2>;
                gpio-controller;
                gpio-ranges = <&pfc 0 0 32>;
+               interrupt-controller;
+               #interrupt-cells = <2>;
        };
        ...
        gpio6: gpio@ffc46000 {
@@ -43,4 +49,6 @@ Example: R8A7779 (R-Car H1) GPIO controller nodes
                #gpio-cells = <2>;
                gpio-controller;
                gpio-ranges = <&pfc 0 192 9>;
+               interrupt-controller;
+               #interrupt-cells = <2>;
        };
index b571560ed5f956f05da7edf425b2c3529023cda1..2956800f0240c8b3e48c9427151220ef2fc39fc1 100644 (file)
@@ -38,6 +38,7 @@ linux Linux-specific binding
 lsi    LSI Corp. (LSI Logic)
 marvell        Marvell Technology Group Ltd.
 maxim  Maxim Integrated Products
+microchip      Microchip Technology Inc.
 mosaixtech     Mosaix Technologies, Inc.
 national       National Semiconductor
 nintendo       Nintendo
index e775ecaf5d1f49a1c97ebe333869cff9463c07a5..b6b29c38b6b67d5c950188da793f35696e00e7be 100644 (file)
@@ -1320,7 +1320,6 @@ L:        linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
 F:     arch/arm/mach-vt8500/
 F:     drivers/clocksource/vt8500_timer.c
-F:     drivers/gpio/gpio-vt8500.c
 F:     drivers/i2c/busses/i2c-wmt.c
 F:     drivers/mmc/host/wmt-sdmmc.c
 F:     drivers/pwm/pwm-vt8500.c
index b2450ba14138ba241b691c462865a8dbed157cf0..349b16160ac9b8b4cd2943751c6d8478d5cb0962 100644 (file)
@@ -146,6 +146,16 @@ config GPIO_MM_LANTIQ
          (EBU) found on Lantiq SoCs. The gpios are output only as they are
          created by attaching a 16bit latch to the bus.
 
+config GPIO_F7188X
+       tristate "F71882FG and F71889F GPIO support"
+       depends on X86
+       help
+         This option enables support for GPIOs found on Fintek Super-I/O
+         chips F71882FG and F71889F.
+
+         To compile this driver as a module, choose M here: the module will
+         be called f7188x-gpio.
+
 config GPIO_MPC5200
        def_bool y
        depends on PPC_MPC52xx
@@ -242,6 +252,21 @@ config GPIO_TS5500
          blocks of the TS-5500: DIO1, DIO2 and the LCD port, and the TS-5600
          LCD port.
 
+config GPIO_TZ1090
+       bool "Toumaz Xenif TZ1090 GPIO support"
+       depends on SOC_TZ1090
+       select GENERIC_IRQ_CHIP
+       default y
+       help
+         Say yes here to support Toumaz Xenif TZ1090 GPIOs.
+
+config GPIO_TZ1090_PDC
+       bool "Toumaz Xenif TZ1090 PDC GPIO support"
+       depends on SOC_TZ1090
+       default y
+       help
+         Say yes here to support Toumaz Xenif TZ1090 PDC GPIOs.
+
 config GPIO_XILINX
        bool "Xilinx GPIO support"
        depends on PPC_OF || MICROBLAZE || ARCH_ZYNQ
@@ -676,6 +701,18 @@ config GPIO_UCB1400
          This enables support for the Philips UCB1400 GPIO pins.
          The UCB1400 is an AC97 audio codec.
 
+comment "LPC GPIO expanders:"
+
+config GPIO_KEMPLD
+       tristate "Kontron ETX / COMexpress GPIO"
+       depends on MFD_KEMPLD
+       help
+         This enables support for the PLD GPIO interface on some Kontron ETX
+         and COMexpress (ETXexpress) modules.
+
+         This driver can also be built as a module. If so, the module will be
+         called gpio-kempld.
+
 comment "MODULbus GPIO expanders:"
 
 config GPIO_JANZ_TTL
index ef3e983a2f1ead46b6e39d650de2c67b757883b7..97438bf8434a76aee67c06bb526044b38817f12f 100644 (file)
@@ -24,11 +24,13 @@ obj-$(CONFIG_GPIO_DA9055)   += gpio-da9055.o
 obj-$(CONFIG_ARCH_DAVINCI)     += gpio-davinci.o
 obj-$(CONFIG_GPIO_EM)          += gpio-em.o
 obj-$(CONFIG_GPIO_EP93XX)      += gpio-ep93xx.o
+obj-$(CONFIG_GPIO_F7188X)      += gpio-f7188x.o
 obj-$(CONFIG_GPIO_GE_FPGA)     += gpio-ge.o
 obj-$(CONFIG_GPIO_GRGPIO)      += gpio-grgpio.o
 obj-$(CONFIG_GPIO_ICH)         += gpio-ich.o
 obj-$(CONFIG_GPIO_IT8761E)     += gpio-it8761e.o
 obj-$(CONFIG_GPIO_JANZ_TTL)    += gpio-janz-ttl.o
+obj-$(CONFIG_GPIO_KEMPLD)      += gpio-kempld.o
 obj-$(CONFIG_ARCH_KS8695)      += gpio-ks8695.o
 obj-$(CONFIG_GPIO_LANGWELL)    += gpio-langwell.o
 obj-$(CONFIG_ARCH_LPC32XX)     += gpio-lpc32xx.o
@@ -79,6 +81,8 @@ obj-$(CONFIG_GPIO_TPS65912)   += gpio-tps65912.o
 obj-$(CONFIG_GPIO_TS5500)      += gpio-ts5500.o
 obj-$(CONFIG_GPIO_TWL4030)     += gpio-twl4030.o
 obj-$(CONFIG_GPIO_TWL6040)     += gpio-twl6040.o
+obj-$(CONFIG_GPIO_TZ1090)      += gpio-tz1090.o
+obj-$(CONFIG_GPIO_TZ1090_PDC)  += gpio-tz1090-pdc.o
 obj-$(CONFIG_GPIO_UCB1400)     += gpio-ucb1400.o
 obj-$(CONFIG_GPIO_VIPERBOARD)  += gpio-viperboard.o
 obj-$(CONFIG_GPIO_VR41XX)      += gpio-vr41xx.o
index 721607904d0a4837590f0a295e394c727a537f38..5d518d5db7a0ae4a084f3652cb2ac61067a3dbc6 100644 (file)
@@ -129,7 +129,7 @@ static int gen_74x164_probe(struct spi_device *spi)
        if (!chip)
                return -ENOMEM;
 
-       pdata = spi->dev.platform_data;
+       pdata = dev_get_platdata(&spi->dev);
        if (pdata && pdata->base)
                chip->gpio_chip.base = pdata->base;
        else
index e60567fc50736904741d0e1a8e70bb19ddf3c743..c0f3fc44ab0eca1957a1bbf192dca1bc6be04291 100644 (file)
@@ -490,15 +490,11 @@ static int adnp_irq_setup(struct adnp *adnp)
        if (err != 0) {
                dev_err(chip->dev, "can't request IRQ#%d: %d\n",
                        adnp->client->irq, err);
-               goto error;
+               return err;
        }
 
        chip->to_irq = adnp_gpio_to_irq;
        return 0;
-
-error:
-       irq_domain_remove(adnp->domain);
-       return err;
 }
 
 static void adnp_irq_teardown(struct adnp *adnp)
index f33f78dcadaad817ed331c40daa0447d126282a6..084337d5514d8d1c373413d4c66d1ec1aa317163 100644 (file)
@@ -89,7 +89,7 @@ static int adp5520_gpio_direction_output(struct gpio_chip *chip,
 
 static int adp5520_gpio_probe(struct platform_device *pdev)
 {
-       struct adp5520_gpio_platform_data *pdata = pdev->dev.platform_data;
+       struct adp5520_gpio_platform_data *pdata = dev_get_platdata(&pdev->dev);
        struct adp5520_gpio *dev;
        struct gpio_chip *gc;
        int ret, i, gpios;
index 2ba56987db04dded1c231d38315f124260e0e432..90fc4c99c024ee39605381c247236644e4c927b4 100644 (file)
@@ -276,7 +276,8 @@ static irqreturn_t adp5588_irq_handler(int irq, void *devid)
 static int adp5588_irq_setup(struct adp5588_gpio *dev)
 {
        struct i2c_client *client = dev->client;
-       struct adp5588_gpio_platform_data *pdata = client->dev.platform_data;
+       struct adp5588_gpio_platform_data *pdata =
+                       dev_get_platdata(&client->dev);
        unsigned gpio;
        int ret;
 
@@ -349,7 +350,8 @@ static void adp5588_irq_teardown(struct adp5588_gpio *dev)
 static int adp5588_gpio_probe(struct i2c_client *client,
                                        const struct i2c_device_id *id)
 {
-       struct adp5588_gpio_platform_data *pdata = client->dev.platform_data;
+       struct adp5588_gpio_platform_data *pdata =
+                       dev_get_platdata(&client->dev);
        struct adp5588_gpio *dev;
        struct gpio_chip *gc;
        int ret, i, revid;
@@ -440,7 +442,8 @@ err:
 
 static int adp5588_gpio_remove(struct i2c_client *client)
 {
-       struct adp5588_gpio_platform_data *pdata = client->dev.platform_data;
+       struct adp5588_gpio_platform_data *pdata =
+                       dev_get_platdata(&client->dev);
        struct adp5588_gpio *dev = i2c_get_clientdata(client);
        int ret;
 
index 0ea853f68db2cf63993f29ca8cfcadce1e8e0f2f..fa8b6a762761412a84901e7629b23270b66ac2ec 100644 (file)
@@ -97,7 +97,7 @@ static struct gpio_chip template_chip = {
 static int arizona_gpio_probe(struct platform_device *pdev)
 {
        struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
-       struct arizona_pdata *pdata = arizona->dev->platform_data;
+       struct arizona_pdata *pdata = dev_get_platdata(arizona->dev);
        struct arizona_gpio *arizona_gpio;
        int ret;
 
index 29b11e9b6a78600b2d14d61a178d5e1de3fdc2bc..9b77dc05d4ada6c6744040cf2cdfb5d76c3188a4 100644 (file)
@@ -216,7 +216,7 @@ static int da9052_gpio_probe(struct platform_device *pdev)
                return -ENOMEM;
 
        gpio->da9052 = dev_get_drvdata(pdev->dev.parent);
-       pdata = gpio->da9052->dev->platform_data;
+       pdata = dev_get_platdata(gpio->da9052->dev);
 
        gpio->gp = reference_gp;
        if (pdata && pdata->gpio_base)
index fd6dfe382f13c650170a4f0f20cf3ed6a612dba5..7ef0820032bd157a7adadc368cc521d0a7ff57aa 100644 (file)
@@ -150,7 +150,7 @@ static int da9055_gpio_probe(struct platform_device *pdev)
                return -ENOMEM;
 
        gpio->da9055 = dev_get_drvdata(pdev->dev.parent);
-       pdata = gpio->da9055->dev->platform_data;
+       pdata = dev_get_platdata(gpio->da9055->dev);
 
        gpio->gp = reference_gp;
        if (pdata && pdata->gpio_base)
index 5cba855638bf93b47e72c64ccd508f11db42f771..c6e1f086efe8455733c3f27080f301a1922ea6db 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/gpio.h>
 #include <linux/slab.h>
 #include <linux/module.h>
+#include <linux/pinctrl/consumer.h>
 #include <linux/platform_data/gpio-em.h>
 
 struct em_gio_priv {
@@ -216,6 +217,21 @@ static int em_gio_to_irq(struct gpio_chip *chip, unsigned offset)
        return irq_create_mapping(gpio_to_priv(chip)->irq_domain, offset);
 }
 
+static int em_gio_request(struct gpio_chip *chip, unsigned offset)
+{
+       return pinctrl_request_gpio(chip->base + offset);
+}
+
+static void em_gio_free(struct gpio_chip *chip, unsigned offset)
+{
+       pinctrl_free_gpio(chip->base + offset);
+
+       /* Set the GPIO as an input to ensure that the next GPIO request won't
+       * drive the GPIO pin as an output.
+       */
+       em_gio_direction_input(chip, offset);
+}
+
 static int em_gio_irq_domain_map(struct irq_domain *h, unsigned int virq,
                                 irq_hw_number_t hw)
 {
@@ -237,7 +253,7 @@ static struct irq_domain_ops em_gio_irq_domain_ops = {
 static int em_gio_probe(struct platform_device *pdev)
 {
        struct gpio_em_config pdata_dt;
-       struct gpio_em_config *pdata = pdev->dev.platform_data;
+       struct gpio_em_config *pdata = dev_get_platdata(&pdev->dev);
        struct em_gio_priv *p;
        struct resource *io[2], *irq[2];
        struct gpio_chip *gpio_chip;
@@ -308,6 +324,8 @@ static int em_gio_probe(struct platform_device *pdev)
        gpio_chip->direction_output = em_gio_direction_output;
        gpio_chip->set = em_gio_set;
        gpio_chip->to_irq = em_gio_to_irq;
+       gpio_chip->request = em_gio_request;
+       gpio_chip->free = em_gio_free;
        gpio_chip->label = name;
        gpio_chip->owner = THIS_MODULE;
        gpio_chip->base = pdata->gpio_base;
@@ -351,6 +369,13 @@ static int em_gio_probe(struct platform_device *pdev)
                dev_err(&pdev->dev, "failed to add GPIO controller\n");
                goto err1;
        }
+
+       if (pdata->pctl_name) {
+               ret = gpiochip_add_pin_range(gpio_chip, pdata->pctl_name, 0,
+                                            gpio_chip->base, gpio_chip->ngpio);
+               if (ret < 0)
+                       dev_warn(&pdev->dev, "failed to add pin range\n");
+       }
        return 0;
 
 err1:
diff --git a/drivers/gpio/gpio-f7188x.c b/drivers/gpio/gpio-f7188x.c
new file mode 100644 (file)
index 0000000..9cb8320
--- /dev/null
@@ -0,0 +1,469 @@
+/*
+ * GPIO driver for Fintek Super-I/O F71882 and F71889
+ *
+ * Copyright (C) 2010-2013 LaCie
+ *
+ * Author: Simon Guinot <simon.guinot@sequanux.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+
+#define DRVNAME "gpio-f7188x"
+
+/*
+ * Super-I/O registers
+ */
+#define SIO_LDSEL              0x07    /* Logical device select */
+#define SIO_DEVID              0x20    /* Device ID (2 bytes) */
+#define SIO_DEVREV             0x22    /* Device revision */
+#define SIO_MANID              0x23    /* Fintek ID (2 bytes) */
+
+#define SIO_LD_GPIO            0x06    /* GPIO logical device */
+#define SIO_UNLOCK_KEY         0x87    /* Key to enable Super-I/O */
+#define SIO_LOCK_KEY           0xAA    /* Key to disable Super-I/O */
+
+#define SIO_FINTEK_ID          0x1934  /* Manufacturer ID */
+#define SIO_F71882_ID          0x0541  /* F71882 chipset ID */
+#define SIO_F71889_ID          0x0909  /* F71889 chipset ID */
+
+enum chips { f71882fg, f71889f };
+
+static const char * const f7188x_names[] = {
+       "f71882fg",
+       "f71889f",
+};
+
+struct f7188x_sio {
+       int addr;
+       enum chips type;
+};
+
+struct f7188x_gpio_bank {
+       struct gpio_chip chip;
+       unsigned int regbase;
+       struct f7188x_gpio_data *data;
+};
+
+struct f7188x_gpio_data {
+       struct f7188x_sio *sio;
+       int nr_bank;
+       struct f7188x_gpio_bank *bank;
+};
+
+/*
+ * Super-I/O functions.
+ */
+
+static inline int superio_inb(int base, int reg)
+{
+       outb(reg, base);
+       return inb(base + 1);
+}
+
+static int superio_inw(int base, int reg)
+{
+       int val;
+
+       outb(reg++, base);
+       val = inb(base + 1) << 8;
+       outb(reg, base);
+       val |= inb(base + 1);
+
+       return val;
+}
+
+static inline void superio_outb(int base, int reg, int val)
+{
+       outb(reg, base);
+       outb(val, base + 1);
+}
+
+static inline int superio_enter(int base)
+{
+       /* Don't step on other drivers' I/O space by accident. */
+       if (!request_muxed_region(base, 2, DRVNAME)) {
+               pr_err(DRVNAME "I/O address 0x%04x already in use\n", base);
+               return -EBUSY;
+       }
+
+       /* According to the datasheet the key must be send twice. */
+       outb(SIO_UNLOCK_KEY, base);
+       outb(SIO_UNLOCK_KEY, base);
+
+       return 0;
+}
+
+static inline void superio_select(int base, int ld)
+{
+       outb(SIO_LDSEL, base);
+       outb(ld, base + 1);
+}
+
+static inline void superio_exit(int base)
+{
+       outb(SIO_LOCK_KEY, base);
+       release_region(base, 2);
+}
+
+/*
+ * GPIO chip.
+ */
+
+static int f7188x_gpio_direction_in(struct gpio_chip *chip, unsigned offset);
+static int f7188x_gpio_get(struct gpio_chip *chip, unsigned offset);
+static int f7188x_gpio_direction_out(struct gpio_chip *chip,
+                                    unsigned offset, int value);
+static void f7188x_gpio_set(struct gpio_chip *chip, unsigned offset, int value);
+
+#define F7188X_GPIO_BANK(_base, _ngpio, _regbase)                      \
+       {                                                               \
+               .chip = {                                               \
+                       .label            = DRVNAME,                    \
+                       .owner            = THIS_MODULE,                \
+                       .direction_input  = f7188x_gpio_direction_in,   \
+                       .get              = f7188x_gpio_get,            \
+                       .direction_output = f7188x_gpio_direction_out,  \
+                       .set              = f7188x_gpio_set,            \
+                       .base             = _base,                      \
+                       .ngpio            = _ngpio,                     \
+               },                                                      \
+               .regbase = _regbase,                                    \
+       }
+
+#define gpio_dir(base) (base + 0)
+#define gpio_data_out(base) (base + 1)
+#define gpio_data_in(base) (base + 2)
+/* Output mode register (0:open drain 1:push-pull). */
+#define gpio_out_mode(base) (base + 3)
+
+static struct f7188x_gpio_bank f71882_gpio_bank[] = {
+       F7188X_GPIO_BANK(0 , 8, 0xF0),
+       F7188X_GPIO_BANK(10, 8, 0xE0),
+       F7188X_GPIO_BANK(20, 8, 0xD0),
+       F7188X_GPIO_BANK(30, 4, 0xC0),
+       F7188X_GPIO_BANK(40, 4, 0xB0),
+};
+
+static struct f7188x_gpio_bank f71889_gpio_bank[] = {
+       F7188X_GPIO_BANK(0 , 7, 0xF0),
+       F7188X_GPIO_BANK(10, 7, 0xE0),
+       F7188X_GPIO_BANK(20, 8, 0xD0),
+       F7188X_GPIO_BANK(30, 8, 0xC0),
+       F7188X_GPIO_BANK(40, 8, 0xB0),
+       F7188X_GPIO_BANK(50, 5, 0xA0),
+       F7188X_GPIO_BANK(60, 8, 0x90),
+       F7188X_GPIO_BANK(70, 8, 0x80),
+};
+
+static int f7188x_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
+{
+       int err;
+       struct f7188x_gpio_bank *bank =
+               container_of(chip, struct f7188x_gpio_bank, chip);
+       struct f7188x_sio *sio = bank->data->sio;
+       u8 dir;
+
+       err = superio_enter(sio->addr);
+       if (err)
+               return err;
+       superio_select(sio->addr, SIO_LD_GPIO);
+
+       dir = superio_inb(sio->addr, gpio_dir(bank->regbase));
+       dir &= ~(1 << offset);
+       superio_outb(sio->addr, gpio_dir(bank->regbase), dir);
+
+       superio_exit(sio->addr);
+
+       return 0;
+}
+
+static int f7188x_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+       int err;
+       struct f7188x_gpio_bank *bank =
+               container_of(chip, struct f7188x_gpio_bank, chip);
+       struct f7188x_sio *sio = bank->data->sio;
+       u8 dir, data;
+
+       err = superio_enter(sio->addr);
+       if (err)
+               return err;
+       superio_select(sio->addr, SIO_LD_GPIO);
+
+       dir = superio_inb(sio->addr, gpio_dir(bank->regbase));
+       dir = !!(dir & (1 << offset));
+       if (dir)
+               data = superio_inb(sio->addr, gpio_data_out(bank->regbase));
+       else
+               data = superio_inb(sio->addr, gpio_data_in(bank->regbase));
+
+       superio_exit(sio->addr);
+
+       return !!(data & 1 << offset);
+}
+
+static int f7188x_gpio_direction_out(struct gpio_chip *chip,
+                                    unsigned offset, int value)
+{
+       int err;
+       struct f7188x_gpio_bank *bank =
+               container_of(chip, struct f7188x_gpio_bank, chip);
+       struct f7188x_sio *sio = bank->data->sio;
+       u8 dir, data_out;
+
+       err = superio_enter(sio->addr);
+       if (err)
+               return err;
+       superio_select(sio->addr, SIO_LD_GPIO);
+
+       data_out = superio_inb(sio->addr, gpio_data_out(bank->regbase));
+       if (value)
+               data_out |= (1 << offset);
+       else
+               data_out &= ~(1 << offset);
+       superio_outb(sio->addr, gpio_data_out(bank->regbase), data_out);
+
+       dir = superio_inb(sio->addr, gpio_dir(bank->regbase));
+       dir |= (1 << offset);
+       superio_outb(sio->addr, gpio_dir(bank->regbase), dir);
+
+       superio_exit(sio->addr);
+
+       return 0;
+}
+
+static void f7188x_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+       int err;
+       struct f7188x_gpio_bank *bank =
+               container_of(chip, struct f7188x_gpio_bank, chip);
+       struct f7188x_sio *sio = bank->data->sio;
+       u8 data_out;
+
+       err = superio_enter(sio->addr);
+       if (err)
+               return;
+       superio_select(sio->addr, SIO_LD_GPIO);
+
+       data_out = superio_inb(sio->addr, gpio_data_out(bank->regbase));
+       if (value)
+               data_out |= (1 << offset);
+       else
+               data_out &= ~(1 << offset);
+       superio_outb(sio->addr, gpio_data_out(bank->regbase), data_out);
+
+       superio_exit(sio->addr);
+}
+
+/*
+ * Platform device and driver.
+ */
+
+static int f7188x_gpio_probe(struct platform_device *pdev)
+{
+       int err;
+       int i;
+       struct f7188x_sio *sio = pdev->dev.platform_data;
+       struct f7188x_gpio_data *data;
+
+       data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
+
+       switch (sio->type) {
+       case f71882fg:
+               data->nr_bank = ARRAY_SIZE(f71882_gpio_bank);
+               data->bank = f71882_gpio_bank;
+               break;
+       case f71889f:
+               data->nr_bank = ARRAY_SIZE(f71889_gpio_bank);
+               data->bank = f71889_gpio_bank;
+               break;
+       default:
+               return -ENODEV;
+       }
+       data->sio = sio;
+
+       platform_set_drvdata(pdev, data);
+
+       /* For each GPIO bank, register a GPIO chip. */
+       for (i = 0; i < data->nr_bank; i++) {
+               struct f7188x_gpio_bank *bank = &data->bank[i];
+
+               bank->chip.dev = &pdev->dev;
+               bank->data = data;
+
+               err = gpiochip_add(&bank->chip);
+               if (err) {
+                       dev_err(&pdev->dev,
+                               "Failed to register gpiochip %d: %d\n",
+                               i, err);
+                       goto err_gpiochip;
+               }
+       }
+
+       return 0;
+
+err_gpiochip:
+       for (i = i - 1; i >= 0; i--) {
+               struct f7188x_gpio_bank *bank = &data->bank[i];
+               int tmp;
+
+               tmp = gpiochip_remove(&bank->chip);
+               if (tmp < 0)
+                       dev_err(&pdev->dev,
+                               "Failed to remove gpiochip %d: %d\n",
+                               i, tmp);
+       }
+
+       return err;
+}
+
+static int f7188x_gpio_remove(struct platform_device *pdev)
+{
+       int err;
+       int i;
+       struct f7188x_gpio_data *data = platform_get_drvdata(pdev);
+
+       for (i = 0; i < data->nr_bank; i++) {
+               struct f7188x_gpio_bank *bank = &data->bank[i];
+
+               err = gpiochip_remove(&bank->chip);
+               if (err) {
+                       dev_err(&pdev->dev,
+                               "Failed to remove GPIO gpiochip %d: %d\n",
+                               i, err);
+                       return err;
+               }
+       }
+
+       return 0;
+}
+
+static int __init f7188x_find(int addr, struct f7188x_sio *sio)
+{
+       int err;
+       u16 devid;
+
+       err = superio_enter(addr);
+       if (err)
+               return err;
+
+       err = -ENODEV;
+       devid = superio_inw(addr, SIO_MANID);
+       if (devid != SIO_FINTEK_ID) {
+               pr_debug(DRVNAME ": Not a Fintek device at 0x%08x\n", addr);
+               goto err;
+       }
+
+       devid = superio_inw(addr, SIO_DEVID);
+       switch (devid) {
+       case SIO_F71882_ID:
+               sio->type = f71882fg;
+               break;
+       case SIO_F71889_ID:
+               sio->type = f71889f;
+               break;
+       default:
+               pr_info(DRVNAME ": Unsupported Fintek device 0x%04x\n", devid);
+               goto err;
+       }
+       sio->addr = addr;
+       err = 0;
+
+       pr_info(DRVNAME ": Found %s at %#x, revision %d\n",
+               f7188x_names[sio->type],
+               (unsigned int) addr,
+               (int) superio_inb(addr, SIO_DEVREV));
+
+err:
+       superio_exit(addr);
+       return err;
+}
+
+static struct platform_device *f7188x_gpio_pdev;
+
+static int __init
+f7188x_gpio_device_add(const struct f7188x_sio *sio)
+{
+       int err;
+
+       f7188x_gpio_pdev = platform_device_alloc(DRVNAME, -1);
+       if (!f7188x_gpio_pdev)
+               return -ENOMEM;
+
+       err = platform_device_add_data(f7188x_gpio_pdev,
+                                      sio, sizeof(*sio));
+       if (err) {
+               pr_err(DRVNAME "Platform data allocation failed\n");
+               goto err;
+       }
+
+       err = platform_device_add(f7188x_gpio_pdev);
+       if (err) {
+               pr_err(DRVNAME "Device addition failed\n");
+               goto err;
+       }
+
+       return 0;
+
+err:
+       platform_device_put(f7188x_gpio_pdev);
+
+       return err;
+}
+
+/*
+ * Try to match a supported Fintech device by reading the (hard-wired)
+ * configuration I/O ports. If available, then register both the platform
+ * device and driver to support the GPIOs.
+ */
+
+static struct platform_driver f7188x_gpio_driver = {
+       .driver = {
+               .owner  = THIS_MODULE,
+               .name   = DRVNAME,
+       },
+       .probe          = f7188x_gpio_probe,
+       .remove         = f7188x_gpio_remove,
+};
+
+static int __init f7188x_gpio_init(void)
+{
+       int err;
+       struct f7188x_sio sio;
+
+       if (f7188x_find(0x2e, &sio) &&
+           f7188x_find(0x4e, &sio))
+               return -ENODEV;
+
+       err = platform_driver_register(&f7188x_gpio_driver);
+       if (!err) {
+               err = f7188x_gpio_device_add(&sio);
+               if (err)
+                       platform_driver_unregister(&f7188x_gpio_driver);
+       }
+
+       return err;
+}
+subsys_initcall(f7188x_gpio_init);
+
+static void __exit f7188x_gpio_exit(void)
+{
+       platform_device_unregister(f7188x_gpio_pdev);
+       platform_driver_unregister(&f7188x_gpio_driver);
+}
+module_exit(f7188x_gpio_exit);
+
+MODULE_DESCRIPTION("GPIO driver for Super-I/O chips F71882FG and F71889F");
+MODULE_AUTHOR("Simon Guinot <simon.guinot@sequanux.org>");
+MODULE_LICENSE("GPL");
index 2729e3d2d5bbe9da7781be8cf8de34be26d19535..814addb62d2cce372ac4a9df25733d6f3f52284e 100644 (file)
@@ -354,7 +354,7 @@ static int ichx_gpio_probe(struct platform_device *pdev)
 {
        struct resource *res_base, *res_pm;
        int err;
-       struct lpc_ich_info *ich_info = pdev->dev.platform_data;
+       struct lpc_ich_info *ich_info = dev_get_platdata(&pdev->dev);
 
        if (!ich_info)
                return -ENODEV;
index 7d0a04169a351ba54b0b53b67a0d587063da5bd7..2ecd3a09c743e6dba7434c9cbfab0e5c70bc24c3 100644 (file)
@@ -149,7 +149,7 @@ static int ttl_probe(struct platform_device *pdev)
        struct resource *res;
        int ret;
 
-       pdata = pdev->dev.platform_data;
+       pdata = dev_get_platdata(&pdev->dev);
        if (!pdata) {
                dev_err(dev, "no platform data\n");
                ret = -ENXIO;
diff --git a/drivers/gpio/gpio-kempld.c b/drivers/gpio/gpio-kempld.c
new file mode 100644 (file)
index 0000000..efdc392
--- /dev/null
@@ -0,0 +1,219 @@
+/*
+ * Kontron PLD GPIO driver
+ *
+ * Copyright (c) 2010-2013 Kontron Europe GmbH
+ * Author: Michael Brunner <michael.brunner@kontron.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/bitops.h>
+#include <linux/errno.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/mfd/kempld.h>
+
+#define KEMPLD_GPIO_MAX_NUM            16
+#define KEMPLD_GPIO_MASK(x)            (1 << ((x) % 8))
+#define KEMPLD_GPIO_DIR_NUM(x)         (0x40 + (x) / 8)
+#define KEMPLD_GPIO_LVL_NUM(x)         (0x42 + (x) / 8)
+#define KEMPLD_GPIO_EVT_LVL_EDGE       0x46
+#define KEMPLD_GPIO_IEN                        0x4A
+
+struct kempld_gpio_data {
+       struct gpio_chip                chip;
+       struct kempld_device_data       *pld;
+};
+
+/*
+ * Set or clear GPIO bit
+ * kempld_get_mutex must be called prior to calling this function.
+ */
+static void kempld_gpio_bitop(struct kempld_device_data *pld,
+                             u8 reg, u8 bit, u8 val)
+{
+       u8 status;
+
+       status = kempld_read8(pld, reg);
+       if (val)
+               status |= KEMPLD_GPIO_MASK(bit);
+       else
+               status &= ~KEMPLD_GPIO_MASK(bit);
+       kempld_write8(pld, reg, status);
+}
+
+static int kempld_gpio_get_bit(struct kempld_device_data *pld, u8 reg, u8 bit)
+{
+       u8 status;
+
+       kempld_get_mutex(pld);
+       status = kempld_read8(pld, reg);
+       kempld_release_mutex(pld);
+
+       return !!(status & KEMPLD_GPIO_MASK(bit));
+}
+
+static int kempld_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+       struct kempld_gpio_data *gpio
+               = container_of(chip, struct kempld_gpio_data, chip);
+       struct kempld_device_data *pld = gpio->pld;
+
+       return kempld_gpio_get_bit(pld, KEMPLD_GPIO_LVL_NUM(offset), offset);
+}
+
+static void kempld_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+       struct kempld_gpio_data *gpio
+               = container_of(chip, struct kempld_gpio_data, chip);
+       struct kempld_device_data *pld = gpio->pld;
+
+       kempld_get_mutex(pld);
+       kempld_gpio_bitop(pld, KEMPLD_GPIO_LVL_NUM(offset), offset, value);
+       kempld_release_mutex(pld);
+}
+
+static int kempld_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+       struct kempld_gpio_data *gpio
+               = container_of(chip, struct kempld_gpio_data, chip);
+       struct kempld_device_data *pld = gpio->pld;
+
+       kempld_get_mutex(pld);
+       kempld_gpio_bitop(pld, KEMPLD_GPIO_DIR_NUM(offset), offset, 0);
+       kempld_release_mutex(pld);
+
+       return 0;
+}
+
+static int kempld_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
+                                       int value)
+{
+       struct kempld_gpio_data *gpio
+               = container_of(chip, struct kempld_gpio_data, chip);
+       struct kempld_device_data *pld = gpio->pld;
+
+       kempld_get_mutex(pld);
+       kempld_gpio_bitop(pld, KEMPLD_GPIO_LVL_NUM(offset), offset, value);
+       kempld_gpio_bitop(pld, KEMPLD_GPIO_DIR_NUM(offset), offset, 1);
+       kempld_release_mutex(pld);
+
+       return 0;
+}
+
+static int kempld_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
+{
+       struct kempld_gpio_data *gpio
+               = container_of(chip, struct kempld_gpio_data, chip);
+       struct kempld_device_data *pld = gpio->pld;
+
+       return kempld_gpio_get_bit(pld, KEMPLD_GPIO_DIR_NUM(offset), offset);
+}
+
+static int kempld_gpio_pincount(struct kempld_device_data *pld)
+{
+       u16 evt, evt_back;
+
+       kempld_get_mutex(pld);
+
+       /* Backup event register as it might be already initialized */
+       evt_back = kempld_read16(pld, KEMPLD_GPIO_EVT_LVL_EDGE);
+       /* Clear event register */
+       kempld_write16(pld, KEMPLD_GPIO_EVT_LVL_EDGE, 0x0000);
+       /* Read back event register */
+       evt = kempld_read16(pld, KEMPLD_GPIO_EVT_LVL_EDGE);
+       /* Restore event register */
+       kempld_write16(pld, KEMPLD_GPIO_EVT_LVL_EDGE, evt_back);
+
+       kempld_release_mutex(pld);
+
+       return evt ? __ffs(evt) : 16;
+}
+
+static int kempld_gpio_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct kempld_device_data *pld = dev_get_drvdata(dev->parent);
+       struct kempld_platform_data *pdata = dev_get_platdata(pld->dev);
+       struct kempld_gpio_data *gpio;
+       struct gpio_chip *chip;
+       int ret;
+
+       if (pld->info.spec_major < 2) {
+               dev_err(dev,
+                       "Driver only supports GPIO devices compatible to PLD spec. rev. 2.0 or higher\n");
+               return -ENODEV;
+       }
+
+       gpio = devm_kzalloc(dev, sizeof(*gpio), GFP_KERNEL);
+       if (gpio == NULL)
+               return -ENOMEM;
+
+       gpio->pld = pld;
+
+       platform_set_drvdata(pdev, gpio);
+
+       chip = &gpio->chip;
+       chip->label = "gpio-kempld";
+       chip->owner = THIS_MODULE;
+       chip->dev = dev;
+       chip->can_sleep = 1;
+       if (pdata && pdata->gpio_base)
+               chip->base = pdata->gpio_base;
+       else
+               chip->base = -1;
+       chip->direction_input = kempld_gpio_direction_input;
+       chip->direction_output = kempld_gpio_direction_output;
+       chip->get_direction = kempld_gpio_get_direction;
+       chip->get = kempld_gpio_get;
+       chip->set = kempld_gpio_set;
+       chip->ngpio = kempld_gpio_pincount(pld);
+       if (chip->ngpio == 0) {
+               dev_err(dev, "No GPIO pins detected\n");
+               return -ENODEV;
+       }
+
+       ret = gpiochip_add(chip);
+       if (ret) {
+               dev_err(dev, "Could not register GPIO chip\n");
+               return ret;
+       }
+
+       dev_info(dev, "GPIO functionality initialized with %d pins\n",
+                chip->ngpio);
+
+       return 0;
+}
+
+static int kempld_gpio_remove(struct platform_device *pdev)
+{
+       struct kempld_gpio_data *gpio = platform_get_drvdata(pdev);
+
+       return gpiochip_remove(&gpio->chip);
+}
+
+static struct platform_driver kempld_gpio_driver = {
+       .driver = {
+               .name = "kempld-gpio",
+               .owner = THIS_MODULE,
+       },
+       .probe          = kempld_gpio_probe,
+       .remove         = kempld_gpio_remove,
+};
+
+module_platform_driver(kempld_gpio_driver);
+
+MODULE_DESCRIPTION("KEM PLD GPIO Driver");
+MODULE_AUTHOR("Michael Brunner <michael.brunner@kontron.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:gpio-kempld");
index 761c4705dfbb357b437f263dac54d1a5c8272864..2d9ca6055e5e0bde239247fabe41c960d4dd3020 100644 (file)
@@ -444,6 +444,7 @@ static int lp_gpio_remove(struct platform_device *pdev)
 {
        struct lp_gpio *lg = platform_get_drvdata(pdev);
        int err;
+       pm_runtime_disable(&pdev->dev);
        err = gpiochip_remove(&lg->chip);
        if (err)
                dev_warn(&pdev->dev, "failed to remove gpio_chip.\n");
index 3b16ab7016301f0ff27cb2b05b070b377918d986..6e1c984a75d45e4253d0f2c1563364d310f37708 100644 (file)
@@ -56,8 +56,7 @@ static int max7301_probe(struct spi_device *spi)
        int ret;
 
        /* bits_per_word cannot be configured in platform data */
-       if (spi->dev.platform_data)
-               spi->bits_per_word = 16;
+       spi->bits_per_word = 16;
        ret = spi_setup(spi);
        if (ret < 0)
                return ret;
index 00092342b84c050d0c1d0e32b9202919108aa11a..f4f4ed19bdc13c8211d1eb74244afab51088738f 100644 (file)
@@ -166,7 +166,7 @@ int __max730x_probe(struct max7301 *ts)
        struct max7301_platform_data *pdata;
        int i, ret;
 
-       pdata = dev->platform_data;
+       pdata = dev_get_platdata(dev);
 
        mutex_init(&ts->lock);
        dev_set_drvdata(dev, ts);
index d4b51b163b039f9aa6ed93c007a3d0d56160f3e1..91ad74dea8ceab68dc6048ce10a1b14e6ccaf80e 100644 (file)
@@ -453,7 +453,7 @@ static int max732x_irq_setup(struct max732x_chip *chip,
                             const struct i2c_device_id *id)
 {
        struct i2c_client *client = chip->client;
-       struct max732x_platform_data *pdata = client->dev.platform_data;
+       struct max732x_platform_data *pdata = dev_get_platdata(&client->dev);
        int has_irq = max732x_features[id->driver_data] >> 32;
        int ret;
 
@@ -512,7 +512,7 @@ static int max732x_irq_setup(struct max732x_chip *chip,
                             const struct i2c_device_id *id)
 {
        struct i2c_client *client = chip->client;
-       struct max732x_platform_data *pdata = client->dev.platform_data;
+       struct max732x_platform_data *pdata = dev_get_platdata(&client->dev);
        int has_irq = max732x_features[id->driver_data] >> 32;
 
        if (pdata->irq_base && has_irq != INT_NONE)
@@ -583,7 +583,7 @@ static int max732x_probe(struct i2c_client *client,
        uint16_t addr_a, addr_b;
        int ret, nr_port;
 
-       pdata = client->dev.platform_data;
+       pdata = dev_get_platdata(&client->dev);
        if (pdata == NULL) {
                dev_dbg(&client->dev, "no platform data\n");
                return -EINVAL;
@@ -653,7 +653,7 @@ out_failed:
 
 static int max732x_remove(struct i2c_client *client)
 {
-       struct max732x_platform_data *pdata = client->dev.platform_data;
+       struct max732x_platform_data *pdata = dev_get_platdata(&client->dev);
        struct max732x_chip *chip = i2c_get_clientdata(client);
        int ret;
 
index 63a7a1bfb2d90a675473015c20591289a61465c1..3fd2caa4a2e02fd05a71022a522c51add55f5e66 100644 (file)
@@ -86,7 +86,7 @@ static int mc33880_probe(struct spi_device *spi)
        struct mc33880_platform_data *pdata;
        int ret;
 
-       pdata = spi->dev.platform_data;
+       pdata = dev_get_platdata(&spi->dev);
        if (!pdata || !pdata->base) {
                dev_dbg(&spi->dev, "incorrect or missing platform data\n");
                return -EINVAL;
index 6a4470b84488eca7907ce509d7d77fcf3f0ff5fb..2deb0c5e54a443a7546c7e4c63bf1e6a833c0d50 100644 (file)
@@ -483,10 +483,21 @@ fail:
 #ifdef CONFIG_SPI_MASTER
 static struct of_device_id mcp23s08_spi_of_match[] = {
        {
-               .compatible = "mcp,mcp23s08", .data = (void *) MCP_TYPE_S08,
+               .compatible = "microchip,mcp23s08",
+               .data = (void *) MCP_TYPE_S08,
        },
        {
-               .compatible = "mcp,mcp23s17", .data = (void *) MCP_TYPE_S17,
+               .compatible = "microchip,mcp23s17",
+               .data = (void *) MCP_TYPE_S17,
+       },
+/* NOTE: The use of the mcp prefix is deprecated and will be removed. */
+       {
+               .compatible = "mcp,mcp23s08",
+               .data = (void *) MCP_TYPE_S08,
+       },
+       {
+               .compatible = "mcp,mcp23s17",
+               .data = (void *) MCP_TYPE_S17,
        },
        { },
 };
@@ -496,10 +507,21 @@ MODULE_DEVICE_TABLE(of, mcp23s08_spi_of_match);
 #if IS_ENABLED(CONFIG_I2C)
 static struct of_device_id mcp23s08_i2c_of_match[] = {
        {
-               .compatible = "mcp,mcp23008", .data = (void *) MCP_TYPE_008,
+               .compatible = "microchip,mcp23008",
+               .data = (void *) MCP_TYPE_008,
+       },
+       {
+               .compatible = "microchip,mcp23017",
+               .data = (void *) MCP_TYPE_017,
+       },
+/* NOTE: The use of the mcp prefix is deprecated and will be removed. */
+       {
+               .compatible = "mcp,mcp23008",
+               .data = (void *) MCP_TYPE_008,
        },
        {
-               .compatible = "mcp,mcp23017", .data = (void *) MCP_TYPE_017,
+               .compatible = "mcp,mcp23017",
+               .data = (void *) MCP_TYPE_017,
        },
        { },
 };
@@ -520,14 +542,13 @@ static int mcp230xx_probe(struct i2c_client *client,
 
        match = of_match_device(of_match_ptr(mcp23s08_i2c_of_match),
                                        &client->dev);
-       if (match) {
+       pdata = dev_get_platdata(&client->dev);
+       if (match || !pdata) {
                base = -1;
                pullups = 0;
        } else {
-               pdata = client->dev.platform_data;
-               if (!pdata || !gpio_is_valid(pdata->base)) {
-                       dev_dbg(&client->dev,
-                                       "invalid or missing platform data\n");
+               if (!gpio_is_valid(pdata->base)) {
+                       dev_dbg(&client->dev, "invalid platform data\n");
                        return -EINVAL;
                }
                base = pdata->base;
@@ -621,10 +642,15 @@ static int mcp23s08_probe(struct spi_device *spi)
        if (match) {
                type = (int)match->data;
                status = of_property_read_u32(spi->dev.of_node,
-                               "mcp,spi-present-mask", &spi_present_mask);
+                           "microchip,spi-present-mask", &spi_present_mask);
                if (status) {
-                       dev_err(&spi->dev, "DT has no spi-present-mask\n");
-                       return -ENODEV;
+                       status = of_property_read_u32(spi->dev.of_node,
+                                   "mcp,spi-present-mask", &spi_present_mask);
+                       if (status) {
+                               dev_err(&spi->dev,
+                                       "DT has no spi-present-mask\n");
+                               return -ENODEV;
+                       }
                }
                if ((spi_present_mask <= 0) || (spi_present_mask >= 256)) {
                        dev_err(&spi->dev, "invalid spi-present-mask\n");
@@ -635,7 +661,7 @@ static int mcp23s08_probe(struct spi_device *spi)
                        pullups[addr] = 0;
        } else {
                type = spi_get_device_id(spi)->driver_data;
-               pdata = spi->dev.platform_data;
+               pdata = dev_get_platdata(&spi->dev);
                if (!pdata || !gpio_is_valid(pdata->base)) {
                        dev_dbg(&spi->dev,
                                        "invalid or missing platform data\n");
index 27ea7b9257ff7ce0eb25ff765e275b36c3a1372f..d75eaa3a1dcc5f2e158ff4bdf59c991402a3b822 100644 (file)
@@ -259,7 +259,7 @@ static void msic_gpio_irq_handler(unsigned irq, struct irq_desc *desc)
 static int platform_msic_gpio_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
-       struct intel_msic_gpio_pdata *pdata = dev->platform_data;
+       struct intel_msic_gpio_pdata *pdata = dev_get_platdata(dev);
        struct msic_gpio *mg;
        int irq = platform_get_irq(pdev, 0);
        int retval;
index c2fa77086eb58cf9de7f2c2a453c900a9771f0b5..f7a0cc4da9502d12ef0aa602dfa249665e5a5c4a 100644 (file)
@@ -106,7 +106,7 @@ struct msm_gpio_dev {
        void __iomem *msm_tlmm_base;
 };
 
-struct msm_gpio_dev msm_gpio;
+static struct msm_gpio_dev msm_gpio;
 
 #define GPIO_INTR_CFG_SU(gpio)    (msm_gpio.msm_tlmm_base + 0x0400 + \
                                                                (0x04 * (gpio)))
index 80ad35e2a8cd5ac3af9f39f0cba644c7062fb592..3c3321f94053ab68f0ab0e691afc1ddf2b83f0e9 100644 (file)
@@ -566,12 +566,6 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
        else
                soc_variant = MVEBU_GPIO_SOC_VARIANT_ORION;
 
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               dev_err(&pdev->dev, "Cannot get memory resource\n");
-               return -ENODEV;
-       }
-
        mvchip = devm_kzalloc(&pdev->dev, sizeof(struct mvebu_gpio_chip), GFP_KERNEL);
        if (!mvchip) {
                dev_err(&pdev->dev, "Cannot allocate memory\n");
@@ -611,6 +605,7 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
        mvchip->chip.dbg_show = mvebu_gpio_dbg_show;
 
        spin_lock_init(&mvchip->lock);
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        mvchip->membase = devm_ioremap_resource(&pdev->dev, res);
        if (IS_ERR(mvchip->membase))
                return PTR_ERR(mvchip->membase);
index 7176743915d3df032cefa2ec33a327f7b22f799b..3307f6db3a925fb3469c29f34eb69bfb93ca312a 100644 (file)
@@ -19,6 +19,7 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
 
+#include <linux/err.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
@@ -291,6 +292,9 @@ static void mx2_gpio_irq_handler(u32 irq, struct irq_desc *desc)
 {
        u32 irq_msk, irq_stat;
        struct mxc_gpio_port *port;
+       struct irq_chip *chip = irq_get_chip(irq);
+
+       chained_irq_enter(chip, desc);
 
        /* walk through all interrupt status registers */
        list_for_each_entry(port, &mxc_gpio_ports, node) {
@@ -302,6 +306,7 @@ static void mx2_gpio_irq_handler(u32 irq, struct irq_desc *desc)
                if (irq_stat)
                        mxc_gpio_irq_handler(port, irq_stat);
        }
+       chained_irq_exit(chip, desc);
 }
 
 /*
@@ -405,34 +410,19 @@ static int mxc_gpio_probe(struct platform_device *pdev)
 
        mxc_gpio_get_hw(pdev);
 
-       port = kzalloc(sizeof(struct mxc_gpio_port), GFP_KERNEL);
+       port = devm_kzalloc(&pdev->dev, sizeof(*port), GFP_KERNEL);
        if (!port)
                return -ENOMEM;
 
        iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!iores) {
-               err = -ENODEV;
-               goto out_kfree;
-       }
-
-       if (!request_mem_region(iores->start, resource_size(iores),
-                               pdev->name)) {
-               err = -EBUSY;
-               goto out_kfree;
-       }
-
-       port->base = ioremap(iores->start, resource_size(iores));
-       if (!port->base) {
-               err = -ENOMEM;
-               goto out_release_mem;
-       }
+       port->base = devm_ioremap_resource(&pdev->dev, iores);
+       if (IS_ERR(port->base))
+               return PTR_ERR(port->base);
 
        port->irq_high = platform_get_irq(pdev, 1);
        port->irq = platform_get_irq(pdev, 0);
-       if (port->irq < 0) {
-               err = -EINVAL;
-               goto out_iounmap;
-       }
+       if (port->irq < 0)
+               return -EINVAL;
 
        /* disable the interrupt and clear the status */
        writel(0, port->base + GPIO_IMR);
@@ -462,7 +452,7 @@ static int mxc_gpio_probe(struct platform_device *pdev)
                         port->base + GPIO_DR, NULL,
                         port->base + GPIO_GDIR, NULL, 0);
        if (err)
-               goto out_iounmap;
+               goto out_bgio;
 
        port->bgc.gc.to_irq = mxc_gpio_to_irq;
        port->bgc.gc.base = (pdev->id < 0) ? of_alias_get_id(np, "gpio") * 32 :
@@ -498,12 +488,7 @@ out_gpiochip_remove:
        WARN_ON(gpiochip_remove(&port->bgc.gc) < 0);
 out_bgpio_remove:
        bgpio_remove(&port->bgc);
-out_iounmap:
-       iounmap(port->base);
-out_release_mem:
-       release_mem_region(iores->start, resource_size(iores));
-out_kfree:
-       kfree(port);
+out_bgio:
        dev_info(&pdev->dev, "%s failed with errno %d\n", __func__, err);
        return err;
 }
index dfeb3a3a8f20949098b5dc0e703ffe1ea944f245..0ff43552d472bf09d5ab0206437e62ae0392c6f1 100644 (file)
@@ -1030,7 +1030,7 @@ omap_mpuio_alloc_gc(struct gpio_bank *bank, unsigned int irq_start,
        ct->chip.irq_set_type = gpio_irq_type;
 
        if (bank->regs->wkup_en)
-               ct->chip.irq_set_wake = gpio_wake_enable,
+               ct->chip.irq_set_wake = gpio_wake_enable;
 
        ct->regs.mask = OMAP_MPUIO_GPIO_INT / bank->stride;
        irq_setup_generic_chip(gc, IRQ_MSK(num), IRQ_GC_INIT_MASK_CACHE,
@@ -1100,7 +1100,7 @@ static int omap_gpio_probe(struct platform_device *pdev)
 
        match = of_match_device(of_match_ptr(omap_gpio_match), dev);
 
-       pdata = match ? match->data : dev->platform_data;
+       pdata = match ? match->data : dev_get_platdata(dev);
        if (!pdata)
                return -EINVAL;
 
index e3a4e56f5a4233d4754449fcd342b4b41c9d623f..8588af0f766126076ef61ff50d58dac120af7ee4 100644 (file)
@@ -43,9 +43,22 @@ static int palmas_gpio_get(struct gpio_chip *gc, unsigned offset)
        unsigned int val;
        int ret;
 
-       ret = palmas_read(palmas, PALMAS_GPIO_BASE, PALMAS_GPIO_DATA_IN, &val);
+       ret = palmas_read(palmas, PALMAS_GPIO_BASE, PALMAS_GPIO_DATA_DIR, &val);
        if (ret < 0) {
-               dev_err(gc->dev, "GPIO_DATA_IN read failed, err = %d\n", ret);
+               dev_err(gc->dev, "GPIO_DATA_DIR read failed, err = %d\n", ret);
+               return ret;
+       }
+
+       if (val & (1 << offset)) {
+               ret = palmas_read(palmas, PALMAS_GPIO_BASE,
+                                 PALMAS_GPIO_DATA_OUT, &val);
+       } else {
+               ret = palmas_read(palmas, PALMAS_GPIO_BASE,
+                                 PALMAS_GPIO_DATA_IN, &val);
+       }
+       if (ret < 0) {
+               dev_err(gc->dev, "GPIO_DATA_IN/OUT read failed, err = %d\n",
+                       ret);
                return ret;
        }
        return !!(val & BIT(offset));
@@ -134,7 +147,7 @@ static int palmas_gpio_probe(struct platform_device *pdev)
        palmas_gpio->gpio_chip.get      = palmas_gpio_get;
        palmas_gpio->gpio_chip.dev = &pdev->dev;
 #ifdef CONFIG_OF_GPIO
-       palmas_gpio->gpio_chip.of_node = palmas->dev->of_node;
+       palmas_gpio->gpio_chip.of_node = pdev->dev.of_node;
 #endif
        palmas_pdata = dev_get_platdata(palmas->dev);
        if (palmas_pdata && palmas_pdata->gpio_base)
@@ -159,9 +172,19 @@ static int palmas_gpio_remove(struct platform_device *pdev)
        return gpiochip_remove(&palmas_gpio->gpio_chip);
 }
 
+static struct of_device_id of_palmas_gpio_match[] = {
+       { .compatible = "ti,palmas-gpio"},
+       { .compatible = "ti,tps65913-gpio"},
+       { .compatible = "ti,tps65914-gpio"},
+       { .compatible = "ti,tps80036-gpio"},
+       { },
+};
+MODULE_DEVICE_TABLE(of, of_palmas_gpio_match);
+
 static struct platform_driver palmas_gpio_driver = {
        .driver.name    = "palmas-gpio",
        .driver.owner   = THIS_MODULE,
+       .driver.of_match_table = of_palmas_gpio_match,
        .probe          = palmas_gpio_probe,
        .remove         = palmas_gpio_remove,
 };
index 8804aec2950fb9f81e317f4b7e46bd2a2d601aaf..cdd1aa12b895e3017bfd79da95e6b499fb3bf28f 100644 (file)
@@ -308,7 +308,7 @@ static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off)
                return 0;
        }
 
-       return (reg_val & (1u << off)) ? 1 : 0;
+       return (reg_val & (1u << (off % BANK_SZ))) ? 1 : 0;
 }
 
 static void pca953x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val)
@@ -731,7 +731,7 @@ static int pca953x_probe(struct i2c_client *client,
        if (chip == NULL)
                return -ENOMEM;
 
-       pdata = client->dev.platform_data;
+       pdata = dev_get_platdata(&client->dev);
        if (pdata) {
                irq_base = pdata->irq_base;
                chip->gpio_start = pdata->gpio_base;
@@ -785,7 +785,7 @@ static int pca953x_probe(struct i2c_client *client,
 
 static int pca953x_remove(struct i2c_client *client)
 {
-       struct pca953x_platform_data *pdata = client->dev.platform_data;
+       struct pca953x_platform_data *pdata = dev_get_platdata(&client->dev);
        struct pca953x_chip *chip = i2c_get_clientdata(client);
        int ret = 0;
 
index e8faf53f3875df488eaba35c7463de6a3f03bd29..9e61bb0719d0cac80f176b941adf51aa52cd9b01 100644 (file)
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <linux/kernel.h>
-#include <linux/slab.h>
 #include <linux/gpio.h>
 #include <linux/i2c.h>
 #include <linux/i2c/pcf857x.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/irqdomain.h>
+#include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/workqueue.h>
 
@@ -223,7 +223,6 @@ static void pcf857x_irq_domain_cleanup(struct pcf857x *gpio)
 }
 
 static int pcf857x_irq_domain_init(struct pcf857x *gpio,
-                                  struct pcf857x_platform_data *pdata,
                                   struct i2c_client *client)
 {
        int status;
@@ -262,7 +261,7 @@ static int pcf857x_probe(struct i2c_client *client,
        struct pcf857x                  *gpio;
        int                             status;
 
-       pdata = client->dev.platform_data;
+       pdata = dev_get_platdata(&client->dev);
        if (!pdata) {
                dev_dbg(&client->dev, "no platform data\n");
        }
@@ -286,8 +285,8 @@ static int pcf857x_probe(struct i2c_client *client,
        gpio->chip.ngpio                = id->driver_data;
 
        /* enable gpio_to_irq() if platform has settings */
-       if (pdata && client->irq) {
-               status = pcf857x_irq_domain_init(gpio, pdata, client);
+       if (client->irq) {
+               status = pcf857x_irq_domain_init(gpio, client);
                if (status < 0) {
                        dev_err(&client->dev, "irq_domain init failed\n");
                        goto fail;
@@ -388,7 +387,7 @@ fail:
        dev_dbg(&client->dev, "probe error %d for '%s'\n",
                        status, client->name);
 
-       if (pdata && client->irq)
+       if (client->irq)
                pcf857x_irq_domain_cleanup(gpio);
 
        return status;
@@ -396,7 +395,7 @@ fail:
 
 static int pcf857x_remove(struct i2c_client *client)
 {
-       struct pcf857x_platform_data    *pdata = client->dev.platform_data;
+       struct pcf857x_platform_data    *pdata = dev_get_platdata(&client->dev);
        struct pcf857x                  *gpio = i2c_get_clientdata(client);
        int                             status = 0;
 
@@ -411,7 +410,7 @@ static int pcf857x_remove(struct i2c_client *client)
                }
        }
 
-       if (pdata && client->irq)
+       if (client->irq)
                pcf857x_irq_domain_cleanup(gpio);
 
        status = gpiochip_remove(&gpio->chip);
index 6a4bd0dae0ceb9c3d2d6f7c020c273f0fb269618..4274e2e70ef8e8e31fcdb6da0370ae265f383190 100644 (file)
@@ -259,7 +259,7 @@ static const struct irq_domain_ops pl061_domain_ops = {
 static int pl061_probe(struct amba_device *adev, const struct amba_id *id)
 {
        struct device *dev = &adev->dev;
-       struct pl061_platform_data *pdata = dev->platform_data;
+       struct pl061_platform_data *pdata = dev_get_platdata(dev);
        struct pl061_gpio *chip;
        int ret, irq, i, irq_base;
 
index df2199dd149975e37a31efc6a881450a6ad6af12..cc13d1b74fad09f06c0d2bd42cc4d41b196df2cf 100644 (file)
@@ -524,8 +524,8 @@ const struct irq_domain_ops pxa_irq_domain_ops = {
 
 static int pxa_gpio_probe_dt(struct platform_device *pdev)
 {
-       int ret, nr_gpios;
-       struct device_node *prev, *next, *np = pdev->dev.of_node;
+       int ret = 0, nr_gpios;
+       struct device_node *np = pdev->dev.of_node;
        const struct of_device_id *of_id =
                                of_match_device(pxa_gpio_dt_ids, &pdev->dev);
        const struct pxa_gpio_id *gpio_id;
@@ -537,20 +537,13 @@ static int pxa_gpio_probe_dt(struct platform_device *pdev)
        gpio_id = of_id->data;
        gpio_type = gpio_id->type;
 
-       next = of_get_next_child(np, NULL);
-       prev = next;
-       if (!next) {
-               dev_err(&pdev->dev, "Failed to find child gpio node\n");
-               ret = -EINVAL;
-               goto err;
-       }
-       of_node_put(prev);
        nr_gpios = gpio_id->gpio_nums;
        pxa_last_gpio = nr_gpios - 1;
 
        irq_base = irq_alloc_descs(-1, 0, nr_gpios, 0);
        if (irq_base < 0) {
                dev_err(&pdev->dev, "Failed to allocate IRQ numbers\n");
+               ret = irq_base;
                goto err;
        }
        domain = irq_domain_add_legacy(np, nr_gpios, irq_base, 0,
index e8198dd686155da6487440a84d5a64e04c213317..e3745eb075708092d0a56e04f7bb2a10b4d274dd 100644 (file)
@@ -285,7 +285,7 @@ static struct irq_domain_ops gpio_rcar_irq_domain_ops = {
 
 static void gpio_rcar_parse_pdata(struct gpio_rcar_priv *p)
 {
-       struct gpio_rcar_config *pdata = p->pdev->dev.platform_data;
+       struct gpio_rcar_config *pdata = dev_get_platdata(&p->pdev->dev);
        struct device_node *np = p->pdev->dev.of_node;
        struct of_phandle_args args;
        int ret;
index 368c3c00fca5973fd02bcb5661af1546ded23e16..88577c3272a5536871f903e199aaf2a7bd37d3eb 100644 (file)
@@ -135,7 +135,7 @@ static int rdc321x_gpio_probe(struct platform_device *pdev)
        struct rdc321x_gpio *rdc321x_gpio_dev;
        struct rdc321x_gpio_pdata *pdata;
 
-       pdata = pdev->dev.platform_data;
+       pdata = dev_get_platdata(&pdev->dev);
        if (!pdata) {
                dev_err(&pdev->dev, "no platform data supplied\n");
                return -ENODEV;
index a1392f47bbda5b06b55f41035cf728b0e38d97a5..358a21c2d811bc6637960ed167ae8e95260ecfca 100644 (file)
@@ -161,28 +161,6 @@ int s3c24xx_gpio_setpull_1down(struct samsung_gpio_chip *chip,
        return s3c24xx_gpio_setpull_1(chip, off, pull, S3C_GPIO_PULL_DOWN);
 }
 
-static int exynos_gpio_setpull(struct samsung_gpio_chip *chip,
-                               unsigned int off, samsung_gpio_pull_t pull)
-{
-       if (pull == S3C_GPIO_PULL_UP)
-               pull = 3;
-
-       return samsung_gpio_setpull_updown(chip, off, pull);
-}
-
-static samsung_gpio_pull_t exynos_gpio_getpull(struct samsung_gpio_chip *chip,
-                                               unsigned int off)
-{
-       samsung_gpio_pull_t pull;
-
-       pull = samsung_gpio_getpull_updown(chip, off);
-
-       if (pull == 3)
-               pull = S3C_GPIO_PULL_UP;
-
-       return pull;
-}
-
 /*
  * samsung_gpio_setcfg_2bit - Samsung 2bit style GPIO configuration.
  * @chip: The gpio chip that is being configured.
@@ -444,15 +422,6 @@ static struct samsung_gpio_cfg s3c24xx_gpiocfg_banka = {
 };
 #endif
 
-#if defined(CONFIG_ARCH_EXYNOS4) || defined(CONFIG_SOC_EXYNOS5250)
-static struct samsung_gpio_cfg exynos_gpio_cfg = {
-       .set_pull       = exynos_gpio_setpull,
-       .get_pull       = exynos_gpio_getpull,
-       .set_config     = samsung_gpio_setcfg_4bit,
-       .get_config     = samsung_gpio_getcfg_4bit,
-};
-#endif
-
 #if defined(CONFIG_CPU_S5P6440) || defined(CONFIG_CPU_S5P6450)
 static struct samsung_gpio_cfg s5p64x0_gpio_cfg_rbank = {
        .cfg_eint       = 0x3,
@@ -495,15 +464,6 @@ static struct samsung_gpio_cfg samsung_gpio_cfgs[] = {
                .set_config     = samsung_gpio_setcfg_2bit,
                .get_config     = samsung_gpio_getcfg_2bit,
        },
-       [8] = {
-               .set_pull       = exynos_gpio_setpull,
-               .get_pull       = exynos_gpio_getpull,
-       },
-       [9] = {
-               .cfg_eint       = 0x3,
-               .set_pull       = exynos_gpio_setpull,
-               .get_pull       = exynos_gpio_getpull,
-       }
 };
 
 /*
@@ -2115,833 +2075,6 @@ static struct samsung_gpio_chip s5pv210_gpios_4bit[] = {
 #endif
 };
 
-/*
- * Followings are the gpio banks in EXYNOS SoCs
- *
- * The 'config' member when left to NULL, is initialized to the default
- * structure exynos_gpio_cfg in the init function below.
- *
- * The 'base' member is also initialized in the init function below.
- * Note: The initialization of 'base' member of samsung_gpio_chip structure
- * uses the above macro and depends on the banks being listed in order here.
- */
-
-#ifdef CONFIG_ARCH_EXYNOS4
-static struct samsung_gpio_chip exynos4_gpios_1[] = {
-       {
-               .chip   = {
-                       .base   = EXYNOS4_GPA0(0),
-                       .ngpio  = EXYNOS4_GPIO_A0_NR,
-                       .label  = "GPA0",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPA1(0),
-                       .ngpio  = EXYNOS4_GPIO_A1_NR,
-                       .label  = "GPA1",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPB(0),
-                       .ngpio  = EXYNOS4_GPIO_B_NR,
-                       .label  = "GPB",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPC0(0),
-                       .ngpio  = EXYNOS4_GPIO_C0_NR,
-                       .label  = "GPC0",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPC1(0),
-                       .ngpio  = EXYNOS4_GPIO_C1_NR,
-                       .label  = "GPC1",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPD0(0),
-                       .ngpio  = EXYNOS4_GPIO_D0_NR,
-                       .label  = "GPD0",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPD1(0),
-                       .ngpio  = EXYNOS4_GPIO_D1_NR,
-                       .label  = "GPD1",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPE0(0),
-                       .ngpio  = EXYNOS4_GPIO_E0_NR,
-                       .label  = "GPE0",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPE1(0),
-                       .ngpio  = EXYNOS4_GPIO_E1_NR,
-                       .label  = "GPE1",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPE2(0),
-                       .ngpio  = EXYNOS4_GPIO_E2_NR,
-                       .label  = "GPE2",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPE3(0),
-                       .ngpio  = EXYNOS4_GPIO_E3_NR,
-                       .label  = "GPE3",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPE4(0),
-                       .ngpio  = EXYNOS4_GPIO_E4_NR,
-                       .label  = "GPE4",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPF0(0),
-                       .ngpio  = EXYNOS4_GPIO_F0_NR,
-                       .label  = "GPF0",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPF1(0),
-                       .ngpio  = EXYNOS4_GPIO_F1_NR,
-                       .label  = "GPF1",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPF2(0),
-                       .ngpio  = EXYNOS4_GPIO_F2_NR,
-                       .label  = "GPF2",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPF3(0),
-                       .ngpio  = EXYNOS4_GPIO_F3_NR,
-                       .label  = "GPF3",
-               },
-       },
-};
-#endif
-
-#ifdef CONFIG_ARCH_EXYNOS4
-static struct samsung_gpio_chip exynos4_gpios_2[] = {
-       {
-               .chip   = {
-                       .base   = EXYNOS4_GPJ0(0),
-                       .ngpio  = EXYNOS4_GPIO_J0_NR,
-                       .label  = "GPJ0",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPJ1(0),
-                       .ngpio  = EXYNOS4_GPIO_J1_NR,
-                       .label  = "GPJ1",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPK0(0),
-                       .ngpio  = EXYNOS4_GPIO_K0_NR,
-                       .label  = "GPK0",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPK1(0),
-                       .ngpio  = EXYNOS4_GPIO_K1_NR,
-                       .label  = "GPK1",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPK2(0),
-                       .ngpio  = EXYNOS4_GPIO_K2_NR,
-                       .label  = "GPK2",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPK3(0),
-                       .ngpio  = EXYNOS4_GPIO_K3_NR,
-                       .label  = "GPK3",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPL0(0),
-                       .ngpio  = EXYNOS4_GPIO_L0_NR,
-                       .label  = "GPL0",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPL1(0),
-                       .ngpio  = EXYNOS4_GPIO_L1_NR,
-                       .label  = "GPL1",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPL2(0),
-                       .ngpio  = EXYNOS4_GPIO_L2_NR,
-                       .label  = "GPL2",
-               },
-       }, {
-               .config = &samsung_gpio_cfgs[8],
-               .chip   = {
-                       .base   = EXYNOS4_GPY0(0),
-                       .ngpio  = EXYNOS4_GPIO_Y0_NR,
-                       .label  = "GPY0",
-               },
-       }, {
-               .config = &samsung_gpio_cfgs[8],
-               .chip   = {
-                       .base   = EXYNOS4_GPY1(0),
-                       .ngpio  = EXYNOS4_GPIO_Y1_NR,
-                       .label  = "GPY1",
-               },
-       }, {
-               .config = &samsung_gpio_cfgs[8],
-               .chip   = {
-                       .base   = EXYNOS4_GPY2(0),
-                       .ngpio  = EXYNOS4_GPIO_Y2_NR,
-                       .label  = "GPY2",
-               },
-       }, {
-               .config = &samsung_gpio_cfgs[8],
-               .chip   = {
-                       .base   = EXYNOS4_GPY3(0),
-                       .ngpio  = EXYNOS4_GPIO_Y3_NR,
-                       .label  = "GPY3",
-               },
-       }, {
-               .config = &samsung_gpio_cfgs[8],
-               .chip   = {
-                       .base   = EXYNOS4_GPY4(0),
-                       .ngpio  = EXYNOS4_GPIO_Y4_NR,
-                       .label  = "GPY4",
-               },
-       }, {
-               .config = &samsung_gpio_cfgs[8],
-               .chip   = {
-                       .base   = EXYNOS4_GPY5(0),
-                       .ngpio  = EXYNOS4_GPIO_Y5_NR,
-                       .label  = "GPY5",
-               },
-       }, {
-               .config = &samsung_gpio_cfgs[8],
-               .chip   = {
-                       .base   = EXYNOS4_GPY6(0),
-                       .ngpio  = EXYNOS4_GPIO_Y6_NR,
-                       .label  = "GPY6",
-               },
-       }, {
-               .config = &samsung_gpio_cfgs[9],
-               .irq_base = IRQ_EINT(0),
-               .chip   = {
-                       .base   = EXYNOS4_GPX0(0),
-                       .ngpio  = EXYNOS4_GPIO_X0_NR,
-                       .label  = "GPX0",
-                       .to_irq = samsung_gpiolib_to_irq,
-               },
-       }, {
-               .config = &samsung_gpio_cfgs[9],
-               .irq_base = IRQ_EINT(8),
-               .chip   = {
-                       .base   = EXYNOS4_GPX1(0),
-                       .ngpio  = EXYNOS4_GPIO_X1_NR,
-                       .label  = "GPX1",
-                       .to_irq = samsung_gpiolib_to_irq,
-               },
-       }, {
-               .config = &samsung_gpio_cfgs[9],
-               .irq_base = IRQ_EINT(16),
-               .chip   = {
-                       .base   = EXYNOS4_GPX2(0),
-                       .ngpio  = EXYNOS4_GPIO_X2_NR,
-                       .label  = "GPX2",
-                       .to_irq = samsung_gpiolib_to_irq,
-               },
-       }, {
-               .config = &samsung_gpio_cfgs[9],
-               .irq_base = IRQ_EINT(24),
-               .chip   = {
-                       .base   = EXYNOS4_GPX3(0),
-                       .ngpio  = EXYNOS4_GPIO_X3_NR,
-                       .label  = "GPX3",
-                       .to_irq = samsung_gpiolib_to_irq,
-               },
-       },
-};
-#endif
-
-#ifdef CONFIG_ARCH_EXYNOS4
-static struct samsung_gpio_chip exynos4_gpios_3[] = {
-       {
-               .chip   = {
-                       .base   = EXYNOS4_GPZ(0),
-                       .ngpio  = EXYNOS4_GPIO_Z_NR,
-                       .label  = "GPZ",
-               },
-       },
-};
-#endif
-
-#ifdef CONFIG_SOC_EXYNOS5250
-static struct samsung_gpio_chip exynos5_gpios_1[] = {
-       {
-               .chip   = {
-                       .base   = EXYNOS5_GPA0(0),
-                       .ngpio  = EXYNOS5_GPIO_A0_NR,
-                       .label  = "GPA0",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS5_GPA1(0),
-                       .ngpio  = EXYNOS5_GPIO_A1_NR,
-                       .label  = "GPA1",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS5_GPA2(0),
-                       .ngpio  = EXYNOS5_GPIO_A2_NR,
-                       .label  = "GPA2",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS5_GPB0(0),
-                       .ngpio  = EXYNOS5_GPIO_B0_NR,
-                       .label  = "GPB0",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS5_GPB1(0),
-                       .ngpio  = EXYNOS5_GPIO_B1_NR,
-                       .label  = "GPB1",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS5_GPB2(0),
-                       .ngpio  = EXYNOS5_GPIO_B2_NR,
-                       .label  = "GPB2",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS5_GPB3(0),
-                       .ngpio  = EXYNOS5_GPIO_B3_NR,
-                       .label  = "GPB3",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS5_GPC0(0),
-                       .ngpio  = EXYNOS5_GPIO_C0_NR,
-                       .label  = "GPC0",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS5_GPC1(0),
-                       .ngpio  = EXYNOS5_GPIO_C1_NR,
-                       .label  = "GPC1",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS5_GPC2(0),
-                       .ngpio  = EXYNOS5_GPIO_C2_NR,
-                       .label  = "GPC2",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS5_GPC3(0),
-                       .ngpio  = EXYNOS5_GPIO_C3_NR,
-                       .label  = "GPC3",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS5_GPD0(0),
-                       .ngpio  = EXYNOS5_GPIO_D0_NR,
-                       .label  = "GPD0",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS5_GPD1(0),
-                       .ngpio  = EXYNOS5_GPIO_D1_NR,
-                       .label  = "GPD1",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS5_GPY0(0),
-                       .ngpio  = EXYNOS5_GPIO_Y0_NR,
-                       .label  = "GPY0",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS5_GPY1(0),
-                       .ngpio  = EXYNOS5_GPIO_Y1_NR,
-                       .label  = "GPY1",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS5_GPY2(0),
-                       .ngpio  = EXYNOS5_GPIO_Y2_NR,
-                       .label  = "GPY2",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS5_GPY3(0),
-                       .ngpio  = EXYNOS5_GPIO_Y3_NR,
-                       .label  = "GPY3",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS5_GPY4(0),
-                       .ngpio  = EXYNOS5_GPIO_Y4_NR,
-                       .label  = "GPY4",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS5_GPY5(0),
-                       .ngpio  = EXYNOS5_GPIO_Y5_NR,
-                       .label  = "GPY5",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS5_GPY6(0),
-                       .ngpio  = EXYNOS5_GPIO_Y6_NR,
-                       .label  = "GPY6",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS5_GPC4(0),
-                       .ngpio  = EXYNOS5_GPIO_C4_NR,
-                       .label  = "GPC4",
-               },
-       }, {
-               .config = &samsung_gpio_cfgs[9],
-               .irq_base = IRQ_EINT(0),
-               .chip   = {
-                       .base   = EXYNOS5_GPX0(0),
-                       .ngpio  = EXYNOS5_GPIO_X0_NR,
-                       .label  = "GPX0",
-                       .to_irq = samsung_gpiolib_to_irq,
-               },
-       }, {
-               .config = &samsung_gpio_cfgs[9],
-               .irq_base = IRQ_EINT(8),
-               .chip   = {
-                       .base   = EXYNOS5_GPX1(0),
-                       .ngpio  = EXYNOS5_GPIO_X1_NR,
-                       .label  = "GPX1",
-                       .to_irq = samsung_gpiolib_to_irq,
-               },
-       }, {
-               .config = &samsung_gpio_cfgs[9],
-               .irq_base = IRQ_EINT(16),
-               .chip   = {
-                       .base   = EXYNOS5_GPX2(0),
-                       .ngpio  = EXYNOS5_GPIO_X2_NR,
-                       .label  = "GPX2",
-                       .to_irq = samsung_gpiolib_to_irq,
-               },
-       }, {
-               .config = &samsung_gpio_cfgs[9],
-               .irq_base = IRQ_EINT(24),
-               .chip   = {
-                       .base   = EXYNOS5_GPX3(0),
-                       .ngpio  = EXYNOS5_GPIO_X3_NR,
-                       .label  = "GPX3",
-                       .to_irq = samsung_gpiolib_to_irq,
-               },
-       },
-};
-#endif
-
-#ifdef CONFIG_SOC_EXYNOS5250
-static struct samsung_gpio_chip exynos5_gpios_2[] = {
-       {
-               .chip   = {
-                       .base   = EXYNOS5_GPE0(0),
-                       .ngpio  = EXYNOS5_GPIO_E0_NR,
-                       .label  = "GPE0",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS5_GPE1(0),
-                       .ngpio  = EXYNOS5_GPIO_E1_NR,
-                       .label  = "GPE1",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS5_GPF0(0),
-                       .ngpio  = EXYNOS5_GPIO_F0_NR,
-                       .label  = "GPF0",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS5_GPF1(0),
-                       .ngpio  = EXYNOS5_GPIO_F1_NR,
-                       .label  = "GPF1",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS5_GPG0(0),
-                       .ngpio  = EXYNOS5_GPIO_G0_NR,
-                       .label  = "GPG0",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS5_GPG1(0),
-                       .ngpio  = EXYNOS5_GPIO_G1_NR,
-                       .label  = "GPG1",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS5_GPG2(0),
-                       .ngpio  = EXYNOS5_GPIO_G2_NR,
-                       .label  = "GPG2",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS5_GPH0(0),
-                       .ngpio  = EXYNOS5_GPIO_H0_NR,
-                       .label  = "GPH0",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS5_GPH1(0),
-                       .ngpio  = EXYNOS5_GPIO_H1_NR,
-                       .label  = "GPH1",
-
-               },
-       },
-};
-#endif
-
-#ifdef CONFIG_SOC_EXYNOS5250
-static struct samsung_gpio_chip exynos5_gpios_3[] = {
-       {
-               .chip   = {
-                       .base   = EXYNOS5_GPV0(0),
-                       .ngpio  = EXYNOS5_GPIO_V0_NR,
-                       .label  = "GPV0",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS5_GPV1(0),
-                       .ngpio  = EXYNOS5_GPIO_V1_NR,
-                       .label  = "GPV1",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS5_GPV2(0),
-                       .ngpio  = EXYNOS5_GPIO_V2_NR,
-                       .label  = "GPV2",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS5_GPV3(0),
-                       .ngpio  = EXYNOS5_GPIO_V3_NR,
-                       .label  = "GPV3",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS5_GPV4(0),
-                       .ngpio  = EXYNOS5_GPIO_V4_NR,
-                       .label  = "GPV4",
-               },
-       },
-};
-#endif
-
-#ifdef CONFIG_SOC_EXYNOS5250
-static struct samsung_gpio_chip exynos5_gpios_4[] = {
-       {
-               .chip   = {
-                       .base   = EXYNOS5_GPZ(0),
-                       .ngpio  = EXYNOS5_GPIO_Z_NR,
-                       .label  = "GPZ",
-               },
-       },
-};
-#endif
-
-
-#if defined(CONFIG_ARCH_EXYNOS) && defined(CONFIG_OF)
-static int exynos_gpio_xlate(struct gpio_chip *gc,
-                       const struct of_phandle_args *gpiospec, u32 *flags)
-{
-       unsigned int pin;
-
-       if (WARN_ON(gc->of_gpio_n_cells < 4))
-               return -EINVAL;
-
-       if (WARN_ON(gpiospec->args_count < gc->of_gpio_n_cells))
-               return -EINVAL;
-
-       if (gpiospec->args[0] > gc->ngpio)
-               return -EINVAL;
-
-       pin = gc->base + gpiospec->args[0];
-
-       if (s3c_gpio_cfgpin(pin, S3C_GPIO_SFN(gpiospec->args[1])))
-               pr_warn("gpio_xlate: failed to set pin function\n");
-       if (s3c_gpio_setpull(pin, gpiospec->args[2] & 0xffff))
-               pr_warn("gpio_xlate: failed to set pin pull up/down\n");
-       if (s5p_gpio_set_drvstr(pin, gpiospec->args[3]))
-               pr_warn("gpio_xlate: failed to set pin drive strength\n");
-
-       if (flags)
-               *flags = gpiospec->args[2] >> 16;
-
-       return gpiospec->args[0];
-}
-
-static const struct of_device_id exynos_gpio_dt_match[] __initdata = {
-       { .compatible = "samsung,exynos4-gpio", },
-       {}
-};
-
-static __init void exynos_gpiolib_attach_ofnode(struct samsung_gpio_chip *chip,
-                                               u64 base, u64 offset)
-{
-       struct gpio_chip *gc =  &chip->chip;
-       u64 address;
-
-       if (!of_have_populated_dt())
-               return;
-
-       address = chip->base ? base + ((u32)chip->base & 0xfff) : base + offset;
-       gc->of_node = of_find_matching_node_by_address(NULL,
-                       exynos_gpio_dt_match, address);
-       if (!gc->of_node) {
-               pr_info("gpio: device tree node not found for gpio controller"
-                       " with base address %08llx\n", address);
-               return;
-       }
-       gc->of_gpio_n_cells = 4;
-       gc->of_xlate = exynos_gpio_xlate;
-}
-#elif defined(CONFIG_ARCH_EXYNOS)
-static __init void exynos_gpiolib_attach_ofnode(struct samsung_gpio_chip *chip,
-                                               u64 base, u64 offset)
-{
-       return;
-}
-#endif /* defined(CONFIG_ARCH_EXYNOS) && defined(CONFIG_OF) */
-
-static __init void exynos4_gpiolib_init(void)
-{
-#ifdef CONFIG_CPU_EXYNOS4210
-       struct samsung_gpio_chip *chip;
-       int i, nr_chips;
-       void __iomem *gpio_base1, *gpio_base2, *gpio_base3;
-       int group = 0;
-       void __iomem *gpx_base;
-
-       /* gpio part1 */
-       gpio_base1 = ioremap(EXYNOS4_PA_GPIO1, SZ_4K);
-       if (gpio_base1 == NULL) {
-               pr_err("unable to ioremap for gpio_base1\n");
-               goto err_ioremap1;
-       }
-
-       chip = exynos4_gpios_1;
-       nr_chips = ARRAY_SIZE(exynos4_gpios_1);
-
-       for (i = 0; i < nr_chips; i++, chip++) {
-               if (!chip->config) {
-                       chip->config = &exynos_gpio_cfg;
-                       chip->group = group++;
-               }
-               exynos_gpiolib_attach_ofnode(chip,
-                               EXYNOS4_PA_GPIO1, i * 0x20);
-       }
-       samsung_gpiolib_add_4bit_chips(exynos4_gpios_1,
-                                      nr_chips, gpio_base1);
-
-       /* gpio part2 */
-       gpio_base2 = ioremap(EXYNOS4_PA_GPIO2, SZ_4K);
-       if (gpio_base2 == NULL) {
-               pr_err("unable to ioremap for gpio_base2\n");
-               goto err_ioremap2;
-       }
-
-       /* need to set base address for gpx */
-       chip = &exynos4_gpios_2[16];
-       gpx_base = gpio_base2 + 0xC00;
-       for (i = 0; i < 4; i++, chip++, gpx_base += 0x20)
-               chip->base = gpx_base;
-
-       chip = exynos4_gpios_2;
-       nr_chips = ARRAY_SIZE(exynos4_gpios_2);
-
-       for (i = 0; i < nr_chips; i++, chip++) {
-               if (!chip->config) {
-                       chip->config = &exynos_gpio_cfg;
-                       chip->group = group++;
-               }
-               exynos_gpiolib_attach_ofnode(chip,
-                               EXYNOS4_PA_GPIO2, i * 0x20);
-       }
-       samsung_gpiolib_add_4bit_chips(exynos4_gpios_2,
-                                      nr_chips, gpio_base2);
-
-       /* gpio part3 */
-       gpio_base3 = ioremap(EXYNOS4_PA_GPIO3, SZ_256);
-       if (gpio_base3 == NULL) {
-               pr_err("unable to ioremap for gpio_base3\n");
-               goto err_ioremap3;
-       }
-
-       chip = exynos4_gpios_3;
-       nr_chips = ARRAY_SIZE(exynos4_gpios_3);
-
-       for (i = 0; i < nr_chips; i++, chip++) {
-               if (!chip->config) {
-                       chip->config = &exynos_gpio_cfg;
-                       chip->group = group++;
-               }
-               exynos_gpiolib_attach_ofnode(chip,
-                               EXYNOS4_PA_GPIO3, i * 0x20);
-       }
-       samsung_gpiolib_add_4bit_chips(exynos4_gpios_3,
-                                      nr_chips, gpio_base3);
-
-#if defined(CONFIG_CPU_EXYNOS4210) && defined(CONFIG_S5P_GPIO_INT)
-       s5p_register_gpioint_bank(IRQ_GPIO_XA, 0, IRQ_GPIO1_NR_GROUPS);
-       s5p_register_gpioint_bank(IRQ_GPIO_XB, IRQ_GPIO1_NR_GROUPS, IRQ_GPIO2_NR_GROUPS);
-#endif
-
-       return;
-
-err_ioremap3:
-       iounmap(gpio_base2);
-err_ioremap2:
-       iounmap(gpio_base1);
-err_ioremap1:
-       return;
-#endif /* CONFIG_CPU_EXYNOS4210 */
-}
-
-static __init void exynos5_gpiolib_init(void)
-{
-#ifdef CONFIG_SOC_EXYNOS5250
-       struct samsung_gpio_chip *chip;
-       int i, nr_chips;
-       void __iomem *gpio_base1, *gpio_base2, *gpio_base3, *gpio_base4;
-       int group = 0;
-       void __iomem *gpx_base;
-
-       /* gpio part1 */
-       gpio_base1 = ioremap(EXYNOS5_PA_GPIO1, SZ_4K);
-       if (gpio_base1 == NULL) {
-               pr_err("unable to ioremap for gpio_base1\n");
-               goto err_ioremap1;
-       }
-
-       /* need to set base address for gpc4 */
-       exynos5_gpios_1[20].base = gpio_base1 + 0x2E0;
-
-       /* need to set base address for gpx */
-       chip = &exynos5_gpios_1[21];
-       gpx_base = gpio_base1 + 0xC00;
-       for (i = 0; i < 4; i++, chip++, gpx_base += 0x20)
-               chip->base = gpx_base;
-
-       chip = exynos5_gpios_1;
-       nr_chips = ARRAY_SIZE(exynos5_gpios_1);
-
-       for (i = 0; i < nr_chips; i++, chip++) {
-               if (!chip->config) {
-                       chip->config = &exynos_gpio_cfg;
-                       chip->group = group++;
-               }
-               exynos_gpiolib_attach_ofnode(chip,
-                               EXYNOS5_PA_GPIO1, i * 0x20);
-       }
-       samsung_gpiolib_add_4bit_chips(exynos5_gpios_1,
-                                      nr_chips, gpio_base1);
-
-       /* gpio part2 */
-       gpio_base2 = ioremap(EXYNOS5_PA_GPIO2, SZ_4K);
-       if (gpio_base2 == NULL) {
-               pr_err("unable to ioremap for gpio_base2\n");
-               goto err_ioremap2;
-       }
-
-       chip = exynos5_gpios_2;
-       nr_chips = ARRAY_SIZE(exynos5_gpios_2);
-
-       for (i = 0; i < nr_chips; i++, chip++) {
-               if (!chip->config) {
-                       chip->config = &exynos_gpio_cfg;
-                       chip->group = group++;
-               }
-               exynos_gpiolib_attach_ofnode(chip,
-                               EXYNOS5_PA_GPIO2, i * 0x20);
-       }
-       samsung_gpiolib_add_4bit_chips(exynos5_gpios_2,
-                                      nr_chips, gpio_base2);
-
-       /* gpio part3 */
-       gpio_base3 = ioremap(EXYNOS5_PA_GPIO3, SZ_4K);
-       if (gpio_base3 == NULL) {
-               pr_err("unable to ioremap for gpio_base3\n");
-               goto err_ioremap3;
-       }
-
-       /* need to set base address for gpv */
-       exynos5_gpios_3[0].base = gpio_base3;
-       exynos5_gpios_3[1].base = gpio_base3 + 0x20;
-       exynos5_gpios_3[2].base = gpio_base3 + 0x60;
-       exynos5_gpios_3[3].base = gpio_base3 + 0x80;
-       exynos5_gpios_3[4].base = gpio_base3 + 0xC0;
-
-       chip = exynos5_gpios_3;
-       nr_chips = ARRAY_SIZE(exynos5_gpios_3);
-
-       for (i = 0; i < nr_chips; i++, chip++) {
-               if (!chip->config) {
-                       chip->config = &exynos_gpio_cfg;
-                       chip->group = group++;
-               }
-               exynos_gpiolib_attach_ofnode(chip,
-                               EXYNOS5_PA_GPIO3, i * 0x20);
-       }
-       samsung_gpiolib_add_4bit_chips(exynos5_gpios_3,
-                                      nr_chips, gpio_base3);
-
-       /* gpio part4 */
-       gpio_base4 = ioremap(EXYNOS5_PA_GPIO4, SZ_4K);
-       if (gpio_base4 == NULL) {
-               pr_err("unable to ioremap for gpio_base4\n");
-               goto err_ioremap4;
-       }
-
-       chip = exynos5_gpios_4;
-       nr_chips = ARRAY_SIZE(exynos5_gpios_4);
-
-       for (i = 0; i < nr_chips; i++, chip++) {
-               if (!chip->config) {
-                       chip->config = &exynos_gpio_cfg;
-                       chip->group = group++;
-               }
-               exynos_gpiolib_attach_ofnode(chip,
-                               EXYNOS5_PA_GPIO4, i * 0x20);
-       }
-       samsung_gpiolib_add_4bit_chips(exynos5_gpios_4,
-                                      nr_chips, gpio_base4);
-       return;
-
-err_ioremap4:
-       iounmap(gpio_base3);
-err_ioremap3:
-       iounmap(gpio_base2);
-err_ioremap2:
-       iounmap(gpio_base1);
-err_ioremap1:
-       return;
-
-#endif /* CONFIG_SOC_EXYNOS5250 */
-}
-
 /* TODO: cleanup soc_is_* */
 static __init int samsung_gpiolib_init(void)
 {
@@ -3040,10 +2173,6 @@ static __init int samsung_gpiolib_init(void)
 #if defined(CONFIG_CPU_S5PV210) && defined(CONFIG_S5P_GPIO_INT)
                s5p_register_gpioint_bank(IRQ_GPIOINT, 0, S5P_GPIOINT_GROUP_MAXNR);
 #endif
-       } else if (soc_is_exynos4210()) {
-               exynos4_gpiolib_init();
-       } else if (soc_is_exynos5250()) {
-               exynos5_gpiolib_init();
        } else {
                WARN(1, "Unknown SoC in gpio-samsung, no GPIOs added\n");
                return -ENODEV;
index 7a4bf7c0d98f266197f3d06fa069564f2028cbeb..e9a0415834ea5240e16994420660ea5131744070 100644 (file)
@@ -128,18 +128,13 @@ static int spics_gpio_probe(struct platform_device *pdev)
        struct resource *res;
        int ret;
 
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               dev_err(&pdev->dev, "invalid IORESOURCE_MEM\n");
-               return -EBUSY;
-       }
-
        spics = devm_kzalloc(&pdev->dev, sizeof(*spics), GFP_KERNEL);
        if (!spics) {
                dev_err(&pdev->dev, "memory allocation fail\n");
                return -ENOMEM;
        }
 
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        spics->base = devm_ioremap_resource(&pdev->dev, res);
        if (IS_ERR(spics->base))
                return PTR_ERR(spics->base);
index f43ab6aea281d2f20c03608a495a32b4c0ed2d49..f2fb12c18da97616b24b9232ac7ce8d271424115 100644 (file)
@@ -361,7 +361,7 @@ static int gsta_probe(struct platform_device *dev)
        struct gsta_gpio *chip;
        struct resource *res;
 
-       pdev = *(struct pci_dev **)(dev->dev.platform_data);
+       pdev = *(struct pci_dev **)dev_get_platdata(&dev->dev);
        gpio_pdata = dev_get_platdata(&pdev->dev);
 
        if (gpio_pdata == NULL)
index f371732591d2ab894798dd224dab6062094bfec0..d2983e9ad6af78ee1705b6377cea93f5de41d245 100644 (file)
@@ -583,7 +583,7 @@ static int sx150x_probe(struct i2c_client *client,
        struct sx150x_chip *chip;
        int rc;
 
-       pdata = client->dev.platform_data;
+       pdata = dev_get_platdata(&client->dev);
        if (!pdata)
                return -EINVAL;
 
index 4c65f8883204b95417c143e61aa5e3d9027ea5c9..7a0e956ef1ed1b47d8d034bf8e48ed3f812010f3 100644 (file)
@@ -227,7 +227,7 @@ static int timbgpio_probe(struct platform_device *pdev)
        struct gpio_chip *gc;
        struct timbgpio *tgpio;
        struct resource *iomem;
-       struct timbgpio_platform_data *pdata = pdev->dev.platform_data;
+       struct timbgpio_platform_data *pdata = dev_get_platdata(&pdev->dev);
        int irq = platform_get_irq(pdev, 0);
 
        if (!pdata || pdata->nr_pins > 32) {
@@ -318,7 +318,7 @@ err_mem:
 static int timbgpio_remove(struct platform_device *pdev)
 {
        int err;
-       struct timbgpio_platform_data *pdata = pdev->dev.platform_data;
+       struct timbgpio_platform_data *pdata = dev_get_platdata(&pdev->dev);
        struct timbgpio *tgpio = platform_get_drvdata(pdev);
        struct resource *iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        int irq = platform_get_irq(pdev, 0);
index 30a5844a7dca212d0d36f17c6ccc26b6778e59b8..276a4229b032583379dd1490716dd98565c6bca3 100644 (file)
@@ -87,7 +87,7 @@ static struct gpio_chip template_chip = {
 static int tps65912_gpio_probe(struct platform_device *pdev)
 {
        struct tps65912 *tps65912 = dev_get_drvdata(pdev->dev.parent);
-       struct tps65912_board *pdata = tps65912->dev->platform_data;
+       struct tps65912_board *pdata = dev_get_platdata(tps65912->dev);
        struct tps65912_gpio_data *tps65912_gpio;
        int ret;
 
index cc53cab8df2acb89042673347acf128056c57026..3df3ebdb3e5267f5e4ea1575ff9d6217a950f36a 100644 (file)
@@ -322,7 +322,7 @@ static void ts5500_disable_irq(struct ts5500_priv *priv)
 static int ts5500_dio_probe(struct platform_device *pdev)
 {
        enum ts5500_blocks block = platform_get_device_id(pdev)->driver_data;
-       struct ts5500_dio_platform_data *pdata = pdev->dev.platform_data;
+       struct ts5500_dio_platform_data *pdata = dev_get_platdata(&pdev->dev);
        struct device *dev = &pdev->dev;
        const char *name = dev_name(dev);
        struct ts5500_priv *priv;
index 4d330e36da1da0e6c68a3dcd40a075c571f857bd..d8e4f6efcb29315fe77f6cecc52d3048c3e1f270 100644 (file)
@@ -256,7 +256,7 @@ static int twl_request(struct gpio_chip *chip, unsigned offset)
                /* optionally have the first two GPIOs switch vMMC1
                 * and vMMC2 power supplies based on card presence.
                 */
-               pdata = chip->dev->platform_data;
+               pdata = dev_get_platdata(chip->dev);
                if (pdata)
                        value |= pdata->mmc_cd & 0x03;
 
@@ -460,7 +460,7 @@ static struct twl4030_gpio_platform_data *of_gpio_twl4030(struct device *dev)
 
 static int gpio_twl4030_probe(struct platform_device *pdev)
 {
-       struct twl4030_gpio_platform_data *pdata = pdev->dev.platform_data;
+       struct twl4030_gpio_platform_data *pdata = dev_get_platdata(&pdev->dev);
        struct device_node *node = pdev->dev.of_node;
        struct gpio_twl4030_priv *priv;
        int ret, irq_base;
@@ -556,7 +556,7 @@ out:
 /* Cannot use as gpio_twl4030_probe() calls us */
 static int gpio_twl4030_remove(struct platform_device *pdev)
 {
-       struct twl4030_gpio_platform_data *pdata = pdev->dev.platform_data;
+       struct twl4030_gpio_platform_data *pdata = dev_get_platdata(&pdev->dev);
        struct gpio_twl4030_priv *priv = platform_get_drvdata(pdev);
        int status;
 
index 0be82c6dd796cf5e0daac94f1804afcef8750273..d420d30b86e73233314b74f36d8412b4e0c01166 100644 (file)
@@ -84,15 +84,11 @@ static struct gpio_chip twl6040gpo_chip = {
 
 static int gpo_twl6040_probe(struct platform_device *pdev)
 {
-       struct twl6040_gpo_data *pdata = pdev->dev.platform_data;
        struct device *twl6040_core_dev = pdev->dev.parent;
        struct twl6040 *twl6040 = dev_get_drvdata(twl6040_core_dev);
        int ret;
 
-       if (pdata)
-               twl6040gpo_chip.base = pdata->gpio_base;
-       else
-               twl6040gpo_chip.base = -1;
+       twl6040gpo_chip.base = -1;
 
        if (twl6040_get_revid(twl6040) < TWL6041_REV_ES2_0)
                twl6040gpo_chip.ngpio = 3; /* twl6040 have 3 GPO */
diff --git a/drivers/gpio/gpio-tz1090-pdc.c b/drivers/gpio/gpio-tz1090-pdc.c
new file mode 100644 (file)
index 0000000..f512da2
--- /dev/null
@@ -0,0 +1,243 @@
+/*
+ * Toumaz Xenif TZ1090 PDC GPIO handling.
+ *
+ * Copyright (C) 2012-2013 Imagination Technologies Ltd.
+ *
+ * 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/bitops.h>
+#include <linux/gpio.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_irq.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/syscore_ops.h>
+#include <asm/global_lock.h>
+
+/* Register offsets from SOC_GPIO_CONTROL0 */
+#define REG_SOC_GPIO_CONTROL0  0x00
+#define REG_SOC_GPIO_CONTROL1  0x04
+#define REG_SOC_GPIO_CONTROL2  0x08
+#define REG_SOC_GPIO_CONTROL3  0x0c
+#define REG_SOC_GPIO_STATUS    0x80
+
+/* PDC GPIOs go after normal GPIOs */
+#define GPIO_PDC_BASE          90
+#define GPIO_PDC_NGPIO         7
+
+/* Out of PDC gpios, only syswakes have irqs */
+#define GPIO_PDC_IRQ_FIRST     2
+#define GPIO_PDC_NIRQ          3
+
+/**
+ * struct tz1090_pdc_gpio - GPIO bank private data
+ * @chip:      Generic GPIO chip for GPIO bank
+ * @reg:       Base of registers, offset for this GPIO bank
+ * @irq:       IRQ numbers for Syswake GPIOs
+ *
+ * This is the main private data for the PDC GPIO driver. It encapsulates a
+ * gpio_chip, and the callbacks for the gpio_chip can access the private data
+ * with the to_pdc() macro below.
+ */
+struct tz1090_pdc_gpio {
+       struct gpio_chip chip;
+       void __iomem *reg;
+       int irq[GPIO_PDC_NIRQ];
+};
+#define to_pdc(c)      container_of(c, struct tz1090_pdc_gpio, chip)
+
+/* Register accesses into the PDC MMIO area */
+
+static inline void pdc_write(struct tz1090_pdc_gpio *priv, unsigned int reg_offs,
+                     unsigned int data)
+{
+       writel(data, priv->reg + reg_offs);
+}
+
+static inline unsigned int pdc_read(struct tz1090_pdc_gpio *priv,
+                            unsigned int reg_offs)
+{
+       return readl(priv->reg + reg_offs);
+}
+
+/* Generic GPIO interface */
+
+static int tz1090_pdc_gpio_direction_input(struct gpio_chip *chip,
+                                          unsigned int offset)
+{
+       struct tz1090_pdc_gpio *priv = to_pdc(chip);
+       u32 value;
+       int lstat;
+
+       __global_lock2(lstat);
+       value = pdc_read(priv, REG_SOC_GPIO_CONTROL1);
+       value |= BIT(offset);
+       pdc_write(priv, REG_SOC_GPIO_CONTROL1, value);
+       __global_unlock2(lstat);
+
+       return 0;
+}
+
+static int tz1090_pdc_gpio_direction_output(struct gpio_chip *chip,
+                                           unsigned int offset,
+                                           int output_value)
+{
+       struct tz1090_pdc_gpio *priv = to_pdc(chip);
+       u32 value;
+       int lstat;
+
+       __global_lock2(lstat);
+       /* EXT_POWER doesn't seem to have an output value bit */
+       if (offset < 6) {
+               value = pdc_read(priv, REG_SOC_GPIO_CONTROL0);
+               if (output_value)
+                       value |= BIT(offset);
+               else
+                       value &= ~BIT(offset);
+               pdc_write(priv, REG_SOC_GPIO_CONTROL0, value);
+       }
+
+       value = pdc_read(priv, REG_SOC_GPIO_CONTROL1);
+       value &= ~BIT(offset);
+       pdc_write(priv, REG_SOC_GPIO_CONTROL1, value);
+       __global_unlock2(lstat);
+
+       return 0;
+}
+
+static int tz1090_pdc_gpio_get(struct gpio_chip *chip, unsigned int offset)
+{
+       struct tz1090_pdc_gpio *priv = to_pdc(chip);
+       return pdc_read(priv, REG_SOC_GPIO_STATUS) & BIT(offset);
+}
+
+static void tz1090_pdc_gpio_set(struct gpio_chip *chip, unsigned int offset,
+                               int output_value)
+{
+       struct tz1090_pdc_gpio *priv = to_pdc(chip);
+       u32 value;
+       int lstat;
+
+       /* EXT_POWER doesn't seem to have an output value bit */
+       if (offset >= 6)
+               return;
+
+       __global_lock2(lstat);
+       value = pdc_read(priv, REG_SOC_GPIO_CONTROL0);
+       if (output_value)
+               value |= BIT(offset);
+       else
+               value &= ~BIT(offset);
+       pdc_write(priv, REG_SOC_GPIO_CONTROL0, value);
+       __global_unlock2(lstat);
+}
+
+static int tz1090_pdc_gpio_request(struct gpio_chip *chip, unsigned int offset)
+{
+       return pinctrl_request_gpio(chip->base + offset);
+}
+
+static void tz1090_pdc_gpio_free(struct gpio_chip *chip, unsigned int offset)
+{
+       pinctrl_free_gpio(chip->base + offset);
+}
+
+static int tz1090_pdc_gpio_to_irq(struct gpio_chip *chip, unsigned int offset)
+{
+       struct tz1090_pdc_gpio *priv = to_pdc(chip);
+       unsigned int syswake = offset - GPIO_PDC_IRQ_FIRST;
+       int irq;
+
+       /* only syswakes have irqs */
+       if (syswake >= GPIO_PDC_NIRQ)
+               return -EINVAL;
+
+       irq = priv->irq[syswake];
+       if (!irq)
+               return -EINVAL;
+
+       return irq;
+}
+
+static int tz1090_pdc_gpio_probe(struct platform_device *pdev)
+{
+       struct device_node *np = pdev->dev.of_node;
+       struct resource *res_regs;
+       struct tz1090_pdc_gpio *priv;
+       unsigned int i;
+
+       if (!np) {
+               dev_err(&pdev->dev, "must be instantiated via devicetree\n");
+               return -ENOENT;
+       }
+
+       res_regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res_regs) {
+               dev_err(&pdev->dev, "cannot find registers resource\n");
+               return -ENOENT;
+       }
+
+       priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+       if (!priv) {
+               dev_err(&pdev->dev, "unable to allocate driver data\n");
+               return -ENOMEM;
+       }
+
+       /* Ioremap the registers */
+       priv->reg = devm_ioremap(&pdev->dev, res_regs->start,
+                                res_regs->end - res_regs->start);
+       if (!priv->reg) {
+               dev_err(&pdev->dev, "unable to ioremap registers\n");
+               return -ENOMEM;
+       }
+
+       /* Set up GPIO chip */
+       priv->chip.label                = "tz1090-pdc-gpio";
+       priv->chip.dev                  = &pdev->dev;
+       priv->chip.direction_input      = tz1090_pdc_gpio_direction_input;
+       priv->chip.direction_output     = tz1090_pdc_gpio_direction_output;
+       priv->chip.get                  = tz1090_pdc_gpio_get;
+       priv->chip.set                  = tz1090_pdc_gpio_set;
+       priv->chip.free                 = tz1090_pdc_gpio_free;
+       priv->chip.request              = tz1090_pdc_gpio_request;
+       priv->chip.to_irq               = tz1090_pdc_gpio_to_irq;
+       priv->chip.of_node              = np;
+
+       /* GPIO numbering */
+       priv->chip.base                 = GPIO_PDC_BASE;
+       priv->chip.ngpio                = GPIO_PDC_NGPIO;
+
+       /* Map the syswake irqs */
+       for (i = 0; i < GPIO_PDC_NIRQ; ++i)
+               priv->irq[i] = irq_of_parse_and_map(np, i);
+
+       /* Add the GPIO bank */
+       gpiochip_add(&priv->chip);
+
+       return 0;
+}
+
+static struct of_device_id tz1090_pdc_gpio_of_match[] = {
+       { .compatible = "img,tz1090-pdc-gpio" },
+       { },
+};
+
+static struct platform_driver tz1090_pdc_gpio_driver = {
+       .driver = {
+               .name           = "tz1090-pdc-gpio",
+               .owner          = THIS_MODULE,
+               .of_match_table = tz1090_pdc_gpio_of_match,
+       },
+       .probe          = tz1090_pdc_gpio_probe,
+};
+
+static int __init tz1090_pdc_gpio_init(void)
+{
+       return platform_driver_register(&tz1090_pdc_gpio_driver);
+}
+subsys_initcall(tz1090_pdc_gpio_init);
diff --git a/drivers/gpio/gpio-tz1090.c b/drivers/gpio/gpio-tz1090.c
new file mode 100644 (file)
index 0000000..23e0613
--- /dev/null
@@ -0,0 +1,606 @@
+/*
+ * Toumaz Xenif TZ1090 GPIO handling.
+ *
+ * Copyright (C) 2008-2013 Imagination Technologies Ltd.
+ *
+ *  Based on ARM PXA code and others.
+ *
+ * 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/bitops.h>
+#include <linux/export.h>
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/kernel.h>
+#include <linux/of_irq.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/syscore_ops.h>
+#include <asm/global_lock.h>
+
+/* Register offsets from bank base address */
+#define REG_GPIO_DIR           0x00
+#define REG_GPIO_IRQ_PLRT      0x20
+#define REG_GPIO_IRQ_TYPE      0x30
+#define REG_GPIO_IRQ_EN                0x40
+#define REG_GPIO_IRQ_STS       0x50
+#define REG_GPIO_BIT_EN                0x60
+#define REG_GPIO_DIN           0x70
+#define REG_GPIO_DOUT          0x80
+
+/* REG_GPIO_IRQ_PLRT */
+#define REG_GPIO_IRQ_PLRT_LOW  0
+#define REG_GPIO_IRQ_PLRT_HIGH 1
+
+/* REG_GPIO_IRQ_TYPE */
+#define REG_GPIO_IRQ_TYPE_LEVEL        0
+#define REG_GPIO_IRQ_TYPE_EDGE 1
+
+/**
+ * struct tz1090_gpio_bank - GPIO bank private data
+ * @chip:      Generic GPIO chip for GPIO bank
+ * @domain:    IRQ domain for GPIO bank (may be NULL)
+ * @reg:       Base of registers, offset for this GPIO bank
+ * @irq:       IRQ number for GPIO bank
+ * @label:     Debug GPIO bank label, used for storage of chip->label
+ *
+ * This is the main private data for a GPIO bank. It encapsulates a gpio_chip,
+ * and the callbacks for the gpio_chip can access the private data with the
+ * to_bank() macro below.
+ */
+struct tz1090_gpio_bank {
+       struct gpio_chip chip;
+       struct irq_domain *domain;
+       void __iomem *reg;
+       int irq;
+       char label[16];
+};
+#define to_bank(c)     container_of(c, struct tz1090_gpio_bank, chip)
+
+/**
+ * struct tz1090_gpio - Overall GPIO device private data
+ * @dev:       Device (from platform device)
+ * @reg:       Base of GPIO registers
+ *
+ * Represents the overall GPIO device. This structure is actually only
+ * temporary, and used during init.
+ */
+struct tz1090_gpio {
+       struct device *dev;
+       void __iomem *reg;
+};
+
+/**
+ * struct tz1090_gpio_bank_info - Temporary registration info for GPIO bank
+ * @priv:      Overall GPIO device private data
+ * @node:      Device tree node specific to this GPIO bank
+ * @index:     Index of bank in range 0-2
+ */
+struct tz1090_gpio_bank_info {
+       struct tz1090_gpio *priv;
+       struct device_node *node;
+       unsigned int index;
+};
+
+/* Convenience register accessors */
+static inline void tz1090_gpio_write(struct tz1090_gpio_bank *bank,
+                             unsigned int reg_offs, u32 data)
+{
+       iowrite32(data, bank->reg + reg_offs);
+}
+
+static inline u32 tz1090_gpio_read(struct tz1090_gpio_bank *bank,
+                           unsigned int reg_offs)
+{
+       return ioread32(bank->reg + reg_offs);
+}
+
+/* caller must hold LOCK2 */
+static inline void _tz1090_gpio_clear_bit(struct tz1090_gpio_bank *bank,
+                                         unsigned int reg_offs,
+                                         unsigned int offset)
+{
+       u32 value;
+
+       value = tz1090_gpio_read(bank, reg_offs);
+       value &= ~BIT(offset);
+       tz1090_gpio_write(bank, reg_offs, value);
+}
+
+static void tz1090_gpio_clear_bit(struct tz1090_gpio_bank *bank,
+                                 unsigned int reg_offs,
+                                 unsigned int offset)
+{
+       int lstat;
+
+       __global_lock2(lstat);
+       _tz1090_gpio_clear_bit(bank, reg_offs, offset);
+       __global_unlock2(lstat);
+}
+
+/* caller must hold LOCK2 */
+static inline void _tz1090_gpio_set_bit(struct tz1090_gpio_bank *bank,
+                                       unsigned int reg_offs,
+                                       unsigned int offset)
+{
+       u32 value;
+
+       value = tz1090_gpio_read(bank, reg_offs);
+       value |= BIT(offset);
+       tz1090_gpio_write(bank, reg_offs, value);
+}
+
+static void tz1090_gpio_set_bit(struct tz1090_gpio_bank *bank,
+                               unsigned int reg_offs,
+                               unsigned int offset)
+{
+       int lstat;
+
+       __global_lock2(lstat);
+       _tz1090_gpio_set_bit(bank, reg_offs, offset);
+       __global_unlock2(lstat);
+}
+
+/* caller must hold LOCK2 */
+static inline void _tz1090_gpio_mod_bit(struct tz1090_gpio_bank *bank,
+                                       unsigned int reg_offs,
+                                       unsigned int offset,
+                                       bool val)
+{
+       u32 value;
+
+       value = tz1090_gpio_read(bank, reg_offs);
+       value &= ~BIT(offset);
+       if (val)
+               value |= BIT(offset);
+       tz1090_gpio_write(bank, reg_offs, value);
+}
+
+static void tz1090_gpio_mod_bit(struct tz1090_gpio_bank *bank,
+                               unsigned int reg_offs,
+                               unsigned int offset,
+                               bool val)
+{
+       int lstat;
+
+       __global_lock2(lstat);
+       _tz1090_gpio_mod_bit(bank, reg_offs, offset, val);
+       __global_unlock2(lstat);
+}
+
+static inline int tz1090_gpio_read_bit(struct tz1090_gpio_bank *bank,
+                                      unsigned int reg_offs,
+                                      unsigned int offset)
+{
+       return tz1090_gpio_read(bank, reg_offs) & BIT(offset);
+}
+
+/* GPIO chip callbacks */
+
+static int tz1090_gpio_direction_input(struct gpio_chip *chip,
+                                      unsigned int offset)
+{
+       struct tz1090_gpio_bank *bank = to_bank(chip);
+       tz1090_gpio_set_bit(bank, REG_GPIO_DIR, offset);
+
+       return 0;
+}
+
+static int tz1090_gpio_direction_output(struct gpio_chip *chip,
+                                       unsigned int offset, int output_value)
+{
+       struct tz1090_gpio_bank *bank = to_bank(chip);
+       int lstat;
+
+       __global_lock2(lstat);
+       _tz1090_gpio_mod_bit(bank, REG_GPIO_DOUT, offset, output_value);
+       _tz1090_gpio_clear_bit(bank, REG_GPIO_DIR, offset);
+       __global_unlock2(lstat);
+
+       return 0;
+}
+
+/*
+ * Return GPIO level
+ */
+static int tz1090_gpio_get(struct gpio_chip *chip, unsigned int offset)
+{
+       struct tz1090_gpio_bank *bank = to_bank(chip);
+
+       return tz1090_gpio_read_bit(bank, REG_GPIO_DIN, offset);
+}
+
+/*
+ * Set output GPIO level
+ */
+static void tz1090_gpio_set(struct gpio_chip *chip, unsigned int offset,
+                           int output_value)
+{
+       struct tz1090_gpio_bank *bank = to_bank(chip);
+
+       tz1090_gpio_mod_bit(bank, REG_GPIO_DOUT, offset, output_value);
+}
+
+static int tz1090_gpio_request(struct gpio_chip *chip, unsigned int offset)
+{
+       struct tz1090_gpio_bank *bank = to_bank(chip);
+       int ret;
+
+       ret = pinctrl_request_gpio(chip->base + offset);
+       if (ret)
+               return ret;
+
+       tz1090_gpio_set_bit(bank, REG_GPIO_DIR, offset);
+       tz1090_gpio_set_bit(bank, REG_GPIO_BIT_EN, offset);
+
+       return 0;
+}
+
+static void tz1090_gpio_free(struct gpio_chip *chip, unsigned int offset)
+{
+       struct tz1090_gpio_bank *bank = to_bank(chip);
+
+       pinctrl_free_gpio(chip->base + offset);
+
+       tz1090_gpio_clear_bit(bank, REG_GPIO_BIT_EN, offset);
+}
+
+static int tz1090_gpio_to_irq(struct gpio_chip *chip, unsigned int offset)
+{
+       struct tz1090_gpio_bank *bank = to_bank(chip);
+
+       if (!bank->domain)
+               return -EINVAL;
+
+       return irq_create_mapping(bank->domain, offset);
+}
+
+/* IRQ chip handlers */
+
+/* Get TZ1090 GPIO chip from irq data provided to generic IRQ callbacks */
+static inline struct tz1090_gpio_bank *irqd_to_gpio_bank(struct irq_data *data)
+{
+       return (struct tz1090_gpio_bank *)data->domain->host_data;
+}
+
+static void tz1090_gpio_irq_polarity(struct tz1090_gpio_bank *bank,
+                                    unsigned int offset, unsigned int polarity)
+{
+       tz1090_gpio_mod_bit(bank, REG_GPIO_IRQ_PLRT, offset, polarity);
+}
+
+static void tz1090_gpio_irq_type(struct tz1090_gpio_bank *bank,
+                                unsigned int offset, unsigned int type)
+{
+       tz1090_gpio_mod_bit(bank, REG_GPIO_IRQ_TYPE, offset, type);
+}
+
+/* set polarity to trigger on next edge, whether rising or falling */
+static void tz1090_gpio_irq_next_edge(struct tz1090_gpio_bank *bank,
+                                     unsigned int offset)
+{
+       unsigned int value_p, value_i;
+       int lstat;
+
+       /*
+        * Set the GPIO's interrupt polarity to the opposite of the current
+        * input value so that the next edge triggers an interrupt.
+        */
+       __global_lock2(lstat);
+       value_i = ~tz1090_gpio_read(bank, REG_GPIO_DIN);
+       value_p = tz1090_gpio_read(bank, REG_GPIO_IRQ_PLRT);
+       value_p &= ~BIT(offset);
+       value_p |= value_i & BIT(offset);
+       tz1090_gpio_write(bank, REG_GPIO_IRQ_PLRT, value_p);
+       __global_unlock2(lstat);
+}
+
+static unsigned int gpio_startup_irq(struct irq_data *data)
+{
+       /*
+        * This warning indicates that the type of the irq hasn't been set
+        * before enabling the irq. This would normally be done by passing some
+        * trigger flags to request_irq().
+        */
+       WARN(irqd_get_trigger_type(data) == IRQ_TYPE_NONE,
+               "irq type not set before enabling gpio irq %d", data->irq);
+
+       irq_gc_ack_clr_bit(data);
+       irq_gc_mask_set_bit(data);
+       return 0;
+}
+
+static int gpio_set_irq_type(struct irq_data *data, unsigned int flow_type)
+{
+       struct tz1090_gpio_bank *bank = irqd_to_gpio_bank(data);
+       unsigned int type;
+       unsigned int polarity;
+
+       switch (flow_type) {
+       case IRQ_TYPE_EDGE_BOTH:
+               type = REG_GPIO_IRQ_TYPE_EDGE;
+               polarity = REG_GPIO_IRQ_PLRT_LOW;
+               break;
+       case IRQ_TYPE_EDGE_RISING:
+               type = REG_GPIO_IRQ_TYPE_EDGE;
+               polarity = REG_GPIO_IRQ_PLRT_HIGH;
+               break;
+       case IRQ_TYPE_EDGE_FALLING:
+               type = REG_GPIO_IRQ_TYPE_EDGE;
+               polarity = REG_GPIO_IRQ_PLRT_LOW;
+               break;
+       case IRQ_TYPE_LEVEL_HIGH:
+               type = REG_GPIO_IRQ_TYPE_LEVEL;
+               polarity = REG_GPIO_IRQ_PLRT_HIGH;
+               break;
+       case IRQ_TYPE_LEVEL_LOW:
+               type = REG_GPIO_IRQ_TYPE_LEVEL;
+               polarity = REG_GPIO_IRQ_PLRT_LOW;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       tz1090_gpio_irq_type(bank, data->hwirq, type);
+       irq_setup_alt_chip(data, flow_type);
+
+       if (flow_type == IRQ_TYPE_EDGE_BOTH)
+               tz1090_gpio_irq_next_edge(bank, data->hwirq);
+       else
+               tz1090_gpio_irq_polarity(bank, data->hwirq, polarity);
+
+       return 0;
+}
+
+#ifdef CONFIG_SUSPEND
+static int gpio_set_irq_wake(struct irq_data *data, unsigned int on)
+{
+       struct tz1090_gpio_bank *bank = irqd_to_gpio_bank(data);
+
+#ifdef CONFIG_PM_DEBUG
+       pr_info("irq_wake irq%d state:%d\n", data->irq, on);
+#endif
+
+       /* wake on gpio block interrupt */
+       return irq_set_irq_wake(bank->irq, on);
+}
+#else
+#define gpio_set_irq_wake NULL
+#endif
+
+static void tz1090_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
+{
+       irq_hw_number_t hw;
+       unsigned int irq_stat, irq_no;
+       struct tz1090_gpio_bank *bank;
+       struct irq_desc *child_desc;
+
+       bank = (struct tz1090_gpio_bank *)irq_desc_get_handler_data(desc);
+       irq_stat = tz1090_gpio_read(bank, REG_GPIO_DIR) &
+                  tz1090_gpio_read(bank, REG_GPIO_IRQ_STS) &
+                  tz1090_gpio_read(bank, REG_GPIO_IRQ_EN) &
+                  0x3FFFFFFF; /* 30 bits only */
+
+       for (hw = 0; irq_stat; irq_stat >>= 1, ++hw) {
+               if (!(irq_stat & 1))
+                       continue;
+
+               irq_no = irq_linear_revmap(bank->domain, hw);
+               child_desc = irq_to_desc(irq_no);
+
+               /* Toggle edge for pin with both edges triggering enabled */
+               if (irqd_get_trigger_type(&child_desc->irq_data)
+                               == IRQ_TYPE_EDGE_BOTH)
+                       tz1090_gpio_irq_next_edge(bank, hw);
+
+               generic_handle_irq_desc(irq_no, child_desc);
+       }
+}
+
+static int tz1090_gpio_bank_probe(struct tz1090_gpio_bank_info *info)
+{
+       struct device_node *np = info->node;
+       struct device *dev = info->priv->dev;
+       struct tz1090_gpio_bank *bank;
+       struct irq_chip_generic *gc;
+       int err;
+
+       bank = devm_kzalloc(dev, sizeof(*bank), GFP_KERNEL);
+       if (!bank) {
+               dev_err(dev, "unable to allocate driver data\n");
+               return -ENOMEM;
+       }
+
+       /* Offset the main registers to the first register in this bank */
+       bank->reg = info->priv->reg + info->index * 4;
+
+       /* Set up GPIO chip */
+       snprintf(bank->label, sizeof(bank->label), "tz1090-gpio-%u",
+                info->index);
+       bank->chip.label                = bank->label;
+       bank->chip.dev                  = dev;
+       bank->chip.direction_input      = tz1090_gpio_direction_input;
+       bank->chip.direction_output     = tz1090_gpio_direction_output;
+       bank->chip.get                  = tz1090_gpio_get;
+       bank->chip.set                  = tz1090_gpio_set;
+       bank->chip.free                 = tz1090_gpio_free;
+       bank->chip.request              = tz1090_gpio_request;
+       bank->chip.to_irq               = tz1090_gpio_to_irq;
+       bank->chip.of_node              = np;
+
+       /* GPIO numbering from 0 */
+       bank->chip.base                 = info->index * 30;
+       bank->chip.ngpio                = 30;
+
+       /* Add the GPIO bank */
+       gpiochip_add(&bank->chip);
+
+       /* Get the GPIO bank IRQ if provided */
+       bank->irq = irq_of_parse_and_map(np, 0);
+
+       /* The interrupt is optional (it may be used by another core on chip) */
+       if (bank->irq < 0) {
+               dev_info(dev, "IRQ not provided for bank %u, IRQs disabled\n",
+                        info->index);
+               return 0;
+       }
+
+       dev_info(dev, "Setting up IRQs for GPIO bank %u\n",
+                info->index);
+
+       /*
+        * Initialise all interrupts to disabled so we don't get
+        * spurious ones on a dirty boot and hit the BUG_ON in the
+        * handler.
+        */
+       tz1090_gpio_write(bank, REG_GPIO_IRQ_EN, 0);
+
+       /* Add a virtual IRQ for each GPIO */
+       bank->domain = irq_domain_add_linear(np,
+                                            bank->chip.ngpio,
+                                            &irq_generic_chip_ops,
+                                            bank);
+
+       /* Set up a generic irq chip with 2 chip types (level and edge) */
+       err = irq_alloc_domain_generic_chips(bank->domain, bank->chip.ngpio, 2,
+                                            bank->label, handle_bad_irq, 0, 0,
+                                            IRQ_GC_INIT_NESTED_LOCK);
+       if (err) {
+               dev_info(dev,
+                        "irq_alloc_domain_generic_chips failed for bank %u, IRQs disabled\n",
+                        info->index);
+               irq_domain_remove(bank->domain);
+               return 0;
+       }
+
+       gc = irq_get_domain_generic_chip(bank->domain, 0);
+       gc->reg_base    = bank->reg;
+
+       /* level chip type */
+       gc->chip_types[0].type                  = IRQ_TYPE_LEVEL_MASK;
+       gc->chip_types[0].handler               = handle_level_irq;
+       gc->chip_types[0].regs.ack              = REG_GPIO_IRQ_STS;
+       gc->chip_types[0].regs.mask             = REG_GPIO_IRQ_EN;
+       gc->chip_types[0].chip.irq_startup      = gpio_startup_irq,
+       gc->chip_types[0].chip.irq_ack          = irq_gc_ack_clr_bit,
+       gc->chip_types[0].chip.irq_mask         = irq_gc_mask_clr_bit,
+       gc->chip_types[0].chip.irq_unmask       = irq_gc_mask_set_bit,
+       gc->chip_types[0].chip.irq_set_type     = gpio_set_irq_type,
+       gc->chip_types[0].chip.irq_set_wake     = gpio_set_irq_wake,
+       gc->chip_types[0].chip.flags            = IRQCHIP_MASK_ON_SUSPEND,
+
+       /* edge chip type */
+       gc->chip_types[1].type                  = IRQ_TYPE_EDGE_BOTH;
+       gc->chip_types[1].handler               = handle_edge_irq;
+       gc->chip_types[1].regs.ack              = REG_GPIO_IRQ_STS;
+       gc->chip_types[1].regs.mask             = REG_GPIO_IRQ_EN;
+       gc->chip_types[1].chip.irq_startup      = gpio_startup_irq,
+       gc->chip_types[1].chip.irq_ack          = irq_gc_ack_clr_bit,
+       gc->chip_types[1].chip.irq_mask         = irq_gc_mask_clr_bit,
+       gc->chip_types[1].chip.irq_unmask       = irq_gc_mask_set_bit,
+       gc->chip_types[1].chip.irq_set_type     = gpio_set_irq_type,
+       gc->chip_types[1].chip.irq_set_wake     = gpio_set_irq_wake,
+       gc->chip_types[1].chip.flags            = IRQCHIP_MASK_ON_SUSPEND,
+
+       /* Setup chained handler for this GPIO bank */
+       irq_set_handler_data(bank->irq, bank);
+       irq_set_chained_handler(bank->irq, tz1090_gpio_irq_handler);
+
+       return 0;
+}
+
+static void tz1090_gpio_register_banks(struct tz1090_gpio *priv)
+{
+       struct device_node *np = priv->dev->of_node;
+       struct device_node *node;
+
+       for_each_available_child_of_node(np, node) {
+               struct tz1090_gpio_bank_info info;
+               u32 addr;
+               int ret;
+
+               ret = of_property_read_u32(node, "reg", &addr);
+               if (ret) {
+                       dev_err(priv->dev, "invalid reg on %s\n",
+                               node->full_name);
+                       continue;
+               }
+               if (addr >= 3) {
+                       dev_err(priv->dev, "index %u in %s out of range\n",
+                               addr, node->full_name);
+                       continue;
+               }
+
+               info.index = addr;
+               info.node = of_node_get(node);
+               info.priv = priv;
+
+               ret = tz1090_gpio_bank_probe(&info);
+               if (ret) {
+                       dev_err(priv->dev, "failure registering %s\n",
+                               node->full_name);
+                       of_node_put(node);
+                       continue;
+               }
+       }
+}
+
+static int tz1090_gpio_probe(struct platform_device *pdev)
+{
+       struct device_node *np = pdev->dev.of_node;
+       struct resource *res_regs;
+       struct tz1090_gpio priv;
+
+       if (!np) {
+               dev_err(&pdev->dev, "must be instantiated via devicetree\n");
+               return -ENOENT;
+       }
+
+       res_regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res_regs) {
+               dev_err(&pdev->dev, "cannot find registers resource\n");
+               return -ENOENT;
+       }
+
+       priv.dev = &pdev->dev;
+
+       /* Ioremap the registers */
+       priv.reg = devm_ioremap(&pdev->dev, res_regs->start,
+                                res_regs->end - res_regs->start);
+       if (!priv.reg) {
+               dev_err(&pdev->dev, "unable to ioremap registers\n");
+               return -ENOMEM;
+       }
+
+       /* Look for banks */
+       tz1090_gpio_register_banks(&priv);
+
+       return 0;
+}
+
+static struct of_device_id tz1090_gpio_of_match[] = {
+       { .compatible = "img,tz1090-gpio" },
+       { },
+};
+
+static struct platform_driver tz1090_gpio_driver = {
+       .driver = {
+               .name           = "tz1090-gpio",
+               .owner          = THIS_MODULE,
+               .of_match_table = tz1090_gpio_of_match,
+       },
+       .probe          = tz1090_gpio_probe,
+};
+
+static int __init tz1090_gpio_init(void)
+{
+       return platform_driver_register(&tz1090_gpio_driver);
+}
+subsys_initcall(tz1090_gpio_init);
index 6d0feb234d3c65ad8fb8115bd187811475f79a90..1a605f2a0f55f8fac1675dd18f37dae366215edc 100644 (file)
@@ -45,7 +45,7 @@ static void ucb1400_gpio_set(struct gpio_chip *gc, unsigned off, int val)
 
 static int ucb1400_gpio_probe(struct platform_device *dev)
 {
-       struct ucb1400_gpio *ucb = dev->dev.platform_data;
+       struct ucb1400_gpio *ucb = dev_get_platdata(&dev->dev);
        int err = 0;
 
        if (!(ucb && ucb->gpio_offset)) {
index 2a743e10ecb65336e59de61ef32586ba83639644..456000c5c4579fd380cb00c68b450b883e28dfb7 100644 (file)
@@ -246,7 +246,7 @@ static struct gpio_chip template_chip = {
 static int wm831x_gpio_probe(struct platform_device *pdev)
 {
        struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
-       struct wm831x_pdata *pdata = wm831x->dev->platform_data;
+       struct wm831x_pdata *pdata = dev_get_platdata(wm831x->dev);
        struct wm831x_gpio *wm831x_gpio;
        int ret;
 
index 0b598cf3df9dc6320b6047a15a4e7a9f73252e3b..fc49154be7b14a8bccf2b7aa58d078b7da939d22 100644 (file)
@@ -112,7 +112,7 @@ static struct gpio_chip template_chip = {
 static int wm8350_gpio_probe(struct platform_device *pdev)
 {
        struct wm8350 *wm8350 = dev_get_drvdata(pdev->dev.parent);
-       struct wm8350_platform_data *pdata = wm8350->dev->platform_data;
+       struct wm8350_platform_data *pdata = dev_get_platdata(wm8350->dev);
        struct wm8350_gpio_data *wm8350_gpio;
        int ret;
 
index ae409fd94af7421e9b2f42ddc4af73eeda6936a9..a53dbdefc7ee147c86255fa795c7bacfc1a42d0d 100644 (file)
@@ -248,7 +248,7 @@ static struct gpio_chip template_chip = {
 static int wm8994_gpio_probe(struct platform_device *pdev)
 {
        struct wm8994 *wm8994 = dev_get_drvdata(pdev->dev.parent);
-       struct wm8994_pdata *pdata = wm8994->dev->platform_data;
+       struct wm8994_pdata *pdata = dev_get_platdata(wm8994->dev);
        struct wm8994_gpio *wm8994_gpio;
        int ret;
 
index 665f9530c950f96fd4cf54fb70c03edffbcc2ef2..ba9876ffb017ba3c8874512e73acbbf9c97d0cbb 100644 (file)
@@ -76,7 +76,8 @@ int of_get_named_gpio_flags(struct device_node *np, const char *propname,
        ret = of_parse_phandle_with_args(np, propname, "#gpio-cells", index,
                                         &gg_data.gpiospec);
        if (ret) {
-               pr_debug("%s: can't parse gpios property\n", __func__);
+               pr_debug("%s: can't parse gpios property of node '%s[%d]'\n",
+                       __func__, np->full_name, index);
                return ret;
        }
 
index ff0fd655729f9e22d920d4efcb20777b93469df3..86ef3461ec0647b42f1e1ff94a9f47225151f7f6 100644 (file)
@@ -349,7 +349,7 @@ static ssize_t gpio_value_store(struct device *dev,
        else {
                long            value;
 
-               status = strict_strtol(buf, 0, &value);
+               status = kstrtol(buf, 0, &value);
                if (status == 0) {
                        if (test_bit(FLAG_ACTIVE_LOW, &desc->flags))
                                value = !value;
@@ -570,7 +570,7 @@ static ssize_t gpio_active_low_store(struct device *dev,
        } else {
                long            value;
 
-               status = strict_strtol(buf, 0, &value);
+               status = kstrtol(buf, 0, &value);
                if (status == 0)
                        status = sysfs_set_active_low(desc, dev, value != 0);
        }
@@ -652,7 +652,7 @@ static ssize_t export_store(struct class *class,
        struct gpio_desc        *desc;
        int                     status;
 
-       status = strict_strtol(buf, 0, &gpio);
+       status = kstrtol(buf, 0, &gpio);
        if (status < 0)
                goto done;
 
@@ -694,7 +694,7 @@ static ssize_t unexport_store(struct class *class,
        struct gpio_desc        *desc;
        int                     status;
 
-       status = strict_strtol(buf, 0, &gpio);
+       status = kstrtol(buf, 0, &gpio);
        if (status < 0)
                goto done;
 
@@ -1398,7 +1398,7 @@ static int gpiod_request(struct gpio_desc *desc, const char *label)
        int                     status = -EPROBE_DEFER;
        unsigned long           flags;
 
-       if (!desc) {
+       if (!desc || !desc->chip) {
                pr_warn("%s: invalid GPIO\n", __func__);
                return -EINVAL;
        }
@@ -1406,8 +1406,6 @@ static int gpiod_request(struct gpio_desc *desc, const char *label)
        spin_lock_irqsave(&gpio_lock, flags);
 
        chip = desc->chip;
-       if (chip == NULL)
-               goto done;
 
        if (!try_module_get(chip->owner))
                goto done;
@@ -1630,16 +1628,20 @@ static int gpiod_direction_input(struct gpio_desc *desc)
        int                     status = -EINVAL;
        int                     offset;
 
-       if (!desc) {
+       if (!desc || !desc->chip) {
                pr_warn("%s: invalid GPIO\n", __func__);
                return -EINVAL;
        }
 
+       chip = desc->chip;
+       if (!chip->get || !chip->direction_input) {
+               pr_warn("%s: missing get() or direction_input() operations\n",
+                       __func__);
+               return -EIO;
+       }
+
        spin_lock_irqsave(&gpio_lock, flags);
 
-       chip = desc->chip;
-       if (!chip || !chip->get || !chip->direction_input)
-               goto fail;
        status = gpio_ensure_requested(desc);
        if (status < 0)
                goto fail;
@@ -1691,7 +1693,7 @@ static int gpiod_direction_output(struct gpio_desc *desc, int value)
        int                     status = -EINVAL;
        int offset;
 
-       if (!desc) {
+       if (!desc || !desc->chip) {
                pr_warn("%s: invalid GPIO\n", __func__);
                return -EINVAL;
        }
@@ -1704,11 +1706,15 @@ static int gpiod_direction_output(struct gpio_desc *desc, int value)
        if (!value && test_bit(FLAG_OPEN_SOURCE,  &desc->flags))
                return gpiod_direction_input(desc);
 
+       chip = desc->chip;
+       if (!chip->set || !chip->direction_output) {
+               pr_warn("%s: missing set() or direction_output() operations\n",
+                       __func__);
+               return -EIO;
+       }
+
        spin_lock_irqsave(&gpio_lock, flags);
 
-       chip = desc->chip;
-       if (!chip || !chip->set || !chip->direction_output)
-               goto fail;
        status = gpio_ensure_requested(desc);
        if (status < 0)
                goto fail;
@@ -1757,6 +1763,9 @@ EXPORT_SYMBOL_GPL(gpio_direction_output);
  * gpio_set_debounce - sets @debounce time for a @gpio
  * @gpio: the gpio to set debounce time
  * @debounce: debounce time is microseconds
+ *
+ * returns -ENOTSUPP if the controller does not support setting
+ * debounce.
  */
 static int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce)
 {
@@ -1765,16 +1774,19 @@ static int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce)
        int                     status = -EINVAL;
        int                     offset;
 
-       if (!desc) {
+       if (!desc || !desc->chip) {
                pr_warn("%s: invalid GPIO\n", __func__);
                return -EINVAL;
        }
 
-       spin_lock_irqsave(&gpio_lock, flags);
-
        chip = desc->chip;
-       if (!chip || !chip->set || !chip->set_debounce)
-               goto fail;
+       if (!chip->set || !chip->set_debounce) {
+               pr_debug("%s: missing set() or set_debounce() operations\n",
+                       __func__);
+               return -ENOTSUPP;
+       }
+
+       spin_lock_irqsave(&gpio_lock, flags);
 
        status = gpio_ensure_requested(desc);
        if (status < 0)
index 573edfb046c4f5943ea4acb2449a9c6ec3154285..7c5a519d2dcde2bd08816c78f4c59f8d41f8324c 100644 (file)
@@ -5,6 +5,7 @@ struct gpio_em_config {
        unsigned int gpio_base;
        unsigned int irq_base;
        unsigned int number_of_pins;
+       const char *pctl_name;
 };
 
 #endif /* __GPIO_EM_H__ */