diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-02-26 09:35:29 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-02-26 09:35:29 -0800 |
commit | 4c8c225abf972ce422c241579ce1d4d27eaeb166 (patch) | |
tree | 77bc67defdc53c494b20632e66b82ce9be3c06af /drivers/gpio/gpio-mxs.c | |
parent | 3eb05225ee8efb81fe50558f5f9d94e7477ade8f (diff) | |
parent | 9170100ee46402af6d318134525c728027318d67 (diff) |
Merge tag 'gpio-for-linus' of git://git.secretlab.ca/git/linux
Pull GPIO changes from Grant Likely:
"This branch contains the usual set of individual driver improvements
and bug fixes, as well as updates to the core code. The more notable
changes include:
- Internally add new API for referencing GPIOs by gpio_desc instead
of number. Eventually this will become a public API
- ACPI GPIO binding support"
* tag 'gpio-for-linus' of git://git.secretlab.ca/git/linux: (33 commits)
arm64: select ARCH_WANT_OPTIONAL_GPIOLIB
gpio: em: Use irq_domain_add_simple() to fix runtime error
gpio: using common order: let 'static const' instead of 'const static'
gpio/vt8500: memory cleanup missing
gpiolib: Fix locking on gpio debugfs files
gpiolib: let gpio_chip reference its descriptors
gpiolib: use descriptors internally
gpiolib: use gpio_chips list in gpiochip_find_base
gpiolib: use gpio_chips list in sysfs ops
gpiolib: use gpio_chips list in gpiochip_find
gpiolib: use gpio_chips list in gpiolib_sysfs_init
gpiolib: link all gpio_chips using a list
gpio/langwell: cleanup driver
gpio/langwell: Add Cloverview ids to pci device table
gpio/lynxpoint: add chipset gpio driver.
gpiolib: add missing braces in gpio_direction_show
gpiolib-acpi: Fix error checks in interrupt requesting
gpio: mpc8xxx: don't set IRQ_TYPE_NONE when creating irq mapping
gpiolib: remove gpiochip_reserve()
arm: pxa: tosa: do not use gpiochip_reserve()
...
Diffstat (limited to 'drivers/gpio/gpio-mxs.c')
-rw-r--r-- | drivers/gpio/gpio-mxs.c | 31 |
1 files changed, 31 insertions, 0 deletions
diff --git a/drivers/gpio/gpio-mxs.c b/drivers/gpio/gpio-mxs.c index 45d97c46831a..25000b0f8453 100644 --- a/drivers/gpio/gpio-mxs.c +++ b/drivers/gpio/gpio-mxs.c @@ -66,6 +66,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) @@ -82,13 +83,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; @@ -125,6 +136,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) { @@ -138,6 +166,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); } |