Skip to contentSkip to conversation

Add PSCI support for Jetson TK1/Tegra124

PATCH Superseded Jan Kiszka 2 participants 13 messages Feb 14, 2015 – Feb 15, 2015

Subsystems (3)

v1 of 6 Superseded Latest is v6 →

lore
Share & tools
lore

Jan Kiszka

author
#0 lore raw

cover Add PSCI support for Jetson TK1/Tegra124

I've picked up Ian's and Thierry's work on PSCI support for Tegra124, specifically the Jetson TK1 board. This series contains Ian's patches and a rewritten version of the PSCI core as suggested by Thierry. It's working fine on the TK1, allowing Linux to online/offline CPUs 1-3 as it likes (provided CONFIG_CPU_IDLE is off).

Patches are also available here:

https://github.com/siemens/u-boot/tree/jetson-tk1

Looking forward to review.

Jan

CC Ian Campbell <[email protected]>
CC Jan Kiszka <[email protected]>

Ian Campbell (4):
tegra124: Add more registers to struct mc_ctlr
virt-dt: Allow reservation of the secure region when it is in a RAM
carveout.
jetson-tk1: Add PSCI configuration options and reserve secure code
tegra124: Reserve secure RAM using MC_SECURITY_CFG{0, 1}_0

Jan Kiszka (5):
ARM: Factor out reusable psci_cpu_off_common
ARM: Factor out reusable psci_cpu_entry
tegra: Make tegra_powergate_power_on public
tegra: Add ap_pm_init hook
tegra124: Add PSCI support for Tegra124

 arch/arm/cpu/armv7/Makefile                 |   1 +
 arch/arm/cpu/armv7/psci.S                   |  90 +++++++++++++++++++++++++
 arch/arm/cpu/armv7/sunxi/psci.S             |  84 +----------------------
 arch/arm/cpu/armv7/tegra-common/Makefile    |   1 +
 arch/arm/cpu/armv7/tegra-common/psci.S      | 101 ++++++++++++++++++++++++++++
 arch/arm/cpu/armv7/tegra124/Kconfig         |   2 +
 arch/arm/cpu/armv7/tegra124/Makefile        |   7 ++
 arch/arm/cpu/armv7/tegra124/ap.c            |  44 ++++++++++++
 arch/arm/cpu/armv7/virt-dt.c                |   5 ++
 arch/arm/cpu/armv7/virt-v7.c                |   5 ++
 arch/arm/cpu/tegra-common/ap.c              |  15 +++++
 arch/arm/cpu/tegra-common/powergate.c       |   2 +-
 arch/arm/include/asm/arch-tegra/ap.h        |   5 ++
 arch/arm/include/asm/arch-tegra/powergate.h |   1 +
 arch/arm/include/asm/arch-tegra124/flow.h   |   5 ++
 arch/arm/include/asm/arch-tegra124/mc.h     |  35 +++++++++-
 arch/arm/include/asm/system.h               |   1 +
 board/nvidia/common/board.c                 |   4 ++
 include/configs/jetson-tk1.h                |   5 ++
 19 files changed, 329 insertions(+), 84 deletions(-)
 create mode 100644 arch/arm/cpu/armv7/tegra-common/psci.S
 create mode 100644 arch/arm/cpu/armv7/tegra124/Makefile
 create mode 100644 arch/arm/cpu/armv7/tegra124/ap.c
Signature · 1 line
2.1.4
author
#1 lore raw

PATCH 1/9 ARM: Factor out reusable psci_cpu_off_common

From: Jan Kiszka <[email protected]>

Move parts of sunxi's psci_cpu_off into psci_cpu_off_common, namely cache disabling and flushing, clrex and the disabling of SMP for the dying CPU. These steps are apparently generic for ARMv7 and will be reused for Tegra124 support.

---
 arch/arm/cpu/armv7/psci.S       | 71 +++++++++++++++++++++++++++++++++++++++++
 arch/arm/cpu/armv7/sunxi/psci.S | 63 +-----------------------------------
 2 files changed, 72 insertions(+), 62 deletions(-)
arch/arm/cpu/armv7/psci.S +71 -0
index bf11a34..d688607 100644
@@ -99,4 +99,75 @@ _smc_psci:
 	pop	{r4-r7, lr}
 	movs	pc, lr			@ Return to the kernel
 
