[RFC PATCH 10/17] clk: sunxi: Add support for the D1 CCU

Sam Edwards cfsworks at gmail.com
Fri May 26 22:22:29 CEST 2023


Hi folks,

On 5/26/23 13:27, Maksim Kiselev wrote:
> 
> There is a Linux patch that allows to bring up the second core.
> https://github.com/szemzoa/awboot/blob/6ea4ae4ad7a558ad952fefee1942e260aea1a69f/linux/second_core_support_in_platsmp.patch#L10
> 
> I think this could be useful for adding PSCI support for T113.

I'm a little surprised that apparently all that is necessary is to set 
the entry point and deassert reset. I've been trying essentially that so 
far with no success (entirely possible I made a mistake somewhere). 
Perhaps this patch assumes that power to the core is enabled before 
kernel boot? I haven't yet figured out what in the PRCM I need to poke 
to get power to the core, and the PRCM for this chip is not well-documented.

On 5/26/23 04:50, Andre Przywara wrote:
 > I checked the manuals, and it seems the required bits are documented,
 > but IIRC they differ from the other (much older) 32-bit parts. So it
 > would require some refactoring of the existing sunxi PSCI code to
 > accommodate the T113.

Yeah, I decided to factor out the register-manipulating bits to a 
handful of sunxi_cpu_set_* functions, which can be switched out to suit 
the specific SoC in use. psci.c is growing way too many #ifdef branches, 
so I might refactor this yet again to the "weak symbols with strong 
overrides in e.g. psci-r528.c" pattern, unless you find that pattern 
particularly distasteful.

I have my WIP diff below. Before inclusion, I'll split it into multiple 
patches (refactoring -> adding R528 support) but it's definitely not 
ready for that yet. However if you could, it would help if you checked 
my changes to cpu_sunxi_ncat2.h and squashed them into your own series 
if they look good to you.

Cheers,
Sam

---
diff --git a/arch/arm/cpu/armv7/sunxi/psci.c 
b/arch/arm/cpu/armv7/sunxi/psci.c
index e1d3638b5c..02c5c56c86 100644
--- a/arch/arm/cpu/armv7/sunxi/psci.c
+++ b/arch/arm/cpu/armv7/sunxi/psci.c
@@ -38,6 +38,8 @@
  #define SUN8I_R40_PWR_CLAMP(cpu)		(0x120 + (cpu) * 0x4)
  #define SUN8I_R40_SRAMC_SOFT_ENTRY_REG0		(0xbc)

+#define SUN8I_R528_SOFT_ENTRY			(0x1c8)
+
  static void __secure cp15_write_cntp_tval(u32 tval)
  {
  	asm volatile ("mcr p15, 0, %0, c14, c2, 0" : : "r" (tval));
@@ -125,6 +127,13 @@ static void __secure sunxi_set_entry_address(void 
*entry)
  	writel((u32)entry,
  	       SUNXI_SRAMC_BASE + SUN8I_R40_SRAMC_SOFT_ENTRY_REG0);
  }
+#elif defined CONFIG_MACH_SUN8I_R528
+/* secondary core entry address is programmed differently on R528 */
+static void __secure sunxi_set_entry_address(void *entry)
+{
+	writel((u32)entry,
+	       SUNXI_R_CPUCFG_BASE + SUN8I_R528_SOFT_ENTRY);
+}
  #else
  static void __secure sunxi_set_entry_address(void *entry)
  {
@@ -155,6 +164,10 @@ static void __secure sunxi_cpu_set_power(int cpu, 
bool on)
  			   (void *)cpucfg + SUN8I_R40_PWROFF,
  			   on, cpu);
  }
+#elif defined CONFIG_MACH_SUN8I_R528
+static void __secure sunxi_cpu_set_power(int __always_unused cpu, bool 
__always_unused on)
+{
+}
  #else /* ! CONFIG_MACH_SUN7I && ! CONFIG_MACH_SUN8I_R40 */
  static void __secure sunxi_cpu_set_power(int cpu, bool on)
  {
@@ -166,30 +179,91 @@ static void __secure sunxi_cpu_set_power(int cpu, 
bool on)
  }
  #endif /* CONFIG_MACH_SUN7I */

