Browse Source

feat(allwinner): add support for Allwinner T507 SoC

The Allwinner T507 SoC is using the same die as the H616, but in a
different package. On top of this, there is at least one different die
revision out there, which uses a different CPU cluster control block.
The same die revision has been spotted in some, but not all, H313 SoCs.

Apart from that IP block, the rest of the SoC seems the same, so we can
support them using the existing H616 port. The die revision can be
auto-detected, so there is no extra build option or knowledge needed.

Provide the deviating CPU power up/down sequence for the die variant.
The new IP block uses per-core instead of per-cluster registers, but
follows the same pattern otherwise.

Since the CPU ops code is shared among all Allwinner SoCs, we need to
dummy-define the new register names for the older SoCs. The actual new
code is guarded by a predicate function, that is hard coded to return
true on the other SoCs. Since this is a static inline function in a
header file, the compiler will optimise away the unneeded branch there,
so the generated code for the other SoCs stays the same.

Change-Id: Ib5ade99d34b4ccb161ccde0e34f280ca6bd16ecd
Signed-off-by: Mikhail Kalashnikov <iuncuim@gmail.com>
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
pull/1997/head
Mikhail Kalashnikov 2 years ago
committed by Andre Przywara
parent
commit
018c1d878f
  1. 2
      docs/plat/allwinner.rst
  2. 95
      plat/allwinner/common/sunxi_cpu_ops.c
  3. 20
      plat/allwinner/common/sunxi_pm.c

2
docs/plat/allwinner.rst

@ -23,6 +23,8 @@ There is one build target per supported SoC:
+------+-------------------+
| H313 | sun50i_h616 |
+------+-------------------+
| T507 | sun50i_h616 |
+------+-------------------+
| R329 | sun50i_r329 |
+------+-------------------+

95
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)
@ -53,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)
@ -71,23 +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_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));
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)

20
plat/allwinner/common/sunxi_pm.c

@ -25,6 +25,11 @@ bool sunxi_psci_is_scpi(void)
}
#endif
#ifndef SUNXI_ALT_RVBAR_LO_REG
#define SUNXI_ALT_RVBAR_LO_REG(n) 0
#define SUNXI_ALT_RVBAR_HI_REG(n) 0
#endif
int sunxi_validate_ns_entrypoint(uintptr_t ns_entrypoint)
{
/* The non-secure entry point must be in DRAM */
@ -42,10 +47,17 @@ int plat_setup_psci_ops(uintptr_t sec_entrypoint,
/* Program all CPU entry points. */
for (unsigned int cpu = 0; cpu < PLATFORM_CORE_COUNT; ++cpu) {
mmio_write_32(SUNXI_CPUCFG_RVBAR_LO_REG(cpu),
sec_entrypoint & 0xffffffff);
mmio_write_32(SUNXI_CPUCFG_RVBAR_HI_REG(cpu),
sec_entrypoint >> 32);
if (sunxi_cpucfg_has_per_cluster_regs()) {
mmio_write_32(SUNXI_CPUCFG_RVBAR_LO_REG(cpu),
sec_entrypoint & 0xffffffff);
mmio_write_32(SUNXI_CPUCFG_RVBAR_HI_REG(cpu),
sec_entrypoint >> 32);
} else {
mmio_write_32(SUNXI_ALT_RVBAR_LO_REG(cpu),
sec_entrypoint & 0xffffffff);
mmio_write_32(SUNXI_ALT_RVBAR_HI_REG(cpu),
sec_entrypoint >> 32);
}
}
if (sunxi_set_scpi_psci_ops(psci_ops) == 0) {

Loading…
Cancel
Save