+/* Imported from Linux kernel */
+LENTRY(v7_flush_dcache_all)
+	dmb					@ ensure ordering with previous memory accesses
+	mrc	p15, 1, r0, c0, c0, 1		@ read clidr
+	ands	r3, r0, #0x7000000		@ extract loc from clidr
+	mov	r3, r3, lsr #23			@ left align loc bit field
+	beq	finished			@ if loc is 0, then no need to clean
+	mov	r10, #0				@ start clean at cache level 0
+flush_levels:
+	add	r2, r10, r10, lsr #1		@ work out 3x current cache level
+	mov	r1, r0, lsr r2			@ extract cache type bits from clidr
+	and	r1, r1, #7			@ mask of the bits for current cache only
+	cmp	r1, #2				@ see what cache we have at this level
+	blt	skip				@ skip if no cache, or just i-cache
+	mrs     r9, cpsr			@ make cssr&csidr read atomic
+	mcr	p15, 2, r10, c0, c0, 0		@ select current cache level in cssr
+	isb					@ isb to sych the new cssr&csidr
+	mrc	p15, 1, r1, c0, c0, 0		@ read the new csidr
+	msr     cpsr_c, r9
+	and	r2, r1, #7			@ extract the length of the cache lines
+	add	r2, r2, #4			@ add 4 (line length offset)
+	ldr	r4, =0x3ff
+	ands	r4, r4, r1, lsr #3		@ find maximum number on the way size
+	clz	r5, r4				@ find bit position of way size increment
+	ldr	r7, =0x7fff
+	ands	r7, r7, r1, lsr #13		@ extract max number of the index size
+loop1:
+	mov	r9, r7				@ create working copy of max index
+loop2:
+	orr	r11, r10, r4, lsl r5		@ factor way and cache number into r11
+	orr	r11, r11, r9, lsl r2		@ factor index number into r11
+	mcr	p15, 0, r11, c7, c14, 2		@ clean & invalidate by set/way
+	subs	r9, r9, #1			@ decrement the index
+	bge	loop2
+	subs	r4, r4, #1			@ decrement the way
+	bge	loop1
+skip:
+	add	r10, r10, #2			@ increment cache number
+	cmp	r3, r10
+	bgt	flush_levels
+finished:
+	mov	r10, #0				@ swith back to cache level 0
+	mcr	p15, 2, r10, c0, c0, 0		@ select current cache level in cssr
+	dsb	st
+	isb
+	bx	lr
+ENDPROC(v7_flush_dcache_all)
+
+ENTRY(psci_cpu_off_common)
+	push	{lr}
+
+	mrc	p15, 0, r0, c1, c0, 0		@ SCTLR
+	bic	r0, r0, #(1 << 2)		@ Clear C bit
+	mcr	p15, 0, r0, c1, c0, 0		@ SCTLR
+	isb
+	dsb
+
+	bl	v7_flush_dcache_all
+
+	clrex					@ Why???
+
+	mrc	p15, 0, r0, c1, c0, 1		@ ACTLR
+	bic	r0, r0, #(1 << 6)		@ Clear SMP bit
+	mcr	p15, 0, r0, c1, c0, 1		@ ACTLR
+	isb
+	dsb
+
+	pop	{lr}
+	bx	lr
+ENDPROC(psci_cpu_off_common)
+
 	.popsection
arch/arm/cpu/armv7/sunxi/psci.S +1 -62

75 lines not on this page · raw message

Signature · 1 line
2.1.4
author
#2 lore raw

PATCH 2/9 ARM: Factor out reusable psci_cpu_entry

In reply to Jan Kiszka

From: Jan Kiszka <[email protected]>

_sunxi_cpu_entry can be converted completely into a reusable psci_cpu_entry. Tegra124 will use it as well.

---
 arch/arm/cpu/armv7/psci.S       | 19 +++++++++++++++++++
 arch/arm/cpu/armv7/sunxi/psci.S | 21 ++-------------------
 2 files changed, 21 insertions(+), 19 deletions(-)
arch/arm/cpu/armv7/psci.S +19 -0
index d688607..e916d71 100644
@@ -170,4 +170,23 @@ ENTRY(psci_cpu_off_common)
 	bx	lr
 ENDPROC(psci_cpu_off_common)
 
+ENTRY(psci_cpu_entry)
+	@ Set SMP bit
+	mrc	p15, 0, r0, c1, c0, 1		@ ACTLR
+	orr	r0, r0, #(1 << 6)		@ Set SMP bit
+	mcr	p15, 0, r0, c1, c0, 1		@ ACTLR
+	isb
+
+	bl	_nonsec_init
+	bl	psci_arch_init
+
+	adr	r0, _psci_target_pc
+	ldr	r0, [r0]
+	b	_do_nonsec_entry
+ENDPROC(psci_cpu_entry)
+
+.globl _psci_target_pc
+_psci_target_pc:
+	.word	0
+
 	.popsection
