1 /*
2 * Based on arch/arm64/kernel/chipid-sunxi.c
3 *
4 * Copyright (C) 2015 Allwinnertech Ltd.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18 #include <linux/io.h>
19 #include <linux/kernel.h>
20 #include <sunxi-smc.h>
21 #include <linux/arm-smccc.h>
22 #include <linux/bitops.h>
23
24 #include <linux/module.h>
25 #include <linux/printk.h>
26 #include <linux/kernel.h>
27 #include <linux/device.h>
28 #include <linux/vmalloc.h>
29 #include <linux/uaccess.h>
30 #include <linux/fs.h>
31 #include <linux/miscdevice.h>
32
33 #ifndef OPTEE_SMC_STD_CALL_VAL
34 #define OPTEE_SMC_STD_CALL_VAL(func_num) \
35 ARM_SMCCC_CALL_VAL(ARM_SMCCC_STD_CALL, ARM_SMCCC_SMC_32, \
36 ARM_SMCCC_OWNER_TRUSTED_OS, (func_num))
37 #endif
38
39 #ifndef OPTEE_SMC_FAST_CALL_VAL
40 #define OPTEE_SMC_FAST_CALL_VAL(func_num) \
41 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, ARM_SMCCC_SMC_32, \
42 ARM_SMCCC_OWNER_TRUSTED_OS, (func_num))
43 #endif
44 /*
45 * Function specified by SMC Calling convention.
46 */
47 #define OPTEE_SMC_FUNCID_READ_REG (17 | sunxi_smc_call_offset())
48 #define OPTEE_SMC_READ_REG \
49 OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_READ_REG)
50
51
52 #define OPTEE_SMC_FUNCID_WRITE_REG (18 | sunxi_smc_call_offset())
53 #define OPTEE_SMC_WRITE_REG \
54 OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_WRITE_REG)
55
56 #define OPTEE_SMC_FUNCID_COPY_ARISC_PARAS (19 | sunxi_smc_call_offset())
57 #define OPTEE_SMC_COPY_ARISC_PARAS \
58 OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_COPY_ARISC_PARAS)
59 #define ARM_SVC_COPY_ARISC_PARAS OPTEE_SMC_COPY_ARISC_PARAS
60
61 #define OPTEE_SMC_FUNCID_GET_TEEADDR_PARAS (20 | sunxi_smc_call_offset())
62 #define OPTEE_SMC_GET_TEEADDR_PARAS \
63 OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_GET_TEEADDR_PARAS)
64 #define ARM_SVC_GET_TEEADDR_PARAS OPTEE_SMC_GET_TEEADDR_PARAS
65
66 #define OPTEE_SMC_FUNCID_GET_DRMINFO (15 | sunxi_smc_call_offset())
67 #define OPTEE_SMC_GET_DRM_INFO \
68 OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_GET_DRMINFO)
69
70 #define OPTEE_SMC_FUNCID_READ_EFUSE 24
71 #define OPTEE_SMC_READ_EFUSE \
72 OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_READ_EFUSE)
73
74
75 #define OPTEE_SMC_FUNCID_WRITE_EFUSE 25
76 #define OPTEE_SMC_WRITE_EFUSE \
77 OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_WRITE_EFUSE)
78
79 #if defined(CONFIG_ARM64)
80 /*cmd to call ATF service*/
81 #define ARM_SVC_EFUSE_PROBE_SECURE_ENABLE (0xc000fe03)
82 #define ARM_SVC_READ_SEC_REG (0xC000ff05)
83 #define ARM_SVC_WRITE_SEC_REG (0xC000ff06)
84 #define ARM_SVC_EFUSE_READ_AARCH64 (0xc000fe00)
85 #define ARM_SVC_EFUSE_WRITE_AARCH64 (0xc000fe01)
86 #define ARM_SVC_EFUSE_READ ARM_SVC_EFUSE_READ_AARCH64
87 #define ARM_SVC_EFUSE_WRITE ARM_SVC_EFUSE_WRITE_AARCH64
88
89 #elif defined(CONFIG_ARCH_SUN50I) && defined(CONFIG_ARM)
90 #define ARM_SVC_EFUSE_PROBE_SECURE_ENABLE (0x8000fe03)
91 #define ARM_SVC_READ_SEC_REG (0x8000ff05)
92 #define ARM_SVC_WRITE_SEC_REG (0x8000ff06)
93 #define ARM_SVC_EFUSE_READ_AARCH32 (0x8000fe00)
94 #define ARM_SVC_EFUSE_WRITE_AARCH32 (0x8000fe01)
95 #define ARM_SVC_EFUSE_READ ARM_SVC_EFUSE_READ_AARCH32
96 #define ARM_SVC_EFUSE_WRITE ARM_SVC_EFUSE_WRITE_AARCH32
97
98 #else
99 /*cmd to call TEE service*/
100 #define ARM_SVC_READ_SEC_REG OPTEE_SMC_READ_REG
101 #define ARM_SVC_WRITE_SEC_REG OPTEE_SMC_WRITE_REG
102 #define ARM_SVC_EFUSE_READ OPTEE_SMC_READ_EFUSE
103 #define ARM_SVC_EFUSE_WRITE OPTEE_SMC_WRITE_EFUSE
104 #endif
105
106 /*interface for smc */
sunxi_smc_readl(phys_addr_t addr)107 u32 sunxi_smc_readl(phys_addr_t addr)
108 {
109 #if defined(CONFIG_ARM64) || defined(CONFIG_TEE)
110 struct arm_smccc_res res;
111 arm_smccc_smc(ARM_SVC_READ_SEC_REG, addr, 0, 0, 0, 0, 0, 0, &res);
112 return res.a0;
113 #else
114 void __iomem *vaddr = ioremap(addr, 4);
115 u32 ret;
116 ret = readl(vaddr);
117 iounmap(vaddr);
118 return ret;
119 #endif
120 }
121 EXPORT_SYMBOL(sunxi_smc_readl);
122
sunxi_smc_writel(u32 value,phys_addr_t addr)123 int sunxi_smc_writel(u32 value, phys_addr_t addr)
124 {
125 #if defined(CONFIG_ARM64) || defined(CONFIG_TEE)
126 struct arm_smccc_res res;
127 arm_smccc_smc(ARM_SVC_WRITE_SEC_REG, addr, value, 0, 0, 0, 0, 0, &res);
128 return res.a0;
129 #else
130 void __iomem *vaddr = ioremap(addr, 4);
131 writel(value, vaddr);
132 iounmap(vaddr);
133 return 0;
134 #endif
135 }
136 EXPORT_SYMBOL(sunxi_smc_writel);
137
arm_svc_efuse_write(phys_addr_t key_buf)138 int arm_svc_efuse_write(phys_addr_t key_buf)
139 {
140 #if defined(CONFIG_ARM64)
141 struct arm_smccc_res res;
142 arm_smccc_smc(ARM_SVC_EFUSE_WRITE, (unsigned long)key_buf, 0, 0, 0, 0,
143 0, 0, &res);
144 return res.a0;
145 #elif defined(CONFIG_ARCH_SUN50I) && defined(CONFIG_ARM)
146 struct arm_smccc_res res;
147 arm_smccc_smc(ARM_SVC_EFUSE_WRITE, (unsigned long)key_buf, 0, 0, 0, 0,
148 0, 0, &res);
149 return res.a0;
150 #elif defined(CONFIG_TEE)
151 struct arm_smccc_res res;
152 arm_smccc_smc(ARM_SVC_EFUSE_WRITE, (unsigned long)key_buf, 0, 0, 0, 0,
153 0, 0, &res);
154 return res.a0;
155 #else
156 return -1;
157 #endif
158 }
159 EXPORT_SYMBOL_GPL(arm_svc_efuse_write);
160
arm_svc_efuse_read(phys_addr_t key_buf,phys_addr_t read_buf)161 int arm_svc_efuse_read(phys_addr_t key_buf, phys_addr_t read_buf)
162 {
163 #if defined(CONFIG_ARM64)
164 struct arm_smccc_res res;
165 arm_smccc_smc(ARM_SVC_EFUSE_READ, (unsigned long)key_buf,
166 (unsigned long)read_buf, 0, 0, 0, 0, 0, &res);
167 return res.a0;
168 #elif defined(CONFIG_ARCH_SUN50I) && defined(CONFIG_ARM)
169 struct arm_smccc_res res;
170 arm_smccc_smc(ARM_SVC_EFUSE_READ, (unsigned long)key_buf,
171 (unsigned long)read_buf, 0, 0, 0, 0, 0, &res);
172 return res.a0;
173 #elif defined(CONFIG_TEE)
174 struct arm_smccc_res res;
175 arm_smccc_smc(ARM_SVC_EFUSE_READ, (unsigned long)key_buf,
176 (unsigned long)read_buf, 0, 0, 0, 0, 0, &res);
177 return res.a0;
178 #else
179 return -1;
180 #endif
181 }
182 EXPORT_SYMBOL_GPL(arm_svc_efuse_read);
183
sunxi_smc_copy_arisc_paras(phys_addr_t dest,phys_addr_t src,u32 len)184 int sunxi_smc_copy_arisc_paras(phys_addr_t dest, phys_addr_t src, u32 len)
185 {
186 struct arm_smccc_res res;
187 arm_smccc_smc(ARM_SVC_COPY_ARISC_PARAS, dest, src, len, 0, 0, 0, 0, &res);
188 return res.a0;
189 }
190
sunxi_smc_get_teeaddr_paras(phys_addr_t resumeaddr)191 phys_addr_t sunxi_smc_get_teeaddr_paras(phys_addr_t resumeaddr)
192 {
193 struct arm_smccc_res res;
194
195 arm_smccc_smc(ARM_SVC_GET_TEEADDR_PARAS,
196 resumeaddr, 0, 0, 0, 0, 0, 0, &res);
197 return res.a0;
198 }
199 /*optee smc*/
200 #define ARM_SMCCC_SMC_32 0
201 #define ARM_SMCCC_SMC_64 1
202 #define ARM_SMCCC_CALL_CONV_SHIFT 30
203
204 #define ARM_SMCCC_OWNER_MASK 0x3F
205 #define ARM_SMCCC_OWNER_SHIFT 24
206
207 #define ARM_SMCCC_FUNC_MASK 0xFFFF
208 #define ARM_SMCCC_OWNER_TRUSTED_OS 50
209
210 #define ARM_SMCCC_IS_FAST_CALL(smc_val) \
211 ((smc_val) & (ARM_SMCCC_FAST_CALL << ARM_SMCCC_TYPE_SHIFT))
212 #define ARM_SMCCC_IS_64(smc_val) \
213 ((smc_val) & (ARM_SMCCC_SMC_64 << ARM_SMCCC_CALL_CONV_SHIFT))
214 #define ARM_SMCCC_FUNC_NUM(smc_val) ((smc_val) & ARM_SMCCC_FUNC_MASK)
215 #define ARM_SMCCC_OWNER_NUM(smc_val) \
216 (((smc_val) >> ARM_SMCCC_OWNER_SHIFT) & ARM_SMCCC_OWNER_MASK)
217
218 #define ARM_SMCCC_CALL_VAL(type, calling_convention, owner, func_num) \
219 (((type) << ARM_SMCCC_TYPE_SHIFT) | \
220 ((calling_convention) << ARM_SMCCC_CALL_CONV_SHIFT) | \
221 (((owner) & ARM_SMCCC_OWNER_MASK) << ARM_SMCCC_OWNER_SHIFT) | \
222 ((func_num) & ARM_SMCCC_FUNC_MASK))
223
224 #define OPTEE_SMC_FAST_CALL_VAL(func_num) \
225 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, ARM_SMCCC_SMC_32, \
226 ARM_SMCCC_OWNER_TRUSTED_OS, (func_num))
227
228 #define OPTEE_SMC_FUNCID_CRYPT 16
229 #define OPTEE_SMC_CRYPT \
230 OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_CRYPT)
231
232 #define TEESMC_RSSK_DECRYPT 5
sunxi_smc_refresh_hdcp(void)233 int sunxi_smc_refresh_hdcp(void)
234 {
235 struct arm_smccc_res res;
236 arm_smccc_smc(OPTEE_SMC_CRYPT, TEESMC_RSSK_DECRYPT, 0, 0, 0, 0, 0, 0, &res);
237 return res.a0;
238 }
239 EXPORT_SYMBOL(sunxi_smc_refresh_hdcp);
240
241 #define OPTEE_MSG_FUNCID_GET_OS_REVISION 0x0001
242 #define OPTEE_SMC_CALL_GET_OS_REVISION \
243 OPTEE_SMC_FAST_CALL_VAL(OPTEE_MSG_FUNCID_GET_OS_REVISION)
244
smc_tee_get_os_revision(uint32_t * major,uint32_t * minor)245 int smc_tee_get_os_revision(uint32_t *major, uint32_t *minor)
246 {
247 struct arm_smccc_res param = { 0 };
248
249 arm_smccc_smc(OPTEE_SMC_CALL_GET_OS_REVISION, 0, 0, 0, 0, 0, 0, 0,
250 ¶m);
251 *major = param.a0;
252 *minor = param.a1;
253 return 0;
254 }
255
sunxi_smc_call_offset(void)256 int sunxi_smc_call_offset(void)
257 {
258 uint32_t major, minor;
259
260 smc_tee_get_os_revision(&major, &minor);
261 if ((major > 3) || ((major == 3) && (minor >= 5))) {
262 return SUNXI_OPTEE_SMC_OFFSET;
263 } else {
264 return 0;
265 }
266 }
267
optee_probe_drm_configure(unsigned long * drm_base,size_t * drm_size,unsigned long * tee_base)268 int optee_probe_drm_configure(unsigned long *drm_base,
269 size_t *drm_size, unsigned long *tee_base)
270 {
271 struct arm_smccc_res res;
272
273 arm_smccc_smc(OPTEE_SMC_GET_DRM_INFO, 0, 0, 0, 0, 0, 0, 0, &res);
274 if (res.a0 != 0) {
275 printk("drm config service not available: %X", (uint32_t)res.a0);
276 return -EINVAL;
277 }
278
279 *drm_base = res.a1;
280 *drm_size = res.a2;
281 *tee_base = res.a3;
282
283 printk("drm_base=0x%x\n", (uint32_t)*drm_base);
284 printk("drm_size=0x%x\n", (uint32_t)*drm_size);
285 printk("tee_base=0x%x\n", (uint32_t)*tee_base);
286
287 return 0;
288 }
289 EXPORT_SYMBOL(optee_probe_drm_configure);
290
sunxi_smc_init(void)291 static int __init sunxi_smc_init(void)
292 {
293 return 0;
294 }
295
sunxi_smc_exit(void)296 static void __exit sunxi_smc_exit(void)
297 {
298 }
299
300 module_init(sunxi_smc_init);
301 module_exit(sunxi_smc_exit);
302 MODULE_LICENSE("GPL v2");
303 MODULE_AUTHOR("weidonghui<weidonghui@allwinnertech.com>");
304 MODULE_DESCRIPTION("sunxi smc.");
305