[U-Boot] [V2] [PATCH 7/8] sun8i: Enable PSCI cpu_on support for A83t

tpearson at raptorengineering.com tpearson at raptorengineering.com
Tue May 17 21:37:15 CEST 2016


This patch adds support for the PSCI cpu_on command on Allwinner
A83t devices.  Since cluster 1 is already set up by early init,
the majority of this patch focuses on adding multi-cluster support
to PSCI and A83t power sequencing.

Signed-off-by: Timothy Pearson <tpearson at raptorengineering.com>
---
 arch/arm/cpu/armv7/sunxi/psci_sun6i.S | 174 ++++++++++++++++++++++++++++++++--
 1 file changed, 164 insertions(+), 10 deletions(-)

diff --git a/arch/arm/cpu/armv7/sunxi/psci_sun6i.S b/arch/arm/cpu/armv7/sunxi/psci_sun6i.S
index d35b63e..b3090ec 100644
--- a/arch/arm/cpu/armv7/sunxi/psci_sun6i.S
+++ b/arch/arm/cpu/armv7/sunxi/psci_sun6i.S
@@ -21,6 +21,7 @@

 #include <asm/arch-armv7/generictimer.h>
 #include <asm/gic.h>
+#include <linux/linkage.h>
 #include <asm/macro.h>
 #include <asm/psci.h>
 #include <asm/arch/cpu.h>
@@ -45,6 +46,16 @@
 #define	GICD_BASE		0x1c81000
 #define	GICC_BASE		0x1c82000

+@ Attempts to condense sparse ID space on multi-cluster systems to dense ID space
+ENTRY(psci_get_cpu_id)
+	mrc	p15, 0, r0, c0, c0, 5	/* read MPIDR */
+	lsr	r1, r0, #6		/* extract cluster offset */
+	and	r1, r1, #0xff
+	and	r0, r0, #0xff		/* extract CPU ID in cluster */
+	add	r0, r0, r1		/* return adjusted CPU ID */
+	bx	lr
+ENDPROC(psci_get_cpu_id)
+
 .globl	psci_fiq_enter
 psci_fiq_enter:
 	push	{r0-r12}
