summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMikhail Kalashnikov <iuncuim@gmail.com>2023-03-27 18:36:14 +0300
committerAndre Przywara <andre.przywara@arm.com>2023-04-26 17:45:29 +0100
commit018c1d878fbfd696ebeda52b5188e4658b87bf75 (patch)
tree6c525fbf5cd6c30ec87757548d14921cc355b09c
parentfbde260b11171f0f67afbc631e22fe26366ff448 (diff)
downloadarm-trusted-firmware-018c1d878fbfd696ebeda52b5188e4658b87bf75.tar.gz
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>
-rw-r--r--docs/plat/allwinner.rst2
-rw-r--r--plat/allwinner/common/sunxi_cpu_ops.c95
-rw-r--r--plat/allwinner/common/sunxi_pm.c20
3 files changed, 87 insertions, 30 deletions
diff --git a/docs/plat/allwinner.rst b/docs/plat/allwinner.rst
index 3e9ce511f..8e967dcde 100644
--- a/docs/plat/allwinner.rst
+++ b/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 |
+------+-------------------+
diff --git a/plat/allwinner/common/sunxi_cpu_ops.c b/plat/allwinner/common/sunxi_cpu_ops.c
index 46e7090ab..30841e2ea 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)
@@ -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)
diff --git a/plat/allwinner/common/sunxi_pm.c b/plat/allwinner/common/sunxi_pm.c
index 3772b4a57..ebc406b91 100644
--- a/plat/allwinner/common/sunxi_pm.c
+++ b/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) {