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", ®->offset);
268 of_property_read_u32(child_pnode, "shift", ®->shift);
269 of_property_read_u32(child_pnode, "mask", ®->mask);
270 of_property_read_u32(child_pnode, "ver_a", ®->ver_map.rev[0]);
271 of_property_read_u32(child_pnode, "ver_b", ®->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, ®);
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, ®);
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, ®);
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