Merge branch 'for_3.5/gpio/cleanup' of git://git.kernel.org/pub/scm/linux/kernel...
authorGrant Likely <grant.likely@secretlab.ca>
Sat, 12 May 2012 00:51:19 +0000 (18:51 -0600)
committerGrant Likely <grant.likely@secretlab.ca>
Sat, 12 May 2012 00:51:19 +0000 (18:51 -0600)
31 files changed:
Documentation/gpio.txt
arch/alpha/include/asm/gpio.h
arch/arm/Kconfig
arch/avr32/Kconfig
arch/blackfin/Kconfig
arch/ia64/include/asm/gpio.h
arch/m68k/Kconfig.cpu
arch/microblaze/include/asm/gpio.h
arch/mips/Kconfig
arch/openrisc/include/asm/gpio.h
arch/powerpc/include/asm/gpio.h
arch/sh/Kconfig
arch/sparc/include/asm/gpio.h
arch/unicore32/Kconfig
arch/x86/include/asm/gpio.h
arch/xtensa/include/asm/gpio.h
drivers/gpio/Kconfig
drivers/gpio/Makefile
drivers/gpio/gpio-bt8xx.c
drivers/gpio/gpio-langwell.c
drivers/gpio/gpio-ml-ioh.c
drivers/gpio/gpio-msic.c [new file with mode: 0644]
drivers/gpio/gpio-pch.c
drivers/gpio/gpio-samsung.c
drivers/gpio/gpio-sodaville.c
drivers/gpio/gpiolib-of.c [new file with mode: 0644]
drivers/gpio/gpiolib.c
drivers/of/Kconfig
drivers/of/Makefile
drivers/of/gpio.c [deleted file]
include/linux/gpio.h

index 620a07844e8cee6af9fe7415c7cd016766252250..e08a883de36e316715bcdacebf9670f952c0de02 100644 (file)
@@ -322,6 +322,9 @@ where 'flags' is currently defined to specify the following properties:
        * GPIOF_OPEN_DRAIN      - gpio pin is open drain type.
        * GPIOF_OPEN_SOURCE     - gpio pin is open source type.
 
+       * GPIOF_EXPORT_DIR_FIXED        - export gpio to sysfs, keep direction
+       * GPIOF_EXPORT_DIR_CHANGEABLE   - also export, allow changing direction
+
 since GPIOF_INIT_* are only valid when configured as output, so group valid
 combinations as:
 
index 7dc6a6343c06f7d78cfa7451e006a3a172bd8f19..b3799d88ffcfe8911d50399c2624569321912f10 100644 (file)
@@ -1,55 +1,4 @@
-/*
- * Generic GPIO API implementation for Alpha.
- *
- * A stright copy of that for PowerPC which was:
- *
- * Copyright (c) 2007-2008  MontaVista Software, Inc.
- *
- * Author: Anton Vorontsov <avorontsov@ru.mvista.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.
- */
-
-#ifndef _ASM_ALPHA_GPIO_H
-#define _ASM_ALPHA_GPIO_H
-
-#include <linux/errno.h>
-#include <asm-generic/gpio.h>
-
-#ifdef CONFIG_GPIOLIB
-
-/*
- * We don't (yet) implement inlined/rapid versions for on-chip gpios.
- * Just call gpiolib.
- */
-static inline int gpio_get_value(unsigned int gpio)
-{
-       return __gpio_get_value(gpio);
-}
-
-static inline void gpio_set_value(unsigned int gpio, int value)
-{
-       __gpio_set_value(gpio, value);
-}
-
-static inline int gpio_cansleep(unsigned int gpio)
-{
-       return __gpio_cansleep(gpio);
-}
-
-static inline int gpio_to_irq(unsigned int gpio)
-{
-       return __gpio_to_irq(gpio);
-}
-
-static inline int irq_to_gpio(unsigned int irq)
-{
-       return -EINVAL;
-}
-
-#endif /* CONFIG_GPIOLIB */
-
-#endif /* _ASM_ALPHA_GPIO_H */
+#ifndef __LINUX_GPIO_H
+#warning Include linux/gpio.h instead of asm/gpio.h
+#include <linux/gpio.h>
+#endif
index 36586dba6fa6e0af6260dce3827cfe1495c7f592..777025e773d9045cd0d8007b356d100c5a55ec92 100644 (file)
@@ -1,6 +1,7 @@
 config ARM
        bool
        default y
+       select ARCH_HAVE_CUSTOM_GPIO_H
        select HAVE_AOUT
        select HAVE_DMA_API_DEBUG
        select HAVE_IDE if PCI || ISA || PCMCIA
index 3dea7231f637c5d09e8c545fdee437a550b67c10..859b2de4a624a665e13f16fe36908e7453b20146 100644 (file)
@@ -11,6 +11,7 @@ config AVR32
        select GENERIC_ATOMIC64
        select HARDIRQS_SW_RESEND
        select GENERIC_IRQ_SHOW
+       select ARCH_HAVE_CUSTOM_GPIO_H
        select ARCH_HAVE_NMI_SAFE_CMPXCHG
        help
          AVR32 is a high-performance 32-bit RISC microprocessor core,
index 373a6902d8fa6c7955732b1d1cb2d5911c24a431..bf3d80f9738bf5ab6afc4c771f267e59109188a3 100644 (file)
@@ -31,6 +31,7 @@ config BLACKFIN
        select HAVE_KERNEL_LZO if RAMKERNEL
        select HAVE_OPROFILE
        select HAVE_PERF_EVENTS
+       select ARCH_HAVE_CUSTOM_GPIO_H
        select ARCH_WANT_OPTIONAL_GPIOLIB
        select HAVE_GENERIC_HARDIRQS
        select GENERIC_ATOMIC64
index 590a20debc4e59a9296b61d91b197dfba341d67d..b3799d88ffcfe8911d50399c2624569321912f10 100644 (file)
@@ -1,55 +1,4 @@
-/*
- * Generic GPIO API implementation for IA-64.
- *
- * A stright copy of that for PowerPC which was:
- *
- * Copyright (c) 2007-2008  MontaVista Software, Inc.
- *
- * Author: Anton Vorontsov <avorontsov@ru.mvista.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.
- */
-
-#ifndef _ASM_IA64_GPIO_H
-#define _ASM_IA64_GPIO_H
-
-#include <linux/errno.h>
-#include <asm-generic/gpio.h>
-
-#ifdef CONFIG_GPIOLIB
-
-/*
- * We don't (yet) implement inlined/rapid versions for on-chip gpios.
- * Just call gpiolib.
- */
-static inline int gpio_get_value(unsigned int gpio)
-{
-       return __gpio_get_value(gpio);
-}
-
-static inline void gpio_set_value(unsigned int gpio, int value)
-{
-       __gpio_set_value(gpio, value);
-}
-
-static inline int gpio_cansleep(unsigned int gpio)
-{
-       return __gpio_cansleep(gpio);
-}
-
-static inline int gpio_to_irq(unsigned int gpio)
-{
-       return __gpio_to_irq(gpio);
-}
-
-static inline int irq_to_gpio(unsigned int irq)
-{
-       return -EINVAL;
-}
-
-#endif /* CONFIG_GPIOLIB */
-
-#endif /* _ASM_IA64_GPIO_H */
+#ifndef __LINUX_GPIO_H
+#warning Include linux/gpio.h instead of asm/gpio.h
+#include <linux/gpio.h>
+#endif
index 8a9c767125a4758b27e08f1488e27fa8b85ad258..8941af1d3ad2f4b4f22a5fb1c82f511d669547e6 100644 (file)
@@ -24,6 +24,7 @@ config COLDFIRE
        bool "Coldfire CPU family support"
        select GENERIC_GPIO
        select ARCH_REQUIRE_GPIOLIB
+       select ARCH_HAVE_CUSTOM_GPIO_H
        select CPU_HAS_NO_BITFIELDS
        select CPU_HAS_NO_MULDIV64
        select GENERIC_CSUM
index 2b2c18be71c6512e84ea0007bfb994941f399c7c..b3799d88ffcfe8911d50399c2624569321912f10 100644 (file)
@@ -1,53 +1,4 @@
-/*
- * Generic GPIO API implementation for PowerPC.
- *
- * Copyright (c) 2007-2008  MontaVista Software, Inc.
- *
- * Author: Anton Vorontsov <avorontsov@ru.mvista.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.
- */
-
-#ifndef _ASM_MICROBLAZE_GPIO_H
-#define _ASM_MICROBLAZE_GPIO_H
-
-#include <linux/errno.h>
-#include <asm-generic/gpio.h>
-
-#ifdef CONFIG_GPIOLIB
-
-/*
- * We don't (yet) implement inlined/rapid versions for on-chip gpios.
- * Just call gpiolib.
- */
-static inline int gpio_get_value(unsigned int gpio)
-{
-       return __gpio_get_value(gpio);
-}
-
-static inline void gpio_set_value(unsigned int gpio, int value)
-{
-       __gpio_set_value(gpio, value);
-}
-
-static inline int gpio_cansleep(unsigned int gpio)
-{
-       return __gpio_cansleep(gpio);
-}
-
-static inline int gpio_to_irq(unsigned int gpio)
-{
-       return __gpio_to_irq(gpio);
-}
-
-static inline int irq_to_gpio(unsigned int irq)
-{
-       return -EINVAL;
-}
-
-#endif /* CONFIG_GPIOLIB */
-
-#endif /* _ASM_MICROBLAZE_GPIO_H */
+#ifndef __LINUX_GPIO_H
+#warning Include linux/gpio.h instead of asm/gpio.h
+#include <linux/gpio.h>
+#endif
index ce30e2f91d7748c0c36eb8847390bd101192a044..63321b283fe44e4f50abf5d8b721273782770869 100644 (file)
@@ -8,6 +8,7 @@ config MIPS
        select HAVE_PERF_EVENTS
        select PERF_USE_VMALLOC
        select HAVE_ARCH_KGDB
+       select ARCH_HAVE_CUSTOM_GPIO_H
        select HAVE_FUNCTION_TRACER
        select HAVE_FUNCTION_TRACE_MCOUNT_TEST
        select HAVE_DYNAMIC_FTRACE
index 0b0d174f47cdd13cce8fcbd29bcf2247ab88d62a..b3799d88ffcfe8911d50399c2624569321912f10 100644 (file)
@@ -1,65 +1,4 @@
-/*
- * OpenRISC Linux
- *
- * Linux architectural port borrowing liberally from similar works of
- * others.  All original copyrights apply as per the original source
- * declaration.
- *
- * OpenRISC implementation:
- * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
- * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
- * et al.
- *
- * 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.
- */
-
-#ifndef __ASM_OPENRISC_GPIO_H
-#define __ASM_OPENRISC_GPIO_H
-
-#include <linux/errno.h>
-#include <asm-generic/gpio.h>
-
-#ifdef CONFIG_GPIOLIB
-
-/*
- * OpenRISC (or1k) does not have on-chip GPIO's so there is not really
- * any standardized implementation that makes sense here.  If passing
- * through gpiolib becomes a bottleneck then it may make sense, on a
- * case-by-case basis, to implement these inlined/rapid versions.
- *
- * Just call gpiolib.
- */
-static inline int gpio_get_value(unsigned int gpio)
-{
-       return __gpio_get_value(gpio);
-}
-
-static inline void gpio_set_value(unsigned int gpio, int value)
-{
-       __gpio_set_value(gpio, value);
-}
-
-static inline int gpio_cansleep(unsigned int gpio)
-{
-       return __gpio_cansleep(gpio);
-}
-
-/*
- * Not implemented, yet.
- */
-static inline int gpio_to_irq(unsigned int gpio)
-{
-       return -ENOSYS;
-}
-
-static inline int irq_to_gpio(unsigned int irq)
-{
-       return -EINVAL;
-}
-
-#endif /* CONFIG_GPIOLIB */
-
-#endif /* __ASM_OPENRISC_GPIO_H */
+#ifndef __LINUX_GPIO_H
+#warning Include linux/gpio.h instead of asm/gpio.h
+#include <linux/gpio.h>
+#endif
index 38762edb5e5804e714a81aa223b6ce8d338336ca..b3799d88ffcfe8911d50399c2624569321912f10 100644 (file)
@@ -1,53 +1,4 @@
-/*
- * Generic GPIO API implementation for PowerPC.
- *
- * Copyright (c) 2007-2008  MontaVista Software, Inc.
- *
- * Author: Anton Vorontsov <avorontsov@ru.mvista.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.
- */
-
-#ifndef __ASM_POWERPC_GPIO_H
-#define __ASM_POWERPC_GPIO_H
-
-#include <linux/errno.h>
-#include <asm-generic/gpio.h>
-
-#ifdef CONFIG_GPIOLIB
-
-/*
- * We don't (yet) implement inlined/rapid versions for on-chip gpios.
- * Just call gpiolib.
- */
-static inline int gpio_get_value(unsigned int gpio)
-{
-       return __gpio_get_value(gpio);
-}
-
-static inline void gpio_set_value(unsigned int gpio, int value)
-{
-       __gpio_set_value(gpio, value);
-}
-
-static inline int gpio_cansleep(unsigned int gpio)
-{
-       return __gpio_cansleep(gpio);
-}
-
-static inline int gpio_to_irq(unsigned int gpio)
-{
-       return __gpio_to_irq(gpio);
-}
-
-static inline int irq_to_gpio(unsigned int irq)
-{
-       return -EINVAL;
-}
-
-#endif /* CONFIG_GPIOLIB */
-
-#endif /* __ASM_POWERPC_GPIO_H */
+#ifndef __LINUX_GPIO_H
+#warning Include linux/gpio.h instead of asm/gpio.h
+#include <linux/gpio.h>
+#endif
index ff9e033ce626774fe5b0ad7ddf1c199fe7789471..c40b29ac364419bd6816ac687e6b453474e5f8c8 100644 (file)
@@ -13,6 +13,7 @@ config SUPERH
        select HAVE_DMA_ATTRS
        select HAVE_IRQ_WORK
        select HAVE_PERF_EVENTS
+       select ARCH_HAVE_CUSTOM_GPIO_H
        select ARCH_HAVE_NMI_SAFE_CMPXCHG if (GUSA_RB || CPU_SH4A)
        select PERF_USE_VMALLOC
        select HAVE_KERNEL_GZIP
index a0e3ac0af599c36681a80db126a48bc37bc440f5..b3799d88ffcfe8911d50399c2624569321912f10 100644 (file)
@@ -1,36 +1,4 @@
-#ifndef __ASM_SPARC_GPIO_H
-#define __ASM_SPARC_GPIO_H
-
-#include <linux/errno.h>
-#include <asm-generic/gpio.h>
-
-#ifdef CONFIG_GPIOLIB
-
-static inline int gpio_get_value(unsigned int gpio)
-{
-       return __gpio_get_value(gpio);
-}
-
-static inline void gpio_set_value(unsigned int gpio, int value)
-{
-       __gpio_set_value(gpio, value);
-}
-
-static inline int gpio_cansleep(unsigned int gpio)
-{
-       return __gpio_cansleep(gpio);
-}
-
-static inline int gpio_to_irq(unsigned int gpio)
-{
-       return -ENOSYS;
-}
-
-static inline int irq_to_gpio(unsigned int irq)
-{
-       return -EINVAL;
-}
-
-#endif /* CONFIG_GPIOLIB */
-
-#endif /* __ASM_SPARC_GPIO_H */
+#ifndef __LINUX_GPIO_H
+#warning Include linux/gpio.h instead of asm/gpio.h
+#include <linux/gpio.h>
+#endif
index eeb8054c7cd84347d242bba052c44cd64a5da5af..7ff6d10c0be2a5413713d205b8862f2cc6786a26 100644 (file)
@@ -8,6 +8,7 @@ config UNICORE32
        select HAVE_KERNEL_BZIP2
        select HAVE_KERNEL_LZO
        select HAVE_KERNEL_LZMA
+       select ARCH_HAVE_CUSTOM_GPIO_H
        select GENERIC_FIND_FIRST_BIT
        select GENERIC_IRQ_PROBE
        select GENERIC_IRQ_SHOW
index 91d915a6525995e79c306519b43e1812d154a09b..b3799d88ffcfe8911d50399c2624569321912f10 100644 (file)
@@ -1,53 +1,4 @@
-/*
- * Generic GPIO API implementation for x86.
- *
- * Derived from the generic GPIO API for powerpc:
- *
- * Copyright (c) 2007-2008  MontaVista Software, Inc.
- *
- * Author: Anton Vorontsov <avorontsov@ru.mvista.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.
- */
-
-#ifndef _ASM_X86_GPIO_H
-#define _ASM_X86_GPIO_H
-
-#include <asm-generic/gpio.h>
-
-#ifdef CONFIG_GPIOLIB
-
-/*
- * Just call gpiolib.
- */
-static inline int gpio_get_value(unsigned int gpio)
-{
-       return __gpio_get_value(gpio);
-}
-
-static inline void gpio_set_value(unsigned int gpio, int value)
-{
-       __gpio_set_value(gpio, value);
-}
-
-static inline int gpio_cansleep(unsigned int gpio)
-{
-       return __gpio_cansleep(gpio);
-}
-
-static inline int gpio_to_irq(unsigned int gpio)
-{
-       return __gpio_to_irq(gpio);
-}
-
-static inline int irq_to_gpio(unsigned int irq)
-{
-       return -EINVAL;
-}
-
-#endif /* CONFIG_GPIOLIB */
-
-#endif /* _ASM_X86_GPIO_H */
+#ifndef __LINUX_GPIO_H
+#warning Include linux/gpio.h instead of asm/gpio.h
+#include <linux/gpio.h>
+#endif
index a8c9fc46c790922e6a8e6116e8a66b7a645d7e20..b3799d88ffcfe8911d50399c2624569321912f10 100644 (file)
@@ -1,56 +1,4 @@
-/*
- * Generic GPIO API implementation for xtensa.
- *
- * Stolen from x86, which is derived from the generic GPIO API for powerpc:
- *
- * Copyright (c) 2007-2008  MontaVista Software, Inc.
- *
- * Author: Anton Vorontsov <avorontsov@ru.mvista.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.
- */
-
-#ifndef _ASM_XTENSA_GPIO_H
-#define _ASM_XTENSA_GPIO_H
-
-#include <asm-generic/gpio.h>
-
-#ifdef CONFIG_GPIOLIB
-
-/*
- * Just call gpiolib.
- */
-static inline int gpio_get_value(unsigned int gpio)
-{
-       return __gpio_get_value(gpio);
-}
-
-static inline void gpio_set_value(unsigned int gpio, int value)
-{
-       __gpio_set_value(gpio, value);
-}
-
-static inline int gpio_cansleep(unsigned int gpio)
-{
-       return __gpio_cansleep(gpio);
-}
-
-static inline int gpio_to_irq(unsigned int gpio)
-{
-       return __gpio_to_irq(gpio);
-}
-
-/*
- * Not implemented, yet.
- */
-static inline int irq_to_gpio(unsigned int irq)
-{
-       return -EINVAL;
-}
-
-#endif /* CONFIG_GPIOLIB */
-
-#endif /* _ASM_XTENSA_GPIO_H */
+#ifndef __LINUX_GPIO_H
+#warning Include linux/gpio.h instead of asm/gpio.h
+#include <linux/gpio.h>
+#endif
index e03653d6935778423a5f3dd44d4ac06722d5f15f..25535ebf4f90804d243b62be50a7e1beb700d1a0 100644 (file)
@@ -2,6 +2,14 @@
 # GPIO infrastructure and drivers
 #
 
+config ARCH_HAVE_CUSTOM_GPIO_H
+       bool
+       help
+         Selecting this config option from the architecture Kconfig allows
+         the architecture to provide a custom asm/gpio.h implementation
+         overriding the default implementations.  New uses of this are
+         strongly discouraged.
+
 config ARCH_WANT_OPTIONAL_GPIOLIB
        bool
        help
