1*4882a593Smuzhiyun/* 2*4882a593Smuzhiyun * Secure entry function for CPU Core #1 3*4882a593Smuzhiyun * 4*4882a593Smuzhiyun * (C) Copyright 2016 5*4882a593Smuzhiyun * Texas Instruments, <www.ti.com> 6*4882a593Smuzhiyun * 7*4882a593Smuzhiyun * Author : 8*4882a593Smuzhiyun * Harinarayan Bhatta <harinarayan@ti.com> 9*4882a593Smuzhiyun * 10*4882a593Smuzhiyun * SPDX-License-Identifier: GPL-2.0+ 11*4882a593Smuzhiyun */ 12*4882a593Smuzhiyun 13*4882a593Smuzhiyun#include <config.h> 14*4882a593Smuzhiyun#include <asm/arch/omap.h> 15*4882a593Smuzhiyun#include <asm/omap_common.h> 16*4882a593Smuzhiyun#include <linux/linkage.h> 17*4882a593Smuzhiyun 18*4882a593Smuzhiyun.arch_extension sec 19*4882a593Smuzhiyun 20*4882a593Smuzhiyun#if !defined(CONFIG_SYS_DCACHE_OFF) 21*4882a593Smuzhiyun.global flush_dcache_range 22*4882a593Smuzhiyun#endif 23*4882a593Smuzhiyun 24*4882a593Smuzhiyun#define AUX_CORE_BOOT_0 0x48281800 25*4882a593Smuzhiyun#define AUX_CORE_BOOT_1 0x48281804 26*4882a593Smuzhiyun 27*4882a593Smuzhiyun#ifdef CONFIG_DRA7XX 28*4882a593Smuzhiyun/* DRA7xx ROM code function "startup_BootSlave". This function is where CPU1 29*4882a593Smuzhiyun * waits on WFE, polling on AUX_CORE_BOOT_x registers. 30*4882a593Smuzhiyun * This address is same for J6 and J6 Eco. 31*4882a593Smuzhiyun */ 32*4882a593Smuzhiyun#define ROM_FXN_STARTUP_BOOTSLAVE 0x00038a64 33*4882a593Smuzhiyun#endif 34*4882a593Smuzhiyun 35*4882a593Smuzhiyun/* Assembly core where CPU1 is woken up into 36*4882a593Smuzhiyun * No need to save-restore registers, does not use stack. 37*4882a593Smuzhiyun */ 38*4882a593SmuzhiyunLENTRY(cpu1_entry) 39*4882a593Smuzhiyun ldr r4, =omap_smc_sec_cpu1_args 40*4882a593Smuzhiyun ldm r4, {r0,r1,r2,r3} @ Retrieve args 41*4882a593Smuzhiyun 42*4882a593Smuzhiyun mov r6, #0xFF @ Indicate new Task call 43*4882a593Smuzhiyun mov r12, #0x00 @ Secure Service ID in R12 44*4882a593Smuzhiyun 45*4882a593Smuzhiyun dsb 46*4882a593Smuzhiyun dmb 47*4882a593Smuzhiyun smc 0 @ SMC #0 to enter monitor mode 48*4882a593Smuzhiyun 49*4882a593Smuzhiyun b .Lend @ exit at end of the service execution 50*4882a593Smuzhiyun nop 51*4882a593Smuzhiyun 52*4882a593Smuzhiyun @ In case of IRQ happening in Secure, then ARM will branch here. 53*4882a593Smuzhiyun @ At that moment, IRQ will be pending and ARM will jump to Non Secure 54*4882a593Smuzhiyun @ IRQ handler 55*4882a593Smuzhiyun mov r12, #0xFE 56*4882a593Smuzhiyun 57*4882a593Smuzhiyun dsb 58*4882a593Smuzhiyun dmb 59*4882a593Smuzhiyun smc 0 @ SMC #0 to enter monitor mode 60*4882a593Smuzhiyun 61*4882a593Smuzhiyun.Lend: 62*4882a593Smuzhiyun ldr r4, =omap_smc_sec_cpu1_args 63*4882a593Smuzhiyun str r0, [r4, #0x10] @ save return value 64*4882a593Smuzhiyun ldr r4, =AUX_CORE_BOOT_0 65*4882a593Smuzhiyun mov r5, #0x0 66*4882a593Smuzhiyun str r5, [r4] 67*4882a593Smuzhiyun ldr r4, =ROM_FXN_STARTUP_BOOTSLAVE 68*4882a593Smuzhiyun sev @ Tell CPU0 we are done 69*4882a593Smuzhiyun bx r4 @ Jump back to ROM 70*4882a593SmuzhiyunEND(cpu1_entry) 71*4882a593Smuzhiyun 72*4882a593Smuzhiyun/* 73*4882a593Smuzhiyun * u32 omap_smc_sec_cpu1(u32 service, u32 proc_id, u32 flag, u32 *params); 74*4882a593Smuzhiyun * 75*4882a593Smuzhiyun * Makes a secure ROM/PPA call on CPU Core #1 on supported platforms. 76*4882a593Smuzhiyun * Assumes that CPU #1 is waiting in ROM code and not yet woken up or used by 77*4882a593Smuzhiyun * u-boot. 78*4882a593Smuzhiyun */ 79*4882a593SmuzhiyunENTRY(omap_smc_sec_cpu1) 80*4882a593Smuzhiyun push {r4, r5, lr} 81*4882a593Smuzhiyun ldr r4, =omap_smc_sec_cpu1_args 82*4882a593Smuzhiyun stm r4, {r0,r1,r2,r3} @ Save args to memory 83*4882a593Smuzhiyun#if !defined(CONFIG_SYS_DCACHE_OFF) 84*4882a593Smuzhiyun mov r0, r4 85*4882a593Smuzhiyun mov r1, #CONFIG_SYS_CACHELINE_SIZE 86*4882a593Smuzhiyun add r1, r0, r1 @ dcache is not enabled on CPU1, so 87*4882a593Smuzhiyun blx flush_dcache_range @ flush the cache on args buffer 88*4882a593Smuzhiyun#endif 89*4882a593Smuzhiyun ldr r4, =AUX_CORE_BOOT_1 90*4882a593Smuzhiyun ldr r5, =cpu1_entry 91*4882a593Smuzhiyun str r5, [r4] @ Setup CPU1 entry function 92*4882a593Smuzhiyun ldr r4, =AUX_CORE_BOOT_0 93*4882a593Smuzhiyun mov r5, #0x10 94*4882a593Smuzhiyun str r5, [r4] @ Tell ROM to exit while loop 95*4882a593Smuzhiyun sev @ Wake up CPU1 96*4882a593Smuzhiyun.Lwait: 97*4882a593Smuzhiyun wfe @ Wait for CPU1 to finish 98*4882a593Smuzhiyun nop 99*4882a593Smuzhiyun ldr r5, [r4] @ Check if CPU1 is done 100*4882a593Smuzhiyun cmp r5, #0 101*4882a593Smuzhiyun bne .Lwait 102*4882a593Smuzhiyun 103*4882a593Smuzhiyun ldr r4, =omap_smc_sec_cpu1_args 104*4882a593Smuzhiyun ldr r0, [r4, #0x10] @ Retrieve return value 105*4882a593Smuzhiyun pop {r4, r5, pc} 106*4882a593SmuzhiyunENDPROC(omap_smc_sec_cpu1) 107*4882a593Smuzhiyun 108*4882a593Smuzhiyun/* 109*4882a593Smuzhiyun * Buffer to save function arguments and return value for omap_smc_sec_cpu1 110*4882a593Smuzhiyun */ 111*4882a593Smuzhiyun.section .data 112*4882a593Smuzhiyunomap_smc_sec_cpu1_args: 113*4882a593Smuzhiyun#if !defined(CONFIG_SYS_DCACHE_OFF) 114*4882a593Smuzhiyun .balign CONFIG_SYS_CACHELINE_SIZE 115*4882a593Smuzhiyun .rept CONFIG_SYS_CACHELINE_SIZE/4 116*4882a593Smuzhiyun .word 0 117*4882a593Smuzhiyun .endr 118*4882a593Smuzhiyun#else 119*4882a593Smuzhiyun .rept 5 120*4882a593Smuzhiyun .word 0 121*4882a593Smuzhiyun .endr 122*4882a593Smuzhiyun#endif 123*4882a593SmuzhiyunEND(omap_smc_sec_cpu1_args) 124