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