aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@armlinux.org.uk>2019-04-08 15:46:53 -0400
committerLinus Walleij <linus.walleij@linaro.org>2019-04-11 09:13:33 -0400
commite6818d29ea1591b3e37d9cf635dc9dbca1a398ae (patch)
tree1ef23ddc4fa32e9455da5e4ba2bb9a7916aba87b
parent4779a066e71dee0784e09eeebb57dcd56cb7c7f6 (diff)
gpio: gpio-omap: configure edge detection for level IRQs for idle wakeup
The GPIO block can enter idle independently of the CPU power management calls via smart-idle. When the GPIO block enters idle, level detection stops working due to clocks being shut off, and an alternative form of edge detection is used. However, this needs the edge detection registers set to mark the appropriate edges. Arrange to configure the edge detection enables along with the level detection to ensure that any transition to active interrupt state that occurs while the block is idle is detected as a wake-up event. Since we enable the edge detection when configuring the IRQ, both omap2_gpio_enable_level_quirk() nor omap2_gpio_disable_level_quirk() become redundant, which also means OMAP_GPIO_QUIRK_IDLE_REMOVE_TRIGGER can be removed. This can be now done without regressions as patch "gpio: gpio-omap: fix level interrupt idling" allows level interrupts to idle on omap4 without a workaround. Cc: Aaro Koskinen <aaro.koskinen@iki.fi> Cc: Grygorii Strashko <grygorii.strashko@ti.com> Cc: Keerthy <j-keerthy@ti.com> Cc: Peter Ujfalusi <peter.ujfalusi@ti.com> Cc: Tero Kristo <t-kristo@ti.com> Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk> [tony@atomide.com: update description for the fix dependency] Signed-off-by: Tony Lindgren <tony@atomide.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
-rw-r--r--drivers/gpio/gpio-omap.c90
-rw-r--r--include/linux/platform_data/gpio-omap.h2
2 files changed, 11 insertions, 81 deletions
diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c
index 8cbb109928cb..e9dedee0af10 100644
--- a/drivers/gpio/gpio-omap.c
+++ b/drivers/gpio/gpio-omap.c
@@ -31,8 +31,6 @@
31 31
32#define OMAP4_GPIO_DEBOUNCINGTIME_MASK 0xFF 32#define OMAP4_GPIO_DEBOUNCINGTIME_MASK 0xFF
33 33
34#define OMAP_GPIO_QUIRK_IDLE_REMOVE_TRIGGER BIT(2)
35
36struct gpio_regs { 34struct gpio_regs {
37 u32 irqenable1; 35 u32 irqenable1;
38 u32 irqenable2; 36 u32 irqenable2;
@@ -48,13 +46,6 @@ struct gpio_regs {
48 u32 debounce_en; 46 u32 debounce_en;
49}; 47};
50 48
51struct gpio_bank;
52
53struct gpio_omap_funcs {
54 void (*idle_enable_level_quirk)(struct gpio_bank *bank);
55 void (*idle_disable_level_quirk)(struct gpio_bank *bank);
56};
57
58struct gpio_bank { 49struct gpio_bank {
59 struct list_head node; 50 struct list_head node;
60 void __iomem *base; 51 void __iomem *base;
@@ -62,7 +53,6 @@ struct gpio_bank {
62 u32 non_wakeup_gpios; 53 u32 non_wakeup_gpios;
63 u32 enabled_non_wakeup_gpios; 54 u32 enabled_non_wakeup_gpios;
64 struct gpio_regs context; 55 struct gpio_regs context;
65 struct gpio_omap_funcs funcs;
66 u32 saved_datain; 56 u32 saved_datain;
67 u32 level_mask; 57 u32 level_mask;
68 u32 toggle_mask; 58 u32 toggle_mask;
@@ -83,7 +73,6 @@ struct gpio_bank {
83 int stride; 73 int stride;
84 u32 width; 74 u32 width;
85 int context_loss_count; 75 int context_loss_count;
86 u32 quirks;
87 76
88 void (*set_dataout)(struct gpio_bank *bank, unsigned gpio, int enable); 77 void (*set_dataout)(struct gpio_bank *bank, unsigned gpio, int enable);
89 void (*set_dataout_multiple)(struct gpio_bank *bank, 78 void (*set_dataout_multiple)(struct gpio_bank *bank,
@@ -378,10 +367,16 @@ static inline void omap_set_gpio_trigger(struct gpio_bank *bank, int gpio,
378 trigger & IRQ_TYPE_LEVEL_LOW); 367 trigger & IRQ_TYPE_LEVEL_LOW);
379 omap_gpio_rmw(base, bank->regs->leveldetect1, gpio_bit, 368 omap_gpio_rmw(base, bank->regs->leveldetect1, gpio_bit,
380 trigger & IRQ_TYPE_LEVEL_HIGH); 369 trigger & IRQ_TYPE_LEVEL_HIGH);
370
371 /*
372 * We need the edge detection enabled for to allow the GPIO block
373 * to be woken from idle state. Set the appropriate edge detection
374 * in addition to the level detection.
375 */
381 omap_gpio_rmw(base, bank->regs->risingdetect, gpio_bit, 376 omap_gpio_rmw(base, bank->regs->risingdetect, gpio_bit,
382 trigger & IRQ_TYPE_EDGE_RISING); 377 trigger & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_LEVEL_HIGH));
383 omap_gpio_rmw(base, bank->regs->fallingdetect, gpio_bit, 378 omap_gpio_rmw(base, bank->regs->fallingdetect, gpio_bit,
384 trigger & IRQ_TYPE_EDGE_FALLING); 379 trigger & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_LEVEL_LOW));
385 380
386 bank->context.leveldetect0 = 381 bank->context.leveldetect0 =
387 readl_relaxed(bank->base + bank->regs->leveldetect0); 382 readl_relaxed(bank->base + bank->regs->leveldetect0);
@@ -904,44 +899,6 @@ static void omap_gpio_unmask_irq(struct irq_data *d)
904 raw_spin_unlock_irqrestore(&bank->lock, flags); 899 raw_spin_unlock_irqrestore(&bank->lock, flags);
905} 900}
906 901
907/*
908 * Only edges can generate a wakeup event to the PRCM.
909 *
910 * Therefore, ensure any wake-up capable GPIOs have
911 * edge-detection enabled before going idle to ensure a wakeup
912 * to the PRCM is generated on a GPIO transition. (c.f. 34xx
913 * NDA TRM 25.5.3.1)
914 *
915 * The normal values will be restored upon ->runtime_resume()
916 * by writing back the values saved in bank->context.
917 */
918static void __maybe_unused
919omap2_gpio_enable_level_quirk(struct gpio_bank *bank)
920{
921 u32 wake_low, wake_hi;
922
923 /* Enable additional edge detection for level gpios for idle */
924 wake_low = bank->context.leveldetect0 & bank->context.wake_en;
925 if (wake_low)
926 writel_relaxed(wake_low | bank->context.fallingdetect,
927 bank->base + bank->regs->fallingdetect);
928
929 wake_hi = bank->context.leveldetect1 & bank->context.wake_en;
930 if (wake_hi)
931 writel_relaxed(wake_hi | bank->context.risingdetect,
932 bank->base + bank->regs->risingdetect);
933}
934
935static void __maybe_unused
936omap2_gpio_disable_level_quirk(struct gpio_bank *bank)
937{
938 /* Disable edge detection for level gpios after idle */
939 writel_relaxed(bank->context.fallingdetect,
940 bank->base + bank->regs->fallingdetect);
941 writel_relaxed(bank->context.risingdetect,
942 bank->base + bank->regs->risingdetect);
943}
944
945/*---------------------------------------------------------------------*/ 902/*---------------------------------------------------------------------*/
946 903
947static int omap_mpuio_suspend_noirq(struct device *dev) 904static int omap_mpuio_suspend_noirq(struct device *dev)
@@ -1324,9 +1281,6 @@ static void omap_gpio_idle(struct gpio_bank *bank, bool may_lose_context)
1324 1281
1325 bank->saved_datain = readl_relaxed(base + bank->regs->datain); 1282 bank->saved_datain = readl_relaxed(base + bank->regs->datain);
1326 1283
1327 if (bank->funcs.idle_enable_level_quirk)
1328 bank->funcs.idle_enable_level_quirk(bank);
1329
1330 if (!bank->enabled_non_wakeup_gpios) 1284 if (!bank->enabled_non_wakeup_gpios)
1331 goto update_gpio_context_count; 1285 goto update_gpio_context_count;
1332 1286
@@ -1373,9 +1327,6 @@ static void omap_gpio_unidle(struct gpio_bank *bank)
1373 1327
1374 omap_gpio_dbck_enable(bank); 1328 omap_gpio_dbck_enable(bank);
1375 1329
1376 if (bank->funcs.idle_disable_level_quirk)
1377 bank->funcs.idle_disable_level_quirk(bank);
1378
1379 if (bank->loses_context) { 1330 if (bank->loses_context) {
1380 if (!bank->get_context_loss_count) { 1331 if (!bank->get_context_loss_count) {
1381 omap_gpio_restore_context(bank); 1332 omap_gpio_restore_context(bank);
@@ -1519,11 +1470,6 @@ static struct omap_gpio_reg_offs omap4_gpio_regs = {
1519 .fallingdetect = OMAP4_GPIO_FALLINGDETECT, 1470 .fallingdetect = OMAP4_GPIO_FALLINGDETECT,
1520}; 1471};
1521 1472
1522/*
1523 * Note that omap2 does not currently support idle modes with context loss so
1524 * no need to add OMAP_GPIO_QUIRK_IDLE_REMOVE_TRIGGER quirk flag to save
1525 * and restore context.
1526 */
1527static const struct omap_gpio_platform_data omap2_pdata = { 1473static const struct omap_gpio_platform_data omap2_pdata = {
1528 .regs = &omap2_gpio_regs, 1474 .regs = &omap2_gpio_regs,
1529 .bank_width = 32, 1475 .bank_width = 32,
@@ -1534,14 +1480,12 @@ static const struct omap_gpio_platform_data omap3_pdata = {
1534 .regs = &omap2_gpio_regs, 1480 .regs = &omap2_gpio_regs,
1535 .bank_width = 32, 1481 .bank_width = 32,
1536 .dbck_flag = true, 1482 .dbck_flag = true,
1537 .quirks = OMAP_GPIO_QUIRK_IDLE_REMOVE_TRIGGER,
1538}; 1483};
1539 1484
1540static const struct omap_gpio_platform_data omap4_pdata = { 1485static const struct omap_gpio_platform_data omap4_pdata = {
1541 .regs = &omap4_gpio_regs, 1486 .regs = &omap4_gpio_regs,
1542 .bank_width = 32, 1487 .bank_width = 32,
1543 .dbck_flag = true, 1488 .dbck_flag = true,
1544 .quirks = OMAP_GPIO_QUIRK_IDLE_REMOVE_TRIGGER,
1545}; 1489};
1546 1490
1547static const struct of_device_id omap_gpio_match[] = { 1491static const struct of_device_id omap_gpio_match[] = {
@@ -1611,7 +1555,6 @@ static int omap_gpio_probe(struct platform_device *pdev)
1611 bank->chip.parent = dev; 1555 bank->chip.parent = dev;
1612 bank->chip.owner = THIS_MODULE; 1556 bank->chip.owner = THIS_MODULE;
1613 bank->dbck_flag = pdata->dbck_flag; 1557 bank->dbck_flag = pdata->dbck_flag;
1614 bank->quirks = pdata->quirks;
1615 bank->stride = pdata->bank_stride; 1558 bank->stride = pdata->bank_stride;
1616 bank->width = pdata->bank_width; 1559 bank->width = pdata->bank_width;
1617 bank->is_mpuio = pdata->is_mpuio; 1560 bank->is_mpuio = pdata->is_mpuio;
@@ -1641,13 +1584,6 @@ static int omap_gpio_probe(struct platform_device *pdev)
1641 omap_set_gpio_dataout_mask_multiple; 1584 omap_set_gpio_dataout_mask_multiple;
1642 } 1585 }
1643 1586
1644 if (bank->quirks & OMAP_GPIO_QUIRK_IDLE_REMOVE_TRIGGER) {
1645 bank->funcs.idle_enable_level_quirk =
1646 omap2_gpio_enable_level_quirk;
1647 bank->funcs.idle_disable_level_quirk =
1648 omap2_gpio_disable_level_quirk;
1649 }