From fc3a1f04f5040255cbc086c419e4237f29f89f88 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Tue, 13 Dec 2011 18:34:01 +0100 Subject: gpio: add flags to export GPIOs when requesting Introduce new flags to automatically export GPIOs when using the convenience functions gpio_request_one() or gpio_request_array(). This eases support for custom boards where lots of GPIOs need to be exported for customer applications. Signed-off-by: Wolfram Sang Signed-off-by: Grant Likely --- include/linux/gpio.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'include') diff --git a/include/linux/gpio.h b/include/linux/gpio.h index 6155ecf192b0..af511a682925 100644 --- a/include/linux/gpio.h +++ b/include/linux/gpio.h @@ -20,6 +20,11 @@ /* 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 -- cgit v1.2.3 From 2c96922ae3f0bfb7324a7a433d96d319fe6de729 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 4 Apr 2012 16:14:48 +0100 Subject: gpiolib: Add !CONFIG_GPIOLIB definitions of devm_ functions Currently the managed gpio_request() and gpio_free() are not stubbed out for configurations not using gpiolib - do that to aid use in drivers. Signed-off-by: Mark Brown Signed-off-by: Grant Likely --- include/linux/gpio.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'include') diff --git a/include/linux/gpio.h b/include/linux/gpio.h index af511a682925..d1890d46b6ce 100644 --- a/include/linux/gpio.h +++ b/include/linux/gpio.h @@ -60,6 +60,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) { @@ -79,6 +85,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(); -- cgit v1.2.3 From 7563bbf89d065a2c3f05059ecbcc805645edcc62 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sun, 15 Apr 2012 10:52:54 +0100 Subject: gpiolib/arches: Centralise bolierplate asm/gpio.h Rather than requiring architectures that use gpiolib but don't have any need to define anything custom to copy an asm/gpio.h provide a Kconfig symbol which architectures must select in order to include gpio.h and for other architectures just provide the trivial implementation directly. This makes it much easier to do gpiolib updates and is also a step towards making gpiolib APIs available on every architecture. For architectures with existing boilerplate code leave a stub header in place which warns on direct inclusion of asm/gpio.h and includes linux/gpio.h to catch code that's doing this. Direct inclusion of asm/gpio.h has long been deprecated. Signed-off-by: Mark Brown Acked-by: Jonas Bonn Acked-by: Tony Luck Acked-by: Linus Walleij Signed-off-by: Grant Likely --- arch/alpha/include/asm/gpio.h | 59 +++----------------------------- arch/arm/Kconfig | 1 + arch/avr32/Kconfig | 1 + arch/blackfin/Kconfig | 1 + arch/ia64/include/asm/gpio.h | 59 +++----------------------------- arch/m68k/Kconfig.cpu | 1 + arch/microblaze/include/asm/gpio.h | 57 +++---------------------------- arch/mips/Kconfig | 1 + arch/openrisc/include/asm/gpio.h | 69 +++----------------------------------- arch/powerpc/include/asm/gpio.h | 57 +++---------------------------- arch/sh/Kconfig | 1 + arch/sparc/include/asm/gpio.h | 40 +++------------------- arch/unicore32/Kconfig | 1 + arch/x86/include/asm/gpio.h | 57 +++---------------------------- arch/xtensa/include/asm/gpio.h | 60 +++------------------------------ drivers/gpio/Kconfig | 8 +++++ include/linux/gpio.h | 34 +++++++++++++++++++ 17 files changed, 81 insertions(+), 426 deletions(-) (limited to 'include') diff --git a/arch/alpha/include/asm/gpio.h b/arch/alpha/include/asm/gpio.h index 7dc6a6343c06..b3799d88ffcf 100644 --- a/arch/alpha/include/asm/gpio.h +++ b/arch/alpha/include/asm/gpio.h @@ -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 - * - * 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 -#include - -#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 +#endif diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 36586dba6fa6..777025e773d9 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -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 diff --git a/arch/avr32/Kconfig b/arch/avr32/Kconfig index 3dea7231f637..859b2de4a624 100644 --- a/arch/avr32/Kconfig +++ b/arch/avr32/Kconfig @@ -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, diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig index 373a6902d8fa..bf3d80f9738b 100644 --- a/arch/blackfin/Kconfig +++ b/arch/blackfin/Kconfig @@ -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 diff --git a/arch/ia64/include/asm/gpio.h b/arch/ia64/include/asm/gpio.h index 590a20debc4e..b3799d88ffcf 100644 --- a/arch/ia64/include/asm/gpio.h +++ b/arch/ia64/include/asm/gpio.h @@ -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 - * - * 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 -#include - -#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 +#endif diff --git a/arch/m68k/Kconfig.cpu b/arch/m68k/Kconfig.cpu index 8a9c767125a4..8941af1d3ad2 100644 --- a/arch/m68k/Kconfig.cpu +++ b/arch/m68k/Kconfig.cpu @@ -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 diff --git a/arch/microblaze/include/asm/gpio.h b/arch/microblaze/include/asm/gpio.h index 2b2c18be71c6..b3799d88ffcf 100644 --- a/arch/microblaze/include/asm/gpio.h +++ b/arch/microblaze/include/asm/gpio.h @@ -1,53 +1,4 @@ -/* - * Generic GPIO API implementation for PowerPC. - * - * Copyright (c) 2007-2008 MontaVista Software, Inc. - * - * Author: Anton Vorontsov - * - * 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 -#include - -#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 +#endif diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index ce30e2f91d77..63321b283fe4 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -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 diff --git a/arch/openrisc/include/asm/gpio.h b/arch/openrisc/include/asm/gpio.h index 0b0d174f47cd..b3799d88ffcf 100644 --- a/arch/openrisc/include/asm/gpio.h +++ b/arch/openrisc/include/asm/gpio.h @@ -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 - * Copyright (C) 2010-2011 Jonas Bonn - * 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 -#include - -#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 +#endif diff --git a/arch/powerpc/include/asm/gpio.h b/arch/powerpc/include/asm/gpio.h index 38762edb5e58..b3799d88ffcf 100644 --- a/arch/powerpc/include/asm/gpio.h +++ b/arch/powerpc/include/asm/gpio.h @@ -1,53 +1,4 @@ -/* - * Generic GPIO API implementation for PowerPC. - * - * Copyright (c) 2007-2008 MontaVista Software, Inc. - * - * Author: Anton Vorontsov - * - * 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 -#include - -#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 +#endif diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index ff9e033ce626..c40b29ac3644 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -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 diff --git a/arch/sparc/include/asm/gpio.h b/arch/sparc/include/asm/gpio.h index a0e3ac0af599..b3799d88ffcf 100644 --- a/arch/sparc/include/asm/gpio.h +++ b/arch/sparc/include/asm/gpio.h @@ -1,36 +1,4 @@ -#ifndef __ASM_SPARC_GPIO_H -#define __ASM_SPARC_GPIO_H - -#include -#include - -#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 +#endif diff --git a/arch/unicore32/Kconfig b/arch/unicore32/Kconfig index eeb8054c7cd8..7ff6d10c0be2 100644 --- a/arch/unicore32/Kconfig +++ b/arch/unicore32/Kconfig @@ -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 diff --git a/arch/x86/include/asm/gpio.h b/arch/x86/include/asm/gpio.h index 91d915a65259..b3799d88ffcf 100644 --- a/arch/x86/include/asm/gpio.h +++ b/arch/x86/include/asm/gpio.h @@ -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 - * - * 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 - -#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 +#endif diff --git a/arch/xtensa/include/asm/gpio.h b/arch/xtensa/include/asm/gpio.h index a8c9fc46c790..b3799d88ffcf 100644 --- a/arch/xtensa/include/asm/gpio.h +++ b/arch/xtensa/include/asm/gpio.h @@ -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 - * - * 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 - -#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 +#endif diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 5169a99e9f61..25535ebf4f90 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -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 diff --git a/include/linux/gpio.h b/include/linux/gpio.h index d1890d46b6ce..7a8816a1a0d8 100644 --- a/include/linux/gpio.h +++ b/include/linux/gpio.h @@ -1,6 +1,8 @@ #ifndef __LINUX_GPIO_H #define __LINUX_GPIO_H +#include + /* see Documentation/gpio.txt */ /* make these flag values available regardless of GPIO kconfig options */ @@ -38,7 +40,39 @@ struct gpio { }; #ifdef CONFIG_GENERIC_GPIO + +#ifdef CONFIG_ARCH_HAVE_CUSTOM_GPIO_H #include +#else + +#include + +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 -- cgit v1.2.3 From 09d71ff19404b3957fab6de942fb8026ccfd8524 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 2 May 2012 12:46:46 +0100 Subject: gpiolib: Implement devm_gpio_request_one() Allow drivers to use the modern request and configure idiom together with devres. As with plain gpio_request() and gpio_request_one() we can't implement the old school version in terms of _one() as this would force the explicit selection of a direction in gpio_request() which could break systems if we pick the wrong one. Implementing devm_gpio_request_one() in terms of devm_gpio_request() would needlessly complicate things or lead to duplication from the unmanaged version depending on how it's done. Signed-off-by: Mark Brown Acked-by: Linus Walleij Signed-off-by: Grant Likely --- drivers/gpio/devres.c | 29 +++++++++++++++++++++++++++++ include/asm-generic/gpio.h | 2 ++ include/linux/gpio.h | 6 ++++++ 3 files changed, 37 insertions(+) (limited to 'include') diff --git a/drivers/gpio/devres.c b/drivers/gpio/devres.c index 3dd29399cef5..d21a9ff38551 100644 --- a/drivers/gpio/devres.c +++ b/drivers/gpio/devres.c @@ -70,6 +70,35 @@ int devm_gpio_request(struct device *dev, unsigned gpio, const char *label) } EXPORT_SYMBOL(devm_gpio_request); +/** + * devm_gpio_request_one - request a single GPIO with initial setup + * @dev: device to request for + * @gpio: the GPIO number + * @flags: GPIO configuration as specified by GPIOF_* + * @label: a literal description string of this GPIO + */ +int devm_gpio_request_one(struct device *dev, unsigned gpio, + unsigned long flags, const char *label) +{ + unsigned *dr; + int rc; + + dr = devres_alloc(devm_gpio_release, sizeof(unsigned), GFP_KERNEL); + if (!dr) + return -ENOMEM; + + rc = gpio_request_one(gpio, flags, label); + if (rc) { + devres_free(dr); + return rc; + } + + *dr = gpio; + devres_add(dev, dr); + + return 0; +} + /** * devm_gpio_free - free an interrupt * @dev: device to free gpio for diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h index 5f52690c3c8f..4ead12332c66 100644 --- a/include/asm-generic/gpio.h +++ b/include/asm-generic/gpio.h @@ -179,6 +179,8 @@ extern void gpio_free_array(const struct gpio *array, size_t num); /* bindings for managed devices that want to request gpios */ int devm_gpio_request(struct device *dev, unsigned gpio, const char *label); +int devm_gpio_request_one(struct device *dev, unsigned gpio, + unsigned long flags, const char *label); void devm_gpio_free(struct device *dev, unsigned int gpio); #ifdef CONFIG_GPIO_SYSFS diff --git a/include/linux/gpio.h b/include/linux/gpio.h index 7a8816a1a0d8..f07fc2d08159 100644 --- a/include/linux/gpio.h +++ b/include/linux/gpio.h @@ -106,6 +106,12 @@ static inline int gpio_request_one(unsigned gpio, return -ENOSYS; } +static inline int devm_gpio_request_one(struct device *dev, unsigned gpio, + unsigned long flags, const char *label) +{ + return -ENOSYS; +} + static inline int gpio_request_array(const struct gpio *array, size_t num) { return -ENOSYS; -- cgit v1.2.3 From 3d0f7cf0f3633f92ddeb767eb59cab73963d4dee Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Thu, 17 May 2012 13:54:40 -0600 Subject: gpio: Adjust of_xlate API to support multiple GPIO chips This patch changes the of_xlate API to make it possible for multiple gpio_chips to refer to the same device tree node. This is useful for banked GPIO controllers that use multiple gpio_chips for a single device. With this change the core code will try calling of_xlate on each gpio_chip that references the device_node and will return the gpio number for the first one to return 'true'. Tested-by: Roland Stigge Acked-by: Arnd Bergmann Signed-off-by: Grant Likely --- arch/arm/mach-imx/mach-mx35_3ds.c | 3 +- drivers/gpio/gpiolib-of.c | 80 +++++++++++++++++++-------------------- drivers/gpio/gpiolib.c | 2 +- include/asm-generic/gpio.h | 2 +- include/linux/of_gpio.h | 1 - 5 files changed, 41 insertions(+), 47 deletions(-) (limited to 'include') diff --git a/arch/arm/mach-imx/mach-mx35_3ds.c b/arch/arm/mach-imx/mach-mx35_3ds.c index 6ae51c6b95b7..6a7cf91ee819 100644 --- a/arch/arm/mach-imx/mach-mx35_3ds.c +++ b/arch/arm/mach-imx/mach-mx35_3ds.c @@ -96,8 +96,7 @@ static struct i2c_board_info __initdata i2c_devices_3ds[] = { static int lcd_power_gpio = -ENXIO; -static int mc9s08dz60_gpiochip_match(struct gpio_chip *chip, - const void *data) +static int mc9s08dz60_gpiochip_match(struct gpio_chip *chip, void *data) { return !strcmp(chip->label, data); } diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c index bf984b6dc477..d18068a9f3ec 100644 --- a/drivers/gpio/gpiolib-of.c +++ b/drivers/gpio/gpiolib-of.c @@ -15,11 +15,39 @@ #include #include #include +#include #include #include #include #include +/* Private data structure for of_gpiochip_is_match */ +struct gg_data { + enum of_gpio_flags *flags; + struct of_phandle_args gpiospec; + + int out_gpio; +}; + +/* Private function for resolving node pointer to gpio_chip */ +static int of_gpiochip_find_and_xlate(struct gpio_chip *gc, void *data) +{ + struct gg_data *gg_data = data; + int ret; + + if ((gc->of_node != gg_data->gpiospec.np) || + (gc->of_gpio_n_cells != gg_data->gpiospec.args_count) || + (!gc->of_xlate)) + return false; + + ret = gc->of_xlate(gc, &gg_data->gpiospec, gg_data->flags); + if (ret < 0) + return false; + + gg_data->out_gpio = ret + gc->base; + return true; +} + /** * of_get_named_gpio_flags() - Get a GPIO number and flags to use with GPIO API * @np: device node to get GPIO from @@ -34,46 +62,25 @@ int of_get_named_gpio_flags(struct device_node *np, const char *propname, int index, enum of_gpio_flags *flags) { + struct gg_data gg_data = { .flags = flags, .out_gpio = -ENODEV }; int ret; - struct gpio_chip *gc; - struct of_phandle_args gpiospec; + + /* .of_xlate might decide to not fill in the flags, so clear it. */ + if (flags) + *flags = 0; ret = of_parse_phandle_with_args(np, propname, "#gpio-cells", index, - &gpiospec); + &gg_data.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; + return -EINVAL; } - /* .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; + gpiochip_find(&gg_data, of_gpiochip_find_and_xlate); - ret += gc->base; -err1: - of_node_put(gpiospec.np); -err0: + of_node_put(gg_data.gpiospec.np); pr_debug("%s exited with status %d\n", __func__, ret); - return ret; + return gg_data.out_gpio; } EXPORT_SYMBOL(of_get_named_gpio_flags); @@ -227,14 +234,3 @@ 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); -} diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 566d0122d832..38353c028fdd 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1156,7 +1156,7 @@ EXPORT_SYMBOL_GPL(gpiochip_remove); */ struct gpio_chip *gpiochip_find(const void *data, int (*match)(struct gpio_chip *chip, - const void *data)) + void *data)) { struct gpio_chip *chip = NULL; unsigned long flags; diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h index 4ead12332c66..1ba08f0e49a3 100644 --- a/include/asm-generic/gpio.h +++ b/include/asm-generic/gpio.h @@ -144,7 +144,7 @@ extern int gpiochip_add(struct gpio_chip *chip); extern int __must_check gpiochip_remove(struct gpio_chip *chip); extern struct gpio_chip *gpiochip_find(const void *data, int (*match)(struct gpio_chip *chip, - const void *data)); + void *data)); /* Always use the library code for GPIO management calls, diff --git a/include/linux/of_gpio.h b/include/linux/of_gpio.h index 81733d12cbea..c454f5796747 100644 --- a/include/linux/of_gpio.h +++ b/include/linux/of_gpio.h @@ -58,7 +58,6 @@ extern int of_mm_gpiochip_add(struct device_node *np, extern void of_gpiochip_add(struct gpio_chip *gc); extern void of_gpiochip_remove(struct gpio_chip *gc); -extern struct gpio_chip *of_node_to_gpiochip(struct device_node *np); extern int of_gpio_simple_xlate(struct gpio_chip *gc, const struct of_phandle_args *gpiospec, u32 *flags); -- cgit v1.2.3 From e9fe32bcadb8a7a40411d77f168abd45941b049b Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Mon, 14 May 2012 12:46:12 +0530 Subject: gpio/rc5t583: add gpio driver for RICOH PMIC RC5T583 The PMIC device RC5T583 from RICOH supports 8 gpios. Adding gpio driver for this device to access the pins control through gpio library. Signed-off-by: Laxman Dewangan [grant.likely: slight cosmetic changes] Signed-off-by: Grant Likely --- drivers/gpio/Kconfig | 9 +++ drivers/gpio/Makefile | 1 + drivers/gpio/gpio-rc5t583.c | 180 ++++++++++++++++++++++++++++++++++++++++++++ include/linux/mfd/rc5t583.h | 2 + 4 files changed, 192 insertions(+) create mode 100644 drivers/gpio/gpio-rc5t583.c (limited to 'include') diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 25535ebf4f90..7028f7bee7fc 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -301,6 +301,15 @@ config GPIO_PCF857X This driver provides an in-kernel interface to those GPIOs using platform-neutral GPIO calls. +config GPIO_RC5T583 + bool "RICOH RC5T583 GPIO" + depends on MFD_RC5T583 + help + Select this option to enable GPIO driver for the Ricoh RC5T583 + chip family. + This driver provides the support for driving/reading the gpio pins + of RC5T583 device through standard gpio library. + config GPIO_SX150X bool "Semtech SX150x I2C GPIO expander" depends on I2C=y diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 7862f49b4d05..8f36637b4ae3 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -45,6 +45,7 @@ obj-$(CONFIG_GPIO_PCF857X) += gpio-pcf857x.o obj-$(CONFIG_GPIO_PCH) += gpio-pch.o obj-$(CONFIG_GPIO_PL061) += gpio-pl061.o obj-$(CONFIG_GPIO_PXA) += gpio-pxa.o +obj-$(CONFIG_GPIO_RC5T583) += gpio-rc5t583.o obj-$(CONFIG_GPIO_RDC321X) += gpio-rdc321x.o obj-$(CONFIG_PLAT_SAMSUNG) += gpio-samsung.o obj-$(CONFIG_ARCH_SA1100) += gpio-sa1100.o diff --git a/drivers/gpio/gpio-rc5t583.c b/drivers/gpio/gpio-rc5t583.c new file mode 100644 index 000000000000..08428bf17718 --- /dev/null +++ b/drivers/gpio/gpio-rc5t583.c @@ -0,0 +1,180 @@ +/* + * GPIO driver for RICOH583 power management chip. + * + * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. + * Author: Laxman dewangan + * + * Based on code + * Copyright (C) 2011 RICOH COMPANY,LTD + * + * 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, see . + * + */ +#include +#include +#include +#include +#include +#include +#include +#include + +struct rc5t583_gpio { + struct gpio_chip gpio_chip; + struct rc5t583 *rc5t583; +}; + +static inline struct rc5t583_gpio *to_rc5t583_gpio(struct gpio_chip *chip) +{ + return container_of(chip, struct rc5t583_gpio, gpio_chip); +} + +static int rc5t583_gpio_get(struct gpio_chip *gc, unsigned int offset) +{ + struct rc5t583_gpio *rc5t583_gpio = to_rc5t583_gpio(gc); + struct device *parent = rc5t583_gpio->rc5t583->dev; + uint8_t val = 0; + int ret; + + ret = rc5t583_read(parent, RC5T583_GPIO_MON_IOIN, &val); + if (ret < 0) + return ret; + + return !!(val & BIT(offset)); +} + +static void rc5t583_gpio_set(struct gpio_chip *gc, unsigned int offset, int val) +{ + struct rc5t583_gpio *rc5t583_gpio = to_rc5t583_gpio(gc); + struct device *parent = rc5t583_gpio->rc5t583->dev; + if (val) + rc5t583_set_bits(parent, RC5T583_GPIO_IOOUT, BIT(offset)); + else + rc5t583_clear_bits(parent, RC5T583_GPIO_IOOUT, BIT(offset)); +} + +static int rc5t583_gpio_dir_input(struct gpio_chip *gc, unsigned int offset) +{ + struct rc5t583_gpio *rc5t583_gpio = to_rc5t583_gpio(gc); + struct device *parent = rc5t583_gpio->rc5t583->dev; + int ret; + + ret = rc5t583_clear_bits(parent, RC5T583_GPIO_IOSEL, BIT(offset)); + if (ret < 0) + return ret; + + /* Set pin to gpio mode */ + return rc5t583_clear_bits(parent, RC5T583_GPIO_PGSEL, BIT(offset)); +} + +static int rc5t583_gpio_dir_output(struct gpio_chip *gc, unsigned offset, + int value) +{ + struct rc5t583_gpio *rc5t583_gpio = to_rc5t583_gpio(gc); + struct device *parent = rc5t583_gpio->rc5t583->dev; + int ret; + + rc5t583_gpio_set(gc, offset, value); + ret = rc5t583_set_bits(parent, RC5T583_GPIO_IOSEL, BIT(offset)); + if (ret < 0) + return ret; + + /* Set pin to gpio mode */ + return rc5t583_clear_bits(parent, RC5T583_GPIO_PGSEL, BIT(offset)); +} + +static int rc5t583_gpio_to_irq(struct gpio_chip *gc, unsigned offset) +{ + struct rc5t583_gpio *rc5t583_gpio = to_rc5t583_gpio(gc); + + if ((offset >= 0) && (offset < 8)) + return rc5t583_gpio->rc5t583->irq_base + + RC5T583_IRQ_GPIO0 + offset; + return -EINVAL; +} + +static void rc5t583_gpio_free(struct gpio_chip *gc, unsigned offset) +{ + struct rc5t583_gpio *rc5t583_gpio = to_rc5t583_gpio(gc); + struct device *parent = rc5t583_gpio->rc5t583->dev; + + rc5t583_set_bits(parent, RC5T583_GPIO_PGSEL, BIT(offset)); +} + +static int __devinit rc5t583_gpio_probe(struct platform_device *pdev) +{ + struct rc5t583 *rc5t583 = dev_get_drvdata(pdev->dev.parent); + struct rc5t583_platform_data *pdata = dev_get_platdata(rc5t583->dev); + struct rc5t583_gpio *rc5t583_gpio; + + rc5t583_gpio = devm_kzalloc(&pdev->dev, sizeof(*rc5t583_gpio), + GFP_KERNEL); + if (!rc5t583_gpio) { + dev_warn(&pdev->dev, "Mem allocation for rc5t583_gpio failed"); + return -ENOMEM; + } + + rc5t583_gpio->gpio_chip.label = "gpio-rc5t583", + rc5t583_gpio->gpio_chip.owner = THIS_MODULE, + rc5t583_gpio->gpio_chip.free = rc5t583_gpio_free, + rc5t583_gpio->gpio_chip.direction_input = rc5t583_gpio_dir_input, + rc5t583_gpio->gpio_chip.direction_output = rc5t583_gpio_dir_output, + rc5t583_gpio->gpio_chip.set = rc5t583_gpio_set, + rc5t583_gpio->gpio_chip.get = rc5t583_gpio_get, + rc5t583_gpio->gpio_chip.to_irq = rc5t583_gpio_to_irq, + rc5t583_gpio->gpio_chip.ngpio = RC5T583_MAX_GPIO, + rc5t583_gpio->gpio_chip.can_sleep = 1, + rc5t583_gpio->gpio_chip.dev = &pdev->dev; + rc5t583_gpio->gpio_chip.base = -1; + rc5t583_gpio->rc5t583 = rc5t583; + + if (pdata && pdata->gpio_base) + rc5t583_gpio->gpio_chip.base = pdata->gpio_base; + + platform_set_drvdata(pdev, rc5t583_gpio); + + return gpiochip_add(&rc5t583_gpio->gpio_chip); +} + +static int __devexit rc5t583_gpio_remove(struct platform_device *pdev) +{ + struct rc5t583_gpio *rc5t583_gpio = platform_get_drvdata(pdev); + + return gpiochip_remove(&rc5t583_gpio->gpio_chip); +} + +static struct platform_driver rc5t583_gpio_driver = { + .driver = { + .name = "rc5t583-gpio", + .owner = THIS_MODULE, + }, + .probe = rc5t583_gpio_probe, + .remove = __devexit_p(rc5t583_gpio_remove), +}; + +static int __init rc5t583_gpio_init(void) +{ + return platform_driver_register(&rc5t583_gpio_driver); +} +subsys_initcall(rc5t583_gpio_init); + +static void __exit rc5t583_gpio_exit(void) +{ + platform_driver_unregister(&rc5t583_gpio_driver); +} +module_exit(rc5t583_gpio_exit); + +MODULE_AUTHOR("Laxman Dewangan "); +MODULE_DESCRIPTION("GPIO interface for RC5T583"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:rc5t583-gpio"); diff --git a/include/linux/mfd/rc5t583.h b/include/linux/mfd/rc5t583.h index 0b64b19d81ab..7875370f7bca 100644 --- a/include/linux/mfd/rc5t583.h +++ b/include/linux/mfd/rc5t583.h @@ -272,11 +272,13 @@ struct rc5t583 { * rc5t583_platform_data: Platform data for ricoh rc5t583 pmu. * The board specific data is provided through this structure. * @irq_base: Irq base number on which this device registers their interrupts. + * @gpio_base: GPIO base from which gpio of this device will start. * @enable_shutdown: Enable shutdown through the input pin "shutdown". */ struct rc5t583_platform_data { int irq_base; + int gpio_base; bool enable_shutdown; }; -- cgit v1.2.3 From 07ce8ec7308ab3fa55fe2861671b157f857fff58 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Fri, 18 May 2012 23:01:05 -0600 Subject: gpiolib: Remove 'const' from data argument of gpiochip_find() Commit 3d0f7cf0 "gpio: Adjust of_xlate API to support multiple GPIO chips" changed the api of gpiochip_find to drop const from the data parameter of the match hook, but didn't also drop const from data causing a build warning. Signed-off-by: Grant Likely --- drivers/gpio/gpiolib.c | 2 +- include/asm-generic/gpio.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index e48b70c6ddf1..120b2a0e3167 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1154,7 +1154,7 @@ EXPORT_SYMBOL_GPL(gpiochip_remove); * non-zero, this function will return to the caller and not iterate over any * more gpio_chips. */ -struct gpio_chip *gpiochip_find(const void *data, +struct gpio_chip *gpiochip_find(void *data, int (*match)(struct gpio_chip *chip, void *data)) { diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h index 1ba08f0e49a3..365ea09ed3b0 100644 --- a/include/asm-generic/gpio.h +++ b/include/asm-generic/gpio.h @@ -142,7 +142,7 @@ extern int __must_check gpiochip_reserve(int start, int ngpio); /* add/remove chips */ extern int gpiochip_add(struct gpio_chip *chip); extern int __must_check gpiochip_remove(struct gpio_chip *chip); -extern struct gpio_chip *gpiochip_find(const void *data, +extern struct gpio_chip *gpiochip_find(void *data, int (*match)(struct gpio_chip *chip, void *data)); -- cgit v1.2.3 From 3e11f7b840b4671213c66817294ad7dd0b572756 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Sat, 19 May 2012 21:34:58 +0800 Subject: gpio/generic: initialize basic_mmio_gpio shadow variables properly It fixes the issue in gpio-generic that commit fb14921 (gpio/mxc: add missing initialization of basic_mmio_gpio shadow variables) manged to fix in gpio-mxc driver, so that other platform specific drivers do not suffer from the same problem over and over again. Changes since v1: * Turn the last parameter of bgpio_init() "bool big_endian" into "unsigned long flags" and give those really quirky hardwares a chance to tell that reg_set and reg_dir are unreadable. Signed-off-by: Shawn Guo [grant.likely: Fix big-endian usage to explicitly set BBGPIOF_BIG_ENDIAN] Signed-off-by: Grant Likely --- drivers/gpio/gpio-ep93xx.c | 2 +- drivers/gpio/gpio-generic.c | 16 +++++++++++----- drivers/gpio/gpio-mxc.c | 2 +- drivers/gpio/gpio-mxs.c | 2 +- drivers/gpio/gpio-sodaville.c | 2 +- include/linux/basic_mmio_gpio.h | 6 +++++- 6 files changed, 20 insertions(+), 10 deletions(-) (limited to 'include') diff --git a/drivers/gpio/gpio-ep93xx.c b/drivers/gpio/gpio-ep93xx.c index 776b772523e5..9fe5b8fe9be8 100644 --- a/drivers/gpio/gpio-ep93xx.c +++ b/drivers/gpio/gpio-ep93xx.c @@ -325,7 +325,7 @@ static int ep93xx_gpio_add_bank(struct bgpio_chip *bgc, struct device *dev, void __iomem *dir = mmio_base + bank->dir; int err; - err = bgpio_init(bgc, dev, 1, data, NULL, NULL, dir, NULL, false); + err = bgpio_init(bgc, dev, 1, data, NULL, NULL, dir, NULL, 0); if (err) return err; diff --git a/drivers/gpio/gpio-generic.c b/drivers/gpio/gpio-generic.c index e38dd0c31973..82e2e4fe599e 100644 --- a/drivers/gpio/gpio-generic.c +++ b/drivers/gpio/gpio-generic.c @@ -364,7 +364,7 @@ EXPORT_SYMBOL_GPL(bgpio_remove); int bgpio_init(struct bgpio_chip *bgc, struct device *dev, unsigned long sz, void __iomem *dat, void __iomem *set, void __iomem *clr, void __iomem *dirout, void __iomem *dirin, - bool big_endian) + unsigned long flags) { int ret; @@ -385,7 +385,7 @@ int bgpio_init(struct bgpio_chip *bgc, struct device *dev, if (ret) return ret; - ret = bgpio_setup_accessors(dev, bgc, big_endian); + ret = bgpio_setup_accessors(dev, bgc, flags & BGPIOF_BIG_ENDIAN); if (ret) return ret; @@ -394,6 +394,11 @@ int bgpio_init(struct bgpio_chip *bgc, struct device *dev, return ret; bgc->data = bgc->read_reg(bgc->reg_dat); + if (bgc->gc.set == bgpio_set_set && + !(flags & BGPIOF_UNREADABLE_REG_SET)) + bgc->data = bgc->read_reg(bgc->reg_set); + if (bgc->reg_dir && !(flags & BGPIOF_UNREADABLE_REG_DIR)) + bgc->dir = bgc->read_reg(bgc->reg_dir); return ret; } @@ -449,7 +454,7 @@ static int __devinit bgpio_pdev_probe(struct platform_device *pdev) void __iomem *dirout; void __iomem *dirin; unsigned long sz; - bool be; + unsigned long flags = 0; int err; struct bgpio_chip *bgc; struct bgpio_pdata *pdata = dev_get_platdata(dev); @@ -480,13 +485,14 @@ static int __devinit bgpio_pdev_probe(struct platform_device *pdev) if (err) return err; - be = !strcmp(platform_get_device_id(pdev)->name, "basic-mmio-gpio-be"); + if (!strcmp(platform_get_device_id(pdev)->name, "basic-mmio-gpio-be")) + flags |= BGPIOF_BIG_ENDIAN; bgc = devm_kzalloc(&pdev->dev, sizeof(*bgc), GFP_KERNEL); if (!bgc) return -ENOMEM; - err = bgpio_init(bgc, dev, sz, dat, set, clr, dirout, dirin, be); + err = bgpio_init(bgc, dev, sz, dat, set, clr, dirout, dirin, flags); if (err) return err; diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c index e79147634573..c337143b18f8 100644 --- a/drivers/gpio/gpio-mxc.c +++ b/drivers/gpio/gpio-mxc.c @@ -417,7 +417,7 @@ static int __devinit mxc_gpio_probe(struct platform_device *pdev) err = bgpio_init(&port->bgc, &pdev->dev, 4, port->base + GPIO_PSR, port->base + GPIO_DR, NULL, - port->base + GPIO_GDIR, NULL, false); + port->base + GPIO_GDIR, NULL, 0); if (err) goto out_iounmap; diff --git a/drivers/gpio/gpio-mxs.c b/drivers/gpio/gpio-mxs.c index 385c58e8405b..b4136501abd8 100644 --- a/drivers/gpio/gpio-mxs.c +++ b/drivers/gpio/gpio-mxs.c @@ -244,7 +244,7 @@ static int __devinit mxs_gpio_probe(struct platform_device *pdev) err = bgpio_init(&port->bgc, &pdev->dev, 4, port->base + PINCTRL_DIN(port->id), port->base + PINCTRL_DOUT(port->id), NULL, - port->base + PINCTRL_DOE(port->id), NULL, false); + port->base + PINCTRL_DOE(port->id), NULL, 0); if (err) goto out_iounmap; diff --git a/drivers/gpio/gpio-sodaville.c b/drivers/gpio/gpio-sodaville.c index 820209c420e3..9d9891f7a607 100644 --- a/drivers/gpio/gpio-sodaville.c +++ b/drivers/gpio/gpio-sodaville.c @@ -224,7 +224,7 @@ static int __devinit sdv_gpio_probe(struct pci_dev *pdev, ret = bgpio_init(&sd->bgpio, &pdev->dev, 4, sd->gpio_pub_base + GPINR, sd->gpio_pub_base + GPOUTR, - NULL, sd->gpio_pub_base + GPOER, NULL, false); + NULL, sd->gpio_pub_base + GPOER, NULL, 0); if (ret) goto unmap; sd->bgpio.gc.ngpio = SDV_NUM_PUB_GPIOS; diff --git a/include/linux/basic_mmio_gpio.h b/include/linux/basic_mmio_gpio.h index feb912196745..1c504ca5bdb3 100644 --- a/include/linux/basic_mmio_gpio.h +++ b/include/linux/basic_mmio_gpio.h @@ -67,6 +67,10 @@ int bgpio_remove(struct bgpio_chip *bgc); int bgpio_init(struct bgpio_chip *bgc, struct device *dev, unsigned long sz, void __iomem *dat, void __iomem *set, void __iomem *clr, void __iomem *dirout, void __iomem *dirin, - bool big_endian); + unsigned long flags); + +#define BGPIOF_BIG_ENDIAN BIT(0) +#define BGPIOF_UNREADABLE_REG_SET BIT(1) /* reg_set is unreadable */ +#define BGPIOF_UNREADABLE_REG_DIR BIT(2) /* reg_dir is unreadable */ #endif /* __BASIC_MMIO_GPIO_H */ -- cgit v1.2.3