arm: dts: rk3288-android: use secure efuse
[firefly-linux-kernel-4.4.55.git] / drivers / soc / rockchip / sdmmc_vendor_storage.c
1 /*
2  * Copyright (c) 2016, Fuzhou Rockchip Electronics Co., Ltd
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or (at
7  * your option) any later version.
8  */
9
10 #include <linux/miscdevice.h>
11 #include <linux/platform_device.h>
12 #include <linux/fs.h>
13 #include <linux/file.h>
14 #include <linux/mm.h>
15 #include <linux/list.h>
16 #include <linux/debugfs.h>
17 #include <linux/mempolicy.h>
18 #include <linux/sched.h>
19 #include <linux/dma-mapping.h>
20 #include <linux/io.h>
21 #include <linux/uaccess.h>
22 #include <linux/module.h>
23 #include <linux/soc/rockchip/rk_vendor_storage.h>
24 #include <linux/kthread.h>
25 #include <linux/delay.h>
26
27 #define EMMC_IDB_PART_OFFSET            64
28 #define EMMC_SYS_PART_OFFSET            8064
29 #define EMMC_BOOT_PART_SIZE             1024
30 #define EMMC_VENDOR_PART_START          (1024 * 7)
31 #define EMMC_VENDOR_PART_SIZE           128
32 #define EMMC_VENDOR_PART_NUM            4
33 #define EMMC_VENDOR_TAG                 0x524B5644
34
35 struct rk_sys_req {
36         u32     tag;
37         u32     len;
38         u8      data[512];
39 };
40
41 struct rk_vendor_req {
42         u32 tag;
43         u16 id;
44         u16 len;
45         u8 data[1024];
46 };
47
48 struct vendor_item {
49         u16  id;
50         u16  offset;
51         u16  size;
52         u16  flag;
53 };
54
55 struct vendor_info {
56         u32     tag;
57         u32     version;
58         u16     next_index;
59         u16     item_num;
60         u16     free_offset;
61         u16     free_size;
62         struct  vendor_item item[126]; /* 126 * 8*/
63         u8      data[EMMC_VENDOR_PART_SIZE * 512 - 1024 - 8];
64         u32     hash;
65         u32     version2;
66 };
67
68 #define READ_SECTOR_IO          _IOW('r', 0x04, unsigned int)
69 #define WRITE_SECTOR_IO         _IOW('r', 0x05, unsigned int)
70 #define END_WRITE_SECTOR_IO     _IOW('r', 0x52, unsigned int)
71 #define GET_FLASH_INFO_IO       _IOW('r', 0x1A, unsigned int)
72 #define GET_BAD_BLOCK_IO        _IOW('r', 0x03, unsigned int)
73 #define GET_LOCK_FLAG_IO        _IOW('r', 0x53, unsigned int)
74
75 #define VENDOR_REQ_TAG          0x56524551
76 #define VENDOR_READ_IO          _IOW('v', 0x01, unsigned int)
77 #define VENDOR_WRITE_IO         _IOW('v', 0x02, unsigned int)
78
79 static u8 *g_idb_buffer;
80 static struct vendor_info *g_vendor;
81
82 extern int rk_emmc_transfer(u8 *buffer, unsigned addr, unsigned blksz,
83                             int write);
84
85 static int emmc_vendor_ops(u8 *buffer, u32 addr, u32 n_sec, int write)
86 {
87         u32 i, ret;
88
89         for (i = 0; i < n_sec; i++)
90                 ret = rk_emmc_transfer(buffer + i * 512, addr + i, 512, write);
91
92         return ret;
93 }
94
95 static int emmc_vendor_storage_init(void)
96 {
97         u32 i, max_ver, max_index;
98         u8 *p_buf;
99
100         g_vendor = kmalloc(sizeof(*g_vendor), GFP_KERNEL | GFP_DMA);
101         if (!g_vendor)
102                 return -1;
103
104         max_ver = 0;
105         max_index = 0;
106         for (i = 0; i < EMMC_VENDOR_PART_NUM; i++) {
107                 /* read first 512 bytes */
108                 p_buf = (u8 *)g_vendor;
109                 if (rk_emmc_transfer(p_buf, EMMC_VENDOR_PART_START +
110                                  EMMC_VENDOR_PART_SIZE * i, 512, 0))
111                         goto error_exit;
112                 /* read last 512 bytes */
113                 p_buf += (EMMC_VENDOR_PART_SIZE - 1) * 512;
114                 if (rk_emmc_transfer(p_buf, EMMC_VENDOR_PART_START +
115                                  EMMC_VENDOR_PART_SIZE * (i + 1) - 1,
116                                  512, 0))
117                         goto error_exit;
118
119                 if (g_vendor->tag == EMMC_VENDOR_TAG &&
120                     g_vendor->version2 == g_vendor->version) {
121                         if (max_ver < g_vendor->version) {
122                                 max_index = i;
123                                 max_ver = g_vendor->version;
124                         }
125                 }
126         }
127         if (max_ver) {
128                 if (emmc_vendor_ops((u8 *)g_vendor, EMMC_VENDOR_PART_START +
129                                 EMMC_VENDOR_PART_SIZE * max_index,
130                                 EMMC_VENDOR_PART_SIZE, 0))
131                         goto error_exit;
132         } else {
133                 memset((void *)g_vendor, 0, sizeof(g_vendor));
134                 g_vendor->version = 1;
135                 g_vendor->tag = EMMC_VENDOR_TAG;
136                 g_vendor->version2 = g_vendor->version;
137                 g_vendor->free_offset = 0;
138                 g_vendor->free_size = sizeof(g_vendor->data);
139         }
140         return 0;
141 error_exit:
142         kfree(g_vendor);
143         g_vendor = NULL;
144         return -1;
145 }
146
147 static int emmc_vendor_read(u32 id, void *pbuf, u32 size)
148 {
149         u32 i;
150
151         if (!g_vendor)
152                 return -1;
153
154         for (i = 0; i < g_vendor->item_num; i++) {
155                 if (g_vendor->item[i].id == id) {
156                         if (size > g_vendor->item[i].size)
157                                 size = g_vendor->item[i].size;
158                         memcpy(pbuf,
159                                &g_vendor->data[g_vendor->item[i].offset],
160                                size);
161                         return size;
162                 }
163         }
164         return (-1);
165 }
166
167 static int emmc_vendor_write(u32 id, void *pbuf, u32 size)
168 {
169         u32 i, next_index, algin_size;
170         struct vendor_item *item;
171
172         if (!g_vendor)
173                 return -1;
174
175         algin_size = (size + 0x3F) & (~0x3F); /* algin to 32 bytes*/
176         next_index = g_vendor->next_index;
177         for (i = 0; i < g_vendor->item_num; i++) {
178                 if (g_vendor->item[i].id == id) {
179                         if (size > algin_size)
180                                 return -1;
181                         memcpy(&g_vendor->data[g_vendor->item[i].offset],
182                                pbuf,
183                                size);
184                         g_vendor->item[i].size = size;
185                         g_vendor->version++;
186                         g_vendor->version2 = g_vendor->version;
187                         g_vendor->next_index++;
188                         if (g_vendor->next_index >= EMMC_VENDOR_PART_NUM)
189                                 g_vendor->next_index = 0;
190                         emmc_vendor_ops((u8 *)g_vendor, EMMC_VENDOR_PART_START +
191                                         EMMC_VENDOR_PART_SIZE * next_index,
192                                         EMMC_VENDOR_PART_SIZE, 1);
193                         return 0;
194                 }
195         }
196
197         if (g_vendor->free_size >= algin_size) {
198                 item = &g_vendor->item[g_vendor->item_num];
199                 item->id = id;
200                 item->offset = g_vendor->free_offset;
201                 item->size = size;
202                 g_vendor->free_offset += algin_size;
203                 g_vendor->free_size -= algin_size;
204                 memcpy(&g_vendor->data[item->offset], pbuf, size);
205                 g_vendor->item_num++;
206                 g_vendor->version++;
207                 g_vendor->version2 = g_vendor->version;
208                 g_vendor->next_index++;
209                 if (g_vendor->next_index >= EMMC_VENDOR_PART_NUM)
210                         g_vendor->next_index = 0;
211                 emmc_vendor_ops((u8 *)g_vendor, EMMC_VENDOR_PART_START +
212                                 EMMC_VENDOR_PART_SIZE * next_index,
213                                 EMMC_VENDOR_PART_SIZE, 1);
214                 return 0;
215         }
216         return(-1);
217 }
218
219 static int id_blk_read_data(u32 index, u32 n_sec, u8 *buf)
220 {
221         u32 i;
222         u32 ret = 0;
223
224         if (index + n_sec >= 1024 * 5)
225                 return 0;
226         index = index + EMMC_IDB_PART_OFFSET;
227         for (i = 0; i < n_sec; i++) {
228                 ret = rk_emmc_transfer(buf + i * 512, index + i, 512, 0);
229                 if (ret)
230                         return ret;
231         }
232         return ret;
233 }
234
235 static int id_blk_write_data(u32 index, u32 n_sec, u8 *buf)
236 {
237         u32 i;
238         u32 ret = 0;
239
240         if (index + n_sec >= 1024 * 5)
241                 return 0;
242         index = index + EMMC_IDB_PART_OFFSET;
243         for (i = 0; i < n_sec; i++) {
244                 ret = rk_emmc_transfer(buf + i * 512, index + i, 512, 1);
245                 if (ret)
246                         return ret;
247         }
248         return ret;
249 }
250
251 static int emmc_write_idblock(u32 size, u8 *buf, u32 *id_blk_tbl)
252 {
253         u32 i, totle_sec, j;
254         u32 totle_write_count = 0;
255         u32 *p_raw_data = (u32 *)buf;
256         u32 *p_check_buf = kmalloc(EMMC_BOOT_PART_SIZE * 512, GFP_KERNEL);
257
258         if (!p_check_buf)
259                 return -1;
260
261         totle_sec = (size + 511) >> 9;
262         if (totle_sec <= 8)
263                 totle_sec = 8;
264
265         for (i = 0; i < 5; i++) {
266                 memset(p_check_buf, 0, 512);
267                 id_blk_write_data(EMMC_BOOT_PART_SIZE * i, 1,
268                                   (u8 *)p_check_buf);
269                 id_blk_write_data(EMMC_BOOT_PART_SIZE * i + 1,
270                                   totle_sec - 1, buf + 512);
271                 id_blk_write_data(EMMC_BOOT_PART_SIZE * i, 1, buf);
272                 id_blk_read_data(EMMC_BOOT_PART_SIZE * i, totle_sec,
273                                  (u8 *)p_check_buf);
274                 for (j = 0; j < totle_sec * 128; j++) {
275                         if (p_check_buf[j] != p_raw_data[j]) {
276                                 memset(p_check_buf, 0, 512);
277                                 id_blk_write_data(EMMC_BOOT_PART_SIZE * i, 1,
278                                                   (u8 *)p_check_buf);
279                                 break;
280                         }
281                 }
282                 if (j >= totle_sec * 128)
283                         totle_write_count++;
284         }
285         kfree(p_check_buf);
286         if (totle_write_count)
287                 return 0;
288         return (-1);
289 }
290
291 static int vendor_storage_open(struct inode *inode, struct file *file)
292 {
293         return 0;
294 }
295
296 static int vendor_storage_release(struct inode *inode, struct file *file)
297 {
298         return 0;
299 }
300
301 static const u32 g_crc32_tbl[256] = {
302         0x00000000, 0x04c10db7, 0x09821b6e, 0x0d4316d9,
303         0x130436dc, 0x17c53b6b, 0x1a862db2, 0x1e472005,
304         0x26086db8, 0x22c9600f, 0x2f8a76d6, 0x2b4b7b61,
305         0x350c5b64, 0x31cd56d3, 0x3c8e400a, 0x384f4dbd,
306         0x4c10db70, 0x48d1d6c7, 0x4592c01e, 0x4153cda9,
307         0x5f14edac, 0x5bd5e01b, 0x5696f6c2, 0x5257fb75,
308         0x6a18b6c8, 0x6ed9bb7f, 0x639aada6, 0x675ba011,
309         0x791c8014, 0x7ddd8da3, 0x709e9b7a, 0x745f96cd,
310         0x9821b6e0, 0x9ce0bb57, 0x91a3ad8e, 0x9562a039,
311         0x8b25803c, 0x8fe48d8b, 0x82a79b52, 0x866696e5,
312         0xbe29db58, 0xbae8d6ef, 0xb7abc036, 0xb36acd81,
313         0xad2ded84, 0xa9ece033, 0xa4aff6ea, 0xa06efb5d,
314         0xd4316d90, 0xd0f06027, 0xddb376fe, 0xd9727b49,
315         0xc7355b4c, 0xc3f456fb, 0xceb74022, 0xca764d95,
316         0xf2390028, 0xf6f80d9f, 0xfbbb1b46, 0xff7a16f1,
317         0xe13d36f4, 0xe5fc3b43, 0xe8bf2d9a, 0xec7e202d,
318         0x34826077, 0x30436dc0, 0x3d007b19, 0x39c176ae,
319         0x278656ab, 0x23475b1c, 0x2e044dc5, 0x2ac54072,
320         0x128a0dcf, 0x164b0078, 0x1b0816a1, 0x1fc91b16,
321         0x018e3b13, 0x054f36a4, 0x080c207d, 0x0ccd2dca,
322         0x7892bb07, 0x7c53b6b0, 0x7110a069, 0x75d1adde,
323         0x6b968ddb, 0x6f57806c, 0x621496b5, 0x66d59b02,
324         0x5e9ad6bf, 0x5a5bdb08, 0x5718cdd1, 0x53d9c066,
325         0x4d9ee063, 0x495fedd4, 0x441cfb0d, 0x40ddf6ba,
326         0xaca3d697, 0xa862db20, 0xa521cdf9, 0xa1e0c04e,
327         0xbfa7e04b, 0xbb66edfc, 0xb625fb25, 0xb2e4f692,
328         0x8aabbb2f, 0x8e6ab698, 0x8329a041, 0x87e8adf6,
329         0x99af8df3, 0x9d6e8044, 0x902d969d, 0x94ec9b2a,
330         0xe0b30de7, 0xe4720050, 0xe9311689, 0xedf01b3e,
331         0xf3b73b3b, 0xf776368c, 0xfa352055, 0xfef42de2,
332         0xc6bb605f, 0xc27a6de8, 0xcf397b31, 0xcbf87686,
333         0xd5bf5683, 0xd17e5b34, 0xdc3d4ded, 0xd8fc405a,
334         0x6904c0ee, 0x6dc5cd59, 0x6086db80, 0x6447d637,
335         0x7a00f632, 0x7ec1fb85, 0x7382ed5c, 0x7743e0eb,
336         0x4f0cad56, 0x4bcda0e1, 0x468eb638, 0x424fbb8f,
337         0x5c089b8a, 0x58c9963d, 0x558a80e4, 0x514b8d53,
338         0x25141b9e, 0x21d51629, 0x2c9600f0, 0x28570d47,
339         0x36102d42, 0x32d120f5, 0x3f92362c, 0x3b533b9b,
340         0x031c7626, 0x07dd7b91, 0x0a9e6d48, 0x0e5f60ff,
341         0x101840fa, 0x14d94d4d, 0x199a5b94, 0x1d5b5623,
342         0xf125760e, 0xf5e47bb9, 0xf8a76d60, 0xfc6660d7,
343         0xe22140d2, 0xe6e04d65, 0xeba35bbc, 0xef62560b,
344         0xd72d1bb6, 0xd3ec1601, 0xdeaf00d8, 0xda6e0d6f,
345         0xc4292d6a, 0xc0e820dd, 0xcdab3604, 0xc96a3bb3,
346         0xbd35ad7e, 0xb9f4a0c9, 0xb4b7b610, 0xb076bba7,
347         0xae319ba2, 0xaaf09615, 0xa7b380cc, 0xa3728d7b,
348         0x9b3dc0c6, 0x9ffccd71, 0x92bfdba8, 0x967ed61f,
349         0x8839f61a, 0x8cf8fbad, 0x81bbed74, 0x857ae0c3,
350         0x5d86a099, 0x5947ad2e, 0x5404bbf7, 0x50c5b640,
351         0x4e829645, 0x4a439bf2, 0x47008d2b, 0x43c1809c,
352         0x7b8ecd21, 0x7f4fc096, 0x720cd64f, 0x76cddbf8,
353         0x688afbfd, 0x6c4bf64a, 0x6108e093, 0x65c9ed24,
354         0x11967be9, 0x1557765e, 0x18146087, 0x1cd56d30,
355         0x02924d35, 0x06534082, 0x0b10565b, 0x0fd15bec,
356         0x379e1651, 0x335f1be6, 0x3e1c0d3f, 0x3add0088,
357         0x249a208d, 0x205b2d3a, 0x2d183be3, 0x29d93654,
358         0xc5a71679, 0xc1661bce, 0xcc250d17, 0xc8e400a0,
359         0xd6a320a5, 0xd2622d12, 0xdf213bcb, 0xdbe0367c,
360         0xe3af7bc1, 0xe76e7676, 0xea2d60af, 0xeeec6d18,
361         0xf0ab4d1d, 0xf46a40aa, 0xf9295673, 0xfde85bc4,
362         0x89b7cd09, 0x8d76c0be, 0x8035d667, 0x84f4dbd0,
363         0x9ab3fbd5, 0x9e72f662, 0x9331e0bb, 0x97f0ed0c,
364         0xafbfa0b1, 0xab7ead06, 0xa63dbbdf, 0xa2fcb668,
365         0xbcbb966d, 0xb87a9bda, 0xb5398d03, 0xb1f880b4,
366 };
367
368 static u32 rk_crc_32(unsigned char *buf, u32 len)
369 {
370         u32 i;
371         u32 crc = 0;
372
373         for (i = 0; i < len; i++)
374                 crc = (crc << 8) ^ g_crc32_tbl[(crc >> 24) ^ *buf++];
375         return crc;
376 }
377
378 static long vendor_storage_ioctl(struct file *file, unsigned int cmd,
379                                  unsigned long arg)
380 {
381         long ret = -1;
382         u32 size;
383         struct rk_sys_req *s_req;
384         struct rk_vendor_req *v_req;
385         u32 *page_buf;
386
387         page_buf = kmalloc(4096, GFP_KERNEL);
388         if (!page_buf)
389                 return ret;
390
391         v_req = (struct rk_vendor_req *)page_buf;
392         s_req = (struct rk_sys_req *)page_buf;
393
394         switch (cmd) {
395         case VENDOR_READ_IO:
396         {
397                 if (copy_from_user(page_buf, (void __user *)arg, 8)) {
398                         ret = -EFAULT;
399                         break;
400                 }
401                 if (v_req->tag == VENDOR_REQ_TAG) {
402                         size = emmc_vendor_read(v_req->id, v_req->data,
403                                                 v_req->len);
404                         if (size != -1) {
405                                 v_req->len = size;
406                                 ret = 0;
407                                 if (copy_to_user((void __user *)arg,
408                                                  page_buf,
409                                                  v_req->len + 8))
410                                         ret = -EFAULT;
411                         }
412                 }
413         } break;
414         case VENDOR_WRITE_IO:
415         {
416                 if (copy_from_user(page_buf, (void __user *)arg, 8)) {
417                         ret = -EFAULT;
418                         break;
419                 }
420                 if (v_req->tag == VENDOR_REQ_TAG && (v_req->len < 4096 - 8)) {
421                         if (copy_from_user(page_buf, (void __user *)arg,
422                                            v_req->len + 8)) {
423                                 ret = -EFAULT;
424                                 break;
425                         }
426                         ret = emmc_vendor_write(v_req->id,
427                                                 v_req->data,
428                                                 v_req->len);
429                 }
430         } break;
431
432         case READ_SECTOR_IO:
433         {
434                 if (copy_from_user(page_buf, (void __user *)arg, 512)) {
435                         ret = -EFAULT;
436                         goto exit;
437                 }
438
439                 size = page_buf[1];
440                 if (size <= 8) {
441                         id_blk_read_data(page_buf[0], size, (u8 *)page_buf);
442                         if (copy_to_user((void __user *)arg, page_buf,
443                                          size * 512)) {
444                                 ret = -EFAULT;
445                                 goto exit;
446                         }
447                 } else {
448                         return -EFAULT;
449                 }
450                 ret = 0;
451         } break;
452
453         case WRITE_SECTOR_IO:
454         {
455                 if (copy_from_user(page_buf, (void __user *)arg, 4096)) {
456                         ret = -EFAULT;
457                         goto exit;
458                 }
459                 if (!g_idb_buffer) {
460                         g_idb_buffer = kmalloc(4096 + EMMC_BOOT_PART_SIZE * 512,
461                                                GFP_KERNEL);
462                         if (!g_idb_buffer) {
463                                 ret = -EFAULT;
464                                 goto exit;
465                         }
466                 }
467                 if (page_buf[1] <= 4088 && page_buf[0] <=
468                     (EMMC_BOOT_PART_SIZE * 512 - 4096)) {
469                         memcpy(g_idb_buffer + page_buf[0], page_buf + 2,
470                                page_buf[1]);
471                 } else {
472                         ret = -EFAULT;
473                         goto exit;
474                 }
475                 ret = 0;
476         } break;
477
478         case END_WRITE_SECTOR_IO:
479         {
480                 if (copy_from_user(page_buf, (void __user *)arg, 28)) {
481                         ret = -EFAULT;
482                         goto exit;
483                 }
484                 if (page_buf[0] <= (EMMC_BOOT_PART_SIZE * 512)) {
485                         if (!g_idb_buffer) {
486                                 ret = -EFAULT;
487                                 goto exit;
488                         }
489                         if (page_buf[1] !=
490                                 rk_crc_32(g_idb_buffer, page_buf[0])) {
491                                 ret = -2;
492                                 goto exit;
493                         }
494                         ret =  emmc_write_idblock(page_buf[0],
495                                                   (u8 *)g_idb_buffer,
496                                                   &page_buf[2]);
497                         kfree(g_idb_buffer);
498                         g_idb_buffer = NULL;
499                 } else {
500                         ret = -EFAULT;
501                         goto exit;
502                 }
503                 ret = 0;
504         } break;
505
506         case GET_BAD_BLOCK_IO:
507         {
508                 memset(page_buf, 0, 64);
509                 if (copy_to_user((void __user *)arg, page_buf, 64)) {
510                         ret = -EFAULT;
511                         goto exit;
512                 }
513                 ret = 0;
514         } break;
515
516         case GET_LOCK_FLAG_IO:
517         {
518                 page_buf[0] = 0;
519                 if (copy_to_user((void __user *)arg, page_buf, 4)) {
520                         ret = -EFAULT;
521                         goto exit;
522                 }
523                 ret = 0;
524         } break;
525
526         case GET_FLASH_INFO_IO:
527         {
528                 page_buf[0] = 0x00800000;
529                 page_buf[1] = 0x00040400;
530                 page_buf[2] = 0x00010028;
531                 if (copy_to_user((void __user *)arg, page_buf, 11)) {
532                         ret = -EFAULT;
533                         goto exit;
534                 }
535                 ret = 0;
536         } break;
537
538         default:
539                 ret = -EFAULT;
540                 goto exit;
541         }
542 exit:
543         pr_info("ret = %lx\n", ret);
544         kfree(page_buf);
545         return ret;
546 }
547
548 const struct file_operations vendor_storage_fops = {
549         .open = vendor_storage_open,
550         .compat_ioctl   = vendor_storage_ioctl,
551         .unlocked_ioctl = vendor_storage_ioctl,
552         .release = vendor_storage_release,
553 };
554
555 static struct miscdevice vender_storage_dev = {
556         .minor = MISC_DYNAMIC_MINOR,
557         .name  = "vendor_storage",
558         .fops  = &vendor_storage_fops,
559 };
560
561 static int vendor_init_thread(void *arg)
562 {
563         int ret;
564
565         /* sleep 500ms wait emmc initialize completed */
566         msleep(500);
567         ret = emmc_vendor_storage_init();
568         if (!ret) {
569                 ret = misc_register(&vender_storage_dev);
570                 rk_vendor_register(emmc_vendor_read, emmc_vendor_write);
571         }
572         pr_info("vendor storage:20160801 ret = %d\n", ret);
573         return ret;
574 }
575
576 static int __init vendor_storage_init(void)
577 {
578         g_idb_buffer = NULL;
579         kthread_run(vendor_init_thread, (void *)NULL, "vendor_storage_init");
580         return 0;
581 }
582
583 static __exit void vendor_storage_deinit(void)
584 {
585         if (g_vendor)
586                 misc_deregister(&vender_storage_dev);
587 }
588
589 device_initcall_sync(vendor_storage_init);
590 module_exit(vendor_storage_deinit);