diff options
author | Florian Fainelli <f.fainelli@gmail.com> | 2017-12-01 03:10:12 +0300 |
---|---|---|
committer | Russell King <rmk+kernel@armlinux.org.uk> | 2017-12-18 01:15:37 +0300 |
commit | 534f5f36a2c10fda181de2d7023d2100e2a59048 (patch) | |
tree | f25996a268d8094fca6d80359b29a7140db20ab0 | |
parent | 55de88778f4bfe6333db4e475afb15ef413b4874 (diff) | |
download | linux-534f5f36a2c10fda181de2d7023d2100e2a59048.tar.xz |
ARM: 8730/1: B15: Add suspend/resume hooks
The Broadcom Brahma-B15 CPU readahead cache registers will be restored
to their Power-on-Reset values after a S3 suspend/resume cycles, so we
want to restore what we had enabled before.
Another thing we want to take care of is disabling the read-ahead cache
prior to suspending to avoid any sort of side effect with the spinlock
we need to grab to serialize register accesses.
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
-rw-r--r-- | arch/arm/mm/cache-b15-rac.c | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/arch/arm/mm/cache-b15-rac.c b/arch/arm/mm/cache-b15-rac.c index d85b63211759..9ee1d89cced0 100644 --- a/arch/arm/mm/cache-b15-rac.c +++ b/arch/arm/mm/cache-b15-rac.c @@ -15,6 +15,7 @@ #include <linux/of_address.h> #include <linux/notifier.h> #include <linux/cpu.h> +#include <linux/syscore_ops.h> #include <asm/cacheflush.h> #include <asm/hardware/cache-b15-rac.h> @@ -41,6 +42,10 @@ extern void v7_flush_kern_cache_all(void); RACENPREF_MASK << RACENDATA_SHIFT) #define RAC_ENABLED 0 +/* Special state where we want to bypass the spinlock and call directly + * into the v7 cache maintenance operations during suspend/resume + */ +#define RAC_SUSPENDED 1 static void __iomem *b15_rac_base; static DEFINE_SPINLOCK(rac_lock); @@ -96,6 +101,12 @@ void b15_flush_##name(void) \ unsigned int do_flush; \ u32 val = 0; \ \ + if (test_bit(RAC_SUSPENDED, &b15_rac_flags)) { \ + v7_flush_##name(); \ + bar; \ + return; \ + } \ + \ spin_lock(&rac_lock); \ do_flush = test_bit(RAC_ENABLED, &b15_rac_flags); \ if (do_flush) \ @@ -208,6 +219,39 @@ static int b15_rac_dead_cpu(unsigned int cpu) } #endif /* CONFIG_HOTPLUG_CPU */ +#ifdef CONFIG_PM_SLEEP +static int b15_rac_suspend(void) +{ + /* Suspend the read-ahead cache oeprations, forcing our cache + * implementation to fallback to the regular ARMv7 calls. + * + * We are guaranteed to be running on the boot CPU at this point and + * with every other CPU quiesced, so setting RAC_SUSPENDED is not racy + * here. + */ + rac_config0_reg = b15_rac_disable_and_flush(); + set_bit(RAC_SUSPENDED, &b15_rac_flags); + + return 0; +} + +static void b15_rac_resume(void) +{ + /* Coming out of a S3 suspend/resume cycle, the read-ahead cache + * register RAC_CONFIG0_REG will be restored to its default value, make + * sure we re-enable it and set the enable flag, we are also guaranteed + * to run on the boot CPU, so not racy again. + */ + __b15_rac_enable(rac_config0_reg); + clear_bit(RAC_SUSPENDED, &b15_rac_flags); +} + +static struct syscore_ops b15_rac_syscore_ops = { + .suspend = b15_rac_suspend, + .resume = b15_rac_resume, +}; +#endif + static int __init b15_rac_init(void) { struct device_node *dn; @@ -242,6 +286,10 @@ static int __init b15_rac_init(void) goto out_cpu_dead; #endif +#ifdef CONFIG_PM_SLEEP + register_syscore_ops(&b15_rac_syscore_ops); +#endif + spin_lock(&rac_lock); reg = __raw_readl(b15_rac_base + RAC_CONFIG0_REG); for_each_possible_cpu(cpu) |