@@ -37,6 +45,10 @@ menuconfig GPIOLIB
 
 if GPIOLIB
 
+config OF_GPIO
+       def_bool y
+       depends on OF && !SPARC
+
 config DEBUG_GPIO
        bool "Debug GPIO calls"
        depends on DEBUG_KERNEL
@@ -243,7 +255,7 @@ config GPIO_MC9S08DZ60
          Select this to enable the MC9S08DZ60 GPIO driver
 
 config GPIO_PCA953X
-       tristate "PCA953x, PCA955x, TCA64xx, and MAX7310 I/O ports"
+       tristate "PCA953x, PCA955x, PCA957x, TCA64xx, and MAX7310 I/O ports"
        depends on I2C
        help
          Say yes here to provide access to several register-oriented
@@ -252,10 +264,11 @@ config GPIO_PCA953X
 
          4 bits:       pca9536, pca9537
 
-         8 bits:       max7310, pca9534, pca9538, pca9554, pca9557,
-                       tca6408
+         8 bits:       max7310, max7315, pca6107, pca9534, pca9538, pca9554,
+                       pca9556, pca9557, pca9574, tca6408
 
-         16 bits:      pca9535, pca9539, pca9555, tca6416
+         16 bits:      max7312, max7313, pca9535, pca9539, pca9555, pca9575,
+                       tca6416
 
 config GPIO_PCA953X_IRQ
        bool "Interrupt controller support for PCA953x"
@@ -399,6 +412,7 @@ config GPIO_BT8XX
 config GPIO_LANGWELL
        bool "Intel Langwell/Penwell GPIO support"
        depends on PCI && X86
+       select IRQ_DOMAIN
        help
          Say Y here to support Intel Langwell/Penwell GPIO.
 
@@ -514,4 +528,12 @@ config GPIO_TPS65910
        help
          Select this option to enable GPIO driver for the TPS65910
          chip family.
+
+config GPIO_MSIC
+       bool "Intel MSIC mixed signal gpio support"
+       depends on MFD_INTEL_MSIC
+       help
+         Enable support for GPIO on intel MSIC controllers found in
+         intel MID devices
+
 endif
index 007f54bd0081203dcf04ec775254b6b72c8d422f..7862f49b4d053e05585c85622b1bc33af6c11b7c 100644 (file)
@@ -3,6 +3,7 @@
 ccflags-$(CONFIG_DEBUG_GPIO)   += -DDEBUG
 
 obj-$(CONFIG_GPIOLIB)          += gpiolib.o devres.o
+obj-$(CONFIG_OF_GPIO)          += gpiolib-of.o
 
 # Device drivers. Generally keep list sorted alphabetically
 obj-$(CONFIG_GPIO_GENERIC)     += gpio-generic.o
@@ -32,6 +33,7 @@ obj-$(CONFIG_GPIO_MCP23S08)   += gpio-mcp23s08.o
 obj-$(CONFIG_GPIO_ML_IOH)      += gpio-ml-ioh.o
 obj-$(CONFIG_GPIO_MPC5200)     += gpio-mpc5200.o
 obj-$(CONFIG_GPIO_MPC8XXX)     += gpio-mpc8xxx.o
+obj-$(CONFIG_GPIO_MSIC)                += gpio-msic.o
 obj-$(CONFIG_GPIO_MSM_V1)      += gpio-msm-v1.o
 obj-$(CONFIG_GPIO_MSM_V2)      += gpio-msm-v2.o
 obj-$(CONFIG_GPIO_MXC)         += gpio-mxc.o
index 5ca4098ba0925c44af3e6d688c609342f821b5af..e4cc7eb69bb2488e36c3db104feab9858fa6a764 100644 (file)
@@ -328,17 +328,7 @@ static struct pci_driver bt8xxgpio_pci_driver = {
        .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_pci_driver(bt8xxgpio_pci_driver);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Michael Buesch");
index 00692e89ef878ac20834354df75f173d40fe68b8..a1c8754f52cf1b523c3da1bb9e572dc084ddde0b 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/gpio.h>
 #include <linux/slab.h>
 #include <linux/pm_runtime.h>
+#include <linux/irqdomain.h>
 
 /*
  * Langwell chip has 64 pins and thus there are 2 32bit registers to control
@@ -66,8 +67,8 @@ struct lnw_gpio {
        struct gpio_chip                chip;
        void                            *reg_base;
        spinlock_t                      lock;
-       unsigned                        irq_base;
        struct pci_dev                  *pdev;
+       struct irq_domain               *domain;
 };
 
 static void __iomem *gpio_reg(struct gpio_chip *chip, unsigned offset,
@@ -176,13 +177,13 @@ static int lnw_gpio_direction_output(struct gpio_chip *chip,
 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;
+       return irq_create_mapping(lnw->domain, 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;
+       u32 gpio = irqd_to_hwirq(d);
        unsigned long flags;
        u32 value;
        void __iomem *grer = gpio_reg(&lnw->chip, gpio, GRER);
@@ -249,20 +250,55 @@ static void lnw_irq_handler(unsigned irq, struct irq_desc *desc)
        /* 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) {
+               while ((pending = readl(gedr))) {
                        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);
+                       generic_handle_irq(irq_find_mapping(lnw->domain,
+                                                           base + gpio));
                }
        }
 
        chip->irq_eoi(data);
 }
 
+static void lnw_irq_init_hw(struct lnw_gpio *lnw)
+{
+       void __iomem *reg;
+       unsigned base;
+
+       for (base = 0; base < lnw->chip.ngpio; base += 32) {
+               /* Clear the rising-edge detect register */
+               reg = gpio_reg(&lnw->chip, base, GRER);
+               writel(0, reg);
+               /* Clear the falling-edge detect register */
+               reg = gpio_reg(&lnw->chip, base, GFER);
+               writel(0, reg);
+               /* Clear the edge detect status register */
+               reg = gpio_reg(&lnw->chip, base, GEDR);
+               writel(~0, reg);
+       }
+}
+
+static int lnw_gpio_irq_map(struct irq_domain *d, unsigned int virq,
+                           irq_hw_number_t hw)
+{
+       struct lnw_gpio *lnw = d->host_data;
+
+       irq_set_chip_and_handler_name(virq, &lnw_irqchip, handle_simple_irq,
+                                     "demux");
+       irq_set_chip_data(virq, lnw);
+       irq_set_irq_type(virq, IRQ_TYPE_NONE);
+
+       return 0;
+}
+
+static const struct irq_domain_ops lnw_gpio_irq_ops = {
+       .map = lnw_gpio_irq_map,
+       .xlate = irq_domain_xlate_twocell,
+};
+
 #ifdef CONFIG_PM
 static int lnw_gpio_runtime_resume(struct device *dev)
 {
@@ -300,23 +336,22 @@ 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;
+       int ngpio = id->driver_data;
 
        retval = pci_enable_device(pdev);
        if (retval)
-               goto done;
+               return retval;
 
        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 */
+       /* get the gpio_base from bar1 */
        start = pci_resource_start(pdev, 1);
        len = pci_resource_len(pdev, 1);
        base = ioremap_nocache(start, len);
@@ -324,28 +359,32 @@ static int __devinit lnw_gpio_probe(struct pci_dev *pdev,
                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);
+       base = devm_ioremap_nocache(&pdev->dev, start, len);
        if (!base) {
                dev_err(&pdev->dev, "error mapping bar0\n");
                retval = -EFAULT;
                goto err3;
        }
 
-       lnw = kzalloc(sizeof(struct lnw_gpio), GFP_KERNEL);
+       lnw = devm_kzalloc(&pdev->dev, sizeof(struct lnw_gpio), GFP_KERNEL);
        if (!lnw) {
                dev_err(&pdev->dev, "can't allocate langwell_gpio chip data\n");
                retval = -ENOMEM;
-               goto err4;
+               goto err3;
        }
+
+       lnw->domain = irq_domain_add_linear(pdev->dev.of_node, ngpio,
+                                           &lnw_gpio_irq_ops, lnw);
+       if (!lnw->domain)
+               goto err3;
+
        lnw->reg_base = base;
-       lnw->irq_base = irq_base;
        lnw->chip.label = dev_name(&pdev->dev);
        lnw->chip.request = lnw_gpio_request;
        lnw->chip.direction_input = lnw_gpio_direction_input;
@@ -354,38 +393,32 @@ static int __devinit lnw_gpio_probe(struct pci_dev *pdev,
        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.ngpio = ngpio;
        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;
+               goto err3;
        }
+
+       lnw_irq_init_hw(lnw);
+
        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);
+       return 0;
+
 err3:
        pci_release_regions(pdev);
 err2:
        pci_disable_device(pdev);
-done:
        return retval;
 }
 
