diff options
author | Weike Chen <alvin.chen@intel.com> | 2014-09-17 12:18:41 -0400 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2014-09-23 11:51:38 -0400 |
commit | 5d60d9efe1447b46f33075fb5841fd83247cdbb2 (patch) | |
tree | a947ba97594ecc9c521cfd08ab5f29541ba221e2 /drivers/gpio | |
parent | 67809b974a07042dc61cb9d06e30df7a5f25446a (diff) |
GPIO: gpio-dwapb: Support Debounce
This patch enables 'debounce' for the designware GPIO, and
it is based on Josef Ahmad's previous work.
Reviewed-by: Hock Leong Kweh <hock.leong.kweh@intel.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Weike Chen <alvin.chen@intel.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/gpio')
-rw-r--r-- | drivers/gpio/gpio-dwapb.c | 36 |
1 files changed, 34 insertions, 2 deletions
diff --git a/drivers/gpio/gpio-dwapb.c b/drivers/gpio/gpio-dwapb.c index 551eaf7208f4..db059bb8edc3 100644 --- a/drivers/gpio/gpio-dwapb.c +++ b/drivers/gpio/gpio-dwapb.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #define GPIO_INTTYPE_LEVEL 0x38 | 37 | #define GPIO_INTTYPE_LEVEL 0x38 |
38 | #define GPIO_INT_POLARITY 0x3c | 38 | #define GPIO_INT_POLARITY 0x3c |
39 | #define GPIO_INTSTATUS 0x40 | 39 | #define GPIO_INTSTATUS 0x40 |
40 | #define GPIO_PORTA_DEBOUNCE 0x48 | ||
40 | #define GPIO_PORTA_EOI 0x4c | 41 | #define GPIO_PORTA_EOI 0x4c |
41 | #define GPIO_EXT_PORTA 0x50 | 42 | #define GPIO_EXT_PORTA 0x50 |
42 | #define GPIO_EXT_PORTB 0x54 | 43 | #define GPIO_EXT_PORTB 0x54 |
@@ -64,6 +65,12 @@ struct dwapb_gpio { | |||
64 | struct irq_domain *domain; | 65 | struct irq_domain *domain; |
65 | }; | 66 | }; |
66 | 67 | ||
68 | static inline struct dwapb_gpio_port * | ||
69 | to_dwapb_gpio_port(struct bgpio_chip *bgc) | ||
70 | { | ||
71 | return container_of(bgc, struct dwapb_gpio_port, bgc); | ||
72 | } | ||
73 | |||
67 | static inline u32 dwapb_read(struct dwapb_gpio *gpio, unsigned int offset) | 74 | static inline u32 dwapb_read(struct dwapb_gpio *gpio, unsigned int offset) |
68 | { | 75 | { |
69 | struct bgpio_chip *bgc = &gpio->ports[0].bgc; | 76 | struct bgpio_chip *bgc = &gpio->ports[0].bgc; |
@@ -84,8 +91,7 @@ static inline void dwapb_write(struct dwapb_gpio *gpio, unsigned int offset, | |||
84 | static int dwapb_gpio_to_irq(struct gpio_chip *gc, unsigned offset) | 91 | static int dwapb_gpio_to_irq(struct gpio_chip *gc, unsigned offset) |
85 | { | 92 | { |
86 | struct bgpio_chip *bgc = to_bgpio_chip(gc); | 93 | struct bgpio_chip *bgc = to_bgpio_chip(gc); |
87 | struct dwapb_gpio_port *port = container_of(bgc, struct | 94 | struct dwapb_gpio_port *port = to_dwapb_gpio_port(bgc); |
88 | dwapb_gpio_port, bgc); | ||
89 | struct dwapb_gpio *gpio = port->gpio; | 95 | struct dwapb_gpio *gpio = port->gpio; |
90 | 96 | ||
91 | return irq_find_mapping(gpio->domain, offset); | 97 | return irq_find_mapping(gpio->domain, offset); |
@@ -235,6 +241,28 @@ static int dwapb_irq_set_type(struct irq_data *d, u32 type) | |||
235 | return 0; | 241 | return 0; |
236 | } | 242 | } |
237 | 243 | ||
244 | static int dwapb_gpio_set_debounce(struct gpio_chip *gc, | ||
245 | unsigned offset, unsigned debounce) | ||
246 | { | ||
247 | struct bgpio_chip *bgc = to_bgpio_chip(gc); | ||
248 | struct dwapb_gpio_port *port = to_dwapb_gpio_port(bgc); | ||
249 | struct dwapb_gpio *gpio = port->gpio; | ||
250 | unsigned long flags, val_deb; | ||
251 | unsigned long mask = bgc->pin2mask(bgc, offset); | ||
252 | |||
253 | spin_lock_irqsave(&bgc->lock, flags); | ||
254 | |||
255 | val_deb = dwapb_read(gpio, GPIO_PORTA_DEBOUNCE); | ||
256 | if (debounce) | ||
257 | dwapb_write(gpio, GPIO_PORTA_DEBOUNCE, val_deb | mask); | ||
258 | else | ||
259 | dwapb_write(gpio, GPIO_PORTA_DEBOUNCE, val_deb & ~mask); | ||
260 | |||
261 | spin_unlock_irqrestore(&bgc->lock, flags); | ||
262 | |||
263 | return 0; | ||
264 | } | ||
265 | |||
238 | static irqreturn_t dwapb_irq_handler_mfd(int irq, void *dev_id) | 266 | static irqreturn_t dwapb_irq_handler_mfd(int irq, void *dev_id) |
239 | { | 267 | { |
240 | u32 worked; | 268 | u32 worked; |
@@ -373,6 +401,10 @@ static int dwapb_gpio_add_port(struct dwapb_gpio *gpio, | |||
373 | port->bgc.gc.ngpio = pp->ngpio; | 401 | port->bgc.gc.ngpio = pp->ngpio; |
374 | port->bgc.gc.base = pp->gpio_base; | 402 | port->bgc.gc.base = pp->gpio_base; |
375 | 403 | ||
404 | /* Only port A support debounce */ | ||
405 | if (pp->idx == 0) | ||
406 | port->bgc.gc.set_debounce = dwapb_gpio_set_debounce; | ||
407 | |||
376 | if (pp->irq) | 408 | if (pp->irq) |
377 | dwapb_configure_irqs(gpio, port, pp); | 409 | dwapb_configure_irqs(gpio, port, pp); |
378 | 410 | ||