• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * drivers/soc/sunxi-sid.c
3  *
4  * Copyright(c) 2014-2016 Allwinnertech Co., Ltd.
5  *         http://www.allwinnertech.com
6  *
7  * Author: sunny <sunny@allwinnertech.com>
8  * Author: superm <superm@allwinnertech.com>
9  * Author: Matteo <duanmintao@allwinnertech.com>
10  *
11  * Allwinner sunxi soc chip version and chip id manager.
12  *
13  * This program is free software; you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License as published by
15  * the Free Software Foundation; either version 2 of the License, or
16  * (at your option) any later version.
17  */
18 
19 #include <linux/io.h>
20 #include <linux/of.h>
21 #include <linux/of_address.h>
22 #include <linux/err.h>
23 #include <sunxi-smc.h>
24 
25 #include <linux/module.h>
26 #include <linux/printk.h>
27 #include <linux/kernel.h>
28 #include <linux/device.h>
29 #include <linux/vmalloc.h>
30 #include <linux/uaccess.h>
31 #include <linux/fs.h>
32 #include <linux/miscdevice.h>
33 
34 #include <sunxi-sid.h>
35 #include <linux/acpi.h>
36 
37 #define SID_DBG(fmt, arg...) pr_debug("%s()%d - "fmt, __func__, __LINE__, ##arg)
38 #define SID_WARN(fmt, arg...) pr_warn("%s()%d - "fmt, __func__, __LINE__, ##arg)
39 #define SID_ERR(fmt, arg...) pr_err("%s()%d - "fmt, __func__, __LINE__, ##arg)
40 
41 #if defined(CONFIG_ARCH_SUN50I) || defined(CONFIG_ARCH_SUN8IW6)
42 #define SUNXI_SECURITY_SUPPORT	1
43 #endif
44 
45 #define SUNXI_VER_MAX_NUM	8
46 struct soc_ver_map {
47 	u32 id;
48 	u32 rev[SUNXI_VER_MAX_NUM];
49 };
50 
51 #define SUNXI_SOC_ID_INDEX		1
52 #define SUNXI_SECURITY_ENABLE_INDEX	2
53 struct soc_ver_reg {
54 	s8 compatile[48];
55 	u32 offset;
56 	u32 mask;
57 	u32 shift;
58 	struct soc_ver_map ver_map;
59 };
60 
61 #define SUNXI_SOC_ID_IN_SID
62 
63 #if defined(CONFIG_ARCH_SUN50IW6)
64 #define TYPE_SB (0b001)
65 #define TYPE_NB (0b010)
66 #define TYPE_FB (0b011)
67 #else
68 #define TYPE_SB (0b001)
69 #define TYPE_NB (0b011)
70 #define TYPE_FB (0b111)
71 #endif
72 
73 typedef struct {
74 	char name[64];
75 	uint32_t len;
76 	uint32_t offset;
77 	uint64_t key_data;
78 } sunxi_efuse_key_info_t;
79 
80 struct efuse_crypt {
81 	sunxi_efuse_key_info_t key_store;
82 	struct work_struct work;
83 	struct completion work_end;
84 	struct mutex mutex;
85 	unsigned char *temp_data;
86 	unsigned int cmd;
87 	unsigned int ret;
88 };
89 
90 typedef struct efuse_crypt efuse_cry_st;
91 typedef struct efuse_crypt *efuse_cry_pt;
92 
93 #define SECBLK_READ							_IO('V', 20)
94 #define SECBLK_WRITE						_IO('V', 21)
95 #define SECBLK_IOCTL						_IO('V', 22)
96 
97 struct secblc_op_t {
98 	int item;
99 	unsigned char *buf;
100 	unsigned int len;
101 };
102 
103 static unsigned int sunxi_soc_chipid[4];
104 static unsigned int sunxi_soc_ftzone[4];
105 static unsigned int sunxi_serial[4];
106 static int sunxi_soc_secure;
107 static unsigned int sunxi_soc_bin;
108 static unsigned int sunxi_soc_ver;
109 static unsigned int sunxi_soc_rotpk_status;
110 
chip_ver_platform_process(u32 val)111 u32 chip_ver_platform_process(u32 val)
112 {
113 #if defined(CONFIG_ARCH_SUN8IW20) || defined(CONFIG_ARCH_SUN20IW1)
114 	/*c_version is 101*/
115 	if (val == 0x5) {
116 		return 3;
117 	}
118 #endif
119 	return val;
120 }
121 
sid_get_vir_base(struct device_node ** pnode,void __iomem ** base,s8 * compatible)122 static s32 sid_get_vir_base(struct device_node **pnode, void __iomem **base,
123 		s8 *compatible)
124 {
125 	*pnode = of_find_compatible_node(NULL, NULL, compatible);
126 	if (IS_ERR_OR_NULL(*pnode)) {
127 		SID_ERR("Failed to find \"%s\" in dts.\n", compatible);
128 		return -ENXIO;
129 	}
130 
131 	*base = of_iomap(*pnode, 0); /* reg[0] must be accessible. */
132 	if (*base == NULL) {
133 		SID_ERR("Unable to remap IO\n");
134 		return -ENXIO;
135 	}
136 	SID_DBG("Base addr of \"%s\" is %p\n", compatible, *base);
137 	return 0;
138 }
139 
sid_get_phy_base(struct device_node ** pnode,phys_addr_t ** base,s8 * compatible)140 static s32  sid_get_phy_base(struct device_node **pnode, phys_addr_t **base,
141 		s8 *compatible)
142 {
143 	struct resource res = {0};
144 	int ret;
145 	*pnode = of_find_compatible_node(*pnode, NULL, compatible);
146 	if (IS_ERR_OR_NULL(*pnode)) {
147 		SID_ERR("Failed to find \"%s\" in dts.\n", compatible);
148 		return -ENXIO;
149 	}
150 
151 	ret = of_address_to_resource(*pnode, 0, &res);
152 	if (ret) {
153 		SID_ERR("ret:%d Failed to get \"%s\"  base address\n", ret, compatible);
154 		return -ENXIO;
155 	}
156 	*base = (phys_addr_t *)res.start;
157 	SID_DBG("Base addr of \"%s\" is %p\n", compatible, (void *)*base);
158 	return 0;
159 }
160 
sid_get_base(struct device_node ** pnode,void __iomem ** base,s8 * compatible,u32 sec)161 static s32 sid_get_base(struct device_node **pnode,
162 		void __iomem **base, s8 *compatible, u32 sec)
163 {
164 	if (sec == 1)
165 		return sid_get_phy_base(pnode,
166 			(phys_addr_t **)base, compatible);
167 	else
168 		return sid_get_vir_base(pnode, base, compatible);
169 }
170 
sid_put_base(struct device_node * pnode,void __iomem * base,u32 sec)171 static void sid_put_base(struct device_node *pnode, void __iomem *base, u32 sec)
172 {
173 	SID_DBG("base = %p, Sec = %d\n", base, sec);
174 	if ((sec == 0) && (base != NULL))
175 		iounmap(base);
176 	if (pnode)
177 		of_node_put(pnode);
178 }
179 
sid_readl(void __iomem * base,u32 sec)180 static u32 sid_readl(void __iomem *base, u32 sec)
181 {
182 	if (sec == 0)
183 		return readl(base);
184 	else
185 		return sunxi_smc_readl((phys_addr_t)base);
186 }
187 
get_key_map_info(s8 * name,u8 * compatile,u32 * offset,u32 * max_size)188 int get_key_map_info(s8 *name, u8 *compatile, u32 *offset, u32 *max_size)
189 {
190 	struct device_node *child_pnode;
191 	struct device_node *pnode = of_find_compatible_node(NULL, NULL, compatile);
192 	if (IS_ERR_OR_NULL(pnode)) {
193 		SID_ERR("Failed to find \"%s\" in dts.\n", compatile);
194 		return -ENXIO;
195 	}
196 	child_pnode = of_get_child_by_name(pnode, name);
197 	if (IS_ERR_OR_NULL(child_pnode)) {
198 		SID_ERR("Failed to find \"%s\" in dts.\n", name);
199 		return -ENXIO;
200 	}
201 	of_property_read_u32(child_pnode, "offset", offset);
202 	of_property_read_u32(child_pnode, "size", max_size);
203 	return 0;
204 }
205 
206 
sid_read_key(s8 * key_name,u32 * key_buf,u32 key_size,u32 sec)207 static u32 sid_read_key(s8 *key_name, u32 *key_buf, u32 key_size, u32 sec)
208 {
209 	u32 i, offset = 0, max_size = 0;
210 	void __iomem *baseaddr = NULL;
211 	struct device_node *dev_node = NULL;
212 
213 	if (sid_get_base(&dev_node, &baseaddr, EFUSE_SID_BASE, sec))
214 		return 0;
215 
216 	get_key_map_info(key_name, EFUSE_SID_BASE, &offset, &max_size);
217 	SID_DBG("key_name:%s offset:0x%x max_size:0x%x\n", key_name, offset, max_size);
218 	if (key_size > max_size) {
219 		key_size = max_size;
220 	}
221 	for (i = 0; i < key_size; i += 4) {
222 		key_buf[i/4] = sid_readl(baseaddr + offset + i, sec);
223 	}
224 
225 	sid_put_base(dev_node, baseaddr, sec);
226 	return 0;
227 }
228 
229 
sid_rd_bits(s8 * name,u32 offset,u32 shift,u32 mask,u32 sec)230 static u32 sid_rd_bits(s8 *name, u32 offset, u32 shift, u32 mask, u32 sec)
231 {
232 	u32 value = 0;
233 	void __iomem *baseaddr = NULL;
234 	struct device_node *dev_node = NULL;
235 
236 #ifdef SID_REG_READ
237 	return __sid_reg_read_key(offset);
238 #else
239 	if (sid_get_base(&dev_node, &baseaddr, name, sec))
240 		return 0;
241 
242 	value = sid_readl(baseaddr + offset, sec);
243 
244 	value = (value >> shift) & mask;
245 	SID_DBG("Read \"%s\" + %#x, shift %#x, mask %#x, return %#x, Sec %d\n",
246 			name, offset, shift, mask, value, sec);
247 
248 	sid_put_base(dev_node, baseaddr, sec);
249 	return value;
250 #endif
251 }
252 
get_soc_ver_regs(u8 * name,u8 * compatile,struct soc_ver_reg * reg)253 int get_soc_ver_regs(u8 *name, u8 *compatile, struct soc_ver_reg *reg)
254 {
255 	struct device_node *child_pnode;
256 	struct device_node *pnode = of_find_compatible_node(NULL, NULL, compatile);
257 	if (IS_ERR_OR_NULL(pnode)) {
258 		SID_ERR("Failed to find \"%s\" in dts.\n", SRAM_CTRL_BASE);
259 		return -ENXIO;
260 	}
261 	child_pnode = of_get_child_by_name(pnode, name);
262 	if (IS_ERR_OR_NULL(child_pnode)) {
263 		SID_ERR("Failed to find \"%s\" in dts.\n", name);
264 		return -ENXIO;
265 	}
266 
267 	of_property_read_u32(child_pnode, "offset", &reg->offset);
268 	of_property_read_u32(child_pnode, "shift", &reg->shift);
269 	of_property_read_u32(child_pnode, "mask", &reg->mask);
270 	of_property_read_u32(child_pnode, "ver_a", &reg->ver_map.rev[0]);
271 	of_property_read_u32(child_pnode, "ver_b", &reg->ver_map.rev[1]);
272 	return 0;
273 }
274 
sid_rd_ver_reg(u32 id)275 void sid_rd_ver_reg(u32 id)
276 {
277 	s32 i = 0;
278 	u32 ver = 0;
279 	static struct soc_ver_reg reg = {0};
280 	get_soc_ver_regs("soc_ver", SRAM_CTRL_BASE, &reg);
281 	ver = sid_rd_bits(SRAM_CTRL_BASE, reg.offset,
282 		reg.shift, reg.mask, 0);
283 	if (ver >= SUNXI_VER_MAX_NUM/2)
284 		SID_WARN("ver >= %d, soc ver:%d\n", SUNXI_VER_MAX_NUM/2, ver);
285 
286 	ver = chip_ver_platform_process(ver);
287 	sunxi_soc_ver = reg.ver_map.rev[0] + ver;
288 
289 	SID_DBG("%d-%d: soc_ver %#x\n", i, ver, sunxi_soc_ver);
290 }
291 
sid_rd_soc_ver_from_sid(void)292 static s32 sid_rd_soc_ver_from_sid(void)
293 {
294 	u32 id = 0;
295 	static struct soc_ver_reg reg = {0};
296 	get_soc_ver_regs("soc_id", SRAM_CTRL_BASE, &reg);
297 	id = sid_rd_bits(EFUSE_SID_BASE, reg.offset, reg.shift, reg.mask, 0);
298 	sid_rd_ver_reg(id);
299 
300 	return 0;
301 }
302 
sid_soc_ver_init(void)303 static void sid_soc_ver_init(void)
304 {
305 	static s32 init_flag;
306 
307 	if (init_flag == 1) {
308 		SID_DBG("It's already inited.\n");
309 		return;
310 	}
311 
312 	sid_rd_soc_ver_from_sid();
313 
314 	SID_DBG("The SoC version: %#x\n", sunxi_soc_ver);
315 	init_flag = 1;
316 }
317 
318 
sid_chipid_init(void)319 static void sid_chipid_init(void)
320 {
321 	u32 type = 0, offset = 0, max_size;
322 	static s32 init_flag;
323 	static struct soc_ver_reg reg = {0};
324 
325 	if (init_flag == 1) {
326 		SID_DBG("It's already inited.\n");
327 		return;
328 	}
329 	sid_read_key("chipid", sunxi_soc_chipid, 16, sunxi_soc_is_secure());
330 
331 	sunxi_serial[0] = sunxi_soc_chipid[3];
332 	sunxi_serial[1] = sunxi_soc_chipid[2];
333 	sunxi_serial[2] = (sunxi_soc_chipid[1] >> 16) & 0x0FFFF;
334 
335 	get_key_map_info("chipid", EFUSE_SID_BASE, &offset, &max_size);
336 	get_soc_ver_regs("soc_bin", SRAM_CTRL_BASE, &reg);
337 
338 	type = sid_rd_bits(EFUSE_SID_BASE, reg.offset + offset, reg.shift,
339 		reg.mask, sunxi_soc_is_secure());
340 
341 	switch (type) {
342 	case 0b000001:
343 		sunxi_soc_bin = 1;
344 		break;
345 	case 0b000011:
346 		sunxi_soc_bin = 2;
347 		break;
348 	case 0b000111:
349 		sunxi_soc_bin = 3;
350 		break;
351 	default:
352 		break;
353 	}
354 	SID_DBG("soc bin: %d\n", sunxi_soc_bin);
355 
356 	init_flag = 1;
357 }
358 
sid_ft_zone_init(void)359 void sid_ft_zone_init(void)
360 {
361 	static s32 init_flag;
362 	if (init_flag == 1) {
363 		SID_DBG("It's already inited.\n");
364 		return;
365 	}
366 	sid_read_key(EFUSE_FT_ZONE_NAME, sunxi_soc_ftzone, 0x10, sunxi_soc_is_secure());
367 
368 	init_flag = 1;
369 
370 }
371 
sid_rd_soc_secure_status(void)372 void sid_rd_soc_secure_status(void)
373 {
374 #if defined(CONFIG_TEE) && \
375 	(defined(CONFIG_ARCH_SUN8IW7) || defined(CONFIG_ARCH_SUN8IW6))
376 	sunxi_soc_secure = 1;
377 #else
378 	static s32 init_flag;
379 	void __iomem *base = NULL;
380 	struct device_node *node = NULL;
381 	u32 offset = 0, max_size;
382 
383 	if (init_flag == 1) {
384 		SID_DBG("It's already inited.\n");
385 		return;
386 	}
387 
388 	if (sid_get_base(&node, &base, EFUSE_SID_BASE, 1))
389 		return;
390 
391 	get_key_map_info("secure_status", EFUSE_SID_BASE, &offset, &max_size);
392 
393 	sunxi_soc_secure = ((sunxi_smc_readl((phys_addr_t)(base + offset))) & 0x1);
394 
395 	sid_put_base(node, base, 1);
396 	init_flag = 1;
397 #endif
398 }
399 
sid_rotpk_status_init(void)400 void sid_rotpk_status_init(void)
401 {
402 	static s32 init_flag;
403 	if (init_flag == 1) {
404 		SID_DBG("It's already inited.\n");
405 		return;
406 	}
407 	sid_read_key(EFUSE_ROTPK_NAME, &sunxi_soc_rotpk_status, 4, sunxi_soc_is_secure());
408 
409 	init_flag = 1;
410 
411 }
412 
413 //#define CONFIG_SUNXI_SOC_NAME "sun50iw10"
sunxi_get_platform(s8 * buf,s32 size)414 s32 sunxi_get_platform(s8 *buf, s32 size)
415 {
416 	return snprintf(buf, size, "%s", CONFIG_AW_SOC_NAME);
417 }
418 EXPORT_SYMBOL(sunxi_get_platform);
419 
420 
421 /**
422  * get module_param:
423  * argc[0]---dst buf
424  * argc[1]---the sid offset
425  * argc[2]---len(btye)
426  */
sunxi_get_module_param_from_sid(u32 * dst,u32 offset,u32 len)427 int sunxi_get_module_param_from_sid(u32 *dst, u32 offset, u32 len)
428 {
429 	void __iomem *baseaddr = NULL;
430 	struct device_node *dev_node = NULL;
431 	int i;
432 
433 	if (dst == NULL) {
434 		pr_err("the dst buf is NULL\n");
435 		return -1;
436 	}
437 
438 	if (len & 0x3) {
439 		pr_err("the len must be word algin\n");
440 		return -2;
441 	}
442 
443 	if (sid_get_base(&dev_node, &baseaddr, EFUSE_SID_BASE, 0)) {
444 		pr_err("sid_get_base fail \n");
445 		return 0;
446 	}
447 
448 	SID_DBG("baseaddr: 0x%p offset:0x%x len(word):0x%x\n", baseaddr, offset, len);
449 
450 	for (i = 0; i < len; i += 4) {
451 		dst[i] = sid_readl(baseaddr + 0x200 + offset + i, 0);
452 	}
453 
454 	sid_put_base(dev_node, baseaddr, 0);
455 
456 	return 0;
457 }
458 EXPORT_SYMBOL_GPL(sunxi_get_module_param_from_sid);
459 
460 
461 
462 
463 
464 /**
465  * soc chipid:
466  */
sunxi_get_soc_chipid(u8 * chipid)467 int sunxi_get_soc_chipid(u8 *chipid)
468 {
469 	sid_chipid_init();
470 	memcpy(chipid, sunxi_soc_chipid, 16);
471 	return 0;
472 }
473 EXPORT_SYMBOL(sunxi_get_soc_chipid);
474 
475 /**
476  * soc chipid serial:
477  */
sunxi_get_serial(u8 * serial)478 int sunxi_get_serial(u8 *serial)
479 {
480 	sid_chipid_init();
481 	memcpy(serial, sunxi_serial, 16);
482 	return 0;
483 }
484 EXPORT_SYMBOL(sunxi_get_serial);
485 
486 /**
487  * soc chipid str:
488  */
sunxi_get_soc_chipid_str(char * serial)489 int sunxi_get_soc_chipid_str(char *serial)
490 {
491 	size_t size;
492 
493 	sid_chipid_init();
494 #if defined(CONFIG_ARCH_SUN50IW9) || defined(CONFIG_ARCH_SUN50IW10)
495 	size = sprintf(serial, "%08x", sunxi_soc_chipid[0] & 0xffff);
496 #else
497 	size = sprintf(serial, "%08x", sunxi_soc_chipid[0] & 0x0ff);
498 #endif
499 	return size;
500 }
501 EXPORT_SYMBOL(sunxi_get_soc_chipid_str);
502 
503 /**
504  * soc ft zone str:
505  */
sunxi_get_soc_ft_zone_str(char * serial)506 int sunxi_get_soc_ft_zone_str(char *serial)
507 {
508 	size_t size;
509 
510 	sid_ft_zone_init();
511 	size = sprintf(serial, "%08x", (sunxi_soc_ftzone[0] & 0xff000000) >> 24);
512 	return size;
513 }
514 EXPORT_SYMBOL(sunxi_get_soc_ft_zone_str);
515 
516 /**
517  * soc rotpk status str:
518  */
sunxi_get_soc_rotpk_status_str(char * status)519 int sunxi_get_soc_rotpk_status_str(char *status)
520 {
521 	size_t size;
522 
523 	sid_rotpk_status_init();
524 	size = sprintf(status, "%d", (sunxi_soc_rotpk_status & 0x3) >> 1);
525 	return size;
526 }
527 EXPORT_SYMBOL(sunxi_get_soc_rotpk_status_str);
528 
529 /**
530  * soc chipid:
531  */
sunxi_soc_is_secure(void)532 int sunxi_soc_is_secure(void)
533 {
534 	sid_rd_soc_secure_status();
535 	return sunxi_soc_secure;
536 }
537 EXPORT_SYMBOL(sunxi_soc_is_secure);
538 
539 /**
540  * get sunxi soc bin
541  *
542  * return: the bin of sunxi soc, like that:
543  * 0 : fail
544  * 1 : slow
545  * 2 : normal
546  * 3 : fast
547  */
sunxi_get_soc_bin(void)548 unsigned int sunxi_get_soc_bin(void)
549 {
550 	sid_chipid_init();
551 	return sunxi_soc_bin;
552 }
553 EXPORT_SYMBOL(sunxi_get_soc_bin);
554 
sunxi_get_soc_ver(void)555 unsigned int sunxi_get_soc_ver(void)
556 {
557 	sid_soc_ver_init();
558 	return sunxi_soc_ver;
559 }
560 EXPORT_SYMBOL(sunxi_get_soc_ver);
561 
sunxi_efuse_readn(s8 * key_name,void * buf,u32 n)562 s32 sunxi_efuse_readn(s8 *key_name, void *buf, u32 n)
563 {
564 	char name[32] = {0};
565 
566 	if ((key_name == NULL) || (*(s8 *)key_name == 0)
567 			|| (n == 0) || (buf == NULL)) {
568 		SID_ERR("Invalid parameter. name: %p, read_buf: %p, size: %d\n",
569 		key_name, buf, n);
570 		return -EINVAL;
571 	}
572 	WARN_ON(n < 4);
573 
574 	strncpy(name, key_name, strlen(key_name) - 1);
575 	sid_read_key(name, buf, n, sunxi_soc_is_secure());
576 	return 0;
577 }
578 EXPORT_SYMBOL(sunxi_efuse_readn);
579 
580 #define SEC_BLK_SIZE						(4096)
581 
582 #define SUNXI_EFUSE_READ	_IO('V', 1)
583 #define SUNXI_EFUSE_WRITE	_IO('V', 2)
584 
585 static efuse_cry_pt nfcr;
586 static sunxi_efuse_key_info_t temp_key;
587 
sunxi_efuse_open(struct inode * inode,struct file * file)588 static int sunxi_efuse_open(struct inode *inode, struct file *file)
589 {
590 	return 0;
591 }
592 
sunxi_efuse_release(struct inode * inode,struct file * file)593 static int sunxi_efuse_release(struct inode *inode, struct file *file)
594 {
595 	return 0;
596 }
597 
sunxi_efuse_ioctl(struct file * file,unsigned int ioctl_num,unsigned long ioctl_param)598 static long sunxi_efuse_ioctl(struct file *file, unsigned int ioctl_num,
599 			      unsigned long ioctl_param)
600 {
601 	int err = 0;
602 
603 	mutex_lock(&nfcr->mutex);
604 	if (copy_from_user(&nfcr->key_store, (void __user *)ioctl_param,
605 			   sizeof(nfcr->key_store))) {
606 		err = -EFAULT;
607 		goto _out;
608 	}
609 	nfcr->cmd = ioctl_num;
610 
611 #if 0
612 	pr_err("sunxi_efuse_ioctl: ioctl_num=%d\n", ioctl_num);
613 	pr_err("nfcr = %p\n", nfcr);
614 	pr_err("name = %s\n", nfcr->key_store.name);
615 	pr_err("len = %d\n", nfcr->key_store.len);
616 #endif
617 
618 	switch (ioctl_num) {
619 	case SUNXI_EFUSE_READ:
620 		schedule_work(&nfcr->work);
621 		wait_for_completion(&nfcr->work_end);
622 		/*sunxi_dump(nfcr->temp_data, 50);*/
623 		err = nfcr->ret;
624 		if (!err) {
625 			if (copy_to_user(
626 				    (void __user *)(phys_addr_t)
627 					    nfcr->key_store.key_data,
628 				    (nfcr->temp_data + nfcr->key_store.offset),
629 				    nfcr->key_store.len)) {
630 				err = -EFAULT;
631 				pr_err("copy_to_user: err:%d\n", err);
632 				goto _out;
633 			}
634 		}
635 		break;
636 	case SUNXI_EFUSE_WRITE:
637 		if (copy_from_user(nfcr->temp_data,
638 				   (void __user *)(phys_addr_t)
639 					   nfcr->key_store.key_data,
640 				   nfcr->key_store.len)) {
641 			err = -EFAULT;
642 			pr_err("copy_from_user: err:%d\n", err);
643 			goto _out;
644 		}
645 		sprintf(temp_key.name, "%s", nfcr->key_store.name);
646 		temp_key.len = nfcr->key_store.len;
647 		temp_key.offset = nfcr->key_store.offset;
648 		temp_key.key_data =
649 			virt_to_phys((const volatile void *)nfcr->temp_data);
650 		schedule_work(&nfcr->work);
651 		wait_for_completion(&nfcr->work_end);
652 		err = nfcr->ret;
653 		break;
654 	default:
655 		pr_err("sunxi_efuse_ioctl: un supported cmd:%d\n", ioctl_num);
656 		break;
657 	}
658 _out:
659 	memset(nfcr->temp_data, 0, SEC_BLK_SIZE);
660 	memset(&nfcr->key_store, 0, sizeof(nfcr->key_store));
661 	nfcr->cmd = -1;
662 	mutex_unlock(&nfcr->mutex);
663 	return err;
664 }
665 
666 static const struct file_operations sunxi_efuse_ops = {
667 	.owner = THIS_MODULE,
668 	.open = sunxi_efuse_open,
669 	.release = sunxi_efuse_release,
670 	.unlocked_ioctl = sunxi_efuse_ioctl,
671 	.compat_ioctl = sunxi_efuse_ioctl,
672 };
673 
674 struct miscdevice sunxi_efuse_device = {
675 	.minor = MISC_DYNAMIC_MINOR,
676 	.name = "sid_efuse",
677 	.fops = &sunxi_efuse_ops,
678 };
679 
sunxi_efuse_work(struct work_struct * data)680 static void sunxi_efuse_work(struct work_struct *data)
681 {
682 	efuse_cry_pt fcpt = container_of(data, struct efuse_crypt, work);
683 	switch (fcpt->cmd) {
684 #if IS_ENABLED(CONFIG_AW_SMC)
685 	case SUNXI_EFUSE_READ:
686 		fcpt->ret =
687 			(((nfcr->key_store.offset + nfcr->key_store.len) >
688 			  (arm_svc_efuse_read(
689 				  virt_to_phys((const volatile void *)
690 						       fcpt->key_store.name),
691 				  virt_to_phys((const volatile void *)
692 						       fcpt->temp_data)))) ?
693 				       -1 :
694 				       0);
695 		break;
696 	case SUNXI_EFUSE_WRITE:
697 		fcpt->ret = arm_svc_efuse_write(
698 			virt_to_phys((const volatile void *)&temp_key));
699 		break;
700 #endif
701 	default:
702 		fcpt->ret = -1;
703 		pr_err("sunxi_efuse_work: un supported cmd:%d\n", fcpt->cmd);
704 		break;
705 	}
706 
707 	if ((fcpt->cmd == SUNXI_EFUSE_READ) || (fcpt->cmd == SUNXI_EFUSE_WRITE))
708 		complete(&fcpt->work_end);
709 }
710 
sunxi_efuse_exit(void)711 static void sunxi_efuse_exit(void)
712 {
713 	pr_debug("sunxi efuse driver exit\n");
714 
715 	misc_deregister(&sunxi_efuse_device);
716 	kfree(nfcr->temp_data);
717 	kfree(nfcr);
718 }
719 
sunxi_efuse_init(void)720 static int sunxi_efuse_init(void)
721 {
722 	int ret;
723 
724 	ret = misc_register(&sunxi_efuse_device);
725 	if (ret) {
726 		pr_err("%s: cannot deregister miscdev.(return value-%d)\n",
727 		       __func__, ret);
728 		return ret;
729 	}
730 
731 	nfcr = kmalloc(sizeof(*nfcr), GFP_KERNEL);
732 	if (!nfcr) {
733 		pr_err(" - Malloc failed\n");
734 		return -1;
735 	}
736 	memset(nfcr, 0, sizeof(*nfcr));
737 
738 	nfcr->temp_data = kmalloc(SEC_BLK_SIZE, GFP_KERNEL);
739 	if (!nfcr->temp_data) {
740 		pr_err("sunxi_efuse_ioctl: error to kmalloc\n");
741 		return -1;
742 	}
743 	memset(nfcr->temp_data, 0, SEC_BLK_SIZE);
744 	INIT_WORK(&nfcr->work, sunxi_efuse_work);
745 	init_completion(&nfcr->work_end);
746 	mutex_init(&nfcr->mutex);
747 
748 	return 0;
749 }
750 
sunxi_sid_init(void)751 static int __init sunxi_sid_init(void)
752 {
753 	SID_WARN("insmod ok\n");
754 	return sunxi_efuse_init();
755 	;
756 }
757 
sunxi_sid_exit(void)758 static void __exit sunxi_sid_exit(void)
759 {
760 	sunxi_efuse_exit();
761 	SID_WARN("rmmod ok\n");
762 }
763 
764 module_init(sunxi_sid_init);
765 module_exit(sunxi_sid_exit);
766 MODULE_LICENSE("GPL v2");
767 MODULE_AUTHOR("weidonghui<weidonghui@allwinnertech.com>");
768 MODULE_DESCRIPTION("sunxi sid.");
769