diff options
Diffstat (limited to 'arch/arm/mach-bcm/bcm_kona_smc.c')
-rw-r--r-- | arch/arm/mach-bcm/bcm_kona_smc.c | 46 |
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 | */ | ||
91 | static 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 */ |
80 | static void __bcm_kona_smc(void *info) | 124 | static 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 | ||
101 | unsigned bcm_kona_smc(unsigned service_id, unsigned arg0, unsigned arg1, | 145 | unsigned bcm_kona_smc(unsigned service_id, unsigned arg0, unsigned arg1, |