aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-qcom/scm.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-qcom/scm.c')
-rw-r--r--arch/arm/mach-qcom/scm.c31
1 files changed, 23 insertions, 8 deletions
diff --git a/arch/arm/mach-qcom/scm.c b/arch/arm/mach-qcom/scm.c
index c536fd6bf827..820c72165e19 100644
--- a/arch/arm/mach-qcom/scm.c
+++ b/arch/arm/mach-qcom/scm.c
@@ -22,6 +22,7 @@
22#include <linux/errno.h> 22#include <linux/errno.h>
23#include <linux/err.h> 23#include <linux/err.h>
24 24
25#include <asm/outercache.h>
25#include <asm/cacheflush.h> 26#include <asm/cacheflush.h>
26 27
27#include "scm.h" 28#include "scm.h"
@@ -203,6 +204,7 @@ static int __scm_call(const struct scm_command *cmd)
203 * side in the buffer. 204 * side in the buffer.
204 */ 205 */
205 flush_cache_all(); 206 flush_cache_all();
207 outer_flush_all();
206 ret = smc(cmd_addr); 208 ret = smc(cmd_addr);
207 if (ret < 0) 209 if (ret < 0)
208 ret = scm_remap_error(ret); 210 ret = scm_remap_error(ret);
@@ -210,6 +212,20 @@ static int __scm_call(const struct scm_command *cmd)
210 return ret; 212 return ret;
211} 213}
212 214
215static void scm_inv_range(unsigned long start, unsigned long end)
216{
217 start = round_down(start, CACHELINESIZE);
218 end = round_up(end, CACHELINESIZE);
219 outer_inv_range(start, end);
220 while (start < end) {
221 asm ("mcr p15, 0, %0, c7, c6, 1" : : "r" (start)
222 : "memory");
223 start += CACHELINESIZE;
224 }
225 dsb();
226 isb();
227}
228
213/** 229/**
214 * scm_call() - Send an SCM command 230 * scm_call() - Send an SCM command
215 * @svc_id: service identifier 231 * @svc_id: service identifier
@@ -227,6 +243,7 @@ int scm_call(u32 svc_id, u32 cmd_id, const void *cmd_buf, size_t cmd_len,
227 int ret; 243 int ret;
228 struct scm_command *cmd; 244 struct scm_command *cmd;
229 struct scm_response *rsp; 245 struct scm_response *rsp;
246 unsigned long start, end;
230 247
231 cmd = alloc_scm_command(cmd_len, resp_len); 248 cmd = alloc_scm_command(cmd_len, resp_len);
232 if (!cmd) 249 if (!cmd)
@@ -243,17 +260,15 @@ int scm_call(u32 svc_id, u32 cmd_id, const void *cmd_buf, size_t cmd_len,
243 goto out; 260 goto out;
244 261
245 rsp = scm_command_to_response(cmd); 262 rsp = scm_command_to_response(cmd);
263 start = (unsigned long)rsp;
264
246 do { 265 do {
247 u32 start = (u32)rsp; 266 scm_inv_range(start, start + sizeof(*rsp));
248 u32 end = (u32)scm_get_response_buffer(rsp) + resp_len;
249 start &= ~(CACHELINESIZE - 1);
250 while (start < end) {
251 asm ("mcr p15, 0, %0, c7, c6, 1" : : "r" (start)
252 : "memory");
253 start += CACHELINESIZE;
254 }
255 } while (!rsp->is_complete); 267 } while (!rsp->is_complete);
256 268
269 end = (unsigned long)scm_get_response_buffer(rsp) + resp_len;
270 scm_inv_range(start, end);
271
257 if (resp_buf) 272 if (resp_buf)
258 memcpy(resp_buf, scm_get_response_buffer(rsp), resp_len); 273 memcpy(resp_buf, scm_get_response_buffer(rsp), resp_len);
259out: 274out: