diff options
Diffstat (limited to 'plat/allwinner/common/sunxi_cpu_ops.c')
-rw-r--r-- | plat/allwinner/common/sunxi_cpu_ops.c | 95 |
1 files changed, 70 insertions, 25 deletions
diff --git a/plat/allwinner/common/sunxi_cpu_ops.c b/plat/allwinner/common/sunxi_cpu_ops.c index 420b507abe..30841e2eab 100644 --- a/plat/allwinner/common/sunxi_cpu_ops.c +++ b/plat/allwinner/common/sunxi_cpu_ops.c @@ -19,6 +19,12 @@ #include <sunxi_mmap.h> #include <sunxi_private.h> +#ifndef SUNXI_C0_CPU_CTRL_REG +#define SUNXI_C0_CPU_CTRL_REG(n) 0 +#define SUNXI_CPU_UNK_REG(n) 0 +#define SUNXI_CPU_CTRL_REG(n) 0 +#endif + static void sunxi_cpu_disable_power(unsigned int cluster, unsigned int core) { if (mmio_read_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core)) == 0xff) @@ -42,6 +48,7 @@ static void sunxi_cpu_enable_power(unsigned int cluster, unsigned int core) mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0xe0); mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0x80); mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0x00); + udelay(1); } /* We can't turn ourself off like this, but it works for other cores. */ @@ -52,15 +59,30 @@ static void sunxi_cpu_off(u_register_t mpidr) VERBOSE("PSCI: Powering off cluster %d core %d\n", cluster, core); - /* Deassert DBGPWRDUP */ - mmio_clrbits_32(SUNXI_CPUCFG_DBG_REG0, BIT(core)); - /* Activate the core output clamps, but not for core 0. */ - if (core != 0) - mmio_setbits_32(SUNXI_POWEROFF_GATING_REG(cluster), BIT(core)); - /* Assert CPU power-on reset */ - mmio_clrbits_32(SUNXI_POWERON_RST_REG(cluster), BIT(core)); - /* Remove power from the CPU */ - sunxi_cpu_disable_power(cluster, core); + if (sunxi_cpucfg_has_per_cluster_regs()) { + /* Deassert DBGPWRDUP */ + mmio_clrbits_32(SUNXI_CPUCFG_DBG_REG0, BIT(core)); + /* Activate the core output clamps, but not for core 0. */ + if (core != 0) { + mmio_setbits_32(SUNXI_POWEROFF_GATING_REG(cluster), + BIT(core)); + } + /* Assert CPU power-on reset */ + mmio_clrbits_32(SUNXI_POWERON_RST_REG(cluster), BIT(core)); + /* Remove power from the CPU */ + sunxi_cpu_disable_power(cluster, core); + } else { + /* power down(?) debug core */ + mmio_clrbits_32(SUNXI_C0_CPU_CTRL_REG(core), BIT(8)); + /* ??? Activate the core output clamps, but not for core 0 */ + if (core != 0) { + mmio_setbits_32(SUNXI_CPU_UNK_REG(core), BIT(1)); + } + /* ??? Assert CPU power-on reset ??? */ + mmio_clrbits_32(SUNXI_CPU_UNK_REG(core), BIT(0)); + /* Remove power from the CPU */ + sunxi_cpu_disable_power(cluster, core); + } } void sunxi_cpu_on(u_register_t mpidr) @@ -70,22 +92,45 @@ void sunxi_cpu_on(u_register_t mpidr) VERBOSE("PSCI: Powering on cluster %d core %d\n", cluster, core); - /* Assert CPU core reset */ - mmio_clrbits_32(SUNXI_CPUCFG_RST_CTRL_REG(cluster), BIT(core)); - /* Assert CPU power-on reset */ - mmio_clrbits_32(SUNXI_POWERON_RST_REG(cluster), BIT(core)); - /* Set CPU to start in AArch64 mode */ - mmio_setbits_32(SUNXI_CPUCFG_CLS_CTRL_REG0(cluster), BIT(24 + core)); - /* Apply power to the CPU */ - sunxi_cpu_enable_power(cluster, core); - /* Release the core output clamps */ - mmio_clrbits_32(SUNXI_POWEROFF_GATING_REG(cluster), BIT(core)); - /* Deassert CPU power-on reset */ - mmio_setbits_32(SUNXI_POWERON_RST_REG(cluster), BIT(core)); - /* Deassert CPU core reset */ - mmio_setbits_32(SUNXI_CPUCFG_RST_CTRL_REG(cluster), BIT(core)); - /* Assert DBGPWRDUP */ - mmio_setbits_32(SUNXI_CPUCFG_DBG_REG0, BIT(core)); + if (sunxi_cpucfg_has_per_cluster_regs()) { + /* Assert CPU core reset */ + mmio_clrbits_32(SUNXI_CPUCFG_RST_CTRL_REG(cluster), BIT(core)); + /* Assert CPU power-on reset */ + mmio_clrbits_32(SUNXI_POWERON_RST_REG(cluster), BIT(core)); + /* Set CPU to start in AArch64 mode */ + mmio_setbits_32(SUNXI_AA64nAA32_REG(cluster), + BIT(SUNXI_AA64nAA32_OFFSET + core)); + /* Apply power to the CPU */ + sunxi_cpu_enable_power(cluster, core); + /* Release the core output clamps */ + mmio_clrbits_32(SUNXI_POWEROFF_GATING_REG(cluster), BIT(core)); + /* Deassert CPU power-on reset */ + mmio_setbits_32(SUNXI_POWERON_RST_REG(cluster), BIT(core)); + /* Deassert CPU core reset */ + mmio_setbits_32(SUNXI_CPUCFG_RST_CTRL_REG(cluster), BIT(core)); + /* Assert DBGPWRDUP */ + mmio_setbits_32(SUNXI_CPUCFG_DBG_REG0, BIT(core)); + } else { + /* Assert CPU core reset */ + mmio_clrbits_32(SUNXI_C0_CPU_CTRL_REG(core), BIT(0)); + /* ??? Assert CPU power-on reset ??? */ + mmio_clrbits_32(SUNXI_CPU_UNK_REG(core), BIT(0)); + + /* Set CPU to start in AArch64 mode */ + mmio_setbits_32(SUNXI_CPU_CTRL_REG(core), BIT(0)); + + /* Apply power to the CPU */ + sunxi_cpu_enable_power(cluster, core); + + /* ??? Release the core output clamps ??? */ + mmio_clrbits_32(SUNXI_CPU_UNK_REG(core), BIT(1)); + /* ??? Deassert CPU power-on reset ??? */ + mmio_setbits_32(SUNXI_CPU_UNK_REG(core), BIT(0)); + /* Deassert CPU core reset */ + mmio_setbits_32(SUNXI_C0_CPU_CTRL_REG(core), BIT(0)); + /* power up(?) debug core */ + mmio_setbits_32(SUNXI_C0_CPU_CTRL_REG(core), BIT(8)); + } } void sunxi_cpu_power_off_others(void) |