[U-Boot] [PATCH][v2] 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 --- Chages for v2: Updated description
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_ */

On 11/03/2015 11:24 PM, Prabhakar Kushwaha wrote:
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
Chages for v2: Updated description
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);
Why do you need a variable to override the calculation?
- ulong interval_mhz = get_bus_freq(0) / (1000 * 1000);
Please add a comment here to explain what the interval does and why it is calculated this way.
York

-----Original Message----- From: York Sun [mailto:yorksun@freescale.com] Sent: Thursday, November 05, 2015 12:27 AM To: Kushwaha Prabhakar-B32579 prabhakar@freescale.com; u- boot@lists.denx.de Subject: Re: [PATCH][v2] armv8: ls2085a: Add workaround of errata A009635
On 11/03/2015 11:24 PM, Prabhakar Kushwaha wrote:
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
Chages for v2: Updated description
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);
Why do you need a variable to override the calculation?
Following needs to be supported as part of errata workaround 1. Ability to modify platform clock value to increase time interval 2. Disable workaround in platform clock 0
As per Errata workaround, "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."
- ulong interval_mhz = get_bus_freq(0) / (1000 * 1000);
Please add a comment here to explain what the interval does and why it is calculated this way.
Sure,
--PK

On 11/04/2015 07:58 PM, Kushwaha Prabhakar-B32579 wrote:
-----Original Message----- From: York Sun [mailto:yorksun@freescale.com] Sent: Thursday, November 05, 2015 12:27 AM To: Kushwaha Prabhakar-B32579 prabhakar@freescale.com; u- boot@lists.denx.de Subject: Re: [PATCH][v2] armv8: ls2085a: Add workaround of errata A009635
On 11/03/2015 11:24 PM, Prabhakar Kushwaha wrote:
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
Chages for v2: Updated description
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);
Why do you need a variable to override the calculation?
Following needs to be supported as part of errata workaround
- Ability to modify platform clock value to increase time interval
- Disable workaround in platform clock 0
As per Errata workaround, "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."
This is taken care of by the formula. Is there any need to adjust the time interval? If you do, you are risking of running too fast or too slow. If setting the variable as 0, does it have the same effect as not running this workaround? If this is a debug technique, please remove if not required by the workaround. If you really want to support override, please add a comment inline and in commit message.
- ulong interval_mhz = get_bus_freq(0) / (1000 * 1000);
Please add a comment here to explain what the interval does and why it is calculated this way.
Sure,
York

-----Original Message----- From: York Sun [mailto:yorksun@freescale.com] Sent: Thursday, November 05, 2015 9:38 AM To: Kushwaha Prabhakar-B32579 prabhakar@freescale.com; u- boot@lists.denx.de Subject: Re: [PATCH][v2] armv8: ls2085a: Add workaround of errata A009635
On 11/04/2015 07:58 PM, Kushwaha Prabhakar-B32579 wrote:
-----Original Message----- From: York Sun [mailto:yorksun@freescale.com] Sent: Thursday, November 05, 2015 12:27 AM To: Kushwaha Prabhakar-B32579 prabhakar@freescale.com; u- boot@lists.denx.de Subject: Re: [PATCH][v2] armv8: ls2085a: Add workaround of errata A009635
On 11/03/2015 11:24 PM, Prabhakar Kushwaha wrote:
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
Chages for v2: Updated description
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);
Why do you need a variable to override the calculation?
Following needs to be supported as part of errata workaround 1. Ability to modify platform clock value to increase time interval 2. Disable workaround in platform clock 0
As per Errata workaround, "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."
This is taken care of by the formula. Is there any need to adjust the time interval? If you do, you are risking of running too fast or too slow.
Yes, customer may like to increase or decrease the time interval to fine tune the system behavior.
If setting the variable as 0, does it have the same effect as not running this workaround?
Yes, setting 0 == Not running WA. I verified it.
If this is a debug technique, please remove if not required by the workaround.
This problem occur when core clock is > 2.5.x of platform clock. If anyone using core clock < 2.5x of platform clock, this workaround is not required.
If you really want to support override, please add a comment inline and in commit message.
OK
- ulong interval_mhz = get_bus_freq(0) / (1000 * 1000);
Please add a comment here to explain what the interval does and why it is calculated this way.
Sure,
York
participants (3)
-
Kushwaha Prabhakar
-
Prabhakar Kushwaha
-
York Sun