gpio: reorganize drivers
authorGrant Likely <grant.likely@secretlab.ca>
Sun, 5 Jun 2011 00:38:28 +0000 (18:38 -0600)
committerGrant Likely <grant.likely@secretlab.ca>
Mon, 6 Jun 2011 16:10:11 +0000 (10:10 -0600)
Sort the gpio makefile and enforce the naming convention gpio-*.c for
gpio drivers.

v2: cleaned up filenames in Kconfig and comment blocks
v3: fixup use of BASIC_MMIO to GENERIC_GPIO for mxc

Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
80 files changed:
drivers/gpio/74x164.c [deleted file]
drivers/gpio/Kconfig
drivers/gpio/Makefile
drivers/gpio/ab8500-gpio.c [deleted file]
drivers/gpio/adp5520-gpio.c [deleted file]
drivers/gpio/adp5588-gpio.c [deleted file]
drivers/gpio/basic_mmio_gpio.c [deleted file]
drivers/gpio/bt8xxgpio.c [deleted file]
drivers/gpio/cs5535-gpio.c [deleted file]
drivers/gpio/gpio-74x164.c [new file with mode: 0644]
drivers/gpio/gpio-ab8500.c [new file with mode: 0644]
drivers/gpio/gpio-adp5520.c [new file with mode: 0644]
drivers/gpio/gpio-adp5588.c [new file with mode: 0644]
drivers/gpio/gpio-bt8xx.c [new file with mode: 0644]
drivers/gpio/gpio-cs5535.c [new file with mode: 0644]
drivers/gpio/gpio-ep93xx.c
drivers/gpio/gpio-exynos4.c
drivers/gpio/gpio-generic.c [new file with mode: 0644]
drivers/gpio/gpio-it8761e.c [new file with mode: 0644]
drivers/gpio/gpio-janz-ttl.c [new file with mode: 0644]
drivers/gpio/gpio-langwell.c [new file with mode: 0644]
drivers/gpio/gpio-max7300.c [new file with mode: 0644]
drivers/gpio/gpio-max7301.c [new file with mode: 0644]
drivers/gpio/gpio-max730x.c [new file with mode: 0644]
drivers/gpio/gpio-max732x.c [new file with mode: 0644]
drivers/gpio/gpio-mc33880.c [new file with mode: 0644]
drivers/gpio/gpio-mcp23s08.c [new file with mode: 0644]
drivers/gpio/gpio-ml-ioh.c [new file with mode: 0644]
drivers/gpio/gpio-pca953x.c [new file with mode: 0644]
drivers/gpio/gpio-pcf857x.c [new file with mode: 0644]
drivers/gpio/gpio-pch.c [new file with mode: 0644]
drivers/gpio/gpio-pl061.c [new file with mode: 0644]
drivers/gpio/gpio-plat-samsung.c
drivers/gpio/gpio-rdc321x.c [new file with mode: 0644]
drivers/gpio/gpio-s5pc100.c
drivers/gpio/gpio-s5pv210.c
drivers/gpio/gpio-sch.c [new file with mode: 0644]
drivers/gpio/gpio-stmpe.c [new file with mode: 0644]
drivers/gpio/gpio-sx150x.c [new file with mode: 0644]
drivers/gpio/gpio-tc3589x.c [new file with mode: 0644]
drivers/gpio/gpio-timberdale.c [new file with mode: 0644]
drivers/gpio/gpio-tps65910.c [new file with mode: 0644]
drivers/gpio/gpio-twl4030.c [new file with mode: 0644]
drivers/gpio/gpio-u300.c
drivers/gpio/gpio-ucb1400.c [new file with mode: 0644]
drivers/gpio/gpio-vr41xx.c [new file with mode: 0644]
drivers/gpio/gpio-vx855.c [new file with mode: 0644]
drivers/gpio/gpio-wm831x.c [new file with mode: 0644]
drivers/gpio/gpio-wm8350.c [new file with mode: 0644]
drivers/gpio/gpio-wm8994.c [new file with mode: 0644]
drivers/gpio/gpio-xilinx.c [new file with mode: 0644]
drivers/gpio/it8761e_gpio.c [deleted file]
drivers/gpio/janz-ttl.c [deleted file]
drivers/gpio/langwell_gpio.c [deleted file]
drivers/gpio/max7300.c [deleted file]
drivers/gpio/max7301.c [deleted file]
drivers/gpio/max730x.c [deleted file]
drivers/gpio/max732x.c [deleted file]
drivers/gpio/mc33880.c [deleted file]
drivers/gpio/mcp23s08.c [deleted file]
drivers/gpio/ml_ioh_gpio.c [deleted file]
drivers/gpio/pca953x.c [deleted file]
drivers/gpio/pcf857x.c [deleted file]
drivers/gpio/pch_gpio.c [deleted file]
drivers/gpio/pl061.c [deleted file]
drivers/gpio/rdc321x-gpio.c [deleted file]
drivers/gpio/sch_gpio.c [deleted file]
drivers/gpio/stmpe-gpio.c [deleted file]
drivers/gpio/sx150x.c [deleted file]
drivers/gpio/tc3589x-gpio.c [deleted file]
drivers/gpio/timbgpio.c [deleted file]
drivers/gpio/tps65910-gpio.c [deleted file]
drivers/gpio/twl4030-gpio.c [deleted file]
drivers/gpio/ucb1400_gpio.c [deleted file]
drivers/gpio/vr41xx_giu.c [deleted file]
drivers/gpio/vx855_gpio.c [deleted file]
drivers/gpio/wm831x-gpio.c [deleted file]
drivers/gpio/wm8350-gpiolib.c [deleted file]
drivers/gpio/wm8994-gpio.c [deleted file]
drivers/gpio/xilinx_gpio.c [deleted file]

diff --git a/drivers/gpio/74x164.c b/drivers/gpio/74x164.c
deleted file mode 100644 (file)
index 7fb60b6..0000000
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- *  74Hx164 - Generic serial-in/parallel-out 8-bits shift register GPIO driver
- *
- *  Copyright (C) 2010 Gabor Juhos <juhosg@openwrt.org>
- *  Copyright (C) 2010 Miguel Gaio <miguel.gaio@efixo.com>
- *
- *  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/init.h>
-#include <linux/mutex.h>
-#include <linux/spi/spi.h>
-#include <linux/spi/74x164.h>
-#include <linux/gpio.h>
-#include <linux/slab.h>
-
-struct gen_74x164_chip {
-       struct spi_device       *spi;
-       struct gpio_chip        gpio_chip;
-       struct mutex            lock;
-       u8                      port_config;
-};
-
-static struct gen_74x164_chip *gpio_to_chip(struct gpio_chip *gc)
-{
-       return container_of(gc, struct gen_74x164_chip, gpio_chip);
-}
-
-static int __gen_74x164_write_config(struct gen_74x164_chip *chip)
-{
-       return spi_write(chip->spi,
-                        &chip->port_config, sizeof(chip->port_config));
-}
-
-static int gen_74x164_get_value(struct gpio_chip *gc, unsigned offset)
-{
-       struct gen_74x164_chip *chip = gpio_to_chip(gc);
-       int ret;
-
-       mutex_lock(&chip->lock);
-       ret = (chip->port_config >> offset) & 0x1;
-       mutex_unlock(&chip->lock);
-
-       return ret;
-}
-
-static void gen_74x164_set_value(struct gpio_chip *gc,
-               unsigned offset, int val)
-{
-       struct gen_74x164_chip *chip = gpio_to_chip(gc);
-
-       mutex_lock(&chip->lock);
-       if (val)
-               chip->port_config |= (1 << offset);
-       else
-               chip->port_config &= ~(1 << offset);
-
-       __gen_74x164_write_config(chip);
-       mutex_unlock(&chip->lock);
-}
-
-static int gen_74x164_direction_output(struct gpio_chip *gc,
-               unsigned offset, int val)
-{
-       gen_74x164_set_value(gc, offset, val);
-       return 0;
-}
-
-static int __devinit gen_74x164_probe(struct spi_device *spi)
-{
-       struct gen_74x164_chip *chip;
-       struct gen_74x164_chip_platform_data *pdata;
-       int ret;
-
-       pdata = spi->dev.platform_data;
-       if (!pdata || !pdata->base) {
-               dev_dbg(&spi->dev, "incorrect or missing platform data\n");
-               return -EINVAL;
-       }
-
-       /*
-        * bits_per_word cannot be configured in platform data
-        */
-       spi->bits_per_word = 8;
-
-       ret = spi_setup(spi);
-       if (ret < 0)
-               return ret;
-
-       chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-       if (!chip)
-               return -ENOMEM;
-
-       mutex_init(&chip->lock);
-
-       dev_set_drvdata(&spi->dev, chip);
-
-       chip->spi = spi;
-
-       chip->gpio_chip.label = spi->modalias;
-       chip->gpio_chip.direction_output = gen_74x164_direction_output;
-       chip->gpio_chip.get = gen_74x164_get_value;
-       chip->gpio_chip.set = gen_74x164_set_value;
-       chip->gpio_chip.base = pdata->base;
-       chip->gpio_chip.ngpio = 8;
-       chip->gpio_chip.can_sleep = 1;
-       chip->gpio_chip.dev = &spi->dev;
-       chip->gpio_chip.owner = THIS_MODULE;
-
-       ret = __gen_74x164_write_config(chip);
-       if (ret) {
-               dev_err(&spi->dev, "Failed writing: %d\n", ret);
-               goto exit_destroy;
-       }
-
-       ret = gpiochip_add(&chip->gpio_chip);
-       if (ret)
-               goto exit_destroy;
-
-       return ret;
-
-exit_destroy:
-       dev_set_drvdata(&spi->dev, NULL);
-       mutex_destroy(&chip->lock);
-       kfree(chip);
-       return ret;
-}
-
-static int __devexit gen_74x164_remove(struct spi_device *spi)
-{
-       struct gen_74x164_chip *chip;
-       int ret;
-
-       chip = dev_get_drvdata(&spi->dev);
-       if (chip == NULL)
-               return -ENODEV;
-
-       dev_set_drvdata(&spi->dev, NULL);
-
-       ret = gpiochip_remove(&chip->gpio_chip);
-       if (!ret) {
-               mutex_destroy(&chip->lock);
-               kfree(chip);
-       } else
-               dev_err(&spi->dev, "Failed to remove the GPIO controller: %d\n",
-                               ret);
-
-       return ret;
-}
-
-static struct spi_driver gen_74x164_driver = {
-       .driver = {
-               .name           = "74x164",
-               .owner          = THIS_MODULE,
-       },
-       .probe          = gen_74x164_probe,
-       .remove         = __devexit_p(gen_74x164_remove),
-};
-
-static int __init gen_74x164_init(void)
-{
-       return spi_register_driver(&gen_74x164_driver);
-}
-subsys_initcall(gen_74x164_init);
-
-static void __exit gen_74x164_exit(void)
-{
-       spi_unregister_driver(&gen_74x164_driver);
-}
-module_exit(gen_74x164_exit);
-
-MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>");
-MODULE_AUTHOR("Miguel Gaio <miguel.gaio@efixo.com>");
-MODULE_DESCRIPTION("GPIO expander driver for 74X164 8-bits shift register");
-MODULE_LICENSE("GPL v2");
index f8b6e7d27e4c156476cb66c2c63f00f576dd7f48..89a6a34cc5153447a8540b5674c3756f082dfa38 100644 (file)
@@ -63,6 +63,9 @@ config GPIO_SYSFS
          Kernel drivers may also request that a particular GPIO be
          exported to userspace; this can be useful when debugging.
 
+config GPIO_GENERIC
+       tristate
+
 # put drivers in the right section, in alphabetical order
 
 config GPIO_MAX730X
@@ -70,16 +73,11 @@ config GPIO_MAX730X
 
 comment "Memory mapped GPIO drivers:"
 
-config GPIO_BASIC_MMIO_CORE
-       tristate
-       help
-         Provides core functionality for basic memory-mapped GPIO controllers.
-
-config GPIO_BASIC_MMIO
-       tristate "Basic memory-mapped GPIO controllers support"
-       select GPIO_BASIC_MMIO_CORE
+config GPIO_GENERIC_PLATFORM
+       tristate "Generic memory-mapped GPIO controller support (MMIO platform device)"
+       select GPIO_GENERIC
        help
-         Say yes here to support basic memory-mapped GPIO controllers.
+         Say yes here to support basic platform_device memory-mapped GPIO controllers.
 
 config GPIO_IT8761E
        tristate "IT8761E GPIO support"
@@ -94,14 +92,14 @@ config GPIO_EXYNOS4
        def_bool y
        depends on CPU_EXYNOS4210
 
-config GPIO_MXS
-       def_bool y
-       depends on ARCH_MXS
-
 config GPIO_MXC
        def_bool y
        depends on ARCH_MXC
-       select GPIO_BASIC_MMIO_CORE
+       select GPIO_GENERIC
+
+config GPIO_MXS
+       def_bool y
+       depends on ARCH_MXS
 
 config GPIO_PLAT_SAMSUNG
        def_bool y
@@ -150,9 +148,6 @@ config GPIO_SCH
          The Intel Tunnel Creek processor has 5 GPIOs powered by the
          core power rail and 9 from suspend power supply.
 
-         This driver can also be built as a module. If so, the module
-         will be called sch-gpio.
-
 config GPIO_VX855
        tristate "VIA VX855/VX875 GPIO"
        depends on MFD_SUPPORT && PCI
@@ -215,9 +210,6 @@ config GPIO_PCA953X
 
          16 bits:      pca9535, pca9539, pca9555, tca6416
 
-         This driver can also be built as a module.  If so, the module
-         will be called pca953x.
-
 config GPIO_PCA953X_IRQ
        bool "Interrupt controller support for PCA953x"
        depends on GPIO_PCA953X=y
@@ -309,17 +301,12 @@ config GPIO_ADP5520
          This option enables support for on-chip GPIO found
          on Analog Devices ADP5520 PMICs.
 
-         To compile this driver as a module, choose M here: the module will
-         be called adp5520-gpio.
-
 config GPIO_ADP5588
        tristate "ADP5588 I2C GPIO expander"
        depends on I2C
        help
          This option enables support for 18 GPIOs found
          on Analog Devices ADP5588 GPIO Expanders.
-         To compile this driver as a module, choose M here: the module will be
-         called adp5588-gpio.
 
 config GPIO_ADP5588_IRQ
        bool "Interrupt controller support for ADP5588"
@@ -441,9 +428,6 @@ config GPIO_UCB1400
          This enables support for the Philips UCB1400 GPIO pins.
          The UCB1400 is an AC97 audio codec.
 
-         To compile this driver as a module, choose M here: the
-         module will be called ucb1400_gpio.
-
 comment "MODULbus GPIO expanders:"
 
 config GPIO_JANZ_TTL
@@ -454,7 +438,7 @@ config GPIO_JANZ_TTL
          This driver provides support for driving the pins in output
          mode only. Input mode is not supported.
 
-config AB8500_GPIO
+config GPIO_AB8500
        bool "ST-Ericsson AB8500 Mixed Signal Circuit gpio functions"
        depends on AB8500_CORE && BROKEN
        help
index 66923cf3ad6a8bd4d0a70d71b3d6d6da1694462a..68e3bfd35e0ff6030177b7d899ba94ee986aabe2 100644 (file)
@@ -4,50 +4,53 @@ ccflags-$(CONFIG_DEBUG_GPIO)  += -DDEBUG
 
 obj-$(CONFIG_GPIOLIB)          += gpiolib.o
 
-obj-$(CONFIG_GPIO_ADP5520)     += adp5520-gpio.o
-obj-$(CONFIG_GPIO_ADP5588)     += adp5588-gpio.o
-obj-$(CONFIG_GPIO_BASIC_MMIO_CORE)     += basic_mmio_gpio.o
-obj-$(CONFIG_GPIO_BASIC_MMIO)  += basic_mmio_gpio.o
+# Device drivers. Generally keep list sorted alphabetically
+obj-$(CONFIG_GPIO_GENERIC)     += gpio-generic.o
+
+obj-$(CONFIG_GPIO_74X164)      += gpio-74x164.o
+obj-$(CONFIG_GPIO_AB8500)      += gpio-ab8500.o
+obj-$(CONFIG_GPIO_ADP5520)     += gpio-adp5520.o
+obj-$(CONFIG_GPIO_ADP5588)     += gpio-adp5588.o
+obj-$(CONFIG_GPIO_BT8XX)       += gpio-bt8xx.o
+obj-$(CONFIG_GPIO_CS5535)      += gpio-cs5535.o
 obj-$(CONFIG_GPIO_EP93XX)      += gpio-ep93xx.o
 obj-$(CONFIG_GPIO_EXYNOS4)     += gpio-exynos4.o
+obj-$(CONFIG_GPIO_IT8761E)     += gpio-it8761e.o
+obj-$(CONFIG_GPIO_JANZ_TTL)    += gpio-janz-ttl.o
+obj-$(CONFIG_GPIO_LANGWELL)    += gpio-langwell.o
+obj-$(CONFIG_GPIO_MAX730X)     += gpio-max730x.o
+obj-$(CONFIG_GPIO_MAX7300)     += gpio-max7300.o
+obj-$(CONFIG_GPIO_MAX7301)     += gpio-max7301.o
+obj-$(CONFIG_GPIO_MAX732X)     += gpio-max732x.o
+obj-$(CONFIG_GPIO_MC33880)     += gpio-mc33880.o
+obj-$(CONFIG_GPIO_MCP23S08)    += gpio-mcp23s08.o
+obj-$(CONFIG_GPIO_ML_IOH)      += gpio-ml-ioh.o
 obj-$(CONFIG_GPIO_MXC)         += gpio-mxc.o
 obj-$(CONFIG_GPIO_MXS)         += gpio-mxs.o
+obj-$(CONFIG_PLAT_NOMADIK)     += gpio-nomadik.o
+obj-$(CONFIG_ARCH_OMAP)                += gpio-omap.o
+obj-$(CONFIG_GPIO_PCA953X)     += gpio-pca953x.o
+obj-$(CONFIG_GPIO_PCF857X)     += gpio-pcf857x.o
+obj-$(CONFIG_GPIO_PCH)         += gpio-pch.o
+obj-$(CONFIG_GPIO_PL061)       += gpio-pl061.o
+obj-$(CONFIG_GPIO_RDC321X)     += gpio-rdc321x.o
+
 obj-$(CONFIG_GPIO_PLAT_SAMSUNG)        += gpio-plat-samsung.o
 obj-$(CONFIG_GPIO_S5PC100)     += gpio-s5pc100.o
 obj-$(CONFIG_GPIO_S5PV210)     += gpio-s5pv210.o
-obj-$(CONFIG_GPIO_LANGWELL)    += langwell_gpio.o
-obj-$(CONFIG_GPIO_MAX730X)     += max730x.o
-obj-$(CONFIG_GPIO_MAX7300)     += max7300.o
-obj-$(CONFIG_GPIO_MAX7301)     += max7301.o
-obj-$(CONFIG_GPIO_MAX732X)     += max732x.o
-obj-$(CONFIG_GPIO_MC33880)     += mc33880.o
-obj-$(CONFIG_GPIO_MCP23S08)    += mcp23s08.o
-obj-$(CONFIG_GPIO_74X164)      += 74x164.o
-obj-$(CONFIG_ARCH_OMAP)         += gpio-omap.o
-obj-$(CONFIG_GPIO_PCA953X)     += pca953x.o
-obj-$(CONFIG_GPIO_PCF857X)     += pcf857x.o
-obj-$(CONFIG_GPIO_PCH)         += pch_gpio.o
-obj-$(CONFIG_GPIO_PL061)       += pl061.o
-obj-$(CONFIG_GPIO_STMPE)       += stmpe-gpio.o
-obj-$(CONFIG_GPIO_TC3589X)     += tc3589x-gpio.o
-obj-$(CONFIG_GPIO_TIMBERDALE)  += timbgpio.o
-obj-$(CONFIG_GPIO_TWL4030)     += twl4030-gpio.o
-obj-$(CONFIG_GPIO_UCB1400)     += ucb1400_gpio.o
-obj-$(CONFIG_GPIO_XILINX)      += xilinx_gpio.o
-obj-$(CONFIG_GPIO_CS5535)      += cs5535-gpio.o
-obj-$(CONFIG_GPIO_BT8XX)       += bt8xxgpio.o
-obj-$(CONFIG_GPIO_IT8761E)     += it8761e_gpio.o
-obj-$(CONFIG_GPIO_VR41XX)      += vr41xx_giu.o
-obj-$(CONFIG_GPIO_WM831X)      += wm831x-gpio.o
-obj-$(CONFIG_GPIO_WM8350)      += wm8350-gpiolib.o
-obj-$(CONFIG_GPIO_WM8994)      += wm8994-gpio.o
-obj-$(CONFIG_GPIO_SCH)         += sch_gpio.o
+
+obj-$(CONFIG_GPIO_SCH)         += gpio-sch.o
+obj-$(CONFIG_GPIO_STMPE)       += gpio-stmpe.o
+obj-$(CONFIG_GPIO_SX150X)      += gpio-sx150x.o
+obj-$(CONFIG_GPIO_TC3589X)     += gpio-tc3589x.o
+obj-$(CONFIG_GPIO_TIMBERDALE)  += gpio-timberdale.o
+obj-$(CONFIG_GPIO_TPS65910)    += gpio-tps65910.o
+obj-$(CONFIG_GPIO_TWL4030)     += gpio-twl4030.o
 obj-$(CONFIG_MACH_U300)                += gpio-u300.o
-obj-$(CONFIG_PLAT_NOMADIK)     += gpio-nomadik.o
-obj-$(CONFIG_GPIO_RDC321X)     += rdc321x-gpio.o
-obj-$(CONFIG_GPIO_JANZ_TTL)    += janz-ttl.o
-obj-$(CONFIG_GPIO_SX150X)      += sx150x.o
-obj-$(CONFIG_GPIO_VX855)       += vx855_gpio.o
-obj-$(CONFIG_GPIO_ML_IOH)      += ml_ioh_gpio.o
-obj-$(CONFIG_AB8500_GPIO)       += ab8500-gpio.o
-obj-$(CONFIG_GPIO_TPS65910)    += tps65910-gpio.o
+obj-$(CONFIG_GPIO_UCB1400)     += gpio-ucb1400.o
+obj-$(CONFIG_GPIO_VR41XX)      += gpio-vr41xx.o
+obj-$(CONFIG_GPIO_VX855)       += gpio-vx855.o
+obj-$(CONFIG_GPIO_WM831X)      += gpio-wm831x.o
+obj-$(CONFIG_GPIO_WM8350)      += gpio-wm8350.o
+obj-$(CONFIG_GPIO_WM8994)      += gpio-wm8994.o
+obj-$(CONFIG_GPIO_XILINX)      += gpio-xilinx.o
diff --git a/drivers/gpio/ab8500-gpio.c b/drivers/gpio/ab8500-gpio.c
deleted file mode 100644 (file)
index 970053c..0000000
+++ /dev/null
@@ -1,521 +0,0 @@
-/*
- * Copyright (C) ST-Ericsson SA 2011
- *
- * Author: BIBEK BASU <bibek.basu@stericsson.com>
- * License terms: GNU General Public License (GPL) version 2
- *
- * 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/kernel.h>
-#include <linux/types.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/err.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include <linux/gpio.h>
-#include <linux/irq.h>
-#include <linux/interrupt.h>
-#include <linux/mfd/ab8500.h>
-#include <linux/mfd/abx500.h>
-#include <linux/mfd/ab8500/gpio.h>
-
-/*
- * GPIO registers offset
- * Bank: 0x10
- */
-#define AB8500_GPIO_SEL1_REG   0x00
-#define AB8500_GPIO_SEL2_REG   0x01
-#define AB8500_GPIO_SEL3_REG   0x02
-#define AB8500_GPIO_SEL4_REG   0x03
-#define AB8500_GPIO_SEL5_REG   0x04
-#define AB8500_GPIO_SEL6_REG   0x05
-
-#define AB8500_GPIO_DIR1_REG   0x10
-#define AB8500_GPIO_DIR2_REG   0x11
-#define AB8500_GPIO_DIR3_REG   0x12
-#define AB8500_GPIO_DIR4_REG   0x13
-#define AB8500_GPIO_DIR5_REG   0x14
-#define AB8500_GPIO_DIR6_REG   0x15
-
-#define AB8500_GPIO_OUT1_REG   0x20
-#define AB8500_GPIO_OUT2_REG   0x21
-#define AB8500_GPIO_OUT3_REG   0x22
-#define AB8500_GPIO_OUT4_REG   0x23
-#define AB8500_GPIO_OUT5_REG   0x24
-#define AB8500_GPIO_OUT6_REG   0x25
-
-#define AB8500_GPIO_PUD1_REG   0x30
-#define AB8500_GPIO_PUD2_REG   0x31
-#define AB8500_GPIO_PUD3_REG   0x32
-#define AB8500_GPIO_PUD4_REG   0x33
-#define AB8500_GPIO_PUD5_REG   0x34
-#define AB8500_GPIO_PUD6_REG   0x35
-
-#define AB8500_GPIO_IN1_REG    0x40
-#define AB8500_GPIO_IN2_REG    0x41
-#define AB8500_GPIO_IN3_REG    0x42
-#define AB8500_GPIO_IN4_REG    0x43
-#define AB8500_GPIO_IN5_REG    0x44
-#define AB8500_GPIO_IN6_REG    0x45
-#define AB8500_GPIO_ALTFUN_REG 0x45
-#define ALTFUN_REG_INDEX       6
-#define AB8500_NUM_GPIO                42
-#define AB8500_NUM_VIR_GPIO_IRQ        16
-
-enum ab8500_gpio_action {
-       NONE,
-       STARTUP,
-       SHUTDOWN,
-       MASK,
-       UNMASK
-};
-
-struct ab8500_gpio {
-       struct gpio_chip chip;
-       struct ab8500 *parent;
-       struct device *dev;
-       struct mutex lock;
-       u32 irq_base;
-       enum ab8500_gpio_action irq_action;
-       u16 rising;
-       u16 falling;
-};
-/**
- * to_ab8500_gpio() - get the pointer to ab8500_gpio
- * @chip:      Member of the structure ab8500_gpio
- */
-static inline struct ab8500_gpio *to_ab8500_gpio(struct gpio_chip *chip)
-{
-       return container_of(chip, struct ab8500_gpio, chip);
-}
-
-static int ab8500_gpio_set_bits(struct gpio_chip *chip, u8 reg,
-                                       unsigned offset, int val)
-{
-       struct ab8500_gpio *ab8500_gpio = to_ab8500_gpio(chip);
-       u8 pos = offset % 8;
-       int ret;
-
-       reg = reg + (offset / 8);
-       ret = abx500_mask_and_set_register_interruptible(ab8500_gpio->dev,
-                               AB8500_MISC, reg, 1 << pos, val << pos);
-       if (ret < 0)
-               dev_err(ab8500_gpio->dev, "%s write failed\n", __func__);
-       return ret;
-}
-/**
- * ab8500_gpio_get() - Get the particular GPIO value
- * @chip: Gpio device
- * @offset: GPIO number to read
- */
-static int ab8500_gpio_get(struct gpio_chip *chip, unsigned offset)
-{
-       struct ab8500_gpio *ab8500_gpio = to_ab8500_gpio(chip);
-       u8 mask = 1 << (offset % 8);
-       u8 reg = AB8500_GPIO_OUT1_REG + (offset / 8);
-       int ret;
-       u8 data;
-       ret = abx500_get_register_interruptible(ab8500_gpio->dev, AB8500_MISC,
-                                               reg, &data);
-       if (ret < 0) {
-               dev_err(ab8500_gpio->dev, "%s read failed\n", __func__);
-               return ret;
-       }
-       return (data & mask) >> (offset % 8);
-}
-
-static void ab8500_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
-{
-       struct ab8500_gpio *ab8500_gpio = to_ab8500_gpio(chip);
-       int ret;
-       /* Write the data */
-       ret = ab8500_gpio_set_bits(chip, AB8500_GPIO_OUT1_REG, offset, 1);
-       if (ret < 0)
-               dev_err(ab8500_gpio->dev, "%s write failed\n", __func__);
-}
-
-static int ab8500_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
-                                       int val)
-{
-       int ret;
-       /* set direction as output */
-       ret = ab8500_gpio_set_bits(chip, AB8500_GPIO_DIR1_REG, offset, 1);
-       if (ret < 0)
-               return ret;
-       /* disable pull down */
-       ret = ab8500_gpio_set_bits(chip, AB8500_GPIO_PUD1_REG, offset, 1);
-       if (ret < 0)
-               return ret;
-       /* set the output as 1 or 0 */
-       return ab8500_gpio_set_bits(chip, AB8500_GPIO_OUT1_REG, offset, val);
-
-}
-
-static int ab8500_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
-{
-       /* set the register as input */
-       return ab8500_gpio_set_bits(chip, AB8500_GPIO_DIR1_REG, offset, 0);
-}
-
-static int ab8500_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
-{
-       /*
-        * Only some GPIOs are interrupt capable, and they are
-        * organized in discontiguous clusters:
-        *
-        *      GPIO6 to GPIO13
-        *      GPIO24 and GPIO25
-        *      GPIO36 to GPIO41
-        */
-       static struct ab8500_gpio_irq_cluster {
-               int start;
-               int end;
-       } clusters[] = {
-               {.start = 6,  .end = 13},
-               {.start = 24, .end = 25},
-               {.start = 36, .end = 41},
-       };
-       struct ab8500_gpio *ab8500_gpio = to_ab8500_gpio(chip);
-       int base = ab8500_gpio->irq_base;
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(clusters); i++) {
-               struct ab8500_gpio_irq_cluster *cluster = &clusters[i];
-
-               if (offset >= cluster->start && offset <= cluster->end)
-                       return base + offset - cluster->start;
-
-               /* Advance by the number of gpios in this cluster */
-               base += cluster->end - cluster->start + 1;
-       }
-
-       return -EINVAL;
-}
-
-static struct gpio_chip ab8500gpio_chip = {
-       .label                  = "ab8500_gpio",
-       .owner                  = THIS_MODULE,
-       .direction_input        = ab8500_gpio_direction_input,
-       .get                    = ab8500_gpio_get,
-       .direction_output       = ab8500_gpio_direction_output,
-       .set                    = ab8500_gpio_set,
-       .to_irq                 = ab8500_gpio_to_irq,
-};
-
-static unsigned int irq_to_rising(unsigned int irq)
-{
-       struct ab8500_gpio *ab8500_gpio = get_irq_chip_data(irq);
-       int offset = irq - ab8500_gpio->irq_base;
-       int new_irq = offset +  AB8500_INT_GPIO6R
-                       + ab8500_gpio->parent->irq_base;
-       return new_irq;
-}
-
-static unsigned int irq_to_falling(unsigned int irq)
-{
-       struct ab8500_gpio *ab8500_gpio = get_irq_chip_data(irq);
-       int offset = irq - ab8500_gpio->irq_base;
-       int new_irq = offset +  AB8500_INT_GPIO6F
-                       +  ab8500_gpio->parent->irq_base;
-       return new_irq;
-
-}
-
-static unsigned int rising_to_irq(unsigned int irq, void *dev)
-{
-       struct ab8500_gpio *ab8500_gpio = dev;
-       int offset = irq - AB8500_INT_GPIO6R
-                       - ab8500_gpio->parent->irq_base ;
-       int new_irq = offset + ab8500_gpio->irq_base;
-       return new_irq;
-}
-
-static unsigned int falling_to_irq(unsigned int irq, void *dev)
-{
-       struct ab8500_gpio *ab8500_gpio = dev;
-       int offset = irq - AB8500_INT_GPIO6F
-                       - ab8500_gpio->parent->irq_base ;
-       int new_irq = offset + ab8500_gpio->irq_base;
-       return new_irq;
-
-}
-
-/*
- * IRQ handler
- */
-
-static irqreturn_t handle_rising(int irq, void *dev)
-{
-
-       handle_nested_irq(rising_to_irq(irq , dev));
-       return IRQ_HANDLED;
-}
-
-static irqreturn_t handle_falling(int irq, void *dev)
-{
-
-       handle_nested_irq(falling_to_irq(irq, dev));
-       return IRQ_HANDLED;
-}
-
-static void ab8500_gpio_irq_lock(unsigned int irq)
-{
-       struct ab8500_gpio *ab8500_gpio = get_irq_chip_data(irq);
-       mutex_lock(&ab8500_gpio->lock);
-}
-
-static void ab8500_gpio_irq_sync_unlock(unsigned int irq)
-{
-       struct ab8500_gpio *ab8500_gpio = get_irq_chip_data(irq);
-       int offset = irq - ab8500_gpio->irq_base;
-       bool rising = ab8500_gpio->rising & BIT(offset);
-       bool falling = ab8500_gpio->falling & BIT(offset);
-       int ret;
-
-       switch (ab8500_gpio->irq_action)        {
-       case STARTUP:
-               if (rising)
-                       ret = request_threaded_irq(irq_to_rising(irq),
-                                       NULL, handle_rising,
-                                       IRQF_TRIGGER_RISING,
-                                       "ab8500-gpio-r", ab8500_gpio);
-               if (falling)
-                       ret = request_threaded_irq(irq_to_falling(irq),
-                                      NULL, handle_falling,
-                                      IRQF_TRIGGER_FALLING,
-                                      "ab8500-gpio-f", ab8500_gpio);
-               break;
-       case SHUTDOWN:
-               if (rising)
-                       free_irq(irq_to_rising(irq), ab8500_gpio);
-               if (falling)
-                       free_irq(irq_to_falling(irq), ab8500_gpio);
-               break;
-       case MASK:
-               if (rising)
-                       disable_irq(irq_to_rising(irq));
-               if (falling)
-                       disable_irq(irq_to_falling(irq));
-               break;
-       case UNMASK:
-               if (rising)
-                       enable_irq(irq_to_rising(irq));
-               if (falling)
-                       enable_irq(irq_to_falling(irq));
-               break;
-       case NONE:
-               break;
-       }
-       ab8500_gpio->irq_action = NONE;
-       ab8500_gpio->rising &= ~(BIT(offset));
-       ab8500_gpio->falling &= ~(BIT(offset));
-       mutex_unlock(&ab8500_gpio->lock);
-}
-
-
-static void ab8500_gpio_irq_mask(unsigned int irq)
-{
-       struct ab8500_gpio *ab8500_gpio = get_irq_chip_data(irq);
-       ab8500_gpio->irq_action = MASK;
-}
-
-static void ab8500_gpio_irq_unmask(unsigned int irq)
-{
-       struct ab8500_gpio *ab8500_gpio = get_irq_chip_data(irq);
-       ab8500_gpio->irq_action = UNMASK;
-}
-
-static int ab8500_gpio_irq_set_type(unsigned int irq, unsigned int type)
-{
-       struct ab8500_gpio *ab8500_gpio = get_irq_chip_data(irq);
-       int offset = irq - ab8500_gpio->irq_base;
-
-       if (type == IRQ_TYPE_EDGE_BOTH) {
-               ab8500_gpio->rising =  BIT(offset);
-               ab8500_gpio->falling = BIT(offset);
-       } else if (type == IRQ_TYPE_EDGE_RISING) {
-               ab8500_gpio->rising =  BIT(offset);
-       } else  {
-               ab8500_gpio->falling = BIT(offset);
-       }
-       return 0;
-}
-
-unsigned int ab8500_gpio_irq_startup(unsigned int irq)
-{
-       struct ab8500_gpio *ab8500_gpio = get_irq_chip_data(irq);
-       ab8500_gpio->irq_action = STARTUP;
-       return 0;
-}
-
-void ab8500_gpio_irq_shutdown(unsigned int irq)
-{
-       struct ab8500_gpio *ab8500_gpio = get_irq_chip_data(irq);
-       ab8500_gpio->irq_action = SHUTDOWN;
-}
-
-static struct irq_chip ab8500_gpio_irq_chip = {
-       .name                   = "ab8500-gpio",
-       .startup                = ab8500_gpio_irq_startup,
-       .shutdown               = ab8500_gpio_irq_shutdown,
-       .bus_lock               = ab8500_gpio_irq_lock,
-       .bus_sync_unlock        = ab8500_gpio_irq_sync_unlock,
-       .mask                   = ab8500_gpio_irq_mask,
-       .unmask                 = ab8500_gpio_irq_unmask,
-       .set_type               = ab8500_gpio_irq_set_type,
-};
-
-static int ab8500_gpio_irq_init(struct ab8500_gpio *ab8500_gpio)
-{
-       u32 base = ab8500_gpio->irq_base;
-       int irq;
-
-       for (irq = base; irq < base + AB8500_NUM_VIR_GPIO_IRQ ; irq++) {
-               set_irq_chip_data(irq, ab8500_gpio);
-               set_irq_chip_and_handler(irq, &ab8500_gpio_irq_chip,
-                               handle_simple_irq);
-               set_irq_nested_thread(irq, 1);
-#ifdef CONFIG_ARM
-               set_irq_flags(irq, IRQF_VALID);
-#else
-               set_irq_noprobe(irq);
-#endif
-       }
-
-       return 0;
-}
-
-static void ab8500_gpio_irq_remove(struct ab8500_gpio *ab8500_gpio)
-{
-       int base = ab8500_gpio->irq_base;
-       int irq;
-
-       for (irq = base; irq < base + AB8500_NUM_VIR_GPIO_IRQ; irq++) {
-#ifdef CONFIG_ARM
-               set_irq_flags(irq, 0);
-#endif
-               set_irq_chip_and_handler(irq, NULL, NULL);
-               set_irq_chip_data(irq, NULL);
-       }
-}
-
-static int __devinit ab8500_gpio_probe(struct platform_device *pdev)
-{
-       struct ab8500_platform_data *ab8500_pdata =
-                               dev_get_platdata(pdev->dev.parent);
-       struct ab8500_gpio_platform_data *pdata;
-       struct ab8500_gpio *ab8500_gpio;
-       int ret;
-       int i;
-
-       pdata = ab8500_pdata->gpio;
-       if (!pdata)     {
-               dev_err(&pdev->dev, "gpio platform data missing\n");
-               return -ENODEV;
-       }
-
-       ab8500_gpio = kzalloc(sizeof(struct ab8500_gpio), GFP_KERNEL);
-       if (ab8500_gpio == NULL) {
-               dev_err(&pdev->dev, "failed to allocate memory\n");
-               return -ENOMEM;
-       }
-       ab8500_gpio->dev = &pdev->dev;
-       ab8500_gpio->parent = dev_get_drvdata(pdev->dev.parent);
-       ab8500_gpio->chip = ab8500gpio_chip;
-       ab8500_gpio->chip.ngpio = AB8500_NUM_GPIO;
-       ab8500_gpio->chip.dev = &pdev->dev;
-       ab8500_gpio->chip.base = pdata->gpio_base;
-       ab8500_gpio->irq_base = pdata->irq_base;
-       /* initialize the lock */
-       mutex_init(&ab8500_gpio->lock);
-       /*
-        * AB8500 core will handle and clear the IRQ
-        * configre GPIO based on config-reg value.
-        * These values are for selecting the PINs as
-        * GPIO or alternate function
-        */
-       for (i = AB8500_GPIO_SEL1_REG; i <= AB8500_GPIO_SEL6_REG; i++)  {
-               ret = abx500_set_register_interruptible(ab8500_gpio->dev,
-                               AB8500_MISC, i,
-                               pdata->config_reg[i]);
-               if (ret < 0)
-                       goto out_free;
-       }
-       ret = abx500_set_register_interruptible(ab8500_gpio->dev, AB8500_MISC,
-                               AB8500_GPIO_ALTFUN_REG,
-                               pdata->config_reg[ALTFUN_REG_INDEX]);
-       if (ret < 0)
-               goto out_free;
-
-       ret = ab8500_gpio_irq_init(ab8500_gpio);
-       if (ret)
-               goto out_free;
-       ret = gpiochip_add(&ab8500_gpio->chip);
-       if (ret) {
-               dev_err(&pdev->dev, "unable to add gpiochip: %d\n",
-                               ret);
-               goto out_rem_irq;
-       }
-       platform_set_drvdata(pdev, ab8500_gpio);
-       return 0;
-
-out_rem_irq:
-       ab8500_gpio_irq_remove(ab8500_gpio);
-out_free:
-       mutex_destroy(&ab8500_gpio->lock);
-       kfree(ab8500_gpio);
-       return ret;
-}
-
-/*
- * ab8500_gpio_remove() - remove Ab8500-gpio driver
- * @pdev :     Platform device registered
- */
-static int __devexit ab8500_gpio_remove(struct platform_device *pdev)
-{
-       struct ab8500_gpio *ab8500_gpio = platform_get_drvdata(pdev);
-       int ret;
-
-       ret = gpiochip_remove(&ab8500_gpio->chip);
-       if (ret < 0) {
-               dev_err(ab8500_gpio->dev, "unable to remove gpiochip: %d\n",
-                       ret);
-               return ret;
-       }
-
-       platform_set_drvdata(pdev, NULL);
-       mutex_destroy(&ab8500_gpio->lock);
-       kfree(ab8500_gpio);
-
-       return 0;
-}
-
-static struct platform_driver ab8500_gpio_driver = {
-       .driver = {
-               .name = "ab8500-gpio",
-               .owner = THIS_MODULE,
-       },
-       .probe = ab8500_gpio_probe,
-       .remove = __devexit_p(ab8500_gpio_remove),
-};
-
-static int __init ab8500_gpio_init(void)
-{
-       return platform_driver_register(&ab8500_gpio_driver);
-}
-arch_initcall(ab8500_gpio_init);
-
-static void __exit ab8500_gpio_exit(void)
-{
-       platform_driver_unregister(&ab8500_gpio_driver);
-}
-module_exit(ab8500_gpio_exit);
-
-MODULE_AUTHOR("BIBEK BASU <bibek.basu@stericsson.com>");
-MODULE_DESCRIPTION("Driver allows to use AB8500 unused pins to be used as GPIO");
-MODULE_ALIAS("AB8500 GPIO driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpio/adp5520-gpio.c b/drivers/gpio/adp5520-gpio.c
deleted file mode 100644 (file)
index 9f27815..0000000
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * GPIO driver for Analog Devices ADP5520 MFD PMICs
- *
- * Copyright 2009 Analog Devices Inc.
- *
- * Licensed under the GPL-2 or later.
- */
-
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/mfd/adp5520.h>
-
-#include <linux/gpio.h>
-
-struct adp5520_gpio {
-       struct device *master;
-       struct gpio_chip gpio_chip;
-       unsigned char lut[ADP5520_MAXGPIOS];
-       unsigned long output;
-};
-
-static int adp5520_gpio_get_value(struct gpio_chip *chip, unsigned off)
-{
-       struct adp5520_gpio *dev;
-       uint8_t reg_val;
-
-       dev = container_of(chip, struct adp5520_gpio, gpio_chip);
-
-       /*
-        * There are dedicated registers for GPIO IN/OUT.
-        * Make sure we return the right value, even when configured as output
-        */
-
-       if (test_bit(off, &dev->output))
-               adp5520_read(dev->master, ADP5520_GPIO_OUT, &reg_val);
-       else
-               adp5520_read(dev->master, ADP5520_GPIO_IN, &reg_val);
-
-       return !!(reg_val & dev->lut[off]);
-}
-
-static void adp5520_gpio_set_value(struct gpio_chip *chip,
-               unsigned off, int val)
-{
-       struct adp5520_gpio *dev;
-       dev = container_of(chip, struct adp5520_gpio, gpio_chip);
-
-       if (val)
-               adp5520_set_bits(dev->master, ADP5520_GPIO_OUT, dev->lut[off]);
-       else
-               adp5520_clr_bits(dev->master, ADP5520_GPIO_OUT, dev->lut[off]);
-}
-
-static int adp5520_gpio_direction_input(struct gpio_chip *chip, unsigned off)
-{
-       struct adp5520_gpio *dev;
-       dev = container_of(chip, struct adp5520_gpio, gpio_chip);
-
-       clear_bit(off, &dev->output);
-
-       return adp5520_clr_bits(dev->master, ADP5520_GPIO_CFG_2,
-                               dev->lut[off]);
-}
-
-static int adp5520_gpio_direction_output(struct gpio_chip *chip,
-               unsigned off, int val)
-{
-       struct adp5520_gpio *dev;
-       int ret = 0;
-       dev = container_of(chip, struct adp5520_gpio, gpio_chip);
-
-       set_bit(off, &dev->output);
-
-       if (val)
-               ret |= adp5520_set_bits(dev->master, ADP5520_GPIO_OUT,
-                                       dev->lut[off]);
-       else
-               ret |= adp5520_clr_bits(dev->master, ADP5520_GPIO_OUT,
-                                       dev->lut[off]);
-
-       ret |= adp5520_set_bits(dev->master, ADP5520_GPIO_CFG_2,
-                                       dev->lut[off]);
-
-       return ret;
-}
-
-static int __devinit adp5520_gpio_probe(struct platform_device *pdev)
-{
-       struct adp5520_gpio_platform_data *pdata = pdev->dev.platform_data;
-       struct adp5520_gpio *dev;
-       struct gpio_chip *gc;
-       int ret, i, gpios;
-       unsigned char ctl_mask = 0;
-
-       if (pdata == NULL) {
-               dev_err(&pdev->dev, "missing platform data\n");
-               return -ENODEV;
-       }
-
-       if (pdev->id != ID_ADP5520) {
-               dev_err(&pdev->dev, "only ADP5520 supports GPIO\n");
-               return -ENODEV;
-       }
-
-       dev = kzalloc(sizeof(*dev), GFP_KERNEL);
-       if (dev == NULL) {
-               dev_err(&pdev->dev, "failed to alloc memory\n");
-               return -ENOMEM;
-       }
-
-       dev->master = pdev->dev.parent;
-
-       for (gpios = 0, i = 0; i < ADP5520_MAXGPIOS; i++)
-               if (pdata->gpio_en_mask & (1 << i))
-                       dev->lut[gpios++] = 1 << i;
-
-       if (gpios < 1) {
-               ret = -EINVAL;
-               goto err;
-       }
-
-       gc = &dev->gpio_chip;
-       gc->direction_input  = adp5520_gpio_direction_input;
-       gc->direction_output = adp5520_gpio_direction_output;
-       gc->get = adp5520_gpio_get_value;
-       gc->set = adp5520_gpio_set_value;
-       gc->can_sleep = 1;
-
-       gc->base = pdata->gpio_start;
-       gc->ngpio = gpios;
-       gc->label = pdev->name;
-       gc->owner = THIS_MODULE;
-
-       ret = adp5520_clr_bits(dev->master, ADP5520_GPIO_CFG_1,
-               pdata->gpio_en_mask);
-
-       if (pdata->gpio_en_mask & ADP5520_GPIO_C3)
-               ctl_mask |= ADP5520_C3_MODE;
-
-       if (pdata->gpio_en_mask & ADP5520_GPIO_R3)
-               ctl_mask |= ADP5520_R3_MODE;
-
-       if (ctl_mask)
-               ret = adp5520_set_bits(dev->master, ADP5520_LED_CONTROL,
-                       ctl_mask);
-
-       ret |= adp5520_set_bits(dev->master, ADP5520_GPIO_PULLUP,
-               pdata->gpio_pullup_mask);
-
-       if (ret) {
-               dev_err(&pdev->dev, "failed to write\n");
-               goto err;
-       }
-
-       ret = gpiochip_add(&dev->gpio_chip);
-       if (ret)
-               goto err;
-
-       platform_set_drvdata(pdev, dev);
-       return 0;
-
-err:
-       kfree(dev);
-       return ret;
-}
-
-static int __devexit adp5520_gpio_remove(struct platform_device *pdev)
-{
-       struct adp5520_gpio *dev;
-       int ret;
-
-       dev = platform_get_drvdata(pdev);
-       ret = gpiochip_remove(&dev->gpio_chip);
-       if (ret) {
-               dev_err(&pdev->dev, "%s failed, %d\n",
-                               "gpiochip_remove()", ret);
-               return ret;
-       }
-
-       kfree(dev);
-       return 0;
-}
-
-static struct platform_driver adp5520_gpio_driver = {
-       .driver = {
-               .name   = "adp5520-gpio",
-               .owner  = THIS_MODULE,
-       },
-       .probe          = adp5520_gpio_probe,
-       .remove         = __devexit_p(adp5520_gpio_remove),
-};
-
-static int __init adp5520_gpio_init(void)
-{
-       return platform_driver_register(&adp5520_gpio_driver);
-}
-module_init(adp5520_gpio_init);
-
-static void __exit adp5520_gpio_exit(void)
-{
-       platform_driver_unregister(&adp5520_gpio_driver);
-}
-module_exit(adp5520_gpio_exit);
-
-MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
-MODULE_DESCRIPTION("GPIO ADP5520 Driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:adp5520-gpio");
diff --git a/drivers/gpio/adp5588-gpio.c b/drivers/gpio/adp5588-gpio.c
deleted file mode 100644 (file)
index 3525ad9..0000000
+++ /dev/null
@@ -1,503 +0,0 @@
-/*
- * GPIO Chip driver for Analog Devices
- * ADP5588/ADP5587 I/O Expander and QWERTY Keypad Controller
- *
- * Copyright 2009-2010 Analog Devices Inc.
- *
- * Licensed under the GPL-2 or later.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/i2c.h>
-#include <linux/gpio.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-
-#include <linux/i2c/adp5588.h>
-
-#define DRV_NAME       "adp5588-gpio"
-
-/*
- * Early pre 4.0 Silicon required to delay readout by at least 25ms,
- * since the Event Counter Register updated 25ms after the interrupt
- * asserted.
- */
-#define WA_DELAYED_READOUT_REVID(rev)  ((rev) < 4)
-
-struct adp5588_gpio {
-       struct i2c_client *client;
-       struct gpio_chip gpio_chip;
-       struct mutex lock;      /* protect cached dir, dat_out */
-       /* protect serialized access to the interrupt controller bus */
-       struct mutex irq_lock;
-       unsigned gpio_start;
-       unsigned irq_base;
-       uint8_t dat_out[3];
-       uint8_t dir[3];
-       uint8_t int_lvl[3];
-       uint8_t int_en[3];
-       uint8_t irq_mask[3];
-       uint8_t irq_stat[3];
-};
-
-static int adp5588_gpio_read(struct i2c_client *client, u8 reg)
-{
-       int ret = i2c_smbus_read_byte_data(client, reg);
-
-       if (ret < 0)
-               dev_err(&client->dev, "Read Error\n");
-
-       return ret;
-}
-
-static int adp5588_gpio_write(struct i2c_client *client, u8 reg, u8 val)
-{
-       int ret = i2c_smbus_write_byte_data(client, reg, val);
-
-       if (ret < 0)
-               dev_err(&client->dev, "Write Error\n");
-
-       return ret;
-}
-
-static int adp5588_gpio_get_value(struct gpio_chip *chip, unsigned off)
-{
-       struct adp5588_gpio *dev =
-           container_of(chip, struct adp5588_gpio, gpio_chip);
-
-       return !!(adp5588_gpio_read(dev->client,
-                 GPIO_DAT_STAT1 + ADP5588_BANK(off)) & ADP5588_BIT(off));
-}
-
-static void adp5588_gpio_set_value(struct gpio_chip *chip,
-                                  unsigned off, int val)
-{
-       unsigned bank, bit;
-       struct adp5588_gpio *dev =
-           container_of(chip, struct adp5588_gpio, gpio_chip);
-
-       bank = ADP5588_BANK(off);
-       bit = ADP5588_BIT(off);
-
-       mutex_lock(&dev->lock);
-       if (val)
-               dev->dat_out[bank] |= bit;
-       else
-               dev->dat_out[bank] &= ~bit;
-
-       adp5588_gpio_write(dev->client, GPIO_DAT_OUT1 + bank,
-                          dev->dat_out[bank]);
-       mutex_unlock(&dev->lock);
-}
-
-static int adp5588_gpio_direction_input(struct gpio_chip *chip, unsigned off)
-{
-       int ret;
-       unsigned bank;
-       struct adp5588_gpio *dev =
-           container_of(chip, struct adp5588_gpio, gpio_chip);
-
-       bank = ADP5588_BANK(off);
-
-       mutex_lock(&dev->lock);
-       dev->dir[bank] &= ~ADP5588_BIT(off);
-       ret = adp5588_gpio_write(dev->client, GPIO_DIR1 + bank, dev->dir[bank]);
-       mutex_unlock(&dev->lock);
-
-       return ret;
-}
-
-static int adp5588_gpio_direction_output(struct gpio_chip *chip,
-                                        unsigned off, int val)
-{
-       int ret;
-       unsigned bank, bit;
-       struct adp5588_gpio *dev =
-           container_of(chip, struct adp5588_gpio, gpio_chip);
-
-       bank = ADP5588_BANK(off);
-       bit = ADP5588_BIT(off);
-
-       mutex_lock(&dev->lock);
-       dev->dir[bank] |= bit;
-
-       if (val)
-               dev->dat_out[bank] |= bit;
-       else
-               dev->dat_out[bank] &= ~bit;
-
-       ret = adp5588_gpio_write(dev->client, GPIO_DAT_OUT1 + bank,
-                                dev->dat_out[bank]);
-       ret |= adp5588_gpio_write(dev->client, GPIO_DIR1 + bank,
-                                dev->dir[bank]);
-       mutex_unlock(&dev->lock);
-
-       return ret;
-}
-
-#ifdef CONFIG_GPIO_ADP5588_IRQ
-static int adp5588_gpio_to_irq(struct gpio_chip *chip, unsigned off)
-{
-       struct adp5588_gpio *dev =
-               container_of(chip, struct adp5588_gpio, gpio_chip);
-       return dev->irq_base + off;
-}
-
-static void adp5588_irq_bus_lock(struct irq_data *d)
-{
-       struct adp5588_gpio *dev = irq_data_get_irq_chip_data(d);
-
-       mutex_lock(&dev->irq_lock);
-}
-
- /*
-  * genirq core code can issue chip->mask/unmask from atomic context.
-  * This doesn't work for slow busses where an access needs to sleep.
-  * bus_sync_unlock() is therefore called outside the atomic context,
-  * syncs the current irq mask state with the slow external controller
-  * and unlocks the bus.
-  */
-
-static void adp5588_irq_bus_sync_unlock(struct irq_data *d)
-{
-       struct adp5588_gpio *dev = irq_data_get_irq_chip_data(d);
-       int i;
-
-       for (i = 0; i <= ADP5588_BANK(ADP5588_MAXGPIO); i++)
-               if (dev->int_en[i] ^ dev->irq_mask[i]) {
-                       dev->int_en[i] = dev->irq_mask[i];
-                       adp5588_gpio_write(dev->client, GPIO_INT_EN1 + i,
-                                          dev->int_en[i]);
-               }
-
-       mutex_unlock(&dev->irq_lock);
-}
-
-static void adp5588_irq_mask(struct irq_data *d)
-{
-       struct adp5588_gpio *dev = irq_data_get_irq_chip_data(d);
-       unsigned gpio = d->irq - dev->irq_base;
-
-       dev->irq_mask[ADP5588_BANK(gpio)] &= ~ADP5588_BIT(gpio);
-}
-
-static void adp5588_irq_unmask(struct irq_data *d)
-{
-       struct adp5588_gpio *dev = irq_data_get_irq_chip_data(d);
-       unsigned gpio = d->irq - dev->irq_base;
-
-       dev->irq_mask[ADP5588_BANK(gpio)] |= ADP5588_BIT(gpio);
-}
-
-static int adp5588_irq_set_type(struct irq_data *d, unsigned int type)
-{
-       struct adp5588_gpio *dev = irq_data_get_irq_chip_data(d);
-       uint16_t gpio = d->irq - dev->irq_base;
-       unsigned bank, bit;
-
-       if ((type & IRQ_TYPE_EDGE_BOTH)) {
-               dev_err(&dev->client->dev, "irq %d: unsupported type %d\n",
-                       d->irq, type);
-               return -EINVAL;
-       }
-
-       bank = ADP5588_BANK(gpio);
-       bit = ADP5588_BIT(gpio);
-
-       if (type & IRQ_TYPE_LEVEL_HIGH)
-               dev->int_lvl[bank] |= bit;
-       else if (type & IRQ_TYPE_LEVEL_LOW)
-               dev->int_lvl[bank] &= ~bit;
-       else
-               return -EINVAL;
-
-       adp5588_gpio_direction_input(&dev->gpio_chip, gpio);
-       adp5588_gpio_write(dev->client, GPIO_INT_LVL1 + bank,
-                          dev->int_lvl[bank]);
-
-       return 0;
-}
-
-static struct irq_chip adp5588_irq_chip = {
-       .name                   = "adp5588",
-       .irq_mask               = adp5588_irq_mask,
-       .irq_unmask             = adp5588_irq_unmask,
-       .irq_bus_lock           = adp5588_irq_bus_lock,
-       .irq_bus_sync_unlock    = adp5588_irq_bus_sync_unlock,
-       .irq_set_type           = adp5588_irq_set_type,
-};
-
-static int adp5588_gpio_read_intstat(struct i2c_client *client, u8 *buf)
-{
-       int ret = i2c_smbus_read_i2c_block_data(client, GPIO_INT_STAT1, 3, buf);
-
-       if (ret < 0)
-               dev_err(&client->dev, "Read INT_STAT Error\n");
-
-       return ret;
-}
-
-static irqreturn_t adp5588_irq_handler(int irq, void *devid)
-{
-       struct adp5588_gpio *dev = devid;
-       unsigned status, bank, bit, pending;
-       int ret;
-       status = adp5588_gpio_read(dev->client, INT_STAT);
-
-       if (status & ADP5588_GPI_INT) {
-               ret = adp5588_gpio_read_intstat(dev->client, dev->irq_stat);
-               if (ret < 0)
-                       memset(dev->irq_stat, 0, ARRAY_SIZE(dev->irq_stat));
-
-               for (bank = 0; bank <= ADP5588_BANK(ADP5588_MAXGPIO);
-                       bank++, bit = 0) {
-                       pending = dev->irq_stat[bank] & dev->irq_mask[bank];
-
-                       while (pending) {
-                               if (pending & (1 << bit)) {
-                                       handle_nested_irq(dev->irq_base +
-                                                         (bank << 3) + bit);
-                                       pending &= ~(1 << bit);
-
-                               }
-                               bit++;
-                       }
-               }
-       }
-
-       adp5588_gpio_write(dev->client, INT_STAT, status); /* Status is W1C */
-
-       return IRQ_HANDLED;
-}
-
-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;
-       unsigned gpio;
-       int ret;
-
-       adp5588_gpio_write(client, CFG, ADP5588_AUTO_INC);
-       adp5588_gpio_write(client, INT_STAT, -1); /* status is W1C */
-       adp5588_gpio_read_intstat(client, dev->irq_stat); /* read to clear */
-
-       dev->irq_base = pdata->irq_base;
-       mutex_init(&dev->irq_lock);
-
-       for (gpio = 0; gpio < dev->gpio_chip.ngpio; gpio++) {
-               int irq = gpio + dev->irq_base;
-               irq_set_chip_data(irq, dev);
-               irq_set_chip_and_handler(irq, &adp5588_irq_chip,
-                                        handle_level_irq);
-               irq_set_nested_thread(irq, 1);
-#ifdef CONFIG_ARM
-               /*
-                * ARM needs us to explicitly flag the IRQ as VALID,
-                * once we do so, it will also set the noprobe.
-                */
-               set_irq_flags(irq, IRQF_VALID);
-#else
-               irq_set_noprobe(irq);
-#endif
-       }
-
-       ret = request_threaded_irq(client->irq,
-                                  NULL,
-                                  adp5588_irq_handler,
-                                  IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
-                                  dev_name(&client->dev), dev);
-       if (ret) {
-               dev_err(&client->dev, "failed to request irq %d\n",
-                       client->irq);
-               goto out;
-       }
-
-       dev->gpio_chip.to_irq = adp5588_gpio_to_irq;
-       adp5588_gpio_write(client, CFG,
-               ADP5588_AUTO_INC | ADP5588_INT_CFG | ADP5588_GPI_INT);
-
-       return 0;
-
-out:
-       dev->irq_base = 0;
-       return ret;
-}
-
-static void adp5588_irq_teardown(struct adp5588_gpio *dev)
-{
-       if (dev->irq_base)
-               free_irq(dev->client->irq, dev);
-}
-
-#else
-static int adp5588_irq_setup(struct adp5588_gpio *dev)
-{
-       struct i2c_client *client = dev->client;
-       dev_warn(&client->dev, "interrupt support not compiled in\n");
-
-       return 0;
-}
-
-static void adp5588_irq_teardown(struct adp5588_gpio *dev)
-{
-}
-#endif /* CONFIG_GPIO_ADP5588_IRQ */
-
-static int __devinit 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 *dev;
-       struct gpio_chip *gc;
-       int ret, i, revid;
-
-       if (pdata == NULL) {
-               dev_err(&client->dev, "missing platform data\n");
-               return -ENODEV;
-       }
-
-       if (!i2c_check_functionality(client->adapter,
-                                       I2C_FUNC_SMBUS_BYTE_DATA)) {
-               dev_err(&client->dev, "SMBUS Byte Data not Supported\n");
-               return -EIO;
-       }
-
-       dev = kzalloc(sizeof(*dev), GFP_KERNEL);
-       if (dev == NULL) {
-               dev_err(&client->dev, "failed to alloc memory\n");
-               return -ENOMEM;
-       }
-
-       dev->client = client;
-
-       gc = &dev->gpio_chip;
-       gc->direction_input = adp5588_gpio_direction_input;
-       gc->direction_output = adp5588_gpio_direction_output;
-       gc->get = adp5588_gpio_get_value;
-       gc->set = adp5588_gpio_set_value;
-       gc->can_sleep = 1;
-
-       gc->base = pdata->gpio_start;
-       gc->ngpio = ADP5588_MAXGPIO;
-       gc->label = client->name;
-       gc->owner = THIS_MODULE;
-
-       mutex_init(&dev->lock);
-
-       ret = adp5588_gpio_read(dev->client, DEV_ID);
-       if (ret < 0)
-               goto err;
-
-       revid = ret & ADP5588_DEVICE_ID_MASK;
-
-       for (i = 0, ret = 0; i <= ADP5588_BANK(ADP5588_MAXGPIO); i++) {
-               dev->dat_out[i] = adp5588_gpio_read(client, GPIO_DAT_OUT1 + i);
-               dev->dir[i] = adp5588_gpio_read(client, GPIO_DIR1 + i);
-               ret |= adp5588_gpio_write(client, KP_GPIO1 + i, 0);
-               ret |= adp5588_gpio_write(client, GPIO_PULL1 + i,
-                               (pdata->pullup_dis_mask >> (8 * i)) & 0xFF);
-               ret |= adp5588_gpio_write(client, GPIO_INT_EN1 + i, 0);
-               if (ret)
-                       goto err;
-       }
-
-       if (pdata->irq_base) {
-               if (WA_DELAYED_READOUT_REVID(revid)) {
-                       dev_warn(&client->dev, "GPIO int not supported\n");
-               } else {
-                       ret = adp5588_irq_setup(dev);
-                       if (ret)
-                               goto err;
-               }
-       }
-
-       ret = gpiochip_add(&dev->gpio_chip);
-       if (ret)
-               goto err_irq;
-
-       dev_info(&client->dev, "gpios %d..%d (IRQ Base %d) on a %s Rev. %d\n",
-                       gc->base, gc->base + gc->ngpio - 1,
-                       pdata->irq_base, client->name, revid);
-
-       if (pdata->setup) {
-               ret = pdata->setup(client, gc->base, gc->ngpio, pdata->context);
-               if (ret < 0)
-                       dev_warn(&client->dev, "setup failed, %d\n", ret);
-       }
-
-       i2c_set_clientdata(client, dev);
-
-       return 0;
-
-err_irq:
-       adp5588_irq_teardown(dev);
-err:
-       kfree(dev);
-       return ret;
-}
-
-static int __devexit adp5588_gpio_remove(struct i2c_client *client)
-{
-       struct adp5588_gpio_platform_data *pdata = client->dev.platform_data;
-       struct adp5588_gpio *dev = i2c_get_clientdata(client);
-       int ret;
-
-       if (pdata->teardown) {
-               ret = pdata->teardown(client,
-                                     dev->gpio_chip.base, dev->gpio_chip.ngpio,
-                                     pdata->context);
-               if (ret < 0) {
-                       dev_err(&client->dev, "teardown failed %d\n", ret);
-                       return ret;
-               }
-       }
-
-       if (dev->irq_base)
-               free_irq(dev->client->irq, dev);
-
-       ret = gpiochip_remove(&dev->gpio_chip);
-       if (ret) {
-               dev_err(&client->dev, "gpiochip_remove failed %d\n", ret);
-               return ret;
-       }
-
-       kfree(dev);
-       return 0;
-}
-
-static const struct i2c_device_id adp5588_gpio_id[] = {
-       {DRV_NAME, 0},
-       {}
-};
-
-MODULE_DEVICE_TABLE(i2c, adp5588_gpio_id);
-
-static struct i2c_driver adp5588_gpio_driver = {
-       .driver = {
-                  .name = DRV_NAME,
-                  },
-       .probe = adp5588_gpio_probe,
-       .remove = __devexit_p(adp5588_gpio_remove),
-       .id_table = adp5588_gpio_id,
-};
-
-static int __init adp5588_gpio_init(void)
-{
-       return i2c_add_driver(&adp5588_gpio_driver);
-}
-
-module_init(adp5588_gpio_init);
-
-static void __exit adp5588_gpio_exit(void)
-{
-       i2c_del_driver(&adp5588_gpio_driver);
-}
-
-module_exit(adp5588_gpio_exit);
-
-MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
-MODULE_DESCRIPTION("GPIO ADP5588 Driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/basic_mmio_gpio.c b/drivers/gpio/basic_mmio_gpio.c
deleted file mode 100644 (file)
index 8152e9f..0000000
+++ /dev/null
@@ -1,548 +0,0 @@
-/*
- * Driver for basic memory-mapped GPIO controllers.
- *
- * Copyright 2008 MontaVista Software, Inc.
- * Copyright 2008,2010 Anton Vorontsov <cbouatmailru@gmail.com>
- *
- * 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.
- *
- * ....``.```~~~~````.`.`.`.`.```````'',,,.........`````......`.......
- * ...``                                                         ```````..
- * ..The simplest form of a GPIO controller that the driver supports is``
- *  `.just a single "data" register, where GPIO state can be read and/or `
- *    `,..written. ,,..``~~~~ .....``.`.`.~~.```.`.........``````.```````
- *        `````````
-                                    ___
-_/~~|___/~|   . ```~~~~~~       ___/___\___     ,~.`.`.`.`````.~~...,,,,...
-__________|~$@~~~        %~    /o*o*o*o*o*o\   .. Implementing such a GPIO .
-o        `                     ~~~~\___/~~~~    ` controller in FPGA is ,.`
-                                                 `....trivial..'~`.```.```
- *                                                    ```````
- *  .```````~~~~`..`.``.``.
- * .  The driver supports  `...       ,..```.`~~~```````````````....````.``,,
- * .   big-endian notation, just`.  .. A bit more sophisticated controllers ,
- *  . register the device with -be`. .with a pair of set/clear-bit registers ,
- *   `.. suffix.  ```~~`````....`.`   . affecting the data register and the .`
- *     ``.`.``...```                  ```.. output pins are also supported.`
- *                        ^^             `````.`````````.,``~``~``~~``````
- *                                                   .                  ^^
- *   ,..`.`.`...````````````......`.`.`.`.`.`..`.`.`..
- * .. The expectation is that in at least some cases .    ,-~~~-,
- *  .this will be used with roll-your-own ASIC/FPGA .`     \   /
- *  .logic in Verilog or VHDL. ~~~`````````..`````~~`       \ /
- *  ..````````......```````````                             \o_
- *                                                           |
- *                              ^^                          / \
- *
- *           ...`````~~`.....``.`..........``````.`.``.```........``.
- *            `  8, 16, 32 and 64 bits registers are supported, and``.
- *            . the number of GPIOs is determined by the width of   ~
- *             .. the registers. ,............```.`.`..`.`.~~~.`.`.`~
- *               `.......````.```
- */
-
-#include <linux/init.h>
-#include <linux/err.h>
-#include <linux/bug.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/spinlock.h>
-#include <linux/compiler.h>
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/log2.h>
-#include <linux/ioport.h>
-#include <linux/io.h>
-#include <linux/gpio.h>
-#include <linux/slab.h>
-#include <linux/platform_device.h>
-#include <linux/mod_devicetable.h>
-#include <linux/basic_mmio_gpio.h>
-
-static void bgpio_write8(void __iomem *reg, unsigned long data)
-{
-       writeb(data, reg);
-}
-
-static unsigned long bgpio_read8(void __iomem *reg)
-{
-       return readb(reg);
-}
-
-static void bgpio_write16(void __iomem *reg, unsigned long data)
-{
-       writew(data, reg);
-}
-
-static unsigned long bgpio_read16(void __iomem *reg)
-{
-       return readw(reg);
-}
-
-static void bgpio_write32(void __iomem *reg, unsigned long data)
-{
-       writel(data, reg);
-}
-
-static unsigned long bgpio_read32(void __iomem *reg)
-{
-       return readl(reg);
-}
-
-#if BITS_PER_LONG >= 64
-static void bgpio_write64(void __iomem *reg, unsigned long data)
-{
-       writeq(data, reg);
-}
-
-static unsigned long bgpio_read64(void __iomem *reg)
-{
-       return readq(reg);
-}
-#endif /* BITS_PER_LONG >= 64 */
-
-static unsigned long bgpio_pin2mask(struct bgpio_chip *bgc, unsigned int pin)
-{
-       return 1 << pin;
-}
-
-static unsigned long bgpio_pin2mask_be(struct bgpio_chip *bgc,
-                                      unsigned int pin)
-{
-       return 1 << (bgc->bits - 1 - pin);
-}
-
-static int bgpio_get(struct gpio_chip *gc, unsigned int gpio)
-{
-       struct bgpio_chip *bgc = to_bgpio_chip(gc);
-
-       return bgc->read_reg(bgc->reg_dat) & bgc->pin2mask(bgc, gpio);
-}
-
-static void bgpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
-{
-       struct bgpio_chip *bgc = to_bgpio_chip(gc);
-       unsigned long mask = bgc->pin2mask(bgc, gpio);
-       unsigned long flags;
-
-       spin_lock_irqsave(&bgc->lock, flags);
-
-       if (val)
-               bgc->data |= mask;
-       else
-               bgc->data &= ~mask;
-
-       bgc->write_reg(bgc->reg_dat, bgc->data);
-
-       spin_unlock_irqrestore(&bgc->lock, flags);
-}
-
-static void bgpio_set_with_clear(struct gpio_chip *gc, unsigned int gpio,
-                                int val)
-{
-       struct bgpio_chip *bgc = to_bgpio_chip(gc);
-       unsigned long mask = bgc->pin2mask(bgc, gpio);
-
-       if (val)
-               bgc->write_reg(bgc->reg_set, mask);
-       else
-               bgc->write_reg(bgc->reg_clr, mask);
-}
-
-static void bgpio_set_set(struct gpio_chip *gc, unsigned int gpio, int val)
-{
-       struct bgpio_chip *bgc = to_bgpio_chip(gc);
-       unsigned long mask = bgc->pin2mask(bgc, gpio);
-       unsigned long flags;
-
-       spin_lock_irqsave(&bgc->lock, flags);
-
-       if (val)
-               bgc->data |= mask;
-       else
-               bgc->data &= ~mask;
-
-       bgc->write_reg(bgc->reg_set, bgc->data);
-
-       spin_unlock_irqrestore(&bgc->lock, flags);
-}
-
-static int bgpio_simple_dir_in(struct gpio_chip *gc, unsigned int gpio)
-{
-       return 0;
-}
-
-static int bgpio_simple_dir_out(struct gpio_chip *gc, unsigned int gpio,
-                               int val)
-{
-       gc->set(gc, gpio, val);
-
-       return 0;
-}
-
-static int bgpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
-{
-       struct bgpio_chip *bgc = to_bgpio_chip(gc);
-       unsigned long flags;
-
-       spin_lock_irqsave(&bgc->lock, flags);
-
-       bgc->dir &= ~bgc->pin2mask(bgc, gpio);
-       bgc->write_reg(bgc->reg_dir, bgc->dir);
-
-       spin_unlock_irqrestore(&bgc->lock, flags);
-
-       return 0;
-}
-
-static int bgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
-{
-       struct bgpio_chip *bgc = to_bgpio_chip(gc);
-       unsigned long flags;
-
-       gc->set(gc, gpio, val);
-
-       spin_lock_irqsave(&bgc->lock, flags);
-
-       bgc->dir |= bgc->pin2mask(bgc, gpio);
-       bgc->write_reg(bgc->reg_dir, bgc->dir);
-
-       spin_unlock_irqrestore(&bgc->lock, flags);
-
-       return 0;
-}
-
-static int bgpio_dir_in_inv(struct gpio_chip *gc, unsigned int gpio)
-{
-       struct bgpio_chip *bgc = to_bgpio_chip(gc);
-       unsigned long flags;
-
-       spin_lock_irqsave(&bgc->lock, flags);
-
-       bgc->dir |= bgc->pin2mask(bgc, gpio);
-       bgc->write_reg(bgc->reg_dir, bgc->dir);
-
-       spin_unlock_irqrestore(&bgc->lock, flags);
-
-       return 0;
-}
-
-static int bgpio_dir_out_inv(struct gpio_chip *gc, unsigned int gpio, int val)
-{
-       struct bgpio_chip *bgc = to_bgpio_chip(gc);
-       unsigned long flags;
-
-       gc->set(gc, gpio, val);
-
-       spin_lock_irqsave(&bgc->lock, flags);
-
-       bgc->dir &= ~bgc->pin2mask(bgc, gpio);
-       bgc->write_reg(bgc->reg_dir, bgc->dir);
-
-       spin_unlock_irqrestore(&bgc->lock, flags);
-
-       return 0;
-}
-
-static int bgpio_setup_accessors(struct device *dev,
-                                struct bgpio_chip *bgc,
-                                bool be)
-{
-
-       switch (bgc->bits) {
-       case 8:
-               bgc->read_reg   = bgpio_read8;
-               bgc->write_reg  = bgpio_write8;
-               break;
-       case 16:
-               bgc->read_reg   = bgpio_read16;
-               bgc->write_reg  = bgpio_write16;
-               break;
-       case 32:
-               bgc->read_reg   = bgpio_read32;
-               bgc->write_reg  = bgpio_write32;
-               break;
-#if BITS_PER_LONG >= 64
-       case 64:
-               bgc->read_reg   = bgpio_read64;
-               bgc->write_reg  = bgpio_write64;
-               break;
-#endif /* BITS_PER_LONG >= 64 */
-       default:
-               dev_err(dev, "unsupported data width %u bits\n", bgc->bits);
-               return -EINVAL;
-       }
-
-       bgc->pin2mask = be ? bgpio_pin2mask_be : bgpio_pin2mask;
-
-       return 0;
-}
-
-/*
- * Create the device and allocate the resources.  For setting GPIO's there are
- * three supported configurations:
- *
- *     - single input/output register resource (named "dat").
- *     - set/clear pair (named "set" and "clr").
- *     - single output register resource and single input resource ("set" and
- *     dat").
- *
- * For the single output register, this drives a 1 by setting a bit and a zero
- * by clearing a bit.  For the set clr pair, this drives a 1 by setting a bit
- * in the set register and clears it by setting a bit in the clear register.
- * The configuration is detected by which resources are present.
- *
- * For setting the GPIO direction, there are three supported configurations:
- *
- *     - simple bidirection GPIO that requires no configuration.
- *     - an output direction register (named "dirout") where a 1 bit
- *     indicates the GPIO is an output.
- *     - an input direction register (named "dirin") where a 1 bit indicates
- *     the GPIO is an input.
- */
-static int bgpio_setup_io(struct bgpio_chip *bgc,
-                         void __iomem *dat,
-                         void __iomem *set,
-                         void __iomem *clr)
-{
-
-       bgc->reg_dat = dat;
-       if (!bgc->reg_dat)
-               return -EINVAL;
-
-       if (set && clr) {
-               bgc->reg_set = set;
-               bgc->reg_clr = clr;
-               bgc->gc.set = bgpio_set_with_clear;
-       } else if (set && !clr) {
-               bgc->reg_set = set;
-               bgc->gc.set = bgpio_set_set;
-       } else {
-               bgc->gc.set = bgpio_set;
-       }
-
-       bgc->gc.get = bgpio_get;
-
-       return 0;
-}
-
-static int bgpio_setup_direction(struct bgpio_chip *bgc,
-                                void __iomem *dirout,
-                                void __iomem *dirin)
-{
-       if (dirout && dirin) {
-               return -EINVAL;
-       } else if (dirout) {
-               bgc->reg_dir = dirout;
-               bgc->gc.direction_output = bgpio_dir_out;
-               bgc->gc.direction_input = bgpio_dir_in;
-       } else if (dirin) {
-               bgc->reg_dir = dirin;
-               bgc->gc.direction_output = bgpio_dir_out_inv;
-               bgc->gc.direction_input = bgpio_dir_in_inv;
-       } else {
-               bgc->gc.direction_output = bgpio_simple_dir_out;
-               bgc->gc.direction_input = bgpio_simple_dir_in;
-       }
-
-       return 0;
-}
-
-int __devexit bgpio_remove(struct bgpio_chip *bgc)
-{
-       int err = gpiochip_remove(&bgc->gc);
-
-       kfree(bgc);
-
-       return err;
-}
-EXPORT_SYMBOL_GPL(bgpio_remove);
-
-int __devinit bgpio_init(struct bgpio_chip *bgc,
-                        struct device *dev,
-                        unsigned long sz,
-                        void __iomem *dat,
-                        void __iomem *set,
-                        void __iomem *clr,
-                        void __iomem *dirout,
-                        void __iomem *dirin,
-                        bool big_endian)
-{
-       int ret;
-
-       if (!is_power_of_2(sz))
-               return -EINVAL;
-
-       bgc->bits = sz * 8;
-       if (bgc->bits > BITS_PER_LONG)
-               return -EINVAL;
-
-       spin_lock_init(&bgc->lock);
-       bgc->gc.dev = dev;
-       bgc->gc.label = dev_name(dev);
-       bgc->gc.base = -1;
-       bgc->gc.ngpio = bgc->bits;
-
-       ret = bgpio_setup_io(bgc, dat, set, clr);
-       if (ret)
-               return ret;
-
-       ret = bgpio_setup_accessors(dev, bgc, big_endian);
-       if (ret)
-               return ret;
-
-       ret = bgpio_setup_direction(bgc, dirout, dirin);
-       if (ret)
-               return ret;
-
-       bgc->data = bgc->read_reg(bgc->reg_dat);
-
-       return ret;
-}
-EXPORT_SYMBOL_GPL(bgpio_init);
-
-#ifdef CONFIG_GPIO_BASIC_MMIO
-
-static void __iomem *bgpio_map(struct platform_device *pdev,
-                              const char *name,
-                              resource_size_t sane_sz,
-                              int *err)
-{
-       struct device *dev = &pdev->dev;
-       struct resource *r;
-       resource_size_t start;
-       resource_size_t sz;
-       void __iomem *ret;
-
-       *err = 0;
-
-       r = platform_get_resource_byname(pdev, IORESOURCE_MEM, name);
-       if (!r)
-               return NULL;
-
-       sz = resource_size(r);
-       if (sz != sane_sz) {
-               *err = -EINVAL;
-               return NULL;
-       }
-
-       start = r->start;
-       if (!devm_request_mem_region(dev, start, sz, r->name)) {
-               *err = -EBUSY;
-               return NULL;
-       }
-
-       ret = devm_ioremap(dev, start, sz);
-       if (!ret) {
-               *err = -ENOMEM;
-               return NULL;
-       }
-
-       return ret;
-}
-
-static int __devinit bgpio_pdev_probe(struct platform_device *pdev)
-{
-       struct device *dev = &pdev->dev;
-       struct resource *r;
-       void __iomem *dat;
-       void __iomem *set;
-       void __iomem *clr;
-       void __iomem *dirout;
-       void __iomem *dirin;
-       unsigned long sz;
-       bool be;
-       int err;
-       struct bgpio_chip *bgc;
-       struct bgpio_pdata *pdata = dev_get_platdata(dev);
-
-       r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dat");
-       if (!r)
-               return -EINVAL;
-
-       sz = resource_size(r);
-
-       dat = bgpio_map(pdev, "dat", sz, &err);
-       if (!dat)
-               return err ? err : -EINVAL;
-
-       set = bgpio_map(pdev, "set", sz, &err);
-       if (err)
-               return err;
-
-       clr = bgpio_map(pdev, "clr", sz, &err);
-       if (err)
-               return err;
-
-       dirout = bgpio_map(pdev, "dirout", sz, &err);
-       if (err)
-               return err;
-
-       dirin = bgpio_map(pdev, "dirin", sz, &err);
-       if (err)
-               return err;
-
-       be = !strcmp(platform_get_device_id(pdev)->name, "basic-mmio-gpio-be");
-
-       bgc = devm_kzalloc(&pdev->dev, sizeof(*bgc), GFP_KERNEL);
-       if (!bgc)
-               return -ENOMEM;
-
-       err = bgpio_init(bgc, dev, sz, dat, set, clr, dirout, dirin, be);
-       if (err)
-               return err;
-
-       if (pdata) {
-               bgc->gc.base = pdata->base;
-               if (pdata->ngpio > 0)
-                       bgc->gc.ngpio = pdata->ngpio;
-       }
-
-       platform_set_drvdata(pdev, bgc);
-
-       return gpiochip_add(&bgc->gc);
-}
-
-static int __devexit bgpio_pdev_remove(struct platform_device *pdev)
-{
-       struct bgpio_chip *bgc = platform_get_drvdata(pdev);
-
-       return bgpio_remove(bgc);
-}
-
-static const struct platform_device_id bgpio_id_table[] = {
-       { "basic-mmio-gpio", },
-       { "basic-mmio-gpio-be", },
-       {},
-};
-MODULE_DEVICE_TABLE(platform, bgpio_id_table);
-
-static struct platform_driver bgpio_driver = {
-       .driver = {
-               .name = "basic-mmio-gpio",
-       },
-       .id_table = bgpio_id_table,
-       .probe = bgpio_pdev_probe,
-       .remove = __devexit_p(bgpio_pdev_remove),
-};
-
-static int __init bgpio_platform_init(void)
-{
-       return platform_driver_register(&bgpio_driver);
-}
-module_init(bgpio_platform_init);
-
-static void __exit bgpio_platform_exit(void)
-{
-       platform_driver_unregister(&bgpio_driver);
-}
-module_exit(bgpio_platform_exit);
-
-#endif /* CONFIG_GPIO_BASIC_MMIO */
-
-MODULE_DESCRIPTION("Driver for basic memory-mapped GPIO controllers");
-MODULE_AUTHOR("Anton Vorontsov <cbouatmailru@gmail.com>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/bt8xxgpio.c b/drivers/gpio/bt8xxgpio.c
deleted file mode 100644 (file)
index aa4f09a..0000000
+++ /dev/null
@@ -1,348 +0,0 @@
-/*
-
-    bt8xx GPIO abuser
-
-    Copyright (C) 2008 Michael Buesch <mb@bu3sch.de>
-
-    Please do _only_ contact the people listed _above_ with issues related to this driver.
-    All the other people listed below are not related to this driver. Their names
-    are only here, because this driver is derived from the bt848 driver.
-
-
-    Derived from the bt848 driver:
-
-    Copyright (C) 1996,97,98 Ralph  Metzler
-                          & Marcus Metzler
-    (c) 1999-2002 Gerd Knorr
-
-    some v4l2 code lines are taken from Justin's bttv2 driver which is
-    (c) 2000 Justin Schoeman
-
-    V4L1 removal from:
-    (c) 2005-2006 Nickolay V. Shmyrev
-
-    Fixes to be fully V4L2 compliant by
-    (c) 2006 Mauro Carvalho Chehab
-
-    Cropping and overscan support
-    Copyright (C) 2005, 2006 Michael H. Schimek
-    Sponsored by OPQ Systems AB
-
-    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.
-
-    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.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/spinlock.h>
-#include <linux/gpio.h>
-#include <linux/slab.h>
-
-/* Steal the hardware definitions from the bttv driver. */
-#include "../media/video/bt8xx/bt848.h"
-
-
-#define BT8XXGPIO_NR_GPIOS             24 /* We have 24 GPIO pins */
-
-
-struct bt8xxgpio {
-       spinlock_t lock;
-
-       void __iomem *mmio;
-       struct pci_dev *pdev;
-       struct gpio_chip gpio;
-
-#ifdef CONFIG_PM
-       u32 saved_outen;
-       u32 saved_data;
-#endif
-};
-
-#define bgwrite(dat, adr)      writel((dat), bg->mmio+(adr))
-#define bgread(adr)            readl(bg->mmio+(adr))
-
-
-static int modparam_gpiobase = -1/* dynamic */;
-module_param_named(gpiobase, modparam_gpiobase, int, 0444);
-MODULE_PARM_DESC(gpiobase, "The GPIO number base. -1 means dynamic, which is the default.");
-
-
-static int bt8xxgpio_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
-{
-       struct bt8xxgpio *bg = container_of(gpio, struct bt8xxgpio, gpio);
-       unsigned long flags;
-       u32 outen, data;
-
-       spin_lock_irqsave(&bg->lock, flags);
-
-       data = bgread(BT848_GPIO_DATA);
-       data &= ~(1 << nr);
-       bgwrite(data, BT848_GPIO_DATA);
-
-       outen = bgread(BT848_GPIO_OUT_EN);
-       outen &= ~(1 << nr);
-       bgwrite(outen, BT848_GPIO_OUT_EN);
-
-       spin_unlock_irqrestore(&bg->lock, flags);
-
-       return 0;
-}
-
-static int bt8xxgpio_gpio_get(struct gpio_chip *gpio, unsigned nr)
-{
-       struct bt8xxgpio *bg = container_of(gpio, struct bt8xxgpio, gpio);
-       unsigned long flags;
-       u32 val;
-
-       spin_lock_irqsave(&bg->lock, flags);
-       val = bgread(BT848_GPIO_DATA);
-       spin_unlock_irqrestore(&bg->lock, flags);
-
-       return !!(val & (1 << nr));
-}
-
-static int bt8xxgpio_gpio_direction_output(struct gpio_chip *gpio,
-                                       unsigned nr, int val)
-{
-       struct bt8xxgpio *bg = container_of(gpio, struct bt8xxgpio, gpio);
-       unsigned long flags;
-       u32 outen, data;
-
-       spin_lock_irqsave(&bg->lock, flags);
-
-       outen = bgread(BT848_GPIO_OUT_EN);
-       outen |= (1 << nr);
-       bgwrite(outen, BT848_GPIO_OUT_EN);
-
-       data = bgread(BT848_GPIO_DATA);
-       if (val)
-               data |= (1 << nr);
-       else
-               data &= ~(1 << nr);
-       bgwrite(data, BT848_GPIO_DATA);
-
-       spin_unlock_irqrestore(&bg->lock, flags);
-
-       return 0;
-}
-
-static void bt8xxgpio_gpio_set(struct gpio_chip *gpio,
-                           unsigned nr, int val)
-{
-       struct bt8xxgpio *bg = container_of(gpio, struct bt8xxgpio, gpio);
-       unsigned long flags;
-       u32 data;
-
-       spin_lock_irqsave(&bg->lock, flags);
-
-       data = bgread(BT848_GPIO_DATA);
-       if (val)
-               data |= (1 << nr);
-       else
-               data &= ~(1 << nr);
-       bgwrite(data, BT848_GPIO_DATA);
-
-       spin_unlock_irqrestore(&bg->lock, flags);
-}
-
-static void bt8xxgpio_gpio_setup(struct bt8xxgpio *bg)
-{
-       struct gpio_chip *c = &bg->gpio;
-
-       c->label = dev_name(&bg->pdev->dev);
-       c->owner = THIS_MODULE;
-       c->direction_input = bt8xxgpio_gpio_direction_input;
-       c->get = bt8xxgpio_gpio_get;
-       c->direction_output = bt8xxgpio_gpio_direction_output;
-       c->set = bt8xxgpio_gpio_set;
-       c->dbg_show = NULL;
-       c->base = modparam_gpiobase;
-       c->ngpio = BT8XXGPIO_NR_GPIOS;
-       c->can_sleep = 0;
-}
-
-static int bt8xxgpio_probe(struct pci_dev *dev,
-                       const struct pci_device_id *pci_id)
-{
-       struct bt8xxgpio *bg;
-       int err;
-
-       bg = kzalloc(sizeof(*bg), GFP_KERNEL);
-       if (!bg)
-               return -ENOMEM;
-
-       bg->pdev = dev;
-       spin_lock_init(&bg->lock);
-
-       err = pci_enable_device(dev);
-       if (err) {
-               printk(KERN_ERR "bt8xxgpio: Can't enable device.\n");
-               goto err_freebg;
-       }
-       if (!request_mem_region(pci_resource_start(dev, 0),
-                               pci_resource_len(dev, 0),
-                               "bt8xxgpio")) {
-               printk(KERN_WARNING "bt8xxgpio: Can't request iomem (0x%llx).\n",
-                      (unsigned long long)pci_resource_start(dev, 0));
-               err = -EBUSY;
-               goto err_disable;
-       }
-       pci_set_master(dev);
-       pci_set_drvdata(dev, bg);
-
-       bg->mmio = ioremap(pci_resource_start(dev, 0), 0x1000);
-       if (!bg->mmio) {
-               printk(KERN_ERR "bt8xxgpio: ioremap() failed\n");
-               err = -EIO;
-               goto err_release_mem;
-       }
-
-       /* Disable interrupts */
-       bgwrite(0, BT848_INT_MASK);
-
-       /* gpio init */
-       bgwrite(0, BT848_GPIO_DMA_CTL);
-       bgwrite(0, BT848_GPIO_REG_INP);
-       bgwrite(0, BT848_GPIO_OUT_EN);
-
-       bt8xxgpio_gpio_setup(bg);
-       err = gpiochip_add(&bg->gpio);
-       if (err) {
-               printk(KERN_ERR "bt8xxgpio: Failed to register GPIOs\n");
-               goto err_release_mem;
-       }
-
-       printk(KERN_INFO "bt8xxgpio: Abusing BT8xx card for GPIOs %d to %d\n",
-              bg->gpio.base, bg->gpio.base + BT8XXGPIO_NR_GPIOS - 1);
-
-       return 0;
-
-err_release_mem:
-       release_mem_region(pci_resource_start(dev, 0),
-                          pci_resource_len(dev, 0));
-       pci_set_drvdata(dev, NULL);
-err_disable:
-       pci_disable_device(dev);
-err_freebg:
-       kfree(bg);
-
-       return err;
-}
-
-static void bt8xxgpio_remove(struct pci_dev *pdev)
-{
-       struct bt8xxgpio *bg = pci_get_drvdata(pdev);
-
-       gpiochip_remove(&bg->gpio);
-
-       bgwrite(0, BT848_INT_MASK);
-       bgwrite(~0x0, BT848_INT_STAT);
-       bgwrite(0x0, BT848_GPIO_OUT_EN);
-
-       iounmap(bg->mmio);
-       release_mem_region(pci_resource_start(pdev, 0),
-                          pci_resource_len(pdev, 0));
-       pci_disable_device(pdev);
-
-       pci_set_drvdata(pdev, NULL);
-       kfree(bg);
-}
-
-#ifdef CONFIG_PM
-static int bt8xxgpio_suspend(struct pci_dev *pdev, pm_message_t state)
-{
-       struct bt8xxgpio *bg = pci_get_drvdata(pdev);
-       unsigned long flags;
-
-       spin_lock_irqsave(&bg->lock, flags);
-
-       bg->saved_outen = bgread(BT848_GPIO_OUT_EN);
-       bg->saved_data = bgread(BT848_GPIO_DATA);
-
-       bgwrite(0, BT848_INT_MASK);
-       bgwrite(~0x0, BT848_INT_STAT);
-       bgwrite(0x0, BT848_GPIO_OUT_EN);
-
-       spin_unlock_irqrestore(&bg->lock, flags);
-
-       pci_save_state(pdev);
-       pci_disable_device(pdev);
-       pci_set_power_state(pdev, pci_choose_state(pdev, state));
-
-       return 0;
-}
-
-static int bt8xxgpio_resume(struct pci_dev *pdev)
-{
-       struct bt8xxgpio *bg = pci_get_drvdata(pdev);
-       unsigned long flags;
-       int err;
-
-       pci_set_power_state(pdev, 0);
-       err = pci_enable_device(pdev);
-       if (err)
-               return err;
-       pci_restore_state(pdev);
-
-       spin_lock_irqsave(&bg->lock, flags);
-
-       bgwrite(0, BT848_INT_MASK);
-       bgwrite(0, BT848_GPIO_DMA_CTL);
-       bgwrite(0, BT848_GPIO_REG_INP);
-       bgwrite(bg->saved_outen, BT848_GPIO_OUT_EN);
-       bgwrite(bg->saved_data & bg->saved_outen,
-               BT848_GPIO_DATA);
-
-       spin_unlock_irqrestore(&bg->lock, flags);
-
-       return 0;
-}
-#else
-#define bt8xxgpio_suspend NULL
-#define bt8xxgpio_resume NULL
-#endif /* CONFIG_PM */
-
-static struct pci_device_id bt8xxgpio_pci_tbl[] = {
-       { PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT848) },
-       { PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT849) },
-       { PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT878) },
-       { PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT879) },
-       { 0, },
-};
-MODULE_DEVICE_TABLE(pci, bt8xxgpio_pci_tbl);
-
-static struct pci_driver bt8xxgpio_pci_driver = {
-       .name           = "bt8xxgpio",
-       .id_table       = bt8xxgpio_pci_tbl,
-       .probe          = bt8xxgpio_probe,
-       .remove         = bt8xxgpio_remove,
-       .suspend        = bt8xxgpio_suspend,
-       .resume         = bt8xxgpio_resume,
-};
-
-static int __init bt8xxgpio_init(void)
-{
-       return pci_register_driver(&bt8xxgpio_pci_driver);
-}
-module_init(bt8xxgpio_init)
-
-static void __exit bt8xxgpio_exit(void)
-{
-       pci_unregister_driver(&bt8xxgpio_pci_driver);
-}
-module_exit(bt8xxgpio_exit)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Michael Buesch");
-MODULE_DESCRIPTION("Abuse a BT8xx framegrabber card as generic GPIO card");
diff --git a/drivers/gpio/cs5535-gpio.c b/drivers/gpio/cs5535-gpio.c
deleted file mode 100644 (file)
index 6e16cba..0000000
+++ /dev/null
@@ -1,401 +0,0 @@
-/*
- * AMD CS5535/CS5536 GPIO driver
- * Copyright (C) 2006  Advanced Micro Devices, Inc.
- * Copyright (C) 2007-2009  Andres Salomon <dilinger@collabora.co.uk>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public License
- * as published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/spinlock.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/gpio.h>
-#include <linux/io.h>
-#include <linux/cs5535.h>
-#include <asm/msr.h>
-
-#define DRV_NAME "cs5535-gpio"
-
-/*
- * Some GPIO pins
- *  31-29,23 : reserved (always mask out)
- *  28       : Power Button
- *  26       : PME#
- *  22-16    : LPC
- *  14,15    : SMBus
- *  9,8      : UART1
- *  7        : PCI INTB
- *  3,4      : UART2/DDC
- *  2        : IDE_IRQ0
- *  1        : AC_BEEP
- *  0        : PCI INTA
- *
- * If a mask was not specified, allow all except
- * reserved and Power Button
- */
-#define GPIO_DEFAULT_MASK 0x0F7FFFFF
-
-static ulong mask = GPIO_DEFAULT_MASK;
-module_param_named(mask, mask, ulong, 0444);
-MODULE_PARM_DESC(mask, "GPIO channel mask.");
-
-static struct cs5535_gpio_chip {
-       struct gpio_chip chip;
-       resource_size_t base;
-
-       struct platform_device *pdev;
-       spinlock_t lock;
-} cs5535_gpio_chip;
-
-/*
- * The CS5535/CS5536 GPIOs support a number of extra features not defined
- * by the gpio_chip API, so these are exported.  For a full list of the
- * registers, see include/linux/cs5535.h.
- */
-
-static void errata_outl(struct cs5535_gpio_chip *chip, u32 val,
-               unsigned int reg)
-{
-       unsigned long addr = chip->base + 0x80 + reg;
-
-       /*
-        * According to the CS5536 errata (#36), after suspend
-        * a write to the high bank GPIO register will clear all
-        * non-selected bits; the recommended workaround is a
-        * read-modify-write operation.
-        *
-        * Don't apply this errata to the edge status GPIOs, as writing
-        * to their lower bits will clear them.
-        */
-       if (reg != GPIO_POSITIVE_EDGE_STS && reg != GPIO_NEGATIVE_EDGE_STS) {
-               if (val & 0xffff)
-                       val |= (inl(addr) & 0xffff); /* ignore the high bits */
-               else
-                       val |= (inl(addr) ^ (val >> 16));
-       }
-       outl(val, addr);
-}
-
-static void __cs5535_gpio_set(struct cs5535_gpio_chip *chip, unsigned offset,
-               unsigned int reg)
-{
-       if (offset < 16)
-               /* low bank register */
-               outl(1 << offset, chip->base + reg);
-       else
-               /* high bank register */
-               errata_outl(chip, 1 << (offset - 16), reg);
-}
-
-void cs5535_gpio_set(unsigned offset, unsigned int reg)
-{
-       struct cs5535_gpio_chip *chip = &cs5535_gpio_chip;
-       unsigned long flags;
-
-       spin_lock_irqsave(&chip->lock, flags);
-       __cs5535_gpio_set(chip, offset, reg);
-       spin_unlock_irqrestore(&chip->lock, flags);
-}
-EXPORT_SYMBOL_GPL(cs5535_gpio_set);
-
-static void __cs5535_gpio_clear(struct cs5535_gpio_chip *chip, unsigned offset,
-               unsigned int reg)
-{
-       if (offset < 16)
-               /* low bank register */
-               outl(1 << (offset + 16), chip->base + reg);
-       else
-               /* high bank register */
-               errata_outl(chip, 1 << offset, reg);
-}
-
-void cs5535_gpio_clear(unsigned offset, unsigned int reg)
-{
-       struct cs5535_gpio_chip *chip = &cs5535_gpio_chip;
-       unsigned long flags;
-
-       spin_lock_irqsave(&chip->lock, flags);
-       __cs5535_gpio_clear(chip, offset, reg);
-       spin_unlock_irqrestore(&chip->lock, flags);
-}
-EXPORT_SYMBOL_GPL(cs5535_gpio_clear);
-
-int cs5535_gpio_isset(unsigned offset, unsigned int reg)
-{
-       struct cs5535_gpio_chip *chip = &cs5535_gpio_chip;
-       unsigned long flags;
-       long val;
-
-       spin_lock_irqsave(&chip->lock, flags);
-       if (offset < 16)
-               /* low bank register */
-               val = inl(chip->base + reg);
-       else {
-               /* high bank register */
-               val = inl(chip->base + 0x80 + reg);
-               offset -= 16;
-       }
-       spin_unlock_irqrestore(&chip->lock, flags);
-
-       return (val & (1 << offset)) ? 1 : 0;
-}
-EXPORT_SYMBOL_GPL(cs5535_gpio_isset);
-
-int cs5535_gpio_set_irq(unsigned group, unsigned irq)
-{
-       uint32_t lo, hi;
-
-       if (group > 7 || irq > 15)
-               return -EINVAL;
-
-       rdmsr(MSR_PIC_ZSEL_HIGH, lo, hi);
-
-       lo &= ~(0xF << (group * 4));
-       lo |= (irq & 0xF) << (group * 4);
-
-       wrmsr(MSR_PIC_ZSEL_HIGH, lo, hi);
-       return 0;
-}
-EXPORT_SYMBOL_GPL(cs5535_gpio_set_irq);
-
-void cs5535_gpio_setup_event(unsigned offset, int pair, int pme)
-{
-       struct cs5535_gpio_chip *chip = &cs5535_gpio_chip;
-       uint32_t shift = (offset % 8) * 4;
-       unsigned long flags;
-       uint32_t val;
-
-       if (offset >= 24)
-               offset = GPIO_MAP_W;
-       else if (offset >= 16)
-               offset = GPIO_MAP_Z;
-       else if (offset >= 8)
-               offset = GPIO_MAP_Y;
-       else
-               offset = GPIO_MAP_X;
-
-       spin_lock_irqsave(&chip->lock, flags);
-       val = inl(chip->base + offset);
-
-       /* Clear whatever was there before */
-       val &= ~(0xF << shift);
-
-       /* Set the new value */
-       val |= ((pair & 7) << shift);
-
-       /* Set the PME bit if this is a PME event */
-       if (pme)
-               val |= (1 << (shift + 3));
-
-       outl(val, chip->base + offset);
-       spin_unlock_irqrestore(&chip->lock, flags);
-}
-EXPORT_SYMBOL_GPL(cs5535_gpio_setup_event);
-
-/*
- * Generic gpio_chip API support.
- */
-
-static int chip_gpio_request(struct gpio_chip *c, unsigned offset)
-{
-       struct cs5535_gpio_chip *chip = (struct cs5535_gpio_chip *) c;
-       unsigned long flags;
-
-       spin_lock_irqsave(&chip->lock, flags);
-
-       /* check if this pin is available */
-       if ((mask & (1 << offset)) == 0) {
-               dev_info(&chip->pdev->dev,
-                       "pin %u is not available (check mask)\n", offset);
-               spin_unlock_irqrestore(&chip->lock, flags);
-               return -EINVAL;
-       }
-
-       /* disable output aux 1 & 2 on this pin */
-       __cs5535_gpio_clear(chip, offset, GPIO_OUTPUT_AUX1);
-       __cs5535_gpio_clear(chip, offset, GPIO_OUTPUT_AUX2);
-
-       /* disable input aux 1 on this pin */
-       __cs5535_gpio_clear(chip, offset, GPIO_INPUT_AUX1);
-
-       spin_unlock_irqrestore(&chip->lock, flags);
-
-       return 0;
-}
-
-static int chip_gpio_get(struct gpio_chip *chip, unsigned offset)
-{
-       return cs5535_gpio_isset(offset, GPIO_READ_BACK);
-}
-
-static void chip_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
-{
-       if (val)
-               cs5535_gpio_set(offset, GPIO_OUTPUT_VAL);
-       else
-               cs5535_gpio_clear(offset, GPIO_OUTPUT_VAL);
-}
-
-static int chip_direction_input(struct gpio_chip *c, unsigned offset)
-{
-       struct cs5535_gpio_chip *chip = (struct cs5535_gpio_chip *) c;
-       unsigned long flags;
-
-       spin_lock_irqsave(&chip->lock, flags);
-       __cs5535_gpio_set(chip, offset, GPIO_INPUT_ENABLE);
-       __cs5535_gpio_clear(chip, offset, GPIO_OUTPUT_ENABLE);
-       spin_unlock_irqrestore(&chip->lock, flags);
-
-       return 0;
-}
-
-static int chip_direction_output(struct gpio_chip *c, unsigned offset, int val)
-{
-       struct cs5535_gpio_chip *chip = (struct cs5535_gpio_chip *) c;
-       unsigned long flags;
-
-       spin_lock_irqsave(&chip->lock, flags);
-
-       __cs5535_gpio_set(chip, offset, GPIO_INPUT_ENABLE);
-       __cs5535_gpio_set(chip, offset, GPIO_OUTPUT_ENABLE);
-       if (val)
-               __cs5535_gpio_set(chip, offset, GPIO_OUTPUT_VAL);
-       else
-               __cs5535_gpio_clear(chip, offset, GPIO_OUTPUT_VAL);
-
-       spin_unlock_irqrestore(&chip->lock, flags);
-
-       return 0;
-}
-
-static const char * const cs5535_gpio_names[] = {
-       "GPIO0", "GPIO1", "GPIO2", "GPIO3",
-       "GPIO4", "GPIO5", "GPIO6", "GPIO7",
-       "GPIO8", "GPIO9", "GPIO10", "GPIO11",
-       "GPIO12", "GPIO13", "GPIO14", "GPIO15",
-       "GPIO16", "GPIO17", "GPIO18", "GPIO19",
-       "GPIO20", "GPIO21", "GPIO22", NULL,
-       "GPIO24", "GPIO25", "GPIO26", "GPIO27",
-       "GPIO28", NULL, NULL, NULL,
-};
-
-static struct cs5535_gpio_chip cs5535_gpio_chip = {
-       .chip = {
-               .owner = THIS_MODULE,
-               .label = DRV_NAME,
-
-               .base = 0,
-               .ngpio = 32,
-               .names = cs5535_gpio_names,
-               .request = chip_gpio_request,
-
-               .get = chip_gpio_get,
-               .set = chip_gpio_set,
-
-               .direction_input = chip_direction_input,
-               .direction_output = chip_direction_output,
-       },
-};
-
-static int __devinit cs5535_gpio_probe(struct platform_device *pdev)
-{
-       struct resource *res;
-       int err = -EIO;
-       ulong mask_orig = mask;
-
-       /* There are two ways to get the GPIO base address; one is by
-        * fetching it from MSR_LBAR_GPIO, the other is by reading the
-        * PCI BAR info.  The latter method is easier (especially across
-        * different architectures), so we'll stick with that for now.  If
-        * it turns out to be unreliable in the face of crappy BIOSes, we
-        * can always go back to using MSRs.. */
-
-       res = platform_get_resource(pdev, IORESOURCE_IO, 0);
-       if (!res) {
-               dev_err(&pdev->dev, "can't fetch device resource info\n");
-               goto done;
-       }
-
-       if (!request_region(res->start, resource_size(res), pdev->name)) {
-               dev_err(&pdev->dev, "can't request region\n");
-               goto done;
-       }
-
-       /* set up the driver-specific struct */
-       cs5535_gpio_chip.base = res->start;
-       cs5535_gpio_chip.pdev = pdev;
-       spin_lock_init(&cs5535_gpio_chip.lock);
-
-       dev_info(&pdev->dev, "reserved resource region %pR\n", res);
-
-       /* mask out reserved pins */
-       mask &= 0x1F7FFFFF;
-
-       /* do not allow pin 28, Power Button, as there's special handling
-        * in the PMC needed. (note 12, p. 48) */
-       mask &= ~(1 << 28);
-
-       if (mask_orig != mask)
-               dev_info(&pdev->dev, "mask changed from 0x%08lX to 0x%08lX\n",
-                               mask_orig, mask);
-
-       /* finally, register with the generic GPIO API */
-       err = gpiochip_add(&cs5535_gpio_chip.chip);
-       if (err)
-               goto release_region;
-
-       dev_info(&pdev->dev, "GPIO support successfully loaded.\n");
-       return 0;
-
-release_region:
-       release_region(res->start, resource_size(res));
-done:
-       return err;
-}
-
-static int __devexit cs5535_gpio_remove(struct platform_device *pdev)
-{
-       struct resource *r;
-       int err;
-
-       err = gpiochip_remove(&cs5535_gpio_chip.chip);
-       if (err) {
-               /* uhh? */
-               dev_err(&pdev->dev, "unable to remove gpio_chip?\n");
-               return err;
-       }
-
-       r = platform_get_resource(pdev, IORESOURCE_IO, 0);
-       release_region(r->start, resource_size(r));
-       return 0;
-}
-
-static struct platform_driver cs5535_gpio_driver = {
-       .driver = {
-               .name = DRV_NAME,
-               .owner = THIS_MODULE,
-       },
-       .probe = cs5535_gpio_probe,
-       .remove = __devexit_p(cs5535_gpio_remove),
-};
-
-static int __init cs5535_gpio_init(void)
-{
-       return platform_driver_register(&cs5535_gpio_driver);
-}
-
-static void __exit cs5535_gpio_exit(void)
-{
-       platform_driver_unregister(&cs5535_gpio_driver);
-}
-
-module_init(cs5535_gpio_init);
-module_exit(cs5535_gpio_exit);
-
-MODULE_AUTHOR("Andres Salomon <dilinger@queued.net>");
-MODULE_DESCRIPTION("AMD CS5535/CS5536 GPIO driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/drivers/gpio/gpio-74x164.c b/drivers/gpio/gpio-74x164.c
new file mode 100644 (file)
index 0000000..7fb60b6
--- /dev/null
@@ -0,0 +1,177 @@
+/*
+ *  74Hx164 - Generic serial-in/parallel-out 8-bits shift register GPIO driver
+ *
+ *  Copyright (C) 2010 Gabor Juhos <juhosg@openwrt.org>
+ *  Copyright (C) 2010 Miguel Gaio <miguel.gaio@efixo.com>
+ *
+ *  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/init.h>
+#include <linux/mutex.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/74x164.h>
+#include <linux/gpio.h>
+#include <linux/slab.h>
+
+struct gen_74x164_chip {
+       struct spi_device       *spi;
+       struct gpio_chip        gpio_chip;
+       struct mutex            lock;
+       u8                      port_config;
+};
+
+static struct gen_74x164_chip *gpio_to_chip(struct gpio_chip *gc)
+{
+       return container_of(gc, struct gen_74x164_chip, gpio_chip);
+}
+
+static int __gen_74x164_write_config(struct gen_74x164_chip *chip)
+{
+       return spi_write(chip->spi,
+                        &chip->port_config, sizeof(chip->port_config));
+}
+
+static int gen_74x164_get_value(struct gpio_chip *gc, unsigned offset)
+{
+       struct gen_74x164_chip *chip = gpio_to_chip(gc);
+       int ret;
+
+       mutex_lock(&chip->lock);
+       ret = (chip->port_config >> offset) & 0x1;
+       mutex_unlock(&chip->lock);
+
+       return ret;
+}
+
+static void gen_74x164_set_value(struct gpio_chip *gc,
+               unsigned offset, int val)
+{
+       struct gen_74x164_chip *chip = gpio_to_chip(gc);
+
+       mutex_lock(&chip->lock);
+       if (val)
+               chip->port_config |= (1 << offset);
+       else
+               chip->port_config &= ~(1 << offset);
+
+       __gen_74x164_write_config(chip);
+       mutex_unlock(&chip->lock);
+}
+
+static int gen_74x164_direction_output(struct gpio_chip *gc,
+               unsigned offset, int val)
+{
+       gen_74x164_set_value(gc, offset, val);
+       return 0;
+}
+
+static int __devinit gen_74x164_probe(struct spi_device *spi)
+{
+       struct gen_74x164_chip *chip;
+       struct gen_74x164_chip_platform_data *pdata;
+       int ret;
+
+       pdata = spi->dev.platform_data;
+       if (!pdata || !pdata->base) {
+               dev_dbg(&spi->dev, "incorrect or missing platform data\n");
+               return -EINVAL;
+       }
+
+       /*
+        * bits_per_word cannot be configured in platform data
+        */
+       spi->bits_per_word = 8;
+
+       ret = spi_setup(spi);
+       if (ret < 0)
+               return ret;
+
+       chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+       if (!chip)
+               return -ENOMEM;
+
+       mutex_init(&chip->lock);
+
+       dev_set_drvdata(&spi->dev, chip);
+
+       chip->spi = spi;
+
+       chip->gpio_chip.label = spi->modalias;
+       chip->gpio_chip.direction_output = gen_74x164_direction_output;
+       chip->gpio_chip.get = gen_74x164_get_value;
+       chip->gpio_chip.set = gen_74x164_set_value;
+       chip->gpio_chip.base = pdata->base;
+       chip->gpio_chip.ngpio = 8;
+       chip->gpio_chip.can_sleep = 1;
+       chip->gpio_chip.dev = &spi->dev;
+       chip->gpio_chip.owner = THIS_MODULE;
+
+       ret = __gen_74x164_write_config(chip);
+       if (ret) {
+               dev_err(&spi->dev, "Failed writing: %d\n", ret);
+               goto exit_destroy;
+       }
+
+       ret = gpiochip_add(&chip->gpio_chip);
+       if (ret)
+               goto exit_destroy;
+
+       return ret;
+
+exit_destroy:
+       dev_set_drvdata(&spi->dev, NULL);
+       mutex_destroy(&chip->lock);
+       kfree(chip);
+       return ret;
+}
+
+static int __devexit gen_74x164_remove(struct spi_device *spi)
+{
+       struct gen_74x164_chip *chip;
+       int ret;
+
+       chip = dev_get_drvdata(&spi->dev);
+       if (chip == NULL)
+               return -ENODEV;
+
+       dev_set_drvdata(&spi->dev, NULL);
+
+       ret = gpiochip_remove(&chip->gpio_chip);
+       if (!ret) {
+               mutex_destroy(&chip->lock);
+               kfree(chip);
+       } else
+               dev_err(&spi->dev, "Failed to remove the GPIO controller: %d\n",
+                               ret);
+
+       return ret;
+}
+
+static struct spi_driver gen_74x164_driver = {
+       .driver = {
+               .name           = "74x164",
+               .owner          = THIS_MODULE,
+       },
+       .probe          = gen_74x164_probe,
+       .remove         = __devexit_p(gen_74x164_remove),
+};
+
+static int __init gen_74x164_init(void)
+{
+       return spi_register_driver(&gen_74x164_driver);
+}
+subsys_initcall(gen_74x164_init);
+
+static void __exit gen_74x164_exit(void)
+{
+       spi_unregister_driver(&gen_74x164_driver);
+}
+module_exit(gen_74x164_exit);
+
+MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>");
+MODULE_AUTHOR("Miguel Gaio <miguel.gaio@efixo.com>");
+MODULE_DESCRIPTION("GPIO expander driver for 74X164 8-bits shift register");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpio/gpio-ab8500.c b/drivers/gpio/gpio-ab8500.c
new file mode 100644 (file)
index 0000000..970053c
--- /dev/null
@@ -0,0 +1,521 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2011
+ *
+ * Author: BIBEK BASU <bibek.basu@stericsson.com>
+ * License terms: GNU General Public License (GPL) version 2
+ *
+ * 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/kernel.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/gpio.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/mfd/ab8500.h>
+#include <linux/mfd/abx500.h>
+#include <linux/mfd/ab8500/gpio.h>
+
+/*
+ * GPIO registers offset
+ * Bank: 0x10
+ */
+#define AB8500_GPIO_SEL1_REG   0x00
+#define AB8500_GPIO_SEL2_REG   0x01
+#define AB8500_GPIO_SEL3_REG   0x02
+#define AB8500_GPIO_SEL4_REG   0x03
+#define AB8500_GPIO_SEL5_REG   0x04
+#define AB8500_GPIO_SEL6_REG   0x05
+
+#define AB8500_GPIO_DIR1_REG   0x10
+#define AB8500_GPIO_DIR2_REG   0x11
+#define AB8500_GPIO_DIR3_REG   0x12
+#define AB8500_GPIO_DIR4_REG   0x13
+#define AB8500_GPIO_DIR5_REG   0x14
+#define AB8500_GPIO_DIR6_REG   0x15
+
+#define AB8500_GPIO_OUT1_REG   0x20
+#define AB8500_GPIO_OUT2_REG   0x21
+#define AB8500_GPIO_OUT3_REG   0x22
+#define AB8500_GPIO_OUT4_REG   0x23
+#define AB8500_GPIO_OUT5_REG   0x24
+#define AB8500_GPIO_OUT6_REG   0x25
+
+#define AB8500_GPIO_PUD1_REG   0x30
+#define AB8500_GPIO_PUD2_REG   0x31
+#define AB8500_GPIO_PUD3_REG   0x32
+#define AB8500_GPIO_PUD4_REG   0x33
+#define AB8500_GPIO_PUD5_REG   0x34
+#define AB8500_GPIO_PUD6_REG   0x35
+
+#define AB8500_GPIO_IN1_REG    0x40
+#define AB8500_GPIO_IN2_REG    0x41
+#define AB8500_GPIO_IN3_REG    0x42
+#define AB8500_GPIO_IN4_REG    0x43
+#define AB8500_GPIO_IN5_REG    0x44
+#define AB8500_GPIO_IN6_REG    0x45
+#define AB8500_GPIO_ALTFUN_REG 0x45
+#define ALTFUN_REG_INDEX       6
+#define AB8500_NUM_GPIO                42
+#define AB8500_NUM_VIR_GPIO_IRQ        16
+
+enum ab8500_gpio_action {
+       NONE,
+       STARTUP,
+       SHUTDOWN,
+       MASK,
+       UNMASK
+};
+
+struct ab8500_gpio {
+       struct gpio_chip chip;
+       struct ab8500 *parent;
+       struct device *dev;
+       struct mutex lock;
+       u32 irq_base;
+       enum ab8500_gpio_action irq_action;
+       u16 rising;
+       u16 falling;
+};
+/**
+ * to_ab8500_gpio() - get the pointer to ab8500_gpio
+ * @chip:      Member of the structure ab8500_gpio
+ */
+static inline struct ab8500_gpio *to_ab8500_gpio(struct gpio_chip *chip)
+{
+       return container_of(chip, struct ab8500_gpio, chip);
+}
+
+static int ab8500_gpio_set_bits(struct gpio_chip *chip, u8 reg,
+                                       unsigned offset, int val)
+{
+       struct ab8500_gpio *ab8500_gpio = to_ab8500_gpio(chip);
+       u8 pos = offset % 8;
+       int ret;
+
+       reg = reg + (offset / 8);
+       ret = abx500_mask_and_set_register_interruptible(ab8500_gpio->dev,
+                               AB8500_MISC, reg, 1 << pos, val << pos);
+       if (ret < 0)
+               dev_err(ab8500_gpio->dev, "%s write failed\n", __func__);
+       return ret;
+}
+/**
+ * ab8500_gpio_get() - Get the particular GPIO value
+ * @chip: Gpio device
+ * @offset: GPIO number to read
+ */
+static int ab8500_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+       struct ab8500_gpio *ab8500_gpio = to_ab8500_gpio(chip);
+       u8 mask = 1 << (offset % 8);
+       u8 reg = AB8500_GPIO_OUT1_REG + (offset / 8);
+       int ret;
+       u8 data;
+       ret = abx500_get_register_interruptible(ab8500_gpio->dev, AB8500_MISC,
+                                               reg, &data);
+       if (ret < 0) {
+               dev_err(ab8500_gpio->dev, "%s read failed\n", __func__);
+               return ret;
+       }
+       return (data & mask) >> (offset % 8);
+}
+
+static void ab8500_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
+{
+       struct ab8500_gpio *ab8500_gpio = to_ab8500_gpio(chip);
+       int ret;
+       /* Write the data */
+       ret = ab8500_gpio_set_bits(chip, AB8500_GPIO_OUT1_REG, offset, 1);
+       if (ret < 0)
+               dev_err(ab8500_gpio->dev, "%s write failed\n", __func__);
+}
+
+static int ab8500_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
+                                       int val)
+{
+       int ret;
+       /* set direction as output */
+       ret = ab8500_gpio_set_bits(chip, AB8500_GPIO_DIR1_REG, offset, 1);
+       if (ret < 0)
+               return ret;
+       /* disable pull down */
+       ret = ab8500_gpio_set_bits(chip, AB8500_GPIO_PUD1_REG, offset, 1);
+       if (ret < 0)
+               return ret;
+       /* set the output as 1 or 0 */
+       return ab8500_gpio_set_bits(chip, AB8500_GPIO_OUT1_REG, offset, val);
+
+}
+
+static int ab8500_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+       /* set the register as input */
+       return ab8500_gpio_set_bits(chip, AB8500_GPIO_DIR1_REG, offset, 0);
+}
+
+static int ab8500_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+       /*
+        * Only some GPIOs are interrupt capable, and they are
+        * organized in discontiguous clusters:
+        *
+        *      GPIO6 to GPIO13
+        *      GPIO24 and GPIO25
+        *      GPIO36 to GPIO41
+        */
+       static struct ab8500_gpio_irq_cluster {
+               int start;
+               int end;
+       } clusters[] = {
+               {.start = 6,  .end = 13},
+               {.start = 24, .end = 25},
+               {.start = 36, .end = 41},
+       };
+       struct ab8500_gpio *ab8500_gpio = to_ab8500_gpio(chip);
+       int base = ab8500_gpio->irq_base;
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(clusters); i++) {
+               struct ab8500_gpio_irq_cluster *cluster = &clusters[i];
+
+               if (offset >= cluster->start && offset <= cluster->end)
+                       return base + offset - cluster->start;
+
+               /* Advance by the number of gpios in this cluster */
+               base += cluster->end - cluster->start + 1;
+       }
+
+       return -EINVAL;
+}
+
+static struct gpio_chip ab8500gpio_chip = {
+       .label                  = "ab8500_gpio",
+       .owner                  = THIS_MODULE,
+       .direction_input        = ab8500_gpio_direction_input,
+       .get                    = ab8500_gpio_get,
+       .direction_output       = ab8500_gpio_direction_output,
+       .set                    = ab8500_gpio_set,
+       .to_irq                 = ab8500_gpio_to_irq,
+};
+
+static unsigned int irq_to_rising(unsigned int irq)
+{
+       struct ab8500_gpio *ab8500_gpio = get_irq_chip_data(irq);
+       int offset = irq - ab8500_gpio->irq_base;
+       int new_irq = offset +  AB8500_INT_GPIO6R
+                       + ab8500_gpio->parent->irq_base;
+       return new_irq;
+}
+
+static unsigned int irq_to_falling(unsigned int irq)
+{
+       struct ab8500_gpio *ab8500_gpio = get_irq_chip_data(irq);
+       int offset = irq - ab8500_gpio->irq_base;
+       int new_irq = offset +  AB8500_INT_GPIO6F
+                       +  ab8500_gpio->parent->irq_base;
+       return new_irq;
+
+}
+
+static unsigned int rising_to_irq(unsigned int irq, void *dev)
+{
+       struct ab8500_gpio *ab8500_gpio = dev;
+       int offset = irq - AB8500_INT_GPIO6R
+                       - ab8500_gpio->parent->irq_base ;
+       int new_irq = offset + ab8500_gpio->irq_base;
+       return new_irq;
+}
+
+static unsigned int falling_to_irq(unsigned int irq, void *dev)
+{
+       struct ab8500_gpio *ab8500_gpio = dev;
+       int offset = irq - AB8500_INT_GPIO6F
+                       - ab8500_gpio->parent->irq_base ;
+       int new_irq = offset + ab8500_gpio->irq_base;
+       return new_irq;
+
+}
+
+/*
+ * IRQ handler
+ */
+
+static irqreturn_t handle_rising(int irq, void *dev)
+{
+
+       handle_nested_irq(rising_to_irq(irq , dev));
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t handle_falling(int irq, void *dev)
+{
+
+       handle_nested_irq(falling_to_irq(irq, dev));
+       return IRQ_HANDLED;
+}
+
+static void ab8500_gpio_irq_lock(unsigned int irq)
+{
+       struct ab8500_gpio *ab8500_gpio = get_irq_chip_data(irq);
+       mutex_lock(&ab8500_gpio->lock);
+}
+
+static void ab8500_gpio_irq_sync_unlock(unsigned int irq)
+{
+       struct ab8500_gpio *ab8500_gpio = get_irq_chip_data(irq);
+       int offset = irq - ab8500_gpio->irq_base;
+       bool rising = ab8500_gpio->rising & BIT(offset);
+       bool falling = ab8500_gpio->falling & BIT(offset);
+       int ret;
+
+       switch (ab8500_gpio->irq_action)        {
+       case STARTUP:
+               if (rising)
+                       ret = request_threaded_irq(irq_to_rising(irq),
+                                       NULL, handle_rising,
+                                       IRQF_TRIGGER_RISING,
+                                       "ab8500-gpio-r", ab8500_gpio);
+               if (falling)
+                       ret = request_threaded_irq(irq_to_falling(irq),
+                                      NULL, handle_falling,
+                                      IRQF_TRIGGER_FALLING,
+                                      "ab8500-gpio-f", ab8500_gpio);
+               break;
+       case SHUTDOWN:
+               if (rising)
+                       free_irq(irq_to_rising(irq), ab8500_gpio);
+               if (falling)
+                       free_irq(irq_to_falling(irq), ab8500_gpio);
+               break;
+       case MASK:
+               if (rising)
+                       disable_irq(irq_to_rising(irq));
+               if (falling)
+                       disable_irq(irq_to_falling(irq));
+               break;
+       case UNMASK:
+               if (rising)
+                       enable_irq(irq_to_rising(irq));
+               if (falling)
+                       enable_irq(irq_to_falling(irq));
+               break;
+       case NONE:
+               break;
+       }
+       ab8500_gpio->irq_action = NONE;
+       ab8500_gpio->rising &= ~(BIT(offset));
+       ab8500_gpio->falling &= ~(BIT(offset));
+       mutex_unlock(&ab8500_gpio->lock);
+}
+
+
+static void ab8500_gpio_irq_mask(unsigned int irq)
+{
+       struct ab8500_gpio *ab8500_gpio = get_irq_chip_data(irq);
+       ab8500_gpio->irq_action = MASK;
+}
+
+static void ab8500_gpio_irq_unmask(unsigned int irq)
+{
+       struct ab8500_gpio *ab8500_gpio = get_irq_chip_data(irq);
+       ab8500_gpio->irq_action = UNMASK;
+}
+
+static int ab8500_gpio_irq_set_type(unsigned int irq, unsigned int type)
+{
+       struct ab8500_gpio *ab8500_gpio = get_irq_chip_data(irq);
+       int offset = irq - ab8500_gpio->irq_base;
+
+       if (type == IRQ_TYPE_EDGE_BOTH) {
+               ab8500_gpio->rising =  BIT(offset);
+               ab8500_gpio->falling = BIT(offset);
+       } else if (type == IRQ_TYPE_EDGE_RISING) {
+               ab8500_gpio->rising =  BIT(offset);
+       } else  {
+               ab8500_gpio->falling = BIT(offset);
+       }
+       return 0;
+}
+
+unsigned int ab8500_gpio_irq_startup(unsigned int irq)
+{
+       struct ab8500_gpio *ab8500_gpio = get_irq_chip_data(irq);
+       ab8500_gpio->irq_action = STARTUP;
+       return 0;
+}
+
+void ab8500_gpio_irq_shutdown(unsigned int irq)
+{
+       struct ab8500_gpio *ab8500_gpio = get_irq_chip_data(irq);
+       ab8500_gpio->irq_action = SHUTDOWN;
+}
+
+static struct irq_chip ab8500_gpio_irq_chip = {
+       .name                   = "ab8500-gpio",
+       .startup                = ab8500_gpio_irq_startup,
+       .shutdown               = ab8500_gpio_irq_shutdown,
+       .bus_lock               = ab8500_gpio_irq_lock,
+       .bus_sync_unlock        = ab8500_gpio_irq_sync_unlock,
+       .mask                   = ab8500_gpio_irq_mask,
+       .unmask                 = ab8500_gpio_irq_unmask,
+       .set_type               = ab8500_gpio_irq_set_type,
+};
+
+static int ab8500_gpio_irq_init(struct ab8500_gpio *ab8500_gpio)
+{
+       u32 base = ab8500_gpio->irq_base;
+       int irq;
+
+       for (irq = base; irq < base + AB8500_NUM_VIR_GPIO_IRQ ; irq++) {
+               set_irq_chip_data(irq, ab8500_gpio);
+               set_irq_chip_and_handler(irq, &ab8500_gpio_irq_chip,
+                               handle_simple_irq);
+               set_irq_nested_thread(irq, 1);
+#ifdef CONFIG_ARM
+               set_irq_flags(irq, IRQF_VALID);
+#else
+               set_irq_noprobe(irq);
+#endif
+       }
+
+       return 0;
+}
+
+static void ab8500_gpio_irq_remove(struct ab8500_gpio *ab8500_gpio)
+{
+       int base = ab8500_gpio->irq_base;
+       int irq;
+
+       for (irq = base; irq < base + AB8500_NUM_VIR_GPIO_IRQ; irq++) {
+#ifdef CONFIG_ARM
+               set_irq_flags(irq, 0);
+#endif
+               set_irq_chip_and_handler(irq, NULL, NULL);
+               set_irq_chip_data(irq, NULL);
+       }
+}
+
+static int __devinit ab8500_gpio_probe(struct platform_device *pdev)
+{
+       struct ab8500_platform_data *ab8500_pdata =
+                               dev_get_platdata(pdev->dev.parent);
+       struct ab8500_gpio_platform_data *pdata;
+       struct ab8500_gpio *ab8500_gpio;
+       int ret;
+       int i;
+
+       pdata = ab8500_pdata->gpio;
+       if (!pdata)     {
+               dev_err(&pdev->dev, "gpio platform data missing\n");
+               return -ENODEV;
+       }
+
+       ab8500_gpio = kzalloc(sizeof(struct ab8500_gpio), GFP_KERNEL);
+       if (ab8500_gpio == NULL) {
+               dev_err(&pdev->dev, "failed to allocate memory\n");
+               return -ENOMEM;
+       }
+       ab8500_gpio->dev = &pdev->dev;
+       ab8500_gpio->parent = dev_get_drvdata(pdev->dev.parent);
+       ab8500_gpio->chip = ab8500gpio_chip;
+       ab8500_gpio->chip.ngpio = AB8500_NUM_GPIO;
+       ab8500_gpio->chip.dev = &pdev->dev;
+       ab8500_gpio->chip.base = pdata->gpio_base;
+       ab8500_gpio->irq_base = pdata->irq_base;
+       /* initialize the lock */
+       mutex_init(&ab8500_gpio->lock);
+       /*
+        * AB8500 core will handle and clear the IRQ
+        * configre GPIO based on config-reg value.
+        * These values are for selecting the PINs as
+        * GPIO or alternate function
+        */
+       for (i = AB8500_GPIO_SEL1_REG; i <= AB8500_GPIO_SEL6_REG; i++)  {
+               ret = abx500_set_register_interruptible(ab8500_gpio->dev,
+                               AB8500_MISC, i,
+                               pdata->config_reg[i]);
+               if (ret < 0)
+                       goto out_free;
+       }
+       ret = abx500_set_register_interruptible(ab8500_gpio->dev, AB8500_MISC,
+                               AB8500_GPIO_ALTFUN_REG,
+                               pdata->config_reg[ALTFUN_REG_INDEX]);
+       if (ret < 0)
+               goto out_free;
+
+       ret = ab8500_gpio_irq_init(ab8500_gpio);
+       if (ret)
+               goto out_free;
+       ret = gpiochip_add(&ab8500_gpio->chip);
+       if (ret) {
+               dev_err(&pdev->dev, "unable to add gpiochip: %d\n",
+                               ret);
+               goto out_rem_irq;
+       }
+       platform_set_drvdata(pdev, ab8500_gpio);
+       return 0;
+
+out_rem_irq:
+       ab8500_gpio_irq_remove(ab8500_gpio);
+out_free:
+       mutex_destroy(&ab8500_gpio->lock);
+       kfree(ab8500_gpio);
+       return ret;
+}
+
+/*
+ * ab8500_gpio_remove() - remove Ab8500-gpio driver
+ * @pdev :     Platform device registered
+ */
+static int __devexit ab8500_gpio_remove(struct platform_device *pdev)
+{
+       struct ab8500_gpio *ab8500_gpio = platform_get_drvdata(pdev);
+       int ret;
+
+       ret = gpiochip_remove(&ab8500_gpio->chip);
+       if (ret < 0) {
+               dev_err(ab8500_gpio->dev, "unable to remove gpiochip: %d\n",
+                       ret);
+               return ret;
+       }
+
+       platform_set_drvdata(pdev, NULL);
+       mutex_destroy(&ab8500_gpio->lock);
+       kfree(ab8500_gpio);
+
+       return 0;
+}
+
+static struct platform_driver ab8500_gpio_driver = {
+       .driver = {
+               .name = "ab8500-gpio",
+               .owner = THIS_MODULE,
+       },
+       .probe = ab8500_gpio_probe,
+       .remove = __devexit_p(ab8500_gpio_remove),
+};
+
+static int __init ab8500_gpio_init(void)
+{
+       return platform_driver_register(&ab8500_gpio_driver);
+}
+arch_initcall(ab8500_gpio_init);
+
+static void __exit ab8500_gpio_exit(void)
+{
+       platform_driver_unregister(&ab8500_gpio_driver);
+}
+module_exit(ab8500_gpio_exit);
+
+MODULE_AUTHOR("BIBEK BASU <bibek.basu@stericsson.com>");
+MODULE_DESCRIPTION("Driver allows to use AB8500 unused pins to be used as GPIO");
+MODULE_ALIAS("AB8500 GPIO driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpio/gpio-adp5520.c b/drivers/gpio/gpio-adp5520.c
new file mode 100644 (file)
index 0000000..9f27815
--- /dev/null
@@ -0,0 +1,211 @@
+/*
+ * GPIO driver for Analog Devices ADP5520 MFD PMICs
+ *
+ * Copyright 2009 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/adp5520.h>
+
+#include <linux/gpio.h>
+
+struct adp5520_gpio {
+       struct device *master;
+       struct gpio_chip gpio_chip;
+       unsigned char lut[ADP5520_MAXGPIOS];
+       unsigned long output;
+};
+
+static int adp5520_gpio_get_value(struct gpio_chip *chip, unsigned off)
+{
+       struct adp5520_gpio *dev;
+       uint8_t reg_val;
+
+       dev = container_of(chip, struct adp5520_gpio, gpio_chip);
+
+       /*
+        * There are dedicated registers for GPIO IN/OUT.
+        * Make sure we return the right value, even when configured as output
+        */
+
+       if (test_bit(off, &dev->output))
+               adp5520_read(dev->master, ADP5520_GPIO_OUT, &reg_val);
+       else
+               adp5520_read(dev->master, ADP5520_GPIO_IN, &reg_val);
+
+       return !!(reg_val & dev->lut[off]);
+}
+
+static void adp5520_gpio_set_value(struct gpio_chip *chip,
+               unsigned off, int val)
+{
+       struct adp5520_gpio *dev;
+       dev = container_of(chip, struct adp5520_gpio, gpio_chip);
+
+       if (val)
+               adp5520_set_bits(dev->master, ADP5520_GPIO_OUT, dev->lut[off]);
+       else
+               adp5520_clr_bits(dev->master, ADP5520_GPIO_OUT, dev->lut[off]);
+}
+
+static int adp5520_gpio_direction_input(struct gpio_chip *chip, unsigned off)
+{
+       struct adp5520_gpio *dev;
+       dev = container_of(chip, struct adp5520_gpio, gpio_chip);
+
+       clear_bit(off, &dev->output);
+
+       return adp5520_clr_bits(dev->master, ADP5520_GPIO_CFG_2,
+                               dev->lut[off]);
+}
+
+static int adp5520_gpio_direction_output(struct gpio_chip *chip,
+               unsigned off, int val)
+{
+       struct adp5520_gpio *dev;
+       int ret = 0;
+       dev = container_of(chip, struct adp5520_gpio, gpio_chip);
+
+       set_bit(off, &dev->output);
+
+       if (val)
+               ret |= adp5520_set_bits(dev->master, ADP5520_GPIO_OUT,
+                                       dev->lut[off]);
+       else
+               ret |= adp5520_clr_bits(dev->master, ADP5520_GPIO_OUT,
+                                       dev->lut[off]);
+
+       ret |= adp5520_set_bits(dev->master, ADP5520_GPIO_CFG_2,
+                                       dev->lut[off]);
+
+       return ret;
+}
+
+static int __devinit adp5520_gpio_probe(struct platform_device *pdev)
+{
+       struct adp5520_gpio_platform_data *pdata = pdev->dev.platform_data;
+       struct adp5520_gpio *dev;
+       struct gpio_chip *gc;
+       int ret, i, gpios;
+       unsigned char ctl_mask = 0;
+
+       if (pdata == NULL) {
+               dev_err(&pdev->dev, "missing platform data\n");
+               return -ENODEV;
+       }
+
+       if (pdev->id != ID_ADP5520) {
+               dev_err(&pdev->dev, "only ADP5520 supports GPIO\n");
+               return -ENODEV;
+       }
+
+       dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+       if (dev == NULL) {
+               dev_err(&pdev->dev, "failed to alloc memory\n");
+               return -ENOMEM;
+       }
+
+       dev->master = pdev->dev.parent;
+
+       for (gpios = 0, i = 0; i < ADP5520_MAXGPIOS; i++)
+               if (pdata->gpio_en_mask & (1 << i))
+                       dev->lut[gpios++] = 1 << i;
+
+       if (gpios < 1) {
+               ret = -EINVAL;
+               goto err;
+       }
+
+       gc = &dev->gpio_chip;
+       gc->direction_input  = adp5520_gpio_direction_input;
+       gc->direction_output = adp5520_gpio_direction_output;
+       gc->get = adp5520_gpio_get_value;
+       gc->set = adp5520_gpio_set_value;
+       gc->can_sleep = 1;
+
+       gc->base = pdata->gpio_start;
+       gc->ngpio = gpios;
+       gc->label = pdev->name;
+       gc->owner = THIS_MODULE;
+
+       ret = adp5520_clr_bits(dev->master, ADP5520_GPIO_CFG_1,
+               pdata->gpio_en_mask);
+
+       if (pdata->gpio_en_mask & ADP5520_GPIO_C3)
+               ctl_mask |= ADP5520_C3_MODE;
+
+       if (pdata->gpio_en_mask & ADP5520_GPIO_R3)
+               ctl_mask |= ADP5520_R3_MODE;
+
+       if (ctl_mask)
+               ret = adp5520_set_bits(dev->master, ADP5520_LED_CONTROL,
+                       ctl_mask);
+
+       ret |= adp5520_set_bits(dev->master, ADP5520_GPIO_PULLUP,
+               pdata->gpio_pullup_mask);
+
+       if (ret) {
+               dev_err(&pdev->dev, "failed to write\n");
+               goto err;
+       }
+
+       ret = gpiochip_add(&dev->gpio_chip);
+       if (ret)
+               goto err;
+
+       platform_set_drvdata(pdev, dev);
+       return 0;
+
+err:
+       kfree(dev);
+       return ret;
+}
+
+static int __devexit adp5520_gpio_remove(struct platform_device *pdev)
+{
+       struct adp5520_gpio *dev;
+       int ret;
+
+       dev = platform_get_drvdata(pdev);
+       ret = gpiochip_remove(&dev->gpio_chip);
+       if (ret) {
+               dev_err(&pdev->dev, "%s failed, %d\n",
+                               "gpiochip_remove()", ret);
+               return ret;
+       }
+
+       kfree(dev);
+       return 0;
+}
+
+static struct platform_driver adp5520_gpio_driver = {
+       .driver = {
+               .name   = "adp5520-gpio",
+               .owner  = THIS_MODULE,
+       },
+       .probe          = adp5520_gpio_probe,
+       .remove         = __devexit_p(adp5520_gpio_remove),
+};
+
+static int __init adp5520_gpio_init(void)
+{
+       return platform_driver_register(&adp5520_gpio_driver);
+}
+module_init(adp5520_gpio_init);
+
+static void __exit adp5520_gpio_exit(void)
+{
+       platform_driver_unregister(&adp5520_gpio_driver);
+}
+module_exit(adp5520_gpio_exit);
+
+MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
+MODULE_DESCRIPTION("GPIO ADP5520 Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:adp5520-gpio");
diff --git a/drivers/gpio/gpio-adp5588.c b/drivers/gpio/gpio-adp5588.c
new file mode 100644 (file)
index 0000000..3525ad9
--- /dev/null
@@ -0,0 +1,503 @@
+/*
+ * GPIO Chip driver for Analog Devices
+ * ADP5588/ADP5587 I/O Expander and QWERTY Keypad Controller
+ *
+ * Copyright 2009-2010 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+
+#include <linux/i2c/adp5588.h>
+
+#define DRV_NAME       "adp5588-gpio"
+
+/*
+ * Early pre 4.0 Silicon required to delay readout by at least 25ms,
+ * since the Event Counter Register updated 25ms after the interrupt
+ * asserted.
+ */
+#define WA_DELAYED_READOUT_REVID(rev)  ((rev) < 4)
+
+struct adp5588_gpio {
+       struct i2c_client *client;
+       struct gpio_chip gpio_chip;
+       struct mutex lock;      /* protect cached dir, dat_out */
+       /* protect serialized access to the interrupt controller bus */
+       struct mutex irq_lock;
+       unsigned gpio_start;
+       unsigned irq_base;
+       uint8_t dat_out[3];
+       uint8_t dir[3];
+       uint8_t int_lvl[3];
+       uint8_t int_en[3];
+       uint8_t irq_mask[3];
+       uint8_t irq_stat[3];
+};
+
+static int adp5588_gpio_read(struct i2c_client *client, u8 reg)
+{
+       int ret = i2c_smbus_read_byte_data(client, reg);
+
+       if (ret < 0)
+               dev_err(&client->dev, "Read Error\n");
+
+       return ret;
+}
+
+static int adp5588_gpio_write(struct i2c_client *client, u8 reg, u8 val)
+{
+       int ret = i2c_smbus_write_byte_data(client, reg, val);
+
+       if (ret < 0)
+               dev_err(&client->dev, "Write Error\n");
+
+       return ret;
+}
+
+static int adp5588_gpio_get_value(struct gpio_chip *chip, unsigned off)
+{
+       struct adp5588_gpio *dev =
+           container_of(chip, struct adp5588_gpio, gpio_chip);
+
+       return !!(adp5588_gpio_read(dev->client,
+                 GPIO_DAT_STAT1 + ADP5588_BANK(off)) & ADP5588_BIT(off));
+}
+
+static void adp5588_gpio_set_value(struct gpio_chip *chip,
+                                  unsigned off, int val)
+{
+       unsigned bank, bit;
+       struct adp5588_gpio *dev =
+           container_of(chip, struct adp5588_gpio, gpio_chip);
+
+       bank = ADP5588_BANK(off);
+       bit = ADP5588_BIT(off);
+
+       mutex_lock(&dev->lock);
+       if (val)
+               dev->dat_out[bank] |= bit;
+       else
+               dev->dat_out[bank] &= ~bit;
+
+       adp5588_gpio_write(dev->client, GPIO_DAT_OUT1 + bank,
+                          dev->dat_out[bank]);
+       mutex_unlock(&dev->lock);
+}
+
+static int adp5588_gpio_direction_input(struct gpio_chip *chip, unsigned off)
+{
+       int ret;
+       unsigned bank;
+       struct adp5588_gpio *dev =
+           container_of(chip, struct adp5588_gpio, gpio_chip);
+
+       bank = ADP5588_BANK(off);
+
+       mutex_lock(&dev->lock);
+       dev->dir[bank] &= ~ADP5588_BIT(off);
+       ret = adp5588_gpio_write(dev->client, GPIO_DIR1 + bank, dev->dir[bank]);
+       mutex_unlock(&dev->lock);
+
+       return ret;
+}
+
+static int adp5588_gpio_direction_output(struct gpio_chip *chip,
+                                        unsigned off, int val)
+{
+       int ret;
+       unsigned bank, bit;
+       struct adp5588_gpio *dev =
+           container_of(chip, struct adp5588_gpio, gpio_chip);
+
+       bank = ADP5588_BANK(off);
+       bit = ADP5588_BIT(off);
+
+       mutex_lock(&dev->lock);
+       dev->dir[bank] |= bit;
+
+       if (val)
+               dev->dat_out[bank] |= bit;
+       else
+               dev->dat_out[bank] &= ~bit;
+
+       ret = adp5588_gpio_write(dev->client, GPIO_DAT_OUT1 + bank,
+                                dev->dat_out[bank]);
+       ret |= adp5588_gpio_write(dev->client, GPIO_DIR1 + bank,
+                                dev->dir[bank]);
+       mutex_unlock(&dev->lock);
+
+       return ret;
+}
+
+#ifdef CONFIG_GPIO_ADP5588_IRQ
+static int adp5588_gpio_to_irq(struct gpio_chip *chip, unsigned off)
+{
+       struct adp5588_gpio *dev =
+               container_of(chip, struct adp5588_gpio, gpio_chip);
+       return dev->irq_base + off;
+}
+
+static void adp5588_irq_bus_lock(struct irq_data *d)
+{
+       struct adp5588_gpio *dev = irq_data_get_irq_chip_data(d);
+
+       mutex_lock(&dev->irq_lock);
+}
+
+ /*
+  * genirq core code can issue chip->mask/unmask from atomic context.
+  * This doesn't work for slow busses where an access needs to sleep.
+  * bus_sync_unlock() is therefore called outside the atomic context,
+  * syncs the current irq mask state with the slow external controller
+  * and unlocks the bus.
+  */
+
+static void adp5588_irq_bus_sync_unlock(struct irq_data *d)
+{
+       struct adp5588_gpio *dev = irq_data_get_irq_chip_data(d);
+       int i;
+
+       for (i = 0; i <= ADP5588_BANK(ADP5588_MAXGPIO); i++)
+               if (dev->int_en[i] ^ dev->irq_mask[i]) {
+                       dev->int_en[i] = dev->irq_mask[i];
+                       adp5588_gpio_write(dev->client, GPIO_INT_EN1 + i,
+                                          dev->int_en[i]);
+               }
+
+       mutex_unlock(&dev->irq_lock);
+}
+
+static void adp5588_irq_mask(struct irq_data *d)
+{
+       struct adp5588_gpio *dev = irq_data_get_irq_chip_data(d);
+       unsigned gpio = d->irq - dev->irq_base;
+
+       dev->irq_mask[ADP5588_BANK(gpio)] &= ~ADP5588_BIT(gpio);
+}
+
+static void adp5588_irq_unmask(struct irq_data *d)
+{
+       struct adp5588_gpio *dev = irq_data_get_irq_chip_data(d);
+       unsigned gpio = d->irq - dev->irq_base;
+
+       dev->irq_mask[ADP5588_BANK(gpio)] |= ADP5588_BIT(gpio);
+}
+
+static int adp5588_irq_set_type(struct irq_data *d, unsigned int type)
+{
+       struct adp5588_gpio *dev = irq_data_get_irq_chip_data(d);
+       uint16_t gpio = d->irq - dev->irq_base;
+       unsigned bank, bit;
+
+       if ((type & IRQ_TYPE_EDGE_BOTH)) {
+               dev_err(&dev->client->dev, "irq %d: unsupported type %d\n",
+                       d->irq, type);
+               return -EINVAL;
+       }
+
+       bank = ADP5588_BANK(gpio);
+       bit = ADP5588_BIT(gpio);
+
+       if (type & IRQ_TYPE_LEVEL_HIGH)
+               dev->int_lvl[bank] |= bit;
+       else if (type & IRQ_TYPE_LEVEL_LOW)
+               dev->int_lvl[bank] &= ~bit;
+       else
+               return -EINVAL;
+
+       adp5588_gpio_direction_input(&dev->gpio_chip, gpio);
+       adp5588_gpio_write(dev->client, GPIO_INT_LVL1 + bank,
+                          dev->int_lvl[bank]);
+
+       return 0;
+}
+
+static struct irq_chip adp5588_irq_chip = {
+       .name                   = "adp5588",
+       .irq_mask               = adp5588_irq_mask,
+       .irq_unmask             = adp5588_irq_unmask,
+       .irq_bus_lock           = adp5588_irq_bus_lock,
+       .irq_bus_sync_unlock    = adp5588_irq_bus_sync_unlock,
+       .irq_set_type           = adp5588_irq_set_type,
+};
+
+static int adp5588_gpio_read_intstat(struct i2c_client *client, u8 *buf)
+{
+       int ret = i2c_smbus_read_i2c_block_data(client, GPIO_INT_STAT1, 3, buf);
+
+       if (ret < 0)
+               dev_err(&client->dev, "Read INT_STAT Error\n");
+
+       return ret;
+}
+
+static irqreturn_t adp5588_irq_handler(int irq, void *devid)
+{
+       struct adp5588_gpio *dev = devid;
+       unsigned status, bank, bit, pending;
+       int ret;
+       status = adp5588_gpio_read(dev->client, INT_STAT);
+
+       if (status & ADP5588_GPI_INT) {
+               ret = adp5588_gpio_read_intstat(dev->client, dev->irq_stat);
+               if (ret < 0)
+                       memset(dev->irq_stat, 0, ARRAY_SIZE(dev->irq_stat));
+
+               for (bank = 0; bank <= ADP5588_BANK(ADP5588_MAXGPIO);
+                       bank++, bit = 0) {
+                       pending = dev->irq_stat[bank] & dev->irq_mask[bank];
+
+                       while (pending) {
+                               if (pending & (1 << bit)) {
+                                       handle_nested_irq(dev->irq_base +
+                                                         (bank << 3) + bit);
+                                       pending &= ~(1 << bit);
+
+                               }
+                               bit++;
+                       }
+               }
+       }
+
+       adp5588_gpio_write(dev->client, INT_STAT, status); /* Status is W1C */
+
+       return IRQ_HANDLED;
+}
+
+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;
+       unsigned gpio;
+       int ret;
+
+       adp5588_gpio_write(client, CFG, ADP5588_AUTO_INC);
+       adp5588_gpio_write(client, INT_STAT, -1); /* status is W1C */
+       adp5588_gpio_read_intstat(client, dev->irq_stat); /* read to clear */
+
+       dev->irq_base = pdata->irq_base;
+       mutex_init(&dev->irq_lock);
+
+       for (gpio = 0; gpio < dev->gpio_chip.ngpio; gpio++) {
+               int irq = gpio + dev->irq_base;
+               irq_set_chip_data(irq, dev);
+               irq_set_chip_and_handler(irq, &adp5588_irq_chip,
+                                        handle_level_irq);
+               irq_set_nested_thread(irq, 1);
+#ifdef CONFIG_ARM
+               /*
+                * ARM needs us to explicitly flag the IRQ as VALID,
+                * once we do so, it will also set the noprobe.
+                */
+               set_irq_flags(irq, IRQF_VALID);
+#else
+               irq_set_noprobe(irq);
+#endif
+       }
+
+       ret = request_threaded_irq(client->irq,
+                                  NULL,
+                                  adp5588_irq_handler,
+                                  IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+                                  dev_name(&client->dev), dev);
+       if (ret) {
+               dev_err(&client->dev, "failed to request irq %d\n",
+                       client->irq);
+               goto out;
+       }
+
+       dev->gpio_chip.to_irq = adp5588_gpio_to_irq;
+       adp5588_gpio_write(client, CFG,
+               ADP5588_AUTO_INC | ADP5588_INT_CFG | ADP5588_GPI_INT);
+
+       return 0;
+
+out:
+       dev->irq_base = 0;
+       return ret;
+}
+
+static void adp5588_irq_teardown(struct adp5588_gpio *dev)
+{
+       if (dev->irq_base)
+               free_irq(dev->client->irq, dev);
+}
+
+#else
+static int adp5588_irq_setup(struct adp5588_gpio *dev)
+{
+       struct i2c_client *client = dev->client;
+       dev_warn(&client->dev, "interrupt support not compiled in\n");
+
+       return 0;
+}
+
+static void adp5588_irq_teardown(struct adp5588_gpio *dev)
+{
+}
+#endif /* CONFIG_GPIO_ADP5588_IRQ */
+
+static int __devinit 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 *dev;
+       struct gpio_chip *gc;
+       int ret, i, revid;
+
+       if (pdata == NULL) {
+               dev_err(&client->dev, "missing platform data\n");
+               return -ENODEV;
+       }
+
+       if (!i2c_check_functionality(client->adapter,
+                                       I2C_FUNC_SMBUS_BYTE_DATA)) {
+               dev_err(&client->dev, "SMBUS Byte Data not Supported\n");
+               return -EIO;
+       }
+
+       dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+       if (dev == NULL) {
+               dev_err(&client->dev, "failed to alloc memory\n");
+               return -ENOMEM;
+       }
+
+       dev->client = client;
+
+       gc = &dev->gpio_chip;
+       gc->direction_input = adp5588_gpio_direction_input;
+       gc->direction_output = adp5588_gpio_direction_output;
+       gc->get = adp5588_gpio_get_value;
+       gc->set = adp5588_gpio_set_value;
+       gc->can_sleep = 1;
+
+       gc->base = pdata->gpio_start;
+       gc->ngpio = ADP5588_MAXGPIO;
+       gc->label = client->name;
+       gc->owner = THIS_MODULE;
+
+       mutex_init(&dev->lock);
+
+       ret = adp5588_gpio_read(dev->client, DEV_ID);
+       if (ret < 0)
+               goto err;
+
+       revid = ret & ADP5588_DEVICE_ID_MASK;
+
+       for (i = 0, ret = 0; i <= ADP5588_BANK(ADP5588_MAXGPIO); i++) {
+               dev->dat_out[i] = adp5588_gpio_read(client, GPIO_DAT_OUT1 + i);
+               dev->dir[i] = adp5588_gpio_read(client, GPIO_DIR1 + i);
+               ret |= adp5588_gpio_write(client, KP_GPIO1 + i, 0);
+               ret |= adp5588_gpio_write(client, GPIO_PULL1 + i,
+                               (pdata->pullup_dis_mask >> (8 * i)) & 0xFF);
+               ret |= adp5588_gpio_write(client, GPIO_INT_EN1 + i, 0);
+               if (ret)
+                       goto err;
+       }
+
+       if (pdata->irq_base) {
+               if (WA_DELAYED_READOUT_REVID(revid)) {
+                       dev_warn(&client->dev, "GPIO int not supported\n");
+               } else {
+                       ret = adp5588_irq_setup(dev);
+                       if (ret)
+                               goto err;
+               }
+       }
+
+       ret = gpiochip_add(&dev->gpio_chip);
+       if (ret)
+               goto err_irq;
+
+       dev_info(&client->dev, "gpios %d..%d (IRQ Base %d) on a %s Rev. %d\n",
+                       gc->base, gc->base + gc->ngpio - 1,
+                       pdata->irq_base, client->name, revid);
+
+       if (pdata->setup) {
+               ret = pdata->setup(client, gc->base, gc->ngpio, pdata->context);
+               if (ret < 0)
+                       dev_warn(&client->dev, "setup failed, %d\n", ret);
+       }
+
+       i2c_set_clientdata(client, dev);
+
+       return 0;
+
+err_irq:
+       adp5588_irq_teardown(dev);
+err:
+       kfree(dev);
+       return ret;
+}
+
+static int __devexit adp5588_gpio_remove(struct i2c_client *client)
+{
+       struct adp5588_gpio_platform_data *pdata = client->dev.platform_data;
+       struct adp5588_gpio *dev = i2c_get_clientdata(client);
+       int ret;
+
+       if (pdata->teardown) {
+               ret = pdata->teardown(client,
+                                     dev->gpio_chip.base, dev->gpio_chip.ngpio,
+                                     pdata->context);
+               if (ret < 0) {
+                       dev_err(&client->dev, "teardown failed %d\n", ret);
+                       return ret;
+               }
+       }
+
+       if (dev->irq_base)
+               free_irq(dev->client->irq, dev);
+
+       ret = gpiochip_remove(&dev->gpio_chip);
+       if (ret) {
+               dev_err(&client->dev, "gpiochip_remove failed %d\n", ret);
+               return ret;
+       }
+
+       kfree(dev);
+       return 0;
+}
+
+static const struct i2c_device_id adp5588_gpio_id[] = {
+       {DRV_NAME, 0},
+       {}
+};
+
+MODULE_DEVICE_TABLE(i2c, adp5588_gpio_id);
+
+static struct i2c_driver adp5588_gpio_driver = {
+       .driver = {
+                  .name = DRV_NAME,
+                  },
+       .probe = adp5588_gpio_probe,
+       .remove = __devexit_p(adp5588_gpio_remove),
+       .id_table = adp5588_gpio_id,
+};
+
+static int __init adp5588_gpio_init(void)
+{
+       return i2c_add_driver(&adp5588_gpio_driver);
+}
+
+module_init(adp5588_gpio_init);
+
+static void __exit adp5588_gpio_exit(void)
+{
+       i2c_del_driver(&adp5588_gpio_driver);
+}
+
+module_exit(adp5588_gpio_exit);
+
+MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
+MODULE_DESCRIPTION("GPIO ADP5588 Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/gpio-bt8xx.c b/drivers/gpio/gpio-bt8xx.c
new file mode 100644 (file)
index 0000000..aa4f09a
--- /dev/null
@@ -0,0 +1,348 @@
+/*
+
+    bt8xx GPIO abuser
+
+    Copyright (C) 2008 Michael Buesch <mb@bu3sch.de>
+
+    Please do _only_ contact the people listed _above_ with issues related to this driver.
+    All the other people listed below are not related to this driver. Their names
+    are only here, because this driver is derived from the bt848 driver.
+
+
+    Derived from the bt848 driver:
+
+    Copyright (C) 1996,97,98 Ralph  Metzler
+                          & Marcus Metzler
+    (c) 1999-2002 Gerd Knorr
+
+    some v4l2 code lines are taken from Justin's bttv2 driver which is
+    (c) 2000 Justin Schoeman
+
+    V4L1 removal from:
+    (c) 2005-2006 Nickolay V. Shmyrev
+
+    Fixes to be fully V4L2 compliant by
+    (c) 2006 Mauro Carvalho Chehab
+
+    Cropping and overscan support
+    Copyright (C) 2005, 2006 Michael H. Schimek
+    Sponsored by OPQ Systems AB
+
+    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.
+
+    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.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/spinlock.h>
+#include <linux/gpio.h>
+#include <linux/slab.h>
+
+/* Steal the hardware definitions from the bttv driver. */
+#include "../media/video/bt8xx/bt848.h"
+
+
+#define BT8XXGPIO_NR_GPIOS             24 /* We have 24 GPIO pins */
+
+
+struct bt8xxgpio {
+       spinlock_t lock;
+
+       void __iomem *mmio;
+       struct pci_dev *pdev;
+       struct gpio_chip gpio;
+
+#ifdef CONFIG_PM
+       u32 saved_outen;
+       u32 saved_data;
+#endif
+};
+
+#define bgwrite(dat, adr)      writel((dat), bg->mmio+(adr))
+#define bgread(adr)            readl(bg->mmio+(adr))
+
+
+static int modparam_gpiobase = -1/* dynamic */;
+module_param_named(gpiobase, modparam_gpiobase, int, 0444);
+MODULE_PARM_DESC(gpiobase, "The GPIO number base. -1 means dynamic, which is the default.");
+
+
+static int bt8xxgpio_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
+{
+       struct bt8xxgpio *bg = container_of(gpio, struct bt8xxgpio, gpio);
+       unsigned long flags;
+       u32 outen, data;
+
+       spin_lock_irqsave(&bg->lock, flags);
+
+       data = bgread(BT848_GPIO_DATA);
+       data &= ~(1 << nr);
+       bgwrite(data, BT848_GPIO_DATA);
+
+       outen = bgread(BT848_GPIO_OUT_EN);
+       outen &= ~(1 << nr);
+       bgwrite(outen, BT848_GPIO_OUT_EN);
+
+       spin_unlock_irqrestore(&bg->lock, flags);
+
+       return 0;
+}
+
+static int bt8xxgpio_gpio_get(struct gpio_chip *gpio, unsigned nr)
+{
+       struct bt8xxgpio *bg = container_of(gpio, struct bt8xxgpio, gpio);
+       unsigned long flags;
+       u32 val;
+
+       spin_lock_irqsave(&bg->lock, flags);
+       val = bgread(BT848_GPIO_DATA);
+       spin_unlock_irqrestore(&bg->lock, flags);
+
+       return !!(val & (1 << nr));
+}
+
+static int bt8xxgpio_gpio_direction_output(struct gpio_chip *gpio,
+                                       unsigned nr, int val)
+{
+       struct bt8xxgpio *bg = container_of(gpio, struct bt8xxgpio, gpio);
+       unsigned long flags;
+       u32 outen, data;
+
+       spin_lock_irqsave(&bg->lock, flags);
+
+       outen = bgread(BT848_GPIO_OUT_EN);
+       outen |= (1 << nr);
+       bgwrite(outen, BT848_GPIO_OUT_EN);
+
+       data = bgread(BT848_GPIO_DATA);
+       if (val)
+               data |= (1 << nr);
+       else
+               data &= ~(1 << nr);
+       bgwrite(data, BT848_GPIO_DATA);
+
+       spin_unlock_irqrestore(&bg->lock, flags);
+
+       return 0;
+}
+
+static void bt8xxgpio_gpio_set(struct gpio_chip *gpio,
+                           unsigned nr, int val)
+{
+       struct bt8xxgpio *bg = container_of(gpio, struct bt8xxgpio, gpio);
+       unsigned long flags;
+       u32 data;
+
+       spin_lock_irqsave(&bg->lock, flags);
+
+       data = bgread(BT848_GPIO_DATA);
+       if (val)
+               data |= (1 << nr);
+       else
+               data &= ~(1 << nr);
+       bgwrite(data, BT848_GPIO_DATA);
+
+       spin_unlock_irqrestore(&bg->lock, flags);
+}
+
+static void bt8xxgpio_gpio_setup(struct bt8xxgpio *bg)
+{
+       struct gpio_chip *c = &bg->gpio;
+
+       c->label = dev_name(&bg->pdev->dev);
+       c->owner = THIS_MODULE;
+       c->direction_input = bt8xxgpio_gpio_direction_input;
+       c->get = bt8xxgpio_gpio_get;
+       c->direction_output = bt8xxgpio_gpio_direction_output;
+       c->set = bt8xxgpio_gpio_set;
+       c->dbg_show = NULL;
+       c->base = modparam_gpiobase;
+       c->ngpio = BT8XXGPIO_NR_GPIOS;
+       c->can_sleep = 0;
+}
+
+static int bt8xxgpio_probe(struct pci_dev *dev,
+                       const struct pci_device_id *pci_id)
+{
+       struct bt8xxgpio *bg;
+       int err;
+
+       bg = kzalloc(sizeof(*bg), GFP_KERNEL);
+       if (!bg)
+               return -ENOMEM;
+
+       bg->pdev = dev;
+       spin_lock_init(&bg->lock);
+
+       err = pci_enable_device(dev);
+       if (err) {
+               printk(KERN_ERR "bt8xxgpio: Can't enable device.\n");
+               goto err_freebg;
+       }
+       if (!request_mem_region(pci_resource_start(dev, 0),
+                               pci_resource_len(dev, 0),
+                               "bt8xxgpio")) {
+               printk(KERN_WARNING "bt8xxgpio: Can't request iomem (0x%llx).\n",
+                      (unsigned long long)pci_resource_start(dev, 0));
+               err = -EBUSY;
+               goto err_disable;
+       }
+       pci_set_master(dev);
+       pci_set_drvdata(dev, bg);
+
+       bg->mmio = ioremap(pci_resource_start(dev, 0), 0x1000);
+       if (!bg->mmio) {
+               printk(KERN_ERR "bt8xxgpio: ioremap() failed\n");
+               err = -EIO;
+               goto err_release_mem;
+       }
+
+       /* Disable interrupts */
+       bgwrite(0, BT848_INT_MASK);
+
+       /* gpio init */
+       bgwrite(0, BT848_GPIO_DMA_CTL);
+       bgwrite(0, BT848_GPIO_REG_INP);
+       bgwrite(0, BT848_GPIO_OUT_EN);
+
+       bt8xxgpio_gpio_setup(bg);
+       err = gpiochip_add(&bg->gpio);
+       if (err) {
+               printk(KERN_ERR "bt8xxgpio: Failed to register GPIOs\n");
+               goto err_release_mem;
+       }
+
+       printk(KERN_INFO "bt8xxgpio: Abusing BT8xx card for GPIOs %d to %d\n",
+              bg->gpio.base, bg->gpio.base + BT8XXGPIO_NR_GPIOS - 1);
+
+       return 0;
+
+err_release_mem:
+       release_mem_region(pci_resource_start(dev, 0),
+                          pci_resource_len(dev, 0));
+       pci_set_drvdata(dev, NULL);
+err_disable:
+       pci_disable_device(dev);
+err_freebg:
+       kfree(bg);
+
+       return err;
+}
+
+static void bt8xxgpio_remove(struct pci_dev *pdev)
+{
+       struct bt8xxgpio *bg = pci_get_drvdata(pdev);
+
+       gpiochip_remove(&bg->gpio);
+
+       bgwrite(0, BT848_INT_MASK);
+       bgwrite(~0x0, BT848_INT_STAT);
+       bgwrite(0x0, BT848_GPIO_OUT_EN);
+
+       iounmap(bg->mmio);
+       release_mem_region(pci_resource_start(pdev, 0),
+                          pci_resource_len(pdev, 0));
+       pci_disable_device(pdev);
+
+       pci_set_drvdata(pdev, NULL);
+       kfree(bg);
+}
+
+#ifdef CONFIG_PM
+static int bt8xxgpio_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+       struct bt8xxgpio *bg = pci_get_drvdata(pdev);
+       unsigned long flags;
+
+       spin_lock_irqsave(&bg->lock, flags);
+
+       bg->saved_outen = bgread(BT848_GPIO_OUT_EN);
+       bg->saved_data = bgread(BT848_GPIO_DATA);
+
+       bgwrite(0, BT848_INT_MASK);
+       bgwrite(~0x0, BT848_INT_STAT);
+       bgwrite(0x0, BT848_GPIO_OUT_EN);
+
+       spin_unlock_irqrestore(&bg->lock, flags);
+
+       pci_save_state(pdev);
+       pci_disable_device(pdev);
+       pci_set_power_state(pdev, pci_choose_state(pdev, state));
+
+       return 0;
+}
+
+static int bt8xxgpio_resume(struct pci_dev *pdev)
+{
+       struct bt8xxgpio *bg = pci_get_drvdata(pdev);
+       unsigned long flags;
+       int err;
+
+       pci_set_power_state(pdev, 0);
+       err = pci_enable_device(pdev);
+       if (err)
+               return err;
+       pci_restore_state(pdev);
+
+       spin_lock_irqsave(&bg->lock, flags);
+
+       bgwrite(0, BT848_INT_MASK);
+       bgwrite(0, BT848_GPIO_DMA_CTL);
+       bgwrite(0, BT848_GPIO_REG_INP);
+       bgwrite(bg->saved_outen, BT848_GPIO_OUT_EN);
+       bgwrite(bg->saved_data & bg->saved_outen,
+               BT848_GPIO_DATA);
+
+       spin_unlock_irqrestore(&bg->lock, flags);
+
+       return 0;
+}
+#else
+#define bt8xxgpio_suspend NULL
+#define bt8xxgpio_resume NULL
+#endif /* CONFIG_PM */
+
+static struct pci_device_id bt8xxgpio_pci_tbl[] = {
+       { PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT848) },
+       { PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT849) },
+       { PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT878) },
+       { PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT879) },
+       { 0, },
+};
+MODULE_DEVICE_TABLE(pci, bt8xxgpio_pci_tbl);
+
+static struct pci_driver bt8xxgpio_pci_driver = {
+       .name           = "bt8xxgpio",
+       .id_table       = bt8xxgpio_pci_tbl,
+       .probe          = bt8xxgpio_probe,
+       .remove         = bt8xxgpio_remove,
+       .suspend        = bt8xxgpio_suspend,
+       .resume         = bt8xxgpio_resume,
+};
+
+static int __init bt8xxgpio_init(void)
+{
+       return pci_register_driver(&bt8xxgpio_pci_driver);
+}
+module_init(bt8xxgpio_init)
+
+static void __exit bt8xxgpio_exit(void)
+{
+       pci_unregister_driver(&bt8xxgpio_pci_driver);
+}
+module_exit(bt8xxgpio_exit)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Michael Buesch");
+MODULE_DESCRIPTION("Abuse a BT8xx framegrabber card as generic GPIO card");
diff --git a/drivers/gpio/gpio-cs5535.c b/drivers/gpio/gpio-cs5535.c
new file mode 100644 (file)
index 0000000..6e16cba
--- /dev/null
@@ -0,0 +1,401 @@
+/*
+ * AMD CS5535/CS5536 GPIO driver
+ * Copyright (C) 2006  Advanced Micro Devices, Inc.
+ * Copyright (C) 2007-2009  Andres Salomon <dilinger@collabora.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/io.h>
+#include <linux/cs5535.h>
+#include <asm/msr.h>
+
+#define DRV_NAME "cs5535-gpio"
+
+/*
+ * Some GPIO pins
+ *  31-29,23 : reserved (always mask out)
+ *  28       : Power Button
+ *  26       : PME#
+ *  22-16    : LPC
+ *  14,15    : SMBus
+ *  9,8      : UART1
+ *  7        : PCI INTB
+ *  3,4      : UART2/DDC
+ *  2        : IDE_IRQ0
+ *  1        : AC_BEEP
+ *  0        : PCI INTA
+ *
+ * If a mask was not specified, allow all except
+ * reserved and Power Button
+ */
+#define GPIO_DEFAULT_MASK 0x0F7FFFFF
+
+static ulong mask = GPIO_DEFAULT_MASK;
+module_param_named(mask, mask, ulong, 0444);
+MODULE_PARM_DESC(mask, "GPIO channel mask.");
+
+static struct cs5535_gpio_chip {
+       struct gpio_chip chip;
+       resource_size_t base;
+
+       struct platform_device *pdev;
+       spinlock_t lock;
+} cs5535_gpio_chip;
+
+/*
+ * The CS5535/CS5536 GPIOs support a number of extra features not defined
+ * by the gpio_chip API, so these are exported.  For a full list of the
+ * registers, see include/linux/cs5535.h.
+ */
+
+static void errata_outl(struct cs5535_gpio_chip *chip, u32 val,
+               unsigned int reg)
+{
+       unsigned long addr = chip->base + 0x80 + reg;
+
+       /*
+        * According to the CS5536 errata (#36), after suspend
+        * a write to the high bank GPIO register will clear all
+        * non-selected bits; the recommended workaround is a
+        * read-modify-write operation.
+        *
+        * Don't apply this errata to the edge status GPIOs, as writing
+        * to their lower bits will clear them.
+        */
+       if (reg != GPIO_POSITIVE_EDGE_STS && reg != GPIO_NEGATIVE_EDGE_STS) {
+               if (val & 0xffff)
+                       val |= (inl(addr) & 0xffff); /* ignore the high bits */
+               else
+                       val |= (inl(addr) ^ (val >> 16));
+       }
+       outl(val, addr);
+}
+
+static void __cs5535_gpio_set(struct cs5535_gpio_chip *chip, unsigned offset,
+               unsigned int reg)
+{
+       if (offset < 16)
+               /* low bank register */
+               outl(1 << offset, chip->base + reg);
+       else
+               /* high bank register */
+               errata_outl(chip, 1 << (offset - 16), reg);
+}
+
+void cs5535_gpio_set(unsigned offset, unsigned int reg)
+{
+       struct cs5535_gpio_chip *chip = &cs5535_gpio_chip;
+       unsigned long flags;
+
+       spin_lock_irqsave(&chip->lock, flags);
+       __cs5535_gpio_set(chip, offset, reg);
+       spin_unlock_irqrestore(&chip->lock, flags);
+}
+EXPORT_SYMBOL_GPL(cs5535_gpio_set);
+
+static void __cs5535_gpio_clear(struct cs5535_gpio_chip *chip, unsigned offset,
+               unsigned int reg)
+{
+       if (offset < 16)
+               /* low bank register */
+               outl(1 << (offset + 16), chip->base + reg);
+       else
+               /* high bank register */
+               errata_outl(chip, 1 << offset, reg);
+}
+
+void cs5535_gpio_clear(unsigned offset, unsigned int reg)
+{
+       struct cs5535_gpio_chip *chip = &cs5535_gpio_chip;
+       unsigned long flags;
+
+       spin_lock_irqsave(&chip->lock, flags);
+       __cs5535_gpio_clear(chip, offset, reg);
+       spin_unlock_irqrestore(&chip->lock, flags);
+}
+EXPORT_SYMBOL_GPL(cs5535_gpio_clear);
+
+int cs5535_gpio_isset(unsigned offset, unsigned int reg)
+{
+       struct cs5535_gpio_chip *chip = &cs5535_gpio_chip;
+       unsigned long flags;
+       long val;
+
+       spin_lock_irqsave(&chip->lock, flags);
+       if (offset < 16)
+               /* low bank register */
+               val = inl(chip->base + reg);
+       else {
+               /* high bank register */
+               val = inl(chip->base + 0x80 + reg);
+               offset -= 16;
+       }
+       spin_unlock_irqrestore(&chip->lock, flags);
+
+       return (val & (1 << offset)) ? 1 : 0;
+}
+EXPORT_SYMBOL_GPL(cs5535_gpio_isset);
+
+int cs5535_gpio_set_irq(unsigned group, unsigned irq)
+{
+       uint32_t lo, hi;
+
+       if (group > 7 || irq > 15)
+               return -EINVAL;
+
+       rdmsr(MSR_PIC_ZSEL_HIGH, lo, hi);
+
+       lo &= ~(0xF << (group * 4));
+       lo |= (irq & 0xF) << (group * 4);
+
+       wrmsr(MSR_PIC_ZSEL_HIGH, lo, hi);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(cs5535_gpio_set_irq);
+
+void cs5535_gpio_setup_event(unsigned offset, int pair, int pme)
+{
+       struct cs5535_gpio_chip *chip = &cs5535_gpio_chip;
+       uint32_t shift = (offset % 8) * 4;
+       unsigned long flags;
+       uint32_t val;
+
+       if (offset >= 24)
+               offset = GPIO_MAP_W;
+       else if (offset >= 16)
+               offset = GPIO_MAP_Z;
+       else if (offset >= 8)
+               offset = GPIO_MAP_Y;
+       else
+               offset = GPIO_MAP_X;
+
+       spin_lock_irqsave(&chip->lock, flags);
+       val = inl(chip->base + offset);
+
+       /* Clear whatever was there before */
+       val &= ~(0xF << shift);
+
+       /* Set the new value */
+       val |= ((pair & 7) << shift);
+
+       /* Set the PME bit if this is a PME event */
+       if (pme)
+               val |= (1 << (shift + 3));
+
+       outl(val, chip->base + offset);
+       spin_unlock_irqrestore(&chip->lock, flags);
+}
+EXPORT_SYMBOL_GPL(cs5535_gpio_setup_event);
+
+/*
+ * Generic gpio_chip API support.
+ */
+
+static int chip_gpio_request(struct gpio_chip *c, unsigned offset)
+{
+       struct cs5535_gpio_chip *chip = (struct cs5535_gpio_chip *) c;
+       unsigned long flags;
+
+       spin_lock_irqsave(&chip->lock, flags);
+
+       /* check if this pin is available */
+       if ((mask & (1 << offset)) == 0) {
+               dev_info(&chip->pdev->dev,
+                       "pin %u is not available (check mask)\n", offset);
+               spin_unlock_irqrestore(&chip->lock, flags);
+               return -EINVAL;
+       }
+
+       /* disable output aux 1 & 2 on this pin */
+       __cs5535_gpio_clear(chip, offset, GPIO_OUTPUT_AUX1);
+       __cs5535_gpio_clear(chip, offset, GPIO_OUTPUT_AUX2);
+
+       /* disable input aux 1 on this pin */
+       __cs5535_gpio_clear(chip, offset, GPIO_INPUT_AUX1);
+
+       spin_unlock_irqrestore(&chip->lock, flags);
+
+       return 0;
+}
+
+static int chip_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+       return cs5535_gpio_isset(offset, GPIO_READ_BACK);
+}
+
+static void chip_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
+{
+       if (val)
+               cs5535_gpio_set(offset, GPIO_OUTPUT_VAL);
+       else
+               cs5535_gpio_clear(offset, GPIO_OUTPUT_VAL);
+}
+
+static int chip_direction_input(struct gpio_chip *c, unsigned offset)
+{
+       struct cs5535_gpio_chip *chip = (struct cs5535_gpio_chip *) c;
+       unsigned long flags;
+
+       spin_lock_irqsave(&chip->lock, flags);
+       __cs5535_gpio_set(chip, offset, GPIO_INPUT_ENABLE);
+       __cs5535_gpio_clear(chip, offset, GPIO_OUTPUT_ENABLE);
+       spin_unlock_irqrestore(&chip->lock, flags);
+
+       return 0;
+}
+
+static int chip_direction_output(struct gpio_chip *c, unsigned offset, int val)
+{
+       struct cs5535_gpio_chip *chip = (struct cs5535_gpio_chip *) c;
+       unsigned long flags;
+
+       spin_lock_irqsave(&chip->lock, flags);
+
+       __cs5535_gpio_set(chip, offset, GPIO_INPUT_ENABLE);
+       __cs5535_gpio_set(chip, offset, GPIO_OUTPUT_ENABLE);
+       if (val)
+               __cs5535_gpio_set(chip, offset, GPIO_OUTPUT_VAL);
+       else
+               __cs5535_gpio_clear(chip, offset, GPIO_OUTPUT_VAL);
+
+       spin_unlock_irqrestore(&chip->lock, flags);
+
+       return 0;
+}
+
+static const char * const cs5535_gpio_names[] = {
+       "GPIO0", "GPIO1", "GPIO2", "GPIO3",
+       "GPIO4", "GPIO5", "GPIO6", "GPIO7",
+       "GPIO8", "GPIO9", "GPIO10", "GPIO11",
+       "GPIO12", "GPIO13", "GPIO14", "GPIO15",
+       "GPIO16", "GPIO17", "GPIO18", "GPIO19",
+       "GPIO20", "GPIO21", "GPIO22", NULL,
+       "GPIO24", "GPIO25", "GPIO26", "GPIO27",
+       "GPIO28", NULL, NULL, NULL,
+};
+
+static struct cs5535_gpio_chip cs5535_gpio_chip = {
+       .chip = {
+               .owner = THIS_MODULE,
+               .label = DRV_NAME,
+
+               .base = 0,
+               .ngpio = 32,
+               .names = cs5535_gpio_names,
+               .request = chip_gpio_request,
+
+               .get = chip_gpio_get,
+               .set = chip_gpio_set,
+
+               .direction_input = chip_direction_input,
+               .direction_output = chip_direction_output,
+       },
+};
+
+static int __devinit cs5535_gpio_probe(struct platform_device *pdev)
+{
+       struct resource *res;
+       int err = -EIO;
+       ulong mask_orig = mask;
+
+       /* There are two ways to get the GPIO base address; one is by
+        * fetching it from MSR_LBAR_GPIO, the other is by reading the
+        * PCI BAR info.  The latter method is easier (especially across
+        * different architectures), so we'll stick with that for now.  If
+        * it turns out to be unreliable in the face of crappy BIOSes, we
+        * can always go back to using MSRs.. */
+
+       res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+       if (!res) {
+               dev_err(&pdev->dev, "can't fetch device resource info\n");
+               goto done;
+       }
+
+       if (!request_region(res->start, resource_size(res), pdev->name)) {
+               dev_err(&pdev->dev, "can't request region\n");
+               goto done;
+       }
+
+       /* set up the driver-specific struct */
+       cs5535_gpio_chip.base = res->start;
+       cs5535_gpio_chip.pdev = pdev;
+       spin_lock_init(&cs5535_gpio_chip.lock);
+
+       dev_info(&pdev->dev, "reserved resource region %pR\n", res);
+
+       /* mask out reserved pins */
+       mask &= 0x1F7FFFFF;
+
+       /* do not allow pin 28, Power Button, as there's special handling
+        * in the PMC needed. (note 12, p. 48) */
+       mask &= ~(1 << 28);
+
+       if (mask_orig != mask)
+               dev_info(&pdev->dev, "mask changed from 0x%08lX to 0x%08lX\n",
+                               mask_orig, mask);
+
+       /* finally, register with the generic GPIO API */
+       err = gpiochip_add(&cs5535_gpio_chip.chip);
+       if (err)
+               goto release_region;
+
+       dev_info(&pdev->dev, "GPIO support successfully loaded.\n");
+       return 0;
+
+release_region:
+       release_region(res->start, resource_size(res));
+done:
+       return err;
+}
+
+static int __devexit cs5535_gpio_remove(struct platform_device *pdev)
+{
+       struct resource *r;
+       int err;
+
+       err = gpiochip_remove(&cs5535_gpio_chip.chip);
+       if (err) {
+               /* uhh? */
+               dev_err(&pdev->dev, "unable to remove gpio_chip?\n");
+               return err;
+       }
+
+       r = platform_get_resource(pdev, IORESOURCE_IO, 0);
+       release_region(r->start, resource_size(r));
+       return 0;
+}
+
+static struct platform_driver cs5535_gpio_driver = {
+       .driver = {
+               .name = DRV_NAME,
+               .owner = THIS_MODULE,
+       },
+       .probe = cs5535_gpio_probe,
+       .remove = __devexit_p(cs5535_gpio_remove),
+};
+
+static int __init cs5535_gpio_init(void)
+{
+       return platform_driver_register(&cs5535_gpio_driver);
+}
+
+static void __exit cs5535_gpio_exit(void)
+{
+       platform_driver_unregister(&cs5535_gpio_driver);
+}
+
+module_init(cs5535_gpio_init);
+module_exit(cs5535_gpio_exit);
+
+MODULE_AUTHOR("Andres Salomon <dilinger@queued.net>");
+MODULE_DESCRIPTION("AMD CS5535/CS5536 GPIO driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRV_NAME);
index 415dce37b88c8d732e5826292173d8c88420d61b..c33c9a80e14934250637ecf31914a12b55d71c66 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * linux/arch/arm/mach-ep93xx/gpio.c
- *
  * Generic EP93xx GPIO handling
  *
  * Copyright (c) 2008 Ryan Mallon <ryan@bluewatersys.com>
index d54ca6adb660be5c92a320c829a4361492ef226e..6093a14037c38a0ba0705943e8b5f1c5dce5d44c 100644 (file)
@@ -1,10 +1,9 @@
-/* linux/arch/arm/mach-exynos4/gpiolib.c
+/*
+ * EXYNOS4 - GPIOlib support
  *
  * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
  *             http://www.samsung.com
  *
- * EXYNOS4 - GPIOlib support
- *
  * 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.
diff --git a/drivers/gpio/gpio-generic.c b/drivers/gpio/gpio-generic.c
new file mode 100644 (file)
index 0000000..231714d
--- /dev/null
@@ -0,0 +1,548 @@
+/*
+ * Generic driver for memory-mapped GPIO controllers.
+ *
+ * Copyright 2008 MontaVista Software, Inc.
+ * Copyright 2008,2010 Anton Vorontsov <cbouatmailru@gmail.com>
+ *
+ * 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.
+ *
+ * ....``.```~~~~````.`.`.`.`.```````'',,,.........`````......`.......
+ * ...``                                                         ```````..
+ * ..The simplest form of a GPIO controller that the driver supports is``
+ *  `.just a single "data" register, where GPIO state can be read and/or `
+ *    `,..written. ,,..``~~~~ .....``.`.`.~~.```.`.........``````.```````
+ *        `````````
+                                    ___
+_/~~|___/~|   . ```~~~~~~       ___/___\___     ,~.`.`.`.`````.~~...,,,,...
+__________|~$@~~~        %~    /o*o*o*o*o*o\   .. Implementing such a GPIO .
+o        `                     ~~~~\___/~~~~    ` controller in FPGA is ,.`
+                                                 `....trivial..'~`.```.```
+ *                                                    ```````
+ *  .```````~~~~`..`.``.``.
+ * .  The driver supports  `...       ,..```.`~~~```````````````....````.``,,
+ * .   big-endian notation, just`.  .. A bit more sophisticated controllers ,
+ *  . register the device with -be`. .with a pair of set/clear-bit registers ,
+ *   `.. suffix.  ```~~`````....`.`   . affecting the data register and the .`
+ *     ``.`.``...```                  ```.. output pins are also supported.`
+ *                        ^^             `````.`````````.,``~``~``~~``````
+ *                                                   .                  ^^
+ *   ,..`.`.`...````````````......`.`.`.`.`.`..`.`.`..
+ * .. The expectation is that in at least some cases .    ,-~~~-,
+ *  .this will be used with roll-your-own ASIC/FPGA .`     \   /
+ *  .logic in Verilog or VHDL. ~~~`````````..`````~~`       \ /
+ *  ..````````......```````````                             \o_
+ *                                                           |
+ *                              ^^                          / \
+ *
+ *           ...`````~~`.....``.`..........``````.`.``.```........``.
+ *            `  8, 16, 32 and 64 bits registers are supported, and``.
+ *            . the number of GPIOs is determined by the width of   ~
+ *             .. the registers. ,............```.`.`..`.`.~~~.`.`.`~
+ *               `.......````.```
+ */
+
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/bug.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/compiler.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/log2.h>
+#include <linux/ioport.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/mod_devicetable.h>
+#include <linux/basic_mmio_gpio.h>
+
+static void bgpio_write8(void __iomem *reg, unsigned long data)
+{
+       writeb(data, reg);
+}
+
+static unsigned long bgpio_read8(void __iomem *reg)
+{
+       return readb(reg);
+}
+
+static void bgpio_write16(void __iomem *reg, unsigned long data)
+{
+       writew(data, reg);
+}
+
+static unsigned long bgpio_read16(void __iomem *reg)
+{
+       return readw(reg);
+}
+
+static void bgpio_write32(void __iomem *reg, unsigned long data)
+{
+       writel(data, reg);
+}
+
+static unsigned long bgpio_read32(void __iomem *reg)
+{
+       return readl(reg);
+}
+
+#if BITS_PER_LONG >= 64
+static void bgpio_write64(void __iomem *reg, unsigned long data)
+{
+       writeq(data, reg);
+}
+
+static unsigned long bgpio_read64(void __iomem *reg)
+{
+       return readq(reg);
+}
+#endif /* BITS_PER_LONG >= 64 */
+
+static unsigned long bgpio_pin2mask(struct bgpio_chip *bgc, unsigned int pin)
+{
+       return 1 << pin;
+}
+
+static unsigned long bgpio_pin2mask_be(struct bgpio_chip *bgc,
+                                      unsigned int pin)
+{
+       return 1 << (bgc->bits - 1 - pin);
+}
+
+static int bgpio_get(struct gpio_chip *gc, unsigned int gpio)
+{
+       struct bgpio_chip *bgc = to_bgpio_chip(gc);
+
+       return bgc->read_reg(bgc->reg_dat) & bgc->pin2mask(bgc, gpio);
+}
+
+static void bgpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
+{
+       struct bgpio_chip *bgc = to_bgpio_chip(gc);
+       unsigned long mask = bgc->pin2mask(bgc, gpio);
+       unsigned long flags;
+
+       spin_lock_irqsave(&bgc->lock, flags);
+
+       if (val)
+               bgc->data |= mask;
+       else
+               bgc->data &= ~mask;
+
+       bgc->write_reg(bgc->reg_dat, bgc->data);
+
+       spin_unlock_irqrestore(&bgc->lock, flags);
+}
+
+static void bgpio_set_with_clear(struct gpio_chip *gc, unsigned int gpio,
+                                int val)
+{
+       struct bgpio_chip *bgc = to_bgpio_chip(gc);
+       unsigned long mask = bgc->pin2mask(bgc, gpio);
+
+       if (val)
+               bgc->write_reg(bgc->reg_set, mask);
+       else
+               bgc->write_reg(bgc->reg_clr, mask);
+}
+
+static void bgpio_set_set(struct gpio_chip *gc, unsigned int gpio, int val)
+{
+       struct bgpio_chip *bgc = to_bgpio_chip(gc);
+       unsigned long mask = bgc->pin2mask(bgc, gpio);
+       unsigned long flags;
+
+       spin_lock_irqsave(&bgc->lock, flags);
+
+       if (val)
+               bgc->data |= mask;
+       else
+               bgc->data &= ~mask;
+
+       bgc->write_reg(bgc->reg_set, bgc->data);
+
+       spin_unlock_irqrestore(&bgc->lock, flags);
+}
+
+static int bgpio_simple_dir_in(struct gpio_chip *gc, unsigned int gpio)
+{
+       return 0;
+}
+
+static int bgpio_simple_dir_out(struct gpio_chip *gc, unsigned int gpio,
+                               int val)
+{
+       gc->set(gc, gpio, val);
+
+       return 0;
+}
+
+static int bgpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
+{
+       struct bgpio_chip *bgc = to_bgpio_chip(gc);
+       unsigned long flags;
+
+       spin_lock_irqsave(&bgc->lock, flags);
+
+       bgc->dir &= ~bgc->pin2mask(bgc, gpio);
+       bgc->write_reg(bgc->reg_dir, bgc->dir);
+
+       spin_unlock_irqrestore(&bgc->lock, flags);
+
+       return 0;
+}
+
+static int bgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
+{
+       struct bgpio_chip *bgc = to_bgpio_chip(gc);
+       unsigned long flags;
+
+       gc->set(gc, gpio, val);
+
+       spin_lock_irqsave(&bgc->lock, flags);
+
+       bgc->dir |= bgc->pin2mask(bgc, gpio);
+       bgc->write_reg(bgc->reg_dir, bgc->dir);
+
+       spin_unlock_irqrestore(&bgc->lock, flags);
+
+       return 0;
+}
+
+static int bgpio_dir_in_inv(struct gpio_chip *gc, unsigned int gpio)
+{
+       struct bgpio_chip *bgc = to_bgpio_chip(gc);
+       unsigned long flags;
+
+       spin_lock_irqsave(&bgc->lock, flags);
+
+       bgc->dir |= bgc->pin2mask(bgc, gpio);
+       bgc->write_reg(bgc->reg_dir, bgc->dir);
+
+       spin_unlock_irqrestore(&bgc->lock, flags);
+
+       return 0;
+}
+
+static int bgpio_dir_out_inv(struct gpio_chip *gc, unsigned int gpio, int val)
+{
+       struct bgpio_chip *bgc = to_bgpio_chip(gc);
+       unsigned long flags;
+
+       gc->set(gc, gpio, val);
+
+       spin_lock_irqsave(&bgc->lock, flags);
+
+       bgc->dir &= ~bgc->pin2mask(bgc, gpio);
+       bgc->write_reg(bgc->reg_dir, bgc->dir);
+
+       spin_unlock_irqrestore(&bgc->lock, flags);
+
+       return 0;
+}
+
+static int bgpio_setup_accessors(struct device *dev,
+                                struct bgpio_chip *bgc,
+                                bool be)
+{
+
+       switch (bgc->bits) {
+       case 8:
+               bgc->read_reg   = bgpio_read8;
+               bgc->write_reg  = bgpio_write8;
+               break;
+       case 16:
+               bgc->read_reg   = bgpio_read16;
+               bgc->write_reg  = bgpio_write16;
+               break;
+       case 32:
+               bgc->read_reg   = bgpio_read32;
+               bgc->write_reg  = bgpio_write32;
+               break;
+#if BITS_PER_LONG >= 64
+       case 64:
+               bgc->read_reg   = bgpio_read64;
+               bgc->write_reg  = bgpio_write64;
+               break;
+#endif /* BITS_PER_LONG >= 64 */
+       default:
+               dev_err(dev, "unsupported data width %u bits\n", bgc->bits);
+               return -EINVAL;
+       }
+
+       bgc->pin2mask = be ? bgpio_pin2mask_be : bgpio_pin2mask;
+
+       return 0;
+}
+
+/*
+ * Create the device and allocate the resources.  For setting GPIO's there are
+ * three supported configurations:
+ *
+ *     - single input/output register resource (named "dat").
+ *     - set/clear pair (named "set" and "clr").
+ *     - single output register resource and single input resource ("set" and
+ *     dat").
+ *
+ * For the single output register, this drives a 1 by setting a bit and a zero
+ * by clearing a bit.  For the set clr pair, this drives a 1 by setting a bit
+ * in the set register and clears it by setting a bit in the clear register.
+ * The configuration is detected by which resources are present.
+ *
+ * For setting the GPIO direction, there are three supported configurations:
+ *
+ *     - simple bidirection GPIO that requires no configuration.
+ *     - an output direction register (named "dirout") where a 1 bit
+ *     indicates the GPIO is an output.
+ *     - an input direction register (named "dirin") where a 1 bit indicates
+ *     the GPIO is an input.
+ */
+static int bgpio_setup_io(struct bgpio_chip *bgc,
+                         void __iomem *dat,
+                         void __iomem *set,
+                         void __iomem *clr)
+{
+
+       bgc->reg_dat = dat;
+       if (!bgc->reg_dat)
+               return -EINVAL;
+
+       if (set && clr) {
+               bgc->reg_set = set;
+               bgc->reg_clr = clr;
+               bgc->gc.set = bgpio_set_with_clear;
+       } else if (set && !clr) {
+               bgc->reg_set = set;
+               bgc->gc.set = bgpio_set_set;
+       } else {
+               bgc->gc.set = bgpio_set;
+       }
+
+       bgc->gc.get = bgpio_get;
+
+       return 0;
+}
+
+static int bgpio_setup_direction(struct bgpio_chip *bgc,
+                                void __iomem *dirout,
+                                void __iomem *dirin)
+{
+       if (dirout && dirin) {
+               return -EINVAL;
+       } else if (dirout) {
+               bgc->reg_dir = dirout;
+               bgc->gc.direction_output = bgpio_dir_out;
+               bgc->gc.direction_input = bgpio_dir_in;
+       } else if (dirin) {
+               bgc->reg_dir = dirin;
+               bgc->gc.direction_output = bgpio_dir_out_inv;
+               bgc->gc.direction_input = bgpio_dir_in_inv;
+       } else {
+               bgc->gc.direction_output = bgpio_simple_dir_out;
+               bgc->gc.direction_input = bgpio_simple_dir_in;
+       }
+
+       return 0;
+}
+
+int __devexit bgpio_remove(struct bgpio_chip *bgc)
+{
+       int err = gpiochip_remove(&bgc->gc);
+
+       kfree(bgc);
+
+       return err;
+}
+EXPORT_SYMBOL_GPL(bgpio_remove);
+
+int __devinit bgpio_init(struct bgpio_chip *bgc,
+                        struct device *dev,
+                        unsigned long sz,
+                        void __iomem *dat,
+                        void __iomem *set,
+                        void __iomem *clr,
+                        void __iomem *dirout,
+                        void __iomem *dirin,
+                        bool big_endian)
+{
+       int ret;
+
+       if (!is_power_of_2(sz))
+               return -EINVAL;
+
+       bgc->bits = sz * 8;
+       if (bgc->bits > BITS_PER_LONG)
+               return -EINVAL;
+
+       spin_lock_init(&bgc->lock);
+       bgc->gc.dev = dev;
+       bgc->gc.label = dev_name(dev);
+       bgc->gc.base = -1;
+       bgc->gc.ngpio = bgc->bits;
+
+       ret = bgpio_setup_io(bgc, dat, set, clr);
+       if (ret)
+               return ret;
+
+       ret = bgpio_setup_accessors(dev, bgc, big_endian);
+       if (ret)
+               return ret;
+
+       ret = bgpio_setup_direction(bgc, dirout, dirin);
+       if (ret)
+               return ret;
+
+       bgc->data = bgc->read_reg(bgc->reg_dat);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(bgpio_init);
+
+#ifdef CONFIG_GPIO_GENERIC_PLATFORM
+
+static void __iomem *bgpio_map(struct platform_device *pdev,
+                              const char *name,
+                              resource_size_t sane_sz,
+                              int *err)
+{
+       struct device *dev = &pdev->dev;
+       struct resource *r;
+       resource_size_t start;
+       resource_size_t sz;
+       void __iomem *ret;
+
+       *err = 0;
+
+       r = platform_get_resource_byname(pdev, IORESOURCE_MEM, name);
+       if (!r)
+               return NULL;
+
+       sz = resource_size(r);
+       if (sz != sane_sz) {
+               *err = -EINVAL;
+               return NULL;
+       }
+
+       start = r->start;
+       if (!devm_request_mem_region(dev, start, sz, r->name)) {
+               *err = -EBUSY;
+               return NULL;
+       }
+
+       ret = devm_ioremap(dev, start, sz);
+       if (!ret) {
+               *err = -ENOMEM;
+               return NULL;
+       }
+
+       return ret;
+}
+
+static int __devinit bgpio_pdev_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct resource *r;
+       void __iomem *dat;
+       void __iomem *set;
+       void __iomem *clr;
+       void __iomem *dirout;
+       void __iomem *dirin;
+       unsigned long sz;
+       bool be;
+       int err;
+       struct bgpio_chip *bgc;
+       struct bgpio_pdata *pdata = dev_get_platdata(dev);
+
+       r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dat");
+       if (!r)
+               return -EINVAL;
+
+       sz = resource_size(r);
+
+       dat = bgpio_map(pdev, "dat", sz, &err);
+       if (!dat)
+               return err ? err : -EINVAL;
+
+       set = bgpio_map(pdev, "set", sz, &err);
+       if (err)
+               return err;
+
+       clr = bgpio_map(pdev, "clr", sz, &err);
+       if (err)
+               return err;
+
+       dirout = bgpio_map(pdev, "dirout", sz, &err);
+       if (err)
+               return err;
+
+       dirin = bgpio_map(pdev, "dirin", sz, &err);
+       if (err)
+               return err;
+
+       be = !strcmp(platform_get_device_id(pdev)->name, "basic-mmio-gpio-be");
+
+       bgc = devm_kzalloc(&pdev->dev, sizeof(*bgc), GFP_KERNEL);
+       if (!bgc)
+               return -ENOMEM;
+
+       err = bgpio_init(bgc, dev, sz, dat, set, clr, dirout, dirin, be);
+       if (err)
+               return err;
+
+       if (pdata) {
+               bgc->gc.base = pdata->base;
+               if (pdata->ngpio > 0)
+                       bgc->gc.ngpio = pdata->ngpio;
+       }
+
+       platform_set_drvdata(pdev, bgc);
+
+       return gpiochip_add(&bgc->gc);
+}
+
+static int __devexit bgpio_pdev_remove(struct platform_device *pdev)
+{
+       struct bgpio_chip *bgc = platform_get_drvdata(pdev);
+
+       return bgpio_remove(bgc);
+}
+
+static const struct platform_device_id bgpio_id_table[] = {
+       { "basic-mmio-gpio", },
+       { "basic-mmio-gpio-be", },
+       {},
+};
+MODULE_DEVICE_TABLE(platform, bgpio_id_table);
+
+static struct platform_driver bgpio_driver = {
+       .driver = {
+               .name = "basic-mmio-gpio",
+       },
+       .id_table = bgpio_id_table,
+       .probe = bgpio_pdev_probe,
+       .remove = __devexit_p(bgpio_pdev_remove),
+};
+
+static int __init bgpio_platform_init(void)
+{
+       return platform_driver_register(&bgpio_driver);
+}
+module_init(bgpio_platform_init);
+
+static void __exit bgpio_platform_exit(void)
+{
+       platform_driver_unregister(&bgpio_driver);
+}
+module_exit(bgpio_platform_exit);
+
+#endif /* CONFIG_GPIO_GENERIC_PLATFORM */
+
+MODULE_DESCRIPTION("Driver for basic memory-mapped GPIO controllers");
+MODULE_AUTHOR("Anton Vorontsov <cbouatmailru@gmail.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/gpio-it8761e.c b/drivers/gpio/gpio-it8761e.c
new file mode 100644 (file)
index 0000000..278b813
--- /dev/null
@@ -0,0 +1,234 @@
+/*
+ *  GPIO interface for IT8761E Super I/O chip
+ *
+ *  Author: Denis Turischev <denis@compulab.co.il>
+ *
+ *  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.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; see the file COPYING.  If not, write to
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+
+#include <linux/gpio.h>
+
+#define SIO_CHIP_ID            0x8761
+#define CHIP_ID_HIGH_BYTE      0x20
+#define CHIP_ID_LOW_BYTE       0x21
+
+static u8 ports[2] = { 0x2e, 0x4e };
+static u8 port;
+
+static DEFINE_SPINLOCK(sio_lock);
+
+#define GPIO_NAME              "it8761-gpio"
+#define GPIO_BA_HIGH_BYTE      0x60
+#define GPIO_BA_LOW_BYTE       0x61
+#define GPIO_IOSIZE            4
+#define GPIO1X_IO              0xf0
+#define GPIO2X_IO              0xf1
+
+static u16 gpio_ba;
+
+static u8 read_reg(u8 addr, u8 port)
+{
+       outb(addr, port);
+       return inb(port + 1);
+}
+
+static void write_reg(u8 data, u8 addr, u8 port)
+{
+       outb(addr, port);
+       outb(data, port + 1);
+}
+
+static void enter_conf_mode(u8 port)
+{
+       outb(0x87, port);
+       outb(0x61, port);
+       outb(0x55, port);
+       outb((port == 0x2e) ? 0x55 : 0xaa, port);
+}
+
+static void exit_conf_mode(u8 port)
+{
+       outb(0x2, port);
+       outb(0x2, port + 1);
+}
+
+static void enter_gpio_mode(u8 port)
+{
+       write_reg(0x2, 0x7, port);
+}
+
+static int it8761e_gpio_get(struct gpio_chip *gc, unsigned gpio_num)
+{
+       u16 reg;
+       u8 bit;
+
+       bit = gpio_num % 8;
+       reg = (gpio_num >= 8) ? gpio_ba + 1 : gpio_ba;
+
+       return !!(inb(reg) & (1 << bit));
+}
+
+static int it8761e_gpio_direction_in(struct gpio_chip *gc, unsigned gpio_num)
+{
+       u8 curr_dirs;
+       u8 io_reg, bit;
+
+       bit = gpio_num % 8;
+       io_reg = (gpio_num >= 8) ? GPIO2X_IO : GPIO1X_IO;
+
+       spin_lock(&sio_lock);
+
+       enter_conf_mode(port);
+       enter_gpio_mode(port);
+
+       curr_dirs = read_reg(io_reg, port);
+
+       if (curr_dirs & (1 << bit))
+               write_reg(curr_dirs & ~(1 << bit), io_reg, port);
+
+       exit_conf_mode(port);
+
+       spin_unlock(&sio_lock);
+       return 0;
+}
+
+static void it8761e_gpio_set(struct gpio_chip *gc,
+                               unsigned gpio_num, int val)
+{
+       u8 curr_vals, bit;
+       u16 reg;
+
+       bit = gpio_num % 8;
+       reg = (gpio_num >= 8) ? gpio_ba + 1 : gpio_ba;
+
+       spin_lock(&sio_lock);
+
+       curr_vals = inb(reg);
+       if (val)
+               outb(curr_vals | (1 << bit) , reg);
+       else
+               outb(curr_vals & ~(1 << bit), reg);
+
+       spin_unlock(&sio_lock);
+}
+
+static int it8761e_gpio_direction_out(struct gpio_chip *gc,
+                                       unsigned gpio_num, int val)
+{
+       u8 curr_dirs, io_reg, bit;
+
+       bit = gpio_num % 8;
+       io_reg = (gpio_num >= 8) ? GPIO2X_IO : GPIO1X_IO;
+
+       it8761e_gpio_set(gc, gpio_num, val);
+
+       spin_lock(&sio_lock);
+
+       enter_conf_mode(port);
+       enter_gpio_mode(port);
+
+       curr_dirs = read_reg(io_reg, port);
+
+       if (!(curr_dirs & (1 << bit)))
+               write_reg(curr_dirs | (1 << bit), io_reg, port);
+
+       exit_conf_mode(port);
+
+       spin_unlock(&sio_lock);
+       return 0;
+}
+
+static struct gpio_chip it8761e_gpio_chip = {
+       .label                  = GPIO_NAME,
+       .owner                  = THIS_MODULE,
+       .get                    = it8761e_gpio_get,
+       .direction_input        = it8761e_gpio_direction_in,
+       .set                    = it8761e_gpio_set,
+       .direction_output       = it8761e_gpio_direction_out,
+};
+
+static int __init it8761e_gpio_init(void)
+{
+       int i, id, err;
+
+       /* chip and port detection */
+       for (i = 0; i < ARRAY_SIZE(ports); i++) {
+               spin_lock(&sio_lock);
+               enter_conf_mode(ports[i]);
+
+               id = (read_reg(CHIP_ID_HIGH_BYTE, ports[i]) << 8) +
+                               read_reg(CHIP_ID_LOW_BYTE, ports[i]);
+
+               exit_conf_mode(ports[i]);
+               spin_unlock(&sio_lock);
+
+               if (id == SIO_CHIP_ID) {
+                       port = ports[i];
+                       break;
+               }
+       }
+
+       if (!port)
+               return -ENODEV;
+
+       /* fetch GPIO base address */
+       enter_conf_mode(port);
+       enter_gpio_mode(port);
+       gpio_ba = (read_reg(GPIO_BA_HIGH_BYTE, port) << 8) +
+                               read_reg(GPIO_BA_LOW_BYTE, port);
+       exit_conf_mode(port);
+
+       if (!request_region(gpio_ba, GPIO_IOSIZE, GPIO_NAME))
+               return -EBUSY;
+
+       it8761e_gpio_chip.base = -1;
+       it8761e_gpio_chip.ngpio = 16;
+
+       err = gpiochip_add(&it8761e_gpio_chip);
+       if (err < 0)
+               goto gpiochip_add_err;
+
+       return 0;
+
+gpiochip_add_err:
+       release_region(gpio_ba, GPIO_IOSIZE);
+       gpio_ba = 0;
+       return err;
+}
+
+static void __exit it8761e_gpio_exit(void)
+{
+       if (gpio_ba) {
+               int ret = gpiochip_remove(&it8761e_gpio_chip);
+
+               WARN(ret, "%s(): gpiochip_remove() failed, ret=%d\n",
+                               __func__, ret);
+
+               release_region(gpio_ba, GPIO_IOSIZE);
+               gpio_ba = 0;
+       }
+}
+module_init(it8761e_gpio_init);
+module_exit(it8761e_gpio_exit);
+
+MODULE_AUTHOR("Denis Turischev <denis@compulab.co.il>");
+MODULE_DESCRIPTION("GPIO interface for IT8761E Super I/O chip");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/gpio-janz-ttl.c b/drivers/gpio/gpio-janz-ttl.c
new file mode 100644 (file)
index 0000000..813ac07
--- /dev/null
@@ -0,0 +1,258 @@
+/*
+ * Janz MODULbus VMOD-TTL GPIO Driver
+ *
+ * Copyright (c) 2010 Ira W. Snyder <iws@ovro.caltech.edu>
+ *
+ * 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/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/slab.h>
+
+#include <linux/mfd/janz.h>
+
+#define DRV_NAME "janz-ttl"
+
+#define PORTA_DIRECTION                0x23
+#define PORTB_DIRECTION                0x2B
+#define PORTC_DIRECTION                0x06
+#define PORTA_IOCTL            0x24
+#define PORTB_IOCTL            0x2C
+#define PORTC_IOCTL            0x07
+
+#define MASTER_INT_CTL         0x00
+#define MASTER_CONF_CTL                0x01
+
+#define CONF_PAE               (1 << 2)
+#define CONF_PBE               (1 << 7)
+#define CONF_PCE               (1 << 4)
+
+struct ttl_control_regs {
+       __be16 portc;
+       __be16 portb;
+       __be16 porta;
+       __be16 control;
+};
+
+struct ttl_module {
+       struct gpio_chip gpio;
+
+       /* base address of registers */
+       struct ttl_control_regs __iomem *regs;
+
+       u8 portc_shadow;
+       u8 portb_shadow;
+       u8 porta_shadow;
+
+       spinlock_t lock;
+};
+
+static int ttl_get_value(struct gpio_chip *gpio, unsigned offset)
+{
+       struct ttl_module *mod = dev_get_drvdata(gpio->dev);
+       u8 *shadow;
+       int ret;
+
+       if (offset < 8) {
+               shadow = &mod->porta_shadow;
+       } else if (offset < 16) {
+               shadow = &mod->portb_shadow;
+               offset -= 8;
+       } else {
+               shadow = &mod->portc_shadow;
+               offset -= 16;
+       }
+
+       spin_lock(&mod->lock);
+       ret = *shadow & (1 << offset);
+       spin_unlock(&mod->lock);
+       return ret;
+}
+
+static void ttl_set_value(struct gpio_chip *gpio, unsigned offset, int value)
+{
+       struct ttl_module *mod = dev_get_drvdata(gpio->dev);
+       void __iomem *port;
+       u8 *shadow;
+
+       if (offset < 8) {
+               port = &mod->regs->porta;
+               shadow = &mod->porta_shadow;
+       } else if (offset < 16) {
+               port = &mod->regs->portb;
+               shadow = &mod->portb_shadow;
+               offset -= 8;
+       } else {
+               port = &mod->regs->portc;
+               shadow = &mod->portc_shadow;
+               offset -= 16;
+       }
+
+       spin_lock(&mod->lock);
+       if (value)
+               *shadow |= (1 << offset);
+       else
+               *shadow &= ~(1 << offset);
+
+       iowrite16be(*shadow, port);
+       spin_unlock(&mod->lock);
+}
+
+static void __devinit ttl_write_reg(struct ttl_module *mod, u8 reg, u16 val)
+{
+       iowrite16be(reg, &mod->regs->control);
+       iowrite16be(val, &mod->regs->control);
+}
+
+static void __devinit ttl_setup_device(struct ttl_module *mod)
+{
+       /* reset the device to a known state */
+       iowrite16be(0x0000, &mod->regs->control);
+       iowrite16be(0x0001, &mod->regs->control);
+       iowrite16be(0x0000, &mod->regs->control);
+
+       /* put all ports in open-drain mode */
+       ttl_write_reg(mod, PORTA_IOCTL, 0x00ff);
+       ttl_write_reg(mod, PORTB_IOCTL, 0x00ff);
+       ttl_write_reg(mod, PORTC_IOCTL, 0x000f);
+
+       /* set all ports as outputs */
+       ttl_write_reg(mod, PORTA_DIRECTION, 0x0000);
+       ttl_write_reg(mod, PORTB_DIRECTION, 0x0000);
+       ttl_write_reg(mod, PORTC_DIRECTION, 0x0000);
+
+       /* set all ports to drive zeroes */
+       iowrite16be(0x0000, &mod->regs->porta);
+       iowrite16be(0x0000, &mod->regs->portb);
+       iowrite16be(0x0000, &mod->regs->portc);
+
+       /* enable all ports */
+       ttl_write_reg(mod, MASTER_CONF_CTL, CONF_PAE | CONF_PBE | CONF_PCE);
+}
+
+static int __devinit ttl_probe(struct platform_device *pdev)
+{
+       struct janz_platform_data *pdata;
+       struct device *dev = &pdev->dev;
+       struct ttl_module *mod;
+       struct gpio_chip *gpio;
+       struct resource *res;
+       int ret;
+
+       pdata = pdev->dev.platform_data;
+       if (!pdata) {
+               dev_err(dev, "no platform data\n");
+               ret = -ENXIO;
+               goto out_return;
+       }
+
+       mod = kzalloc(sizeof(*mod), GFP_KERNEL);
+       if (!mod) {
+               dev_err(dev, "unable to allocate private data\n");
+               ret = -ENOMEM;
+               goto out_return;
+       }
+
+       platform_set_drvdata(pdev, mod);
+       spin_lock_init(&mod->lock);
+
+       /* get access to the MODULbus registers for this module */
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res) {
+               dev_err(dev, "MODULbus registers not found\n");
+               ret = -ENODEV;
+               goto out_free_mod;
+       }
+
+       mod->regs = ioremap(res->start, resource_size(res));
+       if (!mod->regs) {
+               dev_err(dev, "MODULbus registers not ioremap\n");
+               ret = -ENOMEM;
+               goto out_free_mod;
+       }
+
+       ttl_setup_device(mod);
+
+       /* Initialize the GPIO data structures */
+       gpio = &mod->gpio;
+       gpio->dev = &pdev->dev;
+       gpio->label = pdev->name;
+       gpio->get = ttl_get_value;
+       gpio->set = ttl_set_value;
+       gpio->owner = THIS_MODULE;
+
+       /* request dynamic allocation */
+       gpio->base = -1;
+       gpio->ngpio = 20;
+
+       ret = gpiochip_add(gpio);
+       if (ret) {
+               dev_err(dev, "unable to add GPIO chip\n");
+               goto out_iounmap_regs;
+       }
+
+       dev_info(&pdev->dev, "module %d: registered GPIO device\n",
+                            pdata->modno);
+       return 0;
+
+out_iounmap_regs:
+       iounmap(mod->regs);
+out_free_mod:
+       kfree(mod);
+out_return:
+       return ret;
+}
+
+static int __devexit ttl_remove(struct platform_device *pdev)
+{
+       struct ttl_module *mod = platform_get_drvdata(pdev);
+       struct device *dev = &pdev->dev;
+       int ret;
+
+       ret = gpiochip_remove(&mod->gpio);
+       if (ret) {
+               dev_err(dev, "unable to remove GPIO chip\n");
+               return ret;
+       }
+
+       iounmap(mod->regs);
+       kfree(mod);
+       return 0;
+}
+
+static struct platform_driver ttl_driver = {
+       .driver         = {
+               .name   = DRV_NAME,
+               .owner  = THIS_MODULE,
+       },
+       .probe          = ttl_probe,
+       .remove         = __devexit_p(ttl_remove),
+};
+
+static int __init ttl_init(void)
+{
+       return platform_driver_register(&ttl_driver);
+}
+
+static void __exit ttl_exit(void)
+{
+       platform_driver_unregister(&ttl_driver);
+}
+
+MODULE_AUTHOR("Ira W. Snyder <iws@ovro.caltech.edu>");
+MODULE_DESCRIPTION("Janz MODULbus VMOD-TTL Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:janz-ttl");
+
+module_init(ttl_init);
+module_exit(ttl_exit);
diff --git a/drivers/gpio/gpio-langwell.c b/drivers/gpio/gpio-langwell.c
new file mode 100644 (file)
index 0000000..e7a7ea7
--- /dev/null
@@ -0,0 +1,458 @@
+/*
+ * Moorestown platform Langwell chip GPIO driver
+ *
+ * Copyright (c) 2008 - 2009,  Intel Corporation.
+ *
+ * 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.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* Supports:
+ * Moorestown platform Langwell chip.
+ * Medfield platform Penwell chip.
+ * Whitney point.
+ */
+
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/platform_device.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/stddef.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/slab.h>
+#include <linux/pm_runtime.h>
+
+/*
+ * Langwell chip has 64 pins and thus there are 2 32bit registers to control
+ * each feature, while Penwell chip has 96 pins for each block, and need 3 32bit
+ * registers to control them, so we only define the order here instead of a
+ * structure, to get a bit offset for a pin (use GPDR as an example):
+ *
+ * nreg = ngpio / 32;
+ * reg = offset / 32;
+ * bit = offset % 32;
+ * reg_addr = reg_base + GPDR * nreg * 4 + reg * 4;
+ *
+ * so the bit of reg_addr is to control pin offset's GPDR feature
+*/
+
+enum GPIO_REG {
+       GPLR = 0,       /* pin level read-only */
+       GPDR,           /* pin direction */
+       GPSR,           /* pin set */
+       GPCR,           /* pin clear */
+       GRER,           /* rising edge detect */
+       GFER,           /* falling edge detect */
+       GEDR,           /* edge detect result */
+};
+
+struct lnw_gpio {
+       struct gpio_chip                chip;
+       void                            *reg_base;
+       spinlock_t                      lock;
+       unsigned                        irq_base;
+       struct pci_dev                  *pdev;
+};
+
+static void __iomem *gpio_reg(struct gpio_chip *chip, unsigned offset,
+                       enum GPIO_REG reg_type)
+{
+       struct lnw_gpio *lnw = container_of(chip, struct lnw_gpio, chip);
+       unsigned nreg = chip->ngpio / 32;
+       u8 reg = offset / 32;
+       void __iomem *ptr;
+
+       ptr = (void __iomem *)(lnw->reg_base + reg_type * nreg * 4 + reg * 4);
+       return ptr;
+}
+
+static int lnw_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+       void __iomem *gplr = gpio_reg(chip, offset, GPLR);
+
+       return readl(gplr) & BIT(offset % 32);
+}
+
+static void lnw_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+       void __iomem *gpsr, *gpcr;
+
+       if (value) {
+               gpsr = gpio_reg(chip, offset, GPSR);
+               writel(BIT(offset % 32), gpsr);
+       } else {
+               gpcr = gpio_reg(chip, offset, GPCR);
+               writel(BIT(offset % 32), gpcr);
+       }
+}
+
+static int lnw_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+       struct lnw_gpio *lnw = container_of(chip, struct lnw_gpio, chip);
+       void __iomem *gpdr = gpio_reg(chip, offset, GPDR);
+       u32 value;
+       unsigned long flags;
+
+       if (lnw->pdev)
+               pm_runtime_get(&lnw->pdev->dev);
+
+       spin_lock_irqsave(&lnw->lock, flags);
+       value = readl(gpdr);
+       value &= ~BIT(offset % 32);
+       writel(value, gpdr);
+       spin_unlock_irqrestore(&lnw->lock, flags);
+
+       if (lnw->pdev)
+               pm_runtime_put(&lnw->pdev->dev);
+
+       return 0;
+}
+
+static int lnw_gpio_direction_output(struct gpio_chip *chip,
+                       unsigned offset, int value)
+{
+       struct lnw_gpio *lnw = container_of(chip, struct lnw_gpio, chip);
+       void __iomem *gpdr = gpio_reg(chip, offset, GPDR);
+       unsigned long flags;
+
+       lnw_gpio_set(chip, offset, value);
+
+       if (lnw->pdev)
+               pm_runtime_get(&lnw->pdev->dev);
+
+       spin_lock_irqsave(&lnw->lock, flags);
+       value = readl(gpdr);
+       value |= BIT(offset % 32);
+       writel(value, gpdr);
+       spin_unlock_irqrestore(&lnw->lock, flags);
+
+       if (lnw->pdev)
+               pm_runtime_put(&lnw->pdev->dev);
+
+       return 0;
+}
+
+static int lnw_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+       struct lnw_gpio *lnw = container_of(chip, struct lnw_gpio, chip);
+       return lnw->irq_base + offset;
+}
+
+static int lnw_irq_type(struct irq_data *d, unsigned type)
+{
+       struct lnw_gpio *lnw = irq_data_get_irq_chip_data(d);
+       u32 gpio = d->irq - lnw->irq_base;
+       unsigned long flags;
+       u32 value;
+       void __iomem *grer = gpio_reg(&lnw->chip, gpio, GRER);
+       void __iomem *gfer = gpio_reg(&lnw->chip, gpio, GFER);
+
+       if (gpio >= lnw->chip.ngpio)
+               return -EINVAL;
+
+       if (lnw->pdev)
+               pm_runtime_get(&lnw->pdev->dev);
+
+       spin_lock_irqsave(&lnw->lock, flags);
+       if (type & IRQ_TYPE_EDGE_RISING)
+               value = readl(grer) | BIT(gpio % 32);
+       else
+               value = readl(grer) & (~BIT(gpio % 32));
+       writel(value, grer);
+
+       if (type & IRQ_TYPE_EDGE_FALLING)
+               value = readl(gfer) | BIT(gpio % 32);
+       else
+               value = readl(gfer) & (~BIT(gpio % 32));
+       writel(value, gfer);
+       spin_unlock_irqrestore(&lnw->lock, flags);
+
+       if (lnw->pdev)
+               pm_runtime_put(&lnw->pdev->dev);
+
+       return 0;
+}
+
+static void lnw_irq_unmask(struct irq_data *d)
+{
+}
+
+static void lnw_irq_mask(struct irq_data *d)
+{
+}
+
+static struct irq_chip lnw_irqchip = {
+       .name           = "LNW-GPIO",
+       .irq_mask       = lnw_irq_mask,
+       .irq_unmask     = lnw_irq_unmask,
+       .irq_set_type   = lnw_irq_type,
+};
+
+static DEFINE_PCI_DEVICE_TABLE(lnw_gpio_ids) = {   /* pin number */
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x080f), .driver_data = 64 },
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081f), .driver_data = 96 },
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081a), .driver_data = 96 },
+       { 0, }
+};
+MODULE_DEVICE_TABLE(pci, lnw_gpio_ids);
+
+static void lnw_irq_handler(unsigned irq, struct irq_desc *desc)
+{
+       struct irq_data *data = irq_desc_get_irq_data(desc);
+       struct lnw_gpio *lnw = irq_data_get_irq_handler_data(data);
+       struct irq_chip *chip = irq_data_get_irq_chip(data);
+       u32 base, gpio, mask;
+       unsigned long pending;
+       void __iomem *gedr;
+
+       /* check GPIO controller to check which pin triggered the interrupt */
+       for (base = 0; base < lnw->chip.ngpio; base += 32) {
+               gedr = gpio_reg(&lnw->chip, base, GEDR);
+               pending = readl(gedr);
+               while (pending) {
+                       gpio = __ffs(pending) - 1;
+                       mask = BIT(gpio);
+                       pending &= ~mask;
+                       /* Clear before handling so we can't lose an edge */
+                       writel(mask, gedr);
+                       generic_handle_irq(lnw->irq_base + base + gpio);
+               }
+       }
+
+       chip->irq_eoi(data);
+}
+
+#ifdef CONFIG_PM
+static int lnw_gpio_runtime_resume(struct device *dev)
+{
+       return 0;
+}
+
+static int lnw_gpio_runtime_suspend(struct device *dev)
+{
+       return 0;
+}
+
+static int lnw_gpio_runtime_idle(struct device *dev)
+{
+       int err = pm_schedule_suspend(dev, 500);
+
+       if (!err)
+               return 0;
+
+       return -EBUSY;
+}
+
+#else
+#define lnw_gpio_runtime_suspend       NULL
+#define lnw_gpio_runtime_resume                NULL
+#define lnw_gpio_runtime_idle          NULL
+#endif
+
+static const struct dev_pm_ops lnw_gpio_pm_ops = {
+       .runtime_suspend = lnw_gpio_runtime_suspend,
+       .runtime_resume = lnw_gpio_runtime_resume,
+       .runtime_idle = lnw_gpio_runtime_idle,
+};
+
+static int __devinit lnw_gpio_probe(struct pci_dev *pdev,
+                       const struct pci_device_id *id)
+{
+       void *base;
+       int i;
+       resource_size_t start, len;
+       struct lnw_gpio *lnw;
+       u32 irq_base;
+       u32 gpio_base;
+       int retval = 0;
+
+       retval = pci_enable_device(pdev);
+       if (retval)
+               goto done;
+
+       retval = pci_request_regions(pdev, "langwell_gpio");
+       if (retval) {
+               dev_err(&pdev->dev, "error requesting resources\n");
+               goto err2;
+       }
+       /* get the irq_base from bar1 */
+       start = pci_resource_start(pdev, 1);
+       len = pci_resource_len(pdev, 1);
+       base = ioremap_nocache(start, len);
+       if (!base) {
+               dev_err(&pdev->dev, "error mapping bar1\n");
+               goto err3;
+       }
+       irq_base = *(u32 *)base;
+       gpio_base = *((u32 *)base + 1);
+       /* release the IO mapping, since we already get the info from bar1 */
+       iounmap(base);
+       /* get the register base from bar0 */
+       start = pci_resource_start(pdev, 0);
+       len = pci_resource_len(pdev, 0);
+       base = ioremap_nocache(start, len);
+       if (!base) {
+               dev_err(&pdev->dev, "error mapping bar0\n");
+               retval = -EFAULT;
+               goto err3;
+       }
+
+       lnw = kzalloc(sizeof(struct lnw_gpio), GFP_KERNEL);
+       if (!lnw) {
+               dev_err(&pdev->dev, "can't allocate langwell_gpio chip data\n");
+               retval = -ENOMEM;
+               goto err4;
+       }
+       lnw->reg_base = base;
+       lnw->irq_base = irq_base;
+       lnw->chip.label = dev_name(&pdev->dev);
+       lnw->chip.direction_input = lnw_gpio_direction_input;
+       lnw->chip.direction_output = lnw_gpio_direction_output;
+       lnw->chip.get = lnw_gpio_get;
+       lnw->chip.set = lnw_gpio_set;
+       lnw->chip.to_irq = lnw_gpio_to_irq;
+       lnw->chip.base = gpio_base;
+       lnw->chip.ngpio = id->driver_data;
+       lnw->chip.can_sleep = 0;
+       lnw->pdev = pdev;
+       pci_set_drvdata(pdev, lnw);
+       retval = gpiochip_add(&lnw->chip);
+       if (retval) {
+               dev_err(&pdev->dev, "langwell gpiochip_add error %d\n", retval);
+               goto err5;
+       }
+       irq_set_handler_data(pdev->irq, lnw);
+       irq_set_chained_handler(pdev->irq, lnw_irq_handler);
+       for (i = 0; i < lnw->chip.ngpio; i++) {
+               irq_set_chip_and_handler_name(i + lnw->irq_base, &lnw_irqchip,
+                                             handle_simple_irq, "demux");
+               irq_set_chip_data(i + lnw->irq_base, lnw);
+       }
+
+       spin_lock_init(&lnw->lock);
+
+       pm_runtime_put_noidle(&pdev->dev);
+       pm_runtime_allow(&pdev->dev);
+
+       goto done;
+err5:
+       kfree(lnw);
+err4:
+       iounmap(base);
+err3:
+       pci_release_regions(pdev);
+err2:
+       pci_disable_device(pdev);
+done:
+       return retval;
+}
+
+static struct pci_driver lnw_gpio_driver = {
+       .name           = "langwell_gpio",
+       .id_table       = lnw_gpio_ids,
+       .probe          = lnw_gpio_probe,
+       .driver         = {
+               .pm     = &lnw_gpio_pm_ops,
+       },
+};
+
+
+static int __devinit wp_gpio_probe(struct platform_device *pdev)
+{
+       struct lnw_gpio *lnw;
+       struct gpio_chip *gc;
+       struct resource *rc;
+       int retval = 0;
+
+       rc = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!rc)
+               return -EINVAL;
+
+       lnw = kzalloc(sizeof(struct lnw_gpio), GFP_KERNEL);
+       if (!lnw) {
+               dev_err(&pdev->dev,
+                       "can't allocate whitneypoint_gpio chip data\n");
+               return -ENOMEM;
+       }
+       lnw->reg_base = ioremap_nocache(rc->start, resource_size(rc));
+       if (lnw->reg_base == NULL) {
+               retval = -EINVAL;
+               goto err_kmalloc;
+       }
+       spin_lock_init(&lnw->lock);
+       gc = &lnw->chip;
+       gc->label = dev_name(&pdev->dev);
+       gc->owner = THIS_MODULE;
+       gc->direction_input = lnw_gpio_direction_input;
+       gc->direction_output = lnw_gpio_direction_output;
+       gc->get = lnw_gpio_get;
+       gc->set = lnw_gpio_set;
+       gc->to_irq = NULL;
+       gc->base = 0;
+       gc->ngpio = 64;
+       gc->can_sleep = 0;
+       retval = gpiochip_add(gc);
+       if (retval) {
+               dev_err(&pdev->dev, "whitneypoint gpiochip_add error %d\n",
+                                                               retval);
+               goto err_ioremap;
+       }
+       platform_set_drvdata(pdev, lnw);
+       return 0;
+err_ioremap:
+       iounmap(lnw->reg_base);
+err_kmalloc:
+       kfree(lnw);
+       return retval;
+}
+
+static int __devexit wp_gpio_remove(struct platform_device *pdev)
+{
+       struct lnw_gpio *lnw = platform_get_drvdata(pdev);
+       int err;
+       err = gpiochip_remove(&lnw->chip);
+       if (err)
+               dev_err(&pdev->dev, "failed to remove gpio_chip.\n");
+       iounmap(lnw->reg_base);
+       kfree(lnw);
+       platform_set_drvdata(pdev, NULL);
+       return 0;
+}
+
+static struct platform_driver wp_gpio_driver = {
+       .probe          = wp_gpio_probe,
+       .remove         = __devexit_p(wp_gpio_remove),
+       .driver         = {
+               .name   = "wp_gpio",
+               .owner  = THIS_MODULE,
+       },
+};
+
+static int __init lnw_gpio_init(void)
+{
+       int ret;
+       ret =  pci_register_driver(&lnw_gpio_driver);
+       if (ret < 0)
+               return ret;
+       ret = platform_driver_register(&wp_gpio_driver);
+       if (ret < 0)
+               pci_unregister_driver(&lnw_gpio_driver);
+       return ret;
+}
+
+device_initcall(lnw_gpio_init);
diff --git a/drivers/gpio/gpio-max7300.c b/drivers/gpio/gpio-max7300.c
new file mode 100644 (file)
index 0000000..a5ca0ab
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2009 Wolfram Sang, Pengutronix
+ *
+ * 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.
+ *
+ * Check max730x.c for further details.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/mutex.h>
+#include <linux/i2c.h>
+#include <linux/spi/max7301.h>
+#include <linux/slab.h>
+
+static int max7300_i2c_write(struct device *dev, unsigned int reg,
+                               unsigned int val)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+
+       return i2c_smbus_write_byte_data(client, reg, val);
+}
+
+static int max7300_i2c_read(struct device *dev, unsigned int reg)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+
+       return i2c_smbus_read_byte_data(client, reg);
+}
+
+static int __devinit max7300_probe(struct i2c_client *client,
+                        const struct i2c_device_id *id)
+{
+       struct max7301 *ts;
+       int ret;
+
+       if (!i2c_check_functionality(client->adapter,
+                       I2C_FUNC_SMBUS_BYTE_DATA))
+               return -EIO;
+
+       ts = kzalloc(sizeof(struct max7301), GFP_KERNEL);
+       if (!ts)
+               return -ENOMEM;
+
+       ts->read = max7300_i2c_read;
+       ts->write = max7300_i2c_write;
+       ts->dev = &client->dev;
+
+       ret = __max730x_probe(ts);
+       if (ret)
+               kfree(ts);
+       return ret;
+}
+
+static int __devexit max7300_remove(struct i2c_client *client)
+{
+       return __max730x_remove(&client->dev);
+}
+
+static const struct i2c_device_id max7300_id[] = {
+       { "max7300", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, max7300_id);
+
+static struct i2c_driver max7300_driver = {
+       .driver = {
+               .name = "max7300",
+               .owner = THIS_MODULE,
+       },
+       .probe = max7300_probe,
+       .remove = __devexit_p(max7300_remove),
+       .id_table = max7300_id,
+};
+
+static int __init max7300_init(void)
+{
+       return i2c_add_driver(&max7300_driver);
+}
+subsys_initcall(max7300_init);
+
+static void __exit max7300_exit(void)
+{
+       i2c_del_driver(&max7300_driver);
+}
+module_exit(max7300_exit);
+
+MODULE_AUTHOR("Wolfram Sang");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("MAX7300 GPIO-Expander");
diff --git a/drivers/gpio/gpio-max7301.c b/drivers/gpio/gpio-max7301.c
new file mode 100644 (file)
index 0000000..741acfc
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2006 Juergen Beisert, Pengutronix
+ * Copyright (C) 2008 Guennadi Liakhovetski, Pengutronix
+ * Copyright (C) 2009 Wolfram Sang, Pengutronix
+ *
+ * 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.
+ *
+ * Check max730x.c for further details.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/max7301.h>
+
+/* A write to the MAX7301 means one message with one transfer */
+static int max7301_spi_write(struct device *dev, unsigned int reg,
+                               unsigned int val)
+{
+       struct spi_device *spi = to_spi_device(dev);
+       u16 word = ((reg & 0x7F) << 8) | (val & 0xFF);
+
+       return spi_write(spi, (const u8 *)&word, sizeof(word));
+}
+
+/* A read from the MAX7301 means two transfers; here, one message each */
+
+static int max7301_spi_read(struct device *dev, unsigned int reg)
+{
+       int ret;
+       u16 word;
+       struct spi_device *spi = to_spi_device(dev);
+
+       word = 0x8000 | (reg << 8);
+       ret = spi_write(spi, (const u8 *)&word, sizeof(word));
+       if (ret)
+               return ret;
+       /*
+        * This relies on the fact, that a transfer with NULL tx_buf shifts out
+        * zero bytes (=NOOP for MAX7301)
+        */
+       ret = spi_read(spi, (u8 *)&word, sizeof(word));
+       if (ret)
+               return ret;
+       return word & 0xff;
+}
+
+static int __devinit max7301_probe(struct spi_device *spi)
+{
+       struct max7301 *ts;
+       int ret;
+
+       /* bits_per_word cannot be configured in platform data */
+       spi->bits_per_word = 16;
+       ret = spi_setup(spi);
+       if (ret < 0)
+               return ret;
+
+       ts = kzalloc(sizeof(struct max7301), GFP_KERNEL);
+       if (!ts)
+               return -ENOMEM;
+
+       ts->read = max7301_spi_read;
+       ts->write = max7301_spi_write;
+       ts->dev = &spi->dev;
+
+       ret = __max730x_probe(ts);
+       if (ret)
+               kfree(ts);
+       return ret;
+}
+
+static int __devexit max7301_remove(struct spi_device *spi)
+{
+       return __max730x_remove(&spi->dev);
+}
+
+static const struct spi_device_id max7301_id[] = {
+       { "max7301", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(spi, max7301_id);
+
+static struct spi_driver max7301_driver = {
+       .driver = {
+               .name = "max7301",
+               .owner = THIS_MODULE,
+       },
+       .probe = max7301_probe,
+       .remove = __devexit_p(max7301_remove),
+       .id_table = max7301_id,
+};
+
+static int __init max7301_init(void)
+{
+       return spi_register_driver(&max7301_driver);
+}
+/* register after spi postcore initcall and before
+ * subsys initcalls that may rely on these GPIOs
+ */
+subsys_initcall(max7301_init);
+
+static void __exit max7301_exit(void)
+{
+       spi_unregister_driver(&max7301_driver);
+}
+module_exit(max7301_exit);
+
+MODULE_AUTHOR("Juergen Beisert, Wolfram Sang");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("MAX7301 GPIO-Expander");
diff --git a/drivers/gpio/gpio-max730x.c b/drivers/gpio/gpio-max730x.c
new file mode 100644 (file)
index 0000000..05e2dac
--- /dev/null
@@ -0,0 +1,255 @@
+/**
+ * Copyright (C) 2006 Juergen Beisert, Pengutronix
+ * Copyright (C) 2008 Guennadi Liakhovetski, Pengutronix
+ * Copyright (C) 2009 Wolfram Sang, Pengutronix
+ *
+ * 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.
+ *
+ * The Maxim MAX7300/1 device is an I2C/SPI driven GPIO expander. There are
+ * 28 GPIOs. 8 of them can trigger an interrupt. See datasheet for more
+ * details
+ * Note:
+ * - DIN must be stable at the rising edge of clock.
+ * - when writing:
+ *   - always clock in 16 clocks at once
+ *   - at DIN: D15 first, D0 last
+ *   - D0..D7 = databyte, D8..D14 = commandbyte
+ *   - D15 = low -> write command
+ * - when reading
+ *   - always clock in 16 clocks at once
+ *   - at DIN: D15 first, D0 last
+ *   - D0..D7 = dummy, D8..D14 = register address
+ *   - D15 = high -> read command
+ *   - raise CS and assert it again
+ *   - always clock in 16 clocks at once
+ *   - at DOUT: D15 first, D0 last
+ *   - D0..D7 contains the data from the first cycle
+ *
+ * The driver exports a standard gpiochip interface
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/mutex.h>
+#include <linux/spi/max7301.h>
+#include <linux/gpio.h>
+#include <linux/slab.h>
+
+/*
+ * Pin configurations, see MAX7301 datasheet page 6
+ */
+#define PIN_CONFIG_MASK 0x03
+#define PIN_CONFIG_IN_PULLUP 0x03
+#define PIN_CONFIG_IN_WO_PULLUP 0x02
+#define PIN_CONFIG_OUT 0x01
+
+#define PIN_NUMBER 28
+
+static int max7301_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+       struct max7301 *ts = container_of(chip, struct max7301, chip);
+       u8 *config;
+       u8 offset_bits, pin_config;
+       int ret;
+
+       /* First 4 pins are unused in the controller */
+       offset += 4;
+       offset_bits = (offset & 3) << 1;
+
+       config = &ts->port_config[offset >> 2];
+
+       if (ts->input_pullup_active & BIT(offset))
+               pin_config = PIN_CONFIG_IN_PULLUP;
+       else
+               pin_config = PIN_CONFIG_IN_WO_PULLUP;
+
+       mutex_lock(&ts->lock);
+
+       *config = (*config & ~(PIN_CONFIG_MASK << offset_bits))
+                          | (pin_config << offset_bits);
+
+       ret = ts->write(ts->dev, 0x08 + (offset >> 2), *config);
+
+       mutex_unlock(&ts->lock);
+
+       return ret;
+}
+
+static int __max7301_set(struct max7301 *ts, unsigned offset, int value)
+{
+       if (value) {
+               ts->out_level |= 1 << offset;
+               return ts->write(ts->dev, 0x20 + offset, 0x01);
+       } else {
+               ts->out_level &= ~(1 << offset);
+               return ts->write(ts->dev, 0x20 + offset, 0x00);
+       }
+}
+
+static int max7301_direction_output(struct gpio_chip *chip, unsigned offset,
+                                   int value)
+{
+       struct max7301 *ts = container_of(chip, struct max7301, chip);
+       u8 *config;
+       u8 offset_bits;
+       int ret;
+
+       /* First 4 pins are unused in the controller */
+       offset += 4;
+       offset_bits = (offset & 3) << 1;
+
+       config = &ts->port_config[offset >> 2];
+
+       mutex_lock(&ts->lock);
+
+       *config = (*config & ~(PIN_CONFIG_MASK << offset_bits))
+                          | (PIN_CONFIG_OUT << offset_bits);
+
+       ret = __max7301_set(ts, offset, value);
+
+       if (!ret)
+               ret = ts->write(ts->dev, 0x08 + (offset >> 2), *config);
+
+       mutex_unlock(&ts->lock);
+
+       return ret;
+}
+
+static int max7301_get(struct gpio_chip *chip, unsigned offset)
+{
+       struct max7301 *ts = container_of(chip, struct max7301, chip);
+       int config, level = -EINVAL;
+
+       /* First 4 pins are unused in the controller */
+       offset += 4;
+
+       mutex_lock(&ts->lock);
+
+       config = (ts->port_config[offset >> 2] >> ((offset & 3) << 1))
+                       & PIN_CONFIG_MASK;
+
+       switch (config) {
+       case PIN_CONFIG_OUT:
+               /* Output: return cached level */
+               level =  !!(ts->out_level & (1 << offset));
+               break;
+       case PIN_CONFIG_IN_WO_PULLUP:
+       case PIN_CONFIG_IN_PULLUP:
+               /* Input: read out */
+               level = ts->read(ts->dev, 0x20 + offset) & 0x01;
+       }
+       mutex_unlock(&ts->lock);
+
+       return level;
+}
+
+static void max7301_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+       struct max7301 *ts = container_of(chip, struct max7301, chip);
+
+       /* First 4 pins are unused in the controller */
+       offset += 4;
+
+       mutex_lock(&ts->lock);
+
+       __max7301_set(ts, offset, value);
+
+       mutex_unlock(&ts->lock);
+}
+
+int __devinit __max730x_probe(struct max7301 *ts)
+{
+       struct device *dev = ts->dev;
+       struct max7301_platform_data *pdata;
+       int i, ret;
+
+       pdata = dev->platform_data;
+       if (!pdata || !pdata->base) {
+               dev_err(dev, "incorrect or missing platform data\n");
+               return -EINVAL;
+       }
+
+       mutex_init(&ts->lock);
+       dev_set_drvdata(dev, ts);
+
+       /* Power up the chip and disable IRQ output */
+       ts->write(dev, 0x04, 0x01);
+
+       ts->input_pullup_active = pdata->input_pullup_active;
+       ts->chip.label = dev->driver->name;
+
+       ts->chip.direction_input = max7301_direction_input;
+       ts->chip.get = max7301_get;
+       ts->chip.direction_output = max7301_direction_output;
+       ts->chip.set = max7301_set;
+
+       ts->chip.base = pdata->base;
+       ts->chip.ngpio = PIN_NUMBER;
+       ts->chip.can_sleep = 1;
+       ts->chip.dev = dev;
+       ts->chip.owner = THIS_MODULE;
+
+       /*
+        * initialize pullups according to platform data and cache the
+        * register values for later use.
+        */
+       for (i = 1; i < 8; i++) {
+               int j;
+               /*
+                * initialize port_config with "0xAA", which means
+                * input with internal pullup disabled. This is needed
+                * to avoid writing zeros (in the inner for loop),
+                * which is not allowed according to the datasheet.
+                */
+               ts->port_config[i] = 0xAA;
+               for (j = 0; j < 4; j++) {
+                       int offset = (i - 1) * 4 + j;
+                       ret = max7301_direction_input(&ts->chip, offset);
+                       if (ret)
+                               goto exit_destroy;
+               }
+       }
+
+       ret = gpiochip_add(&ts->chip);
+       if (ret)
+               goto exit_destroy;
+
+       return ret;
+
+exit_destroy:
+       dev_set_drvdata(dev, NULL);
+       mutex_destroy(&ts->lock);
+       return ret;
+}
+EXPORT_SYMBOL_GPL(__max730x_probe);
+
+int __devexit __max730x_remove(struct device *dev)
+{
+       struct max7301 *ts = dev_get_drvdata(dev);
+       int ret;
+
+       if (ts == NULL)
+               return -ENODEV;
+
+       dev_set_drvdata(dev, NULL);
+
+       /* Power down the chip and disable IRQ output */
+       ts->write(dev, 0x04, 0x00);
+
+       ret = gpiochip_remove(&ts->chip);
+       if (!ret) {
+               mutex_destroy(&ts->lock);
+               kfree(ts);
+       } else
+               dev_err(dev, "Failed to remove GPIO controller: %d\n", ret);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(__max730x_remove);
+
+MODULE_AUTHOR("Juergen Beisert, Wolfram Sang");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("MAX730x GPIO-Expanders, generic parts");
diff --git a/drivers/gpio/gpio-max732x.c b/drivers/gpio/gpio-max732x.c
new file mode 100644 (file)
index 0000000..9504120
--- /dev/null
@@ -0,0 +1,714 @@
+/*
+ *  MAX732x I2C Port Expander with 8/16 I/O
+ *
+ *  Copyright (C) 2007 Marvell International Ltd.
+ *  Copyright (C) 2008 Jack Ren <jack.ren@marvell.com>
+ *  Copyright (C) 2008 Eric Miao <eric.miao@marvell.com>
+ *
+ *  Derived from drivers/gpio/pca953x.c
+ *
+ *  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; version 2 of the License.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/i2c.h>
+#include <linux/i2c/max732x.h>
+
+
+/*
+ * Each port of MAX732x (including MAX7319) falls into one of the
+ * following three types:
+ *
+ *   - Push Pull Output
+ *   - Input
+ *   - Open Drain I/O
+ *
+ * designated by 'O', 'I' and 'P' individually according to MAXIM's
+ * datasheets. 'I' and 'P' ports are interrupt capables, some with
+ * a dedicated interrupt mask.
+ *
+ * There are two groups of I/O ports, each group usually includes
+ * up to 8 I/O ports, and is accessed by a specific I2C address:
+ *
+ *   - Group A : by I2C address 0b'110xxxx
+ *   - Group B : by I2C address 0b'101xxxx
+ *
+ * where 'xxxx' is decided by the connections of pin AD2/AD0.  The
+ * address used also affects the initial state of output signals.
+ *
+ * Within each group of ports, there are five known combinations of
+ * I/O ports: 4I4O, 4P4O, 8I, 8P, 8O, see the definitions below for
+ * the detailed organization of these ports. Only Goup A is interrupt
+ * capable.
+ *
+ * GPIO numbers start from 'gpio_base + 0' to 'gpio_base + 8/16',
+ * and GPIOs from GROUP_A are numbered before those from GROUP_B
+ * (if there are two groups).
+ *
+ * NOTE: MAX7328/MAX7329 are drop-in replacements for PCF8574/a, so
+ * they are not supported by this driver.
+ */
+
+#define PORT_NONE      0x0     /* '/' No Port */
+#define PORT_OUTPUT    0x1     /* 'O' Push-Pull, Output Only */
+#define PORT_INPUT     0x2     /* 'I' Input Only */
+#define PORT_OPENDRAIN 0x3     /* 'P' Open-Drain, I/O */
+
+#define IO_4I4O                0x5AA5  /* O7 O6 I5 I4 I3 I2 O1 O0 */
+#define IO_4P4O                0x5FF5  /* O7 O6 P5 P4 P3 P2 O1 O0 */
+#define IO_8I          0xAAAA  /* I7 I6 I5 I4 I3 I2 I1 I0 */
+#define IO_8P          0xFFFF  /* P7 P6 P5 P4 P3 P2 P1 P0 */
+#define IO_8O          0x5555  /* O7 O6 O5 O4 O3 O2 O1 O0 */
+
+#define GROUP_A(x)     ((x) & 0xffff)  /* I2C Addr: 0b'110xxxx */
+#define GROUP_B(x)     ((x) << 16)     /* I2C Addr: 0b'101xxxx */
+
+#define INT_NONE       0x0     /* No interrupt capability */
+#define INT_NO_MASK    0x1     /* Has interrupts, no mask */
+#define INT_INDEP_MASK 0x2     /* Has interrupts, independent mask */
+#define INT_MERGED_MASK 0x3    /* Has interrupts, merged mask */
+
+#define INT_CAPS(x)    (((uint64_t)(x)) << 32)
+
+enum {
+       MAX7319,
+       MAX7320,
+       MAX7321,
+       MAX7322,
+       MAX7323,
+       MAX7324,
+       MAX7325,
+       MAX7326,
+       MAX7327,
+};
+
+static uint64_t max732x_features[] = {
+       [MAX7319] = GROUP_A(IO_8I) | INT_CAPS(INT_MERGED_MASK),
+       [MAX7320] = GROUP_B(IO_8O),
+       [MAX7321] = GROUP_A(IO_8P) | INT_CAPS(INT_NO_MASK),
+       [MAX7322] = GROUP_A(IO_4I4O) | INT_CAPS(INT_MERGED_MASK),
+       [MAX7323] = GROUP_A(IO_4P4O) | INT_CAPS(INT_INDEP_MASK),
+       [MAX7324] = GROUP_A(IO_8I) | GROUP_B(IO_8O) | INT_CAPS(INT_MERGED_MASK),
+       [MAX7325] = GROUP_A(IO_8P) | GROUP_B(IO_8O) | INT_CAPS(INT_NO_MASK),
+       [MAX7326] = GROUP_A(IO_4I4O) | GROUP_B(IO_8O) | INT_CAPS(INT_MERGED_MASK),
+       [MAX7327] = GROUP_A(IO_4P4O) | GROUP_B(IO_8O) | INT_CAPS(INT_NO_MASK),
+};
+
+static const struct i2c_device_id max732x_id[] = {
+       { "max7319", MAX7319 },
+       { "max7320", MAX7320 },
+       { "max7321", MAX7321 },
+       { "max7322", MAX7322 },
+       { "max7323", MAX7323 },
+       { "max7324", MAX7324 },
+       { "max7325", MAX7325 },
+       { "max7326", MAX7326 },
+       { "max7327", MAX7327 },
+       { },
+};
+MODULE_DEVICE_TABLE(i2c, max732x_id);
+
+struct max732x_chip {
+       struct gpio_chip gpio_chip;
+
+       struct i2c_client *client;      /* "main" client */
+       struct i2c_client *client_dummy;
+       struct i2c_client *client_group_a;
+       struct i2c_client *client_group_b;
+
+       unsigned int    mask_group_a;
+       unsigned int    dir_input;
+       unsigned int    dir_output;
+
+       struct mutex    lock;
+       uint8_t         reg_out[2];
+
+#ifdef CONFIG_GPIO_MAX732X_IRQ
+       struct mutex    irq_lock;
+       int             irq_base;
+       uint8_t         irq_mask;
+       uint8_t         irq_mask_cur;
+       uint8_t         irq_trig_raise;
+       uint8_t         irq_trig_fall;
+       uint8_t         irq_features;
+#endif
+};
+
+static int max732x_writeb(struct max732x_chip *chip, int group_a, uint8_t val)
+{
+       struct i2c_client *client;
+       int ret;
+
+       client = group_a ? chip->client_group_a : chip->client_group_b;
+       ret = i2c_smbus_write_byte(client, val);
+       if (ret < 0) {
+               dev_err(&client->dev, "failed writing\n");
+               return ret;
+       }
+
+       return 0;
+}
+
+static int max732x_readb(struct max732x_chip *chip, int group_a, uint8_t *val)
+{
+       struct i2c_client *client;
+       int ret;
+
+       client = group_a ? chip->client_group_a : chip->client_group_b;
+       ret = i2c_smbus_read_byte(client);
+       if (ret < 0) {
+               dev_err(&client->dev, "failed reading\n");
+               return ret;
+       }
+
+       *val = (uint8_t)ret;
+       return 0;
+}
+
+static inline int is_group_a(struct max732x_chip *chip, unsigned off)
+{
+       return (1u << off) & chip->mask_group_a;
+}
+
+static int max732x_gpio_get_value(struct gpio_chip *gc, unsigned off)
+{
+       struct max732x_chip *chip;
+       uint8_t reg_val;
+       int ret;
+
+       chip = container_of(gc, struct max732x_chip, gpio_chip);
+
+       ret = max732x_readb(chip, is_group_a(chip, off), &reg_val);
+       if (ret < 0)
+               return 0;
+
+       return reg_val & (1u << (off & 0x7));
+}
+
+static void max732x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val)
+{
+       struct max732x_chip *chip;
+       uint8_t reg_out, mask = 1u << (off & 0x7);
+       int ret;
+
+       chip = container_of(gc, struct max732x_chip, gpio_chip);
+
+       mutex_lock(&chip->lock);
+
+       reg_out = (off > 7) ? chip->reg_out[1] : chip->reg_out[0];
+       reg_out = (val) ? reg_out | mask : reg_out & ~mask;
+
+       ret = max732x_writeb(chip, is_group_a(chip, off), reg_out);
+       if (ret < 0)
+               goto out;
+
+       /* update the shadow register then */
+       if (off > 7)
+               chip->reg_out[1] = reg_out;
+       else
+               chip->reg_out[0] = reg_out;
+out:
+       mutex_unlock(&chip->lock);
+}
+
+static int max732x_gpio_direction_input(struct gpio_chip *gc, unsigned off)
+{
+       struct max732x_chip *chip;
+       unsigned int mask = 1u << off;
+
+       chip = container_of(gc, struct max732x_chip, gpio_chip);
+
+       if ((mask & chip->dir_input) == 0) {
+               dev_dbg(&chip->client->dev, "%s port %d is output only\n",
+                       chip->client->name, off);
+               return -EACCES;
+       }
+
+       /*
+        * Open-drain pins must be set to high impedance (which is
+        * equivalent to output-high) to be turned into an input.
+        */
+       if ((mask & chip->dir_output))
+               max732x_gpio_set_value(gc, off, 1);
+
+       return 0;
+}
+
+static int max732x_gpio_direction_output(struct gpio_chip *gc,
+               unsigned off, int val)
+{
+       struct max732x_chip *chip;
+       unsigned int mask = 1u << off;
+
+       chip = container_of(gc, struct max732x_chip, gpio_chip);
+
+       if ((mask & chip->dir_output) == 0) {
+               dev_dbg(&chip->client->dev, "%s port %d is input only\n",
+                       chip->client->name, off);
+               return -EACCES;
+       }
+
+       max732x_gpio_set_value(gc, off, val);
+       return 0;
+}
+
+#ifdef CONFIG_GPIO_MAX732X_IRQ
+static int max732x_writew(struct max732x_chip *chip, uint16_t val)
+{
+       int ret;
+
+       val = cpu_to_le16(val);
+
+       ret = i2c_master_send(chip->client_group_a, (char *)&val, 2);
+       if (ret < 0) {
+               dev_err(&chip->client_group_a->dev, "failed writing\n");
+               return ret;
+       }
+
+       return 0;
+}
+
+static int max732x_readw(struct max732x_chip *chip, uint16_t *val)
+{
+       int ret;
+
+       ret = i2c_master_recv(chip->client_group_a, (char *)val, 2);
+       if (ret < 0) {
+               dev_err(&chip->client_group_a->dev, "failed reading\n");
+               return ret;
+       }
+
+       *val = le16_to_cpu(*val);
+       return 0;
+}
+
+static void max732x_irq_update_mask(struct max732x_chip *chip)
+{
+       uint16_t msg;
+
+       if (chip->irq_mask == chip->irq_mask_cur)
+               return;
+
+       chip->irq_mask = chip->irq_mask_cur;
+
+       if (chip->irq_features == INT_NO_MASK)
+               return;
+
+       mutex_lock(&chip->lock);
+
+       switch (chip->irq_features) {
+       case INT_INDEP_MASK:
+               msg = (chip->irq_mask << 8) | chip->reg_out[0];
+               max732x_writew(chip, msg);
+               break;
+
+       case INT_MERGED_MASK:
+               msg = chip->irq_mask | chip->reg_out[0];
+               max732x_writeb(chip, 1, (uint8_t)msg);
+               break;
+       }
+
+       mutex_unlock(&chip->lock);
+}
+
+static int max732x_gpio_to_irq(struct gpio_chip *gc, unsigned off)
+{
+       struct max732x_chip *chip;
+
+       chip = container_of(gc, struct max732x_chip, gpio_chip);
+       return chip->irq_base + off;
+}
+
+static void max732x_irq_mask(struct irq_data *d)
+{
+       struct max732x_chip *chip = irq_data_get_irq_chip_data(d);
+
+       chip->irq_mask_cur &= ~(1 << (d->irq - chip->irq_base));
+}
+
+static void max732x_irq_unmask(struct irq_data *d)
+{
+       struct max732x_chip *chip = irq_data_get_irq_chip_data(d);
+
+       chip->irq_mask_cur |= 1 << (d->irq - chip->irq_base);
+}
+
+static void max732x_irq_bus_lock(struct irq_data *d)
+{
+       struct max732x_chip *chip = irq_data_get_irq_chip_data(d);
+
+       mutex_lock(&chip->irq_lock);
+       chip->irq_mask_cur = chip->irq_mask;
+}
+
+static void max732x_irq_bus_sync_unlock(struct irq_data *d)
+{
+       struct max732x_chip *chip = irq_data_get_irq_chip_data(d);
+
+       max732x_irq_update_mask(chip);
+       mutex_unlock(&chip->irq_lock);
+}
+
+static int max732x_irq_set_type(struct irq_data *d, unsigned int type)
+{
+       struct max732x_chip *chip = irq_data_get_irq_chip_data(d);
+       uint16_t off = d->irq - chip->irq_base;
+       uint16_t mask = 1 << off;
+
+       if (!(mask & chip->dir_input)) {
+               dev_dbg(&chip->client->dev, "%s port %d is output only\n",
+                       chip->client->name, off);
+               return -EACCES;
+       }
+
+       if (!(type & IRQ_TYPE_EDGE_BOTH)) {
+               dev_err(&chip->client->dev, "irq %d: unsupported type %d\n",
+                       d->irq, type);
+               return -EINVAL;
+       }
+
+       if (type & IRQ_TYPE_EDGE_FALLING)
+               chip->irq_trig_fall |= mask;
+       else
+               chip->irq_trig_fall &= ~mask;
+
+       if (type & IRQ_TYPE_EDGE_RISING)
+               chip->irq_trig_raise |= mask;
+       else
+               chip->irq_trig_raise &= ~mask;
+
+       return max732x_gpio_direction_input(&chip->gpio_chip, off);
+}
+
+static struct irq_chip max732x_irq_chip = {
+       .name                   = "max732x",
+       .irq_mask               = max732x_irq_mask,
+       .irq_unmask             = max732x_irq_unmask,
+       .irq_bus_lock           = max732x_irq_bus_lock,
+       .irq_bus_sync_unlock    = max732x_irq_bus_sync_unlock,
+       .irq_set_type           = max732x_irq_set_type,
+};
+
+static uint8_t max732x_irq_pending(struct max732x_chip *chip)
+{
+       uint8_t cur_stat;
+       uint8_t old_stat;
+       uint8_t trigger;
+       uint8_t pending;
+       uint16_t status;
+       int ret;
+
+       ret = max732x_readw(chip, &status);
+       if (ret)
+               return 0;
+
+       trigger = status >> 8;
+       trigger &= chip->irq_mask;
+
+       if (!trigger)
+               return 0;
+
+       cur_stat = status & 0xFF;
+       cur_stat &= chip->irq_mask;
+
+       old_stat = cur_stat ^ trigger;
+
+       pending = (old_stat & chip->irq_trig_fall) |
+                 (cur_stat & chip->irq_trig_raise);
+       pending &= trigger;
+
+       return pending;
+}
+
+static irqreturn_t max732x_irq_handler(int irq, void *devid)
+{
+       struct max732x_chip *chip = devid;
+       uint8_t pending;
+       uint8_t level;
+
+       pending = max732x_irq_pending(chip);
+
+       if (!pending)
+               return IRQ_HANDLED;
+
+       do {
+               level = __ffs(pending);
+               handle_nested_irq(level + chip->irq_base);
+
+               pending &= ~(1 << level);
+       } while (pending);
+
+       return IRQ_HANDLED;
+}
+
+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;
+       int has_irq = max732x_features[id->driver_data] >> 32;
+       int ret;
+
+       if (pdata->irq_base && has_irq != INT_NONE) {
+               int lvl;
+
+               chip->irq_base = pdata->irq_base;
+               chip->irq_features = has_irq;
+               mutex_init(&chip->irq_lock);
+
+               for (lvl = 0; lvl < chip->gpio_chip.ngpio; lvl++) {
+                       int irq = lvl + chip->irq_base;
+
+                       if (!(chip->dir_input & (1 << lvl)))
+                               continue;
+
+                       irq_set_chip_data(irq, chip);
+                       irq_set_chip_and_handler(irq, &max732x_irq_chip,
+                                                handle_edge_irq);
+                       irq_set_nested_thread(irq, 1);
+#ifdef CONFIG_ARM
+                       set_irq_flags(irq, IRQF_VALID);
+#else
+                       irq_set_noprobe(irq);
+#endif
+               }
+
+               ret = request_threaded_irq(client->irq,
+                                          NULL,
+                                          max732x_irq_handler,
+                                          IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+                                          dev_name(&client->dev), chip);
+               if (ret) {
+                       dev_err(&client->dev, "failed to request irq %d\n",
+                               client->irq);
+                       goto out_failed;
+               }
+
+               chip->gpio_chip.to_irq = max732x_gpio_to_irq;
+       }
+
+       return 0;
+
+out_failed:
+       chip->irq_base = 0;
+       return ret;
+}
+
+static void max732x_irq_teardown(struct max732x_chip *chip)
+{
+       if (chip->irq_base)
+               free_irq(chip->client->irq, chip);
+}
+#else /* CONFIG_GPIO_MAX732X_IRQ */
+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;
+       int has_irq = max732x_features[id->driver_data] >> 32;
+
+       if (pdata->irq_base && has_irq != INT_NONE)
+               dev_warn(&client->dev, "interrupt support not compiled in\n");
+
+       return 0;
+}
+
+static void max732x_irq_teardown(struct max732x_chip *chip)
+{
+}
+#endif
+
+static int __devinit max732x_setup_gpio(struct max732x_chip *chip,
+                                       const struct i2c_device_id *id,
+                                       unsigned gpio_start)
+{
+       struct gpio_chip *gc = &chip->gpio_chip;
+       uint32_t id_data = (uint32_t)max732x_features[id->driver_data];
+       int i, port = 0;
+
+       for (i = 0; i < 16; i++, id_data >>= 2) {
+               unsigned int mask = 1 << port;
+
+               switch (id_data & 0x3) {
+               case PORT_OUTPUT:
+                       chip->dir_output |= mask;
+                       break;
+               case PORT_INPUT:
+                       chip->dir_input |= mask;
+                       break;
+               case PORT_OPENDRAIN:
+                       chip->dir_output |= mask;
+                       chip->dir_input |= mask;
+                       break;
+               default:
+                       continue;
+               }
+
+               if (i < 8)
+                       chip->mask_group_a |= mask;
+               port++;
+       }
+
+       if (chip->dir_input)
+               gc->direction_input = max732x_gpio_direction_input;
+       if (chip->dir_output) {
+               gc->direction_output = max732x_gpio_direction_output;
+               gc->set = max732x_gpio_set_value;
+       }
+       gc->get = max732x_gpio_get_value;
+       gc->can_sleep = 1;
+
+       gc->base = gpio_start;
+       gc->ngpio = port;
+       gc->label = chip->client->name;
+       gc->owner = THIS_MODULE;
+
+       return port;
+}
+
+static int __devinit max732x_probe(struct i2c_client *client,
+                                  const struct i2c_device_id *id)
+{
+       struct max732x_platform_data *pdata;
+       struct max732x_chip *chip;
+       struct i2c_client *c;
+       uint16_t addr_a, addr_b;
+       int ret, nr_port;
+
+       pdata = client->dev.platform_data;
+       if (pdata == NULL) {
+               dev_dbg(&client->dev, "no platform data\n");
+               return -EINVAL;
+       }
+
+       chip = kzalloc(sizeof(struct max732x_chip), GFP_KERNEL);
+       if (chip == NULL)
+               return -ENOMEM;
+       chip->client = client;
+
+       nr_port = max732x_setup_gpio(chip, id, pdata->gpio_base);
+
+       addr_a = (client->addr & 0x0f) | 0x60;
+       addr_b = (client->addr & 0x0f) | 0x50;
+
+       switch (client->addr & 0x70) {
+       case 0x60:
+               chip->client_group_a = client;
+               if (nr_port > 8) {
+                       c = i2c_new_dummy(client->adapter, addr_b);
+                       chip->client_group_b = chip->client_dummy = c;
+               }
+               break;
+       case 0x50:
+               chip->client_group_b = client;
+               if (nr_port > 8) {
+                       c = i2c_new_dummy(client->adapter, addr_a);
+                       chip->client_group_a = chip->client_dummy = c;
+               }
+               break;
+       default:
+               dev_err(&client->dev, "invalid I2C address specified %02x\n",
+                               client->addr);
+               ret = -EINVAL;
+               goto out_failed;
+       }
+
+       mutex_init(&chip->lock);
+
+       max732x_readb(chip, is_group_a(chip, 0), &chip->reg_out[0]);
+       if (nr_port > 8)
+               max732x_readb(chip, is_group_a(chip, 8), &chip->reg_out[1]);
+
+       ret = max732x_irq_setup(chip, id);
+       if (ret)
+               goto out_failed;
+
+       ret = gpiochip_add(&chip->gpio_chip);
+       if (ret)
+               goto out_failed;
+
+       if (pdata->setup) {
+               ret = pdata->setup(client, chip->gpio_chip.base,
+                               chip->gpio_chip.ngpio, pdata->context);
+               if (ret < 0)
+                       dev_warn(&client->dev, "setup failed, %d\n", ret);
+       }
+
+       i2c_set_clientdata(client, chip);
+       return 0;
+
+out_failed:
+       max732x_irq_teardown(chip);
+       kfree(chip);
+       return ret;
+}
+
+static int __devexit max732x_remove(struct i2c_client *client)
+{
+       struct max732x_platform_data *pdata = client->dev.platform_data;
+       struct max732x_chip *chip = i2c_get_clientdata(client);
+       int ret;
+
+       if (pdata->teardown) {
+               ret = pdata->teardown(client, chip->gpio_chip.base,
+                               chip->gpio_chip.ngpio, pdata->context);
+               if (ret < 0) {
+                       dev_err(&client->dev, "%s failed, %d\n",
+                                       "teardown", ret);
+                       return ret;
+               }
+       }
+
+       ret = gpiochip_remove(&chip->gpio_chip);
+       if (ret) {
+               dev_err(&client->dev, "%s failed, %d\n",
+                               "gpiochip_remove()", ret);
+               return ret;
+       }
+
+       max732x_irq_teardown(chip);
+
+       /* unregister any dummy i2c_client */
+       if (chip->client_dummy)
+               i2c_unregister_device(chip->client_dummy);
+
+       kfree(chip);
+       return 0;
+}
+
+static struct i2c_driver max732x_driver = {
+       .driver = {
+               .name   = "max732x",
+               .owner  = THIS_MODULE,
+       },
+       .probe          = max732x_probe,
+       .remove         = __devexit_p(max732x_remove),
+       .id_table       = max732x_id,
+};
+
+static int __init max732x_init(void)
+{
+       return i2c_add_driver(&max732x_driver);
+}
+/* register after i2c postcore initcall and before
+ * subsys initcalls that may rely on these GPIOs
+ */
+subsys_initcall(max732x_init);
+
+static void __exit max732x_exit(void)
+{
+       i2c_del_driver(&max732x_driver);
+}
+module_exit(max732x_exit);
+
+MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>");
+MODULE_DESCRIPTION("GPIO expander driver for MAX732X");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/gpio-mc33880.c b/drivers/gpio/gpio-mc33880.c
new file mode 100644 (file)
index 0000000..b3b4652
--- /dev/null
@@ -0,0 +1,197 @@
+/*
+ * MC33880 high-side/low-side switch GPIO driver
+ * Copyright (c) 2009 Intel Corporation
+ *
+ * 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.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* Supports:
+ * Freescale MC33880 high-side/low-side switch
+ */
+
+#include <linux/init.h>
+#include <linux/mutex.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/mc33880.h>
+#include <linux/gpio.h>
+#include <linux/slab.h>
+
+#define DRIVER_NAME "mc33880"
+
+/*
+ * Pin configurations, see MAX7301 datasheet page 6
+ */
+#define PIN_CONFIG_MASK 0x03
+#define PIN_CONFIG_IN_PULLUP 0x03
+#define PIN_CONFIG_IN_WO_PULLUP 0x02
+#define PIN_CONFIG_OUT 0x01
+
+#define PIN_NUMBER 8
+
+
+/*
+ * Some registers must be read back to modify.
+ * To save time we cache them here in memory
+ */
+struct mc33880 {
+       struct mutex    lock;   /* protect from simultaneous accesses */
+       u8              port_config;
+       struct gpio_chip chip;
+       struct spi_device *spi;
+};
+
+static int mc33880_write_config(struct mc33880 *mc)
+{
+       return spi_write(mc->spi, &mc->port_config, sizeof(mc->port_config));
+}
+
+
+static int __mc33880_set(struct mc33880 *mc, unsigned offset, int value)
+{
+       if (value)
+               mc->port_config |= 1 << offset;
+       else
+               mc->port_config &= ~(1 << offset);
+
+       return mc33880_write_config(mc);
+}
+
+
+static void mc33880_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+       struct mc33880 *mc = container_of(chip, struct mc33880, chip);
+
+       mutex_lock(&mc->lock);
+
+       __mc33880_set(mc, offset, value);
+
+       mutex_unlock(&mc->lock);
+}
+
+static int __devinit mc33880_probe(struct spi_device *spi)
+{
+       struct mc33880 *mc;
+       struct mc33880_platform_data *pdata;
+       int ret;
+
+       pdata = spi->dev.platform_data;
+       if (!pdata || !pdata->base) {
+               dev_dbg(&spi->dev, "incorrect or missing platform data\n");
+               return -EINVAL;
+       }
+
+       /*
+        * bits_per_word cannot be configured in platform data
+        */
+       spi->bits_per_word = 8;
+
+       ret = spi_setup(spi);
+       if (ret < 0)
+               return ret;
+
+       mc = kzalloc(sizeof(struct mc33880), GFP_KERNEL);
+       if (!mc)
+               return -ENOMEM;
+
+       mutex_init(&mc->lock);
+
+       dev_set_drvdata(&spi->dev, mc);
+
+       mc->spi = spi;
+
+       mc->chip.label = DRIVER_NAME,
+       mc->chip.set = mc33880_set;
+       mc->chip.base = pdata->base;
+       mc->chip.ngpio = PIN_NUMBER;
+       mc->chip.can_sleep = 1;
+       mc->chip.dev = &spi->dev;
+       mc->chip.owner = THIS_MODULE;
+
+       mc->port_config = 0x00;
+       /* write twice, because during initialisation the first setting
+        * is just for testing SPI communication, and the second is the
+        * "real" configuration
+        */
+       ret = mc33880_write_config(mc);
+       mc->port_config = 0x00;
+       if (!ret)
+               ret = mc33880_write_config(mc);
+
+       if (ret) {
+               printk(KERN_ERR "Failed writing to " DRIVER_NAME ": %d\n", ret);
+               goto exit_destroy;
+       }
+
+       ret = gpiochip_add(&mc->chip);
+       if (ret)
+               goto exit_destroy;
+
+       return ret;
+
+exit_destroy:
+       dev_set_drvdata(&spi->dev, NULL);
+       mutex_destroy(&mc->lock);
+       kfree(mc);
+       return ret;
+}
+
+static int __devexit mc33880_remove(struct spi_device *spi)
+{
+       struct mc33880 *mc;
+       int ret;
+
+       mc = dev_get_drvdata(&spi->dev);
+       if (mc == NULL)
+               return -ENODEV;
+
+       dev_set_drvdata(&spi->dev, NULL);
+
+       ret = gpiochip_remove(&mc->chip);
+       if (!ret) {
+               mutex_destroy(&mc->lock);
+               kfree(mc);
+       } else
+               dev_err(&spi->dev, "Failed to remove the GPIO controller: %d\n",
+                       ret);
+
+       return ret;
+}
+
+static struct spi_driver mc33880_driver = {
+       .driver = {
+               .name           = DRIVER_NAME,
+               .owner          = THIS_MODULE,
+       },
+       .probe          = mc33880_probe,
+       .remove         = __devexit_p(mc33880_remove),
+};
+
+static int __init mc33880_init(void)
+{
+       return spi_register_driver(&mc33880_driver);
+}
+/* register after spi postcore initcall and before
+ * subsys initcalls that may rely on these GPIOs
+ */
+subsys_initcall(mc33880_init);
+
+static void __exit mc33880_exit(void)
+{
+       spi_unregister_driver(&mc33880_driver);
+}
+module_exit(mc33880_exit);
+
+MODULE_AUTHOR("Mocean Laboratories <info@mocean-labs.com>");
+MODULE_LICENSE("GPL v2");
+
diff --git a/drivers/gpio/gpio-mcp23s08.c b/drivers/gpio/gpio-mcp23s08.c
new file mode 100644 (file)
index 0000000..0083ec0
--- /dev/null
@@ -0,0 +1,530 @@
+/*
+ * MCP23S08 SPI gpio expander driver
+ */
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/workqueue.h>
+#include <linux/mutex.h>
+#include <linux/gpio.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/mcp23s08.h>
+#include <linux/slab.h>
+#include <asm/byteorder.h>
+
+/**
+ * MCP types supported by driver
+ */
+#define MCP_TYPE_S08   0
+#define MCP_TYPE_S17   1
+
+/* Registers are all 8 bits wide.
+ *
+ * The mcp23s17 has twice as many bits, and can be configured to work
+ * with either 16 bit registers or with two adjacent 8 bit banks.
+ *
+ * Also, there are I2C versions of both chips.
+ */
+#define MCP_IODIR      0x00            /* init/reset:  all ones */
+#define MCP_IPOL       0x01
+#define MCP_GPINTEN    0x02
+#define MCP_DEFVAL     0x03
+#define MCP_INTCON     0x04
+#define MCP_IOCON      0x05
+#      define IOCON_SEQOP      (1 << 5)
+#      define IOCON_HAEN       (1 << 3)
+#      define IOCON_ODR        (1 << 2)
+#      define IOCON_INTPOL     (1 << 1)
+#define MCP_GPPU       0x06
+#define MCP_INTF       0x07
+#define MCP_INTCAP     0x08
+#define MCP_GPIO       0x09
+#define MCP_OLAT       0x0a
+
+struct mcp23s08;
+
+struct mcp23s08_ops {
+       int     (*read)(struct mcp23s08 *mcp, unsigned reg);
+       int     (*write)(struct mcp23s08 *mcp, unsigned reg, unsigned val);
+       int     (*read_regs)(struct mcp23s08 *mcp, unsigned reg,
+                            u16 *vals, unsigned n);
+};
+
+struct mcp23s08 {
+       struct spi_device       *spi;
+       u8                      addr;
+
+       u16                     cache[11];
+       /* lock protects the cached values */
+       struct mutex            lock;
+
+       struct gpio_chip        chip;
+
+       struct work_struct      work;
+
+       const struct mcp23s08_ops       *ops;
+};
+
+/* A given spi_device can represent up to eight mcp23sxx chips
+ * sharing the same chipselect but using different addresses
+ * (e.g. chips #0 and #3 might be populated, but not #1 or $2).
+ * Driver data holds all the per-chip data.
+ */
+struct mcp23s08_driver_data {
+       unsigned                ngpio;
+       struct mcp23s08         *mcp[8];
+       struct mcp23s08         chip[];
+};
+
+static int mcp23s08_read(struct mcp23s08 *mcp, unsigned reg)
+{
+       u8      tx[2], rx[1];
+       int     status;
+
+       tx[0] = mcp->addr | 0x01;
+       tx[1] = reg;
+       status = spi_write_then_read(mcp->spi, tx, sizeof tx, rx, sizeof rx);
+       return (status < 0) ? status : rx[0];
+}
+
+static int mcp23s08_write(struct mcp23s08 *mcp, unsigned reg, unsigned val)
+{
+       u8      tx[3];
+
+       tx[0] = mcp->addr;
+       tx[1] = reg;
+       tx[2] = val;
+       return spi_write_then_read(mcp->spi, tx, sizeof tx, NULL, 0);
+}
+
+static int
+mcp23s08_read_regs(struct mcp23s08 *mcp, unsigned reg, u16 *vals, unsigned n)
+{
+       u8      tx[2], *tmp;
+       int     status;
+
+       if ((n + reg) > sizeof mcp->cache)
+               return -EINVAL;
+       tx[0] = mcp->addr | 0x01;
+       tx[1] = reg;
+
+       tmp = (u8 *)vals;
+       status = spi_write_then_read(mcp->spi, tx, sizeof tx, tmp, n);
+       if (status >= 0) {
+               while (n--)
+                       vals[n] = tmp[n]; /* expand to 16bit */
+       }
+       return status;
+}
+
+static int mcp23s17_read(struct mcp23s08 *mcp, unsigned reg)
+{
+       u8      tx[2], rx[2];
+       int     status;
+
+       tx[0] = mcp->addr | 0x01;
+       tx[1] = reg << 1;
+       status = spi_write_then_read(mcp->spi, tx, sizeof tx, rx, sizeof rx);
+       return (status < 0) ? status : (rx[0] | (rx[1] << 8));
+}
+
+static int mcp23s17_write(struct mcp23s08 *mcp, unsigned reg, unsigned val)
+{
+       u8      tx[4];
+
+       tx[0] = mcp->addr;
+       tx[1] = reg << 1;
+       tx[2] = val;
+       tx[3] = val >> 8;
+       return spi_write_then_read(mcp->spi, tx, sizeof tx, NULL, 0);
+}
+
+static int
+mcp23s17_read_regs(struct mcp23s08 *mcp, unsigned reg, u16 *vals, unsigned n)
+{
+       u8      tx[2];
+       int     status;
+
+       if ((n + reg) > sizeof mcp->cache)
+               return -EINVAL;
+       tx[0] = mcp->addr | 0x01;
+       tx[1] = reg << 1;
+
+       status = spi_write_then_read(mcp->spi, tx, sizeof tx,
+                                    (u8 *)vals, n * 2);
+       if (status >= 0) {
+               while (n--)
+                       vals[n] = __le16_to_cpu((__le16)vals[n]);
+       }
+
+       return status;
+}
+
+static const struct mcp23s08_ops mcp23s08_ops = {
+       .read           = mcp23s08_read,
+       .write          = mcp23s08_write,
+       .read_regs      = mcp23s08_read_regs,
+};
+
+static const struct mcp23s08_ops mcp23s17_ops = {
+       .read           = mcp23s17_read,
+       .write          = mcp23s17_write,
+       .read_regs      = mcp23s17_read_regs,
+};
+
+
+/*----------------------------------------------------------------------*/
+
+static int mcp23s08_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+       struct mcp23s08 *mcp = container_of(chip, struct mcp23s08, chip);
+       int status;
+
+       mutex_lock(&mcp->lock);
+       mcp->cache[MCP_IODIR] |= (1 << offset);
+       status = mcp->ops->write(mcp, MCP_IODIR, mcp->cache[MCP_IODIR]);
+       mutex_unlock(&mcp->lock);
+       return status;
+}
+
+static int mcp23s08_get(struct gpio_chip *chip, unsigned offset)
+{
+       struct mcp23s08 *mcp = container_of(chip, struct mcp23s08, chip);
+       int status;
+
+       mutex_lock(&mcp->lock);
+
+       /* REVISIT reading this clears any IRQ ... */
+       status = mcp->ops->read(mcp, MCP_GPIO);
+       if (status < 0)
+               status = 0;
+       else {
+               mcp->cache[MCP_GPIO] = status;
+               status = !!(status & (1 << offset));
+       }
+       mutex_unlock(&mcp->lock);
+       return status;
+}
+
+static int __mcp23s08_set(struct mcp23s08 *mcp, unsigned mask, int value)
+{
+       unsigned olat = mcp->cache[MCP_OLAT];
+
+       if (value)
+               olat |= mask;
+       else
+               olat &= ~mask;
+       mcp->cache[MCP_OLAT] = olat;
+       return mcp->ops->write(mcp, MCP_OLAT, olat);
+}
+
+static void mcp23s08_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+       struct mcp23s08 *mcp = container_of(chip, struct mcp23s08, chip);
+       unsigned mask = 1 << offset;
+
+       mutex_lock(&mcp->lock);
+       __mcp23s08_set(mcp, mask, value);
+       mutex_unlock(&mcp->lock);
+}
+
+static int
+mcp23s08_direction_output(struct gpio_chip *chip, unsigned offset, int value)
+{
+       struct mcp23s08 *mcp = container_of(chip, struct mcp23s08, chip);
+       unsigned mask = 1 << offset;
+       int status;
+
+       mutex_lock(&mcp->lock);
+       status = __mcp23s08_set(mcp, mask, value);
+       if (status == 0) {
+               mcp->cache[MCP_IODIR] &= ~mask;
+               status = mcp->ops->write(mcp, MCP_IODIR, mcp->cache[MCP_IODIR]);
+       }
+       mutex_unlock(&mcp->lock);
+       return status;
+}
+
+/*----------------------------------------------------------------------*/
+
+#ifdef CONFIG_DEBUG_FS
+
+#include <linux/seq_file.h>
+
+/*
+ * This shows more info than the generic gpio dump code:
+ * pullups, deglitching, open drain drive.
+ */
+static void mcp23s08_dbg_show(struct seq_file *s, struct gpio_chip *chip)
+{
+       struct mcp23s08 *mcp;
+       char            bank;
+       int             t;
+       unsigned        mask;
+
+       mcp = container_of(chip, struct mcp23s08, chip);
+
+       /* NOTE: we only handle one bank for now ... */
+       bank = '0' + ((mcp->addr >> 1) & 0x7);
+
+       mutex_lock(&mcp->lock);
+       t = mcp->ops->read_regs(mcp, 0, mcp->cache, ARRAY_SIZE(mcp->cache));
+       if (t < 0) {
+               seq_printf(s, " I/O ERROR %d\n", t);
+               goto done;
+       }
+
+       for (t = 0, mask = 1; t < chip->ngpio; t++, mask <<= 1) {
+               const char      *label;
+
+               label = gpiochip_is_requested(chip, t);
+               if (!label)
+                       continue;
+
+               seq_printf(s, " gpio-%-3d P%c.%d (%-12s) %s %s %s",
+                       chip->base + t, bank, t, label,
+                       (mcp->cache[MCP_IODIR] & mask) ? "in " : "out",
+                       (mcp->cache[MCP_GPIO] & mask) ? "hi" : "lo",
+                       (mcp->cache[MCP_GPPU] & mask) ? "  " : "up");
+               /* NOTE:  ignoring the irq-related registers */
+               seq_printf(s, "\n");
+       }
+done:
+       mutex_unlock(&mcp->lock);
+}
+
+#else
+#define mcp23s08_dbg_show      NULL
+#endif
+
+/*----------------------------------------------------------------------*/
+
+static int mcp23s08_probe_one(struct spi_device *spi, unsigned addr,
+                             unsigned type, unsigned base, unsigned pullups)
+{
+       struct mcp23s08_driver_data     *data = spi_get_drvdata(spi);
+       struct mcp23s08                 *mcp = data->mcp[addr];
+       int                             status;
+
+       mutex_init(&mcp->lock);
+
+       mcp->spi = spi;
+       mcp->addr = 0x40 | (addr << 1);
+
+       mcp->chip.direction_input = mcp23s08_direction_input;
+       mcp->chip.get = mcp23s08_get;
+       mcp->chip.direction_output = mcp23s08_direction_output;
+       mcp->chip.set = mcp23s08_set;
+       mcp->chip.dbg_show = mcp23s08_dbg_show;
+
+       if (type == MCP_TYPE_S17) {
+               mcp->ops = &mcp23s17_ops;
+               mcp->chip.ngpio = 16;
+               mcp->chip.label = "mcp23s17";
+       } else {
+               mcp->ops = &mcp23s08_ops;
+               mcp->chip.ngpio = 8;
+               mcp->chip.label = "mcp23s08";
+       }
+       mcp->chip.base = base;
+       mcp->chip.can_sleep = 1;
+       mcp->chip.dev = &spi->dev;
+       mcp->chip.owner = THIS_MODULE;
+
+       /* verify MCP_IOCON.SEQOP = 0, so sequential reads work,
+        * and MCP_IOCON.HAEN = 1, so we work with all chips.
+        */
+       status = mcp->ops->read(mcp, MCP_IOCON);
+       if (status < 0)
+               goto fail;
+       if ((status & IOCON_SEQOP) || !(status & IOCON_HAEN)) {
+               /* mcp23s17 has IOCON twice, make sure they are in sync */
+               status &= ~(IOCON_SEQOP | (IOCON_SEQOP << 8));
+               status |= IOCON_HAEN | (IOCON_HAEN << 8);
+               status = mcp->ops->write(mcp, MCP_IOCON, status);
+               if (status < 0)
+                       goto fail;
+       }
+
+       /* configure ~100K pullups */
+       status = mcp->ops->write(mcp, MCP_GPPU, pullups);
+       if (status < 0)
+               goto fail;
+
+       status = mcp->ops->read_regs(mcp, 0, mcp->cache, ARRAY_SIZE(mcp->cache));
+       if (status < 0)
+               goto fail;
+
+       /* disable inverter on input */
+       if (mcp->cache[MCP_IPOL] != 0) {
+               mcp->cache[MCP_IPOL] = 0;
+               status = mcp->ops->write(mcp, MCP_IPOL, 0);
+               if (status < 0)
+                       goto fail;
+       }
+
+       /* disable irqs */
+       if (mcp->cache[MCP_GPINTEN] != 0) {
+               mcp->cache[MCP_GPINTEN] = 0;
+               status = mcp->ops->write(mcp, MCP_GPINTEN, 0);
+               if (status < 0)
+                       goto fail;
+       }
+
+       status = gpiochip_add(&mcp->chip);
+fail:
+       if (status < 0)
+               dev_dbg(&spi->dev, "can't setup chip %d, --> %d\n",
+                               addr, status);
+       return status;
+}
+
+static int mcp23s08_probe(struct spi_device *spi)
+{
+       struct mcp23s08_platform_data   *pdata;
+       unsigned                        addr;
+       unsigned                        chips = 0;
+       struct mcp23s08_driver_data     *data;
+       int                             status, type;
+       unsigned                        base;
+
+       type = spi_get_device_id(spi)->driver_data;
+
+       pdata = spi->dev.platform_data;
+       if (!pdata || !gpio_is_valid(pdata->base)) {
+               dev_dbg(&spi->dev, "invalid or missing platform data\n");
+               return -EINVAL;
+       }
+
+       for (addr = 0; addr < ARRAY_SIZE(pdata->chip); addr++) {
+               if (!pdata->chip[addr].is_present)
+                       continue;
+               chips++;
+               if ((type == MCP_TYPE_S08) && (addr > 3)) {
+                       dev_err(&spi->dev,
+                               "mcp23s08 only supports address 0..3\n");
+                       return -EINVAL;
+               }
+       }
+       if (!chips)
+               return -ENODEV;
+
+       data = kzalloc(sizeof *data + chips * sizeof(struct mcp23s08),
+                       GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
+       spi_set_drvdata(spi, data);
+
+       base = pdata->base;
+       for (addr = 0; addr < ARRAY_SIZE(pdata->chip); addr++) {
+               if (!pdata->chip[addr].is_present)
+                       continue;
+               chips--;
+               data->mcp[addr] = &data->chip[chips];
+               status = mcp23s08_probe_one(spi, addr, type, base,
+                                           pdata->chip[addr].pullups);
+               if (status < 0)
+                       goto fail;
+
+               base += (type == MCP_TYPE_S17) ? 16 : 8;
+       }
+       data->ngpio = base - pdata->base;
+
+       /* NOTE:  these chips have a relatively sane IRQ framework, with
+        * per-signal masking and level/edge triggering.  It's not yet
+        * handled here...
+        */
+
+       if (pdata->setup) {
+               status = pdata->setup(spi,
+                               pdata->base, data->ngpio,
+                               pdata->context);
+               if (status < 0)
+                       dev_dbg(&spi->dev, "setup --> %d\n", status);
+       }
+
+       return 0;
+
+fail:
+       for (addr = 0; addr < ARRAY_SIZE(data->mcp); addr++) {
+               int tmp;
+
+               if (!data->mcp[addr])
+                       continue;
+               tmp = gpiochip_remove(&data->mcp[addr]->chip);
+               if (tmp < 0)
+                       dev_err(&spi->dev, "%s --> %d\n", "remove", tmp);
+       }
+       kfree(data);
+       return status;
+}
+
+static int mcp23s08_remove(struct spi_device *spi)
+{
+       struct mcp23s08_driver_data     *data = spi_get_drvdata(spi);
+       struct mcp23s08_platform_data   *pdata = spi->dev.platform_data;
+       unsigned                        addr;
+       int                             status = 0;
+
+       if (pdata->teardown) {
+               status = pdata->teardown(spi,
+                               pdata->base, data->ngpio,
+                               pdata->context);
+               if (status < 0) {
+                       dev_err(&spi->dev, "%s --> %d\n", "teardown", status);
+                       return status;
+               }
+       }
+
+       for (addr = 0; addr < ARRAY_SIZE(data->mcp); addr++) {
+               int tmp;
+
+               if (!data->mcp[addr])
+                       continue;
+
+               tmp = gpiochip_remove(&data->mcp[addr]->chip);
+               if (tmp < 0) {
+                       dev_err(&spi->dev, "%s --> %d\n", "remove", tmp);
+                       status = tmp;
+               }
+       }
+       if (status == 0)
+               kfree(data);
+       return status;
+}
+
+static const struct spi_device_id mcp23s08_ids[] = {
+       { "mcp23s08", MCP_TYPE_S08 },
+       { "mcp23s17", MCP_TYPE_S17 },
+       { },
+};
+MODULE_DEVICE_TABLE(spi, mcp23s08_ids);
+
+static struct spi_driver mcp23s08_driver = {
+       .probe          = mcp23s08_probe,
+       .remove         = mcp23s08_remove,
+       .id_table       = mcp23s08_ids,
+       .driver = {
+               .name   = "mcp23s08",
+               .owner  = THIS_MODULE,
+       },
+};
+
+/*----------------------------------------------------------------------*/
+
+static int __init mcp23s08_init(void)
+{
+       return spi_register_driver(&mcp23s08_driver);
+}
+/* register after spi postcore initcall and before
+ * subsys initcalls that may rely on these GPIOs
+ */
+subsys_initcall(mcp23s08_init);
+
+static void __exit mcp23s08_exit(void)
+{
+       spi_unregister_driver(&mcp23s08_driver);
+}
+module_exit(mcp23s08_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/gpio-ml-ioh.c b/drivers/gpio/gpio-ml-ioh.c
new file mode 100644 (file)
index 0000000..1bc621a
--- /dev/null
@@ -0,0 +1,357 @@
+/*
+ * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD.
+ *
+ * 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; version 2 of the License.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <linux/gpio.h>
+
+#define PCI_VENDOR_ID_ROHM             0x10DB
+
+struct ioh_reg_comn {
+       u32     ien;
+       u32     istatus;
+       u32     idisp;
+       u32     iclr;
+       u32     imask;
+       u32     imaskclr;
+       u32     po;
+       u32     pi;
+       u32     pm;
+       u32     im_0;
+       u32     im_1;
+       u32     reserved;
+};
+
+struct ioh_regs {
+       struct ioh_reg_comn regs[8];
+       u32 reserve1[16];
+       u32 ioh_sel_reg[4];
+       u32 reserve2[11];
+       u32 srst;
+};
+
+/**
+ * struct ioh_gpio_reg_data - The register store data.
+ * @po_reg:    To store contents of PO register.
+ * @pm_reg:    To store contents of PM register.
+ */
+struct ioh_gpio_reg_data {
+       u32 po_reg;
+       u32 pm_reg;
+};
+
+/**
+ * struct ioh_gpio - GPIO private data structure.
+ * @base:                      PCI base address of Memory mapped I/O register.
+ * @reg:                       Memory mapped IOH GPIO register list.
+ * @dev:                       Pointer to device structure.
+ * @gpio:                      Data for GPIO infrastructure.
+ * @ioh_gpio_reg:              Memory mapped Register data is saved here
+ *                             when suspend.
+ * @ch:                                Indicate GPIO channel
+ */
+struct ioh_gpio {
+       void __iomem *base;
+       struct ioh_regs __iomem *reg;
+       struct device *dev;
+       struct gpio_chip gpio;
+       struct ioh_gpio_reg_data ioh_gpio_reg;
+       struct mutex lock;
+       int ch;
+};
+
+static const int num_ports[] = {6, 12, 16, 16, 15, 16, 16, 12};
+
+static void ioh_gpio_set(struct gpio_chip *gpio, unsigned nr, int val)
+{
+       u32 reg_val;
+       struct ioh_gpio *chip = container_of(gpio, struct ioh_gpio, gpio);
+
+       mutex_lock(&chip->lock);
+       reg_val = ioread32(&chip->reg->regs[chip->ch].po);
+       if (val)
+               reg_val |= (1 << nr);
+       else
+               reg_val &= ~(1 << nr);
+
+       iowrite32(reg_val, &chip->reg->regs[chip->ch].po);
+       mutex_unlock(&chip->lock);
+}
+
+static int ioh_gpio_get(struct gpio_chip *gpio, unsigned nr)
+{
+       struct ioh_gpio *chip = container_of(gpio, struct ioh_gpio, gpio);
+
+       return ioread32(&chip->reg->regs[chip->ch].pi) & (1 << nr);
+}
+
+static int ioh_gpio_direction_output(struct gpio_chip *gpio, unsigned nr,
+                                    int val)
+{
+       struct ioh_gpio *chip = container_of(gpio, struct ioh_gpio, gpio);
+       u32 pm;
+       u32 reg_val;
+
+       mutex_lock(&chip->lock);
+       pm = ioread32(&chip->reg->regs[chip->ch].pm) &
+                                       ((1 << num_ports[chip->ch]) - 1);
+       pm |= (1 << nr);
+       iowrite32(pm, &chip->reg->regs[chip->ch].pm);
+
+       reg_val = ioread32(&chip->reg->regs[chip->ch].po);
+       if (val)
+               reg_val |= (1 << nr);
+       else
+               reg_val &= ~(1 << nr);
+       iowrite32(reg_val, &chip->reg->regs[chip->ch].po);
+
+       mutex_unlock(&chip->lock);
+
+       return 0;
+}
+
+static int ioh_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
+{
+       struct ioh_gpio *chip = container_of(gpio, struct ioh_gpio, gpio);
+       u32 pm;
+
+       mutex_lock(&chip->lock);
+       pm = ioread32(&chip->reg->regs[chip->ch].pm) &
+                               ((1 << num_ports[chip->ch]) - 1);
+       pm &= ~(1 << nr);
+       iowrite32(pm, &chip->reg->regs[chip->ch].pm);
+       mutex_unlock(&chip->lock);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM
+/*
+ * Save register configuration and disable interrupts.
+ */
+static void ioh_gpio_save_reg_conf(struct ioh_gpio *chip)
+{
+       chip->ioh_gpio_reg.po_reg = ioread32(&chip->reg->regs[chip->ch].po);
+       chip->ioh_gpio_reg.pm_reg = ioread32(&chip->reg->regs[chip->ch].pm);
+}
+
+/*
+ * This function restores the register configuration of the GPIO device.
+ */
+static void ioh_gpio_restore_reg_conf(struct ioh_gpio *chip)
+{
+       /* to store contents of PO register */
+       iowrite32(chip->ioh_gpio_reg.po_reg, &chip->reg->regs[chip->ch].po);
+       /* to store contents of PM register */
+       iowrite32(chip->ioh_gpio_reg.pm_reg, &chip->reg->regs[chip->ch].pm);
+}
+#endif
+
+static void ioh_gpio_setup(struct ioh_gpio *chip, int num_port)
+{
+       struct gpio_chip *gpio = &chip->gpio;
+
+       gpio->label = dev_name(chip->dev);
+       gpio->owner = THIS_MODULE;
+       gpio->direction_input = ioh_gpio_direction_input;
+       gpio->get = ioh_gpio_get;
+       gpio->direction_output = ioh_gpio_direction_output;
+       gpio->set = ioh_gpio_set;
+       gpio->dbg_show = NULL;
+       gpio->base = -1;
+       gpio->ngpio = num_port;
+       gpio->can_sleep = 0;
+}
+
+static int __devinit ioh_gpio_probe(struct pci_dev *pdev,
+                                   const struct pci_device_id *id)
+{
+       int ret;
+       int i;
+       struct ioh_gpio *chip;
+       void __iomem *base;
+       void __iomem *chip_save;
+
+       ret = pci_enable_device(pdev);
+       if (ret) {
+               dev_err(&pdev->dev, "%s : pci_enable_device failed", __func__);
+               goto err_pci_enable;
+       }
+
+       ret = pci_request_regions(pdev, KBUILD_MODNAME);
+       if (ret) {
+               dev_err(&pdev->dev, "pci_request_regions failed-%d", ret);
+               goto err_request_regions;
+       }
+
+       base = pci_iomap(pdev, 1, 0);
+       if (base == 0) {
+               dev_err(&pdev->dev, "%s : pci_iomap failed", __func__);
+               ret = -ENOMEM;
+               goto err_iomap;
+       }
+
+       chip_save = kzalloc(sizeof(*chip) * 8, GFP_KERNEL);
+       if (chip_save == NULL) {
+               dev_err(&pdev->dev, "%s : kzalloc failed", __func__);
+               ret = -ENOMEM;
+               goto err_kzalloc;
+       }
+
+       chip = chip_save;
+       for (i = 0; i < 8; i++, chip++) {
+               chip->dev = &pdev->dev;
+               chip->base = base;
+               chip->reg = chip->base;
+               chip->ch = i;
+               mutex_init(&chip->lock);
+               ioh_gpio_setup(chip, num_ports[i]);
+               ret = gpiochip_add(&chip->gpio);
+               if (ret) {
+                       dev_err(&pdev->dev, "IOH gpio: Failed to register GPIO\n");
+                       goto err_gpiochip_add;
+               }
+       }
+
+       chip = chip_save;
+       pci_set_drvdata(pdev, chip);
+
+       return 0;
+
+err_gpiochip_add:
+       for (; i != 0; i--) {
+               chip--;
+               ret = gpiochip_remove(&chip->gpio);
+               if (ret)
+                       dev_err(&pdev->dev, "Failed gpiochip_remove(%d)\n", i);
+       }
+       kfree(chip_save);
+
+err_kzalloc:
+       pci_iounmap(pdev, base);
+
+err_iomap:
+       pci_release_regions(pdev);
+
+err_request_regions:
+       pci_disable_device(pdev);
+
+err_pci_enable:
+
+       dev_err(&pdev->dev, "%s Failed returns %d\n", __func__, ret);
+       return ret;
+}
+
+static void __devexit ioh_gpio_remove(struct pci_dev *pdev)
+{
+       int err;
+       int i;
+       struct ioh_gpio *chip = pci_get_drvdata(pdev);
+       void __iomem *chip_save;
+
+       chip_save = chip;
+       for (i = 0; i < 8; i++, chip++) {
+               err = gpiochip_remove(&chip->gpio);
+               if (err)
+                       dev_err(&pdev->dev, "Failed gpiochip_remove\n");
+       }
+
+       chip = chip_save;
+       pci_iounmap(pdev, chip->base);
+       pci_release_regions(pdev);
+       pci_disable_device(pdev);
+       kfree(chip);
+}
+
+#ifdef CONFIG_PM
+static int ioh_gpio_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+       s32 ret;
+       struct ioh_gpio *chip = pci_get_drvdata(pdev);
+
+       ioh_gpio_save_reg_conf(chip);
+       ioh_gpio_restore_reg_conf(chip);
+
+       ret = pci_save_state(pdev);
+       if (ret) {
+               dev_err(&pdev->dev, "pci_save_state Failed-%d\n", ret);
+               return ret;
+       }
+       pci_disable_device(pdev);
+       pci_set_power_state(pdev, PCI_D0);
+       ret = pci_enable_wake(pdev, PCI_D0, 1);
+       if (ret)
+               dev_err(&pdev->dev, "pci_enable_wake Failed -%d\n", ret);
+
+       return 0;
+}
+
+static int ioh_gpio_resume(struct pci_dev *pdev)
+{
+       s32 ret;
+       struct ioh_gpio *chip = pci_get_drvdata(pdev);
+
+       ret = pci_enable_wake(pdev, PCI_D0, 0);
+
+       pci_set_power_state(pdev, PCI_D0);
+       ret = pci_enable_device(pdev);
+       if (ret) {
+               dev_err(&pdev->dev, "pci_enable_device Failed-%d ", ret);
+               return ret;
+       }
+       pci_restore_state(pdev);
+
+       iowrite32(0x01, &chip->reg->srst);
+       iowrite32(0x00, &chip->reg->srst);
+       ioh_gpio_restore_reg_conf(chip);
+
+       return 0;
+}
+#else
+#define ioh_gpio_suspend NULL
+#define ioh_gpio_resume NULL
+#endif
+
+static DEFINE_PCI_DEVICE_TABLE(ioh_gpio_pcidev_id) = {
+       { PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x802E) },
+       { 0, }
+};
+MODULE_DEVICE_TABLE(pci, ioh_gpio_pcidev_id);
+
+static struct pci_driver ioh_gpio_driver = {
+       .name = "ml_ioh_gpio",
+       .id_table = ioh_gpio_pcidev_id,
+       .probe = ioh_gpio_probe,
+       .remove = __devexit_p(ioh_gpio_remove),
+       .suspend = ioh_gpio_suspend,
+       .resume = ioh_gpio_resume
+};
+
+static int __init ioh_gpio_pci_init(void)
+{
+       return pci_register_driver(&ioh_gpio_driver);
+}
+module_init(ioh_gpio_pci_init);
+
+static void __exit ioh_gpio_pci_exit(void)
+{
+       pci_unregister_driver(&ioh_gpio_driver);
+}
+module_exit(ioh_gpio_pci_exit);
+
+MODULE_DESCRIPTION("OKI SEMICONDUCTOR ML-IOH series GPIO Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c
new file mode 100644 (file)
index 0000000..a610864
--- /dev/null
@@ -0,0 +1,768 @@
+/*
+ *  PCA953x 4/8/16 bit I/O ports
+ *
+ *  Copyright (C) 2005 Ben Gardner <bgardner@wabtec.com>
+ *  Copyright (C) 2007 Marvell International Ltd.
+ *
+ *  Derived from drivers/i2c/chips/pca9539.c
+ *
+ *  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; version 2 of the License.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/i2c.h>
+#include <linux/i2c/pca953x.h>
+#include <linux/slab.h>
+#ifdef CONFIG_OF_GPIO
+#include <linux/of_platform.h>
+#include <linux/of_gpio.h>
+#endif
+
+#define PCA953X_INPUT          0
+#define PCA953X_OUTPUT         1
+#define PCA953X_INVERT         2
+#define PCA953X_DIRECTION      3
+
+#define PCA957X_IN             0
+#define PCA957X_INVRT          1
+#define PCA957X_BKEN           2
+#define PCA957X_PUPD           3
+#define PCA957X_CFG            4
+#define PCA957X_OUT            5
+#define PCA957X_MSK            6
+#define PCA957X_INTS           7
+
+#define PCA_GPIO_MASK          0x00FF
+#define PCA_INT                        0x0100
+#define PCA953X_TYPE           0x1000
+#define PCA957X_TYPE           0x2000
+
+static const struct i2c_device_id pca953x_id[] = {
+       { "pca9534", 8  | PCA953X_TYPE | PCA_INT, },
+       { "pca9535", 16 | PCA953X_TYPE | PCA_INT, },
+       { "pca9536", 4  | PCA953X_TYPE, },
+       { "pca9537", 4  | PCA953X_TYPE | PCA_INT, },
+       { "pca9538", 8  | PCA953X_TYPE | PCA_INT, },
+       { "pca9539", 16 | PCA953X_TYPE | PCA_INT, },
+       { "pca9554", 8  | PCA953X_TYPE | PCA_INT, },
+       { "pca9555", 16 | PCA953X_TYPE | PCA_INT, },
+       { "pca9556", 8  | PCA953X_TYPE, },
+       { "pca9557", 8  | PCA953X_TYPE, },
+       { "pca9574", 8  | PCA957X_TYPE | PCA_INT, },
+       { "pca9575", 16 | PCA957X_TYPE | PCA_INT, },
+
+       { "max7310", 8  | PCA953X_TYPE, },
+       { "max7312", 16 | PCA953X_TYPE | PCA_INT, },
+       { "max7313", 16 | PCA953X_TYPE | PCA_INT, },
+       { "max7315", 8  | PCA953X_TYPE | PCA_INT, },
+       { "pca6107", 8  | PCA953X_TYPE | PCA_INT, },
+       { "tca6408", 8  | PCA953X_TYPE | PCA_INT, },
+       { "tca6416", 16 | PCA953X_TYPE | PCA_INT, },
+       /* NYET:  { "tca6424", 24, }, */
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, pca953x_id);
+
+struct pca953x_chip {
+       unsigned gpio_start;
+       uint16_t reg_output;
+       uint16_t reg_direction;
+       struct mutex i2c_lock;
+
+#ifdef CONFIG_GPIO_PCA953X_IRQ
+       struct mutex irq_lock;
+       uint16_t irq_mask;
+       uint16_t irq_stat;
+       uint16_t irq_trig_raise;
+       uint16_t irq_trig_fall;
+       int      irq_base;
+#endif
+
+       struct i2c_client *client;
+       struct pca953x_platform_data *dyn_pdata;
+       struct gpio_chip gpio_chip;
+       const char *const *names;
+       int     chip_type;
+};
+
+static int pca953x_write_reg(struct pca953x_chip *chip, int reg, uint16_t val)
+{
+       int ret = 0;
+
+       if (chip->gpio_chip.ngpio <= 8)
+               ret = i2c_smbus_write_byte_data(chip->client, reg, val);
+       else {
+               switch (chip->chip_type) {
+               case PCA953X_TYPE:
+                       ret = i2c_smbus_write_word_data(chip->client,
+                                                       reg << 1, val);
+                       break;
+               case PCA957X_TYPE:
+                       ret = i2c_smbus_write_byte_data(chip->client, reg << 1,
+                                                       val & 0xff);
+                       if (ret < 0)
+                               break;
+                       ret = i2c_smbus_write_byte_data(chip->client,
+                                                       (reg << 1) + 1,
+                                                       (val & 0xff00) >> 8);
+                       break;
+               }
+       }
+
+       if (ret < 0) {
+               dev_err(&chip->client->dev, "failed writing register\n");
+               return ret;
+       }
+
+       return 0;
+}
+
+static int pca953x_read_reg(struct pca953x_chip *chip, int reg, uint16_t *val)
+{
+       int ret;
+
+       if (chip->gpio_chip.ngpio <= 8)
+               ret = i2c_smbus_read_byte_data(chip->client, reg);
+       else
+               ret = i2c_smbus_read_word_data(chip->client, reg << 1);
+
+       if (ret < 0) {
+               dev_err(&chip->client->dev, "failed reading register\n");
+               return ret;
+       }
+
+       *val = (uint16_t)ret;
+       return 0;
+}
+
+static int pca953x_gpio_direction_input(struct gpio_chip *gc, unsigned off)
+{
+       struct pca953x_chip *chip;
+       uint16_t reg_val;
+       int ret, offset = 0;
+
+       chip = container_of(gc, struct pca953x_chip, gpio_chip);
+
+       mutex_lock(&chip->i2c_lock);
+       reg_val = chip->reg_direction | (1u << off);
+
+       switch (chip->chip_type) {
+       case PCA953X_TYPE:
+               offset = PCA953X_DIRECTION;
+               break;
+       case PCA957X_TYPE:
+               offset = PCA957X_CFG;
+               break;
+       }
+       ret = pca953x_write_reg(chip, offset, reg_val);
+       if (ret)
+               goto exit;
+
+       chip->reg_direction = reg_val;
+       ret = 0;
+exit:
+       mutex_unlock(&chip->i2c_lock);
+       return ret;
+}
+
+static int pca953x_gpio_direction_output(struct gpio_chip *gc,
+               unsigned off, int val)
+{
+       struct pca953x_chip *chip;
+       uint16_t reg_val;
+       int ret, offset = 0;
+
+       chip = container_of(gc, struct pca953x_chip, gpio_chip);
+
+       mutex_lock(&chip->i2c_lock);
+       /* set output level */
+       if (val)
+               reg_val = chip->reg_output | (1u << off);
+       else
+               reg_val = chip->reg_output & ~(1u << off);
+
+       switch (chip->chip_type) {
+       case PCA953X_TYPE:
+               offset = PCA953X_OUTPUT;
+               break;
+       case PCA957X_TYPE:
+               offset = PCA957X_OUT;
+               break;
+       }
+       ret = pca953x_write_reg(chip, offset, reg_val);
+       if (ret)
+               goto exit;
+
+       chip->reg_output = reg_val;
+
+       /* then direction */
+       reg_val = chip->reg_direction & ~(1u << off);
+       switch (chip->chip_type) {
+       case PCA953X_TYPE:
+               offset = PCA953X_DIRECTION;
+               break;
+       case PCA957X_TYPE:
+               offset = PCA957X_CFG;
+               break;
+       }
+       ret = pca953x_write_reg(chip, offset, reg_val);
+       if (ret)
+               goto exit;
+
+       chip->reg_direction = reg_val;
+       ret = 0;
+exit:
+       mutex_unlock(&chip->i2c_lock);
+       return ret;
+}
+
+static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off)
+{
+       struct pca953x_chip *chip;
+       uint16_t reg_val;
+       int ret, offset = 0;
+
+       chip = container_of(gc, struct pca953x_chip, gpio_chip);
+
+       mutex_lock(&chip->i2c_lock);
+       switch (chip->chip_type) {
+       case PCA953X_TYPE:
+               offset = PCA953X_INPUT;
+               break;
+       case PCA957X_TYPE:
+               offset = PCA957X_IN;
+               break;
+       }
+       ret = pca953x_read_reg(chip, offset, &reg_val);
+       mutex_unlock(&chip->i2c_lock);
+       if (ret < 0) {
+               /* NOTE:  diagnostic already emitted; that's all we should
+                * do unless gpio_*_value_cansleep() calls become different
+                * from their nonsleeping siblings (and report faults).
+                */
+               return 0;
+       }
+
+       return (reg_val & (1u << off)) ? 1 : 0;
+}
+
+static void pca953x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val)
+{
+       struct pca953x_chip *chip;
+       uint16_t reg_val;
+       int ret, offset = 0;
+
+       chip = container_of(gc, struct pca953x_chip, gpio_chip);
+
+       mutex_lock(&chip->i2c_lock);
+       if (val)
+               reg_val = chip->reg_output | (1u << off);
+       else
+               reg_val = chip->reg_output & ~(1u << off);
+
+       switch (chip->chip_type) {
+       case PCA953X_TYPE:
+               offset = PCA953X_OUTPUT;
+               break;
+       case PCA957X_TYPE:
+               offset = PCA957X_OUT;
+               break;
+       }
+       ret = pca953x_write_reg(chip, offset, reg_val);
+       if (ret)
+               goto exit;
+
+       chip->reg_output = reg_val;
+exit:
+       mutex_unlock(&chip->i2c_lock);
+}
+
+static void pca953x_setup_gpio(struct pca953x_chip *chip, int gpios)
+{
+       struct gpio_chip *gc;
+
+       gc = &chip->gpio_chip;
+
+       gc->direction_input  = pca953x_gpio_direction_input;
+       gc->direction_output = pca953x_gpio_direction_output;
+       gc->get = pca953x_gpio_get_value;
+       gc->set = pca953x_gpio_set_value;
+       gc->can_sleep = 1;
+
+       gc->base = chip->gpio_start;
+       gc->ngpio = gpios;
+       gc->label = chip->client->name;
+       gc->dev = &chip->client->dev;
+       gc->owner = THIS_MODULE;
+       gc->names = chip->names;
+}
+
+#ifdef CONFIG_GPIO_PCA953X_IRQ
+static int pca953x_gpio_to_irq(struct gpio_chip *gc, unsigned off)
+{
+       struct pca953x_chip *chip;
+
+       chip = container_of(gc, struct pca953x_chip, gpio_chip);
+       return chip->irq_base + off;
+}
+
+static void pca953x_irq_mask(struct irq_data *d)
+{
+       struct pca953x_chip *chip = irq_data_get_irq_chip_data(d);
+
+       chip->irq_mask &= ~(1 << (d->irq - chip->irq_base));
+}
+
+static void pca953x_irq_unmask(struct irq_data *d)
+{
+       struct pca953x_chip *chip = irq_data_get_irq_chip_data(d);
+
+       chip->irq_mask |= 1 << (d->irq - chip->irq_base);
+}
+
+static void pca953x_irq_bus_lock(struct irq_data *d)
+{
+       struct pca953x_chip *chip = irq_data_get_irq_chip_data(d);
+
+       mutex_lock(&chip->irq_lock);
+}
+
+static void pca953x_irq_bus_sync_unlock(struct irq_data *d)
+{
+       struct pca953x_chip *chip = irq_data_get_irq_chip_data(d);
+       uint16_t new_irqs;
+       uint16_t level;
+
+       /* Look for any newly setup interrupt */
+       new_irqs = chip->irq_trig_fall | chip->irq_trig_raise;
+       new_irqs &= ~chip->reg_direction;
+
+       while (new_irqs) {
+               level = __ffs(new_irqs);
+               pca953x_gpio_direction_input(&chip->gpio_chip, level);
+               new_irqs &= ~(1 << level);
+       }
+
+       mutex_unlock(&chip->irq_lock);
+}
+
+static int pca953x_irq_set_type(struct irq_data *d, unsigned int type)
+{
+       struct pca953x_chip *chip = irq_data_get_irq_chip_data(d);
+       uint16_t level = d->irq - chip->irq_base;
+       uint16_t mask = 1 << level;
+
+       if (!(type & IRQ_TYPE_EDGE_BOTH)) {
+               dev_err(&chip->client->dev, "irq %d: unsupported type %d\n",
+                       d->irq, type);
+               return -EINVAL;
+       }
+
+       if (type & IRQ_TYPE_EDGE_FALLING)
+               chip->irq_trig_fall |= mask;
+       else
+               chip->irq_trig_fall &= ~mask;
+
+       if (type & IRQ_TYPE_EDGE_RISING)
+               chip->irq_trig_raise |= mask;
+       else
+               chip->irq_trig_raise &= ~mask;
+
+       return 0;
+}
+
+static struct irq_chip pca953x_irq_chip = {
+       .name                   = "pca953x",
+       .irq_mask               = pca953x_irq_mask,
+       .irq_unmask             = pca953x_irq_unmask,
+       .irq_bus_lock           = pca953x_irq_bus_lock,
+       .irq_bus_sync_unlock    = pca953x_irq_bus_sync_unlock,
+       .irq_set_type           = pca953x_irq_set_type,
+};
+
+static uint16_t pca953x_irq_pending(struct pca953x_chip *chip)
+{
+       uint16_t cur_stat;
+       uint16_t old_stat;
+       uint16_t pending;
+       uint16_t trigger;
+       int ret, offset = 0;
+
+       switch (chip->chip_type) {
+       case PCA953X_TYPE:
+               offset = PCA953X_INPUT;
+               break;
+       case PCA957X_TYPE:
+               offset = PCA957X_IN;
+               break;
+       }
+       ret = pca953x_read_reg(chip, offset, &cur_stat);
+       if (ret)
+               return 0;
+
+       /* Remove output pins from the equation */
+       cur_stat &= chip->reg_direction;
+
+       old_stat = chip->irq_stat;
+       trigger = (cur_stat ^ old_stat) & chip->irq_mask;
+
+       if (!trigger)
+               return 0;
+
+       chip->irq_stat = cur_stat;
+
+       pending = (old_stat & chip->irq_trig_fall) |
+                 (cur_stat & chip->irq_trig_raise);
+       pending &= trigger;
+
+       return pending;
+}
+
+static irqreturn_t pca953x_irq_handler(int irq, void *devid)
+{
+       struct pca953x_chip *chip = devid;
+       uint16_t pending;
+       uint16_t level;
+
+       pending = pca953x_irq_pending(chip);
+
+       if (!pending)
+               return IRQ_HANDLED;
+
+       do {
+               level = __ffs(pending);
+               generic_handle_irq(level + chip->irq_base);
+
+               pending &= ~(1 << level);
+       } while (pending);
+
+       return IRQ_HANDLED;
+}
+
+static int pca953x_irq_setup(struct pca953x_chip *chip,
+                            const struct i2c_device_id *id)
+{
+       struct i2c_client *client = chip->client;
+       struct pca953x_platform_data *pdata = client->dev.platform_data;
+       int ret, offset = 0;
+
+       if (pdata->irq_base != -1
+                       && (id->driver_data & PCA_INT)) {
+               int lvl;
+
+               switch (chip->chip_type) {
+               case PCA953X_TYPE:
+                       offset = PCA953X_INPUT;
+                       break;
+               case PCA957X_TYPE:
+                       offset = PCA957X_IN;
+                       break;
+               }
+               ret = pca953x_read_reg(chip, offset, &chip->irq_stat);
+               if (ret)
+                       goto out_failed;
+
+               /*
+                * There is no way to know which GPIO line generated the
+                * interrupt.  We have to rely on the previous read for
+                * this purpose.
+                */
+               chip->irq_stat &= chip->reg_direction;
+               chip->irq_base = pdata->irq_base;
+               mutex_init(&chip->irq_lock);
+
+               for (lvl = 0; lvl < chip->gpio_chip.ngpio; lvl++) {
+                       int irq = lvl + chip->irq_base;
+
+                       irq_set_chip_data(irq, chip);
+                       irq_set_chip_and_handler(irq, &pca953x_irq_chip,
+                                                handle_simple_irq);
+#ifdef CONFIG_ARM
+                       set_irq_flags(irq, IRQF_VALID);
+#else
+                       irq_set_noprobe(irq);
+#endif
+               }
+
+               ret = request_threaded_irq(client->irq,
+                                          NULL,
+                                          pca953x_irq_handler,
+                                          IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+                                          dev_name(&client->dev), chip);
+               if (ret) {
+                       dev_err(&client->dev, "failed to request irq %d\n",
+                               client->irq);
+                       goto out_failed;
+               }
+
+               chip->gpio_chip.to_irq = pca953x_gpio_to_irq;
+       }
+
+       return 0;
+
+out_failed:
+       chip->irq_base = -1;
+       return ret;
+}
+
+static void pca953x_irq_teardown(struct pca953x_chip *chip)
+{
+       if (chip->irq_base != -1)
+               free_irq(chip->client->irq, chip);
+}
+#else /* CONFIG_GPIO_PCA953X_IRQ */
+static int pca953x_irq_setup(struct pca953x_chip *chip,
+                            const struct i2c_device_id *id)
+{
+       struct i2c_client *client = chip->client;
+       struct pca953x_platform_data *pdata = client->dev.platform_data;
+
+       if (pdata->irq_base != -1 && (id->driver_data & PCA_INT))
+               dev_warn(&client->dev, "interrupt support not compiled in\n");
+
+       return 0;
+}
+
+static void pca953x_irq_teardown(struct pca953x_chip *chip)
+{
+}
+#endif
+
+/*
+ * Handlers for alternative sources of platform_data
+ */
+#ifdef CONFIG_OF_GPIO
+/*
+ * Translate OpenFirmware node properties into platform_data
+ */
+static struct pca953x_platform_data *
+pca953x_get_alt_pdata(struct i2c_client *client)
+{
+       struct pca953x_platform_data *pdata;
+       struct device_node *node;
+       const __be32 *val;
+       int size;
+
+       node = client->dev.of_node;
+       if (node == NULL)
+               return NULL;
+
+       pdata = kzalloc(sizeof(struct pca953x_platform_data), GFP_KERNEL);
+       if (pdata == NULL) {
+               dev_err(&client->dev, "Unable to allocate platform_data\n");
+               return NULL;
+       }
+
+       pdata->gpio_base = -1;
+       val = of_get_property(node, "linux,gpio-base", &size);
+       if (val) {
+               if (size != sizeof(*val))
+                       dev_warn(&client->dev, "%s: wrong linux,gpio-base\n",
+                                node->full_name);
+               else
+                       pdata->gpio_base = be32_to_cpup(val);
+       }
+
+       val = of_get_property(node, "polarity", NULL);
+       if (val)
+               pdata->invert = *val;
+
+       return pdata;
+}
+#else
+static struct pca953x_platform_data *
+pca953x_get_alt_pdata(struct i2c_client *client)
+{
+       return NULL;
+}
+#endif
+
+static int __devinit device_pca953x_init(struct pca953x_chip *chip, int invert)
+{
+       int ret;
+
+       ret = pca953x_read_reg(chip, PCA953X_OUTPUT, &chip->reg_output);
+       if (ret)
+               goto out;
+
+       ret = pca953x_read_reg(chip, PCA953X_DIRECTION,
+                              &chip->reg_direction);
+       if (ret)
+               goto out;
+
+       /* set platform specific polarity inversion */
+       ret = pca953x_write_reg(chip, PCA953X_INVERT, invert);
+       if (ret)
+               goto out;
+       return 0;
+out:
+       return ret;
+}
+
+static int __devinit device_pca957x_init(struct pca953x_chip *chip, int invert)
+{
+       int ret;
+       uint16_t val = 0;
+
+       /* Let every port in proper state, that could save power */
+       pca953x_write_reg(chip, PCA957X_PUPD, 0x0);
+       pca953x_write_reg(chip, PCA957X_CFG, 0xffff);
+       pca953x_write_reg(chip, PCA957X_OUT, 0x0);
+
+       ret = pca953x_read_reg(chip, PCA957X_IN, &val);
+       if (ret)
+               goto out;
+       ret = pca953x_read_reg(chip, PCA957X_OUT, &chip->reg_output);
+       if (ret)
+               goto out;
+       ret = pca953x_read_reg(chip, PCA957X_CFG, &chip->reg_direction);
+       if (ret)
+               goto out;
+
+       /* set platform specific polarity inversion */
+       pca953x_write_reg(chip, PCA957X_INVRT, invert);
+
+       /* To enable register 6, 7 to controll pull up and pull down */
+       pca953x_write_reg(chip, PCA957X_BKEN, 0x202);
+
+       return 0;
+out:
+       return ret;
+}
+
+static int __devinit pca953x_probe(struct i2c_client *client,
+                                  const struct i2c_device_id *id)
+{
+       struct pca953x_platform_data *pdata;
+       struct pca953x_chip *chip;
+       int ret = 0;
+
+       chip = kzalloc(sizeof(struct pca953x_chip), GFP_KERNEL);
+       if (chip == NULL)
+               return -ENOMEM;
+
+       pdata = client->dev.platform_data;
+       if (pdata == NULL) {
+               pdata = pca953x_get_alt_pdata(client);
+               /*
+                * Unlike normal platform_data, this is allocated
+                * dynamically and must be freed in the driver
+                */
+               chip->dyn_pdata = pdata;
+       }
+
+       if (pdata == NULL) {
+               dev_dbg(&client->dev, "no platform data\n");
+               ret = -EINVAL;
+               goto out_failed;
+       }
+
+       chip->client = client;
+
+       chip->gpio_start = pdata->gpio_base;
+
+       chip->names = pdata->names;
+       chip->chip_type = id->driver_data & (PCA953X_TYPE | PCA957X_TYPE);
+
+       mutex_init(&chip->i2c_lock);
+
+       /* initialize cached registers from their original values.
+        * we can't share this chip with another i2c master.
+        */
+       pca953x_setup_gpio(chip, id->driver_data & PCA_GPIO_MASK);
+
+       if (chip->chip_type == PCA953X_TYPE)
+               device_pca953x_init(chip, pdata->invert);
+       else if (chip->chip_type == PCA957X_TYPE)
+               device_pca957x_init(chip, pdata->invert);
+       else
+               goto out_failed;
+
+       ret = pca953x_irq_setup(chip, id);
+       if (ret)
+               goto out_failed;
+
+       ret = gpiochip_add(&chip->gpio_chip);
+       if (ret)
+               goto out_failed_irq;
+
+       if (pdata->setup) {
+               ret = pdata->setup(client, chip->gpio_chip.base,
+                               chip->gpio_chip.ngpio, pdata->context);
+               if (ret < 0)
+                       dev_warn(&client->dev, "setup failed, %d\n", ret);
+       }
+
+       i2c_set_clientdata(client, chip);
+       return 0;
+
+out_failed_irq:
+       pca953x_irq_teardown(chip);
+out_failed:
+       kfree(chip->dyn_pdata);
+       kfree(chip);
+       return ret;
+}
+
+static int pca953x_remove(struct i2c_client *client)
+{
+       struct pca953x_platform_data *pdata = client->dev.platform_data;
+       struct pca953x_chip *chip = i2c_get_clientdata(client);
+       int ret = 0;
+
+       if (pdata->teardown) {
+               ret = pdata->teardown(client, chip->gpio_chip.base,
+                               chip->gpio_chip.ngpio, pdata->context);
+               if (ret < 0) {
+                       dev_err(&client->dev, "%s failed, %d\n",
+                                       "teardown", ret);
+                       return ret;
+               }
+       }
+
+       ret = gpiochip_remove(&chip->gpio_chip);
+       if (ret) {
+               dev_err(&client->dev, "%s failed, %d\n",
+                               "gpiochip_remove()", ret);
+               return ret;
+       }
+
+       pca953x_irq_teardown(chip);
+       kfree(chip->dyn_pdata);
+       kfree(chip);
+       return 0;
+}
+
+static struct i2c_driver pca953x_driver = {
+       .driver = {
+               .name   = "pca953x",
+       },
+       .probe          = pca953x_probe,
+       .remove         = pca953x_remove,
+       .id_table       = pca953x_id,
+};
+
+static int __init pca953x_init(void)
+{
+       return i2c_add_driver(&pca953x_driver);
+}
+/* register after i2c postcore initcall and before
+ * subsys initcalls that may rely on these GPIOs
+ */
+subsys_initcall(pca953x_init);
+
+static void __exit pca953x_exit(void)
+{
+       i2c_del_driver(&pca953x_driver);
+}
+module_exit(pca953x_exit);
+
+MODULE_AUTHOR("eric miao <eric.miao@marvell.com>");
+MODULE_DESCRIPTION("GPIO expander driver for PCA953x");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/gpio-pcf857x.c b/drivers/gpio/gpio-pcf857x.c
new file mode 100644 (file)
index 0000000..7369fdd
--- /dev/null
@@ -0,0 +1,369 @@
+/*
+ * Driver for pcf857x, pca857x, and pca967x I2C GPIO expanders
+ *
+ * Copyright (C) 2007 David Brownell
+ *
+ * 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.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * 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>
+
+
+static const struct i2c_device_id pcf857x_id[] = {
+       { "pcf8574", 8 },
+       { "pcf8574a", 8 },
+       { "pca8574", 8 },
+       { "pca9670", 8 },
+       { "pca9672", 8 },
+       { "pca9674", 8 },
+       { "pcf8575", 16 },
+       { "pca8575", 16 },
+       { "pca9671", 16 },
+       { "pca9673", 16 },
+       { "pca9675", 16 },
+       { "max7328", 8 },
+       { "max7329", 8 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, pcf857x_id);
+
+/*
+ * The pcf857x, pca857x, and pca967x chips only expose one read and one
+ * write register.  Writing a "one" bit (to match the reset state) lets
+ * that pin be used as an input; it's not an open-drain model, but acts
+ * a bit like one.  This is described as "quasi-bidirectional"; read the
+ * chip documentation for details.
+ *
+ * Many other I2C GPIO expander chips (like the pca953x models) have
+ * more complex register models and more conventional circuitry using
+ * push/pull drivers.  They often use the same 0x20..0x27 addresses as
+ * pcf857x parts, making the "legacy" I2C driver model problematic.
+ */
+struct pcf857x {
+       struct gpio_chip        chip;
+       struct i2c_client       *client;
+       struct mutex            lock;           /* protect 'out' */
+       unsigned                out;            /* software latch */
+};
+
+/*-------------------------------------------------------------------------*/
+
+/* Talk to 8-bit I/O expander */
+
+static int pcf857x_input8(struct gpio_chip *chip, unsigned offset)
+{
+       struct pcf857x  *gpio = container_of(chip, struct pcf857x, chip);
+       int             status;
+
+       mutex_lock(&gpio->lock);
+       gpio->out |= (1 << offset);
+       status = i2c_smbus_write_byte(gpio->client, gpio->out);
+       mutex_unlock(&gpio->lock);
+
+       return status;
+}
+
+static int pcf857x_get8(struct gpio_chip *chip, unsigned offset)
+{
+       struct pcf857x  *gpio = container_of(chip, struct pcf857x, chip);
+       s32             value;
+
+       value = i2c_smbus_read_byte(gpio->client);
+       return (value < 0) ? 0 : (value & (1 << offset));
+}
+
+static int pcf857x_output8(struct gpio_chip *chip, unsigned offset, int value)
+{
+       struct pcf857x  *gpio = container_of(chip, struct pcf857x, chip);
+       unsigned        bit = 1 << offset;
+       int             status;
+
+       mutex_lock(&gpio->lock);
+       if (value)
+               gpio->out |= bit;
+       else
+               gpio->out &= ~bit;
+       status = i2c_smbus_write_byte(gpio->client, gpio->out);
+       mutex_unlock(&gpio->lock);
+
+       return status;
+}
+
+static void pcf857x_set8(struct gpio_chip *chip, unsigned offset, int value)
+{
+       pcf857x_output8(chip, offset, value);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* Talk to 16-bit I/O expander */
+
+static int i2c_write_le16(struct i2c_client *client, u16 word)
+{
+       u8 buf[2] = { word & 0xff, word >> 8, };
+       int status;
+
+       status = i2c_master_send(client, buf, 2);
+       return (status < 0) ? status : 0;
+}
+
+static int i2c_read_le16(struct i2c_client *client)
+{
+       u8 buf[2];
+       int status;
+
+       status = i2c_master_recv(client, buf, 2);
+       if (status < 0)
+               return status;
+       return (buf[1] << 8) | buf[0];
+}
+
+static int pcf857x_input16(struct gpio_chip *chip, unsigned offset)
+{
+       struct pcf857x  *gpio = container_of(chip, struct pcf857x, chip);
+       int             status;
+
+       mutex_lock(&gpio->lock);
+       gpio->out |= (1 << offset);
+       status = i2c_write_le16(gpio->client, gpio->out);
+       mutex_unlock(&gpio->lock);
+
+       return status;
+}
+
+static int pcf857x_get16(struct gpio_chip *chip, unsigned offset)
+{
+       struct pcf857x  *gpio = container_of(chip, struct pcf857x, chip);
+       int             value;
+
+       value = i2c_read_le16(gpio->client);
+       return (value < 0) ? 0 : (value & (1 << offset));
+}
+
+static int pcf857x_output16(struct gpio_chip *chip, unsigned offset, int value)
+{
+       struct pcf857x  *gpio = container_of(chip, struct pcf857x, chip);
+       unsigned        bit = 1 << offset;
+       int             status;
+
+       mutex_lock(&gpio->lock);
+       if (value)
+               gpio->out |= bit;
+       else
+               gpio->out &= ~bit;
+       status = i2c_write_le16(gpio->client, gpio->out);
+       mutex_unlock(&gpio->lock);
+
+       return status;
+}
+
+static void pcf857x_set16(struct gpio_chip *chip, unsigned offset, int value)
+{
+       pcf857x_output16(chip, offset, value);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int pcf857x_probe(struct i2c_client *client,
+                        const struct i2c_device_id *id)
+{
+       struct pcf857x_platform_data    *pdata;
+       struct pcf857x                  *gpio;
+       int                             status;
+
+       pdata = client->dev.platform_data;
+       if (!pdata) {
+               dev_dbg(&client->dev, "no platform data\n");
+       }
+
+       /* Allocate, initialize, and register this gpio_chip. */
+       gpio = kzalloc(sizeof *gpio, GFP_KERNEL);
+       if (!gpio)
+               return -ENOMEM;
+
+       mutex_init(&gpio->lock);
+
+       gpio->chip.base = pdata ? pdata->gpio_base : -1;
+       gpio->chip.can_sleep = 1;
+       gpio->chip.dev = &client->dev;
+       gpio->chip.owner = THIS_MODULE;
+
+       /* NOTE:  the OnSemi jlc1562b is also largely compatible with
+        * these parts, notably for output.  It has a low-resolution
+        * DAC instead of pin change IRQs; and its inputs can be the
+        * result of comparators.
+        */
+
+       /* 8574 addresses are 0x20..0x27; 8574a uses 0x38..0x3f;
+        * 9670, 9672, 9764, and 9764a use quite a variety.
+        *
+        * NOTE: we don't distinguish here between *4 and *4a parts.
+        */
+       gpio->chip.ngpio = id->driver_data;
+       if (gpio->chip.ngpio == 8) {
+               gpio->chip.direction_input = pcf857x_input8;
+               gpio->chip.get = pcf857x_get8;
+               gpio->chip.direction_output = pcf857x_output8;
+               gpio->chip.set = pcf857x_set8;
+
+               if (!i2c_check_functionality(client->adapter,
+                               I2C_FUNC_SMBUS_BYTE))
+                       status = -EIO;
+
+               /* fail if there's no chip present */
+               else
+                       status = i2c_smbus_read_byte(client);
+
+       /* '75/'75c addresses are 0x20..0x27, just like the '74;
+        * the '75c doesn't have a current source pulling high.
+        * 9671, 9673, and 9765 use quite a variety of addresses.
+        *
+        * NOTE: we don't distinguish here between '75 and '75c parts.
+        */
+       } else if (gpio->chip.ngpio == 16) {
+               gpio->chip.direction_input = pcf857x_input16;
+               gpio->chip.get = pcf857x_get16;
+               gpio->chip.direction_output = pcf857x_output16;
+               gpio->chip.set = pcf857x_set16;
+
+               if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
+                       status = -EIO;
+
+               /* fail if there's no chip present */
+               else
+                       status = i2c_read_le16(client);
+
+       } else {
+               dev_dbg(&client->dev, "unsupported number of gpios\n");
+               status = -EINVAL;
+       }
+
+       if (status < 0)
+               goto fail;
+
+       gpio->chip.label = client->name;
+
+       gpio->client = client;
+       i2c_set_clientdata(client, gpio);
+
+       /* NOTE:  these chips have strange "quasi-bidirectional" I/O pins.
+        * We can't actually know whether a pin is configured (a) as output
+        * and driving the signal low, or (b) as input and reporting a low
+        * value ... without knowing the last value written since the chip
+        * came out of reset (if any).  We can't read the latched output.
+        *
+        * In short, the only reliable solution for setting up pin direction
+        * is to do it explicitly.  The setup() method can do that, but it
+        * may cause transient glitching since it can't know the last value
+        * written (some pins may need to be driven low).
+        *
+        * Using pdata->n_latch avoids that trouble.  When left initialized
+        * to zero, our software copy of the "latch" then matches the chip's
+        * all-ones reset state.  Otherwise it flags pins to be driven low.
+        */
+       gpio->out = pdata ? ~pdata->n_latch : ~0;
+
+       status = gpiochip_add(&gpio->chip);
+       if (status < 0)
+               goto fail;
+
+       /* NOTE: these chips can issue "some pin-changed" IRQs, which we
+        * don't yet even try to use.  Among other issues, the relevant
+        * genirq state isn't available to modular drivers; and most irq
+        * methods can't be called from sleeping contexts.
+        */
+
+       dev_info(&client->dev, "gpios %d..%d on a %s%s\n",
+                       gpio->chip.base,
+                       gpio->chip.base + gpio->chip.ngpio - 1,
+                       client->name,
+                       client->irq ? " (irq ignored)" : "");
+
+       /* Let platform code set up the GPIOs and their users.
+        * Now is the first time anyone could use them.
+        */
+       if (pdata && pdata->setup) {
+               status = pdata->setup(client,
+                               gpio->chip.base, gpio->chip.ngpio,
+                               pdata->context);
+               if (status < 0)
+                       dev_warn(&client->dev, "setup --> %d\n", status);
+       }
+
+       return 0;
+
+fail:
+       dev_dbg(&client->dev, "probe error %d for '%s'\n",
+                       status, client->name);
+       kfree(gpio);
+       return status;
+}
+
+static int pcf857x_remove(struct i2c_client *client)
+{
+       struct pcf857x_platform_data    *pdata = client->dev.platform_data;
+       struct pcf857x                  *gpio = i2c_get_clientdata(client);
+       int                             status = 0;
+
+       if (pdata && pdata->teardown) {
+               status = pdata->teardown(client,
+                               gpio->chip.base, gpio->chip.ngpio,
+                               pdata->context);
+               if (status < 0) {
+                       dev_err(&client->dev, "%s --> %d\n",
+                                       "teardown", status);
+                       return status;
+               }
+       }
+
+       status = gpiochip_remove(&gpio->chip);
+       if (status == 0)
+               kfree(gpio);
+       else
+               dev_err(&client->dev, "%s --> %d\n", "remove", status);
+       return status;
+}
+
+static struct i2c_driver pcf857x_driver = {
+       .driver = {
+               .name   = "pcf857x",
+               .owner  = THIS_MODULE,
+       },
+       .probe  = pcf857x_probe,
+       .remove = pcf857x_remove,
+       .id_table = pcf857x_id,
+};
+
+static int __init pcf857x_init(void)
+{
+       return i2c_add_driver(&pcf857x_driver);
+}
+/* register after i2c postcore initcall and before
+ * subsys initcalls that may rely on these GPIOs
+ */
+subsys_initcall(pcf857x_init);
+
+static void __exit pcf857x_exit(void)
+{
+       i2c_del_driver(&pcf857x_driver);
+}
+module_exit(pcf857x_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("David Brownell");
diff --git a/drivers/gpio/gpio-pch.c b/drivers/gpio/gpio-pch.c
new file mode 100644 (file)
index 0000000..36919e7
--- /dev/null
@@ -0,0 +1,316 @@
+/*
+ * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD.
+ *
+ * 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; version 2 of the License.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/gpio.h>
+
+#define PCH_GPIO_ALL_PINS      0xfff /* Mask for GPIO pins 0 to 11 */
+#define GPIO_NUM_PINS  12      /* Specifies number of GPIO PINS GPIO0-GPIO11 */
+
+struct pch_regs {
+       u32     ien;
+       u32     istatus;
+       u32     idisp;
+       u32     iclr;
+       u32     imask;
+       u32     imaskclr;
+       u32     po;
+       u32     pi;
+       u32     pm;
+       u32     im0;
+       u32     im1;
+       u32     reserved[4];
+       u32     reset;
+};
+
+/**
+ * struct pch_gpio_reg_data - The register store data.
+ * @po_reg:    To store contents of PO register.
+ * @pm_reg:    To store contents of PM register.
+ */
+struct pch_gpio_reg_data {
+       u32 po_reg;
+       u32 pm_reg;
+};
+
+/**
+ * struct pch_gpio - GPIO private data structure.
+ * @base:                      PCI base address of Memory mapped I/O register.
+ * @reg:                       Memory mapped PCH GPIO register list.
+ * @dev:                       Pointer to device structure.
+ * @gpio:                      Data for GPIO infrastructure.
+ * @pch_gpio_reg:              Memory mapped Register data is saved here
+ *                             when suspend.
+ */
+struct pch_gpio {
+       void __iomem *base;
+       struct pch_regs __iomem *reg;
+       struct device *dev;
+       struct gpio_chip gpio;
+       struct pch_gpio_reg_data pch_gpio_reg;
+       struct mutex lock;
+};
+
+static void pch_gpio_set(struct gpio_chip *gpio, unsigned nr, int val)
+{
+       u32 reg_val;
+       struct pch_gpio *chip = container_of(gpio, struct pch_gpio, gpio);
+
+       mutex_lock(&chip->lock);
+       reg_val = ioread32(&chip->reg->po);
+       if (val)
+               reg_val |= (1 << nr);
+       else
+               reg_val &= ~(1 << nr);
+
+       iowrite32(reg_val, &chip->reg->po);
+       mutex_unlock(&chip->lock);
+}
+
+static int pch_gpio_get(struct gpio_chip *gpio, unsigned nr)
+{
+       struct pch_gpio *chip = container_of(gpio, struct pch_gpio, gpio);
+
+       return ioread32(&chip->reg->pi) & (1 << nr);
+}
+
+static int pch_gpio_direction_output(struct gpio_chip *gpio, unsigned nr,
+                                    int val)
+{
+       struct pch_gpio *chip = container_of(gpio, struct pch_gpio, gpio);
+       u32 pm;
+       u32 reg_val;
+
+       mutex_lock(&chip->lock);
+       pm = ioread32(&chip->reg->pm) & PCH_GPIO_ALL_PINS;
+       pm |= (1 << nr);
+       iowrite32(pm, &chip->reg->pm);
+
+       reg_val = ioread32(&chip->reg->po);
+       if (val)
+               reg_val |= (1 << nr);
+       else
+               reg_val &= ~(1 << nr);
+       iowrite32(reg_val, &chip->reg->po);
+
+       mutex_unlock(&chip->lock);
+
+       return 0;
+}
+
+static int pch_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
+{
+       struct pch_gpio *chip = container_of(gpio, struct pch_gpio, gpio);
+       u32 pm;
+
+       mutex_lock(&chip->lock);
+       pm = ioread32(&chip->reg->pm) & PCH_GPIO_ALL_PINS; /*bits 0-11*/
+       pm &= ~(1 << nr);
+       iowrite32(pm, &chip->reg->pm);
+       mutex_unlock(&chip->lock);
+
+       return 0;
+}
+
+/*
+ * Save register configuration and disable interrupts.
+ */
+static void pch_gpio_save_reg_conf(struct pch_gpio *chip)
+{
+       chip->pch_gpio_reg.po_reg = ioread32(&chip->reg->po);
+       chip->pch_gpio_reg.pm_reg = ioread32(&chip->reg->pm);
+}
+
+/*
+ * This function restores the register configuration of the GPIO device.
+ */
+static void pch_gpio_restore_reg_conf(struct pch_gpio *chip)
+{
+       /* to store contents of PO register */
+       iowrite32(chip->pch_gpio_reg.po_reg, &chip->reg->po);
+       /* to store contents of PM register */
+       iowrite32(chip->pch_gpio_reg.pm_reg, &chip->reg->pm);
+}
+
+static void pch_gpio_setup(struct pch_gpio *chip)
+{
+       struct gpio_chip *gpio = &chip->gpio;
+
+       gpio->label = dev_name(chip->dev);
+       gpio->owner = THIS_MODULE;
+       gpio->direction_input = pch_gpio_direction_input;
+       gpio->get = pch_gpio_get;
+       gpio->direction_output = pch_gpio_direction_output;
+       gpio->set = pch_gpio_set;
+       gpio->dbg_show = NULL;
+       gpio->base = -1;
+       gpio->ngpio = GPIO_NUM_PINS;
+       gpio->can_sleep = 0;
+}
+
+static int __devinit pch_gpio_probe(struct pci_dev *pdev,
+                                   const struct pci_device_id *id)
+{
+       s32 ret;
+       struct pch_gpio *chip;
+
+       chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+       if (chip == NULL)
+               return -ENOMEM;
+
+       chip->dev = &pdev->dev;
+       ret = pci_enable_device(pdev);
+       if (ret) {
+               dev_err(&pdev->dev, "%s : pci_enable_device FAILED", __func__);
+               goto err_pci_enable;
+       }
+
+       ret = pci_request_regions(pdev, KBUILD_MODNAME);
+       if (ret) {
+               dev_err(&pdev->dev, "pci_request_regions FAILED-%d", ret);
+               goto err_request_regions;
+       }
+
+       chip->base = pci_iomap(pdev, 1, 0);
+       if (chip->base == 0) {
+               dev_err(&pdev->dev, "%s : pci_iomap FAILED", __func__);
+               ret = -ENOMEM;
+               goto err_iomap;
+       }
+
+       chip->reg = chip->base;
+       pci_set_drvdata(pdev, chip);
+       mutex_init(&chip->lock);
+       pch_gpio_setup(chip);
+       ret = gpiochip_add(&chip->gpio);
+       if (ret) {
+               dev_err(&pdev->dev, "PCH gpio: Failed to register GPIO\n");
+               goto err_gpiochip_add;
+       }
+
+       return 0;
+
+err_gpiochip_add:
+       pci_iounmap(pdev, chip->base);
+
+err_iomap:
+       pci_release_regions(pdev);
+
+err_request_regions:
+       pci_disable_device(pdev);
+
+err_pci_enable:
+       kfree(chip);
+       dev_err(&pdev->dev, "%s Failed returns %d\n", __func__, ret);
+       return ret;
+}
+
+static void __devexit pch_gpio_remove(struct pci_dev *pdev)
+{
+       int err;
+       struct pch_gpio *chip = pci_get_drvdata(pdev);
+
+       err = gpiochip_remove(&chip->gpio);
+       if (err)
+               dev_err(&pdev->dev, "Failed gpiochip_remove\n");
+
+       pci_iounmap(pdev, chip->base);
+       pci_release_regions(pdev);
+       pci_disable_device(pdev);
+       kfree(chip);
+}
+
+#ifdef CONFIG_PM
+static int pch_gpio_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+       s32 ret;
+       struct pch_gpio *chip = pci_get_drvdata(pdev);
+
+       pch_gpio_save_reg_conf(chip);
+       pch_gpio_restore_reg_conf(chip);
+
+       ret = pci_save_state(pdev);
+       if (ret) {
+               dev_err(&pdev->dev, "pci_save_state Failed-%d\n", ret);
+               return ret;
+       }
+       pci_disable_device(pdev);
+       pci_set_power_state(pdev, PCI_D0);
+       ret = pci_enable_wake(pdev, PCI_D0, 1);
+       if (ret)
+               dev_err(&pdev->dev, "pci_enable_wake Failed -%d\n", ret);
+
+       return 0;
+}
+
+static int pch_gpio_resume(struct pci_dev *pdev)
+{
+       s32 ret;
+       struct pch_gpio *chip = pci_get_drvdata(pdev);
+
+       ret = pci_enable_wake(pdev, PCI_D0, 0);
+
+       pci_set_power_state(pdev, PCI_D0);
+       ret = pci_enable_device(pdev);
+       if (ret) {
+               dev_err(&pdev->dev, "pci_enable_device Failed-%d ", ret);
+               return ret;
+       }
+       pci_restore_state(pdev);
+
+       iowrite32(0x01, &chip->reg->reset);
+       iowrite32(0x00, &chip->reg->reset);
+       pch_gpio_restore_reg_conf(chip);
+
+       return 0;
+}
+#else
+#define pch_gpio_suspend NULL
+#define pch_gpio_resume NULL
+#endif
+
+#define PCI_VENDOR_ID_ROHM             0x10DB
+static DEFINE_PCI_DEVICE_TABLE(pch_gpio_pcidev_id) = {
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8803) },
+       { PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8014) },
+       { 0, }
+};
+MODULE_DEVICE_TABLE(pci, pch_gpio_pcidev_id);
+
+static struct pci_driver pch_gpio_driver = {
+       .name = "pch_gpio",
+       .id_table = pch_gpio_pcidev_id,
+       .probe = pch_gpio_probe,
+       .remove = __devexit_p(pch_gpio_remove),
+       .suspend = pch_gpio_suspend,
+       .resume = pch_gpio_resume
+};
+
+static int __init pch_gpio_pci_init(void)
+{
+       return pci_register_driver(&pch_gpio_driver);
+}
+module_init(pch_gpio_pci_init);
+
+static void __exit pch_gpio_pci_exit(void)
+{
+       pci_unregister_driver(&pch_gpio_driver);
+}
+module_exit(pch_gpio_pci_exit);
+
+MODULE_DESCRIPTION("PCH GPIO PCI Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/gpio-pl061.c b/drivers/gpio/gpio-pl061.c
new file mode 100644 (file)
index 0000000..2c5a18f
--- /dev/null
@@ -0,0 +1,358 @@
+/*
+ * Copyright (C) 2008, 2009 Provigent 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.
+ *
+ * Driver for the ARM PrimeCell(tm) General Purpose Input/Output (PL061)
+ *
+ * Data sheet: ARM DDI 0190B, September 2000
+ */
+#include <linux/spinlock.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/list.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/irq.h>
+#include <linux/bitops.h>
+#include <linux/workqueue.h>
+#include <linux/gpio.h>
+#include <linux/device.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/pl061.h>
+#include <linux/slab.h>
+
+#define GPIODIR 0x400
+#define GPIOIS  0x404
+#define GPIOIBE 0x408
+#define GPIOIEV 0x40C
+#define GPIOIE  0x410
+#define GPIORIS 0x414
+#define GPIOMIS 0x418
+#define GPIOIC  0x41C
+
+#define PL061_GPIO_NR  8
+
+struct pl061_gpio {
+       /* We use a list of pl061_gpio structs for each trigger IRQ in the main
+        * interrupts controller of the system. We need this to support systems
+        * in which more that one PL061s are connected to the same IRQ. The ISR
+        * interates through this list to find the source of the interrupt.
+        */
+       struct list_head        list;
+
+       /* Each of the two spinlocks protects a different set of hardware
+        * regiters and data structurs. This decouples the code of the IRQ from
+        * the GPIO code. This also makes the case of a GPIO routine call from
+        * the IRQ code simpler.
+        */
+       spinlock_t              lock;           /* GPIO registers */
+       spinlock_t              irq_lock;       /* IRQ registers */
+
+       void __iomem            *base;
+       unsigned                irq_base;
+       struct gpio_chip        gc;
+};
+
+static int pl061_direction_input(struct gpio_chip *gc, unsigned offset)
+{
+       struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
+       unsigned long flags;
+       unsigned char gpiodir;
+
+       if (offset >= gc->ngpio)
+               return -EINVAL;
+
+       spin_lock_irqsave(&chip->lock, flags);
+       gpiodir = readb(chip->base + GPIODIR);
+       gpiodir &= ~(1 << offset);
+       writeb(gpiodir, chip->base + GPIODIR);
+       spin_unlock_irqrestore(&chip->lock, flags);
+
+       return 0;
+}
+
+static int pl061_direction_output(struct gpio_chip *gc, unsigned offset,
+               int value)
+{
+       struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
+       unsigned long flags;
+       unsigned char gpiodir;
+
+       if (offset >= gc->ngpio)
+               return -EINVAL;
+
+       spin_lock_irqsave(&chip->lock, flags);
+       writeb(!!value << offset, chip->base + (1 << (offset + 2)));
+       gpiodir = readb(chip->base + GPIODIR);
+       gpiodir |= 1 << offset;
+       writeb(gpiodir, chip->base + GPIODIR);
+
+       /*
+        * gpio value is set again, because pl061 doesn't allow to set value of
+        * a gpio pin before configuring it in OUT mode.
+        */
+       writeb(!!value << offset, chip->base + (1 << (offset + 2)));
+       spin_unlock_irqrestore(&chip->lock, flags);
+
+       return 0;
+}
+
+static int pl061_get_value(struct gpio_chip *gc, unsigned offset)
+{
+       struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
+
+       return !!readb(chip->base + (1 << (offset + 2)));
+}
+
+static void pl061_set_value(struct gpio_chip *gc, unsigned offset, int value)
+{
+       struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
+
+       writeb(!!value << offset, chip->base + (1 << (offset + 2)));
+}
+
+static int pl061_to_irq(struct gpio_chip *gc, unsigned offset)
+{
+       struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
+
+       if (chip->irq_base == (unsigned) -1)
+               return -EINVAL;
+
+       return chip->irq_base + offset;
+}
+
+/*
+ * PL061 GPIO IRQ
+ */
+static void pl061_irq_disable(struct irq_data *d)
+{
+       struct pl061_gpio *chip = irq_data_get_irq_chip_data(d);
+       int offset = d->irq - chip->irq_base;
+       unsigned long flags;
+       u8 gpioie;
+
+       spin_lock_irqsave(&chip->irq_lock, flags);
+       gpioie = readb(chip->base + GPIOIE);
+       gpioie &= ~(1 << offset);
+       writeb(gpioie, chip->base + GPIOIE);
+       spin_unlock_irqrestore(&chip->irq_lock, flags);
+}
+
+static void pl061_irq_enable(struct irq_data *d)
+{
+       struct pl061_gpio *chip = irq_data_get_irq_chip_data(d);
+       int offset = d->irq - chip->irq_base;
+       unsigned long flags;
+       u8 gpioie;
+
+       spin_lock_irqsave(&chip->irq_lock, flags);
+       gpioie = readb(chip->base + GPIOIE);
+       gpioie |= 1 << offset;
+       writeb(gpioie, chip->base + GPIOIE);
+       spin_unlock_irqrestore(&chip->irq_lock, flags);
+}
+
+static int pl061_irq_type(struct irq_data *d, unsigned trigger)
+{
+       struct pl061_gpio *chip = irq_data_get_irq_chip_data(d);
+       int offset = d->irq - chip->irq_base;
+       unsigned long flags;
+       u8 gpiois, gpioibe, gpioiev;
+
+       if (offset < 0 || offset >= PL061_GPIO_NR)
+               return -EINVAL;
+
+       spin_lock_irqsave(&chip->irq_lock, flags);
+
+       gpioiev = readb(chip->base + GPIOIEV);
+
+       gpiois = readb(chip->base + GPIOIS);
+       if (trigger & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {
+               gpiois |= 1 << offset;
+               if (trigger & IRQ_TYPE_LEVEL_HIGH)
+                       gpioiev |= 1 << offset;
+               else
+                       gpioiev &= ~(1 << offset);
+       } else
+               gpiois &= ~(1 << offset);
+       writeb(gpiois, chip->base + GPIOIS);
+
+       gpioibe = readb(chip->base + GPIOIBE);
+       if ((trigger & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH)
+               gpioibe |= 1 << offset;
+       else {
+               gpioibe &= ~(1 << offset);
+               if (trigger & IRQ_TYPE_EDGE_RISING)
+                       gpioiev |= 1 << offset;
+               else if (trigger & IRQ_TYPE_EDGE_FALLING)
+                       gpioiev &= ~(1 << offset);
+       }
+       writeb(gpioibe, chip->base + GPIOIBE);
+
+       writeb(gpioiev, chip->base + GPIOIEV);
+
+       spin_unlock_irqrestore(&chip->irq_lock, flags);
+
+       return 0;
+}
+
+static struct irq_chip pl061_irqchip = {
+       .name           = "GPIO",
+       .irq_enable     = pl061_irq_enable,
+       .irq_disable    = pl061_irq_disable,
+       .irq_set_type   = pl061_irq_type,
+};
+
+static void pl061_irq_handler(unsigned irq, struct irq_desc *desc)
+{
+       struct list_head *chip_list = irq_get_handler_data(irq);
+       struct list_head *ptr;
+       struct pl061_gpio *chip;
+
+       desc->irq_data.chip->irq_ack(&desc->irq_data);
+       list_for_each(ptr, chip_list) {
+               unsigned long pending;
+               int offset;
+
+               chip = list_entry(ptr, struct pl061_gpio, list);
+               pending = readb(chip->base + GPIOMIS);
+               writeb(pending, chip->base + GPIOIC);
+
+               if (pending == 0)
+                       continue;
+
+               for_each_set_bit(offset, &pending, PL061_GPIO_NR)
+                       generic_handle_irq(pl061_to_irq(&chip->gc, offset));
+       }
+       desc->irq_data.chip->irq_unmask(&desc->irq_data);
+}
+
+static int pl061_probe(struct amba_device *dev, const struct amba_id *id)
+{
+       struct pl061_platform_data *pdata;
+       struct pl061_gpio *chip;
+       struct list_head *chip_list;
+       int ret, irq, i;
+       static DECLARE_BITMAP(init_irq, NR_IRQS);
+
+       pdata = dev->dev.platform_data;
+       if (pdata == NULL)
+               return -ENODEV;
+
+       chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+       if (chip == NULL)
+               return -ENOMEM;
+
+       if (!request_mem_region(dev->res.start,
+                               resource_size(&dev->res), "pl061")) {
+               ret = -EBUSY;
+               goto free_mem;
+       }
+
+       chip->base = ioremap(dev->res.start, resource_size(&dev->res));
+       if (chip->base == NULL) {
+               ret = -ENOMEM;
+               goto release_region;
+       }
+
+       spin_lock_init(&chip->lock);
+       spin_lock_init(&chip->irq_lock);
+       INIT_LIST_HEAD(&chip->list);
+
+       chip->gc.direction_input = pl061_direction_input;
+       chip->gc.direction_output = pl061_direction_output;
+       chip->gc.get = pl061_get_value;
+       chip->gc.set = pl061_set_value;
+       chip->gc.to_irq = pl061_to_irq;
+       chip->gc.base = pdata->gpio_base;
+       chip->gc.ngpio = PL061_GPIO_NR;
+       chip->gc.label = dev_name(&dev->dev);
+       chip->gc.dev = &dev->dev;
+       chip->gc.owner = THIS_MODULE;
+
+       chip->irq_base = pdata->irq_base;
+
+       ret = gpiochip_add(&chip->gc);
+       if (ret)
+               goto iounmap;
+
+       /*
+        * irq_chip support
+        */
+
+       if (chip->irq_base == (unsigned) -1)
+               return 0;
+
+       writeb(0, chip->base + GPIOIE); /* disable irqs */
+       irq = dev->irq[0];
+       if (irq < 0) {
+               ret = -ENODEV;
+               goto iounmap;
+       }
+       irq_set_chained_handler(irq, pl061_irq_handler);
+       if (!test_and_set_bit(irq, init_irq)) { /* list initialized? */
+               chip_list = kmalloc(sizeof(*chip_list), GFP_KERNEL);
+               if (chip_list == NULL) {
+                       clear_bit(irq, init_irq);
+                       ret = -ENOMEM;
+                       goto iounmap;
+               }
+               INIT_LIST_HEAD(chip_list);
+               irq_set_handler_data(irq, chip_list);
+       } else
+               chip_list = irq_get_handler_data(irq);
+       list_add(&chip->list, chip_list);
+
+       for (i = 0; i < PL061_GPIO_NR; i++) {
+               if (pdata->directions & (1 << i))
+                       pl061_direction_output(&chip->gc, i,
+                                       pdata->values & (1 << i));
+               else
+                       pl061_direction_input(&chip->gc, i);
+
+               irq_set_chip_and_handler(i + chip->irq_base, &pl061_irqchip,
+                                        handle_simple_irq);
+               set_irq_flags(i+chip->irq_base, IRQF_VALID);
+               irq_set_chip_data(i + chip->irq_base, chip);
+       }
+
+       return 0;
+
+iounmap:
+       iounmap(chip->base);
+release_region:
+       release_mem_region(dev->res.start, resource_size(&dev->res));
+free_mem:
+       kfree(chip);
+
+       return ret;
+}
+
+static struct amba_id pl061_ids[] = {
+       {
+               .id     = 0x00041061,
+               .mask   = 0x000fffff,
+       },
+       { 0, 0 },
+};
+
+static struct amba_driver pl061_gpio_driver = {
+       .drv = {
+               .name   = "pl061_gpio",
+       },
+       .id_table       = pl061_ids,
+       .probe          = pl061_probe,
+};
+
+static int __init pl061_gpio_init(void)
+{
+       return amba_driver_register(&pl061_gpio_driver);
+}
+subsys_initcall(pl061_gpio_init);
+
+MODULE_AUTHOR("Baruch Siach <baruch@tkos.co.il>");
+MODULE_DESCRIPTION("PL061 GPIO driver");
+MODULE_LICENSE("GPL");
index ea37c04617884b467f2b009a839276a5a0aa1697..ef67f1952a721f724cc2b478fe98ec6cd71e0c2b 100644 (file)
@@ -1,5 +1,4 @@
-/* arch/arm/plat-samsung/gpiolib.c
- *
+/*
  * Copyright 2008 Openmoko, Inc.
  * Copyright 2008 Simtec Electronics
  *      Ben Dooks <ben@simtec.co.uk>
diff --git a/drivers/gpio/gpio-rdc321x.c b/drivers/gpio/gpio-rdc321x.c
new file mode 100644 (file)
index 0000000..2762698
--- /dev/null
@@ -0,0 +1,246 @@
+/*
+ * RDC321x GPIO driver
+ *
+ * Copyright (C) 2008, Volker Weiss <dev@tintuc.de>
+ * Copyright (C) 2007-2010 Florian Fainelli <florian@openwrt.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.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/platform_device.h>
+#include <linux/pci.h>
+#include <linux/gpio.h>
+#include <linux/mfd/rdc321x.h>
+#include <linux/slab.h>
+
+struct rdc321x_gpio {
+       spinlock_t              lock;
+       struct pci_dev          *sb_pdev;
+       u32                     data_reg[2];
+       int                     reg1_ctrl_base;
+       int                     reg1_data_base;
+       int                     reg2_ctrl_base;
+       int                     reg2_data_base;
+       struct gpio_chip        chip;
+};
+
+/* read GPIO pin */
+static int rdc_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
+{
+       struct rdc321x_gpio *gpch;
+       u32 value = 0;
+       int reg;
+
+       gpch = container_of(chip, struct rdc321x_gpio, chip);
+       reg = gpio < 32 ? gpch->reg1_data_base : gpch->reg2_data_base;
+
+       spin_lock(&gpch->lock);
+       pci_write_config_dword(gpch->sb_pdev, reg,
+                                       gpch->data_reg[gpio < 32 ? 0 : 1]);
+       pci_read_config_dword(gpch->sb_pdev, reg, &value);
+       spin_unlock(&gpch->lock);
+
+       return (1 << (gpio & 0x1f)) & value ? 1 : 0;
+}
+
+static void rdc_gpio_set_value_impl(struct gpio_chip *chip,
+                               unsigned gpio, int value)
+{
+       struct rdc321x_gpio *gpch;
+       int reg = (gpio < 32) ? 0 : 1;
+
+       gpch = container_of(chip, struct rdc321x_gpio, chip);
+
+       if (value)
+               gpch->data_reg[reg] |= 1 << (gpio & 0x1f);
+       else
+               gpch->data_reg[reg] &= ~(1 << (gpio & 0x1f));
+
+       pci_write_config_dword(gpch->sb_pdev,
+                       reg ? gpch->reg2_data_base : gpch->reg1_data_base,
+                       gpch->data_reg[reg]);
+}
+
+/* set GPIO pin to value */
+static void rdc_gpio_set_value(struct gpio_chip *chip,
+                               unsigned gpio, int value)
+{
+       struct rdc321x_gpio *gpch;
+
+       gpch = container_of(chip, struct rdc321x_gpio, chip);
+       spin_lock(&gpch->lock);
+       rdc_gpio_set_value_impl(chip, gpio, value);
+       spin_unlock(&gpch->lock);
+}
+
+static int rdc_gpio_config(struct gpio_chip *chip,
+                               unsigned gpio, int value)
+{
+       struct rdc321x_gpio *gpch;
+       int err;
+       u32 reg;
+
+       gpch = container_of(chip, struct rdc321x_gpio, chip);
+
+       spin_lock(&gpch->lock);
+       err = pci_read_config_dword(gpch->sb_pdev, gpio < 32 ?
+                       gpch->reg1_ctrl_base : gpch->reg2_ctrl_base, &reg);
+       if (err)
+               goto unlock;
+
+       reg |= 1 << (gpio & 0x1f);
+
+       err = pci_write_config_dword(gpch->sb_pdev, gpio < 32 ?
+                       gpch->reg1_ctrl_base : gpch->reg2_ctrl_base, reg);
+       if (err)
+               goto unlock;
+
+       rdc_gpio_set_value_impl(chip, gpio, value);
+
+unlock:
+       spin_unlock(&gpch->lock);
+
+       return err;
+}
+
+/* configure GPIO pin as input */
+static int rdc_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
+{
+       return rdc_gpio_config(chip, gpio, 1);
+}
+
+/*
+ * Cache the initial value of both GPIO data registers
+ */
+static int __devinit rdc321x_gpio_probe(struct platform_device *pdev)
+{
+       int err;
+       struct resource *r;
+       struct rdc321x_gpio *rdc321x_gpio_dev;
+       struct rdc321x_gpio_pdata *pdata;
+
+       pdata = pdev->dev.platform_data;
+       if (!pdata) {
+               dev_err(&pdev->dev, "no platform data supplied\n");
+               return -ENODEV;
+       }
+
+       rdc321x_gpio_dev = kzalloc(sizeof(struct rdc321x_gpio), GFP_KERNEL);
+       if (!rdc321x_gpio_dev) {
+               dev_err(&pdev->dev, "failed to allocate private data\n");
+               return -ENOMEM;
+       }
+
+       r = platform_get_resource_byname(pdev, IORESOURCE_IO, "gpio-reg1");
+       if (!r) {
+               dev_err(&pdev->dev, "failed to get gpio-reg1 resource\n");
+               err = -ENODEV;
+               goto out_free;
+       }
+
+       spin_lock_init(&rdc321x_gpio_dev->lock);
+       rdc321x_gpio_dev->sb_pdev = pdata->sb_pdev;
+       rdc321x_gpio_dev->reg1_ctrl_base = r->start;
+       rdc321x_gpio_dev->reg1_data_base = r->start + 0x4;
+
+       r = platform_get_resource_byname(pdev, IORESOURCE_IO, "gpio-reg2");
+       if (!r) {
+               dev_err(&pdev->dev, "failed to get gpio-reg2 resource\n");
+               err = -ENODEV;
+               goto out_free;
+       }
+
+       rdc321x_gpio_dev->reg2_ctrl_base = r->start;
+       rdc321x_gpio_dev->reg2_data_base = r->start + 0x4;
+
+       rdc321x_gpio_dev->chip.label = "rdc321x-gpio";
+       rdc321x_gpio_dev->chip.direction_input = rdc_gpio_direction_input;
+       rdc321x_gpio_dev->chip.direction_output = rdc_gpio_config;
+       rdc321x_gpio_dev->chip.get = rdc_gpio_get_value;
+       rdc321x_gpio_dev->chip.set = rdc_gpio_set_value;
+       rdc321x_gpio_dev->chip.base = 0;
+       rdc321x_gpio_dev->chip.ngpio = pdata->max_gpios;
+
+       platform_set_drvdata(pdev, rdc321x_gpio_dev);
+
+       /* This might not be, what others (BIOS, bootloader, etc.)
+          wrote to these registers before, but it's a good guess. Still
+          better than just using 0xffffffff. */
+       err = pci_read_config_dword(rdc321x_gpio_dev->sb_pdev,
+                                       rdc321x_gpio_dev->reg1_data_base,
+                                       &rdc321x_gpio_dev->data_reg[0]);
+       if (err)
+               goto out_drvdata;
+
+       err = pci_read_config_dword(rdc321x_gpio_dev->sb_pdev,
+                                       rdc321x_gpio_dev->reg2_data_base,
+                                       &rdc321x_gpio_dev->data_reg[1]);
+       if (err)
+               goto out_drvdata;
+
+       dev_info(&pdev->dev, "registering %d GPIOs\n",
+                                       rdc321x_gpio_dev->chip.ngpio);
+       return gpiochip_add(&rdc321x_gpio_dev->chip);
+
+out_drvdata:
+       platform_set_drvdata(pdev, NULL);
+out_free:
+       kfree(rdc321x_gpio_dev);
+       return err;
+}
+
+static int __devexit rdc321x_gpio_remove(struct platform_device *pdev)
+{
+       int ret;
+       struct rdc321x_gpio *rdc321x_gpio_dev = platform_get_drvdata(pdev);
+
+       ret = gpiochip_remove(&rdc321x_gpio_dev->chip);
+       if (ret)
+               dev_err(&pdev->dev, "failed to unregister chip\n");
+
+       kfree(rdc321x_gpio_dev);
+       platform_set_drvdata(pdev, NULL);
+
+       return ret;
+}
+
+static struct platform_driver rdc321x_gpio_driver = {
+       .driver.name    = "rdc321x-gpio",
+       .driver.owner   = THIS_MODULE,
+       .probe          = rdc321x_gpio_probe,
+       .remove         = __devexit_p(rdc321x_gpio_remove),
+};
+
+static int __init rdc321x_gpio_init(void)
+{
+       return platform_driver_register(&rdc321x_gpio_driver);
+}
+
+static void __exit rdc321x_gpio_exit(void)
+{
+       platform_driver_unregister(&rdc321x_gpio_driver);
+}
+
+module_init(rdc321x_gpio_init);
+module_exit(rdc321x_gpio_exit);
+
+MODULE_AUTHOR("Florian Fainelli <florian@openwrt.org>");
+MODULE_DESCRIPTION("RDC321x GPIO driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:rdc321x-gpio");
index 2842394b28b5fb23a01f71fa231793c3697b2aa9..7f87b0c76e0bcca132f689b03bfe16a0fd7a396c 100644 (file)
@@ -1,4 +1,5 @@
-/* linux/arch/arm/mach-s5pc100/gpiolib.c
+/*
+ * S5PC100 - GPIOlib support
  *
  * Copyright (c) 2010 Samsung Electronics Co., Ltd.
  *             http://www.samsung.com
@@ -6,8 +7,6 @@
  *  Copyright 2009 Samsung Electronics Co
  *  Kyungmin Park <kyungmin.park@samsung.com>
  *
- * S5PC100 - GPIOlib support
- *
  * 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.
index 1ba20a703e05f839a4ac799d3cb6d4ea047abca7..eb12f1602de950fbb9a3201dedf20ad52429dd39 100644 (file)
@@ -1,10 +1,9 @@
-/* linux/arch/arm/mach-s5pv210/gpiolib.c
+/*
+ * S5PV210 - GPIOlib support
  *
  * Copyright (c) 2010 Samsung Electronics Co., Ltd.
  *             http://www.samsung.com/
  *
- * S5PV210 - GPIOlib support
- *
  * 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.
diff --git a/drivers/gpio/gpio-sch.c b/drivers/gpio/gpio-sch.c
new file mode 100644 (file)
index 0000000..1635158
--- /dev/null
@@ -0,0 +1,316 @@
+/*
+ * GPIO interface for Intel Poulsbo SCH
+ *
+ *  Copyright (c) 2010 CompuLab Ltd
+ *  Author: Denis Turischev <denis@compulab.co.il>
+ *
+ *  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.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; see the file COPYING.  If not, write to
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/errno.h>
+#include <linux/acpi.h>
+#include <linux/platform_device.h>
+#include <linux/pci_ids.h>
+
+#include <linux/gpio.h>
+
+static DEFINE_SPINLOCK(gpio_lock);
+
+#define CGEN   (0x00)
+#define CGIO   (0x04)
+#define CGLV   (0x08)
+
+#define RGEN   (0x20)
+#define RGIO   (0x24)
+#define RGLV   (0x28)
+
+static unsigned short gpio_ba;
+
+static int sch_gpio_core_direction_in(struct gpio_chip *gc, unsigned  gpio_num)
+{
+       u8 curr_dirs;
+       unsigned short offset, bit;
+
+       spin_lock(&gpio_lock);
+
+       offset = CGIO + gpio_num / 8;
+       bit = gpio_num % 8;
+
+       curr_dirs = inb(gpio_ba + offset);
+
+       if (!(curr_dirs & (1 << bit)))
+               outb(curr_dirs | (1 << bit), gpio_ba + offset);
+
+       spin_unlock(&gpio_lock);
+       return 0;
+}
+
+static int sch_gpio_core_get(struct gpio_chip *gc, unsigned gpio_num)
+{
+       int res;
+       unsigned short offset, bit;
+
+       offset = CGLV + gpio_num / 8;
+       bit = gpio_num % 8;
+
+       res = !!(inb(gpio_ba + offset) & (1 << bit));
+       return res;
+}
+
+static void sch_gpio_core_set(struct gpio_chip *gc, unsigned gpio_num, int val)
+{
+       u8 curr_vals;
+       unsigned short offset, bit;
+
+       spin_lock(&gpio_lock);
+
+       offset = CGLV + gpio_num / 8;
+       bit = gpio_num % 8;
+
+       curr_vals = inb(gpio_ba + offset);
+
+       if (val)
+               outb(curr_vals | (1 << bit), gpio_ba + offset);
+       else
+               outb((curr_vals & ~(1 << bit)), gpio_ba + offset);
+       spin_unlock(&gpio_lock);
+}
+
+static int sch_gpio_core_direction_out(struct gpio_chip *gc,
+                                       unsigned gpio_num, int val)
+{
+       u8 curr_dirs;
+       unsigned short offset, bit;
+
+       sch_gpio_core_set(gc, gpio_num, val);
+
+       spin_lock(&gpio_lock);
+
+       offset = CGIO + gpio_num / 8;
+       bit = gpio_num % 8;
+
+       curr_dirs = inb(gpio_ba + offset);
+       if (curr_dirs & (1 << bit))
+               outb(curr_dirs & ~(1 << bit), gpio_ba + offset);
+
+       spin_unlock(&gpio_lock);
+       return 0;
+}
+
+static struct gpio_chip sch_gpio_core = {
+       .label                  = "sch_gpio_core",
+       .owner                  = THIS_MODULE,
+       .direction_input        = sch_gpio_core_direction_in,
+       .get                    = sch_gpio_core_get,
+       .direction_output       = sch_gpio_core_direction_out,
+       .set                    = sch_gpio_core_set,
+};
+
+static int sch_gpio_resume_direction_in(struct gpio_chip *gc,
+                                       unsigned gpio_num)
+{
+       u8 curr_dirs;
+
+       spin_lock(&gpio_lock);
+
+       curr_dirs = inb(gpio_ba + RGIO);
+
+       if (!(curr_dirs & (1 << gpio_num)))
+               outb(curr_dirs | (1 << gpio_num) , gpio_ba + RGIO);
+
+       spin_unlock(&gpio_lock);
+       return 0;
+}
+
+static int sch_gpio_resume_get(struct gpio_chip *gc, unsigned gpio_num)
+{
+       return !!(inb(gpio_ba + RGLV) & (1 << gpio_num));
+}
+
+static void sch_gpio_resume_set(struct gpio_chip *gc,
+                               unsigned gpio_num, int val)
+{
+       u8 curr_vals;
+
+       spin_lock(&gpio_lock);
+
+       curr_vals = inb(gpio_ba + RGLV);
+
+       if (val)
+               outb(curr_vals | (1 << gpio_num), gpio_ba + RGLV);
+       else
+               outb((curr_vals & ~(1 << gpio_num)), gpio_ba + RGLV);
+
+       spin_unlock(&gpio_lock);
+}
+
+static int sch_gpio_resume_direction_out(struct gpio_chip *gc,
+                                       unsigned gpio_num, int val)
+{
+       u8 curr_dirs;
+
+       sch_gpio_resume_set(gc, gpio_num, val);
+
+       spin_lock(&gpio_lock);
+
+       curr_dirs = inb(gpio_ba + RGIO);
+       if (curr_dirs & (1 << gpio_num))
+               outb(curr_dirs & ~(1 << gpio_num), gpio_ba + RGIO);
+
+       spin_unlock(&gpio_lock);
+       return 0;
+}
+
+static struct gpio_chip sch_gpio_resume = {
+       .label                  = "sch_gpio_resume",
+       .owner                  = THIS_MODULE,
+       .direction_input        = sch_gpio_resume_direction_in,
+       .get                    = sch_gpio_resume_get,
+       .direction_output       = sch_gpio_resume_direction_out,
+       .set                    = sch_gpio_resume_set,
+};
+
+static int __devinit sch_gpio_probe(struct platform_device *pdev)
+{
+       struct resource *res;
+       int err, id;
+
+       id = pdev->id;
+       if (!id)
+               return -ENODEV;
+
+       res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+       if (!res)
+               return -EBUSY;
+
+       if (!request_region(res->start, resource_size(res), pdev->name))
+               return -EBUSY;
+
+       gpio_ba = res->start;
+
+       switch (id) {
+               case PCI_DEVICE_ID_INTEL_SCH_LPC:
+                       sch_gpio_core.base = 0;
+                       sch_gpio_core.ngpio = 10;
+
+                       sch_gpio_resume.base = 10;
+                       sch_gpio_resume.ngpio = 4;
+
+                       /*
+                        * GPIO[6:0] enabled by default
+                        * GPIO7 is configured by the CMC as SLPIOVR
+                        * Enable GPIO[9:8] core powered gpios explicitly
+                        */
+                       outb(0x3, gpio_ba + CGEN + 1);
+                       /*
+                        * SUS_GPIO[2:0] enabled by default
+                        * Enable SUS_GPIO3 resume powered gpio explicitly
+                        */
+                       outb(0x8, gpio_ba + RGEN);
+                       break;
+
+               case PCI_DEVICE_ID_INTEL_ITC_LPC:
+                       sch_gpio_core.base = 0;
+                       sch_gpio_core.ngpio = 5;
+
+                       sch_gpio_resume.base = 5;
+                       sch_gpio_resume.ngpio = 9;
+                       break;
+
+               default:
+                       return -ENODEV;
+       }
+
+       sch_gpio_core.dev = &pdev->dev;
+       sch_gpio_resume.dev = &pdev->dev;
+
+       err = gpiochip_add(&sch_gpio_core);
+       if (err < 0)
+               goto err_sch_gpio_core;
+
+       err = gpiochip_add(&sch_gpio_resume);
+       if (err < 0)
+               goto err_sch_gpio_resume;
+
+       return 0;
+
+err_sch_gpio_resume:
+       err = gpiochip_remove(&sch_gpio_core);
+       if (err)
+               dev_err(&pdev->dev, "%s failed, %d\n",
+                               "gpiochip_remove()", err);
+
+err_sch_gpio_core:
+       release_region(res->start, resource_size(res));
+       gpio_ba = 0;
+
+       return err;
+}
+
+static int __devexit sch_gpio_remove(struct platform_device *pdev)
+{
+       struct resource *res;
+       if (gpio_ba) {
+               int err;
+
+               err  = gpiochip_remove(&sch_gpio_core);
+               if (err)
+                       dev_err(&pdev->dev, "%s failed, %d\n",
+                               "gpiochip_remove()", err);
+               err = gpiochip_remove(&sch_gpio_resume);
+               if (err)
+                       dev_err(&pdev->dev, "%s failed, %d\n",
+                               "gpiochip_remove()", err);
+
+               res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+
+               release_region(res->start, resource_size(res));
+               gpio_ba = 0;
+
+               return err;
+       }
+
+       return 0;
+}
+
+static struct platform_driver sch_gpio_driver = {
+       .driver = {
+               .name = "sch_gpio",
+               .owner = THIS_MODULE,
+       },
+       .probe          = sch_gpio_probe,
+       .remove         = __devexit_p(sch_gpio_remove),
+};
+
+static int __init sch_gpio_init(void)
+{
+       return platform_driver_register(&sch_gpio_driver);
+}
+
+static void __exit sch_gpio_exit(void)
+{
+       platform_driver_unregister(&sch_gpio_driver);
+}
+
+module_init(sch_gpio_init);
+module_exit(sch_gpio_exit);
+
+MODULE_AUTHOR("Denis Turischev <denis@compulab.co.il>");
+MODULE_DESCRIPTION("GPIO interface for Intel Poulsbo SCH");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:sch_gpio");
diff --git a/drivers/gpio/gpio-stmpe.c b/drivers/gpio/gpio-stmpe.c
new file mode 100644 (file)
index 0000000..4c980b5
--- /dev/null
@@ -0,0 +1,404 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * License Terms: GNU General Public License, version 2
+ * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/gpio.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/mfd/stmpe.h>
+
+/*
+ * These registers are modified under the irq bus lock and cached to avoid
+ * unnecessary writes in bus_sync_unlock.
+ */
+enum { REG_RE, REG_FE, REG_IE };
+
+#define CACHE_NR_REGS  3
+#define CACHE_NR_BANKS (STMPE_NR_GPIOS / 8)
+
+struct stmpe_gpio {
+       struct gpio_chip chip;
+       struct stmpe *stmpe;
+       struct device *dev;
+       struct mutex irq_lock;
+
+       int irq_base;
+       unsigned norequest_mask;
+
+       /* Caches of interrupt control registers for bus_lock */
+       u8 regs[CACHE_NR_REGS][CACHE_NR_BANKS];
+       u8 oldregs[CACHE_NR_REGS][CACHE_NR_BANKS];
+};
+
+static inline struct stmpe_gpio *to_stmpe_gpio(struct gpio_chip *chip)
+{
+       return container_of(chip, struct stmpe_gpio, chip);
+}
+
+static int stmpe_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+       struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(chip);
+       struct stmpe *stmpe = stmpe_gpio->stmpe;
+       u8 reg = stmpe->regs[STMPE_IDX_GPMR_LSB] - (offset / 8);
+       u8 mask = 1 << (offset % 8);
+       int ret;
+
+       ret = stmpe_reg_read(stmpe, reg);
+       if (ret < 0)
+               return ret;
+
+       return ret & mask;
+}
+
+static void stmpe_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
+{
+       struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(chip);
+       struct stmpe *stmpe = stmpe_gpio->stmpe;
+       int which = val ? STMPE_IDX_GPSR_LSB : STMPE_IDX_GPCR_LSB;
+       u8 reg = stmpe->regs[which] - (offset / 8);
+       u8 mask = 1 << (offset % 8);
+
+       stmpe_reg_write(stmpe, reg, mask);
+}
+
+static int stmpe_gpio_direction_output(struct gpio_chip *chip,
+                                        unsigned offset, int val)
+{
+       struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(chip);
+       struct stmpe *stmpe = stmpe_gpio->stmpe;
+       u8 reg = stmpe->regs[STMPE_IDX_GPDR_LSB] - (offset / 8);
+       u8 mask = 1 << (offset % 8);
+
+       stmpe_gpio_set(chip, offset, val);
+
+       return stmpe_set_bits(stmpe, reg, mask, mask);
+}
+
+static int stmpe_gpio_direction_input(struct gpio_chip *chip,
+                                       unsigned offset)
+{
+       struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(chip);
+       struct stmpe *stmpe = stmpe_gpio->stmpe;
+       u8 reg = stmpe->regs[STMPE_IDX_GPDR_LSB] - (offset / 8);
+       u8 mask = 1 << (offset % 8);
+
+       return stmpe_set_bits(stmpe, reg, mask, 0);
+}
+
+static int stmpe_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+       struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(chip);
+
+       return stmpe_gpio->irq_base + offset;
+}
+
+static int stmpe_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+       struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(chip);
+       struct stmpe *stmpe = stmpe_gpio->stmpe;
+
+       if (stmpe_gpio->norequest_mask & (1 << offset))
+               return -EINVAL;
+
+       return stmpe_set_altfunc(stmpe, 1 << offset, STMPE_BLOCK_GPIO);
+}
+
+static struct gpio_chip template_chip = {
+       .label                  = "stmpe",
+       .owner                  = THIS_MODULE,
+       .direction_input        = stmpe_gpio_direction_input,
+       .get                    = stmpe_gpio_get,
+       .direction_output       = stmpe_gpio_direction_output,
+       .set                    = stmpe_gpio_set,
+       .to_irq                 = stmpe_gpio_to_irq,
+       .request                = stmpe_gpio_request,
+       .can_sleep              = 1,
+};
+
+static int stmpe_gpio_irq_set_type(struct irq_data *d, unsigned int type)
+{
+       struct stmpe_gpio *stmpe_gpio = irq_data_get_irq_chip_data(d);
+       int offset = d->irq - stmpe_gpio->irq_base;
+       int regoffset = offset / 8;
+       int mask = 1 << (offset % 8);
+
+       if (type == IRQ_TYPE_LEVEL_LOW || type == IRQ_TYPE_LEVEL_HIGH)
+               return -EINVAL;
+
+       if (type == IRQ_TYPE_EDGE_RISING)
+               stmpe_gpio->regs[REG_RE][regoffset] |= mask;
+       else
+               stmpe_gpio->regs[REG_RE][regoffset] &= ~mask;
+
+       if (type == IRQ_TYPE_EDGE_FALLING)
+               stmpe_gpio->regs[REG_FE][regoffset] |= mask;
+       else
+               stmpe_gpio->regs[REG_FE][regoffset] &= ~mask;
+
+       return 0;
+}
+
+static void stmpe_gpio_irq_lock(struct irq_data *d)
+{
+       struct stmpe_gpio *stmpe_gpio = irq_data_get_irq_chip_data(d);
+
+       mutex_lock(&stmpe_gpio->irq_lock);
+}
+
+static void stmpe_gpio_irq_sync_unlock(struct irq_data *d)
+{
+       struct stmpe_gpio *stmpe_gpio = irq_data_get_irq_chip_data(d);
+       struct stmpe *stmpe = stmpe_gpio->stmpe;
+       int num_banks = DIV_ROUND_UP(stmpe->num_gpios, 8);
+       static const u8 regmap[] = {
+               [REG_RE]        = STMPE_IDX_GPRER_LSB,
+               [REG_FE]        = STMPE_IDX_GPFER_LSB,
+               [REG_IE]        = STMPE_IDX_IEGPIOR_LSB,
+       };
+       int i, j;
+
+       for (i = 0; i < CACHE_NR_REGS; i++) {
+               for (j = 0; j < num_banks; j++) {
+                       u8 old = stmpe_gpio->oldregs[i][j];
+                       u8 new = stmpe_gpio->regs[i][j];
+
+                       if (new == old)
+                               continue;
+
+                       stmpe_gpio->oldregs[i][j] = new;
+                       stmpe_reg_write(stmpe, stmpe->regs[regmap[i]] - j, new);
+               }
+       }
+
+       mutex_unlock(&stmpe_gpio->irq_lock);
+}
+
+static void stmpe_gpio_irq_mask(struct irq_data *d)
+{
+       struct stmpe_gpio *stmpe_gpio = irq_data_get_irq_chip_data(d);
+       int offset = d->irq - stmpe_gpio->irq_base;
+       int regoffset = offset / 8;
+       int mask = 1 << (offset % 8);
+
+       stmpe_gpio->regs[REG_IE][regoffset] &= ~mask;
+}
+
+static void stmpe_gpio_irq_unmask(struct irq_data *d)
+{
+       struct stmpe_gpio *stmpe_gpio = irq_data_get_irq_chip_data(d);
+       int offset = d->irq - stmpe_gpio->irq_base;
+       int regoffset = offset / 8;
+       int mask = 1 << (offset % 8);
+
+       stmpe_gpio->regs[REG_IE][regoffset] |= mask;
+}
+
+static struct irq_chip stmpe_gpio_irq_chip = {
+       .name                   = "stmpe-gpio",
+       .irq_bus_lock           = stmpe_gpio_irq_lock,
+       .irq_bus_sync_unlock    = stmpe_gpio_irq_sync_unlock,
+       .irq_mask               = stmpe_gpio_irq_mask,
+       .irq_unmask             = stmpe_gpio_irq_unmask,
+       .irq_set_type           = stmpe_gpio_irq_set_type,
+};
+
+static irqreturn_t stmpe_gpio_irq(int irq, void *dev)
+{
+       struct stmpe_gpio *stmpe_gpio = dev;
+       struct stmpe *stmpe = stmpe_gpio->stmpe;
+       u8 statmsbreg = stmpe->regs[STMPE_IDX_ISGPIOR_MSB];
+       int num_banks = DIV_ROUND_UP(stmpe->num_gpios, 8);
+       u8 status[num_banks];
+       int ret;
+       int i;
+
+       ret = stmpe_block_read(stmpe, statmsbreg, num_banks, status);
+       if (ret < 0)
+               return IRQ_NONE;
+
+       for (i = 0; i < num_banks; i++) {
+               int bank = num_banks - i - 1;
+               unsigned int enabled = stmpe_gpio->regs[REG_IE][bank];
+               unsigned int stat = status[i];
+
+               stat &= enabled;
+               if (!stat)
+                       continue;
+
+               while (stat) {
+                       int bit = __ffs(stat);
+                       int line = bank * 8 + bit;
+
+                       handle_nested_irq(stmpe_gpio->irq_base + line);
+                       stat &= ~(1 << bit);
+               }
+
+               stmpe_reg_write(stmpe, statmsbreg + i, status[i]);
+               stmpe_reg_write(stmpe, stmpe->regs[STMPE_IDX_GPEDR_MSB] + i,
+                               status[i]);
+       }
+
+       return IRQ_HANDLED;
+}
+
+static int __devinit stmpe_gpio_irq_init(struct stmpe_gpio *stmpe_gpio)
+{
+       int base = stmpe_gpio->irq_base;
+       int irq;
+
+       for (irq = base; irq < base + stmpe_gpio->chip.ngpio; irq++) {
+               irq_set_chip_data(irq, stmpe_gpio);
+               irq_set_chip_and_handler(irq, &stmpe_gpio_irq_chip,
+                                        handle_simple_irq);
+               irq_set_nested_thread(irq, 1);
+#ifdef CONFIG_ARM
+               set_irq_flags(irq, IRQF_VALID);
+#else
+               irq_set_noprobe(irq);
+#endif
+       }
+
+       return 0;
+}
+
+static void stmpe_gpio_irq_remove(struct stmpe_gpio *stmpe_gpio)
+{
+       int base = stmpe_gpio->irq_base;
+       int irq;
+
+       for (irq = base; irq < base + stmpe_gpio->chip.ngpio; irq++) {
+#ifdef CONFIG_ARM
+               set_irq_flags(irq, 0);
+#endif
+               irq_set_chip_and_handler(irq, NULL, NULL);
+               irq_set_chip_data(irq, NULL);
+       }
+}
+
+static int __devinit stmpe_gpio_probe(struct platform_device *pdev)
+{
+       struct stmpe *stmpe = dev_get_drvdata(pdev->dev.parent);
+       struct stmpe_gpio_platform_data *pdata;
+       struct stmpe_gpio *stmpe_gpio;
+       int ret;
+       int irq;
+
+       pdata = stmpe->pdata->gpio;
+
+       irq = platform_get_irq(pdev, 0);
+       if (irq < 0)
+               return irq;
+
+       stmpe_gpio = kzalloc(sizeof(struct stmpe_gpio), GFP_KERNEL);
+       if (!stmpe_gpio)
+               return -ENOMEM;
+
+       mutex_init(&stmpe_gpio->irq_lock);
+
+       stmpe_gpio->dev = &pdev->dev;
+       stmpe_gpio->stmpe = stmpe;
+       stmpe_gpio->norequest_mask = pdata ? pdata->norequest_mask : 0;
+
+       stmpe_gpio->chip = template_chip;
+       stmpe_gpio->chip.ngpio = stmpe->num_gpios;
+       stmpe_gpio->chip.dev = &pdev->dev;
+       stmpe_gpio->chip.base = pdata ? pdata->gpio_base : -1;
+
+       stmpe_gpio->irq_base = stmpe->irq_base + STMPE_INT_GPIO(0);
+
+       ret = stmpe_enable(stmpe, STMPE_BLOCK_GPIO);
+       if (ret)
+               goto out_free;
+
+       ret = stmpe_gpio_irq_init(stmpe_gpio);
+       if (ret)
+               goto out_disable;
+
+       ret = request_threaded_irq(irq, NULL, stmpe_gpio_irq, IRQF_ONESHOT,
+                                  "stmpe-gpio", stmpe_gpio);
+       if (ret) {
+               dev_err(&pdev->dev, "unable to get irq: %d\n", ret);
+               goto out_removeirq;
+       }
+
+       ret = gpiochip_add(&stmpe_gpio->chip);
+       if (ret) {
+               dev_err(&pdev->dev, "unable to add gpiochip: %d\n", ret);
+               goto out_freeirq;
+       }
+
+       if (pdata && pdata->setup)
+               pdata->setup(stmpe, stmpe_gpio->chip.base);
+
+       platform_set_drvdata(pdev, stmpe_gpio);
+
+       return 0;
+
+out_freeirq:
+       free_irq(irq, stmpe_gpio);
+out_removeirq:
+       stmpe_gpio_irq_remove(stmpe_gpio);
+out_disable:
+       stmpe_disable(stmpe, STMPE_BLOCK_GPIO);
+out_free:
+       kfree(stmpe_gpio);
+       return ret;
+}
+
+static int __devexit stmpe_gpio_remove(struct platform_device *pdev)
+{
+       struct stmpe_gpio *stmpe_gpio = platform_get_drvdata(pdev);
+       struct stmpe *stmpe = stmpe_gpio->stmpe;
+       struct stmpe_gpio_platform_data *pdata = stmpe->pdata->gpio;
+       int irq = platform_get_irq(pdev, 0);
+       int ret;
+
+       if (pdata && pdata->remove)
+               pdata->remove(stmpe, stmpe_gpio->chip.base);
+
+       ret = gpiochip_remove(&stmpe_gpio->chip);
+       if (ret < 0) {
+               dev_err(stmpe_gpio->dev,
+                       "unable to remove gpiochip: %d\n", ret);
+               return ret;
+       }
+
+       stmpe_disable(stmpe, STMPE_BLOCK_GPIO);
+
+       free_irq(irq, stmpe_gpio);
+       stmpe_gpio_irq_remove(stmpe_gpio);
+       platform_set_drvdata(pdev, NULL);
+       kfree(stmpe_gpio);
+
+       return 0;
+}
+
+static struct platform_driver stmpe_gpio_driver = {
+       .driver.name    = "stmpe-gpio",
+       .driver.owner   = THIS_MODULE,
+       .probe          = stmpe_gpio_probe,
+       .remove         = __devexit_p(stmpe_gpio_remove),
+};
+
+static int __init stmpe_gpio_init(void)
+{
+       return platform_driver_register(&stmpe_gpio_driver);
+}
+subsys_initcall(stmpe_gpio_init);
+
+static void __exit stmpe_gpio_exit(void)
+{
+       platform_driver_unregister(&stmpe_gpio_driver);
+}
+module_exit(stmpe_gpio_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("STMPExxxx GPIO driver");
+MODULE_AUTHOR("Rabin Vincent <rabin.vincent@stericsson.com>");
diff --git a/drivers/gpio/gpio-sx150x.c b/drivers/gpio/gpio-sx150x.c
new file mode 100644 (file)
index 0000000..a4f7353
--- /dev/null
@@ -0,0 +1,680 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/workqueue.h>
+#include <linux/i2c/sx150x.h>
+
+#define NO_UPDATE_PENDING      -1
+
+struct sx150x_device_data {
+       u8 reg_pullup;
+       u8 reg_pulldn;
+       u8 reg_drain;
+       u8 reg_polarity;
+       u8 reg_dir;
+       u8 reg_data;
+       u8 reg_irq_mask;
+       u8 reg_irq_src;
+       u8 reg_sense;
+       u8 reg_clock;
+       u8 reg_misc;
+       u8 reg_reset;
+       u8 ngpios;
+};
+
+struct sx150x_chip {
+       struct gpio_chip                 gpio_chip;
+       struct i2c_client               *client;
+       const struct sx150x_device_data *dev_cfg;
+       int                              irq_summary;
+       int                              irq_base;
+       int                              irq_update;
+       u32                              irq_sense;
+       u32                              irq_masked;
+       u32                              dev_sense;
+       u32                              dev_masked;
+       struct irq_chip                  irq_chip;
+       struct mutex                     lock;
+};
+
+static const struct sx150x_device_data sx150x_devices[] = {
+       [0] = { /* sx1508q */
+               .reg_pullup   = 0x03,
+               .reg_pulldn   = 0x04,
+               .reg_drain    = 0x05,
+               .reg_polarity = 0x06,
+               .reg_dir      = 0x07,
+               .reg_data     = 0x08,
+               .reg_irq_mask = 0x09,
+               .reg_irq_src  = 0x0c,
+               .reg_sense    = 0x0b,
+               .reg_clock    = 0x0f,
+               .reg_misc     = 0x10,
+               .reg_reset    = 0x7d,
+               .ngpios       = 8
+       },
+       [1] = { /* sx1509q */
+               .reg_pullup   = 0x07,
+               .reg_pulldn   = 0x09,
+               .reg_drain    = 0x0b,
+               .reg_polarity = 0x0d,
+               .reg_dir      = 0x0f,
+               .reg_data     = 0x11,
+               .reg_irq_mask = 0x13,
+               .reg_irq_src  = 0x19,
+               .reg_sense    = 0x17,
+               .reg_clock    = 0x1e,
+               .reg_misc     = 0x1f,
+               .reg_reset    = 0x7d,
+               .ngpios       = 16
+       },
+};
+
+static const struct i2c_device_id sx150x_id[] = {
+       {"sx1508q", 0},
+       {"sx1509q", 1},
+       {}
+};
+MODULE_DEVICE_TABLE(i2c, sx150x_id);
+
+static s32 sx150x_i2c_write(struct i2c_client *client, u8 reg, u8 val)
+{
+       s32 err = i2c_smbus_write_byte_data(client, reg, val);
+
+       if (err < 0)
+               dev_warn(&client->dev,
+                       "i2c write fail: can't write %02x to %02x: %d\n",
+                       val, reg, err);
+       return err;
+}
+
+static s32 sx150x_i2c_read(struct i2c_client *client, u8 reg, u8 *val)
+{
+       s32 err = i2c_smbus_read_byte_data(client, reg);
+
+       if (err >= 0)
+               *val = err;
+       else
+               dev_warn(&client->dev,
+                       "i2c read fail: can't read from %02x: %d\n",
+                       reg, err);
+       return err;
+}
+
+static inline bool offset_is_oscio(struct sx150x_chip *chip, unsigned offset)
+{
+       return (chip->dev_cfg->ngpios == offset);
+}
+
+/*
+ * These utility functions solve the common problem of locating and setting
+ * configuration bits.  Configuration bits are grouped into registers
+ * whose indexes increase downwards.  For example, with eight-bit registers,
+ * sixteen gpios would have their config bits grouped in the following order:
+ * REGISTER N-1 [ f e d c b a 9 8 ]
+ *          N   [ 7 6 5 4 3 2 1 0 ]
+ *
+ * For multi-bit configurations, the pattern gets wider:
+ * REGISTER N-3 [ f f e e d d c c ]
+ *          N-2 [ b b a a 9 9 8 8 ]
+ *          N-1 [ 7 7 6 6 5 5 4 4 ]
+ *          N   [ 3 3 2 2 1 1 0 0 ]
+ *
+ * Given the address of the starting register 'N', the index of the gpio
+ * whose configuration we seek to change, and the width in bits of that
+ * configuration, these functions allow us to locate the correct
+ * register and mask the correct bits.
+ */
+static inline void sx150x_find_cfg(u8 offset, u8 width,
+                               u8 *reg, u8 *mask, u8 *shift)
+{
+       *reg   -= offset * width / 8;
+       *mask   = (1 << width) - 1;
+       *shift  = (offset * width) % 8;
+       *mask <<= *shift;
+}
+
+static s32 sx150x_write_cfg(struct sx150x_chip *chip,
+                       u8 offset, u8 width, u8 reg, u8 val)
+{
+       u8  mask;
+       u8  data;
+       u8  shift;
+       s32 err;
+
+       sx150x_find_cfg(offset, width, &reg, &mask, &shift);
+       err = sx150x_i2c_read(chip->client, reg, &data);
+       if (err < 0)
+               return err;
+
+       data &= ~mask;
+       data |= (val << shift) & mask;
+       return sx150x_i2c_write(chip->client, reg, data);
+}
+
+static int sx150x_get_io(struct sx150x_chip *chip, unsigned offset)
+{
+       u8  reg = chip->dev_cfg->reg_data;
+       u8  mask;
+       u8  data;
+       u8  shift;
+       s32 err;
+
+       sx150x_find_cfg(offset, 1, &reg, &mask, &shift);
+       err = sx150x_i2c_read(chip->client, reg, &data);
+       if (err >= 0)
+               err = (data & mask) != 0 ? 1 : 0;
+
+       return err;
+}
+
+static void sx150x_set_oscio(struct sx150x_chip *chip, int val)
+{
+       sx150x_i2c_write(chip->client,
+                       chip->dev_cfg->reg_clock,
+                       (val ? 0x1f : 0x10));
+}
+
+static void sx150x_set_io(struct sx150x_chip *chip, unsigned offset, int val)
+{
+       sx150x_write_cfg(chip,
+                       offset,
+                       1,
+                       chip->dev_cfg->reg_data,
+                       (val ? 1 : 0));
+}
+
+static int sx150x_io_input(struct sx150x_chip *chip, unsigned offset)
+{
+       return sx150x_write_cfg(chip,
+                               offset,
+                               1,
+                               chip->dev_cfg->reg_dir,
+                               1);
+}
+
+static int sx150x_io_output(struct sx150x_chip *chip, unsigned offset, int val)
+{
+       int err;
+
+       err = sx150x_write_cfg(chip,
+                       offset,
+                       1,
+                       chip->dev_cfg->reg_data,
+                       (val ? 1 : 0));
+       if (err >= 0)
+               err = sx150x_write_cfg(chip,
+                               offset,
+                               1,
+                               chip->dev_cfg->reg_dir,
+                               0);
+       return err;
+}
+
+static int sx150x_gpio_get(struct gpio_chip *gc, unsigned offset)
+{
+       struct sx150x_chip *chip;
+       int status = -EINVAL;
+
+       chip = container_of(gc, struct sx150x_chip, gpio_chip);
+
+       if (!offset_is_oscio(chip, offset)) {
+               mutex_lock(&chip->lock);
+               status = sx150x_get_io(chip, offset);
+               mutex_unlock(&chip->lock);
+       }
+
+       return status;
+}
+
+static void sx150x_gpio_set(struct gpio_chip *gc, unsigned offset, int val)
+{
+       struct sx150x_chip *chip;
+
+       chip = container_of(gc, struct sx150x_chip, gpio_chip);
+
+       mutex_lock(&chip->lock);
+       if (offset_is_oscio(chip, offset))
+               sx150x_set_oscio(chip, val);
+       else
+               sx150x_set_io(chip, offset, val);
+       mutex_unlock(&chip->lock);
+}
+
+static int sx150x_gpio_direction_input(struct gpio_chip *gc, unsigned offset)
+{
+       struct sx150x_chip *chip;
+       int status = -EINVAL;
+
+       chip = container_of(gc, struct sx150x_chip, gpio_chip);
+
+       if (!offset_is_oscio(chip, offset)) {
+               mutex_lock(&chip->lock);
+               status = sx150x_io_input(chip, offset);
+               mutex_unlock(&chip->lock);
+       }
+       return status;
+}
+
+static int sx150x_gpio_direction_output(struct gpio_chip *gc,
+                                       unsigned offset,
+                                       int val)
+{
+       struct sx150x_chip *chip;
+       int status = 0;
+
+       chip = container_of(gc, struct sx150x_chip, gpio_chip);
+
+       if (!offset_is_oscio(chip, offset)) {
+               mutex_lock(&chip->lock);
+               status = sx150x_io_output(chip, offset, val);
+               mutex_unlock(&chip->lock);
+       }
+       return status;
+}
+
+static int sx150x_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
+{
+       struct sx150x_chip *chip;
+
+       chip = container_of(gc, struct sx150x_chip, gpio_chip);
+
+       if (offset >= chip->dev_cfg->ngpios)
+               return -EINVAL;
+
+       if (chip->irq_base < 0)
+               return -EINVAL;
+
+       return chip->irq_base + offset;
+}
+
+static void sx150x_irq_mask(struct irq_data *d)
+{
+       struct irq_chip *ic = irq_data_get_irq_chip(d);
+       struct sx150x_chip *chip;
+       unsigned n;
+
+       chip = container_of(ic, struct sx150x_chip, irq_chip);
+       n = d->irq - chip->irq_base;
+       chip->irq_masked |= (1 << n);
+       chip->irq_update = n;
+}
+
+static void sx150x_irq_unmask(struct irq_data *d)
+{
+       struct irq_chip *ic = irq_data_get_irq_chip(d);
+       struct sx150x_chip *chip;
+       unsigned n;
+
+       chip = container_of(ic, struct sx150x_chip, irq_chip);
+       n = d->irq - chip->irq_base;
+
+       chip->irq_masked &= ~(1 << n);
+       chip->irq_update = n;
+}
+
+static int sx150x_irq_set_type(struct irq_data *d, unsigned int flow_type)
+{
+       struct irq_chip *ic = irq_data_get_irq_chip(d);
+       struct sx150x_chip *chip;
+       unsigned n, val = 0;
+
+       if (flow_type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW))
+               return -EINVAL;
+
+       chip = container_of(ic, struct sx150x_chip, irq_chip);
+       n = d->irq - chip->irq_base;
+
+       if (flow_type & IRQ_TYPE_EDGE_RISING)
+               val |= 0x1;
+       if (flow_type & IRQ_TYPE_EDGE_FALLING)
+               val |= 0x2;
+
+       chip->irq_sense &= ~(3UL << (n * 2));
+       chip->irq_sense |= val << (n * 2);
+       chip->irq_update = n;
+       return 0;
+}
+
+static irqreturn_t sx150x_irq_thread_fn(int irq, void *dev_id)
+{
+       struct sx150x_chip *chip = (struct sx150x_chip *)dev_id;
+       unsigned nhandled = 0;
+       unsigned sub_irq;
+       unsigned n;
+       s32 err;
+       u8 val;
+       int i;
+
+       for (i = (chip->dev_cfg->ngpios / 8) - 1; i >= 0; --i) {
+               err = sx150x_i2c_read(chip->client,
+                                     chip->dev_cfg->reg_irq_src - i,
+                                     &val);
+               if (err < 0)
+                       continue;
+
+               sx150x_i2c_write(chip->client,
+                               chip->dev_cfg->reg_irq_src - i,
+                               val);
+               for (n = 0; n < 8; ++n) {
+                       if (val & (1 << n)) {
+                               sub_irq = chip->irq_base + (i * 8) + n;
+                               handle_nested_irq(sub_irq);
+                               ++nhandled;
+                       }
+               }
+       }
+
+       return (nhandled > 0 ? IRQ_HANDLED : IRQ_NONE);
+}
+
+static void sx150x_irq_bus_lock(struct irq_data *d)
+{
+       struct irq_chip *ic = irq_data_get_irq_chip(d);
+       struct sx150x_chip *chip;
+
+       chip = container_of(ic, struct sx150x_chip, irq_chip);
+
+       mutex_lock(&chip->lock);
+}
+
+static void sx150x_irq_bus_sync_unlock(struct irq_data *d)
+{
+       struct irq_chip *ic = irq_data_get_irq_chip(d);
+       struct sx150x_chip *chip;
+       unsigned n;
+
+       chip = container_of(ic, struct sx150x_chip, irq_chip);
+
+       if (chip->irq_update == NO_UPDATE_PENDING)
+               goto out;
+
+       n = chip->irq_update;
+       chip->irq_update = NO_UPDATE_PENDING;
+
+       /* Avoid updates if nothing changed */
+       if (chip->dev_sense == chip->irq_sense &&
+           chip->dev_sense == chip->irq_masked)
+               goto out;
+
+       chip->dev_sense = chip->irq_sense;
+       chip->dev_masked = chip->irq_masked;
+
+       if (chip->irq_masked & (1 << n)) {
+               sx150x_write_cfg(chip, n, 1, chip->dev_cfg->reg_irq_mask, 1);
+               sx150x_write_cfg(chip, n, 2, chip->dev_cfg->reg_sense, 0);
+       } else {
+               sx150x_write_cfg(chip, n, 1, chip->dev_cfg->reg_irq_mask, 0);
+               sx150x_write_cfg(chip, n, 2, chip->dev_cfg->reg_sense,
+                                chip->irq_sense >> (n * 2));
+       }
+out:
+       mutex_unlock(&chip->lock);
+}
+
+static void sx150x_init_chip(struct sx150x_chip *chip,
+                       struct i2c_client *client,
+                       kernel_ulong_t driver_data,
+                       struct sx150x_platform_data *pdata)
+{
+       mutex_init(&chip->lock);
+
+       chip->client                     = client;
+       chip->dev_cfg                    = &sx150x_devices[driver_data];
+       chip->gpio_chip.label            = client->name;
+       chip->gpio_chip.direction_input  = sx150x_gpio_direction_input;
+       chip->gpio_chip.direction_output = sx150x_gpio_direction_output;
+       chip->gpio_chip.get              = sx150x_gpio_get;
+       chip->gpio_chip.set              = sx150x_gpio_set;
+       chip->gpio_chip.to_irq           = sx150x_gpio_to_irq;
+       chip->gpio_chip.base             = pdata->gpio_base;
+       chip->gpio_chip.can_sleep        = 1;
+       chip->gpio_chip.ngpio            = chip->dev_cfg->ngpios;
+       if (pdata->oscio_is_gpo)
+               ++chip->gpio_chip.ngpio;
+
+       chip->irq_chip.name                = client->name;
+       chip->irq_chip.irq_mask            = sx150x_irq_mask;
+       chip->irq_chip.irq_unmask          = sx150x_irq_unmask;
+       chip->irq_chip.irq_set_type        = sx150x_irq_set_type;
+       chip->irq_chip.irq_bus_lock        = sx150x_irq_bus_lock;
+       chip->irq_chip.irq_bus_sync_unlock = sx150x_irq_bus_sync_unlock;
+       chip->irq_summary                  = -1;
+       chip->irq_base                     = -1;
+       chip->irq_masked                   = ~0;
+       chip->irq_sense                    = 0;
+       chip->dev_masked                   = ~0;
+       chip->dev_sense                    = 0;
+       chip->irq_update                   = NO_UPDATE_PENDING;
+}
+
+static int sx150x_init_io(struct sx150x_chip *chip, u8 base, u16 cfg)
+{
+       int err = 0;
+       unsigned n;
+
+       for (n = 0; err >= 0 && n < (chip->dev_cfg->ngpios / 8); ++n)
+               err = sx150x_i2c_write(chip->client, base - n, cfg >> (n * 8));
+       return err;
+}
+
+static int sx150x_reset(struct sx150x_chip *chip)
+{
+       int err;
+
+       err = i2c_smbus_write_byte_data(chip->client,
+                                       chip->dev_cfg->reg_reset,
+                                       0x12);
+       if (err < 0)
+               return err;
+
+       err = i2c_smbus_write_byte_data(chip->client,
+                                       chip->dev_cfg->reg_reset,
+                                       0x34);
+       return err;
+}
+
+static int sx150x_init_hw(struct sx150x_chip *chip,
+                       struct sx150x_platform_data *pdata)
+{
+       int err = 0;
+
+       if (pdata->reset_during_probe) {
+               err = sx150x_reset(chip);
+               if (err < 0)
+                       return err;
+       }
+
+       err = sx150x_i2c_write(chip->client,
+                       chip->dev_cfg->reg_misc,
+                       0x01);
+       if (err < 0)
+               return err;
+
+       err = sx150x_init_io(chip, chip->dev_cfg->reg_pullup,
+                       pdata->io_pullup_ena);
+       if (err < 0)
+               return err;
+
+       err = sx150x_init_io(chip, chip->dev_cfg->reg_pulldn,
+                       pdata->io_pulldn_ena);
+       if (err < 0)
+               return err;
+
+       err = sx150x_init_io(chip, chip->dev_cfg->reg_drain,
+                       pdata->io_open_drain_ena);
+       if (err < 0)
+               return err;
+
+       err = sx150x_init_io(chip, chip->dev_cfg->reg_polarity,
+                       pdata->io_polarity);
+       if (err < 0)
+               return err;
+
+       if (pdata->oscio_is_gpo)
+               sx150x_set_oscio(chip, 0);
+
+       return err;
+}
+
+static int sx150x_install_irq_chip(struct sx150x_chip *chip,
+                               int irq_summary,
+                               int irq_base)
+{
+       int err;
+       unsigned n;
+       unsigned irq;
+
+       chip->irq_summary = irq_summary;
+       chip->irq_base    = irq_base;
+
+       for (n = 0; n < chip->dev_cfg->ngpios; ++n) {
+               irq = irq_base + n;
+               irq_set_chip_and_handler(irq, &chip->irq_chip, handle_edge_irq);
+               irq_set_nested_thread(irq, 1);
+#ifdef CONFIG_ARM
+               set_irq_flags(irq, IRQF_VALID);
+#else
+               irq_set_noprobe(irq);
+#endif
+       }
+
+       err = request_threaded_irq(irq_summary,
+                               NULL,
+                               sx150x_irq_thread_fn,
+                               IRQF_SHARED | IRQF_TRIGGER_FALLING,
+                               chip->irq_chip.name,
+                               chip);
+       if (err < 0) {
+               chip->irq_summary = -1;
+               chip->irq_base    = -1;
+       }
+
+       return err;
+}
+
+static void sx150x_remove_irq_chip(struct sx150x_chip *chip)
+{
+       unsigned n;
+       unsigned irq;
+
+       free_irq(chip->irq_summary, chip);
+
+       for (n = 0; n < chip->dev_cfg->ngpios; ++n) {
+               irq = chip->irq_base + n;
+               irq_set_chip_and_handler(irq, NULL, NULL);
+       }
+}
+
+static int __devinit sx150x_probe(struct i2c_client *client,
+                               const struct i2c_device_id *id)
+{
+       static const u32 i2c_funcs = I2C_FUNC_SMBUS_BYTE_DATA |
+                                    I2C_FUNC_SMBUS_WRITE_WORD_DATA;
+       struct sx150x_platform_data *pdata;
+       struct sx150x_chip *chip;
+       int rc;
+
+       pdata = client->dev.platform_data;
+       if (!pdata)
+               return -EINVAL;
+
+       if (!i2c_check_functionality(client->adapter, i2c_funcs))
+               return -ENOSYS;
+
+       chip = kzalloc(sizeof(struct sx150x_chip), GFP_KERNEL);
+       if (!chip)
+               return -ENOMEM;
+
+       sx150x_init_chip(chip, client, id->driver_data, pdata);
+       rc = sx150x_init_hw(chip, pdata);
+       if (rc < 0)
+               goto probe_fail_pre_gpiochip_add;
+
+       rc = gpiochip_add(&chip->gpio_chip);
+       if (rc < 0)
+               goto probe_fail_pre_gpiochip_add;
+
+       if (pdata->irq_summary >= 0) {
+               rc = sx150x_install_irq_chip(chip,
+                                       pdata->irq_summary,
+                                       pdata->irq_base);
+               if (rc < 0)
+                       goto probe_fail_post_gpiochip_add;
+       }
+
+       i2c_set_clientdata(client, chip);
+
+       return 0;
+probe_fail_post_gpiochip_add:
+       WARN_ON(gpiochip_remove(&chip->gpio_chip) < 0);
+probe_fail_pre_gpiochip_add:
+       kfree(chip);
+       return rc;
+}
+
+static int __devexit sx150x_remove(struct i2c_client *client)
+{
+       struct sx150x_chip *chip;
+       int rc;
+
+       chip = i2c_get_clientdata(client);
+       rc = gpiochip_remove(&chip->gpio_chip);
+       if (rc < 0)
+               return rc;
+
+       if (chip->irq_summary >= 0)
+               sx150x_remove_irq_chip(chip);
+
+       kfree(chip);
+
+       return 0;
+}
+
+static struct i2c_driver sx150x_driver = {
+       .driver = {
+               .name = "sx150x",
+               .owner = THIS_MODULE
+       },
+       .probe    = sx150x_probe,
+       .remove   = __devexit_p(sx150x_remove),
+       .id_table = sx150x_id,
+};
+
+static int __init sx150x_init(void)
+{
+       return i2c_add_driver(&sx150x_driver);
+}
+subsys_initcall(sx150x_init);
+
+static void __exit sx150x_exit(void)
+{
+       return i2c_del_driver(&sx150x_driver);
+}
+module_exit(sx150x_exit);
+
+MODULE_AUTHOR("Gregory Bean <gbean@codeaurora.org>");
+MODULE_DESCRIPTION("Driver for Semtech SX150X I2C GPIO Expanders");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("i2c:sx150x");
diff --git a/drivers/gpio/gpio-tc3589x.c b/drivers/gpio/gpio-tc3589x.c
new file mode 100644 (file)
index 0000000..2a82e89
--- /dev/null
@@ -0,0 +1,389 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * License Terms: GNU General Public License, version 2
+ * Author: Hanumath Prasad <hanumath.prasad@stericsson.com> for ST-Ericsson
+ * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/gpio.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/mfd/tc3589x.h>
+
+/*
+ * These registers are modified under the irq bus lock and cached to avoid
+ * unnecessary writes in bus_sync_unlock.
+ */
+enum { REG_IBE, REG_IEV, REG_IS, REG_IE };
+
+#define CACHE_NR_REGS  4
+#define CACHE_NR_BANKS 3
+
+struct tc3589x_gpio {
+       struct gpio_chip chip;
+       struct tc3589x *tc3589x;
+       struct device *dev;
+       struct mutex irq_lock;
+
+       int irq_base;
+
+       /* Caches of interrupt control registers for bus_lock */
+       u8 regs[CACHE_NR_REGS][CACHE_NR_BANKS];
+       u8 oldregs[CACHE_NR_REGS][CACHE_NR_BANKS];
+};
+
+static inline struct tc3589x_gpio *to_tc3589x_gpio(struct gpio_chip *chip)
+{
+       return container_of(chip, struct tc3589x_gpio, chip);
+}
+
+static int tc3589x_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+       struct tc3589x_gpio *tc3589x_gpio = to_tc3589x_gpio(chip);
+       struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
+       u8 reg = TC3589x_GPIODATA0 + (offset / 8) * 2;
+       u8 mask = 1 << (offset % 8);
+       int ret;
+
+       ret = tc3589x_reg_read(tc3589x, reg);
+       if (ret < 0)
+               return ret;
+
+       return ret & mask;
+}
+
+static void tc3589x_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
+{
+       struct tc3589x_gpio *tc3589x_gpio = to_tc3589x_gpio(chip);
+       struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
+       u8 reg = TC3589x_GPIODATA0 + (offset / 8) * 2;
+       unsigned pos = offset % 8;
+       u8 data[] = {!!val << pos, 1 << pos};
+
+       tc3589x_block_write(tc3589x, reg, ARRAY_SIZE(data), data);
+}
+
+static int tc3589x_gpio_direction_output(struct gpio_chip *chip,
+                                        unsigned offset, int val)
+{
+       struct tc3589x_gpio *tc3589x_gpio = to_tc3589x_gpio(chip);
+       struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
+       u8 reg = TC3589x_GPIODIR0 + offset / 8;
+       unsigned pos = offset % 8;
+
+       tc3589x_gpio_set(chip, offset, val);
+
+       return tc3589x_set_bits(tc3589x, reg, 1 << pos, 1 << pos);
+}
+
+static int tc3589x_gpio_direction_input(struct gpio_chip *chip,
+                                       unsigned offset)
+{
+       struct tc3589x_gpio *tc3589x_gpio = to_tc3589x_gpio(chip);
+       struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
+       u8 reg = TC3589x_GPIODIR0 + offset / 8;
+       unsigned pos = offset % 8;
+
+       return tc3589x_set_bits(tc3589x, reg, 1 << pos, 0);
+}
+
+static int tc3589x_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+       struct tc3589x_gpio *tc3589x_gpio = to_tc3589x_gpio(chip);
+
+       return tc3589x_gpio->irq_base + offset;
+}
+
+static struct gpio_chip template_chip = {
+       .label                  = "tc3589x",
+       .owner                  = THIS_MODULE,
+       .direction_input        = tc3589x_gpio_direction_input,
+       .get                    = tc3589x_gpio_get,
+       .direction_output       = tc3589x_gpio_direction_output,
+       .set                    = tc3589x_gpio_set,
+       .to_irq                 = tc3589x_gpio_to_irq,
+       .can_sleep              = 1,
+};
+
+static int tc3589x_gpio_irq_set_type(struct irq_data *d, unsigned int type)
+{
+       struct tc3589x_gpio *tc3589x_gpio = irq_data_get_irq_chip_data(d);
+       int offset = d->irq - tc3589x_gpio->irq_base;
+       int regoffset = offset / 8;
+       int mask = 1 << (offset % 8);
+
+       if (type == IRQ_TYPE_EDGE_BOTH) {
+               tc3589x_gpio->regs[REG_IBE][regoffset] |= mask;
+               return 0;
+       }
+
+       tc3589x_gpio->regs[REG_IBE][regoffset] &= ~mask;
+
+       if (type == IRQ_TYPE_LEVEL_LOW || type == IRQ_TYPE_LEVEL_HIGH)
+               tc3589x_gpio->regs[REG_IS][regoffset] |= mask;
+       else
+               tc3589x_gpio->regs[REG_IS][regoffset] &= ~mask;
+
+       if (type == IRQ_TYPE_EDGE_RISING || type == IRQ_TYPE_LEVEL_HIGH)
+               tc3589x_gpio->regs[REG_IEV][regoffset] |= mask;
+       else
+               tc3589x_gpio->regs[REG_IEV][regoffset] &= ~mask;
+
+       return 0;
+}
+
+static void tc3589x_gpio_irq_lock(struct irq_data *d)
+{
+       struct tc3589x_gpio *tc3589x_gpio = irq_data_get_irq_chip_data(d);
+
+       mutex_lock(&tc3589x_gpio->irq_lock);
+}
+
+static void tc3589x_gpio_irq_sync_unlock(struct irq_data *d)
+{
+       struct tc3589x_gpio *tc3589x_gpio = irq_data_get_irq_chip_data(d);
+       struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
+       static const u8 regmap[] = {
+               [REG_IBE]       = TC3589x_GPIOIBE0,
+               [REG_IEV]       = TC3589x_GPIOIEV0,
+               [REG_IS]        = TC3589x_GPIOIS0,
+               [REG_IE]        = TC3589x_GPIOIE0,
+       };
+       int i, j;
+
+       for (i = 0; i < CACHE_NR_REGS; i++) {
+               for (j = 0; j < CACHE_NR_BANKS; j++) {
+                       u8 old = tc3589x_gpio->oldregs[i][j];
+                       u8 new = tc3589x_gpio->regs[i][j];
+
+                       if (new == old)
+                               continue;
+
+                       tc3589x_gpio->oldregs[i][j] = new;
+                       tc3589x_reg_write(tc3589x, regmap[i] + j * 8, new);
+               }
+       }
+
+       mutex_unlock(&tc3589x_gpio->irq_lock);
+}
+
+static void tc3589x_gpio_irq_mask(struct irq_data *d)
+{
+       struct tc3589x_gpio *tc3589x_gpio = irq_data_get_irq_chip_data(d);
+       int offset = d->irq - tc3589x_gpio->irq_base;
+       int regoffset = offset / 8;
+       int mask = 1 << (offset % 8);
+
+       tc3589x_gpio->regs[REG_IE][regoffset] &= ~mask;
+}
+
+static void tc3589x_gpio_irq_unmask(struct irq_data *d)
+{
+       struct tc3589x_gpio *tc3589x_gpio = irq_data_get_irq_chip_data(d);
+       int offset = d->irq - tc3589x_gpio->irq_base;
+       int regoffset = offset / 8;
+       int mask = 1 << (offset % 8);
+
+       tc3589x_gpio->regs[REG_IE][regoffset] |= mask;
+}
+
+static struct irq_chip tc3589x_gpio_irq_chip = {
+       .name                   = "tc3589x-gpio",
+       .irq_bus_lock           = tc3589x_gpio_irq_lock,
+       .irq_bus_sync_unlock    = tc3589x_gpio_irq_sync_unlock,
+       .irq_mask               = tc3589x_gpio_irq_mask,
+       .irq_unmask             = tc3589x_gpio_irq_unmask,
+       .irq_set_type           = tc3589x_gpio_irq_set_type,
+};
+
+static irqreturn_t tc3589x_gpio_irq(int irq, void *dev)
+{
+       struct tc3589x_gpio *tc3589x_gpio = dev;
+       struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
+       u8 status[CACHE_NR_BANKS];
+       int ret;
+       int i;
+
+       ret = tc3589x_block_read(tc3589x, TC3589x_GPIOMIS0,
+                                ARRAY_SIZE(status), status);
+       if (ret < 0)
+               return IRQ_NONE;
+
+       for (i = 0; i < ARRAY_SIZE(status); i++) {
+               unsigned int stat = status[i];
+               if (!stat)
+                       continue;
+
+               while (stat) {
+                       int bit = __ffs(stat);
+                       int line = i * 8 + bit;
+
+                       handle_nested_irq(tc3589x_gpio->irq_base + line);
+                       stat &= ~(1 << bit);
+               }
+
+               tc3589x_reg_write(tc3589x, TC3589x_GPIOIC0 + i, status[i]);
+       }
+
+       return IRQ_HANDLED;
+}
+
+static int tc3589x_gpio_irq_init(struct tc3589x_gpio *tc3589x_gpio)
+{
+       int base = tc3589x_gpio->irq_base;
+       int irq;
+
+       for (irq = base; irq < base + tc3589x_gpio->chip.ngpio; irq++) {
+               irq_set_chip_data(irq, tc3589x_gpio);
+               irq_set_chip_and_handler(irq, &tc3589x_gpio_irq_chip,
+                                        handle_simple_irq);
+               irq_set_nested_thread(irq, 1);
+#ifdef CONFIG_ARM
+               set_irq_flags(irq, IRQF_VALID);
+#else
+               irq_set_noprobe(irq);
+#endif
+       }
+
+       return 0;
+}
+
+static void tc3589x_gpio_irq_remove(struct tc3589x_gpio *tc3589x_gpio)
+{
+       int base = tc3589x_gpio->irq_base;
+       int irq;
+
+       for (irq = base; irq < base + tc3589x_gpio->chip.ngpio; irq++) {
+#ifdef CONFIG_ARM
+               set_irq_flags(irq, 0);
+#endif
+               irq_set_chip_and_handler(irq, NULL, NULL);
+               irq_set_chip_data(irq, NULL);
+       }
+}
+
+static int __devinit tc3589x_gpio_probe(struct platform_device *pdev)
+{
+       struct tc3589x *tc3589x = dev_get_drvdata(pdev->dev.parent);
+       struct tc3589x_gpio_platform_data *pdata;
+       struct tc3589x_gpio *tc3589x_gpio;
+       int ret;
+       int irq;
+
+       pdata = tc3589x->pdata->gpio;
+       if (!pdata)
+               return -ENODEV;
+
+       irq = platform_get_irq(pdev, 0);
+       if (irq < 0)
+               return irq;
+
+       tc3589x_gpio = kzalloc(sizeof(struct tc3589x_gpio), GFP_KERNEL);
+       if (!tc3589x_gpio)
+               return -ENOMEM;
+
+       mutex_init(&tc3589x_gpio->irq_lock);
+
+       tc3589x_gpio->dev = &pdev->dev;
+       tc3589x_gpio->tc3589x = tc3589x;
+
+       tc3589x_gpio->chip = template_chip;
+       tc3589x_gpio->chip.ngpio = tc3589x->num_gpio;
+       tc3589x_gpio->chip.dev = &pdev->dev;
+       tc3589x_gpio->chip.base = pdata->gpio_base;
+
+       tc3589x_gpio->irq_base = tc3589x->irq_base + TC3589x_INT_GPIO(0);
+
+       /* Bring the GPIO module out of reset */
+       ret = tc3589x_set_bits(tc3589x, TC3589x_RSTCTRL,
+                              TC3589x_RSTCTRL_GPIRST, 0);
+       if (ret < 0)
+               goto out_free;
+
+       ret = tc3589x_gpio_irq_init(tc3589x_gpio);
+       if (ret)
+               goto out_free;
+
+       ret = request_threaded_irq(irq, NULL, tc3589x_gpio_irq, IRQF_ONESHOT,
+                                  "tc3589x-gpio", tc3589x_gpio);
+       if (ret) {
+               dev_err(&pdev->dev, "unable to get irq: %d\n", ret);
+               goto out_removeirq;
+       }
+
+       ret = gpiochip_add(&tc3589x_gpio->chip);
+       if (ret) {
+               dev_err(&pdev->dev, "unable to add gpiochip: %d\n", ret);
+               goto out_freeirq;
+       }
+
+       if (pdata->setup)
+               pdata->setup(tc3589x, tc3589x_gpio->chip.base);
+
+       platform_set_drvdata(pdev, tc3589x_gpio);
+
+       return 0;
+
+out_freeirq:
+       free_irq(irq, tc3589x_gpio);
+out_removeirq:
+       tc3589x_gpio_irq_remove(tc3589x_gpio);
+out_free:
+       kfree(tc3589x_gpio);
+       return ret;
+}
+
+static int __devexit tc3589x_gpio_remove(struct platform_device *pdev)
+{
+       struct tc3589x_gpio *tc3589x_gpio = platform_get_drvdata(pdev);
+       struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
+       struct tc3589x_gpio_platform_data *pdata = tc3589x->pdata->gpio;
+       int irq = platform_get_irq(pdev, 0);
+       int ret;
+
+       if (pdata->remove)
+               pdata->remove(tc3589x, tc3589x_gpio->chip.base);
+
+       ret = gpiochip_remove(&tc3589x_gpio->chip);
+       if (ret < 0) {
+               dev_err(tc3589x_gpio->dev,
+                       "unable to remove gpiochip: %d\n", ret);
+               return ret;
+       }
+
+       free_irq(irq, tc3589x_gpio);
+       tc3589x_gpio_irq_remove(tc3589x_gpio);
+
+       platform_set_drvdata(pdev, NULL);
+       kfree(tc3589x_gpio);
+
+       return 0;
+}
+
+static struct platform_driver tc3589x_gpio_driver = {
+       .driver.name    = "tc3589x-gpio",
+       .driver.owner   = THIS_MODULE,
+       .probe          = tc3589x_gpio_probe,
+       .remove         = __devexit_p(tc3589x_gpio_remove),
+};
+
+static int __init tc3589x_gpio_init(void)
+{
+       return platform_driver_register(&tc3589x_gpio_driver);
+}
+subsys_initcall(tc3589x_gpio_init);
+
+static void __exit tc3589x_gpio_exit(void)
+{
+       platform_driver_unregister(&tc3589x_gpio_driver);
+}
+module_exit(tc3589x_gpio_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("TC3589x GPIO driver");
+MODULE_AUTHOR("Hanumath Prasad, Rabin Vincent");
diff --git a/drivers/gpio/gpio-timberdale.c b/drivers/gpio/gpio-timberdale.c
new file mode 100644 (file)
index 0000000..c593bd4
--- /dev/null
@@ -0,0 +1,379 @@
+/*
+ * Timberdale FPGA GPIO driver
+ * Copyright (c) 2009 Intel Corporation
+ *
+ * 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.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* Supports:
+ * Timberdale FPGA GPIO
+ */
+
+#include <linux/module.h>
+#include <linux/gpio.h>
+#include <linux/platform_device.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <linux/timb_gpio.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+
+#define DRIVER_NAME "timb-gpio"
+
+#define TGPIOVAL       0x00
+#define TGPIODIR       0x04
+#define TGPIO_IER      0x08
+#define TGPIO_ISR      0x0c
+#define TGPIO_IPR      0x10
+#define TGPIO_ICR      0x14
+#define TGPIO_FLR      0x18
+#define TGPIO_LVR      0x1c
+#define TGPIO_VER      0x20
+#define TGPIO_BFLR     0x24
+
+struct timbgpio {
+       void __iomem            *membase;
+       spinlock_t              lock; /* mutual exclusion */
+       struct gpio_chip        gpio;
+       int                     irq_base;
+       unsigned long           last_ier;
+};
+
+static int timbgpio_update_bit(struct gpio_chip *gpio, unsigned index,
+       unsigned offset, bool enabled)
+{
+       struct timbgpio *tgpio = container_of(gpio, struct timbgpio, gpio);
+       u32 reg;
+
+       spin_lock(&tgpio->lock);
+       reg = ioread32(tgpio->membase + offset);
+
+       if (enabled)
+               reg |= (1 << index);
+       else
+               reg &= ~(1 << index);
+
+       iowrite32(reg, tgpio->membase + offset);
+       spin_unlock(&tgpio->lock);
+
+       return 0;
+}
+
+static int timbgpio_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
+{
+       return timbgpio_update_bit(gpio, nr, TGPIODIR, true);
+}
+
+static int timbgpio_gpio_get(struct gpio_chip *gpio, unsigned nr)
+{
+       struct timbgpio *tgpio = container_of(gpio, struct timbgpio, gpio);
+       u32 value;
+
+       value = ioread32(tgpio->membase + TGPIOVAL);
+       return (value & (1 << nr)) ? 1 : 0;
+}
+
+static int timbgpio_gpio_direction_output(struct gpio_chip *gpio,
+                                               unsigned nr, int val)
+{
+       return timbgpio_update_bit(gpio, nr, TGPIODIR, false);
+}
+
+static void timbgpio_gpio_set(struct gpio_chip *gpio,
+                               unsigned nr, int val)
+{
+       timbgpio_update_bit(gpio, nr, TGPIOVAL, val != 0);
+}
+
+static int timbgpio_to_irq(struct gpio_chip *gpio, unsigned offset)
+{
+       struct timbgpio *tgpio = container_of(gpio, struct timbgpio, gpio);
+
+       if (tgpio->irq_base <= 0)
+               return -EINVAL;
+
+       return tgpio->irq_base + offset;
+}
+
+/*
+ * GPIO IRQ
+ */
+static void timbgpio_irq_disable(struct irq_data *d)
+{
+       struct timbgpio *tgpio = irq_data_get_irq_chip_data(d);
+       int offset = d->irq - tgpio->irq_base;
+       unsigned long flags;
+
+       spin_lock_irqsave(&tgpio->lock, flags);
+       tgpio->last_ier &= ~(1 << offset);
+       iowrite32(tgpio->last_ier, tgpio->membase + TGPIO_IER);
+       spin_unlock_irqrestore(&tgpio->lock, flags);
+}
+
+static void timbgpio_irq_enable(struct irq_data *d)
+{
+       struct timbgpio *tgpio = irq_data_get_irq_chip_data(d);
+       int offset = d->irq - tgpio->irq_base;
+       unsigned long flags;
+
+       spin_lock_irqsave(&tgpio->lock, flags);
+       tgpio->last_ier |= 1 << offset;
+       iowrite32(tgpio->last_ier, tgpio->membase + TGPIO_IER);
+       spin_unlock_irqrestore(&tgpio->lock, flags);
+}
+
+static int timbgpio_irq_type(struct irq_data *d, unsigned trigger)
+{
+       struct timbgpio *tgpio = irq_data_get_irq_chip_data(d);
+       int offset = d->irq - tgpio->irq_base;
+       unsigned long flags;
+       u32 lvr, flr, bflr = 0;
+       u32 ver;
+       int ret = 0;
+
+       if (offset < 0 || offset > tgpio->gpio.ngpio)
+               return -EINVAL;
+
+       ver = ioread32(tgpio->membase + TGPIO_VER);
+
+       spin_lock_irqsave(&tgpio->lock, flags);
+
+       lvr = ioread32(tgpio->membase + TGPIO_LVR);
+       flr = ioread32(tgpio->membase + TGPIO_FLR);
+       if (ver > 2)
+               bflr = ioread32(tgpio->membase + TGPIO_BFLR);
+
+       if (trigger & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {
+               bflr &= ~(1 << offset);
+               flr &= ~(1 << offset);
+               if (trigger & IRQ_TYPE_LEVEL_HIGH)
+                       lvr |= 1 << offset;
+               else
+                       lvr &= ~(1 << offset);
+       }
+
+       if ((trigger & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) {
+               if (ver < 3) {
+                       ret = -EINVAL;
+                       goto out;
+               }
+               else {
+                       flr |= 1 << offset;
+                       bflr |= 1 << offset;
+               }
+       } else {
+               bflr &= ~(1 << offset);
+               flr |= 1 << offset;
+               if (trigger & IRQ_TYPE_EDGE_FALLING)
+                       lvr &= ~(1 << offset);
+               else
+                       lvr |= 1 << offset;
+       }
+
+       iowrite32(lvr, tgpio->membase + TGPIO_LVR);
+       iowrite32(flr, tgpio->membase + TGPIO_FLR);
+       if (ver > 2)
+               iowrite32(bflr, tgpio->membase + TGPIO_BFLR);
+
+       iowrite32(1 << offset, tgpio->membase + TGPIO_ICR);
+
+out:
+       spin_unlock_irqrestore(&tgpio->lock, flags);
+       return ret;
+}
+
+static void timbgpio_irq(unsigned int irq, struct irq_desc *desc)
+{
+       struct timbgpio *tgpio = irq_get_handler_data(irq);
+       unsigned long ipr;
+       int offset;
+
+       desc->irq_data.chip->irq_ack(irq_get_irq_data(irq));
+       ipr = ioread32(tgpio->membase + TGPIO_IPR);
+       iowrite32(ipr, tgpio->membase + TGPIO_ICR);
+
+       /*
+        * Some versions of the hardware trash the IER register if more than
+        * one interrupt is received simultaneously.
+        */
+       iowrite32(0, tgpio->membase + TGPIO_IER);
+
+       for_each_set_bit(offset, &ipr, tgpio->gpio.ngpio)
+               generic_handle_irq(timbgpio_to_irq(&tgpio->gpio, offset));
+
+       iowrite32(tgpio->last_ier, tgpio->membase + TGPIO_IER);
+}
+
+static struct irq_chip timbgpio_irqchip = {
+       .name           = "GPIO",
+       .irq_enable     = timbgpio_irq_enable,
+       .irq_disable    = timbgpio_irq_disable,
+       .irq_set_type   = timbgpio_irq_type,
+};
+
+static int __devinit timbgpio_probe(struct platform_device *pdev)
+{
+       int err, i;
+       struct gpio_chip *gc;
+       struct timbgpio *tgpio;
+       struct resource *iomem;
+       struct timbgpio_platform_data *pdata = pdev->dev.platform_data;
+       int irq = platform_get_irq(pdev, 0);
+
+       if (!pdata || pdata->nr_pins > 32) {
+               err = -EINVAL;
+               goto err_mem;
+       }
+
+       iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!iomem) {
+               err = -EINVAL;
+               goto err_mem;
+       }
+
+       tgpio = kzalloc(sizeof(*tgpio), GFP_KERNEL);
+       if (!tgpio) {
+               err = -EINVAL;
+               goto err_mem;
+       }
+       tgpio->irq_base = pdata->irq_base;
+
+       spin_lock_init(&tgpio->lock);
+
+       if (!request_mem_region(iomem->start, resource_size(iomem),
+               DRIVER_NAME)) {
+               err = -EBUSY;
+               goto err_request;
+       }
+
+       tgpio->membase = ioremap(iomem->start, resource_size(iomem));
+       if (!tgpio->membase) {
+               err = -ENOMEM;
+               goto err_ioremap;
+       }
+
+       gc = &tgpio->gpio;
+
+       gc->label = dev_name(&pdev->dev);
+       gc->owner = THIS_MODULE;
+       gc->dev = &pdev->dev;
+       gc->direction_input = timbgpio_gpio_direction_input;
+       gc->get = timbgpio_gpio_get;
+       gc->direction_output = timbgpio_gpio_direction_output;
+       gc->set = timbgpio_gpio_set;
+       gc->to_irq = (irq >= 0 && tgpio->irq_base > 0) ? timbgpio_to_irq : NULL;
+       gc->dbg_show = NULL;
+       gc->base = pdata->gpio_base;
+       gc->ngpio = pdata->nr_pins;
+       gc->can_sleep = 0;
+
+       err = gpiochip_add(gc);
+       if (err)
+               goto err_chipadd;
+
+       platform_set_drvdata(pdev, tgpio);
+
+       /* make sure to disable interrupts */
+       iowrite32(0x0, tgpio->membase + TGPIO_IER);
+
+       if (irq < 0 || tgpio->irq_base <= 0)
+               return 0;
+
+       for (i = 0; i < pdata->nr_pins; i++) {
+               irq_set_chip_and_handler_name(tgpio->irq_base + i,
+                       &timbgpio_irqchip, handle_simple_irq, "mux");
+               irq_set_chip_data(tgpio->irq_base + i, tgpio);
+#ifdef CONFIG_ARM
+               set_irq_flags(tgpio->irq_base + i, IRQF_VALID | IRQF_PROBE);
+#endif
+       }
+
+       irq_set_handler_data(irq, tgpio);
+       irq_set_chained_handler(irq, timbgpio_irq);
+
+       return 0;
+
+err_chipadd:
+       iounmap(tgpio->membase);
+err_ioremap:
+       release_mem_region(iomem->start, resource_size(iomem));
+err_request:
+       kfree(tgpio);
+err_mem:
+       printk(KERN_ERR DRIVER_NAME": Failed to register GPIOs: %d\n", err);
+
+       return err;
+}
+
+static int __devexit timbgpio_remove(struct platform_device *pdev)
+{
+       int err;
+       struct timbgpio_platform_data *pdata = pdev->dev.platform_data;
+       struct timbgpio *tgpio = platform_get_drvdata(pdev);
+       struct resource *iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       int irq = platform_get_irq(pdev, 0);
+
+       if (irq >= 0 && tgpio->irq_base > 0) {
+               int i;
+               for (i = 0; i < pdata->nr_pins; i++) {
+                       irq_set_chip(tgpio->irq_base + i, NULL);
+                       irq_set_chip_data(tgpio->irq_base + i, NULL);
+               }
+
+               irq_set_handler(irq, NULL);
+               irq_set_handler_data(irq, NULL);
+       }
+
+       err = gpiochip_remove(&tgpio->gpio);
+       if (err)
+               printk(KERN_ERR DRIVER_NAME": failed to remove gpio_chip\n");
+
+       iounmap(tgpio->membase);
+       release_mem_region(iomem->start, resource_size(iomem));
+       kfree(tgpio);
+
+       platform_set_drvdata(pdev, NULL);
+
+       return 0;
+}
+
+static struct platform_driver timbgpio_platform_driver = {
+       .driver = {
+               .name   = DRIVER_NAME,
+               .owner  = THIS_MODULE,
+       },
+       .probe          = timbgpio_probe,
+       .remove         = timbgpio_remove,
+};
+
+/*--------------------------------------------------------------------------*/
+
+static int __init timbgpio_init(void)
+{
+       return platform_driver_register(&timbgpio_platform_driver);
+}
+
+static void __exit timbgpio_exit(void)
+{
+       platform_driver_unregister(&timbgpio_platform_driver);
+}
+
+module_init(timbgpio_init);
+module_exit(timbgpio_exit);
+
+MODULE_DESCRIPTION("Timberdale GPIO driver");
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Mocean Laboratories");
+MODULE_ALIAS("platform:"DRIVER_NAME);
+
diff --git a/drivers/gpio/gpio-tps65910.c b/drivers/gpio/gpio-tps65910.c
new file mode 100644 (file)
index 0000000..4171033
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * TI TPS6591x GPIO driver
+ *
+ * Copyright 2010 Texas Instruments Inc.
+ *
+ * Author: Graeme Gregory <gg@slimlogic.co.uk>
+ * Author: Jorge Eduardo Candelaria jedu@slimlogic.co.uk>
+ *
+ *  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/kernel.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/mfd/tps65910.h>
+
+static int tps65910_gpio_get(struct gpio_chip *gc, unsigned offset)
+{
+       struct tps65910 *tps65910 = container_of(gc, struct tps65910, gpio);
+       uint8_t val;
+
+       tps65910->read(tps65910, TPS65910_GPIO0 + offset, 1, &val);
+
+       if (val & GPIO_STS_MASK)
+               return 1;
+
+       return 0;
+}
+
+static void tps65910_gpio_set(struct gpio_chip *gc, unsigned offset,
+                             int value)
+{
+       struct tps65910 *tps65910 = container_of(gc, struct tps65910, gpio);
+
+       if (value)
+               tps65910_set_bits(tps65910, TPS65910_GPIO0 + offset,
+                                               GPIO_SET_MASK);
+       else
+               tps65910_clear_bits(tps65910, TPS65910_GPIO0 + offset,
+                                               GPIO_SET_MASK);
+}
+
+static int tps65910_gpio_output(struct gpio_chip *gc, unsigned offset,
+                               int value)
+{
+       struct tps65910 *tps65910 = container_of(gc, struct tps65910, gpio);
+
+       /* Set the initial value */
+       tps65910_gpio_set(gc, 0, value);
+
+       return tps65910_set_bits(tps65910, TPS65910_GPIO0 + offset,
+                                               GPIO_CFG_MASK);
+}
+
+static int tps65910_gpio_input(struct gpio_chip *gc, unsigned offset)
+{
+       struct tps65910 *tps65910 = container_of(gc, struct tps65910, gpio);
+
+       return tps65910_clear_bits(tps65910, TPS65910_GPIO0 + offset,
+                                               GPIO_CFG_MASK);
+}
+
+void tps65910_gpio_init(struct tps65910 *tps65910, int gpio_base)
+{
+       int ret;
+
+       if (!gpio_base)
+               return;
+
+       tps65910->gpio.owner            = THIS_MODULE;
+       tps65910->gpio.label            = tps65910->i2c_client->name;
+       tps65910->gpio.dev              = tps65910->dev;
+       tps65910->gpio.base             = gpio_base;
+
+       switch(tps65910_chip_id(tps65910)) {
+       case TPS65910:
+               tps65910->gpio.ngpio    = 6;
+       case TPS65911:
+               tps65910->gpio.ngpio    = 9;
+       default:
+               return;
+       }
+       tps65910->gpio.can_sleep        = 1;
+
+       tps65910->gpio.direction_input  = tps65910_gpio_input;
+       tps65910->gpio.direction_output = tps65910_gpio_output;
+       tps65910->gpio.set              = tps65910_gpio_set;
+       tps65910->gpio.get              = tps65910_gpio_get;
+
+       ret = gpiochip_add(&tps65910->gpio);
+
+       if (ret)
+               dev_warn(tps65910->dev, "GPIO registration failed: %d\n", ret);
+}
diff --git a/drivers/gpio/gpio-twl4030.c b/drivers/gpio/gpio-twl4030.c
new file mode 100644 (file)
index 0000000..b8b4f22
--- /dev/null
@@ -0,0 +1,513 @@
+/*
+ * Access to GPIOs on TWL4030/TPS659x0 chips
+ *
+ * Copyright (C) 2006-2007 Texas Instruments, Inc.
+ * Copyright (C) 2006 MontaVista Software, Inc.
+ *
+ * Code re-arranged and cleaned up by:
+ *     Syed Mohammed Khasim <x0khasim@ti.com>
+ *
+ * Initial Code:
+ *     Andy Lowe / Nishanth Menon
+ *
+ * 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.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/kthread.h>
+#include <linux/irq.h>
+#include <linux/gpio.h>
+#include <linux/platform_device.h>
+
+#include <linux/i2c/twl.h>
+
+
+/*
+ * The GPIO "subchip" supports 18 GPIOs which can be configured as
+ * inputs or outputs, with pullups or pulldowns on each pin.  Each
+ * GPIO can trigger interrupts on either or both edges.
+ *
+ * GPIO interrupts can be fed to either of two IRQ lines; this is
+ * intended to support multiple hosts.
+ *
+ * There are also two LED pins used sometimes as output-only GPIOs.
+ */
+
+
+static struct gpio_chip twl_gpiochip;
+static int twl4030_gpio_irq_base;
+
+/* genirq interfaces are not available to modules */
+#ifdef MODULE
+#define is_module()    true
+#else
+#define is_module()    false
+#endif
+
+/* GPIO_CTRL Fields */
+#define MASK_GPIO_CTRL_GPIO0CD1                BIT(0)
+#define MASK_GPIO_CTRL_GPIO1CD2                BIT(1)
+#define MASK_GPIO_CTRL_GPIO_ON         BIT(2)
+
+/* Mask for GPIO registers when aggregated into a 32-bit integer */
+#define GPIO_32_MASK                   0x0003ffff
+
+/* Data structures */
+static DEFINE_MUTEX(gpio_lock);
+
+/* store usage of each GPIO. - each bit represents one GPIO */
+static unsigned int gpio_usage_count;
+
+/*----------------------------------------------------------------------*/
+
+/*
+ * To configure TWL4030 GPIO module registers
+ */
+static inline int gpio_twl4030_write(u8 address, u8 data)
+{
+       return twl_i2c_write_u8(TWL4030_MODULE_GPIO, data, address);
+}
+
+/*----------------------------------------------------------------------*/
+
+/*
+ * LED register offsets (use TWL4030_MODULE_{LED,PWMA,PWMB}))
+ * PWMs A and B are dedicated to LEDs A and B, respectively.
+ */
+
+#define TWL4030_LED_LEDEN      0x0
+
+/* LEDEN bits */
+#define LEDEN_LEDAON           BIT(0)
+#define LEDEN_LEDBON           BIT(1)
+#define LEDEN_LEDAEXT          BIT(2)
+#define LEDEN_LEDBEXT          BIT(3)
+#define LEDEN_LEDAPWM          BIT(4)
+#define LEDEN_LEDBPWM          BIT(5)
+#define LEDEN_PWM_LENGTHA      BIT(6)
+#define LEDEN_PWM_LENGTHB      BIT(7)
+
+#define TWL4030_PWMx_PWMxON    0x0
+#define TWL4030_PWMx_PWMxOFF   0x1
+
+#define PWMxON_LENGTH          BIT(7)
+
+/*----------------------------------------------------------------------*/
+
+/*
+ * To read a TWL4030 GPIO module register
+ */
+static inline int gpio_twl4030_read(u8 address)
+{
+       u8 data;
+       int ret = 0;
+
+       ret = twl_i2c_read_u8(TWL4030_MODULE_GPIO, &data, address);
+       return (ret < 0) ? ret : data;
+}
+
+/*----------------------------------------------------------------------*/
+
+static u8 cached_leden;                /* protected by gpio_lock */
+
+/* The LED lines are open drain outputs ... a FET pulls to GND, so an
+ * external pullup is needed.  We could also expose the integrated PWM
+ * as a LED brightness control; we initialize it as "always on".
+ */
+static void twl4030_led_set_value(int led, int value)
+{
+       u8 mask = LEDEN_LEDAON | LEDEN_LEDAPWM;
+       int status;
+
+       if (led)
+               mask <<= 1;
+
+       mutex_lock(&gpio_lock);
+       if (value)
+               cached_leden &= ~mask;
+       else
+               cached_leden |= mask;
+       status = twl_i2c_write_u8(TWL4030_MODULE_LED, cached_leden,
+                       TWL4030_LED_LEDEN);
+       mutex_unlock(&gpio_lock);
+}
+
+static int twl4030_set_gpio_direction(int gpio, int is_input)
+{
+       u8 d_bnk = gpio >> 3;
+       u8 d_msk = BIT(gpio & 0x7);
+       u8 reg = 0;
+       u8 base = REG_GPIODATADIR1 + d_bnk;
+       int ret = 0;
+
+       mutex_lock(&gpio_lock);
+       ret = gpio_twl4030_read(base);
+       if (ret >= 0) {
+               if (is_input)
+                       reg = ret & ~d_msk;
+               else
+                       reg = ret | d_msk;
+
+               ret = gpio_twl4030_write(base, reg);
+       }
+       mutex_unlock(&gpio_lock);
+       return ret;
+}
+
+static int twl4030_set_gpio_dataout(int gpio, int enable)
+{
+       u8 d_bnk = gpio >> 3;
+       u8 d_msk = BIT(gpio & 0x7);
+       u8 base = 0;
+
+       if (enable)
+               base = REG_SETGPIODATAOUT1 + d_bnk;
+       else
+               base = REG_CLEARGPIODATAOUT1 + d_bnk;
+
+       return gpio_twl4030_write(base, d_msk);
+}
+
+static int twl4030_get_gpio_datain(int gpio)
+{
+       u8 d_bnk = gpio >> 3;
+       u8 d_off = gpio & 0x7;
+       u8 base = 0;
+       int ret = 0;
+
+       if (unlikely((gpio >= TWL4030_GPIO_MAX)
+               || !(gpio_usage_count & BIT(gpio))))
+               return -EPERM;
+
+       base = REG_GPIODATAIN1 + d_bnk;
+       ret = gpio_twl4030_read(base);
+       if (ret > 0)
+               ret = (ret >> d_off) & 0x1;
+
+       return ret;
+}
+
+/*----------------------------------------------------------------------*/
+
+static int twl_request(struct gpio_chip *chip, unsigned offset)
+{
+       int status = 0;
+
+       mutex_lock(&gpio_lock);
+
+       /* Support the two LED outputs as output-only GPIOs. */
+       if (offset >= TWL4030_GPIO_MAX) {
+               u8      ledclr_mask = LEDEN_LEDAON | LEDEN_LEDAEXT
+                               | LEDEN_LEDAPWM | LEDEN_PWM_LENGTHA;
+               u8      module = TWL4030_MODULE_PWMA;
+
+               offset -= TWL4030_GPIO_MAX;
+               if (offset) {
+                       ledclr_mask <<= 1;
+                       module = TWL4030_MODULE_PWMB;
+               }
+
+               /* initialize PWM to always-drive */
+               status = twl_i2c_write_u8(module, 0x7f,
+                               TWL4030_PWMx_PWMxOFF);
+               if (status < 0)
+                       goto done;
+               status = twl_i2c_write_u8(module, 0x7f,
+                               TWL4030_PWMx_PWMxON);
+               if (status < 0)
+                       goto done;
+
+               /* init LED to not-driven (high) */
+               module = TWL4030_MODULE_LED;
+               status = twl_i2c_read_u8(module, &cached_leden,
+                               TWL4030_LED_LEDEN);
+               if (status < 0)
+                       goto done;
+               cached_leden &= ~ledclr_mask;
+               status = twl_i2c_write_u8(module, cached_leden,
+                               TWL4030_LED_LEDEN);
+               if (status < 0)
+                       goto done;
+
+               status = 0;
+               goto done;
+       }
+
+       /* on first use, turn GPIO module "on" */
+       if (!gpio_usage_count) {
+               struct twl4030_gpio_platform_data *pdata;
+               u8 value = MASK_GPIO_CTRL_GPIO_ON;
+
+               /* optionally have the first two GPIOs switch vMMC1
+                * and vMMC2 power supplies based on card presence.
+                */
+               pdata = chip->dev->platform_data;
+               value |= pdata->mmc_cd & 0x03;
+
+               status = gpio_twl4030_write(REG_GPIO_CTRL, value);
+       }
+
+       if (!status)
+               gpio_usage_count |= (0x1 << offset);
+
+done:
+       mutex_unlock(&gpio_lock);
+       return status;
+}
+
+static void twl_free(struct gpio_chip *chip, unsigned offset)
+{
+       if (offset >= TWL4030_GPIO_MAX) {
+               twl4030_led_set_value(offset - TWL4030_GPIO_MAX, 1);
+               return;
+       }
+
+       mutex_lock(&gpio_lock);
+
+       gpio_usage_count &= ~BIT(offset);
+
+       /* on last use, switch off GPIO module */
+       if (!gpio_usage_count)
+               gpio_twl4030_write(REG_GPIO_CTRL, 0x0);
+
+       mutex_unlock(&gpio_lock);
+}
+
+static int twl_direction_in(struct gpio_chip *chip, unsigned offset)
+{
+       return (offset < TWL4030_GPIO_MAX)
+               ? twl4030_set_gpio_direction(offset, 1)
+               : -EINVAL;
+}
+
+static int twl_get(struct gpio_chip *chip, unsigned offset)
+{
+       int status = 0;
+
+       if (offset < TWL4030_GPIO_MAX)
+               status = twl4030_get_gpio_datain(offset);
+       else if (offset == TWL4030_GPIO_MAX)
+               status = cached_leden & LEDEN_LEDAON;
+       else
+               status = cached_leden & LEDEN_LEDBON;
+       return (status < 0) ? 0 : status;
+}
+
+static int twl_direction_out(struct gpio_chip *chip, unsigned offset, int value)
+{
+       if (offset < TWL4030_GPIO_MAX) {
+               twl4030_set_gpio_dataout(offset, value);
+               return twl4030_set_gpio_direction(offset, 0);
+       } else {
+               twl4030_led_set_value(offset - TWL4030_GPIO_MAX, value);
+               return 0;
+       }
+}
+
+static void twl_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+       if (offset < TWL4030_GPIO_MAX)
+               twl4030_set_gpio_dataout(offset, value);
+       else
+               twl4030_led_set_value(offset - TWL4030_GPIO_MAX, value);
+}
+
+static int twl_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+       return (twl4030_gpio_irq_base && (offset < TWL4030_GPIO_MAX))
+               ? (twl4030_gpio_irq_base + offset)
+               : -EINVAL;
+}
+
+static struct gpio_chip twl_gpiochip = {
+       .label                  = "twl4030",
+       .owner                  = THIS_MODULE,
+       .request                = twl_request,
+       .free                   = twl_free,
+       .direction_input        = twl_direction_in,
+       .get                    = twl_get,
+       .direction_output       = twl_direction_out,
+       .set                    = twl_set,
+       .to_irq                 = twl_to_irq,
+       .can_sleep              = 1,
+};
+
+/*----------------------------------------------------------------------*/
+
+static int __devinit gpio_twl4030_pulls(u32 ups, u32 downs)
+{
+       u8              message[6];
+       unsigned        i, gpio_bit;
+
+       /* For most pins, a pulldown was enabled by default.
+        * We should have data that's specific to this board.
+        */
+       for (gpio_bit = 1, i = 1; i < 6; i++) {
+               u8              bit_mask;
+               unsigned        j;
+
+               for (bit_mask = 0, j = 0; j < 8; j += 2, gpio_bit <<= 1) {
+                       if (ups & gpio_bit)
+                               bit_mask |= 1 << (j + 1);
+                       else if (downs & gpio_bit)
+                               bit_mask |= 1 << (j + 0);
+               }
+               message[i] = bit_mask;
+       }
+
+       return twl_i2c_write(TWL4030_MODULE_GPIO, message,
+                               REG_GPIOPUPDCTR1, 5);
+}
+
+static int __devinit gpio_twl4030_debounce(u32 debounce, u8 mmc_cd)
+{
+       u8              message[4];
+
+       /* 30 msec of debouncing is always used for MMC card detect,
+        * and is optional for everything else.
+        */
+       message[1] = (debounce & 0xff) | (mmc_cd & 0x03);
+       debounce >>= 8;
+       message[2] = (debounce & 0xff);
+       debounce >>= 8;
+       message[3] = (debounce & 0x03);
+
+       return twl_i2c_write(TWL4030_MODULE_GPIO, message,
+                               REG_GPIO_DEBEN1, 3);
+}
+
+static int gpio_twl4030_remove(struct platform_device *pdev);
+
+static int __devinit gpio_twl4030_probe(struct platform_device *pdev)
+{
+       struct twl4030_gpio_platform_data *pdata = pdev->dev.platform_data;
+       int ret;
+
+       /* maybe setup IRQs */
+       if (pdata->irq_base) {
+               if (is_module()) {
+                       dev_err(&pdev->dev,
+                               "can't dispatch IRQs from modules\n");
+                       goto no_irqs;
+               }
+               ret = twl4030_sih_setup(TWL4030_MODULE_GPIO);
+               if (ret < 0)
+                       return ret;
+               WARN_ON(ret != pdata->irq_base);
+               twl4030_gpio_irq_base = ret;
+       }
+
+no_irqs:
+       /*
+        * NOTE:  boards may waste power if they don't set pullups
+        * and pulldowns correctly ... default for non-ULPI pins is
+        * pulldown, and some other pins may have external pullups
+        * or pulldowns.  Careful!
+        */
+       ret = gpio_twl4030_pulls(pdata->pullups, pdata->pulldowns);
+       if (ret)
+               dev_dbg(&pdev->dev, "pullups %.05x %.05x --> %d\n",
+                               pdata->pullups, pdata->pulldowns,
+                               ret);
+
+       ret = gpio_twl4030_debounce(pdata->debounce, pdata->mmc_cd);
+       if (ret)
+               dev_dbg(&pdev->dev, "debounce %.03x %.01x --> %d\n",
+                               pdata->debounce, pdata->mmc_cd,
+                               ret);
+
+       twl_gpiochip.base = pdata->gpio_base;
+       twl_gpiochip.ngpio = TWL4030_GPIO_MAX;
+       twl_gpiochip.dev = &pdev->dev;
+
+       /* NOTE: we assume VIBRA_CTL.VIBRA_EN, in MODULE_AUDIO_VOICE,
+        * is (still) clear if use_leds is set.
+        */
+       if (pdata->use_leds)
+               twl_gpiochip.ngpio += 2;
+
+       ret = gpiochip_add(&twl_gpiochip);
+       if (ret < 0) {
+               dev_err(&pdev->dev,
+                               "could not register gpiochip, %d\n",
+                               ret);
+               twl_gpiochip.ngpio = 0;
+               gpio_twl4030_remove(pdev);
+       } else if (pdata->setup) {
+               int status;
+
+               status = pdata->setup(&pdev->dev,
+                               pdata->gpio_base, TWL4030_GPIO_MAX);
+               if (status)
+                       dev_dbg(&pdev->dev, "setup --> %d\n", status);
+       }
+
+       return ret;
+}
+
+/* Cannot use __devexit 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;
+       int status;
+
+       if (pdata->teardown) {
+               status = pdata->teardown(&pdev->dev,
+                               pdata->gpio_base, TWL4030_GPIO_MAX);
+               if (status) {
+                       dev_dbg(&pdev->dev, "teardown --> %d\n", status);
+                       return status;
+               }
+       }
+
+       status = gpiochip_remove(&twl_gpiochip);
+       if (status < 0)
+               return status;
+
+       if (is_module())
+               return 0;
+
+       /* REVISIT no support yet for deregistering all the IRQs */
+       WARN_ON(1);
+       return -EIO;
+}
+
+/* Note:  this hardware lives inside an I2C-based multi-function device. */
+MODULE_ALIAS("platform:twl4030_gpio");
+
+static struct platform_driver gpio_twl4030_driver = {
+       .driver.name    = "twl4030_gpio",
+       .driver.owner   = THIS_MODULE,
+       .probe          = gpio_twl4030_probe,
+       .remove         = gpio_twl4030_remove,
+};
+
+static int __init gpio_twl4030_init(void)
+{
+       return platform_driver_register(&gpio_twl4030_driver);
+}
+subsys_initcall(gpio_twl4030_init);
+
+static void __exit gpio_twl4030_exit(void)
+{
+       platform_driver_unregister(&gpio_twl4030_driver);
+}
+module_exit(gpio_twl4030_exit);
+
+MODULE_AUTHOR("Texas Instruments, Inc.");
+MODULE_DESCRIPTION("GPIO interface for TWL4030");
+MODULE_LICENSE("GPL");
index d92790140fe53852bd4e571ed29fe95f490e8e77..fd2dfeeefdf3710675c30b76790e37788a92030c 100644 (file)
@@ -1,11 +1,8 @@
 /*
- *
- * arch/arm/mach-u300/gpio.c
- *
+ * U300 GPIO module.
  *
  * Copyright (C) 2007-2009 ST-Ericsson AB
  * License terms: GNU General Public License (GPL) version 2
- * U300 GPIO module.
  * This can driver either of the two basic GPIO cores
  * available in the U300 platforms:
  * COH 901 335   - Used in DB3150 (U300 1.0) and DB3200 (U330 1.0)
diff --git a/drivers/gpio/gpio-ucb1400.c b/drivers/gpio/gpio-ucb1400.c
new file mode 100644 (file)
index 0000000..50e6bd1
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * Philips UCB1400 GPIO driver
+ *
+ * Author: Marek Vasut <marek.vasut@gmail.com>
+ *
+ * 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/module.h>
+#include <linux/ucb1400.h>
+
+struct ucb1400_gpio_data *ucbdata;
+
+static int ucb1400_gpio_dir_in(struct gpio_chip *gc, unsigned off)
+{
+       struct ucb1400_gpio *gpio;
+       gpio = container_of(gc, struct ucb1400_gpio, gc);
+       ucb1400_gpio_set_direction(gpio->ac97, off, 0);
+       return 0;
+}
+
+static int ucb1400_gpio_dir_out(struct gpio_chip *gc, unsigned off, int val)
+{
+       struct ucb1400_gpio *gpio;
+       gpio = container_of(gc, struct ucb1400_gpio, gc);
+       ucb1400_gpio_set_direction(gpio->ac97, off, 1);
+       ucb1400_gpio_set_value(gpio->ac97, off, val);
+       return 0;
+}
+
+static int ucb1400_gpio_get(struct gpio_chip *gc, unsigned off)
+{
+       struct ucb1400_gpio *gpio;
+       gpio = container_of(gc, struct ucb1400_gpio, gc);
+       return ucb1400_gpio_get_value(gpio->ac97, off);
+}
+
+static void ucb1400_gpio_set(struct gpio_chip *gc, unsigned off, int val)
+{
+       struct ucb1400_gpio *gpio;
+       gpio = container_of(gc, struct ucb1400_gpio, gc);
+       ucb1400_gpio_set_value(gpio->ac97, off, val);
+}
+
+static int ucb1400_gpio_probe(struct platform_device *dev)
+{
+       struct ucb1400_gpio *ucb = dev->dev.platform_data;
+       int err = 0;
+
+       if (!(ucbdata && ucbdata->gpio_offset)) {
+               err = -EINVAL;
+               goto err;
+       }
+
+       platform_set_drvdata(dev, ucb);
+
+       ucb->gc.label = "ucb1400_gpio";
+       ucb->gc.base = ucbdata->gpio_offset;
+       ucb->gc.ngpio = 10;
+       ucb->gc.owner = THIS_MODULE;
+
+       ucb->gc.direction_input = ucb1400_gpio_dir_in;
+       ucb->gc.direction_output = ucb1400_gpio_dir_out;
+       ucb->gc.get = ucb1400_gpio_get;
+       ucb->gc.set = ucb1400_gpio_set;
+       ucb->gc.can_sleep = 1;
+
+       err = gpiochip_add(&ucb->gc);
+       if (err)
+               goto err;
+
+       if (ucbdata && ucbdata->gpio_setup)
+               err = ucbdata->gpio_setup(&dev->dev, ucb->gc.ngpio);
+
+err:
+       return err;
+
+}
+
+static int ucb1400_gpio_remove(struct platform_device *dev)
+{
+       int err = 0;
+       struct ucb1400_gpio *ucb = platform_get_drvdata(dev);
+
+       if (ucbdata && ucbdata->gpio_teardown) {
+               err = ucbdata->gpio_teardown(&dev->dev, ucb->gc.ngpio);
+               if (err)
+                       return err;
+       }
+
+       err = gpiochip_remove(&ucb->gc);
+       return err;
+}
+
+static struct platform_driver ucb1400_gpio_driver = {
+       .probe  = ucb1400_gpio_probe,
+       .remove = ucb1400_gpio_remove,
+       .driver = {
+               .name   = "ucb1400_gpio"
+       },
+};
+
+static int __init ucb1400_gpio_init(void)
+{
+       return platform_driver_register(&ucb1400_gpio_driver);
+}
+
+static void __exit ucb1400_gpio_exit(void)
+{
+       platform_driver_unregister(&ucb1400_gpio_driver);
+}
+
+void __init ucb1400_gpio_set_data(struct ucb1400_gpio_data *data)
+{
+       ucbdata = data;
+}
+
+module_init(ucb1400_gpio_init);
+module_exit(ucb1400_gpio_exit);
+
+MODULE_DESCRIPTION("Philips UCB1400 GPIO driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/gpio-vr41xx.c b/drivers/gpio/gpio-vr41xx.c
new file mode 100644 (file)
index 0000000..a365be0
--- /dev/null
@@ -0,0 +1,585 @@
+/*
+ *  Driver for NEC VR4100 series General-purpose I/O Unit.
+ *
+ *  Copyright (C) 2002 MontaVista Software Inc.
+ *     Author: Yoichi Yuasa <source@mvista.com>
+ *  Copyright (C) 2003-2009  Yoichi Yuasa <yuasa@linux-mips.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.
+ *
+ *  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.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/gpio.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+
+#include <asm/vr41xx/giu.h>
+#include <asm/vr41xx/irq.h>
+#include <asm/vr41xx/vr41xx.h>
+
+MODULE_AUTHOR("Yoichi Yuasa <yuasa@linux-mips.org>");
+MODULE_DESCRIPTION("NEC VR4100 series General-purpose I/O Unit driver");
+MODULE_LICENSE("GPL");
+
+#define GIUIOSELL      0x00
+#define GIUIOSELH      0x02
+#define GIUPIODL       0x04
+#define GIUPIODH       0x06
+#define GIUINTSTATL    0x08
+#define GIUINTSTATH    0x0a
+#define GIUINTENL      0x0c
+#define GIUINTENH      0x0e
+#define GIUINTTYPL     0x10
+#define GIUINTTYPH     0x12
+#define GIUINTALSELL   0x14
+#define GIUINTALSELH   0x16
+#define GIUINTHTSELL   0x18
+#define GIUINTHTSELH   0x1a
+#define GIUPODATL      0x1c
+#define GIUPODATEN     0x1c
+#define GIUPODATH      0x1e
+ #define PIOEN0                0x0100
+ #define PIOEN1                0x0200
+#define GIUPODAT       0x1e
+#define GIUFEDGEINHL   0x20
+#define GIUFEDGEINHH   0x22
+#define GIUREDGEINHL   0x24
+#define GIUREDGEINHH   0x26
+
+#define GIUUSEUPDN     0x1e0
+#define GIUTERMUPDN    0x1e2
+
+#define GPIO_HAS_PULLUPDOWN_IO         0x0001
+#define GPIO_HAS_OUTPUT_ENABLE         0x0002
+#define GPIO_HAS_INTERRUPT_EDGE_SELECT 0x0100
+
+enum {
+       GPIO_INPUT,
+       GPIO_OUTPUT,
+};
+
+static DEFINE_SPINLOCK(giu_lock);
+static unsigned long giu_flags;
+
+static void __iomem *giu_base;
+
+#define giu_read(offset)               readw(giu_base + (offset))
+#define giu_write(offset, value)       writew((value), giu_base + (offset))
+
+#define GPIO_PIN_OF_IRQ(irq)   ((irq) - GIU_IRQ_BASE)
+#define GIUINT_HIGH_OFFSET     16
+#define GIUINT_HIGH_MAX                32
+
+static inline u16 giu_set(u16 offset, u16 set)
+{
+       u16 data;
+
+       data = giu_read(offset);
+       data |= set;
+       giu_write(offset, data);
+
+       return data;
+}
+
+static inline u16 giu_clear(u16 offset, u16 clear)
+{
+       u16 data;
+
+       data = giu_read(offset);
+       data &= ~clear;
+       giu_write(offset, data);
+
+       return data;
+}
+
+static void ack_giuint_low(struct irq_data *d)
+{
+       giu_write(GIUINTSTATL, 1 << GPIO_PIN_OF_IRQ(d->irq));
+}
+
+static void mask_giuint_low(struct irq_data *d)
+{
+       giu_clear(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(d->irq));
+}
+
+static void mask_ack_giuint_low(struct irq_data *d)
+{
+       unsigned int pin;
+
+       pin = GPIO_PIN_OF_IRQ(d->irq);
+       giu_clear(GIUINTENL, 1 << pin);
+       giu_write(GIUINTSTATL, 1 << pin);
+}
+
+static void unmask_giuint_low(struct irq_data *d)
+{
+       giu_set(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(d->irq));
+}
+
+static struct irq_chip giuint_low_irq_chip = {
+       .name           = "GIUINTL",
+       .irq_ack        = ack_giuint_low,
+       .irq_mask       = mask_giuint_low,
+       .irq_mask_ack   = mask_ack_giuint_low,
+       .irq_unmask     = unmask_giuint_low,
+};
+
+static void ack_giuint_high(struct irq_data *d)
+{
+       giu_write(GIUINTSTATH,
+                 1 << (GPIO_PIN_OF_IRQ(d->irq) - GIUINT_HIGH_OFFSET));
+}
+
+static void mask_giuint_high(struct irq_data *d)
+{
+       giu_clear(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(d->irq) - GIUINT_HIGH_OFFSET));
+}
+
+static void mask_ack_giuint_high(struct irq_data *d)
+{
+       unsigned int pin;
+
+       pin = GPIO_PIN_OF_IRQ(d->irq) - GIUINT_HIGH_OFFSET;
+       giu_clear(GIUINTENH, 1 << pin);
+       giu_write(GIUINTSTATH, 1 << pin);
+}
+
+static void unmask_giuint_high(struct irq_data *d)
+{
+       giu_set(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(d->irq) - GIUINT_HIGH_OFFSET));
+}
+
+static struct irq_chip giuint_high_irq_chip = {
+       .name           = "GIUINTH",
+       .irq_ack        = ack_giuint_high,
+       .irq_mask       = mask_giuint_high,
+       .irq_mask_ack   = mask_ack_giuint_high,
+       .irq_unmask     = unmask_giuint_high,
+};
+
+static int giu_get_irq(unsigned int irq)
+{
+       u16 pendl, pendh, maskl, maskh;
+       int i;
+
+       pendl = giu_read(GIUINTSTATL);
+       pendh = giu_read(GIUINTSTATH);
+       maskl = giu_read(GIUINTENL);
+       maskh = giu_read(GIUINTENH);
+
+       maskl &= pendl;
+       maskh &= pendh;
+
+       if (maskl) {
+               for (i = 0; i < 16; i++) {
+                       if (maskl & (1 << i))
+                               return GIU_IRQ(i);
+               }
+       } else if (maskh) {
+               for (i = 0; i < 16; i++) {
+                       if (maskh & (1 << i))
+                               return GIU_IRQ(i + GIUINT_HIGH_OFFSET);
+               }
+       }
+
+       printk(KERN_ERR "spurious GIU interrupt: %04x(%04x),%04x(%04x)\n",
+              maskl, pendl, maskh, pendh);
+
+       atomic_inc(&irq_err_count);
+
+       return -EINVAL;
+}
+
+void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger,
+                           irq_signal_t signal)
+{
+       u16 mask;
+
+       if (pin < GIUINT_HIGH_OFFSET) {
+               mask = 1 << pin;
+               if (trigger != IRQ_TRIGGER_LEVEL) {
+                       giu_set(GIUINTTYPL, mask);
+                       if (signal == IRQ_SIGNAL_HOLD)
+                               giu_set(GIUINTHTSELL, mask);
+                       else
+                               giu_clear(GIUINTHTSELL, mask);
+                       if (giu_flags & GPIO_HAS_INTERRUPT_EDGE_SELECT) {
+                               switch (trigger) {
+                               case IRQ_TRIGGER_EDGE_FALLING:
+                                       giu_set(GIUFEDGEINHL, mask);
+                                       giu_clear(GIUREDGEINHL, mask);
+                                       break;
+                               case IRQ_TRIGGER_EDGE_RISING:
+                                       giu_clear(GIUFEDGEINHL, mask);
+                                       giu_set(GIUREDGEINHL, mask);
+                                       break;
+                               default:
+                                       giu_set(GIUFEDGEINHL, mask);
+                                       giu_set(GIUREDGEINHL, mask);
+                                       break;
+                               }
+                       }
+                       irq_set_chip_and_handler(GIU_IRQ(pin),
+                                                &giuint_low_irq_chip,
+                                                handle_edge_irq);
+               } else {
+                       giu_clear(GIUINTTYPL, mask);
+                       giu_clear(GIUINTHTSELL, mask);
+                       irq_set_chip_and_handler(GIU_IRQ(pin),
+                                                &giuint_low_irq_chip,
+                                                handle_level_irq);
+               }
+               giu_write(GIUINTSTATL, mask);
+       } else if (pin < GIUINT_HIGH_MAX) {
+               mask = 1 << (pin - GIUINT_HIGH_OFFSET);
+               if (trigger != IRQ_TRIGGER_LEVEL) {
+                       giu_set(GIUINTTYPH, mask);
+                       if (signal == IRQ_SIGNAL_HOLD)
+                               giu_set(GIUINTHTSELH, mask);
+                       else
+                               giu_clear(GIUINTHTSELH, mask);
+                       if (giu_flags & GPIO_HAS_INTERRUPT_EDGE_SELECT) {
+                               switch (trigger) {
+                               case IRQ_TRIGGER_EDGE_FALLING:
+                                       giu_set(GIUFEDGEINHH, mask);
+                                       giu_clear(GIUREDGEINHH, mask);
+                                       break;
+                               case IRQ_TRIGGER_EDGE_RISING:
+                                       giu_clear(GIUFEDGEINHH, mask);
+                                       giu_set(GIUREDGEINHH, mask);
+                                       break;
+                               default:
+                                       giu_set(GIUFEDGEINHH, mask);
+                                       giu_set(GIUREDGEINHH, mask);
+                                       break;
+                               }
+                       }
+                       irq_set_chip_and_handler(GIU_IRQ(pin),
+                                                &giuint_high_irq_chip,
+                                                handle_edge_irq);
+               } else {
+                       giu_clear(GIUINTTYPH, mask);
+                       giu_clear(GIUINTHTSELH, mask);
+                       irq_set_chip_and_handler(GIU_IRQ(pin),
+                                                &giuint_high_irq_chip,
+                                                handle_level_irq);
+               }
+               giu_write(GIUINTSTATH, mask);
+       }
+}
+EXPORT_SYMBOL_GPL(vr41xx_set_irq_trigger);
+
+void vr41xx_set_irq_level(unsigned int pin, irq_level_t level)
+{
+       u16 mask;
+
+       if (pin < GIUINT_HIGH_OFFSET) {
+               mask = 1 << pin;
+               if (level == IRQ_LEVEL_HIGH)
+                       giu_set(GIUINTALSELL, mask);
+               else
+                       giu_clear(GIUINTALSELL, mask);
+               giu_write(GIUINTSTATL, mask);
+       } else if (pin < GIUINT_HIGH_MAX) {
+               mask = 1 << (pin - GIUINT_HIGH_OFFSET);
+               if (level == IRQ_LEVEL_HIGH)
+                       giu_set(GIUINTALSELH, mask);
+               else
+                       giu_clear(GIUINTALSELH, mask);
+               giu_write(GIUINTSTATH, mask);
+       }
+}
+EXPORT_SYMBOL_GPL(vr41xx_set_irq_level);
+
+static int giu_set_direction(struct gpio_chip *chip, unsigned pin, int dir)
+{
+       u16 offset, mask, reg;
+       unsigned long flags;
+
+       if (pin >= chip->ngpio)
+               return -EINVAL;
+
+       if (pin < 16) {
+               offset = GIUIOSELL;
+               mask = 1 << pin;
+       } else if (pin < 32) {
+               offset = GIUIOSELH;
+               mask = 1 << (pin - 16);
+       } else {
+               if (giu_flags & GPIO_HAS_OUTPUT_ENABLE) {
+                       offset = GIUPODATEN;
+                       mask = 1 << (pin - 32);
+               } else {
+                       switch (pin) {
+                       case 48:
+                               offset = GIUPODATH;
+                               mask = PIOEN0;
+                               break;
+                       case 49:
+                               offset = GIUPODATH;
+                               mask = PIOEN1;
+                               break;
+                       default:
+                               return -EINVAL;
+                       }
+               }
+       }
+
+       spin_lock_irqsave(&giu_lock, flags);
+
+       reg = giu_read(offset);
+       if (dir == GPIO_OUTPUT)
+               reg |= mask;
+       else
+               reg &= ~mask;
+       giu_write(offset, reg);
+
+       spin_unlock_irqrestore(&giu_lock, flags);
+
+       return 0;
+}
+
+int vr41xx_gpio_pullupdown(unsigned int pin, gpio_pull_t pull)
+{
+       u16 reg, mask;
+       unsigned long flags;
+
+       if ((giu_flags & GPIO_HAS_PULLUPDOWN_IO) != GPIO_HAS_PULLUPDOWN_IO)
+               return -EPERM;
+
+       if (pin >= 15)
+               return -EINVAL;
+
+       mask = 1 << pin;
+
+       spin_lock_irqsave(&giu_lock, flags);
+
+       if (pull == GPIO_PULL_UP || pull == GPIO_PULL_DOWN) {
+               reg = giu_read(GIUTERMUPDN);
+               if (pull == GPIO_PULL_UP)
+                       reg |= mask;
+               else
+                       reg &= ~mask;
+               giu_write(GIUTERMUPDN, reg);
+
+               reg = giu_read(GIUUSEUPDN);
+               reg |= mask;
+               giu_write(GIUUSEUPDN, reg);
+       } else {
+               reg = giu_read(GIUUSEUPDN);
+               reg &= ~mask;
+               giu_write(GIUUSEUPDN, reg);
+       }
+
+       spin_unlock_irqrestore(&giu_lock, flags);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(vr41xx_gpio_pullupdown);
+
+static int vr41xx_gpio_get(struct gpio_chip *chip, unsigned pin)
+{
+       u16 reg, mask;
+
+       if (pin >= chip->ngpio)
+               return -EINVAL;
+
+       if (pin < 16) {
+               reg = giu_read(GIUPIODL);
+               mask = 1 << pin;
+       } else if (pin < 32) {
+               reg = giu_read(GIUPIODH);
+               mask = 1 << (pin - 16);
+       } else if (pin < 48) {
+               reg = giu_read(GIUPODATL);
+               mask = 1 << (pin - 32);
+       } else {
+               reg = giu_read(GIUPODATH);
+               mask = 1 << (pin - 48);
+       }
+
+       if (reg & mask)
+               return 1;
+
+       return 0;
+}
+
+static void vr41xx_gpio_set(struct gpio_chip *chip, unsigned pin,
+                           int value)
+{
+       u16 offset, mask, reg;
+       unsigned long flags;
+
+       if (pin >= chip->ngpio)
+               return;
+
+       if (pin < 16) {
+               offset = GIUPIODL;
+               mask = 1 << pin;
+       } else if (pin < 32) {
+               offset = GIUPIODH;
+               mask = 1 << (pin - 16);
+       } else if (pin < 48) {
+               offset = GIUPODATL;
+               mask = 1 << (pin - 32);
+       } else {
+               offset = GIUPODATH;
+               mask = 1 << (pin - 48);
+       }
+
+       spin_lock_irqsave(&giu_lock, flags);
+
+       reg = giu_read(offset);
+       if (value)
+               reg |= mask;
+       else
+               reg &= ~mask;
+       giu_write(offset, reg);
+
+       spin_unlock_irqrestore(&giu_lock, flags);
+}
+
+
+static int vr41xx_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+       return giu_set_direction(chip, offset, GPIO_INPUT);
+}
+
+static int vr41xx_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
+                               int value)
+{
+       vr41xx_gpio_set(chip, offset, value);
+
+       return giu_set_direction(chip, offset, GPIO_OUTPUT);
+}
+
+static int vr41xx_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+       if (offset >= chip->ngpio)
+               return -EINVAL;
+
+       return GIU_IRQ_BASE + offset;
+}
+
+static struct gpio_chip vr41xx_gpio_chip = {
+       .label                  = "vr41xx",
+       .owner                  = THIS_MODULE,
+       .direction_input        = vr41xx_gpio_direction_input,
+       .get                    = vr41xx_gpio_get,
+       .direction_output       = vr41xx_gpio_direction_output,
+       .set                    = vr41xx_gpio_set,
+       .to_irq                 = vr41xx_gpio_to_irq,
+};
+
+static int __devinit giu_probe(struct platform_device *pdev)
+{
+       struct resource *res;
+       unsigned int trigger, i, pin;
+       struct irq_chip *chip;
+       int irq, retval;
+
+       switch (pdev->id) {
+       case GPIO_50PINS_PULLUPDOWN:
+               giu_flags = GPIO_HAS_PULLUPDOWN_IO;
+               vr41xx_gpio_chip.ngpio = 50;
+               break;
+       case GPIO_36PINS:
+               vr41xx_gpio_chip.ngpio = 36;
+               break;
+       case GPIO_48PINS_EDGE_SELECT:
+               giu_flags = GPIO_HAS_INTERRUPT_EDGE_SELECT;
+               vr41xx_gpio_chip.ngpio = 48;
+               break;
+       default:
+               dev_err(&pdev->dev, "GIU: unknown ID %d\n", pdev->id);
+               return -ENODEV;
+       }
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res)
+               return -EBUSY;
+
+       giu_base = ioremap(res->start, res->end - res->start + 1);
+       if (!giu_base)
+               return -ENOMEM;
+
+       vr41xx_gpio_chip.dev = &pdev->dev;
+
+       retval = gpiochip_add(&vr41xx_gpio_chip);
+
+       giu_write(GIUINTENL, 0);
+       giu_write(GIUINTENH, 0);
+
+       trigger = giu_read(GIUINTTYPH) << 16;
+       trigger |= giu_read(GIUINTTYPL);
+       for (i = GIU_IRQ_BASE; i <= GIU_IRQ_LAST; i++) {
+               pin = GPIO_PIN_OF_IRQ(i);
+               if (pin < GIUINT_HIGH_OFFSET)
+                       chip = &giuint_low_irq_chip;
+               else
+                       chip = &giuint_high_irq_chip;
+
+               if (trigger & (1 << pin))
+                       irq_set_chip_and_handler(i, chip, handle_edge_irq);
+               else
+                       irq_set_chip_and_handler(i, chip, handle_level_irq);
+
+       }
+
+       irq = platform_get_irq(pdev, 0);
+       if (irq < 0 || irq >= nr_irqs)
+               return -EBUSY;
+
+       return cascade_irq(irq, giu_get_irq);
+}
+
+static int __devexit giu_remove(struct platform_device *pdev)
+{
+       if (giu_base) {
+               iounmap(giu_base);
+               giu_base = NULL;
+       }
+
+       return 0;
+}
+
+static struct platform_driver giu_device_driver = {
+       .probe          = giu_probe,
+       .remove         = __devexit_p(giu_remove),
+       .driver         = {
+               .name   = "GIU",
+               .owner  = THIS_MODULE,
+       },
+};
+
+static int __init vr41xx_giu_init(void)
+{
+       return platform_driver_register(&giu_device_driver);
+}
+
+static void __exit vr41xx_giu_exit(void)
+{
+       platform_driver_unregister(&giu_device_driver);
+}
+
+module_init(vr41xx_giu_init);
+module_exit(vr41xx_giu_exit);
diff --git a/drivers/gpio/gpio-vx855.c b/drivers/gpio/gpio-vx855.c
new file mode 100644 (file)
index 0000000..ef5aabd
--- /dev/null
@@ -0,0 +1,333 @@
+/*
+ * Linux GPIOlib driver for the VIA VX855 integrated southbridge GPIO
+ *
+ * Copyright (C) 2009 VIA Technologies, Inc.
+ * Copyright (C) 2010 One Laptop per Child
+ * Author: Harald Welte <HaraldWelte@viatech.com>
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/gpio.h>
+#include <linux/slab.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/pci.h>
+#include <linux/io.h>
+
+#define MODULE_NAME "vx855_gpio"
+
+/* The VX855 south bridge has the following GPIO pins:
+ *     GPI 0...13      General Purpose Input
+ *     GPO 0...12      General Purpose Output
+ *     GPIO 0...14     General Purpose I/O (Open-Drain)
+ */
+
+#define NR_VX855_GPI   14
+#define NR_VX855_GPO   13
+#define NR_VX855_GPIO  15
+
+#define NR_VX855_GPInO (NR_VX855_GPI + NR_VX855_GPO)
+#define NR_VX855_GP    (NR_VX855_GPI + NR_VX855_GPO + NR_VX855_GPIO)
+
+struct vx855_gpio {
+       struct gpio_chip gpio;
+       spinlock_t lock;
+       u32 io_gpi;
+       u32 io_gpo;
+       bool gpi_reserved;
+       bool gpo_reserved;
+};
+
+/* resolve a GPIx into the corresponding bit position */
+static inline u_int32_t gpi_i_bit(int i)
+{
+       if (i < 10)
+               return 1 << i;
+       else
+               return 1 << (i + 14);
+}
+
+static inline u_int32_t gpo_o_bit(int i)
+{
+       if (i < 11)
+               return 1 << i;
+       else
+               return 1 << (i + 14);
+}
+
+static inline u_int32_t gpio_i_bit(int i)
+{
+       if (i < 14)
+               return 1 << (i + 10);
+       else
+               return 1 << (i + 14);
+}
+
+static inline u_int32_t gpio_o_bit(int i)
+{
+       if (i < 14)
+               return 1 << (i + 11);
+       else
+               return 1 << (i + 13);
+}
+
+/* Mapping betwee numeric GPIO ID and the actual GPIO hardware numbering:
+ * 0..13       GPI 0..13
+ * 14..26      GPO 0..12
+ * 27..41      GPIO 0..14
+ */
+
+static int vx855gpio_direction_input(struct gpio_chip *gpio,
+                                    unsigned int nr)
+{
+       struct vx855_gpio *vg = container_of(gpio, struct vx855_gpio, gpio);
+       unsigned long flags;
+       u_int32_t reg_out;
+
+       /* Real GPI bits are always in input direction */
+       if (nr < NR_VX855_GPI)
+               return 0;
+
+       /* Real GPO bits cannot be put in output direction */
+       if (nr < NR_VX855_GPInO)
+               return -EINVAL;
+
+       /* Open Drain GPIO have to be set to one */
+       spin_lock_irqsave(&vg->lock, flags);
+       reg_out = inl(vg->io_gpo);
+       reg_out |= gpio_o_bit(nr - NR_VX855_GPInO);
+       outl(reg_out, vg->io_gpo);
+       spin_unlock_irqrestore(&vg->lock, flags);
+
+       return 0;
+}
+
+static int vx855gpio_get(struct gpio_chip *gpio, unsigned int nr)
+{
+       struct vx855_gpio *vg = container_of(gpio, struct vx855_gpio, gpio);
+       u_int32_t reg_in;
+       int ret = 0;
+
+       if (nr < NR_VX855_GPI) {
+               reg_in = inl(vg->io_gpi);
+               if (reg_in & gpi_i_bit(nr))
+                       ret = 1;
+       } else if (nr < NR_VX855_GPInO) {
+               /* GPO don't have an input bit, we need to read it
+                * back from the output register */
+               reg_in = inl(vg->io_gpo);
+               if (reg_in & gpo_o_bit(nr - NR_VX855_GPI))
+                       ret = 1;
+       } else {
+               reg_in = inl(vg->io_gpi);
+               if (reg_in & gpio_i_bit(nr - NR_VX855_GPInO))
+                       ret = 1;
+       }
+
+       return ret;
+}
+
+static void vx855gpio_set(struct gpio_chip *gpio, unsigned int nr,
+                         int val)
+{
+       struct vx855_gpio *vg = container_of(gpio, struct vx855_gpio, gpio);
+       unsigned long flags;
+       u_int32_t reg_out;
+
+       /* True GPI cannot be switched to output mode */
+       if (nr < NR_VX855_GPI)
+               return;
+
+       spin_lock_irqsave(&vg->lock, flags);
+       reg_out = inl(vg->io_gpo);
+       if (nr < NR_VX855_GPInO) {
+               if (val)
+                       reg_out |= gpo_o_bit(nr - NR_VX855_GPI);
+               else
+                       reg_out &= ~gpo_o_bit(nr - NR_VX855_GPI);
+       } else {
+               if (val)
+                       reg_out |= gpio_o_bit(nr - NR_VX855_GPInO);
+               else
+                       reg_out &= ~gpio_o_bit(nr - NR_VX855_GPInO);
+       }
+       outl(reg_out, vg->io_gpo);
+       spin_unlock_irqrestore(&vg->lock, flags);
+}
+
+static int vx855gpio_direction_output(struct gpio_chip *gpio,
+                                     unsigned int nr, int val)
+{
+       /* True GPI cannot be switched to output mode */
+       if (nr < NR_VX855_GPI)
+               return -EINVAL;
+
+       /* True GPO don't need to be switched to output mode,
+        * and GPIO are open-drain, i.e. also need no switching,
+        * so all we do is set the level */
+       vx855gpio_set(gpio, nr, val);
+
+       return 0;
+}
+
+static const char *vx855gpio_names[NR_VX855_GP] = {
+       "VX855_GPI0", "VX855_GPI1", "VX855_GPI2", "VX855_GPI3", "VX855_GPI4",
+       "VX855_GPI5", "VX855_GPI6", "VX855_GPI7", "VX855_GPI8", "VX855_GPI9",
+       "VX855_GPI10", "VX855_GPI11", "VX855_GPI12", "VX855_GPI13",
+       "VX855_GPO0", "VX855_GPO1", "VX855_GPO2", "VX855_GPO3", "VX855_GPO4",
+       "VX855_GPO5", "VX855_GPO6", "VX855_GPO7", "VX855_GPO8", "VX855_GPO9",
+       "VX855_GPO10", "VX855_GPO11", "VX855_GPO12",
+       "VX855_GPIO0", "VX855_GPIO1", "VX855_GPIO2", "VX855_GPIO3",
+       "VX855_GPIO4", "VX855_GPIO5", "VX855_GPIO6", "VX855_GPIO7",
+       "VX855_GPIO8", "VX855_GPIO9", "VX855_GPIO10", "VX855_GPIO11",
+       "VX855_GPIO12", "VX855_GPIO13", "VX855_GPIO14"
+};
+
+static void vx855gpio_gpio_setup(struct vx855_gpio *vg)
+{
+       struct gpio_chip *c = &vg->gpio;
+
+       c->label = "VX855 South Bridge";
+       c->owner = THIS_MODULE;
+       c->direction_input = vx855gpio_direction_input;
+       c->direction_output = vx855gpio_direction_output;
+       c->get = vx855gpio_get;
+       c->set = vx855gpio_set;
+       c->dbg_show = NULL;
+       c->base = 0;
+       c->ngpio = NR_VX855_GP;
+       c->can_sleep = 0;
+       c->names = vx855gpio_names;
+}
+
+/* This platform device is ordinarily registered by the vx855 mfd driver */
+static __devinit int vx855gpio_probe(struct platform_device *pdev)
+{
+       struct resource *res_gpi;
+       struct resource *res_gpo;
+       struct vx855_gpio *vg;
+       int ret;
+
+       res_gpi = platform_get_resource(pdev, IORESOURCE_IO, 0);
+       res_gpo = platform_get_resource(pdev, IORESOURCE_IO, 1);
+       if (!res_gpi || !res_gpo)
+               return -EBUSY;
+
+       vg = kzalloc(sizeof(*vg), GFP_KERNEL);
+       if (!vg)
+               return -ENOMEM;
+
+       platform_set_drvdata(pdev, vg);
+
+       dev_info(&pdev->dev, "found VX855 GPIO controller\n");
+       vg->io_gpi = res_gpi->start;
+       vg->io_gpo = res_gpo->start;
+       spin_lock_init(&vg->lock);
+
+       /*
+        * A single byte is used to control various GPIO ports on the VX855,
+        * and in the case of the OLPC XO-1.5, some of those ports are used
+        * for switches that are interpreted and exposed through ACPI. ACPI
+        * will have reserved the region, so our own reservation will not
+        * succeed. Ignore and continue.
+        */
+
+       if (!request_region(res_gpi->start, resource_size(res_gpi),
+                       MODULE_NAME "_gpi"))
+               dev_warn(&pdev->dev,
+                       "GPI I/O resource busy, probably claimed by ACPI\n");
+       else
+               vg->gpi_reserved = true;
+
+       if (!request_region(res_gpo->start, resource_size(res_gpo),
+                       MODULE_NAME "_gpo"))
+               dev_warn(&pdev->dev,
+                       "GPO I/O resource busy, probably claimed by ACPI\n");
+       else
+               vg->gpo_reserved = true;
+
+       vx855gpio_gpio_setup(vg);
+
+       ret = gpiochip_add(&vg->gpio);
+       if (ret) {
+               dev_err(&pdev->dev, "failed to register GPIOs\n");
+               goto out_release;
+       }
+
+       return 0;
+
+out_release:
+       if (vg->gpi_reserved)
+               release_region(res_gpi->start, resource_size(res_gpi));
+       if (vg->gpo_reserved)
+               release_region(res_gpi->start, resource_size(res_gpo));
+       platform_set_drvdata(pdev, NULL);
+       kfree(vg);
+       return ret;
+}
+
+static int __devexit vx855gpio_remove(struct platform_device *pdev)
+{
+       struct vx855_gpio *vg = platform_get_drvdata(pdev);
+       struct resource *res;
+
+       if (gpiochip_remove(&vg->gpio))
+               dev_err(&pdev->dev, "unable to remove gpio_chip?\n");
+
+       if (vg->gpi_reserved) {
+               res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+               release_region(res->start, resource_size(res));
+       }
+       if (vg->gpo_reserved) {
+               res = platform_get_resource(pdev, IORESOURCE_IO, 1);
+               release_region(res->start, resource_size(res));
+       }
+
+       platform_set_drvdata(pdev, NULL);
+       kfree(vg);
+       return 0;
+}
+
+static struct platform_driver vx855gpio_driver = {
+       .driver = {
+               .name   = MODULE_NAME,
+               .owner  = THIS_MODULE,
+       },
+       .probe          = vx855gpio_probe,
+       .remove         = __devexit_p(vx855gpio_remove),
+};
+
+static int vx855gpio_init(void)
+{
+       return platform_driver_register(&vx855gpio_driver);
+}
+module_init(vx855gpio_init);
+
+static void vx855gpio_exit(void)
+{
+       platform_driver_unregister(&vx855gpio_driver);
+}
+module_exit(vx855gpio_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Harald Welte <HaraldWelte@viatech.com>");
+MODULE_DESCRIPTION("GPIO driver for the VIA VX855 chipset");
+MODULE_ALIAS("platform:vx855_gpio");
diff --git a/drivers/gpio/gpio-wm831x.c b/drivers/gpio/gpio-wm831x.c
new file mode 100644 (file)
index 0000000..31a9ed7
--- /dev/null
@@ -0,0 +1,317 @@
+/*
+ * gpiolib support for Wolfson WM831x PMICs
+ *
+ * Copyright 2009 Wolfson Microelectronics PLC.
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ *  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/kernel.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/gpio.h>
+#include <linux/mfd/core.h>
+#include <linux/platform_device.h>
+#include <linux/seq_file.h>
+
+#include <linux/mfd/wm831x/core.h>
+#include <linux/mfd/wm831x/pdata.h>
+#include <linux/mfd/wm831x/gpio.h>
+#include <linux/mfd/wm831x/irq.h>
+
+struct wm831x_gpio {
+       struct wm831x *wm831x;
+       struct gpio_chip gpio_chip;
+};
+
+static inline struct wm831x_gpio *to_wm831x_gpio(struct gpio_chip *chip)
+{
+       return container_of(chip, struct wm831x_gpio, gpio_chip);
+}
+
+static int wm831x_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
+{
+       struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip);
+       struct wm831x *wm831x = wm831x_gpio->wm831x;
+       int val = WM831X_GPN_DIR;
+
+       if (wm831x->has_gpio_ena)
+               val |= WM831X_GPN_TRI;
+
+       return wm831x_set_bits(wm831x, WM831X_GPIO1_CONTROL + offset,
+                              WM831X_GPN_DIR | WM831X_GPN_TRI |
+                              WM831X_GPN_FN_MASK, val);
+}
+
+static int wm831x_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+       struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip);
+       struct wm831x *wm831x = wm831x_gpio->wm831x;
+       int ret;
+
+       ret = wm831x_reg_read(wm831x, WM831X_GPIO_LEVEL);
+       if (ret < 0)
+               return ret;
+
+       if (ret & 1 << offset)
+               return 1;
+       else
+               return 0;
+}
+
+static void wm831x_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+       struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip);
+       struct wm831x *wm831x = wm831x_gpio->wm831x;
+
+       wm831x_set_bits(wm831x, WM831X_GPIO_LEVEL, 1 << offset,
+                       value << offset);
+}
+
+static int wm831x_gpio_direction_out(struct gpio_chip *chip,
+                                    unsigned offset, int value)
+{
+       struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip);
+       struct wm831x *wm831x = wm831x_gpio->wm831x;
+       int val = 0;
+       int ret;
+
+       if (wm831x->has_gpio_ena)
+               val |= WM831X_GPN_TRI;
+
+       ret = wm831x_set_bits(wm831x, WM831X_GPIO1_CONTROL + offset,
+                             WM831X_GPN_DIR | WM831X_GPN_TRI |
+                             WM831X_GPN_FN_MASK, val);
+       if (ret < 0)
+               return ret;
+
+       /* Can only set GPIO state once it's in output mode */
+       wm831x_gpio_set(chip, offset, value);
+
+       return 0;
+}
+
+static int wm831x_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+       struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip);
+       struct wm831x *wm831x = wm831x_gpio->wm831x;
+
+       if (!wm831x->irq_base)
+               return -EINVAL;
+
+       return wm831x->irq_base + WM831X_IRQ_GPIO_1 + offset;
+}
+
+static int wm831x_gpio_set_debounce(struct gpio_chip *chip, unsigned offset,
+                                   unsigned debounce)
+{
+       struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip);
+       struct wm831x *wm831x = wm831x_gpio->wm831x;
+       int reg = WM831X_GPIO1_CONTROL + offset;
+       int ret, fn;
+
+       ret = wm831x_reg_read(wm831x, reg);
+       if (ret < 0)
+               return ret;
+
+       switch (ret & WM831X_GPN_FN_MASK) {
+       case 0:
+       case 1:
+               break;
+       default:
+               /* Not in GPIO mode */
+               return -EBUSY;
+       }
+
+       if (debounce >= 32 && debounce <= 64)
+               fn = 0;
+       else if (debounce >= 4000 && debounce <= 8000)
+               fn = 1;
+       else
+               return -EINVAL;
+
+       return wm831x_set_bits(wm831x, reg, WM831X_GPN_FN_MASK, fn);
+}
+
+#ifdef CONFIG_DEBUG_FS
+static void wm831x_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
+{
+       struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip);
+       struct wm831x *wm831x = wm831x_gpio->wm831x;
+       int i, tristated;
+
+       for (i = 0; i < chip->ngpio; i++) {
+               int gpio = i + chip->base;
+               int reg;
+               const char *label, *pull, *powerdomain;
+
+               /* We report the GPIO even if it's not requested since
+                * we're also reporting things like alternate
+                * functions which apply even when the GPIO is not in
+                * use as a GPIO.
+                */
+               label = gpiochip_is_requested(chip, i);
+               if (!label)
+                       label = "Unrequested";
+
+               seq_printf(s, " gpio-%-3d (%-20.20s) ", gpio, label);
+
+               reg = wm831x_reg_read(wm831x, WM831X_GPIO1_CONTROL + i);
+               if (reg < 0) {
+                       dev_err(wm831x->dev,
+                               "GPIO control %d read failed: %d\n",
+                               gpio, reg);
+                       seq_printf(s, "\n");
+                       continue;
+               }
+
+               switch (reg & WM831X_GPN_PULL_MASK) {
+               case WM831X_GPIO_PULL_NONE:
+                       pull = "nopull";
+                       break;
+               case WM831X_GPIO_PULL_DOWN:
+                       pull = "pulldown";
+                       break;
+               case WM831X_GPIO_PULL_UP:
+                       pull = "pullup";
+               default:
+                       pull = "INVALID PULL";
+                       break;
+               }
+
+               switch (i + 1) {
+               case 1 ... 3:
+               case 7 ... 9:
+                       if (reg & WM831X_GPN_PWR_DOM)
+                               powerdomain = "VPMIC";
+                       else
+                               powerdomain = "DBVDD";
+                       break;
+
+               case 4 ... 6:
+               case 10 ... 12:
+                       if (reg & WM831X_GPN_PWR_DOM)
+                               powerdomain = "SYSVDD";
+                       else
+                               powerdomain = "DBVDD";
+                       break;
+
+               case 13 ... 16:
+                       powerdomain = "TPVDD";
+                       break;
+
+               default:
+                       BUG();
+                       break;
+               }
+
+               tristated = reg & WM831X_GPN_TRI;
+               if (wm831x->has_gpio_ena)
+                       tristated = !tristated;
+
+               seq_printf(s, " %s %s %s %s%s\n"
+                          "                                  %s%s (0x%4x)\n",
+                          reg & WM831X_GPN_DIR ? "in" : "out",
+                          wm831x_gpio_get(chip, i) ? "high" : "low",
+                          pull,
+                          powerdomain,
+                          reg & WM831X_GPN_POL ? "" : " inverted",
+                          reg & WM831X_GPN_OD ? "open-drain" : "CMOS",
+                          tristated ? " tristated" : "",
+                          reg);
+       }
+}
+#else
+#define wm831x_gpio_dbg_show NULL
+#endif
+
+static struct gpio_chip template_chip = {
+       .label                  = "wm831x",
+       .owner                  = THIS_MODULE,
+       .direction_input        = wm831x_gpio_direction_in,
+       .get                    = wm831x_gpio_get,
+       .direction_output       = wm831x_gpio_direction_out,
+       .set                    = wm831x_gpio_set,
+       .to_irq                 = wm831x_gpio_to_irq,
+       .set_debounce           = wm831x_gpio_set_debounce,
+       .dbg_show               = wm831x_gpio_dbg_show,
+       .can_sleep              = 1,
+};
+
+static int __devinit 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_gpio *wm831x_gpio;
+       int ret;
+
+       wm831x_gpio = kzalloc(sizeof(*wm831x_gpio), GFP_KERNEL);
+       if (wm831x_gpio == NULL)
+               return -ENOMEM;
+
+       wm831x_gpio->wm831x = wm831x;
+       wm831x_gpio->gpio_chip = template_chip;
+       wm831x_gpio->gpio_chip.ngpio = wm831x->num_gpio;
+       wm831x_gpio->gpio_chip.dev = &pdev->dev;
+       if (pdata && pdata->gpio_base)
+               wm831x_gpio->gpio_chip.base = pdata->gpio_base;
+       else
+               wm831x_gpio->gpio_chip.base = -1;
+
+       ret = gpiochip_add(&wm831x_gpio->gpio_chip);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "Could not register gpiochip, %d\n",
+                       ret);
+               goto err;
+       }
+
+       platform_set_drvdata(pdev, wm831x_gpio);
+
+       return ret;
+
+err:
+       kfree(wm831x_gpio);
+       return ret;
+}
+
+static int __devexit wm831x_gpio_remove(struct platform_device *pdev)
+{
+       struct wm831x_gpio *wm831x_gpio = platform_get_drvdata(pdev);
+       int ret;
+
+       ret = gpiochip_remove(&wm831x_gpio->gpio_chip);
+       if (ret == 0)
+               kfree(wm831x_gpio);
+
+       return ret;
+}
+
+static struct platform_driver wm831x_gpio_driver = {
+       .driver.name    = "wm831x-gpio",
+       .driver.owner   = THIS_MODULE,
+       .probe          = wm831x_gpio_probe,
+       .remove         = __devexit_p(wm831x_gpio_remove),
+};
+
+static int __init wm831x_gpio_init(void)
+{
+       return platform_driver_register(&wm831x_gpio_driver);
+}
+subsys_initcall(wm831x_gpio_init);
+
+static void __exit wm831x_gpio_exit(void)
+{
+       platform_driver_unregister(&wm831x_gpio_driver);
+}
+module_exit(wm831x_gpio_exit);
+
+MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
+MODULE_DESCRIPTION("GPIO interface for WM831x PMICs");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:wm831x-gpio");
diff --git a/drivers/gpio/gpio-wm8350.c b/drivers/gpio/gpio-wm8350.c
new file mode 100644 (file)
index 0000000..a06af51
--- /dev/null
@@ -0,0 +1,182 @@
+/*
+ * gpiolib support for Wolfson WM835x PMICs
+ *
+ * Copyright 2009 Wolfson Microelectronics PLC.
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ *  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/kernel.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/gpio.h>
+#include <linux/mfd/core.h>
+#include <linux/platform_device.h>
+#include <linux/seq_file.h>
+
+#include <linux/mfd/wm8350/core.h>
+#include <linux/mfd/wm8350/gpio.h>
+
+struct wm8350_gpio_data {
+       struct wm8350 *wm8350;
+       struct gpio_chip gpio_chip;
+};
+
+static inline struct wm8350_gpio_data *to_wm8350_gpio(struct gpio_chip *chip)
+{
+       return container_of(chip, struct wm8350_gpio_data, gpio_chip);
+}
+
+static int wm8350_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
+{
+       struct wm8350_gpio_data *wm8350_gpio = to_wm8350_gpio(chip);
+       struct wm8350 *wm8350 = wm8350_gpio->wm8350;
+
+       return wm8350_set_bits(wm8350, WM8350_GPIO_CONFIGURATION_I_O,
+                              1 << offset);
+}
+
+static int wm8350_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+       struct wm8350_gpio_data *wm8350_gpio = to_wm8350_gpio(chip);
+       struct wm8350 *wm8350 = wm8350_gpio->wm8350;
+       int ret;
+
+       ret = wm8350_reg_read(wm8350, WM8350_GPIO_LEVEL);
+       if (ret < 0)
+               return ret;
+
+       if (ret & (1 << offset))
+               return 1;
+       else
+               return 0;
+}
+
+static void wm8350_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+       struct wm8350_gpio_data *wm8350_gpio = to_wm8350_gpio(chip);
+       struct wm8350 *wm8350 = wm8350_gpio->wm8350;
+
+       if (value)
+               wm8350_set_bits(wm8350, WM8350_GPIO_LEVEL, 1 << offset);
+       else
+               wm8350_clear_bits(wm8350, WM8350_GPIO_LEVEL, 1 << offset);
+}
+
+static int wm8350_gpio_direction_out(struct gpio_chip *chip,
+                                    unsigned offset, int value)
+{
+       struct wm8350_gpio_data *wm8350_gpio = to_wm8350_gpio(chip);
+       struct wm8350 *wm8350 = wm8350_gpio->wm8350;
+       int ret;
+
+       ret = wm8350_clear_bits(wm8350, WM8350_GPIO_CONFIGURATION_I_O,
+                               1 << offset);
+       if (ret < 0)
+               return ret;
+
+       /* Don't have an atomic direction/value setup */
+       wm8350_gpio_set(chip, offset, value);
+
+       return 0;
+}
+
+static int wm8350_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+       struct wm8350_gpio_data *wm8350_gpio = to_wm8350_gpio(chip);
+       struct wm8350 *wm8350 = wm8350_gpio->wm8350;
+
+       if (!wm8350->irq_base)
+               return -EINVAL;
+
+       return wm8350->irq_base + WM8350_IRQ_GPIO(offset);
+}
+
+static struct gpio_chip template_chip = {
+       .label                  = "wm8350",
+       .owner                  = THIS_MODULE,
+       .direction_input        = wm8350_gpio_direction_in,
+       .get                    = wm8350_gpio_get,
+       .direction_output       = wm8350_gpio_direction_out,
+       .set                    = wm8350_gpio_set,
+       .to_irq                 = wm8350_gpio_to_irq,
+       .can_sleep              = 1,
+};
+
+static int __devinit 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_gpio_data *wm8350_gpio;
+       int ret;
+
+       wm8350_gpio = kzalloc(sizeof(*wm8350_gpio), GFP_KERNEL);
+       if (wm8350_gpio == NULL)
+               return -ENOMEM;
+
+       wm8350_gpio->wm8350 = wm8350;
+       wm8350_gpio->gpio_chip = template_chip;
+       wm8350_gpio->gpio_chip.ngpio = 13;
+       wm8350_gpio->gpio_chip.dev = &pdev->dev;
+       if (pdata && pdata->gpio_base)
+               wm8350_gpio->gpio_chip.base = pdata->gpio_base;
+       else
+               wm8350_gpio->gpio_chip.base = -1;
+
+       ret = gpiochip_add(&wm8350_gpio->gpio_chip);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "Could not register gpiochip, %d\n",
+                       ret);
+               goto err;
+       }
+
+       platform_set_drvdata(pdev, wm8350_gpio);
+
+       return ret;
+
+err:
+       kfree(wm8350_gpio);
+       return ret;
+}
+
+static int __devexit wm8350_gpio_remove(struct platform_device *pdev)
+{
+       struct wm8350_gpio_data *wm8350_gpio = platform_get_drvdata(pdev);
+       int ret;
+
+       ret = gpiochip_remove(&wm8350_gpio->gpio_chip);
+       if (ret == 0)
+               kfree(wm8350_gpio);
+
+       return ret;
+}
+
+static struct platform_driver wm8350_gpio_driver = {
+       .driver.name    = "wm8350-gpio",
+       .driver.owner   = THIS_MODULE,
+       .probe          = wm8350_gpio_probe,
+       .remove         = __devexit_p(wm8350_gpio_remove),
+};
+
+static int __init wm8350_gpio_init(void)
+{
+       return platform_driver_register(&wm8350_gpio_driver);
+}
+subsys_initcall(wm8350_gpio_init);
+
+static void __exit wm8350_gpio_exit(void)
+{
+       platform_driver_unregister(&wm8350_gpio_driver);
+}
+module_exit(wm8350_gpio_exit);
+
+MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
+MODULE_DESCRIPTION("GPIO interface for WM8350 PMICs");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:wm8350-gpio");
diff --git a/drivers/gpio/gpio-wm8994.c b/drivers/gpio/gpio-wm8994.c
new file mode 100644 (file)
index 0000000..96198f3
--- /dev/null
@@ -0,0 +1,242 @@
+/*
+ * gpiolib support for Wolfson WM8994
+ *
+ * Copyright 2009 Wolfson Microelectronics PLC.
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ *  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/kernel.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/gpio.h>
+#include <linux/mfd/core.h>
+#include <linux/platform_device.h>
+#include <linux/seq_file.h>
+
+#include <linux/mfd/wm8994/core.h>
+#include <linux/mfd/wm8994/pdata.h>
+#include <linux/mfd/wm8994/gpio.h>
+#include <linux/mfd/wm8994/registers.h>
+
+struct wm8994_gpio {
+       struct wm8994 *wm8994;
+       struct gpio_chip gpio_chip;
+};
+
+static inline struct wm8994_gpio *to_wm8994_gpio(struct gpio_chip *chip)
+{
+       return container_of(chip, struct wm8994_gpio, gpio_chip);
+}
+
+static int wm8994_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+       struct wm8994_gpio *wm8994_gpio = to_wm8994_gpio(chip);
+       struct wm8994 *wm8994 = wm8994_gpio->wm8994;
+
+       switch (wm8994->type) {
+       case WM8958:
+               switch (offset) {
+               case 1:
+               case 2:
+               case 3:
+               case 4:
+               case 6:
+                       return -EINVAL;
+               }
+               break;
+       default:
+               break;
+       }
+
+       return 0;
+}
+
+static int wm8994_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
+{
+       struct wm8994_gpio *wm8994_gpio = to_wm8994_gpio(chip);
+       struct wm8994 *wm8994 = wm8994_gpio->wm8994;
+
+       return wm8994_set_bits(wm8994, WM8994_GPIO_1 + offset,
+                              WM8994_GPN_DIR, WM8994_GPN_DIR);
+}
+
+static int wm8994_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+       struct wm8994_gpio *wm8994_gpio = to_wm8994_gpio(chip);
+       struct wm8994 *wm8994 = wm8994_gpio->wm8994;
+       int ret;
+
+       ret = wm8994_reg_read(wm8994, WM8994_GPIO_1 + offset);
+       if (ret < 0)
+               return ret;
+
+       if (ret & WM8994_GPN_LVL)
+               return 1;
+       else
+               return 0;
+}
+
+static int wm8994_gpio_direction_out(struct gpio_chip *chip,
+                                    unsigned offset, int value)
+{
+       struct wm8994_gpio *wm8994_gpio = to_wm8994_gpio(chip);
+       struct wm8994 *wm8994 = wm8994_gpio->wm8994;
+
+       return wm8994_set_bits(wm8994, WM8994_GPIO_1 + offset,
+                              WM8994_GPN_DIR, 0);
+}
+
+static void wm8994_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+       struct wm8994_gpio *wm8994_gpio = to_wm8994_gpio(chip);
+       struct wm8994 *wm8994 = wm8994_gpio->wm8994;
+
+       if (value)
+               value = WM8994_GPN_LVL;
+
+       wm8994_set_bits(wm8994, WM8994_GPIO_1 + offset, WM8994_GPN_LVL, value);
+}
+
+static int wm8994_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+       struct wm8994_gpio *wm8994_gpio = to_wm8994_gpio(chip);
+       struct wm8994 *wm8994 = wm8994_gpio->wm8994;
+
+       if (!wm8994->irq_base)
+               return -EINVAL;
+
+       return wm8994->irq_base + offset;
+}
+
+
+#ifdef CONFIG_DEBUG_FS
+static void wm8994_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
+{
+       struct wm8994_gpio *wm8994_gpio = to_wm8994_gpio(chip);
+       struct wm8994 *wm8994 = wm8994_gpio->wm8994;
+       int i;
+
+       for (i = 0; i < chip->ngpio; i++) {
+               int gpio = i + chip->base;
+               int reg;
+               const char *label;
+
+               /* We report the GPIO even if it's not requested since
+                * we're also reporting things like alternate
+                * functions which apply even when the GPIO is not in
+                * use as a GPIO.
+                */
+               label = gpiochip_is_requested(chip, i);
+               if (!label)
+                       label = "Unrequested";
+
+               seq_printf(s, " gpio-%-3d (%-20.20s) ", gpio, label);
+
+               reg = wm8994_reg_read(wm8994, WM8994_GPIO_1 + i);
+               if (reg < 0) {
+                       dev_err(wm8994->dev,
+                               "GPIO control %d read failed: %d\n",
+                               gpio, reg);
+                       seq_printf(s, "\n");
+                       continue;
+               }
+
+               /* No decode yet; note that GPIO2 is special */
+               seq_printf(s, "(%x)\n", reg);
+       }
+}
+#else
+#define wm8994_gpio_dbg_show NULL
+#endif
+
+static struct gpio_chip template_chip = {
+       .label                  = "wm8994",
+       .owner                  = THIS_MODULE,
+       .request                = wm8994_gpio_request,
+       .direction_input        = wm8994_gpio_direction_in,
+       .get                    = wm8994_gpio_get,
+       .direction_output       = wm8994_gpio_direction_out,
+       .set                    = wm8994_gpio_set,
+       .to_irq                 = wm8994_gpio_to_irq,
+       .dbg_show               = wm8994_gpio_dbg_show,
+       .can_sleep              = 1,
+};
+
+static int __devinit 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_gpio *wm8994_gpio;
+       int ret;
+
+       wm8994_gpio = kzalloc(sizeof(*wm8994_gpio), GFP_KERNEL);
+       if (wm8994_gpio == NULL)
+               return -ENOMEM;
+
+       wm8994_gpio->wm8994 = wm8994;
+       wm8994_gpio->gpio_chip = template_chip;
+       wm8994_gpio->gpio_chip.ngpio = WM8994_GPIO_MAX;
+       wm8994_gpio->gpio_chip.dev = &pdev->dev;
+       if (pdata && pdata->gpio_base)
+               wm8994_gpio->gpio_chip.base = pdata->gpio_base;
+       else
+               wm8994_gpio->gpio_chip.base = -1;
+
+       ret = gpiochip_add(&wm8994_gpio->gpio_chip);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "Could not register gpiochip, %d\n",
+                       ret);
+               goto err;
+       }
+
+       platform_set_drvdata(pdev, wm8994_gpio);
+
+       return ret;
+
+err:
+       kfree(wm8994_gpio);
+       return ret;
+}
+
+static int __devexit wm8994_gpio_remove(struct platform_device *pdev)
+{
+       struct wm8994_gpio *wm8994_gpio = platform_get_drvdata(pdev);
+       int ret;
+
+       ret = gpiochip_remove(&wm8994_gpio->gpio_chip);
+       if (ret == 0)
+               kfree(wm8994_gpio);
+
+       return ret;
+}
+
+static struct platform_driver wm8994_gpio_driver = {
+       .driver.name    = "wm8994-gpio",
+       .driver.owner   = THIS_MODULE,
+       .probe          = wm8994_gpio_probe,
+       .remove         = __devexit_p(wm8994_gpio_remove),
+};
+
+static int __init wm8994_gpio_init(void)
+{
+       return platform_driver_register(&wm8994_gpio_driver);
+}
+subsys_initcall(wm8994_gpio_init);
+
+static void __exit wm8994_gpio_exit(void)
+{
+       platform_driver_unregister(&wm8994_gpio_driver);
+}
+module_exit(wm8994_gpio_exit);
+
+MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
+MODULE_DESCRIPTION("GPIO interface for WM8994");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:wm8994-gpio");
diff --git a/drivers/gpio/gpio-xilinx.c b/drivers/gpio/gpio-xilinx.c
new file mode 100644 (file)
index 0000000..846fbd5
--- /dev/null
@@ -0,0 +1,233 @@
+/*
+ * Xilinx gpio driver
+ *
+ * Copyright 2008 Xilinx, Inc.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
+#include <linux/of_gpio.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/slab.h>
+
+/* Register Offset Definitions */
+#define XGPIO_DATA_OFFSET   (0x0)      /* Data register  */
+#define XGPIO_TRI_OFFSET    (0x4)      /* I/O direction register  */
+
+struct xgpio_instance {
+       struct of_mm_gpio_chip mmchip;
+       u32 gpio_state;         /* GPIO state shadow register */
+       u32 gpio_dir;           /* GPIO direction shadow register */
+       spinlock_t gpio_lock;   /* Lock used for synchronization */
+};
+
+/**
+ * xgpio_get - Read the specified signal of the GPIO device.
+ * @gc:     Pointer to gpio_chip device structure.
+ * @gpio:   GPIO signal number.
+ *
+ * This function reads the specified signal of the GPIO device. It returns 0 if
+ * the signal clear, 1 if signal is set or negative value on error.
+ */
+static int xgpio_get(struct gpio_chip *gc, unsigned int gpio)
+{
+       struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
+
+       return (in_be32(mm_gc->regs + XGPIO_DATA_OFFSET) >> gpio) & 1;
+}
+
+/**
+ * xgpio_set - Write the specified signal of the GPIO device.
+ * @gc:     Pointer to gpio_chip device structure.
+ * @gpio:   GPIO signal number.
+ * @val:    Value to be written to specified signal.
+ *
+ * This function writes the specified value in to the specified signal of the
+ * GPIO device.
+ */
+static void xgpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
+{
+       unsigned long flags;
+       struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
+       struct xgpio_instance *chip =
+           container_of(mm_gc, struct xgpio_instance, mmchip);
+
+       spin_lock_irqsave(&chip->gpio_lock, flags);
+
+       /* Write to GPIO signal and set its direction to output */
+       if (val)
+               chip->gpio_state |= 1 << gpio;
+       else
+               chip->gpio_state &= ~(1 << gpio);
+       out_be32(mm_gc->regs + XGPIO_DATA_OFFSET, chip->gpio_state);
+
+       spin_unlock_irqrestore(&chip->gpio_lock, flags);
+}
+
+/**
+ * xgpio_dir_in - Set the direction of the specified GPIO signal as input.
+ * @gc:     Pointer to gpio_chip device structure.
+ * @gpio:   GPIO signal number.
+ *
+ * This function sets the direction of specified GPIO signal as input.
+ * It returns 0 if direction of GPIO signals is set as input otherwise it
+ * returns negative error value.
+ */
+static int xgpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
+{
+       unsigned long flags;
+       struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
+       struct xgpio_instance *chip =
+           container_of(mm_gc, struct xgpio_instance, mmchip);
+
+       spin_lock_irqsave(&chip->gpio_lock, flags);
+
+       /* Set the GPIO bit in shadow register and set direction as input */
+       chip->gpio_dir |= (1 << gpio);
+       out_be32(mm_gc->regs + XGPIO_TRI_OFFSET, chip->gpio_dir);
+
+       spin_unlock_irqrestore(&chip->gpio_lock, flags);
+
+       return 0;
+}
+
+/**
+ * xgpio_dir_out - Set the direction of the specified GPIO signal as output.
+ * @gc:     Pointer to gpio_chip device structure.
+ * @gpio:   GPIO signal number.
+ * @val:    Value to be written to specified signal.
+ *
+ * This function sets the direction of specified GPIO signal as output. If all
+ * GPIO signals of GPIO chip is configured as input then it returns
+ * error otherwise it returns 0.
+ */
+static int xgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
+{
+       unsigned long flags;
+       struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
+       struct xgpio_instance *chip =
+           container_of(mm_gc, struct xgpio_instance, mmchip);
+
+       spin_lock_irqsave(&chip->gpio_lock, flags);
+
+       /* Write state of GPIO signal */
+       if (val)
+               chip->gpio_state |= 1 << gpio;
+       else
+               chip->gpio_state &= ~(1 << gpio);
+       out_be32(mm_gc->regs + XGPIO_DATA_OFFSET, chip->gpio_state);
+
+       /* Clear the GPIO bit in shadow register and set direction as output */
+       chip->gpio_dir &= (~(1 << gpio));
+       out_be32(mm_gc->regs + XGPIO_TRI_OFFSET, chip->gpio_dir);
+
+       spin_unlock_irqrestore(&chip->gpio_lock, flags);
+
+       return 0;
+}
+
+/**
+ * xgpio_save_regs - Set initial values of GPIO pins
+ * @mm_gc: pointer to memory mapped GPIO chip structure
+ */
+static void xgpio_save_regs(struct of_mm_gpio_chip *mm_gc)
+{
+       struct xgpio_instance *chip =
+           container_of(mm_gc, struct xgpio_instance, mmchip);
+
+       out_be32(mm_gc->regs + XGPIO_DATA_OFFSET, chip->gpio_state);
+       out_be32(mm_gc->regs + XGPIO_TRI_OFFSET, chip->gpio_dir);
+}
+
+/**
+ * xgpio_of_probe - Probe method for the GPIO device.
+ * @np: pointer to device tree node
+ *
+ * This function probes the GPIO device in the device tree. It initializes the
+ * driver data structure. It returns 0, if the driver is bound to the GPIO
+ * device, or a negative value if there is an error.
+ */
+static int __devinit xgpio_of_probe(struct device_node *np)
+{
+       struct xgpio_instance *chip;
+       int status = 0;
+       const u32 *tree_info;
+
+       chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+       if (!chip)
+               return -ENOMEM;
+
+       /* Update GPIO state shadow register with default value */
+       tree_info = of_get_property(np, "xlnx,dout-default", NULL);
+       if (tree_info)
+               chip->gpio_state = be32_to_cpup(tree_info);
+
+       /* Update GPIO direction shadow register with default value */
+       chip->gpio_dir = 0xFFFFFFFF; /* By default, all pins are inputs */
+       tree_info = of_get_property(np, "xlnx,tri-default", NULL);
+       if (tree_info)
+               chip->gpio_dir = be32_to_cpup(tree_info);
+
+       /* Check device node and parent device node for device width */
+       chip->mmchip.gc.ngpio = 32; /* By default assume full GPIO controller */
+       tree_info = of_get_property(np, "xlnx,gpio-width", NULL);
+       if (!tree_info)
+               tree_info = of_get_property(np->parent,
+                                           "xlnx,gpio-width", NULL);
+       if (tree_info)
+               chip->mmchip.gc.ngpio = be32_to_cpup(tree_info);
+
+       spin_lock_init(&chip->gpio_lock);
+
+       chip->mmchip.gc.direction_input = xgpio_dir_in;
+       chip->mmchip.gc.direction_output = xgpio_dir_out;
+       chip->mmchip.gc.get = xgpio_get;
+       chip->mmchip.gc.set = xgpio_set;
+
+       chip->mmchip.save_regs = xgpio_save_regs;
+
+       /* Call the OF gpio helper to setup and register the GPIO device */
+       status = of_mm_gpiochip_add(np, &chip->mmchip);
+       if (status) {
+               kfree(chip);
+               pr_err("%s: error in probe function with status %d\n",
+                      np->full_name, status);
+               return status;
+       }
+       pr_info("XGpio: %s: registered\n", np->full_name);
+       return 0;
+}
+
+static struct of_device_id xgpio_of_match[] __devinitdata = {
+       { .compatible = "xlnx,xps-gpio-1.00.a", },
+       { /* end of list */ },
+};
+
+static int __init xgpio_init(void)
+{
+       struct device_node *np;
+
+       for_each_matching_node(np, xgpio_of_match)
+               xgpio_of_probe(np);
+
+       return 0;
+}
+
+/* Make sure we get initialized before anyone else tries to use us */
+subsys_initcall(xgpio_init);
+/* No exit call at the moment as we cannot unregister of GPIO chips */
+
+MODULE_AUTHOR("Xilinx, Inc.");
+MODULE_DESCRIPTION("Xilinx GPIO driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/it8761e_gpio.c b/drivers/gpio/it8761e_gpio.c
deleted file mode 100644 (file)
index 48fc43c..0000000
+++ /dev/null
@@ -1,234 +0,0 @@
-/*
- *  it8761_gpio.c - GPIO interface for IT8761E Super I/O chip
- *
- *  Author: Denis Turischev <denis@compulab.co.il>
- *
- *  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.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; see the file COPYING.  If not, write to
- *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/io.h>
-#include <linux/errno.h>
-#include <linux/ioport.h>
-
-#include <linux/gpio.h>
-
-#define SIO_CHIP_ID            0x8761
-#define CHIP_ID_HIGH_BYTE      0x20
-#define CHIP_ID_LOW_BYTE       0x21
-
-static u8 ports[2] = { 0x2e, 0x4e };
-static u8 port;
-
-static DEFINE_SPINLOCK(sio_lock);
-
-#define GPIO_NAME              "it8761-gpio"
-#define GPIO_BA_HIGH_BYTE      0x60
-#define GPIO_BA_LOW_BYTE       0x61
-#define GPIO_IOSIZE            4
-#define GPIO1X_IO              0xf0
-#define GPIO2X_IO              0xf1
-
-static u16 gpio_ba;
-
-static u8 read_reg(u8 addr, u8 port)
-{
-       outb(addr, port);
-       return inb(port + 1);
-}
-
-static void write_reg(u8 data, u8 addr, u8 port)
-{
-       outb(addr, port);
-       outb(data, port + 1);
-}
-
-static void enter_conf_mode(u8 port)
-{
-       outb(0x87, port);
-       outb(0x61, port);
-       outb(0x55, port);
-       outb((port == 0x2e) ? 0x55 : 0xaa, port);
-}
-
-static void exit_conf_mode(u8 port)
-{
-       outb(0x2, port);
-       outb(0x2, port + 1);
-}
-
-static void enter_gpio_mode(u8 port)
-{
-       write_reg(0x2, 0x7, port);
-}
-
-static int it8761e_gpio_get(struct gpio_chip *gc, unsigned gpio_num)
-{
-       u16 reg;
-       u8 bit;
-
-       bit = gpio_num % 8;
-       reg = (gpio_num >= 8) ? gpio_ba + 1 : gpio_ba;
-
-       return !!(inb(reg) & (1 << bit));
-}
-
-static int it8761e_gpio_direction_in(struct gpio_chip *gc, unsigned gpio_num)
-{
-       u8 curr_dirs;
-       u8 io_reg, bit;
-
-       bit = gpio_num % 8;
-       io_reg = (gpio_num >= 8) ? GPIO2X_IO : GPIO1X_IO;
-
-       spin_lock(&sio_lock);
-
-       enter_conf_mode(port);
-       enter_gpio_mode(port);
-
-       curr_dirs = read_reg(io_reg, port);
-
-       if (curr_dirs & (1 << bit))
-               write_reg(curr_dirs & ~(1 << bit), io_reg, port);
-
-       exit_conf_mode(port);
-
-       spin_unlock(&sio_lock);
-       return 0;
-}
-
-static void it8761e_gpio_set(struct gpio_chip *gc,
-                               unsigned gpio_num, int val)
-{
-       u8 curr_vals, bit;
-       u16 reg;
-
-       bit = gpio_num % 8;
-       reg = (gpio_num >= 8) ? gpio_ba + 1 : gpio_ba;
-
-       spin_lock(&sio_lock);
-
-       curr_vals = inb(reg);
-       if (val)
-               outb(curr_vals | (1 << bit) , reg);
-       else
-               outb(curr_vals & ~(1 << bit), reg);
-
-       spin_unlock(&sio_lock);
-}
-
-static int it8761e_gpio_direction_out(struct gpio_chip *gc,
-                                       unsigned gpio_num, int val)
-{
-       u8 curr_dirs, io_reg, bit;
-
-       bit = gpio_num % 8;
-       io_reg = (gpio_num >= 8) ? GPIO2X_IO : GPIO1X_IO;
-
-       it8761e_gpio_set(gc, gpio_num, val);
-
-       spin_lock(&sio_lock);
-
-       enter_conf_mode(port);
-       enter_gpio_mode(port);
-
-       curr_dirs = read_reg(io_reg, port);
-
-       if (!(curr_dirs & (1 << bit)))
-               write_reg(curr_dirs | (1 << bit), io_reg, port);
-
-       exit_conf_mode(port);
-
-       spin_unlock(&sio_lock);
-       return 0;
-}
-
-static struct gpio_chip it8761e_gpio_chip = {
-       .label                  = GPIO_NAME,
-       .owner                  = THIS_MODULE,
-       .get                    = it8761e_gpio_get,
-       .direction_input        = it8761e_gpio_direction_in,
-       .set                    = it8761e_gpio_set,
-       .direction_output       = it8761e_gpio_direction_out,
-};
-
-static int __init it8761e_gpio_init(void)
-{
-       int i, id, err;
-
-       /* chip and port detection */
-       for (i = 0; i < ARRAY_SIZE(ports); i++) {
-               spin_lock(&sio_lock);
-               enter_conf_mode(ports[i]);
-
-               id = (read_reg(CHIP_ID_HIGH_BYTE, ports[i]) << 8) +
-                               read_reg(CHIP_ID_LOW_BYTE, ports[i]);
-
-               exit_conf_mode(ports[i]);
-               spin_unlock(&sio_lock);
-
-               if (id == SIO_CHIP_ID) {
-                       port = ports[i];
-                       break;
-               }
-       }
-
-       if (!port)
-               return -ENODEV;
-
-       /* fetch GPIO base address */
-       enter_conf_mode(port);
-       enter_gpio_mode(port);
-       gpio_ba = (read_reg(GPIO_BA_HIGH_BYTE, port) << 8) +
-                               read_reg(GPIO_BA_LOW_BYTE, port);
-       exit_conf_mode(port);
-
-       if (!request_region(gpio_ba, GPIO_IOSIZE, GPIO_NAME))
-               return -EBUSY;
-
-       it8761e_gpio_chip.base = -1;
-       it8761e_gpio_chip.ngpio = 16;
-
-       err = gpiochip_add(&it8761e_gpio_chip);
-       if (err < 0)
-               goto gpiochip_add_err;
-
-       return 0;
-
-gpiochip_add_err:
-       release_region(gpio_ba, GPIO_IOSIZE);
-       gpio_ba = 0;
-       return err;
-}
-
-static void __exit it8761e_gpio_exit(void)
-{
-       if (gpio_ba) {
-               int ret = gpiochip_remove(&it8761e_gpio_chip);
-
-               WARN(ret, "%s(): gpiochip_remove() failed, ret=%d\n",
-                               __func__, ret);
-
-               release_region(gpio_ba, GPIO_IOSIZE);
-               gpio_ba = 0;
-       }
-}
-module_init(it8761e_gpio_init);
-module_exit(it8761e_gpio_exit);
-
-MODULE_AUTHOR("Denis Turischev <denis@compulab.co.il>");
-MODULE_DESCRIPTION("GPIO interface for IT8761E Super I/O chip");
-MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/janz-ttl.c b/drivers/gpio/janz-ttl.c
deleted file mode 100644 (file)
index 813ac07..0000000
+++ /dev/null
@@ -1,258 +0,0 @@
-/*
- * Janz MODULbus VMOD-TTL GPIO Driver
- *
- * Copyright (c) 2010 Ira W. Snyder <iws@ovro.caltech.edu>
- *
- * 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/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/gpio.h>
-#include <linux/slab.h>
-
-#include <linux/mfd/janz.h>
-
-#define DRV_NAME "janz-ttl"
-
-#define PORTA_DIRECTION                0x23
-#define PORTB_DIRECTION                0x2B
-#define PORTC_DIRECTION                0x06
-#define PORTA_IOCTL            0x24
-#define PORTB_IOCTL            0x2C
-#define PORTC_IOCTL            0x07
-
-#define MASTER_INT_CTL         0x00
-#define MASTER_CONF_CTL                0x01
-
-#define CONF_PAE               (1 << 2)
-#define CONF_PBE               (1 << 7)
-#define CONF_PCE               (1 << 4)
-
-struct ttl_control_regs {
-       __be16 portc;
-       __be16 portb;
-       __be16 porta;
-       __be16 control;
-};
-
-struct ttl_module {
-       struct gpio_chip gpio;
-
-       /* base address of registers */
-       struct ttl_control_regs __iomem *regs;
-
-       u8 portc_shadow;
-       u8 portb_shadow;
-       u8 porta_shadow;
-
-       spinlock_t lock;
-};
-
-static int ttl_get_value(struct gpio_chip *gpio, unsigned offset)
-{
-       struct ttl_module *mod = dev_get_drvdata(gpio->dev);
-       u8 *shadow;
-       int ret;
-
-       if (offset < 8) {
-               shadow = &mod->porta_shadow;
-       } else if (offset < 16) {
-               shadow = &mod->portb_shadow;
-               offset -= 8;
-       } else {
-               shadow = &mod->portc_shadow;
-               offset -= 16;
-       }
-
-       spin_lock(&mod->lock);
-       ret = *shadow & (1 << offset);
-       spin_unlock(&mod->lock);
-       return ret;
-}
-
-static void ttl_set_value(struct gpio_chip *gpio, unsigned offset, int value)
-{
-       struct ttl_module *mod = dev_get_drvdata(gpio->dev);
-       void __iomem *port;
-       u8 *shadow;
-
-       if (offset < 8) {
-               port = &mod->regs->porta;
-               shadow = &mod->porta_shadow;
-       } else if (offset < 16) {
-               port = &mod->regs->portb;
-               shadow = &mod->portb_shadow;
-               offset -= 8;
-       } else {
-               port = &mod->regs->portc;
-               shadow = &mod->portc_shadow;
-               offset -= 16;
-       }
-
-       spin_lock(&mod->lock);
-       if (value)
-               *shadow |= (1 << offset);
-       else
-               *shadow &= ~(1 << offset);
-
-       iowrite16be(*shadow, port);
-       spin_unlock(&mod->lock);
-}
-
-static void __devinit ttl_write_reg(struct ttl_module *mod, u8 reg, u16 val)
-{
-       iowrite16be(reg, &mod->regs->control);
-       iowrite16be(val, &mod->regs->control);
-}
-
-static void __devinit ttl_setup_device(struct ttl_module *mod)
-{
-       /* reset the device to a known state */
-       iowrite16be(0x0000, &mod->regs->control);
-       iowrite16be(0x0001, &mod->regs->control);
-       iowrite16be(0x0000, &mod->regs->control);
-
-       /* put all ports in open-drain mode */
-       ttl_write_reg(mod, PORTA_IOCTL, 0x00ff);
-       ttl_write_reg(mod, PORTB_IOCTL, 0x00ff);
-       ttl_write_reg(mod, PORTC_IOCTL, 0x000f);
-
-       /* set all ports as outputs */
-       ttl_write_reg(mod, PORTA_DIRECTION, 0x0000);
-       ttl_write_reg(mod, PORTB_DIRECTION, 0x0000);
-       ttl_write_reg(mod, PORTC_DIRECTION, 0x0000);
-
-       /* set all ports to drive zeroes */
-       iowrite16be(0x0000, &mod->regs->porta);
-       iowrite16be(0x0000, &mod->regs->portb);
-       iowrite16be(0x0000, &mod->regs->portc);
-
-       /* enable all ports */
-       ttl_write_reg(mod, MASTER_CONF_CTL, CONF_PAE | CONF_PBE | CONF_PCE);
-}
-
-static int __devinit ttl_probe(struct platform_device *pdev)
-{
-       struct janz_platform_data *pdata;
-       struct device *dev = &pdev->dev;
-       struct ttl_module *mod;
-       struct gpio_chip *gpio;
-       struct resource *res;
-       int ret;
-
-       pdata = pdev->dev.platform_data;
-       if (!pdata) {
-               dev_err(dev, "no platform data\n");
-               ret = -ENXIO;
-               goto out_return;
-       }
-
-       mod = kzalloc(sizeof(*mod), GFP_KERNEL);
-       if (!mod) {
-               dev_err(dev, "unable to allocate private data\n");
-               ret = -ENOMEM;
-               goto out_return;
-       }
-
-       platform_set_drvdata(pdev, mod);
-       spin_lock_init(&mod->lock);
-
-       /* get access to the MODULbus registers for this module */
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               dev_err(dev, "MODULbus registers not found\n");
-               ret = -ENODEV;
-               goto out_free_mod;
-       }
-
-       mod->regs = ioremap(res->start, resource_size(res));
-       if (!mod->regs) {
-               dev_err(dev, "MODULbus registers not ioremap\n");
-               ret = -ENOMEM;
-               goto out_free_mod;
-       }
-
-       ttl_setup_device(mod);
-
-       /* Initialize the GPIO data structures */
-       gpio = &mod->gpio;
-       gpio->dev = &pdev->dev;
-       gpio->label = pdev->name;
-       gpio->get = ttl_get_value;
-       gpio->set = ttl_set_value;
-       gpio->owner = THIS_MODULE;
-
-       /* request dynamic allocation */
-       gpio->base = -1;
-       gpio->ngpio = 20;
-
-       ret = gpiochip_add(gpio);
-       if (ret) {
-               dev_err(dev, "unable to add GPIO chip\n");
-               goto out_iounmap_regs;
-       }
-
-       dev_info(&pdev->dev, "module %d: registered GPIO device\n",
-                            pdata->modno);
-       return 0;
-
-out_iounmap_regs:
-       iounmap(mod->regs);
-out_free_mod:
-       kfree(mod);
-out_return:
-       return ret;
-}
-
-static int __devexit ttl_remove(struct platform_device *pdev)
-{
-       struct ttl_module *mod = platform_get_drvdata(pdev);
-       struct device *dev = &pdev->dev;
-       int ret;
-
-       ret = gpiochip_remove(&mod->gpio);
-       if (ret) {
-               dev_err(dev, "unable to remove GPIO chip\n");
-               return ret;
-       }
-
-       iounmap(mod->regs);
-       kfree(mod);
-       return 0;
-}
-
-static struct platform_driver ttl_driver = {
-       .driver         = {
-               .name   = DRV_NAME,
-               .owner  = THIS_MODULE,
-       },
-       .probe          = ttl_probe,
-       .remove         = __devexit_p(ttl_remove),
-};
-
-static int __init ttl_init(void)
-{
-       return platform_driver_register(&ttl_driver);
-}
-
-static void __exit ttl_exit(void)
-{
-       platform_driver_unregister(&ttl_driver);
-}
-
-MODULE_AUTHOR("Ira W. Snyder <iws@ovro.caltech.edu>");
-MODULE_DESCRIPTION("Janz MODULbus VMOD-TTL Driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:janz-ttl");
-
-module_init(ttl_init);
-module_exit(ttl_exit);
diff --git a/drivers/gpio/langwell_gpio.c b/drivers/gpio/langwell_gpio.c
deleted file mode 100644 (file)
index bd6571e..0000000
+++ /dev/null
@@ -1,456 +0,0 @@
-/* langwell_gpio.c Moorestown platform Langwell chip GPIO driver
- * Copyright (c) 2008 - 2009,  Intel Corporation.
- *
- * 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.
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-/* Supports:
- * Moorestown platform Langwell chip.
- * Medfield platform Penwell chip.
- * Whitney point.
- */
-
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/platform_device.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/stddef.h>
-#include <linux/interrupt.h>
-#include <linux/init.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-#include <linux/gpio.h>
-#include <linux/slab.h>
-#include <linux/pm_runtime.h>
-
-/*
- * Langwell chip has 64 pins and thus there are 2 32bit registers to control
- * each feature, while Penwell chip has 96 pins for each block, and need 3 32bit
- * registers to control them, so we only define the order here instead of a
- * structure, to get a bit offset for a pin (use GPDR as an example):
- *
- * nreg = ngpio / 32;
- * reg = offset / 32;
- * bit = offset % 32;
- * reg_addr = reg_base + GPDR * nreg * 4 + reg * 4;
- *
- * so the bit of reg_addr is to control pin offset's GPDR feature
-*/
-
-enum GPIO_REG {
-       GPLR = 0,       /* pin level read-only */
-       GPDR,           /* pin direction */
-       GPSR,           /* pin set */
-       GPCR,           /* pin clear */
-       GRER,           /* rising edge detect */
-       GFER,           /* falling edge detect */
-       GEDR,           /* edge detect result */
-};
-
-struct lnw_gpio {
-       struct gpio_chip                chip;
-       void                            *reg_base;
-       spinlock_t                      lock;
-       unsigned                        irq_base;
-       struct pci_dev                  *pdev;
-};
-
-static void __iomem *gpio_reg(struct gpio_chip *chip, unsigned offset,
-                       enum GPIO_REG reg_type)
-{
-       struct lnw_gpio *lnw = container_of(chip, struct lnw_gpio, chip);
-       unsigned nreg = chip->ngpio / 32;
-       u8 reg = offset / 32;
-       void __iomem *ptr;
-
-       ptr = (void __iomem *)(lnw->reg_base + reg_type * nreg * 4 + reg * 4);
-       return ptr;
-}
-
-static int lnw_gpio_get(struct gpio_chip *chip, unsigned offset)
-{
-       void __iomem *gplr = gpio_reg(chip, offset, GPLR);
-
-       return readl(gplr) & BIT(offset % 32);
-}
-
-static void lnw_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
-{
-       void __iomem *gpsr, *gpcr;
-
-       if (value) {
-               gpsr = gpio_reg(chip, offset, GPSR);
-               writel(BIT(offset % 32), gpsr);
-       } else {
-               gpcr = gpio_reg(chip, offset, GPCR);
-               writel(BIT(offset % 32), gpcr);
-       }
-}
-
-static int lnw_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
-{
-       struct lnw_gpio *lnw = container_of(chip, struct lnw_gpio, chip);
-       void __iomem *gpdr = gpio_reg(chip, offset, GPDR);
-       u32 value;
-       unsigned long flags;
-
-       if (lnw->pdev)
-               pm_runtime_get(&lnw->pdev->dev);
-
-       spin_lock_irqsave(&lnw->lock, flags);
-       value = readl(gpdr);
-       value &= ~BIT(offset % 32);
-       writel(value, gpdr);
-       spin_unlock_irqrestore(&lnw->lock, flags);
-
-       if (lnw->pdev)
-               pm_runtime_put(&lnw->pdev->dev);
-
-       return 0;
-}
-
-static int lnw_gpio_direction_output(struct gpio_chip *chip,
-                       unsigned offset, int value)
-{
-       struct lnw_gpio *lnw = container_of(chip, struct lnw_gpio, chip);
-       void __iomem *gpdr = gpio_reg(chip, offset, GPDR);
-       unsigned long flags;
-
-       lnw_gpio_set(chip, offset, value);
-
-       if (lnw->pdev)
-               pm_runtime_get(&lnw->pdev->dev);
-
-       spin_lock_irqsave(&lnw->lock, flags);
-       value = readl(gpdr);
-       value |= BIT(offset % 32);
-       writel(value, gpdr);
-       spin_unlock_irqrestore(&lnw->lock, flags);
-
-       if (lnw->pdev)
-               pm_runtime_put(&lnw->pdev->dev);
-
-       return 0;
-}
-
-static int lnw_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
-{
-       struct lnw_gpio *lnw = container_of(chip, struct lnw_gpio, chip);
-       return lnw->irq_base + offset;
-}
-
-static int lnw_irq_type(struct irq_data *d, unsigned type)
-{
-       struct lnw_gpio *lnw = irq_data_get_irq_chip_data(d);
-       u32 gpio = d->irq - lnw->irq_base;
-       unsigned long flags;
-       u32 value;
-       void __iomem *grer = gpio_reg(&lnw->chip, gpio, GRER);
-       void __iomem *gfer = gpio_reg(&lnw->chip, gpio, GFER);
-
-       if (gpio >= lnw->chip.ngpio)
-               return -EINVAL;
-
-       if (lnw->pdev)
-               pm_runtime_get(&lnw->pdev->dev);
-
-       spin_lock_irqsave(&lnw->lock, flags);
-       if (type & IRQ_TYPE_EDGE_RISING)
-               value = readl(grer) | BIT(gpio % 32);
-       else
-               value = readl(grer) & (~BIT(gpio % 32));
-       writel(value, grer);
-
-       if (type & IRQ_TYPE_EDGE_FALLING)
-               value = readl(gfer) | BIT(gpio % 32);
-       else
-               value = readl(gfer) & (~BIT(gpio % 32));
-       writel(value, gfer);
-       spin_unlock_irqrestore(&lnw->lock, flags);
-
-       if (lnw->pdev)
-               pm_runtime_put(&lnw->pdev->dev);
-
-       return 0;
-}
-
-static void lnw_irq_unmask(struct irq_data *d)
-{
-}
-
-static void lnw_irq_mask(struct irq_data *d)
-{
-}
-
-static struct irq_chip lnw_irqchip = {
-       .name           = "LNW-GPIO",
-       .irq_mask       = lnw_irq_mask,
-       .irq_unmask     = lnw_irq_unmask,
-       .irq_set_type   = lnw_irq_type,
-};
-
-static DEFINE_PCI_DEVICE_TABLE(lnw_gpio_ids) = {   /* pin number */
-       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x080f), .driver_data = 64 },
-       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081f), .driver_data = 96 },
-       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081a), .driver_data = 96 },
-       { 0, }
-};
-MODULE_DEVICE_TABLE(pci, lnw_gpio_ids);
-
-static void lnw_irq_handler(unsigned irq, struct irq_desc *desc)
-{
-       struct irq_data *data = irq_desc_get_irq_data(desc);
-       struct lnw_gpio *lnw = irq_data_get_irq_handler_data(data);
-       struct irq_chip *chip = irq_data_get_irq_chip(data);
-       u32 base, gpio, mask;
-       unsigned long pending;
-       void __iomem *gedr;
-
-       /* check GPIO controller to check which pin triggered the interrupt */
-       for (base = 0; base < lnw->chip.ngpio; base += 32) {
-               gedr = gpio_reg(&lnw->chip, base, GEDR);
-               pending = readl(gedr);
-               while (pending) {
-                       gpio = __ffs(pending) - 1;
-                       mask = BIT(gpio);
-                       pending &= ~mask;
-                       /* Clear before handling so we can't lose an edge */
-                       writel(mask, gedr);
-                       generic_handle_irq(lnw->irq_base + base + gpio);
-               }
-       }
-
-       chip->irq_eoi(data);
-}
-
-#ifdef CONFIG_PM
-static int lnw_gpio_runtime_resume(struct device *dev)
-{
-       return 0;
-}
-
-static int lnw_gpio_runtime_suspend(struct device *dev)
-{
-       return 0;
-}
-
-static int lnw_gpio_runtime_idle(struct device *dev)
-{
-       int err = pm_schedule_suspend(dev, 500);
-
-       if (!err)
-               return 0;
-
-       return -EBUSY;
-}
-
-#else
-#define lnw_gpio_runtime_suspend       NULL
-#define lnw_gpio_runtime_resume                NULL
-#define lnw_gpio_runtime_idle          NULL
-#endif
-
-static const struct dev_pm_ops lnw_gpio_pm_ops = {
-       .runtime_suspend = lnw_gpio_runtime_suspend,
-       .runtime_resume = lnw_gpio_runtime_resume,
-       .runtime_idle = lnw_gpio_runtime_idle,
-};
-
-static int __devinit lnw_gpio_probe(struct pci_dev *pdev,
-                       const struct pci_device_id *id)
-{
-       void *base;
-       int i;
-       resource_size_t start, len;
-       struct lnw_gpio *lnw;
-       u32 irq_base;
-       u32 gpio_base;
-       int retval = 0;
-
-       retval = pci_enable_device(pdev);
-       if (retval)
-               goto done;
-
-       retval = pci_request_regions(pdev, "langwell_gpio");
-       if (retval) {
-               dev_err(&pdev->dev, "error requesting resources\n");
-               goto err2;
-       }
-       /* get the irq_base from bar1 */
-       start = pci_resource_start(pdev, 1);
-       len = pci_resource_len(pdev, 1);
-       base = ioremap_nocache(start, len);
-       if (!base) {
-               dev_err(&pdev->dev, "error mapping bar1\n");
-               goto err3;
-       }
-       irq_base = *(u32 *)base;
-       gpio_base = *((u32 *)base + 1);
-       /* release the IO mapping, since we already get the info from bar1 */
-       iounmap(base);
-       /* get the register base from bar0 */
-       start = pci_resource_start(pdev, 0);
-       len = pci_resource_len(pdev, 0);
-       base = ioremap_nocache(start, len);
-       if (!base) {
-               dev_err(&pdev->dev, "error mapping bar0\n");
-               retval = -EFAULT;
-               goto err3;
-       }
-
-       lnw = kzalloc(sizeof(struct lnw_gpio), GFP_KERNEL);
-       if (!lnw) {
-               dev_err(&pdev->dev, "can't allocate langwell_gpio chip data\n");
-               retval = -ENOMEM;
-               goto err4;
-       }
-       lnw->reg_base = base;
-       lnw->irq_base = irq_base;
-       lnw->chip.label = dev_name(&pdev->dev);
-       lnw->chip.direction_input = lnw_gpio_direction_input;
-       lnw->chip.direction_output = lnw_gpio_direction_output;
-       lnw->chip.get = lnw_gpio_get;
-       lnw->chip.set = lnw_gpio_set;
-       lnw->chip.to_irq = lnw_gpio_to_irq;
-       lnw->chip.base = gpio_base;
-       lnw->chip.ngpio = id->driver_data;
-       lnw->chip.can_sleep = 0;
-       lnw->pdev = pdev;
-       pci_set_drvdata(pdev, lnw);
-       retval = gpiochip_add(&lnw->chip);
-       if (retval) {
-               dev_err(&pdev->dev, "langwell gpiochip_add error %d\n", retval);
-               goto err5;
-       }
-       irq_set_handler_data(pdev->irq, lnw);
-       irq_set_chained_handler(pdev->irq, lnw_irq_handler);
-       for (i = 0; i < lnw->chip.ngpio; i++) {
-               irq_set_chip_and_handler_name(i + lnw->irq_base, &lnw_irqchip,
-                                             handle_simple_irq, "demux");
-               irq_set_chip_data(i + lnw->irq_base, lnw);
-       }
-
-       spin_lock_init(&lnw->lock);
-
-       pm_runtime_put_noidle(&pdev->dev);
-       pm_runtime_allow(&pdev->dev);
-
-       goto done;
-err5:
-       kfree(lnw);
-err4:
-       iounmap(base);
-err3:
-       pci_release_regions(pdev);
-err2:
-       pci_disable_device(pdev);
-done:
-       return retval;
-}
-
-static struct pci_driver lnw_gpio_driver = {
-       .name           = "langwell_gpio",
-       .id_table       = lnw_gpio_ids,
-       .probe          = lnw_gpio_probe,
-       .driver         = {
-               .pm     = &lnw_gpio_pm_ops,
-       },
-};
-
-
-static int __devinit wp_gpio_probe(struct platform_device *pdev)
-{
-       struct lnw_gpio *lnw;
-       struct gpio_chip *gc;
-       struct resource *rc;
-       int retval = 0;
-
-       rc = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!rc)
-               return -EINVAL;
-
-       lnw = kzalloc(sizeof(struct lnw_gpio), GFP_KERNEL);
-       if (!lnw) {
-               dev_err(&pdev->dev,
-                       "can't allocate whitneypoint_gpio chip data\n");
-               return -ENOMEM;
-       }
-       lnw->reg_base = ioremap_nocache(rc->start, resource_size(rc));
-       if (lnw->reg_base == NULL) {
-               retval = -EINVAL;
-               goto err_kmalloc;
-       }
-       spin_lock_init(&lnw->lock);
-       gc = &lnw->chip;
-       gc->label = dev_name(&pdev->dev);
-       gc->owner = THIS_MODULE;
-       gc->direction_input = lnw_gpio_direction_input;
-       gc->direction_output = lnw_gpio_direction_output;
-       gc->get = lnw_gpio_get;
-       gc->set = lnw_gpio_set;
-       gc->to_irq = NULL;
-       gc->base = 0;
-       gc->ngpio = 64;
-       gc->can_sleep = 0;
-       retval = gpiochip_add(gc);
-       if (retval) {
-               dev_err(&pdev->dev, "whitneypoint gpiochip_add error %d\n",
-                                                               retval);
-               goto err_ioremap;
-       }
-       platform_set_drvdata(pdev, lnw);
-       return 0;
-err_ioremap:
-       iounmap(lnw->reg_base);
-err_kmalloc:
-       kfree(lnw);
-       return retval;
-}
-
-static int __devexit wp_gpio_remove(struct platform_device *pdev)
-{
-       struct lnw_gpio *lnw = platform_get_drvdata(pdev);
-       int err;
-       err = gpiochip_remove(&lnw->chip);
-       if (err)
-               dev_err(&pdev->dev, "failed to remove gpio_chip.\n");
-       iounmap(lnw->reg_base);
-       kfree(lnw);
-       platform_set_drvdata(pdev, NULL);
-       return 0;
-}
-
-static struct platform_driver wp_gpio_driver = {
-       .probe          = wp_gpio_probe,
-       .remove         = __devexit_p(wp_gpio_remove),
-       .driver         = {
-               .name   = "wp_gpio",
-               .owner  = THIS_MODULE,
-       },
-};
-
-static int __init lnw_gpio_init(void)
-{
-       int ret;
-       ret =  pci_register_driver(&lnw_gpio_driver);
-       if (ret < 0)
-               return ret;
-       ret = platform_driver_register(&wp_gpio_driver);
-       if (ret < 0)
-               pci_unregister_driver(&lnw_gpio_driver);
-       return ret;
-}
-
-device_initcall(lnw_gpio_init);
diff --git a/drivers/gpio/max7300.c b/drivers/gpio/max7300.c
deleted file mode 100644 (file)
index 962f661..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * drivers/gpio/max7300.c
- *
- * Copyright (C) 2009 Wolfram Sang, Pengutronix
- *
- * 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.
- *
- * Check max730x.c for further details.
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/mutex.h>
-#include <linux/i2c.h>
-#include <linux/spi/max7301.h>
-#include <linux/slab.h>
-
-static int max7300_i2c_write(struct device *dev, unsigned int reg,
-                               unsigned int val)
-{
-       struct i2c_client *client = to_i2c_client(dev);
-
-       return i2c_smbus_write_byte_data(client, reg, val);
-}
-
-static int max7300_i2c_read(struct device *dev, unsigned int reg)
-{
-       struct i2c_client *client = to_i2c_client(dev);
-
-       return i2c_smbus_read_byte_data(client, reg);
-}
-
-static int __devinit max7300_probe(struct i2c_client *client,
-                        const struct i2c_device_id *id)
-{
-       struct max7301 *ts;
-       int ret;
-
-       if (!i2c_check_functionality(client->adapter,
-                       I2C_FUNC_SMBUS_BYTE_DATA))
-               return -EIO;
-
-       ts = kzalloc(sizeof(struct max7301), GFP_KERNEL);
-       if (!ts)
-               return -ENOMEM;
-
-       ts->read = max7300_i2c_read;
-       ts->write = max7300_i2c_write;
-       ts->dev = &client->dev;
-
-       ret = __max730x_probe(ts);
-       if (ret)
-               kfree(ts);
-       return ret;
-}
-
-static int __devexit max7300_remove(struct i2c_client *client)
-{
-       return __max730x_remove(&client->dev);
-}
-
-static const struct i2c_device_id max7300_id[] = {
-       { "max7300", 0 },
-       { }
-};
-MODULE_DEVICE_TABLE(i2c, max7300_id);
-
-static struct i2c_driver max7300_driver = {
-       .driver = {
-               .name = "max7300",
-               .owner = THIS_MODULE,
-       },
-       .probe = max7300_probe,
-       .remove = __devexit_p(max7300_remove),
-       .id_table = max7300_id,
-};
-
-static int __init max7300_init(void)
-{
-       return i2c_add_driver(&max7300_driver);
-}
-subsys_initcall(max7300_init);
-
-static void __exit max7300_exit(void)
-{
-       i2c_del_driver(&max7300_driver);
-}
-module_exit(max7300_exit);
-
-MODULE_AUTHOR("Wolfram Sang");
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("MAX7300 GPIO-Expander");
diff --git a/drivers/gpio/max7301.c b/drivers/gpio/max7301.c
deleted file mode 100644 (file)
index 92a100d..0000000
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * drivers/gpio/max7301.c
- *
- * Copyright (C) 2006 Juergen Beisert, Pengutronix
- * Copyright (C) 2008 Guennadi Liakhovetski, Pengutronix
- * Copyright (C) 2009 Wolfram Sang, Pengutronix
- *
- * 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.
- *
- * Check max730x.c for further details.
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/mutex.h>
-#include <linux/slab.h>
-#include <linux/spi/spi.h>
-#include <linux/spi/max7301.h>
-
-/* A write to the MAX7301 means one message with one transfer */
-static int max7301_spi_write(struct device *dev, unsigned int reg,
-                               unsigned int val)
-{
-       struct spi_device *spi = to_spi_device(dev);
-       u16 word = ((reg & 0x7F) << 8) | (val & 0xFF);
-
-       return spi_write(spi, (const u8 *)&word, sizeof(word));
-}
-
-/* A read from the MAX7301 means two transfers; here, one message each */
-
-static int max7301_spi_read(struct device *dev, unsigned int reg)
-{
-       int ret;
-       u16 word;
-       struct spi_device *spi = to_spi_device(dev);
-
-       word = 0x8000 | (reg << 8);
-       ret = spi_write(spi, (const u8 *)&word, sizeof(word));
-       if (ret)
-               return ret;
-       /*
-        * This relies on the fact, that a transfer with NULL tx_buf shifts out
-        * zero bytes (=NOOP for MAX7301)
-        */
-       ret = spi_read(spi, (u8 *)&word, sizeof(word));
-       if (ret)
-               return ret;
-       return word & 0xff;
-}
-
-static int __devinit max7301_probe(struct spi_device *spi)
-{
-       struct max7301 *ts;
-       int ret;
-
-       /* bits_per_word cannot be configured in platform data */
-       spi->bits_per_word = 16;
-       ret = spi_setup(spi);
-       if (ret < 0)
-               return ret;
-
-       ts = kzalloc(sizeof(struct max7301), GFP_KERNEL);
-       if (!ts)
-               return -ENOMEM;
-
-       ts->read = max7301_spi_read;
-       ts->write = max7301_spi_write;
-       ts->dev = &spi->dev;
-
-       ret = __max730x_probe(ts);
-       if (ret)
-               kfree(ts);
-       return ret;
-}
-
-static int __devexit max7301_remove(struct spi_device *spi)
-{
-       return __max730x_remove(&spi->dev);
-}
-
-static const struct spi_device_id max7301_id[] = {
-       { "max7301", 0 },
-       { }
-};
-MODULE_DEVICE_TABLE(spi, max7301_id);
-
-static struct spi_driver max7301_driver = {
-       .driver = {
-               .name = "max7301",
-               .owner = THIS_MODULE,
-       },
-       .probe = max7301_probe,
-       .remove = __devexit_p(max7301_remove),
-       .id_table = max7301_id,
-};
-
-static int __init max7301_init(void)
-{
-       return spi_register_driver(&max7301_driver);
-}
-/* register after spi postcore initcall and before
- * subsys initcalls that may rely on these GPIOs
- */
-subsys_initcall(max7301_init);
-
-static void __exit max7301_exit(void)
-{
-       spi_unregister_driver(&max7301_driver);
-}
-module_exit(max7301_exit);
-
-MODULE_AUTHOR("Juergen Beisert, Wolfram Sang");
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("MAX7301 GPIO-Expander");
diff --git a/drivers/gpio/max730x.c b/drivers/gpio/max730x.c
deleted file mode 100644 (file)
index 94ce773..0000000
+++ /dev/null
@@ -1,257 +0,0 @@
-/**
- * drivers/gpio/max7301.c
- *
- * Copyright (C) 2006 Juergen Beisert, Pengutronix
- * Copyright (C) 2008 Guennadi Liakhovetski, Pengutronix
- * Copyright (C) 2009 Wolfram Sang, Pengutronix
- *
- * 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.
- *
- * The Maxim MAX7300/1 device is an I2C/SPI driven GPIO expander. There are
- * 28 GPIOs. 8 of them can trigger an interrupt. See datasheet for more
- * details
- * Note:
- * - DIN must be stable at the rising edge of clock.
- * - when writing:
- *   - always clock in 16 clocks at once
- *   - at DIN: D15 first, D0 last
- *   - D0..D7 = databyte, D8..D14 = commandbyte
- *   - D15 = low -> write command
- * - when reading
- *   - always clock in 16 clocks at once
- *   - at DIN: D15 first, D0 last
- *   - D0..D7 = dummy, D8..D14 = register address
- *   - D15 = high -> read command
- *   - raise CS and assert it again
- *   - always clock in 16 clocks at once
- *   - at DOUT: D15 first, D0 last
- *   - D0..D7 contains the data from the first cycle
- *
- * The driver exports a standard gpiochip interface
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/mutex.h>
-#include <linux/spi/max7301.h>
-#include <linux/gpio.h>
-#include <linux/slab.h>
-
-/*
- * Pin configurations, see MAX7301 datasheet page 6
- */
-#define PIN_CONFIG_MASK 0x03
-#define PIN_CONFIG_IN_PULLUP 0x03
-#define PIN_CONFIG_IN_WO_PULLUP 0x02
-#define PIN_CONFIG_OUT 0x01
-
-#define PIN_NUMBER 28
-
-static int max7301_direction_input(struct gpio_chip *chip, unsigned offset)
-{
-       struct max7301 *ts = container_of(chip, struct max7301, chip);
-       u8 *config;
-       u8 offset_bits, pin_config;
-       int ret;
-
-       /* First 4 pins are unused in the controller */
-       offset += 4;
-       offset_bits = (offset & 3) << 1;
-
-       config = &ts->port_config[offset >> 2];
-
-       if (ts->input_pullup_active & BIT(offset))
-               pin_config = PIN_CONFIG_IN_PULLUP;
-       else
-               pin_config = PIN_CONFIG_IN_WO_PULLUP;
-
-       mutex_lock(&ts->lock);
-
-       *config = (*config & ~(PIN_CONFIG_MASK << offset_bits))
-                          | (pin_config << offset_bits);
-
-       ret = ts->write(ts->dev, 0x08 + (offset >> 2), *config);
-
-       mutex_unlock(&ts->lock);
-
-       return ret;
-}
-
-static int __max7301_set(struct max7301 *ts, unsigned offset, int value)
-{
-       if (value) {
-               ts->out_level |= 1 << offset;
-               return ts->write(ts->dev, 0x20 + offset, 0x01);
-       } else {
-               ts->out_level &= ~(1 << offset);
-               return ts->write(ts->dev, 0x20 + offset, 0x00);
-       }
-}
-
-static int max7301_direction_output(struct gpio_chip *chip, unsigned offset,
-                                   int value)
-{
-       struct max7301 *ts = container_of(chip, struct max7301, chip);
-       u8 *config;
-       u8 offset_bits;
-       int ret;
-
-       /* First 4 pins are unused in the controller */
-       offset += 4;
-       offset_bits = (offset & 3) << 1;
-
-       config = &ts->port_config[offset >> 2];
-
-       mutex_lock(&ts->lock);
-
-       *config = (*config & ~(PIN_CONFIG_MASK << offset_bits))
-                          | (PIN_CONFIG_OUT << offset_bits);
-
-       ret = __max7301_set(ts, offset, value);
-
-       if (!ret)
-               ret = ts->write(ts->dev, 0x08 + (offset >> 2), *config);
-
-       mutex_unlock(&ts->lock);
-
-       return ret;
-}
-
-static int max7301_get(struct gpio_chip *chip, unsigned offset)
-{
-       struct max7301 *ts = container_of(chip, struct max7301, chip);
-       int config, level = -EINVAL;
-
-       /* First 4 pins are unused in the controller */
-       offset += 4;
-
-       mutex_lock(&ts->lock);
-
-       config = (ts->port_config[offset >> 2] >> ((offset & 3) << 1))
-                       & PIN_CONFIG_MASK;
-
-       switch (config) {
-       case PIN_CONFIG_OUT:
-               /* Output: return cached level */
-               level =  !!(ts->out_level & (1 << offset));
-               break;
-       case PIN_CONFIG_IN_WO_PULLUP:
-       case PIN_CONFIG_IN_PULLUP:
-               /* Input: read out */
-               level = ts->read(ts->dev, 0x20 + offset) & 0x01;
-       }
-       mutex_unlock(&ts->lock);
-
-       return level;
-}
-
-static void max7301_set(struct gpio_chip *chip, unsigned offset, int value)
-{
-       struct max7301 *ts = container_of(chip, struct max7301, chip);
-
-       /* First 4 pins are unused in the controller */
-       offset += 4;
-
-       mutex_lock(&ts->lock);
-
-       __max7301_set(ts, offset, value);
-
-       mutex_unlock(&ts->lock);
-}
-
-int __devinit __max730x_probe(struct max7301 *ts)
-{
-       struct device *dev = ts->dev;
-       struct max7301_platform_data *pdata;
-       int i, ret;
-
-       pdata = dev->platform_data;
-       if (!pdata || !pdata->base) {
-               dev_err(dev, "incorrect or missing platform data\n");
-               return -EINVAL;
-       }
-
-       mutex_init(&ts->lock);
-       dev_set_drvdata(dev, ts);
-
-       /* Power up the chip and disable IRQ output */
-       ts->write(dev, 0x04, 0x01);
-
-       ts->input_pullup_active = pdata->input_pullup_active;
-       ts->chip.label = dev->driver->name;
-
-       ts->chip.direction_input = max7301_direction_input;
-       ts->chip.get = max7301_get;
-       ts->chip.direction_output = max7301_direction_output;
-       ts->chip.set = max7301_set;
-
-       ts->chip.base = pdata->base;
-       ts->chip.ngpio = PIN_NUMBER;
-       ts->chip.can_sleep = 1;
-       ts->chip.dev = dev;
-       ts->chip.owner = THIS_MODULE;
-
-       /*
-        * initialize pullups according to platform data and cache the
-        * register values for later use.
-        */
-       for (i = 1; i < 8; i++) {
-               int j;
-               /*
-                * initialize port_config with "0xAA", which means
-                * input with internal pullup disabled. This is needed
-                * to avoid writing zeros (in the inner for loop),
-                * which is not allowed according to the datasheet.
-                */
-               ts->port_config[i] = 0xAA;
-               for (j = 0; j < 4; j++) {
-                       int offset = (i - 1) * 4 + j;
-                       ret = max7301_direction_input(&ts->chip, offset);
-                       if (ret)
-                               goto exit_destroy;
-               }
-       }
-
-       ret = gpiochip_add(&ts->chip);
-       if (ret)
-               goto exit_destroy;
-
-       return ret;
-
-exit_destroy:
-       dev_set_drvdata(dev, NULL);
-       mutex_destroy(&ts->lock);
-       return ret;
-}
-EXPORT_SYMBOL_GPL(__max730x_probe);
-
-int __devexit __max730x_remove(struct device *dev)
-{
-       struct max7301 *ts = dev_get_drvdata(dev);
-       int ret;
-
-       if (ts == NULL)
-               return -ENODEV;
-
-       dev_set_drvdata(dev, NULL);
-
-       /* Power down the chip and disable IRQ output */
-       ts->write(dev, 0x04, 0x00);
-
-       ret = gpiochip_remove(&ts->chip);
-       if (!ret) {
-               mutex_destroy(&ts->lock);
-               kfree(ts);
-       } else
-               dev_err(dev, "Failed to remove GPIO controller: %d\n", ret);
-
-       return ret;
-}
-EXPORT_SYMBOL_GPL(__max730x_remove);
-
-MODULE_AUTHOR("Juergen Beisert, Wolfram Sang");
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("MAX730x GPIO-Expanders, generic parts");
diff --git a/drivers/gpio/max732x.c b/drivers/gpio/max732x.c
deleted file mode 100644 (file)
index ad6951e..0000000
+++ /dev/null
@@ -1,714 +0,0 @@
-/*
- *  max732x.c - I2C Port Expander with 8/16 I/O
- *
- *  Copyright (C) 2007 Marvell International Ltd.
- *  Copyright (C) 2008 Jack Ren <jack.ren@marvell.com>
- *  Copyright (C) 2008 Eric Miao <eric.miao@marvell.com>
- *
- *  Derived from drivers/gpio/pca953x.c
- *
- *  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; version 2 of the License.
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/gpio.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/i2c.h>
-#include <linux/i2c/max732x.h>
-
-
-/*
- * Each port of MAX732x (including MAX7319) falls into one of the
- * following three types:
- *
- *   - Push Pull Output
- *   - Input
- *   - Open Drain I/O
- *
- * designated by 'O', 'I' and 'P' individually according to MAXIM's
- * datasheets. 'I' and 'P' ports are interrupt capables, some with
- * a dedicated interrupt mask.
- *
- * There are two groups of I/O ports, each group usually includes
- * up to 8 I/O ports, and is accessed by a specific I2C address:
- *
- *   - Group A : by I2C address 0b'110xxxx
- *   - Group B : by I2C address 0b'101xxxx
- *
- * where 'xxxx' is decided by the connections of pin AD2/AD0.  The
- * address used also affects the initial state of output signals.
- *
- * Within each group of ports, there are five known combinations of
- * I/O ports: 4I4O, 4P4O, 8I, 8P, 8O, see the definitions below for
- * the detailed organization of these ports. Only Goup A is interrupt
- * capable.
- *
- * GPIO numbers start from 'gpio_base + 0' to 'gpio_base + 8/16',
- * and GPIOs from GROUP_A are numbered before those from GROUP_B
- * (if there are two groups).
- *
- * NOTE: MAX7328/MAX7329 are drop-in replacements for PCF8574/a, so
- * they are not supported by this driver.
- */
-
-#define PORT_NONE      0x0     /* '/' No Port */
-#define PORT_OUTPUT    0x1     /* 'O' Push-Pull, Output Only */
-#define PORT_INPUT     0x2     /* 'I' Input Only */
-#define PORT_OPENDRAIN 0x3     /* 'P' Open-Drain, I/O */
-
-#define IO_4I4O                0x5AA5  /* O7 O6 I5 I4 I3 I2 O1 O0 */
-#define IO_4P4O                0x5FF5  /* O7 O6 P5 P4 P3 P2 O1 O0 */
-#define IO_8I          0xAAAA  /* I7 I6 I5 I4 I3 I2 I1 I0 */
-#define IO_8P          0xFFFF  /* P7 P6 P5 P4 P3 P2 P1 P0 */
-#define IO_8O          0x5555  /* O7 O6 O5 O4 O3 O2 O1 O0 */
-
-#define GROUP_A(x)     ((x) & 0xffff)  /* I2C Addr: 0b'110xxxx */
-#define GROUP_B(x)     ((x) << 16)     /* I2C Addr: 0b'101xxxx */
-
-#define INT_NONE       0x0     /* No interrupt capability */
-#define INT_NO_MASK    0x1     /* Has interrupts, no mask */
-#define INT_INDEP_MASK 0x2     /* Has interrupts, independent mask */
-#define INT_MERGED_MASK 0x3    /* Has interrupts, merged mask */
-
-#define INT_CAPS(x)    (((uint64_t)(x)) << 32)
-
-enum {
-       MAX7319,
-       MAX7320,
-       MAX7321,
-       MAX7322,
-       MAX7323,
-       MAX7324,
-       MAX7325,
-       MAX7326,
-       MAX7327,
-};
-
-static uint64_t max732x_features[] = {
-       [MAX7319] = GROUP_A(IO_8I) | INT_CAPS(INT_MERGED_MASK),
-       [MAX7320] = GROUP_B(IO_8O),
-       [MAX7321] = GROUP_A(IO_8P) | INT_CAPS(INT_NO_MASK),
-       [MAX7322] = GROUP_A(IO_4I4O) | INT_CAPS(INT_MERGED_MASK),
-       [MAX7323] = GROUP_A(IO_4P4O) | INT_CAPS(INT_INDEP_MASK),
-       [MAX7324] = GROUP_A(IO_8I) | GROUP_B(IO_8O) | INT_CAPS(INT_MERGED_MASK),
-       [MAX7325] = GROUP_A(IO_8P) | GROUP_B(IO_8O) | INT_CAPS(INT_NO_MASK),
-       [MAX7326] = GROUP_A(IO_4I4O) | GROUP_B(IO_8O) | INT_CAPS(INT_MERGED_MASK),
-       [MAX7327] = GROUP_A(IO_4P4O) | GROUP_B(IO_8O) | INT_CAPS(INT_NO_MASK),
-};
-
-static const struct i2c_device_id max732x_id[] = {
-       { "max7319", MAX7319 },
-       { "max7320", MAX7320 },
-       { "max7321", MAX7321 },
-       { "max7322", MAX7322 },
-       { "max7323", MAX7323 },
-       { "max7324", MAX7324 },
-       { "max7325", MAX7325 },
-       { "max7326", MAX7326 },
-       { "max7327", MAX7327 },
-       { },
-};
-MODULE_DEVICE_TABLE(i2c, max732x_id);
-
-struct max732x_chip {
-       struct gpio_chip gpio_chip;
-
-       struct i2c_client *client;      /* "main" client */
-       struct i2c_client *client_dummy;
-       struct i2c_client *client_group_a;
-       struct i2c_client *client_group_b;
-
-       unsigned int    mask_group_a;
-       unsigned int    dir_input;
-       unsigned int    dir_output;
-
-       struct mutex    lock;
-       uint8_t         reg_out[2];
-
-#ifdef CONFIG_GPIO_MAX732X_IRQ
-       struct mutex    irq_lock;
-       int             irq_base;
-       uint8_t         irq_mask;
-       uint8_t         irq_mask_cur;
-       uint8_t         irq_trig_raise;
-       uint8_t         irq_trig_fall;
-       uint8_t         irq_features;
-#endif
-};
-
-static int max732x_writeb(struct max732x_chip *chip, int group_a, uint8_t val)
-{
-       struct i2c_client *client;
-       int ret;
-
-       client = group_a ? chip->client_group_a : chip->client_group_b;
-       ret = i2c_smbus_write_byte(client, val);
-       if (ret < 0) {
-               dev_err(&client->dev, "failed writing\n");
-               return ret;
-       }
-
-       return 0;
-}
-
-static int max732x_readb(struct max732x_chip *chip, int group_a, uint8_t *val)
-{
-       struct i2c_client *client;
-       int ret;
-
-       client = group_a ? chip->client_group_a : chip->client_group_b;
-       ret = i2c_smbus_read_byte(client);
-       if (ret < 0) {
-               dev_err(&client->dev, "failed reading\n");
-               return ret;
-       }
-
-       *val = (uint8_t)ret;
-       return 0;
-}
-
-static inline int is_group_a(struct max732x_chip *chip, unsigned off)
-{
-       return (1u << off) & chip->mask_group_a;
-}
-
-static int max732x_gpio_get_value(struct gpio_chip *gc, unsigned off)
-{
-       struct max732x_chip *chip;
-       uint8_t reg_val;
-       int ret;
-
-       chip = container_of(gc, struct max732x_chip, gpio_chip);
-
-       ret = max732x_readb(chip, is_group_a(chip, off), &reg_val);
-       if (ret < 0)
-               return 0;
-
-       return reg_val & (1u << (off & 0x7));
-}
-
-static void max732x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val)
-{
-       struct max732x_chip *chip;
-       uint8_t reg_out, mask = 1u << (off & 0x7);
-       int ret;
-
-       chip = container_of(gc, struct max732x_chip, gpio_chip);
-
-       mutex_lock(&chip->lock);
-
-       reg_out = (off > 7) ? chip->reg_out[1] : chip->reg_out[0];
-       reg_out = (val) ? reg_out | mask : reg_out & ~mask;
-
-       ret = max732x_writeb(chip, is_group_a(chip, off), reg_out);
-       if (ret < 0)
-               goto out;
-
-       /* update the shadow register then */
-       if (off > 7)
-               chip->reg_out[1] = reg_out;
-       else
-               chip->reg_out[0] = reg_out;
-out:
-       mutex_unlock(&chip->lock);
-}
-
-static int max732x_gpio_direction_input(struct gpio_chip *gc, unsigned off)
-{
-       struct max732x_chip *chip;
-       unsigned int mask = 1u << off;
-
-       chip = container_of(gc, struct max732x_chip, gpio_chip);
-
-       if ((mask & chip->dir_input) == 0) {
-               dev_dbg(&chip->client->dev, "%s port %d is output only\n",
-                       chip->client->name, off);
-               return -EACCES;
-       }
-
-       /*
-        * Open-drain pins must be set to high impedance (which is
-        * equivalent to output-high) to be turned into an input.
-        */
-       if ((mask & chip->dir_output))
-               max732x_gpio_set_value(gc, off, 1);
-
-       return 0;
-}
-
-static int max732x_gpio_direction_output(struct gpio_chip *gc,
-               unsigned off, int val)
-{
-       struct max732x_chip *chip;
-       unsigned int mask = 1u << off;
-
-       chip = container_of(gc, struct max732x_chip, gpio_chip);
-
-       if ((mask & chip->dir_output) == 0) {
-               dev_dbg(&chip->client->dev, "%s port %d is input only\n",
-                       chip->client->name, off);
-               return -EACCES;
-       }
-
-       max732x_gpio_set_value(gc, off, val);
-       return 0;
-}
-
-#ifdef CONFIG_GPIO_MAX732X_IRQ
-static int max732x_writew(struct max732x_chip *chip, uint16_t val)
-{
-       int ret;
-
-       val = cpu_to_le16(val);
-
-       ret = i2c_master_send(chip->client_group_a, (char *)&val, 2);
-       if (ret < 0) {
-               dev_err(&chip->client_group_a->dev, "failed writing\n");
-               return ret;
-       }
-
-       return 0;
-}
-
-static int max732x_readw(struct max732x_chip *chip, uint16_t *val)
-{
-       int ret;
-
-       ret = i2c_master_recv(chip->client_group_a, (char *)val, 2);
-       if (ret < 0) {
-               dev_err(&chip->client_group_a->dev, "failed reading\n");
-               return ret;
-       }
-
-       *val = le16_to_cpu(*val);
-       return 0;
-}
-
-static void max732x_irq_update_mask(struct max732x_chip *chip)
-{
-       uint16_t msg;
-
-       if (chip->irq_mask == chip->irq_mask_cur)
-               return;
-
-       chip->irq_mask = chip->irq_mask_cur;
-
-       if (chip->irq_features == INT_NO_MASK)
-               return;
-
-       mutex_lock(&chip->lock);
-
-       switch (chip->irq_features) {
-       case INT_INDEP_MASK:
-               msg = (chip->irq_mask << 8) | chip->reg_out[0];
-               max732x_writew(chip, msg);
-               break;
-
-       case INT_MERGED_MASK:
-               msg = chip->irq_mask | chip->reg_out[0];
-               max732x_writeb(chip, 1, (uint8_t)msg);
-               break;
-       }
-
-       mutex_unlock(&chip->lock);
-}
-
-static int max732x_gpio_to_irq(struct gpio_chip *gc, unsigned off)
-{
-       struct max732x_chip *chip;
-
-       chip = container_of(gc, struct max732x_chip, gpio_chip);
-       return chip->irq_base + off;
-}
-
-static void max732x_irq_mask(struct irq_data *d)
-{
-       struct max732x_chip *chip = irq_data_get_irq_chip_data(d);
-
-       chip->irq_mask_cur &= ~(1 << (d->irq - chip->irq_base));
-}
-
-static void max732x_irq_unmask(struct irq_data *d)
-{
-       struct max732x_chip *chip = irq_data_get_irq_chip_data(d);
-
-       chip->irq_mask_cur |= 1 << (d->irq - chip->irq_base);
-}
-
-static void max732x_irq_bus_lock(struct irq_data *d)
-{
-       struct max732x_chip *chip = irq_data_get_irq_chip_data(d);
-
-       mutex_lock(&chip->irq_lock);
-       chip->irq_mask_cur = chip->irq_mask;
-}
-
-static void max732x_irq_bus_sync_unlock(struct irq_data *d)
-{
-       struct max732x_chip *chip = irq_data_get_irq_chip_data(d);
-
-       max732x_irq_update_mask(chip);
-       mutex_unlock(&chip->irq_lock);
-}
-
-static int max732x_irq_set_type(struct irq_data *d, unsigned int type)
-{
-       struct max732x_chip *chip = irq_data_get_irq_chip_data(d);
-       uint16_t off = d->irq - chip->irq_base;
-       uint16_t mask = 1 << off;
-
-       if (!(mask & chip->dir_input)) {
-               dev_dbg(&chip->client->dev, "%s port %d is output only\n",
-                       chip->client->name, off);
-               return -EACCES;
-       }
-
-       if (!(type & IRQ_TYPE_EDGE_BOTH)) {
-               dev_err(&chip->client->dev, "irq %d: unsupported type %d\n",
-                       d->irq, type);
-               return -EINVAL;
-       }
-
-       if (type & IRQ_TYPE_EDGE_FALLING)
-               chip->irq_trig_fall |= mask;
-       else
-               chip->irq_trig_fall &= ~mask;
-
-       if (type & IRQ_TYPE_EDGE_RISING)
-               chip->irq_trig_raise |= mask;
-       else
-               chip->irq_trig_raise &= ~mask;
-
-       return max732x_gpio_direction_input(&chip->gpio_chip, off);
-}
-
-static struct irq_chip max732x_irq_chip = {
-       .name                   = "max732x",
-       .irq_mask               = max732x_irq_mask,
-       .irq_unmask             = max732x_irq_unmask,
-       .irq_bus_lock           = max732x_irq_bus_lock,
-       .irq_bus_sync_unlock    = max732x_irq_bus_sync_unlock,
-       .irq_set_type           = max732x_irq_set_type,
-};
-
-static uint8_t max732x_irq_pending(struct max732x_chip *chip)
-{
-       uint8_t cur_stat;
-       uint8_t old_stat;
-       uint8_t trigger;
-       uint8_t pending;
-       uint16_t status;
-       int ret;
-
-       ret = max732x_readw(chip, &status);
-       if (ret)
-               return 0;
-
-       trigger = status >> 8;
-       trigger &= chip->irq_mask;
-
-       if (!trigger)
-               return 0;
-
-       cur_stat = status & 0xFF;
-       cur_stat &= chip->irq_mask;
-
-       old_stat = cur_stat ^ trigger;
-
-       pending = (old_stat & chip->irq_trig_fall) |
-                 (cur_stat & chip->irq_trig_raise);
-       pending &= trigger;
-
-       return pending;
-}
-
-static irqreturn_t max732x_irq_handler(int irq, void *devid)
-{
-       struct max732x_chip *chip = devid;
-       uint8_t pending;
-       uint8_t level;
-
-       pending = max732x_irq_pending(chip);
-
-       if (!pending)
-               return IRQ_HANDLED;
-
-       do {
-               level = __ffs(pending);
-               handle_nested_irq(level + chip->irq_base);
-
-               pending &= ~(1 << level);
-       } while (pending);
-
-       return IRQ_HANDLED;
-}
-
-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;
-       int has_irq = max732x_features[id->driver_data] >> 32;
-       int ret;
-
-       if (pdata->irq_base && has_irq != INT_NONE) {
-               int lvl;
-
-               chip->irq_base = pdata->irq_base;
-               chip->irq_features = has_irq;
-               mutex_init(&chip->irq_lock);
-
-               for (lvl = 0; lvl < chip->gpio_chip.ngpio; lvl++) {
-                       int irq = lvl + chip->irq_base;
-
-                       if (!(chip->dir_input & (1 << lvl)))
-                               continue;
-
-                       irq_set_chip_data(irq, chip);
-                       irq_set_chip_and_handler(irq, &max732x_irq_chip,
-                                                handle_edge_irq);
-                       irq_set_nested_thread(irq, 1);
-#ifdef CONFIG_ARM
-                       set_irq_flags(irq, IRQF_VALID);
-#else
-                       irq_set_noprobe(irq);
-#endif
-               }
-
-               ret = request_threaded_irq(client->irq,
-                                          NULL,
-                                          max732x_irq_handler,
-                                          IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
-                                          dev_name(&client->dev), chip);
-               if (ret) {
-                       dev_err(&client->dev, "failed to request irq %d\n",
-                               client->irq);
-                       goto out_failed;
-               }
-
-               chip->gpio_chip.to_irq = max732x_gpio_to_irq;
-       }
-
-       return 0;
-
-out_failed:
-       chip->irq_base = 0;
-       return ret;
-}
-
-static void max732x_irq_teardown(struct max732x_chip *chip)
-{
-       if (chip->irq_base)
-               free_irq(chip->client->irq, chip);
-}
-#else /* CONFIG_GPIO_MAX732X_IRQ */
-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;
-       int has_irq = max732x_features[id->driver_data] >> 32;
-
-       if (pdata->irq_base && has_irq != INT_NONE)
-               dev_warn(&client->dev, "interrupt support not compiled in\n");
-
-       return 0;
-}
-
-static void max732x_irq_teardown(struct max732x_chip *chip)
-{
-}
-#endif
-
-static int __devinit max732x_setup_gpio(struct max732x_chip *chip,
-                                       const struct i2c_device_id *id,
-                                       unsigned gpio_start)
-{
-       struct gpio_chip *gc = &chip->gpio_chip;
-       uint32_t id_data = (uint32_t)max732x_features[id->driver_data];
-       int i, port = 0;
-
-       for (i = 0; i < 16; i++, id_data >>= 2) {
-               unsigned int mask = 1 << port;
-
-               switch (id_data & 0x3) {
-               case PORT_OUTPUT:
-                       chip->dir_output |= mask;
-                       break;
-               case PORT_INPUT:
-                       chip->dir_input |= mask;
-                       break;
-               case PORT_OPENDRAIN:
-                       chip->dir_output |= mask;
-                       chip->dir_input |= mask;
-                       break;
-               default:
-                       continue;
-               }
-
-               if (i < 8)
-                       chip->mask_group_a |= mask;
-               port++;
-       }
-
-       if (chip->dir_input)
-               gc->direction_input = max732x_gpio_direction_input;
-       if (chip->dir_output) {
-               gc->direction_output = max732x_gpio_direction_output;
-               gc->set = max732x_gpio_set_value;
-       }
-       gc->get = max732x_gpio_get_value;
-       gc->can_sleep = 1;
-
-       gc->base = gpio_start;
-       gc->ngpio = port;
-       gc->label = chip->client->name;
-       gc->owner = THIS_MODULE;
-
-       return port;
-}
-
-static int __devinit max732x_probe(struct i2c_client *client,
-                                  const struct i2c_device_id *id)
-{
-       struct max732x_platform_data *pdata;
-       struct max732x_chip *chip;
-       struct i2c_client *c;
-       uint16_t addr_a, addr_b;
-       int ret, nr_port;
-
-       pdata = client->dev.platform_data;
-       if (pdata == NULL) {
-               dev_dbg(&client->dev, "no platform data\n");
-               return -EINVAL;
-       }
-
-       chip = kzalloc(sizeof(struct max732x_chip), GFP_KERNEL);
-       if (chip == NULL)
-               return -ENOMEM;
-       chip->client = client;
-
-       nr_port = max732x_setup_gpio(chip, id, pdata->gpio_base);
-
-       addr_a = (client->addr & 0x0f) | 0x60;
-       addr_b = (client->addr & 0x0f) | 0x50;
-
-       switch (client->addr & 0x70) {
-       case 0x60:
-               chip->client_group_a = client;
-               if (nr_port > 8) {
-                       c = i2c_new_dummy(client->adapter, addr_b);
-                       chip->client_group_b = chip->client_dummy = c;
-               }
-               break;
-       case 0x50:
-               chip->client_group_b = client;
-               if (nr_port > 8) {
-                       c = i2c_new_dummy(client->adapter, addr_a);
-                       chip->client_group_a = chip->client_dummy = c;
-               }
-               break;
-       default:
-               dev_err(&client->dev, "invalid I2C address specified %02x\n",
-                               client->addr);
-               ret = -EINVAL;
-               goto out_failed;
-       }
-
-       mutex_init(&chip->lock);
-
-       max732x_readb(chip, is_group_a(chip, 0), &chip->reg_out[0]);
-       if (nr_port > 8)
-               max732x_readb(chip, is_group_a(chip, 8), &chip->reg_out[1]);
-
-       ret = max732x_irq_setup(chip, id);
-       if (ret)
-               goto out_failed;
-
-       ret = gpiochip_add(&chip->gpio_chip);
-       if (ret)
-               goto out_failed;
-
-       if (pdata->setup) {
-               ret = pdata->setup(client, chip->gpio_chip.base,
-                               chip->gpio_chip.ngpio, pdata->context);
-               if (ret < 0)
-                       dev_warn(&client->dev, "setup failed, %d\n", ret);
-       }
-
-       i2c_set_clientdata(client, chip);
-       return 0;
-
-out_failed:
-       max732x_irq_teardown(chip);
-       kfree(chip);
-       return ret;
-}
-
-static int __devexit max732x_remove(struct i2c_client *client)
-{
-       struct max732x_platform_data *pdata = client->dev.platform_data;
-       struct max732x_chip *chip = i2c_get_clientdata(client);
-       int ret;
-
-       if (pdata->teardown) {
-               ret = pdata->teardown(client, chip->gpio_chip.base,
-                               chip->gpio_chip.ngpio, pdata->context);
-               if (ret < 0) {
-                       dev_err(&client->dev, "%s failed, %d\n",
-                                       "teardown", ret);
-                       return ret;
-               }
-       }
-
-       ret = gpiochip_remove(&chip->gpio_chip);
-       if (ret) {
-               dev_err(&client->dev, "%s failed, %d\n",
-                               "gpiochip_remove()", ret);
-               return ret;
-       }
-
-       max732x_irq_teardown(chip);
-
-       /* unregister any dummy i2c_client */
-       if (chip->client_dummy)
-               i2c_unregister_device(chip->client_dummy);
-
-       kfree(chip);
-       return 0;
-}
-
-static struct i2c_driver max732x_driver = {
-       .driver = {
-               .name   = "max732x",
-               .owner  = THIS_MODULE,
-       },
-       .probe          = max732x_probe,
-       .remove         = __devexit_p(max732x_remove),
-       .id_table       = max732x_id,
-};
-
-static int __init max732x_init(void)
-{
-       return i2c_add_driver(&max732x_driver);
-}
-/* register after i2c postcore initcall and before
- * subsys initcalls that may rely on these GPIOs
- */
-subsys_initcall(max732x_init);
-
-static void __exit max732x_exit(void)
-{
-       i2c_del_driver(&max732x_driver);
-}
-module_exit(max732x_exit);
-
-MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>");
-MODULE_DESCRIPTION("GPIO expander driver for MAX732X");
-MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/mc33880.c b/drivers/gpio/mc33880.c
deleted file mode 100644 (file)
index 4ec7975..0000000
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- * mc33880.c MC33880 high-side/low-side switch GPIO driver
- * Copyright (c) 2009 Intel Corporation
- *
- * 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.
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-/* Supports:
- * Freescale MC33880 high-side/low-side switch
- */
-
-#include <linux/init.h>
-#include <linux/mutex.h>
-#include <linux/spi/spi.h>
-#include <linux/spi/mc33880.h>
-#include <linux/gpio.h>
-#include <linux/slab.h>
-
-#define DRIVER_NAME "mc33880"
-
-/*
- * Pin configurations, see MAX7301 datasheet page 6
- */
-#define PIN_CONFIG_MASK 0x03
-#define PIN_CONFIG_IN_PULLUP 0x03
-#define PIN_CONFIG_IN_WO_PULLUP 0x02
-#define PIN_CONFIG_OUT 0x01
-
-#define PIN_NUMBER 8
-
-
-/*
- * Some registers must be read back to modify.
- * To save time we cache them here in memory
- */
-struct mc33880 {
-       struct mutex    lock;   /* protect from simultaneous accesses */
-       u8              port_config;
-       struct gpio_chip chip;
-       struct spi_device *spi;
-};
-
-static int mc33880_write_config(struct mc33880 *mc)
-{
-       return spi_write(mc->spi, &mc->port_config, sizeof(mc->port_config));
-}
-
-
-static int __mc33880_set(struct mc33880 *mc, unsigned offset, int value)
-{
-       if (value)
-               mc->port_config |= 1 << offset;
-       else
-               mc->port_config &= ~(1 << offset);
-
-       return mc33880_write_config(mc);
-}
-
-
-static void mc33880_set(struct gpio_chip *chip, unsigned offset, int value)
-{
-       struct mc33880 *mc = container_of(chip, struct mc33880, chip);
-
-       mutex_lock(&mc->lock);
-
-       __mc33880_set(mc, offset, value);
-
-       mutex_unlock(&mc->lock);
-}
-
-static int __devinit mc33880_probe(struct spi_device *spi)
-{
-       struct mc33880 *mc;
-       struct mc33880_platform_data *pdata;
-       int ret;
-
-       pdata = spi->dev.platform_data;
-       if (!pdata || !pdata->base) {
-               dev_dbg(&spi->dev, "incorrect or missing platform data\n");
-               return -EINVAL;
-       }
-
-       /*
-        * bits_per_word cannot be configured in platform data
-        */
-       spi->bits_per_word = 8;
-
-       ret = spi_setup(spi);
-       if (ret < 0)
-               return ret;
-
-       mc = kzalloc(sizeof(struct mc33880), GFP_KERNEL);
-       if (!mc)
-               return -ENOMEM;
-
-       mutex_init(&mc->lock);
-
-       dev_set_drvdata(&spi->dev, mc);
-
-       mc->spi = spi;
-
-       mc->chip.label = DRIVER_NAME,
-       mc->chip.set = mc33880_set;
-       mc->chip.base = pdata->base;
-       mc->chip.ngpio = PIN_NUMBER;
-       mc->chip.can_sleep = 1;
-       mc->chip.dev = &spi->dev;
-       mc->chip.owner = THIS_MODULE;
-
-       mc->port_config = 0x00;
-       /* write twice, because during initialisation the first setting
-        * is just for testing SPI communication, and the second is the
-        * "real" configuration
-        */
-       ret = mc33880_write_config(mc);
-       mc->port_config = 0x00;
-       if (!ret)
-               ret = mc33880_write_config(mc);
-
-       if (ret) {
-               printk(KERN_ERR "Failed writing to " DRIVER_NAME ": %d\n", ret);
-               goto exit_destroy;
-       }
-
-       ret = gpiochip_add(&mc->chip);
-       if (ret)
-               goto exit_destroy;
-
-       return ret;
-
-exit_destroy:
-       dev_set_drvdata(&spi->dev, NULL);
-       mutex_destroy(&mc->lock);
-       kfree(mc);
-       return ret;
-}
-
-static int __devexit mc33880_remove(struct spi_device *spi)
-{
-       struct mc33880 *mc;
-       int ret;
-
-       mc = dev_get_drvdata(&spi->dev);
-       if (mc == NULL)
-               return -ENODEV;
-
-       dev_set_drvdata(&spi->dev, NULL);
-
-       ret = gpiochip_remove(&mc->chip);
-       if (!ret) {
-               mutex_destroy(&mc->lock);
-               kfree(mc);
-       } else
-               dev_err(&spi->dev, "Failed to remove the GPIO controller: %d\n",
-                       ret);
-
-       return ret;
-}
-
-static struct spi_driver mc33880_driver = {
-       .driver = {
-               .name           = DRIVER_NAME,
-               .owner          = THIS_MODULE,
-       },
-       .probe          = mc33880_probe,
-       .remove         = __devexit_p(mc33880_remove),
-};
-
-static int __init mc33880_init(void)
-{
-       return spi_register_driver(&mc33880_driver);
-}
-/* register after spi postcore initcall and before
- * subsys initcalls that may rely on these GPIOs
- */
-subsys_initcall(mc33880_init);
-
-static void __exit mc33880_exit(void)
-{
-       spi_unregister_driver(&mc33880_driver);
-}
-module_exit(mc33880_exit);
-
-MODULE_AUTHOR("Mocean Laboratories <info@mocean-labs.com>");
-MODULE_LICENSE("GPL v2");
-
diff --git a/drivers/gpio/mcp23s08.c b/drivers/gpio/mcp23s08.c
deleted file mode 100644 (file)
index 40e0760..0000000
+++ /dev/null
@@ -1,530 +0,0 @@
-/*
- * mcp23s08.c - SPI gpio expander driver
- */
-
-#include <linux/kernel.h>
-#include <linux/device.h>
-#include <linux/workqueue.h>
-#include <linux/mutex.h>
-#include <linux/gpio.h>
-#include <linux/spi/spi.h>
-#include <linux/spi/mcp23s08.h>
-#include <linux/slab.h>
-#include <asm/byteorder.h>
-
-/**
- * MCP types supported by driver
- */
-#define MCP_TYPE_S08   0
-#define MCP_TYPE_S17   1
-
-/* Registers are all 8 bits wide.
- *
- * The mcp23s17 has twice as many bits, and can be configured to work
- * with either 16 bit registers or with two adjacent 8 bit banks.
- *
- * Also, there are I2C versions of both chips.
- */
-#define MCP_IODIR      0x00            /* init/reset:  all ones */
-#define MCP_IPOL       0x01
-#define MCP_GPINTEN    0x02
-#define MCP_DEFVAL     0x03
-#define MCP_INTCON     0x04
-#define MCP_IOCON      0x05
-#      define IOCON_SEQOP      (1 << 5)
-#      define IOCON_HAEN       (1 << 3)
-#      define IOCON_ODR        (1 << 2)
-#      define IOCON_INTPOL     (1 << 1)
-#define MCP_GPPU       0x06
-#define MCP_INTF       0x07
-#define MCP_INTCAP     0x08
-#define MCP_GPIO       0x09
-#define MCP_OLAT       0x0a
-
-struct mcp23s08;
-
-struct mcp23s08_ops {
-       int     (*read)(struct mcp23s08 *mcp, unsigned reg);
-       int     (*write)(struct mcp23s08 *mcp, unsigned reg, unsigned val);
-       int     (*read_regs)(struct mcp23s08 *mcp, unsigned reg,
-                            u16 *vals, unsigned n);
-};
-
-struct mcp23s08 {
-       struct spi_device       *spi;
-       u8                      addr;
-
-       u16                     cache[11];
-       /* lock protects the cached values */
-       struct mutex            lock;
-
-       struct gpio_chip        chip;
-
-       struct work_struct      work;
-
-       const struct mcp23s08_ops       *ops;
-};
-
-/* A given spi_device can represent up to eight mcp23sxx chips
- * sharing the same chipselect but using different addresses
- * (e.g. chips #0 and #3 might be populated, but not #1 or $2).
- * Driver data holds all the per-chip data.
- */
-struct mcp23s08_driver_data {
-       unsigned                ngpio;
-       struct mcp23s08         *mcp[8];
-       struct mcp23s08         chip[];
-};
-
-static int mcp23s08_read(struct mcp23s08 *mcp, unsigned reg)
-{
-       u8      tx[2], rx[1];
-       int     status;
-
-       tx[0] = mcp->addr | 0x01;
-       tx[1] = reg;
-       status = spi_write_then_read(mcp->spi, tx, sizeof tx, rx, sizeof rx);
-       return (status < 0) ? status : rx[0];
-}
-
-static int mcp23s08_write(struct mcp23s08 *mcp, unsigned reg, unsigned val)
-{
-       u8      tx[3];
-
-       tx[0] = mcp->addr;
-       tx[1] = reg;
-       tx[2] = val;
-       return spi_write_then_read(mcp->spi, tx, sizeof tx, NULL, 0);
-}
-
-static int
-mcp23s08_read_regs(struct mcp23s08 *mcp, unsigned reg, u16 *vals, unsigned n)
-{
-       u8      tx[2], *tmp;
-       int     status;
-
-       if ((n + reg) > sizeof mcp->cache)
-               return -EINVAL;
-       tx[0] = mcp->addr | 0x01;
-       tx[1] = reg;
-
-       tmp = (u8 *)vals;
-       status = spi_write_then_read(mcp->spi, tx, sizeof tx, tmp, n);
-       if (status >= 0) {
-               while (n--)
-                       vals[n] = tmp[n]; /* expand to 16bit */
-       }
-       return status;
-}
-
-static int mcp23s17_read(struct mcp23s08 *mcp, unsigned reg)
-{
-       u8      tx[2], rx[2];
-       int     status;
-
-       tx[0] = mcp->addr | 0x01;
-       tx[1] = reg << 1;
-       status = spi_write_then_read(mcp->spi, tx, sizeof tx, rx, sizeof rx);
-       return (status < 0) ? status : (rx[0] | (rx[1] << 8));
-}
-
-static int mcp23s17_write(struct mcp23s08 *mcp, unsigned reg, unsigned val)
-{
-       u8      tx[4];
-
-       tx[0] = mcp->addr;
-       tx[1] = reg << 1;
-       tx[2] = val;
-       tx[3] = val >> 8;
-       return spi_write_then_read(mcp->spi, tx, sizeof tx, NULL, 0);
-}
-
-static int
-mcp23s17_read_regs(struct mcp23s08 *mcp, unsigned reg, u16 *vals, unsigned n)
-{
-       u8      tx[2];
-       int     status;
-
-       if ((n + reg) > sizeof mcp->cache)
-               return -EINVAL;
-       tx[0] = mcp->addr | 0x01;
-       tx[1] = reg << 1;
-
-       status = spi_write_then_read(mcp->spi, tx, sizeof tx,
-                                    (u8 *)vals, n * 2);
-       if (status >= 0) {
-               while (n--)
-                       vals[n] = __le16_to_cpu((__le16)vals[n]);
-       }
-
-       return status;
-}
-
-static const struct mcp23s08_ops mcp23s08_ops = {
-       .read           = mcp23s08_read,
-       .write          = mcp23s08_write,
-       .read_regs      = mcp23s08_read_regs,
-};
-
-static const struct mcp23s08_ops mcp23s17_ops = {
-       .read           = mcp23s17_read,
-       .write          = mcp23s17_write,
-       .read_regs      = mcp23s17_read_regs,
-};
-
-
-/*----------------------------------------------------------------------*/
-
-static int mcp23s08_direction_input(struct gpio_chip *chip, unsigned offset)
-{
-       struct mcp23s08 *mcp = container_of(chip, struct mcp23s08, chip);
-       int status;
-
-       mutex_lock(&mcp->lock);
-       mcp->cache[MCP_IODIR] |= (1 << offset);
-       status = mcp->ops->write(mcp, MCP_IODIR, mcp->cache[MCP_IODIR]);
-       mutex_unlock(&mcp->lock);
-       return status;
-}
-
-static int mcp23s08_get(struct gpio_chip *chip, unsigned offset)
-{
-       struct mcp23s08 *mcp = container_of(chip, struct mcp23s08, chip);
-       int status;
-
-       mutex_lock(&mcp->lock);
-
-       /* REVISIT reading this clears any IRQ ... */
-       status = mcp->ops->read(mcp, MCP_GPIO);
-       if (status < 0)
-               status = 0;
-       else {
-               mcp->cache[MCP_GPIO] = status;
-               status = !!(status & (1 << offset));
-       }
-       mutex_unlock(&mcp->lock);
-       return status;
-}
-
-static int __mcp23s08_set(struct mcp23s08 *mcp, unsigned mask, int value)
-{
-       unsigned olat = mcp->cache[MCP_OLAT];
-
-       if (value)
-               olat |= mask;
-       else
-               olat &= ~mask;
-       mcp->cache[MCP_OLAT] = olat;
-       return mcp->ops->write(mcp, MCP_OLAT, olat);
-}
-
-static void mcp23s08_set(struct gpio_chip *chip, unsigned offset, int value)
-{
-       struct mcp23s08 *mcp = container_of(chip, struct mcp23s08, chip);
-       unsigned mask = 1 << offset;
-
-       mutex_lock(&mcp->lock);
-       __mcp23s08_set(mcp, mask, value);
-       mutex_unlock(&mcp->lock);
-}
-
-static int
-mcp23s08_direction_output(struct gpio_chip *chip, unsigned offset, int value)
-{
-       struct mcp23s08 *mcp = container_of(chip, struct mcp23s08, chip);
-       unsigned mask = 1 << offset;
-       int status;
-
-       mutex_lock(&mcp->lock);
-       status = __mcp23s08_set(mcp, mask, value);
-       if (status == 0) {
-               mcp->cache[MCP_IODIR] &= ~mask;
-               status = mcp->ops->write(mcp, MCP_IODIR, mcp->cache[MCP_IODIR]);
-       }
-       mutex_unlock(&mcp->lock);
-       return status;
-}
-
-/*----------------------------------------------------------------------*/
-
-#ifdef CONFIG_DEBUG_FS
-
-#include <linux/seq_file.h>
-
-/*
- * This shows more info than the generic gpio dump code:
- * pullups, deglitching, open drain drive.
- */
-static void mcp23s08_dbg_show(struct seq_file *s, struct gpio_chip *chip)
-{
-       struct mcp23s08 *mcp;
-       char            bank;
-       int             t;
-       unsigned        mask;
-
-       mcp = container_of(chip, struct mcp23s08, chip);
-
-       /* NOTE: we only handle one bank for now ... */
-       bank = '0' + ((mcp->addr >> 1) & 0x7);
-
-       mutex_lock(&mcp->lock);
-       t = mcp->ops->read_regs(mcp, 0, mcp->cache, ARRAY_SIZE(mcp->cache));
-       if (t < 0) {
-               seq_printf(s, " I/O ERROR %d\n", t);
-               goto done;
-       }
-
-       for (t = 0, mask = 1; t < chip->ngpio; t++, mask <<= 1) {
-               const char      *label;
-
-               label = gpiochip_is_requested(chip, t);
-               if (!label)
-                       continue;
-
-               seq_printf(s, " gpio-%-3d P%c.%d (%-12s) %s %s %s",
-                       chip->base + t, bank, t, label,
-                       (mcp->cache[MCP_IODIR] & mask) ? "in " : "out",
-                       (mcp->cache[MCP_GPIO] & mask) ? "hi" : "lo",
-                       (mcp->cache[MCP_GPPU] & mask) ? "  " : "up");
-               /* NOTE:  ignoring the irq-related registers */
-               seq_printf(s, "\n");
-       }
-done:
-       mutex_unlock(&mcp->lock);
-}
-
-#else
-#define mcp23s08_dbg_show      NULL
-#endif
-
-/*----------------------------------------------------------------------*/
-
-static int mcp23s08_probe_one(struct spi_device *spi, unsigned addr,
-                             unsigned type, unsigned base, unsigned pullups)
-{
-       struct mcp23s08_driver_data     *data = spi_get_drvdata(spi);
-       struct mcp23s08                 *mcp = data->mcp[addr];
-       int                             status;
-
-       mutex_init(&mcp->lock);
-
-       mcp->spi = spi;
-       mcp->addr = 0x40 | (addr << 1);
-
-       mcp->chip.direction_input = mcp23s08_direction_input;
-       mcp->chip.get = mcp23s08_get;
-       mcp->chip.direction_output = mcp23s08_direction_output;
-       mcp->chip.set = mcp23s08_set;
-       mcp->chip.dbg_show = mcp23s08_dbg_show;
-
-       if (type == MCP_TYPE_S17) {
-               mcp->ops = &mcp23s17_ops;
-               mcp->chip.ngpio = 16;
-               mcp->chip.label = "mcp23s17";
-       } else {
-               mcp->ops = &mcp23s08_ops;
-               mcp->chip.ngpio = 8;
-               mcp->chip.label = "mcp23s08";
-       }
-       mcp->chip.base = base;
-       mcp->chip.can_sleep = 1;
-       mcp->chip.dev = &spi->dev;
-       mcp->chip.owner = THIS_MODULE;
-
-       /* verify MCP_IOCON.SEQOP = 0, so sequential reads work,
-        * and MCP_IOCON.HAEN = 1, so we work with all chips.
-        */
-       status = mcp->ops->read(mcp, MCP_IOCON);
-       if (status < 0)
-               goto fail;
-       if ((status & IOCON_SEQOP) || !(status & IOCON_HAEN)) {
-               /* mcp23s17 has IOCON twice, make sure they are in sync */
-               status &= ~(IOCON_SEQOP | (IOCON_SEQOP << 8));
-               status |= IOCON_HAEN | (IOCON_HAEN << 8);
-               status = mcp->ops->write(mcp, MCP_IOCON, status);
-               if (status < 0)
-                       goto fail;
-       }
-
-       /* configure ~100K pullups */
-       status = mcp->ops->write(mcp, MCP_GPPU, pullups);
-       if (status < 0)
-               goto fail;
-
-       status = mcp->ops->read_regs(mcp, 0, mcp->cache, ARRAY_SIZE(mcp->cache));
-       if (status < 0)
-               goto fail;
-
-       /* disable inverter on input */
-       if (mcp->cache[MCP_IPOL] != 0) {
-               mcp->cache[MCP_IPOL] = 0;
-               status = mcp->ops->write(mcp, MCP_IPOL, 0);
-               if (status < 0)
-                       goto fail;
-       }
-
-       /* disable irqs */
-       if (mcp->cache[MCP_GPINTEN] != 0) {
-               mcp->cache[MCP_GPINTEN] = 0;
-               status = mcp->ops->write(mcp, MCP_GPINTEN, 0);
-               if (status < 0)
-                       goto fail;
-       }
-
-       status = gpiochip_add(&mcp->chip);
-fail:
-       if (status < 0)
-               dev_dbg(&spi->dev, "can't setup chip %d, --> %d\n",
-                               addr, status);
-       return status;
-}
-
-static int mcp23s08_probe(struct spi_device *spi)
-{
-       struct mcp23s08_platform_data   *pdata;
-       unsigned                        addr;
-       unsigned                        chips = 0;
-       struct mcp23s08_driver_data     *data;
-       int                             status, type;
-       unsigned                        base;
-
-       type = spi_get_device_id(spi)->driver_data;
-
-       pdata = spi->dev.platform_data;
-       if (!pdata || !gpio_is_valid(pdata->base)) {
-               dev_dbg(&spi->dev, "invalid or missing platform data\n");
-               return -EINVAL;
-       }
-
-       for (addr = 0; addr < ARRAY_SIZE(pdata->chip); addr++) {
-               if (!pdata->chip[addr].is_present)
-                       continue;
-               chips++;
-               if ((type == MCP_TYPE_S08) && (addr > 3)) {
-                       dev_err(&spi->dev,
-                               "mcp23s08 only supports address 0..3\n");
-                       return -EINVAL;
-               }
-       }
-       if (!chips)
-               return -ENODEV;
-
-       data = kzalloc(sizeof *data + chips * sizeof(struct mcp23s08),
-                       GFP_KERNEL);
-       if (!data)
-               return -ENOMEM;
-       spi_set_drvdata(spi, data);
-
-       base = pdata->base;
-       for (addr = 0; addr < ARRAY_SIZE(pdata->chip); addr++) {
-               if (!pdata->chip[addr].is_present)
-                       continue;
-               chips--;
-               data->mcp[addr] = &data->chip[chips];
-               status = mcp23s08_probe_one(spi, addr, type, base,
-                                           pdata->chip[addr].pullups);
-               if (status < 0)
-                       goto fail;
-
-               base += (type == MCP_TYPE_S17) ? 16 : 8;
-       }
-       data->ngpio = base - pdata->base;
-
-       /* NOTE:  these chips have a relatively sane IRQ framework, with
-        * per-signal masking and level/edge triggering.  It's not yet
-        * handled here...
-        */
-
-       if (pdata->setup) {
-               status = pdata->setup(spi,
-                               pdata->base, data->ngpio,
-                               pdata->context);
-               if (status < 0)
-                       dev_dbg(&spi->dev, "setup --> %d\n", status);
-       }
-
-       return 0;
-
-fail:
-       for (addr = 0; addr < ARRAY_SIZE(data->mcp); addr++) {
-               int tmp;
-
-               if (!data->mcp[addr])
-                       continue;
-               tmp = gpiochip_remove(&data->mcp[addr]->chip);
-               if (tmp < 0)
-                       dev_err(&spi->dev, "%s --> %d\n", "remove", tmp);
-       }
-       kfree(data);
-       return status;
-}
-
-static int mcp23s08_remove(struct spi_device *spi)
-{
-       struct mcp23s08_driver_data     *data = spi_get_drvdata(spi);
-       struct mcp23s08_platform_data   *pdata = spi->dev.platform_data;
-       unsigned                        addr;
-       int                             status = 0;
-
-       if (pdata->teardown) {
-               status = pdata->teardown(spi,
-                               pdata->base, data->ngpio,
-                               pdata->context);
-               if (status < 0) {
-                       dev_err(&spi->dev, "%s --> %d\n", "teardown", status);
-                       return status;
-               }
-       }
-
-       for (addr = 0; addr < ARRAY_SIZE(data->mcp); addr++) {
-               int tmp;
-
-               if (!data->mcp[addr])
-                       continue;
-
-               tmp = gpiochip_remove(&data->mcp[addr]->chip);
-               if (tmp < 0) {
-                       dev_err(&spi->dev, "%s --> %d\n", "remove", tmp);
-                       status = tmp;
-               }
-       }
-       if (status == 0)
-               kfree(data);
-       return status;
-}
-
-static const struct spi_device_id mcp23s08_ids[] = {
-       { "mcp23s08", MCP_TYPE_S08 },
-       { "mcp23s17", MCP_TYPE_S17 },
-       { },
-};
-MODULE_DEVICE_TABLE(spi, mcp23s08_ids);
-
-static struct spi_driver mcp23s08_driver = {
-       .probe          = mcp23s08_probe,
-       .remove         = mcp23s08_remove,
-       .id_table       = mcp23s08_ids,
-       .driver = {
-               .name   = "mcp23s08",
-               .owner  = THIS_MODULE,
-       },
-};
-
-/*----------------------------------------------------------------------*/
-
-static int __init mcp23s08_init(void)
-{
-       return spi_register_driver(&mcp23s08_driver);
-}
-/* register after spi postcore initcall and before
- * subsys initcalls that may rely on these GPIOs
- */
-subsys_initcall(mcp23s08_init);
-
-static void __exit mcp23s08_exit(void)
-{
-       spi_unregister_driver(&mcp23s08_driver);
-}
-module_exit(mcp23s08_exit);
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/ml_ioh_gpio.c b/drivers/gpio/ml_ioh_gpio.c
deleted file mode 100644 (file)
index 1bc621a..0000000
+++ /dev/null
@@ -1,357 +0,0 @@
-/*
- * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD.
- *
- * 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; version 2 of the License.
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
- */
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/pci.h>
-#include <linux/gpio.h>
-
-#define PCI_VENDOR_ID_ROHM             0x10DB
-
-struct ioh_reg_comn {
-       u32     ien;
-       u32     istatus;
-       u32     idisp;
-       u32     iclr;
-       u32     imask;
-       u32     imaskclr;
-       u32     po;
-       u32     pi;
-       u32     pm;
-       u32     im_0;
-       u32     im_1;
-       u32     reserved;
-};
-
-struct ioh_regs {
-       struct ioh_reg_comn regs[8];
-       u32 reserve1[16];
-       u32 ioh_sel_reg[4];
-       u32 reserve2[11];
-       u32 srst;
-};
-
-/**
- * struct ioh_gpio_reg_data - The register store data.
- * @po_reg:    To store contents of PO register.
- * @pm_reg:    To store contents of PM register.
- */
-struct ioh_gpio_reg_data {
-       u32 po_reg;
-       u32 pm_reg;
-};
-
-/**
- * struct ioh_gpio - GPIO private data structure.
- * @base:                      PCI base address of Memory mapped I/O register.
- * @reg:                       Memory mapped IOH GPIO register list.
- * @dev:                       Pointer to device structure.
- * @gpio:                      Data for GPIO infrastructure.
- * @ioh_gpio_reg:              Memory mapped Register data is saved here
- *                             when suspend.
- * @ch:                                Indicate GPIO channel
- */
-struct ioh_gpio {
-       void __iomem *base;
-       struct ioh_regs __iomem *reg;
-       struct device *dev;
-       struct gpio_chip gpio;
-       struct ioh_gpio_reg_data ioh_gpio_reg;
-       struct mutex lock;
-       int ch;
-};
-
-static const int num_ports[] = {6, 12, 16, 16, 15, 16, 16, 12};
-
-static void ioh_gpio_set(struct gpio_chip *gpio, unsigned nr, int val)
-{
-       u32 reg_val;
-       struct ioh_gpio *chip = container_of(gpio, struct ioh_gpio, gpio);
-
-       mutex_lock(&chip->lock);
-       reg_val = ioread32(&chip->reg->regs[chip->ch].po);
-       if (val)
-               reg_val |= (1 << nr);
-       else
-               reg_val &= ~(1 << nr);
-
-       iowrite32(reg_val, &chip->reg->regs[chip->ch].po);
-       mutex_unlock(&chip->lock);
-}
-
-static int ioh_gpio_get(struct gpio_chip *gpio, unsigned nr)
-{
-       struct ioh_gpio *chip = container_of(gpio, struct ioh_gpio, gpio);
-
-       return ioread32(&chip->reg->regs[chip->ch].pi) & (1 << nr);
-}
-
-static int ioh_gpio_direction_output(struct gpio_chip *gpio, unsigned nr,
-                                    int val)
-{
-       struct ioh_gpio *chip = container_of(gpio, struct ioh_gpio, gpio);
-       u32 pm;
-       u32 reg_val;
-
-       mutex_lock(&chip->lock);
-       pm = ioread32(&chip->reg->regs[chip->ch].pm) &
-                                       ((1 << num_ports[chip->ch]) - 1);
-       pm |= (1 << nr);
-       iowrite32(pm, &chip->reg->regs[chip->ch].pm);
-
-       reg_val = ioread32(&chip->reg->regs[chip->ch].po);
-       if (val)
-               reg_val |= (1 << nr);
-       else
-               reg_val &= ~(1 << nr);
-       iowrite32(reg_val, &chip->reg->regs[chip->ch].po);
-
-       mutex_unlock(&chip->lock);
-
-       return 0;
-}
-
-static int ioh_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
-{
-       struct ioh_gpio *chip = container_of(gpio, struct ioh_gpio, gpio);
-       u32 pm;
-
-       mutex_lock(&chip->lock);
-       pm = ioread32(&chip->reg->regs[chip->ch].pm) &
-                               ((1 << num_ports[chip->ch]) - 1);
-       pm &= ~(1 << nr);
-       iowrite32(pm, &chip->reg->regs[chip->ch].pm);
-       mutex_unlock(&chip->lock);
-
-       return 0;
-}
-
-#ifdef CONFIG_PM
-/*
- * Save register configuration and disable interrupts.
- */
-static void ioh_gpio_save_reg_conf(struct ioh_gpio *chip)
-{
-       chip->ioh_gpio_reg.po_reg = ioread32(&chip->reg->regs[chip->ch].po);
-       chip->ioh_gpio_reg.pm_reg = ioread32(&chip->reg->regs[chip->ch].pm);
-}
-
-/*
- * This function restores the register configuration of the GPIO device.
- */
-static void ioh_gpio_restore_reg_conf(struct ioh_gpio *chip)
-{
-       /* to store contents of PO register */
-       iowrite32(chip->ioh_gpio_reg.po_reg, &chip->reg->regs[chip->ch].po);
-       /* to store contents of PM register */
-       iowrite32(chip->ioh_gpio_reg.pm_reg, &chip->reg->regs[chip->ch].pm);
-}
-#endif
-
-static void ioh_gpio_setup(struct ioh_gpio *chip, int num_port)
-{
-       struct gpio_chip *gpio = &chip->gpio;
-
-       gpio->label = dev_name(chip->dev);
-       gpio->owner = THIS_MODULE;
-       gpio->direction_input = ioh_gpio_direction_input;
-       gpio->get = ioh_gpio_get;
-       gpio->direction_output = ioh_gpio_direction_output;
-       gpio->set = ioh_gpio_set;
-       gpio->dbg_show = NULL;
-       gpio->base = -1;
-       gpio->ngpio = num_port;
-       gpio->can_sleep = 0;
-}
-
-static int __devinit ioh_gpio_probe(struct pci_dev *pdev,
-                                   const struct pci_device_id *id)
-{
-       int ret;
-       int i;
-       struct ioh_gpio *chip;
-       void __iomem *base;
-       void __iomem *chip_save;
-
-       ret = pci_enable_device(pdev);
-       if (ret) {
-               dev_err(&pdev->dev, "%s : pci_enable_device failed", __func__);
-               goto err_pci_enable;
-       }
-
-       ret = pci_request_regions(pdev, KBUILD_MODNAME);
-       if (ret) {
-               dev_err(&pdev->dev, "pci_request_regions failed-%d", ret);
-               goto err_request_regions;
-       }
-
-       base = pci_iomap(pdev, 1, 0);
-       if (base == 0) {
-               dev_err(&pdev->dev, "%s : pci_iomap failed", __func__);
-               ret = -ENOMEM;
-               goto err_iomap;
-       }
-
-       chip_save = kzalloc(sizeof(*chip) * 8, GFP_KERNEL);
-       if (chip_save == NULL) {
-               dev_err(&pdev->dev, "%s : kzalloc failed", __func__);
-               ret = -ENOMEM;
-               goto err_kzalloc;
-       }
-
-       chip = chip_save;
-       for (i = 0; i < 8; i++, chip++) {
-               chip->dev = &pdev->dev;
-               chip->base = base;
-               chip->reg = chip->base;
-               chip->ch = i;
-               mutex_init(&chip->lock);
-               ioh_gpio_setup(chip, num_ports[i]);
-               ret = gpiochip_add(&chip->gpio);
-               if (ret) {
-                       dev_err(&pdev->dev, "IOH gpio: Failed to register GPIO\n");
-                       goto err_gpiochip_add;
-               }
-       }
-
-       chip = chip_save;
-       pci_set_drvdata(pdev, chip);
-
-       return 0;
-
-err_gpiochip_add:
-       for (; i != 0; i--) {
-               chip--;
-               ret = gpiochip_remove(&chip->gpio);
-               if (ret)
-                       dev_err(&pdev->dev, "Failed gpiochip_remove(%d)\n", i);
-       }
-       kfree(chip_save);
-
-err_kzalloc:
-       pci_iounmap(pdev, base);
-
-err_iomap:
-       pci_release_regions(pdev);
-
-err_request_regions:
-       pci_disable_device(pdev);
-
-err_pci_enable:
-
-       dev_err(&pdev->dev, "%s Failed returns %d\n", __func__, ret);
-       return ret;
-}
-
-static void __devexit ioh_gpio_remove(struct pci_dev *pdev)
-{
-       int err;
-       int i;
-       struct ioh_gpio *chip = pci_get_drvdata(pdev);
-       void __iomem *chip_save;
-
-       chip_save = chip;
-       for (i = 0; i < 8; i++, chip++) {
-               err = gpiochip_remove(&chip->gpio);
-               if (err)
-                       dev_err(&pdev->dev, "Failed gpiochip_remove\n");
-       }
-
-       chip = chip_save;
-       pci_iounmap(pdev, chip->base);
-       pci_release_regions(pdev);
-       pci_disable_device(pdev);
-       kfree(chip);
-}
-
-#ifdef CONFIG_PM
-static int ioh_gpio_suspend(struct pci_dev *pdev, pm_message_t state)
-{
-       s32 ret;
-       struct ioh_gpio *chip = pci_get_drvdata(pdev);
-
-       ioh_gpio_save_reg_conf(chip);
-       ioh_gpio_restore_reg_conf(chip);
-
-       ret = pci_save_state(pdev);
-       if (ret) {
-               dev_err(&pdev->dev, "pci_save_state Failed-%d\n", ret);
-               return ret;
-       }
-       pci_disable_device(pdev);
-       pci_set_power_state(pdev, PCI_D0);
-       ret = pci_enable_wake(pdev, PCI_D0, 1);
-       if (ret)
-               dev_err(&pdev->dev, "pci_enable_wake Failed -%d\n", ret);
-
-       return 0;
-}
-
-static int ioh_gpio_resume(struct pci_dev *pdev)
-{
-       s32 ret;
-       struct ioh_gpio *chip = pci_get_drvdata(pdev);
-
-       ret = pci_enable_wake(pdev, PCI_D0, 0);
-
-       pci_set_power_state(pdev, PCI_D0);
-       ret = pci_enable_device(pdev);
-       if (ret) {
-               dev_err(&pdev->dev, "pci_enable_device Failed-%d ", ret);
-               return ret;
-       }
-       pci_restore_state(pdev);
-
-       iowrite32(0x01, &chip->reg->srst);
-       iowrite32(0x00, &chip->reg->srst);
-       ioh_gpio_restore_reg_conf(chip);
-
-       return 0;
-}
-#else
-#define ioh_gpio_suspend NULL
-#define ioh_gpio_resume NULL
-#endif
-
-static DEFINE_PCI_DEVICE_TABLE(ioh_gpio_pcidev_id) = {
-       { PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x802E) },
-       { 0, }
-};
-MODULE_DEVICE_TABLE(pci, ioh_gpio_pcidev_id);
-
-static struct pci_driver ioh_gpio_driver = {
-       .name = "ml_ioh_gpio",
-       .id_table = ioh_gpio_pcidev_id,
-       .probe = ioh_gpio_probe,
-       .remove = __devexit_p(ioh_gpio_remove),
-       .suspend = ioh_gpio_suspend,
-       .resume = ioh_gpio_resume
-};
-
-static int __init ioh_gpio_pci_init(void)
-{
-       return pci_register_driver(&ioh_gpio_driver);
-}
-module_init(ioh_gpio_pci_init);
-
-static void __exit ioh_gpio_pci_exit(void)
-{
-       pci_unregister_driver(&ioh_gpio_driver);
-}
-module_exit(ioh_gpio_pci_exit);
-
-MODULE_DESCRIPTION("OKI SEMICONDUCTOR ML-IOH series GPIO Driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/pca953x.c b/drivers/gpio/pca953x.c
deleted file mode 100644 (file)
index 63022b1..0000000
+++ /dev/null
@@ -1,768 +0,0 @@
-/*
- *  pca953x.c - 4/8/16 bit I/O ports
- *
- *  Copyright (C) 2005 Ben Gardner <bgardner@wabtec.com>
- *  Copyright (C) 2007 Marvell International Ltd.
- *
- *  Derived from drivers/i2c/chips/pca9539.c
- *
- *  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; version 2 of the License.
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/gpio.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/i2c.h>
-#include <linux/i2c/pca953x.h>
-#include <linux/slab.h>
-#ifdef CONFIG_OF_GPIO
-#include <linux/of_platform.h>
-#include <linux/of_gpio.h>
-#endif
-
-#define PCA953X_INPUT          0
-#define PCA953X_OUTPUT         1
-#define PCA953X_INVERT         2
-#define PCA953X_DIRECTION      3
-
-#define PCA957X_IN             0
-#define PCA957X_INVRT          1
-#define PCA957X_BKEN           2
-#define PCA957X_PUPD           3
-#define PCA957X_CFG            4
-#define PCA957X_OUT            5
-#define PCA957X_MSK            6
-#define PCA957X_INTS           7
-
-#define PCA_GPIO_MASK          0x00FF
-#define PCA_INT                        0x0100
-#define PCA953X_TYPE           0x1000
-#define PCA957X_TYPE           0x2000
-
-static const struct i2c_device_id pca953x_id[] = {
-       { "pca9534", 8  | PCA953X_TYPE | PCA_INT, },
-       { "pca9535", 16 | PCA953X_TYPE | PCA_INT, },
-       { "pca9536", 4  | PCA953X_TYPE, },
-       { "pca9537", 4  | PCA953X_TYPE | PCA_INT, },
-       { "pca9538", 8  | PCA953X_TYPE | PCA_INT, },
-       { "pca9539", 16 | PCA953X_TYPE | PCA_INT, },
-       { "pca9554", 8  | PCA953X_TYPE | PCA_INT, },
-       { "pca9555", 16 | PCA953X_TYPE | PCA_INT, },
-       { "pca9556", 8  | PCA953X_TYPE, },
-       { "pca9557", 8  | PCA953X_TYPE, },
-       { "pca9574", 8  | PCA957X_TYPE | PCA_INT, },
-       { "pca9575", 16 | PCA957X_TYPE | PCA_INT, },
-
-       { "max7310", 8  | PCA953X_TYPE, },
-       { "max7312", 16 | PCA953X_TYPE | PCA_INT, },
-       { "max7313", 16 | PCA953X_TYPE | PCA_INT, },
-       { "max7315", 8  | PCA953X_TYPE | PCA_INT, },
-       { "pca6107", 8  | PCA953X_TYPE | PCA_INT, },
-       { "tca6408", 8  | PCA953X_TYPE | PCA_INT, },
-       { "tca6416", 16 | PCA953X_TYPE | PCA_INT, },
-       /* NYET:  { "tca6424", 24, }, */
-       { }
-};
-MODULE_DEVICE_TABLE(i2c, pca953x_id);
-
-struct pca953x_chip {
-       unsigned gpio_start;
-       uint16_t reg_output;
-       uint16_t reg_direction;
-       struct mutex i2c_lock;
-
-#ifdef CONFIG_GPIO_PCA953X_IRQ
-       struct mutex irq_lock;
-       uint16_t irq_mask;
-       uint16_t irq_stat;
-       uint16_t irq_trig_raise;
-       uint16_t irq_trig_fall;
-       int      irq_base;
-#endif
-
-       struct i2c_client *client;
-       struct pca953x_platform_data *dyn_pdata;
-       struct gpio_chip gpio_chip;
-       const char *const *names;
-       int     chip_type;
-};
-
-static int pca953x_write_reg(struct pca953x_chip *chip, int reg, uint16_t val)
-{
-       int ret = 0;
-
-       if (chip->gpio_chip.ngpio <= 8)
-               ret = i2c_smbus_write_byte_data(chip->client, reg, val);
-       else {
-               switch (chip->chip_type) {
-               case PCA953X_TYPE:
-                       ret = i2c_smbus_write_word_data(chip->client,
-                                                       reg << 1, val);
-                       break;
-               case PCA957X_TYPE:
-                       ret = i2c_smbus_write_byte_data(chip->client, reg << 1,
-                                                       val & 0xff);
-                       if (ret < 0)
-                               break;
-                       ret = i2c_smbus_write_byte_data(chip->client,
-                                                       (reg << 1) + 1,
-                                                       (val & 0xff00) >> 8);
-                       break;
-               }
-       }
-
-       if (ret < 0) {
-               dev_err(&chip->client->dev, "failed writing register\n");
-               return ret;
-       }
-
-       return 0;
-}
-
-static int pca953x_read_reg(struct pca953x_chip *chip, int reg, uint16_t *val)
-{
-       int ret;
-
-       if (chip->gpio_chip.ngpio <= 8)
-               ret = i2c_smbus_read_byte_data(chip->client, reg);
-       else
-               ret = i2c_smbus_read_word_data(chip->client, reg << 1);
-
-       if (ret < 0) {
-               dev_err(&chip->client->dev, "failed reading register\n");
-               return ret;
-       }
-
-       *val = (uint16_t)ret;
-       return 0;
-}
-
-static int pca953x_gpio_direction_input(struct gpio_chip *gc, unsigned off)
-{
-       struct pca953x_chip *chip;
-       uint16_t reg_val;
-       int ret, offset = 0;
-
-       chip = container_of(gc, struct pca953x_chip, gpio_chip);
-
-       mutex_lock(&chip->i2c_lock);
-       reg_val = chip->reg_direction | (1u << off);
-
-       switch (chip->chip_type) {
-       case PCA953X_TYPE:
-               offset = PCA953X_DIRECTION;
-               break;
-       case PCA957X_TYPE:
-               offset = PCA957X_CFG;
-               break;
-       }
-       ret = pca953x_write_reg(chip, offset, reg_val);
-       if (ret)
-               goto exit;
-
-       chip->reg_direction = reg_val;
-       ret = 0;
-exit:
-       mutex_unlock(&chip->i2c_lock);
-       return ret;
-}
-
-static int pca953x_gpio_direction_output(struct gpio_chip *gc,
-               unsigned off, int val)
-{
-       struct pca953x_chip *chip;
-       uint16_t reg_val;
-       int ret, offset = 0;
-
-       chip = container_of(gc, struct pca953x_chip, gpio_chip);
-
-       mutex_lock(&chip->i2c_lock);
-       /* set output level */
-       if (val)
-               reg_val = chip->reg_output | (1u << off);
-       else
-               reg_val = chip->reg_output & ~(1u << off);
-
-       switch (chip->chip_type) {
-       case PCA953X_TYPE:
-               offset = PCA953X_OUTPUT;
-               break;
-       case PCA957X_TYPE:
-               offset = PCA957X_OUT;
-               break;
-       }
-       ret = pca953x_write_reg(chip, offset, reg_val);
-       if (ret)
-               goto exit;
-
-       chip->reg_output = reg_val;
-
-       /* then direction */
-       reg_val = chip->reg_direction & ~(1u << off);
-       switch (chip->chip_type) {
-       case PCA953X_TYPE:
-               offset = PCA953X_DIRECTION;
-               break;
-       case PCA957X_TYPE:
-               offset = PCA957X_CFG;
-               break;
-       }
-       ret = pca953x_write_reg(chip, offset, reg_val);
-       if (ret)
-               goto exit;
-
-       chip->reg_direction = reg_val;
-       ret = 0;
-exit:
-       mutex_unlock(&chip->i2c_lock);
-       return ret;
-}
-
-static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off)
-{
-       struct pca953x_chip *chip;
-       uint16_t reg_val;
-       int ret, offset = 0;
-
-       chip = container_of(gc, struct pca953x_chip, gpio_chip);
-
-       mutex_lock(&chip->i2c_lock);
-       switch (chip->chip_type) {
-       case PCA953X_TYPE:
-               offset = PCA953X_INPUT;
-               break;
-       case PCA957X_TYPE:
-               offset = PCA957X_IN;
-               break;
-       }
-       ret = pca953x_read_reg(chip, offset, &reg_val);
-       mutex_unlock(&chip->i2c_lock);
-       if (ret < 0) {
-               /* NOTE:  diagnostic already emitted; that's all we should
-                * do unless gpio_*_value_cansleep() calls become different
-                * from their nonsleeping siblings (and report faults).
-                */
-               return 0;
-       }
-
-       return (reg_val & (1u << off)) ? 1 : 0;
-}
-
-static void pca953x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val)
-{
-       struct pca953x_chip *chip;
-       uint16_t reg_val;
-       int ret, offset = 0;
-
-       chip = container_of(gc, struct pca953x_chip, gpio_chip);
-
-       mutex_lock(&chip->i2c_lock);
-       if (val)
-               reg_val = chip->reg_output | (1u << off);
-       else
-               reg_val = chip->reg_output & ~(1u << off);
-
-       switch (chip->chip_type) {
-       case PCA953X_TYPE:
-               offset = PCA953X_OUTPUT;
-               break;
-       case PCA957X_TYPE:
-               offset = PCA957X_OUT;
-               break;
-       }
-       ret = pca953x_write_reg(chip, offset, reg_val);
-       if (ret)
-               goto exit;
-
-       chip->reg_output = reg_val;
-exit:
-       mutex_unlock(&chip->i2c_lock);
-}
-
-static void pca953x_setup_gpio(struct pca953x_chip *chip, int gpios)
-{
-       struct gpio_chip *gc;
-
-       gc = &chip->gpio_chip;
-
-       gc->direction_input  = pca953x_gpio_direction_input;
-       gc->direction_output = pca953x_gpio_direction_output;
-       gc->get = pca953x_gpio_get_value;
-       gc->set = pca953x_gpio_set_value;
-       gc->can_sleep = 1;
-
-       gc->base = chip->gpio_start;
-       gc->ngpio = gpios;
-       gc->label = chip->client->name;
-       gc->dev = &chip->client->dev;
-       gc->owner = THIS_MODULE;
-       gc->names = chip->names;
-}
-
-#ifdef CONFIG_GPIO_PCA953X_IRQ
-static int pca953x_gpio_to_irq(struct gpio_chip *gc, unsigned off)
-{
-       struct pca953x_chip *chip;
-
-       chip = container_of(gc, struct pca953x_chip, gpio_chip);
-       return chip->irq_base + off;
-}
-
-static void pca953x_irq_mask(struct irq_data *d)
-{
-       struct pca953x_chip *chip = irq_data_get_irq_chip_data(d);
-
-       chip->irq_mask &= ~(1 << (d->irq - chip->irq_base));
-}
-
-static void pca953x_irq_unmask(struct irq_data *d)
-{
-       struct pca953x_chip *chip = irq_data_get_irq_chip_data(d);
-
-       chip->irq_mask |= 1 << (d->irq - chip->irq_base);
-}
-
-static void pca953x_irq_bus_lock(struct irq_data *d)
-{
-       struct pca953x_chip *chip = irq_data_get_irq_chip_data(d);
-
-       mutex_lock(&chip->irq_lock);
-}
-
-static void pca953x_irq_bus_sync_unlock(struct irq_data *d)
-{
-       struct pca953x_chip *chip = irq_data_get_irq_chip_data(d);
-       uint16_t new_irqs;
-       uint16_t level;
-
-       /* Look for any newly setup interrupt */
-       new_irqs = chip->irq_trig_fall | chip->irq_trig_raise;
-       new_irqs &= ~chip->reg_direction;
-
-       while (new_irqs) {
-               level = __ffs(new_irqs);
-               pca953x_gpio_direction_input(&chip->gpio_chip, level);
-               new_irqs &= ~(1 << level);
-       }
-
-       mutex_unlock(&chip->irq_lock);
-}
-
-static int pca953x_irq_set_type(struct irq_data *d, unsigned int type)
-{
-       struct pca953x_chip *chip = irq_data_get_irq_chip_data(d);
-       uint16_t level = d->irq - chip->irq_base;
-       uint16_t mask = 1 << level;
-
-       if (!(type & IRQ_TYPE_EDGE_BOTH)) {
-               dev_err(&chip->client->dev, "irq %d: unsupported type %d\n",
-                       d->irq, type);
-               return -EINVAL;
-       }
-
-       if (type & IRQ_TYPE_EDGE_FALLING)
-               chip->irq_trig_fall |= mask;
-       else
-               chip->irq_trig_fall &= ~mask;
-
-       if (type & IRQ_TYPE_EDGE_RISING)
-               chip->irq_trig_raise |= mask;
-       else
-               chip->irq_trig_raise &= ~mask;
-
-       return 0;
-}
-
-static struct irq_chip pca953x_irq_chip = {
-       .name                   = "pca953x",
-       .irq_mask               = pca953x_irq_mask,
-       .irq_unmask             = pca953x_irq_unmask,
-       .irq_bus_lock           = pca953x_irq_bus_lock,
-       .irq_bus_sync_unlock    = pca953x_irq_bus_sync_unlock,
-       .irq_set_type           = pca953x_irq_set_type,
-};
-
-static uint16_t pca953x_irq_pending(struct pca953x_chip *chip)
-{
-       uint16_t cur_stat;
-       uint16_t old_stat;
-       uint16_t pending;
-       uint16_t trigger;
-       int ret, offset = 0;
-
-       switch (chip->chip_type) {
-       case PCA953X_TYPE:
-               offset = PCA953X_INPUT;
-               break;
-       case PCA957X_TYPE:
-               offset = PCA957X_IN;
-               break;
-       }
-       ret = pca953x_read_reg(chip, offset, &cur_stat);
-       if (ret)
-               return 0;
-
-       /* Remove output pins from the equation */
-       cur_stat &= chip->reg_direction;
-
-       old_stat = chip->irq_stat;
-       trigger = (cur_stat ^ old_stat) & chip->irq_mask;
-
-       if (!trigger)
-               return 0;
-
-       chip->irq_stat = cur_stat;
-
-       pending = (old_stat & chip->irq_trig_fall) |
-                 (cur_stat & chip->irq_trig_raise);
-       pending &= trigger;
-
-       return pending;
-}
-
-static irqreturn_t pca953x_irq_handler(int irq, void *devid)
-{
-       struct pca953x_chip *chip = devid;
-       uint16_t pending;
-       uint16_t level;
-
-       pending = pca953x_irq_pending(chip);
-
-       if (!pending)
-               return IRQ_HANDLED;
-
-       do {
-               level = __ffs(pending);
-               generic_handle_irq(level + chip->irq_base);
-
-               pending &= ~(1 << level);
-       } while (pending);
-
-       return IRQ_HANDLED;
-}
-
-static int pca953x_irq_setup(struct pca953x_chip *chip,
-                            const struct i2c_device_id *id)
-{
-       struct i2c_client *client = chip->client;
-       struct pca953x_platform_data *pdata = client->dev.platform_data;
-       int ret, offset = 0;
-
-       if (pdata->irq_base != -1
-                       && (id->driver_data & PCA_INT)) {
-               int lvl;
-
-               switch (chip->chip_type) {
-               case PCA953X_TYPE:
-                       offset = PCA953X_INPUT;
-                       break;
-               case PCA957X_TYPE:
-                       offset = PCA957X_IN;
-                       break;
-               }
-               ret = pca953x_read_reg(chip, offset, &chip->irq_stat);
-               if (ret)
-                       goto out_failed;
-
-               /*
-                * There is no way to know which GPIO line generated the
-                * interrupt.  We have to rely on the previous read for
-                * this purpose.
-                */
-               chip->irq_stat &= chip->reg_direction;
-               chip->irq_base = pdata->irq_base;
-               mutex_init(&chip->irq_lock);
-
-               for (lvl = 0; lvl < chip->gpio_chip.ngpio; lvl++) {
-                       int irq = lvl + chip->irq_base;
-
-                       irq_set_chip_data(irq, chip);
-                       irq_set_chip_and_handler(irq, &pca953x_irq_chip,
-                                                handle_simple_irq);
-#ifdef CONFIG_ARM
-                       set_irq_flags(irq, IRQF_VALID);
-#else
-                       irq_set_noprobe(irq);
-#endif
-               }
-
-               ret = request_threaded_irq(client->irq,
-                                          NULL,
-                                          pca953x_irq_handler,
-                                          IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
-                                          dev_name(&client->dev), chip);
-               if (ret) {
-                       dev_err(&client->dev, "failed to request irq %d\n",
-                               client->irq);
-                       goto out_failed;
-               }
-
-               chip->gpio_chip.to_irq = pca953x_gpio_to_irq;
-       }
-
-       return 0;
-
-out_failed:
-       chip->irq_base = -1;
-       return ret;
-}
-
-static void pca953x_irq_teardown(struct pca953x_chip *chip)
-{
-       if (chip->irq_base != -1)
-               free_irq(chip->client->irq, chip);
-}
-#else /* CONFIG_GPIO_PCA953X_IRQ */
-static int pca953x_irq_setup(struct pca953x_chip *chip,
-                            const struct i2c_device_id *id)
-{
-       struct i2c_client *client = chip->client;
-       struct pca953x_platform_data *pdata = client->dev.platform_data;
-
-       if (pdata->irq_base != -1 && (id->driver_data & PCA_INT))
-               dev_warn(&client->dev, "interrupt support not compiled in\n");
-
-       return 0;
-}
-
-static void pca953x_irq_teardown(struct pca953x_chip *chip)
-{
-}
-#endif
-
-/*
- * Handlers for alternative sources of platform_data
- */
-#ifdef CONFIG_OF_GPIO
-/*
- * Translate OpenFirmware node properties into platform_data
- */
-static struct pca953x_platform_data *
-pca953x_get_alt_pdata(struct i2c_client *client)
-{
-       struct pca953x_platform_data *pdata;
-       struct device_node *node;
-       const __be32 *val;
-       int size;
-
-       node = client->dev.of_node;
-       if (node == NULL)
-               return NULL;
-
-       pdata = kzalloc(sizeof(struct pca953x_platform_data), GFP_KERNEL);
-       if (pdata == NULL) {
-               dev_err(&client->dev, "Unable to allocate platform_data\n");
-               return NULL;
-       }
-
-       pdata->gpio_base = -1;
-       val = of_get_property(node, "linux,gpio-base", &size);
-       if (val) {
-               if (size != sizeof(*val))
-                       dev_warn(&client->dev, "%s: wrong linux,gpio-base\n",
-                                node->full_name);
-               else
-                       pdata->gpio_base = be32_to_cpup(val);
-       }
-
-       val = of_get_property(node, "polarity", NULL);
-       if (val)
-               pdata->invert = *val;
-
-       return pdata;
-}
-#else
-static struct pca953x_platform_data *
-pca953x_get_alt_pdata(struct i2c_client *client)
-{
-       return NULL;
-}
-#endif
-
-static int __devinit device_pca953x_init(struct pca953x_chip *chip, int invert)
-{
-       int ret;
-
-       ret = pca953x_read_reg(chip, PCA953X_OUTPUT, &chip->reg_output);
-       if (ret)
-               goto out;
-
-       ret = pca953x_read_reg(chip, PCA953X_DIRECTION,
-                              &chip->reg_direction);
-       if (ret)
-               goto out;
-
-       /* set platform specific polarity inversion */
-       ret = pca953x_write_reg(chip, PCA953X_INVERT, invert);
-       if (ret)
-               goto out;
-       return 0;
-out:
-       return ret;
-}
-
-static int __devinit device_pca957x_init(struct pca953x_chip *chip, int invert)
-{
-       int ret;
-       uint16_t val = 0;
-
-       /* Let every port in proper state, that could save power */
-       pca953x_write_reg(chip, PCA957X_PUPD, 0x0);
-       pca953x_write_reg(chip, PCA957X_CFG, 0xffff);
-       pca953x_write_reg(chip, PCA957X_OUT, 0x0);
-
-       ret = pca953x_read_reg(chip, PCA957X_IN, &val);
-       if (ret)
-               goto out;
-       ret = pca953x_read_reg(chip, PCA957X_OUT, &chip->reg_output);
-       if (ret)
-               goto out;
-       ret = pca953x_read_reg(chip, PCA957X_CFG, &chip->reg_direction);
-       if (ret)
-               goto out;
-
-       /* set platform specific polarity inversion */
-       pca953x_write_reg(chip, PCA957X_INVRT, invert);
-
-       /* To enable register 6, 7 to controll pull up and pull down */
-       pca953x_write_reg(chip, PCA957X_BKEN, 0x202);
-
-       return 0;
-out:
-       return ret;
-}
-
-static int __devinit pca953x_probe(struct i2c_client *client,
-                                  const struct i2c_device_id *id)
-{
-       struct pca953x_platform_data *pdata;
-       struct pca953x_chip *chip;
-       int ret = 0;
-
-       chip = kzalloc(sizeof(struct pca953x_chip), GFP_KERNEL);
-       if (chip == NULL)
-               return -ENOMEM;
-
-       pdata = client->dev.platform_data;
-       if (pdata == NULL) {
-               pdata = pca953x_get_alt_pdata(client);
-               /*
-                * Unlike normal platform_data, this is allocated
-                * dynamically and must be freed in the driver
-                */
-               chip->dyn_pdata = pdata;
-       }
-
-       if (pdata == NULL) {
-               dev_dbg(&client->dev, "no platform data\n");
-               ret = -EINVAL;
-               goto out_failed;
-       }
-
-       chip->client = client;
-
-       chip->gpio_start = pdata->gpio_base;
-
-       chip->names = pdata->names;
-       chip->chip_type = id->driver_data & (PCA953X_TYPE | PCA957X_TYPE);
-
-       mutex_init(&chip->i2c_lock);
-
-       /* initialize cached registers from their original values.
-        * we can't share this chip with another i2c master.
-        */
-       pca953x_setup_gpio(chip, id->driver_data & PCA_GPIO_MASK);
-
-       if (chip->chip_type == PCA953X_TYPE)
-               device_pca953x_init(chip, pdata->invert);
-       else if (chip->chip_type == PCA957X_TYPE)
-               device_pca957x_init(chip, pdata->invert);
-       else
-               goto out_failed;
-
-       ret = pca953x_irq_setup(chip, id);
-       if (ret)
-               goto out_failed;
-
-       ret = gpiochip_add(&chip->gpio_chip);
-       if (ret)
-               goto out_failed_irq;
-
-       if (pdata->setup) {
-               ret = pdata->setup(client, chip->gpio_chip.base,
-                               chip->gpio_chip.ngpio, pdata->context);
-               if (ret < 0)
-                       dev_warn(&client->dev, "setup failed, %d\n", ret);
-       }
-
-       i2c_set_clientdata(client, chip);
-       return 0;
-
-out_failed_irq:
-       pca953x_irq_teardown(chip);
-out_failed:
-       kfree(chip->dyn_pdata);
-       kfree(chip);
-       return ret;
-}
-
-static int pca953x_remove(struct i2c_client *client)
-{
-       struct pca953x_platform_data *pdata = client->dev.platform_data;
-       struct pca953x_chip *chip = i2c_get_clientdata(client);
-       int ret = 0;
-
-       if (pdata->teardown) {
-               ret = pdata->teardown(client, chip->gpio_chip.base,
-                               chip->gpio_chip.ngpio, pdata->context);
-               if (ret < 0) {
-                       dev_err(&client->dev, "%s failed, %d\n",
-                                       "teardown", ret);
-                       return ret;
-               }
-       }
-
-       ret = gpiochip_remove(&chip->gpio_chip);
-       if (ret) {
-               dev_err(&client->dev, "%s failed, %d\n",
-                               "gpiochip_remove()", ret);
-               return ret;
-       }
-
-       pca953x_irq_teardown(chip);
-       kfree(chip->dyn_pdata);
-       kfree(chip);
-       return 0;
-}
-
-static struct i2c_driver pca953x_driver = {
-       .driver = {
-               .name   = "pca953x",
-       },
-       .probe          = pca953x_probe,
-       .remove         = pca953x_remove,
-       .id_table       = pca953x_id,
-};
-
-static int __init pca953x_init(void)
-{
-       return i2c_add_driver(&pca953x_driver);
-}
-/* register after i2c postcore initcall and before
- * subsys initcalls that may rely on these GPIOs
- */
-subsys_initcall(pca953x_init);
-
-static void __exit pca953x_exit(void)
-{
-       i2c_del_driver(&pca953x_driver);
-}
-module_exit(pca953x_exit);
-
-MODULE_AUTHOR("eric miao <eric.miao@marvell.com>");
-MODULE_DESCRIPTION("GPIO expander driver for PCA953x");
-MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/pcf857x.c b/drivers/gpio/pcf857x.c
deleted file mode 100644 (file)
index 879b473..0000000
+++ /dev/null
@@ -1,369 +0,0 @@
-/*
- * pcf857x - driver for pcf857x, pca857x, and pca967x I2C GPIO expanders
- *
- * Copyright (C) 2007 David Brownell
- *
- * 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.
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * 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>
-
-
-static const struct i2c_device_id pcf857x_id[] = {
-       { "pcf8574", 8 },
-       { "pcf8574a", 8 },
-       { "pca8574", 8 },
-       { "pca9670", 8 },
-       { "pca9672", 8 },
-       { "pca9674", 8 },
-       { "pcf8575", 16 },
-       { "pca8575", 16 },
-       { "pca9671", 16 },
-       { "pca9673", 16 },
-       { "pca9675", 16 },
-       { "max7328", 8 },
-       { "max7329", 8 },
-       { }
-};
-MODULE_DEVICE_TABLE(i2c, pcf857x_id);
-
-/*
- * The pcf857x, pca857x, and pca967x chips only expose one read and one
- * write register.  Writing a "one" bit (to match the reset state) lets
- * that pin be used as an input; it's not an open-drain model, but acts
- * a bit like one.  This is described as "quasi-bidirectional"; read the
- * chip documentation for details.
- *
- * Many other I2C GPIO expander chips (like the pca953x models) have
- * more complex register models and more conventional circuitry using
- * push/pull drivers.  They often use the same 0x20..0x27 addresses as
- * pcf857x parts, making the "legacy" I2C driver model problematic.
- */
-struct pcf857x {
-       struct gpio_chip        chip;
-       struct i2c_client       *client;
-       struct mutex            lock;           /* protect 'out' */
-       unsigned                out;            /* software latch */
-};
-
-/*-------------------------------------------------------------------------*/
-
-/* Talk to 8-bit I/O expander */
-
-static int pcf857x_input8(struct gpio_chip *chip, unsigned offset)
-{
-       struct pcf857x  *gpio = container_of(chip, struct pcf857x, chip);
-       int             status;
-
-       mutex_lock(&gpio->lock);
-       gpio->out |= (1 << offset);
-       status = i2c_smbus_write_byte(gpio->client, gpio->out);
-       mutex_unlock(&gpio->lock);
-
-       return status;
-}
-
-static int pcf857x_get8(struct gpio_chip *chip, unsigned offset)
-{
-       struct pcf857x  *gpio = container_of(chip, struct pcf857x, chip);
-       s32             value;
-
-       value = i2c_smbus_read_byte(gpio->client);
-       return (value < 0) ? 0 : (value & (1 << offset));
-}
-
-static int pcf857x_output8(struct gpio_chip *chip, unsigned offset, int value)
-{
-       struct pcf857x  *gpio = container_of(chip, struct pcf857x, chip);
-       unsigned        bit = 1 << offset;
-       int             status;
-
-       mutex_lock(&gpio->lock);
-       if (value)
-               gpio->out |= bit;
-       else
-               gpio->out &= ~bit;
-       status = i2c_smbus_write_byte(gpio->client, gpio->out);
-       mutex_unlock(&gpio->lock);
-
-       return status;
-}
-
-static void pcf857x_set8(struct gpio_chip *chip, unsigned offset, int value)
-{
-       pcf857x_output8(chip, offset, value);
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* Talk to 16-bit I/O expander */
-
-static int i2c_write_le16(struct i2c_client *client, u16 word)
-{
-       u8 buf[2] = { word & 0xff, word >> 8, };
-       int status;
-
-       status = i2c_master_send(client, buf, 2);
-       return (status < 0) ? status : 0;
-}
-
-static int i2c_read_le16(struct i2c_client *client)
-{
-       u8 buf[2];
-       int status;
-
-       status = i2c_master_recv(client, buf, 2);
-       if (status < 0)
-               return status;
-       return (buf[1] << 8) | buf[0];
-}
-
-static int pcf857x_input16(struct gpio_chip *chip, unsigned offset)
-{
-       struct pcf857x  *gpio = container_of(chip, struct pcf857x, chip);
-       int             status;
-
-       mutex_lock(&gpio->lock);
-       gpio->out |= (1 << offset);
-       status = i2c_write_le16(gpio->client, gpio->out);
-       mutex_unlock(&gpio->lock);
-
-       return status;
-}
-
-static int pcf857x_get16(struct gpio_chip *chip, unsigned offset)
-{
-       struct pcf857x  *gpio = container_of(chip, struct pcf857x, chip);
-       int             value;
-
-       value = i2c_read_le16(gpio->client);
-       return (value < 0) ? 0 : (value & (1 << offset));
-}
-
-static int pcf857x_output16(struct gpio_chip *chip, unsigned offset, int value)
-{
-       struct pcf857x  *gpio = container_of(chip, struct pcf857x, chip);
-       unsigned        bit = 1 << offset;
-       int             status;
-
-       mutex_lock(&gpio->lock);
-       if (value)
-               gpio->out |= bit;
-       else
-               gpio->out &= ~bit;
-       status = i2c_write_le16(gpio->client, gpio->out);
-       mutex_unlock(&gpio->lock);
-
-       return status;
-}
-
-static void pcf857x_set16(struct gpio_chip *chip, unsigned offset, int value)
-{
-       pcf857x_output16(chip, offset, value);
-}
-
-/*-------------------------------------------------------------------------*/
-
-static int pcf857x_probe(struct i2c_client *client,
-                        const struct i2c_device_id *id)
-{
-       struct pcf857x_platform_data    *pdata;
-       struct pcf857x                  *gpio;
-       int                             status;
-
-       pdata = client->dev.platform_data;
-       if (!pdata) {
-               dev_dbg(&client->dev, "no platform data\n");
-       }
-
-       /* Allocate, initialize, and register this gpio_chip. */
-       gpio = kzalloc(sizeof *gpio, GFP_KERNEL);
-       if (!gpio)
-               return -ENOMEM;
-
-       mutex_init(&gpio->lock);
-
-       gpio->chip.base = pdata ? pdata->gpio_base : -1;
-       gpio->chip.can_sleep = 1;
-       gpio->chip.dev = &client->dev;
-       gpio->chip.owner = THIS_MODULE;
-
-       /* NOTE:  the OnSemi jlc1562b is also largely compatible with
-        * these parts, notably for output.  It has a low-resolution
-        * DAC instead of pin change IRQs; and its inputs can be the
-        * result of comparators.
-        */
-
-       /* 8574 addresses are 0x20..0x27; 8574a uses 0x38..0x3f;
-        * 9670, 9672, 9764, and 9764a use quite a variety.
-        *
-        * NOTE: we don't distinguish here between *4 and *4a parts.
-        */
-       gpio->chip.ngpio = id->driver_data;
-       if (gpio->chip.ngpio == 8) {
-               gpio->chip.direction_input = pcf857x_input8;
-               gpio->chip.get = pcf857x_get8;
-               gpio->chip.direction_output = pcf857x_output8;
-               gpio->chip.set = pcf857x_set8;
-
-               if (!i2c_check_functionality(client->adapter,
-                               I2C_FUNC_SMBUS_BYTE))
-                       status = -EIO;
-
-               /* fail if there's no chip present */
-               else
-                       status = i2c_smbus_read_byte(client);
-
-       /* '75/'75c addresses are 0x20..0x27, just like the '74;
-        * the '75c doesn't have a current source pulling high.
-        * 9671, 9673, and 9765 use quite a variety of addresses.
-        *
-        * NOTE: we don't distinguish here between '75 and '75c parts.
-        */
-       } else if (gpio->chip.ngpio == 16) {
-               gpio->chip.direction_input = pcf857x_input16;
-               gpio->chip.get = pcf857x_get16;
-               gpio->chip.direction_output = pcf857x_output16;
-               gpio->chip.set = pcf857x_set16;
-
-               if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
-                       status = -EIO;
-
-               /* fail if there's no chip present */
-               else
-                       status = i2c_read_le16(client);
-
-       } else {
-               dev_dbg(&client->dev, "unsupported number of gpios\n");
-               status = -EINVAL;
-       }
-
-       if (status < 0)
-               goto fail;
-
-       gpio->chip.label = client->name;
-
-       gpio->client = client;
-       i2c_set_clientdata(client, gpio);
-
-       /* NOTE:  these chips have strange "quasi-bidirectional" I/O pins.
-        * We can't actually know whether a pin is configured (a) as output
-        * and driving the signal low, or (b) as input and reporting a low
-        * value ... without knowing the last value written since the chip
-        * came out of reset (if any).  We can't read the latched output.
-        *
-        * In short, the only reliable solution for setting up pin direction
-        * is to do it explicitly.  The setup() method can do that, but it
-        * may cause transient glitching since it can't know the last value
-        * written (some pins may need to be driven low).
-        *
-        * Using pdata->n_latch avoids that trouble.  When left initialized
-        * to zero, our software copy of the "latch" then matches the chip's
-        * all-ones reset state.  Otherwise it flags pins to be driven low.
-        */
-       gpio->out = pdata ? ~pdata->n_latch : ~0;
-
-       status = gpiochip_add(&gpio->chip);
-       if (status < 0)
-               goto fail;
-
-       /* NOTE: these chips can issue "some pin-changed" IRQs, which we
-        * don't yet even try to use.  Among other issues, the relevant
-        * genirq state isn't available to modular drivers; and most irq
-        * methods can't be called from sleeping contexts.
-        */
-
-       dev_info(&client->dev, "gpios %d..%d on a %s%s\n",
-                       gpio->chip.base,
-                       gpio->chip.base + gpio->chip.ngpio - 1,
-                       client->name,
-                       client->irq ? " (irq ignored)" : "");
-
-       /* Let platform code set up the GPIOs and their users.
-        * Now is the first time anyone could use them.
-        */
-       if (pdata && pdata->setup) {
-               status = pdata->setup(client,
-                               gpio->chip.base, gpio->chip.ngpio,
-                               pdata->context);
-               if (status < 0)
-                       dev_warn(&client->dev, "setup --> %d\n", status);
-       }
-
-       return 0;
-
-fail:
-       dev_dbg(&client->dev, "probe error %d for '%s'\n",
-                       status, client->name);
-       kfree(gpio);
-       return status;
-}
-
-static int pcf857x_remove(struct i2c_client *client)
-{
-       struct pcf857x_platform_data    *pdata = client->dev.platform_data;
-       struct pcf857x                  *gpio = i2c_get_clientdata(client);
-       int                             status = 0;
-
-       if (pdata && pdata->teardown) {
-               status = pdata->teardown(client,
-                               gpio->chip.base, gpio->chip.ngpio,
-                               pdata->context);
-               if (status < 0) {
-                       dev_err(&client->dev, "%s --> %d\n",
-                                       "teardown", status);
-                       return status;
-               }
-       }
-
-       status = gpiochip_remove(&gpio->chip);
-       if (status == 0)
-               kfree(gpio);
-       else
-               dev_err(&client->dev, "%s --> %d\n", "remove", status);
-       return status;
-}
-
-static struct i2c_driver pcf857x_driver = {
-       .driver = {
-               .name   = "pcf857x",
-               .owner  = THIS_MODULE,
-       },
-       .probe  = pcf857x_probe,
-       .remove = pcf857x_remove,
-       .id_table = pcf857x_id,
-};
-
-static int __init pcf857x_init(void)
-{
-       return i2c_add_driver(&pcf857x_driver);
-}
-/* register after i2c postcore initcall and before
- * subsys initcalls that may rely on these GPIOs
- */
-subsys_initcall(pcf857x_init);
-
-static void __exit pcf857x_exit(void)
-{
-       i2c_del_driver(&pcf857x_driver);
-}
-module_exit(pcf857x_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("David Brownell");
diff --git a/drivers/gpio/pch_gpio.c b/drivers/gpio/pch_gpio.c
deleted file mode 100644 (file)
index 36919e7..0000000
+++ /dev/null
@@ -1,316 +0,0 @@
-/*
- * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD.
- *
- * 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; version 2 of the License.
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
- */
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/gpio.h>
-
-#define PCH_GPIO_ALL_PINS      0xfff /* Mask for GPIO pins 0 to 11 */
-#define GPIO_NUM_PINS  12      /* Specifies number of GPIO PINS GPIO0-GPIO11 */
-
-struct pch_regs {
-       u32     ien;
-       u32     istatus;
-       u32     idisp;
-       u32     iclr;
-       u32     imask;
-       u32     imaskclr;
-       u32     po;
-       u32     pi;
-       u32     pm;
-       u32     im0;
-       u32     im1;
-       u32     reserved[4];
-       u32     reset;
-};
-
-/**
- * struct pch_gpio_reg_data - The register store data.
- * @po_reg:    To store contents of PO register.
- * @pm_reg:    To store contents of PM register.
- */
-struct pch_gpio_reg_data {
-       u32 po_reg;
-       u32 pm_reg;
-};
-
-/**
- * struct pch_gpio - GPIO private data structure.
- * @base:                      PCI base address of Memory mapped I/O register.
- * @reg:                       Memory mapped PCH GPIO register list.
- * @dev:                       Pointer to device structure.
- * @gpio:                      Data for GPIO infrastructure.
- * @pch_gpio_reg:              Memory mapped Register data is saved here
- *                             when suspend.
- */
-struct pch_gpio {
-       void __iomem *base;
-       struct pch_regs __iomem *reg;
-       struct device *dev;
-       struct gpio_chip gpio;
-       struct pch_gpio_reg_data pch_gpio_reg;
-       struct mutex lock;
-};
-
-static void pch_gpio_set(struct gpio_chip *gpio, unsigned nr, int val)
-{
-       u32 reg_val;
-       struct pch_gpio *chip = container_of(gpio, struct pch_gpio, gpio);
-
-       mutex_lock(&chip->lock);
-       reg_val = ioread32(&chip->reg->po);
-       if (val)
-               reg_val |= (1 << nr);
-       else
-               reg_val &= ~(1 << nr);
-
-       iowrite32(reg_val, &chip->reg->po);
-       mutex_unlock(&chip->lock);
-}
-
-static int pch_gpio_get(struct gpio_chip *gpio, unsigned nr)
-{
-       struct pch_gpio *chip = container_of(gpio, struct pch_gpio, gpio);
-
-       return ioread32(&chip->reg->pi) & (1 << nr);
-}
-
-static int pch_gpio_direction_output(struct gpio_chip *gpio, unsigned nr,
-                                    int val)
-{
-       struct pch_gpio *chip = container_of(gpio, struct pch_gpio, gpio);
-       u32 pm;
-       u32 reg_val;
-
-       mutex_lock(&chip->lock);
-       pm = ioread32(&chip->reg->pm) & PCH_GPIO_ALL_PINS;
-       pm |= (1 << nr);
-       iowrite32(pm, &chip->reg->pm);
-
-       reg_val = ioread32(&chip->reg->po);
-       if (val)
-               reg_val |= (1 << nr);
-       else
-               reg_val &= ~(1 << nr);
-       iowrite32(reg_val, &chip->reg->po);
-
-       mutex_unlock(&chip->lock);
-
-       return 0;
-}
-
-static int pch_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
-{
-       struct pch_gpio *chip = container_of(gpio, struct pch_gpio, gpio);
-       u32 pm;
-
-       mutex_lock(&chip->lock);
-       pm = ioread32(&chip->reg->pm) & PCH_GPIO_ALL_PINS; /*bits 0-11*/
-       pm &= ~(1 << nr);
-       iowrite32(pm, &chip->reg->pm);
-       mutex_unlock(&chip->lock);
-
-       return 0;
-}
-
-/*
- * Save register configuration and disable interrupts.
- */
-static void pch_gpio_save_reg_conf(struct pch_gpio *chip)
-{
-       chip->pch_gpio_reg.po_reg = ioread32(&chip->reg->po);
-       chip->pch_gpio_reg.pm_reg = ioread32(&chip->reg->pm);
-}
-
-/*
- * This function restores the register configuration of the GPIO device.
- */
-static void pch_gpio_restore_reg_conf(struct pch_gpio *chip)
-{
-       /* to store contents of PO register */
-       iowrite32(chip->pch_gpio_reg.po_reg, &chip->reg->po);
-       /* to store contents of PM register */
-       iowrite32(chip->pch_gpio_reg.pm_reg, &chip->reg->pm);
-}
-
-static void pch_gpio_setup(struct pch_gpio *chip)
-{
-       struct gpio_chip *gpio = &chip->gpio;
-
-       gpio->label = dev_name(chip->dev);
-       gpio->owner = THIS_MODULE;
-       gpio->direction_input = pch_gpio_direction_input;
-       gpio->get = pch_gpio_get;
-       gpio->direction_output = pch_gpio_direction_output;
-       gpio->set = pch_gpio_set;
-       gpio->dbg_show = NULL;
-       gpio->base = -1;
-       gpio->ngpio = GPIO_NUM_PINS;
-       gpio->can_sleep = 0;
-}
-
-static int __devinit pch_gpio_probe(struct pci_dev *pdev,
-                                   const struct pci_device_id *id)
-{
-       s32 ret;
-       struct pch_gpio *chip;
-
-       chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-       if (chip == NULL)
-               return -ENOMEM;
-
-       chip->dev = &pdev->dev;
-       ret = pci_enable_device(pdev);
-       if (ret) {
-               dev_err(&pdev->dev, "%s : pci_enable_device FAILED", __func__);
-               goto err_pci_enable;
-       }
-
-       ret = pci_request_regions(pdev, KBUILD_MODNAME);
-       if (ret) {
-               dev_err(&pdev->dev, "pci_request_regions FAILED-%d", ret);
-               goto err_request_regions;
-       }
-
-       chip->base = pci_iomap(pdev, 1, 0);
-       if (chip->base == 0) {
-               dev_err(&pdev->dev, "%s : pci_iomap FAILED", __func__);
-               ret = -ENOMEM;
-               goto err_iomap;
-       }
-
-       chip->reg = chip->base;
-       pci_set_drvdata(pdev, chip);
-       mutex_init(&chip->lock);
-       pch_gpio_setup(chip);
-       ret = gpiochip_add(&chip->gpio);
-       if (ret) {
-               dev_err(&pdev->dev, "PCH gpio: Failed to register GPIO\n");
-               goto err_gpiochip_add;
-       }
-
-       return 0;
-
-err_gpiochip_add:
-       pci_iounmap(pdev, chip->base);
-
-err_iomap:
-       pci_release_regions(pdev);
-
-err_request_regions:
-       pci_disable_device(pdev);
-
-err_pci_enable:
-       kfree(chip);
-       dev_err(&pdev->dev, "%s Failed returns %d\n", __func__, ret);
-       return ret;
-}
-
-static void __devexit pch_gpio_remove(struct pci_dev *pdev)
-{
-       int err;
-       struct pch_gpio *chip = pci_get_drvdata(pdev);
-
-       err = gpiochip_remove(&chip->gpio);
-       if (err)
-               dev_err(&pdev->dev, "Failed gpiochip_remove\n");
-
-       pci_iounmap(pdev, chip->base);
-       pci_release_regions(pdev);
-       pci_disable_device(pdev);
-       kfree(chip);
-}
-
-#ifdef CONFIG_PM
-static int pch_gpio_suspend(struct pci_dev *pdev, pm_message_t state)
-{
-       s32 ret;
-       struct pch_gpio *chip = pci_get_drvdata(pdev);
-
-       pch_gpio_save_reg_conf(chip);
-       pch_gpio_restore_reg_conf(chip);
-
-       ret = pci_save_state(pdev);
-       if (ret) {
-               dev_err(&pdev->dev, "pci_save_state Failed-%d\n", ret);
-               return ret;
-       }
-       pci_disable_device(pdev);
-       pci_set_power_state(pdev, PCI_D0);
-       ret = pci_enable_wake(pdev, PCI_D0, 1);
-       if (ret)
-               dev_err(&pdev->dev, "pci_enable_wake Failed -%d\n", ret);
-
-       return 0;
-}
-
-static int pch_gpio_resume(struct pci_dev *pdev)
-{
-       s32 ret;
-       struct pch_gpio *chip = pci_get_drvdata(pdev);
-
-       ret = pci_enable_wake(pdev, PCI_D0, 0);
-
-       pci_set_power_state(pdev, PCI_D0);
-       ret = pci_enable_device(pdev);
-       if (ret) {
-               dev_err(&pdev->dev, "pci_enable_device Failed-%d ", ret);
-               return ret;
-       }
-       pci_restore_state(pdev);
-
-       iowrite32(0x01, &chip->reg->reset);
-       iowrite32(0x00, &chip->reg->reset);
-       pch_gpio_restore_reg_conf(chip);
-
-       return 0;
-}
-#else
-#define pch_gpio_suspend NULL
-#define pch_gpio_resume NULL
-#endif
-
-#define PCI_VENDOR_ID_ROHM             0x10DB
-static DEFINE_PCI_DEVICE_TABLE(pch_gpio_pcidev_id) = {
-       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8803) },
-       { PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8014) },
-       { 0, }
-};
-MODULE_DEVICE_TABLE(pci, pch_gpio_pcidev_id);
-
-static struct pci_driver pch_gpio_driver = {
-       .name = "pch_gpio",
-       .id_table = pch_gpio_pcidev_id,
-       .probe = pch_gpio_probe,
-       .remove = __devexit_p(pch_gpio_remove),
-       .suspend = pch_gpio_suspend,
-       .resume = pch_gpio_resume
-};
-
-static int __init pch_gpio_pci_init(void)
-{
-       return pci_register_driver(&pch_gpio_driver);
-}
-module_init(pch_gpio_pci_init);
-
-static void __exit pch_gpio_pci_exit(void)
-{
-       pci_unregister_driver(&pch_gpio_driver);
-}
-module_exit(pch_gpio_pci_exit);
-
-MODULE_DESCRIPTION("PCH GPIO PCI Driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/pl061.c b/drivers/gpio/pl061.c
deleted file mode 100644 (file)
index 6fcb28c..0000000
+++ /dev/null
@@ -1,360 +0,0 @@
-/*
- *  linux/drivers/gpio/pl061.c
- *
- *  Copyright (C) 2008, 2009 Provigent 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.
- *
- * Driver for the ARM PrimeCell(tm) General Purpose Input/Output (PL061)
- *
- * Data sheet: ARM DDI 0190B, September 2000
- */
-#include <linux/spinlock.h>
-#include <linux/errno.h>
-#include <linux/module.h>
-#include <linux/list.h>
-#include <linux/io.h>
-#include <linux/ioport.h>
-#include <linux/irq.h>
-#include <linux/bitops.h>
-#include <linux/workqueue.h>
-#include <linux/gpio.h>
-#include <linux/device.h>
-#include <linux/amba/bus.h>
-#include <linux/amba/pl061.h>
-#include <linux/slab.h>
-
-#define GPIODIR 0x400
-#define GPIOIS  0x404
-#define GPIOIBE 0x408
-#define GPIOIEV 0x40C
-#define GPIOIE  0x410
-#define GPIORIS 0x414
-#define GPIOMIS 0x418
-#define GPIOIC  0x41C
-
-#define PL061_GPIO_NR  8
-
-struct pl061_gpio {
-       /* We use a list of pl061_gpio structs for each trigger IRQ in the main
-        * interrupts controller of the system. We need this to support systems
-        * in which more that one PL061s are connected to the same IRQ. The ISR
-        * interates through this list to find the source of the interrupt.
-        */
-       struct list_head        list;
-
-       /* Each of the two spinlocks protects a different set of hardware
-        * regiters and data structurs. This decouples the code of the IRQ from
-        * the GPIO code. This also makes the case of a GPIO routine call from
-        * the IRQ code simpler.
-        */
-       spinlock_t              lock;           /* GPIO registers */
-       spinlock_t              irq_lock;       /* IRQ registers */
-
-       void __iomem            *base;
-       unsigned                irq_base;
-       struct gpio_chip        gc;
-};
-
-static int pl061_direction_input(struct gpio_chip *gc, unsigned offset)
-{
-       struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
-       unsigned long flags;
-       unsigned char gpiodir;
-
-       if (offset >= gc->ngpio)
-               return -EINVAL;
-
-       spin_lock_irqsave(&chip->lock, flags);
-       gpiodir = readb(chip->base + GPIODIR);
-       gpiodir &= ~(1 << offset);
-       writeb(gpiodir, chip->base + GPIODIR);
-       spin_unlock_irqrestore(&chip->lock, flags);
-
-       return 0;
-}
-
-static int pl061_direction_output(struct gpio_chip *gc, unsigned offset,
-               int value)
-{
-       struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
-       unsigned long flags;
-       unsigned char gpiodir;
-
-       if (offset >= gc->ngpio)
-               return -EINVAL;
-
-       spin_lock_irqsave(&chip->lock, flags);
-       writeb(!!value << offset, chip->base + (1 << (offset + 2)));
-       gpiodir = readb(chip->base + GPIODIR);
-       gpiodir |= 1 << offset;
-       writeb(gpiodir, chip->base + GPIODIR);
-
-       /*
-        * gpio value is set again, because pl061 doesn't allow to set value of
-        * a gpio pin before configuring it in OUT mode.
-        */
-       writeb(!!value << offset, chip->base + (1 << (offset + 2)));
-       spin_unlock_irqrestore(&chip->lock, flags);
-
-       return 0;
-}
-
-static int pl061_get_value(struct gpio_chip *gc, unsigned offset)
-{
-       struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
-
-       return !!readb(chip->base + (1 << (offset + 2)));
-}
-
-static void pl061_set_value(struct gpio_chip *gc, unsigned offset, int value)
-{
-       struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
-
-       writeb(!!value << offset, chip->base + (1 << (offset + 2)));
-}
-
-static int pl061_to_irq(struct gpio_chip *gc, unsigned offset)
-{
-       struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
-
-       if (chip->irq_base == (unsigned) -1)
-               return -EINVAL;
-
-       return chip->irq_base + offset;
-}
-
-/*
- * PL061 GPIO IRQ
- */
-static void pl061_irq_disable(struct irq_data *d)
-{
-       struct pl061_gpio *chip = irq_data_get_irq_chip_data(d);
-       int offset = d->irq - chip->irq_base;
-       unsigned long flags;
-       u8 gpioie;
-
-       spin_lock_irqsave(&chip->irq_lock, flags);
-       gpioie = readb(chip->base + GPIOIE);
-       gpioie &= ~(1 << offset);
-       writeb(gpioie, chip->base + GPIOIE);
-       spin_unlock_irqrestore(&chip->irq_lock, flags);
-}
-
-static void pl061_irq_enable(struct irq_data *d)
-{
-       struct pl061_gpio *chip = irq_data_get_irq_chip_data(d);
-       int offset = d->irq - chip->irq_base;
-       unsigned long flags;
-       u8 gpioie;
-
-       spin_lock_irqsave(&chip->irq_lock, flags);
-       gpioie = readb(chip->base + GPIOIE);
-       gpioie |= 1 << offset;
-       writeb(gpioie, chip->base + GPIOIE);
-       spin_unlock_irqrestore(&chip->irq_lock, flags);
-}
-
-static int pl061_irq_type(struct irq_data *d, unsigned trigger)
-{
-       struct pl061_gpio *chip = irq_data_get_irq_chip_data(d);
-       int offset = d->irq - chip->irq_base;
-       unsigned long flags;
-       u8 gpiois, gpioibe, gpioiev;
-
-       if (offset < 0 || offset >= PL061_GPIO_NR)
-               return -EINVAL;
-
-       spin_lock_irqsave(&chip->irq_lock, flags);
-
-       gpioiev = readb(chip->base + GPIOIEV);
-
-       gpiois = readb(chip->base + GPIOIS);
-       if (trigger & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {
-               gpiois |= 1 << offset;
-               if (trigger & IRQ_TYPE_LEVEL_HIGH)
-                       gpioiev |= 1 << offset;
-               else
-                       gpioiev &= ~(1 << offset);
-       } else
-               gpiois &= ~(1 << offset);
-       writeb(gpiois, chip->base + GPIOIS);
-
-       gpioibe = readb(chip->base + GPIOIBE);
-       if ((trigger & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH)
-               gpioibe |= 1 << offset;
-       else {
-               gpioibe &= ~(1 << offset);
-               if (trigger & IRQ_TYPE_EDGE_RISING)
-                       gpioiev |= 1 << offset;
-               else if (trigger & IRQ_TYPE_EDGE_FALLING)
-                       gpioiev &= ~(1 << offset);
-       }
-       writeb(gpioibe, chip->base + GPIOIBE);
-
-       writeb(gpioiev, chip->base + GPIOIEV);
-
-       spin_unlock_irqrestore(&chip->irq_lock, flags);
-
-       return 0;
-}
-
-static struct irq_chip pl061_irqchip = {
-       .name           = "GPIO",
-       .irq_enable     = pl061_irq_enable,
-       .irq_disable    = pl061_irq_disable,
-       .irq_set_type   = pl061_irq_type,
-};
-
-static void pl061_irq_handler(unsigned irq, struct irq_desc *desc)
-{
-       struct list_head *chip_list = irq_get_handler_data(irq);
-       struct list_head *ptr;
-       struct pl061_gpio *chip;
-
-       desc->irq_data.chip->irq_ack(&desc->irq_data);
-       list_for_each(ptr, chip_list) {
-               unsigned long pending;
-               int offset;
-
-               chip = list_entry(ptr, struct pl061_gpio, list);
-               pending = readb(chip->base + GPIOMIS);
-               writeb(pending, chip->base + GPIOIC);
-
-               if (pending == 0)
-                       continue;
-
-               for_each_set_bit(offset, &pending, PL061_GPIO_NR)
-                       generic_handle_irq(pl061_to_irq(&chip->gc, offset));
-       }
-       desc->irq_data.chip->irq_unmask(&desc->irq_data);
-}
-
-static int pl061_probe(struct amba_device *dev, const struct amba_id *id)
-{
-       struct pl061_platform_data *pdata;
-       struct pl061_gpio *chip;
-       struct list_head *chip_list;
-       int ret, irq, i;
-       static DECLARE_BITMAP(init_irq, NR_IRQS);
-
-       pdata = dev->dev.platform_data;
-       if (pdata == NULL)
-               return -ENODEV;
-
-       chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-       if (chip == NULL)
-               return -ENOMEM;
-
-       if (!request_mem_region(dev->res.start,
-                               resource_size(&dev->res), "pl061")) {
-               ret = -EBUSY;
-               goto free_mem;
-       }
-
-       chip->base = ioremap(dev->res.start, resource_size(&dev->res));
-       if (chip->base == NULL) {
-               ret = -ENOMEM;
-               goto release_region;
-       }
-
-       spin_lock_init(&chip->lock);
-       spin_lock_init(&chip->irq_lock);
-       INIT_LIST_HEAD(&chip->list);
-
-       chip->gc.direction_input = pl061_direction_input;
-       chip->gc.direction_output = pl061_direction_output;
-       chip->gc.get = pl061_get_value;
-       chip->gc.set = pl061_set_value;
-       chip->gc.to_irq = pl061_to_irq;
-       chip->gc.base = pdata->gpio_base;
-       chip->gc.ngpio = PL061_GPIO_NR;
-       chip->gc.label = dev_name(&dev->dev);
-       chip->gc.dev = &dev->dev;
-       chip->gc.owner = THIS_MODULE;
-
-       chip->irq_base = pdata->irq_base;
-
-       ret = gpiochip_add(&chip->gc);
-       if (ret)
-               goto iounmap;
-
-       /*
-        * irq_chip support
-        */
-
-       if (chip->irq_base == (unsigned) -1)
-               return 0;
-
-       writeb(0, chip->base + GPIOIE); /* disable irqs */
-       irq = dev->irq[0];
-       if (irq < 0) {
-               ret = -ENODEV;
-               goto iounmap;
-       }
-       irq_set_chained_handler(irq, pl061_irq_handler);
-       if (!test_and_set_bit(irq, init_irq)) { /* list initialized? */
-               chip_list = kmalloc(sizeof(*chip_list), GFP_KERNEL);
-               if (chip_list == NULL) {
-                       clear_bit(irq, init_irq);
-                       ret = -ENOMEM;
-                       goto iounmap;
-               }
-               INIT_LIST_HEAD(chip_list);
-               irq_set_handler_data(irq, chip_list);
-       } else
-               chip_list = irq_get_handler_data(irq);
-       list_add(&chip->list, chip_list);
-
-       for (i = 0; i < PL061_GPIO_NR; i++) {
-               if (pdata->directions & (1 << i))
-                       pl061_direction_output(&chip->gc, i,
-                                       pdata->values & (1 << i));
-               else
-                       pl061_direction_input(&chip->gc, i);
-
-               irq_set_chip_and_handler(i + chip->irq_base, &pl061_irqchip,
-                                        handle_simple_irq);
-               set_irq_flags(i+chip->irq_base, IRQF_VALID);
-               irq_set_chip_data(i + chip->irq_base, chip);
-       }
-
-       return 0;
-
-iounmap:
-       iounmap(chip->base);
-release_region:
-       release_mem_region(dev->res.start, resource_size(&dev->res));
-free_mem:
-       kfree(chip);
-
-       return ret;
-}
-
-static struct amba_id pl061_ids[] = {
-       {
-               .id     = 0x00041061,
-               .mask   = 0x000fffff,
-       },
-       { 0, 0 },
-};
-
-static struct amba_driver pl061_gpio_driver = {
-       .drv = {
-               .name   = "pl061_gpio",
-       },
-       .id_table       = pl061_ids,
-       .probe          = pl061_probe,
-};
-
-static int __init pl061_gpio_init(void)
-{
-       return amba_driver_register(&pl061_gpio_driver);
-}
-subsys_initcall(pl061_gpio_init);
-
-MODULE_AUTHOR("Baruch Siach <baruch@tkos.co.il>");
-MODULE_DESCRIPTION("PL061 GPIO driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/rdc321x-gpio.c b/drivers/gpio/rdc321x-gpio.c
deleted file mode 100644 (file)
index 2762698..0000000
+++ /dev/null
@@ -1,246 +0,0 @@
-/*
- * RDC321x GPIO driver
- *
- * Copyright (C) 2008, Volker Weiss <dev@tintuc.de>
- * Copyright (C) 2007-2010 Florian Fainelli <florian@openwrt.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.
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/spinlock.h>
-#include <linux/platform_device.h>
-#include <linux/pci.h>
-#include <linux/gpio.h>
-#include <linux/mfd/rdc321x.h>
-#include <linux/slab.h>
-
-struct rdc321x_gpio {
-       spinlock_t              lock;
-       struct pci_dev          *sb_pdev;
-       u32                     data_reg[2];
-       int                     reg1_ctrl_base;
-       int                     reg1_data_base;
-       int                     reg2_ctrl_base;
-       int                     reg2_data_base;
-       struct gpio_chip        chip;
-};
-
-/* read GPIO pin */
-static int rdc_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
-{
-       struct rdc321x_gpio *gpch;
-       u32 value = 0;
-       int reg;
-
-       gpch = container_of(chip, struct rdc321x_gpio, chip);
-       reg = gpio < 32 ? gpch->reg1_data_base : gpch->reg2_data_base;
-
-       spin_lock(&gpch->lock);
-       pci_write_config_dword(gpch->sb_pdev, reg,
-                                       gpch->data_reg[gpio < 32 ? 0 : 1]);
-       pci_read_config_dword(gpch->sb_pdev, reg, &value);
-       spin_unlock(&gpch->lock);
-
-       return (1 << (gpio & 0x1f)) & value ? 1 : 0;
-}
-
-static void rdc_gpio_set_value_impl(struct gpio_chip *chip,
-                               unsigned gpio, int value)
-{
-       struct rdc321x_gpio *gpch;
-       int reg = (gpio < 32) ? 0 : 1;
-
-       gpch = container_of(chip, struct rdc321x_gpio, chip);
-
-       if (value)
-               gpch->data_reg[reg] |= 1 << (gpio & 0x1f);
-       else
-               gpch->data_reg[reg] &= ~(1 << (gpio & 0x1f));
-
-       pci_write_config_dword(gpch->sb_pdev,
-                       reg ? gpch->reg2_data_base : gpch->reg1_data_base,
-                       gpch->data_reg[reg]);
-}
-
-/* set GPIO pin to value */
-static void rdc_gpio_set_value(struct gpio_chip *chip,
-                               unsigned gpio, int value)
-{
-       struct rdc321x_gpio *gpch;
-
-       gpch = container_of(chip, struct rdc321x_gpio, chip);
-       spin_lock(&gpch->lock);
-       rdc_gpio_set_value_impl(chip, gpio, value);
-       spin_unlock(&gpch->lock);
-}
-
-static int rdc_gpio_config(struct gpio_chip *chip,
-                               unsigned gpio, int value)
-{
-       struct rdc321x_gpio *gpch;
-       int err;
-       u32 reg;
-
-       gpch = container_of(chip, struct rdc321x_gpio, chip);
-
-       spin_lock(&gpch->lock);
-       err = pci_read_config_dword(gpch->sb_pdev, gpio < 32 ?
-                       gpch->reg1_ctrl_base : gpch->reg2_ctrl_base, &reg);
-       if (err)
-               goto unlock;
-
-       reg |= 1 << (gpio & 0x1f);
-
-       err = pci_write_config_dword(gpch->sb_pdev, gpio < 32 ?
-                       gpch->reg1_ctrl_base : gpch->reg2_ctrl_base, reg);
-       if (err)
-               goto unlock;
-
-       rdc_gpio_set_value_impl(chip, gpio, value);
-
-unlock:
-       spin_unlock(&gpch->lock);
-
-       return err;
-}
-
-/* configure GPIO pin as input */
-static int rdc_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
-{
-       return rdc_gpio_config(chip, gpio, 1);
-}
-
-/*
- * Cache the initial value of both GPIO data registers
- */
-static int __devinit rdc321x_gpio_probe(struct platform_device *pdev)
-{
-       int err;
-       struct resource *r;
-       struct rdc321x_gpio *rdc321x_gpio_dev;
-       struct rdc321x_gpio_pdata *pdata;
-
-       pdata = pdev->dev.platform_data;
-       if (!pdata) {
-               dev_err(&pdev->dev, "no platform data supplied\n");
-               return -ENODEV;
-       }
-
-       rdc321x_gpio_dev = kzalloc(sizeof(struct rdc321x_gpio), GFP_KERNEL);
-       if (!rdc321x_gpio_dev) {
-               dev_err(&pdev->dev, "failed to allocate private data\n");
-               return -ENOMEM;
-       }
-
-       r = platform_get_resource_byname(pdev, IORESOURCE_IO, "gpio-reg1");
-       if (!r) {
-               dev_err(&pdev->dev, "failed to get gpio-reg1 resource\n");
-               err = -ENODEV;
-               goto out_free;
-       }
-
-       spin_lock_init(&rdc321x_gpio_dev->lock);
-       rdc321x_gpio_dev->sb_pdev = pdata->sb_pdev;
-       rdc321x_gpio_dev->reg1_ctrl_base = r->start;
-       rdc321x_gpio_dev->reg1_data_base = r->start + 0x4;
-
-       r = platform_get_resource_byname(pdev, IORESOURCE_IO, "gpio-reg2");
-       if (!r) {
-               dev_err(&pdev->dev, "failed to get gpio-reg2 resource\n");
-               err = -ENODEV;
-               goto out_free;
-       }
-
-       rdc321x_gpio_dev->reg2_ctrl_base = r->start;
-       rdc321x_gpio_dev->reg2_data_base = r->start + 0x4;
-
-       rdc321x_gpio_dev->chip.label = "rdc321x-gpio";
-       rdc321x_gpio_dev->chip.direction_input = rdc_gpio_direction_input;
-       rdc321x_gpio_dev->chip.direction_output = rdc_gpio_config;
-       rdc321x_gpio_dev->chip.get = rdc_gpio_get_value;
-       rdc321x_gpio_dev->chip.set = rdc_gpio_set_value;
-       rdc321x_gpio_dev->chip.base = 0;
-       rdc321x_gpio_dev->chip.ngpio = pdata->max_gpios;
-
-       platform_set_drvdata(pdev, rdc321x_gpio_dev);
-
-       /* This might not be, what others (BIOS, bootloader, etc.)
-          wrote to these registers before, but it's a good guess. Still
-          better than just using 0xffffffff. */
-       err = pci_read_config_dword(rdc321x_gpio_dev->sb_pdev,
-                                       rdc321x_gpio_dev->reg1_data_base,
-                                       &rdc321x_gpio_dev->data_reg[0]);
-       if (err)
-               goto out_drvdata;
-
-       err = pci_read_config_dword(rdc321x_gpio_dev->sb_pdev,
-                                       rdc321x_gpio_dev->reg2_data_base,
-                                       &rdc321x_gpio_dev->data_reg[1]);
-       if (err)
-               goto out_drvdata;
-
-       dev_info(&pdev->dev, "registering %d GPIOs\n",
-                                       rdc321x_gpio_dev->chip.ngpio);
-       return gpiochip_add(&rdc321x_gpio_dev->chip);
-
-out_drvdata:
-       platform_set_drvdata(pdev, NULL);
-out_free:
-       kfree(rdc321x_gpio_dev);
-       return err;
-}
-
-static int __devexit rdc321x_gpio_remove(struct platform_device *pdev)
-{
-       int ret;
-       struct rdc321x_gpio *rdc321x_gpio_dev = platform_get_drvdata(pdev);
-
-       ret = gpiochip_remove(&rdc321x_gpio_dev->chip);
-       if (ret)
-               dev_err(&pdev->dev, "failed to unregister chip\n");
-
-       kfree(rdc321x_gpio_dev);
-       platform_set_drvdata(pdev, NULL);
-
-       return ret;
-}
-
-static struct platform_driver rdc321x_gpio_driver = {
-       .driver.name    = "rdc321x-gpio",
-       .driver.owner   = THIS_MODULE,
-       .probe          = rdc321x_gpio_probe,
-       .remove         = __devexit_p(rdc321x_gpio_remove),
-};
-
-static int __init rdc321x_gpio_init(void)
-{
-       return platform_driver_register(&rdc321x_gpio_driver);
-}
-
-static void __exit rdc321x_gpio_exit(void)
-{
-       platform_driver_unregister(&rdc321x_gpio_driver);
-}
-
-module_init(rdc321x_gpio_init);
-module_exit(rdc321x_gpio_exit);
-
-MODULE_AUTHOR("Florian Fainelli <florian@openwrt.org>");
-MODULE_DESCRIPTION("RDC321x GPIO driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:rdc321x-gpio");
diff --git a/drivers/gpio/sch_gpio.c b/drivers/gpio/sch_gpio.c
deleted file mode 100644 (file)
index 5606042..0000000
+++ /dev/null
@@ -1,316 +0,0 @@
-/*
- *  sch_gpio.c - GPIO interface for Intel Poulsbo SCH
- *
- *  Copyright (c) 2010 CompuLab Ltd
- *  Author: Denis Turischev <denis@compulab.co.il>
- *
- *  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.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; see the file COPYING.  If not, write to
- *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/io.h>
-#include <linux/errno.h>
-#include <linux/acpi.h>
-#include <linux/platform_device.h>
-#include <linux/pci_ids.h>
-
-#include <linux/gpio.h>
-
-static DEFINE_SPINLOCK(gpio_lock);
-
-#define CGEN   (0x00)
-#define CGIO   (0x04)
-#define CGLV   (0x08)
-
-#define RGEN   (0x20)
-#define RGIO   (0x24)
-#define RGLV   (0x28)
-
-static unsigned short gpio_ba;
-
-static int sch_gpio_core_direction_in(struct gpio_chip *gc, unsigned  gpio_num)
-{
-       u8 curr_dirs;
-       unsigned short offset, bit;
-
-       spin_lock(&gpio_lock);
-
-       offset = CGIO + gpio_num / 8;
-       bit = gpio_num % 8;
-
-       curr_dirs = inb(gpio_ba + offset);
-
-       if (!(curr_dirs & (1 << bit)))
-               outb(curr_dirs | (1 << bit), gpio_ba + offset);
-
-       spin_unlock(&gpio_lock);
-       return 0;
-}
-
-static int sch_gpio_core_get(struct gpio_chip *gc, unsigned gpio_num)
-{
-       int res;
-       unsigned short offset, bit;
-
-       offset = CGLV + gpio_num / 8;
-       bit = gpio_num % 8;
-
-       res = !!(inb(gpio_ba + offset) & (1 << bit));
-       return res;
-}
-
-static void sch_gpio_core_set(struct gpio_chip *gc, unsigned gpio_num, int val)
-{
-       u8 curr_vals;
-       unsigned short offset, bit;
-
-       spin_lock(&gpio_lock);
-
-       offset = CGLV + gpio_num / 8;
-       bit = gpio_num % 8;
-
-       curr_vals = inb(gpio_ba + offset);
-
-       if (val)
-               outb(curr_vals | (1 << bit), gpio_ba + offset);
-       else
-               outb((curr_vals & ~(1 << bit)), gpio_ba + offset);
-       spin_unlock(&gpio_lock);
-}
-
-static int sch_gpio_core_direction_out(struct gpio_chip *gc,
-                                       unsigned gpio_num, int val)
-{
-       u8 curr_dirs;
-       unsigned short offset, bit;
-
-       sch_gpio_core_set(gc, gpio_num, val);
-
-       spin_lock(&gpio_lock);
-
-       offset = CGIO + gpio_num / 8;
-       bit = gpio_num % 8;
-
-       curr_dirs = inb(gpio_ba + offset);
-       if (curr_dirs & (1 << bit))
-               outb(curr_dirs & ~(1 << bit), gpio_ba + offset);
-
-       spin_unlock(&gpio_lock);
-       return 0;
-}
-
-static struct gpio_chip sch_gpio_core = {
-       .label                  = "sch_gpio_core",
-       .owner                  = THIS_MODULE,
-       .direction_input        = sch_gpio_core_direction_in,
-       .get                    = sch_gpio_core_get,
-       .direction_output       = sch_gpio_core_direction_out,
-       .set                    = sch_gpio_core_set,
-};
-
-static int sch_gpio_resume_direction_in(struct gpio_chip *gc,
-                                       unsigned gpio_num)
-{
-       u8 curr_dirs;
-
-       spin_lock(&gpio_lock);
-
-       curr_dirs = inb(gpio_ba + RGIO);
-
-       if (!(curr_dirs & (1 << gpio_num)))
-               outb(curr_dirs | (1 << gpio_num) , gpio_ba + RGIO);
-
-       spin_unlock(&gpio_lock);
-       return 0;
-}
-
-static int sch_gpio_resume_get(struct gpio_chip *gc, unsigned gpio_num)
-{
-       return !!(inb(gpio_ba + RGLV) & (1 << gpio_num));
-}
-
-static void sch_gpio_resume_set(struct gpio_chip *gc,
-                               unsigned gpio_num, int val)
-{
-       u8 curr_vals;
-
-       spin_lock(&gpio_lock);
-
-       curr_vals = inb(gpio_ba + RGLV);
-
-       if (val)
-               outb(curr_vals | (1 << gpio_num), gpio_ba + RGLV);
-       else
-               outb((curr_vals & ~(1 << gpio_num)), gpio_ba + RGLV);
-
-       spin_unlock(&gpio_lock);
-}
-
-static int sch_gpio_resume_direction_out(struct gpio_chip *gc,
-                                       unsigned gpio_num, int val)
-{
-       u8 curr_dirs;
-
-       sch_gpio_resume_set(gc, gpio_num, val);
-
-       spin_lock(&gpio_lock);
-
-       curr_dirs = inb(gpio_ba + RGIO);
-       if (curr_dirs & (1 << gpio_num))
-               outb(curr_dirs & ~(1 << gpio_num), gpio_ba + RGIO);
-
-       spin_unlock(&gpio_lock);
-       return 0;
-}
-
-static struct gpio_chip sch_gpio_resume = {
-       .label                  = "sch_gpio_resume",
-       .owner                  = THIS_MODULE,
-       .direction_input        = sch_gpio_resume_direction_in,
-       .get                    = sch_gpio_resume_get,
-       .direction_output       = sch_gpio_resume_direction_out,
-       .set                    = sch_gpio_resume_set,
-};
-
-static int __devinit sch_gpio_probe(struct platform_device *pdev)
-{
-       struct resource *res;
-       int err, id;
-
-       id = pdev->id;
-       if (!id)
-               return -ENODEV;
-
-       res = platform_get_resource(pdev, IORESOURCE_IO, 0);
-       if (!res)
-               return -EBUSY;
-
-       if (!request_region(res->start, resource_size(res), pdev->name))
-               return -EBUSY;
-
-       gpio_ba = res->start;
-
-       switch (id) {
-               case PCI_DEVICE_ID_INTEL_SCH_LPC:
-                       sch_gpio_core.base = 0;
-                       sch_gpio_core.ngpio = 10;
-
-                       sch_gpio_resume.base = 10;
-                       sch_gpio_resume.ngpio = 4;
-
-                       /*
-                        * GPIO[6:0] enabled by default
-                        * GPIO7 is configured by the CMC as SLPIOVR
-                        * Enable GPIO[9:8] core powered gpios explicitly
-                        */
-                       outb(0x3, gpio_ba + CGEN + 1);
-                       /*
-                        * SUS_GPIO[2:0] enabled by default
-                        * Enable SUS_GPIO3 resume powered gpio explicitly
-                        */
-                       outb(0x8, gpio_ba + RGEN);
-                       break;
-
-               case PCI_DEVICE_ID_INTEL_ITC_LPC:
-                       sch_gpio_core.base = 0;
-                       sch_gpio_core.ngpio = 5;
-
-                       sch_gpio_resume.base = 5;
-                       sch_gpio_resume.ngpio = 9;
-                       break;
-
-               default:
-                       return -ENODEV;
-       }
-
-       sch_gpio_core.dev = &pdev->dev;
-       sch_gpio_resume.dev = &pdev->dev;
-
-       err = gpiochip_add(&sch_gpio_core);
-       if (err < 0)
-               goto err_sch_gpio_core;
-
-       err = gpiochip_add(&sch_gpio_resume);
-       if (err < 0)
-               goto err_sch_gpio_resume;
-
-       return 0;
-
-err_sch_gpio_resume:
-       err = gpiochip_remove(&sch_gpio_core);
-       if (err)
-               dev_err(&pdev->dev, "%s failed, %d\n",
-                               "gpiochip_remove()", err);
-
-err_sch_gpio_core:
-       release_region(res->start, resource_size(res));
-       gpio_ba = 0;
-
-       return err;
-}
-
-static int __devexit sch_gpio_remove(struct platform_device *pdev)
-{
-       struct resource *res;
-       if (gpio_ba) {
-               int err;
-
-               err  = gpiochip_remove(&sch_gpio_core);
-               if (err)
-                       dev_err(&pdev->dev, "%s failed, %d\n",
-                               "gpiochip_remove()", err);
-               err = gpiochip_remove(&sch_gpio_resume);
-               if (err)
-                       dev_err(&pdev->dev, "%s failed, %d\n",
-                               "gpiochip_remove()", err);
-
-               res = platform_get_resource(pdev, IORESOURCE_IO, 0);
-
-               release_region(res->start, resource_size(res));
-               gpio_ba = 0;
-
-               return err;
-       }
-
-       return 0;
-}
-
-static struct platform_driver sch_gpio_driver = {
-       .driver = {
-               .name = "sch_gpio",
-               .owner = THIS_MODULE,
-       },
-       .probe          = sch_gpio_probe,
-       .remove         = __devexit_p(sch_gpio_remove),
-};
-
-static int __init sch_gpio_init(void)
-{
-       return platform_driver_register(&sch_gpio_driver);
-}
-
-static void __exit sch_gpio_exit(void)
-{
-       platform_driver_unregister(&sch_gpio_driver);
-}
-
-module_init(sch_gpio_init);
-module_exit(sch_gpio_exit);
-
-MODULE_AUTHOR("Denis Turischev <denis@compulab.co.il>");
-MODULE_DESCRIPTION("GPIO interface for Intel Poulsbo SCH");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:sch_gpio");
diff --git a/drivers/gpio/stmpe-gpio.c b/drivers/gpio/stmpe-gpio.c
deleted file mode 100644 (file)
index 4c980b5..0000000
+++ /dev/null
@@ -1,404 +0,0 @@
-/*
- * Copyright (C) ST-Ericsson SA 2010
- *
- * License Terms: GNU General Public License, version 2
- * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include <linux/gpio.h>
-#include <linux/irq.h>
-#include <linux/interrupt.h>
-#include <linux/mfd/stmpe.h>
-
-/*
- * These registers are modified under the irq bus lock and cached to avoid
- * unnecessary writes in bus_sync_unlock.
- */
-enum { REG_RE, REG_FE, REG_IE };
-
-#define CACHE_NR_REGS  3
-#define CACHE_NR_BANKS (STMPE_NR_GPIOS / 8)
-
-struct stmpe_gpio {
-       struct gpio_chip chip;
-       struct stmpe *stmpe;
-       struct device *dev;
-       struct mutex irq_lock;
-
-       int irq_base;
-       unsigned norequest_mask;
-
-       /* Caches of interrupt control registers for bus_lock */
-       u8 regs[CACHE_NR_REGS][CACHE_NR_BANKS];
-       u8 oldregs[CACHE_NR_REGS][CACHE_NR_BANKS];
-};
-
-static inline struct stmpe_gpio *to_stmpe_gpio(struct gpio_chip *chip)
-{
-       return container_of(chip, struct stmpe_gpio, chip);
-}
-
-static int stmpe_gpio_get(struct gpio_chip *chip, unsigned offset)
-{
-       struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(chip);
-       struct stmpe *stmpe = stmpe_gpio->stmpe;
-       u8 reg = stmpe->regs[STMPE_IDX_GPMR_LSB] - (offset / 8);
-       u8 mask = 1 << (offset % 8);
-       int ret;
-
-       ret = stmpe_reg_read(stmpe, reg);
-       if (ret < 0)
-               return ret;
-
-       return ret & mask;
-}
-
-static void stmpe_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
-{
-       struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(chip);
-       struct stmpe *stmpe = stmpe_gpio->stmpe;
-       int which = val ? STMPE_IDX_GPSR_LSB : STMPE_IDX_GPCR_LSB;
-       u8 reg = stmpe->regs[which] - (offset / 8);
-       u8 mask = 1 << (offset % 8);
-
-       stmpe_reg_write(stmpe, reg, mask);
-}
-
-static int stmpe_gpio_direction_output(struct gpio_chip *chip,
-                                        unsigned offset, int val)
-{
-       struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(chip);
-       struct stmpe *stmpe = stmpe_gpio->stmpe;
-       u8 reg = stmpe->regs[STMPE_IDX_GPDR_LSB] - (offset / 8);
-       u8 mask = 1 << (offset % 8);
-
-       stmpe_gpio_set(chip, offset, val);
-
-       return stmpe_set_bits(stmpe, reg, mask, mask);
-}
-
-static int stmpe_gpio_direction_input(struct gpio_chip *chip,
-                                       unsigned offset)
-{
-       struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(chip);
-       struct stmpe *stmpe = stmpe_gpio->stmpe;
-       u8 reg = stmpe->regs[STMPE_IDX_GPDR_LSB] - (offset / 8);
-       u8 mask = 1 << (offset % 8);
-
-       return stmpe_set_bits(stmpe, reg, mask, 0);
-}
-
-static int stmpe_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
-{
-       struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(chip);
-
-       return stmpe_gpio->irq_base + offset;
-}
-
-static int stmpe_gpio_request(struct gpio_chip *chip, unsigned offset)
-{
-       struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(chip);
-       struct stmpe *stmpe = stmpe_gpio->stmpe;
-
-       if (stmpe_gpio->norequest_mask & (1 << offset))
-               return -EINVAL;
-
-       return stmpe_set_altfunc(stmpe, 1 << offset, STMPE_BLOCK_GPIO);
-}
-
-static struct gpio_chip template_chip = {
-       .label                  = "stmpe",
-       .owner                  = THIS_MODULE,
-       .direction_input        = stmpe_gpio_direction_input,
-       .get                    = stmpe_gpio_get,
-       .direction_output       = stmpe_gpio_direction_output,
-       .set                    = stmpe_gpio_set,
-       .to_irq                 = stmpe_gpio_to_irq,
-       .request                = stmpe_gpio_request,
-       .can_sleep              = 1,
-};
-
-static int stmpe_gpio_irq_set_type(struct irq_data *d, unsigned int type)
-{
-       struct stmpe_gpio *stmpe_gpio = irq_data_get_irq_chip_data(d);
-       int offset = d->irq - stmpe_gpio->irq_base;
-       int regoffset = offset / 8;
-       int mask = 1 << (offset % 8);
-
-       if (type == IRQ_TYPE_LEVEL_LOW || type == IRQ_TYPE_LEVEL_HIGH)
-               return -EINVAL;
-
-       if (type == IRQ_TYPE_EDGE_RISING)
-               stmpe_gpio->regs[REG_RE][regoffset] |= mask;
-       else
-               stmpe_gpio->regs[REG_RE][regoffset] &= ~mask;
-
-       if (type == IRQ_TYPE_EDGE_FALLING)
-               stmpe_gpio->regs[REG_FE][regoffset] |= mask;
-       else
-               stmpe_gpio->regs[REG_FE][regoffset] &= ~mask;
-
-       return 0;
-}
-
-static void stmpe_gpio_irq_lock(struct irq_data *d)
-{
-       struct stmpe_gpio *stmpe_gpio = irq_data_get_irq_chip_data(d);
-
-       mutex_lock(&stmpe_gpio->irq_lock);
-}
-
-static void stmpe_gpio_irq_sync_unlock(struct irq_data *d)
-{
-       struct stmpe_gpio *stmpe_gpio = irq_data_get_irq_chip_data(d);
-       struct stmpe *stmpe = stmpe_gpio->stmpe;
-       int num_banks = DIV_ROUND_UP(stmpe->num_gpios, 8);
-       static const u8 regmap[] = {
-               [REG_RE]        = STMPE_IDX_GPRER_LSB,
-               [REG_FE]        = STMPE_IDX_GPFER_LSB,
-               [REG_IE]        = STMPE_IDX_IEGPIOR_LSB,
-       };
-       int i, j;
-
-       for (i = 0; i < CACHE_NR_REGS; i++) {
-               for (j = 0; j < num_banks; j++) {
-                       u8 old = stmpe_gpio->oldregs[i][j];
-                       u8 new = stmpe_gpio->regs[i][j];
-
-                       if (new == old)
-                               continue;
-
-                       stmpe_gpio->oldregs[i][j] = new;
-                       stmpe_reg_write(stmpe, stmpe->regs[regmap[i]] - j, new);
-               }
-       }
-
-       mutex_unlock(&stmpe_gpio->irq_lock);
-}
-
-static void stmpe_gpio_irq_mask(struct irq_data *d)
-{
-       struct stmpe_gpio *stmpe_gpio = irq_data_get_irq_chip_data(d);
-       int offset = d->irq - stmpe_gpio->irq_base;
-       int regoffset = offset / 8;
-       int mask = 1 << (offset % 8);
-
-       stmpe_gpio->regs[REG_IE][regoffset] &= ~mask;
-}
-
-static void stmpe_gpio_irq_unmask(struct irq_data *d)
-{
-       struct stmpe_gpio *stmpe_gpio = irq_data_get_irq_chip_data(d);
-       int offset = d->irq - stmpe_gpio->irq_base;
-       int regoffset = offset / 8;
-       int mask = 1 << (offset % 8);
-
-       stmpe_gpio->regs[REG_IE][regoffset] |= mask;
-}
-
-static struct irq_chip stmpe_gpio_irq_chip = {
-       .name                   = "stmpe-gpio",
-       .irq_bus_lock           = stmpe_gpio_irq_lock,
-       .irq_bus_sync_unlock    = stmpe_gpio_irq_sync_unlock,
-       .irq_mask               = stmpe_gpio_irq_mask,
-       .irq_unmask             = stmpe_gpio_irq_unmask,
-       .irq_set_type           = stmpe_gpio_irq_set_type,
-};
-
-static irqreturn_t stmpe_gpio_irq(int irq, void *dev)
-{
-       struct stmpe_gpio *stmpe_gpio = dev;
-       struct stmpe *stmpe = stmpe_gpio->stmpe;
-       u8 statmsbreg = stmpe->regs[STMPE_IDX_ISGPIOR_MSB];
-       int num_banks = DIV_ROUND_UP(stmpe->num_gpios, 8);
-       u8 status[num_banks];
-       int ret;
-       int i;
-
-       ret = stmpe_block_read(stmpe, statmsbreg, num_banks, status);
-       if (ret < 0)
-               return IRQ_NONE;
-
-       for (i = 0; i < num_banks; i++) {
-               int bank = num_banks - i - 1;
-               unsigned int enabled = stmpe_gpio->regs[REG_IE][bank];
-               unsigned int stat = status[i];
-
-               stat &= enabled;
-               if (!stat)
-                       continue;
-
-               while (stat) {
-                       int bit = __ffs(stat);
-                       int line = bank * 8 + bit;
-
-                       handle_nested_irq(stmpe_gpio->irq_base + line);
-                       stat &= ~(1 << bit);
-               }
-
-               stmpe_reg_write(stmpe, statmsbreg + i, status[i]);
-               stmpe_reg_write(stmpe, stmpe->regs[STMPE_IDX_GPEDR_MSB] + i,
-                               status[i]);
-       }
-
-       return IRQ_HANDLED;
-}
-
-static int __devinit stmpe_gpio_irq_init(struct stmpe_gpio *stmpe_gpio)
-{
-       int base = stmpe_gpio->irq_base;
-       int irq;
-
-       for (irq = base; irq < base + stmpe_gpio->chip.ngpio; irq++) {
-               irq_set_chip_data(irq, stmpe_gpio);
-               irq_set_chip_and_handler(irq, &stmpe_gpio_irq_chip,
-                                        handle_simple_irq);
-               irq_set_nested_thread(irq, 1);
-#ifdef CONFIG_ARM
-               set_irq_flags(irq, IRQF_VALID);
-#else
-               irq_set_noprobe(irq);
-#endif
-       }
-
-       return 0;
-}
-
-static void stmpe_gpio_irq_remove(struct stmpe_gpio *stmpe_gpio)
-{
-       int base = stmpe_gpio->irq_base;
-       int irq;
-
-       for (irq = base; irq < base + stmpe_gpio->chip.ngpio; irq++) {
-#ifdef CONFIG_ARM
-               set_irq_flags(irq, 0);
-#endif
-               irq_set_chip_and_handler(irq, NULL, NULL);
-               irq_set_chip_data(irq, NULL);
-       }
-}
-
-static int __devinit stmpe_gpio_probe(struct platform_device *pdev)
-{
-       struct stmpe *stmpe = dev_get_drvdata(pdev->dev.parent);
-       struct stmpe_gpio_platform_data *pdata;
-       struct stmpe_gpio *stmpe_gpio;
-       int ret;
-       int irq;
-
-       pdata = stmpe->pdata->gpio;
-
-       irq = platform_get_irq(pdev, 0);
-       if (irq < 0)
-               return irq;
-
-       stmpe_gpio = kzalloc(sizeof(struct stmpe_gpio), GFP_KERNEL);
-       if (!stmpe_gpio)
-               return -ENOMEM;
-
-       mutex_init(&stmpe_gpio->irq_lock);
-
-       stmpe_gpio->dev = &pdev->dev;
-       stmpe_gpio->stmpe = stmpe;
-       stmpe_gpio->norequest_mask = pdata ? pdata->norequest_mask : 0;
-
-       stmpe_gpio->chip = template_chip;
-       stmpe_gpio->chip.ngpio = stmpe->num_gpios;
-       stmpe_gpio->chip.dev = &pdev->dev;
-       stmpe_gpio->chip.base = pdata ? pdata->gpio_base : -1;
-
-       stmpe_gpio->irq_base = stmpe->irq_base + STMPE_INT_GPIO(0);
-
-       ret = stmpe_enable(stmpe, STMPE_BLOCK_GPIO);
-       if (ret)
-               goto out_free;
-
-       ret = stmpe_gpio_irq_init(stmpe_gpio);
-       if (ret)
-               goto out_disable;
-
-       ret = request_threaded_irq(irq, NULL, stmpe_gpio_irq, IRQF_ONESHOT,
-                                  "stmpe-gpio", stmpe_gpio);
-       if (ret) {
-               dev_err(&pdev->dev, "unable to get irq: %d\n", ret);
-               goto out_removeirq;
-       }
-
-       ret = gpiochip_add(&stmpe_gpio->chip);
-       if (ret) {
-               dev_err(&pdev->dev, "unable to add gpiochip: %d\n", ret);
-               goto out_freeirq;
-       }
-
-       if (pdata && pdata->setup)
-               pdata->setup(stmpe, stmpe_gpio->chip.base);
-
-       platform_set_drvdata(pdev, stmpe_gpio);
-
-       return 0;
-
-out_freeirq:
-       free_irq(irq, stmpe_gpio);
-out_removeirq:
-       stmpe_gpio_irq_remove(stmpe_gpio);
-out_disable:
-       stmpe_disable(stmpe, STMPE_BLOCK_GPIO);
-out_free:
-       kfree(stmpe_gpio);
-       return ret;
-}
-
-static int __devexit stmpe_gpio_remove(struct platform_device *pdev)
-{
-       struct stmpe_gpio *stmpe_gpio = platform_get_drvdata(pdev);
-       struct stmpe *stmpe = stmpe_gpio->stmpe;
-       struct stmpe_gpio_platform_data *pdata = stmpe->pdata->gpio;
-       int irq = platform_get_irq(pdev, 0);
-       int ret;
-
-       if (pdata && pdata->remove)
-               pdata->remove(stmpe, stmpe_gpio->chip.base);
-
-       ret = gpiochip_remove(&stmpe_gpio->chip);
-       if (ret < 0) {
-               dev_err(stmpe_gpio->dev,
-                       "unable to remove gpiochip: %d\n", ret);
-               return ret;
-       }
-
-       stmpe_disable(stmpe, STMPE_BLOCK_GPIO);
-
-       free_irq(irq, stmpe_gpio);
-       stmpe_gpio_irq_remove(stmpe_gpio);
-       platform_set_drvdata(pdev, NULL);
-       kfree(stmpe_gpio);
-
-       return 0;
-}
-
-static struct platform_driver stmpe_gpio_driver = {
-       .driver.name    = "stmpe-gpio",
-       .driver.owner   = THIS_MODULE,
-       .probe          = stmpe_gpio_probe,
-       .remove         = __devexit_p(stmpe_gpio_remove),
-};
-
-static int __init stmpe_gpio_init(void)
-{
-       return platform_driver_register(&stmpe_gpio_driver);
-}
-subsys_initcall(stmpe_gpio_init);
-
-static void __exit stmpe_gpio_exit(void)
-{
-       platform_driver_unregister(&stmpe_gpio_driver);
-}
-module_exit(stmpe_gpio_exit);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("STMPExxxx GPIO driver");
-MODULE_AUTHOR("Rabin Vincent <rabin.vincent@stericsson.com>");
diff --git a/drivers/gpio/sx150x.c b/drivers/gpio/sx150x.c
deleted file mode 100644 (file)
index a4f7353..0000000
+++ /dev/null
@@ -1,680 +0,0 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-#include <linux/gpio.h>
-#include <linux/i2c.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/module.h>
-#include <linux/mutex.h>
-#include <linux/slab.h>
-#include <linux/workqueue.h>
-#include <linux/i2c/sx150x.h>
-
-#define NO_UPDATE_PENDING      -1
-
-struct sx150x_device_data {
-       u8 reg_pullup;
-       u8 reg_pulldn;
-       u8 reg_drain;
-       u8 reg_polarity;
-       u8 reg_dir;
-       u8 reg_data;
-       u8 reg_irq_mask;
-       u8 reg_irq_src;
-       u8 reg_sense;
-       u8 reg_clock;
-       u8 reg_misc;
-       u8 reg_reset;
-       u8 ngpios;
-};
-
-struct sx150x_chip {
-       struct gpio_chip                 gpio_chip;
-       struct i2c_client               *client;
-       const struct sx150x_device_data *dev_cfg;
-       int                              irq_summary;
-       int                              irq_base;
-       int                              irq_update;
-       u32                              irq_sense;
-       u32                              irq_masked;
-       u32                              dev_sense;
-       u32                              dev_masked;
-       struct irq_chip                  irq_chip;
-       struct mutex                     lock;
-};
-
-static const struct sx150x_device_data sx150x_devices[] = {
-       [0] = { /* sx1508q */
-               .reg_pullup   = 0x03,
-               .reg_pulldn   = 0x04,
-               .reg_drain    = 0x05,
-               .reg_polarity = 0x06,
-               .reg_dir      = 0x07,
-               .reg_data     = 0x08,
-               .reg_irq_mask = 0x09,
-               .reg_irq_src  = 0x0c,
-               .reg_sense    = 0x0b,
-               .reg_clock    = 0x0f,
-               .reg_misc     = 0x10,
-               .reg_reset    = 0x7d,
-               .ngpios       = 8
-       },
-       [1] = { /* sx1509q */
-               .reg_pullup   = 0x07,
-               .reg_pulldn   = 0x09,
-               .reg_drain    = 0x0b,
-               .reg_polarity = 0x0d,
-               .reg_dir      = 0x0f,
-               .reg_data     = 0x11,
-               .reg_irq_mask = 0x13,
-               .reg_irq_src  = 0x19,
-               .reg_sense    = 0x17,
-               .reg_clock    = 0x1e,
-               .reg_misc     = 0x1f,
-               .reg_reset    = 0x7d,
-               .ngpios       = 16
-       },
-};
-
-static const struct i2c_device_id sx150x_id[] = {
-       {"sx1508q", 0},
-       {"sx1509q", 1},
-       {}
-};
-MODULE_DEVICE_TABLE(i2c, sx150x_id);
-
-static s32 sx150x_i2c_write(struct i2c_client *client, u8 reg, u8 val)
-{
-       s32 err = i2c_smbus_write_byte_data(client, reg, val);
-
-       if (err < 0)
-               dev_warn(&client->dev,
-                       "i2c write fail: can't write %02x to %02x: %d\n",
-                       val, reg, err);
-       return err;
-}
-
-static s32 sx150x_i2c_read(struct i2c_client *client, u8 reg, u8 *val)
-{
-       s32 err = i2c_smbus_read_byte_data(client, reg);
-
-       if (err >= 0)
-               *val = err;
-       else
-               dev_warn(&client->dev,
-                       "i2c read fail: can't read from %02x: %d\n",
-                       reg, err);
-       return err;
-}
-
-static inline bool offset_is_oscio(struct sx150x_chip *chip, unsigned offset)
-{
-       return (chip->dev_cfg->ngpios == offset);
-}
-
-/*
- * These utility functions solve the common problem of locating and setting
- * configuration bits.  Configuration bits are grouped into registers
- * whose indexes increase downwards.  For example, with eight-bit registers,
- * sixteen gpios would have their config bits grouped in the following order:
- * REGISTER N-1 [ f e d c b a 9 8 ]
- *          N   [ 7 6 5 4 3 2 1 0 ]
- *
- * For multi-bit configurations, the pattern gets wider:
- * REGISTER N-3 [ f f e e d d c c ]
- *          N-2 [ b b a a 9 9 8 8 ]
- *          N-1 [ 7 7 6 6 5 5 4 4 ]
- *          N   [ 3 3 2 2 1 1 0 0 ]
- *
- * Given the address of the starting register 'N', the index of the gpio
- * whose configuration we seek to change, and the width in bits of that
- * configuration, these functions allow us to locate the correct
- * register and mask the correct bits.
- */
-static inline void sx150x_find_cfg(u8 offset, u8 width,
-                               u8 *reg, u8 *mask, u8 *shift)
-{
-       *reg   -= offset * width / 8;
-       *mask   = (1 << width) - 1;
-       *shift  = (offset * width) % 8;
-       *mask <<= *shift;
-}
-
-static s32 sx150x_write_cfg(struct sx150x_chip *chip,
-                       u8 offset, u8 width, u8 reg, u8 val)
-{
-       u8  mask;
-       u8  data;
-       u8  shift;
-       s32 err;
-
-       sx150x_find_cfg(offset, width, &reg, &mask, &shift);
-       err = sx150x_i2c_read(chip->client, reg, &data);
-       if (err < 0)
-               return err;
-
-       data &= ~mask;
-       data |= (val << shift) & mask;
-       return sx150x_i2c_write(chip->client, reg, data);
-}
-
-static int sx150x_get_io(struct sx150x_chip *chip, unsigned offset)
-{
-       u8  reg = chip->dev_cfg->reg_data;
-       u8  mask;
-       u8  data;
-       u8  shift;
-       s32 err;
-
-       sx150x_find_cfg(offset, 1, &reg, &mask, &shift);
-       err = sx150x_i2c_read(chip->client, reg, &data);
-       if (err >= 0)
-               err = (data & mask) != 0 ? 1 : 0;
-
-       return err;
-}
-
-static void sx150x_set_oscio(struct sx150x_chip *chip, int val)
-{
-       sx150x_i2c_write(chip->client,
-                       chip->dev_cfg->reg_clock,
-                       (val ? 0x1f : 0x10));
-}
-
-static void sx150x_set_io(struct sx150x_chip *chip, unsigned offset, int val)
-{
-       sx150x_write_cfg(chip,
-                       offset,
-                       1,
-                       chip->dev_cfg->reg_data,
-                       (val ? 1 : 0));
-}
-
-static int sx150x_io_input(struct sx150x_chip *chip, unsigned offset)
-{
-       return sx150x_write_cfg(chip,
-                               offset,
-                               1,
-                               chip->dev_cfg->reg_dir,
-                               1);
-}
-
-static int sx150x_io_output(struct sx150x_chip *chip, unsigned offset, int val)
-{
-       int err;
-
-       err = sx150x_write_cfg(chip,
-                       offset,
-                       1,
-                       chip->dev_cfg->reg_data,
-                       (val ? 1 : 0));
-       if (err >= 0)
-               err = sx150x_write_cfg(chip,
-                               offset,
-                               1,
-                               chip->dev_cfg->reg_dir,
-                               0);
-       return err;
-}
-
-static int sx150x_gpio_get(struct gpio_chip *gc, unsigned offset)
-{
-       struct sx150x_chip *chip;
-       int status = -EINVAL;
-
-       chip = container_of(gc, struct sx150x_chip, gpio_chip);
-
-       if (!offset_is_oscio(chip, offset)) {
-               mutex_lock(&chip->lock);
-               status = sx150x_get_io(chip, offset);
-               mutex_unlock(&chip->lock);
-       }
-
-       return status;
-}
-
-static void sx150x_gpio_set(struct gpio_chip *gc, unsigned offset, int val)
-{
-       struct sx150x_chip *chip;
-
-       chip = container_of(gc, struct sx150x_chip, gpio_chip);
-
-       mutex_lock(&chip->lock);
-       if (offset_is_oscio(chip, offset))
-               sx150x_set_oscio(chip, val);
-       else
-               sx150x_set_io(chip, offset, val);
-       mutex_unlock(&chip->lock);
-}
-
-static int sx150x_gpio_direction_input(struct gpio_chip *gc, unsigned offset)
-{
-       struct sx150x_chip *chip;
-       int status = -EINVAL;
-
-       chip = container_of(gc, struct sx150x_chip, gpio_chip);
-
-       if (!offset_is_oscio(chip, offset)) {
-               mutex_lock(&chip->lock);
-               status = sx150x_io_input(chip, offset);
-               mutex_unlock(&chip->lock);
-       }
-       return status;
-}
-
-static int sx150x_gpio_direction_output(struct gpio_chip *gc,
-                                       unsigned offset,
-                                       int val)
-{
-       struct sx150x_chip *chip;
-       int status = 0;
-
-       chip = container_of(gc, struct sx150x_chip, gpio_chip);
-
-       if (!offset_is_oscio(chip, offset)) {
-               mutex_lock(&chip->lock);
-               status = sx150x_io_output(chip, offset, val);
-               mutex_unlock(&chip->lock);
-       }
-       return status;
-}
-
-static int sx150x_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
-{
-       struct sx150x_chip *chip;
-
-       chip = container_of(gc, struct sx150x_chip, gpio_chip);
-
-       if (offset >= chip->dev_cfg->ngpios)
-               return -EINVAL;
-
-       if (chip->irq_base < 0)
-               return -EINVAL;
-
-       return chip->irq_base + offset;
-}
-
-static void sx150x_irq_mask(struct irq_data *d)
-{
-       struct irq_chip *ic = irq_data_get_irq_chip(d);
-       struct sx150x_chip *chip;
-       unsigned n;
-
-       chip = container_of(ic, struct sx150x_chip, irq_chip);
-       n = d->irq - chip->irq_base;
-       chip->irq_masked |= (1 << n);
-       chip->irq_update = n;
-}
-
-static void sx150x_irq_unmask(struct irq_data *d)
-{
-       struct irq_chip *ic = irq_data_get_irq_chip(d);
-       struct sx150x_chip *chip;
-       unsigned n;
-
-       chip = container_of(ic, struct sx150x_chip, irq_chip);
-       n = d->irq - chip->irq_base;
-
-       chip->irq_masked &= ~(1 << n);
-       chip->irq_update = n;
-}
-
-static int sx150x_irq_set_type(struct irq_data *d, unsigned int flow_type)
-{
-       struct irq_chip *ic = irq_data_get_irq_chip(d);
-       struct sx150x_chip *chip;
-       unsigned n, val = 0;
-
-       if (flow_type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW))
-               return -EINVAL;
-
-       chip = container_of(ic, struct sx150x_chip, irq_chip);
-       n = d->irq - chip->irq_base;
-
-       if (flow_type & IRQ_TYPE_EDGE_RISING)
-               val |= 0x1;
-       if (flow_type & IRQ_TYPE_EDGE_FALLING)
-               val |= 0x2;
-
-       chip->irq_sense &= ~(3UL << (n * 2));
-       chip->irq_sense |= val << (n * 2);
-       chip->irq_update = n;
-       return 0;
-}
-
-static irqreturn_t sx150x_irq_thread_fn(int irq, void *dev_id)
-{
-       struct sx150x_chip *chip = (struct sx150x_chip *)dev_id;
-       unsigned nhandled = 0;
-       unsigned sub_irq;
-       unsigned n;
-       s32 err;
-       u8 val;
-       int i;
-
-       for (i = (chip->dev_cfg->ngpios / 8) - 1; i >= 0; --i) {
-               err = sx150x_i2c_read(chip->client,
-                                     chip->dev_cfg->reg_irq_src - i,
-                                     &val);
-               if (err < 0)
-                       continue;
-
-               sx150x_i2c_write(chip->client,
-                               chip->dev_cfg->reg_irq_src - i,
-                               val);
-               for (n = 0; n < 8; ++n) {
-                       if (val & (1 << n)) {
-                               sub_irq = chip->irq_base + (i * 8) + n;
-                               handle_nested_irq(sub_irq);
-                               ++nhandled;
-                       }
-               }
-       }
-
-       return (nhandled > 0 ? IRQ_HANDLED : IRQ_NONE);
-}
-
-static void sx150x_irq_bus_lock(struct irq_data *d)
-{
-       struct irq_chip *ic = irq_data_get_irq_chip(d);
-       struct sx150x_chip *chip;
-
-       chip = container_of(ic, struct sx150x_chip, irq_chip);
-
-       mutex_lock(&chip->lock);
-}
-
-static void sx150x_irq_bus_sync_unlock(struct irq_data *d)
-{
-       struct irq_chip *ic = irq_data_get_irq_chip(d);
-       struct sx150x_chip *chip;
-       unsigned n;
-
-       chip = container_of(ic, struct sx150x_chip, irq_chip);
-
-       if (chip->irq_update == NO_UPDATE_PENDING)
-               goto out;
-
-       n = chip->irq_update;
-       chip->irq_update = NO_UPDATE_PENDING;
-
-       /* Avoid updates if nothing changed */
-       if (chip->dev_sense == chip->irq_sense &&
-           chip->dev_sense == chip->irq_masked)
-               goto out;
-
-       chip->dev_sense = chip->irq_sense;
-       chip->dev_masked = chip->irq_masked;
-
-       if (chip->irq_masked & (1 << n)) {
-               sx150x_write_cfg(chip, n, 1, chip->dev_cfg->reg_irq_mask, 1);
-               sx150x_write_cfg(chip, n, 2, chip->dev_cfg->reg_sense, 0);
-       } else {
-               sx150x_write_cfg(chip, n, 1, chip->dev_cfg->reg_irq_mask, 0);
-               sx150x_write_cfg(chip, n, 2, chip->dev_cfg->reg_sense,
-                                chip->irq_sense >> (n * 2));
-       }
-out:
-       mutex_unlock(&chip->lock);
-}
-
-static void sx150x_init_chip(struct sx150x_chip *chip,
-                       struct i2c_client *client,
-                       kernel_ulong_t driver_data,
-                       struct sx150x_platform_data *pdata)
-{
-       mutex_init(&chip->lock);
-
-       chip->client                     = client;
-       chip->dev_cfg                    = &sx150x_devices[driver_data];
-       chip->gpio_chip.label            = client->name;
-       chip->gpio_chip.direction_input  = sx150x_gpio_direction_input;
-       chip->gpio_chip.direction_output = sx150x_gpio_direction_output;
-       chip->gpio_chip.get              = sx150x_gpio_get;
-       chip->gpio_chip.set              = sx150x_gpio_set;
-       chip->gpio_chip.to_irq           = sx150x_gpio_to_irq;
-       chip->gpio_chip.base             = pdata->gpio_base;
-       chip->gpio_chip.can_sleep        = 1;
-       chip->gpio_chip.ngpio            = chip->dev_cfg->ngpios;
-       if (pdata->oscio_is_gpo)
-               ++chip->gpio_chip.ngpio;
-
-       chip->irq_chip.name                = client->name;
-       chip->irq_chip.irq_mask            = sx150x_irq_mask;
-       chip->irq_chip.irq_unmask          = sx150x_irq_unmask;
-       chip->irq_chip.irq_set_type        = sx150x_irq_set_type;
-       chip->irq_chip.irq_bus_lock        = sx150x_irq_bus_lock;
-       chip->irq_chip.irq_bus_sync_unlock = sx150x_irq_bus_sync_unlock;
-       chip->irq_summary                  = -1;
-       chip->irq_base                     = -1;
-       chip->irq_masked                   = ~0;
-       chip->irq_sense                    = 0;
-       chip->dev_masked                   = ~0;
-       chip->dev_sense                    = 0;
-       chip->irq_update                   = NO_UPDATE_PENDING;
-}
-
-static int sx150x_init_io(struct sx150x_chip *chip, u8 base, u16 cfg)
-{
-       int err = 0;
-       unsigned n;
-
-       for (n = 0; err >= 0 && n < (chip->dev_cfg->ngpios / 8); ++n)
-               err = sx150x_i2c_write(chip->client, base - n, cfg >> (n * 8));
-       return err;
-}
-
-static int sx150x_reset(struct sx150x_chip *chip)
-{
-       int err;
-
-       err = i2c_smbus_write_byte_data(chip->client,
-                                       chip->dev_cfg->reg_reset,
-                                       0x12);
-       if (err < 0)
-               return err;
-
-       err = i2c_smbus_write_byte_data(chip->client,
-                                       chip->dev_cfg->reg_reset,
-                                       0x34);
-       return err;
-}
-
-static int sx150x_init_hw(struct sx150x_chip *chip,
-                       struct sx150x_platform_data *pdata)
-{
-       int err = 0;
-
-       if (pdata->reset_during_probe) {
-               err = sx150x_reset(chip);
-               if (err < 0)
-                       return err;
-       }
-
-       err = sx150x_i2c_write(chip->client,
-                       chip->dev_cfg->reg_misc,
-                       0x01);
-       if (err < 0)
-               return err;
-
-       err = sx150x_init_io(chip, chip->dev_cfg->reg_pullup,
-                       pdata->io_pullup_ena);
-       if (err < 0)
-               return err;
-
-       err = sx150x_init_io(chip, chip->dev_cfg->reg_pulldn,
-                       pdata->io_pulldn_ena);
-       if (err < 0)
-               return err;
-
-       err = sx150x_init_io(chip, chip->dev_cfg->reg_drain,
-                       pdata->io_open_drain_ena);
-       if (err < 0)
-               return err;
-
-       err = sx150x_init_io(chip, chip->dev_cfg->reg_polarity,
-                       pdata->io_polarity);
-       if (err < 0)
-               return err;
-
-       if (pdata->oscio_is_gpo)
-               sx150x_set_oscio(chip, 0);
-
-       return err;
-}
-
-static int sx150x_install_irq_chip(struct sx150x_chip *chip,
-                               int irq_summary,
-                               int irq_base)
-{
-       int err;
-       unsigned n;
-       unsigned irq;
-
-       chip->irq_summary = irq_summary;
-       chip->irq_base    = irq_base;
-
-       for (n = 0; n < chip->dev_cfg->ngpios; ++n) {
-               irq = irq_base + n;
-               irq_set_chip_and_handler(irq, &chip->irq_chip, handle_edge_irq);
-               irq_set_nested_thread(irq, 1);
-#ifdef CONFIG_ARM
-               set_irq_flags(irq, IRQF_VALID);
-#else
-               irq_set_noprobe(irq);
-#endif
-       }
-
-       err = request_threaded_irq(irq_summary,
-                               NULL,
-                               sx150x_irq_thread_fn,
-                               IRQF_SHARED | IRQF_TRIGGER_FALLING,
-                               chip->irq_chip.name,
-                               chip);
-       if (err < 0) {
-               chip->irq_summary = -1;
-               chip->irq_base    = -1;
-       }
-
-       return err;
-}
-
-static void sx150x_remove_irq_chip(struct sx150x_chip *chip)
-{
-       unsigned n;
-       unsigned irq;
-
-       free_irq(chip->irq_summary, chip);
-
-       for (n = 0; n < chip->dev_cfg->ngpios; ++n) {
-               irq = chip->irq_base + n;
-               irq_set_chip_and_handler(irq, NULL, NULL);
-       }
-}
-
-static int __devinit sx150x_probe(struct i2c_client *client,
-                               const struct i2c_device_id *id)
-{
-       static const u32 i2c_funcs = I2C_FUNC_SMBUS_BYTE_DATA |
-                                    I2C_FUNC_SMBUS_WRITE_WORD_DATA;
-       struct sx150x_platform_data *pdata;
-       struct sx150x_chip *chip;
-       int rc;
-
-       pdata = client->dev.platform_data;
-       if (!pdata)
-               return -EINVAL;
-
-       if (!i2c_check_functionality(client->adapter, i2c_funcs))
-               return -ENOSYS;
-
-       chip = kzalloc(sizeof(struct sx150x_chip), GFP_KERNEL);
-       if (!chip)
-               return -ENOMEM;
-
-       sx150x_init_chip(chip, client, id->driver_data, pdata);
-       rc = sx150x_init_hw(chip, pdata);
-       if (rc < 0)
-               goto probe_fail_pre_gpiochip_add;
-
-       rc = gpiochip_add(&chip->gpio_chip);
-       if (rc < 0)
-               goto probe_fail_pre_gpiochip_add;
-
-       if (pdata->irq_summary >= 0) {
-               rc = sx150x_install_irq_chip(chip,
-                                       pdata->irq_summary,
-                                       pdata->irq_base);
-               if (rc < 0)
-                       goto probe_fail_post_gpiochip_add;
-       }
-
-       i2c_set_clientdata(client, chip);
-
-       return 0;
-probe_fail_post_gpiochip_add:
-       WARN_ON(gpiochip_remove(&chip->gpio_chip) < 0);
-probe_fail_pre_gpiochip_add:
-       kfree(chip);
-       return rc;
-}
-
-static int __devexit sx150x_remove(struct i2c_client *client)
-{
-       struct sx150x_chip *chip;
-       int rc;
-
-       chip = i2c_get_clientdata(client);
-       rc = gpiochip_remove(&chip->gpio_chip);
-       if (rc < 0)
-               return rc;
-
-       if (chip->irq_summary >= 0)
-               sx150x_remove_irq_chip(chip);
-
-       kfree(chip);
-
-       return 0;
-}
-
-static struct i2c_driver sx150x_driver = {
-       .driver = {
-               .name = "sx150x",
-               .owner = THIS_MODULE
-       },
-       .probe    = sx150x_probe,
-       .remove   = __devexit_p(sx150x_remove),
-       .id_table = sx150x_id,
-};
-
-static int __init sx150x_init(void)
-{
-       return i2c_add_driver(&sx150x_driver);
-}
-subsys_initcall(sx150x_init);
-
-static void __exit sx150x_exit(void)
-{
-       return i2c_del_driver(&sx150x_driver);
-}
-module_exit(sx150x_exit);
-
-MODULE_AUTHOR("Gregory Bean <gbean@codeaurora.org>");
-MODULE_DESCRIPTION("Driver for Semtech SX150X I2C GPIO Expanders");
-MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("i2c:sx150x");
diff --git a/drivers/gpio/tc3589x-gpio.c b/drivers/gpio/tc3589x-gpio.c
deleted file mode 100644 (file)
index 2a82e89..0000000
+++ /dev/null
@@ -1,389 +0,0 @@
-/*
- * Copyright (C) ST-Ericsson SA 2010
- *
- * License Terms: GNU General Public License, version 2
- * Author: Hanumath Prasad <hanumath.prasad@stericsson.com> for ST-Ericsson
- * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include <linux/gpio.h>
-#include <linux/irq.h>
-#include <linux/interrupt.h>
-#include <linux/mfd/tc3589x.h>
-
-/*
- * These registers are modified under the irq bus lock and cached to avoid
- * unnecessary writes in bus_sync_unlock.
- */
-enum { REG_IBE, REG_IEV, REG_IS, REG_IE };
-
-#define CACHE_NR_REGS  4
-#define CACHE_NR_BANKS 3
-
-struct tc3589x_gpio {
-       struct gpio_chip chip;
-       struct tc3589x *tc3589x;
-       struct device *dev;
-       struct mutex irq_lock;
-
-       int irq_base;
-
-       /* Caches of interrupt control registers for bus_lock */
-       u8 regs[CACHE_NR_REGS][CACHE_NR_BANKS];
-       u8 oldregs[CACHE_NR_REGS][CACHE_NR_BANKS];
-};
-
-static inline struct tc3589x_gpio *to_tc3589x_gpio(struct gpio_chip *chip)
-{
-       return container_of(chip, struct tc3589x_gpio, chip);
-}
-
-static int tc3589x_gpio_get(struct gpio_chip *chip, unsigned offset)
-{
-       struct tc3589x_gpio *tc3589x_gpio = to_tc3589x_gpio(chip);
-       struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
-       u8 reg = TC3589x_GPIODATA0 + (offset / 8) * 2;
-       u8 mask = 1 << (offset % 8);
-       int ret;
-
-       ret = tc3589x_reg_read(tc3589x, reg);
-       if (ret < 0)
-               return ret;
-
-       return ret & mask;
-}
-
-static void tc3589x_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
-{
-       struct tc3589x_gpio *tc3589x_gpio = to_tc3589x_gpio(chip);
-       struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
-       u8 reg = TC3589x_GPIODATA0 + (offset / 8) * 2;
-       unsigned pos = offset % 8;
-       u8 data[] = {!!val << pos, 1 << pos};
-
-       tc3589x_block_write(tc3589x, reg, ARRAY_SIZE(data), data);
-}
-
-static int tc3589x_gpio_direction_output(struct gpio_chip *chip,
-                                        unsigned offset, int val)
-{
-       struct tc3589x_gpio *tc3589x_gpio = to_tc3589x_gpio(chip);
-       struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
-       u8 reg = TC3589x_GPIODIR0 + offset / 8;
-       unsigned pos = offset % 8;
-
-       tc3589x_gpio_set(chip, offset, val);
-
-       return tc3589x_set_bits(tc3589x, reg, 1 << pos, 1 << pos);
-}
-
-static int tc3589x_gpio_direction_input(struct gpio_chip *chip,
-                                       unsigned offset)
-{
-       struct tc3589x_gpio *tc3589x_gpio = to_tc3589x_gpio(chip);
-       struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
-       u8 reg = TC3589x_GPIODIR0 + offset / 8;
-       unsigned pos = offset % 8;
-
-       return tc3589x_set_bits(tc3589x, reg, 1 << pos, 0);
-}
-
-static int tc3589x_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
-{
-       struct tc3589x_gpio *tc3589x_gpio = to_tc3589x_gpio(chip);
-
-       return tc3589x_gpio->irq_base + offset;
-}
-
-static struct gpio_chip template_chip = {
-       .label                  = "tc3589x",
-       .owner                  = THIS_MODULE,
-       .direction_input        = tc3589x_gpio_direction_input,
-       .get                    = tc3589x_gpio_get,
-       .direction_output       = tc3589x_gpio_direction_output,
-       .set                    = tc3589x_gpio_set,
-       .to_irq                 = tc3589x_gpio_to_irq,
-       .can_sleep              = 1,
-};
-
-static int tc3589x_gpio_irq_set_type(struct irq_data *d, unsigned int type)
-{
-       struct tc3589x_gpio *tc3589x_gpio = irq_data_get_irq_chip_data(d);
-       int offset = d->irq - tc3589x_gpio->irq_base;
-       int regoffset = offset / 8;
-       int mask = 1 << (offset % 8);
-
-       if (type == IRQ_TYPE_EDGE_BOTH) {
-               tc3589x_gpio->regs[REG_IBE][regoffset] |= mask;
-               return 0;
-       }
-
-       tc3589x_gpio->regs[REG_IBE][regoffset] &= ~mask;
-
-       if (type == IRQ_TYPE_LEVEL_LOW || type == IRQ_TYPE_LEVEL_HIGH)
-               tc3589x_gpio->regs[REG_IS][regoffset] |= mask;
-       else
-               tc3589x_gpio->regs[REG_IS][regoffset] &= ~mask;
-
-       if (type == IRQ_TYPE_EDGE_RISING || type == IRQ_TYPE_LEVEL_HIGH)
-               tc3589x_gpio->regs[REG_IEV][regoffset] |= mask;
-       else
-               tc3589x_gpio->regs[REG_IEV][regoffset] &= ~mask;
-
-       return 0;
-}
-
-static void tc3589x_gpio_irq_lock(struct irq_data *d)
-{
-       struct tc3589x_gpio *tc3589x_gpio = irq_data_get_irq_chip_data(d);
-
-       mutex_lock(&tc3589x_gpio->irq_lock);
-}
-
-static void tc3589x_gpio_irq_sync_unlock(struct irq_data *d)
-{
-       struct tc3589x_gpio *tc3589x_gpio = irq_data_get_irq_chip_data(d);
-       struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
-       static const u8 regmap[] = {
-               [REG_IBE]       = TC3589x_GPIOIBE0,
-               [REG_IEV]       = TC3589x_GPIOIEV0,
-               [REG_IS]        = TC3589x_GPIOIS0,
-               [REG_IE]        = TC3589x_GPIOIE0,
-       };
-       int i, j;
-
-       for (i = 0; i < CACHE_NR_REGS; i++) {
-               for (j = 0; j < CACHE_NR_BANKS; j++) {
-                       u8 old = tc3589x_gpio->oldregs[i][j];
-                       u8 new = tc3589x_gpio->regs[i][j];
-
-                       if (new == old)
-                               continue;
-
-                       tc3589x_gpio->oldregs[i][j] = new;
-                       tc3589x_reg_write(tc3589x, regmap[i] + j * 8, new);
-               }
-       }
-
-       mutex_unlock(&tc3589x_gpio->irq_lock);
-}
-
-static void tc3589x_gpio_irq_mask(struct irq_data *d)
-{
-       struct tc3589x_gpio *tc3589x_gpio = irq_data_get_irq_chip_data(d);
-       int offset = d->irq - tc3589x_gpio->irq_base;
-       int regoffset = offset / 8;
-       int mask = 1 << (offset % 8);
-
-       tc3589x_gpio->regs[REG_IE][regoffset] &= ~mask;
-}
-
-static void tc3589x_gpio_irq_unmask(struct irq_data *d)
-{
-       struct tc3589x_gpio *tc3589x_gpio = irq_data_get_irq_chip_data(d);
-       int offset = d->irq - tc3589x_gpio->irq_base;
-       int regoffset = offset / 8;
-       int mask = 1 << (offset % 8);
-
-       tc3589x_gpio->regs[REG_IE][regoffset] |= mask;
-}
-
-static struct irq_chip tc3589x_gpio_irq_chip = {
-       .name                   = "tc3589x-gpio",
-       .irq_bus_lock           = tc3589x_gpio_irq_lock,
-       .irq_bus_sync_unlock    = tc3589x_gpio_irq_sync_unlock,
-       .irq_mask               = tc3589x_gpio_irq_mask,
-       .irq_unmask             = tc3589x_gpio_irq_unmask,
-       .irq_set_type           = tc3589x_gpio_irq_set_type,
-};
-
-static irqreturn_t tc3589x_gpio_irq(int irq, void *dev)
-{
-       struct tc3589x_gpio *tc3589x_gpio = dev;
-       struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
-       u8 status[CACHE_NR_BANKS];
-       int ret;
-       int i;
-
-       ret = tc3589x_block_read(tc3589x, TC3589x_GPIOMIS0,
-                                ARRAY_SIZE(status), status);
-       if (ret < 0)
-               return IRQ_NONE;
-
-       for (i = 0; i < ARRAY_SIZE(status); i++) {
-               unsigned int stat = status[i];
-               if (!stat)
-                       continue;
-
-               while (stat) {
-                       int bit = __ffs(stat);
-                       int line = i * 8 + bit;
-
-                       handle_nested_irq(tc3589x_gpio->irq_base + line);
-                       stat &= ~(1 << bit);
-               }
-
-               tc3589x_reg_write(tc3589x, TC3589x_GPIOIC0 + i, status[i]);
-       }
-
-       return IRQ_HANDLED;
-}
-
-static int tc3589x_gpio_irq_init(struct tc3589x_gpio *tc3589x_gpio)
-{
-       int base = tc3589x_gpio->irq_base;
-       int irq;
-
-       for (irq = base; irq < base + tc3589x_gpio->chip.ngpio; irq++) {
-               irq_set_chip_data(irq, tc3589x_gpio);
-               irq_set_chip_and_handler(irq, &tc3589x_gpio_irq_chip,
-                                        handle_simple_irq);
-               irq_set_nested_thread(irq, 1);
-#ifdef CONFIG_ARM
-               set_irq_flags(irq, IRQF_VALID);
-#else
-               irq_set_noprobe(irq);
-#endif
-       }
-
-       return 0;
-}
-
-static void tc3589x_gpio_irq_remove(struct tc3589x_gpio *tc3589x_gpio)
-{
-       int base = tc3589x_gpio->irq_base;
-       int irq;
-
-       for (irq = base; irq < base + tc3589x_gpio->chip.ngpio; irq++) {
-#ifdef CONFIG_ARM
-               set_irq_flags(irq, 0);
-#endif
-               irq_set_chip_and_handler(irq, NULL, NULL);
-               irq_set_chip_data(irq, NULL);
-       }
-}
-
-static int __devinit tc3589x_gpio_probe(struct platform_device *pdev)
-{
-       struct tc3589x *tc3589x = dev_get_drvdata(pdev->dev.parent);
-       struct tc3589x_gpio_platform_data *pdata;
-       struct tc3589x_gpio *tc3589x_gpio;
-       int ret;
-       int irq;
-
-       pdata = tc3589x->pdata->gpio;
-       if (!pdata)
-               return -ENODEV;
-
-       irq = platform_get_irq(pdev, 0);
-       if (irq < 0)
-               return irq;
-
-       tc3589x_gpio = kzalloc(sizeof(struct tc3589x_gpio), GFP_KERNEL);
-       if (!tc3589x_gpio)
-               return -ENOMEM;
-
-       mutex_init(&tc3589x_gpio->irq_lock);
-
-       tc3589x_gpio->dev = &pdev->dev;
-       tc3589x_gpio->tc3589x = tc3589x;
-
-       tc3589x_gpio->chip = template_chip;
-       tc3589x_gpio->chip.ngpio = tc3589x->num_gpio;
-       tc3589x_gpio->chip.dev = &pdev->dev;
-       tc3589x_gpio->chip.base = pdata->gpio_base;
-
-       tc3589x_gpio->irq_base = tc3589x->irq_base + TC3589x_INT_GPIO(0);
-
-       /* Bring the GPIO module out of reset */
-       ret = tc3589x_set_bits(tc3589x, TC3589x_RSTCTRL,
-                              TC3589x_RSTCTRL_GPIRST, 0);
-       if (ret < 0)
-               goto out_free;
-
-       ret = tc3589x_gpio_irq_init(tc3589x_gpio);
-       if (ret)
-               goto out_free;
-
-       ret = request_threaded_irq(irq, NULL, tc3589x_gpio_irq, IRQF_ONESHOT,
-                                  "tc3589x-gpio", tc3589x_gpio);
-       if (ret) {
-               dev_err(&pdev->dev, "unable to get irq: %d\n", ret);
-               goto out_removeirq;
-       }
-
-       ret = gpiochip_add(&tc3589x_gpio->chip);
-       if (ret) {
-               dev_err(&pdev->dev, "unable to add gpiochip: %d\n", ret);
-               goto out_freeirq;
-       }
-
-       if (pdata->setup)
-               pdata->setup(tc3589x, tc3589x_gpio->chip.base);
-
-       platform_set_drvdata(pdev, tc3589x_gpio);
-
-       return 0;
-
-out_freeirq:
-       free_irq(irq, tc3589x_gpio);
-out_removeirq:
-       tc3589x_gpio_irq_remove(tc3589x_gpio);
-out_free:
-       kfree(tc3589x_gpio);
-       return ret;
-}
-
-static int __devexit tc3589x_gpio_remove(struct platform_device *pdev)
-{
-       struct tc3589x_gpio *tc3589x_gpio = platform_get_drvdata(pdev);
-       struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
-       struct tc3589x_gpio_platform_data *pdata = tc3589x->pdata->gpio;
-       int irq = platform_get_irq(pdev, 0);
-       int ret;
-
-       if (pdata->remove)
-               pdata->remove(tc3589x, tc3589x_gpio->chip.base);
-
-       ret = gpiochip_remove(&tc3589x_gpio->chip);
-       if (ret < 0) {
-               dev_err(tc3589x_gpio->dev,
-                       "unable to remove gpiochip: %d\n", ret);
-               return ret;
-       }
-
-       free_irq(irq, tc3589x_gpio);
-       tc3589x_gpio_irq_remove(tc3589x_gpio);
-
-       platform_set_drvdata(pdev, NULL);
-       kfree(tc3589x_gpio);
-
-       return 0;
-}
-
-static struct platform_driver tc3589x_gpio_driver = {
-       .driver.name    = "tc3589x-gpio",
-       .driver.owner   = THIS_MODULE,
-       .probe          = tc3589x_gpio_probe,
-       .remove         = __devexit_p(tc3589x_gpio_remove),
-};
-
-static int __init tc3589x_gpio_init(void)
-{
-       return platform_driver_register(&tc3589x_gpio_driver);
-}
-subsys_initcall(tc3589x_gpio_init);
-
-static void __exit tc3589x_gpio_exit(void)
-{
-       platform_driver_unregister(&tc3589x_gpio_driver);
-}
-module_exit(tc3589x_gpio_exit);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("TC3589x GPIO driver");
-MODULE_AUTHOR("Hanumath Prasad, Rabin Vincent");
diff --git a/drivers/gpio/timbgpio.c b/drivers/gpio/timbgpio.c
deleted file mode 100644 (file)
index 0265872..0000000
+++ /dev/null
@@ -1,379 +0,0 @@
-/*
- * timbgpio.c timberdale FPGA GPIO driver
- * Copyright (c) 2009 Intel Corporation
- *
- * 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.
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-/* Supports:
- * Timberdale FPGA GPIO
- */
-
-#include <linux/module.h>
-#include <linux/gpio.h>
-#include <linux/platform_device.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-#include <linux/timb_gpio.h>
-#include <linux/interrupt.h>
-#include <linux/slab.h>
-
-#define DRIVER_NAME "timb-gpio"
-
-#define TGPIOVAL       0x00
-#define TGPIODIR       0x04
-#define TGPIO_IER      0x08
-#define TGPIO_ISR      0x0c
-#define TGPIO_IPR      0x10
-#define TGPIO_ICR      0x14
-#define TGPIO_FLR      0x18
-#define TGPIO_LVR      0x1c
-#define TGPIO_VER      0x20
-#define TGPIO_BFLR     0x24
-
-struct timbgpio {
-       void __iomem            *membase;
-       spinlock_t              lock; /* mutual exclusion */
-       struct gpio_chip        gpio;
-       int                     irq_base;
-       unsigned long           last_ier;
-};
-
-static int timbgpio_update_bit(struct gpio_chip *gpio, unsigned index,
-       unsigned offset, bool enabled)
-{
-       struct timbgpio *tgpio = container_of(gpio, struct timbgpio, gpio);
-       u32 reg;
-
-       spin_lock(&tgpio->lock);
-       reg = ioread32(tgpio->membase + offset);
-
-       if (enabled)
-               reg |= (1 << index);
-       else
-               reg &= ~(1 << index);
-
-       iowrite32(reg, tgpio->membase + offset);
-       spin_unlock(&tgpio->lock);
-
-       return 0;
-}
-
-static int timbgpio_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
-{
-       return timbgpio_update_bit(gpio, nr, TGPIODIR, true);
-}
-
-static int timbgpio_gpio_get(struct gpio_chip *gpio, unsigned nr)
-{
-       struct timbgpio *tgpio = container_of(gpio, struct timbgpio, gpio);
-       u32 value;
-
-       value = ioread32(tgpio->membase + TGPIOVAL);
-       return (value & (1 << nr)) ? 1 : 0;
-}
-
-static int timbgpio_gpio_direction_output(struct gpio_chip *gpio,
-                                               unsigned nr, int val)
-{
-       return timbgpio_update_bit(gpio, nr, TGPIODIR, false);
-}
-
-static void timbgpio_gpio_set(struct gpio_chip *gpio,
-                               unsigned nr, int val)
-{
-       timbgpio_update_bit(gpio, nr, TGPIOVAL, val != 0);
-}
-
-static int timbgpio_to_irq(struct gpio_chip *gpio, unsigned offset)
-{
-       struct timbgpio *tgpio = container_of(gpio, struct timbgpio, gpio);
-
-       if (tgpio->irq_base <= 0)
-               return -EINVAL;
-
-       return tgpio->irq_base + offset;
-}
-
-/*
- * GPIO IRQ
- */
-static void timbgpio_irq_disable(struct irq_data *d)
-{
-       struct timbgpio *tgpio = irq_data_get_irq_chip_data(d);
-       int offset = d->irq - tgpio->irq_base;
-       unsigned long flags;
-
-       spin_lock_irqsave(&tgpio->lock, flags);
-       tgpio->last_ier &= ~(1 << offset);
-       iowrite32(tgpio->last_ier, tgpio->membase + TGPIO_IER);
-       spin_unlock_irqrestore(&tgpio->lock, flags);
-}
-
-static void timbgpio_irq_enable(struct irq_data *d)
-{
-       struct timbgpio *tgpio = irq_data_get_irq_chip_data(d);
-       int offset = d->irq - tgpio->irq_base;
-       unsigned long flags;
-
-       spin_lock_irqsave(&tgpio->lock, flags);
-       tgpio->last_ier |= 1 << offset;
-       iowrite32(tgpio->last_ier, tgpio->membase + TGPIO_IER);
-       spin_unlock_irqrestore(&tgpio->lock, flags);
-}
-
-static int timbgpio_irq_type(struct irq_data *d, unsigned trigger)
-{
-       struct timbgpio *tgpio = irq_data_get_irq_chip_data(d);
-       int offset = d->irq - tgpio->irq_base;
-       unsigned long flags;
-       u32 lvr, flr, bflr = 0;
-       u32 ver;
-       int ret = 0;
-
-       if (offset < 0 || offset > tgpio->gpio.ngpio)
-               return -EINVAL;
-
-       ver = ioread32(tgpio->membase + TGPIO_VER);
-
-       spin_lock_irqsave(&tgpio->lock, flags);
-
-       lvr = ioread32(tgpio->membase + TGPIO_LVR);
-       flr = ioread32(tgpio->membase + TGPIO_FLR);
-       if (ver > 2)
-               bflr = ioread32(tgpio->membase + TGPIO_BFLR);
-
-       if (trigger & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {
-               bflr &= ~(1 << offset);
-               flr &= ~(1 << offset);
-               if (trigger & IRQ_TYPE_LEVEL_HIGH)
-                       lvr |= 1 << offset;
-               else
-                       lvr &= ~(1 << offset);
-       }
-
-       if ((trigger & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) {
-               if (ver < 3) {
-                       ret = -EINVAL;
-                       goto out;
-               }
-               else {
-                       flr |= 1 << offset;
-                       bflr |= 1 << offset;
-               }
-       } else {
-               bflr &= ~(1 << offset);
-               flr |= 1 << offset;
-               if (trigger & IRQ_TYPE_EDGE_FALLING)
-                       lvr &= ~(1 << offset);
-               else
-                       lvr |= 1 << offset;
-       }
-
-       iowrite32(lvr, tgpio->membase + TGPIO_LVR);
-       iowrite32(flr, tgpio->membase + TGPIO_FLR);
-       if (ver > 2)
-               iowrite32(bflr, tgpio->membase + TGPIO_BFLR);
-
-       iowrite32(1 << offset, tgpio->membase + TGPIO_ICR);
-
-out:
-       spin_unlock_irqrestore(&tgpio->lock, flags);
-       return ret;
-}
-
-static void timbgpio_irq(unsigned int irq, struct irq_desc *desc)
-{
-       struct timbgpio *tgpio = irq_get_handler_data(irq);
-       unsigned long ipr;
-       int offset;
-
-       desc->irq_data.chip->irq_ack(irq_get_irq_data(irq));
-       ipr = ioread32(tgpio->membase + TGPIO_IPR);
-       iowrite32(ipr, tgpio->membase + TGPIO_ICR);
-
-       /*
-        * Some versions of the hardware trash the IER register if more than
-        * one interrupt is received simultaneously.
-        */
-       iowrite32(0, tgpio->membase + TGPIO_IER);
-
-       for_each_set_bit(offset, &ipr, tgpio->gpio.ngpio)
-               generic_handle_irq(timbgpio_to_irq(&tgpio->gpio, offset));
-
-       iowrite32(tgpio->last_ier, tgpio->membase + TGPIO_IER);
-}
-
-static struct irq_chip timbgpio_irqchip = {
-       .name           = "GPIO",
-       .irq_enable     = timbgpio_irq_enable,
-       .irq_disable    = timbgpio_irq_disable,
-       .irq_set_type   = timbgpio_irq_type,
-};
-
-static int __devinit timbgpio_probe(struct platform_device *pdev)
-{
-       int err, i;
-       struct gpio_chip *gc;
-       struct timbgpio *tgpio;
-       struct resource *iomem;
-       struct timbgpio_platform_data *pdata = pdev->dev.platform_data;
-       int irq = platform_get_irq(pdev, 0);
-
-       if (!pdata || pdata->nr_pins > 32) {
-               err = -EINVAL;
-               goto err_mem;
-       }
-
-       iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!iomem) {
-               err = -EINVAL;
-               goto err_mem;
-       }
-
-       tgpio = kzalloc(sizeof(*tgpio), GFP_KERNEL);
-       if (!tgpio) {
-               err = -EINVAL;
-               goto err_mem;
-       }
-       tgpio->irq_base = pdata->irq_base;
-
-       spin_lock_init(&tgpio->lock);
-
-       if (!request_mem_region(iomem->start, resource_size(iomem),
-               DRIVER_NAME)) {
-               err = -EBUSY;
-               goto err_request;
-       }
-
-       tgpio->membase = ioremap(iomem->start, resource_size(iomem));
-       if (!tgpio->membase) {
-               err = -ENOMEM;
-               goto err_ioremap;
-       }
-
-       gc = &tgpio->gpio;
-
-       gc->label = dev_name(&pdev->dev);
-       gc->owner = THIS_MODULE;
-       gc->dev = &pdev->dev;
-       gc->direction_input = timbgpio_gpio_direction_input;
-       gc->get = timbgpio_gpio_get;
-       gc->direction_output = timbgpio_gpio_direction_output;
-       gc->set = timbgpio_gpio_set;
-       gc->to_irq = (irq >= 0 && tgpio->irq_base > 0) ? timbgpio_to_irq : NULL;
-       gc->dbg_show = NULL;
-       gc->base = pdata->gpio_base;
-       gc->ngpio = pdata->nr_pins;
-       gc->can_sleep = 0;
-
-       err = gpiochip_add(gc);
-       if (err)
-               goto err_chipadd;
-
-       platform_set_drvdata(pdev, tgpio);
-
-       /* make sure to disable interrupts */
-       iowrite32(0x0, tgpio->membase + TGPIO_IER);
-
-       if (irq < 0 || tgpio->irq_base <= 0)
-               return 0;
-
-       for (i = 0; i < pdata->nr_pins; i++) {
-               irq_set_chip_and_handler_name(tgpio->irq_base + i,
-                       &timbgpio_irqchip, handle_simple_irq, "mux");
-               irq_set_chip_data(tgpio->irq_base + i, tgpio);
-#ifdef CONFIG_ARM
-               set_irq_flags(tgpio->irq_base + i, IRQF_VALID | IRQF_PROBE);
-#endif
-       }
-
-       irq_set_handler_data(irq, tgpio);
-       irq_set_chained_handler(irq, timbgpio_irq);
-
-       return 0;
-
-err_chipadd:
-       iounmap(tgpio->membase);
-err_ioremap:
-       release_mem_region(iomem->start, resource_size(iomem));
-err_request:
-       kfree(tgpio);
-err_mem:
-       printk(KERN_ERR DRIVER_NAME": Failed to register GPIOs: %d\n", err);
-
-       return err;
-}
-
-static int __devexit timbgpio_remove(struct platform_device *pdev)
-{
-       int err;
-       struct timbgpio_platform_data *pdata = pdev->dev.platform_data;
-       struct timbgpio *tgpio = platform_get_drvdata(pdev);
-       struct resource *iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       int irq = platform_get_irq(pdev, 0);
-
-       if (irq >= 0 && tgpio->irq_base > 0) {
-               int i;
-               for (i = 0; i < pdata->nr_pins; i++) {
-                       irq_set_chip(tgpio->irq_base + i, NULL);
-                       irq_set_chip_data(tgpio->irq_base + i, NULL);
-               }
-
-               irq_set_handler(irq, NULL);
-               irq_set_handler_data(irq, NULL);
-       }
-
-       err = gpiochip_remove(&tgpio->gpio);
-       if (err)
-               printk(KERN_ERR DRIVER_NAME": failed to remove gpio_chip\n");
-
-       iounmap(tgpio->membase);
-       release_mem_region(iomem->start, resource_size(iomem));
-       kfree(tgpio);
-
-       platform_set_drvdata(pdev, NULL);
-
-       return 0;
-}
-
-static struct platform_driver timbgpio_platform_driver = {
-       .driver = {
-               .name   = DRIVER_NAME,
-               .owner  = THIS_MODULE,
-       },
-       .probe          = timbgpio_probe,
-       .remove         = timbgpio_remove,
-};
-
-/*--------------------------------------------------------------------------*/
-
-static int __init timbgpio_init(void)
-{
-       return platform_driver_register(&timbgpio_platform_driver);
-}
-
-static void __exit timbgpio_exit(void)
-{
-       platform_driver_unregister(&timbgpio_platform_driver);
-}
-
-module_init(timbgpio_init);
-module_exit(timbgpio_exit);
-
-MODULE_DESCRIPTION("Timberdale GPIO driver");
-MODULE_LICENSE("GPL v2");
-MODULE_AUTHOR("Mocean Laboratories");
-MODULE_ALIAS("platform:"DRIVER_NAME);
-
diff --git a/drivers/gpio/tps65910-gpio.c b/drivers/gpio/tps65910-gpio.c
deleted file mode 100644 (file)
index 8d1ddfd..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * tps65910-gpio.c  --  TI TPS6591x
- *
- * Copyright 2010 Texas Instruments Inc.
- *
- * Author: Graeme Gregory <gg@slimlogic.co.uk>
- * Author: Jorge Eduardo Candelaria jedu@slimlogic.co.uk>
- *
- *  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/kernel.h>
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/gpio.h>
-#include <linux/i2c.h>
-#include <linux/mfd/tps65910.h>
-
-static int tps65910_gpio_get(struct gpio_chip *gc, unsigned offset)
-{
-       struct tps65910 *tps65910 = container_of(gc, struct tps65910, gpio);
-       uint8_t val;
-
-       tps65910->read(tps65910, TPS65910_GPIO0 + offset, 1, &val);
-
-       if (val & GPIO_STS_MASK)
-               return 1;
-
-       return 0;
-}
-
-static void tps65910_gpio_set(struct gpio_chip *gc, unsigned offset,
-                             int value)
-{
-       struct tps65910 *tps65910 = container_of(gc, struct tps65910, gpio);
-
-       if (value)
-               tps65910_set_bits(tps65910, TPS65910_GPIO0 + offset,
-                                               GPIO_SET_MASK);
-       else
-               tps65910_clear_bits(tps65910, TPS65910_GPIO0 + offset,
-                                               GPIO_SET_MASK);
-}
-
-static int tps65910_gpio_output(struct gpio_chip *gc, unsigned offset,
-                               int value)
-{
-       struct tps65910 *tps65910 = container_of(gc, struct tps65910, gpio);
-
-       /* Set the initial value */
-       tps65910_gpio_set(gc, 0, value);
-
-       return tps65910_set_bits(tps65910, TPS65910_GPIO0 + offset,
-                                               GPIO_CFG_MASK);
-}
-
-static int tps65910_gpio_input(struct gpio_chip *gc, unsigned offset)
-{
-       struct tps65910 *tps65910 = container_of(gc, struct tps65910, gpio);
-
-       return tps65910_clear_bits(tps65910, TPS65910_GPIO0 + offset,
-                                               GPIO_CFG_MASK);
-}
-
-void tps65910_gpio_init(struct tps65910 *tps65910, int gpio_base)
-{
-       int ret;
-
-       if (!gpio_base)
-               return;
-
-       tps65910->gpio.owner            = THIS_MODULE;
-       tps65910->gpio.label            = tps65910->i2c_client->name;
-       tps65910->gpio.dev              = tps65910->dev;
-       tps65910->gpio.base             = gpio_base;
-
-       switch(tps65910_chip_id(tps65910)) {
-       case TPS65910:
-               tps65910->gpio.ngpio    = 6;
-       case TPS65911:
-               tps65910->gpio.ngpio    = 9;
-       default:
-               return;
-       }
-       tps65910->gpio.can_sleep        = 1;
-
-       tps65910->gpio.direction_input  = tps65910_gpio_input;
-       tps65910->gpio.direction_output = tps65910_gpio_output;
-       tps65910->gpio.set              = tps65910_gpio_set;
-       tps65910->gpio.get              = tps65910_gpio_get;
-
-       ret = gpiochip_add(&tps65910->gpio);
-
-       if (ret)
-               dev_warn(tps65910->dev, "GPIO registration failed: %d\n", ret);
-}
diff --git a/drivers/gpio/twl4030-gpio.c b/drivers/gpio/twl4030-gpio.c
deleted file mode 100644 (file)
index 57635ac..0000000
+++ /dev/null
@@ -1,513 +0,0 @@
-/*
- * twl4030_gpio.c -- access to GPIOs on TWL4030/TPS659x0 chips
- *
- * Copyright (C) 2006-2007 Texas Instruments, Inc.
- * Copyright (C) 2006 MontaVista Software, Inc.
- *
- * Code re-arranged and cleaned up by:
- *     Syed Mohammed Khasim <x0khasim@ti.com>
- *
- * Initial Code:
- *     Andy Lowe / Nishanth Menon
- *
- * 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.
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/kthread.h>
-#include <linux/irq.h>
-#include <linux/gpio.h>
-#include <linux/platform_device.h>
-
-#include <linux/i2c/twl.h>
-
-
-/*
- * The GPIO "subchip" supports 18 GPIOs which can be configured as
- * inputs or outputs, with pullups or pulldowns on each pin.  Each
- * GPIO can trigger interrupts on either or both edges.
- *
- * GPIO interrupts can be fed to either of two IRQ lines; this is
- * intended to support multiple hosts.
- *
- * There are also two LED pins used sometimes as output-only GPIOs.
- */
-
-
-static struct gpio_chip twl_gpiochip;
-static int twl4030_gpio_irq_base;
-
-/* genirq interfaces are not available to modules */
-#ifdef MODULE
-#define is_module()    true
-#else
-#define is_module()    false
-#endif
-
-/* GPIO_CTRL Fields */
-#define MASK_GPIO_CTRL_GPIO0CD1                BIT(0)
-#define MASK_GPIO_CTRL_GPIO1CD2                BIT(1)
-#define MASK_GPIO_CTRL_GPIO_ON         BIT(2)
-
-/* Mask for GPIO registers when aggregated into a 32-bit integer */
-#define GPIO_32_MASK                   0x0003ffff
-
-/* Data structures */
-static DEFINE_MUTEX(gpio_lock);
-
-/* store usage of each GPIO. - each bit represents one GPIO */
-static unsigned int gpio_usage_count;
-
-/*----------------------------------------------------------------------*/
-
-/*
- * To configure TWL4030 GPIO module registers
- */
-static inline int gpio_twl4030_write(u8 address, u8 data)
-{
-       return twl_i2c_write_u8(TWL4030_MODULE_GPIO, data, address);
-}
-
-/*----------------------------------------------------------------------*/
-
-/*
- * LED register offsets (use TWL4030_MODULE_{LED,PWMA,PWMB}))
- * PWMs A and B are dedicated to LEDs A and B, respectively.
- */
-
-#define TWL4030_LED_LEDEN      0x0
-
-/* LEDEN bits */
-#define LEDEN_LEDAON           BIT(0)
-#define LEDEN_LEDBON           BIT(1)
-#define LEDEN_LEDAEXT          BIT(2)
-#define LEDEN_LEDBEXT          BIT(3)
-#define LEDEN_LEDAPWM          BIT(4)
-#define LEDEN_LEDBPWM          BIT(5)
-#define LEDEN_PWM_LENGTHA      BIT(6)
-#define LEDEN_PWM_LENGTHB      BIT(7)
-
-#define TWL4030_PWMx_PWMxON    0x0
-#define TWL4030_PWMx_PWMxOFF   0x1
-
-#define PWMxON_LENGTH          BIT(7)
-
-/*----------------------------------------------------------------------*/
-
-/*
- * To read a TWL4030 GPIO module register
- */
-static inline int gpio_twl4030_read(u8 address)
-{
-       u8 data;
-       int ret = 0;
-
-       ret = twl_i2c_read_u8(TWL4030_MODULE_GPIO, &data, address);
-       return (ret < 0) ? ret : data;
-}
-
-/*----------------------------------------------------------------------*/
-
-static u8 cached_leden;                /* protected by gpio_lock */
-
-/* The LED lines are open drain outputs ... a FET pulls to GND, so an
- * external pullup is needed.  We could also expose the integrated PWM
- * as a LED brightness control; we initialize it as "always on".
- */
-static void twl4030_led_set_value(int led, int value)
-{
-       u8 mask = LEDEN_LEDAON | LEDEN_LEDAPWM;
-       int status;
-
-       if (led)
-               mask <<= 1;
-
-       mutex_lock(&gpio_lock);
-       if (value)
-               cached_leden &= ~mask;
-       else
-               cached_leden |= mask;
-       status = twl_i2c_write_u8(TWL4030_MODULE_LED, cached_leden,
-                       TWL4030_LED_LEDEN);
-       mutex_unlock(&gpio_lock);
-}
-
-static int twl4030_set_gpio_direction(int gpio, int is_input)
-{
-       u8 d_bnk = gpio >> 3;
-       u8 d_msk = BIT(gpio & 0x7);
-       u8 reg = 0;
-       u8 base = REG_GPIODATADIR1 + d_bnk;
-       int ret = 0;
-
-       mutex_lock(&gpio_lock);
-       ret = gpio_twl4030_read(base);
-       if (ret >= 0) {
-               if (is_input)
-                       reg = ret & ~d_msk;
-               else
-                       reg = ret | d_msk;
-
-               ret = gpio_twl4030_write(base, reg);
-       }
-       mutex_unlock(&gpio_lock);
-       return ret;
-}
-
-static int twl4030_set_gpio_dataout(int gpio, int enable)
-{
-       u8 d_bnk = gpio >> 3;
-       u8 d_msk = BIT(gpio & 0x7);
-       u8 base = 0;
-
-       if (enable)
-               base = REG_SETGPIODATAOUT1 + d_bnk;
-       else
-               base = REG_CLEARGPIODATAOUT1 + d_bnk;
-
-       return gpio_twl4030_write(base, d_msk);
-}
-
-static int twl4030_get_gpio_datain(int gpio)
-{
-       u8 d_bnk = gpio >> 3;
-       u8 d_off = gpio & 0x7;
-       u8 base = 0;
-       int ret = 0;
-
-       if (unlikely((gpio >= TWL4030_GPIO_MAX)
-               || !(gpio_usage_count & BIT(gpio))))
-               return -EPERM;
-
-       base = REG_GPIODATAIN1 + d_bnk;
-       ret = gpio_twl4030_read(base);
-       if (ret > 0)
-               ret = (ret >> d_off) & 0x1;
-
-       return ret;
-}
-
-/*----------------------------------------------------------------------*/
-
-static int twl_request(struct gpio_chip *chip, unsigned offset)
-{
-       int status = 0;
-
-       mutex_lock(&gpio_lock);
-
-       /* Support the two LED outputs as output-only GPIOs. */
-       if (offset >= TWL4030_GPIO_MAX) {
-               u8      ledclr_mask = LEDEN_LEDAON | LEDEN_LEDAEXT
-                               | LEDEN_LEDAPWM | LEDEN_PWM_LENGTHA;
-               u8      module = TWL4030_MODULE_PWMA;
-
-               offset -= TWL4030_GPIO_MAX;
-               if (offset) {
-                       ledclr_mask <<= 1;
-                       module = TWL4030_MODULE_PWMB;
-               }
-
-               /* initialize PWM to always-drive */
-               status = twl_i2c_write_u8(module, 0x7f,
-                               TWL4030_PWMx_PWMxOFF);
-               if (status < 0)
-                       goto done;
-               status = twl_i2c_write_u8(module, 0x7f,
-                               TWL4030_PWMx_PWMxON);
-               if (status < 0)
-                       goto done;
-
-               /* init LED to not-driven (high) */
-               module = TWL4030_MODULE_LED;
-               status = twl_i2c_read_u8(module, &cached_leden,
-                               TWL4030_LED_LEDEN);
-               if (status < 0)
-                       goto done;
-               cached_leden &= ~ledclr_mask;
-               status = twl_i2c_write_u8(module, cached_leden,
-                               TWL4030_LED_LEDEN);
-               if (status < 0)
-                       goto done;
-
-               status = 0;
-               goto done;
-       }
-
-       /* on first use, turn GPIO module "on" */
-       if (!gpio_usage_count) {
-               struct twl4030_gpio_platform_data *pdata;
-               u8 value = MASK_GPIO_CTRL_GPIO_ON;
-
-               /* optionally have the first two GPIOs switch vMMC1
-                * and vMMC2 power supplies based on card presence.
-                */
-               pdata = chip->dev->platform_data;
-               value |= pdata->mmc_cd & 0x03;
-
-               status = gpio_twl4030_write(REG_GPIO_CTRL, value);
-       }
-
-       if (!status)
-               gpio_usage_count |= (0x1 << offset);
-
-done:
-       mutex_unlock(&gpio_lock);
-       return status;
-}
-
-static void twl_free(struct gpio_chip *chip, unsigned offset)
-{
-       if (offset >= TWL4030_GPIO_MAX) {
-               twl4030_led_set_value(offset - TWL4030_GPIO_MAX, 1);
-               return;
-       }
-
-       mutex_lock(&gpio_lock);
-
-       gpio_usage_count &= ~BIT(offset);
-
-       /* on last use, switch off GPIO module */
-       if (!gpio_usage_count)
-               gpio_twl4030_write(REG_GPIO_CTRL, 0x0);
-
-       mutex_unlock(&gpio_lock);
-}
-
-static int twl_direction_in(struct gpio_chip *chip, unsigned offset)
-{
-       return (offset < TWL4030_GPIO_MAX)
-               ? twl4030_set_gpio_direction(offset, 1)
-               : -EINVAL;
-}
-
-static int twl_get(struct gpio_chip *chip, unsigned offset)
-{
-       int status = 0;
-
-       if (offset < TWL4030_GPIO_MAX)
-               status = twl4030_get_gpio_datain(offset);
-       else if (offset == TWL4030_GPIO_MAX)
-               status = cached_leden & LEDEN_LEDAON;
-       else
-               status = cached_leden & LEDEN_LEDBON;
-       return (status < 0) ? 0 : status;
-}
-
-static int twl_direction_out(struct gpio_chip *chip, unsigned offset, int value)
-{
-       if (offset < TWL4030_GPIO_MAX) {
-               twl4030_set_gpio_dataout(offset, value);
-               return twl4030_set_gpio_direction(offset, 0);
-       } else {
-               twl4030_led_set_value(offset - TWL4030_GPIO_MAX, value);
-               return 0;
-       }
-}
-
-static void twl_set(struct gpio_chip *chip, unsigned offset, int value)
-{
-       if (offset < TWL4030_GPIO_MAX)
-               twl4030_set_gpio_dataout(offset, value);
-       else
-               twl4030_led_set_value(offset - TWL4030_GPIO_MAX, value);
-}
-
-static int twl_to_irq(struct gpio_chip *chip, unsigned offset)
-{
-       return (twl4030_gpio_irq_base && (offset < TWL4030_GPIO_MAX))
-               ? (twl4030_gpio_irq_base + offset)
-               : -EINVAL;
-}
-
-static struct gpio_chip twl_gpiochip = {
-       .label                  = "twl4030",
-       .owner                  = THIS_MODULE,
-       .request                = twl_request,
-       .free                   = twl_free,
-       .direction_input        = twl_direction_in,
-       .get                    = twl_get,
-       .direction_output       = twl_direction_out,
-       .set                    = twl_set,
-       .to_irq                 = twl_to_irq,
-       .can_sleep              = 1,
-};
-
-/*----------------------------------------------------------------------*/
-
-static int __devinit gpio_twl4030_pulls(u32 ups, u32 downs)
-{
-       u8              message[6];
-       unsigned        i, gpio_bit;
-
-       /* For most pins, a pulldown was enabled by default.
-        * We should have data that's specific to this board.
-        */
-       for (gpio_bit = 1, i = 1; i < 6; i++) {
-               u8              bit_mask;
-               unsigned        j;
-
-               for (bit_mask = 0, j = 0; j < 8; j += 2, gpio_bit <<= 1) {
-                       if (ups & gpio_bit)
-                               bit_mask |= 1 << (j + 1);
-                       else if (downs & gpio_bit)
-                               bit_mask |= 1 << (j + 0);
-               }
-               message[i] = bit_mask;
-       }
-
-       return twl_i2c_write(TWL4030_MODULE_GPIO, message,
-                               REG_GPIOPUPDCTR1, 5);
-}
-
-static int __devinit gpio_twl4030_debounce(u32 debounce, u8 mmc_cd)
-{
-       u8              message[4];
-
-       /* 30 msec of debouncing is always used for MMC card detect,
-        * and is optional for everything else.
-        */
-       message[1] = (debounce & 0xff) | (mmc_cd & 0x03);
-       debounce >>= 8;
-       message[2] = (debounce & 0xff);
-       debounce >>= 8;
-       message[3] = (debounce & 0x03);
-
-       return twl_i2c_write(TWL4030_MODULE_GPIO, message,
-                               REG_GPIO_DEBEN1, 3);
-}
-
-static int gpio_twl4030_remove(struct platform_device *pdev);
-
-static int __devinit gpio_twl4030_probe(struct platform_device *pdev)
-{
-       struct twl4030_gpio_platform_data *pdata = pdev->dev.platform_data;
-       int ret;
-
-       /* maybe setup IRQs */
-       if (pdata->irq_base) {
-               if (is_module()) {
-                       dev_err(&pdev->dev,
-                               "can't dispatch IRQs from modules\n");
-                       goto no_irqs;
-               }
-               ret = twl4030_sih_setup(TWL4030_MODULE_GPIO);
-               if (ret < 0)
-                       return ret;
-               WARN_ON(ret != pdata->irq_base);
-               twl4030_gpio_irq_base = ret;
-       }
-
-no_irqs:
-       /*
-        * NOTE:  boards may waste power if they don't set pullups
-        * and pulldowns correctly ... default for non-ULPI pins is
-        * pulldown, and some other pins may have external pullups
-        * or pulldowns.  Careful!
-        */
-       ret = gpio_twl4030_pulls(pdata->pullups, pdata->pulldowns);
-       if (ret)
-               dev_dbg(&pdev->dev, "pullups %.05x %.05x --> %d\n",
-                               pdata->pullups, pdata->pulldowns,
-                               ret);
-
-       ret = gpio_twl4030_debounce(pdata->debounce, pdata->mmc_cd);
-       if (ret)
-               dev_dbg(&pdev->dev, "debounce %.03x %.01x --> %d\n",
-                               pdata->debounce, pdata->mmc_cd,
-                               ret);
-
-       twl_gpiochip.base = pdata->gpio_base;
-       twl_gpiochip.ngpio = TWL4030_GPIO_MAX;
-       twl_gpiochip.dev = &pdev->dev;
-
-       /* NOTE: we assume VIBRA_CTL.VIBRA_EN, in MODULE_AUDIO_VOICE,
-        * is (still) clear if use_leds is set.
-        */
-       if (pdata->use_leds)
-               twl_gpiochip.ngpio += 2;
-
-       ret = gpiochip_add(&twl_gpiochip);
-       if (ret < 0) {
-               dev_err(&pdev->dev,
-                               "could not register gpiochip, %d\n",
-                               ret);
-               twl_gpiochip.ngpio = 0;
-               gpio_twl4030_remove(pdev);
-       } else if (pdata->setup) {
-               int status;
-
-               status = pdata->setup(&pdev->dev,
-                               pdata->gpio_base, TWL4030_GPIO_MAX);
-               if (status)
-                       dev_dbg(&pdev->dev, "setup --> %d\n", status);
-       }
-
-       return ret;
-}
-
-/* Cannot use __devexit 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;
-       int status;
-
-       if (pdata->teardown) {
-               status = pdata->teardown(&pdev->dev,
-                               pdata->gpio_base, TWL4030_GPIO_MAX);
-               if (status) {
-                       dev_dbg(&pdev->dev, "teardown --> %d\n", status);
-                       return status;
-               }
-       }
-
-       status = gpiochip_remove(&twl_gpiochip);
-       if (status < 0)
-               return status;
-
-       if (is_module())
-               return 0;
-
-       /* REVISIT no support yet for deregistering all the IRQs */
-       WARN_ON(1);
-       return -EIO;
-}
-
-/* Note:  this hardware lives inside an I2C-based multi-function device. */
-MODULE_ALIAS("platform:twl4030_gpio");
-
-static struct platform_driver gpio_twl4030_driver = {
-       .driver.name    = "twl4030_gpio",
-       .driver.owner   = THIS_MODULE,
-       .probe          = gpio_twl4030_probe,
-       .remove         = gpio_twl4030_remove,
-};
-
-static int __init gpio_twl4030_init(void)
-{
-       return platform_driver_register(&gpio_twl4030_driver);
-}
-subsys_initcall(gpio_twl4030_init);
-
-static void __exit gpio_twl4030_exit(void)
-{
-       platform_driver_unregister(&gpio_twl4030_driver);
-}
-module_exit(gpio_twl4030_exit);
-
-MODULE_AUTHOR("Texas Instruments, Inc.");
-MODULE_DESCRIPTION("GPIO interface for TWL4030");
-MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/ucb1400_gpio.c b/drivers/gpio/ucb1400_gpio.c
deleted file mode 100644 (file)
index 50e6bd1..0000000
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Philips UCB1400 GPIO driver
- *
- * Author: Marek Vasut <marek.vasut@gmail.com>
- *
- * 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/module.h>
-#include <linux/ucb1400.h>
-
-struct ucb1400_gpio_data *ucbdata;
-
-static int ucb1400_gpio_dir_in(struct gpio_chip *gc, unsigned off)
-{
-       struct ucb1400_gpio *gpio;
-       gpio = container_of(gc, struct ucb1400_gpio, gc);
-       ucb1400_gpio_set_direction(gpio->ac97, off, 0);
-       return 0;
-}
-
-static int ucb1400_gpio_dir_out(struct gpio_chip *gc, unsigned off, int val)
-{
-       struct ucb1400_gpio *gpio;
-       gpio = container_of(gc, struct ucb1400_gpio, gc);
-       ucb1400_gpio_set_direction(gpio->ac97, off, 1);
-       ucb1400_gpio_set_value(gpio->ac97, off, val);
-       return 0;
-}
-
-static int ucb1400_gpio_get(struct gpio_chip *gc, unsigned off)
-{
-       struct ucb1400_gpio *gpio;
-       gpio = container_of(gc, struct ucb1400_gpio, gc);
-       return ucb1400_gpio_get_value(gpio->ac97, off);
-}
-
-static void ucb1400_gpio_set(struct gpio_chip *gc, unsigned off, int val)
-{
-       struct ucb1400_gpio *gpio;
-       gpio = container_of(gc, struct ucb1400_gpio, gc);
-       ucb1400_gpio_set_value(gpio->ac97, off, val);
-}
-
-static int ucb1400_gpio_probe(struct platform_device *dev)
-{
-       struct ucb1400_gpio *ucb = dev->dev.platform_data;
-       int err = 0;
-
-       if (!(ucbdata && ucbdata->gpio_offset)) {
-               err = -EINVAL;
-               goto err;
-       }
-
-       platform_set_drvdata(dev, ucb);
-
-       ucb->gc.label = "ucb1400_gpio";
-       ucb->gc.base = ucbdata->gpio_offset;
-       ucb->gc.ngpio = 10;
-       ucb->gc.owner = THIS_MODULE;
-
-       ucb->gc.direction_input = ucb1400_gpio_dir_in;
-       ucb->gc.direction_output = ucb1400_gpio_dir_out;
-       ucb->gc.get = ucb1400_gpio_get;
-       ucb->gc.set = ucb1400_gpio_set;
-       ucb->gc.can_sleep = 1;
-
-       err = gpiochip_add(&ucb->gc);
-       if (err)
-               goto err;
-
-       if (ucbdata && ucbdata->gpio_setup)
-               err = ucbdata->gpio_setup(&dev->dev, ucb->gc.ngpio);
-
-err:
-       return err;
-
-}
-
-static int ucb1400_gpio_remove(struct platform_device *dev)
-{
-       int err = 0;
-       struct ucb1400_gpio *ucb = platform_get_drvdata(dev);
-
-       if (ucbdata && ucbdata->gpio_teardown) {
-               err = ucbdata->gpio_teardown(&dev->dev, ucb->gc.ngpio);
-               if (err)
-                       return err;
-       }
-
-       err = gpiochip_remove(&ucb->gc);
-       return err;
-}
-
-static struct platform_driver ucb1400_gpio_driver = {
-       .probe  = ucb1400_gpio_probe,
-       .remove = ucb1400_gpio_remove,
-       .driver = {
-               .name   = "ucb1400_gpio"
-       },
-};
-
-static int __init ucb1400_gpio_init(void)
-{
-       return platform_driver_register(&ucb1400_gpio_driver);
-}
-
-static void __exit ucb1400_gpio_exit(void)
-{
-       platform_driver_unregister(&ucb1400_gpio_driver);
-}
-
-void __init ucb1400_gpio_set_data(struct ucb1400_gpio_data *data)
-{
-       ucbdata = data;
-}
-
-module_init(ucb1400_gpio_init);
-module_exit(ucb1400_gpio_exit);
-
-MODULE_DESCRIPTION("Philips UCB1400 GPIO driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/vr41xx_giu.c b/drivers/gpio/vr41xx_giu.c
deleted file mode 100644 (file)
index a365be0..0000000
+++ /dev/null
@@ -1,585 +0,0 @@
-/*
- *  Driver for NEC VR4100 series General-purpose I/O Unit.
- *
- *  Copyright (C) 2002 MontaVista Software Inc.
- *     Author: Yoichi Yuasa <source@mvista.com>
- *  Copyright (C) 2003-2009  Yoichi Yuasa <yuasa@linux-mips.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.
- *
- *  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.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/gpio.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/irq.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/spinlock.h>
-#include <linux/types.h>
-
-#include <asm/vr41xx/giu.h>
-#include <asm/vr41xx/irq.h>
-#include <asm/vr41xx/vr41xx.h>
-
-MODULE_AUTHOR("Yoichi Yuasa <yuasa@linux-mips.org>");
-MODULE_DESCRIPTION("NEC VR4100 series General-purpose I/O Unit driver");
-MODULE_LICENSE("GPL");
-
-#define GIUIOSELL      0x00
-#define GIUIOSELH      0x02
-#define GIUPIODL       0x04
-#define GIUPIODH       0x06
-#define GIUINTSTATL    0x08
-#define GIUINTSTATH    0x0a
-#define GIUINTENL      0x0c
-#define GIUINTENH      0x0e
-#define GIUINTTYPL     0x10
-#define GIUINTTYPH     0x12
-#define GIUINTALSELL   0x14
-#define GIUINTALSELH   0x16
-#define GIUINTHTSELL   0x18
-#define GIUINTHTSELH   0x1a
-#define GIUPODATL      0x1c
-#define GIUPODATEN     0x1c
-#define GIUPODATH      0x1e
- #define PIOEN0                0x0100
- #define PIOEN1                0x0200
-#define GIUPODAT       0x1e
-#define GIUFEDGEINHL   0x20
-#define GIUFEDGEINHH   0x22
-#define GIUREDGEINHL   0x24
-#define GIUREDGEINHH   0x26
-
-#define GIUUSEUPDN     0x1e0
-#define GIUTERMUPDN    0x1e2
-
-#define GPIO_HAS_PULLUPDOWN_IO         0x0001
-#define GPIO_HAS_OUTPUT_ENABLE         0x0002
-#define GPIO_HAS_INTERRUPT_EDGE_SELECT 0x0100
-
-enum {
-       GPIO_INPUT,
-       GPIO_OUTPUT,
-};
-
-static DEFINE_SPINLOCK(giu_lock);
-static unsigned long giu_flags;
-
-static void __iomem *giu_base;
-
-#define giu_read(offset)               readw(giu_base + (offset))
-#define giu_write(offset, value)       writew((value), giu_base + (offset))
-
-#define GPIO_PIN_OF_IRQ(irq)   ((irq) - GIU_IRQ_BASE)
-#define GIUINT_HIGH_OFFSET     16
-#define GIUINT_HIGH_MAX                32
-
-static inline u16 giu_set(u16 offset, u16 set)
-{
-       u16 data;
-
-       data = giu_read(offset);
-       data |= set;
-       giu_write(offset, data);
-
-       return data;
-}
-
-static inline u16 giu_clear(u16 offset, u16 clear)
-{
-       u16 data;
-
-       data = giu_read(offset);
-       data &= ~clear;
-       giu_write(offset, data);
-
-       return data;
-}
-
-static void ack_giuint_low(struct irq_data *d)
-{
-       giu_write(GIUINTSTATL, 1 << GPIO_PIN_OF_IRQ(d->irq));
-}
-
-static void mask_giuint_low(struct irq_data *d)
-{
-       giu_clear(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(d->irq));
-}
-
-static void mask_ack_giuint_low(struct irq_data *d)
-{
-       unsigned int pin;
-
-       pin = GPIO_PIN_OF_IRQ(d->irq);
-       giu_clear(GIUINTENL, 1 << pin);
-       giu_write(GIUINTSTATL, 1 << pin);
-}
-
-static void unmask_giuint_low(struct irq_data *d)
-{
-       giu_set(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(d->irq));
-}
-
-static struct irq_chip giuint_low_irq_chip = {
-       .name           = "GIUINTL",
-       .irq_ack        = ack_giuint_low,
-       .irq_mask       = mask_giuint_low,
-       .irq_mask_ack   = mask_ack_giuint_low,
-       .irq_unmask     = unmask_giuint_low,
-};
-
-static void ack_giuint_high(struct irq_data *d)
-{
-       giu_write(GIUINTSTATH,
-                 1 << (GPIO_PIN_OF_IRQ(d->irq) - GIUINT_HIGH_OFFSET));
-}
-
-static void mask_giuint_high(struct irq_data *d)
-{
-       giu_clear(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(d->irq) - GIUINT_HIGH_OFFSET));
-}
-
-static void mask_ack_giuint_high(struct irq_data *d)
-{
-       unsigned int pin;
-
-       pin = GPIO_PIN_OF_IRQ(d->irq) - GIUINT_HIGH_OFFSET;
-       giu_clear(GIUINTENH, 1 << pin);
-       giu_write(GIUINTSTATH, 1 << pin);
-}
-
-static void unmask_giuint_high(struct irq_data *d)
-{
-       giu_set(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(d->irq) - GIUINT_HIGH_OFFSET));
-}
-
-static struct irq_chip giuint_high_irq_chip = {
-       .name           = "GIUINTH",
-       .irq_ack        = ack_giuint_high,
-       .irq_mask       = mask_giuint_high,
-       .irq_mask_ack   = mask_ack_giuint_high,
-       .irq_unmask     = unmask_giuint_high,
-};
-
-static int giu_get_irq(unsigned int irq)
-{
-       u16 pendl, pendh, maskl, maskh;
-       int i;
-
-       pendl = giu_read(GIUINTSTATL);
-       pendh = giu_read(GIUINTSTATH);
-       maskl = giu_read(GIUINTENL);
-       maskh = giu_read(GIUINTENH);
-
-       maskl &= pendl;
-       maskh &= pendh;
-
-       if (maskl) {
-               for (i = 0; i < 16; i++) {
-                       if (maskl & (1 << i))
-                               return GIU_IRQ(i);
-               }
-       } else if (maskh) {
-               for (i = 0; i < 16; i++) {
-                       if (maskh & (1 << i))
-                               return GIU_IRQ(i + GIUINT_HIGH_OFFSET);
-               }
-       }
-
-       printk(KERN_ERR "spurious GIU interrupt: %04x(%04x),%04x(%04x)\n",
-              maskl, pendl, maskh, pendh);
-
-       atomic_inc(&irq_err_count);
-
-       return -EINVAL;
-}
-
-void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger,
-                           irq_signal_t signal)
-{
-       u16 mask;
-
-       if (pin < GIUINT_HIGH_OFFSET) {
-               mask = 1 << pin;
-               if (trigger != IRQ_TRIGGER_LEVEL) {
-                       giu_set(GIUINTTYPL, mask);
-                       if (signal == IRQ_SIGNAL_HOLD)
-                               giu_set(GIUINTHTSELL, mask);
-                       else
-                               giu_clear(GIUINTHTSELL, mask);
-                       if (giu_flags & GPIO_HAS_INTERRUPT_EDGE_SELECT) {
-                               switch (trigger) {
-                               case IRQ_TRIGGER_EDGE_FALLING:
-                                       giu_set(GIUFEDGEINHL, mask);
-                                       giu_clear(GIUREDGEINHL, mask);
-                                       break;
-                               case IRQ_TRIGGER_EDGE_RISING:
-                                       giu_clear(GIUFEDGEINHL, mask);
-                                       giu_set(GIUREDGEINHL, mask);
-                                       break;
-                               default:
-                                       giu_set(GIUFEDGEINHL, mask);
-                                       giu_set(GIUREDGEINHL, mask);
-                                       break;
-                               }
-                       }
-                       irq_set_chip_and_handler(GIU_IRQ(pin),
-                                                &giuint_low_irq_chip,
-                                                handle_edge_irq);
-               } else {
-                       giu_clear(GIUINTTYPL, mask);
-                       giu_clear(GIUINTHTSELL, mask);
-                       irq_set_chip_and_handler(GIU_IRQ(pin),
-                                                &giuint_low_irq_chip,
-                                                handle_level_irq);
-               }
-               giu_write(GIUINTSTATL, mask);
-       } else if (pin < GIUINT_HIGH_MAX) {
-               mask = 1 << (pin - GIUINT_HIGH_OFFSET);
-               if (trigger != IRQ_TRIGGER_LEVEL) {
-                       giu_set(GIUINTTYPH, mask);
-                       if (signal == IRQ_SIGNAL_HOLD)
-                               giu_set(GIUINTHTSELH, mask);
-                       else
-                               giu_clear(GIUINTHTSELH, mask);
-                       if (giu_flags & GPIO_HAS_INTERRUPT_EDGE_SELECT) {
-                               switch (trigger) {
-                               case IRQ_TRIGGER_EDGE_FALLING:
-                                       giu_set(GIUFEDGEINHH, mask);
-                                       giu_clear(GIUREDGEINHH, mask);
-                                       break;
-                               case IRQ_TRIGGER_EDGE_RISING:
-                                       giu_clear(GIUFEDGEINHH, mask);
-                                       giu_set(GIUREDGEINHH, mask);
-                                       break;
-                               default:
-                                       giu_set(GIUFEDGEINHH, mask);
-                                       giu_set(GIUREDGEINHH, mask);
-                                       break;
-                               }
-                       }
-                       irq_set_chip_and_handler(GIU_IRQ(pin),
-                                                &giuint_high_irq_chip,
-                                                handle_edge_irq);
-               } else {
-                       giu_clear(GIUINTTYPH, mask);
-                       giu_clear(GIUINTHTSELH, mask);
-                       irq_set_chip_and_handler(GIU_IRQ(pin),
-                                                &giuint_high_irq_chip,
-                                                handle_level_irq);
-               }
-               giu_write(GIUINTSTATH, mask);
-       }
-}
-EXPORT_SYMBOL_GPL(vr41xx_set_irq_trigger);
-
-void vr41xx_set_irq_level(unsigned int pin, irq_level_t level)
-{
-       u16 mask;
-
-       if (pin < GIUINT_HIGH_OFFSET) {
-               mask = 1 << pin;
-               if (level == IRQ_LEVEL_HIGH)
-                       giu_set(GIUINTALSELL, mask);
-               else
-                       giu_clear(GIUINTALSELL, mask);
-               giu_write(GIUINTSTATL, mask);
-       } else if (pin < GIUINT_HIGH_MAX) {
-               mask = 1 << (pin - GIUINT_HIGH_OFFSET);
-               if (level == IRQ_LEVEL_HIGH)
-                       giu_set(GIUINTALSELH, mask);
-               else
-                       giu_clear(GIUINTALSELH, mask);
-               giu_write(GIUINTSTATH, mask);
-       }
-}
-EXPORT_SYMBOL_GPL(vr41xx_set_irq_level);
-
-static int giu_set_direction(struct gpio_chip *chip, unsigned pin, int dir)
-{
-       u16 offset, mask, reg;
-       unsigned long flags;
-
-       if (pin >= chip->ngpio)
-               return -EINVAL;
-
-       if (pin < 16) {
-               offset = GIUIOSELL;
-               mask = 1 << pin;
-       } else if (pin < 32) {
-               offset = GIUIOSELH;
-               mask = 1 << (pin - 16);
-       } else {
-               if (giu_flags & GPIO_HAS_OUTPUT_ENABLE) {
-                       offset = GIUPODATEN;
-                       mask = 1 << (pin - 32);
-               } else {
-                       switch (pin) {
-                       case 48:
-                               offset = GIUPODATH;
-                               mask = PIOEN0;
-                               break;
-                       case 49:
-                               offset = GIUPODATH;
-                               mask = PIOEN1;
-                               break;
-                       default:
-                               return -EINVAL;
-                       }
-               }
-       }
-
-       spin_lock_irqsave(&giu_lock, flags);
-
-       reg = giu_read(offset);
-       if (dir == GPIO_OUTPUT)
-               reg |= mask;
-       else
-               reg &= ~mask;
-       giu_write(offset, reg);
-
-       spin_unlock_irqrestore(&giu_lock, flags);
-
-       return 0;
-}
-
-int vr41xx_gpio_pullupdown(unsigned int pin, gpio_pull_t pull)
-{
-       u16 reg, mask;
-       unsigned long flags;
-
-       if ((giu_flags & GPIO_HAS_PULLUPDOWN_IO) != GPIO_HAS_PULLUPDOWN_IO)
-               return -EPERM;
-
-       if (pin >= 15)
-               return -EINVAL;
-
-       mask = 1 << pin;
-
-       spin_lock_irqsave(&giu_lock, flags);
-
-       if (pull == GPIO_PULL_UP || pull == GPIO_PULL_DOWN) {
-               reg = giu_read(GIUTERMUPDN);
-               if (pull == GPIO_PULL_UP)
-                       reg |= mask;
-               else
-                       reg &= ~mask;
-               giu_write(GIUTERMUPDN, reg);
-
-               reg = giu_read(GIUUSEUPDN);
-               reg |= mask;
-               giu_write(GIUUSEUPDN, reg);
-       } else {
-               reg = giu_read(GIUUSEUPDN);
-               reg &= ~mask;
-               giu_write(GIUUSEUPDN, reg);
-       }
-
-       spin_unlock_irqrestore(&giu_lock, flags);
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(vr41xx_gpio_pullupdown);
-
-static int vr41xx_gpio_get(struct gpio_chip *chip, unsigned pin)
-{
-       u16 reg, mask;
-
-       if (pin >= chip->ngpio)
-               return -EINVAL;
-
-       if (pin < 16) {
-               reg = giu_read(GIUPIODL);
-               mask = 1 << pin;
-       } else if (pin < 32) {
-               reg = giu_read(GIUPIODH);
-               mask = 1 << (pin - 16);
-       } else if (pin < 48) {
-               reg = giu_read(GIUPODATL);
-               mask = 1 << (pin - 32);
-       } else {
-               reg = giu_read(GIUPODATH);
-               mask = 1 << (pin - 48);
-       }
-
-       if (reg & mask)
-               return 1;
-
-       return 0;
-}
-
-static void vr41xx_gpio_set(struct gpio_chip *chip, unsigned pin,
-                           int value)
-{
-       u16 offset, mask, reg;
-       unsigned long flags;
-
-       if (pin >= chip->ngpio)
-               return;
-
-       if (pin < 16) {
-               offset = GIUPIODL;
-               mask = 1 << pin;
-       } else if (pin < 32) {
-               offset = GIUPIODH;
-               mask = 1 << (pin - 16);
-       } else if (pin < 48) {
-               offset = GIUPODATL;
-               mask = 1 << (pin - 32);
-       } else {
-               offset = GIUPODATH;
-               mask = 1 << (pin - 48);
-       }
-
-       spin_lock_irqsave(&giu_lock, flags);
-
-       reg = giu_read(offset);
-       if (value)
-               reg |= mask;
-       else
-               reg &= ~mask;
-       giu_write(offset, reg);
-
-       spin_unlock_irqrestore(&giu_lock, flags);
-}
-
-
-static int vr41xx_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
-{
-       return giu_set_direction(chip, offset, GPIO_INPUT);
-}
-
-static int vr41xx_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
-                               int value)
-{
-       vr41xx_gpio_set(chip, offset, value);
-
-       return giu_set_direction(chip, offset, GPIO_OUTPUT);
-}
-
-static int vr41xx_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
-{
-       if (offset >= chip->ngpio)
-               return -EINVAL;
-
-       return GIU_IRQ_BASE + offset;
-}
-
-static struct gpio_chip vr41xx_gpio_chip = {
-       .label                  = "vr41xx",
-       .owner                  = THIS_MODULE,
-       .direction_input        = vr41xx_gpio_direction_input,
-       .get                    = vr41xx_gpio_get,
-       .direction_output       = vr41xx_gpio_direction_output,
-       .set                    = vr41xx_gpio_set,
-       .to_irq                 = vr41xx_gpio_to_irq,
-};
-
-static int __devinit giu_probe(struct platform_device *pdev)
-{
-       struct resource *res;
-       unsigned int trigger, i, pin;
-       struct irq_chip *chip;
-       int irq, retval;
-
-       switch (pdev->id) {
-       case GPIO_50PINS_PULLUPDOWN:
-               giu_flags = GPIO_HAS_PULLUPDOWN_IO;
-               vr41xx_gpio_chip.ngpio = 50;
-               break;
-       case GPIO_36PINS:
-               vr41xx_gpio_chip.ngpio = 36;
-               break;
-       case GPIO_48PINS_EDGE_SELECT:
-               giu_flags = GPIO_HAS_INTERRUPT_EDGE_SELECT;
-               vr41xx_gpio_chip.ngpio = 48;
-               break;
-       default:
-               dev_err(&pdev->dev, "GIU: unknown ID %d\n", pdev->id);
-               return -ENODEV;
-       }
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res)
-               return -EBUSY;
-
-       giu_base = ioremap(res->start, res->end - res->start + 1);
-       if (!giu_base)
-               return -ENOMEM;
-
-       vr41xx_gpio_chip.dev = &pdev->dev;
-
-       retval = gpiochip_add(&vr41xx_gpio_chip);
-
-       giu_write(GIUINTENL, 0);
-       giu_write(GIUINTENH, 0);
-
-       trigger = giu_read(GIUINTTYPH) << 16;
-       trigger |= giu_read(GIUINTTYPL);
-       for (i = GIU_IRQ_BASE; i <= GIU_IRQ_LAST; i++) {
-               pin = GPIO_PIN_OF_IRQ(i);
-               if (pin < GIUINT_HIGH_OFFSET)
-                       chip = &giuint_low_irq_chip;
-               else
-                       chip = &giuint_high_irq_chip;
-
-               if (trigger & (1 << pin))
-                       irq_set_chip_and_handler(i, chip, handle_edge_irq);
-               else
-                       irq_set_chip_and_handler(i, chip, handle_level_irq);
-
-       }
-
-       irq = platform_get_irq(pdev, 0);
-       if (irq < 0 || irq >= nr_irqs)
-               return -EBUSY;
-
-       return cascade_irq(irq, giu_get_irq);
-}
-
-static int __devexit giu_remove(struct platform_device *pdev)
-{
-       if (giu_base) {
-               iounmap(giu_base);
-               giu_base = NULL;
-       }
-
-       return 0;
-}
-
-static struct platform_driver giu_device_driver = {
-       .probe          = giu_probe,
-       .remove         = __devexit_p(giu_remove),
-       .driver         = {
-               .name   = "GIU",
-               .owner  = THIS_MODULE,
-       },
-};
-
-static int __init vr41xx_giu_init(void)
-{
-       return platform_driver_register(&giu_device_driver);
-}
-
-static void __exit vr41xx_giu_exit(void)
-{
-       platform_driver_unregister(&giu_device_driver);
-}
-
-module_init(vr41xx_giu_init);
-module_exit(vr41xx_giu_exit);
diff --git a/drivers/gpio/vx855_gpio.c b/drivers/gpio/vx855_gpio.c
deleted file mode 100644 (file)
index ef5aabd..0000000
+++ /dev/null
@@ -1,333 +0,0 @@
-/*
- * Linux GPIOlib driver for the VIA VX855 integrated southbridge GPIO
- *
- * Copyright (C) 2009 VIA Technologies, Inc.
- * Copyright (C) 2010 One Laptop per Child
- * Author: Harald Welte <HaraldWelte@viatech.com>
- * All rights reserved.
- *
- * 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.
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- * MA 02111-1307 USA
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/gpio.h>
-#include <linux/slab.h>
-#include <linux/device.h>
-#include <linux/platform_device.h>
-#include <linux/pci.h>
-#include <linux/io.h>
-
-#define MODULE_NAME "vx855_gpio"
-
-/* The VX855 south bridge has the following GPIO pins:
- *     GPI 0...13      General Purpose Input
- *     GPO 0...12      General Purpose Output
- *     GPIO 0...14     General Purpose I/O (Open-Drain)
- */
-
-#define NR_VX855_GPI   14
-#define NR_VX855_GPO   13
-#define NR_VX855_GPIO  15
-
-#define NR_VX855_GPInO (NR_VX855_GPI + NR_VX855_GPO)
-#define NR_VX855_GP    (NR_VX855_GPI + NR_VX855_GPO + NR_VX855_GPIO)
-
-struct vx855_gpio {
-       struct gpio_chip gpio;
-       spinlock_t lock;
-       u32 io_gpi;
-       u32 io_gpo;
-       bool gpi_reserved;
-       bool gpo_reserved;
-};
-
-/* resolve a GPIx into the corresponding bit position */
-static inline u_int32_t gpi_i_bit(int i)
-{
-       if (i < 10)
-               return 1 << i;
-       else
-               return 1 << (i + 14);
-}
-
-static inline u_int32_t gpo_o_bit(int i)
-{
-       if (i < 11)
-               return 1 << i;
-       else
-               return 1 << (i + 14);
-}
-
-static inline u_int32_t gpio_i_bit(int i)
-{
-       if (i < 14)
-               return 1 << (i + 10);
-       else
-               return 1 << (i + 14);
-}
-
-static inline u_int32_t gpio_o_bit(int i)
-{
-       if (i < 14)
-               return 1 << (i + 11);
-       else
-               return 1 << (i + 13);
-}
-
-/* Mapping betwee numeric GPIO ID and the actual GPIO hardware numbering:
- * 0..13       GPI 0..13
- * 14..26      GPO 0..12
- * 27..41      GPIO 0..14
- */
-
-static int vx855gpio_direction_input(struct gpio_chip *gpio,
-                                    unsigned int nr)
-{
-       struct vx855_gpio *vg = container_of(gpio, struct vx855_gpio, gpio);
-       unsigned long flags;
-       u_int32_t reg_out;
-
-       /* Real GPI bits are always in input direction */
-       if (nr < NR_VX855_GPI)
-               return 0;
-
-       /* Real GPO bits cannot be put in output direction */
-       if (nr < NR_VX855_GPInO)
-               return -EINVAL;
-
-       /* Open Drain GPIO have to be set to one */
-       spin_lock_irqsave(&vg->lock, flags);
-       reg_out = inl(vg->io_gpo);
-       reg_out |= gpio_o_bit(nr - NR_VX855_GPInO);
-       outl(reg_out, vg->io_gpo);
-       spin_unlock_irqrestore(&vg->lock, flags);
-
-       return 0;
-}
-
-static int vx855gpio_get(struct gpio_chip *gpio, unsigned int nr)
-{
-       struct vx855_gpio *vg = container_of(gpio, struct vx855_gpio, gpio);
-       u_int32_t reg_in;
-       int ret = 0;
-
-       if (nr < NR_VX855_GPI) {
-               reg_in = inl(vg->io_gpi);
-               if (reg_in & gpi_i_bit(nr))
-                       ret = 1;
-       } else if (nr < NR_VX855_GPInO) {
-               /* GPO don't have an input bit, we need to read it
-                * back from the output register */
-               reg_in = inl(vg->io_gpo);
-               if (reg_in & gpo_o_bit(nr - NR_VX855_GPI))
-                       ret = 1;
-       } else {
-               reg_in = inl(vg->io_gpi);
-               if (reg_in & gpio_i_bit(nr - NR_VX855_GPInO))
-                       ret = 1;
-       }
-
-       return ret;
-}
-
-static void vx855gpio_set(struct gpio_chip *gpio, unsigned int nr,
-                         int val)
-{
-       struct vx855_gpio *vg = container_of(gpio, struct vx855_gpio, gpio);
-       unsigned long flags;
-       u_int32_t reg_out;
-
-       /* True GPI cannot be switched to output mode */
-       if (nr < NR_VX855_GPI)
-               return;
-
-       spin_lock_irqsave(&vg->lock, flags);
-       reg_out = inl(vg->io_gpo);
-       if (nr < NR_VX855_GPInO) {
-               if (val)
-                       reg_out |= gpo_o_bit(nr - NR_VX855_GPI);
-               else
-                       reg_out &= ~gpo_o_bit(nr - NR_VX855_GPI);
-       } else {
-               if (val)
-                       reg_out |= gpio_o_bit(nr - NR_VX855_GPInO);
-               else
-                       reg_out &= ~gpio_o_bit(nr - NR_VX855_GPInO);
-       }
-       outl(reg_out, vg->io_gpo);
-       spin_unlock_irqrestore(&vg->lock, flags);
-}
-
-static int vx855gpio_direction_output(struct gpio_chip *gpio,
-                                     unsigned int nr, int val)
-{
-       /* True GPI cannot be switched to output mode */
-       if (nr < NR_VX855_GPI)
-               return -EINVAL;
-
-       /* True GPO don't need to be switched to output mode,
-        * and GPIO are open-drain, i.e. also need no switching,
-        * so all we do is set the level */
-       vx855gpio_set(gpio, nr, val);
-
-       return 0;
-}
-
-static const char *vx855gpio_names[NR_VX855_GP] = {
-       "VX855_GPI0", "VX855_GPI1", "VX855_GPI2", "VX855_GPI3", "VX855_GPI4",
-       "VX855_GPI5", "VX855_GPI6", "VX855_GPI7", "VX855_GPI8", "VX855_GPI9",
-       "VX855_GPI10", "VX855_GPI11", "VX855_GPI12", "VX855_GPI13",
-       "VX855_GPO0", "VX855_GPO1", "VX855_GPO2", "VX855_GPO3", "VX855_GPO4",
-       "VX855_GPO5", "VX855_GPO6", "VX855_GPO7", "VX855_GPO8", "VX855_GPO9",
-       "VX855_GPO10", "VX855_GPO11", "VX855_GPO12",
-       "VX855_GPIO0", "VX855_GPIO1", "VX855_GPIO2", "VX855_GPIO3",
-       "VX855_GPIO4", "VX855_GPIO5", "VX855_GPIO6", "VX855_GPIO7",
-       "VX855_GPIO8", "VX855_GPIO9", "VX855_GPIO10", "VX855_GPIO11",
-       "VX855_GPIO12", "VX855_GPIO13", "VX855_GPIO14"
-};
-
-static void vx855gpio_gpio_setup(struct vx855_gpio *vg)
-{
-       struct gpio_chip *c = &vg->gpio;
-
-       c->label = "VX855 South Bridge";
-       c->owner = THIS_MODULE;
-       c->direction_input = vx855gpio_direction_input;
-       c->direction_output = vx855gpio_direction_output;
-       c->get = vx855gpio_get;
-       c->set = vx855gpio_set;
-       c->dbg_show = NULL;
-       c->base = 0;
-       c->ngpio = NR_VX855_GP;
-       c->can_sleep = 0;
-       c->names = vx855gpio_names;
-}
-
-/* This platform device is ordinarily registered by the vx855 mfd driver */
-static __devinit int vx855gpio_probe(struct platform_device *pdev)
-{
-       struct resource *res_gpi;
-       struct resource *res_gpo;
-       struct vx855_gpio *vg;
-       int ret;
-
-       res_gpi = platform_get_resource(pdev, IORESOURCE_IO, 0);
-       res_gpo = platform_get_resource(pdev, IORESOURCE_IO, 1);
-       if (!res_gpi || !res_gpo)
-               return -EBUSY;
-
-       vg = kzalloc(sizeof(*vg), GFP_KERNEL);
-       if (!vg)
-               return -ENOMEM;
-
-       platform_set_drvdata(pdev, vg);
-
-       dev_info(&pdev->dev, "found VX855 GPIO controller\n");
-       vg->io_gpi = res_gpi->start;
-       vg->io_gpo = res_gpo->start;
-       spin_lock_init(&vg->lock);
-
-       /*
-        * A single byte is used to control various GPIO ports on the VX855,
-        * and in the case of the OLPC XO-1.5, some of those ports are used
-        * for switches that are interpreted and exposed through ACPI. ACPI
-        * will have reserved the region, so our own reservation will not
-        * succeed. Ignore and continue.
-        */
-
-       if (!request_region(res_gpi->start, resource_size(res_gpi),
-                       MODULE_NAME "_gpi"))
-               dev_warn(&pdev->dev,
-                       "GPI I/O resource busy, probably claimed by ACPI\n");
-       else
-               vg->gpi_reserved = true;
-
-       if (!request_region(res_gpo->start, resource_size(res_gpo),
-                       MODULE_NAME "_gpo"))
-               dev_warn(&pdev->dev,
-                       "GPO I/O resource busy, probably claimed by ACPI\n");
-       else
-               vg->gpo_reserved = true;
-
-       vx855gpio_gpio_setup(vg);
-
-       ret = gpiochip_add(&vg->gpio);
-       if (ret) {
-               dev_err(&pdev->dev, "failed to register GPIOs\n");
-               goto out_release;
-       }
-
-       return 0;
-
-out_release:
-       if (vg->gpi_reserved)
-               release_region(res_gpi->start, resource_size(res_gpi));
-       if (vg->gpo_reserved)
-               release_region(res_gpi->start, resource_size(res_gpo));
-       platform_set_drvdata(pdev, NULL);
-       kfree(vg);
-       return ret;
-}
-
-static int __devexit vx855gpio_remove(struct platform_device *pdev)
-{
-       struct vx855_gpio *vg = platform_get_drvdata(pdev);
-       struct resource *res;
-
-       if (gpiochip_remove(&vg->gpio))
-               dev_err(&pdev->dev, "unable to remove gpio_chip?\n");
-
-       if (vg->gpi_reserved) {
-               res = platform_get_resource(pdev, IORESOURCE_IO, 0);
-               release_region(res->start, resource_size(res));
-       }
-       if (vg->gpo_reserved) {
-               res = platform_get_resource(pdev, IORESOURCE_IO, 1);
-               release_region(res->start, resource_size(res));
-       }
-
-       platform_set_drvdata(pdev, NULL);
-       kfree(vg);
-       return 0;
-}
-
-static struct platform_driver vx855gpio_driver = {
-       .driver = {
-               .name   = MODULE_NAME,
-               .owner  = THIS_MODULE,
-       },
-       .probe          = vx855gpio_probe,
-       .remove         = __devexit_p(vx855gpio_remove),
-};
-
-static int vx855gpio_init(void)
-{
-       return platform_driver_register(&vx855gpio_driver);
-}
-module_init(vx855gpio_init);
-
-static void vx855gpio_exit(void)
-{
-       platform_driver_unregister(&vx855gpio_driver);
-}
-module_exit(vx855gpio_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Harald Welte <HaraldWelte@viatech.com>");
-MODULE_DESCRIPTION("GPIO driver for the VIA VX855 chipset");
-MODULE_ALIAS("platform:vx855_gpio");
diff --git a/drivers/gpio/wm831x-gpio.c b/drivers/gpio/wm831x-gpio.c
deleted file mode 100644 (file)
index 309644c..0000000
+++ /dev/null
@@ -1,317 +0,0 @@
-/*
- * wm831x-gpio.c  --  gpiolib support for Wolfson WM831x PMICs
- *
- * Copyright 2009 Wolfson Microelectronics PLC.
- *
- * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
- *
- *  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/kernel.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/gpio.h>
-#include <linux/mfd/core.h>
-#include <linux/platform_device.h>
-#include <linux/seq_file.h>
-
-#include <linux/mfd/wm831x/core.h>
-#include <linux/mfd/wm831x/pdata.h>
-#include <linux/mfd/wm831x/gpio.h>
-#include <linux/mfd/wm831x/irq.h>
-
-struct wm831x_gpio {
-       struct wm831x *wm831x;
-       struct gpio_chip gpio_chip;
-};
-
-static inline struct wm831x_gpio *to_wm831x_gpio(struct gpio_chip *chip)
-{
-       return container_of(chip, struct wm831x_gpio, gpio_chip);
-}
-
-static int wm831x_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
-{
-       struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip);
-       struct wm831x *wm831x = wm831x_gpio->wm831x;
-       int val = WM831X_GPN_DIR;
-
-       if (wm831x->has_gpio_ena)
-               val |= WM831X_GPN_TRI;
-
-       return wm831x_set_bits(wm831x, WM831X_GPIO1_CONTROL + offset,
-                              WM831X_GPN_DIR | WM831X_GPN_TRI |
-                              WM831X_GPN_FN_MASK, val);
-}
-
-static int wm831x_gpio_get(struct gpio_chip *chip, unsigned offset)
-{
-       struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip);
-       struct wm831x *wm831x = wm831x_gpio->wm831x;
-       int ret;
-
-       ret = wm831x_reg_read(wm831x, WM831X_GPIO_LEVEL);
-       if (ret < 0)
-               return ret;
-
-       if (ret & 1 << offset)
-               return 1;
-       else
-               return 0;
-}
-
-static void wm831x_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
-{
-       struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip);
-       struct wm831x *wm831x = wm831x_gpio->wm831x;
-
-       wm831x_set_bits(wm831x, WM831X_GPIO_LEVEL, 1 << offset,
-                       value << offset);
-}
-
-static int wm831x_gpio_direction_out(struct gpio_chip *chip,
-                                    unsigned offset, int value)
-{
-       struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip);
-       struct wm831x *wm831x = wm831x_gpio->wm831x;
-       int val = 0;
-       int ret;
-
-       if (wm831x->has_gpio_ena)
-               val |= WM831X_GPN_TRI;
-
-       ret = wm831x_set_bits(wm831x, WM831X_GPIO1_CONTROL + offset,
-                             WM831X_GPN_DIR | WM831X_GPN_TRI |
-                             WM831X_GPN_FN_MASK, val);
-       if (ret < 0)
-               return ret;
-
-       /* Can only set GPIO state once it's in output mode */
-       wm831x_gpio_set(chip, offset, value);
-
-       return 0;
-}
-
-static int wm831x_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
-{
-       struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip);
-       struct wm831x *wm831x = wm831x_gpio->wm831x;
-
-       if (!wm831x->irq_base)
-               return -EINVAL;
-
-       return wm831x->irq_base + WM831X_IRQ_GPIO_1 + offset;
-}
-
-static int wm831x_gpio_set_debounce(struct gpio_chip *chip, unsigned offset,
-                                   unsigned debounce)
-{
-       struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip);
-       struct wm831x *wm831x = wm831x_gpio->wm831x;
-       int reg = WM831X_GPIO1_CONTROL + offset;
-       int ret, fn;
-
-       ret = wm831x_reg_read(wm831x, reg);
-       if (ret < 0)
-               return ret;
-
-       switch (ret & WM831X_GPN_FN_MASK) {
-       case 0:
-       case 1:
-               break;
-       default:
-               /* Not in GPIO mode */
-               return -EBUSY;
-       }
-
-       if (debounce >= 32 && debounce <= 64)
-               fn = 0;
-       else if (debounce >= 4000 && debounce <= 8000)
-               fn = 1;
-       else
-               return -EINVAL;
-
-       return wm831x_set_bits(wm831x, reg, WM831X_GPN_FN_MASK, fn);
-}
-
-#ifdef CONFIG_DEBUG_FS
-static void wm831x_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
-{
-       struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip);
-       struct wm831x *wm831x = wm831x_gpio->wm831x;
-       int i, tristated;
-
-       for (i = 0; i < chip->ngpio; i++) {
-               int gpio = i + chip->base;
-               int reg;
-               const char *label, *pull, *powerdomain;
-
-               /* We report the GPIO even if it's not requested since
-                * we're also reporting things like alternate
-                * functions which apply even when the GPIO is not in
-                * use as a GPIO.
-                */
-               label = gpiochip_is_requested(chip, i);
-               if (!label)
-                       label = "Unrequested";
-
-               seq_printf(s, " gpio-%-3d (%-20.20s) ", gpio, label);
-
-               reg = wm831x_reg_read(wm831x, WM831X_GPIO1_CONTROL + i);
-               if (reg < 0) {
-                       dev_err(wm831x->dev,
-                               "GPIO control %d read failed: %d\n",
-                               gpio, reg);
-                       seq_printf(s, "\n");
-                       continue;
-               }
-
-               switch (reg & WM831X_GPN_PULL_MASK) {
-               case WM831X_GPIO_PULL_NONE:
-                       pull = "nopull";
-                       break;
-               case WM831X_GPIO_PULL_DOWN:
-                       pull = "pulldown";
-                       break;
-               case WM831X_GPIO_PULL_UP:
-                       pull = "pullup";
-               default:
-                       pull = "INVALID PULL";
-                       break;
-               }
-
-               switch (i + 1) {
-               case 1 ... 3:
-               case 7 ... 9:
-                       if (reg & WM831X_GPN_PWR_DOM)
-                               powerdomain = "VPMIC";
-                       else
-                               powerdomain = "DBVDD";
-                       break;
-
-               case 4 ... 6:
-               case 10 ... 12:
-                       if (reg & WM831X_GPN_PWR_DOM)
-                               powerdomain = "SYSVDD";
-                       else
-                               powerdomain = "DBVDD";
-                       break;
-
-               case 13 ... 16:
-                       powerdomain = "TPVDD";
-                       break;
-
-               default:
-                       BUG();
-                       break;
-               }
-
-               tristated = reg & WM831X_GPN_TRI;
-               if (wm831x->has_gpio_ena)
-                       tristated = !tristated;
-
-               seq_printf(s, " %s %s %s %s%s\n"
-                          "                                  %s%s (0x%4x)\n",
-                          reg & WM831X_GPN_DIR ? "in" : "out",
-                          wm831x_gpio_get(chip, i) ? "high" : "low",
-                          pull,
-                          powerdomain,
-                          reg & WM831X_GPN_POL ? "" : " inverted",
-                          reg & WM831X_GPN_OD ? "open-drain" : "CMOS",
-                          tristated ? " tristated" : "",
-                          reg);
-       }
-}
-#else
-#define wm831x_gpio_dbg_show NULL
-#endif
-
-static struct gpio_chip template_chip = {
-       .label                  = "wm831x",
-       .owner                  = THIS_MODULE,
-       .direction_input        = wm831x_gpio_direction_in,
-       .get                    = wm831x_gpio_get,
-       .direction_output       = wm831x_gpio_direction_out,
-       .set                    = wm831x_gpio_set,
-       .to_irq                 = wm831x_gpio_to_irq,
-       .set_debounce           = wm831x_gpio_set_debounce,
-       .dbg_show               = wm831x_gpio_dbg_show,
-       .can_sleep              = 1,
-};
-
-static int __devinit 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_gpio *wm831x_gpio;
-       int ret;
-
-       wm831x_gpio = kzalloc(sizeof(*wm831x_gpio), GFP_KERNEL);
-       if (wm831x_gpio == NULL)
-               return -ENOMEM;
-
-       wm831x_gpio->wm831x = wm831x;
-       wm831x_gpio->gpio_chip = template_chip;
-       wm831x_gpio->gpio_chip.ngpio = wm831x->num_gpio;
-       wm831x_gpio->gpio_chip.dev = &pdev->dev;
-       if (pdata && pdata->gpio_base)
-               wm831x_gpio->gpio_chip.base = pdata->gpio_base;
-       else
-               wm831x_gpio->gpio_chip.base = -1;
-
-       ret = gpiochip_add(&wm831x_gpio->gpio_chip);
-       if (ret < 0) {
-               dev_err(&pdev->dev, "Could not register gpiochip, %d\n",
-                       ret);
-               goto err;
-       }
-
-       platform_set_drvdata(pdev, wm831x_gpio);
-
-       return ret;
-
-err:
-       kfree(wm831x_gpio);
-       return ret;
-}
-
-static int __devexit wm831x_gpio_remove(struct platform_device *pdev)
-{
-       struct wm831x_gpio *wm831x_gpio = platform_get_drvdata(pdev);
-       int ret;
-
-       ret = gpiochip_remove(&wm831x_gpio->gpio_chip);
-       if (ret == 0)
-               kfree(wm831x_gpio);
-
-       return ret;
-}
-
-static struct platform_driver wm831x_gpio_driver = {
-       .driver.name    = "wm831x-gpio",
-       .driver.owner   = THIS_MODULE,
-       .probe          = wm831x_gpio_probe,
-       .remove         = __devexit_p(wm831x_gpio_remove),
-};
-
-static int __init wm831x_gpio_init(void)
-{
-       return platform_driver_register(&wm831x_gpio_driver);
-}
-subsys_initcall(wm831x_gpio_init);
-
-static void __exit wm831x_gpio_exit(void)
-{
-       platform_driver_unregister(&wm831x_gpio_driver);
-}
-module_exit(wm831x_gpio_exit);
-
-MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
-MODULE_DESCRIPTION("GPIO interface for WM831x PMICs");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:wm831x-gpio");
diff --git a/drivers/gpio/wm8350-gpiolib.c b/drivers/gpio/wm8350-gpiolib.c
deleted file mode 100644 (file)
index 3599992..0000000
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * wm835x-gpiolib.c  --  gpiolib support for Wolfson WM835x PMICs
- *
- * Copyright 2009 Wolfson Microelectronics PLC.
- *
- * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
- *
- *  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/kernel.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/gpio.h>
-#include <linux/mfd/core.h>
-#include <linux/platform_device.h>
-#include <linux/seq_file.h>
-
-#include <linux/mfd/wm8350/core.h>
-#include <linux/mfd/wm8350/gpio.h>
-
-struct wm8350_gpio_data {
-       struct wm8350 *wm8350;
-       struct gpio_chip gpio_chip;
-};
-
-static inline struct wm8350_gpio_data *to_wm8350_gpio(struct gpio_chip *chip)
-{
-       return container_of(chip, struct wm8350_gpio_data, gpio_chip);
-}
-
-static int wm8350_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
-{
-       struct wm8350_gpio_data *wm8350_gpio = to_wm8350_gpio(chip);
-       struct wm8350 *wm8350 = wm8350_gpio->wm8350;
-
-       return wm8350_set_bits(wm8350, WM8350_GPIO_CONFIGURATION_I_O,
-                              1 << offset);
-}
-
-static int wm8350_gpio_get(struct gpio_chip *chip, unsigned offset)
-{
-       struct wm8350_gpio_data *wm8350_gpio = to_wm8350_gpio(chip);
-       struct wm8350 *wm8350 = wm8350_gpio->wm8350;
-       int ret;
-
-       ret = wm8350_reg_read(wm8350, WM8350_GPIO_LEVEL);
-       if (ret < 0)
-               return ret;
-
-       if (ret & (1 << offset))
-               return 1;
-       else
-               return 0;
-}
-
-static void wm8350_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
-{
-       struct wm8350_gpio_data *wm8350_gpio = to_wm8350_gpio(chip);
-       struct wm8350 *wm8350 = wm8350_gpio->wm8350;
-
-       if (value)
-               wm8350_set_bits(wm8350, WM8350_GPIO_LEVEL, 1 << offset);
-       else
-               wm8350_clear_bits(wm8350, WM8350_GPIO_LEVEL, 1 << offset);
-}
-
-static int wm8350_gpio_direction_out(struct gpio_chip *chip,
-                                    unsigned offset, int value)
-{
-       struct wm8350_gpio_data *wm8350_gpio = to_wm8350_gpio(chip);
-       struct wm8350 *wm8350 = wm8350_gpio->wm8350;
-       int ret;
-
-       ret = wm8350_clear_bits(wm8350, WM8350_GPIO_CONFIGURATION_I_O,
-                               1 << offset);
-       if (ret < 0)
-               return ret;
-
-       /* Don't have an atomic direction/value setup */
-       wm8350_gpio_set(chip, offset, value);
-
-       return 0;
-}
-
-static int wm8350_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
-{
-       struct wm8350_gpio_data *wm8350_gpio = to_wm8350_gpio(chip);
-       struct wm8350 *wm8350 = wm8350_gpio->wm8350;
-
-       if (!wm8350->irq_base)
-               return -EINVAL;
-
-       return wm8350->irq_base + WM8350_IRQ_GPIO(offset);
-}
-
-static struct gpio_chip template_chip = {
-       .label                  = "wm8350",
-       .owner                  = THIS_MODULE,
-       .direction_input        = wm8350_gpio_direction_in,
-       .get                    = wm8350_gpio_get,
-       .direction_output       = wm8350_gpio_direction_out,
-       .set                    = wm8350_gpio_set,
-       .to_irq                 = wm8350_gpio_to_irq,
-       .can_sleep              = 1,
-};
-
-static int __devinit 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_gpio_data *wm8350_gpio;
-       int ret;
-
-       wm8350_gpio = kzalloc(sizeof(*wm8350_gpio), GFP_KERNEL);
-       if (wm8350_gpio == NULL)
-               return -ENOMEM;
-
-       wm8350_gpio->wm8350 = wm8350;
-       wm8350_gpio->gpio_chip = template_chip;
-       wm8350_gpio->gpio_chip.ngpio = 13;
-       wm8350_gpio->gpio_chip.dev = &pdev->dev;
-       if (pdata && pdata->gpio_base)
-               wm8350_gpio->gpio_chip.base = pdata->gpio_base;
-       else
-               wm8350_gpio->gpio_chip.base = -1;
-
-       ret = gpiochip_add(&wm8350_gpio->gpio_chip);
-       if (ret < 0) {
-               dev_err(&pdev->dev, "Could not register gpiochip, %d\n",
-                       ret);
-               goto err;
-       }
-
-       platform_set_drvdata(pdev, wm8350_gpio);
-
-       return ret;
-
-err:
-       kfree(wm8350_gpio);
-       return ret;
-}
-
-static int __devexit wm8350_gpio_remove(struct platform_device *pdev)
-{
-       struct wm8350_gpio_data *wm8350_gpio = platform_get_drvdata(pdev);
-       int ret;
-
-       ret = gpiochip_remove(&wm8350_gpio->gpio_chip);
-       if (ret == 0)
-               kfree(wm8350_gpio);
-
-       return ret;
-}
-
-static struct platform_driver wm8350_gpio_driver = {
-       .driver.name    = "wm8350-gpio",
-       .driver.owner   = THIS_MODULE,
-       .probe          = wm8350_gpio_probe,
-       .remove         = __devexit_p(wm8350_gpio_remove),
-};
-
-static int __init wm8350_gpio_init(void)
-{
-       return platform_driver_register(&wm8350_gpio_driver);
-}
-subsys_initcall(wm8350_gpio_init);
-
-static void __exit wm8350_gpio_exit(void)
-{
-       platform_driver_unregister(&wm8350_gpio_driver);
-}
-module_exit(wm8350_gpio_exit);
-
-MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
-MODULE_DESCRIPTION("GPIO interface for WM8350 PMICs");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:wm8350-gpio");
diff --git a/drivers/gpio/wm8994-gpio.c b/drivers/gpio/wm8994-gpio.c
deleted file mode 100644 (file)
index c822baa..0000000
+++ /dev/null
@@ -1,242 +0,0 @@
-/*
- * wm8994-gpio.c  --  gpiolib support for Wolfson WM8994
- *
- * Copyright 2009 Wolfson Microelectronics PLC.
- *
- * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
- *
- *  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/kernel.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/gpio.h>
-#include <linux/mfd/core.h>
-#include <linux/platform_device.h>
-#include <linux/seq_file.h>
-
-#include <linux/mfd/wm8994/core.h>
-#include <linux/mfd/wm8994/pdata.h>
-#include <linux/mfd/wm8994/gpio.h>
-#include <linux/mfd/wm8994/registers.h>
-
-struct wm8994_gpio {
-       struct wm8994 *wm8994;
-       struct gpio_chip gpio_chip;
-};
-
-static inline struct wm8994_gpio *to_wm8994_gpio(struct gpio_chip *chip)
-{
-       return container_of(chip, struct wm8994_gpio, gpio_chip);
-}
-
-static int wm8994_gpio_request(struct gpio_chip *chip, unsigned offset)
-{
-       struct wm8994_gpio *wm8994_gpio = to_wm8994_gpio(chip);
-       struct wm8994 *wm8994 = wm8994_gpio->wm8994;
-
-       switch (wm8994->type) {
-       case WM8958:
-               switch (offset) {
-               case 1:
-               case 2:
-               case 3:
-               case 4:
-               case 6:
-                       return -EINVAL;
-               }
-               break;
-       default:
-               break;
-       }
-
-       return 0;
-}
-
-static int wm8994_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
-{
-       struct wm8994_gpio *wm8994_gpio = to_wm8994_gpio(chip);
-       struct wm8994 *wm8994 = wm8994_gpio->wm8994;
-
-       return wm8994_set_bits(wm8994, WM8994_GPIO_1 + offset,
-                              WM8994_GPN_DIR, WM8994_GPN_DIR);
-}
-
-static int wm8994_gpio_get(struct gpio_chip *chip, unsigned offset)
-{
-       struct wm8994_gpio *wm8994_gpio = to_wm8994_gpio(chip);
-       struct wm8994 *wm8994 = wm8994_gpio->wm8994;
-       int ret;
-
-       ret = wm8994_reg_read(wm8994, WM8994_GPIO_1 + offset);
-       if (ret < 0)
-               return ret;
-
-       if (ret & WM8994_GPN_LVL)
-               return 1;
-       else
-               return 0;
-}
-
-static int wm8994_gpio_direction_out(struct gpio_chip *chip,
-                                    unsigned offset, int value)
-{
-       struct wm8994_gpio *wm8994_gpio = to_wm8994_gpio(chip);
-       struct wm8994 *wm8994 = wm8994_gpio->wm8994;
-
-       return wm8994_set_bits(wm8994, WM8994_GPIO_1 + offset,
-                              WM8994_GPN_DIR, 0);
-}
-
-static void wm8994_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
-{
-       struct wm8994_gpio *wm8994_gpio = to_wm8994_gpio(chip);
-       struct wm8994 *wm8994 = wm8994_gpio->wm8994;
-
-       if (value)
-               value = WM8994_GPN_LVL;
-
-       wm8994_set_bits(wm8994, WM8994_GPIO_1 + offset, WM8994_GPN_LVL, value);
-}
-
-static int wm8994_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
-{
-       struct wm8994_gpio *wm8994_gpio = to_wm8994_gpio(chip);
-       struct wm8994 *wm8994 = wm8994_gpio->wm8994;
-
-       if (!wm8994->irq_base)
-               return -EINVAL;
-
-       return wm8994->irq_base + offset;
-}
-
-
-#ifdef CONFIG_DEBUG_FS
-static void wm8994_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
-{
-       struct wm8994_gpio *wm8994_gpio = to_wm8994_gpio(chip);
-       struct wm8994 *wm8994 = wm8994_gpio->wm8994;
-       int i;
-
-       for (i = 0; i < chip->ngpio; i++) {
-               int gpio = i + chip->base;
-               int reg;
-               const char *label;
-
-               /* We report the GPIO even if it's not requested since
-                * we're also reporting things like alternate
-                * functions which apply even when the GPIO is not in
-                * use as a GPIO.
-                */
-               label = gpiochip_is_requested(chip, i);
-               if (!label)
-                       label = "Unrequested";
-
-               seq_printf(s, " gpio-%-3d (%-20.20s) ", gpio, label);
-
-               reg = wm8994_reg_read(wm8994, WM8994_GPIO_1 + i);
-               if (reg < 0) {
-                       dev_err(wm8994->dev,
-                               "GPIO control %d read failed: %d\n",
-                               gpio, reg);
-                       seq_printf(s, "\n");
-                       continue;
-               }
-
-               /* No decode yet; note that GPIO2 is special */
-               seq_printf(s, "(%x)\n", reg);
-       }
-}
-#else
-#define wm8994_gpio_dbg_show NULL
-#endif
-
-static struct gpio_chip template_chip = {
-       .label                  = "wm8994",
-       .owner                  = THIS_MODULE,
-       .request                = wm8994_gpio_request,
-       .direction_input        = wm8994_gpio_direction_in,
-       .get                    = wm8994_gpio_get,
-       .direction_output       = wm8994_gpio_direction_out,
-       .set                    = wm8994_gpio_set,
-       .to_irq                 = wm8994_gpio_to_irq,
-       .dbg_show               = wm8994_gpio_dbg_show,
-       .can_sleep              = 1,
-};
-
-static int __devinit 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_gpio *wm8994_gpio;
-       int ret;
-
-       wm8994_gpio = kzalloc(sizeof(*wm8994_gpio), GFP_KERNEL);
-       if (wm8994_gpio == NULL)
-               return -ENOMEM;
-
-       wm8994_gpio->wm8994 = wm8994;
-       wm8994_gpio->gpio_chip = template_chip;
-       wm8994_gpio->gpio_chip.ngpio = WM8994_GPIO_MAX;
-       wm8994_gpio->gpio_chip.dev = &pdev->dev;
-       if (pdata && pdata->gpio_base)
-               wm8994_gpio->gpio_chip.base = pdata->gpio_base;
-       else
-               wm8994_gpio->gpio_chip.base = -1;
-
-       ret = gpiochip_add(&wm8994_gpio->gpio_chip);
-       if (ret < 0) {
-               dev_err(&pdev->dev, "Could not register gpiochip, %d\n",
-                       ret);
-               goto err;
-       }
-
-       platform_set_drvdata(pdev, wm8994_gpio);
-
-       return ret;
-
-err:
-       kfree(wm8994_gpio);
-       return ret;
-}
-
-static int __devexit wm8994_gpio_remove(struct platform_device *pdev)
-{
-       struct wm8994_gpio *wm8994_gpio = platform_get_drvdata(pdev);
-       int ret;
-
-       ret = gpiochip_remove(&wm8994_gpio->gpio_chip);
-       if (ret == 0)
-               kfree(wm8994_gpio);
-
-       return ret;
-}
-
-static struct platform_driver wm8994_gpio_driver = {
-       .driver.name    = "wm8994-gpio",
-       .driver.owner   = THIS_MODULE,
-       .probe          = wm8994_gpio_probe,
-       .remove         = __devexit_p(wm8994_gpio_remove),
-};
-
-static int __init wm8994_gpio_init(void)
-{
-       return platform_driver_register(&wm8994_gpio_driver);
-}
-subsys_initcall(wm8994_gpio_init);
-
-static void __exit wm8994_gpio_exit(void)
-{
-       platform_driver_unregister(&wm8994_gpio_driver);
-}
-module_exit(wm8994_gpio_exit);
-
-MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
-MODULE_DESCRIPTION("GPIO interface for WM8994");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:wm8994-gpio");
diff --git a/drivers/gpio/xilinx_gpio.c b/drivers/gpio/xilinx_gpio.c
deleted file mode 100644 (file)
index 846fbd5..0000000
+++ /dev/null
@@ -1,233 +0,0 @@
-/*
- * Xilinx gpio driver
- *
- * Copyright 2008 Xilinx, Inc.
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/of_device.h>
-#include <linux/of_platform.h>
-#include <linux/of_gpio.h>
-#include <linux/io.h>
-#include <linux/gpio.h>
-#include <linux/slab.h>
-
-/* Register Offset Definitions */
-#define XGPIO_DATA_OFFSET   (0x0)      /* Data register  */
-#define XGPIO_TRI_OFFSET    (0x4)      /* I/O direction register  */
-
-struct xgpio_instance {
-       struct of_mm_gpio_chip mmchip;
-       u32 gpio_state;         /* GPIO state shadow register */
-       u32 gpio_dir;           /* GPIO direction shadow register */
-       spinlock_t gpio_lock;   /* Lock used for synchronization */
-};
-
-/**
- * xgpio_get - Read the specified signal of the GPIO device.
- * @gc:     Pointer to gpio_chip device structure.
- * @gpio:   GPIO signal number.
- *
- * This function reads the specified signal of the GPIO device. It returns 0 if
- * the signal clear, 1 if signal is set or negative value on error.
- */
-static int xgpio_get(struct gpio_chip *gc, unsigned int gpio)
-{
-       struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
-
-       return (in_be32(mm_gc->regs + XGPIO_DATA_OFFSET) >> gpio) & 1;
-}
-
-/**
- * xgpio_set - Write the specified signal of the GPIO device.
- * @gc:     Pointer to gpio_chip device structure.
- * @gpio:   GPIO signal number.
- * @val:    Value to be written to specified signal.
- *
- * This function writes the specified value in to the specified signal of the
- * GPIO device.
- */
-static void xgpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
-{
-       unsigned long flags;
-       struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
-       struct xgpio_instance *chip =
-           container_of(mm_gc, struct xgpio_instance, mmchip);
-
-       spin_lock_irqsave(&chip->gpio_lock, flags);
-
-       /* Write to GPIO signal and set its direction to output */
-       if (val)
-               chip->gpio_state |= 1 << gpio;
-       else
-               chip->gpio_state &= ~(1 << gpio);
-       out_be32(mm_gc->regs + XGPIO_DATA_OFFSET, chip->gpio_state);
-
-       spin_unlock_irqrestore(&chip->gpio_lock, flags);
-}
-
-/**
- * xgpio_dir_in - Set the direction of the specified GPIO signal as input.
- * @gc:     Pointer to gpio_chip device structure.
- * @gpio:   GPIO signal number.
- *
- * This function sets the direction of specified GPIO signal as input.
- * It returns 0 if direction of GPIO signals is set as input otherwise it
- * returns negative error value.
- */
-static int xgpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
-{
-       unsigned long flags;
-       struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
-       struct xgpio_instance *chip =
-           container_of(mm_gc, struct xgpio_instance, mmchip);
-
-       spin_lock_irqsave(&chip->gpio_lock, flags);
-
-       /* Set the GPIO bit in shadow register and set direction as input */
-       chip->gpio_dir |= (1 << gpio);
-       out_be32(mm_gc->regs + XGPIO_TRI_OFFSET, chip->gpio_dir);
-
-       spin_unlock_irqrestore(&chip->gpio_lock, flags);
-
-       return 0;
-}
-
-/**
- * xgpio_dir_out - Set the direction of the specified GPIO signal as output.
- * @gc:     Pointer to gpio_chip device structure.
- * @gpio:   GPIO signal number.
- * @val:    Value to be written to specified signal.
- *
- * This function sets the direction of specified GPIO signal as output. If all
- * GPIO signals of GPIO chip is configured as input then it returns
- * error otherwise it returns 0.
- */
-static int xgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
-{
-       unsigned long flags;
-       struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
-       struct xgpio_instance *chip =
-           container_of(mm_gc, struct xgpio_instance, mmchip);
-
-       spin_lock_irqsave(&chip->gpio_lock, flags);
-
-       /* Write state of GPIO signal */
-       if (val)
-               chip->gpio_state |= 1 << gpio;
-       else
-               chip->gpio_state &= ~(1 << gpio);
-       out_be32(mm_gc->regs + XGPIO_DATA_OFFSET, chip->gpio_state);
-
-       /* Clear the GPIO bit in shadow register and set direction as output */
-       chip->gpio_dir &= (~(1 << gpio));
-       out_be32(mm_gc->regs + XGPIO_TRI_OFFSET, chip->gpio_dir);
-
-       spin_unlock_irqrestore(&chip->gpio_lock, flags);
-
-       return 0;
-}
-
-/**
- * xgpio_save_regs - Set initial values of GPIO pins
- * @mm_gc: pointer to memory mapped GPIO chip structure
- */
-static void xgpio_save_regs(struct of_mm_gpio_chip *mm_gc)
-{
-       struct xgpio_instance *chip =
-           container_of(mm_gc, struct xgpio_instance, mmchip);
-
-       out_be32(mm_gc->regs + XGPIO_DATA_OFFSET, chip->gpio_state);
-       out_be32(mm_gc->regs + XGPIO_TRI_OFFSET, chip->gpio_dir);
-}
-
-/**
- * xgpio_of_probe - Probe method for the GPIO device.
- * @np: pointer to device tree node
- *
- * This function probes the GPIO device in the device tree. It initializes the
- * driver data structure. It returns 0, if the driver is bound to the GPIO
- * device, or a negative value if there is an error.
- */
-static int __devinit xgpio_of_probe(struct device_node *np)
-{
-       struct xgpio_instance *chip;
-       int status = 0;
-       const u32 *tree_info;
-
-       chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-       if (!chip)
-               return -ENOMEM;
-
-       /* Update GPIO state shadow register with default value */
-       tree_info = of_get_property(np, "xlnx,dout-default", NULL);
-       if (tree_info)
-               chip->gpio_state = be32_to_cpup(tree_info);
-
-       /* Update GPIO direction shadow register with default value */
-       chip->gpio_dir = 0xFFFFFFFF; /* By default, all pins are inputs */
-       tree_info = of_get_property(np, "xlnx,tri-default", NULL);
-       if (tree_info)
-               chip->gpio_dir = be32_to_cpup(tree_info);
-
-       /* Check device node and parent device node for device width */
-       chip->mmchip.gc.ngpio = 32; /* By default assume full GPIO controller */
-       tree_info = of_get_property(np, "xlnx,gpio-width", NULL);
-       if (!tree_info)
-               tree_info = of_get_property(np->parent,
-                                           "xlnx,gpio-width", NULL);
-       if (tree_info)
-               chip->mmchip.gc.ngpio = be32_to_cpup(tree_info);
-
-       spin_lock_init(&chip->gpio_lock);
-
-       chip->mmchip.gc.direction_input = xgpio_dir_in;
-       chip->mmchip.gc.direction_output = xgpio_dir_out;
-       chip->mmchip.gc.get = xgpio_get;
-       chip->mmchip.gc.set = xgpio_set;
-
-       chip->mmchip.save_regs = xgpio_save_regs;
-
-       /* Call the OF gpio helper to setup and register the GPIO device */
-       status = of_mm_gpiochip_add(np, &chip->mmchip);
-       if (status) {
-               kfree(chip);
-               pr_err("%s: error in probe function with status %d\n",
-                      np->full_name, status);
-               return status;
-       }
-       pr_info("XGpio: %s: registered\n", np->full_name);
-       return 0;
-}
-
-static struct of_device_id xgpio_of_match[] __devinitdata = {
-       { .compatible = "xlnx,xps-gpio-1.00.a", },
-       { /* end of list */ },
-};
-
-static int __init xgpio_init(void)
-{
-       struct device_node *np;
-
-       for_each_matching_node(np, xgpio_of_match)
-               xgpio_of_probe(np);
-
-       return 0;
-}
-
-/* Make sure we get initialized before anyone else tries to use us */
-subsys_initcall(xgpio_init);
-/* No exit call at the moment as we cannot unregister of GPIO chips */
-
-MODULE_AUTHOR("Xilinx, Inc.");
-MODULE_DESCRIPTION("Xilinx GPIO driver");
-MODULE_LICENSE("GPL");