From ebe5a0596f2ee4182dc42b39583be71e81aa0443 Mon Sep 17 00:00:00 2001 From: Tony Prisk Date: Mon, 31 Dec 2012 09:29:34 +1300 Subject: gpio: vt8500: Export dedicated GPIO before multifunction pins. The vendor does not provide numbering for gpio pins. Vendor source exports dedicated gpio pins first, followed by multifunction pins. As this is what end users expect, this patch changes vt8500 and wm8505 to do the same. Signed-off-by: Tony Prisk Signed-off-by: Linus Walleij --- drivers/gpio/gpio-vt8500.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpio/gpio-vt8500.c b/drivers/gpio/gpio-vt8500.c index b53320a16fc8..9a7c434d2947 100644 --- a/drivers/gpio/gpio-vt8500.c +++ b/drivers/gpio/gpio-vt8500.c @@ -73,19 +73,20 @@ struct vt8500_gpio_data { static struct vt8500_gpio_data vt8500_data = { .num_banks = 7, .banks = { + VT8500_BANK(NO_REG, 0x3C, 0x5C, 0x7C, 9), VT8500_BANK(0x00, 0x20, 0x40, 0x60, 26), VT8500_BANK(0x04, 0x24, 0x44, 0x64, 28), VT8500_BANK(0x08, 0x28, 0x48, 0x68, 31), VT8500_BANK(0x0C, 0x2C, 0x4C, 0x6C, 19), VT8500_BANK(0x10, 0x30, 0x50, 0x70, 19), VT8500_BANK(0x14, 0x34, 0x54, 0x74, 23), - VT8500_BANK(NO_REG, 0x3C, 0x5C, 0x7C, 9), }, }; static struct vt8500_gpio_data wm8505_data = { .num_banks = 10, .banks = { + VT8500_BANK(0x64, 0x8C, 0xB4, 0xDC, 22), VT8500_BANK(0x40, 0x68, 0x90, 0xB8, 8), VT8500_BANK(0x44, 0x6C, 0x94, 0xBC, 32), VT8500_BANK(0x48, 0x70, 0x98, 0xC0, 6), @@ -95,7 +96,6 @@ static struct vt8500_gpio_data wm8505_data = { VT8500_BANK(0x58, 0x80, 0xA8, 0xD0, 5), VT8500_BANK(0x5C, 0x84, 0xAC, 0xD4, 12), VT8500_BANK(0x60, 0x88, 0xB0, 0xD8, 16), - VT8500_BANK(0x64, 0x8C, 0xB4, 0xDC, 22), VT8500_BANK(0x500, 0x504, 0x508, 0x50C, 6), }, }; -- cgit v1.2.3 From 72c7901ef00925c6d0cc7ab69183a684908303bc Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 6 Dec 2012 10:52:05 +0000 Subject: gpio: twl4030: Introduce private structure to store variables needed runtime Move most of the global variables inside a private structure and allocate it dynamically. Signed-off-by: Peter Ujfalusi Signed-off-by: Linus Walleij --- drivers/gpio/gpio-twl4030.c | 82 +++++++++++++++++++++++++++------------------ 1 file changed, 50 insertions(+), 32 deletions(-) diff --git a/drivers/gpio/gpio-twl4030.c b/drivers/gpio/gpio-twl4030.c index 9572aa137e6f..4643f9cd0cae 100644 --- a/drivers/gpio/gpio-twl4030.c +++ b/drivers/gpio/gpio-twl4030.c @@ -49,11 +49,6 @@ * There are also two LED pins used sometimes as output-only GPIOs. */ - -static struct gpio_chip twl_gpiochip; -static int twl4030_gpio_base; -static int twl4030_gpio_irq_base; - /* genirq interfaces are not available to modules */ #ifdef MODULE #define is_module() true @@ -72,11 +67,20 @@ static int twl4030_gpio_irq_base; /* Data structures */ static DEFINE_MUTEX(gpio_lock); -/* store usage of each GPIO. - each bit represents one GPIO */ -static unsigned int gpio_usage_count; +struct gpio_twl4030_priv { + struct gpio_chip gpio_chip; + int irq_base; + + unsigned int usage_count; +}; /*----------------------------------------------------------------------*/ +static inline struct gpio_twl4030_priv *to_gpio_twl4030(struct gpio_chip *chip) +{ + return container_of(chip, struct gpio_twl4030_priv, gpio_chip); +} + /* * To configure TWL4030 GPIO module registers */ @@ -193,10 +197,6 @@ static int twl4030_get_gpio_datain(int gpio) u8 base = 0; int ret = 0; - if (unlikely((gpio >= TWL4030_GPIO_MAX) - || !(gpio_usage_count & BIT(gpio)))) - return -EPERM; - base = REG_GPIODATAIN1 + d_bnk; ret = gpio_twl4030_read(base); if (ret > 0) @@ -209,6 +209,7 @@ static int twl4030_get_gpio_datain(int gpio) static int twl_request(struct gpio_chip *chip, unsigned offset) { + struct gpio_twl4030_priv *priv = to_gpio_twl4030(chip); int status = 0; mutex_lock(&gpio_lock); @@ -252,7 +253,7 @@ static int twl_request(struct gpio_chip *chip, unsigned offset) } /* on first use, turn GPIO module "on" */ - if (!gpio_usage_count) { + if (!priv->usage_count) { struct twl4030_gpio_platform_data *pdata; u8 value = MASK_GPIO_CTRL_GPIO_ON; @@ -266,16 +267,18 @@ static int twl_request(struct gpio_chip *chip, unsigned offset) status = gpio_twl4030_write(REG_GPIO_CTRL, value); } +done: if (!status) - gpio_usage_count |= (0x1 << offset); + priv->usage_count |= BIT(offset); -done: mutex_unlock(&gpio_lock); return status; } static void twl_free(struct gpio_chip *chip, unsigned offset) { + struct gpio_twl4030_priv *priv = to_gpio_twl4030(chip); + if (offset >= TWL4030_GPIO_MAX) { twl4030_led_set_value(offset - TWL4030_GPIO_MAX, 1); return; @@ -283,10 +286,10 @@ static void twl_free(struct gpio_chip *chip, unsigned offset) mutex_lock(&gpio_lock); - gpio_usage_count &= ~BIT(offset); + priv->usage_count &= ~BIT(offset); /* on last use, switch off GPIO module */ - if (!gpio_usage_count) + if (!priv->usage_count) gpio_twl4030_write(REG_GPIO_CTRL, 0x0); mutex_unlock(&gpio_lock); @@ -301,14 +304,19 @@ static int twl_direction_in(struct gpio_chip *chip, unsigned offset) static int twl_get(struct gpio_chip *chip, unsigned offset) { + struct gpio_twl4030_priv *priv = to_gpio_twl4030(chip); int status = 0; + if (!(priv->usage_count & BIT(offset))) + return -EPERM; + if (offset < TWL4030_GPIO_MAX) status = twl4030_get_gpio_datain(offset); else if (offset == TWL4030_GPIO_MAX) status = cached_leden & LEDEN_LEDAON; else status = cached_leden & LEDEN_LEDBON; + return (status < 0) ? 0 : status; } @@ -333,12 +341,14 @@ static void twl_set(struct gpio_chip *chip, unsigned offset, int value) static int twl_to_irq(struct gpio_chip *chip, unsigned offset) { - return (twl4030_gpio_irq_base && (offset < TWL4030_GPIO_MAX)) - ? (twl4030_gpio_irq_base + offset) + struct gpio_twl4030_priv *priv = to_gpio_twl4030(chip); + + return (priv->irq_base && (offset < TWL4030_GPIO_MAX)) + ? (priv->irq_base + offset) : -EINVAL; } -static struct gpio_chip twl_gpiochip = { +static struct gpio_chip template_chip = { .label = "twl4030", .owner = THIS_MODULE, .request = twl_request, @@ -424,8 +434,14 @@ static int gpio_twl4030_probe(struct platform_device *pdev) { struct twl4030_gpio_platform_data *pdata = pdev->dev.platform_data; struct device_node *node = pdev->dev.of_node; + struct gpio_twl4030_priv *priv; int ret, irq_base; + priv = devm_kzalloc(&pdev->dev, sizeof(struct gpio_twl4030_priv), + GFP_KERNEL); + if (!priv) + return -ENOMEM; + /* maybe setup IRQs */ if (is_module()) { dev_err(&pdev->dev, "can't dispatch IRQs from modules\n"); @@ -445,12 +461,13 @@ static int gpio_twl4030_probe(struct platform_device *pdev) if (ret < 0) return ret; - twl4030_gpio_irq_base = irq_base; + priv->irq_base = irq_base; no_irqs: - twl_gpiochip.base = -1; - twl_gpiochip.ngpio = TWL4030_GPIO_MAX; - twl_gpiochip.dev = &pdev->dev; + priv->gpio_chip = template_chip; + priv->gpio_chip.base = -1; + priv->gpio_chip.ngpio = TWL4030_GPIO_MAX; + priv->gpio_chip.dev = &pdev->dev; if (node) pdata = of_gpio_twl4030(&pdev->dev); @@ -481,23 +498,23 @@ no_irqs: * is (still) clear if use_leds is set. */ if (pdata->use_leds) - twl_gpiochip.ngpio += 2; + priv->gpio_chip.ngpio += 2; - ret = gpiochip_add(&twl_gpiochip); + ret = gpiochip_add(&priv->gpio_chip); if (ret < 0) { dev_err(&pdev->dev, "could not register gpiochip, %d\n", ret); - twl_gpiochip.ngpio = 0; + priv->gpio_chip.ngpio = 0; gpio_twl4030_remove(pdev); goto out; } - twl4030_gpio_base = twl_gpiochip.base; + platform_set_drvdata(pdev, priv); if (pdata && pdata->setup) { int status; - status = pdata->setup(&pdev->dev, - twl4030_gpio_base, TWL4030_GPIO_MAX); + status = pdata->setup(&pdev->dev, priv->gpio_chip.base, + TWL4030_GPIO_MAX); if (status) dev_dbg(&pdev->dev, "setup --> %d\n", status); } @@ -510,18 +527,19 @@ out: static int gpio_twl4030_remove(struct platform_device *pdev) { struct twl4030_gpio_platform_data *pdata = pdev->dev.platform_data; + struct gpio_twl4030_priv *priv = platform_get_drvdata(pdev); int status; if (pdata && pdata->teardown) { - status = pdata->teardown(&pdev->dev, - twl4030_gpio_base, TWL4030_GPIO_MAX); + status = pdata->teardown(&pdev->dev, priv->gpio_chip.base, + TWL4030_GPIO_MAX); if (status) { dev_dbg(&pdev->dev, "teardown --> %d\n", status); return status; } } - status = gpiochip_remove(&twl_gpiochip); + status = gpiochip_remove(&priv->gpio_chip); if (status < 0) return status; -- cgit v1.2.3 From c111feabe2e200b15300d97107ffc1280bf8de2a Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 20 Dec 2012 10:44:11 +0100 Subject: gpio: twl4030: Cache the direction and output states in private data Use more coherent locking in the driver. Use bitfield to store the GPIO direction and if the pin is configured as output store the status also in a bitfiled. In this way we can just look at these bitfields when we need information about the pin status and only reach out to the chip when it is needed. Signed-off-by: Peter Ujfalusi Acked-by: Linus Walleij Signed-off-by: Linus Walleij --- drivers/gpio/gpio-twl4030.c | 100 ++++++++++++++++++++++++++++---------------- 1 file changed, 65 insertions(+), 35 deletions(-) diff --git a/drivers/gpio/gpio-twl4030.c b/drivers/gpio/gpio-twl4030.c index 4643f9cd0cae..4d330e36da1d 100644 --- a/drivers/gpio/gpio-twl4030.c +++ b/drivers/gpio/gpio-twl4030.c @@ -37,7 +37,6 @@ #include - /* * The GPIO "subchip" supports 18 GPIOs which can be configured as * inputs or outputs, with pullups or pulldowns on each pin. Each @@ -64,14 +63,15 @@ /* Mask for GPIO registers when aggregated into a 32-bit integer */ #define GPIO_32_MASK 0x0003ffff -/* Data structures */ -static DEFINE_MUTEX(gpio_lock); - struct gpio_twl4030_priv { struct gpio_chip gpio_chip; + struct mutex mutex; int irq_base; + /* Bitfields for state caching */ unsigned int usage_count; + unsigned int direction; + unsigned int out_state; }; /*----------------------------------------------------------------------*/ @@ -130,7 +130,7 @@ static inline int gpio_twl4030_read(u8 address) /*----------------------------------------------------------------------*/ -static u8 cached_leden; /* protected by gpio_lock */ +static u8 cached_leden; /* The LED lines are open drain outputs ... a FET pulls to GND, so an * external pullup is needed. We could also expose the integrated PWM @@ -144,14 +144,12 @@ static void twl4030_led_set_value(int led, int value) if (led) mask <<= 1; - mutex_lock(&gpio_lock); if (value) cached_leden &= ~mask; else cached_leden |= mask; status = twl_i2c_write_u8(TWL4030_MODULE_LED, cached_leden, TWL4030_LED_LEDEN_REG); - mutex_unlock(&gpio_lock); } static int twl4030_set_gpio_direction(int gpio, int is_input) @@ -162,7 +160,6 @@ static int twl4030_set_gpio_direction(int gpio, int is_input) u8 base = REG_GPIODATADIR1 + d_bnk; int ret = 0; - mutex_lock(&gpio_lock); ret = gpio_twl4030_read(base); if (ret >= 0) { if (is_input) @@ -172,7 +169,6 @@ static int twl4030_set_gpio_direction(int gpio, int is_input) ret = gpio_twl4030_write(base, reg); } - mutex_unlock(&gpio_lock); return ret; } @@ -212,7 +208,7 @@ static int twl_request(struct gpio_chip *chip, unsigned offset) struct gpio_twl4030_priv *priv = to_gpio_twl4030(chip); int status = 0; - mutex_lock(&gpio_lock); + mutex_lock(&priv->mutex); /* Support the two LED outputs as output-only GPIOs. */ if (offset >= TWL4030_GPIO_MAX) { @@ -271,7 +267,7 @@ done: if (!status) priv->usage_count |= BIT(offset); - mutex_unlock(&gpio_lock); + mutex_unlock(&priv->mutex); return status; } @@ -279,64 +275,96 @@ static void twl_free(struct gpio_chip *chip, unsigned offset) { struct gpio_twl4030_priv *priv = to_gpio_twl4030(chip); + mutex_lock(&priv->mutex); if (offset >= TWL4030_GPIO_MAX) { twl4030_led_set_value(offset - TWL4030_GPIO_MAX, 1); - return; + goto out; } - mutex_lock(&gpio_lock); - priv->usage_count &= ~BIT(offset); /* on last use, switch off GPIO module */ if (!priv->usage_count) gpio_twl4030_write(REG_GPIO_CTRL, 0x0); - mutex_unlock(&gpio_lock); +out: + mutex_unlock(&priv->mutex); } static int twl_direction_in(struct gpio_chip *chip, unsigned offset) { - return (offset < TWL4030_GPIO_MAX) - ? twl4030_set_gpio_direction(offset, 1) - : -EINVAL; + struct gpio_twl4030_priv *priv = to_gpio_twl4030(chip); + int ret; + + mutex_lock(&priv->mutex); + if (offset < TWL4030_GPIO_MAX) + ret = twl4030_set_gpio_direction(offset, 1); + else + ret = -EINVAL; + + if (!ret) + priv->direction &= ~BIT(offset); + + mutex_unlock(&priv->mutex); + + return ret; } static int twl_get(struct gpio_chip *chip, unsigned offset) { struct gpio_twl4030_priv *priv = to_gpio_twl4030(chip); + int ret; int status = 0; - if (!(priv->usage_count & BIT(offset))) - return -EPERM; + mutex_lock(&priv->mutex); + if (!(priv->usage_count & BIT(offset))) { + ret = -EPERM; + goto out; + } - if (offset < TWL4030_GPIO_MAX) - status = twl4030_get_gpio_datain(offset); - else if (offset == TWL4030_GPIO_MAX) - status = cached_leden & LEDEN_LEDAON; + if (priv->direction & BIT(offset)) + status = priv->out_state & BIT(offset); else - status = cached_leden & LEDEN_LEDBON; + status = twl4030_get_gpio_datain(offset); - return (status < 0) ? 0 : status; + ret = (status <= 0) ? 0 : 1; +out: + mutex_unlock(&priv->mutex); + return ret; } -static int twl_direction_out(struct gpio_chip *chip, unsigned offset, int value) +static void twl_set(struct gpio_chip *chip, unsigned offset, int value) { - if (offset < TWL4030_GPIO_MAX) { + struct gpio_twl4030_priv *priv = to_gpio_twl4030(chip); + + mutex_lock(&priv->mutex); + if (offset < TWL4030_GPIO_MAX) twl4030_set_gpio_dataout(offset, value); - return twl4030_set_gpio_direction(offset, 0); - } else { + else twl4030_led_set_value(offset - TWL4030_GPIO_MAX, value); - return 0; - } + + if (value) + priv->out_state |= BIT(offset); + else + priv->out_state &= ~BIT(offset); + + mutex_unlock(&priv->mutex); } -static void twl_set(struct gpio_chip *chip, unsigned offset, int value) +static int twl_direction_out(struct gpio_chip *chip, unsigned offset, int value) { + struct gpio_twl4030_priv *priv = to_gpio_twl4030(chip); + + mutex_lock(&priv->mutex); if (offset < TWL4030_GPIO_MAX) twl4030_set_gpio_dataout(offset, value); - else - twl4030_led_set_value(offset - TWL4030_GPIO_MAX, value); + + priv->direction |= BIT(offset); + mutex_unlock(&priv->mutex); + + twl_set(chip, offset, value); + + return 0; } static int twl_to_irq(struct gpio_chip *chip, unsigned offset) @@ -469,6 +497,8 @@ no_irqs: priv->gpio_chip.ngpio = TWL4030_GPIO_MAX; priv->gpio_chip.dev = &pdev->dev; + mutex_init(&priv->mutex); + if (node) pdata = of_gpio_twl4030(&pdev->dev); -- cgit v1.2.3 From d59b4eaaf04db07a02f092bfcb00de7f2e2d10db Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Thu, 17 Jan 2013 22:03:22 +0800 Subject: gpio: fix warning of 'struct gpio_chip' declaration The struct gpio_chip is only defined inside #ifdef CONFIG_GPIOLIB, but it's referenced by gpiochip_add_pin_range() and gpiochip_remove_pin_ranges() which are outside #ifdef CONFIG_GPIOLIB. Thus, we see the following warning when building blackfin image, where GPIOLIB is not required. CC arch/blackfin/kernel/bfin_gpio.o CC init/version.o In file included from arch/blackfin/include/asm/gpio.h:321, from arch/blackfin/kernel/bfin_gpio.c:15: include/asm-generic/gpio.h:298: warning: 'struct gpio_chip' declared inside parameter list include/asm-generic/gpio.h:298: warning: its scope is only this definition or declaration, which is probably not what you want include/asm-generic/gpio.h:304: warning: 'struct gpio_chip' declared inside parameter list Move pinctrl trunk into #ifdef CONFIG_GPIOLIB to fix the warning, since it appears that pinctrl gpio range support depends on GPIOLIB. Signed-off-by: Shawn Guo Signed-off-by: Linus Walleij --- include/asm-generic/gpio.h | 74 +++++++++++++++++++++++----------------------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h index 20ca7663975f..23410147555f 100644 --- a/include/asm-generic/gpio.h +++ b/include/asm-generic/gpio.h @@ -212,6 +212,43 @@ extern void gpio_unexport(unsigned gpio); #endif /* CONFIG_GPIO_SYSFS */ +#ifdef CONFIG_PINCTRL + +/** + * struct gpio_pin_range - pin range controlled by a gpio chip + * @head: list for maintaining set of pin ranges, used internally + * @pctldev: pinctrl device which handles corresponding pins + * @range: actual range of pins controlled by a gpio controller + */ + +struct gpio_pin_range { + struct list_head node; + struct pinctrl_dev *pctldev; + struct pinctrl_gpio_range range; +}; + +int gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name, + unsigned int gpio_offset, unsigned int pin_offset, + unsigned int npins); +void gpiochip_remove_pin_ranges(struct gpio_chip *chip); + +#else + +static inline int +gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name, + unsigned int gpio_offset, unsigned int pin_offset, + unsigned int npins) +{ + return 0; +} + +static inline void +gpiochip_remove_pin_ranges(struct gpio_chip *chip) +{ +} + +#endif /* CONFIG_PINCTRL */ + #else /* !CONFIG_GPIOLIB */ static inline bool gpio_is_valid(int number) @@ -270,41 +307,4 @@ static inline void gpio_unexport(unsigned gpio) } #endif /* CONFIG_GPIO_SYSFS */ -#ifdef CONFIG_PINCTRL - -/** - * struct gpio_pin_range - pin range controlled by a gpio chip - * @head: list for maintaining set of pin ranges, used internally - * @pctldev: pinctrl device which handles corresponding pins - * @range: actual range of pins controlled by a gpio controller - */ - -struct gpio_pin_range { - struct list_head node; - struct pinctrl_dev *pctldev; - struct pinctrl_gpio_range range; -}; - -int gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name, - unsigned int gpio_offset, unsigned int pin_offset, - unsigned int npins); -void gpiochip_remove_pin_ranges(struct gpio_chip *chip); - -#else - -static inline int -gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name, - unsigned int gpio_offset, unsigned int pin_offset, - unsigned int npins) -{ - return 0; -} - -static inline void -gpiochip_remove_pin_ranges(struct gpio_chip *chip) -{ -} - -#endif /* CONFIG_PINCTRL */ - #endif /* _ASM_GENERIC_GPIO_H */ -- cgit v1.2.3 From 6a89a314ab107a12af08c71420c19a37a30fc2d3 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Fri, 18 Jan 2013 15:57:46 +0800 Subject: gpio: devm_gpio_* support should not depend on GPIOLIB Some architectures (e.g. blackfin) provide gpio API without requiring GPIOLIB support (ARCH_WANT_OPTIONAL_GPIOLIB). devm_gpio_* functions should also work for these architectures, since they do not really depend on GPIOLIB. Add a new option GPIO_DEVRES (enabled by default) to control the build of devres.c. It also removes the empty version of devm_gpio_* functions for !GENERIC_GPIO build from linux/gpio.h, and moves the function declarations from asm-generic/gpio.h into linux/gpio.h. Signed-off-by: Shawn Guo Signed-off-by: Linus Walleij --- drivers/gpio/Kconfig | 3 +++ drivers/gpio/Makefile | 3 ++- include/asm-generic/gpio.h | 6 ------ include/linux/gpio.h | 28 ++++++++-------------------- 4 files changed, 13 insertions(+), 27 deletions(-) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 682de754d63f..d9729322b1c7 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -30,6 +30,9 @@ config ARCH_REQUIRE_GPIOLIB Selecting this from the architecture code will cause the gpiolib code to always get built in. +config GPIO_DEVRES + def_bool y + depends on HAS_IOMEM menuconfig GPIOLIB diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index c5aebd008dde..36ca605ff038 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -2,7 +2,8 @@ ccflags-$(CONFIG_DEBUG_GPIO) += -DDEBUG -obj-$(CONFIG_GPIOLIB) += gpiolib.o devres.o +obj-$(CONFIG_GPIO_DEVRES) += devres.o +obj-$(CONFIG_GPIOLIB) += gpiolib.o obj-$(CONFIG_OF_GPIO) += gpiolib-of.o obj-$(CONFIG_GPIO_ACPI) += gpiolib-acpi.o diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h index 23410147555f..45b8916805f3 100644 --- a/include/asm-generic/gpio.h +++ b/include/asm-generic/gpio.h @@ -192,12 +192,6 @@ extern int gpio_request_one(unsigned gpio, unsigned long flags, const char *labe extern int gpio_request_array(const struct gpio *array, size_t num); 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 bfe665621536..f6c7ae3e223b 100644 --- a/include/linux/gpio.h +++ b/include/linux/gpio.h @@ -94,24 +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) { 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; @@ -125,14 +113,6 @@ 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(); @@ -248,4 +228,12 @@ gpiochip_remove_pin_ranges(struct gpio_chip *chip) #endif /* ! CONFIG_GENERIC_GPIO */ +struct device; + +/* 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); + #endif /* __LINUX_GPIO_H */ -- cgit v1.2.3 From 5985d76cc1b62125301754c9b636a18c346bfc52 Mon Sep 17 00:00:00 2001 From: Haojian Zhuang Date: Fri, 18 Jan 2013 15:31:13 +0800 Subject: gpio: pl061: set initcall level to module init Replace subsys initcall by module initcall level. Since pinctrl driver is already launched before gpio driver. It's unnecessary to set gpio driver in subsys init call level. Signed-off-by: Haojian Zhuang Tested-by: Dinh Nguyen Signed-off-by: Linus Walleij --- drivers/gpio/gpio-pl061.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-pl061.c b/drivers/gpio/gpio-pl061.c index c1720de18a4f..b820869ca93c 100644 --- a/drivers/gpio/gpio-pl061.c +++ b/drivers/gpio/gpio-pl061.c @@ -365,7 +365,7 @@ static int __init pl061_gpio_init(void) { return amba_driver_register(&pl061_gpio_driver); } -subsys_initcall(pl061_gpio_init); +module_init(pl061_gpio_init); MODULE_AUTHOR("Baruch Siach "); MODULE_DESCRIPTION("PL061 GPIO driver"); -- cgit v1.2.3 From f5f0b7aa897ebf6b0d077356a787526212460dd7 Mon Sep 17 00:00:00 2001 From: Gregory CLEMENT Date: Tue, 22 Jan 2013 22:10:23 +0100 Subject: gpio: pca953x: make the register access by GPIO bank Until now the pca953x driver accessed all the bank of a given register in a single command using only a 32 bits variable. New expanders from the pca53x family come with 40 GPIOs which no more fit in a 32 variable. This patch make access to the registers more generic by relying on an array of u8 variables. This fits exactly the way the registers are represented in the hardware. It also adds helpers to access to a single register of a bank instead of reading or writing all the banks for a given register. Signed-off-by: Gregory CLEMENT Tested-by: Maxime Ripard Signed-off-by: Linus Walleij --- drivers/gpio/gpio-pca953x.c | 281 +++++++++++++++++++++++++++----------------- 1 file changed, 175 insertions(+), 106 deletions(-) diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index cc102d25ee24..b35ba0690163 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -71,18 +71,23 @@ static const struct i2c_device_id pca953x_id[] = { }; MODULE_DEVICE_TABLE(i2c, pca953x_id); +#define MAX_BANK 5 +#define BANK_SZ 8 + +#define NBANK(chip) (chip->gpio_chip.ngpio / BANK_SZ) + struct pca953x_chip { unsigned gpio_start; - u32 reg_output; - u32 reg_direction; + u8 reg_output[MAX_BANK]; + u8 reg_direction[MAX_BANK]; struct mutex i2c_lock; #ifdef CONFIG_GPIO_PCA953X_IRQ struct mutex irq_lock; - u32 irq_mask; - u32 irq_stat; - u32 irq_trig_raise; - u32 irq_trig_fall; + u8 irq_mask[MAX_BANK]; + u8 irq_stat[MAX_BANK]; + u8 irq_trig_raise[MAX_BANK]; + u8 irq_trig_fall[MAX_BANK]; int irq_base; struct irq_domain *domain; #endif @@ -93,33 +98,69 @@ struct pca953x_chip { int chip_type; }; -static int pca953x_write_reg(struct pca953x_chip *chip, int reg, u32 val) +static int pca953x_read_single(struct pca953x_chip *chip, int reg, u32 *val, + int off) +{ + int ret; + int bank_shift = fls((chip->gpio_chip.ngpio - 1) / BANK_SZ); + int offset = off / BANK_SZ; + + ret = i2c_smbus_read_byte_data(chip->client, + (reg << bank_shift) + offset); + *val = ret; + + if (ret < 0) { + dev_err(&chip->client->dev, "failed reading register\n"); + return ret; + } + + return 0; +} + +static int pca953x_write_single(struct pca953x_chip *chip, int reg, u32 val, + int off) +{ + int ret = 0; + int bank_shift = fls((chip->gpio_chip.ngpio - 1) / BANK_SZ); + int offset = off / BANK_SZ; + + ret = i2c_smbus_write_byte_data(chip->client, + (reg << bank_shift) + offset, val); + + if (ret < 0) { + dev_err(&chip->client->dev, "failed writing register\n"); + return ret; + } + + return 0; +} + +static int pca953x_write_regs(struct pca953x_chip *chip, int reg, u8 *val) { int ret = 0; if (chip->gpio_chip.ngpio <= 8) - ret = i2c_smbus_write_byte_data(chip->client, reg, val); - else if (chip->gpio_chip.ngpio == 24) { - cpu_to_le32s(&val); + ret = i2c_smbus_write_byte_data(chip->client, reg, *val); + else if (chip->gpio_chip.ngpio >= 24) { + int bank_shift = fls((chip->gpio_chip.ngpio - 1) / BANK_SZ); ret = i2c_smbus_write_i2c_block_data(chip->client, - (reg << 2) | REG_ADDR_AI, - 3, - (u8 *) &val); + (reg << bank_shift) | REG_ADDR_AI, + NBANK(chip), val); } else { switch (chip->chip_type) { case PCA953X_TYPE: ret = i2c_smbus_write_word_data(chip->client, - reg << 1, val); + reg << 1, (u16) *val); break; case PCA957X_TYPE: ret = i2c_smbus_write_byte_data(chip->client, reg << 1, - val & 0xff); + val[0]); if (ret < 0) break; ret = i2c_smbus_write_byte_data(chip->client, (reg << 1) + 1, - (val & 0xff00) >> 8); + val[1]); break; } } @@ -132,26 +173,24 @@ static int pca953x_write_reg(struct pca953x_chip *chip, int reg, u32 val) return 0; } -static int pca953x_read_reg(struct pca953x_chip *chip, int reg, u32 *val) +static int pca953x_read_regs(struct pca953x_chip *chip, int reg, u8 *val) { int ret; if (chip->gpio_chip.ngpio <= 8) { ret = i2c_smbus_read_byte_data(chip->client, reg); *val = ret; - } - else if (chip->gpio_chip.ngpio == 24) { - *val = 0; + } else if (chip->gpio_chip.ngpio >= 24) { + int bank_shift = fls((chip->gpio_chip.ngpio - 1) / BANK_SZ); + ret = i2c_smbus_read_i2c_block_data(chip->client, - (reg << 2) | REG_ADDR_AI, - 3, - (u8 *) val); - le32_to_cpus(val); + (reg << bank_shift) | REG_ADDR_AI, + NBANK(chip), val); } else { ret = i2c_smbus_read_word_data(chip->client, reg << 1); - *val = ret; + val[0] = (u16)ret & 0xFF; + val[1] = (u16)ret >> 8; } - if (ret < 0) { dev_err(&chip->client->dev, "failed reading register\n"); return ret; @@ -163,13 +202,13 @@ static int pca953x_read_reg(struct pca953x_chip *chip, int reg, u32 *val) static int pca953x_gpio_direction_input(struct gpio_chip *gc, unsigned off) { struct pca953x_chip *chip; - uint reg_val; + u8 reg_val; int ret, offset = 0; chip = container_of(gc, struct pca953x_chip, gpio_chip); mutex_lock(&chip->i2c_lock); - reg_val = chip->reg_direction | (1u << off); + reg_val = chip->reg_direction[off / BANK_SZ] | (1u << (off % BANK_SZ)); switch (chip->chip_type) { case PCA953X_TYPE: @@ -179,11 +218,11 @@ static int pca953x_gpio_direction_input(struct gpio_chip *gc, unsigned off) offset = PCA957X_CFG; break; } - ret = pca953x_write_reg(chip, offset, reg_val); + ret = pca953x_write_single(chip, offset, reg_val, off); if (ret) goto exit; - chip->reg_direction = reg_val; + chip->reg_direction[off / BANK_SZ] = reg_val; ret = 0; exit: mutex_unlock(&chip->i2c_lock); @@ -194,7 +233,7 @@ static int pca953x_gpio_direction_output(struct gpio_chip *gc, unsigned off, int val) { struct pca953x_chip *chip; - uint reg_val; + u8 reg_val; int ret, offset = 0; chip = container_of(gc, struct pca953x_chip, gpio_chip); @@ -202,9 +241,11 @@ static int pca953x_gpio_direction_output(struct gpio_chip *gc, mutex_lock(&chip->i2c_lock); /* set output level */ if (val) - reg_val = chip->reg_output | (1u << off); + reg_val = chip->reg_output[off / BANK_SZ] + | (1u << (off % BANK_SZ)); else - reg_val = chip->reg_output & ~(1u << off); + reg_val = chip->reg_output[off / BANK_SZ] + & ~(1u << (off % BANK_SZ)); switch (chip->chip_type) { case PCA953X_TYPE: @@ -214,14 +255,14 @@ static int pca953x_gpio_direction_output(struct gpio_chip *gc, offset = PCA957X_OUT; break; } - ret = pca953x_write_reg(chip, offset, reg_val); + ret = pca953x_write_single(chip, offset, reg_val, off); if (ret) goto exit; - chip->reg_output = reg_val; + chip->reg_output[off / BANK_SZ] = reg_val; /* then direction */ - reg_val = chip->reg_direction & ~(1u << off); + reg_val = chip->reg_direction[off / BANK_SZ] & ~(1u << (off % BANK_SZ)); switch (chip->chip_type) { case PCA953X_TYPE: offset = PCA953X_DIRECTION; @@ -230,11 +271,11 @@ static int pca953x_gpio_direction_output(struct gpio_chip *gc, offset = PCA957X_CFG; break; } - ret = pca953x_write_reg(chip, offset, reg_val); + ret = pca953x_write_single(chip, offset, reg_val, off); if (ret) goto exit; - chip->reg_direction = reg_val; + chip->reg_direction[off / BANK_SZ] = reg_val; ret = 0; exit: mutex_unlock(&chip->i2c_lock); @@ -258,7 +299,7 @@ static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off) offset = PCA957X_IN; break; } - ret = pca953x_read_reg(chip, offset, ®_val); + ret = pca953x_read_single(chip, offset, ®_val, off); mutex_unlock(&chip->i2c_lock); if (ret < 0) { /* NOTE: diagnostic already emitted; that's all we should @@ -274,16 +315,18 @@ static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off) static void pca953x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val) { struct pca953x_chip *chip; - u32 reg_val; + u8 reg_val; int ret, offset = 0; chip = container_of(gc, struct pca953x_chip, gpio_chip); mutex_lock(&chip->i2c_lock); if (val) - reg_val = chip->reg_output | (1u << off); + reg_val = chip->reg_output[off / BANK_SZ] + | (1u << (off % BANK_SZ)); else - reg_val = chip->reg_output & ~(1u << off); + reg_val = chip->reg_output[off / BANK_SZ] + & ~(1u << (off % BANK_SZ)); switch (chip->chip_type) { case PCA953X_TYPE: @@ -293,11 +336,11 @@ static void pca953x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val) offset = PCA957X_OUT; break; } - ret = pca953x_write_reg(chip, offset, reg_val); + ret = pca953x_write_single(chip, offset, reg_val, off); if (ret) goto exit; - chip->reg_output = reg_val; + chip->reg_output[off / BANK_SZ] = reg_val; exit: mutex_unlock(&chip->i2c_lock); } @@ -335,14 +378,14 @@ static void pca953x_irq_mask(struct irq_data *d) { struct pca953x_chip *chip = irq_data_get_irq_chip_data(d); - chip->irq_mask &= ~(1 << d->hwirq); + chip->irq_mask[d->hwirq / BANK_SZ] &= ~(1 << (d->hwirq % BANK_SZ)); } static void pca953x_irq_unmask(struct irq_data *d) { struct pca953x_chip *chip = irq_data_get_irq_chip_data(d); - chip->irq_mask |= 1 << d->hwirq; + chip->irq_mask[d->hwirq / BANK_SZ] |= 1 << (d->hwirq % BANK_SZ); } static void pca953x_irq_bus_lock(struct irq_data *d) @@ -355,17 +398,20 @@ static void pca953x_irq_bus_lock(struct irq_data *d) static void pca953x_irq_bus_sync_unlock(struct irq_data *d) { struct pca953x_chip *chip = irq_data_get_irq_chip_data(d); - u32 new_irqs; - u32 level; + u8 new_irqs; + int level, i; /* Look for any newly setup interrupt */ - new_irqs = chip->irq_trig_fall | chip->irq_trig_raise; - new_irqs &= ~chip->reg_direction; - - while (new_irqs) { - level = __ffs(new_irqs); - pca953x_gpio_direction_input(&chip->gpio_chip, level); - new_irqs &= ~(1 << level); + for (i = 0; i < NBANK(chip); i++) { + new_irqs = chip->irq_trig_fall[i] | chip->irq_trig_raise[i]; + new_irqs &= ~chip->reg_direction[i]; + + while (new_irqs) { + level = __ffs(new_irqs); + pca953x_gpio_direction_input(&chip->gpio_chip, + level + (BANK_SZ * i)); + new_irqs &= ~(1 << level); + } } mutex_unlock(&chip->irq_lock); @@ -374,7 +420,8 @@ static void pca953x_irq_bus_sync_unlock(struct irq_data *d) static int pca953x_irq_set_type(struct irq_data *d, unsigned int type) { struct pca953x_chip *chip = irq_data_get_irq_chip_data(d); - u32 mask = 1 << d->hwirq; + int bank_nb = d->hwirq / BANK_SZ; + u8 mask = 1 << (d->hwirq % BANK_SZ); if (!(type & IRQ_TYPE_EDGE_BOTH)) { dev_err(&chip->client->dev, "irq %d: unsupported type %d\n", @@ -383,14 +430,14 @@ static int pca953x_irq_set_type(struct irq_data *d, unsigned int type) } if (type & IRQ_TYPE_EDGE_FALLING) - chip->irq_trig_fall |= mask; + chip->irq_trig_fall[bank_nb] |= mask; else - chip->irq_trig_fall &= ~mask; + chip->irq_trig_fall[bank_nb] &= ~mask; if (type & IRQ_TYPE_EDGE_RISING) - chip->irq_trig_raise |= mask; + chip->irq_trig_raise[bank_nb] |= mask; else - chip->irq_trig_raise &= ~mask; + chip->irq_trig_raise[bank_nb] &= ~mask; return 0; } @@ -404,13 +451,13 @@ static struct irq_chip pca953x_irq_chip = { .irq_set_type = pca953x_irq_set_type, }; -static u32 pca953x_irq_pending(struct pca953x_chip *chip) +static u8 pca953x_irq_pending(struct pca953x_chip *chip, u8 *pending) { - u32 cur_stat; - u32 old_stat; - u32 pending; - u32 trigger; - int ret, offset = 0; + u8 cur_stat[MAX_BANK]; + u8 old_stat[MAX_BANK]; + u8 pendings = 0; + u8 trigger[MAX_BANK], triggers = 0; + int ret, i, offset = 0; switch (chip->chip_type) { case PCA953X_TYPE: @@ -420,45 +467,54 @@ static u32 pca953x_irq_pending(struct pca953x_chip *chip) offset = PCA957X_IN; break; } - ret = pca953x_read_reg(chip, offset, &cur_stat); + ret = pca953x_read_regs(chip, offset, cur_stat); if (ret) return 0; /* Remove output pins from the equation */ - cur_stat &= chip->reg_direction; + for (i = 0; i < NBANK(chip); i++) + cur_stat[i] &= chip->reg_direction[i]; - old_stat = chip->irq_stat; - trigger = (cur_stat ^ old_stat) & chip->irq_mask; + memcpy(old_stat, chip->irq_stat, NBANK(chip)); - if (!trigger) + for (i = 0; i < NBANK(chip); i++) { + trigger[i] = (cur_stat[i] ^ old_stat[i]) & chip->irq_mask[i]; + triggers += trigger[i]; + } + + if (!triggers) return 0; - chip->irq_stat = cur_stat; + memcpy(chip->irq_stat, cur_stat, NBANK(chip)); - pending = (old_stat & chip->irq_trig_fall) | - (cur_stat & chip->irq_trig_raise); - pending &= trigger; + for (i = 0; i < NBANK(chip); i++) { + pending[i] = (old_stat[i] & chip->irq_trig_fall[i]) | + (cur_stat[i] & chip->irq_trig_raise[i]); + pending[i] &= trigger[i]; + pendings += pending[i]; + } - return pending; + return pendings; } static irqreturn_t pca953x_irq_handler(int irq, void *devid) { struct pca953x_chip *chip = devid; - u32 pending; - u32 level; - - pending = pca953x_irq_pending(chip); + u8 pending[MAX_BANK]; + u8 level; + int i; - if (!pending) + if (!pca953x_irq_pending(chip, pending)) return IRQ_HANDLED; - do { - level = __ffs(pending); - handle_nested_irq(irq_find_mapping(chip->domain, level)); - - pending &= ~(1 << level); - } while (pending); + for (i = 0; i < NBANK(chip); i++) { + while (pending[i]) { + level = __ffs(pending[i]); + handle_nested_irq(irq_find_mapping(chip->domain, + level + (BANK_SZ * i))); + pending[i] &= ~(1 << level); + } + } return IRQ_HANDLED; } @@ -468,8 +524,7 @@ static int pca953x_irq_setup(struct pca953x_chip *chip, int irq_base) { struct i2c_client *client = chip->client; - int ret, offset = 0; - u32 temporary; + int ret, i, offset = 0; if (irq_base != -1 && (id->driver_data & PCA_INT)) { @@ -483,8 +538,7 @@ static int pca953x_irq_setup(struct pca953x_chip *chip, offset = PCA957X_IN; break; } - ret = pca953x_read_reg(chip, offset, &temporary); - chip->irq_stat = temporary; + ret = pca953x_read_regs(chip, offset, chip->irq_stat); if (ret) goto out_failed; @@ -493,7 +547,8 @@ static int pca953x_irq_setup(struct pca953x_chip *chip, * interrupt. We have to rely on the previous read for * this purpose. */ - chip->irq_stat &= chip->reg_direction; + for (i = 0; i < NBANK(chip); i++) + chip->irq_stat[i] &= chip->reg_direction[i]; mutex_init(&chip->irq_lock); chip->irq_base = irq_alloc_descs(-1, irq_base, chip->gpio_chip.ngpio, -1); @@ -619,18 +674,24 @@ pca953x_get_alt_pdata(struct i2c_client *client, int *gpio_base, u32 *invert) static int device_pca953x_init(struct pca953x_chip *chip, u32 invert) { int ret; + u8 val[MAX_BANK]; - ret = pca953x_read_reg(chip, PCA953X_OUTPUT, &chip->reg_output); + ret = pca953x_read_regs(chip, PCA953X_OUTPUT, chip->reg_output); if (ret) goto out; - ret = pca953x_read_reg(chip, PCA953X_DIRECTION, - &chip->reg_direction); + ret = pca953x_read_regs(chip, PCA953X_DIRECTION, + chip->reg_direction); if (ret) goto out; /* set platform specific polarity inversion */ - ret = pca953x_write_reg(chip, PCA953X_INVERT, invert); + if (invert) + memset(val, 0xFF, NBANK(chip)); + else + memset(val, 0, NBANK(chip)); + + ret = pca953x_write_regs(chip, PCA953X_INVERT, val); out: return ret; } @@ -638,28 +699,36 @@ out: static int device_pca957x_init(struct pca953x_chip *chip, u32 invert) { int ret; - u32 val = 0; + u8 val[MAX_BANK]; /* Let every port in proper state, that could save power */ - pca953x_write_reg(chip, PCA957X_PUPD, 0x0); - pca953x_write_reg(chip, PCA957X_CFG, 0xffff); - pca953x_write_reg(chip, PCA957X_OUT, 0x0); - - ret = pca953x_read_reg(chip, PCA957X_IN, &val); + memset(val, 0, NBANK(chip)); + pca953x_write_regs(chip, PCA957X_PUPD, val); + memset(val, 0xFF, NBANK(chip)); + pca953x_write_regs(chip, PCA957X_CFG, val); + memset(val, 0, NBANK(chip)); + pca953x_write_regs(chip, PCA957X_OUT, val); + + ret = pca953x_read_regs(chip, PCA957X_IN, val); if (ret) goto out; - ret = pca953x_read_reg(chip, PCA957X_OUT, &chip->reg_output); + ret = pca953x_read_regs(chip, PCA957X_OUT, chip->reg_output); if (ret) goto out; - ret = pca953x_read_reg(chip, PCA957X_CFG, &chip->reg_direction); + ret = pca953x_read_regs(chip, PCA957X_CFG, chip->reg_direction); if (ret) goto out; /* set platform specific polarity inversion */ - pca953x_write_reg(chip, PCA957X_INVRT, invert); + if (invert) + memset(val, 0xFF, NBANK(chip)); + else + memset(val, 0, NBANK(chip)); + pca953x_write_regs(chip, PCA957X_INVRT, val); /* To enable register 6, 7 to controll pull up and pull down */ - pca953x_write_reg(chip, PCA957X_BKEN, 0x202); + memset(val, 0x02, NBANK(chip)); + pca953x_write_regs(chip, PCA957X_BKEN, val); return 0; out: -- cgit v1.2.3 From 89f5df01c6b7f2471267bc55b1ecb196c98e195f Mon Sep 17 00:00:00 2001 From: Gregory CLEMENT Date: Tue, 22 Jan 2013 22:10:24 +0100 Subject: gpio: pca953x: add support for pca9505 Now that pca953x driver can handle GPIO expanders with more than 32 bits this patch adds the support for the pca9505 which cam with 40 GPIOs. Signed-off-by: Gregory CLEMENT Signed-off-by: Linus Walleij --- drivers/gpio/gpio-pca953x.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index b35ba0690163..3a68aed91114 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -46,6 +46,7 @@ #define PCA957X_TYPE 0x2000 static const struct i2c_device_id pca953x_id[] = { + { "pca9505", 40 | PCA953X_TYPE | PCA_INT, }, { "pca9534", 8 | PCA953X_TYPE | PCA_INT, }, { "pca9535", 16 | PCA953X_TYPE | PCA_INT, }, { "pca9536", 4 | PCA953X_TYPE, }, @@ -835,6 +836,7 @@ static int pca953x_remove(struct i2c_client *client) } static const struct of_device_id pca953x_dt_ids[] = { + { .compatible = "nxp,pca9505", }, { .compatible = "nxp,pca9534", }, { .compatible = "nxp,pca9535", }, { .compatible = "nxp,pca9536", }, -- cgit v1.2.3 From 6c7e660a27da7494c670bfba21cfeba30457656c Mon Sep 17 00:00:00 2001 From: Haojian Zhuang Date: Wed, 23 Jan 2013 16:25:45 +0800 Subject: gpio: pxa: set initcall level to module init gpio & pinctrl driver are used together. The pinctrl driver is already launched before gpio driver in Makefile. So set gpio driver to module init level. Otherwise, the sequence will be inverted. Signed-off-by: Haojian Zhuang Signed-off-by: Linus Walleij --- drivers/gpio/gpio-pxa.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/gpio/gpio-pxa.c b/drivers/gpio/gpio-pxa.c index 8325f580c0f1..9cc108d2b770 100644 --- a/drivers/gpio/gpio-pxa.c +++ b/drivers/gpio/gpio-pxa.c @@ -642,12 +642,7 @@ static struct platform_driver pxa_gpio_driver = { .of_match_table = of_match_ptr(pxa_gpio_dt_ids), }, }; - -static int __init pxa_gpio_init(void) -{ - return platform_driver_register(&pxa_gpio_driver); -} -postcore_initcall(pxa_gpio_init); +module_platform_driver(pxa_gpio_driver); #ifdef CONFIG_PM static int pxa_gpio_suspend(void) -- cgit v1.2.3 From 0e8f2fdacf1d44651aa7e57063c76142d1f4988b Mon Sep 17 00:00:00 2001 From: Gregory CLEMENT Date: Fri, 25 Jan 2013 17:59:27 +0100 Subject: gpio: pca953x: use simple irqdomain This switches the legacy irqdomain to the simple one, which will auto-allocate descriptors, and also make sure that we use irq_create_mapping() in the to_irq function. Also use the map function of irq_domain_ops to setup the irq configuration on demand and no more statically during the initialization of the driver. Based on a initial patch from Linus Walleij Signed-off-by: Gregory CLEMENT Signed-off-by: Linus Walleij --- drivers/gpio/gpio-pca953x.c | 65 +++++++++++++++++++-------------------------- 1 file changed, 28 insertions(+), 37 deletions(-) diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index 3a68aed91114..1dc99062eb14 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -89,7 +89,6 @@ struct pca953x_chip { u8 irq_stat[MAX_BANK]; u8 irq_trig_raise[MAX_BANK]; u8 irq_trig_fall[MAX_BANK]; - int irq_base; struct irq_domain *domain; #endif @@ -372,7 +371,7 @@ static int pca953x_gpio_to_irq(struct gpio_chip *gc, unsigned off) struct pca953x_chip *chip; chip = container_of(gc, struct pca953x_chip, gpio_chip); - return chip->irq_base + off; + return irq_create_mapping(chip->domain, off); } static void pca953x_irq_mask(struct irq_data *d) @@ -520,6 +519,27 @@ static irqreturn_t pca953x_irq_handler(int irq, void *devid) return IRQ_HANDLED; } +static int pca953x_gpio_irq_map(struct irq_domain *d, unsigned int irq, + irq_hw_number_t hwirq) +{ + irq_clear_status_flags(irq, IRQ_NOREQUEST); + irq_set_chip_data(irq, d->host_data); + irq_set_chip(irq, &pca953x_irq_chip); + irq_set_nested_thread(irq, true); +#ifdef CONFIG_ARM + set_irq_flags(irq, IRQF_VALID); +#else + irq_set_noprobe(irq); +#endif + + return 0; +} + +static const struct irq_domain_ops pca953x_irq_simple_ops = { + .map = pca953x_gpio_irq_map, + .xlate = irq_domain_xlate_twocell, +}; + static int pca953x_irq_setup(struct pca953x_chip *chip, const struct i2c_device_id *id, int irq_base) @@ -529,7 +549,6 @@ static int pca953x_irq_setup(struct pca953x_chip *chip, if (irq_base != -1 && (id->driver_data & PCA_INT)) { - int lvl; switch (chip->chip_type) { case PCA953X_TYPE: @@ -552,34 +571,13 @@ static int pca953x_irq_setup(struct pca953x_chip *chip, chip->irq_stat[i] &= chip->reg_direction[i]; mutex_init(&chip->irq_lock); - chip->irq_base = irq_alloc_descs(-1, irq_base, chip->gpio_chip.ngpio, -1); - if (chip->irq_base < 0) - goto out_failed; - - chip->domain = irq_domain_add_legacy(client->dev.of_node, + chip->domain = irq_domain_add_simple(client->dev.of_node, chip->gpio_chip.ngpio, - chip->irq_base, - 0, - &irq_domain_simple_ops, + irq_base, + &pca953x_irq_simple_ops, NULL); - if (!chip->domain) { - ret = -ENODEV; - goto out_irqdesc_free; - } - - for (lvl = 0; lvl < chip->gpio_chip.ngpio; lvl++) { - int irq = lvl + chip->irq_base; - - irq_clear_status_flags(irq, IRQ_NOREQUEST); - irq_set_chip_data(irq, chip); - irq_set_chip(irq, &pca953x_irq_chip); - irq_set_nested_thread(irq, true); -#ifdef CONFIG_ARM - set_irq_flags(irq, IRQF_VALID); -#else - irq_set_noprobe(irq); -#endif - } + if (!chip->domain) + return -ENODEV; ret = request_threaded_irq(client->irq, NULL, @@ -589,25 +587,18 @@ static int pca953x_irq_setup(struct pca953x_chip *chip, if (ret) { dev_err(&client->dev, "failed to request irq %d\n", client->irq); - goto out_irqdesc_free; + return ret; } chip->gpio_chip.to_irq = pca953x_gpio_to_irq; } return 0; - -out_irqdesc_free: - irq_free_descs(chip->irq_base, chip->gpio_chip.ngpio); -out_failed: - chip->irq_base = -1; - return ret; } static void pca953x_irq_teardown(struct pca953x_chip *chip) { if (chip->irq_base != -1) { - irq_free_descs(chip->irq_base, chip->gpio_chip.ngpio); free_irq(chip->client->irq, chip); } } -- cgit v1.2.3 From b42748c970d1865685749960cb23f08e259a9f86 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 25 Jan 2013 17:59:28 +0100 Subject: gpio: pca953x: use managed resources Using the devm_* managed resources the pca driver can be simplified and cut down on boilerplate code. [gcl: fixed a inccorect reference to a removed label, "goto fail_out" became "return ret"] Signed-off-by: Linus Walleij Signed-off-by: Gregory CLEMENT Signed-off-by: Linus Walleij --- drivers/gpio/gpio-pca953x.c | 32 ++++++++------------------------ 1 file changed, 8 insertions(+), 24 deletions(-) diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index 1dc99062eb14..24059462c87f 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -560,7 +560,7 @@ static int pca953x_irq_setup(struct pca953x_chip *chip, } ret = pca953x_read_regs(chip, offset, chip->irq_stat); if (ret) - goto out_failed; + return ret; /* * There is no way to know which GPIO line generated the @@ -579,7 +579,8 @@ static int pca953x_irq_setup(struct pca953x_chip *chip, if (!chip->domain) return -ENODEV; - ret = request_threaded_irq(client->irq, + ret = devm_request_threaded_irq(&client->dev, + client->irq, NULL, pca953x_irq_handler, IRQF_TRIGGER_LOW | IRQF_ONESHOT, @@ -596,12 +597,6 @@ static int pca953x_irq_setup(struct pca953x_chip *chip, return 0; } -static void pca953x_irq_teardown(struct pca953x_chip *chip) -{ - if (chip->irq_base != -1) { - free_irq(chip->client->irq, chip); - } -} #else /* CONFIG_GPIO_PCA953X_IRQ */ static int pca953x_irq_setup(struct pca953x_chip *chip, const struct i2c_device_id *id, @@ -614,10 +609,6 @@ static int pca953x_irq_setup(struct pca953x_chip *chip, return 0; } - -static void pca953x_irq_teardown(struct pca953x_chip *chip) -{ -} #endif /* @@ -736,7 +727,8 @@ static int pca953x_probe(struct i2c_client *client, int ret; u32 invert = 0; - chip = kzalloc(sizeof(struct pca953x_chip), GFP_KERNEL); + chip = devm_kzalloc(&client->dev, + sizeof(struct pca953x_chip), GFP_KERNEL); if (chip == NULL) return -ENOMEM; @@ -771,15 +763,15 @@ static int pca953x_probe(struct i2c_client *client, else ret = device_pca957x_init(chip, invert); if (ret) - goto out_failed; + return ret; ret = pca953x_irq_setup(chip, id, irq_base); if (ret) - goto out_failed; + return ret; ret = gpiochip_add(&chip->gpio_chip); if (ret) - goto out_failed_irq; + return ret; if (pdata && pdata->setup) { ret = pdata->setup(client, chip->gpio_chip.base, @@ -790,12 +782,6 @@ static int pca953x_probe(struct i2c_client *client, i2c_set_clientdata(client, chip); return 0; - -out_failed_irq: - pca953x_irq_teardown(chip); -out_failed: - kfree(chip); - return ret; } static int pca953x_remove(struct i2c_client *client) @@ -821,8 +807,6 @@ static int pca953x_remove(struct i2c_client *client) return ret; } - pca953x_irq_teardown(chip); - kfree(chip); return 0; } -- cgit v1.2.3 From 0d1c28a449c6c23a126e3a08ee30914609aac227 Mon Sep 17 00:00:00 2001 From: Mathias Nyman Date: Mon, 28 Jan 2013 16:23:10 +0200 Subject: gpiolib-acpi: Add ACPI5 event model support to gpio. Add ability to handle ACPI events signalled by GPIO interrupts. ACPI5 platforms can use GPIO signaled ACPI events. These GPIO interrupts are handled by ACPI event methods which need to be called from the GPIO controller's interrupt handler. acpi_gpio_request_interrupt() finds out which gpio pins have acpi event methods and assigns interrupt handlers that calls the acpi event methods for those pins. Partially based on work by Rui Zhang Signed-off-by: Mathias Nyman Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib-acpi.c | 82 +++++++++++++++++++++++++++++++++++++++++++++ include/linux/acpi_gpio.h | 4 +++ 2 files changed, 86 insertions(+) diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index cbad6e908d30..54ce2269ed25 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c @@ -15,6 +15,7 @@ #include #include #include +#include static int acpi_gpiochip_find(struct gpio_chip *gc, void *data) { @@ -52,3 +53,84 @@ int acpi_get_gpio(char *path, int pin) return chip->base + pin; } EXPORT_SYMBOL_GPL(acpi_get_gpio); + + +static irqreturn_t acpi_gpio_irq_handler(int irq, void *data) +{ + acpi_handle handle = data; + + acpi_evaluate_object(handle, NULL, NULL, NULL); + + return IRQ_HANDLED; +} + +/** + * acpi_gpiochip_request_interrupts() - Register isr for gpio chip ACPI events + * @chip: gpio chip + * + * ACPI5 platforms can use GPIO signaled ACPI events. These GPIO interrupts are + * handled by ACPI event methods which need to be called from the GPIO + * chip's interrupt handler. acpi_gpiochip_request_interrupts finds out which + * gpio pins have acpi event methods and assigns interrupt handlers that calls + * the acpi event methods for those pins. + * + * Interrupts are automatically freed on driver detach + */ + +void acpi_gpiochip_request_interrupts(struct gpio_chip *chip) +{ + struct acpi_buffer buf = {ACPI_ALLOCATE_BUFFER, NULL}; + struct acpi_resource *res; + acpi_handle handle, ev_handle; + acpi_status status; + unsigned int pin, irq; + char ev_name[5]; + + if (!chip->dev || !chip->to_irq) + return; + + handle = ACPI_HANDLE(chip->dev); + if (!handle) + return; + + status = acpi_get_event_resources(handle, &buf); + if (ACPI_FAILURE(status)) + return; + + /* If a gpio interrupt has an acpi event handler method, then + * set up an interrupt handler that calls the acpi event handler + */ + + for (res = buf.pointer; + res && (res->type != ACPI_RESOURCE_TYPE_END_TAG); + res = ACPI_NEXT_RESOURCE(res)) { + + if (res->type != ACPI_RESOURCE_TYPE_GPIO || + res->data.gpio.connection_type != + ACPI_RESOURCE_GPIO_TYPE_INT) + continue; + + pin = res->data.gpio.pin_table[0]; + if (pin > chip->ngpio) + continue; + + sprintf(ev_name, "_%c%02X", + res->data.gpio.triggering ? 'E' : 'L', pin); + + status = acpi_get_handle(handle, ev_name, &ev_handle); + if (ACPI_FAILURE(status)) + continue; + + irq = chip->to_irq(chip, pin); + if (irq < 0) + continue; + + /* Assume BIOS sets the triggering, so no flags */ + devm_request_threaded_irq(chip->dev, irq, NULL, + acpi_gpio_irq_handler, + 0, + "GPIO-signaled-ACPI-event", + ev_handle); + } +} +EXPORT_SYMBOL(acpi_gpiochip_request_interrupts); diff --git a/include/linux/acpi_gpio.h b/include/linux/acpi_gpio.h index 91615a389b65..b76ebd08ff8e 100644 --- a/include/linux/acpi_gpio.h +++ b/include/linux/acpi_gpio.h @@ -2,10 +2,12 @@ #define _LINUX_ACPI_GPIO_H_ #include +#include #ifdef CONFIG_GPIO_ACPI int acpi_get_gpio(char *path, int pin); +void acpi_gpiochip_request_interrupts(struct gpio_chip *chip); #else /* CONFIG_GPIO_ACPI */ @@ -14,6 +16,8 @@ static inline int acpi_get_gpio(char *path, int pin) return -ENODEV; } +static inline void acpi_gpiochip_request_interrupts(struct gpio_chip *chip) { } + #endif /* CONFIG_GPIO_ACPI */ #endif /* _LINUX_ACPI_GPIO_H_ */ -- cgit v1.2.3 From 66d7990e282f8015686b9bab30be30eec297e736 Mon Sep 17 00:00:00 2001 From: Gwenhael Goavec-Merou Date: Tue, 29 Jan 2013 09:16:33 +0100 Subject: gpio: mxs: Add IRQ_TYPE_EDGE_BOTH support This patch adds support for IRQ_TYPE_EDGE_BOTH needed for some driver (gpio-keys). Inspired from gpio-mxc.c Acked-by: Shawn Guo Signed-off-by: Gwenhael Goavec-Merou Signed-off-by: Linus Walleij --- drivers/gpio/gpio-mxs.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/drivers/gpio/gpio-mxs.c b/drivers/gpio/gpio-mxs.c index fa2a63cad32e..859b6fabc7bc 100644 --- a/drivers/gpio/gpio-mxs.c +++ b/drivers/gpio/gpio-mxs.c @@ -65,6 +65,7 @@ struct mxs_gpio_port { struct irq_domain *domain; struct bgpio_chip bgc; enum mxs_gpio_id devid; + u32 both_edges; }; static inline int is_imx23_gpio(struct mxs_gpio_port *port) @@ -81,13 +82,23 @@ static inline int is_imx28_gpio(struct mxs_gpio_port *port) static int mxs_gpio_set_irq_type(struct irq_data *d, unsigned int type) { + u32 val; u32 pin_mask = 1 << d->hwirq; struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); struct mxs_gpio_port *port = gc->private; void __iomem *pin_addr; int edge; + port->both_edges &= ~pin_mask; switch (type) { + case IRQ_TYPE_EDGE_BOTH: + val = gpio_get_value(port->bgc.gc.base + d->hwirq); + if (val) + edge = GPIO_INT_FALL_EDGE; + else + edge = GPIO_INT_RISE_EDGE; + port->both_edges |= pin_mask; + break; case IRQ_TYPE_EDGE_RISING: edge = GPIO_INT_RISE_EDGE; break; @@ -124,6 +135,23 @@ static int mxs_gpio_set_irq_type(struct irq_data *d, unsigned int type) return 0; } +static void mxs_flip_edge(struct mxs_gpio_port *port, u32 gpio) +{ + u32 bit, val, edge; + void __iomem *pin_addr; + + bit = 1 << gpio; + + pin_addr = port->base + PINCTRL_IRQPOL(port); + val = readl(pin_addr); + edge = val & bit; + + if (edge) + writel(bit, pin_addr + MXS_CLR); + else + writel(bit, pin_addr + MXS_SET); +} + /* MXS has one interrupt *per* gpio port */ static void mxs_gpio_irq_handler(u32 irq, struct irq_desc *desc) { @@ -137,6 +165,9 @@ static void mxs_gpio_irq_handler(u32 irq, struct irq_desc *desc) while (irq_stat != 0) { int irqoffset = fls(irq_stat) - 1; + if (port->both_edges & (1 << irqoffset)) + mxs_flip_edge(port, irqoffset); + generic_handle_irq(irq_find_mapping(port->domain, irqoffset)); irq_stat &= ~(1 << irqoffset); } -- cgit v1.2.3 From 6320c7b7990e1e759a18666b6c616aae9bd3b12d Mon Sep 17 00:00:00 2001 From: Alexandre Courbot Date: Sat, 2 Feb 2013 23:44:05 +0900 Subject: arm: pxa: tosa: do not use gpiochip_reserve() GPIO address space reservation during early platform initialization is not needed anymore for Tosa. Remove the calls to gpiochip_reserve() which is due to be removed. Acked-by: Haojian Zhuang Signed-off-by: Alexandre Courbot Signed-off-by: Linus Walleij --- arch/arm/mach-pxa/tosa.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c index 233629edf7ee..4f35b333de44 100644 --- a/arch/arm/mach-pxa/tosa.c +++ b/arch/arm/mach-pxa/tosa.c @@ -927,8 +927,6 @@ static void tosa_restart(char mode, const char *cmd) static void __init tosa_init(void) { - int dummy; - pxa2xx_mfp_config(ARRAY_AND_SIZE(tosa_pin_config)); pxa_set_ffuart_info(NULL); @@ -947,10 +945,6 @@ static void __init tosa_init(void) /* enable batt_fault */ PMCR = 0x01; - dummy = gpiochip_reserve(TOSA_SCOOP_GPIO_BASE, 12); - dummy = gpiochip_reserve(TOSA_SCOOP_JC_GPIO_BASE, 12); - dummy = gpiochip_reserve(TOSA_TC6393XB_GPIO_BASE, 16); - pxa_set_mci_info(&tosa_mci_platform_data); pxa_set_ficp_info(&tosa_ficp_platform_data); pxa_set_i2c_info(NULL); -- cgit v1.2.3 From 710b40eac4d91bd08f07f289cf6d6f3861c87187 Mon Sep 17 00:00:00 2001 From: Alexandre Courbot Date: Sat, 2 Feb 2013 23:44:06 +0900 Subject: gpiolib: remove gpiochip_reserve() gpiochip_reserve() has no user and stands in the way of the removal of the static gpio_desc[] array. Remove this function as well as the now unneeded RESERVED flag of struct gpio_desc. Signed-off-by: Alexandre Courbot Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib.c | 58 +++++++--------------------------------------- include/asm-generic/gpio.h | 1 - 2 files changed, 8 insertions(+), 51 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 199fca15f270..e27877ad0163 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -52,14 +52,13 @@ struct gpio_desc { /* flag symbols are bit numbers */ #define FLAG_REQUESTED 0 #define FLAG_IS_OUT 1 -#define FLAG_RESERVED 2 -#define FLAG_EXPORT 3 /* protected by sysfs_lock */ -#define FLAG_SYSFS 4 /* exported via /sys/class/gpio/control */ -#define FLAG_TRIG_FALL 5 /* trigger on falling edge */ -#define FLAG_TRIG_RISE 6 /* trigger on rising edge */ -#define FLAG_ACTIVE_LOW 7 /* sysfs value has active low */ -#define FLAG_OPEN_DRAIN 8 /* Gpio is open drain type */ -#define FLAG_OPEN_SOURCE 9 /* Gpio is open source type */ +#define FLAG_EXPORT 2 /* protected by sysfs_lock */ +#define FLAG_SYSFS 3 /* exported via /sys/class/gpio/control */ +#define FLAG_TRIG_FALL 4 /* trigger on falling edge */ +#define FLAG_TRIG_RISE 5 /* trigger on rising edge */ +#define FLAG_ACTIVE_LOW 6 /* sysfs value has active low */ +#define FLAG_OPEN_DRAIN 7 /* Gpio is open drain type */ +#define FLAG_OPEN_SOURCE 8 /* Gpio is open source type */ #define ID_SHIFT 16 /* add new flags before this one */ @@ -132,7 +131,7 @@ static int gpiochip_find_base(int ngpio) struct gpio_desc *desc = &gpio_desc[i]; struct gpio_chip *chip = desc->chip; - if (!chip && !test_bit(FLAG_RESERVED, &desc->flags)) { + if (!chip) { spare++; if (spare == ngpio) { base = i; @@ -150,47 +149,6 @@ static int gpiochip_find_base(int ngpio) return base; } -/** - * gpiochip_reserve() - reserve range of gpios to use with platform code only - * @start: starting gpio number - * @ngpio: number of gpios to reserve - * Context: platform init, potentially before irqs or kmalloc will work - * - * Returns a negative errno if any gpio within the range is already reserved - * or registered, else returns zero as a success code. Use this function - * to mark a range of gpios as unavailable for dynamic gpio number allocation, - * for example because its driver support is not yet loaded. - */ -int __init gpiochip_reserve(int start, int ngpio) -{ - int ret = 0; - unsigned long flags; - int i; - - if (!gpio_is_valid(start) || !gpio_is_valid(start + ngpio - 1)) - return -EINVAL; - - spin_lock_irqsave(&gpio_lock, flags); - - for (i = start; i < start + ngpio; i++) { - struct gpio_desc *desc = &gpio_desc[i]; - - if (desc->chip || test_bit(FLAG_RESERVED, &desc->flags)) { - ret = -EBUSY; - goto err; - } - - set_bit(FLAG_RESERVED, &desc->flags); - } - - pr_debug("%s: reserved gpios from %d to %d\n", - __func__, start, start + ngpio - 1); -err: - spin_unlock_irqrestore(&gpio_lock, flags); - - return ret; -} - /* caller ensures gpio is valid and requested, chip->get_direction may sleep */ static int gpio_get_direction(unsigned gpio) { diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h index 45b8916805f3..2034e691c7ab 100644 --- a/include/asm-generic/gpio.h +++ b/include/asm-generic/gpio.h @@ -152,7 +152,6 @@ struct gpio_chip { extern const char *gpiochip_is_requested(struct gpio_chip *chip, unsigned offset); extern struct gpio_chip *gpio_to_chip(unsigned gpio); -extern int __must_check gpiochip_reserve(int start, int ngpio); /* add/remove chips */ extern int gpiochip_add(struct gpio_chip *chip); -- cgit v1.2.3 From de0ccf788147440eee2383c74408080f3ff0a43b Mon Sep 17 00:00:00 2001 From: Anatolij Gustschin Date: Mon, 4 Feb 2013 09:10:15 +0100 Subject: gpio: mpc8xxx: don't set IRQ_TYPE_NONE when creating irq mapping Exporting gpios over sysfs GPIO interface throws genirq error messages, i.e. on an mpc5121 based board exporting GPIO 5 triggers it: # echo 229 > /sys/class/gpio/export genirq: Setting trigger mode 0 for irq 44 failed (mpc512x_irq_set_type+0x0/0x18c) Similar error messages appear in the kernel boot log since the board specifies GPIOs for matrix keypad and also SD Card write protect and card detect GPIOs in its device tree. For all these GPIOs there is an error message in the log. The issue is triggered by setting the irq type to IRQ_TYPE_NONE in the driver's irq_domain map function mpc8xxx_gpio_irq_map(). ... mpc8xxx_gpio_irq_map irq_set_irq_type __irq_set_trigger __irq_set_trigger() calls irq_set_type() callback of the mpc8xxx gpio irq chip with the IRQ_TYPE_NONE in its 'flags' argument. This callback is either mpc8xxx_irq_set_type() or mpc512x_irq_set_type(). Both these functions return -EINVAL in the case if IRQ_TYPE_NONE is passed in the flow_type argument. This return value triggers the observed error message in __irq_set_trigger(). Modifying these callbacks to not return an error in IRQ_TYPE_NONE case doesn't make any sense to me. The line setting IRQ_TYPE_NONE type has been originally added by commit 345e5c8a "powerpc: Add interrupt support to mpc8xxx_gpio". At this time set_irq_type() checked its type argument and returned 0 if the type argument didn't specify any meaningful type in its type sense bits (and thus was equal to IRQ_TYPE_NONE). Effectively this line was a nop and I wonder what was the point of adding it. Remove IRQ_TYPE_NONE setting in the irq_domain mapping function. Signed-off-by: Anatolij Gustschin Acked-by: Peter Korsgaard Signed-off-by: Linus Walleij --- drivers/gpio/gpio-mpc8xxx.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpio/gpio-mpc8xxx.c b/drivers/gpio/gpio-mpc8xxx.c index 9ae29cc0d17f..a0b33a216d4a 100644 --- a/drivers/gpio/gpio-mpc8xxx.c +++ b/drivers/gpio/gpio-mpc8xxx.c @@ -292,7 +292,6 @@ static int mpc8xxx_gpio_irq_map(struct irq_domain *h, unsigned int virq, irq_set_chip_data(virq, h->host_data); irq_set_chip_and_handler(virq, &mpc8xxx_irq_chip, handle_level_irq); - irq_set_irq_type(virq, IRQ_TYPE_NONE); return 0; } -- cgit v1.2.3 From 1107ca104f0331627f6446bfefa2d4b0e673db18 Mon Sep 17 00:00:00 2001 From: Mathias Nyman Date: Mon, 4 Feb 2013 11:32:22 +0200 Subject: gpiolib-acpi: Fix error checks in interrupt requesting Print error message if requesting an interrupt fails. Use int instead of unsigned for interrupts in case of error values Signed-off-by: Mathias Nyman Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib-acpi.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index 54ce2269ed25..a063eb04b6ce 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c @@ -83,7 +83,8 @@ void acpi_gpiochip_request_interrupts(struct gpio_chip *chip) struct acpi_resource *res; acpi_handle handle, ev_handle; acpi_status status; - unsigned int pin, irq; + unsigned int pin; + int irq, ret; char ev_name[5]; if (!chip->dev || !chip->to_irq) @@ -126,11 +127,15 @@ void acpi_gpiochip_request_interrupts(struct gpio_chip *chip) continue; /* Assume BIOS sets the triggering, so no flags */ - devm_request_threaded_irq(chip->dev, irq, NULL, + ret = devm_request_threaded_irq(chip->dev, irq, NULL, acpi_gpio_irq_handler, 0, "GPIO-signaled-ACPI-event", ev_handle); + if (ret) + dev_err(chip->dev, + "Failed to request IRQ %d ACPI event handler\n", + irq); } } EXPORT_SYMBOL(acpi_gpiochip_request_interrupts); -- cgit v1.2.3 From 476171ce7850b28280db6a2d0c0e4d3ff26c8117 Mon Sep 17 00:00:00 2001 From: Alexandre Courbot Date: Mon, 4 Feb 2013 17:42:04 +0900 Subject: gpiolib: add missing braces in gpio_direction_show Add missing braces in an if..else condition. Signed-off-by: Alexandre Courbot Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index e27877ad0163..e14eb88bbe8d 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -212,13 +212,14 @@ static ssize_t gpio_direction_show(struct device *dev, mutex_lock(&sysfs_lock); - if (!test_bit(FLAG_EXPORT, &desc->flags)) + if (!test_bit(FLAG_EXPORT, &desc->flags)) { status = -EIO; - else + } else { gpio_get_direction(gpio); status = sprintf(buf, "%s\n", test_bit(FLAG_IS_OUT, &desc->flags) ? "out" : "in"); + } mutex_unlock(&sysfs_lock); return status; -- cgit v1.2.3