xref: /linux/drivers/firmware/qcom/qcom_scm-smc.c (revision 3a2c4d55e32ad65efebdb6de44eef3bfa08bb49d)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /* Copyright (c) 2015,2019 The Linux Foundation. All rights reserved.
3  */
4 
5 #include <linux/cleanup.h>
6 #include <linux/io.h>
7 #include <linux/errno.h>
8 #include <linux/delay.h>
9 #include <linux/mutex.h>
10 #include <linux/slab.h>
11 #include <linux/types.h>
12 #include <linux/firmware/qcom/qcom_scm.h>
13 #include <linux/firmware/qcom/qcom_tzmem.h>
14 #include <linux/arm-smccc.h>
15 #include <linux/dma-mapping.h>
16 
17 #include "qcom_scm.h"
18 
19 /**
20  * struct arm_smccc_args
21  * @args:	The array of values used in registers in smc instruction
22  */
23 struct arm_smccc_args {
24 	unsigned long args[8];
25 };
26 
27 #define CREATE_TRACE_POINTS
28 #include "qcom_scm_trace.h"
29 
30 static DEFINE_MUTEX(qcom_scm_lock);
31 
32 #define QCOM_SCM_EBUSY_WAIT_MS 30
33 #define QCOM_SCM_EBUSY_MAX_RETRY 20
34 
35 #define SCM_SMC_N_REG_ARGS	4
36 #define SCM_SMC_FIRST_EXT_IDX	(SCM_SMC_N_REG_ARGS - 1)
37 #define SCM_SMC_N_EXT_ARGS	(MAX_QCOM_SCM_ARGS - SCM_SMC_N_REG_ARGS + 1)
38 #define SCM_SMC_FIRST_REG_IDX	2
39 #define SCM_SMC_LAST_REG_IDX	(SCM_SMC_FIRST_REG_IDX + SCM_SMC_N_REG_ARGS - 1)
40 
41 static void __scm_smc_do_quirk(const struct arm_smccc_args *smc,
42 			       struct arm_smccc_res *res)
43 {
44 	unsigned long a0 = smc->args[0];
45 	struct arm_smccc_quirk quirk = { .id = ARM_SMCCC_QUIRK_QCOM_A6 };
46 
47 	quirk.state.a6 = 0;
48 
49 	do {
50 		trace_scm_smc_request(a0, smc);
51 		arm_smccc_smc_quirk(a0, smc->args[1], smc->args[2],
52 				    smc->args[3], smc->args[4], smc->args[5],
53 				    quirk.state.a6, smc->args[7], res, &quirk);
54 
55 		if (res->a0 == QCOM_SCM_INTERRUPTED)
56 			a0 = res->a0;
57 
58 	} while (res->a0 == QCOM_SCM_INTERRUPTED);
59 }
60 
61 static void fill_wq_resume_args(struct arm_smccc_args *resume, u32 smc_call_ctx)
62 {
63 	memset(resume->args, 0, sizeof(resume->args[0]) * ARRAY_SIZE(resume->args));
64 
65 	resume->args[0] = ARM_SMCCC_CALL_VAL(ARM_SMCCC_STD_CALL,
66 					ARM_SMCCC_SMC_64, ARM_SMCCC_OWNER_SIP,
67 					SCM_SMC_FNID(QCOM_SCM_SVC_WAITQ, QCOM_SCM_WAITQ_RESUME));
68 
69 	resume->args[1] = QCOM_SCM_ARGS(1);
70 
71 	resume->args[2] = smc_call_ctx;
72 }
73 
74 int scm_get_wq_ctx(u32 *wq_ctx, u32 *flags, u32 *more_pending)
75 {
76 	int ret;
77 	struct arm_smccc_res get_wq_res;
78 	struct arm_smccc_args get_wq_ctx = {0};
79 
80 	get_wq_ctx.args[0] = ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL,
81 				ARM_SMCCC_SMC_64, ARM_SMCCC_OWNER_SIP,
82 				SCM_SMC_FNID(QCOM_SCM_SVC_WAITQ, QCOM_SCM_WAITQ_GET_WQ_CTX));
83 
84 	/* Guaranteed to return only success or error, no WAITQ_* */
85 	__scm_smc_do_quirk(&get_wq_ctx, &get_wq_res);
86 	ret = get_wq_res.a0;
87 	if (ret)
88 		return ret;
89 
90 	trace_scm_waitq_get_wq_ctx(get_wq_res.a1, get_wq_res.a2, get_wq_res.a3);
91 	*wq_ctx = get_wq_res.a1;
92 	*flags  = get_wq_res.a2;
93 	*more_pending = get_wq_res.a3;
94 
95 	return 0;
96 }
97 
98 static int __scm_smc_do_quirk_handle_waitq(struct device *dev, struct arm_smccc_args *waitq,
99 					   struct arm_smccc_res *res)
100 {
101 	int ret;
102 	u32 wq_ctx, smc_call_ctx;
103 	struct arm_smccc_args resume;
104 	struct arm_smccc_args *smc = waitq;
105 
106 	do {
107 		__scm_smc_do_quirk(smc, res);
108 
109 		if (res->a0 == QCOM_SCM_WAITQ_SLEEP) {
110 			wq_ctx = res->a1;
111 			smc_call_ctx = res->a2;
112 
113 			trace_scm_waitq_sleep(wq_ctx, smc_call_ctx);
114 			ret = qcom_scm_wait_for_wq_completion(dev, wq_ctx);
115 			if (ret)
116 				return ret;
117 
118 			trace_scm_waitq_resume(smc_call_ctx);
119 			fill_wq_resume_args(&resume, smc_call_ctx);
120 			smc = &resume;
121 		}
122 	} while (res->a0 == QCOM_SCM_WAITQ_SLEEP);
123 
124 	return 0;
125 }
126 
127 static int __scm_smc_do(struct device *dev, struct arm_smccc_args *smc,
128 			struct arm_smccc_res *res, bool atomic)
129 {
130 	int ret, retry_count = 0;
131 
132 	if (atomic) {
133 		__scm_smc_do_quirk(smc, res);
134 		return 0;
135 	}
136 
137 	do {
138 		mutex_lock(&qcom_scm_lock);
139 
140 		ret = __scm_smc_do_quirk_handle_waitq(dev, smc, res);
141 
142 		mutex_unlock(&qcom_scm_lock);
143 
144 		if (ret)
145 			return ret;
146 
147 		if (res->a0 == QCOM_SCM_V2_EBUSY) {
148 			if (retry_count++ > QCOM_SCM_EBUSY_MAX_RETRY)
149 				break;
150 			msleep(QCOM_SCM_EBUSY_WAIT_MS);
151 		}
152 	}  while (res->a0 == QCOM_SCM_V2_EBUSY);
153 
154 	return 0;
155 }
156 
157 
158 int __scm_smc_call(struct device *dev, const struct qcom_scm_desc *desc,
159 		   enum qcom_scm_convention qcom_convention,
160 		   struct qcom_scm_res *res, bool atomic)
161 {
162 	int arglen = desc->arginfo & 0xf;
163 	int i, ret;
164 	void *args_virt __free(qcom_tzmem) = NULL;
165 	gfp_t flag = atomic ? GFP_ATOMIC : GFP_KERNEL;
166 	u32 smccc_call_type = atomic ? ARM_SMCCC_FAST_CALL : ARM_SMCCC_STD_CALL;
167 	u32 qcom_smccc_convention = (qcom_convention == SMC_CONVENTION_ARM_32) ?
168 				    ARM_SMCCC_SMC_32 : ARM_SMCCC_SMC_64;
169 	struct arm_smccc_res smc_res;
170 	struct arm_smccc_args smc = {0};
171 
172 	smc.args[0] = ARM_SMCCC_CALL_VAL(
173 		smccc_call_type,
174 		qcom_smccc_convention,
175 		desc->owner,
176 		SCM_SMC_FNID(desc->svc, desc->cmd));
177 	smc.args[1] = desc->arginfo;
178 	for (i = 0; i < SCM_SMC_N_REG_ARGS; i++)
179 		smc.args[i + SCM_SMC_FIRST_REG_IDX] = desc->args[i];
180 
181 	if (unlikely(arglen > SCM_SMC_N_REG_ARGS)) {
182 		struct qcom_tzmem_pool *mempool = qcom_scm_get_tzmem_pool();
183 
184 		if (!mempool)
185 			return -EINVAL;
186 
187 		args_virt = qcom_tzmem_alloc(mempool,
188 					     SCM_SMC_N_EXT_ARGS * sizeof(u64),
189 					     flag);
190 		if (!args_virt)
191 			return -ENOMEM;
192 
193 		if (qcom_smccc_convention == ARM_SMCCC_SMC_32) {
194 			__le32 *args = args_virt;
195 
196 			for (i = 0; i < SCM_SMC_N_EXT_ARGS; i++)
197 				args[i] = cpu_to_le32(desc->args[i +
198 						      SCM_SMC_FIRST_EXT_IDX]);
199 		} else {
200 			__le64 *args = args_virt;
201 
202 			for (i = 0; i < SCM_SMC_N_EXT_ARGS; i++)
203 				args[i] = cpu_to_le64(desc->args[i +
204 						      SCM_SMC_FIRST_EXT_IDX]);
205 		}
206 
207 		smc.args[SCM_SMC_LAST_REG_IDX] = qcom_tzmem_to_phys(args_virt);
208 	}
209 
210 	ret = __scm_smc_do(dev, &smc, &smc_res, atomic);
211 
212 	trace_scm_smc_done(ret, smc.args[0], &smc_res);
213 
214 	if (ret)
215 		return ret;
216 
217 	if (res) {
218 		res->result[0] = smc_res.a1;
219 		res->result[1] = smc_res.a2;
220 		res->result[2] = smc_res.a3;
221 	}
222 
223 	return (long)smc_res.a0 ? qcom_scm_remap_error(smc_res.a0) : 0;
224 
225 }
226