arm: omap5: Add function to make an SMC call on cpu1
authorHarinarayan Bhatta <harinarayan@ti.com>
Tue, 29 Nov 2016 22:33:22 +0000 (16:33 -0600)
committerTom Rini <trini@konsulko.com>
Sat, 3 Dec 2016 18:21:20 +0000 (13:21 -0500)
On DRA7xx platform, CPU Core 1 is not used in u-boot. However, in some
cases it is need to make secure API calls from Core 1. This patch adds
an assembly function to make a secure (SMC) call from CPU Core #1.

Signed-off-by: Harinarayan Bhatta <harinarayan@ti.com>
Signed-off-by: Andrew F. Davis <afd@ti.com>
Reviewed-by: Tom Rini <trini@konsulko.com>
arch/arm/include/asm/omap_common.h
arch/arm/mach-omap2/omap5/Makefile
arch/arm/mach-omap2/omap5/sec_entry_cpu1.S [new file with mode: 0644]

index 605c549f0a5a647b84874d7cd4ed108762c63cc5..290a190c7b59f1be0654e40d7443228c6e088b98 100644 (file)
@@ -632,6 +632,7 @@ void omap_smc1(u32 service, u32 val);
  * security (HS) device variants by doing a specially-formed smc entry.
  */
 u32 omap_smc_sec(u32 service, u32 proc_id, u32 flag, u32 *params);
+u32 omap_smc_sec_cpu1(u32 service, u32 proc_id, u32 flag, u32 *params);
 
 void enable_edma3_clocks(void);
 void disable_edma3_clocks(void);
index 0212df73c154d90a265736a74de076f8b7053bf6..af17a3deab173aab9b67e0a764f53b3b5cba8ea0 100644 (file)
@@ -15,3 +15,4 @@ obj-y += abb.o
 obj-y  += fdt.o
 obj-$(CONFIG_IODELAY_RECALIBRATION) += dra7xx_iodelay.o
 obj-$(CONFIG_TI_SECURE_DEVICE) += sec-fxns.o
+obj-$(CONFIG_DRA7XX) += sec_entry_cpu1.o
diff --git a/arch/arm/mach-omap2/omap5/sec_entry_cpu1.S b/arch/arm/mach-omap2/omap5/sec_entry_cpu1.S
new file mode 100644 (file)
index 0000000..c2a35ee
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * Secure entry function for CPU Core #1
+ *
+ * (C) Copyright 2016
+ * Texas Instruments, <www.ti.com>
+ *
+ * Author :
+ *     Harinarayan Bhatta <harinarayan@ti.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <config.h>
+#include <asm/arch/omap.h>
+#include <asm/omap_common.h>
+#include <linux/linkage.h>
+
+.arch_extension sec
+
+#if !defined(CONFIG_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 !defined(CONFIG_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 !defined(CONFIG_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)