-void __secure sunxi_cpu_power_off(u32 cpuid)
+#ifdef CONFIG_MACH_SUN8I_R528
+#define C0_RST_CTRL	0x0000
+#define C0_CTRL_REG0	0x0010
+#define C0_CPU_STATUS	0x0080
+
+#define C0_BIT_WFI	16
+
+static void __secure sunxi_cpu_set_reset(int cpu, bool active)
+{
+	if (active)
+		clrbits_le32(SUNXI_CPUX_BASE + C0_RST_CTRL, BIT(cpu));
+	else
+		setbits_le32(SUNXI_CPUX_BASE + C0_RST_CTRL, BIT(cpu));
+}
+
+static void __secure sunxi_cpu_set_locking(int cpu, bool lock)
+{
+	/* TODO: I don't know what this is or how to do it */
+}
+
+static bool __secure sunxi_cpu_poll_wfi(int cpu)
+{
+	return !!(readl(SUNXI_CPUX_BASE + C0_CPU_STATUS) & BIT(C0_BIT_WFI + cpu));
+}
+
+static void __secure sunxi_cpu_invalidate_cache(int cpu)
+{
+	clrbits_le32(SUNXI_CPUX_BASE + C0_CTRL_REG0, BIT(cpu));
+}
+#else /* ! CONFIG_MACH_SUN8I_R528 */
+static void __secure sunxi_cpu_set_reset(int cpu, bool active)
+{
+	struct sunxi_cpucfg_reg *cpucfg =
+		(struct sunxi_cpucfg_reg *)SUNXI_CPUCFG_BASE;
+
+	writel(active ? 0b00 : 0b11, &cpucfg->cpu[cpu].rst);
+}
+
+static void __secure sunxi_cpu_set_locking(int cpu, bool lock)
  {
  	struct sunxi_cpucfg_reg *cpucfg =
  		(struct sunxi_cpucfg_reg *)SUNXI_CPUCFG_BASE;
+
+	if (lock)
+		clrbits_le32(&cpucfg->dbg_ctrl1, BIT(cpu));
+	else
+		setbits_le32(&cpucfg->dbg_ctrl1, BIT(cpu));
+}
+
+static bool __secure sunxi_cpu_poll_wfi(int cpu)
+{
+	struct sunxi_cpucfg_reg *cpucfg =
+		(struct sunxi_cpucfg_reg *)SUNXI_CPUCFG_BASE;
+
+	return !!(readl(&cpucfg->cpu[cpu].status) & BIT(2));
+}
+
+static void __secure sunxi_cpu_invalidate_cache(int cpu)
+{
+	struct sunxi_cpucfg_reg *cpucfg =
+		(struct sunxi_cpucfg_reg *)SUNXI_CPUCFG_BASE;
+
+	clrbits_le32(&cpucfg->gen_ctrl, BIT(cpu));
+}
+#endif
+
+void __secure sunxi_cpu_power_off(u32 cpuid)
+{
  	u32 cpu = cpuid & 0x3;

  	/* Wait for the core to enter WFI */
-	while (1) {
-		if (readl(&cpucfg->cpu[cpu].status) & BIT(2))
-			break;
+	while (!sunxi_cpu_poll_wfi(cpu))
  		__mdelay(1);
-	}

  	/* Assert reset on target CPU */
-	writel(0, &cpucfg->cpu[cpu].rst);
+	sunxi_cpu_set_reset(cpu, true);

  	/* Lock CPU (Disable external debug access) */
-	clrbits_le32(&cpucfg->dbg_ctrl1, BIT(cpu));
+	sunxi_cpu_set_locking(cpu, true);

  	/* Power down CPU */
  	sunxi_cpu_set_power(cpuid, false);

-	/* Unlock CPU (Disable external debug access) */
-	setbits_le32(&cpucfg->dbg_ctrl1, BIT(cpu));
+	/* Unlock CPU (Reenable external debug access) */
+	sunxi_cpu_set_locking(cpu, false);
  }

  static u32 __secure cp15_read_scr(void)
