]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/firmware/qcom_scm-64.c
e785f9cfadd19290faaf2f336eba43aeb491bbc4
[karo-tx-linux.git] / drivers / firmware / qcom_scm-64.c
1 /* Copyright (c) 2015, The Linux Foundation. All rights reserved.
2  *
3  * This program is free software; you can redistribute it and/or modify
4  * it under the terms of the GNU General Public License version 2 and
5  * only version 2 as published by the Free Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15  * 02110-1301, USA.
16  */
17
18 #include <linux/platform_device.h>
19 #include <linux/cpumask.h>
20 #include <linux/delay.h>
21 #include <linux/mutex.h>
22 #include <linux/slab.h>
23 #include <linux/types.h>
24 #include <linux/qcom_scm.h>
25 #include <linux/dma-mapping.h>
26
27 #include <asm/cacheflush.h>
28 #include <asm/compiler.h>
29 #include <asm/smp_plat.h>
30
31 #include "qcom_scm.h"
32
33 #define QCOM_SCM_SIP_FNID(s, c) (((((s) & 0xFF) << 8) | ((c) & 0xFF)) | 0x02000000)
34
35 #define MAX_QCOM_SCM_ARGS 10
36 #define MAX_QCOM_SCM_RETS 3
37
38 enum qcom_scm_arg_types {
39         QCOM_SCM_VAL,
40         QCOM_SCM_RO,
41         QCOM_SCM_RW,
42         QCOM_SCM_BUFVAL,
43 };
44
45 #define QCOM_SCM_ARGS_IMPL(num, a, b, c, d, e, f, g, h, i, j, ...) (\
46                         (((a) & 0xff) << 4) | \
47                         (((b) & 0xff) << 6) | \
48                         (((c) & 0xff) << 8) | \
49                         (((d) & 0xff) << 10) | \
50                         (((e) & 0xff) << 12) | \
51                         (((f) & 0xff) << 14) | \
52                         (((g) & 0xff) << 16) | \
53                         (((h) & 0xff) << 18) | \
54                         (((i) & 0xff) << 20) | \
55                         (((j) & 0xff) << 22) | \
56                         (num & 0xffff))
57
58 #define QCOM_SCM_ARGS(...) QCOM_SCM_ARGS_IMPL(__VA_ARGS__, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
59
60 /**
61  * struct qcom_scm_desc
62  * @arginfo: Metadata describing the arguments in args[]
63  * @args: The array of arguments for the secure syscall
64  * @ret: The values returned by the secure syscall
65  * @extra_arg_buf: The buffer containing extra arguments
66                    (that don't fit in available registers)
67  * @x5: The 4rd argument to the secure syscall or physical address of
68         extra_arg_buf
69  */
70 struct qcom_scm_desc {
71         u32 arginfo;
72         u64 args[MAX_QCOM_SCM_ARGS];
73         u64 ret[MAX_QCOM_SCM_RETS];
74
75         /* private */
76         void *extra_arg_buf;
77         u64 x5;
78 };
79
80
81 #define QCOM_SCM_ENOMEM         -5
82 #define QCOM_SCM_EOPNOTSUPP     -4
83 #define QCOM_SCM_EINVAL_ADDR    -3
84 #define QCOM_SCM_EINVAL_ARG     -2
85 #define QCOM_SCM_ERROR          -1
86 #define QCOM_SCM_INTERRUPTED    1
87 #define QCOM_SCM_EBUSY          -55
88 #define QCOM_SCM_V2_EBUSY       -12
89
90 static DEFINE_MUTEX(qcom_scm_lock);
91
92 #define QCOM_SCM_EBUSY_WAIT_MS 30
93 #define QCOM_SCM_EBUSY_MAX_RETRY 20
94
95 #define N_EXT_QCOM_SCM_ARGS 7
96 #define FIRST_EXT_ARG_IDX 3
97 #define SMC_ATOMIC_SYSCALL 31
98 #define N_REGISTER_ARGS (MAX_QCOM_SCM_ARGS - N_EXT_QCOM_SCM_ARGS + 1)
99 #define SMC64_MASK 0x40000000
100 #define SMC_ATOMIC_MASK 0x80000000
101 #define IS_CALL_AVAIL_CMD 1
102
103 #define R0_STR "x0"
104 #define R1_STR "x1"
105 #define R2_STR "x2"
106 #define R3_STR "x3"
107 #define R4_STR "x4"
108 #define R5_STR "x5"
109 #define R6_STR "x6"
110
111
112 int __qcom_scm_call_armv8_64(u64 x0, u64 x1, u64 x2, u64 x3, u64 x4, u64 x5,
113                                 u64 *ret1, u64 *ret2, u64 *ret3)
114 {
115         register u64 r0 asm("r0") = x0;
116         register u64 r1 asm("r1") = x1;
117         register u64 r2 asm("r2") = x2;
118         register u64 r3 asm("r3") = x3;
119         register u64 r4 asm("r4") = x4;
120         register u64 r5 asm("r5") = x5;
121         register u64 r6 asm("r6") = 0;
122
123         do {
124                 asm volatile(
125                         __asmeq("%0", R0_STR)
126                         __asmeq("%1", R1_STR)
127                         __asmeq("%2", R2_STR)
128                         __asmeq("%3", R3_STR)
129                         __asmeq("%4", R0_STR)
130                         __asmeq("%5", R1_STR)
131                         __asmeq("%6", R2_STR)
132                         __asmeq("%7", R3_STR)
133                         __asmeq("%8", R4_STR)
134                         __asmeq("%9", R5_STR)
135                         __asmeq("%10", R6_STR)
136 #ifdef REQUIRES_SEC
137                         ".arch_extension sec\n"
138 #endif
139                         "smc    #0\n"
140                         : "=r" (r0), "=r" (r1), "=r" (r2), "=r" (r3)
141                         : "r" (r0), "r" (r1), "r" (r2), "r" (r3), "r" (r4),
142                           "r" (r5), "r" (r6)
143                         : "x7", "x8", "x9", "x10", "x11", "x12", "x13",
144                           "x14", "x15", "x16", "x17");
145         } while (r0 == QCOM_SCM_INTERRUPTED);
146
147         if (ret1)
148                 *ret1 = r1;
149         if (ret2)
150                 *ret2 = r2;
151         if (ret3)
152                 *ret3 = r3;
153
154         return r0;
155 }
156
157 int __qcom_scm_call_armv8_32(u32 w0, u32 w1, u32 w2, u32 w3, u32 w4, u32 w5,
158                                 u64 *ret1, u64 *ret2, u64 *ret3)
159 {
160         register u32 r0 asm("r0") = w0;
161         register u32 r1 asm("r1") = w1;
162         register u32 r2 asm("r2") = w2;
163         register u32 r3 asm("r3") = w3;
164         register u32 r4 asm("r4") = w4;
165         register u32 r5 asm("r5") = w5;
166         register u32 r6 asm("r6") = 0;
167
168         do {
169                 asm volatile(
170                         __asmeq("%0", R0_STR)
171                         __asmeq("%1", R1_STR)
172                         __asmeq("%2", R2_STR)
173                         __asmeq("%3", R3_STR)
174                         __asmeq("%4", R0_STR)
175                         __asmeq("%5", R1_STR)
176                         __asmeq("%6", R2_STR)
177                         __asmeq("%7", R3_STR)
178                         __asmeq("%8", R4_STR)
179                         __asmeq("%9", R5_STR)
180                         __asmeq("%10", R6_STR)
181 #ifdef REQUIRES_SEC
182                         ".arch_extension sec\n"
183 #endif
184                         "smc    #0\n"
185                         : "=r" (r0), "=r" (r1), "=r" (r2), "=r" (r3)
186                         : "r" (r0), "r" (r1), "r" (r2), "r" (r3), "r" (r4),
187                           "r" (r5), "r" (r6)
188                         : "x7", "x8", "x9", "x10", "x11", "x12", "x13",
189                         "x14", "x15", "x16", "x17");
190
191         } while (r0 == QCOM_SCM_INTERRUPTED);
192
193         if (ret1)
194                 *ret1 = r1;
195         if (ret2)
196                 *ret2 = r2;
197         if (ret3)
198                 *ret3 = r3;
199
200         return r0;
201 }
202
203 struct qcom_scm_extra_arg {
204         union {
205                 u32 args32[N_EXT_QCOM_SCM_ARGS];
206                 u64 args64[N_EXT_QCOM_SCM_ARGS];
207         };
208 };
209
210 static enum qcom_scm_interface_version {
211         QCOM_SCM_UNKNOWN,
212         QCOM_SCM_LEGACY,
213         QCOM_SCM_ARMV8_32,
214         QCOM_SCM_ARMV8_64,
215 } qcom_scm_version = QCOM_SCM_UNKNOWN;
216
217 /* This will be set to specify SMC32 or SMC64 */
218 static u32 qcom_scm_version_mask;
219
220 /*
221  * If there are more than N_REGISTER_ARGS, allocate a buffer and place
222  * the additional arguments in it. The extra argument buffer will be
223  * pointed to by X5.
224  */
225 static int allocate_extra_arg_buffer(struct qcom_scm_desc *desc, gfp_t flags)
226 {
227         int i, j;
228         struct qcom_scm_extra_arg *argbuf;
229         int arglen = desc->arginfo & 0xf;
230         size_t argbuflen = PAGE_ALIGN(sizeof(struct qcom_scm_extra_arg));
231
232         desc->x5 = desc->args[FIRST_EXT_ARG_IDX];
233
234         if (likely(arglen <= N_REGISTER_ARGS)) {
235                 desc->extra_arg_buf = NULL;
236                 return 0;
237         }
238
239         argbuf = kzalloc(argbuflen, flags);
240         if (!argbuf) {
241                 pr_err("qcom_scm_call: failed to alloc mem for extended argument buffer\n");
242                 return -ENOMEM;
243         }
244
245         desc->extra_arg_buf = argbuf;
246
247         j = FIRST_EXT_ARG_IDX;
248         if (qcom_scm_version == QCOM_SCM_ARMV8_64)
249                 for (i = 0; i < N_EXT_QCOM_SCM_ARGS; i++)
250                         argbuf->args64[i] = desc->args[j++];
251         else
252                 for (i = 0; i < N_EXT_QCOM_SCM_ARGS; i++)
253                         argbuf->args32[i] = desc->args[j++];
254         desc->x5 = virt_to_phys(argbuf);
255         __flush_dcache_area(argbuf, argbuflen);
256
257         return 0;
258 }
259
260 /**
261  * qcom_scm_call() - Invoke a syscall in the secure world
262  * @svc_id: service identifier
263  * @cmd_id: command identifier
264  * @fn_id: The function ID for this syscall
265  * @desc: Descriptor structure containing arguments and return values
266  *
267  * Sends a command to the SCM and waits for the command to finish processing.
268  * This should *only* be called in pre-emptible context.
269  *
270  * A note on cache maintenance:
271  * Note that any buffers that are expected to be accessed by the secure world
272  * must be flushed before invoking qcom_scm_call and invalidated in the cache
273  * immediately after qcom_scm_call returns. An important point that must be noted
274  * is that on ARMV8 architectures, invalidation actually also causes a dirty
275  * cache line to be cleaned (flushed + unset-dirty-bit). Therefore it is of
276  * paramount importance that the buffer be flushed before invoking qcom_scm_call,
277  * even if you don't care about the contents of that buffer.
278  *
279  * Note that cache maintenance on the argument buffer (desc->args) is taken care
280  * of by qcom_scm_call; however, callers are responsible for any other cached
281  * buffers passed over to the secure world.
282 */
283 static int qcom_scm_call(u32 svc_id, u32 cmd_id, struct qcom_scm_desc *desc)
284 {
285         int arglen = desc->arginfo & 0xf;
286         int ret, retry_count = 0;
287         u32 fn_id = QCOM_SCM_SIP_FNID(svc_id, cmd_id);
288         u64 x0;
289
290         ret = allocate_extra_arg_buffer(desc, GFP_KERNEL);
291         if (ret)
292                 return ret;
293
294         x0 = fn_id | qcom_scm_version_mask;
295
296         do {
297                 mutex_lock(&qcom_scm_lock);
298
299                 desc->ret[0] = desc->ret[1] = desc->ret[2] = 0;
300
301                 pr_debug("qcom_scm_call: func id %#llx, args: %#x, %#llx, %#llx, %#llx, %#llx\n",
302                         x0, desc->arginfo, desc->args[0], desc->args[1],
303                         desc->args[2], desc->x5);
304
305                 if (qcom_scm_version == QCOM_SCM_ARMV8_64)
306                         ret = __qcom_scm_call_armv8_64(x0, desc->arginfo,
307                                                   desc->args[0], desc->args[1],
308                                                   desc->args[2], desc->x5,
309                                                   &desc->ret[0], &desc->ret[1],
310                                                   &desc->ret[2]);
311                 else
312                         ret = __qcom_scm_call_armv8_32(x0, desc->arginfo,
313                                                   desc->args[0], desc->args[1],
314                                                   desc->args[2], desc->x5,
315                                                   &desc->ret[0], &desc->ret[1],
316                                                   &desc->ret[2]);
317                 mutex_unlock(&qcom_scm_lock);
318
319                 if (ret == QCOM_SCM_V2_EBUSY)
320                         msleep(QCOM_SCM_EBUSY_WAIT_MS);
321         }  while (ret == QCOM_SCM_V2_EBUSY && (retry_count++ < QCOM_SCM_EBUSY_MAX_RETRY));
322
323         if (ret < 0)
324                 pr_err("qcom_scm_call failed: func id %#llx, arginfo: %#x, args: %#llx, %#llx, %#llx, %#llx, ret: %d, syscall returns: %#llx, %#llx, %#llx\n",
325                         x0, desc->arginfo, desc->args[0], desc->args[1],
326                         desc->args[2], desc->x5, ret, desc->ret[0],
327                         desc->ret[1], desc->ret[2]);
328
329         if (arglen > N_REGISTER_ARGS)
330                 kfree(desc->extra_arg_buf);
331         if (ret < 0)
332                 return qcom_scm_remap_error(ret);
333         return 0;
334 }
335
336 /**
337  * qcom_scm_call_atomic() - Invoke a syscall in the secure world
338  *
339  * Similar to qcom_scm_call except that this can be invoked in atomic context.
340  * There is also no retry mechanism implemented. Please ensure that the
341  * secure world syscall can be executed in such a context and can complete
342  * in a timely manner.
343  */
344 static int qcom_scm_call_atomic(u32 s, u32 c, struct qcom_scm_desc *desc)
345 {
346         int arglen = desc->arginfo & 0xf;
347         int ret;
348         u32 fn_id = QCOM_SCM_SIP_FNID(s, c);
349         u64 x0;
350
351         ret = allocate_extra_arg_buffer(desc, GFP_ATOMIC);
352         if (ret)
353                 return ret;
354
355         x0 = fn_id | BIT(SMC_ATOMIC_SYSCALL) | qcom_scm_version_mask;
356
357         pr_debug("qcom_scm_call: func id %#llx, args: %#x, %#llx, %#llx, %#llx, %#llx\n",
358                 x0, desc->arginfo, desc->args[0], desc->args[1],
359                 desc->args[2], desc->x5);
360
361         if (qcom_scm_version == QCOM_SCM_ARMV8_64)
362                 ret = __qcom_scm_call_armv8_64(x0, desc->arginfo, desc->args[0],
363                                           desc->args[1], desc->args[2],
364                                           desc->x5, &desc->ret[0],
365                                           &desc->ret[1], &desc->ret[2]);
366         else
367                 ret = __qcom_scm_call_armv8_32(x0, desc->arginfo, desc->args[0],
368                                           desc->args[1], desc->args[2],
369                                           desc->x5, &desc->ret[0],
370                                           &desc->ret[1], &desc->ret[2]);
371         if (ret < 0)
372                 pr_err("qcom_scm_call failed: func id %#llx, arginfo: %#x, args: %#llx, %#llx, %#llx, %#llx, ret: %d, syscall returns: %#llx, %#llx, %#llx\n",
373                         x0, desc->arginfo, desc->args[0], desc->args[1],
374                         desc->args[2], desc->x5, ret, desc->ret[0],
375                         desc->ret[1], desc->ret[2]);
376
377         if (arglen > N_REGISTER_ARGS)
378                 kfree(desc->extra_arg_buf);
379         if (ret < 0)
380                 return qcom_scm_remap_error(ret);
381         return ret;
382 }
383
384 static int qcom_scm_set_boot_addr(void *entry, const cpumask_t *cpus, int flags)
385 {
386         struct qcom_scm_desc desc = {0};
387         unsigned int cpu = cpumask_first(cpus);
388         u64 mpidr_el1 = cpu_logical_map(cpu);
389
390         /* For now we assume only a single cpu is set in the mask */
391         WARN_ON(cpumask_weight(cpus) != 1);
392
393         if (mpidr_el1 & ~MPIDR_HWID_BITMASK) {
394                 pr_err("CPU%d:Failed to set boot address\n", cpu);
395                 return -ENOSYS;
396         }
397
398         desc.args[0] = virt_to_phys(entry);
399         desc.args[1] = BIT(MPIDR_AFFINITY_LEVEL(mpidr_el1, 0));
400         desc.args[2] = BIT(MPIDR_AFFINITY_LEVEL(mpidr_el1, 1));
401         desc.args[3] = BIT(MPIDR_AFFINITY_LEVEL(mpidr_el1, 2));
402         desc.args[4] = ~0ULL;
403         desc.args[5] = QCOM_SCM_FLAG_HLOS | flags;
404         desc.arginfo = QCOM_SCM_ARGS(6);
405
406         return qcom_scm_call(QCOM_SCM_SVC_BOOT, QCOM_SCM_BOOT_ADDR_MC, &desc);
407 }
408
409 int __qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus)
410 {
411         int flags = QCOM_SCM_FLAG_COLDBOOT_MC;
412
413         return qcom_scm_set_boot_addr(entry, cpus, flags);
414 }
415
416 int __qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus)
417 {
418         int flags = QCOM_SCM_FLAG_WARMBOOT_MC;
419
420         return qcom_scm_set_boot_addr(entry, cpus, flags);
421 }
422
423 void __qcom_scm_cpu_power_down(u32 flags)
424 {
425         struct qcom_scm_desc desc = {0};
426         desc.args[0] = QCOM_SCM_CMD_CORE_HOTPLUGGED |
427                        (flags & QCOM_SCM_FLUSH_FLAG_MASK);
428         desc.arginfo = QCOM_SCM_ARGS(1);
429
430         qcom_scm_call_atomic(QCOM_SCM_SVC_BOOT, QCOM_SCM_CMD_TERMINATE_PC, &desc);
431 }
432
433 int __qcom_scm_is_call_available(u32 svc_id, u32 cmd_id)
434 {
435         int ret;
436         struct qcom_scm_desc desc = {0};
437
438         desc.arginfo = QCOM_SCM_ARGS(1);
439         desc.args[0] = QCOM_SCM_SIP_FNID(svc_id, cmd_id);
440
441         ret = qcom_scm_call(QCOM_SCM_SVC_INFO, QCOM_IS_CALL_AVAIL_CMD, &desc);
442
443         if (ret)
444                 return ret;
445
446         return desc.ret[0];
447 }
448
449 int __qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp)
450 {
451         int ret;
452         struct qcom_scm_desc desc = {0};
453
454         if (req_cnt > QCOM_SCM_HDCP_MAX_REQ_CNT)
455                 return -ERANGE;
456
457         desc.args[0] = req[0].addr;
458         desc.args[1] = req[0].val;
459         desc.args[2] = req[1].addr;
460         desc.args[3] = req[1].val;
461         desc.args[4] = req[2].addr;
462         desc.args[5] = req[2].val;
463         desc.args[6] = req[3].addr;
464         desc.args[7] = req[3].val;
465         desc.args[8] = req[4].addr;
466         desc.args[9] = req[4].val;
467         desc.arginfo = QCOM_SCM_ARGS(10);
468
469         ret = qcom_scm_call(QCOM_SCM_SVC_HDCP, QCOM_SCM_CMD_HDCP, &desc);
470         *resp = desc.ret[0];
471
472         return ret;
473 }
474
475 int __qcom_scm_restart_proc(u32 proc_id, int restart, u32 *resp)
476 {
477         int ret;
478         struct qcom_scm_desc desc = {0};
479
480         desc.args[0] = restart;
481         desc.args[1] = 0;
482         desc.arginfo = QCOM_SCM_ARGS(2);
483
484         ret = qcom_scm_call(QCOM_SCM_SVC_PIL, proc_id,
485                                 &desc);
486         *resp = desc.ret[0];
487
488         return ret;
489 }
490
491 bool __qcom_scm_pas_supported(u32 peripheral)
492 {
493         int ret;
494         struct qcom_scm_desc desc = {0};
495
496         desc.args[0] = peripheral;
497         desc.arginfo = QCOM_SCM_ARGS(1);
498
499         ret = qcom_scm_call(QCOM_SCM_SVC_PIL, QCOM_SCM_PAS_IS_SUPPORTED_CMD,
500                                 &desc);
501
502         return ret ? false : !!desc.ret[0];
503 }
504
505 int __qcom_scm_pas_init_image(u32 peripheral, dma_addr_t metadata_phys)
506 {
507         int ret;
508         struct qcom_scm_desc desc = {0};
509         u32 scm_ret;
510
511         desc.args[0] = peripheral;
512         desc.args[1] = metadata_phys;
513         desc.arginfo = QCOM_SCM_ARGS(2, QCOM_SCM_VAL, QCOM_SCM_RW);
514
515         ret = qcom_scm_call(QCOM_SCM_SVC_PIL, QCOM_SCM_PAS_INIT_IMAGE_CMD,
516                                 &desc);
517         scm_ret = desc.ret[0];
518
519         return ret ? : scm_ret;
520 }
521
522 int __qcom_scm_pas_mem_setup(u32 peripheral, phys_addr_t addr, phys_addr_t size)
523 {
524         int ret;
525         struct qcom_scm_desc desc = {0};
526         u32 scm_ret;
527
528         desc.args[0] = peripheral;
529         desc.args[1] = addr;
530         desc.args[2] = size;
531         desc.arginfo = QCOM_SCM_ARGS(3);
532
533         ret = qcom_scm_call(QCOM_SCM_SVC_PIL, QCOM_SCM_PAS_MEM_SETUP_CMD,
534                                 &desc);
535         scm_ret = desc.ret[0];
536
537         return ret ? : scm_ret;
538 }
539
540 int __qcom_scm_pas_auth_and_reset(u32 peripheral)
541 {
542         int ret;
543         struct qcom_scm_desc desc = {0};
544         u32 scm_ret;
545
546         desc.args[0] = peripheral;
547         desc.arginfo = QCOM_SCM_ARGS(1);
548
549         ret = qcom_scm_call(QCOM_SCM_SVC_PIL, QCOM_SCM_PAS_AUTH_AND_RESET_CMD,
550                                 &desc);
551         scm_ret = desc.ret[0];
552
553         return ret ? : scm_ret;
554 }
555
556 int __qcom_scm_pas_shutdown(u32 peripheral)
557 {
558         int ret;
559         struct qcom_scm_desc desc = {0};
560         u32 scm_ret;
561
562         desc.args[0] = peripheral;
563         desc.arginfo = QCOM_SCM_ARGS(1);
564
565         ret = qcom_scm_call(QCOM_SCM_SVC_PIL, QCOM_SCM_PAS_SHUTDOWN_CMD,
566                         &desc);
567         scm_ret = desc.ret[0];
568
569         return ret ? : scm_ret;
570 }
571
572 int __qcom_scm_pil_init_image_cmd(u32 proc, u64 image_addr)
573 {
574         struct qcom_scm_desc desc = {0};
575         int ret, scm_ret;
576
577         desc.args[0] = proc;
578         desc.args[1] = image_addr;
579         desc.arginfo = QCOM_SCM_ARGS(2, QCOM_SCM_VAL, QCOM_SCM_RW);
580
581         ret = qcom_scm_call(QCOM_SCM_SVC_PIL, PAS_INIT_IMAGE_CMD, &desc);
582         scm_ret = desc.ret[0];
583
584         if (ret)
585                 return ret;
586
587         return scm_ret;
588 }
589
590 int __qcom_scm_pil_mem_setup_cmd(u32 proc, u64 start_addr, u32 len)
591 {
592         struct qcom_scm_desc desc = {0};
593         int ret, scm_ret;
594
595         desc.args[0] = proc;
596         desc.args[1] = start_addr;
597         desc.args[2] = len;
598         desc.arginfo = QCOM_SCM_ARGS(3);
599
600         ret = qcom_scm_call(QCOM_SCM_SVC_PIL, PAS_MEM_SETUP_CMD, &desc);
601         scm_ret = desc.ret[0];
602
603         if (ret)
604                 return ret;
605
606         return scm_ret;
607 }
608
609 int __qcom_scm_pil_auth_and_reset_cmd(u32 proc)
610 {
611         struct qcom_scm_desc desc = {0};
612         int ret, scm_ret;
613
614         desc.args[0] = proc;
615         desc.arginfo = QCOM_SCM_ARGS(1);
616
617         ret = qcom_scm_call(QCOM_SCM_SVC_PIL, PAS_AUTH_AND_RESET_CMD, &desc);
618         scm_ret = desc.ret[0];
619
620         if (ret)
621                 return ret;
622
623         return scm_ret;
624 }
625
626 int __qcom_scm_pil_shutdown_cmd(u32 proc)
627 {
628         struct qcom_scm_desc desc = {0};
629         int ret, scm_ret;
630
631         desc.args[0] = proc;
632         desc.arginfo = QCOM_SCM_ARGS(1);
633
634         ret = qcom_scm_call(QCOM_SCM_SVC_PIL, PAS_SHUTDOWN_CMD, &desc);
635         scm_ret = desc.ret[0];
636
637         if (ret)
638                 return ret;
639
640         return scm_ret;
641 }
642
643 #define SCM_SVC_UTIL                    0x3
644 #define SCM_SVC_MP                      0xc
645 #define IOMMU_DUMP_SMMU_FAULT_REGS      0xc
646
647 #define IOMMU_SECURE_PTBL_SIZE          3
648 #define IOMMU_SECURE_PTBL_INIT          4
649 #define IOMMU_SET_CP_POOL_SIZE          5
650 #define IOMMU_SECURE_MAP                6
651 #define IOMMU_SECURE_UNMAP              7
652 #define IOMMU_SECURE_MAP2               0xb
653 #define IOMMU_SECURE_MAP2_FLAT          0x12
654 #define IOMMU_SECURE_UNMAP2             0xc
655 #define IOMMU_SECURE_UNMAP2_FLAT        0x13
656
657 int __qcom_scm_iommu_dump_fault_regs(u32 id, u32 context, u64 addr, u32 len)
658 {
659         struct qcom_scm_desc desc = {0};
660
661         desc.args[0] = id;
662         desc.args[1] = context;
663         desc.args[2] = addr;
664         desc.args[3] = len;
665         desc.arginfo = QCOM_SCM_ARGS(4, QCOM_SCM_VAL, QCOM_SCM_VAL, QCOM_SCM_RW, QCOM_SCM_VAL);
666
667         return qcom_scm_call(SCM_SVC_UTIL, IOMMU_DUMP_SMMU_FAULT_REGS, &desc);
668 }
669
670 int __qcom_scm_iommu_set_cp_pool_size(u32 size, u32 spare)
671 {
672         struct qcom_scm_desc desc = {0};
673
674         desc.args[0] = size;
675         desc.args[1] = spare;
676         desc.arginfo = QCOM_SCM_ARGS(2);
677
678         return qcom_scm_call(SCM_SVC_MP, IOMMU_SET_CP_POOL_SIZE, &desc);
679 }
680
681 int __qcom_scm_iommu_secure_ptbl_size(u32 spare, int psize[2])
682 {
683         struct qcom_scm_desc desc = {0};
684         int ret;
685         desc.args[0] = spare;
686         desc.arginfo = QCOM_SCM_ARGS(1);
687
688         ret = qcom_scm_call(SCM_SVC_MP, IOMMU_SECURE_PTBL_SIZE, &desc);
689
690         psize[0] = desc.ret[0];
691         psize[1] = desc.ret[1];
692
693         return ret;
694 }
695
696 int __qcom_scm_iommu_secure_ptbl_init(u64 addr, u32 size, u32 spare)
697 {
698         struct qcom_scm_desc desc = {0};
699         int ret;
700         u64 ptbl_ret;
701
702         desc.args[0] = addr;
703         desc.args[1] = size;
704         desc.args[2] = spare;
705         desc.arginfo = QCOM_SCM_ARGS(3, QCOM_SCM_RW, QCOM_SCM_VAL, QCOM_SCM_VAL);
706
707         ret = qcom_scm_call(SCM_SVC_MP, IOMMU_SECURE_PTBL_INIT, &desc);
708
709         ptbl_ret = desc.ret[0];
710
711         if (ret)
712                 return ret;
713
714         if (ptbl_ret)
715                 return ptbl_ret;
716
717         return 0;
718 }
719
720 int __qcom_scm_iommu_secure_map(u64 list, u32 list_size, u32 size,
721                                 u32 id, u32 ctx_id, u64 va, u32 info_size,
722                                 u32 flags)
723 {
724         struct qcom_scm_desc desc = {0};
725         u32 resp;
726         int ret;
727
728         desc.args[0] = list;
729         desc.args[1] = list_size;
730         desc.args[2] = size;
731         desc.args[3] = id;
732         desc.args[4] = ctx_id;
733         desc.args[5] = va;
734         desc.args[6] = info_size;
735         desc.args[7] = flags;
736         desc.arginfo = QCOM_SCM_ARGS(8, QCOM_SCM_RW, QCOM_SCM_VAL, QCOM_SCM_VAL, QCOM_SCM_VAL,
737                                      QCOM_SCM_VAL, QCOM_SCM_VAL, QCOM_SCM_VAL, QCOM_SCM_VAL);
738
739         ret = qcom_scm_call(SCM_SVC_MP, IOMMU_SECURE_MAP2_FLAT, &desc);
740
741         resp = desc.ret[0];
742
743         if (ret || resp)
744                 return -EINVAL;
745
746         return 0;
747 }
748
749 int __qcom_scm_iommu_secure_unmap(u32 id, u32 ctx_id, u64 va,
750                                   u32 size, u32 flags)
751 {
752         struct qcom_scm_desc desc = {0};
753
754         desc.args[0] = id;
755         desc.args[1] = ctx_id;
756         desc.args[2] = va;
757         desc.args[3] = size;
758         desc.args[4] = flags;
759         desc.arginfo = QCOM_SCM_ARGS(5);
760
761         return qcom_scm_call(SCM_SVC_MP, IOMMU_SECURE_UNMAP2_FLAT, &desc);
762 }
763
764 int __qcom_scm_get_feat_version(u32 feat)
765 {
766         struct qcom_scm_desc desc = {0};
767         int ret;
768
769         ret = __qcom_scm_is_call_available(SCM_SVC_INFO, GET_FEAT_VERSION_CMD);
770         if (ret <= 0)
771                 return 0;
772
773         desc.args[0] = feat;
774         desc.arginfo = QCOM_SCM_ARGS(1);
775
776         ret = qcom_scm_call(SCM_SVC_INFO, GET_FEAT_VERSION_CMD, &desc);
777         if (!ret)
778                 return desc.ret[0];
779
780         return 0;
781 }
782
783 #define RESTORE_SEC_CFG         2
784 int __qcom_scm_restore_sec_cfg(u32 device_id, u32 spare)
785 {
786         struct qcom_scm_desc desc = {0};
787         int ret, scm_ret = 0;
788
789         desc.args[0] = device_id;
790         desc.args[1] = spare;
791         desc.arginfo = QCOM_SCM_ARGS(2);
792
793         ret = qcom_scm_call(SCM_SVC_MP, RESTORE_SEC_CFG, &desc);
794
795         scm_ret = desc.ret[0];
796
797         if (ret || scm_ret)
798                 return ret ? ret : -EINVAL;
799
800         return 0;
801 }
802
803 #define TZBSP_VIDEO_SET_STATE   0xa
804 int __qcom_scm_set_video_state(u32 state, u32 spare)
805 {
806         struct qcom_scm_desc desc = {0};
807         int ret, scm_ret;
808
809         desc.args[0] = state;
810         desc.args[1] = spare;
811         desc.arginfo = QCOM_SCM_ARGS(2);
812
813         ret = qcom_scm_call(SCM_SVC_BOOT, TZBSP_VIDEO_SET_STATE, &desc);
814
815         scm_ret = desc.ret[0];
816
817         if (ret || scm_ret)
818                 return ret ? ret : -EINVAL;
819
820         return 0;
821 }
822
823 #define TZBSP_MEM_PROTECT_VIDEO_VAR     0x8
824
825 int __qcom_scm_mem_protect_video_var(u32 start, u32 size, u32 nonpixel_start,
826                                      u32 nonpixel_size)
827 {
828         struct qcom_scm_desc desc = {0};
829         int ret, scm_ret;
830
831         desc.args[0] = start;
832         desc.args[1] = size;
833         desc.args[2] = nonpixel_start;
834         desc.args[3] = nonpixel_size;
835         desc.arginfo = QCOM_SCM_ARGS(4);
836
837         ret = qcom_scm_call(SCM_SVC_MP, TZBSP_MEM_PROTECT_VIDEO_VAR, &desc);
838
839         scm_ret = desc.ret[0];
840
841         if (ret || scm_ret)
842                 return ret ? ret : -EINVAL;
843
844         return 0;
845 }
846
847 #define QCOM_SCM_SVC_INFO              0x6
848 int __qcom_scm_init(void)
849 {
850         int ret;
851         u64 ret1 = 0, x0;
852
853         /* First try a SMC64 call */
854         qcom_scm_version = QCOM_SCM_ARMV8_64;
855         x0 = QCOM_SCM_SIP_FNID(QCOM_SCM_SVC_INFO, QCOM_IS_CALL_AVAIL_CMD) | SMC_ATOMIC_MASK;
856         ret = __qcom_scm_call_armv8_64(x0 | SMC64_MASK, QCOM_SCM_ARGS(1), x0, 0, 0, 0,
857                                   &ret1, NULL, NULL);
858         if (ret || !ret1) {
859                 /* Try SMC32 call */
860                 ret1 = 0;
861                 ret = __qcom_scm_call_armv8_32(x0, QCOM_SCM_ARGS(1), x0, 0, 0,
862                                                 0, &ret1, NULL, NULL);
863                 if (ret || !ret1)
864                         qcom_scm_version = QCOM_SCM_LEGACY;
865                 else
866                         qcom_scm_version = QCOM_SCM_ARMV8_32;
867         } else
868                 qcom_scm_version_mask = SMC64_MASK;
869
870         pr_debug("qcom_scm_call: qcom_scm version is %x, mask is %x\n",
871                  qcom_scm_version, qcom_scm_version_mask);
872
873         return 0;
874 }