aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-bcm/bcm_kona_smc.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-bcm/bcm_kona_smc.c')
-rw-r--r--arch/arm/mach-bcm/bcm_kona_smc.c46
1 files changed, 45 insertions, 1 deletions
diff --git a/arch/arm/mach-bcm/bcm_kona_smc.c b/arch/arm/mach-bcm/bcm_kona_smc.c
index 6fdcf96ca54e..cc81c86f24b5 100644
--- a/arch/arm/mach-bcm/bcm_kona_smc.c
+++ b/arch/arm/mach-bcm/bcm_kona_smc.c
@@ -76,6 +76,50 @@ int __init bcm_kona_smc_init(void)
76 return 0; 76 return 0;
77} 77}
78 78
79/*
80 * Since interrupts are disabled in the open mode, we must keep
81 * interrupts disabled in secure mode by setting R5=0x3. If interrupts
82 * are enabled in open mode, we can set R5=0x0 to allow interrupts in
83 * secure mode. If we did this, the secure monitor would return back
84 * control to the open mode to handle the interrupt prior to completing
85 * the secure service. If this happened, R12 would not be
86 * SEC_EXIT_NORMAL and we would need to call SMC again after resetting
87 * R5 (it gets clobbered by the secure monitor) and setting R4 to
88 * SSAPI_RET_FROM_INT_SERV to indicate that we want the secure monitor
89 * to finish up the previous uncompleted secure service.
90 */
91static int bcm_kona_do_smc(u32 service_id, u32 buffer_phys)
92{
93 register u32 ip asm("ip"); /* Also called r12 */
94 register u32 r0 asm("r0");
95 register u32 r4 asm("r4");
96 register u32 r5 asm("r5");
97 register u32 r6 asm("r6");
98
99 r4 = service_id;
100 r5 = 0x3; /* Keep IRQ and FIQ off in SM */
101 r6 = buffer_phys;
102
103 asm volatile (
104 /* Make sure we got the registers we want */
105 __asmeq("%0", "ip")
106 __asmeq("%1", "r0")
107 __asmeq("%2", "r4")
108 __asmeq("%3", "r5")
109 __asmeq("%4", "r6")
110#ifdef REQUIRES_SEC
111 ".arch_extension sec\n"
112#endif
113 " smc #0\n"
114 : "=r" (ip), "=r" (r0)
115 : "r" (r4), "r" (r5), "r" (r6)
116 : "r1", "r2", "r3", "r7", "lr");
117
118 BUG_ON(ip != SEC_EXIT_NORMAL);
119
120 return r0;
121}
122
79/* __bcm_kona_smc() should only run on CPU 0, with pre-emption disabled */ 123/* __bcm_kona_smc() should only run on CPU 0, with pre-emption disabled */
80static void __bcm_kona_smc(void *info) 124static void __bcm_kona_smc(void *info)
81{ 125{
@@ -95,7 +139,7 @@ static void __bcm_kona_smc(void *info)
95 flush_cache_all(); 139 flush_cache_all();
96 140
97 /* Trap into Secure Monitor and record the request result */ 141 /* Trap into Secure Monitor and record the request result */
98 data->result = bcm_kona_smc_asm(data->service_id, bcm_smc_buffer_phys); 142 data->result = bcm_kona_do_smc(data->service_id, bcm_smc_buffer_phys);
99} 143}
100 144
101unsigned bcm_kona_smc(unsigned service_id, unsigned arg0, unsigned arg1, 145unsigned bcm_kona_smc(unsigned service_id, unsigned arg0, unsigned arg1,