[U-Boot] [PATCH] armv8: ls2085a: Add workaround of errata A009635
Prabhakar Kushwaha
prabhakar at freescale.com
Tue Nov 3 05:37:39 CET 2015
Description:
When an A57 core is waiting for certain condition, it might use WFE to put
itself into lower power mode to save power if the condition is not met.
Another core can send an event to wake up the first core to check if the
condition is met or not.
When the second A57 core executes SEV instruction,it drives EVENTO for 3
core cycles. The SoC Run Control block samples the signal with the
platform clock, ORed with its own EVENTI event and drive it back to A57
cores as EVENTI.
If the core runs at higher than x3 speed of the platform, EVENTO is
shorter than one platform clock and might be missed by the platform sampling
logic. Taking into the consideration of jitter between A57 PLL
and the platform PLL, A57 must run at no greater than 2.5x speed of
the platform to guarantee the reliable sampling.
Workaround:
Configure Run Control and EPU to periodically send out EVENTI signals to
wake up A57 cores so that cores that are in WFE loop have
chance to check whether the condition for it to exit WFE loop is true
or not. This will make sure that in case SEV instruction is lost,
the core in WFE loop has a bounded time to exit the WFE loop.
Followings are the register values the software need to write to set
up Run Control and EPU:
0x7_0007_0914 = 0x0000_0200;
0x7_0006_0914 = <interval>;
0x7_0006_0814 = 0x8282_0000;
0x7_0006_0228 = 0x002f_0000;
0x7_0006_0314 = 0x2000_0000;
0x7_0006_0000 = 0x8000_0000;
For <interval> value above, it is the number of platform cycles between wake
up events generated by EPU. For example: A typical value is 1 microsecond.
If the platform frequency is 500MHz, each cycle is 2ns.
interval = 1us/2ns=500=0x1F4.
Signed-off-by: Prabhakar Kushwaha <prabhakar at freescale.com>
---
arch/arm/cpu/armv8/fsl-layerscape/cpu.c | 6 ++++
arch/arm/cpu/armv8/fsl-layerscape/soc.c | 39 +++++++++++++++++++++++
arch/arm/include/asm/arch-fsl-layerscape/config.h | 9 ++++++
arch/arm/include/asm/arch-fsl-layerscape/soc.h | 3 ++
4 files changed, 57 insertions(+)
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/cpu.c b/arch/arm/cpu/armv8/fsl-layerscape/cpu.c
index 0cb0afa..dbb12c2 100644
--- a/arch/arm/cpu/armv8/fsl-layerscape/cpu.c
+++ b/arch/arm/cpu/armv8/fsl-layerscape/cpu.c
@@ -484,7 +484,13 @@ int arch_early_init_r(void)
{
#ifdef CONFIG_MP
int rv = 1;
+#endif
+
+#ifdef CONFIG_SYS_FSL_ERRATUM_A009635
+ erratum_a009635();
+#endif
+#ifdef CONFIG_MP
rv = fsl_layerscape_wake_seconday_cores();
if (rv)
printf("Did not wake secondary cores\n");
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/soc.c b/arch/arm/cpu/armv8/fsl-layerscape/soc.c
index 637853d..e8cdb10 100644
--- a/arch/arm/cpu/armv8/fsl-layerscape/soc.c
+++ b/arch/arm/cpu/armv8/fsl-layerscape/soc.c
@@ -9,10 +9,49 @@
#include <asm/arch/soc.h>
#include <asm/io.h>
#include <asm/global_data.h>
+#include <asm/arch-fsl-layerscape/config.h>
DECLARE_GLOBAL_DATA_PTR;
#ifdef CONFIG_LS2085A
+#ifdef CONFIG_SYS_FSL_ERRATUM_A009635
+#define PLATFORM_CYCLE_ENV_VAR "a009635_interval_val"
+
+static unsigned long get_internval_val_mhz(void)
+{
+ char *interval = getenv(PLATFORM_CYCLE_ENV_VAR);
+ ulong interval_mhz = get_bus_freq(0) / (1000 * 1000);
+
+ if (interval)
+ interval_mhz = simple_strtoul(interval, NULL, 10);
+
+ return interval_mhz;
+}
+
+void erratum_a009635(void)
+{
+ u32 val;
+ unsigned long interval_mhz = get_internval_val_mhz();
+
+ if (!interval_mhz)
+ return;
+
+ val = in_le32(DCSR_CGACRE5);
+ writel(val | 0x00000200, DCSR_CGACRE5);
+
+ val = in_le32(EPU_EPCMPR5);
+ writel(interval_mhz, EPU_EPCMPR5);
+ val = in_le32(EPU_EPCCR5);
+ writel(val | 0x82820000, EPU_EPCCR5);
+ val = in_le32(EPU_EPSMCR5);
+ writel(val | 0x002f0000, EPU_EPSMCR5);
+ val = in_le32(EPU_EPECR5);
+ writel(val | 0x20000000, EPU_EPECR5);
+ val = in_le32(EPU_EPGCR);
+ writel(val | 0x80000000, EPU_EPGCR);
+}
+#endif
+
static void erratum_a008751(void)
{
#ifdef CONFIG_SYS_FSL_ERRATUM_A008751
diff --git a/arch/arm/include/asm/arch-fsl-layerscape/config.h b/arch/arm/include/asm/arch-fsl-layerscape/config.h
index 87bb937..c7169ab 100644
--- a/arch/arm/include/asm/arch-fsl-layerscape/config.h
+++ b/arch/arm/include/asm/arch-fsl-layerscape/config.h
@@ -84,11 +84,20 @@
#define TZPCDECPROT_2_SET_BASE (TZPC_BASE + 0x81C)
#define TZPCDECPROT_2_CLR_BASE (TZPC_BASE + 0x820)
+#define DCSR_CGACRE5 0x700070914ULL
+#define EPU_EPCMPR5 0x700060914ULL
+#define EPU_EPCCR5 0x700060814ULL
+#define EPU_EPSMCR5 0x700060228ULL
+#define EPU_EPECR5 0x700060314ULL
+#define EPU_EPCTR5 0x700060a14ULL
+#define EPU_EPGCR 0x700060000ULL
+
#define CONFIG_SYS_FSL_ERRATUM_A008336
#define CONFIG_SYS_FSL_ERRATUM_A008511
#define CONFIG_SYS_FSL_ERRATUM_A008514
#define CONFIG_SYS_FSL_ERRATUM_A008585
#define CONFIG_SYS_FSL_ERRATUM_A008751
+#define CONFIG_SYS_FSL_ERRATUM_A009635
#elif defined(CONFIG_LS1043A)
#define CONFIG_MAX_CPUS 4
#define CONFIG_SYS_CACHELINE_SIZE 64
diff --git a/arch/arm/include/asm/arch-fsl-layerscape/soc.h b/arch/arm/include/asm/arch-fsl-layerscape/soc.h
index 5ed456e..80354f0 100644
--- a/arch/arm/include/asm/arch-fsl-layerscape/soc.h
+++ b/arch/arm/include/asm/arch-fsl-layerscape/soc.h
@@ -50,4 +50,7 @@ void fsl_lsch2_early_init_f(void);
#endif
void cpu_name(char *name);
+#ifdef CONFIG_SYS_FSL_ERRATUM_A009635
+void erratum_a009635(void);
+#endif
#endif /* _ASM_ARMV8_FSL_LAYERSCAPE_SOC_H_ */
--
1.9.1
More information about the U-Boot
mailing list