arm: exynos: Support cluster power off on exynos5420/5800
Subsystems (3)
PATCH 1/1 arm: exynos: Support cluster power off on exynos5420/5800
Turning off a cluster when all 4 cores of the cluster are powered off saves power significantly. Powering off the A15 L2 alone gives around 100mW in savings. Add support for powering off the A15/A7 clusters on exynos5420/5800.
The patch enables specific register bits which ensure that:
- cluster L2 will be turned on before the first man is powered up.
- last man will be turned off before the cluster L2 is turned off.
- core is powered down before powering it up.
Remove the exynos_cluster_power_control function completely as we can rely on the above mentioned bits rather than polling the cluster power status register.
---
The patch is based on Linux-next 20140618. It has been tested on an exynos5420-based chromebook using the "/dev/bL_switcher" interface as well as the script provided by Nicolas Pitre and Dave Martin [1].
Patch depends on:
[v2] ARM: EXYNOS: mcpm: Don't rely on firmware's secondary_cpu_start
[1] http://www.spinics.net/lists/linux-samsung-soc/msg31257.html
arch/arm/mach-exynos/mcpm-exynos.c | 66 ++++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 35 deletions(-)
arch/arm/mach-exynos/mcpm-exynos.c +31 -35
@@ -26,6 +26,10 @@#define EXYNOS5420_CPUS_PER_CLUSTER 4#define EXYNOS5420_NR_CLUSTERS 2 +#define EXYNOS5420_ENABLE_AUTOMATIC_CORE_DOWN BIT(9) +#define EXYNOS5420_USE_ARM_CORE_DOWN_STATE BIT(29) +#define EXYNOS5420_USE_L2_COMMON_UP_STATE BIT(30) +/* * The common v7_exit_coherency_flush API could not be used because of the * Erratum 799270 workaround. This macro is the same as the common one (in
@@ -73,36 +77,9 @@ cpu_use_count[EXYNOS5420_CPUS_PER_CLUSTER][EXYNOS5420_NR_CLUSTERS];#define exynos_cluster_unused (cluster) !exynos_cluster_usecnt(cluster) -static int exynos_cluster_power_control (unsigned int cluster,int enable) -{ -unsigned int tries =100 ; -unsigned int val; - -if (enable) { -exynos_cluster_power_up (cluster); - val =S5P_CORE_LOCAL_PWR_EN ; - }else { -exynos_cluster_power_down (cluster); - val =0 ; - } - -/* Wait until cluster power control is applied */ -while (tries--) { -if (exynos_cluster_power_state (cluster) == val) -return 0 ; - -cpu_relax (); - } -pr_debug ("timed out waiting for cluster %u to power %s\n" , cluster, - enable ?"on" :"off" ); - -return -ETIMEDOUT ; -} -static int exynos_power_up (unsigned int cpu,unsigned int cluster) {unsigned int cpunr = cpu + (cluster *EXYNOS5420_CPUS_PER_CLUSTER ); -int err =0 ;pr_debug ("%s: cpu %u cluster %u\n" , __func__, cpu, cluster); if (cpu >= EXYNOS5420_CPUS_PER_CLUSTER ||
@@ -126,12 +103,9 @@ static int exynos_power_up(unsigned int cpu, unsigned int cluster)* cores. */ if (was_cluster_down) - err =exynos_cluster_power_control (cluster,1 ); +exynos_cluster_power_up (cluster); -if (!err) -exynos_cpu_power_up (cpunr); -else -exynos_cluster_power_control (cluster,0 ); +exynos_cpu_power_up (cpunr); }else if (cpu_use_count[cpu][cluster] !=2 ) {/* * The only possible values are:
@@ -147,7 +121,7 @@ static int exynos_power_up(unsigned int cpu, unsigned int cluster)arch_spin_unlock (&exynos_mcpm_lock);local_irq_enable (); -return err; +return 0 ; }/*
@@ -178,9 +152,10 @@ static void exynos_power_down(void)if (cpu_use_count[cpu][cluster] ==0 ) {exynos_cpu_power_down (cpunr); -if (exynos_cluster_unused (cluster)) -/* TODO: Turn off the cluster here to save power. */ +if (exynos_cluster_unused (cluster)) { +exynos_cluster_power_down (cluster); last_man = true; + } }else if (cpu_use_count[cpu][cluster] ==1 ) {/* * A power_up request went ahead of us.
@@ -299,6 +274,7 @@ static int __init exynos_mcpm_init(void) {struct device_node *node;void __iomem *ns_sram_base_addr; +unsigned int value, i;int ret; node =of_find_matching_node (NULL , exynos_dt_mcpm_match);
@@ -342,6 +318,26 @@ static int __init exynos_mcpm_init(void)pr_info ("Exynos MCPM support installed\n" );/* +* On Exynos5420/5800 for the A15 and A7 clusters: +* +* EXYNOS5420_ENABLE_AUTOMATIC_CORE_DOWN ensures that all the cores +* in a cluster are turned off before turning off the cluster L2. +* +* EXYNOS5420_USE_ARM_CORE_DOWN_STATE ensures that a cores is powered +* off before waking it up. +* +* EXYNOS5420_USE_L2_COMMON_UP_STATE ensures that cluster L2 will be +* turned on before the first man is powered up. +*/ +for (i =0 ; i <EXYNOS5420_NR_CLUSTERS ; i++) { + value =__raw_readl (EXYNOS_COMMON_CONFIGURATION (i) +0x8 ); + value |=EXYNOS5420_ENABLE_AUTOMATIC_CORE_DOWN | +EXYNOS5420_USE_ARM_CORE_DOWN_STATE | +EXYNOS5420_USE_L2_COMMON_UP_STATE ; +__raw_writel (value,EXYNOS_COMMON_CONFIGURATION (i) +0x8 ); + } + +/* * U-Boot SPL is hardcoded to jump to the start of ns_sram_base_addr * as part of secondary_cpu_start(). Let's redirect it to the * mcpm_entry_point().
Signature · 1 line
2.0.0
PATCH 1/1 arm: exynos: Support cluster power off on exynos5420/5800
Quoted 10 lines · Abhilash Kesavan
Turning off a cluster when all 4 cores of the cluster are powered off saves power significantly. Powering off the A15 L2 alone gives around 100mW in savings. Add support for powering off the A15/A7 clusters on exynos5420/5800.
The patch enables specific register bits which ensure that:
- cluster L2 will be turned on before the first man is powered up.
- last man will be turned off before the cluster L2 is turned off.
- core is powered down before powering it up.
Quoted 5 lines
Remove the
exynos_cluster_power_controlfunction completely as we can rely on the above mentioned bits rather than polling the cluster power status register.Signed-off-by Abhilash Kesavan <[email protected]>
Minor nit below:
Quoted 11 lines
arch/arm/mach-exynos/mcpm-exynos.c +7
-0@@ -342,6 +318,26 @@ static int __init exynos_mcpm_init(void)pr_info ("Exynos MCPM support installed\n" );/* +* On Exynos5420/5800 for the A15 and A7 clusters: +* +* EXYNOS5420_ENABLE_AUTOMATIC_CORE_DOWN ensures that all the cores +* in a cluster are turned off before turning off the cluster L2. +* +* EXYNOS5420_USE_ARM_CORE_DOWN_STATE ensures that a cores is powered +* off before waking it up.
arch/arm/mach-exynos/mcpm-exynos.c static int __init exynos_mcpm_init(void) · line 337
Quoted 10 lines
arch/arm/mach-exynos/mcpm-exynos.c +10
-0+* +* EXYNOS5420_USE_L2_COMMON_UP_STATE ensures that cluster L2 will be +* turned on before the first man is powered up. +*/ +for (i =0 ; i <EXYNOS5420_NR_CLUSTERS ; i++) { + value =__raw_readl (EXYNOS_COMMON_CONFIGURATION (i) +0x8 ); + value |=EXYNOS5420_ENABLE_AUTOMATIC_CORE_DOWN | +EXYNOS5420_USE_ARM_CORE_DOWN_STATE | +EXYNOS5420_USE_L2_COMMON_UP_STATE ; +__raw_writel (value,EXYNOS_COMMON_CONFIGURATION (i) +0x8 );
Surely you can add another define in mach-exynos/regs-pmu.h to better identify this register instead of EXYNOS_COMMON_CONFIGURATION()+8 ?
After that, you may add:
Nicolas
PATCH 1/1 arm: exynos: Support cluster power off on exynos5420/5800
Hi Nicolas,
Quoted 45 lines · Nicolas Pitre
Quoted 10 lines · Abhilash Kesavan
Turning off a cluster when all 4 cores of the cluster are powered off saves power significantly. Powering off the A15 L2 alone gives around 100mW in savings. Add support for powering off the A15/A7 clusters on exynos5420/5800.
The patch enables specific register bits which ensure that:
- cluster L2 will be turned on before the first man is powered up.
- last man will be turned off before the cluster L2 is turned off.
- core is powered down before powering it up.Quoted 5 lines
Remove the
exynos_cluster_power_controlfunction completely as we can rely on the above mentioned bits rather than polling the cluster power status register.Signed-off-by Abhilash Kesavan <[email protected]>Minor nit below:
Quoted 11 lines
arch/arm/mach-exynos/mcpm-exynos.c +7
-0@@ -342,6 +318,26 @@ static int __init exynos_mcpm_init(void)pr_info ("Exynos MCPM support installed\n" );/* +* On Exynos5420/5800 for the A15 and A7 clusters: +* +* EXYNOS5420_ENABLE_AUTOMATIC_CORE_DOWN ensures that all the cores +* in a cluster are turned off before turning off the cluster L2. +* +* EXYNOS5420_USE_ARM_CORE_DOWN_STATE ensures that a cores is powered +* off before waking it up. arch/arm/mach-exynos/mcpm-exynos.c static int __init exynos_mcpm_init(void) · line 337
Quoted 10 lines
arch/arm/mach-exynos/mcpm-exynos.c +10
-0+* +* EXYNOS5420_USE_L2_COMMON_UP_STATE ensures that cluster L2 will be +* turned on before the first man is powered up. +*/ +for (i =0 ; i <EXYNOS5420_NR_CLUSTERS ; i++) { + value =__raw_readl (EXYNOS_COMMON_CONFIGURATION (i) +0x8 ); + value |=EXYNOS5420_ENABLE_AUTOMATIC_CORE_DOWN | +EXYNOS5420_USE_ARM_CORE_DOWN_STATE | +EXYNOS5420_USE_L2_COMMON_UP_STATE ; +__raw_writel (value,EXYNOS_COMMON_CONFIGURATION (i) +0x8 );Surely you can add another define in
mach-exynos/regs-pmu.hto better identify this register instead of EXYNOS_COMMON_CONFIGURATION()+8 ?
Quoted 3 lines
After that, you may add:
Acked-by Nicolas Pitre <[email protected]>
Thanks. Will fix and post v2 with your ack.
Regards,
Abhilash
Quoted 3 lines
Nicolas
PATCH v2 1/1 arm: exynos: Support cluster power off on exynos5420/5800
In reply to Abhilash KesavanTurning off a cluster when all 4 cores of the cluster are powered off saves power significantly. Powering off the A15 L2 alone gives around 100mW in savings. Add support for powering off the A15/A7 clusters on exynos5420/5800.
The patch enables specific register bits which ensure that:
- cluster L2 will be turned on before the first man is powered up.
- last man will be turned off before the cluster L2 is turned off.
- core is powered down before powering it up.
Remove the exynos_cluster_power_control function completely as we can rely on the above mentioned bits rather than polling the cluster power status register.
---
Change in v2:
Added a macro for the COMMON_OPTION register and used it in the MCPM back-end.
The patch is based on Linux-next 20140619. It has been tested on an exynos5420-based chromebook using the "/dev/bL_switcher" interface as well as the script provided by Nicolas Pitre and Dave Martin [1].
Patch depends on:
[v2] ARM: EXYNOS: mcpm: Don't rely on firmware's secondary_cpu_start
[1] http://www.spinics.net/lists/linux-samsung-soc/msg31257.html
arch/arm/mach-exynos/mcpm-exynos.c | 66 +++++++++++++++++------------------- arch/arm/mach-exynos/regs-pmu.h | 2 ++ 2 files changed, 33 insertions(+), 35 deletions(-)
arch/arm/mach-exynos/mcpm-exynos.c +31 -35
@@ -26,6 +26,10 @@#define EXYNOS5420_CPUS_PER_CLUSTER 4#define EXYNOS5420_NR_CLUSTERS 2 +#define EXYNOS5420_ENABLE_AUTOMATIC_CORE_DOWN BIT(9) +#define EXYNOS5420_USE_ARM_CORE_DOWN_STATE BIT(29) +#define EXYNOS5420_USE_L2_COMMON_UP_STATE BIT(30) +/* * The common v7_exit_coherency_flush API could not be used because of the * Erratum 799270 workaround. This macro is the same as the common one (in
@@ -73,36 +77,9 @@ cpu_use_count[EXYNOS5420_CPUS_PER_CLUSTER][EXYNOS5420_NR_CLUSTERS];#define exynos_cluster_unused (cluster) !exynos_cluster_usecnt(cluster) -static int exynos_cluster_power_control (unsigned int cluster,int enable) -{ -unsigned int tries =100 ; -unsigned int val; - -if (enable) { -exynos_cluster_power_up (cluster); - val =S5P_CORE_LOCAL_PWR_EN ; - }else { -exynos_cluster_power_down (cluster); - val =0 ; - } - -/* Wait until cluster power control is applied */ -while (tries--) { -if (exynos_cluster_power_state (cluster) == val) -return 0 ; - -cpu_relax (); - } -pr_debug ("timed out waiting for cluster %u to power %s\n" , cluster, - enable ?"on" :"off" ); - -return -ETIMEDOUT ; -} -static int exynos_power_up (unsigned int cpu,unsigned int cluster) {unsigned int cpunr = cpu + (cluster *EXYNOS5420_CPUS_PER_CLUSTER ); -int err =0 ;pr_debug ("%s: cpu %u cluster %u\n" , __func__, cpu, cluster); if (cpu >= EXYNOS5420_CPUS_PER_CLUSTER ||
@@ -126,12 +103,9 @@ static int exynos_power_up(unsigned int cpu, unsigned int cluster)* cores. */ if (was_cluster_down) - err =exynos_cluster_power_control (cluster,1 ); +exynos_cluster_power_up (cluster); -if (!err) -exynos_cpu_power_up (cpunr); -else -exynos_cluster_power_control (cluster,0 ); +exynos_cpu_power_up (cpunr); }else if (cpu_use_count[cpu][cluster] !=2 ) {/* * The only possible values are:
@@ -147,7 +121,7 @@ static int exynos_power_up(unsigned int cpu, unsigned int cluster)arch_spin_unlock (&exynos_mcpm_lock);local_irq_enable (); -return err; +return 0 ; }/*
@@ -178,9 +152,10 @@ static void exynos_power_down(void)if (cpu_use_count[cpu][cluster] ==0 ) {exynos_cpu_power_down (cpunr); -if (exynos_cluster_unused (cluster)) -/* TODO: Turn off the cluster here to save power. */ +if (exynos_cluster_unused (cluster)) { +exynos_cluster_power_down (cluster); last_man = true; + } }else if (cpu_use_count[cpu][cluster] ==1 ) {/* * A power_up request went ahead of us.
@@ -299,6 +274,7 @@ static int __init exynos_mcpm_init(void) {struct device_node *node;void __iomem *ns_sram_base_addr; +unsigned int value, i;int ret; node =of_find_matching_node (NULL , exynos_dt_mcpm_match);
@@ -342,6 +318,26 @@ static int __init exynos_mcpm_init(void)pr_info ("Exynos MCPM support installed\n" );/* +* On Exynos5420/5800 for the A15 and A7 clusters: +* +* EXYNOS5420_ENABLE_AUTOMATIC_CORE_DOWN ensures that all the cores +* in a cluster are turned off before turning off the cluster L2. +* +* EXYNOS5420_USE_ARM_CORE_DOWN_STATE ensures that a cores is powered +* off before waking it up. +* +* EXYNOS5420_USE_L2_COMMON_UP_STATE ensures that cluster L2 will be +* turned on before the first man is powered up. +*/ +for (i =0 ; i <EXYNOS5420_NR_CLUSTERS ; i++) { + value =__raw_readl (EXYNOS_COMMON_OPTION (i)); + value |=EXYNOS5420_ENABLE_AUTOMATIC_CORE_DOWN | +EXYNOS5420_USE_ARM_CORE_DOWN_STATE | +EXYNOS5420_USE_L2_COMMON_UP_STATE ; +__raw_writel (value,EXYNOS_COMMON_OPTION (i)); + } + +/* * U-Boot SPL is hardcoded to jump to the start of ns_sram_base_addr * as part of secondary_cpu_start(). Let's redirect it to the * mcpm_entry_point().
arch/arm/mach-exynos/regs-pmu.h +2 -0
@@ -117,6 +117,8 @@ (EXYNOS_ARM_COMMON_CONFIGURATION + (0x80 * (_nr)))#define EXYNOS_COMMON_STATUS (_nr) \ (EXYNOS_COMMON_CONFIGURATION(_nr) + 0x4) +#define EXYNOS_COMMON_OPTION (_nr) \ + (EXYNOS_COMMON_CONFIGURATION(_nr) + 0x8)#define S5P_PAD_RET_MAUDIO_OPTION S5P_PMUREG(0x3028)#define S5P_PAD_RET_GPIO_OPTION S5P_PMUREG(0x3108)
Signature · 1 line
1.7.9.5
PATCH v2 1/1 arm: exynos: Support cluster power off on exynos5420/5800
Quoted 21 lines · Abhilash Kesavan
Turning off a cluster when all 4 cores of the cluster are powered off saves power significantly. Powering off the A15 L2 alone gives around 100mW in savings. Add support for powering off the A15/A7 clusters on exynos5420/5800.
The patch enables specific register bits which ensure that:
- cluster L2 will be turned on before the first man is powered up.
- last man will be turned off before the cluster L2 is turned off.
- core is powered down before powering it up.Remove the
exynos_cluster_power_controlfunction completely as we can rely on the above mentioned bits rather than polling the cluster power status register.Signed-off-by Abhilash Kesavan <[email protected]>Acked-by Nicolas Pitre <[email protected]>---
Change in v2:
Added a macro for theCOMMON_OPTIONregister and used it in the MCPM back-end.
Quoted 8 lines
The patch is based on Linux-next 20140619. It has been tested on an exynos5420-based chromebook using the "
/dev/bL_switcher" interface as well as the script provided by Nicolas Pitre and Dave Martin [1].Patch depends on:
[v2] ARM: EXYNOS: mcpm: Don't rely on firmware'ssecondary_cpu_start[1] http://www.spinics.net/lists/linux-samsung-soc/msg31257.html
Tested on exynos5800/Chromebook2 along with the dependency patch and using the script from Dave and Nico.
Kevin
Kukjin Kim
AppliedPATCH v2 1/1 arm: exynos: Support cluster power off on exynos5420/5800
Quoted 3 lines · Kevin Hilman
Abhilash Kesavan <[email protected]> writes:
Hi,
Quoted 28 lines
Quoted 28 lines
Turning off a cluster when all 4 cores of the cluster are powered off saves power significantly. Powering off the A15 L2 alone gives around 100mW in savings. Add support for powering off the A15/A7 clusters on exynos5420/5800.
The patch enables specific register bits which ensure that:
- cluster L2 will be turned on before the first man is powered up.
- last man will be turned off before the cluster L2 is turned off.
- core is powered down before powering it up.Remove the
exynos_cluster_power_controlfunction completely as we can rely on the above mentioned bits rather than polling the cluster power status register.Signed-off-by Abhilash Kesavan <[email protected]>Acked-by Nicolas Pitre <[email protected]>---
Change in v2:
Added a macro for theCOMMON_OPTIONregister and used it in the MCPM back-end.The patch is based on Linux-next 20140619. It has been tested on an exynos5420-based chromebook using the "
/dev/bL_switcher" interface as well as the script provided by Nicolas Pitre and Dave Martin [1].Patch depends on:
[v2] ARM: EXYNOS: mcpm: Don't rely on firmware'ssecondary_cpu_start
Quoted 7 lines
Quoted 1 line
[1] http://www.spinics.net/lists/linux-samsung-soc/msg31257.html
Tested on exynos5800/Chromebook2 along with the dependency patch and using the script from Dave and Nico.
Tested-by Kevin Hilman <[email protected]>
Kevin, thanks for your test on the board ;-)
Applied into samsung tree.
Thanks,
Kukjin