summaryrefslogtreecommitdiffstats
path: root/sys/powerpc
diff options
context:
space:
mode:
authorjhibbits <jhibbits@FreeBSD.org>2016-01-01 02:47:40 +0000
committerjhibbits <jhibbits@FreeBSD.org>2016-01-01 02:47:40 +0000
commite13a7f7a36d05e1e0c6d72b3d0c4cd76bf28ffb1 (patch)
treeb6d22b953c5f3ecd118777f5ad688cc08248ddef /sys/powerpc
parentb8e70bf7efef670381034d0f5a8ded060def0121 (diff)
downloadFreeBSD-src-e13a7f7a36d05e1e0c6d72b3d0c4cd76bf28ffb1.zip
FreeBSD-src-e13a7f7a36d05e1e0c6d72b3d0c4cd76bf28ffb1.tar.gz
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.
Diffstat (limited to 'sys/powerpc')
-rw-r--r--sys/powerpc/include/platform.h2
-rw-r--r--sys/powerpc/mpc85xx/mpc85xx.h6
-rw-r--r--sys/powerpc/mpc85xx/platform_mpc85xx.c37
-rw-r--r--sys/powerpc/powerpc/cpu.c13
-rw-r--r--sys/powerpc/powerpc/platform.c14
-rw-r--r--sys/powerpc/powerpc/platform_if.m24
6 files changed, 84 insertions, 12 deletions
diff --git a/sys/powerpc/include/platform.h b/sys/powerpc/include/platform.h
index 28f83cc..8c92e26 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 ac8b8ff..e806225 100644
--- a/sys/powerpc/mpc85xx/mpc85xx.h
+++ b/sys/powerpc/mpc85xx/mpc85xx.h
@@ -132,6 +132,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.
*/
uint32_t ccsr_read4(uintptr_t addr);
diff --git a/sys/powerpc/mpc85xx/platform_mpc85xx.c b/sys/powerpc/mpc85xx/platform_mpc85xx.c
index c84561d..3a36e6d 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 43190ae..1d68531 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 8168758..b29ad92 100644
--- a/sys/powerpc/powerpc/platform.c
+++ b/sys/powerpc/powerpc/platform.c
@@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$");
#include <sys/lock.h>
#include <sys/ktr.h>
#include <sys/mutex.h>
+#include <sys/proc.h>
#include <sys/systm.h>
#include <sys/smp.h>
#include <sys/sysctl.h>
@@ -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 dfa2be1..a562b32 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);
+ }
};
/**
@@ -211,6 +219,22 @@ METHOD void reset {
};
/**
+ * @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
*/
METHOD void sleep {
OpenPOWER on IntegriCloud