aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpio/gpio-mxs.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-02-26 12:35:29 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2013-02-26 12:35:29 -0500
commit4c8c225abf972ce422c241579ce1d4d27eaeb166 (patch)
tree77bc67defdc53c494b20632e66b82ce9be3c06af /drivers/gpio/gpio-mxs.c
parent3eb05225ee8efb81fe50558f5f9d94e7477ade8f (diff)
parent9170100ee46402af6d318134525c728027318d67 (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.c31
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 {
66 struct irq_domain *domain; 66 struct irq_domain *domain;
67 struct bgpio_chip bgc; 67 struct bgpio_chip bgc;
68 enum mxs_gpio_id devid; 68 enum mxs_gpio_id devid;
69 u32 both_edges;
69}; 70};
70 71
71static inline int is_imx23_gpio(struct mxs_gpio_port *port) 72static 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)
82 83
83static int mxs_gpio_set_irq_type(struct irq_data *d, unsigned int type) 84static int mxs_gpio_set_irq_type(struct irq_data *d, unsigned int type)
84{ 85{
86 u32 val;
85 u32 pin_mask = 1 << d->hwirq; 87 u32 pin_mask = 1 << d->hwirq;
86 struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); 88 struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
87 struct mxs_gpio_port *port = gc->private; 89 struct mxs_gpio_port *port = gc->private;
88 void __iomem *pin_addr; 90 void __iomem *pin_addr;
89 int edge; 91 int edge;
90 92
93 port->both_edges &= ~pin_mask;
91 switch (type) { 94 switch (type) {
95 case IRQ_TYPE_EDGE_BOTH:
96 val = gpio_get_value(port->bgc.gc.base + d->hwirq);
97 if (val)
98 edge = GPIO_INT_FALL_EDGE;
99 else
100 edge = GPIO_INT_RISE_EDGE;
101 port->both_edges |= pin_mask;
102 break;
92 case IRQ_TYPE_EDGE_RISING: 103 case IRQ_TYPE_EDGE_RISING:
93 edge = GPIO_INT_RISE_EDGE; 104 edge = GPIO_INT_RISE_EDGE;
94 break; 105 break;
@@ -125,6 +136,23 @@ static int mxs_gpio_set_irq_type(struct irq_data *d, unsigned int type)
125 return 0; 136 return 0;
126} 137}
127 138
139static void mxs_flip_edge(struct mxs_gpio_port *port, u32 gpio)
140{
141 u32 bit, val, edge;
142 void __iomem *pin_addr;
143
144 bit = 1 << gpio;
145
146 pin_addr = port->base + PINCTRL_IRQPOL(port);
147 val = readl(pin_addr);
148 edge = val & bit;
149
150 if (edge)
151 writel(bit, pin_addr + MXS_CLR);
152 else
153 writel(bit, pin_addr + MXS_SET);
154}
155
128/* MXS has one interrupt *per* gpio port */ 156/* MXS has one interrupt *per* gpio port */
129static void mxs_gpio_irq_handler(u32 irq, struct irq_desc *desc) 157static void mxs_gpio_irq_handler(u32 irq, struct irq_desc *desc)
130{ 158{
@@ -138,6 +166,9 @@ static void mxs_gpio_irq_handler(u32 irq, struct irq_desc *desc)
138 166
139 while (irq_stat != 0) { 167 while (irq_stat != 0) {
140 int irqoffset = fls(irq_stat) - 1; 168 int irqoffset = fls(irq_stat) - 1;
169 if (port->both_edges & (1 << irqoffset))
170 mxs_flip_edge(port, irqoffset);
171
141 generic_handle_irq(irq_find_mapping(port->domain, irqoffset)); 172 generic_handle_irq(irq_find_mapping(port->domain, irqoffset));
142 irq_stat &= ~(1 << irqoffset); 173 irq_stat &= ~(1 << irqoffset);
143 } 174 }