| From c0d9c3ff64de9f40e29b5f00aabc4d3ffd2c9175 Mon Sep 17 00:00:00 2001 |
| From: Sebastian Andrzej Siewior <bigeasy@linutronix.de> |
| Date: Wed, 13 Jan 2016 17:43:57 +0100 |
| Subject: [PATCH 257/351] Revert "ARM: OMAP2: Drop the concept of certain power |
| domains not being able to lose context." |
| X-NVConfidentiality: public |
| |
| Requested by Grygorii Strashko <grygorii.strashko@ti.com>, not required |
| for v4.4-RT |
| |
| Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> |
| --- |
| arch/arm/mach-omap2/gpio.c | 1 + |
| arch/arm/mach-omap2/powerdomain.c | 40 +++++++++++++++++++++++++++++++++ |
| arch/arm/mach-omap2/powerdomain.h | 1 + |
| drivers/gpio/gpio-omap.c | 36 +++++++++++++++++------------ |
| include/linux/platform_data/gpio-omap.h | 1 + |
| 5 files changed, 65 insertions(+), 14 deletions(-) |
| |
| diff --git a/arch/arm/mach-omap2/gpio.c b/arch/arm/mach-omap2/gpio.c |
| index 689a1af47c80..7a577145b68b 100644 |
| --- a/arch/arm/mach-omap2/gpio.c |
| +++ b/arch/arm/mach-omap2/gpio.c |
| @@ -130,6 +130,7 @@ static int __init omap2_gpio_dev_init(struct omap_hwmod *oh, void *unused) |
| } |
| |
| pwrdm = omap_hwmod_get_pwrdm(oh); |
| + pdata->loses_context = pwrdm_can_ever_lose_context(pwrdm); |
| |
| pdev = omap_device_build(name, id - 1, oh, pdata, sizeof(*pdata)); |
| kfree(pdata); |
| diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c |
| index ef4227ffa3b6..78af6d8cf2e2 100644 |
| --- a/arch/arm/mach-omap2/powerdomain.c |
| +++ b/arch/arm/mach-omap2/powerdomain.c |
| @@ -1166,3 +1166,43 @@ int pwrdm_get_context_loss_count(struct powerdomain *pwrdm) |
| return count; |
| } |
| |
| +/** |
| + * pwrdm_can_ever_lose_context - can this powerdomain ever lose context? |
| + * @pwrdm: struct powerdomain * |
| + * |
| + * Given a struct powerdomain * @pwrdm, returns 1 if the powerdomain |
| + * can lose either memory or logic context or if @pwrdm is invalid, or |
| + * returns 0 otherwise. This function is not concerned with how the |
| + * powerdomain registers are programmed (i.e., to go off or not); it's |
| + * concerned with whether it's ever possible for this powerdomain to |
| + * go off while some other part of the chip is active. This function |
| + * assumes that every powerdomain can go to either ON or INACTIVE. |
| + */ |
| +bool pwrdm_can_ever_lose_context(struct powerdomain *pwrdm) |
| +{ |
| + int i; |
| + |
| + if (!pwrdm) { |
| + pr_debug("powerdomain: %s: invalid powerdomain pointer\n", |
| + __func__); |
| + return 1; |
| + } |
| + |
| + if (pwrdm->pwrsts & PWRSTS_OFF) |
| + return 1; |
| + |
| + if (pwrdm->pwrsts & PWRSTS_RET) { |
| + if (pwrdm->pwrsts_logic_ret & PWRSTS_OFF) |
| + return 1; |
| + |
| + for (i = 0; i < pwrdm->banks; i++) |
| + if (pwrdm->pwrsts_mem_ret[i] & PWRSTS_OFF) |
| + return 1; |
| + } |
| + |
| + for (i = 0; i < pwrdm->banks; i++) |
| + if (pwrdm->pwrsts_mem_on[i] & PWRSTS_OFF) |
| + return 1; |
| + |
| + return 0; |
| +} |
| diff --git a/arch/arm/mach-omap2/powerdomain.h b/arch/arm/mach-omap2/powerdomain.h |
| index 5e0c033a21db..28a796ce07d7 100644 |
| --- a/arch/arm/mach-omap2/powerdomain.h |
| +++ b/arch/arm/mach-omap2/powerdomain.h |
| @@ -244,6 +244,7 @@ int pwrdm_state_switch(struct powerdomain *pwrdm); |
| int pwrdm_pre_transition(struct powerdomain *pwrdm); |
| int pwrdm_post_transition(struct powerdomain *pwrdm); |
| int pwrdm_get_context_loss_count(struct powerdomain *pwrdm); |
| +bool pwrdm_can_ever_lose_context(struct powerdomain *pwrdm); |
| |
| extern int omap_set_pwrdm_state(struct powerdomain *pwrdm, u8 state); |
| |
| diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c |
| index 4423b6dcc34f..e183351d047c 100644 |
| --- a/drivers/gpio/gpio-omap.c |
| +++ b/drivers/gpio/gpio-omap.c |
| @@ -69,7 +69,7 @@ struct gpio_bank { |
| struct device *dev; |
| bool is_mpuio; |
| bool dbck_flag; |
| - |
| + bool loses_context; |
| bool context_valid; |
| int stride; |
| u32 width; |
| @@ -1208,9 +1208,15 @@ static int omap_gpio_probe(struct platform_device *pdev) |
| #ifdef CONFIG_OF_GPIO |
| bank->chip.of_node = of_node_get(node); |
| #endif |
| - if (!node) { |
| - bank->get_context_loss_count = |
| - pdata->get_context_loss_count; |
| + if (node) { |
| + if (!of_property_read_bool(node, "ti,gpio-always-on")) |
| + bank->loses_context = true; |
| + } else { |
| + bank->loses_context = pdata->loses_context; |
| + |
| + if (bank->loses_context) |
| + bank->get_context_loss_count = |
| + pdata->get_context_loss_count; |
| } |
| |
| if (bank->regs->set_dataout && bank->regs->clr_dataout) |
| @@ -1367,7 +1373,7 @@ static int omap_gpio_runtime_resume(struct device *dev) |
| * been initialised and so initialise it now. Also initialise |
| * the context loss count. |
| */ |
| - if (!bank->context_valid) { |
| + if (bank->loses_context && !bank->context_valid) { |
| omap_gpio_init_context(bank); |
| |
| if (bank->get_context_loss_count) |
| @@ -1388,15 +1394,17 @@ static int omap_gpio_runtime_resume(struct device *dev) |
| writel_relaxed(bank->context.risingdetect, |
| bank->base + bank->regs->risingdetect); |
| |
| - if (!bank->get_context_loss_count) { |
| - omap_gpio_restore_context(bank); |
| - } else { |
| - c = bank->get_context_loss_count(bank->dev); |
| - if (c != bank->context_loss_count) { |
| + if (bank->loses_context) { |
| + if (!bank->get_context_loss_count) { |
| omap_gpio_restore_context(bank); |
| } else { |
| - spin_unlock_irqrestore(&bank->lock, flags); |
| - return 0; |
| + c = bank->get_context_loss_count(bank->dev); |
| + if (c != bank->context_loss_count) { |
| + omap_gpio_restore_context(bank); |
| + } else { |
| + raw_spin_unlock_irqrestore(&bank->lock, flags); |
| + return 0; |
| + } |
| } |
| } |
| |
| @@ -1468,7 +1476,7 @@ void omap2_gpio_prepare_for_idle(int pwr_mode) |
| struct gpio_bank *bank; |
| |
| list_for_each_entry(bank, &omap_gpio_list, node) { |
| - if (!BANK_USED(bank)) |
| + if (!BANK_USED(bank) || !bank->loses_context) |
| continue; |
| |
| bank->power_mode = pwr_mode; |
| @@ -1482,7 +1490,7 @@ void omap2_gpio_resume_after_idle(void) |
| struct gpio_bank *bank; |
| |
| list_for_each_entry(bank, &omap_gpio_list, node) { |
| - if (!BANK_USED(bank)) |
| + if (!BANK_USED(bank) || !bank->loses_context) |
| continue; |
| |
| pm_runtime_get_sync(bank->dev); |
| diff --git a/include/linux/platform_data/gpio-omap.h b/include/linux/platform_data/gpio-omap.h |
| index ff43e01b8ca9..cb2618147c34 100644 |
| --- a/include/linux/platform_data/gpio-omap.h |
| +++ b/include/linux/platform_data/gpio-omap.h |
| @@ -198,6 +198,7 @@ struct omap_gpio_platform_data { |
| int bank_width; /* GPIO bank width */ |
| int bank_stride; /* Only needed for omap1 MPUIO */ |
| bool dbck_flag; /* dbck required or not - True for OMAP3&4 */ |
| + bool loses_context; /* whether the bank would ever lose context */ |
| bool is_mpuio; /* whether the bank is of type MPUIO */ |
| u32 non_wakeup_gpios; |
| |
| -- |
| 2.10.1 |
| |