Message ID | 1421329328-18070-10-git-send-email-akshay.s@samsung.com |
---|---|
State | Changes Requested |
Delegated to: | Minkyu Kang |
Headers | show |
Hi Akshay, On 15 January 2015 at 06:42, Akshay Saraswat <akshay.s@samsung.com> wrote: > From: Doug Anderson <dianders@chromium.org> > > It was found that the L2 cache timings that we had before could cause > freezes and hangs. We should make things more robust with better > timings. Currently the production ChromeOS kernel applies these > timings, but it's nice to fixup firmware too (and upstream probably > won't take our kernel hacks). > > This also provides a big cleanup of the L2 cache init code avoiding > some duplication. The way things used to work: > * low_power_start() was installed by the SPL (both at boot and resume > time) and left resident in iRAM for the kernel to use when bringing > up additional CPUs. It used configure_l2_ctlr() and > configure_l2_actlr() when it detected it was on an A15. This was > needed (despite the L2 cache registers being shared among all A15s) > because we might have been the first man in after the whole A15 > cluster was shutdown. > * secondary_cores_configure() was called on at boot time and at resume > time. Strangely this called configure_l2_ctlr() but not > configure_l2_actlr() which was almost certainly wrong. Given that > we'll call both (see next bullet) later in the boot process it > didn't matter for normal boot, but I guess this is how L2 cache > settings got set on 5420/5800 (but not 5250?) at resume time. > * exynos5_set_l2cache_params() was called as part of cache enablement. > This should happen at boot time (normally in the SPL except for USB > boot where it happens in main U-Boot). > > Note that the old code wasn't setting ECC/parity in the cache > enablement code but we happened to get it anyway because we'd call > secondary_cores_configure() at boot time. For resume time we'd get it > anyway when the 2nd A15 core came up. > > Let's make this a whole lot simpler. Now we always set these > parameters in the same place for all boots and use the same code for > setting up secondary CPUs. > > Intended net effects of this change (other than cleanup): > * Timings go from before: > data: 0 cycle setup, 3 cycles (0x2) latency > tag: 0 cycle setup, 3 cycles (0x2) latency > after: > data: 1 cycle setup, 4 cycles (0x3) latency > tag: 1 cycle setup, 4 cycles (0x3) latency > * L2ACTLR is properly initted on 5420/5800 in all cases. > > One note is that we're still relying on luck to keep low_power_start() > working. The compiler is being nice and not storing anything on the > stack. > > Another note is that on its own this patch won't help to fix cache > settings in an RW U-Boot update where we still have the RO SPL. The > plan for that is: > * Have RW U-Boot re-init the cache right before calling the kernel > (after it has turned the L2 cache off). This is why the functions > are in a header file instead of lowlevel_init.c. > > * Have the kernel save the L2 cache settings of the boot CPU and apply > them to all other CPUs. We get a little lucky here because the old > code was using "|=" to modify the registers and all of the bits that > it's setting are also present in the new settings (!). That means > that when the 2nd CPU in the A15 cluster comes up it doesn't > actually mess up the settings of the 1st CPU in the A15 cluster. An > alternative option is to have the kernel write its own > low_power_start() code. > > Signed-off-by: Doug Anderson <dianders@chromium.org> > Signed-off-by: Akshay Saraswat <akshay.s@samsung.com> > --- > arch/arm/cpu/armv7/exynos/common_setup.h | 55 +++++++++++++++++++++++++++++++ > arch/arm/cpu/armv7/exynos/lowlevel_init.c | 55 +++++++++---------------------- > arch/arm/cpu/armv7/exynos/soc.c | 51 ---------------------------- > 3 files changed, 70 insertions(+), 91 deletions(-) This causes a compilation error on snow, so needs to be adjusted. Tested on pit, pi Tested-by: Simon Glass <sjg@chromium.org> > > diff --git a/arch/arm/cpu/armv7/exynos/common_setup.h b/arch/arm/cpu/armv7/exynos/common_setup.h > index e6318c0..7fa9683 100644 > --- a/arch/arm/cpu/armv7/exynos/common_setup.h > +++ b/arch/arm/cpu/armv7/exynos/common_setup.h > @@ -23,6 +23,8 @@ > * MA 02111-1307 USA > */ > > +#include <asm/arch/system.h> > + > #define DMC_OFFSET 0x10000 > > /* > @@ -43,3 +45,56 @@ void system_clock_init(void); > int do_lowlevel_init(void); > > void sdelay(unsigned long); > + > +enum l2_cache_params { > + CACHE_ECC_AND_PARITY = (1 << 21), > + CACHE_TAG_RAM_SETUP = (1 << 9), > + CACHE_DATA_RAM_SETUP = (1 << 5), > +#ifndef CONFIG_EXYNOS5420 > + CACHE_TAG_RAM_LATENCY = (2 << 6), /* 5250 */ > + CACHE_DATA_RAM_LATENCY = (2 << 0), > +#else > + CACHE_TAG_RAM_LATENCY = (3 << 6), /* 5420 and 5422 */ > + CACHE_DATA_RAM_LATENCY = (3 << 0), > +#endif > +}; > + > +#ifndef CONFIG_SYS_L2CACHE_OFF > +/* > + * Configure L2CTLR to get timings that keep us from hanging/crashing. > + * > + * Must be inline here since low_power_start() is called without a > + * stack (!). > + */ > +static inline void configure_l2_ctlr(void) > +{ > + uint32_t val; > + > + mrc_l2_ctlr(val); > + val |= CACHE_TAG_RAM_SETUP | > + CACHE_DATA_RAM_SETUP | > + CACHE_TAG_RAM_LATENCY | > + CACHE_DATA_RAM_LATENCY | > + CACHE_ECC_AND_PARITY; > + mcr_l2_ctlr(val); > +} > + > +/* > + * Configure L2ACTLR. > + * > + * Must be inline here since low_power_start() is called without a > + * stack (!). > + */ > +static inline void configure_l2_actlr(void) > +{ > +#ifdef CONFIG_EXYNOS5420 > + uint32_t val; > + > + mrc_l2_aux_ctlr(val); > + val |= (1 << 27) | /* Prevents stopping the L2 logic clock */ > + (1 << 7) | /* Enable hazard detect timeout for A15 */ > + (1 << 3); /* Disable clean/evict push to external */ > + mcr_l2_aux_ctlr(val); > +#endif > +} > +#endif > diff --git a/arch/arm/cpu/armv7/exynos/lowlevel_init.c b/arch/arm/cpu/armv7/exynos/lowlevel_init.c > index a459432..40d3e3a 100644 > --- a/arch/arm/cpu/armv7/exynos/lowlevel_init.c > +++ b/arch/arm/cpu/armv7/exynos/lowlevel_init.c > @@ -67,43 +67,6 @@ static void enable_smp(void) > } > > /* > - * Enable ECC by setting L2CTLR[21]. > - * Set L2CTLR[7] to make tag ram latency 3 cycles and > - * set L2CTLR[1] to make data ram latency 3 cycles. > - * We need to make RAM latency of 3 cycles here because cores > - * power ON and OFF while switching. And everytime a core powers > - * ON, iROM provides it a default L2CTLR value 0x400 which stands > - * for TAG RAM setup of 1 cycle. Hence, we face a need of > - * restoring data and tag latency values. > - */ > -static void configure_l2_ctlr(void) > -{ > - uint32_t val; > - > - mrc_l2_ctlr(val); > - val |= (1 << 21); > - val |= (1 << 7); > - val |= (1 << 1); > - mcr_l2_ctlr(val); > -} > - > -/* > - * Set L2ACTLR[7] to reissue any memory transaction in the L2 that has been > - * stalled for 1024 cycles to verify that its hazard condition still exists. > - * Disable clean/evict push to external by setting L2ACTLR[3]. > - */ > -static void configure_l2_actlr(void) > -{ > - uint32_t val; > - > - mrc_l2_aux_ctlr(val); > - val |= (1 << 27); > - val |= (1 << 7); > - val |= (1 << 3); > - mcr_l2_aux_ctlr(val); > -} > - > -/* > * Power up secondary CPUs. > */ > static void secondary_cpu_start(void) > @@ -198,9 +161,6 @@ static void power_down_core(void) > */ > static void secondary_cores_configure(void) > { > - /* Setup L2 cache */ > - configure_l2_ctlr(); > - > /* Clear secondary boot iRAM base */ > writel(0x0, (CONFIG_EXYNOS_RELOCATE_CODE_BASE + 0x1C)); > > @@ -226,6 +186,21 @@ int do_lowlevel_init(void) > > arch_cpu_init(); > > +#ifndef CONFIG_SYS_L2CACHE_OFF > + /* > + * Init L2 cache parameters here for use by boot and resume > + * > + * These are here instead of in v7_outer_cache_enable() so that the > + * L2 cache settings get properly set even at resume time or if we're > + * running U-Boot with the cache off. The kernel still needs us to > + * set these for it. > + */ > + configure_l2_ctlr(); > + configure_l2_actlr(); > + dsb(); > + isb(); > +#endif > + > #ifdef CONFIG_EXYNOS5420 > relocate_wait_code(); > > diff --git a/arch/arm/cpu/armv7/exynos/soc.c b/arch/arm/cpu/armv7/exynos/soc.c > index ea201e7..0f116b1 100644 > --- a/arch/arm/cpu/armv7/exynos/soc.c > +++ b/arch/arm/cpu/armv7/exynos/soc.c > @@ -9,15 +9,6 @@ > #include <asm/io.h> > #include <asm/system.h> > > -enum l2_cache_params { > -#ifndef CONFIG_EXYNOS5420 > - CACHE_TAG_RAM_SETUP = (1 << 9), > - CACHE_DATA_RAM_SETUP = (1 << 5), > -#endif > - CACHE_TAG_RAM_LATENCY = (2 << 6), > - CACHE_DATA_RAM_LATENCY = (2 << 0) > -}; > - > void reset_cpu(ulong addr) > { > writel(0x1, samsung_get_base_swreset()); > @@ -30,45 +21,3 @@ void enable_caches(void) > dcache_enable(); > } > #endif > - > -#ifndef CONFIG_SYS_L2CACHE_OFF > -/* > - * Set L2 cache parameters > - */ > -static void exynos5_set_l2cache_params(void) > -{ > - unsigned int val = 0; > - > - asm volatile("mrc p15, 1, %0, c9, c0, 2\n" : "=r"(val)); > - > -#ifndef CONFIG_EXYNOS5420 > - val |= CACHE_TAG_RAM_SETUP | > - CACHE_DATA_RAM_SETUP | > - CACHE_TAG_RAM_LATENCY | > - CACHE_DATA_RAM_LATENCY; > -#else > - val |= CACHE_TAG_RAM_LATENCY | > - CACHE_DATA_RAM_LATENCY; > -#endif > - > - asm volatile("mcr p15, 1, %0, c9, c0, 2\n" : : "r"(val)); > - > -#ifdef CONFIG_EXYNOS5420 > - /* Read CP15 L2ACTLR value */ > - asm volatile("mrc p15, 1, %0, c15, c0, 0" : "=r" (val)); > - /* Disable clean/evict push to external */ > - val |= (0x1 << 3); > - /* Write new vlaue to L2ACTLR */ > - asm volatile("mcr p15, 1, %0, c15, c0, 0" : : "r" (val)); > -#endif > -} > - > -/* > - * Sets L2 cache related parameters before enabling data cache > - */ > -void v7_outer_cache_enable(void) > -{ > - if (cpu_is_exynos5()) > - exynos5_set_l2cache_params(); > -} > -#endif > -- > 1.9.1 > Regards, Simon
diff --git a/arch/arm/cpu/armv7/exynos/common_setup.h b/arch/arm/cpu/armv7/exynos/common_setup.h index e6318c0..7fa9683 100644 --- a/arch/arm/cpu/armv7/exynos/common_setup.h +++ b/arch/arm/cpu/armv7/exynos/common_setup.h @@ -23,6 +23,8 @@ * MA 02111-1307 USA */ +#include <asm/arch/system.h> + #define DMC_OFFSET 0x10000 /* @@ -43,3 +45,56 @@ void system_clock_init(void); int do_lowlevel_init(void); void sdelay(unsigned long); + +enum l2_cache_params { + CACHE_ECC_AND_PARITY = (1 << 21), + CACHE_TAG_RAM_SETUP = (1 << 9), + CACHE_DATA_RAM_SETUP = (1 << 5), +#ifndef CONFIG_EXYNOS5420 + CACHE_TAG_RAM_LATENCY = (2 << 6), /* 5250 */ + CACHE_DATA_RAM_LATENCY = (2 << 0), +#else + CACHE_TAG_RAM_LATENCY = (3 << 6), /* 5420 and 5422 */ + CACHE_DATA_RAM_LATENCY = (3 << 0), +#endif +}; + +#ifndef CONFIG_SYS_L2CACHE_OFF +/* + * Configure L2CTLR to get timings that keep us from hanging/crashing. + * + * Must be inline here since low_power_start() is called without a + * stack (!). + */ +static inline void configure_l2_ctlr(void) +{ + uint32_t val; + + mrc_l2_ctlr(val); + val |= CACHE_TAG_RAM_SETUP | + CACHE_DATA_RAM_SETUP | + CACHE_TAG_RAM_LATENCY | + CACHE_DATA_RAM_LATENCY | + CACHE_ECC_AND_PARITY; + mcr_l2_ctlr(val); +} + +/* + * Configure L2ACTLR. + * + * Must be inline here since low_power_start() is called without a + * stack (!). + */ +static inline void configure_l2_actlr(void) +{ +#ifdef CONFIG_EXYNOS5420 + uint32_t val; + + mrc_l2_aux_ctlr(val); + val |= (1 << 27) | /* Prevents stopping the L2 logic clock */ + (1 << 7) | /* Enable hazard detect timeout for A15 */ + (1 << 3); /* Disable clean/evict push to external */ + mcr_l2_aux_ctlr(val); +#endif +} +#endif diff --git a/arch/arm/cpu/armv7/exynos/lowlevel_init.c b/arch/arm/cpu/armv7/exynos/lowlevel_init.c index a459432..40d3e3a 100644 --- a/arch/arm/cpu/armv7/exynos/lowlevel_init.c +++ b/arch/arm/cpu/armv7/exynos/lowlevel_init.c @@ -67,43 +67,6 @@ static void enable_smp(void) } /* - * Enable ECC by setting L2CTLR[21]. - * Set L2CTLR[7] to make tag ram latency 3 cycles and - * set L2CTLR[1] to make data ram latency 3 cycles. - * We need to make RAM latency of 3 cycles here because cores - * power ON and OFF while switching. And everytime a core powers - * ON, iROM provides it a default L2CTLR value 0x400 which stands - * for TAG RAM setup of 1 cycle. Hence, we face a need of - * restoring data and tag latency values. - */ -static void configure_l2_ctlr(void) -{ - uint32_t val; - - mrc_l2_ctlr(val); - val |= (1 << 21); - val |= (1 << 7); - val |= (1 << 1); - mcr_l2_ctlr(val); -} - -/* - * Set L2ACTLR[7] to reissue any memory transaction in the L2 that has been - * stalled for 1024 cycles to verify that its hazard condition still exists. - * Disable clean/evict push to external by setting L2ACTLR[3]. - */ -static void configure_l2_actlr(void) -{ - uint32_t val; - - mrc_l2_aux_ctlr(val); - val |= (1 << 27); - val |= (1 << 7); - val |= (1 << 3); - mcr_l2_aux_ctlr(val); -} - -/* * Power up secondary CPUs. */ static void secondary_cpu_start(void) @@ -198,9 +161,6 @@ static void power_down_core(void) */ static void secondary_cores_configure(void) { - /* Setup L2 cache */ - configure_l2_ctlr(); - /* Clear secondary boot iRAM base */ writel(0x0, (CONFIG_EXYNOS_RELOCATE_CODE_BASE + 0x1C)); @@ -226,6 +186,21 @@ int do_lowlevel_init(void) arch_cpu_init(); +#ifndef CONFIG_SYS_L2CACHE_OFF + /* + * Init L2 cache parameters here for use by boot and resume + * + * These are here instead of in v7_outer_cache_enable() so that the + * L2 cache settings get properly set even at resume time or if we're + * running U-Boot with the cache off. The kernel still needs us to + * set these for it. + */ + configure_l2_ctlr(); + configure_l2_actlr(); + dsb(); + isb(); +#endif + #ifdef CONFIG_EXYNOS5420 relocate_wait_code(); diff --git a/arch/arm/cpu/armv7/exynos/soc.c b/arch/arm/cpu/armv7/exynos/soc.c index ea201e7..0f116b1 100644 --- a/arch/arm/cpu/armv7/exynos/soc.c +++ b/arch/arm/cpu/armv7/exynos/soc.c @@ -9,15 +9,6 @@ #include <asm/io.h> #include <asm/system.h> -enum l2_cache_params { -#ifndef CONFIG_EXYNOS5420 - CACHE_TAG_RAM_SETUP = (1 << 9), - CACHE_DATA_RAM_SETUP = (1 << 5), -#endif - CACHE_TAG_RAM_LATENCY = (2 << 6), - CACHE_DATA_RAM_LATENCY = (2 << 0) -}; - void reset_cpu(ulong addr) { writel(0x1, samsung_get_base_swreset()); @@ -30,45 +21,3 @@ void enable_caches(void) dcache_enable(); } #endif - -#ifndef CONFIG_SYS_L2CACHE_OFF -/* - * Set L2 cache parameters - */ -static void exynos5_set_l2cache_params(void) -{ - unsigned int val = 0; - - asm volatile("mrc p15, 1, %0, c9, c0, 2\n" : "=r"(val)); - -#ifndef CONFIG_EXYNOS5420 - val |= CACHE_TAG_RAM_SETUP | - CACHE_DATA_RAM_SETUP | - CACHE_TAG_RAM_LATENCY | - CACHE_DATA_RAM_LATENCY; -#else - val |= CACHE_TAG_RAM_LATENCY | - CACHE_DATA_RAM_LATENCY; -#endif - - asm volatile("mcr p15, 1, %0, c9, c0, 2\n" : : "r"(val)); - -#ifdef CONFIG_EXYNOS5420 - /* Read CP15 L2ACTLR value */ - asm volatile("mrc p15, 1, %0, c15, c0, 0" : "=r" (val)); - /* Disable clean/evict push to external */ - val |= (0x1 << 3); - /* Write new vlaue to L2ACTLR */ - asm volatile("mcr p15, 1, %0, c15, c0, 0" : : "r" (val)); -#endif -} - -/* - * Sets L2 cache related parameters before enabling data cache - */ -void v7_outer_cache_enable(void) -{ - if (cpu_is_exynos5()) - exynos5_set_l2cache_params(); -} -#endif