arch/arm/cpu/armv7/sunxi/psci.S +2 -19
index 6785fdd..c3a8dc1 100644
@@ -138,7 +138,7 @@ out:	mcr	p15, 0, r7, c1, c1, 0
 	@ r2 = target PC
 .globl	psci_cpu_on
 psci_cpu_on:
-	adr	r0, _target_pc
+	ldr	r0, =_psci_target_pc
 	str	r2, [r0]
 	dsb
 
@@ -150,7 +150,7 @@ psci_cpu_on:
 	mov	r4, #1
 	lsl	r4, r4, r1
 
-	adr	r6, _sunxi_cpu_entry
+	ldr	r6, =psci_cpu_entry
 	str	r6, [r0, #0x1a4] @ PRIVATE_REG (boot vector)
 
 	@ Assert reset on target CPU
@@ -196,23 +196,6 @@ psci_cpu_on:
 	mov	r0, #ARM_PSCI_RET_SUCCESS	@ Return PSCI_RET_SUCCESS
 	mov	pc, lr
 
-_target_pc:
-	.word	0
-
-_sunxi_cpu_entry:
-	@ Set SMP bit
-	mrc	p15, 0, r0, c1, c0, 1
-	orr	r0, r0, #0x40
-	mcr	p15, 0, r0, c1, c0, 1
-	isb
-
-	bl	_nonsec_init
-	bl	psci_arch_init
-
-	adr	r0, _target_pc
-	ldr	r0, [r0]
-	b	_do_nonsec_entry
-
 .globl	psci_cpu_off
 psci_cpu_off:
 	bl	psci_cpu_off_common
Signature · 1 line
2.1.4
#3 lore raw

PATCH 2/9 ARM: Factor out reusable psci_cpu_entry

Hi,

Quoted 27 lines · Jan Kiszka

From: Jan Kiszka <[email protected]>

_sunxi_cpu_entry can be converted completely into a reusable psci_cpu_entry. Tegra124 will use it as well.

---
 arch/arm/cpu/armv7/psci.S       | 19 +++++++++++++++++++
 arch/arm/cpu/armv7/sunxi/psci.S | 21 ++-------------------
 2 files changed, 21 insertions(+), 19 deletions(-)
arch/arm/cpu/armv7/psci.S +8 -0
index d688607..e916d71 100644
@@ -170,4 +170,23 @@ ENTRY(psci_cpu_off_common)
        bx      lr
 ENDPROC(psci_cpu_off_common)
 
+ENTRY(psci_cpu_entry)
+       @ Set SMP bit
+       mrc     p15, 0, r0, c1, c0, 1           @ ACTLR
+       orr     r0, r0, #(1 << 6)               @ Set SMP bit
+       mcr     p15, 0, r0, c1, c0, 1           @ ACTLR
+       isb
+
+       bl      _nonsec_init

arch/arm/cpu/armv7/psci.S ENTRY(psci_cpu_off_common) · line 190

Quoted 10 lines
arch/arm/cpu/armv7/psci.S +10 -0
+       bl      psci_arch_init
+
+       adr     r0, _psci_target_pc
+       ldr     r0, [r0]
+       b       _do_nonsec_entry
+ENDPROC(psci_cpu_entry)
+
+.globl _psci_target_pc
+_psci_target_pc:
+       .word   0

The sunxi version didn't have a per-core target_pc variable. It is still the case here. Is this the correct way to implement it? I see per-core storage of this in some of the kernel's smp ops.

On sunxi it works because the only platform using it only has one secondary core.

ChenYu

Quoted 55 lines
arch/arm/cpu/armv7/psci.S +1 -0
+
        .popsection
arch/arm/cpu/armv7/sunxi/psci.S +2 -20
index 6785fdd..c3a8dc1 100644
@@ -138,7 +138,7 @@ out:        mcr     p15, 0, r7, c1, c1, 0
        @ r2 = target PC
 .globl psci_cpu_on
 psci_cpu_on:
-       adr     r0, _target_pc
+       ldr     r0, =_psci_target_pc
        str     r2, [r0]
        dsb
 
@@ -150,7 +150,7 @@ psci_cpu_on:
        mov     r4, #1
        lsl     r4, r4, r1
 
-       adr     r6, _sunxi_cpu_entry
+       ldr     r6, =psci_cpu_entry
        str     r6, [r0, #0x1a4] @ PRIVATE_REG (boot vector)
 
        @ Assert reset on target CPU
@@ -196,23 +196,6 @@ psci_cpu_on:
        mov     r0, #ARM_PSCI_RET_SUCCESS       @ Return PSCI_RET_SUCCESS
        mov     pc, lr
 
-_target_pc:
-       .word   0
-
-_sunxi_cpu_entry:
-       @ Set SMP bit
-       mrc     p15, 0, r0, c1, c0, 1
-       orr     r0, r0, #0x40
-       mcr     p15, 0, r0, c1, c0, 1
-       isb
-
-       bl      _nonsec_init
-       bl      psci_arch_init
-
-       adr     r0, _target_pc
-       ldr     r0, [r0]
-       b       _do_nonsec_entry
-
 .globl psci_cpu_off
 psci_cpu_off:
        bl      psci_cpu_off_common
--

2.1.4

_______________________________________________
U-Boot mailing list
U-Boot at lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

author
#4 lore raw

PATCH 2/9 ARM: Factor out reusable psci_cpu_entry

Quoted 46 lines · Chen-Yu Tsai

Hi,

Quoted 27 lines · Jan Kiszka

From: Jan Kiszka <[email protected]>

_sunxi_cpu_entry can be converted completely into a reusable psci_cpu_entry. Tegra124 will use it as well.

---
 arch/arm/cpu/armv7/psci.S       | 19 +++++++++++++++++++
 arch/arm/cpu/armv7/sunxi/psci.S | 21 ++-------------------
 2 files changed, 21 insertions(+), 19 deletions(-)
arch/arm/cpu/armv7/psci.S +8 -0
index d688607..e916d71 100644
@@ -170,4 +170,23 @@ ENTRY(psci_cpu_off_common)
        bx      lr
 ENDPROC(psci_cpu_off_common)
 
+ENTRY(psci_cpu_entry)
+       @ Set SMP bit
+       mrc     p15, 0, r0, c1, c0, 1           @ ACTLR
+       orr     r0, r0, #(1 << 6)               @ Set SMP bit
+       mcr     p15, 0, r0, c1, c0, 1           @ ACTLR
+       isb
+
+       bl      _nonsec_init

arch/arm/cpu/armv7/psci.S ENTRY(psci_cpu_off_common) · line 190

Quoted 10 lines
arch/arm/cpu/armv7/psci.S +10 -0
+       bl      psci_arch_init
+
+       adr     r0, _psci_target_pc
+       ldr     r0, [r0]
+       b       _do_nonsec_entry
+ENDPROC(psci_cpu_entry)
+
+.globl _psci_target_pc
+_psci_target_pc:
+       .word   0

The sunxi version didn't have a per-core target_pc variable. It is still the case here. Is this the correct way to implement it? I see per-core storage of this in some of the kernel's smp ops.

Quoted 3 lines

On sunxi it works because the only platform using it only has one secondary core.

With homogeneous SMP, it probably works as well because reset vectors may not differ across the cores. But this remains a valid point.

I'm considering to push this variable to the top of the per-CPU stack. Calculating the stack position is actually another function to factor out.

Thanks,
Jan

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 181 bytes
Desc: OpenPGP digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20150215/6a393c34/attachment.sig>

author
#5 lore raw

PATCH 2/9 ARM: Factor out reusable psci_cpu_entry

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Quoted 38 lines · Jan Kiszka
Quoted 33 lines · Chen-Yu Tsai

Hi,

Quoted 16 lines · Jan Kiszka

From: Jan Kiszka <[email protected]>

_sunxi_cpu_entry can be converted completely into a reusable psci_cpu_entry. Tegra124 will use it as well.

arch/arm/cpu/armv7/psci.S | 19 +++++++++++++++++++
arch/arm/cpu/armv7/sunxi/psci.S | 21 ++------------------- 2 files changed, 21 insertions(+), 19 deletions(-)

(quoted diff) +0 -0

b/arch/arm/cpu/armv7/psci.S index d688607..e916d71 100644 --- a/arch/arm/cpu/armv7/psci.S +++ b/arch/arm/cpu/armv7/psci.S @@
-170,4 +170,23 @@ ENTRY(psci_cpu_off_common) bx lr
ENDPROC(psci_cpu_off_common)

Quoted 8 lines

+ENTRY(psci_cpu_entry) + @ Set SMP bit + mrc
p15, 0, r0, c1, c0, 1 @ ACTLR + orr r0, r0,

#(1 << 6)               @ Set SMP bit +       mcr     p15, 0,
r0, c1, c0, 1           @ ACTLR +       isb + +       bl
_nonsec_init +       bl      psci_arch_init + +       adr

r0, _psci_target_pc + ldr r0, [r0] + b
_do_nonsec_entry +ENDPROC(psci_cpu_entry) + +.globl
_psci_target_pc +_psci_target_pc: + .word 0

The sunxi version didn't have a per-core target_pc variable. It is still the case here. Is this the correct way to implement it? I see per-core storage of this in some of the kernel's smp ops.

Quoted 3 lines

On sunxi it works because the only platform using it only has one secondary core.

Quoted 8 lines

With homogeneous SMP, it probably works as well because reset vectors may not differ across the cores. But this remains a valid point.

I'm considering to push this variable to the top of the per-CPU stack. Calculating the stack position is actually another function to factor out.

https://github.com/siemens/u-boot/commits/jetson-tk1-v2

works fine on the TK1, but I'd like to give it a try on a Banana Pi as well (currently out of reach) before reposting.

Jan
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2

iEYEARECAAYFAlTgawwACgkQitSsb3rl5xQCqgCg1cQM3fGHRbU4VhvHlfvwMkFa 2MwAnRy3lYcAXeCYiCfk8h5WlRLxIxRx
=tcEk
-----END PGP SIGNATURE-----

author
#6 lore raw

PATCH 3/9 tegra124: Add more registers to struct mc_ctlr

In reply to Jan Kiszka

From: Ian Campbell <[email protected]>

I will need mc_security_cfg0/1 in a future patch and I added the rest while debugging, so thought I might as well commit them.

---
 arch/arm/include/asm/arch-tegra124/mc.h | 35 +++++++++++++++++++++++++++++++--
 1 file changed, 33 insertions(+), 2 deletions(-)
arch/arm/include/asm/arch-tegra124/mc.h +33 -2
index d526dfe..5557732 100644
@@ -35,9 +35,40 @@ struct mc_ctlr {
 	u32 mc_emem_adr_cfg;			/* offset 0x54 */
 	u32 mc_emem_adr_cfg_dev0;		/* offset 0x58 */
 	u32 mc_emem_adr_cfg_dev1;		/* offset 0x5C */
-	u32 reserved3[12];			/* offset 0x60 - 0x8C */
+	u32 reserved3[4];			/* offset 0x60 - 0x6C */
+	u32 mc_security_cfg0;			/* offset 0x70 */
+	u32 mc_security_cfg1;			/* offset 0x74 */
+	u32 reserved4[6];			/* offset 0x7C - 0x8C */
 	u32 mc_emem_arb_reserved[28];		/* offset 0x90 - 0xFC */
-	u32 reserved4[338];			/* offset 0x100 - 0x644 */
+	u32 reserved5[74];			/* offset 0x100 - 0x224 */
+	u32 mc_smmu_translation_enable_0;	/* offset 0x228 */
+	u32 mc_smmu_translation_enable_1;	/* offset 0x22C */
+	u32 mc_smmu_translation_enable_2;	/* offset 0x230 */
+	u32 mc_smmu_translation_enable_3;	/* offset 0x234 */
+	u32 mc_smmu_afi_asid;			/* offset 0x238 */
+	u32 mc_smmu_avpc_asid;			/* offset 0x23C */
+	u32 mc_smmu_dc_asid;			/* offset 0x240 */
+	u32 mc_smmu_dcb_asid;			/* offset 0x244 */
+	u32 reserved6[2];                       /* offset 0x248 - 0x24C */
+	u32 mc_smmu_hc_asid;			/* offset 0x250 */
+	u32 mc_smmu_hda_asid;			/* offset 0x254 */
+	u32 mc_smmu_isp2_asid;			/* offset 0x258 */
+	u32 reserved7[2];                       /* offset 0x25C - 0x260 */
+	u32 mc_smmu_msenc_asid;			/* offset 0x264 */
+	u32 mc_smmu_nv_asid;			/* offset 0x268 */
+	u32 mc_smmu_nv2_asid;			/* offset 0x26C */
+	u32 mc_smmu_ppcs_asid;			/* offset 0x270 */
+	u32 mc_smmu_sata_asid;			/* offset 0x274 */
+	u32 reserved8[1];                       /* offset 0x278 */
+	u32 mc_smmu_vde_asid;			/* offset 0x27C */
+	u32 mc_smmu_vi_asid;			/* offset 0x280 */
+	u32 mc_smmu_vic_asid;			/* offset 0x284 */
+	u32 mc_smmu_xusb_host_asid;		/* offset 0x288 */
+	u32 mc_smmu_xusb_dev_asid;		/* offset 0x28C */
+	u32 reserved9[1];                       /* offset 0x290 */
+	u32 mc_smmu_tsec_asid;			/* offset 0x294 */
+	u32 mc_smmu_ppcs1_asid;			/* offset 0x298 */
+	u32 reserved10[235];			/* offset 0x29C - 0x644 */
 	u32 mc_video_protect_bom;		/* offset 0x648 */
 	u32 mc_video_protect_size_mb;		/* offset 0x64c */
 	u32 mc_video_protect_reg_ctrl;		/* offset 0x650 */
Signature · 1 line
2.1.4
author
#7 lore raw

PATCH 4/9 virt-dt: Allow reservation of the secure region when it is in a RAM carveout.

In reply to Jan Kiszka

From: Ian Campbell <[email protected]>

In this case the secure code lives in RAM, and hence needs to be reserved, but it has been relocated, so the reservation of __secure_start does not apply.

Add support for setting CONFIG_ARMV7_SECURE_RESERVE_SIZE to reserve such a region.

This will be used in a subsequent patch for Jetson-TK1

---
 arch/arm/cpu/armv7/virt-dt.c | 5 +++++
 1 file changed, 5 insertions(+)
arch/arm/cpu/armv7/virt-dt.c +5 -0
index ad19e4c..eb95031 100644
@@ -96,6 +96,11 @@ int armv7_update_dt(void *fdt)
 	/* secure code lives in RAM, keep it alive */
 	fdt_add_mem_rsv(fdt, (unsigned long)__secure_start,
 			__secure_end - __secure_start);
+#elif defined(CONFIG_ARMV7_SECURE_RESERVE_SIZE)
+	/* secure code has been relocated into RAM carveout, keep it alive */
+	fdt_add_mem_rsv(fdt,
+			CONFIG_ARMV7_SECURE_BASE,
+			CONFIG_ARMV7_SECURE_RESERVE_SIZE);
 #endif
 
 	return fdt_psci(fdt);
Signature · 1 line
2.1.4
author
#8 lore raw

PATCH 5/9 tegra: Make tegra_powergate_power_on public

In reply to Jan Kiszka

From: Jan Kiszka <[email protected]>

Will be used for unpowergating CPUs.

---
 arch/arm/cpu/tegra-common/powergate.c       | 2 +-
 arch/arm/include/asm/arch-tegra/powergate.h | 1 +
 2 files changed, 2 insertions(+), 1 deletion(-)
arch/arm/cpu/tegra-common/powergate.c +1 -1
index 439cff3..6331cd4 100644
@@ -44,7 +44,7 @@ static int tegra_powergate_set(enum tegra_powergate id, bool state)
 	return -ETIMEDOUT;
 }
 
-static int tegra_powergate_power_on(enum tegra_powergate id)
+int tegra_powergate_power_on(enum tegra_powergate id)
 {
 	return tegra_powergate_set(id, true);
 }
arch/arm/include/asm/arch-tegra/powergate.h +1 -0
index 130b58b..2e491f1 100644
@@ -33,6 +33,7 @@ enum tegra_powergate {
 
 int tegra_powergate_sequence_power_up(enum tegra_powergate id,
 				      enum periph_id periph);
+int tegra_powergate_power_on(enum tegra_powergate id);
 int tegra_powergate_power_off(enum tegra_powergate id);
 
 #endif
Signature · 1 line
2.1.4
author
#9 lore raw

PATCH 6/9 tegra: Add ap_pm_init hook

In reply to Jan Kiszka

From: Jan Kiszka <[email protected]>

This function will be used to initialize CPU power management for Tegra SOCs. For now it does nothing.

---
 arch/arm/include/asm/arch-tegra/ap.h | 5 +++++
 board/nvidia/common/board.c          | 4 ++++
 2 files changed, 9 insertions(+)
arch/arm/include/asm/arch-tegra/ap.h +5 -0
index 5c8be94..208db90 100644
@@ -63,6 +63,11 @@ int tegra_get_chip(void);
  */
 int tegra_get_sku_info(void);
 
+/**
+ * Initialize power management for application processors
+ */
+void ap_pm_init(void);
+
 /* Do any chip-specific cache config */
 void config_cache(void);
 
board/nvidia/common/board.c +4 -0
index 80ef8fd..c62b3da 100644
@@ -21,6 +21,7 @@
 #include <asm/arch/pwm.h>
 #endif
 #include <asm/arch/tegra.h>
+#include <asm/arch-tegra/ap.h>
 #include <asm/arch-tegra/board.h>
 #include <asm/arch-tegra/clk_rst.h>
 #include <asm/arch-tegra/pmc.h>
@@ -56,6 +57,7 @@ const struct tegra_sysinfo sysinfo = {
 	CONFIG_TEGRA_BOARD_STRING
 };
 
+__weak void ap_pm_init(void) {}
 __weak void pinmux_init(void) {}
 __weak void pin_mux_usb(void) {}
 __weak void pin_mux_spi(void) {}
@@ -96,6 +98,8 @@ int board_init(void)
 	clock_init();
 	clock_verify();
 
+	ap_pm_init();
+
 #ifdef CONFIG_TEGRA_SPI
 	pin_mux_spi();
 #endif
Signature · 1 line
2.1.4
author
#10 lore raw

PATCH 7/9 tegra124: Add PSCI support for Tegra124

In reply to Jan Kiszka

From: Jan Kiszka <[email protected]>

This is based on Thierry Reding's work and uses Ian Campell's preparatory patches. It comes with full support for CPU_ON/OFF PSCI services. The algorithm used in this version for turning CPUs on and off was proposed by Thierry Reding in
http://thread.gmane.org/gmane.comp.boot-loaders.u-boot/210881. It consists of first enabling CPU1..3 via the PMC, just to powergate them again with the help of the Flow Controller. Once the Flow Controller is in place, we can leave the PMC alone while processing CPU_ON and CPU_OFF PSCI requests.

---
 arch/arm/cpu/armv7/Makefile               |   1 +
 arch/arm/cpu/armv7/tegra-common/Makefile  |   1 +
 arch/arm/cpu/armv7/tegra-common/psci.S    | 101 ++++++++++++++++++++++++++++++
 arch/arm/cpu/armv7/tegra124/Makefile      |   7 +++
 arch/arm/cpu/armv7/tegra124/ap.c          |  44 +++++++++++++
 arch/arm/include/asm/arch-tegra124/flow.h |   5 ++
 6 files changed, 159 insertions(+)
 create mode 100644 arch/arm/cpu/armv7/tegra-common/psci.S
 create mode 100644 arch/arm/cpu/armv7/tegra124/Makefile
 create mode 100644 arch/arm/cpu/armv7/tegra124/ap.c
arch/arm/cpu/armv7/Makefile +1 -0
index 409e6f5..616b6cc 100644
@@ -59,6 +59,7 @@ obj-$(CONFIG_SOCFPGA) += socfpga/
 obj-$(if $(filter stv0991,$(SOC)),y) += stv0991/
 obj-$(CONFIG_ARCH_SUNXI) += sunxi/
 obj-$(CONFIG_TEGRA20) += tegra20/
+obj-$(CONFIG_TEGRA124) += tegra124/
 obj-$(CONFIG_U8500) += u8500/
 obj-$(CONFIG_ARCH_UNIPHIER) += uniphier/
 obj-$(CONFIG_VF610) += vf610/
arch/arm/cpu/armv7/tegra-common/Makefile +1 -0
index 463c260..89355ca 100644
@@ -7,4 +7,5 @@
 # SPDX-License-Identifier:	GPL-2.0+
 #
 
+obj-$(CONFIG_ARMV7_PSCI) += psci.o
 obj-$(CONFIG_CMD_ENTERRCM) += cmd_enterrcm.o
arch/arm/cpu/armv7/tegra-common/psci.S new file +101 -0

101 lines not on this page · raw message

arch/arm/cpu/armv7/tegra124/Makefile new file +7 -0
new file mode 100644
index 0000000..b907277
@@ -0,0 +1,7 @@
+#
+# (C) Copyright 2015, Siemens AG
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+obj-$(CONFIG_ARMV7_PSCI) += ap.o
arch/arm/cpu/armv7/tegra124/ap.c new file +44 -0

44 lines not on this page · raw message

arch/arm/include/asm/arch-tegra124/flow.h +5 -0
index 0db1881..d5f24a0 100644
@@ -37,4 +37,9 @@ struct flow_ctlr {
 /* FLOW_CTLR_CLUSTER_CONTROL_0 0x2c */
 #define ACTIVE_LP		(1 << 0)
 
+/* CPUn_CSR_0 */
+#define CSR_ENABLE		(1 << 0)
+#define CSR_IMMEDIATE_WAKE	(1 << 3)
+#define CSR_WAIT_WFI_SHIFT	8
+
 #endif	/*  _TEGRA124_FLOW_H_ */
Signature · 1 line
2.1.4
author
#11 lore raw

PATCH 8/9 jetson-tk1: Add PSCI configuration options and reserve secure code

In reply to Jan Kiszka

From: Ian Campbell <[email protected]>

The secure world code is relocated to the MB just below the top of 4G, we reserve it in the FDT (by setting CONFIG_ARMV7_SECURE_RESERVE_SIZE) but it is not protected in h/w. See next patch.

---
 arch/arm/cpu/armv7/tegra124/Kconfig | 2 ++
 include/configs/jetson-tk1.h        | 5 +++++
 2 files changed, 7 insertions(+)
arch/arm/cpu/armv7/tegra124/Kconfig +2 -0
index 88f627c..5114299 100644
@@ -5,6 +5,8 @@ choice
 
 config TARGET_JETSON_TK1
 	bool "NVIDIA Tegra124 Jetson TK1 board"
+	select CPU_V7_HAS_NONSEC if !SPL_BUILD
+	select CPU_V7_HAS_VIRT if !SPL_BUILD
 
 config TARGET_NYAN_BIG
 	bool "Google/NVIDIA Nyan-big Chrombook"
include/configs/jetson-tk1.h +5 -0
index 0a79c7c..80c2952 100644
@@ -81,4 +81,9 @@
 #include "tegra-common-usb-gadget.h"
 #include "tegra-common-post.h"
 
+#define CONFIG_ARMV7_PSCI			1
+/* Reserve top 1M for secure RAM */
+#define CONFIG_ARMV7_SECURE_BASE		0xfff00000
+#define CONFIG_ARMV7_SECURE_RESERVE_SIZE	0x00100000
+
 #endif /* __CONFIG_H */
Signature · 1 line
2.1.4
author
#12 lore raw

PATCH 9/9 tegra124: Reserve secure RAM using MC_SECURITY_CFG{0, 1}_0

In reply to Jan Kiszka

From: Ian Campbell <[email protected]>

These registers can be used to prevent non-secure world from accessing a megabyte aligned region of RAM, use them to protect the u-boot secure monitor code.

At first I tried to do this from s_init(), however this inexplicably causes u-boot's networking (e.g. DHCP) to fail, while networking under Linux was fine.

So instead I have added a new weak arch function protect_secure_section() called from relocate_secure_section() and reserved the region there. This is better overall since it defers the reservation until after the sec vs. non-sec decision (which can be influenced by an envvar) has been made when booting the os.

---
 arch/arm/cpu/armv7/virt-v7.c   |  5 +++++
 arch/arm/cpu/tegra-common/ap.c | 15 +++++++++++++++
 arch/arm/include/asm/system.h  |  1 +
 3 files changed, 21 insertions(+)
arch/arm/cpu/armv7/virt-v7.c +5 -0
index b69fd37..eb6195c 100644
@@ -46,6 +46,10 @@ static unsigned long get_gicd_base_address(void)
 #endif
 }
 
+/* Define a specific version of this function to enable any available
+ * hardware protections for the reserved region */
+void __weak protect_secure_section(void) {}
+
 static void relocate_secure_section(void)
 {
 #ifdef CONFIG_ARMV7_SECURE_BASE
@@ -54,6 +58,7 @@ static void relocate_secure_section(void)
 	memcpy((void *)CONFIG_ARMV7_SECURE_BASE, __secure_start, sz);
 	flush_dcache_range(CONFIG_ARMV7_SECURE_BASE,
 			   CONFIG_ARMV7_SECURE_BASE + sz + 1);
+	protect_secure_section();
 	invalidate_icache_all();
 #endif
 }
arch/arm/cpu/tegra-common/ap.c +15 -0
index a17dfd1..f1d3070 100644
@@ -10,6 +10,7 @@
 #include <common.h>
 #include <asm/io.h>
 #include <asm/arch/gp_padctrl.h>
+#include <asm/arch/mc.h>
 #include <asm/arch-tegra/ap.h>
 #include <asm/arch-tegra/clock.h>
 #include <asm/arch-tegra/fuse.h>
@@ -154,6 +155,20 @@ static void init_pmc_scratch(void)
 	writel(odmdata, &pmc->pmc_scratch20);
 }
 
+#ifdef CONFIG_ARMV7_SECURE_RESERVE_SIZE
+void protect_secure_section(void)
+{
+	struct mc_ctlr *mc = (struct mc_ctlr *)NV_PA_MC_BASE;
+
+	/* Must be MB aligned */
+	BUILD_BUG_ON(CONFIG_ARMV7_SECURE_BASE & 0xFFFFF);
+	BUILD_BUG_ON(CONFIG_ARMV7_SECURE_RESERVE_SIZE & 0xFFFFF);
+
+	writel(CONFIG_ARMV7_SECURE_BASE, &mc->mc_security_cfg0);
+	writel(CONFIG_ARMV7_SECURE_RESERVE_SIZE>>20, &mc->mc_security_cfg1);
+}
+#endif
+
 void s_init(void)
 {
 	/* Init PMC scratch memory */
arch/arm/include/asm/system.h +1 -0
index 89f2294..21be69d 100644
@@ -76,6 +76,7 @@ void armv8_switch_to_el1(void);
 void gic_init(void);
 void gic_send_sgi(unsigned long sgino);
 void wait_for_wakeup(void);
+void protect_secure_region(void);
 void smp_kick_all_cpus(void);
 
 void flush_l3_cache(void);
Signature · 1 line
2.1.4