@@ -106,7 +117,7 @@ psci_fiq_enter:
 	str	r10, [r8, #0x100]
 	timer_wait r10, ONE_MS

-#if defined(CONFIG_MACH_SUN6I) || defined(CONFIG_MACH_SUN8I_H3)
+#if defined(CONFIG_MACH_SUN6I) || defined(CONFIG_MACH_SUN8I_H3) || defined(CONFIG_MACH_SUN8I_A83T)
 	@ Activate power clamp
 	lsl	r12, r9, #2		@ x4
 	add	r12, r12, r8
@@ -134,7 +145,13 @@ out:	mcr	p15, 0, r7, c1, c1, 0
 psci_cpu_on:
 	push	{lr}

-	mov	r0, r1
+#if defined(CONFIG_MACH_SUN8I_A83T)
+	lsr	r3, r1, #6	@ extract cluster offset
+	and	r0, r1, #3	@ extract CPU number
+	add	r0, r0, r3	@ pass adjusted CPU number to setup
+#else
+	mov	r0, r1		@ pass CPU number to setup
+#endif
 	bl	psci_get_cpu_stack_top	@ get stack top of target CPU
 	str	r2, [r0]		@ store target PC at stack top
 	dsb
@@ -142,15 +159,74 @@ psci_cpu_on:
 	movw	r0, #(SUN6I_CPUCFG_BASE & 0xffff)
 	movt	r0, #(SUN6I_CPUCFG_BASE >> 16)

+	ldr	r6, =psci_cpu_entry
+	str	r6, [r0, #0x1a4] @ PRIVATE_REG (boot vector)
+
 	@ CPU mask
+#if defined(CONFIG_MACH_SUN8I_A83T)
+	lsr	r3, r1, #8	@ extract cluster number
+	and	r1, r1, #3	@ extract CPU number
+
+	@ obtain silicon revision level
+	movw	r0, #(SUNXI_SRAMC_BASE & 0xffff)
+	movt	r0, #(SUNXI_SRAMC_BASE >> 16)
+	ldr	r2, [r0, #0x24]
+	and	r2, r2, #0x1
+#else
+	ldr	r3, #0		@ only one cluster
 	and	r1, r1, #3	@ only care about first cluster
+	ldr	r2, #0		@ default revision
+#endif
 	mov	r4, #1
 	lsl	r4, r4, r1

-	ldr	r6, =psci_cpu_entry
-	str	r6, [r0, #0x1a4] @ PRIVATE_REG (boot vector)
-
 	@ Assert reset on target CPU
+#if defined(CONFIG_MACH_SUN8I_A83T)
+	movw	r0, #(SUN8I_CPUXCFG_BASE & 0xffff)
+	movt	r0, #(SUN8I_CPUXCFG_BASE >> 16)
+
+	lsl	r5, r3, #2	@ cluster offset
+	add	r5, r5, #0x80	@ SUNXI_CPU_RST_CTRL
+	ldr	r6, [r0, r5]
+	bic	r6, r6, r4	@ assert reset
+	str	r6, [r0, r5]
+
+	cmp	r1, #0
+	bne	skip_cluster_reset_assert
+
+	lsl	r5, r3, #4	@ cluster offset
+	add	r5, r5, #0x04	@ SUNXI_CLUSTER_CTRL1
+	ldr	r6, [r0, r5]
+	orr	r6, r6, #0x1	@ assert ACINACTM
+	str	r6, [r0, r5]
+
+	lsl	r5, r3, #2	@ cluster offset
+	add	r5, r5, #0x80	@ SUNXI_CPU_RST_CTRL
+	ldr	r6, [r0, r5]
+	bic	r6, r6, #0x1000	@ assert HRESET
+	bic	r6, r6, #0x100	@ assert L2 cache reset
+	str	r6, [r0, r5]
+skip_cluster_reset_assert:
+
+	@ re-calculate CPU control register address
+	movw	r0, #(SUN6I_CPUCFG_BASE & 0xffff)
+	movt	r0, #(SUN6I_CPUCFG_BASE >> 16)
+
+	lsl	r5, r3, #2	@ cluster offset
+	add	r5, r5, #0x30	@ SUNXI_CLUSTER_PWRON_RESET
+	ldr	r6, [r0, r5]
+	bic	r6, r6, r4	@ assert reset
+	str	r6, [r0, r5]
+
+	movw	r0, #(SUN8I_CPUXCFG_BASE & 0xffff)
+	movt	r0, #(SUN8I_CPUXCFG_BASE >> 16)
+
+	@ l1 invalidate
+	lsl	r5, r3, #4	@ calculate cluster offset
+	ldr	r6, [r0, r5]	@ CX_CTRL_REG0
+	bic	r6, r6, r4
+	str	r6, [r0, r5]
+#else
 	mov	r6, #0
 	lsl	r5, r1, #6	@ 64 bytes per CPU
 	add	r5, r5, #0x40	@ Offset from base
@@ -166,32 +242,109 @@ psci_cpu_on:
 	ldr	r6, [r0, #0x1e4] @ CPUCFG_DBG_CTL1_REG
 	bic	r6, r6, r4
 	str	r6, [r0, #0x1e4]
+#endif

 	movw	r0, #(SUNXI_PRCM_BASE & 0xffff)
 	movt	r0, #(SUNXI_PRCM_BASE >> 16)

-#if defined(CONFIG_MACH_SUN6I) || defined(CONFIG_MACH_SUN8I_H3)
+#if defined(CONFIG_MACH_SUN6I) || defined(CONFIG_MACH_SUN8I_H3) || defined(CONFIG_MACH_SUN8I_A83T)
 	@ Release power clamp
-	lsl	r5, r1, #2	@ 1 register per CPU
+	lsl	r5, r3, #2	@ calculate cluster offset
+	add	r5, r1		@ add CPU offset
+	lsl	r5, r5, #2	@ 1 register per CPU
 	add	r5, r5, r0	@ PRCM
+#if defined(CONFIG_MACH_SUN8I_A83T)
+	mov	r6, #0xfe
+	str	r6, [r5, #0x140] @ CPUx_PWR_CLAMP
+	timer_wait r6, TEN_MS
+	timer_wait r6, TEN_MS
+	mov	r6, #0xf8
+	str	r6, [r5, #0x140] @ CPUx_PWR_CLAMP
+	timer_wait r6, TEN_MS
+	mov	r6, #0xe0
+	str	r6, [r5, #0x140] @ CPUx_PWR_CLAMP
+	timer_wait r6, TEN_MS
+	mov	r6, #0xc0
+	str	r6, [r5, #0x140] @ CPUx_PWR_CLAMP
+	timer_wait r6, TEN_MS
+	mov	r6, #0x80
+	str	r6, [r5, #0x140] @ CPUx_PWR_CLAMP
+	timer_wait r6, TEN_MS
+	mov	r6, #0x00
+	str	r6, [r5, #0x140] @ CPUx_PWR_CLAMP
+	timer_wait r6, TEN_MS
+#else
 	movw	r6, #0x1ff
 	movt	r6, #0
 1:	lsrs	r6, r6, #1
 	str	r6, [r5, #0x140] @ CPUx_PWR_CLAMP
 	bne	1b
 #endif
+#endif

 	timer_wait r6, TEN_MS

 	@ Clear power gating
-	ldr	r6, [r0, #0x100] @ CPU_PWROFF_GATING
-	bic	r6, r6, r4
-	str	r6, [r0, #0x100]
+	lsl	r5, r3, #2	@ cluster offset
+	add	r5, r5, #0x100	@ SUNXI_CLUSTER_PWROFF_GATING
+	ldr	r6, [r0, r5]
+#if defined(CONFIG_MACH_SUN8I_A83T)
+	cmp	r2, #0
+	beq	skip_a83t_rev_b_fixup
+	cmp	r1, #0
+	bne	skip_a83t_rev_b_fixup
+	bic	r6, r6, #0x10	@ core 0 power gate off
+	b	a83t_rev_b_fixup_done
+#endif
+skip_a83t_rev_b_fixup:
+	bic	r6, r6, r4	@ power gating off
+a83t_rev_b_fixup_done:
+	str	r6, [r0, r5]
+
+	movw	r0, #(SUN8I_CPUXCFG_BASE & 0xffff)
+	movt	r0, #(SUN8I_CPUXCFG_BASE >> 16)

 	@ re-calculate CPU control register address
 	movw	r0, #(SUN6I_CPUCFG_BASE & 0xffff)
 	movt	r0, #(SUN6I_CPUCFG_BASE >> 16)

+#if defined(CONFIG_MACH_SUN8I_A83T)
+	timer_wait r6, TEN_MS
+	timer_wait r6, TEN_MS
+
+	@ Deassert reset on target CPU
+	lsl	r5, r3, #2	@ cluster offset
+	add	r5, r5, #0x30	@ SUNXI_CLUSTER_PWRON_RESET
+	ldr	r6, [r0, r5]
+	orr	r6, r6, r4	@ deassert reset
+	str	r6, [r0, r5]
+
+	movw	r0, #(SUN8I_CPUXCFG_BASE & 0xffff)
+	movt	r0, #(SUN8I_CPUXCFG_BASE >> 16)
+
+	@ Clear any applied cluster resets
+	cmp	r1, #0
+	bne	skip_cluster_reset_deassert
+	lsl	r5, r3, #2	@ cluster offset
+	add	r5, r5, #0x80	@ SUNXI_CPU_RST_CTRL
+	ldr	r6, [r0, r5]
+	orr	r6, r6, #0x1000	@ deassert HRESET
+	orr	r6, r6, #0x100	@ deassert L2 cache reset
+	str	r6, [r0, r5]
+
+	lsl	r5, r3, #4	@ cluster offset
+	add	r5, r5, #0x04	@ SUNXI_CLUSTER_CTRL1
+	ldr	r6, [r0, r5]
+	bic	r6, r6, #0x1	@ deassert ACINACTM
+	str	r6, [r0, r5]
+skip_cluster_reset_deassert:
+
+	lsl	r5, r3, #2	@ cluster offset
+	add	r5, r5, #0x80	@ SUNXI_CPU_RST_CTRL
+	ldr	r6, [r0, r5]
+	orr	r6, r6, r4	@ deassert reset
+	str	r6, [r0, r5]
+#else
 	@ Deassert reset on target CPU
 	mov	r6, #3
 	lsl	r5, r1, #6	@ 64 bytes per CPU
@@ -203,6 +356,7 @@ psci_cpu_on:
 	ldr	r6, [r0, #0x1e4] @ CPUCFG_DBG_CTL1_REG
 	orr	r6, r6, r4
 	str	r6, [r0, #0x1e4]
+#endif

 	mov	r0, #ARM_PSCI_RET_SUCCESS	@ Return PSCI_RET_SUCCESS
 	pop	{pc}
-- 
2.8.0.rc3



More information about the U-Boot mailing list