mirror of
				https://xff.cz/git/u-boot/
				synced 2025-10-30 18:05:48 +01:00 
			
		
		
		
	ARMv8: Add basic PSCI framework
This patch introduces a generic ARMv8 PSCI framework, with all functions returning a dummy ARM_PSCI_RET_NI (Not Implemented), then it is up to each platform to implement their own functions based on this framework. Signed-off-by: Hongbo Zhang <hongbo.zhang@nxp.com> Reviewed-by: Tom Rini <trini@konsulko.com> Reviewed-by: York Sun <york.sun@nxp.com>
This commit is contained in:
		
				
					committed by
					
						 York Sun
						York Sun
					
				
			
			
				
	
			
			
			
						parent
						
							5cc8d6682f
						
					
				
				
					commit
					14bf25d50d
				
			| @@ -58,6 +58,16 @@ config ARMV8_PSCI_NR_CPUS | ||||
| 	  It is no problem to set a larger value than the number of CPUs in | ||||
| 	  the actual hardware implementation. | ||||
|  | ||||
| config ARMV8_PSCI_CPUS_PER_CLUSTER | ||||
| 	int "Number of CPUs per cluster" | ||||
| 	depends on ARMV8_PSCI | ||||
| 	default 0 | ||||
| 	help | ||||
| 	  The number of CPUs per cluster, suppose each cluster has same number | ||||
| 	  of CPU cores, platforms with asymmetric clusters don't apply here. | ||||
| 	  A value 0 or no definition of it works for single cluster system. | ||||
| 	  System with multi-cluster should difine their own exact value. | ||||
|  | ||||
| if SYS_HAS_ARMV8_SECURE_BASE | ||||
|  | ||||
| config ARMV8_SECURE_BASE | ||||
|   | ||||
| @@ -25,3 +25,4 @@ obj-$(CONFIG_FSL_LAYERSCAPE) += fsl-layerscape/ | ||||
| obj-$(CONFIG_S32V234) += s32v234/ | ||||
| obj-$(CONFIG_ARCH_ZYNQMP) += zynqmp/ | ||||
| obj-$(CONFIG_TARGET_HIKEY) += hisilicon/ | ||||
| obj-$(CONFIG_ARMV8_PSCI) += psci.o | ||||
|   | ||||
							
								
								
									
										286
									
								
								arch/arm/cpu/armv8/psci.S
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										286
									
								
								arch/arm/cpu/armv8/psci.S
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,286 @@ | ||||
| /* | ||||
|  * Copyright 2016 Freescale Semiconductor, Inc. | ||||
|  * Author: Hongbo Zhang <hongbo.zhang@nxp.com> | ||||
|  * | ||||
|  * SPDX-License-Identifier:	GPL-2.0+ | ||||
|  * This file implements LS102X platform PSCI SYSTEM-SUSPEND function | ||||
|  */ | ||||
|  | ||||
| #include <config.h> | ||||
| #include <linux/linkage.h> | ||||
| #include <asm/psci.h> | ||||
|  | ||||
| /* Default PSCI function, return -1, Not Implemented */ | ||||
| #define PSCI_DEFAULT(__fn) \ | ||||
| 	ENTRY(__fn); \ | ||||
| 	mov	w0, #ARM_PSCI_RET_NI; \ | ||||
| 	ret; \ | ||||
| 	ENDPROC(__fn); \ | ||||
| 	.weak __fn | ||||
|  | ||||
| /* PSCI function and ID table definition*/ | ||||
| #define PSCI_TABLE(__id, __fn) \ | ||||
| 	.word __id; \ | ||||
| 	.word __fn | ||||
|  | ||||
| .pushsection ._secure.text, "ax" | ||||
|  | ||||
| /* 32 bits PSCI default functions */ | ||||
| PSCI_DEFAULT(psci_version) | ||||
| PSCI_DEFAULT(psci_cpu_suspend) | ||||
| PSCI_DEFAULT(psci_cpu_off) | ||||
| PSCI_DEFAULT(psci_cpu_on) | ||||
| PSCI_DEFAULT(psci_affinity_info) | ||||
| PSCI_DEFAULT(psci_migrate) | ||||
| PSCI_DEFAULT(psci_migrate_info_type) | ||||
| PSCI_DEFAULT(psci_migrate_info_up_cpu) | ||||
| PSCI_DEFAULT(psci_system_off) | ||||
| PSCI_DEFAULT(psci_system_reset) | ||||
| PSCI_DEFAULT(psci_features) | ||||
| PSCI_DEFAULT(psci_cpu_freeze) | ||||
| PSCI_DEFAULT(psci_cpu_default_suspend) | ||||
| PSCI_DEFAULT(psci_node_hw_state) | ||||
| PSCI_DEFAULT(psci_system_suspend) | ||||
| PSCI_DEFAULT(psci_set_suspend_mode) | ||||
| PSCI_DEFAULT(psi_stat_residency) | ||||
| PSCI_DEFAULT(psci_stat_count) | ||||
|  | ||||
| .align 3 | ||||
| _psci_32_table: | ||||
| PSCI_TABLE(ARM_PSCI_FN_CPU_SUSPEND, psci_cpu_suspend) | ||||
| PSCI_TABLE(ARM_PSCI_FN_CPU_OFF, psci_cpu_off) | ||||
| PSCI_TABLE(ARM_PSCI_FN_CPU_ON, psci_cpu_on) | ||||
| PSCI_TABLE(ARM_PSCI_FN_MIGRATE, psci_migrate) | ||||
| PSCI_TABLE(ARM_PSCI_0_2_FN_PSCI_VERSION, psci_version) | ||||
| PSCI_TABLE(ARM_PSCI_0_2_FN_CPU_SUSPEND, psci_cpu_suspend) | ||||
| PSCI_TABLE(ARM_PSCI_0_2_FN_CPU_OFF, psci_cpu_off) | ||||
| PSCI_TABLE(ARM_PSCI_0_2_FN_CPU_ON, psci_cpu_on) | ||||
| PSCI_TABLE(ARM_PSCI_0_2_FN_AFFINITY_INFO, psci_affinity_info) | ||||
| PSCI_TABLE(ARM_PSCI_0_2_FN_MIGRATE, psci_migrate) | ||||
| PSCI_TABLE(ARM_PSCI_0_2_FN_MIGRATE_INFO_TYPE, psci_migrate_info_type) | ||||
| PSCI_TABLE(ARM_PSCI_0_2_FN_MIGRATE_INFO_UP_CPU, psci_migrate_info_up_cpu) | ||||
| PSCI_TABLE(ARM_PSCI_0_2_FN_SYSTEM_OFF, psci_system_off) | ||||
| PSCI_TABLE(ARM_PSCI_0_2_FN_SYSTEM_RESET, psci_system_reset) | ||||
| PSCI_TABLE(ARM_PSCI_1_0_FN_PSCI_FEATURES, psci_features) | ||||
| PSCI_TABLE(ARM_PSCI_1_0_FN_CPU_FREEZE, psci_cpu_freeze) | ||||
| PSCI_TABLE(ARM_PSCI_1_0_FN_CPU_DEFAULT_SUSPEND, psci_cpu_default_suspend) | ||||
| PSCI_TABLE(ARM_PSCI_1_0_FN_NODE_HW_STATE, psci_node_hw_state) | ||||
| PSCI_TABLE(ARM_PSCI_1_0_FN_SYSTEM_SUSPEND, psci_system_suspend) | ||||
| PSCI_TABLE(ARM_PSCI_1_0_FN_SET_SUSPEND_MODE, psci_set_suspend_mode) | ||||
| PSCI_TABLE(ARM_PSCI_1_0_FN_STAT_RESIDENCY, psi_stat_residency) | ||||
| PSCI_TABLE(ARM_PSCI_1_0_FN_STAT_COUNT, psci_stat_count) | ||||
| PSCI_TABLE(0, 0) | ||||
|  | ||||
| /* 64 bits PSCI default functions */ | ||||
| PSCI_DEFAULT(psci_cpu_suspend_64) | ||||
| PSCI_DEFAULT(psci_cpu_on_64) | ||||
| PSCI_DEFAULT(psci_affinity_info_64) | ||||
| PSCI_DEFAULT(psci_migrate_64) | ||||
| PSCI_DEFAULT(psci_migrate_info_up_cpu_64) | ||||
| PSCI_DEFAULT(psci_cpu_default_suspend_64) | ||||
| PSCI_DEFAULT(psci_node_hw_state_64) | ||||
| PSCI_DEFAULT(psci_system_suspend_64) | ||||
| PSCI_DEFAULT(psci_stat_residency_64) | ||||
| PSCI_DEFAULT(psci_stat_count_64) | ||||
|  | ||||
| .align 3 | ||||
| _psci_64_table: | ||||
| PSCI_TABLE(ARM_PSCI_0_2_FN64_CPU_SUSPEND, psci_cpu_suspend_64) | ||||
| PSCI_TABLE(ARM_PSCI_0_2_FN64_CPU_ON, psci_cpu_on_64) | ||||
| PSCI_TABLE(ARM_PSCI_0_2_FN64_AFFINITY_INFO, psci_affinity_info_64) | ||||
| PSCI_TABLE(ARM_PSCI_0_2_FN64_MIGRATE, psci_migrate_64) | ||||
| PSCI_TABLE(ARM_PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU, psci_migrate_info_up_cpu_64) | ||||
| PSCI_TABLE(ARM_PSCI_1_0_FN64_CPU_DEFAULT_SUSPEND, psci_cpu_default_suspend_64) | ||||
| PSCI_TABLE(ARM_PSCI_1_0_FN64_NODE_HW_STATE, psci_node_hw_state_64) | ||||
| PSCI_TABLE(ARM_PSCI_1_0_FN64_SYSTEM_SUSPEND, psci_system_suspend_64) | ||||
| PSCI_TABLE(ARM_PSCI_1_0_FN64_STAT_RESIDENCY, psci_stat_residency_64) | ||||
| PSCI_TABLE(ARM_PSCI_1_0_FN64_STAT_COUNT, psci_stat_count_64) | ||||
| PSCI_TABLE(0, 0) | ||||
|  | ||||
| .macro	psci_enter | ||||
| 	/* PSCI call is Fast Call(atomic), so mask DAIF */ | ||||
| 	mrs	x15, DAIF | ||||
| 	stp	x15, xzr, [sp, #-16]! | ||||
| 	ldr	x15, =0x3C0 | ||||
| 	msr	DAIF, x15 | ||||
| 	/* SMC convention, x18 ~ x30 should be saved by callee */ | ||||
| 	stp	x29, x30, [sp, #-16]! | ||||
| 	stp	x27, x28, [sp, #-16]! | ||||
| 	stp	x25, x26, [sp, #-16]! | ||||
| 	stp	x23, x24, [sp, #-16]! | ||||
| 	stp	x21, x22, [sp, #-16]! | ||||
| 	stp	x19, x20, [sp, #-16]! | ||||
| 	mrs	x15, elr_el3 | ||||
| 	stp	x18, x15, [sp, #-16]! | ||||
| .endm | ||||
|  | ||||
| .macro	psci_return | ||||
| 	/* restore registers */ | ||||
| 	ldp	x18, x15, [sp], #16 | ||||
| 	msr	elr_el3, x15 | ||||
| 	ldp	x19, x20, [sp], #16 | ||||
| 	ldp	x21, x22, [sp], #16 | ||||
| 	ldp	x23, x24, [sp], #16 | ||||
| 	ldp	x25, x26, [sp], #16 | ||||
| 	ldp	x27, x28, [sp], #16 | ||||
| 	ldp	x29, x30, [sp], #16 | ||||
| 	/* restore DAIF */ | ||||
| 	ldp	x15, xzr, [sp], #16 | ||||
| 	msr	DAIF, x15 | ||||
| 	eret | ||||
| .endm | ||||
|  | ||||
| /* Caller must put PSCI function-ID table base in x9 */ | ||||
| handle_psci: | ||||
| 	psci_enter | ||||
| 1:	ldr x10, [x9]			/* Load PSCI function table */ | ||||
| 	ubfx x11, x10, #32, #32 | ||||
| 	ubfx x10, x10, #0, #32 | ||||
| 	cbz	x10, 3f			/* If reach the end, bail out */ | ||||
| 	cmp	x10, x0 | ||||
| 	b.eq	2f			/* PSCI function found */ | ||||
| 	add x9, x9, #8			/* If not match, try next entry */ | ||||
| 	b	1b | ||||
|  | ||||
| 2:	blr	x11			/* Call PSCI function */ | ||||
| 	psci_return | ||||
|  | ||||
| 3:	mov	x0, #ARM_PSCI_RET_NI | ||||
| 	psci_return | ||||
|  | ||||
| unknown_smc_id: | ||||
| 	ldr	x0, =0xFFFFFFFF | ||||
| 	eret | ||||
|  | ||||
| handle_smc32: | ||||
| 	/* SMC function ID  0x84000000-0x8400001F: 32 bits PSCI */ | ||||
| 	ldr	w9, =0x8400001F | ||||
| 	cmp	w0, w9 | ||||
| 	b.gt	unknown_smc_id | ||||
| 	ldr	w9, =0x84000000 | ||||
| 	cmp	w0, w9 | ||||
| 	b.lt	unknown_smc_id | ||||
|  | ||||
| 	adr	x9, _psci_32_table | ||||
| 	b	handle_psci | ||||
|  | ||||
| handle_smc64: | ||||
| 	/* check SMC32 or SMC64 calls */ | ||||
| 	ubfx	x9, x0, #30, #1 | ||||
| 	cbz	x9, handle_smc32 | ||||
|  | ||||
| 	/* SMC function ID 0xC4000000-0xC400001F: 64 bits PSCI */ | ||||
| 	ldr	x9, =0xC400001F | ||||
| 	cmp	x0, x9 | ||||
| 	b.gt	unknown_smc_id | ||||
| 	ldr	x9, =0xC4000000 | ||||
| 	cmp	x0, x9 | ||||
| 	b.lt	unknown_smc_id | ||||
|  | ||||
| 	adr	x9, _psci_64_table | ||||
| 	b	handle_psci | ||||
|  | ||||
| /* | ||||
|  * Get CPU ID from MPIDR, suppose every cluster has same number of CPU cores, | ||||
|  * Platform with asymmetric clusters should implement their own interface. | ||||
|  * In case this function being called by other platform's C code, the ARM | ||||
|  * Architecture Procedure Call Standard is considered, e.g. register X0 is | ||||
|  * used for the return value, while in this PSCI environment, X0 usually holds | ||||
|  * the SMC function identifier, so X0 should be saved by caller function. | ||||
|  */ | ||||
| ENTRY(psci_get_cpu_id) | ||||
| #ifdef CONFIG_ARMV8_PSCI_CPUS_PER_CLUSTER | ||||
| 	mrs	x9, MPIDR_EL1 | ||||
| 	ubfx	x9, x9, #8, #8 | ||||
| 	ldr	x10, =CONFIG_ARMV8_PSCI_CPUS_PER_CLUSTER | ||||
| 	mul	x9, x10, x9 | ||||
| #else | ||||
| 	mov	x9, xzr | ||||
| #endif | ||||
| 	mrs	x10, MPIDR_EL1 | ||||
| 	ubfx	x10, x10, #0, #8 | ||||
| 	add	x0, x10, x9 | ||||
| 	ret | ||||
| ENDPROC(psci_get_cpu_id) | ||||
| .weak psci_get_cpu_id | ||||
|  | ||||
| /* CPU ID input in x0, stack top output in x0*/ | ||||
| LENTRY(psci_get_cpu_stack_top) | ||||
| 	adr	x9, __secure_stack_end | ||||
| 	lsl	x0, x0, #ARM_PSCI_STACK_SHIFT | ||||
| 	sub	x0, x9, x0 | ||||
| 	ret | ||||
| ENDPROC(psci_get_cpu_stack_top) | ||||
|  | ||||
| unhandled_exception: | ||||
| 	b	unhandled_exception	/* simply dead loop */ | ||||
|  | ||||
| handle_sync: | ||||
| 	mov	x15, x30 | ||||
| 	mov	x14, x0 | ||||
|  | ||||
| 	bl	psci_get_cpu_id | ||||
| 	bl	psci_get_cpu_stack_top | ||||
| 	mov	x9, #1 | ||||
| 	msr	spsel, x9 | ||||
| 	mov	sp, x0 | ||||
|  | ||||
| 	mov	x0, x14 | ||||
| 	mov	x30, x15 | ||||
|  | ||||
| 	mrs	x9, esr_el3 | ||||
| 	ubfx	x9, x9, #26, #6 | ||||
| 	cmp	x9, #0x13 | ||||
| 	b.eq	handle_smc32 | ||||
| 	cmp	x9, #0x17 | ||||
| 	b.eq	handle_smc64 | ||||
|  | ||||
| 	b	unhandled_exception | ||||
|  | ||||
| 	.align	11 | ||||
| 	.globl	el3_exception_vectors | ||||
| el3_exception_vectors: | ||||
| 	b	unhandled_exception	/* Sync, Current EL using SP0 */ | ||||
| 	.align	7 | ||||
| 	b	unhandled_exception	/* IRQ, Current EL using SP0 */ | ||||
| 	.align	7 | ||||
| 	b	unhandled_exception	/* FIQ, Current EL using SP0 */ | ||||
| 	.align	7 | ||||
| 	b	unhandled_exception	/* SError, Current EL using SP0 */ | ||||
| 	.align	7 | ||||
| 	b	unhandled_exception	/* Sync, Current EL using SPx */ | ||||
| 	.align	7 | ||||
| 	b	unhandled_exception	/* IRQ, Current EL using SPx */ | ||||
| 	.align	7 | ||||
| 	b	unhandled_exception	/* FIQ, Current EL using SPx */ | ||||
| 	.align	7 | ||||
| 	b	unhandled_exception	/* SError, Current EL using SPx */ | ||||
| 	.align	7 | ||||
| 	b	handle_sync		/* Sync, Lower EL using AArch64 */ | ||||
| 	.align	7 | ||||
| 	b	unhandled_exception	/* IRQ, Lower EL using AArch64 */ | ||||
| 	.align	7 | ||||
| 	b	unhandled_exception	/* FIQ, Lower EL using AArch64 */ | ||||
| 	.align	7 | ||||
| 	b	unhandled_exception	/* SError, Lower EL using AArch64 */ | ||||
| 	.align	7 | ||||
| 	b	unhandled_exception	/* Sync, Lower EL using AArch32 */ | ||||
| 	.align	7 | ||||
| 	b	unhandled_exception	/* IRQ, Lower EL using AArch32 */ | ||||
| 	.align	7 | ||||
| 	b	unhandled_exception	/* FIQ, Lower EL using AArch32 */ | ||||
| 	.align	7 | ||||
| 	b	unhandled_exception	/* SError, Lower EL using AArch32 */ | ||||
|  | ||||
| ENTRY(psci_setup_vectors) | ||||
| 	adr	x0, el3_exception_vectors | ||||
| 	msr	vbar_el3, x0 | ||||
| 	ret | ||||
| ENDPROC(psci_setup_vectors) | ||||
|  | ||||
| ENTRY(psci_arch_init) | ||||
| 	ret | ||||
| ENDPROC(psci_arch_init) | ||||
| .weak psci_arch_init | ||||
|  | ||||
| .popsection | ||||
| @@ -45,6 +45,9 @@ | ||||
| #define ARM_PSCI_0_2_FN_BASE			0x84000000 | ||||
| #define ARM_PSCI_0_2_FN(n)			(ARM_PSCI_0_2_FN_BASE + (n)) | ||||
|  | ||||
| #define ARM_PSCI_0_2_FN64_BASE			0xC4000000 | ||||
| #define ARM_PSCI_0_2_FN64(n)			(ARM_PSCI_0_2_FN64_BASE + (n)) | ||||
|  | ||||
| #define ARM_PSCI_0_2_FN_PSCI_VERSION		ARM_PSCI_0_2_FN(0) | ||||
| #define ARM_PSCI_0_2_FN_CPU_SUSPEND		ARM_PSCI_0_2_FN(1) | ||||
| #define ARM_PSCI_0_2_FN_CPU_OFF			ARM_PSCI_0_2_FN(2) | ||||
| @@ -56,6 +59,12 @@ | ||||
| #define ARM_PSCI_0_2_FN_SYSTEM_OFF		ARM_PSCI_0_2_FN(8) | ||||
| #define ARM_PSCI_0_2_FN_SYSTEM_RESET		ARM_PSCI_0_2_FN(9) | ||||
|  | ||||
| #define ARM_PSCI_0_2_FN64_CPU_SUSPEND		ARM_PSCI_0_2_FN64(1) | ||||
| #define ARM_PSCI_0_2_FN64_CPU_ON		ARM_PSCI_0_2_FN64(3) | ||||
| #define ARM_PSCI_0_2_FN64_AFFINITY_INFO		ARM_PSCI_0_2_FN64(4) | ||||
| #define ARM_PSCI_0_2_FN64_MIGRATE		ARM_PSCI_0_2_FN64(5) | ||||
| #define ARM_PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU	ARM_PSCI_0_2_FN64(7) | ||||
|  | ||||
| /* PSCI 1.0 interface */ | ||||
| #define ARM_PSCI_1_0_FN_PSCI_FEATURES		ARM_PSCI_0_2_FN(10) | ||||
| #define ARM_PSCI_1_0_FN_CPU_FREEZE		ARM_PSCI_0_2_FN(11) | ||||
| @@ -66,6 +75,12 @@ | ||||
| #define ARM_PSCI_1_0_FN_STAT_RESIDENCY		ARM_PSCI_0_2_FN(16) | ||||
| #define ARM_PSCI_1_0_FN_STAT_COUNT		ARM_PSCI_0_2_FN(17) | ||||
|  | ||||
| #define ARM_PSCI_1_0_FN64_CPU_DEFAULT_SUSPEND	ARM_PSCI_0_2_FN64(12) | ||||
| #define ARM_PSCI_1_0_FN64_NODE_HW_STATE		ARM_PSCI_0_2_FN64(13) | ||||
| #define ARM_PSCI_1_0_FN64_SYSTEM_SUSPEND	ARM_PSCI_0_2_FN64(14) | ||||
| #define ARM_PSCI_1_0_FN64_STAT_RESIDENCY	ARM_PSCI_0_2_FN64(16) | ||||
| #define ARM_PSCI_1_0_FN64_STAT_COUNT		ARM_PSCI_0_2_FN64(17) | ||||
|  | ||||
| /* 1KB stack per core */ | ||||
| #define ARM_PSCI_STACK_SHIFT	10 | ||||
| #define ARM_PSCI_STACK_SIZE	(1 << ARM_PSCI_STACK_SHIFT) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user