index f0febe5b8221384c390711208c191a56cc2ee4f8..db01f151d41c428f220f5a0b9fad9a4d6f427f18 100644 (file)
@@ -611,17 +611,7 @@ static struct pci_driver ioh_gpio_driver = {
        .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_pci_driver(ioh_gpio_driver);
 
 MODULE_DESCRIPTION("OKI SEMICONDUCTOR ML-IOH series GPIO Driver");
 MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/gpio-msic.c b/drivers/gpio/gpio-msic.c
new file mode 100644 (file)
index 0000000..71a838f
--- /dev/null
@@ -0,0 +1,339 @@
+/*
+ * Intel Medfield MSIC GPIO driver>
+ * Copyright (c) 2011, Intel Corporation.
+ *
+ * Author: Mathias Nyman <mathias.nyman@linux.intel.com>
+ * Based on intel_pmic_gpio.c
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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 St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/gpio.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/intel_msic.h>
+
+/* the offset for the mapping of global gpio pin to irq */
+#define MSIC_GPIO_IRQ_OFFSET   0x100
+
+#define MSIC_GPIO_DIR_IN       0
+#define MSIC_GPIO_DIR_OUT      BIT(5)
+#define MSIC_GPIO_TRIG_FALL    BIT(1)
+#define MSIC_GPIO_TRIG_RISE    BIT(2)
+
+/* masks for msic gpio output GPIOxxxxCTLO registers */
+#define MSIC_GPIO_DIR_MASK     BIT(5)
+#define MSIC_GPIO_DRV_MASK     BIT(4)
+#define MSIC_GPIO_REN_MASK     BIT(3)
+#define MSIC_GPIO_RVAL_MASK    (BIT(2) | BIT(1))
+#define MSIC_GPIO_DOUT_MASK    BIT(0)
+
+/* masks for msic gpio input GPIOxxxxCTLI registers */
+#define MSIC_GPIO_GLBYP_MASK   BIT(5)
+#define MSIC_GPIO_DBNC_MASK    (BIT(4) | BIT(3))
+#define MSIC_GPIO_INTCNT_MASK  (BIT(2) | BIT(1))
+#define MSIC_GPIO_DIN_MASK     BIT(0)
+
+#define MSIC_NUM_GPIO          24
+
+struct msic_gpio {
+       struct platform_device  *pdev;
+       struct mutex            buslock;
+       struct gpio_chip        chip;
+       int                     irq;
+       unsigned                irq_base;
+       unsigned long           trig_change_mask;
+       unsigned                trig_type;
+};
+
+/*
+ * MSIC has 24 gpios, 16 low voltage (1.2-1.8v) and 8 high voltage (3v).
+ * Both the high and low voltage gpios are divided in two banks.
+ * GPIOs are numbered with GPIO0LV0 as gpio_base in the following order:
+ * GPIO0LV0..GPIO0LV7: low voltage, bank 0, gpio_base
+ * GPIO1LV0..GPIO1LV7: low voltage, bank 1,  gpio_base + 8
+ * GPIO0HV0..GPIO0HV3: high voltage, bank 0, gpio_base + 16
+ * GPIO1HV0..GPIO1HV3: high voltage, bank 1, gpio_base + 20
+ */
+
+static int msic_gpio_to_ireg(unsigned offset)
+{
+       if (offset >= MSIC_NUM_GPIO)
+               return -EINVAL;
+
+       if (offset < 8)
+               return INTEL_MSIC_GPIO0LV0CTLI - offset;
+       if (offset < 16)
+               return INTEL_MSIC_GPIO1LV0CTLI - offset + 8;
+       if (offset < 20)
+               return INTEL_MSIC_GPIO0HV0CTLI - offset + 16;
+
+       return INTEL_MSIC_GPIO1HV0CTLI - offset + 20;
+}
+
+static int msic_gpio_to_oreg(unsigned offset)
+{
+       if (offset >= MSIC_NUM_GPIO)
+               return -EINVAL;
+
+       if (offset < 8)
+               return INTEL_MSIC_GPIO0LV0CTLO - offset;
+       if (offset < 16)
+               return INTEL_MSIC_GPIO1LV0CTLO - offset + 8;
+       if (offset < 20)
+               return INTEL_MSIC_GPIO0HV0CTLO - offset + 16;
+
+       return INTEL_MSIC_GPIO1HV0CTLO + offset + 20;
+}
+
+static int msic_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+       int reg;
+
+       reg = msic_gpio_to_oreg(offset);
+       if (reg < 0)
+               return reg;
+
+       return intel_msic_reg_update(reg, MSIC_GPIO_DIR_IN, MSIC_GPIO_DIR_MASK);
+}
+
+static int msic_gpio_direction_output(struct gpio_chip *chip,
+                       unsigned offset, int value)
+{
+       int reg;
+       unsigned mask;
+
+       value = (!!value) | MSIC_GPIO_DIR_OUT;
+       mask = MSIC_GPIO_DIR_MASK | MSIC_GPIO_DOUT_MASK;
+
+       reg = msic_gpio_to_oreg(offset);
+       if (reg < 0)
+               return reg;
+
+       return intel_msic_reg_update(reg, value, mask);
+}
+
+static int msic_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+       u8 r;
+       int ret;
+       int reg;
+
+       reg = msic_gpio_to_ireg(offset);
+       if (reg < 0)
+               return reg;
+
+       ret = intel_msic_reg_read(reg, &r);
+       if (ret < 0)
+               return ret;
+
+       return r & MSIC_GPIO_DIN_MASK;
+}
+
+static void msic_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+       int reg;
+
+       reg = msic_gpio_to_oreg(offset);
+       if (reg < 0)
+               return;
+
+       intel_msic_reg_update(reg, !!value , MSIC_GPIO_DOUT_MASK);
+}
+
+/*
+ * This is called from genirq with mg->buslock locked and
+ * irq_desc->lock held. We can not access the scu bus here, so we
+ * store the change and update in the bus_sync_unlock() function below
+ */
+static int msic_irq_type(struct irq_data *data, unsigned type)
+{
+       struct msic_gpio *mg = irq_data_get_irq_chip_data(data);
+       u32 gpio = data->irq - mg->irq_base;
+
+       if (gpio >= mg->chip.ngpio)
+               return -EINVAL;
+
+       /* mark for which gpio the trigger changed, protected by buslock */
+       mg->trig_change_mask |= (1 << gpio);
+       mg->trig_type = type;
+
+       return 0;
+}
+
+static int msic_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+       struct msic_gpio *mg = container_of(chip, struct msic_gpio, chip);
+       return mg->irq_base + offset;
+}
+
+static void msic_bus_lock(struct irq_data *data)
+{
+       struct msic_gpio *mg = irq_data_get_irq_chip_data(data);
+       mutex_lock(&mg->buslock);
+}
+
+static void msic_bus_sync_unlock(struct irq_data *data)
+{
+       struct msic_gpio *mg = irq_data_get_irq_chip_data(data);
+       int offset;
+       int reg;
+       u8 trig = 0;
+
+       /* We can only get one change at a time as the buslock covers the
+          entire transaction. The irq_desc->lock is dropped before we are
+          called but that is fine */
+       if (mg->trig_change_mask) {
+               offset = __ffs(mg->trig_change_mask);
+
+               reg = msic_gpio_to_ireg(offset);
+               if (reg < 0)
+                       goto out;
+
+               if (mg->trig_type & IRQ_TYPE_EDGE_RISING)
+                       trig |= MSIC_GPIO_TRIG_RISE;
+               if (mg->trig_type & IRQ_TYPE_EDGE_FALLING)
+                       trig |= MSIC_GPIO_TRIG_FALL;
+
+               intel_msic_reg_update(reg, trig, MSIC_GPIO_INTCNT_MASK);
+               mg->trig_change_mask = 0;
+       }
+out:
+       mutex_unlock(&mg->buslock);
+}
+
+/* Firmware does all the masking and unmasking for us, no masking here. */
+static void msic_irq_unmask(struct irq_data *data) { }
+
+static void msic_irq_mask(struct irq_data *data) { }
+
+static struct irq_chip msic_irqchip = {
+       .name                   = "MSIC-GPIO",
+       .irq_mask               = msic_irq_mask,
+       .irq_unmask             = msic_irq_unmask,
+       .irq_set_type           = msic_irq_type,
+       .irq_bus_lock           = msic_bus_lock,
+       .irq_bus_sync_unlock    = msic_bus_sync_unlock,
+};
+
+static void msic_gpio_irq_handler(unsigned irq, struct irq_desc *desc)
+{
+       struct irq_data *data = irq_desc_get_irq_data(desc);
+       struct msic_gpio *mg = irq_data_get_irq_handler_data(data);
+       struct irq_chip *chip = irq_data_get_irq_chip(data);
+       struct intel_msic *msic = pdev_to_intel_msic(mg->pdev);
+       int i;
+       int bitnr;
+       u8 pin;
+       unsigned long pending = 0;
+
+       for (i = 0; i < (mg->chip.ngpio / BITS_PER_BYTE); i++) {
+               intel_msic_irq_read(msic, INTEL_MSIC_GPIO0LVIRQ + i, &pin);
+               pending = pin;
+
+               if (pending) {
+                       for_each_set_bit(bitnr, &pending, BITS_PER_BYTE)
+                               generic_handle_irq(mg->irq_base +
+                                                  (i * BITS_PER_BYTE) + bitnr);
+               }
+       }
+       chip->irq_eoi(data);
+}
+
+static int __devinit platform_msic_gpio_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct intel_msic_gpio_pdata *pdata = dev->platform_data;
+       struct msic_gpio *mg;
+       int irq = platform_get_irq(pdev, 0);
+       int retval;
+       int i;
+
+       if (irq < 0) {
+               dev_err(dev, "no IRQ line\n");
+               return -EINVAL;
+       }
+
+       if (!pdata || !pdata->gpio_base) {
+               dev_err(dev, "incorrect or missing platform data\n");
+               return -EINVAL;
+       }
+
+       mg = kzalloc(sizeof(*mg), GFP_KERNEL);
+       if (!mg)
+               return -ENOMEM;
+
+       dev_set_drvdata(dev, mg);
+
+       mg->pdev = pdev;
+       mg->irq = irq;
+       mg->irq_base = pdata->gpio_base + MSIC_GPIO_IRQ_OFFSET;
+       mg->chip.label = "msic_gpio";
+       mg->chip.direction_input = msic_gpio_direction_input;
+       mg->chip.direction_output = msic_gpio_direction_output;
+       mg->chip.get = msic_gpio_get;
+       mg->chip.set = msic_gpio_set;
+       mg->chip.to_irq = msic_gpio_to_irq;
+       mg->chip.base = pdata->gpio_base;
+       mg->chip.ngpio = MSIC_NUM_GPIO;
+       mg->chip.can_sleep = 1;
+       mg->chip.dev = dev;
+
+       mutex_init(&mg->buslock);
+
+       retval = gpiochip_add(&mg->chip);
+       if (retval) {
+               dev_err(dev, "Adding MSIC gpio chip failed\n");
+               goto err;
+       }
+
+       for (i = 0; i < mg->chip.ngpio; i++) {
+               irq_set_chip_data(i + mg->irq_base, mg);
+               irq_set_chip_and_handler_name(i + mg->irq_base,
+                                             &msic_irqchip,
+                                             handle_simple_irq,
+                                             "demux");
+       }
+       irq_set_chained_handler(mg->irq, msic_gpio_irq_handler);
+       irq_set_handler_data(mg->irq, mg);
+
+       return 0;
+err:
+       kfree(mg);
+       return retval;
+}
+
+static struct platform_driver platform_msic_gpio_driver = {
+       .driver = {
+               .name           = "msic_gpio",
+               .owner          = THIS_MODULE,
+       },
+       .probe          = platform_msic_gpio_probe,
+};
+
+static int __init platform_msic_gpio_init(void)
+{
+       return platform_driver_register(&platform_msic_gpio_driver);
+}
+
+subsys_initcall(platform_msic_gpio_init);
+
+MODULE_AUTHOR("Mathias Nyman <mathias.nyman@linux.intel.com>");
+MODULE_DESCRIPTION("Intel Medfield MSIC GPIO driver");
+MODULE_LICENSE("GPL v2");
index e8729cc2ba2b9f1dc864a17803252ef40b2adbfa..a05fdb6c464ce7e0a91f2aad6be28bb5ff07fbfb 100644 (file)
@@ -539,17 +539,7 @@ static struct pci_driver pch_gpio_driver = {
        .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_pci_driver(pch_gpio_driver);
 
 MODULE_DESCRIPTION("PCH GPIO PCI Driver");
 MODULE_LICENSE("GPL");
index 19d6fc0229c3505d802e068553db8be4e5b1361e..5d49aff3bb9e1e9b685e1d7ede275a267994694d 100644 (file)
@@ -2714,12 +2714,224 @@ static __init void exynos_gpiolib_attach_ofnode(struct samsung_gpio_chip *chip,
 }
 #endif /* defined(CONFIG_ARCH_EXYNOS) && defined(CONFIG_OF) */
 
+static __init void exynos4_gpiolib_init(void)
+{
+#ifdef CONFIG_CPU_EXYNOS4210
+       struct samsung_gpio_chip *chip;
+       int i, nr_chips;
+       void __iomem *gpio_base1, *gpio_base2, *gpio_base3;
+       int group = 0;
+       void __iomem *gpx_base;
+
+       /* gpio part1 */
+       gpio_base1 = ioremap(EXYNOS4_PA_GPIO1, SZ_4K);
+       if (gpio_base1 == NULL) {
+               pr_err("unable to ioremap for gpio_base1\n");
+               goto err_ioremap1;
+       }
+
+       chip = exynos4_gpios_1;
+       nr_chips = ARRAY_SIZE(exynos4_gpios_1);
+
+       for (i = 0; i < nr_chips; i++, chip++) {
+               if (!chip->config) {
+                       chip->config = &exynos_gpio_cfg;
+                       chip->group = group++;
+               }
+               exynos_gpiolib_attach_ofnode(chip,
+                               EXYNOS4_PA_GPIO1, i * 0x20);
+       }
+       samsung_gpiolib_add_4bit_chips(exynos4_gpios_1,
+                                      nr_chips, gpio_base1);
+
+       /* gpio part2 */
+       gpio_base2 = ioremap(EXYNOS4_PA_GPIO2, SZ_4K);
+       if (gpio_base2 == NULL) {
+               pr_err("unable to ioremap for gpio_base2\n");
+               goto err_ioremap2;
+       }
+
+       /* need to set base address for gpx */
+       chip = &exynos4_gpios_2[16];
+       gpx_base = gpio_base2 + 0xC00;
+       for (i = 0; i < 4; i++, chip++, gpx_base += 0x20)
+               chip->base = gpx_base;
+
+       chip = exynos4_gpios_2;
+       nr_chips = ARRAY_SIZE(exynos4_gpios_2);
+
+       for (i = 0; i < nr_chips; i++, chip++) {
+               if (!chip->config) {
+                       chip->config = &exynos_gpio_cfg;
+                       chip->group = group++;
+               }
+               exynos_gpiolib_attach_ofnode(chip,
+                               EXYNOS4_PA_GPIO2, i * 0x20);
+       }
+       samsung_gpiolib_add_4bit_chips(exynos4_gpios_2,
+                                      nr_chips, gpio_base2);
+
+       /* gpio part3 */
+       gpio_base3 = ioremap(EXYNOS4_PA_GPIO3, SZ_256);
+       if (gpio_base3 == NULL) {
+               pr_err("unable to ioremap for gpio_base3\n");
+               goto err_ioremap3;
+       }
+
+       chip = exynos4_gpios_3;
+       nr_chips = ARRAY_SIZE(exynos4_gpios_3);
+
+       for (i = 0; i < nr_chips; i++, chip++) {
+               if (!chip->config) {
+                       chip->config = &exynos_gpio_cfg;
+                       chip->group = group++;
+               }
+               exynos_gpiolib_attach_ofnode(chip,
+                               EXYNOS4_PA_GPIO3, i * 0x20);
+       }
+       samsung_gpiolib_add_4bit_chips(exynos4_gpios_3,
+                                      nr_chips, gpio_base3);
+
+#if defined(CONFIG_CPU_EXYNOS4210) && defined(CONFIG_S5P_GPIO_INT)
+       s5p_register_gpioint_bank(IRQ_GPIO_XA, 0, IRQ_GPIO1_NR_GROUPS);
+       s5p_register_gpioint_bank(IRQ_GPIO_XB, IRQ_GPIO1_NR_GROUPS, IRQ_GPIO2_NR_GROUPS);
+#endif
+
+       return;
+
+err_ioremap3:
+       iounmap(gpio_base2);
+err_ioremap2:
+       iounmap(gpio_base1);
+err_ioremap1:
+       return;
+#endif /* CONFIG_CPU_EXYNOS4210 */
+}
+
+static __init void exynos5_gpiolib_init(void)
+{
+#ifdef CONFIG_SOC_EXYNOS5250
+       struct samsung_gpio_chip *chip;
+       int i, nr_chips;
+       void __iomem *gpio_base1, *gpio_base2, *gpio_base3, *gpio_base4;
+       int group = 0;
+       void __iomem *gpx_base;
+
+       /* gpio part1 */
+       gpio_base1 = ioremap(EXYNOS5_PA_GPIO1, SZ_4K);
+       if (gpio_base1 == NULL) {
+               pr_err("unable to ioremap for gpio_base1\n");
+               goto err_ioremap1;
+       }
+
+       /* need to set base address for gpx */
+       chip = &exynos5_gpios_1[20];
+       gpx_base = gpio_base1 + 0xC00;
+       for (i = 0; i < 4; i++, chip++, gpx_base += 0x20)
+               chip->base = gpx_base;
+
+       chip = exynos5_gpios_1;
+       nr_chips = ARRAY_SIZE(exynos5_gpios_1);
+
+       for (i = 0; i < nr_chips; i++, chip++) {
+               if (!chip->config) {
+                       chip->config = &exynos_gpio_cfg;
+                       chip->group = group++;
+               }
+               exynos_gpiolib_attach_ofnode(chip,
+                               EXYNOS5_PA_GPIO1, i * 0x20);
+       }
+       samsung_gpiolib_add_4bit_chips(exynos5_gpios_1,
+                                      nr_chips, gpio_base1);
+
+       /* gpio part2 */
+       gpio_base2 = ioremap(EXYNOS5_PA_GPIO2, SZ_4K);
+       if (gpio_base2 == NULL) {
+               pr_err("unable to ioremap for gpio_base2\n");
+               goto err_ioremap2;
+       }
+
+       chip = exynos5_gpios_2;
+       nr_chips = ARRAY_SIZE(exynos5_gpios_2);
+
+       for (i = 0; i < nr_chips; i++, chip++) {
+               if (!chip->config) {
+                       chip->config = &exynos_gpio_cfg;
+                       chip->group = group++;
+               }
+               exynos_gpiolib_attach_ofnode(chip,
+                               EXYNOS5_PA_GPIO2, i * 0x20);
+       }
+       samsung_gpiolib_add_4bit_chips(exynos5_gpios_2,
+                                      nr_chips, gpio_base2);
+
+       /* gpio part3 */
+       gpio_base3 = ioremap(EXYNOS5_PA_GPIO3, SZ_4K);
+       if (gpio_base3 == NULL) {
+               pr_err("unable to ioremap for gpio_base3\n");
+               goto err_ioremap3;
+       }
+
+       /* need to set base address for gpv */
+       exynos5_gpios_3[0].base = gpio_base3;
+       exynos5_gpios_3[1].base = gpio_base3 + 0x20;
+       exynos5_gpios_3[2].base = gpio_base3 + 0x60;
+       exynos5_gpios_3[3].base = gpio_base3 + 0x80;
+       exynos5_gpios_3[4].base = gpio_base3 + 0xC0;
+
+       chip = exynos5_gpios_3;
+       nr_chips = ARRAY_SIZE(exynos5_gpios_3);
+
+       for (i = 0; i < nr_chips; i++, chip++) {
+               if (!chip->config) {
+                       chip->config = &exynos_gpio_cfg;
+                       chip->group = group++;
+               }
+               exynos_gpiolib_attach_ofnode(chip,
+                               EXYNOS5_PA_GPIO3, i * 0x20);
+       }
+       samsung_gpiolib_add_4bit_chips(exynos5_gpios_3,
+                                      nr_chips, gpio_base3);
+
+       /* gpio part4 */
+       gpio_base4 = ioremap(EXYNOS5_PA_GPIO4, SZ_4K);
+       if (gpio_base4 == NULL) {
+               pr_err("unable to ioremap for gpio_base4\n");
+               goto err_ioremap4;
+       }
+
+       chip = exynos5_gpios_4;
+       nr_chips = ARRAY_SIZE(exynos5_gpios_4);
+
+       for (i = 0; i < nr_chips; i++, chip++) {
+               if (!chip->config) {
+                       chip->config = &exynos_gpio_cfg;
+                       chip->group = group++;
+               }
+               exynos_gpiolib_attach_ofnode(chip,
+                               EXYNOS5_PA_GPIO4, i * 0x20);
+       }
+       samsung_gpiolib_add_4bit_chips(exynos5_gpios_4,
+                                      nr_chips, gpio_base4);
+       return;
+
+err_ioremap4:
+       iounmap(gpio_base3);
+err_ioremap3:
+       iounmap(gpio_base2);
+err_ioremap2:
+       iounmap(gpio_base1);
+err_ioremap1:
+       return;
+
+#endif /* CONFIG_SOC_EXYNOS5250 */
+}
+
 /* TODO: cleanup soc_is_* */
 static __init int samsung_gpiolib_init(void)
 {
        struct samsung_gpio_chip *chip;
        int i, nr_chips;
-       void __iomem *gpio_base1, *gpio_base2, *gpio_base3, *gpio_base4;
        int group = 0;
 
        samsung_gpiolib_set_cfg(samsung_gpio_cfgs, ARRAY_SIZE(samsung_gpio_cfgs));
@@ -2785,200 +2997,15 @@ static __init int samsung_gpiolib_init(void)
                s5p_register_gpioint_bank(IRQ_GPIOINT, 0, S5P_GPIOINT_GROUP_MAXNR);
 #endif
        } else if (soc_is_exynos4210()) {
-#ifdef CONFIG_CPU_EXYNOS4210
-               void __iomem *gpx_base;
-
-               /* gpio part1 */
-               gpio_base1 = ioremap(EXYNOS4_PA_GPIO1, SZ_4K);
-               if (gpio_base1 == NULL) {
-                       pr_err("unable to ioremap for gpio_base1\n");
-                       goto err_ioremap1;
-               }
-
-               chip = exynos4_gpios_1;
-               nr_chips = ARRAY_SIZE(exynos4_gpios_1);
-
-               for (i = 0; i < nr_chips; i++, chip++) {
-                       if (!chip->config) {
-                               chip->config = &exynos_gpio_cfg;
-                               chip->group = group++;
-                       }
-                       exynos_gpiolib_attach_ofnode(chip,
-                                       EXYNOS4_PA_GPIO1, i * 0x20);
-               }
-               samsung_gpiolib_add_4bit_chips(exynos4_gpios_1,
-                                              nr_chips, gpio_base1);
-
-               /* gpio part2 */
-               gpio_base2 = ioremap(EXYNOS4_PA_GPIO2, SZ_4K);
-               if (gpio_base2 == NULL) {
-                       pr_err("unable to ioremap for gpio_base2\n");
-                       goto err_ioremap2;
-               }
-
-               /* need to set base address for gpx */
-               chip = &exynos4_gpios_2[16];
-               gpx_base = gpio_base2 + 0xC00;
-               for (i = 0; i < 4; i++, chip++, gpx_base += 0x20)
-                       chip->base = gpx_base;
-
-               chip = exynos4_gpios_2;
-               nr_chips = ARRAY_SIZE(exynos4_gpios_2);
-
-               for (i = 0; i < nr_chips; i++, chip++) {
-                       if (!chip->config) {
-                               chip->config = &exynos_gpio_cfg;
-                               chip->group = group++;
-                       }
-                       exynos_gpiolib_attach_ofnode(chip,
-                                       EXYNOS4_PA_GPIO2, i * 0x20);
-               }
-               samsung_gpiolib_add_4bit_chips(exynos4_gpios_2,
-                                              nr_chips, gpio_base2);
-
-               /* gpio part3 */
-               gpio_base3 = ioremap(EXYNOS4_PA_GPIO3, SZ_256);
-               if (gpio_base3 == NULL) {
-                       pr_err("unable to ioremap for gpio_base3\n");
-                       goto err_ioremap3;
-               }
-
-               chip = exynos4_gpios_3;
-               nr_chips = ARRAY_SIZE(exynos4_gpios_3);
-
-               for (i = 0; i < nr_chips; i++, chip++) {
-                       if (!chip->config) {
-                               chip->config = &exynos_gpio_cfg;
-                               chip->group = group++;
-                       }
-                       exynos_gpiolib_attach_ofnode(chip,
-                                       EXYNOS4_PA_GPIO3, i * 0x20);
-               }
-               samsung_gpiolib_add_4bit_chips(exynos4_gpios_3,
-                                              nr_chips, gpio_base3);
-
-#if defined(CONFIG_CPU_EXYNOS4210) && defined(CONFIG_S5P_GPIO_INT)
-               s5p_register_gpioint_bank(IRQ_GPIO_XA, 0, IRQ_GPIO1_NR_GROUPS);
-               s5p_register_gpioint_bank(IRQ_GPIO_XB, IRQ_GPIO1_NR_GROUPS, IRQ_GPIO2_NR_GROUPS);
-#endif
-
-#endif /* CONFIG_CPU_EXYNOS4210 */
+               exynos4_gpiolib_init();
        } else if (soc_is_exynos5250()) {
-#ifdef CONFIG_SOC_EXYNOS5250
-               void __iomem *gpx_base;
-
-               /* gpio part1 */
-               gpio_base1 = ioremap(EXYNOS5_PA_GPIO1, SZ_4K);
-               if (gpio_base1 == NULL) {
-                       pr_err("unable to ioremap for gpio_base1\n");
-                       goto err_ioremap1;
-               }
-
-               /* need to set base address for gpx */
-               chip = &exynos5_gpios_1[20];
-               gpx_base = gpio_base1 + 0xC00;
-               for (i = 0; i < 4; i++, chip++, gpx_base += 0x20)
-                       chip->base = gpx_base;
-
-               chip = exynos5_gpios_1;
-               nr_chips = ARRAY_SIZE(exynos5_gpios_1);
-
-               for (i = 0; i < nr_chips; i++, chip++) {
-                       if (!chip->config) {
-                               chip->config = &exynos_gpio_cfg;
-                               chip->group = group++;
-                       }
-                       exynos_gpiolib_attach_ofnode(chip,
-                                       EXYNOS5_PA_GPIO1, i * 0x20);
-               }
-               samsung_gpiolib_add_4bit_chips(exynos5_gpios_1,
-                                              nr_chips, gpio_base1);
-
-               /* gpio part2 */
-               gpio_base2 = ioremap(EXYNOS5_PA_GPIO2, SZ_4K);
-               if (gpio_base2 == NULL) {
-                       pr_err("unable to ioremap for gpio_base2\n");
-                       goto err_ioremap2;
-               }
-
-               chip = exynos5_gpios_2;
-               nr_chips = ARRAY_SIZE(exynos5_gpios_2);
-
-               for (i = 0; i < nr_chips; i++, chip++) {
-                       if (!chip->config) {
-                               chip->config = &exynos_gpio_cfg;
-                               chip->group = group++;
-                       }
-                       exynos_gpiolib_attach_ofnode(chip,
-                                       EXYNOS5_PA_GPIO2, i * 0x20);
-               }
-               samsung_gpiolib_add_4bit_chips(exynos5_gpios_2,
-                                              nr_chips, gpio_base2);
-
-               /* gpio part3 */
-               gpio_base3 = ioremap(EXYNOS5_PA_GPIO3, SZ_4K);
-               if (gpio_base3 == NULL) {
-                       pr_err("unable to ioremap for gpio_base3\n");
-                       goto err_ioremap3;
-               }
-
-               /* need to set base address for gpv */
-               exynos5_gpios_3[0].base = gpio_base3;
-               exynos5_gpios_3[1].base = gpio_base3 + 0x20;
-               exynos5_gpios_3[2].base = gpio_base3 + 0x60;
-               exynos5_gpios_3[3].base = gpio_base3 + 0x80;
-               exynos5_gpios_3[4].base = gpio_base3 + 0xC0;
-
-               chip = exynos5_gpios_3;
-               nr_chips = ARRAY_SIZE(exynos5_gpios_3);
-
-               for (i = 0; i < nr_chips; i++, chip++) {
-                       if (!chip->config) {
-                               chip->config = &exynos_gpio_cfg;
-                               chip->group = group++;
-                       }
-                       exynos_gpiolib_attach_ofnode(chip,
-                                       EXYNOS5_PA_GPIO3, i * 0x20);
-               }
-               samsung_gpiolib_add_4bit_chips(exynos5_gpios_3,
-                                              nr_chips, gpio_base3);
-
-               /* gpio part4 */
-               gpio_base4 = ioremap(EXYNOS5_PA_GPIO4, SZ_4K);
-               if (gpio_base4 == NULL) {
-                       pr_err("unable to ioremap for gpio_base4\n");
-                       goto err_ioremap4;
-               }
-
-               chip = exynos5_gpios_4;
-               nr_chips = ARRAY_SIZE(exynos5_gpios_4);
-
-               for (i = 0; i < nr_chips; i++, chip++) {
-                       if (!chip->config) {
-                               chip->config = &exynos_gpio_cfg;
-                               chip->group = group++;
-                       }
-                       exynos_gpiolib_attach_ofnode(chip,
-                                       EXYNOS5_PA_GPIO4, i * 0x20);
-               }
-               samsung_gpiolib_add_4bit_chips(exynos5_gpios_4,
-                                              nr_chips, gpio_base4);
-#endif /* CONFIG_SOC_EXYNOS5250 */
+               exynos5_gpiolib_init();
        } else {
                WARN(1, "Unknown SoC in gpio-samsung, no GPIOs added\n");
                return -ENODEV;
        }
 
        return 0;
-
-err_ioremap4:
-       iounmap(gpio_base3);
-err_ioremap3:
-       iounmap(gpio_base2);
-err_ioremap2:
-       iounmap(gpio_base1);
-err_ioremap1:
-       return -ENOMEM;
 }
 core_initcall(samsung_gpiolib_init);
 
