Skip to content

Commit ec0daae

Browse files
tmlindlinusw
authored andcommitted
gpio: omap: Add level wakeup handling for omap4 based SoCs
I noticed that unlike omap2 and 3 based SoCs, omap4 based SoCs keep the GPIO clocks enabled for GPIO level interrupts with wakeup enabled. This blocks deeper idle states as the whole domain will stay busy. The GPIO functional clock seems to stay enabled if the wakeup register is enabled and a level interrupt is triggered. In that case the only way to have the GPIO module idle is to reset it. It is possible this has gone unnoticed with OSWR (Open SWitch Retention) and off mode during idle resetting GPIO context most GPIO instances in the earlier Android trees for example. Looks like the way to deal with this is to have omap4 based SoCs only set wake for the duration of idle for level interrupts, and clear level registers for the idle. With level interrupts we can do this as the level interrupt from device will be still there on resume. I've taken the long path to fixing this to avoid yet more hard to read code. I've set up a quirks flag, and a struct for function pointers so we can use these to clean up other quirk handling easier in the later patches. The current level quirk handling is moved to the new functions. Cc: Aaro Koskinen <aaro.koskinen@iki.fi> Cc: Ladislav Michl <ladis@linux-mips.org> Cc: Tero Kristo <t-kristo@ti.com> Signed-off-by: Tony Lindgren <tony@atomide.com> Acked-by: Grygorii Strashko <grygorii.strashko@ti.com> Tested-by: Keerthy <j-keerthy@ti.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
1 parent 5b394b2 commit ec0daae

File tree

2 files changed

+120
-33
lines changed

2 files changed

+120
-33
lines changed

drivers/gpio/gpio-omap.c

Lines changed: 118 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131
#define OFF_MODE 1
3232
#define OMAP4_GPIO_DEBOUNCINGTIME_MASK 0xFF
3333

34+
#define OMAP_GPIO_QUIRK_DEFERRED_WKUP_EN BIT(1)
35+
3436
static LIST_HEAD(omap_gpio_list);
3537

