]>
Commit | Line | Data |
---|---|---|
ba172962 SL |
1 | From c8c73d56576c41cb266bc83aa9283f361906252c Mon Sep 17 00:00:00 2001 |
2 | From: Russell King <rmk+kernel@armlinux.org.uk> | |
3 | Date: Fri, 1 Mar 2019 11:02:52 -0800 | |
4 | Subject: gpio: gpio-omap: fix level interrupt idling | |
5 | ||
6 | [ Upstream commit d01849f7deba81f4959fd9e51bf20dbf46987d1c ] | |
7 | ||
8 | Tony notes that the GPIO module does not idle when level interrupts are | |
9 | in use, as the wakeup appears to get stuck. | |
10 | ||
11 | After extensive investigation, it appears that the wakeup will only be | |
12 | cleared if the interrupt status register is cleared while the interrupt | |
13 | is enabled. However, we are currently clearing it with the interrupt | |
14 | disabled for level-based interrupts. | |
15 | ||
16 | It is acknowledged that this observed behaviour conflicts with a | |
17 | statement in the TRM: | |
18 | ||
19 | CAUTION | |
20 | After servicing the interrupt, the status bit in the interrupt status | |
21 | register (GPIOi.GPIO_IRQSTATUS_0 or GPIOi.GPIO_IRQSTATUS_1) must be | |
22 | reset and the interrupt line released (by setting the corresponding | |
23 | bit of the interrupt status register to 1) before enabling an | |
24 | interrupt for the GPIO channel in the interrupt-enable register | |
25 | (GPIOi.GPIO_IRQSTATUS_SET_0 or GPIOi.GPIO_IRQSTATUS_SET_1) to prevent | |
26 | the occurrence of unexpected interrupts when enabling an interrupt | |
27 | for the GPIO channel. | |
28 | ||
29 | However, this does not appear to be a practical problem. | |
30 | ||
31 | Further, as reported by Grygorii Strashko <grygorii.strashko@ti.com>, | |
32 | the TI Android kernel tree has an earlier similar patch as "GPIO: OMAP: | |
33 | Fix the sequence to clear the IRQ status" saying: | |
34 | ||
35 | if the status is cleared after disabling the IRQ then sWAKEUP will not | |
36 | be cleared and gates the module transition | |
37 | ||
38 | When we unmask the level interrupt after the interrupt has been handled, | |
39 | enable the interrupt and only then clear the interrupt. If the interrupt | |
40 | is still pending, the hardware will re-assert the interrupt status. | |
41 | ||
42 | Should the caution note in the TRM prove to be a problem, we could | |
43 | use a clear-enable-clear sequence instead. | |
44 | ||
45 | Cc: Aaro Koskinen <aaro.koskinen@iki.fi> | |
46 | Cc: Keerthy <j-keerthy@ti.com> | |
47 | Cc: Peter Ujfalusi <peter.ujfalusi@ti.com> | |
48 | Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk> | |
49 | [tony@atomide.com: updated comments based on an earlier TI patch] | |
50 | Signed-off-by: Tony Lindgren <tony@atomide.com> | |
51 | Acked-by: Grygorii Strashko <grygorii.strashko@ti.com> | |
52 | Signed-off-by: Linus Walleij <linus.walleij@linaro.org> | |
53 | Signed-off-by: Sasha Levin <sashal@kernel.org> | |
54 | --- | |
55 | drivers/gpio/gpio-omap.c | 14 ++++++++------ | |
56 | 1 file changed, 8 insertions(+), 6 deletions(-) | |
57 | ||
58 | diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c | |
59 | index e81008678a38..6c1acf642c8e 100644 | |
60 | --- a/drivers/gpio/gpio-omap.c | |
61 | +++ b/drivers/gpio/gpio-omap.c | |
62 | @@ -888,14 +888,16 @@ static void omap_gpio_unmask_irq(struct irq_data *d) | |
63 | if (trigger) | |
64 | omap_set_gpio_triggering(bank, offset, trigger); | |
65 | ||
66 | - /* For level-triggered GPIOs, the clearing must be done after | |
67 | - * the HW source is cleared, thus after the handler has run */ | |
68 | - if (bank->level_mask & BIT(offset)) { | |
69 | - omap_set_gpio_irqenable(bank, offset, 0); | |
70 | + omap_set_gpio_irqenable(bank, offset, 1); | |
71 | + | |
72 | + /* | |
73 | + * For level-triggered GPIOs, clearing must be done after the source | |
74 | + * is cleared, thus after the handler has run. OMAP4 needs this done | |
75 | + * after enabing the interrupt to clear the wakeup status. | |
76 | + */ | |
77 | + if (bank->level_mask & BIT(offset)) | |
78 | omap_clear_gpio_irqstatus(bank, offset); | |
79 | - } | |
80 | ||
81 | - omap_set_gpio_irqenable(bank, offset, 1); | |
82 | raw_spin_unlock_irqrestore(&bank->lock, flags); | |
83 | } | |
84 | ||
85 | -- | |
86 | 2.19.1 | |
87 |