index 031e5d24837dc6e8d8b8fe4a2016c306903d9f9a..820209c420e300ceb47979ae6a121db8f55cdf03 100644 (file)
@@ -282,17 +282,7 @@ static struct pci_driver sdv_gpio_driver = {
        .remove = sdv_gpio_remove,
 };
 
-static int __init sdv_gpio_init(void)
-{
-       return pci_register_driver(&sdv_gpio_driver);
-}
-module_init(sdv_gpio_init);
-
-static void __exit sdv_gpio_exit(void)
-{
-       pci_unregister_driver(&sdv_gpio_driver);
-}
-module_exit(sdv_gpio_exit);
+module_pci_driver(sdv_gpio_driver);
 
 MODULE_AUTHOR("Hans J. Koch <hjk@linutronix.de>");
 MODULE_DESCRIPTION("GPIO interface for Intel Sodaville SoCs");
diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c
new file mode 100644 (file)
index 0000000..bf984b6
--- /dev/null
@@ -0,0 +1,240 @@
+/*
+ * OF helpers for the GPIO API
+ *
+ * Copyright (c) 2007-2008  MontaVista Software, Inc.
+ *
+ * Author: Anton Vorontsov <avorontsov@ru.mvista.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/device.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_gpio.h>
+#include <linux/slab.h>
+
+/**
+ * of_get_named_gpio_flags() - Get a GPIO number and flags to use with GPIO API
+ * @np:                device node to get GPIO from
+ * @propname:  property name containing gpio specifier(s)
+ * @index:     index of the GPIO
+ * @flags:     a flags pointer to fill in
+ *
+ * Returns GPIO number to use with Linux generic GPIO API, or one of the errno
+ * value on the error condition. If @flags is not NULL the function also fills
+ * in flags for the GPIO.
+ */
+int of_get_named_gpio_flags(struct device_node *np, const char *propname,
+                           int index, enum of_gpio_flags *flags)
+{
+       int ret;
+       struct gpio_chip *gc;
+       struct of_phandle_args gpiospec;
+
+       ret = of_parse_phandle_with_args(np, propname, "#gpio-cells", index,
+                                        &gpiospec);
+       if (ret) {
+               pr_debug("%s: can't parse gpios property\n", __func__);
+               goto err0;
+       }
+
+       gc = of_node_to_gpiochip(gpiospec.np);
+       if (!gc) {
+               pr_debug("%s: gpio controller %s isn't registered\n",
+                        np->full_name, gpiospec.np->full_name);
+               ret = -ENODEV;
+               goto err1;
+       }
+
+       if (gpiospec.args_count != gc->of_gpio_n_cells) {
+               pr_debug("%s: wrong #gpio-cells for %s\n",
+                        np->full_name, gpiospec.np->full_name);
+               ret = -EINVAL;
+               goto err1;
+       }
+
+       /* .xlate might decide to not fill in the flags, so clear it. */
+       if (flags)
+               *flags = 0;
+
+       ret = gc->of_xlate(gc, &gpiospec, flags);
+       if (ret < 0)
+               goto err1;
+
+       ret += gc->base;
+err1:
+       of_node_put(gpiospec.np);
+err0:
+       pr_debug("%s exited with status %d\n", __func__, ret);
+       return ret;
+}
+EXPORT_SYMBOL(of_get_named_gpio_flags);
+
+/**
+ * of_gpio_named_count - Count GPIOs for a device
+ * @np:                device node to count GPIOs for
+ * @propname:  property name containing gpio specifier(s)
+ *
+ * The function returns the count of GPIOs specified for a node.
+ *
+ * Note that the empty GPIO specifiers counts too. For example,
+ *
+ * gpios = <0
+ *          &pio1 1 2
+ *          0
+ *          &pio2 3 4>;
+ *
+ * defines four GPIOs (so this function will return 4), two of which
+ * are not specified.
+ */
+unsigned int of_gpio_named_count(struct device_node *np, const char* propname)
+{
+       unsigned int cnt = 0;
+
+       do {
+               int ret;
+
+               ret = of_parse_phandle_with_args(np, propname, "#gpio-cells",
+                                                cnt, NULL);
+               /* A hole in the gpios = <> counts anyway. */
+               if (ret < 0 && ret != -EEXIST)
+                       break;
+       } while (++cnt);
+
+       return cnt;
+}
+EXPORT_SYMBOL(of_gpio_named_count);
+
+/**
+ * of_gpio_simple_xlate - translate gpio_spec to the GPIO number and flags
+ * @gc:                pointer to the gpio_chip structure
+ * @np:                device node of the GPIO chip
+ * @gpio_spec: gpio specifier as found in the device tree
+ * @flags:     a flags pointer to fill in
+ *
+ * This is simple translation function, suitable for the most 1:1 mapped
+ * gpio chips. This function performs only one sanity check: whether gpio
+ * is less than ngpios (that is specified in the gpio_chip).
+ */
+int of_gpio_simple_xlate(struct gpio_chip *gc,
+                        const struct of_phandle_args *gpiospec, u32 *flags)
+{
+       /*
+        * We're discouraging gpio_cells < 2, since that way you'll have to
+        * write your own xlate function (that will have to retrive the GPIO
+        * number and the flags from a single gpio cell -- this is possible,
+        * but not recommended).
+        */
+       if (gc->of_gpio_n_cells < 2) {
+               WARN_ON(1);
+               return -EINVAL;
+       }
+
+       if (WARN_ON(gpiospec->args_count < gc->of_gpio_n_cells))
+               return -EINVAL;
+
+       if (gpiospec->args[0] >= gc->ngpio)
+               return -EINVAL;
+
+       if (flags)
+               *flags = gpiospec->args[1];
+
+       return gpiospec->args[0];
+}
+EXPORT_SYMBOL(of_gpio_simple_xlate);
+
+/**
+ * of_mm_gpiochip_add - Add memory mapped GPIO chip (bank)
+ * @np:                device node of the GPIO chip
+ * @mm_gc:     pointer to the of_mm_gpio_chip allocated structure
+ *
+ * To use this function you should allocate and fill mm_gc with:
+ *
+ * 1) In the gpio_chip structure:
+ *    - all the callbacks
+ *    - of_gpio_n_cells
+ *    - of_xlate callback (optional)
+ *
+ * 3) In the of_mm_gpio_chip structure:
+ *    - save_regs callback (optional)
+ *
+ * If succeeded, this function will map bank's memory and will
+ * do all necessary work for you. Then you'll able to use .regs
+ * to manage GPIOs from the callbacks.
+ */
+int of_mm_gpiochip_add(struct device_node *np,
+                      struct of_mm_gpio_chip *mm_gc)
+{
+       int ret = -ENOMEM;
+       struct gpio_chip *gc = &mm_gc->gc;
+
+       gc->label = kstrdup(np->full_name, GFP_KERNEL);
+       if (!gc->label)
+               goto err0;
+
+       mm_gc->regs = of_iomap(np, 0);
+       if (!mm_gc->regs)
+               goto err1;
+
+       gc->base = -1;
+
+       if (mm_gc->save_regs)
+               mm_gc->save_regs(mm_gc);
+
+       mm_gc->gc.of_node = np;
+
+       ret = gpiochip_add(gc);
+       if (ret)
+               goto err2;
+
+       return 0;
+err2:
+       iounmap(mm_gc->regs);
+err1:
+       kfree(gc->label);
+err0:
+       pr_err("%s: GPIO chip registration failed with status %d\n",
+              np->full_name, ret);
+       return ret;
+}
+EXPORT_SYMBOL(of_mm_gpiochip_add);
+
+void of_gpiochip_add(struct gpio_chip *chip)
+{
+       if ((!chip->of_node) && (chip->dev))
+               chip->of_node = chip->dev->of_node;
+
+       if (!chip->of_node)
+               return;
+
+       if (!chip->of_xlate) {
+               chip->of_gpio_n_cells = 2;
+               chip->of_xlate = of_gpio_simple_xlate;
+       }
+
+       of_node_get(chip->of_node);
+}
+
+void of_gpiochip_remove(struct gpio_chip *chip)
+{
+       if (chip->of_node)
+               of_node_put(chip->of_node);
+}
+
+/* Private function for resolving node pointer to gpio_chip */
+static int of_gpiochip_is_match(struct gpio_chip *chip, const void *data)
+{
+       return chip->of_node == data;
+}
+
+struct gpio_chip *of_node_to_gpiochip(struct device_node *np)
+{
+       return gpiochip_find(np, of_gpiochip_is_match);
+}
index 5a75510d66bb14a2148c71432104fc7ac5f39d9b..566d0122d832a98f3a009ecba52961c71b73f08f 100644 (file)
@@ -1302,8 +1302,18 @@ int gpio_request_one(unsigned gpio, unsigned long flags, const char *label)
                                (flags & GPIOF_INIT_HIGH) ? 1 : 0);
 
        if (err)