@@ -246,8 +320,6 @@ out:
  int __secure psci_cpu_on(u32 __always_unused unused, u32 mpidr, u32 pc,
  			 u32 context_id)
  {
-	struct sunxi_cpucfg_reg *cpucfg =
-		(struct sunxi_cpucfg_reg *)SUNXI_CPUCFG_BASE;
  	u32 cpu = (mpidr & 0x3);

  	/* store target PC and context id */
@@ -257,22 +329,22 @@ int __secure psci_cpu_on(u32 __always_unused 
unused, u32 mpidr, u32 pc,
  	sunxi_set_entry_address(&psci_cpu_entry);

  	/* Assert reset on target CPU */
-	writel(0, &cpucfg->cpu[cpu].rst);
+	sunxi_cpu_set_reset(cpu, true);

  	/* Invalidate L1 cache */
-	clrbits_le32(&cpucfg->gen_ctrl, BIT(cpu));
+	sunxi_cpu_invalidate_cache(cpu);

  	/* Lock CPU (Disable external debug access) */
-	clrbits_le32(&cpucfg->dbg_ctrl1, BIT(cpu));
+	sunxi_cpu_set_locking(cpu, true);

  	/* Power up target CPU */
  	sunxi_cpu_set_power(cpu, true);

  	/* De-assert reset on target CPU */
-	writel(BIT(1) | BIT(0), &cpucfg->cpu[cpu].rst);
+	sunxi_cpu_set_reset(cpu, false);

-	/* Unlock CPU (Disable external debug access) */
-	setbits_le32(&cpucfg->dbg_ctrl1, BIT(cpu));
+	/* Unlock CPU (Reenable external debug access) */
+	sunxi_cpu_set_locking(cpu, false);

  	return ARM_PSCI_RET_SUCCESS;
  }
diff --git a/arch/arm/include/asm/arch-sunxi/cpu_sunxi_ncat2.h 
b/arch/arm/include/asm/arch-sunxi/cpu_sunxi_ncat2.h
index d01508517c..629d761aa6 100644
--- a/arch/arm/include/asm/arch-sunxi/cpu_sunxi_ncat2.h
+++ b/arch/arm/include/asm/arch-sunxi/cpu_sunxi_ncat2.h
@@ -17,6 +17,8 @@
  #define SUNXI_SIDC_BASE			0x03006000
  #define SUNXI_SID_BASE			0x03006200
  #define SUNXI_TIMER_BASE		0x02050000
+#define SUNXI_GIC400_BASE		0x03020000
+#define SUNXI_CPUX_BASE			0x09010000

  #ifdef CONFIG_MACH_SUN50I_H6
  #define SUNXI_DRAM_COM_BASE		0x04002000
@@ -34,11 +36,11 @@
  #define SUNXI_SPI0_BASE			0x04025000
  #define SUNXI_SPI1_BASE			0x04026000

-#define SUNXI_RTC_BASE			0x07000000
  #define SUNXI_R_CPUCFG_BASE		0x07000400
  #define SUNXI_PRCM_BASE			0x07010000
  #define SUNXI_R_WDOG_BASE		0x07020400
-#define SUNXI_R_TWI_BASE		0x07081400
+#define SUNXI_R_TWI_BASE		0x07020800
+#define SUNXI_RTC_BASE			0x07090000

  #ifndef __ASSEMBLY__
  void sunxi_board_init(void);
diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
index bb9b863d2c..a5d312d377 100644
--- a/arch/arm/mach-sunxi/Kconfig
+++ b/arch/arm/mach-sunxi/Kconfig
@@ -366,6 +366,8 @@ config MACH_SUN8I_R40
  config MACH_SUN8I_R528
  	bool "sun8i (Allwinner R528)"
  	select CPU_V7A
+	select CPU_V7_HAS_NONSEC
+	select ARCH_SUPPORT_PSCI
  	select SUNXI_GEN_NCAT2
  	select SUNXI_NEW_PINCTRL
  	select MMC_SUNXI_HAS_NEW_MODE


More information about the U-Boot mailing list