]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/firmware/qcom_scm-32.c
firmware: qcom-scm: Expose mss_restart through a reset-controller
[karo-tx-linux.git] / drivers / firmware / qcom_scm-32.c
1 /* Copyright (c) 2010,2015, The Linux Foundation. All rights reserved.
2 >>>>>>> firmware: qcom: scm: Split out 32-bit specific SCM code
3  * Copyright (C) 2015 Linaro Ltd.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 and
7  * only version 2 as published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  * 02110-1301, USA.
18  */
19
20 #include <linux/slab.h>
21 #include <linux/io.h>
22 #include <linux/module.h>
23 #include <linux/mutex.h>
24 #include <linux/errno.h>
25 #include <linux/err.h>
26 #include <linux/qcom_scm.h>
27 #include <linux/dma-mapping.h>
28
29 #include <asm/cacheflush.h>
30
31 #include "qcom_scm.h"
32
33 #define QCOM_SCM_ENOMEM         -5
34 #define QCOM_SCM_EOPNOTSUPP     -4
35 #define QCOM_SCM_EINVAL_ADDR    -3
36 #define QCOM_SCM_EINVAL_ARG     -2
37 #define QCOM_SCM_ERROR          -1
38 #define QCOM_SCM_INTERRUPTED    1
39
40 #define QCOM_SCM_FLAG_COLDBOOT_CPU0     0x00
41 #define QCOM_SCM_FLAG_COLDBOOT_CPU1     0x01
42 #define QCOM_SCM_FLAG_COLDBOOT_CPU2     0x08
43 #define QCOM_SCM_FLAG_COLDBOOT_CPU3     0x20
44
45 #define QCOM_SCM_FLAG_WARMBOOT_CPU0     0x04
46 #define QCOM_SCM_FLAG_WARMBOOT_CPU1     0x02
47 #define QCOM_SCM_FLAG_WARMBOOT_CPU2     0x10
48 #define QCOM_SCM_FLAG_WARMBOOT_CPU3     0x40
49
50 #define IOMMU_SECURE_PTBL_SIZE          3
51 #define IOMMU_SECURE_PTBL_INIT          4
52 #define IOMMU_SET_CP_POOL_SIZE          5
53 #define IOMMU_SECURE_MAP                6
54 #define IOMMU_SECURE_UNMAP              7
55 #define IOMMU_SECURE_MAP2               0xb
56 #define IOMMU_SECURE_MAP2_FLAT          0x12
57 #define IOMMU_SECURE_UNMAP2             0xc
58
59 struct qcom_scm_entry {
60         int flag;
61         void *entry;
62 };
63
64 static struct qcom_scm_entry qcom_scm_wb[] = {
65         { .flag = QCOM_SCM_FLAG_WARMBOOT_CPU0 },
66         { .flag = QCOM_SCM_FLAG_WARMBOOT_CPU1 },
67         { .flag = QCOM_SCM_FLAG_WARMBOOT_CPU2 },
68         { .flag = QCOM_SCM_FLAG_WARMBOOT_CPU3 },
69 };
70
71 static DEFINE_MUTEX(qcom_scm_lock);
72
73 /**
74  * struct qcom_scm_command - one SCM command buffer
75  * @len: total available memory for command and response
76  * @buf_offset: start of command buffer
77  * @resp_hdr_offset: start of response buffer
78  * @id: command to be executed
79  * @buf: buffer returned from qcom_scm_get_command_buffer()
80  *
81  * An SCM command is laid out in memory as follows:
82  *
83  *      ------------------- <--- struct qcom_scm_command
84  *      | command header  |
85  *      ------------------- <--- qcom_scm_get_command_buffer()
86  *      | command buffer  |
87  *      ------------------- <--- struct qcom_scm_response and
88  *      | response header |      qcom_scm_command_to_response()
89  *      ------------------- <--- qcom_scm_get_response_buffer()
90  *      | response buffer |
91  *      -------------------
92  *
93  * There can be arbitrary padding between the headers and buffers so
94  * you should always use the appropriate qcom_scm_get_*_buffer() routines
95  * to access the buffers in a safe manner.
96  */
97 struct qcom_scm_command {
98         __le32 len;
99         __le32 buf_offset;
100         __le32 resp_hdr_offset;
101         __le32 id;
102         __le32 buf[0];
103 };
104
105 /**
106  * struct qcom_scm_response - one SCM response buffer
107  * @len: total available memory for response
108  * @buf_offset: start of response data relative to start of qcom_scm_response
109  * @is_complete: indicates if the command has finished processing
110  */
111 struct qcom_scm_response {
112         __le32 len;
113         __le32 buf_offset;
114         __le32 is_complete;
115 };
116
117 /**
118  * alloc_qcom_scm_command() - Allocate an SCM command
119  * @cmd_size: size of the command buffer
120  * @resp_size: size of the response buffer
121  *
122  * Allocate an SCM command, including enough room for the command
123  * and response headers as well as the command and response buffers.
124  *
125  * Returns a valid &qcom_scm_command on success or %NULL if the allocation fails.
126  */
127 static struct qcom_scm_command *alloc_qcom_scm_command(size_t cmd_size, size_t resp_size)
128 {
129         struct qcom_scm_command *cmd;
130         size_t len = sizeof(*cmd) + sizeof(struct qcom_scm_response) + cmd_size +
131                 resp_size;
132         u32 offset;
133
134         cmd = kzalloc(PAGE_ALIGN(len), GFP_KERNEL);
135         if (cmd) {
136                 cmd->len = cpu_to_le32(len);
137                 offset = offsetof(struct qcom_scm_command, buf);
138                 cmd->buf_offset = cpu_to_le32(offset);
139                 cmd->resp_hdr_offset = cpu_to_le32(offset + cmd_size);
140         }
141         return cmd;
142 }
143
144 /**
145  * free_qcom_scm_command() - Free an SCM command
146  * @cmd: command to free
147  *
148  * Free an SCM command.
149  */
150 static inline void free_qcom_scm_command(struct qcom_scm_command *cmd)
151 {
152         kfree(cmd);
153 }
154
155 /**
156  * qcom_scm_command_to_response() - Get a pointer to a qcom_scm_response
157  * @cmd: command
158  *
159  * Returns a pointer to a response for a command.
160  */
161 static inline struct qcom_scm_response *qcom_scm_command_to_response(
162                 const struct qcom_scm_command *cmd)
163 {
164         return (void *)cmd + le32_to_cpu(cmd->resp_hdr_offset);
165 }
166
167 /**
168  * qcom_scm_get_command_buffer() - Get a pointer to a command buffer
169  * @cmd: command
170  *
171  * Returns a pointer to the command buffer of a command.
172  */
173 static inline void *qcom_scm_get_command_buffer(const struct qcom_scm_command *cmd)
174 {
175         return (void *)cmd->buf;
176 }
177
178 /**
179  * qcom_scm_get_response_buffer() - Get a pointer to a response buffer
180  * @rsp: response
181  *
182  * Returns a pointer to a response buffer of a response.
183  */
184 static inline void *qcom_scm_get_response_buffer(const struct qcom_scm_response *rsp)
185 {
186         return (void *)rsp + le32_to_cpu(rsp->buf_offset);
187 }
188
189 static u32 smc(u32 cmd_addr)
190 {
191         int context_id;
192         register u32 r0 asm("r0") = 1;
193         register u32 r1 asm("r1") = (u32)&context_id;
194         register u32 r2 asm("r2") = cmd_addr;
195         do {
196                 asm volatile(
197                         __asmeq("%0", "r0")
198                         __asmeq("%1", "r0")
199                         __asmeq("%2", "r1")
200                         __asmeq("%3", "r2")
201 #ifdef REQUIRES_SEC
202                         ".arch_extension sec\n"
203 #endif
204                         "smc    #0      @ switch to secure world\n"
205                         : "=r" (r0)
206                         : "r" (r0), "r" (r1), "r" (r2)
207                         : "r3");
208         } while (r0 == QCOM_SCM_INTERRUPTED);
209
210         return r0;
211 }
212
213 static int __qcom_scm_call(const struct qcom_scm_command *cmd)
214 {
215         int ret;
216         u32 cmd_addr = virt_to_phys(cmd);
217
218         /*
219          * Flush the command buffer so that the secure world sees
220          * the correct data.
221          */
222         secure_flush_area(cmd, cmd->len);
223
224         ret = smc(cmd_addr);
225         if (ret < 0)
226                 ret = qcom_scm_remap_error(ret);
227
228         return ret;
229 }
230
231 static void qcom_scm_inv_range(unsigned long start, unsigned long end)
232 {
233         u32 cacheline_size, ctr;
234
235         asm volatile("mrc p15, 0, %0, c0, c0, 1" : "=r" (ctr));
236         cacheline_size = 4 << ((ctr >> 16) & 0xf);
237
238         start = round_down(start, cacheline_size);
239         end = round_up(end, cacheline_size);
240         outer_inv_range(start, end);
241         while (start < end) {
242                 asm ("mcr p15, 0, %0, c7, c6, 1" : : "r" (start)
243                      : "memory");
244                 start += cacheline_size;
245         }
246         dsb();
247         isb();
248 }
249
250 /**
251  * qcom_scm_call() - Send an SCM command
252  * @svc_id: service identifier
253  * @cmd_id: command identifier
254  * @cmd_buf: command buffer
255  * @cmd_len: length of the command buffer
256  * @resp_buf: response buffer
257  * @resp_len: length of the response buffer
258  *
259  * Sends a command to the SCM and waits for the command to finish processing.
260  *
261  * A note on cache maintenance:
262  * Note that any buffers that are expected to be accessed by the secure world
263  * must be flushed before invoking qcom_scm_call and invalidated in the cache
264  * immediately after qcom_scm_call returns. Cache maintenance on the command
265  * and response buffers is taken care of by qcom_scm_call; however, callers are
266  * responsible for any other cached buffers passed over to the secure world.
267  */
268 static int qcom_scm_call(u32 svc_id, u32 cmd_id, const void *cmd_buf,
269                         size_t cmd_len, void *resp_buf, size_t resp_len)
270 {
271         int ret;
272         struct qcom_scm_command *cmd;
273         struct qcom_scm_response *rsp;
274         unsigned long start, end;
275
276         cmd = alloc_qcom_scm_command(cmd_len, resp_len);
277         if (!cmd)
278                 return -ENOMEM;
279
280         cmd->id = cpu_to_le32((svc_id << 10) | cmd_id);
281         if (cmd_buf)
282                 memcpy(qcom_scm_get_command_buffer(cmd), cmd_buf, cmd_len);
283
284         mutex_lock(&qcom_scm_lock);
285         ret = __qcom_scm_call(cmd);
286         mutex_unlock(&qcom_scm_lock);
287         if (ret)
288                 goto out;
289
290         rsp = qcom_scm_command_to_response(cmd);
291         start = (unsigned long)rsp;
292
293         do {
294                 qcom_scm_inv_range(start, start + sizeof(*rsp));
295         } while (!rsp->is_complete);
296
297         end = (unsigned long)qcom_scm_get_response_buffer(rsp) + resp_len;
298         qcom_scm_inv_range(start, end);
299
300         if (resp_buf)
301                 memcpy(resp_buf, qcom_scm_get_response_buffer(rsp), resp_len);
302 out:
303         free_qcom_scm_command(cmd);
304         return ret;
305 }
306
307 #define SCM_CLASS_REGISTER      (0x2 << 8)
308 #define SCM_MASK_IRQS           BIT(5)
309 #define SCM_ATOMIC(svc, cmd, n) (((((svc) << 10)|((cmd) & 0x3ff)) << 12) | \
310                                 SCM_CLASS_REGISTER | \
311                                 SCM_MASK_IRQS | \
312                                 (n & 0xf))
313
314 /**
315  * qcom_scm_call_atomic1() - Send an atomic SCM command with one argument
316  * @svc_id: service identifier
317  * @cmd_id: command identifier
318  * @arg1: first argument
319  *
320  * This shall only be used with commands that are guaranteed to be
321  * uninterruptable, atomic and SMP safe.
322  */
323 static s32 qcom_scm_call_atomic1(u32 svc, u32 cmd, u32 arg1)
324 {
325         int context_id;
326
327         register u32 r0 asm("r0") = SCM_ATOMIC(svc, cmd, 1);
328         register u32 r1 asm("r1") = (u32)&context_id;
329         register u32 r2 asm("r2") = arg1;
330
331         asm volatile(
332                         __asmeq("%0", "r0")
333                         __asmeq("%1", "r0")
334                         __asmeq("%2", "r1")
335                         __asmeq("%3", "r2")
336 #ifdef REQUIRES_SEC
337                         ".arch_extension sec\n"
338 #endif
339                         "smc    #0      @ switch to secure world\n"
340                         : "=r" (r0)
341                         : "r" (r0), "r" (r1), "r" (r2)
342                         : "r3");
343         return r0;
344 }
345
346 u32 qcom_scm_get_version(void)
347 {
348         int context_id;
349         static u32 version = -1;
350         register u32 r0 asm("r0");
351         register u32 r1 asm("r1");
352
353         if (version != -1)
354                 return version;
355
356         mutex_lock(&qcom_scm_lock);
357
358         r0 = 0x1 << 8;
359         r1 = (u32)&context_id;
360         do {
361                 asm volatile(
362                         __asmeq("%0", "r0")
363                         __asmeq("%1", "r1")
364                         __asmeq("%2", "r0")
365                         __asmeq("%3", "r1")
366 #ifdef REQUIRES_SEC
367                         ".arch_extension sec\n"
368 #endif
369                         "smc    #0      @ switch to secure world\n"
370                         : "=r" (r0), "=r" (r1)
371                         : "r" (r0), "r" (r1)
372                         : "r2", "r3");
373         } while (r0 == QCOM_SCM_INTERRUPTED);
374
375         version = r1;
376         mutex_unlock(&qcom_scm_lock);
377
378         return version;
379 }
380 EXPORT_SYMBOL(qcom_scm_get_version);
381
382 /*
383  * Set the cold/warm boot address for one of the CPU cores.
384  */
385 static int qcom_scm_set_boot_addr(u32 addr, int flags)
386 {
387         struct {
388                 __le32 flags;
389                 __le32 addr;
390         } cmd;
391
392         cmd.addr = cpu_to_le32(addr);
393         cmd.flags = cpu_to_le32(flags);
394         return qcom_scm_call(QCOM_SCM_SVC_BOOT, QCOM_SCM_BOOT_ADDR,
395                         &cmd, sizeof(cmd), NULL, 0);
396 }
397
398 /**
399  * qcom_scm_set_cold_boot_addr() - Set the cold boot address for cpus
400  * @entry: Entry point function for the cpus
401  * @cpus: The cpumask of cpus that will use the entry point
402  *
403  * Set the cold boot address of the cpus. Any cpu outside the supported
404  * range would be removed from the cpu present mask.
405  */
406 int __qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus)
407 {
408         int flags = 0;
409         int cpu;
410         int scm_cb_flags[] = {
411                 QCOM_SCM_FLAG_COLDBOOT_CPU0,
412                 QCOM_SCM_FLAG_COLDBOOT_CPU1,
413                 QCOM_SCM_FLAG_COLDBOOT_CPU2,
414                 QCOM_SCM_FLAG_COLDBOOT_CPU3,
415         };
416
417         if (!cpus || (cpus && cpumask_empty(cpus)))
418                 return -EINVAL;
419
420         for_each_cpu(cpu, cpus) {
421                 if (cpu < ARRAY_SIZE(scm_cb_flags))
422                         flags |= scm_cb_flags[cpu];
423                 else
424                         set_cpu_present(cpu, false);
425         }
426
427         return qcom_scm_set_boot_addr(virt_to_phys(entry), flags);
428 }
429
430 /**
431  * qcom_scm_set_warm_boot_addr() - Set the warm boot address for cpus
432  * @entry: Entry point function for the cpus
433  * @cpus: The cpumask of cpus that will use the entry point
434  *
435  * Set the Linux entry point for the SCM to transfer control to when coming
436  * out of a power down. CPU power down may be executed on cpuidle or hotplug.
437  */
438 int __qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus)
439 {
440         int ret;
441         int flags = 0;
442         int cpu;
443
444         /*
445          * Reassign only if we are switching from hotplug entry point
446          * to cpuidle entry point or vice versa.
447          */
448         for_each_cpu(cpu, cpus) {
449                 if (entry == qcom_scm_wb[cpu].entry)
450                         continue;
451                 flags |= qcom_scm_wb[cpu].flag;
452         }
453
454         /* No change in entry function */
455         if (!flags)
456                 return 0;
457
458         ret = qcom_scm_set_boot_addr(virt_to_phys(entry), flags);
459         if (!ret) {
460                 for_each_cpu(cpu, cpus)
461                         qcom_scm_wb[cpu].entry = entry;
462         }
463
464         return ret;
465 }
466
467 /**
468  * qcom_scm_cpu_power_down() - Power down the cpu
469  * @flags - Flags to flush cache
470  *
471  * This is an end point to power down cpu. If there was a pending interrupt,
472  * the control would return from this function, otherwise, the cpu jumps to the
473  * warm boot entry point set for this cpu upon reset.
474  */
475 void __qcom_scm_cpu_power_down(u32 flags)
476 {
477         qcom_scm_call_atomic1(QCOM_SCM_SVC_BOOT, QCOM_SCM_CMD_TERMINATE_PC,
478                         flags & QCOM_SCM_FLUSH_FLAG_MASK);
479 }
480
481 int __qcom_scm_is_call_available(u32 svc_id, u32 cmd_id)
482 {
483         int ret;
484         __le32 svc_cmd = cpu_to_le32((svc_id << 10) | cmd_id);
485         __le32 ret_val = 0;
486
487         ret = qcom_scm_call(QCOM_SCM_SVC_INFO, QCOM_IS_CALL_AVAIL_CMD, &svc_cmd,
488                         sizeof(svc_cmd), &ret_val, sizeof(ret_val));
489         if (ret)
490                 return ret;
491
492         return le32_to_cpu(ret_val);
493 }
494
495 int __qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp)
496 {
497         if (req_cnt > QCOM_SCM_HDCP_MAX_REQ_CNT)
498                 return -ERANGE;
499
500         return qcom_scm_call(QCOM_SCM_SVC_HDCP, QCOM_SCM_CMD_HDCP,
501                 req, req_cnt * sizeof(*req), resp, sizeof(*resp));
502 }
503
504 int __qcom_scm_pas_mss_reset(bool reset)
505 {
506         __le32 val = cpu_to_le32(reset);
507         __le32 resp;
508
509         return qcom_scm_call(QCOM_SCM_SVC_PIL, QCOM_SCM_PAS_MSS_RESET,
510                                 &val, sizeof(val),
511                                 &resp, sizeof(resp));
512 }
513
514 bool __qcom_scm_pas_supported(u32 peripheral)
515 {
516         u32 ret_val;
517         int ret;
518
519         ret = qcom_scm_call(QCOM_SCM_SVC_PIL, QCOM_SCM_PAS_IS_SUPPORTED_CMD,
520                             &peripheral, sizeof(peripheral),
521                             &ret_val, sizeof(ret_val));
522
523         return ret ? false : !!ret_val;
524 }
525
526 int __qcom_scm_pas_init_image(u32 peripheral, dma_addr_t metadata_phys)
527 {
528         __le32 scm_ret;
529         int ret;
530         struct {
531                 __le32 proc;
532                 __le32 image_addr;
533         } request;
534
535         request.proc = cpu_to_le32(peripheral);
536         request.image_addr = cpu_to_le32(metadata_phys);
537
538         ret = qcom_scm_call(QCOM_SCM_SVC_PIL, QCOM_SCM_PAS_INIT_IMAGE_CMD,
539                             &request, sizeof(request),
540                             &scm_ret, sizeof(scm_ret));
541
542         return ret ? : le32_to_cpu(scm_ret);
543 }
544
545 int __qcom_scm_pas_mem_setup(u32 peripheral, phys_addr_t addr, phys_addr_t size)
546 {
547         u32 scm_ret;
548         int ret;
549         struct pas_init_image_req {
550                 u32 proc;
551                 u32 addr;
552                 u32 len;
553         } request;
554
555         request.proc = peripheral;
556         request.addr = addr;
557         request.len = size;
558
559         ret = qcom_scm_call(QCOM_SCM_SVC_PIL, QCOM_SCM_PAS_MEM_SETUP_CMD,
560                             &request, sizeof(request),
561                             &scm_ret, sizeof(scm_ret));
562
563         return ret ? : scm_ret;
564 }
565
566 int __qcom_scm_pas_auth_and_reset(u32 peripheral)
567 {
568         u32 scm_ret;
569         int ret;
570
571         ret = qcom_scm_call(QCOM_SCM_SVC_PIL, QCOM_SCM_PAS_AUTH_AND_RESET_CMD,
572                             &peripheral, sizeof(peripheral),
573                             &scm_ret, sizeof(scm_ret));
574
575         return ret ? : scm_ret;
576 }
577
578 int __qcom_scm_pas_shutdown(u32 peripheral)
579 {
580         u32 scm_ret;
581         int ret;
582
583         ret = qcom_scm_call(QCOM_SCM_SVC_PIL, QCOM_SCM_PAS_SHUTDOWN_CMD,
584                             &peripheral, sizeof(peripheral),
585                             &scm_ret, sizeof(scm_ret));
586
587         return ret ? : scm_ret;
588 }
589
590
591 int __qcom_scm_pil_init_image_cmd(u32 proc, u64 image_addr)
592 {
593         int ret;
594         u32 scm_ret = 0;
595         struct {
596                 u32 proc;
597                 u32 image_addr;
598         } req;
599
600         req.proc = proc;
601         req.image_addr = image_addr;
602
603         ret = qcom_scm_call(SCM_SVC_PIL, PAS_INIT_IMAGE_CMD, &req,
604                             sizeof(req), &scm_ret, sizeof(scm_ret));
605         if (ret)
606                 return ret;
607
608         return scm_ret;
609 }
610
611 int __qcom_scm_pil_mem_setup_cmd(u32 proc, u64 start_addr, u32 len)
612 {
613         u32 scm_ret = 0;
614         int ret;
615         struct {
616                 u32 proc;
617                 u32 start_addr;
618                 u32 len;
619         } req;
620
621         req.proc = proc;
622         req.start_addr = start_addr;
623         req.len = len;
624
625         ret = qcom_scm_call(SCM_SVC_PIL, PAS_MEM_SETUP_CMD, &req,
626                             sizeof(req), &scm_ret, sizeof(scm_ret));
627         if (ret)
628                 return ret;
629
630         return scm_ret;
631 }
632
633 int __qcom_scm_pil_auth_and_reset_cmd(u32 proc)
634 {
635         u32 scm_ret = 0;
636         int ret;
637         u32 req;
638
639         req = proc;
640
641         ret = qcom_scm_call(SCM_SVC_PIL, PAS_AUTH_AND_RESET_CMD, &req,
642                             sizeof(req), &scm_ret, sizeof(scm_ret));
643         if (ret)
644                 return ret;
645
646         return scm_ret;
647 }
648
649 int __qcom_scm_pil_shutdown_cmd(u32 proc)
650 {
651         u32 scm_ret = 0;
652         int ret;
653         u32 req;
654
655         req = proc;
656
657         ret = qcom_scm_call(SCM_SVC_PIL, PAS_SHUTDOWN_CMD, &req,
658                             sizeof(req), &scm_ret, sizeof(scm_ret));
659         if (ret)
660                 return ret;
661
662         return scm_ret;
663 }
664
665 #define SCM_SVC_UTIL                    0x3
666 #define SCM_SVC_MP                      0xc
667 #define IOMMU_DUMP_SMMU_FAULT_REGS      0x0c
668
669 int __qcom_scm_iommu_dump_fault_regs(u32 id, u32 context, u64 addr, u32 len)
670 {
671         struct {
672                 u32 id;
673                 u32 cb_num;
674                 u32 buff;
675                 u32 len;
676         } req;
677         int resp = 0;
678
679         return qcom_scm_call(SCM_SVC_UTIL, IOMMU_DUMP_SMMU_FAULT_REGS,
680                        &req, sizeof(req), &resp, 1);
681 }
682
683 int __qcom_scm_iommu_set_cp_pool_size(u32 size, u32 spare)
684 {
685         struct {
686                 u32 size;
687                 u32 spare;
688         } req;
689         int retval;
690
691         req.size = size;
692         req.spare = spare;
693
694         return qcom_scm_call(SCM_SVC_MP, IOMMU_SET_CP_POOL_SIZE,
695                              &req, sizeof(req), &retval, sizeof(retval));
696 }
697
698 int __qcom_scm_iommu_secure_ptbl_size(u32 spare, int psize[2])
699 {
700         struct {
701                 u32 spare;
702         } req;
703
704         req.spare = spare;
705
706         return qcom_scm_call(SCM_SVC_MP, IOMMU_SECURE_PTBL_SIZE, &req,
707                              sizeof(req), psize, sizeof(psize));
708 }
709
710 int __qcom_scm_iommu_secure_ptbl_init(u64 addr, u32 size, u32 spare)
711 {
712         struct {
713                 u32 addr;
714                 u32 size;
715                 u32 spare;
716         } req = {0};
717         int ret, ptbl_ret = 0;
718
719         req.addr = addr;
720         req.size = size;
721         req.spare = spare;
722
723         ret = qcom_scm_call(SCM_SVC_MP, IOMMU_SECURE_PTBL_INIT, &req,
724                             sizeof(req), &ptbl_ret, sizeof(ptbl_ret));
725
726         if (ret)
727                 return ret;
728
729         if (ptbl_ret)
730                 return ptbl_ret;
731
732         return 0;
733 }
734
735 int __qcom_scm_iommu_secure_map(u64 list, u32 list_size, u32 size,
736                                 u32 id, u32 ctx_id, u64 va, u32 info_size,
737                                 u32 flags)
738 {
739         struct {
740                 struct {
741                         unsigned int list;
742                         unsigned int list_size;
743                         unsigned int size;
744                 } plist;
745                 struct {
746                         unsigned int id;
747                         unsigned int ctx_id;
748                         unsigned int va;
749                         unsigned int size;
750                 } info;
751                 unsigned int flags;
752         } req;
753         u32 resp;
754         int ret;
755
756         req.plist.list = list;
757         req.plist.list_size = list_size;
758         req.plist.size = size;
759         req.info.id = id;
760         req.info.ctx_id = ctx_id;
761         req.info.va = va;
762         req.info.size = info_size;
763         req.flags = flags;
764
765         ret = qcom_scm_call(SCM_SVC_MP, IOMMU_SECURE_MAP2, &req, sizeof(req),
766                             &resp, sizeof(resp));
767
768         if (ret || resp)
769                 return -EINVAL;
770
771         return 0;
772 }
773
774 int __qcom_scm_iommu_secure_unmap(u32 id, u32 ctx_id, u64 va,
775                                   u32 size, u32 flags)
776 {
777         struct {
778                 struct {
779                         unsigned int id;
780                         unsigned int ctx_id;
781                         unsigned int va;
782                         unsigned int size;
783                 } info;
784                 unsigned int flags;
785         } req;
786         int ret, scm_ret;
787
788         req.info.id = id;
789         req.info.ctx_id = ctx_id;
790         req.info.va = va;
791         req.info.size = size;
792         req.flags = flags;
793
794         return qcom_scm_call(SCM_SVC_MP, IOMMU_SECURE_UNMAP2, &req,
795                              sizeof(req), &scm_ret, sizeof(scm_ret));
796 }
797
798 int __qcom_scm_get_feat_version(u32 feat)
799 {
800         int ret;
801
802         if (__qcom_scm_is_call_available(SCM_SVC_INFO, GET_FEAT_VERSION_CMD)) {
803                 u32 version;
804
805                 if (!qcom_scm_call(SCM_SVC_INFO, GET_FEAT_VERSION_CMD, &feat,
806                                    sizeof(feat), &version, sizeof(version)))
807                         return version;
808         }
809
810         return 0;
811 }
812
813 #define RESTORE_SEC_CFG         2
814 int __qcom_scm_restore_sec_cfg(u32 device_id, u32 spare)
815 {
816         struct {
817                 u32 device_id;
818                 u32 spare;
819         } req;
820         int ret, scm_ret = 0;
821
822         req.device_id = device_id;
823         req.spare = spare;
824
825         ret = qcom_scm_call(SCM_SVC_MP, RESTORE_SEC_CFG, &req, sizeof(req),
826                             scm_ret, sizeof(scm_ret));
827         if (ret || scm_ret)
828                 return ret ? ret : -EINVAL;
829
830         return 0;
831 }
832
833 #define TZBSP_VIDEO_SET_STATE   0xa
834 int __qcom_scm_set_video_state(u32 state, u32 spare)
835 {
836         struct {
837                 u32 state;
838                 u32 spare;
839         } req;
840         int scm_ret = 0;
841         int ret;
842
843         req.state = state;
844         req.spare = spare;
845
846         ret = qcom_scm_call(SCM_SVC_BOOT, TZBSP_VIDEO_SET_STATE, &req,
847                             sizeof(req), &scm_ret, sizeof(scm_ret));
848         if (ret || scm_ret)
849                         return ret ? ret : -EINVAL;
850
851         return 0;
852 }
853
854 #define TZBSP_MEM_PROTECT_VIDEO_VAR     0x8
855
856 int __qcom_scm_mem_protect_video_var(u32 start, u32 size, u32 nonpixel_start,
857                                      u32 nonpixel_size)
858 {
859         struct {
860                 u32 cp_start;
861                 u32 cp_size;
862                 u32 cp_nonpixel_start;
863                 u32 cp_nonpixel_size;
864         } req;
865         int ret, scm_ret;
866
867         req.cp_start = start;
868         req.cp_size = size;
869         req.cp_nonpixel_start = nonpixel_start;
870         req.cp_nonpixel_size = nonpixel_size;
871
872         ret = qcom_scm_call(SCM_SVC_MP, TZBSP_MEM_PROTECT_VIDEO_VAR, &req,
873                             sizeof(req), &scm_ret, sizeof(scm_ret));
874
875         if (ret || scm_ret)
876                         return ret ? ret : -EINVAL;
877
878         return 0;
879 }
880
881 int __qcom_scm_init(void)
882 {
883         return 0;
884 }