From 637f34cb64781c450cab323d85d5307a4d7f9349 Mon Sep 17 00:00:00 2001 From: Justin Hibbits Date: Fri, 1 Jan 2016 02:47:40 +0000 Subject: [PATCH] Extend idle support for newer Book-E cores. Newer Book-E cores (e500mc, e5500, e6500) do not support the WE bit in the MSR, and instead delegate CPU idling to the SoC. Perhaps in the future the QORIQ_DPAA option for the mpc85xx platform will become a subclass, which will eliminate most of the #ifdef's. --- sys/powerpc/include/platform.h | 2 ++ sys/powerpc/mpc85xx/mpc85xx.h | 6 +++++ sys/powerpc/mpc85xx/platform_mpc85xx.c | 37 ++++++++++++++++++++++++++ sys/powerpc/powerpc/cpu.c | 13 +-------- sys/powerpc/powerpc/platform.c | 14 ++++++++++ sys/powerpc/powerpc/platform_if.m | 24 +++++++++++++++++ 6 files changed, 84 insertions(+), 12 deletions(-) diff --git a/sys/powerpc/include/platform.h b/sys/powerpc/include/platform.h index 28f83ccd9f6..8c92e26221a 100644 --- a/sys/powerpc/include/platform.h +++ b/sys/powerpc/include/platform.h @@ -57,6 +57,8 @@ void platform_smp_ap_init(void); const char *installed_platform(void); void platform_probe_and_attach(void); +void platform_cpu_idle(int); + void platform_sleep(void); #endif /* _MACHINE_PLATFORM_H_ */ diff --git a/sys/powerpc/mpc85xx/mpc85xx.h b/sys/powerpc/mpc85xx/mpc85xx.h index ac8b8ff8ba5..e806225618e 100644 --- a/sys/powerpc/mpc85xx/mpc85xx.h +++ b/sys/powerpc/mpc85xx/mpc85xx.h @@ -131,6 +131,12 @@ extern vm_offset_t ccsrbar_va; */ #define OCP85XX_RSTCR (CCSRBAR_VA + 0xe00b0) +/* + * Run Control/Power Management Registers. + */ +#define OCP85XX_RCPM_CDOZSR (CCSRBAR_VA + 0xe2004) +#define OCP85XX_RCPM_CDOZCR (CCSRBAR_VA + 0xe200c) + /* * Prototypes. */ diff --git a/sys/powerpc/mpc85xx/platform_mpc85xx.c b/sys/powerpc/mpc85xx/platform_mpc85xx.c index c84561d09c7..3a36e6dbbe7 100644 --- a/sys/powerpc/mpc85xx/platform_mpc85xx.c +++ b/sys/powerpc/mpc85xx/platform_mpc85xx.c @@ -80,6 +80,8 @@ static int mpc85xx_smp_first_cpu(platform_t, struct cpuref *cpuref); static int mpc85xx_smp_next_cpu(platform_t, struct cpuref *cpuref); static int mpc85xx_smp_get_bsp(platform_t, struct cpuref *cpuref); static int mpc85xx_smp_start_cpu(platform_t, struct pcpu *cpu); +static void mpc85xx_idle(platform_t, int cpu); +static int mpc85xx_idle_wakeup(platform_t plat, int cpu); static void mpc85xx_reset(platform_t); @@ -95,6 +97,8 @@ static platform_method_t mpc85xx_methods[] = { PLATFORMMETHOD(platform_smp_start_cpu, mpc85xx_smp_start_cpu), PLATFORMMETHOD(platform_reset, mpc85xx_reset), + PLATFORMMETHOD(platform_idle, mpc85xx_idle), + PLATFORMMETHOD(platform_idle_wakeup, mpc85xx_idle_wakeup), PLATFORMMETHOD_END }; @@ -478,3 +482,36 @@ mpc85xx_reset(platform_t plat) ; } +static void +mpc85xx_idle(platform_t plat, int cpu) +{ +#ifdef QORIQ_DPAA + uint32_t reg; + + reg = ccsr_read4(OCP85XX_RCPM_CDOZCR); + ccsr_write4(OCP85XX_RCPM_CDOZCR, reg | (1 << cpu)); + ccsr_read4(OCP85XX_RCPM_CDOZCR); +#else + register_t msr; + + msr = mfmsr(); + /* Freescale E500 core RM section 6.4.1. */ + __asm __volatile("msync; mtmsr %0; isync" :: + "r" (msr | PSL_WE)); +#endif +} + +static int +mpc85xx_idle_wakeup(platform_t plat, int cpu) +{ +#ifdef QORIQ_DPAA + uint32_t reg; + + reg = ccsr_read4(OCP85XX_RCPM_CDOZCR); + ccsr_write4(OCP85XX_RCPM_CDOZCR, reg & ~(1 << cpu)); + ccsr_read4(OCP85XX_RCPM_CDOZCR); + + return (1); +#endif + return (0); +} diff --git a/sys/powerpc/powerpc/cpu.c b/sys/powerpc/powerpc/cpu.c index 43190ae98a4..1d685315b49 100644 --- a/sys/powerpc/powerpc/cpu.c +++ b/sys/powerpc/powerpc/cpu.c @@ -607,12 +607,6 @@ cpu_idle(int busy) busy, curcpu); } -int -cpu_idle_wakeup(int cpu) -{ - return (0); -} - static void cpu_idle_60x(sbintime_t sbt) { @@ -651,14 +645,9 @@ cpu_idle_60x(sbintime_t sbt) static void cpu_idle_booke(sbintime_t sbt) { - register_t msr; - - msr = mfmsr(); #ifdef E500 - /* Freescale E500 core RM section 6.4.1. */ - __asm __volatile("msync; mtmsr %0; isync" :: - "r" (msr | PSL_WE)); + platform_cpu_idle(PCPU_GET(cpuid)); #endif } diff --git a/sys/powerpc/powerpc/platform.c b/sys/powerpc/powerpc/platform.c index 8168758f885..b29ad92eb62 100644 --- a/sys/powerpc/powerpc/platform.c +++ b/sys/powerpc/powerpc/platform.c @@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -252,6 +253,19 @@ cpu_reset() PLATFORM_RESET(plat_obj); } +int +cpu_idle_wakeup(int cpu) +{ + return (PLATFORM_IDLE_WAKEUP(plat_obj, cpu)); +} + +void +platform_cpu_idle(int cpu) +{ + + PLATFORM_IDLE(plat_obj, cpu); +} + /* * Platform install routines. Highest priority wins, using the same * algorithm as bus attachment. diff --git a/sys/powerpc/powerpc/platform_if.m b/sys/powerpc/powerpc/platform_if.m index dfa2be1baa6..a562b321a92 100644 --- a/sys/powerpc/powerpc/platform_if.m +++ b/sys/powerpc/powerpc/platform_if.m @@ -84,6 +84,14 @@ CODE { { return; } + static void platform_null_idle(platform_t plat, int cpu) + { + return; + } + static int platform_null_idle_wakeup(platform_t plat, int cpu) + { + return (0); + } }; /** @@ -210,6 +218,22 @@ METHOD void reset { platform_t _plat; }; +/** + * @brief Idle a CPU + */ +METHOD void idle { + platform_t _plat; + int _cpu; +} DEFAULT platform_null_idle; + +/** + * @brief Wake up an idle CPU + */ +METHOD int idle_wakeup { + platform_t _plat; + int _cpu; +} DEFAULT platform_null_idle_wakeup; + /** * @brief Suspend the CPU */ -- 2.45.0