-               gpio_free(gpio);
+               goto free_gpio;
+
+       if (flags & GPIOF_EXPORT) {
+               err = gpio_export(gpio, flags & GPIOF_EXPORT_CHANGEABLE);
+               if (err)
+                       goto free_gpio;
+       }
+
+       return 0;
 
+ free_gpio:
+       gpio_free(gpio);
        return err;
 }
 EXPORT_SYMBOL_GPL(gpio_request_one);
index 8e84ce9765a9257a8429cd33838ab7e4bbd8fb15..ce00d11144de3e92ca66ec285681252835dcadaa 100644 (file)
@@ -51,12 +51,6 @@ config OF_IRQ
 config OF_DEVICE
        def_bool y
 
-config OF_GPIO
-       def_bool y
-       depends on GPIOLIB && !SPARC
-       help
-         OpenFirmware GPIO accessors
-
 config OF_I2C
        def_tristate I2C
        depends on I2C && !SPARC
index aa90e602c8a7e5dfbe66770edf8e85dadcc27173..aff2c62303907529ae88a3fd2a61b2f6af214b76 100644 (file)
@@ -4,7 +4,6 @@ obj-$(CONFIG_OF_PROMTREE) += pdt.o
 obj-$(CONFIG_OF_ADDRESS)  += address.o
 obj-$(CONFIG_OF_IRQ)    += irq.o
 obj-$(CONFIG_OF_DEVICE) += device.o platform.o
