armv8: ls2085a: Add workaround of errata A009635
[platform/kernel/u-boot.git] / arch / arm / cpu / armv8 / fsl-layerscape / soc.c
index f427ac2..8896b70 100644 (file)
@@ -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