• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 		      &param);
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