diff options
author | Gwenhael Goavec-Merou <gwenhael.goavec-merou@armadeus.com> | 2013-01-29 03:16:33 -0500 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2013-01-29 06:02:05 -0500 |
commit | 66d7990e282f8015686b9bab30be30eec297e736 (patch) | |
tree | 539def58cb73bb84493def504fc4e6354990aa10 /drivers/gpio | |
parent | 0d1c28a449c6c23a126e3a08ee30914609aac227 (diff) |
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 <shawn.guo@linaro.org>
Signed-off-by: Gwenhael Goavec-Merou <gwenhael.goavec-merou@armadeus.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/gpio')
-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 fa2a63cad32e..859b6fabc7bc 100644 --- a/drivers/gpio/gpio-mxs.c +++ b/drivers/gpio/gpio-mxs.c | |||
@@ -65,6 +65,7 @@ struct mxs_gpio_port { | |||
65 | struct irq_domain *domain; | 65 | struct irq_domain *domain; |
66 | struct bgpio_chip bgc; | 66 | struct bgpio_chip bgc; |
67 | enum mxs_gpio_id devid; | 67 | enum mxs_gpio_id devid; |
68 | u32 both_edges; | ||
68 | }; | 69 | }; |
69 | 70 | ||
70 | static inline int is_imx23_gpio(struct mxs_gpio_port *port) | 71 | 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) | |||
81 | 82 | ||
82 | static int mxs_gpio_set_irq_type(struct irq_data *d, unsigned int type) | 83 | static int mxs_gpio_set_irq_type(struct irq_data *d, unsigned int type) |
83 | { | 84 | { |
85 | u32 val; | ||
84 | u32 pin_mask = 1 << d->hwirq; | 86 | u32 pin_mask = 1 << d->hwirq; |
85 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); | 87 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); |
86 | struct mxs_gpio_port *port = gc->private; | 88 | struct mxs_gpio_port *port = gc->private; |
87 | void __iomem *pin_addr; | 89 | void __iomem *pin_addr; |
88 | int edge; | 90 | int edge; |
89 | 91 | ||
92 | port->both_edges &= ~pin_mask; | ||
90 | switch (type) { | 93 | switch (type) { |
94 | case IRQ_TYPE_EDGE_BOTH: | ||
95 | val = gpio_get_value(port->bgc.gc.base + d->hwirq); | ||
96 | if (val) | ||
97 | edge = GPIO_INT_FALL_EDGE; | ||
98 | else | ||
99 | edge = GPIO_INT_RISE_EDGE; | ||
100 | port->both_edges |= pin_mask; | ||
101 | break; | ||
91 | case IRQ_TYPE_EDGE_RISING: | 102 | case IRQ_TYPE_EDGE_RISING: |
92 | edge = GPIO_INT_RISE_EDGE; | 103 | edge = GPIO_INT_RISE_EDGE; |
93 | break; | 104 | break; |
@@ -124,6 +135,23 @@ static int mxs_gpio_set_irq_type(struct irq_data *d, unsigned int type) | |||
124 | return 0; | 135 | return 0; |
125 | } | 136 | } |
126 | 137 | ||
138 | static void mxs_flip_edge(struct mxs_gpio_port *port, u32 gpio) | ||
139 | { | ||
140 | u32 bit, val, edge; | ||
141 | void __iomem *pin_addr; | ||
142 | |||
143 | bit = 1 << gpio; | ||
144 | |||
145 | pin_addr = port->base + PINCTRL_IRQPOL(port); | ||
146 | val = readl(pin_addr); | ||
147 | edge = val & bit; | ||
148 | |||
149 | if (edge) | ||
150 | writel(bit, pin_addr + MXS_CLR); | ||
151 | else | ||
152 | writel(bit, pin_addr + MXS_SET); | ||
153 | } | ||
154 | |||
127 | /* MXS has one interrupt *per* gpio port */ | 155 | /* MXS has one interrupt *per* gpio port */ |
128 | static void mxs_gpio_irq_handler(u32 irq, struct irq_desc *desc) | 156 | static void mxs_gpio_irq_handler(u32 irq, struct irq_desc *desc) |
129 | { | 157 | { |
@@ -137,6 +165,9 @@ static void mxs_gpio_irq_handler(u32 irq, struct irq_desc *desc) | |||
137 | 165 | ||
138 | while (irq_stat != 0) { | 166 | while (irq_stat != 0) { |
139 | int irqoffset = fls(irq_stat) - 1; | 167 | int irqoffset = fls(irq_stat) - 1; |
168 | if (port->both_edges & (1 << irqoffset)) | ||
169 | mxs_flip_edge(port, irqoffset); | ||
170 | |||
140 | generic_handle_irq(irq_find_mapping(port->domain, irqoffset)); | 171 | generic_handle_irq(irq_find_mapping(port->domain, irqoffset)); |
141 | irq_stat &= ~(1 << irqoffset); | 172 | irq_stat &= ~(1 << irqoffset); |
142 | } | 173 | } |