3638
struct gpio_regs {
@@ -48,13 +50,21 @@ struct gpio_regs {
4850
u32 debounce_en;
4951
};
5052

53+
struct gpio_bank;
54+
55+
struct gpio_omap_funcs {
56+
void (*idle_enable_level_quirk)(struct gpio_bank *bank);
57+
void (*idle_disable_level_quirk)(struct gpio_bank *bank);
58+
};
59+
5160
struct gpio_bank {
5261
struct list_head node;
5362
void __iomem *base;
5463
int irq;
5564
u32 non_wakeup_gpios;
5665
u32 enabled_non_wakeup_gpios;
5766
struct gpio_regs context;
67+
struct gpio_omap_funcs funcs;
5868
u32 saved_datain;
5969
u32 level_mask;
6070
u32 toggle_mask;
@@ -75,6 +85,7 @@ struct gpio_bank {
7585
int context_loss_count;
7686
int power_mode;
7787
bool workaround_enabled;
88+
u32 quirks;
7889

7990
void (*set_dataout)(struct gpio_bank *bank, unsigned gpio, int enable);
8091
void (*set_dataout_multiple)(struct gpio_bank *bank,
@@ -368,9 +379,18 @@ static inline void omap_set_gpio_trigger(struct gpio_bank *bank, int gpio,
368379
readl_relaxed(bank->base + bank->regs->fallingdetect);
369380

370381
if (likely(!(bank->non_wakeup_gpios & gpio_bit))) {
371-
omap_gpio_rmw(base, bank->regs->wkup_en, gpio_bit, trigger != 0);
372-
bank->context.wake_en =
373-
readl_relaxed(bank->base + bank->regs->wkup_en);
382+
/* Defer wkup_en register update until we idle? */
383+
if (bank->quirks & OMAP_GPIO_QUIRK_DEFERRED_WKUP_EN) {
384+
if (trigger)
385+
bank->context.wake_en |= gpio_bit;
386+
else
387+
bank->context.wake_en &= ~gpio_bit;
388+
} else {
389+
omap_gpio_rmw(base, bank->regs->wkup_en, gpio_bit,
390+
trigger != 0);
391+
bank->context.wake_en =
392+
readl_relaxed(bank->base + bank->regs->wkup_en);
393+
}
374394
}
375395

376396
/* This part needs to be executed always for OMAP{34xx, 44xx} */
@@ -899,6 +919,82 @@ static void omap_gpio_unmask_irq(struct irq_data *d)
899919
raw_spin_unlock_irqrestore(&bank->lock, flags);
900920
}
901921

922+
/*
923+
* Only edges can generate a wakeup event to the PRCM.
924+
*
925+
* Therefore, ensure any wake-up capable GPIOs have
926+
* edge-detection enabled before going idle to ensure a wakeup
927+
* to the PRCM is generated on a GPIO transition. (c.f. 34xx
928+
* NDA TRM 25.5.3.1)
929+
*
930+
* The normal values will be restored upon ->runtime_resume()
931+
* by writing back the values saved in bank->context.
932+
*/
933+
static void __maybe_unused
934+
omap2_gpio_enable_level_quirk(struct gpio_bank *bank)
935+
{
936+
u32 wake_low, wake_hi;
937+
938+
/* Enable additional edge detection for level gpios for idle */
939+
wake_low = bank->context.leveldetect0 & bank->context.wake_en;
940+
if (wake_low)
941+
writel_relaxed(wake_low | bank->context.fallingdetect,
942+
bank->base + bank->regs->fallingdetect);
943+
944+
wake_hi = bank->context.leveldetect1 & bank->context.wake_en;
945+
if (wake_hi)
946+
writel_relaxed(wake_hi | bank->context.risingdetect,
947+
bank->base + bank->regs->risingdetect);
948+
}
949+
950+
static void __maybe_unused
951+
omap2_gpio_disable_level_quirk(struct gpio_bank *bank)
952+
{
953+
/* Disable edge detection for level gpios after idle */
954+
writel_relaxed(bank->context.fallingdetect,
955+
bank->base + bank->regs->fallingdetect);
956+
writel_relaxed(bank->context.risingdetect,
957+
bank->base + bank->regs->risingdetect);
958+
}
959+
960+
/*
961+
* On omap4 and later SoC variants a level interrupt with wkup_en
962+
* enabled blocks the GPIO functional clock from idling until the GPIO
963+
* instance has been reset. To avoid that, we must set wkup_en only for
964+
* idle for level interrupts, and clear level registers for the duration
965+
* of idle. The level interrupts will be still there on wakeup by their
966+
* nature.
967+
*/
968+
static void __maybe_unused
969+
omap4_gpio_enable_level_quirk(struct gpio_bank *bank)
970+
{
971+
/* Update wake register for idle, edge bits might be already set */
972+
writel_relaxed(bank->context.wake_en,
973+
bank->base + bank->regs->wkup_en);
974+
975+
/* Clear level registers for idle */
976+
writel_relaxed(0, bank->base + bank->regs->leveldetect0);
977+
writel_relaxed(0, bank->base + bank->regs->leveldetect1);
978+
}
979+
980+
static void __maybe_unused
981+
omap4_gpio_disable_level_quirk(struct gpio_bank *bank)
982+
{
983+
/* Restore level registers after idle */
984+
writel_relaxed(bank->context.leveldetect0,
985+
bank->base + bank->regs->leveldetect0);
986+
writel_relaxed(bank->context.leveldetect1,
987+
bank->base + bank->regs->leveldetect1);
988+
989+
/* Clear saved wkup_en for level, it will be set for next idle again */
990+
bank->context.wake_en &= ~(bank->context.leveldetect0 |
991+
bank->context.leveldetect1);
992+
993+
/* Update wake with only edge configuration */
994+
writel_relaxed(bank->context.wake_en,
995+
bank->base + bank->regs->wkup_en);
996+
}
997+
902998
/*---------------------------------------------------------------------*/
903999

9041000
static int omap_mpuio_suspend_noirq(struct device *dev)
@@ -1270,6 +1366,7 @@ static int omap_gpio_probe(struct platform_device *pdev)
12701366
bank->chip.parent = dev;
12711367
bank->chip.owner = THIS_MODULE;
12721368
bank->dbck_flag = pdata->dbck_flag;
1369+
bank->quirks = pdata->quirks;
12731370
bank->stride = pdata->bank_stride;
12741371
bank->width = pdata->bank_width;
12751372
bank->is_mpuio = pdata->is_mpuio;
@@ -1278,6 +1375,7 @@ static int omap_gpio_probe(struct platform_device *pdev)
12781375
#ifdef CONFIG_OF_GPIO
12791376
bank->chip.of_node = of_node_get(node);
12801377
#endif
1378+
12811379
if (node) {
12821380
if (!of_property_read_bool(node, "ti,gpio-always-on"))
12831381
bank->loses_context = true;
@@ -1298,6 +1396,18 @@ static int omap_gpio_probe(struct platform_device *pdev)
12981396
omap_set_gpio_dataout_mask_multiple;
12991397
}
13001398

1399+
if (bank->quirks & OMAP_GPIO_QUIRK_DEFERRED_WKUP_EN) {
1400+
bank->funcs.idle_enable_level_quirk =
1401+
omap4_gpio_enable_level_quirk;
1402+
bank->funcs.idle_disable_level_quirk =
1403+
omap4_gpio_disable_level_quirk;
1404+
} else {
1405+
bank->funcs.idle_enable_level_quirk =
1406+
omap2_gpio_enable_level_quirk;
1407+
bank->funcs.idle_disable_level_quirk =
1408+
omap2_gpio_disable_level_quirk;
1409+
}
1410+
13011411
raw_spin_lock_init(&bank->lock);
13021412
raw_spin_lock_init(&bank->wa_lock);
13031413

@@ -1372,29 +1482,11 @@ static int omap_gpio_runtime_suspend(struct device *dev)
13721482
struct gpio_bank *bank = platform_get_drvdata(pdev);
13731483
u32 l1 = 0, l2 = 0;
13741484
unsigned long flags;
1375-
u32 wake_low, wake_hi;
13761485

13771486
raw_spin_lock_irqsave(&bank->lock, flags);
13781487

1379-
/*
1380-
* Only edges can generate a wakeup event to the PRCM.
1381-
*
1382-
* Therefore, ensure any wake-up capable GPIOs have
1383-
* edge-detection enabled before going idle to ensure a wakeup
1384-
* to the PRCM is generated on a GPIO transition. (c.f. 34xx
1385-
* NDA TRM 25.5.3.1)
1386-
*
1387-
* The normal values will be restored upon ->runtime_resume()
1388-
* by writing back the values saved in bank->context.
1389-
*/
1390-
wake_low = bank->context.leveldetect0 & bank->context.wake_en;
1391-
if (wake_low)
1392-
writel_relaxed(wake_low | bank->context.fallingdetect,
1393-
bank->base + bank->regs->fallingdetect);
1394-
wake_hi = bank->context.leveldetect1 & bank->context.wake_en;
1395-
if (wake_hi)
1396-
writel_relaxed(wake_hi | bank->context.risingdetect,
1397-
bank->base + bank->regs->risingdetect);
1488+
if (bank->funcs.idle_enable_level_quirk)
1489+
bank->funcs.idle_enable_level_quirk(bank);
13981490

13991491
if (!bank->enabled_non_wakeup_gpios)
14001492
goto update_gpio_context_count;
@@ -1459,16 +1551,8 @@ static int omap_gpio_runtime_resume(struct device *dev)
14591551

14601552
omap_gpio_dbck_enable(bank);
14611553

1462-
/*
1463-
* In ->runtime_suspend(), level-triggered, wakeup-enabled
1464-
* GPIOs were set to edge trigger also in order to be able to
1465-
* generate a PRCM wakeup. Here we restore the
1466-
* pre-runtime_suspend() values for edge triggering.
1467-
*/
1468-
writel_relaxed(bank->context.fallingdetect,
1469-
bank->base + bank->regs->fallingdetect);
1470-
writel_relaxed(bank->context.risingdetect,
1471-
bank->base + bank->regs->risingdetect);
1554+
if (bank->funcs.idle_disable_level_quirk)
1555+
bank->funcs.idle_disable_level_quirk(bank);
14721556

14731557
if (bank->loses_context) {
14741558
if (!bank->get_context_loss_count) {
@@ -1706,6 +1790,7 @@ static const struct omap_gpio_platform_data omap4_pdata = {
17061790
.regs = &omap4_gpio_regs,
17071791
.bank_width = 32,
17081792
.dbck_flag = true,
1793+
.quirks = OMAP_GPIO_QUIRK_DEFERRED_WKUP_EN,
17091794
};
17101795

17111796
static const struct of_device_id omap_gpio_match[] = {

include/linux/platform_data/gpio-omap.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,8 @@ struct omap_gpio_platform_data {
197197
bool is_mpuio; /* whether the bank is of type MPUIO */
198198
u32 non_wakeup_gpios;
199199

200+
u32 quirks; /* Version specific quirks mask */
201+
200202
struct omap_gpio_reg_offs *regs;
201203

202204
/* Return context loss count due to PM states changing */

0 commit comments

Comments
 (0)