Merge branch 'gpio/next' of git://git.secretlab.ca/git/linux-2.6
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 22 Jul 2011 21:50:57 +0000 (14:50 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 22 Jul 2011 21:50:57 +0000 (14:50 -0700)
* 'gpio/next' of git://git.secretlab.ca/git/linux-2.6: (61 commits)
  gpio/mxc/mxs: fix build error introduced by the irq_gc_ack() renaming
  mcp23s08: add i2c support
  mcp23s08: isolate spi specific parts
  mcp23s08: get rid of setup/teardown callbacks
  gpio/tegra: dt: add binding for gpio polarity
  mcp23s08: remove unused work queue
  gpio/da9052: remove a redundant assignment for gpio->da9052
  gpio/mxc: add device tree probe support
  ARM: mxc: use ARCH_NR_GPIOS to define gpio number
  gpio/mxc: get rid of the uses of cpu_is_mx()
  gpio/mxc: add missing initialization of basic_mmio_gpio shadow variables
  gpio: Move mpc5200 gpio driver to drivers/gpio
  GPIO: DA9052 GPIO module v3
  gpio/tegra: Use engineering names in DT compatible property
  of/gpio: Add new method for getting gpios under different property names
  gpio/dt: Refine GPIO device tree binding
  gpio/ml-ioh: fix off-by-one for displaying variable i in dev_err
  gpio/pca953x: Deprecate meaningless device-tree bindings
  gpio/pca953x: Remove dynamic platform data pointer
  gpio/pca953x: Fix IRQ support.
  ...

1  2 
arch/arm/mach-ep93xx/core.c
arch/arm/mach-imx/mach-mx31_3ds.c
arch/arm/mach-omap1/gpio15xx.c
arch/arm/mach-omap1/gpio16xx.c
arch/arm/mach-omap1/gpio7xx.c
drivers/gpio/gpio-langwell.c
drivers/gpio/gpio-omap.c
drivers/gpio/gpio-tps65910.c
drivers/gpio/gpio-wm831x.c
drivers/leds/Kconfig

Simple merge
Simple merge
@@@ -39,9 -49,10 +49,10 @@@ static struct __initdata omap_gpio_plat
        .bank_type              = METHOD_MPUIO,
        .bank_width             = 16,
        .bank_stride            = 1,
+       .regs                   = &omap15xx_mpuio_regs,
  };
  
 -static struct __initdata platform_device omap15xx_mpu_gpio = {
 +static struct platform_device omap15xx_mpu_gpio = {
        .name           = "omap_gpio",
        .id             = 0,
        .dev            = {
@@@ -68,9 -89,10 +89,10 @@@ static struct __initdata omap_gpio_plat
        .virtual_irq_start      = IH_GPIO_BASE,
        .bank_type              = METHOD_GPIO_1510,
        .bank_width             = 16,
+       .regs                   = &omap15xx_gpio_regs,
  };
  
 -static struct __initdata platform_device omap15xx_gpio = {
 +static struct platform_device omap15xx_gpio = {
        .name           = "omap_gpio",
        .id             = 1,
        .dev            = {
@@@ -42,9 -52,10 +52,10 @@@ static struct __initdata omap_gpio_plat
        .bank_type              = METHOD_MPUIO,
        .bank_width             = 16,
        .bank_stride            = 1,
+       .regs                   = &omap16xx_mpuio_regs,
  };
  
 -static struct __initdata platform_device omap16xx_mpu_gpio = {
 +static struct platform_device omap16xx_mpu_gpio = {
        .name           = "omap_gpio",
        .id             = 0,
        .dev            = {
@@@ -71,9 -95,10 +95,10 @@@ static struct __initdata omap_gpio_plat
        .virtual_irq_start      = IH_GPIO_BASE,
        .bank_type              = METHOD_GPIO_1610,
        .bank_width             = 16,
+       .regs                   = &omap16xx_gpio_regs,
  };
  
 -static struct __initdata platform_device omap16xx_gpio1 = {
 +static struct platform_device omap16xx_gpio1 = {
        .name           = "omap_gpio",
        .id             = 1,
        .dev            = {
@@@ -100,9 -125,10 +125,10 @@@ static struct __initdata omap_gpio_plat
        .virtual_irq_start      = IH_GPIO_BASE + 16,
        .bank_type              = METHOD_GPIO_1610,
        .bank_width             = 16,
+       .regs                   = &omap16xx_gpio_regs,
  };
  
 -static struct __initdata platform_device omap16xx_gpio2 = {
 +static struct platform_device omap16xx_gpio2 = {
        .name           = "omap_gpio",
        .id             = 2,
        .dev            = {
@@@ -129,9 -155,10 +155,10 @@@ static struct __initdata omap_gpio_plat
        .virtual_irq_start      = IH_GPIO_BASE + 32,
        .bank_type              = METHOD_GPIO_1610,
        .bank_width             = 16,
+       .regs                   = &omap16xx_gpio_regs,
  };
  
 -static struct __initdata platform_device omap16xx_gpio3 = {
 +static struct platform_device omap16xx_gpio3 = {
        .name           = "omap_gpio",
        .id             = 3,
        .dev            = {
@@@ -158,9 -185,10 +185,10 @@@ static struct __initdata omap_gpio_plat
        .virtual_irq_start      = IH_GPIO_BASE + 48,
        .bank_type              = METHOD_GPIO_1610,
        .bank_width             = 16,
+       .regs                   = &omap16xx_gpio_regs,
  };
  
 -static struct __initdata platform_device omap16xx_gpio4 = {
 +static struct platform_device omap16xx_gpio4 = {
        .name           = "omap_gpio",
        .id             = 4,
        .dev            = {
@@@ -44,9 -54,10 +54,10 @@@ static struct __initdata omap_gpio_plat
        .bank_type              = METHOD_MPUIO,
        .bank_width             = 32,
        .bank_stride            = 2,
+       .regs                   = &omap7xx_mpuio_regs,
  };
  
 -static struct __initdata platform_device omap7xx_mpu_gpio = {
 +static struct platform_device omap7xx_mpu_gpio = {
        .name           = "omap_gpio",
        .id             = 0,
        .dev            = {
@@@ -73,9 -94,10 +94,10 @@@ static struct __initdata omap_gpio_plat
        .virtual_irq_start      = IH_GPIO_BASE,
        .bank_type              = METHOD_GPIO_7XX,
        .bank_width             = 32,
+       .regs                   = &omap7xx_gpio_regs,
  };
  
 -static struct __initdata platform_device omap7xx_gpio1 = {
 +static struct platform_device omap7xx_gpio1 = {
        .name           = "omap_gpio",
        .id             = 1,
        .dev            = {
@@@ -102,9 -124,10 +124,10 @@@ static struct __initdata omap_gpio_plat
        .virtual_irq_start      = IH_GPIO_BASE + 32,
        .bank_type              = METHOD_GPIO_7XX,
        .bank_width             = 32,
+       .regs                   = &omap7xx_gpio_regs,
  };
  
 -static struct __initdata platform_device omap7xx_gpio2 = {
 +static struct platform_device omap7xx_gpio2 = {
        .name           = "omap_gpio",
        .id             = 2,
        .dev            = {
@@@ -131,9 -154,10 +154,10 @@@ static struct __initdata omap_gpio_plat
        .virtual_irq_start      = IH_GPIO_BASE + 64,
        .bank_type              = METHOD_GPIO_7XX,
        .bank_width             = 32,
+       .regs                   = &omap7xx_gpio_regs,
  };
  
 -static struct __initdata platform_device omap7xx_gpio3 = {
 +static struct platform_device omap7xx_gpio3 = {
        .name           = "omap_gpio",
        .id             = 3,
        .dev            = {
@@@ -160,9 -184,10 +184,10 @@@ static struct __initdata omap_gpio_plat
        .virtual_irq_start      = IH_GPIO_BASE + 96,
        .bank_type              = METHOD_GPIO_7XX,
        .bank_width             = 32,
+       .regs                   = &omap7xx_gpio_regs,
  };
  
 -static struct __initdata platform_device omap7xx_gpio4 = {
 +static struct platform_device omap7xx_gpio4 = {
        .name           = "omap_gpio",
        .id             = 4,
        .dev            = {
@@@ -189,9 -214,10 +214,10 @@@ static struct __initdata omap_gpio_plat
        .virtual_irq_start      = IH_GPIO_BASE + 128,
        .bank_type              = METHOD_GPIO_7XX,
        .bank_width             = 32,
+       .regs                   = &omap7xx_gpio_regs,
  };
  
 -static struct __initdata platform_device omap7xx_gpio5 = {
 +static struct platform_device omap7xx_gpio5 = {
        .name           = "omap_gpio",
        .id             = 5,
        .dev            = {
@@@ -218,9 -244,10 +244,10 @@@ static struct __initdata omap_gpio_plat
        .virtual_irq_start      = IH_GPIO_BASE + 160,
        .bank_type              = METHOD_GPIO_7XX,
        .bank_width             = 32,
+       .regs                   = &omap7xx_gpio_regs,
  };
  
 -static struct __initdata platform_device omap7xx_gpio6 = {
 +static struct platform_device omap7xx_gpio6 = {
        .name           = "omap_gpio",
        .id             = 6,
        .dev            = {
index 0000000,e7a7ea7..d2eb57c
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,458 +1,458 @@@
 -                      gpio = __ffs(pending) - 1;
+ /*
+  * 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);
+                       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);
Simple merge
index 0000000,4171033..b9c1c29
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,100 +1,102 @@@
+ /*
+  * 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;
++              break;
+       case TPS65911:
+               tps65910->gpio.ngpio    = 9;
++              break;
+       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);
+ }
index 0000000,31a9ed7..deb949e
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,317 +1,318 @@@
+ /*
+  * 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";
++                      break;
+               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");
Simple merge