xref: /rk3399_rockchip-uboot/drivers/rkflash/sfc_nor.c (revision bc04a3dd9a41813372820ba50655022a6a28bfbf)
1 /*
2  * Copyright (c) 2018 Fuzhou Rockchip Electronics Co., Ltd
3  *
4  * SPDX-License-Identifier:	GPL-2.0
5  */
6 #include <linux/compat.h>
7 #include <linux/delay.h>
8 #include <linux/kernel.h>
9 #include <linux/string.h>
10 
11 #include "sfc_nor.h"
12 #include "rkflash_debug.h"
13 #include "rkflash_blk.h"
14 
15 static struct flash_info spi_flash_tbl[] = {
16 	/* GD25Q32B */
17 	{0xc84016, 128, 8, 0x03, 0x02, 0x6B, 0x32, 0x20, 0xD8, 0x0D, 13, 9, 0},
18 	/* GD25Q64B */
19 	{0xc84017, 128, 8, 0x03, 0x02, 0x6B, 0x32, 0x20, 0xD8, 0x0D, 14, 9, 0},
20 	/* GD25Q127C and GD25Q128C*/
21 	{0xc84018, 128, 8, 0x03, 0x02, 0x6B, 0x32, 0x20, 0xD8, 0x0C, 15, 9, 0},
22 	/* GD25Q256B */
23 	{0xc84019, 128, 8, 0x13, 0x12, 0x6C, 0x3E, 0x21, 0xDC, 0x1C, 16, 6, 0},
24 	/* GD25Q512MC */
25 	{0xc84020, 128, 8, 0x13, 0x12, 0x6C, 0x3E, 0x21, 0xDC, 0x1C, 17, 6, 0},
26 	/* 25Q64JVSSIQ */
27 	{0xef4017, 128, 8, 0x13, 0x02, 0x6B, 0x32, 0x20, 0xD8, 0x0C, 14, 9, 0},
28 	/* 25Q128FV */
29 	{0xef4018, 128, 8, 0x03, 0x02, 0x6B, 0x32, 0x20, 0xD8, 0x0C, 15, 9, 0},
30 	/* 25Q256FV */
31 	{0xef4019, 128, 8, 0x13, 0x02, 0x6C, 0x32, 0x20, 0xD8, 0x3C, 16, 9, 0},
32 	/* 25Q64FWSSIG */
33 	{0xef6017, 128, 8, 0x13, 0x02, 0x6B, 0x32, 0x20, 0xD8, 0x0C, 14, 9, 0},
34 	/* XT25F128A */
35 	{0x207018, 128, 8, 0x03, 0x02, 0x6B, 0x32, 0x20, 0xD8, 0x00, 15, 0, 0},
36 	/* MX25L25635E/F */
37 	{0xc22019, 128, 8, 0x03, 0x02, 0x6B, 0x38, 0x20, 0xD8, 0x30, 16, 6, 0},
38 	/* XM25QH64A */
39 	{0x207017, 128, 8, 0x03, 0x02, 0x6B, 0x32, 0x20, 0xD8, 0x0C, 14, 0, 0},
40 	/* XM25QH128A */
41 	{0x207018, 128, 8, 0x03, 0x02, 0x6B, 0x32, 0x20, 0xD8, 0x0C, 15, 0, 0},
42 	/* EN25QH128A */
43 	{0x1c7018, 128, 8, 0x03, 0x02, 0x6B, 0x32, 0x20, 0xD8, 0x0C, 15, 0, 0},
44 };
45 
46 static const u8 sfnor_dev_code[] = {
47 	0x11,
48 	0x12,
49 	0x13,
50 	0x14,
51 	0x15,
52 	0x16,
53 	0x17,
54 	0x18,
55 	0x19
56 };
57 
58 static const u32 sfnor_capacity[] = {
59 	0x20000,        /* 128k-byte */
60 	0x40000,        /* 256k-byte */
61 	0x80000,        /* 512k-byte */
62 	0x100000,       /* 1M-byte */
63 	0x200000,       /* 2M-byte */
64 	0x400000,       /* 4M-byte */
65 	0x800000,       /* 8M-byte */
66 	0x1000000,      /* 16M-byte */
67 	0x2000000       /* 32M-byte */
68 };
69 
70 static struct flash_info *g_spi_flash_info;
71 
72 static int snor_write_en(void)
73 {
74 	int ret;
75 	union SFCCMD_DATA     sfcmd;
76 
77 	sfcmd.d32 = 0;
78 	sfcmd.b.cmd = CMD_WRITE_EN;
79 
80 	ret = sfc_request(sfcmd.d32, 0, 0, NULL);
81 
82 	return ret;
83 }
84 
85 static int snor_enter_4byte_mode(void)
86 {
87 	int ret;
88 	union SFCCMD_DATA sfcmd;
89 
90 	sfcmd.d32 = 0;
91 	sfcmd.b.cmd = CMD_ENTER_4BYTE_MODE;
92 
93 	ret = sfc_request(sfcmd.d32, 0, 0, NULL);
94 	return ret;
95 }
96 
97 static int snor_read_status(u32 reg_index, u8 *status)
98 {
99 	int ret;
100 	union SFCCMD_DATA sfcmd;
101 	u8 read_stat_cmd[] = {CMD_READ_STATUS,
102 				CMD_READ_STATUS2, CMD_READ_STATUS3};
103 	sfcmd.d32 = 0;
104 	sfcmd.b.cmd = read_stat_cmd[reg_index];
105 	sfcmd.b.datasize = 1;
106 
107 	ret = sfc_request(sfcmd.d32, 0, 0, status);
108 
109 	return ret;
110 }
111 
112 static int snor_wait_busy(int timeout)
113 {
114 	int ret;
115 	union SFCCMD_DATA sfcmd;
116 	int i;
117 	u32 status;
118 
119 	sfcmd.d32 = 0;
120 	sfcmd.b.cmd = CMD_READ_STATUS;
121 	sfcmd.b.datasize = 1;
122 
123 	for (i = 0; i < timeout; i++) {
124 		ret = sfc_request(sfcmd.d32, 0, 0, &status);
125 		if (ret != SFC_OK)
126 			return ret;
127 
128 		if ((status & 0x01) == 0)
129 			return SFC_OK;
130 
131 		sfc_delay(1);
132 	}
133 	PRINT_SFC_E("%s  error %x\n", __func__, timeout);
134 
135 	return SFC_BUSY_TIMEOUT;
136 }
137 
138 static int snor_write_status2(u32 reg_index, u8 status)
139 {
140 	int ret;
141 	union SFCCMD_DATA sfcmd;
142 	u8 status2[2];
143 	u8 read_index;
144 
145 	status2[reg_index] = status;
146 	read_index = (reg_index == 0) ? 1 : 0;
147 	ret = snor_read_status(read_index, &status2[read_index]);
148 	if (ret != SFC_OK)
149 		return ret;
150 
151 	snor_write_en();
152 
153 	sfcmd.d32 = 0;
154 	sfcmd.b.cmd = CMD_WRITE_STATUS;
155 	sfcmd.b.datasize = 2;
156 	sfcmd.b.rw = SFC_WRITE;
157 
158 	ret = sfc_request(sfcmd.d32, 0, 0, &status2[0]);
159 	if (ret != SFC_OK)
160 		return ret;
161 
162 	ret = snor_wait_busy(10000);    /* 10ms */
163 
164 	return ret;
165 }
166 
167 static int snor_write_status(u32 reg_index, u8 status)
168 {
169 	int ret;
170 	union SFCCMD_DATA sfcmd;
171 	u8 write_stat_cmd[] = {CMD_WRITE_STATUS,
172 			       CMD_WRITE_STATUS2, CMD_WRITE_STATUS3};
173 	snor_write_en();
174 	sfcmd.d32 = 0;
175 	sfcmd.b.cmd = write_stat_cmd[reg_index];
176 	sfcmd.b.datasize = 1;
177 	sfcmd.b.rw = SFC_WRITE;
178 
179 	ret = sfc_request(sfcmd.d32, 0, 0, &status);
180 	if (ret != SFC_OK)
181 		return ret;
182 
183 	ret = snor_wait_busy(10000);    /* 10ms */
184 
185 	return ret;
186 }
187 
188 static int snor_erase(struct SFNOR_DEV *p_dev,
189 		      u32 addr,
190 		      enum NOR_ERASE_TYPE erase_type)
191 {
192 	int ret;
193 	union SFCCMD_DATA sfcmd;
194 	int timeout[] = {400, 2000, 40000};   /* ms */
195 
196 	if (erase_type > ERASE_CHIP)
197 		return SFC_PARAM_ERR;
198 
199 	sfcmd.d32 = 0;
200 	if (erase_type == ERASE_BLOCK64K)
201 		sfcmd.b.cmd = p_dev->blk_erase_cmd;
202 	else if (erase_type == ERASE_SECTOR)
203 		sfcmd.b.cmd = p_dev->sec_erase_cmd;
204 	else
205 		sfcmd.b.cmd = CMD_CHIP_ERASE;
206 
207 	sfcmd.b.addrbits = (erase_type != ERASE_CHIP) ?
208 				SFC_ADDR_24BITS : SFC_ADDR_0BITS;
209 	if (p_dev->addr_mode == ADDR_MODE_4BYTE && erase_type != ERASE_CHIP)
210 		sfcmd.b.addrbits = SFC_ADDR_32BITS;
211 
212 	snor_write_en();
213 
214 	ret = sfc_request(sfcmd.d32, 0, addr, NULL);
215 	if (ret != SFC_OK)
216 		return ret;
217 
218 	ret = snor_wait_busy(timeout[erase_type] * 1000);
219 	return ret;
220 }
221 
222 static int snor_prog_page(struct SFNOR_DEV *p_dev,
223 			  u32 addr,
224 			  void *p_data,
225 			  u32 size)
226 {
227 	int ret;
228 	union SFCCMD_DATA sfcmd;
229 	union SFCCTRL_DATA sfctrl;
230 
231 	sfcmd.d32 = 0;
232 	sfcmd.b.cmd = p_dev->prog_cmd;
233 	sfcmd.b.addrbits = SFC_ADDR_24BITS;
234 	sfcmd.b.datasize = size;
235 	sfcmd.b.rw = SFC_WRITE;
236 
237 	sfctrl.d32 = 0;
238 	sfctrl.b.datalines = p_dev->prog_lines;
239 	sfctrl.b.enbledma = 0;
240 	if (p_dev->prog_cmd == CMD_PAGE_PROG_A4)
241 		sfctrl.b.addrlines = SFC_4BITS_LINE;
242 
243 	if (p_dev->addr_mode == ADDR_MODE_4BYTE)
244 		sfcmd.b.addrbits = SFC_ADDR_32BITS;
245 
246 	snor_write_en();
247 
248 	ret = sfc_request(sfcmd.d32, sfctrl.d32, addr, p_data);
249 	if (ret != SFC_OK)
250 		return ret;
251 
252 	ret = snor_wait_busy(10000);
253 
254 	return ret;
255 }
256 
257 static int snor_prog(struct SFNOR_DEV *p_dev, u32 addr, void *p_data, u32 size)
258 {
259 	int ret = SFC_OK;
260 	u32 page_size, len;
261 	u8 *p_buf =  (u8 *)p_data;
262 
263 	page_size = NOR_PAGE_SIZE;
264 	while (size) {
265 		len = page_size < size ? page_size : size;
266 		ret = snor_prog_page(p_dev, addr, p_buf, len);
267 		if (ret != SFC_OK)
268 			return ret;
269 
270 		size -= len;
271 		addr += len;
272 		p_buf += len;
273 	}
274 
275 	return ret;
276 }
277 
278 static int snor_enable_QE(struct SFNOR_DEV *p_dev)
279 {
280 	int ret = SFC_OK;
281 	int reg_index;
282 	int bit_offset;
283 	u8 status;
284 
285 	if (p_dev->manufacturer == MID_GIGADEV ||
286 	    p_dev->manufacturer == MID_WINBOND) {
287 		reg_index = p_dev->QE_bits >> 3;
288 		bit_offset = p_dev->QE_bits & 0x7;
289 		ret = snor_read_status(reg_index, &status);
290 		if (ret != SFC_OK)
291 			return ret;
292 
293 		if (status & (1 << bit_offset))   /* is QE bit set */
294 			return SFC_OK;
295 
296 		status |= (1 << bit_offset);
297 		return p_dev->write_status(reg_index, status);
298 	}
299 
300 	return ret;
301 }
302 
303 #if (SNOR_4BIT_DATA_DETECT_EN)
304 static int snor_set_dlines(struct SFNOR_DEV *p_dev, enum SFC_DATA_LINES lines)
305 {
306 	int ret;
307 	u8 read_cmd[] = {CMD_FAST_READ_X1, CMD_FAST_READ_X2, CMD_FAST_READ_X4};
308 
309 	if (lines == DATA_LINES_X4) {
310 		ret = snor_enable_QE(p_dev);
311 		if (ret != SFC_OK)
312 			return ret;
313 	}
314 
315 	p_dev->read_lines = lines;
316 	p_dev->read_cmd = read_cmd[lines];
317 
318 	if (p_dev->manufacturer == MID_GIGADEV ||
319 	    p_dev->manufacturer == MID_WINBOND ||
320 	    p_dev->manufacturer == MID_MACRONIX) {
321 		p_dev->prog_lines = (lines != DATA_LINES_X2) ?
322 				     lines : DATA_LINES_X1;
323 		if (lines == DATA_LINES_X1) {
324 			p_dev->prog_cmd = CMD_PAGE_PROG;
325 		} else {
326 			if (p_dev->manufacturer == MID_GIGADEV ||
327 			    p_dev->manufacturer == MID_WINBOND)
328 				p_dev->prog_cmd = CMD_PAGE_PROG_X4;
329 			else
330 				p_dev->prog_cmd = CMD_PAGE_PROG_A4;
331 		}
332 	}
333 
334 	return SFC_OK;
335 }
336 #endif
337 
338 static int snor_read_data(struct SFNOR_DEV *p_dev,
339 			  u32 addr,
340 			  void *p_data,
341 			  u32 size)
342 {
343 	int ret;
344 	union SFCCMD_DATA sfcmd;
345 	union SFCCTRL_DATA sfctrl;
346 
347 	sfcmd.d32 = 0;
348 	sfcmd.b.cmd = p_dev->read_cmd;
349 	sfcmd.b.datasize = size;
350 	sfcmd.b.addrbits = SFC_ADDR_24BITS;
351 
352 	sfctrl.d32 = 0;
353 	sfctrl.b.datalines = p_dev->read_lines;
354 	if (!(size & 0x3) && size >= 4)
355 		sfctrl.b.enbledma = 0;
356 
357 	if (p_dev->read_cmd == CMD_FAST_READ_X1 ||
358 	    p_dev->read_cmd == CMD_FAST_READ_X4 ||
359 	    p_dev->read_cmd == CMD_FAST_READ_X2 ||
360 	    p_dev->read_cmd == CMD_FAST_4READ_X4) {
361 		sfcmd.b.dummybits = 8;
362 	} else if (p_dev->read_cmd == CMD_FAST_READ_A4) {
363 		sfcmd.b.addrbits = SFC_ADDR_32BITS;
364 		addr = (addr << 8) | 0xFF;	/* Set M[7:0] = 0xFF */
365 		sfcmd.b.dummybits = 4;
366 		sfctrl.b.addrlines = SFC_4BITS_LINE;
367 	}
368 
369 	if (p_dev->addr_mode == ADDR_MODE_4BYTE)
370 		sfcmd.b.addrbits = SFC_ADDR_32BITS;
371 
372 	ret = sfc_request(sfcmd.d32, sfctrl.d32, addr, p_data);
373 
374 	return ret;
375 }
376 
377 int snor_read(struct SFNOR_DEV *p_dev, u32 sec, u32 n_sec, void *p_data)
378 {
379 	int ret = SFC_OK;
380 	u32 addr, size, len;
381 	u8 *p_buf =  (u8 *)p_data;
382 
383 	if ((sec + n_sec) > p_dev->capacity)
384 		return SFC_PARAM_ERR;
385 
386 	mutex_lock(&p_dev->lock);
387 	addr = sec << 9;
388 	size = n_sec << 9;
389 	while (size) {
390 		len = size < SFC_MAX_IOSIZE ? size : SFC_MAX_IOSIZE;
391 		ret = snor_read_data(p_dev, addr, p_buf, len);
392 		if (ret != SFC_OK) {
393 			PRINT_SFC_E("snor_read_data %x ret= %x\n",
394 				    addr >> 9, ret);
395 			goto out;
396 		}
397 
398 		size -= len;
399 		addr += len;
400 		p_buf += len;
401 	}
402 out:
403 	mutex_unlock(&p_dev->lock);
404 	if (!ret)
405 		ret = n_sec;
406 
407 	return ret;
408 }
409 
410 int snor_write(struct SFNOR_DEV *p_dev, u32 sec, u32 n_sec, const void *p_data)
411 {
412 	int ret = SFC_OK;
413 	u32 len, blk_size, offset;
414 	u8 *p_buf =  (u8 *)p_data;
415 	u32 total_sec = n_sec;
416 
417 	if ((sec + n_sec) > p_dev->capacity)
418 		return SFC_PARAM_ERR;
419 
420 	mutex_lock(&p_dev->lock);
421 	while (n_sec) {
422 		if (sec < 512 || sec >= p_dev->capacity  - 512)
423 			blk_size = 8;
424 		else
425 			blk_size = p_dev->blk_size;
426 
427 		offset = (sec & (blk_size - 1));
428 		if (!offset) {
429 			ret = snor_erase(p_dev, sec << 9, (blk_size == 8) ?
430 				ERASE_SECTOR : ERASE_BLOCK64K);
431 			if (ret != SFC_OK) {
432 				PRINT_SFC_E("snor_erase %x ret= %x\n",
433 					    sec, ret);
434 				goto out;
435 			}
436 		}
437 		len = (blk_size - offset) < n_sec ?
438 		      (blk_size - offset) : n_sec;
439 		ret = snor_prog(p_dev, sec << 9, p_buf, len << 9);
440 		if (ret != SFC_OK) {
441 			PRINT_SFC_E("snor_prog %x ret= %x\n", sec, ret);
442 			goto out;
443 		}
444 		n_sec -= len;
445 		sec += len;
446 		p_buf += len << 9;
447 	}
448 out:
449 	mutex_unlock(&p_dev->lock);
450 	if (!ret)
451 		ret = total_sec;
452 
453 	return ret;
454 }
455 
456 static int snor_read_id(u8 *data)
457 {
458 	int ret;
459 	union SFCCMD_DATA     sfcmd;
460 
461 	sfcmd.d32 = 0;
462 	sfcmd.b.cmd = CMD_READ_JEDECID;
463 	sfcmd.b.datasize = 3;
464 
465 	ret = sfc_request(sfcmd.d32, 0, 0, data);
466 
467 	return ret;
468 }
469 
470 static int snor_read_parameter(u32 addr, u8 *data)
471 {
472 	int ret;
473 	union SFCCMD_DATA     sfcmd;
474 
475 	sfcmd.d32 = 0;
476 	sfcmd.b.cmd = CMD_READ_PARAMETER;
477 	sfcmd.b.datasize = 1;
478 	sfcmd.b.addrbits = SFC_ADDR_24BITS;
479 	sfcmd.b.dummybits = 8;
480 
481 	ret = sfc_request(sfcmd.d32, 0, addr, data);
482 
483 	return ret;
484 }
485 
486 u32 snor_get_capacity(struct SFNOR_DEV *p_dev)
487 {
488 	return p_dev->capacity;
489 }
490 
491 static void snor_print_spi_chip_info(struct SFNOR_DEV *p_dev)
492 {
493 	PRINT_SFC_I("addr_mode: %x\n", p_dev->addr_mode);
494 	PRINT_SFC_I("read_lines: %x\n", p_dev->read_lines);
495 	PRINT_SFC_I("prog_lines: %x\n", p_dev->prog_lines);
496 	PRINT_SFC_I("read_cmd: %x\n", p_dev->read_cmd);
497 	PRINT_SFC_I("prog_cmd: %x\n", p_dev->prog_cmd);
498 	PRINT_SFC_I("blk_erase_cmd: %x\n", p_dev->blk_erase_cmd);
499 	PRINT_SFC_I("sec_erase_cmd: %x\n", p_dev->sec_erase_cmd);
500 }
501 
502 static struct flash_info *snor_get_flash_info(u8 *flash_id)
503 {
504 	u32 i;
505 	u32 id = (flash_id[0] << 16) | (flash_id[1] << 8) | (flash_id[2] << 0);
506 
507 	for (i = 0; i < ARRAY_SIZE(spi_flash_tbl); i++) {
508 		if (spi_flash_tbl[i].id == id)
509 			return &spi_flash_tbl[i];
510 	}
511 	return NULL;
512 }
513 
514 /* Adjust flash info in ram base on parameter */
515 static void *snor_flash_info_adjust(struct flash_info *spi_flash_info)
516 {
517 	u32 addr;
518 	u8 para_version;
519 
520 	if (spi_flash_info->id == 0xc84019) {
521 		addr = 0x09;
522 		snor_read_parameter(addr, &para_version);
523 		if (para_version == 0x06) {
524 			spi_flash_info->QE_bits = 9;
525 			spi_flash_info->prog_cmd_4 = 0x34;
526 		}
527 	}
528 	return 0;
529 }
530 
531 int snor_init(struct SFNOR_DEV *p_dev)
532 {
533 	u32 i;
534 	u8 id_byte[5];
535 	int err;
536 
537 	memset(p_dev, 0, sizeof(struct SFNOR_DEV));
538 	snor_read_id(id_byte);
539 	PRINT_SFC_E("sfc nor id: %x %x %x\n",
540 		    id_byte[0], id_byte[1], id_byte[2]);
541 	if (0xFF == id_byte[0] || 0x00 == id_byte[0]) {
542 		err = SFC_ERROR;
543 		goto err_out;
544 	}
545 
546 	p_dev->manufacturer = id_byte[0];
547 	p_dev->mem_type = id_byte[1];
548 
549 	mutex_init(&p_dev->lock);
550 	g_spi_flash_info = snor_get_flash_info(id_byte);
551 	if (g_spi_flash_info) {
552 		snor_flash_info_adjust(g_spi_flash_info);
553 		p_dev->capacity = 1 << g_spi_flash_info->density;
554 		p_dev->blk_size = g_spi_flash_info->block_size;
555 		p_dev->page_size = NOR_SECS_PAGE;
556 		p_dev->read_cmd = g_spi_flash_info->read_cmd;
557 		p_dev->prog_cmd = g_spi_flash_info->prog_cmd;
558 		p_dev->sec_erase_cmd = g_spi_flash_info->sector_erase_cmd;
559 		p_dev->blk_erase_cmd = g_spi_flash_info->block_erase_cmd;
560 		p_dev->prog_lines = DATA_LINES_X1;
561 		p_dev->read_lines = DATA_LINES_X1;
562 		p_dev->QE_bits = g_spi_flash_info->QE_bits;
563 
564 		i = g_spi_flash_info->feature & FEA_READ_STATUE_MASK;
565 		if (i == 0)
566 			p_dev->write_status = snor_write_status;
567 		else
568 			p_dev->write_status = snor_write_status2;
569 		if (g_spi_flash_info->feature & FEA_4BIT_READ) {
570 			if (snor_enable_QE(p_dev) == SFC_OK) {
571 				p_dev->read_lines = DATA_LINES_X4;
572 				p_dev->read_cmd = g_spi_flash_info->read_cmd_4;
573 			}
574 		}
575 		if (g_spi_flash_info->feature & FEA_4BIT_PROG &&
576 		    p_dev->read_lines == DATA_LINES_X4) {
577 			p_dev->prog_lines = DATA_LINES_X4;
578 			p_dev->prog_cmd = g_spi_flash_info->prog_cmd_4;
579 		}
580 
581 		if (g_spi_flash_info->feature & FEA_4BYTE_ADDR)
582 			p_dev->addr_mode = ADDR_MODE_4BYTE;
583 
584 		if ((g_spi_flash_info->feature & FEA_4BYTE_ADDR_MODE))
585 			snor_enter_4byte_mode();
586 
587 		goto normal_out;
588 	}
589 
590 	for (i = 0; i < sizeof(sfnor_dev_code); i++) {
591 		if (id_byte[2] == sfnor_dev_code[i]) {
592 			p_dev->capacity = sfnor_capacity[i] >> 9;
593 			break;
594 		}
595 	}
596 
597 	if (i >= sizeof(sfnor_dev_code)) {
598 		err = SFC_ERROR;
599 		goto err_out;
600 	}
601 
602 	p_dev->QE_bits = 9;
603 	p_dev->blk_size = NOR_SECS_BLK;
604 	p_dev->page_size = NOR_SECS_PAGE;
605 	p_dev->read_cmd = CMD_READ_DATA;
606 	p_dev->prog_cmd = CMD_PAGE_PROG;
607 	p_dev->sec_erase_cmd = CMD_SECTOR_ERASE;
608 	p_dev->blk_erase_cmd = CMD_BLOCK_ERASE;
609 	p_dev->write_status = snor_write_status2;
610 	#if (SNOR_4BIT_DATA_DETECT_EN)
611 	snor_set_dlines(p_dev, DATA_LINES_X4);
612 	#endif
613 
614 normal_out:
615 	snor_print_spi_chip_info(p_dev);
616 
617 	return SFC_OK;
618 
619 err_out:
620 	return err;
621 }
622 
623