1 /* Copyright (c) 2015, The Linux Foundation. All rights reserved.
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.
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.
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
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>
27 #include <asm/cacheflush.h>
28 #include <asm/compiler.h>
29 #include <asm/smp_plat.h>
33 #define QCOM_SCM_SIP_FNID(s, c) (((((s) & 0xFF) << 8) | ((c) & 0xFF)) | 0x02000000)
35 #define MAX_QCOM_SCM_ARGS 10
36 #define MAX_QCOM_SCM_RETS 3
38 enum qcom_scm_arg_types {
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) | \
58 #define QCOM_SCM_ARGS(...) QCOM_SCM_ARGS_IMPL(__VA_ARGS__, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
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
70 struct qcom_scm_desc {
72 u64 args[MAX_QCOM_SCM_ARGS];
73 u64 ret[MAX_QCOM_SCM_RETS];
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
90 static DEFINE_MUTEX(qcom_scm_lock);
92 #define QCOM_SCM_EBUSY_WAIT_MS 30
93 #define QCOM_SCM_EBUSY_MAX_RETRY 20
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
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)
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;
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)
137 ".arch_extension sec\n"
140 : "=r" (r0), "=r" (r1), "=r" (r2), "=r" (r3)
141 : "r" (r0), "r" (r1), "r" (r2), "r" (r3), "r" (r4),
143 : "x7", "x8", "x9", "x10", "x11", "x12", "x13",
144 "x14", "x15", "x16", "x17");
145 } while (r0 == QCOM_SCM_INTERRUPTED);
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)
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;
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)
182 ".arch_extension sec\n"
185 : "=r" (r0), "=r" (r1), "=r" (r2), "=r" (r3)
186 : "r" (r0), "r" (r1), "r" (r2), "r" (r3), "r" (r4),
188 : "x7", "x8", "x9", "x10", "x11", "x12", "x13",
189 "x14", "x15", "x16", "x17");
191 } while (r0 == QCOM_SCM_INTERRUPTED);
203 struct qcom_scm_extra_arg {
205 u32 args32[N_EXT_QCOM_SCM_ARGS];
206 u64 args64[N_EXT_QCOM_SCM_ARGS];
210 static enum qcom_scm_interface_version {
215 } qcom_scm_version = QCOM_SCM_UNKNOWN;
217 /* This will be set to specify SMC32 or SMC64 */
218 static u32 qcom_scm_version_mask;
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
225 static int allocate_extra_arg_buffer(struct qcom_scm_desc *desc, gfp_t flags)
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));
232 desc->x5 = desc->args[FIRST_EXT_ARG_IDX];
234 if (likely(arglen <= N_REGISTER_ARGS)) {
235 desc->extra_arg_buf = NULL;
239 argbuf = kzalloc(argbuflen, flags);
241 pr_err("qcom_scm_call: failed to alloc mem for extended argument buffer\n");
245 desc->extra_arg_buf = argbuf;
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++];
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);
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
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.
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.
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.
283 static int qcom_scm_call(u32 svc_id, u32 cmd_id, struct qcom_scm_desc *desc)
285 int arglen = desc->arginfo & 0xf;
286 int ret, retry_count = 0;
287 u32 fn_id = QCOM_SCM_SIP_FNID(svc_id, cmd_id);
290 ret = allocate_extra_arg_buffer(desc, GFP_KERNEL);
294 x0 = fn_id | qcom_scm_version_mask;
297 mutex_lock(&qcom_scm_lock);
299 desc->ret[0] = desc->ret[1] = desc->ret[2] = 0;
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);
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],
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],
317 mutex_unlock(&qcom_scm_lock);
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));
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]);
329 if (arglen > N_REGISTER_ARGS)
330 kfree(desc->extra_arg_buf);
332 return qcom_scm_remap_error(ret);
337 * qcom_scm_call_atomic() - Invoke a syscall in the secure world
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.
344 static int qcom_scm_call_atomic(u32 s, u32 c, struct qcom_scm_desc *desc)
346 int arglen = desc->arginfo & 0xf;
348 u32 fn_id = QCOM_SCM_SIP_FNID(s, c);
351 ret = allocate_extra_arg_buffer(desc, GFP_ATOMIC);
355 x0 = fn_id | BIT(SMC_ATOMIC_SYSCALL) | qcom_scm_version_mask;
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);
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]);
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]);
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]);
377 if (arglen > N_REGISTER_ARGS)
378 kfree(desc->extra_arg_buf);
380 return qcom_scm_remap_error(ret);
384 static int qcom_scm_set_boot_addr(void *entry, const cpumask_t *cpus, int flags)
386 struct qcom_scm_desc desc = {0};
387 unsigned int cpu = cpumask_first(cpus);
388 u64 mpidr_el1 = cpu_logical_map(cpu);
390 /* For now we assume only a single cpu is set in the mask */
391 WARN_ON(cpumask_weight(cpus) != 1);
393 if (mpidr_el1 & ~MPIDR_HWID_BITMASK) {
394 pr_err("CPU%d:Failed to set boot address\n", cpu);
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);
406 return qcom_scm_call(QCOM_SCM_SVC_BOOT, QCOM_SCM_BOOT_ADDR_MC, &desc);
409 int __qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus)
411 int flags = QCOM_SCM_FLAG_COLDBOOT_MC;
413 return qcom_scm_set_boot_addr(entry, cpus, flags);
416 int __qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus)
418 int flags = QCOM_SCM_FLAG_WARMBOOT_MC;
420 return qcom_scm_set_boot_addr(entry, cpus, flags);
423 void __qcom_scm_cpu_power_down(u32 flags)
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);
430 qcom_scm_call_atomic(QCOM_SCM_SVC_BOOT, QCOM_SCM_CMD_TERMINATE_PC, &desc);
433 int __qcom_scm_is_call_available(u32 svc_id, u32 cmd_id)
436 struct qcom_scm_desc desc = {0};
438 desc.arginfo = QCOM_SCM_ARGS(1);
439 desc.args[0] = QCOM_SCM_SIP_FNID(svc_id, cmd_id);
441 ret = qcom_scm_call(QCOM_SCM_SVC_INFO, QCOM_IS_CALL_AVAIL_CMD, &desc);
449 int __qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp)
452 struct qcom_scm_desc desc = {0};
454 if (req_cnt > QCOM_SCM_HDCP_MAX_REQ_CNT)
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);
469 ret = qcom_scm_call(QCOM_SCM_SVC_HDCP, QCOM_SCM_CMD_HDCP, &desc);
475 int __qcom_scm_restart_proc(u32 proc_id, int restart, u32 *resp)
478 struct qcom_scm_desc desc = {0};
480 desc.args[0] = restart;
482 desc.arginfo = QCOM_SCM_ARGS(2);
484 ret = qcom_scm_call(QCOM_SCM_SVC_PIL, proc_id,
491 bool __qcom_scm_pas_supported(u32 peripheral)
494 struct qcom_scm_desc desc = {0};
496 desc.args[0] = peripheral;
497 desc.arginfo = QCOM_SCM_ARGS(1);
499 ret = qcom_scm_call(QCOM_SCM_SVC_PIL, QCOM_SCM_PAS_IS_SUPPORTED_CMD,
502 return ret ? false : !!desc.ret[0];
505 int __qcom_scm_pas_init_image(u32 peripheral, dma_addr_t metadata_phys)
508 struct qcom_scm_desc desc = {0};
511 desc.args[0] = peripheral;
512 desc.args[1] = metadata_phys;
513 desc.arginfo = QCOM_SCM_ARGS(2, QCOM_SCM_VAL, QCOM_SCM_RW);
515 ret = qcom_scm_call(QCOM_SCM_SVC_PIL, QCOM_SCM_PAS_INIT_IMAGE_CMD,
517 scm_ret = desc.ret[0];
519 return ret ? : scm_ret;
522 int __qcom_scm_pas_mem_setup(u32 peripheral, phys_addr_t addr, phys_addr_t size)
525 struct qcom_scm_desc desc = {0};
528 desc.args[0] = peripheral;
531 desc.arginfo = QCOM_SCM_ARGS(3);
533 ret = qcom_scm_call(QCOM_SCM_SVC_PIL, QCOM_SCM_PAS_MEM_SETUP_CMD,
535 scm_ret = desc.ret[0];
537 return ret ? : scm_ret;
540 int __qcom_scm_pas_auth_and_reset(u32 peripheral)
543 struct qcom_scm_desc desc = {0};
546 desc.args[0] = peripheral;
547 desc.arginfo = QCOM_SCM_ARGS(1);
549 ret = qcom_scm_call(QCOM_SCM_SVC_PIL, QCOM_SCM_PAS_AUTH_AND_RESET_CMD,
551 scm_ret = desc.ret[0];
553 return ret ? : scm_ret;
556 int __qcom_scm_pas_shutdown(u32 peripheral)
559 struct qcom_scm_desc desc = {0};
562 desc.args[0] = peripheral;
563 desc.arginfo = QCOM_SCM_ARGS(1);
565 ret = qcom_scm_call(QCOM_SCM_SVC_PIL, QCOM_SCM_PAS_SHUTDOWN_CMD,
567 scm_ret = desc.ret[0];
569 return ret ? : scm_ret;
572 int __qcom_scm_pil_init_image_cmd(u32 proc, u64 image_addr)
574 struct qcom_scm_desc desc = {0};
578 desc.args[1] = image_addr;
579 desc.arginfo = QCOM_SCM_ARGS(2, QCOM_SCM_VAL, QCOM_SCM_RW);
581 ret = qcom_scm_call(QCOM_SCM_SVC_PIL, PAS_INIT_IMAGE_CMD, &desc);
582 scm_ret = desc.ret[0];
590 int __qcom_scm_pil_mem_setup_cmd(u32 proc, u64 start_addr, u32 len)
592 struct qcom_scm_desc desc = {0};
596 desc.args[1] = start_addr;
598 desc.arginfo = QCOM_SCM_ARGS(3);
600 ret = qcom_scm_call(QCOM_SCM_SVC_PIL, PAS_MEM_SETUP_CMD, &desc);
601 scm_ret = desc.ret[0];
609 int __qcom_scm_pil_auth_and_reset_cmd(u32 proc)
611 struct qcom_scm_desc desc = {0};
615 desc.arginfo = QCOM_SCM_ARGS(1);
617 ret = qcom_scm_call(QCOM_SCM_SVC_PIL, PAS_AUTH_AND_RESET_CMD, &desc);
618 scm_ret = desc.ret[0];
626 int __qcom_scm_pil_shutdown_cmd(u32 proc)
628 struct qcom_scm_desc desc = {0};
632 desc.arginfo = QCOM_SCM_ARGS(1);
634 ret = qcom_scm_call(QCOM_SCM_SVC_PIL, PAS_SHUTDOWN_CMD, &desc);
635 scm_ret = desc.ret[0];
643 #define SCM_SVC_UTIL 0x3
644 #define SCM_SVC_MP 0xc
645 #define IOMMU_DUMP_SMMU_FAULT_REGS 0xc
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
657 int __qcom_scm_iommu_dump_fault_regs(u32 id, u32 context, u64 addr, u32 len)
659 struct qcom_scm_desc desc = {0};
662 desc.args[1] = context;
665 desc.arginfo = QCOM_SCM_ARGS(4, QCOM_SCM_VAL, QCOM_SCM_VAL, QCOM_SCM_RW, QCOM_SCM_VAL);
667 return qcom_scm_call(SCM_SVC_UTIL, IOMMU_DUMP_SMMU_FAULT_REGS, &desc);
670 int __qcom_scm_iommu_set_cp_pool_size(u32 size, u32 spare)
672 struct qcom_scm_desc desc = {0};
675 desc.args[1] = spare;
676 desc.arginfo = QCOM_SCM_ARGS(2);
678 return qcom_scm_call(SCM_SVC_MP, IOMMU_SET_CP_POOL_SIZE, &desc);
681 int __qcom_scm_iommu_secure_ptbl_size(u32 spare, int psize[2])
683 struct qcom_scm_desc desc = {0};
685 desc.args[0] = spare;
686 desc.arginfo = QCOM_SCM_ARGS(1);
688 ret = qcom_scm_call(SCM_SVC_MP, IOMMU_SECURE_PTBL_SIZE, &desc);
690 psize[0] = desc.ret[0];
691 psize[1] = desc.ret[1];
696 int __qcom_scm_iommu_secure_ptbl_init(u64 addr, u32 size, u32 spare)
698 struct qcom_scm_desc desc = {0};
704 desc.args[2] = spare;
705 desc.arginfo = QCOM_SCM_ARGS(3, QCOM_SCM_RW, QCOM_SCM_VAL, QCOM_SCM_VAL);
707 ret = qcom_scm_call(SCM_SVC_MP, IOMMU_SECURE_PTBL_INIT, &desc);
709 ptbl_ret = desc.ret[0];
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,
724 struct qcom_scm_desc desc = {0};
729 desc.args[1] = list_size;
732 desc.args[4] = ctx_id;
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);
739 ret = qcom_scm_call(SCM_SVC_MP, IOMMU_SECURE_MAP2_FLAT, &desc);
749 int __qcom_scm_iommu_secure_unmap(u32 id, u32 ctx_id, u64 va,
752 struct qcom_scm_desc desc = {0};
755 desc.args[1] = ctx_id;
758 desc.args[4] = flags;
759 desc.arginfo = QCOM_SCM_ARGS(5);
761 return qcom_scm_call(SCM_SVC_MP, IOMMU_SECURE_UNMAP2_FLAT, &desc);
764 int __qcom_scm_get_feat_version(u32 feat)
766 struct qcom_scm_desc desc = {0};
769 ret = __qcom_scm_is_call_available(SCM_SVC_INFO, GET_FEAT_VERSION_CMD);
774 desc.arginfo = QCOM_SCM_ARGS(1);
776 ret = qcom_scm_call(SCM_SVC_INFO, GET_FEAT_VERSION_CMD, &desc);
783 #define RESTORE_SEC_CFG 2
784 int __qcom_scm_restore_sec_cfg(u32 device_id, u32 spare)
786 struct qcom_scm_desc desc = {0};
787 int ret, scm_ret = 0;
789 desc.args[0] = device_id;
790 desc.args[1] = spare;
791 desc.arginfo = QCOM_SCM_ARGS(2);
793 ret = qcom_scm_call(SCM_SVC_MP, RESTORE_SEC_CFG, &desc);
795 scm_ret = desc.ret[0];
798 return ret ? ret : -EINVAL;
803 #define TZBSP_VIDEO_SET_STATE 0xa
804 int __qcom_scm_set_video_state(u32 state, u32 spare)
806 struct qcom_scm_desc desc = {0};
809 desc.args[0] = state;
810 desc.args[1] = spare;
811 desc.arginfo = QCOM_SCM_ARGS(2);
813 ret = qcom_scm_call(SCM_SVC_BOOT, TZBSP_VIDEO_SET_STATE, &desc);
815 scm_ret = desc.ret[0];
818 return ret ? ret : -EINVAL;
823 #define TZBSP_MEM_PROTECT_VIDEO_VAR 0x8
825 int __qcom_scm_mem_protect_video_var(u32 start, u32 size, u32 nonpixel_start,
828 struct qcom_scm_desc desc = {0};
831 desc.args[0] = start;
833 desc.args[2] = nonpixel_start;
834 desc.args[3] = nonpixel_size;
835 desc.arginfo = QCOM_SCM_ARGS(4);
837 ret = qcom_scm_call(SCM_SVC_MP, TZBSP_MEM_PROTECT_VIDEO_VAR, &desc);
839 scm_ret = desc.ret[0];
842 return ret ? ret : -EINVAL;
847 #define QCOM_SCM_SVC_INFO 0x6
848 int __qcom_scm_init(void)
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,
861 ret = __qcom_scm_call_armv8_32(x0, QCOM_SCM_ARGS(1), x0, 0, 0,
862 0, &ret1, NULL, NULL);
864 qcom_scm_version = QCOM_SCM_LEGACY;
866 qcom_scm_version = QCOM_SCM_ARMV8_32;
868 qcom_scm_version_mask = SMC64_MASK;
870 pr_debug("qcom_scm_call: qcom_scm version is %x, mask is %x\n",
871 qcom_scm_version, qcom_scm_version_mask);