-obj-$(CONFIG_OF_GPIO)   += gpio.o
 obj-$(CONFIG_OF_I2C)   += of_i2c.o
 obj-$(CONFIG_OF_NET)   += of_net.o
 obj-$(CONFIG_OF_SPI)   += of_spi.o
diff --git a/drivers/of/gpio.c b/drivers/of/gpio.c
deleted file mode 100644 (file)
index bf984b6..0000000
+++ /dev/null
@@ -1,240 +0,0 @@
-/*
- * OF helpers for the GPIO API
- *
- * Copyright (c) 2007-2008  MontaVista Software, Inc.
- *
- * Author: Anton Vorontsov <avorontsov@ru.mvista.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/device.h>
-#include <linux/errno.h>
-#include <linux/module.h>
-#include <linux/io.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/of_gpio.h>
-#include <linux/slab.h>
-
-/**
- * of_get_named_gpio_flags() - Get a GPIO number and flags to use with GPIO API
- * @np:                device node to get GPIO from
- * @propname:  property name containing gpio specifier(s)
- * @index:     index of the GPIO
- * @flags:     a flags pointer to fill in
- *
- * Returns GPIO number to use with Linux generic GPIO API, or one of the errno
- * value on the error condition. If @flags is not NULL the function also fills
- * in flags for the GPIO.
- */
-int of_get_named_gpio_flags(struct device_node *np, const char *propname,
-                           int index, enum of_gpio_flags *flags)
-{
-       int ret;
-       struct gpio_chip *gc;
-       struct of_phandle_args gpiospec;
-
-       ret = of_parse_phandle_with_args(np, propname, "#gpio-cells", index,
-                                        &gpiospec);
-       if (ret) {
-               pr_debug("%s: can't parse gpios property\n", __func__);
-               goto err0;
-       }
-
-       gc = of_node_to_gpiochip(gpiospec.np);
-       if (!gc) {
-               pr_debug("%s: gpio controller %s isn't registered\n",
-                        np->full_name, gpiospec.np->full_name);
-               ret = -ENODEV;
-               goto err1;
-       }
-
-       if (gpiospec.args_count != gc->of_gpio_n_cells) {
-               pr_debug("%s: wrong #gpio-cells for %s\n",
-                        np->full_name, gpiospec.np->full_name);
-               ret = -EINVAL;
-               goto err1;
-       }
-
-       /* .xlate might decide to not fill in the flags, so clear it. */
-       if (flags)
-               *flags = 0;
-
-       ret = gc->of_xlate(gc, &gpiospec, flags);
-       if (ret < 0)
-               goto err1;
-
-       ret += gc->base;
-err1:
-       of_node_put(gpiospec.np);
-err0:
-       pr_debug("%s exited with status %d\n", __func__, ret);
-       return ret;
-}
-EXPORT_SYMBOL(of_get_named_gpio_flags);
-
-/**
- * of_gpio_named_count - Count GPIOs for a device
- * @np:                device node to count GPIOs for
- * @propname:  property name containing gpio specifier(s)
- *
- * The function returns the count of GPIOs specified for a node.
- *
- * Note that the empty GPIO specifiers counts too. For example,
- *
- * gpios = <0
- *          &pio1 1 2
- *          0
- *          &pio2 3 4>;
- *
- * defines four GPIOs (so this function will return 4), two of which
- * are not specified.
- */
-unsigned int of_gpio_named_count(struct device_node *np, const char* propname)
-{
-       unsigned int cnt = 0;
-
-       do {
-               int ret;
-
-               ret = of_parse_phandle_with_args(np, propname, "#gpio-cells",
-                                                cnt, NULL);
-               /* A hole in the gpios = <> counts anyway. */
-               if (ret < 0 && ret != -EEXIST)
-                       break;
-       } while (++cnt);
-
-       return cnt;
-}
-EXPORT_SYMBOL(of_gpio_named_count);
-
-/**
- * of_gpio_simple_xlate - translate gpio_spec to the GPIO number and flags
- * @gc:                pointer to the gpio_chip structure
- * @np:                device node of the GPIO chip
- * @gpio_spec: gpio specifier as found in the device tree
- * @flags:     a flags pointer to fill in
- *
- * This is simple translation function, suitable for the most 1:1 mapped
- * gpio chips. This function performs only one sanity check: whether gpio
- * is less than ngpios (that is specified in the gpio_chip).
- */
-int of_gpio_simple_xlate(struct gpio_chip *gc,
-                        const struct of_phandle_args *gpiospec, u32 *flags)
-{
-       /*
-        * We're discouraging gpio_cells < 2, since that way you'll have to
-        * write your own xlate function (that will have to retrive the GPIO
-        * number and the flags from a single gpio cell -- this is possible,
-        * but not recommended).
-        */
-       if (gc->of_gpio_n_cells < 2) {
-               WARN_ON(1);
-               return -EINVAL;
-       }
-
-       if (WARN_ON(gpiospec->args_count < gc->of_gpio_n_cells))
-               return -EINVAL;
-
-       if (gpiospec->args[0] >= gc->ngpio)
-               return -EINVAL;
-
-       if (flags)
-               *flags = gpiospec->args[1];
-
-       return gpiospec->args[0];
-}
-EXPORT_SYMBOL(of_gpio_simple_xlate);
-
-/**
- * of_mm_gpiochip_add - Add memory mapped GPIO chip (bank)
- * @np:                device node of the GPIO chip
- * @mm_gc:     pointer to the of_mm_gpio_chip allocated structure
- *
- * To use this function you should allocate and fill mm_gc with:
- *
- * 1) In the gpio_chip structure:
- *    - all the callbacks
- *    - of_gpio_n_cells
- *    - of_xlate callback (optional)
- *
- * 3) In the of_mm_gpio_chip structure:
- *    - save_regs callback (optional)
- *
- * If succeeded, this function will map bank's memory and will
- * do all necessary work for you. Then you'll able to use .regs
- * to manage GPIOs from the callbacks.
- */
-int of_mm_gpiochip_add(struct device_node *np,
-                      struct of_mm_gpio_chip *mm_gc)
-{
-       int ret = -ENOMEM;
-       struct gpio_chip *gc = &mm_gc->gc;
-
-       gc->label = kstrdup(np->full_name, GFP_KERNEL);
-       if (!gc->label)
-               goto err0;
-
-       mm_gc->regs = of_iomap(np, 0);
-       if (!mm_gc->regs)
-               goto err1;
-
-       gc->base = -1;
-
-       if (mm_gc->save_regs)
-               mm_gc->save_regs(mm_gc);
-
-       mm_gc->gc.of_node = np;
-
-       ret = gpiochip_add(gc);
-       if (ret)
-               goto err2;
-
-       return 0;
-err2:
-       iounmap(mm_gc->regs);
-err1:
-       kfree(gc->label);
-err0:
-       pr_err("%s: GPIO chip registration failed with status %d\n",
-              np->full_name, ret);
-       return ret;
-}
-EXPORT_SYMBOL(of_mm_gpiochip_add);
-
-void of_gpiochip_add(struct gpio_chip *chip)
-{
-       if ((!chip->of_node) && (chip->dev))
-               chip->of_node = chip->dev->of_node;
-
-       if (!chip->of_node)
-               return;
-
-       if (!chip->of_xlate) {
-               chip->of_gpio_n_cells = 2;
-               chip->of_xlate = of_gpio_simple_xlate;
-       }
-
-       of_node_get(chip->of_node);
-}
-
-void of_gpiochip_remove(struct gpio_chip *chip)
-{
-       if (chip->of_node)
-               of_node_put(chip->of_node);
-}
-
-/* Private function for resolving node pointer to gpio_chip */
-static int of_gpiochip_is_match(struct gpio_chip *chip, const void *data)
-{
-       return chip->of_node == data;
-}
-
-struct gpio_chip *of_node_to_gpiochip(struct device_node *np)
-{
-       return gpiochip_find(np, of_gpiochip_is_match);
-}
index 6155ecf192b0466f02ea616b5b8d8ef9fd5fc2f5..7a8816a1a0d8a29e79656dc7db3979844110deb2 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef __LINUX_GPIO_H
 #define __LINUX_GPIO_H
 
+#include <linux/errno.h>
+
 /* see Documentation/gpio.txt */
 
 /* make these flag values available regardless of GPIO kconfig options */
 /* Gpio pin is open source */
 #define GPIOF_OPEN_SOURCE      (1 << 3)
 
+#define GPIOF_EXPORT           (1 << 2)
+#define GPIOF_EXPORT_CHANGEABLE        (1 << 3)
+#define GPIOF_EXPORT_DIR_FIXED (GPIOF_EXPORT)
+#define GPIOF_EXPORT_DIR_CHANGEABLE (GPIOF_EXPORT | GPIOF_EXPORT_CHANGEABLE)
+
 /**
  * struct gpio - a structure describing a GPIO with configuration
  * @gpio:      the GPIO number
@@ -33,7 +40,39 @@ struct gpio {
 };
 
 #ifdef CONFIG_GENERIC_GPIO
+
+#ifdef CONFIG_ARCH_HAVE_CUSTOM_GPIO_H
 #include <asm/gpio.h>
+#else
+
+#include <asm-generic/gpio.h>
+
+static inline int gpio_get_value(unsigned int gpio)
+{
+       return __gpio_get_value(gpio);
+}
+
+static inline void gpio_set_value(unsigned int gpio, int value)
+{
+       __gpio_set_value(gpio, value);
+}
+
+static inline int gpio_cansleep(unsigned int gpio)
+{
+       return __gpio_cansleep(gpio);
+}
+
+static inline int gpio_to_irq(unsigned int gpio)
+{
+       return __gpio_to_irq(gpio);
+}
+
+static inline int irq_to_gpio(unsigned int irq)
+{
+       return -EINVAL;
+}
+
+#endif
 
 #else
 
@@ -55,6 +94,12 @@ static inline int gpio_request(unsigned gpio, const char *label)
        return -ENOSYS;
 }
 
+static inline int devm_gpio_request(struct device *dev, unsigned gpio,
+                                   const char *label)
+{
+       return -ENOSYS;
+}
+
 static inline int gpio_request_one(unsigned gpio,
                                        unsigned long flags, const char *label)
 {
@@ -74,6 +119,14 @@ static inline void gpio_free(unsigned gpio)
        WARN_ON(1);
 }
 
+static inline void devm_gpio_free(struct device *dev, unsigned gpio)
+{
+       might_sleep();
+
+       /* GPIO can never have been requested */
+       WARN_ON(1);
+}
+
 static inline void gpio_free_array(const struct gpio *array, size_t num)
 {
        might_sleep();