[U-Boot] [PATCH 11/11] Exynos: Fix L2 cache timings on Exynos5420 and Exynos5800
Simon Glass
sjg at chromium.org
Wed Jan 28 05:13:09 CET 2015
Hi Akshay,
On 15 January 2015 at 06:42, Akshay Saraswat <akshay.s at samsung.com> wrote:
> From: Doug Anderson <dianders at 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 at chromium.org>
> Signed-off-by: Akshay Saraswat <akshay.s at 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 at 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
More information about the U-Boot
mailing list