diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-02-26 12:35:29 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-02-26 12:35:29 -0500 |
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 { | |||
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 | ||
71 | static inline int is_imx23_gpio(struct mxs_gpio_port *port) | 72 | 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) | |||
82 | 83 | ||
83 | static int mxs_gpio_set_irq_type(struct irq_data *d, unsigned int type) | 84 | static 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 | ||
139 | static 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 */ |
129 | static void mxs_gpio_irq_handler(u32 irq, struct irq_desc *desc) | 157 | static 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 | } |