123 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
			
		
		
	
	
			123 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
| /* SPDX-License-Identifier: GPL-2.0+ */
 | |
| /*
 | |
|  * Secure entry function for CPU Core #1
 | |
|  *
 | |
|  * (C) Copyright 2016
 | |
|  * Texas Instruments, <www.ti.com>
 | |
|  *
 | |
|  * Author :
 | |
|  *	Harinarayan Bhatta <harinarayan@ti.com>
 | |
|  */
 | |
| 
 | |
| #include <config.h>
 | |
| #include <asm/arch/omap.h>
 | |
| #include <asm/omap_common.h>
 | |
| #include <linux/linkage.h>
 | |
| 
 | |
| .arch_extension sec
 | |
| 
 | |
| #if !CONFIG_IS_ENABLED(SYS_DCACHE_OFF)
 | |
| .global flush_dcache_range
 | |
| #endif
 | |
| 
 | |
| #define AUX_CORE_BOOT_0		0x48281800
 | |
| #define AUX_CORE_BOOT_1		0x48281804
 | |
| 
 | |
| #ifdef CONFIG_DRA7XX
 | |
| /* DRA7xx ROM code function "startup_BootSlave". This function is where CPU1
 | |
|  * waits on WFE, polling on AUX_CORE_BOOT_x registers.
 | |
|  * This address is same for J6 and J6 Eco.
 | |
|  */
 | |
| #define ROM_FXN_STARTUP_BOOTSLAVE     0x00038a64
 | |
| #endif
 | |
| 
 | |
| /* Assembly core where CPU1 is woken up into
 | |
|  * No need to save-restore registers, does not use stack.
 | |
|  */
 | |
| LENTRY(cpu1_entry)
 | |
| 	ldr	r4, =omap_smc_sec_cpu1_args
 | |
| 	ldm	r4, {r0,r1,r2,r3}	@ Retrieve args
 | |
| 
 | |
| 	mov	r6, #0xFF	@ Indicate new Task call
 | |
| 	mov	r12, #0x00	@ Secure Service ID in R12
 | |
| 
 | |
| 	dsb
 | |
| 	dmb
 | |
| 	smc	0		@ SMC #0 to enter monitor mode
 | |
| 
 | |
| 	b	.Lend		@ exit at end of the service execution
 | |
| 	nop
 | |
| 
 | |
| 	@ In case of IRQ happening in Secure, then ARM will branch here.
 | |
| 	@ At that moment, IRQ will be pending and ARM will jump to Non Secure
 | |
| 	@ IRQ handler
 | |
| 	mov	r12, #0xFE
 | |
| 
 | |
| 	dsb
 | |
| 	dmb
 | |
| 	smc	0		@ SMC #0 to enter monitor mode
 | |
| 
 | |
| .Lend:
 | |
| 	ldr	r4, =omap_smc_sec_cpu1_args
 | |
| 	str	r0, [r4, #0x10]		@ save return value
 | |
| 	ldr	r4, =AUX_CORE_BOOT_0
 | |
| 	mov	r5, #0x0
 | |
| 	str	r5, [r4]
 | |
| 	ldr	r4, =ROM_FXN_STARTUP_BOOTSLAVE
 | |
| 	sev				@ Tell CPU0 we are done
 | |
| 	bx	r4			@ Jump back to ROM
 | |
| END(cpu1_entry)
 | |
| 
 | |
| /*
 | |
|  * u32 omap_smc_sec_cpu1(u32 service, u32 proc_id, u32 flag, u32 *params);
 | |
|  *
 | |
|  * Makes a secure ROM/PPA call on CPU Core #1 on supported platforms.
 | |
|  * Assumes that CPU #1 is waiting in ROM code and not yet woken up or used by
 | |
|  * u-boot.
 | |
|  */
 | |
| ENTRY(omap_smc_sec_cpu1)
 | |
| 	push	{r4, r5, lr}
 | |
| 	ldr	r4, =omap_smc_sec_cpu1_args
 | |
| 	stm	r4, {r0,r1,r2,r3}	@ Save args to memory
 | |
| #if !CONFIG_IS_ENABLED(SYS_DCACHE_OFF)
 | |
| 	mov	r0, r4
 | |
| 	mov	r1, #CONFIG_SYS_CACHELINE_SIZE
 | |
| 	add	r1, r0, r1		@ dcache is not enabled on CPU1, so
 | |
| 	blx	flush_dcache_range	@ flush the cache on args buffer
 | |
| #endif
 | |
| 	ldr	r4, =AUX_CORE_BOOT_1
 | |
| 	ldr	r5, =cpu1_entry
 | |
| 	str	r5, [r4]		@ Setup CPU1 entry function
 | |
| 	ldr	r4, =AUX_CORE_BOOT_0
 | |
| 	mov	r5, #0x10
 | |
| 	str	r5, [r4]		@ Tell ROM to exit while loop
 | |
| 	sev				@ Wake up CPU1
 | |
| .Lwait:
 | |
| 	wfe				@ Wait for CPU1 to finish
 | |
| 	nop
 | |
| 	ldr	r5, [r4]		@ Check if CPU1 is done
 | |
| 	cmp	r5, #0
 | |
| 	bne	.Lwait
 | |
| 
 | |
| 	ldr	r4, =omap_smc_sec_cpu1_args
 | |
| 	ldr	r0, [r4, #0x10]         @ Retrieve return value
 | |
| 	pop	{r4, r5, pc}
 | |
| ENDPROC(omap_smc_sec_cpu1)
 | |
| 
 | |
| /*
 | |
|  * Buffer to save function arguments and return value for omap_smc_sec_cpu1
 | |
|  */
 | |
| .section .data
 | |
| omap_smc_sec_cpu1_args:
 | |
| #if !CONFIG_IS_ENABLED(SYS_DCACHE_OFF)
 | |
| 	.balign CONFIG_SYS_CACHELINE_SIZE
 | |
| 	.rept  CONFIG_SYS_CACHELINE_SIZE/4
 | |
| 	.word 0
 | |
| 	.endr
 | |
| #else
 | |
| 	.rept 5
 | |
| 	.word 0
 | |
| 	.endr
 | |
| #endif
 | |
| END(omap_smc_sec_cpu1_args)
 |