summaryrefslogtreecommitdiff
path: root/arch/arm/cpu
diff options
context:
space:
mode:
authorPrabhakar Kushwaha <prabhakar@freescale.com>2015-11-05 12:00:14 +0530
committerYork Sun <yorksun@freescale.com>2015-11-30 09:11:12 -0800
commitb4017364630fbc526bbf5e917d8fae6013805488 (patch)
treeea2df6ef79c7526db3f91e1cfb06803b3e96aebd /arch/arm/cpu
parent5380335e66e7d731bd417f0fe6fcee68750b0245 (diff)
downloadu-boot-imx-b4017364630fbc526bbf5e917d8fae6013805488.zip
u-boot-imx-b4017364630fbc526bbf5e917d8fae6013805488.tar.gz
u-boot-imx-b4017364630fbc526bbf5e917d8fae6013805488.tar.bz2
armv8: ls2085a: Add workaround of errata A009635
If the core runs at higher than x3 speed of the platform, there is possiblity about sev instruction to getting missed by other cores. This is because of SoC Run Control block may not able to sample the EVENTI(Sev) signals. Configure Run Control and EPU to periodically send out EVENTI signals to wake up A57 cores. Signed-off-by: Prabhakar Kushwaha <prabhakar@freescale.com> Reviewed-by: York Sun <yorksun@freescale.com>
Diffstat (limited to 'arch/arm/cpu')
-rw-r--r--arch/arm/cpu/armv8/fsl-layerscape/README.lsch320
-rw-r--r--arch/arm/cpu/armv8/fsl-layerscape/cpu.c6
-rw-r--r--arch/arm/cpu/armv8/fsl-layerscape/soc.c43
3 files changed, 69 insertions, 0 deletions
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/README.lsch3 b/arch/arm/cpu/armv8/fsl-layerscape/README.lsch3
index db9359d..f9323c1 100644
--- a/arch/arm/cpu/armv8/fsl-layerscape/README.lsch3
+++ b/arch/arm/cpu/armv8/fsl-layerscape/README.lsch3
@@ -303,3 +303,23 @@ How to use commands :-
=> fsl_mc start aiop 0x580900000
=> setenv ethact DPMAC1@xgmii
=> fsl_mc apply dpl 580700000
+
+Errata A009635
+---------------
+If the core runs at higher than x3 speed of the platform, there is
+possiblity about sev instruction to getting missed by other cores.
+This is because of SoC Run Control block may not able to sample
+the EVENTI(Sev) signals.
+
+Workaround: Configure Run Control and EPU to periodically send out EVENTI signals to
+wake up A57 cores
+
+Errata workaround uses Env variable "a009635_interval_val". It uses decimal
+value.
+- Default value of env variable is platform clock (MHz)
+
+- User can modify default value by updating the env variable
+ setenv a009635_interval_val 600; saveenv;
+ It configure platform clock as 600 MHz
+
+- Env variable as 0 signifies no workaround
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/cpu.c b/arch/arm/cpu/armv8/fsl-layerscape/cpu.c
index 571ee7b..8847fc0 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 f427ac2..8896b70 100644
--- a/arch/arm/cpu/armv8/fsl-layerscape/soc.c
+++ b/arch/arm/cpu/armv8/fsl-layerscape/soc.c
@@ -9,10 +9,53 @@
#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;
#if defined(CONFIG_LS2080A) || defined(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);
+ /*
+ * interval is the number of platform cycles(MHz) between
+ * wake up events generated by EPU.
+ */
+ 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 /* CONFIG_SYS_FSL_ERRATUM_A009635 */
+
static void erratum_a008751(void)
{
#ifdef CONFIG_SYS_FSL_ERRATUM_A008751