xref: /rk3399_rockchip-uboot/drivers/rkflash/sfc_nand.c (revision 8d6469cd312d1a3fc9be75da54ec1070f7ba5089)
1 /*
2  * Copyright (c) 2018 Fuzhou Rockchip Electronics Co., Ltd
3  *
4  * SPDX-License-Identifier:	GPL-2.0
5  */
6 
7 #include <common.h>
8 #include <linux/bug.h>
9 #include <linux/delay.h>
10 
11 #include "flash_com.h"
12 #include "rkflash_debug.h"
13 #include "rk_sftl.h"
14 #include "sfc.h"
15 #include "sfc_nand.h"
16 
17 static u32 sfc_nand_get_ecc_status0(void);
18 static u32 sfc_nand_get_ecc_status1(void);
19 static u32 sfc_nand_get_ecc_status2(void);
20 static u32 sfc_nand_get_ecc_status3(void);
21 static u32 sfc_nand_get_ecc_status4(void);
22 static u32 sfc_nand_get_ecc_status5(void);
23 static u32 sfc_nand_get_ecc_status6(void);
24 static u32 sfc_nand_get_ecc_status7(void);
25 static u32 sfc_nand_get_ecc_status8(void);
26 static u32 sfc_nand_get_ecc_status9(void);
27 static u32 sfc_nand_get_ecc_status10(void);
28 
29 static struct nand_info spi_nand_tbl[] = {
30 	/* TC58CVG0S0HxAIx */
31 	{ 0x98, 0xC2, 0x00, 4, 0x40, 1, 1024, 0x00, 18, 0x8, 0, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status0 },
32 	/* TC58CVG1S0HxAIx */
33 	{ 0x98, 0xCB, 0x00, 4, 0x40, 2, 1024, 0x00, 19, 0x8, 0, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status0 },
34 	/* TC58CVG2S0HRAIJ */
35 	{ 0x98, 0xED, 0x00, 8, 0x40, 1, 2048, 0x0C, 20, 0x8, 0, { 0x04, 0x0C, 0x08, 0x10 }, &sfc_nand_get_ecc_status0 },
36 	/* TC58CVG1S3HRAIJ */
37 	{ 0x98, 0xEB, 0x00, 4, 0x40, 1, 2048, 0x0C, 19, 0x8, 0, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status0 },
38 	/* TC58CVG0S3HRAIJ */
39 	{ 0x98, 0xE2, 0x00, 4, 0x40, 1, 1024, 0x0C, 18, 0x8, 0, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status0 },
40 
41 	/* MX35LF1GE4AB */
42 	{ 0xC2, 0x12, 0x00, 4, 0x40, 1, 1024, 0x0C, 18, 0x4, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status1 },
43 	/* MX35LF2GE4AB */
44 	{ 0xC2, 0x22, 0x00, 4, 0x40, 2, 1024, 0x0C, 19, 0x4, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status1 },
45 	/* MX35LF2GE4AD */
46 	{ 0xC2, 0x26, 0x00, 4, 0x40, 1, 2048, 0x0C, 19, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status0 },
47 	/* MX35LF4GE4AD */
48 	{ 0xC2, 0x37, 0x00, 8, 0x40, 1, 2048, 0x0C, 20, 0x8, 1, { 0x04, 0x08, 0x14, 0x18 }, &sfc_nand_get_ecc_status0 },
49 	/* MX35UF1GE4AC */
50 	{ 0xC2, 0x92, 0x00, 4, 0x40, 1, 1024, 0x0C, 18, 0x4, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status0 },
51 	/* MX35UF2GE4AC */
52 	{ 0xC2, 0xA2, 0x00, 4, 0x40, 1, 2048, 0x0C, 19, 0x4, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status0 },
53 	/* MX35UF1GE4AD */
54 	{ 0xC2, 0x96, 0x00, 4, 0x40, 1, 1024, 0x0C, 18, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status0 },
55 	/* MX35UF2GE4AD */
56 	{ 0xC2, 0xA6, 0x00, 4, 0x40, 1, 2048, 0x0C, 19, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status0 },
57 	/* MX35UF4GE4AD */
58 	{ 0xC2, 0xB7, 0x00, 8, 0x40, 1, 2048, 0x0C, 20, 0x8, 1, { 0x04, 0x08, 0x14, 0x18 }, &sfc_nand_get_ecc_status0 },
59 
60 	/* GD5F1GQ4UAYIG */
61 	{ 0xC8, 0xF1, 0x00, 4, 0x40, 1, 1024, 0x0C, 18, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status0 },
62 	/* GD5F1GQ4RB9IGR */
63 	{ 0xC8, 0xD1, 0x00, 4, 0x40, 1, 1024, 0x0C, 18, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status3 },
64 	/* GD5F2GQ40BY2GR */
65 	{ 0xC8, 0xD2, 0x00, 4, 0x40, 2, 1024, 0x0C, 19, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status3 },
66 	/* GD5F1GQ5UEYIG */
67 	{ 0xC8, 0x51, 0x00, 4, 0x40, 1, 1024, 0x4C, 18, 0x4, 1, { 0x04, 0x14, 0xFF, 0xFF }, &sfc_nand_get_ecc_status2 },
68 	/* GD5F2GQ5UEYIG */
69 	{ 0xC8, 0x52, 0x00, 4, 0x40, 1, 2048, 0x4C, 19, 0x4, 1, { 0x04, 0x14, 0xFF, 0xFF }, &sfc_nand_get_ecc_status2 },
70 	/* GD5F1GQ4R */
71 	{ 0xC8, 0xC1, 0x00, 4, 0x40, 1, 1024, 0x0C, 18, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status3 },
72 	/* GD5F4GQ6RExxG 1*4096 */
73 	{ 0xC8, 0x45, 0x00, 4, 0x40, 2, 2048, 0x4C, 20, 0x4, 1, { 0x04, 0x08, 0x14, 0x18 }, &sfc_nand_get_ecc_status2 },
74 	/* GD5F4GQ6UExxG 1*4096 */
75 	{ 0xC8, 0x55, 0x00, 4, 0x40, 2, 2048, 0x4C, 20, 0x4, 1, { 0x04, 0x08, 0x14, 0x18 }, &sfc_nand_get_ecc_status2 },
76 	/* GD5F1GQ4UExxH */
77 	{ 0xC8, 0xD9, 0x00, 4, 0x40, 1, 1024, 0x0C, 18, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status3 },
78 	/* GD5F1GQ5REYIG Add 3rd code to distingush with F50L2G41KA */
79 	{ 0xC8, 0x41, 0xC8, 4, 0x40, 1, 1024, 0x4C, 18, 0x4, 1, { 0x04, 0x14, 0xFF, 0xFF }, &sfc_nand_get_ecc_status2 },
80 	/* GD5F2GQ5REYIG */
81 	{ 0xC8, 0x42, 0x00, 4, 0x40, 1, 2048, 0x4C, 19, 0x4, 1, { 0x04, 0x14, 0xFF, 0xFF }, &sfc_nand_get_ecc_status2 },
82 	/* GD5F2GM7RxG */
83 	{ 0xC8, 0x82, 0x00, 4, 0x40, 1, 2048, 0x0C, 19, 0x8, 1, { 0x04, 0x14, 0xFF, 0xFF }, &sfc_nand_get_ecc_status3 },
84 	/* GD5F2GM7UxG */
85 	{ 0xC8, 0x92, 0x00, 4, 0x40, 1, 2048, 0x0C, 19, 0x8, 1, { 0x04, 0x14, 0xFF, 0xFF }, &sfc_nand_get_ecc_status3 },
86 	/* GD5F1GM7UxG */
87 	{ 0xC8, 0x91, 0x00, 4, 0x40, 1, 1024, 0x0C, 18, 0x8, 1, { 0x04, 0x14, 0xFF, 0xFF }, &sfc_nand_get_ecc_status3 },
88 	/* GD5F4GQ4UAYIG 1*4096 */
89 	{ 0xC8, 0xF4, 0x00, 4, 0x40, 2, 2048, 0x0C, 20, 0x8, 1, { 0x04, 0x08, 0x14, 0x18 }, &sfc_nand_get_ecc_status0 },
90 	/* GD5F1GM7REYIGR */
91 	{ 0xC8, 0x81, 0x00, 4, 0x40, 1, 1024, 0x4C, 18, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status3 },
92 	/* GD5F4GM8UEYIGR */
93 	{ 0xC8, 0x95, 0x00, 4, 0x40, 1, 4096, 0x4C, 20, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status3 },
94 
95 	/* W25N01GV */
96 	{ 0xEF, 0xAA, 0x21, 4, 0x40, 1, 1024, 0x4C, 18, 0x1, 0, { 0x04, 0x14, 0x24, 0xFF }, &sfc_nand_get_ecc_status1 },
97 	/* W25N02KVZEIR */
98 	{ 0xEF, 0xAA, 0x22, 4, 0x40, 1, 2048, 0x4C, 19, 0x8, 0, { 0x04, 0x14, 0x24, 0xFF }, &sfc_nand_get_ecc_status0 },
99 	/* W25N04KVZEIR */
100 	{ 0xEF, 0xAA, 0x23, 4, 0x40, 1, 4096, 0x4C, 20, 0x8, 0, { 0x04, 0x14, 0x24, 0x34 }, &sfc_nand_get_ecc_status0 },
101 	/* W25N01GW */
102 	{ 0xEF, 0xBA, 0x21, 4, 0x40, 1, 1024, 0x4C, 18, 0x1, 0, { 0x04, 0x14, 0x24, 0xFF }, &sfc_nand_get_ecc_status1 },
103 	/* W25N02KW */
104 	{ 0xEF, 0xBA, 0x22, 4, 0x40, 1, 2048, 0x4C, 19, 0x8, 0, { 0x04, 0x14, 0x24, 0xFF }, &sfc_nand_get_ecc_status0 },
105 	/* W25N512GVEIG */
106 	{ 0xEF, 0xAA, 0x20, 4, 0x40, 1, 512, 0x4C, 17, 0x1, 0, { 0x04, 0x14, 0x24, 0xFF }, &sfc_nand_get_ecc_status1 },
107 	/* W25N01KV */
108 	{ 0xEF, 0xAE, 0x21, 4, 0x40, 1, 1024, 0x4C, 18, 0x4, 0, { 0x04, 0x14, 0xFF, 0xFF }, &sfc_nand_get_ecc_status0 },
109 	/* W25N01JWZEIG */
110 	{ 0xEF, 0xBC, 0x21, 4, 0x40, 1, 1024, 0x4C, 18, 0x1, 1, { 0x04, 0x14, 0xFF, 0xFF }, &sfc_nand_get_ecc_status1 },
111 	/* W25N01KWZPIG */
112 	{ 0xEF, 0xBE, 0x21, 4, 0x40, 1, 1024, 0x4C, 18, 0x4, 0, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status0 },
113 
114 	/* HYF2GQ4UAACAE */
115 	{ 0xC9, 0x52, 0x00, 4, 0x40, 1, 2048, 0x4C, 19, 0xE, 1, { 0x04, 0x24, 0xFF, 0xFF }, &sfc_nand_get_ecc_status0 },
116 	/* HYF1GQ4UDACAE */
117 	{ 0xC9, 0x21, 0x00, 4, 0x40, 1, 1024, 0x4C, 18, 0x4, 1, { 0x04, 0x14, 0xFF, 0xFF }, &sfc_nand_get_ecc_status0 },
118 	/* HYF1GQ4UPACAE */
119 	{ 0xC9, 0xA1, 0x00, 4, 0x40, 1, 1024, 0x4C, 18, 0x1, 1, { 0x04, 0x14, 0xFF, 0xFF }, &sfc_nand_get_ecc_status1 },
120 	/* HYF2GQ4UDACAE */
121 	{ 0xC9, 0x22, 0x00, 4, 0x40, 1, 2048, 0x4C, 19, 0x4, 1, { 0x04, 0x14, 0xFF, 0xFF }, &sfc_nand_get_ecc_status0 },
122 	/* HYF2GQ4UHCCAE */
123 	{ 0xC9, 0x5A, 0x00, 4, 0x40, 1, 2048, 0x4C, 19, 0xE, 1, { 0x04, 0x24, 0xFF, 0xFF }, &sfc_nand_get_ecc_status0 },
124 	/* HYF4GQ4UAACBE */
125 	{ 0xC9, 0xD4, 0x00, 8, 0x40, 1, 2048, 0x4C, 20, 0xE, 1, { 0x20, 0x40, 0x24, 0x44 }, &sfc_nand_get_ecc_status0 },
126 	/* HYF2GQ4IAACAE */
127 	{ 0xC9, 0x82, 0x00, 4, 0x40, 1, 2048, 0x4C, 20, 0xE, 1, { 0x04, 0x24, 0xFF, 0xFF }, &sfc_nand_get_ecc_status0 },
128 	/* HYF1GQ4IDACAE */
129 	{ 0xC9, 0x81, 0x00, 4, 0x40, 1, 1024, 0x4C, 20, 0x4, 1, { 0x04, 0x14, 0xFF, 0xFF }, &sfc_nand_get_ecc_status0 },
130 
131 	/* FS35ND01G-S1 */
132 	{ 0xCD, 0xB1, 0x00, 4, 0x40, 1, 1024, 0x0C, 18, 0x4, 1, { 0x10, 0x14, 0xFF, 0xFF }, &sfc_nand_get_ecc_status5 },
133 	/* FS35ND02G-S2 */
134 	{ 0xCD, 0xA2, 0x00, 4, 0x40, 1, 2048, 0x00, 19, 0x4, 0, { 0x10, 0x14, 0xFF, 0xFF }, &sfc_nand_get_ecc_status5 },
135 	/* FS35ND01G-S1Y2 */
136 	{ 0xCD, 0xEA, 0x00, 4, 0x40, 1, 1024, 0x4C, 18, 0x4, 0, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status1 },
137 	/* FS35ND02G-S3Y2 */
138 	{ 0xCD, 0xEB, 0x00, 4, 0x40, 1, 2048, 0x4C, 19, 0x4, 0, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status1 },
139 	/* FS35ND04G-S2Y2 1*4096 */
140 	{ 0xCD, 0xEC, 0x00, 4, 0x40, 2, 2048, 0x4C, 20, 0x4, 0, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status1 },
141 	/* F35SQA001G */
142 	{ 0xCD, 0x71, 0x00, 4, 0x40, 1, 1024, 0x4C, 18, 0x1, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status1 },
143 	/* F35SQA002G */
144 	{ 0xCD, 0x72, 0x00, 4, 0x40, 1, 2048, 0x4C, 19, 0x1, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status1 },
145 	/* F35SQA512M */
146 	{ 0xCD, 0x70, 0x00, 4, 0x40, 1, 512, 0x4C, 17, 0x1, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status1 },
147 	/* F35UQA512M */
148 	{ 0xCD, 0x60, 0x00, 4, 0x40, 1, 512, 0x4C, 17, 0x1, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status1 },
149 	/* F35UQA002G-WWT */
150 	{ 0xCD, 0x62, 0x00, 4, 0x40, 1, 2048, 0x4C, 19, 0x1, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status1 },
151 	/* F35SQB004G-WWT */
152 	{ 0xCD, 0x61, 0x00, 4, 0x40, 1, 1024, 0x4C, 18, 0x1, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status1 },
153 	/* F35SQB004G */
154 	{ 0xCD, 0x53, 0x00, 8, 0x40, 1, 2048, 0x0C, 20, 0x8, 1, { 0x04, 0x08, 0x0C, 0x10 }, &sfc_nand_get_ecc_status10 },
155 	/* F35SQB002G */
156 	{ 0xCD, 0x52, 0x00, 4, 0x40, 1, 2048, 0x4C, 19, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status10 },
157 
158 	/* DS35Q1GA-IB */
159 	{ 0xE5, 0x71, 0x00, 4, 0x40, 1, 1024, 0x0C, 18, 0x4, 1, { 0x04, 0x14, 0xFF, 0xFF }, &sfc_nand_get_ecc_status1 },
160 	/* DS35Q2GA-IB */
161 	{ 0xE5, 0x72, 0x00, 4, 0x40, 2, 1024, 0x0C, 19, 0x4, 1, { 0x04, 0x14, 0xFF, 0xFF }, &sfc_nand_get_ecc_status1 },
162 	/* DS35M1GA-1B */
163 	{ 0xE5, 0x21, 0x00, 4, 0x40, 1, 1024, 0x0C, 18, 0x4, 1, { 0x04, 0x14, 0xFF, 0xFF }, &sfc_nand_get_ecc_status1 },
164 	/* DS35M2GA-IB */
165 	{ 0xE5, 0x22, 0x00, 4, 0x40, 2, 1024, 0x0C, 19, 0x4, 1, { 0x04, 0x14, 0xFF, 0xFF }, &sfc_nand_get_ecc_status1 },
166 	/* DS35Q1GB-IB */
167 	{ 0xE5, 0xF1, 0x00, 4, 0x40, 1, 1024, 0x0C, 18, 0x8, 1, { 0x04, 0x14, 0xFF, 0xFF }, &sfc_nand_get_ecc_status6 },
168 	/* DS35Q2GB-IB */
169 	{ 0xE5, 0xF2, 0x00, 4, 0x40, 2, 1024, 0x0C, 19, 0x8, 1, { 0x04, 0x14, 0xFF, 0xFF }, &sfc_nand_get_ecc_status6 },
170 	/* DS35Q4GM */
171 	{ 0xE5, 0xF4, 0x00, 4, 0x40, 2, 2048, 0x0C, 20, 0x8, 1, { 0x04, 0x14, 0xFF, 0xFF }, &sfc_nand_get_ecc_status6 },
172 	/* DS35M1GB-IB */
173 	{ 0xE5, 0xA1, 0x00, 4, 0x40, 1, 1024, 0x0C, 18, 0x8, 1, { 0x04, 0x14, 0xFF, 0xFF }, &sfc_nand_get_ecc_status6 },
174 	/* DS35Q12B-IB */
175 	{ 0xE5, 0xF5, 0x00, 4, 0x40, 1, 512, 0x0C, 17, 0x8, 1, { 0x04, 0x14, 0xFF, 0xFF }, &sfc_nand_get_ecc_status6 },
176 	/* DS35M12B-IB */
177 	{ 0xE5, 0xA5, 0x00, 4, 0x40, 1, 512, 0x0C, 17, 0x8, 1, { 0x04, 0x14, 0xFF, 0xFF }, &sfc_nand_get_ecc_status6 },
178 	/* DS35Q1GD-IB */
179 	{ 0xE5, 0x51, 0x00, 4, 0x40, 1, 1024, 0x4C, 18, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status6 },
180 	/* DS35M4GB-IB */
181 	{ 0xE5, 0x64, 0x00, 4, 0x40, 1, 4096, 0x4C, 20, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status6 },
182 	/* DS35Q4GB-IB */
183 	{ 0xE5, 0xB4, 0x00, 4, 0x40, 1, 4096, 0x4C, 20, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status6 },
184 	/* DS35M12C-IB */
185 	{ 0xE5, 0x25, 0x00, 4, 0x40, 1, 512, 0x4C, 17, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status6 },
186 	/* DS35Q12C-IB */
187 	{ 0xE5, 0x75, 0x00, 4, 0x40, 1, 512, 0x4C, 17, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status6 },
188 	/* DS35Q2GBS */
189 	{ 0xE5, 0xB2, 0x00, 4, 0x40, 1, 2048, 0x4C, 19, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status6 },
190 
191 	/* EM73C044VCC-H */
192 	{ 0xD5, 0x22, 0x00, 4, 0x40, 1, 1024, 0x0C, 18, 0x8, 1, { 0x04, 0x14, 0xFF, 0xFF }, &sfc_nand_get_ecc_status0 },
193 	/* EM73D044VCE-H */
194 	{ 0xD5, 0x20, 0x00, 4, 0x40, 1, 2048, 0x0C, 19, 0x8, 1, { 0x04, 0x14, 0xFF, 0xFF }, &sfc_nand_get_ecc_status0 },
195 	/* EM73E044SNA-G */
196 	{ 0xD5, 0x03, 0x00, 8, 0x40, 1, 2048, 0x4C, 20, 0x8, 1, { 0x04, 0x28, 0x08, 0x2C }, &sfc_nand_get_ecc_status0 },
197 	/* EM73C044VCF-H */
198 	{ 0xD5, 0x25, 0x00, 4, 0x40, 1, 1024, 0x0C, 18, 0x4, 1, { 0x04, 0x14, 0xFF, 0xFF }, &sfc_nand_get_ecc_status0 },
199 
200 	/* XT26G02A */
201 	{ 0x0B, 0xE2, 0x00, 4, 0x40, 1, 2048, 0x4C, 19, 0x8, 1, { 0x08, 0x0C, 0xFF, 0xFF }, &sfc_nand_get_ecc_status4 },
202 	/* XT26G01A */
203 	{ 0x0B, 0xE1, 0x00, 4, 0x40, 1, 1024, 0x4C, 18, 0x8, 1, { 0x08, 0x0C, 0xFF, 0xFF }, &sfc_nand_get_ecc_status4 },
204 	/* XT26G04A */
205 	{ 0x0B, 0xE3, 0x00, 4, 0x80, 1, 2048, 0x4C, 20, 0x8, 1, { 0x08, 0x0C, 0xFF, 0xFF }, &sfc_nand_get_ecc_status4 },
206 	/* XT26G01B */
207 	{ 0x0B, 0xF1, 0x00, 4, 0x40, 1, 1024, 0x4C, 18, 0x8, 1, { 0x08, 0x0C, 0xFF, 0xFF }, &sfc_nand_get_ecc_status4 },
208 	/* XT26G02B */
209 	{ 0x0B, 0xF2, 0x00, 4, 0x40, 1, 2048, 0x4C, 19, 0x4, 1, { 0x08, 0x0C, 0xFF, 0xFF }, &sfc_nand_get_ecc_status5 },
210 	/* XT26G01C */
211 	{ 0x0B, 0x11, 0x00, 4, 0x40, 1, 1024, 0x4C, 18, 0x8, 1, { 0x08, 0x0C, 0xFF, 0xFF }, &sfc_nand_get_ecc_status7 },
212 	/* XT26G02C */
213 	{ 0x0B, 0x12, 0x00, 4, 0x40, 1, 2048, 0x4C, 19, 0x8, 1, { 0x08, 0x0C, 0xFF, 0xFF }, &sfc_nand_get_ecc_status7 },
214 	/* XT26G04C */
215 	{ 0x0B, 0x13, 0x00, 8, 0x40, 1, 2048, 0x4C, 20, 0x8, 1, { 0x04, 0x08, 0x0C, 0x10 }, &sfc_nand_get_ecc_status7 },
216 	/* XT26G11C */
217 	{ 0x0B, 0x15, 0x00, 4, 0x40, 1, 1024, 0x4C, 18, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status0 },
218 	/* XT26Q02DWSIGA */
219 	{ 0x0B, 0x52, 0x00, 4, 0x40, 1, 2048, 0x4C, 19, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status0 },
220 	/* XT26Q01DWSIGA */
221 	{ 0x0B, 0x51, 0x00, 4, 0x40, 1, 1024, 0x4C, 18, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status0 },
222 	/* XT26Q04DWSIGA */
223 	{ 0x0B, 0x53, 0x00, 8, 0x40, 1, 2048, 0x4C, 20, 0x8, 1, { 0x04, 0x08, 0x0C, 0x10 }, &sfc_nand_get_ecc_status0 },
224 	/* XT26G01DWSIGA */
225 	{ 0x0B, 0x31, 0x00, 4, 0x40, 1, 1024, 0x4C, 18, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status0 },
226 	/* XT26G02DWSIGA */
227 	{ 0x0B, 0x32, 0x00, 4, 0x40, 1, 2048, 0x4C, 19, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status0 },
228 	/* XT26G04DWSIGA */
229 	{ 0x0B, 0x33, 0x00, 8, 0x40, 1, 2048, 0x4C, 20, 0x8, 1, { 0x04, 0x08, 0x0C, 0x10 }, &sfc_nand_get_ecc_status0 },
230 	/* XT26Q04DWSIGT-B */
231 	{ 0x0B, 0x53, 0x00, 8, 0x40, 1, 2048, 0x4C, 20, 0x14, 1, { 0x04, 0x08, 0x0C, 0x10 }, &sfc_nand_get_ecc_status0 },
232 	/* XT26Q01DWSIGA */
233 	{ 0x0B, 0x51, 0x00, 4, 0x40, 1, 1024, 0x4C, 18, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status0 },
234 
235 	/* MT29F2G01ABA, XT26G02E, F50L2G41XA */
236 	{ 0x2C, 0x24, 0x00, 4, 0x40, 2, 1024, 0x4C, 19, 0x8, 0, { 0x20, 0x24, 0xFF, 0xFF }, &sfc_nand_get_ecc_status6 },
237 	/* MT29F1G01ABA, F50L1G41XA */
238 	{ 0x2C, 0x14, 0x00, 4, 0x40, 1, 1024, 0x4C, 18, 0x8, 0, { 0x20, 0x24, 0xFF, 0xFF }, &sfc_nand_get_ecc_status6 },
239 
240 	/* FM25S01 */
241 	{ 0xA1, 0xA1, 0x00, 4, 0x40, 1, 1024, 0x4C, 18, 0x1, 0, { 0x00, 0x04, 0xFF, 0xFF }, &sfc_nand_get_ecc_status1 },
242 	/* FM25S01A */
243 	{ 0xA1, 0xE4, 0x00, 4, 0x40, 1, 1024, 0x4C, 18, 0x1, 0, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status1 },
244 	/* FM25S02A */
245 	{ 0xA1, 0xE5, 0x00, 4, 0x40, 2, 1024, 0x4C, 19, 0x1, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status1 },
246 	/* FM25LS01 */
247 	{ 0xA1, 0xA5, 0x00, 4, 0x40, 1, 1024, 0x4C, 18, 0x1, 0, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status1 },
248 	/* FM25S01BI3 */
249 	{ 0xA1, 0xD4, 0x00, 4, 0x40, 1, 1024, 0x4C, 18, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status6 },
250 	/* FM25G02BI3 */
251 	{ 0xA1, 0xD2, 0x00, 4, 0x40, 1, 2048, 0x4C, 19, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status6 },
252 	/* FM25S02BI3-DND-A-G3 */
253 	{ 0xA1, 0xD6, 0x00, 4, 0x40, 1, 1024, 0x4C, 18, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status6 },
254 	/* FM25G02D */
255 	{ 0xA1, 0xF2, 0x00, 4, 0x40, 1, 2048, 0x4C, 19, 0x4, 1, { 0x04, 0x14, 0xFF, 0xFF }, &sfc_nand_get_ecc_status5 },
256 
257 	/* IS37SML01G1 */
258 	{ 0xC8, 0x21, 0x00, 4, 0x40, 1, 1024, 0x00, 18, 0x1, 0, { 0x08, 0x0C, 0xFF, 0xFF }, &sfc_nand_get_ecc_status1 },
259 	/* F50L1G41LB */
260 	{ 0xC8, 0x01, 0x00, 4, 0x40, 1, 1024, 0x4C, 18, 0x1, 0, { 0x14, 0x24, 0xFF, 0xFF }, &sfc_nand_get_ecc_status1 },
261 	/* F50L2G41KA */
262 	{ 0xC8, 0x41, 0x7F, 4, 0x40, 1, 2048, 0x4C, 19, 0x8, 0, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status6 },
263 
264 	/* UM19A1HISW */
265 	{ 0xB0, 0x24, 0x00, 4, 0x40, 1, 2048, 0x4C, 19, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status6 },
266 	/* UM19A0HCSW */
267 	{ 0xB0, 0x14, 0x00, 4, 0x40, 1, 1024, 0x4C, 18, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status6 },
268 	/* UM19A0LCSW */
269 	{ 0xB0, 0x15, 0x00, 4, 0x40, 1, 1024, 0x4C, 18, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status6 },
270 	/* UM19A1LISW */
271 	{ 0xB0, 0x25, 0x00, 4, 0x40, 1, 2048, 0x4C, 19, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status6 },
272 	/* UM19A9LISW */
273 	{ 0xB0, 0x0D, 0x00, 4, 0x40, 1, 512, 0x4C, 17, 0x4, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status0 },
274 	/* UM19A9HISW */
275 	{ 0xB0, 0x0C, 0x00, 4, 0x40, 1, 512, 0x4C, 17, 0x4, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status0 },
276 
277 	/* ATO25D1GA */
278 	{ 0x9B, 0x12, 0x00, 4, 0x40, 1, 1024, 0x40, 18, 0x1, 1, { 0x14, 0x24, 0xFF, 0xFF }, &sfc_nand_get_ecc_status1 },
279 	/* BWJX08K-2Gb */
280 	{ 0xBC, 0xB3, 0x00, 4, 0x40, 1, 2048, 0x4C, 19, 0x8, 1, { 0x04, 0x10, 0xFF, 0xFF }, &sfc_nand_get_ecc_status0 },
281 	/* JS28U1GQSCAHG-83 */
282 	{ 0xBF, 0x21, 0x00, 4, 0x40, 1, 1024, 0x40, 18, 0x4, 1, { 0x08, 0x0C, 0xFF, 0xFF }, &sfc_nand_get_ecc_status8 },
283 	/* SGM7000I-S24W1GH */
284 	{ 0xEA, 0xC1, 0x00, 4, 0x40, 1, 1024, 0x0C, 18, 0x4, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status1 },
285 	/* TX25G01 */
286 	{ 0xA1, 0xF1, 0x00, 4, 0x40, 1, 1024, 0x0C, 18, 0x4, 1, { 0x04, 0x14, 0xFF, 0xFF }, &sfc_nand_get_ecc_status8 },
287 
288 	/* S35ML01G3, ANV1GCP0CLG, HYF1GQ4UTXCAE, YX25G1E, GSS01GSAM0 */
289 	{ 0x01, 0x15, 0x00, 4, 0x40, 1, 1024, 0x4C, 18, 0x4, 0, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status9 },
290 	/* S35ML02G3, ANV2GCP0CLG, HYF2GQ4UTXCAE, YX25G2E */
291 	{ 0x01, 0x25, 0x00, 4, 0x40, 2, 1024, 0x4C, 19, 0x4, 0, { 0x04, 0x08, 0x0C, 0x10 }, &sfc_nand_get_ecc_status9 },
292 	/* S35ML04G3 */
293 	{ 0x01, 0x35, 0x00, 4, 0x40, 2, 2048, 0x4C, 20, 0x4, 0, { 0x04, 0x08, 0x0C, 0x10 }, &sfc_nand_get_ecc_status9 },
294 
295 	/* GSS01GSAK1 */
296 	{ 0x52, 0xBA, 0x13, 4, 0x40, 1, 1024, 0x4C, 18, 0x4, 0, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status1 },
297 	/* GSS02GSAK1 */
298 	{ 0x52, 0xBA, 0x23, 4, 0x40, 1, 2048, 0x4C, 19, 0x4, 0, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status1 },
299 	/* GSS02GSAX1 */
300 	{ 0x52, 0xCA, 0x23, 4, 0x40, 1, 2048, 0x4C, 19, 0x8, 0, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status1 },
301 	/* GSS01GSAX1 */
302 	{ 0x52, 0xCA, 0x13, 4, 0x40, 1, 1024, 0x4C, 18, 0x8, 0, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status1 },
303 
304 	/* XCSP2AAPK */
305 	{ 0x8C, 0xA1, 0x00, 4, 0x40, 1, 2048, 0x4C, 19, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status0 },
306 	/* XCSP1AAPK */
307 	{ 0x8C, 0x01, 0x00, 4, 0x40, 1, 1024, 0x4C, 18, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status0 },
308 	/* F50L1G41LC */
309 	{ 0x8C, 0x2C, 0x00, 4, 0x40, 1, 2048, 0x4C, 19, 0x1, 0, { 0x04, 0x14, 0xFF, 0xFF }, &sfc_nand_get_ecc_status1 },
310 
311 	/* ZB35Q01BYIG */
312 	{ 0x5E, 0xA1, 0x00, 4, 0x40, 1, 1024, 0x4C, 18, 0x8, 0, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status1 },
313 	/* ZB35Q04BYIG */
314 	{ 0x5E, 0xA3, 0x00, 4, 0x80, 1, 2048, 0x4C, 20, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status1 },
315 
316 	/* HSESYHDSW2G */
317 	{ 0x3C, 0xD2, 0x00, 4, 0x40, 1, 2048, 0x4C, 19, 0x4, 0, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status1 },
318 };
319 
320 static struct nand_info *p_nand_info;
321 static u32 gp_page_buf[SFC_NAND_PAGE_MAX_SIZE / 4];
322 static struct SFNAND_DEV sfc_nand_dev;
323 
324 static struct nand_info *sfc_nand_get_info(u8 *nand_id)
325 {
326 	u32 i;
327 
328 	for (i = 0; i < ARRAY_SIZE(spi_nand_tbl); i++) {
329 		if (spi_nand_tbl[i].id0 == nand_id[0] &&
330 		    spi_nand_tbl[i].id1 == nand_id[1]) {
331 			if (spi_nand_tbl[i].id2 &&
332 			    spi_nand_tbl[i].id2 != nand_id[2])
333 				continue;
334 
335 			return &spi_nand_tbl[i];
336 		}
337 	}
338 
339 	return NULL;
340 }
341 
342 static int sfc_nand_write_en(void)
343 {
344 	int ret;
345 	struct rk_sfc_op op;
346 
347 	op.sfcmd.d32 = 0;
348 	op.sfcmd.b.cmd = CMD_WRITE_EN;
349 
350 	op.sfctrl.d32 = 0;
351 
352 	ret = sfc_request(&op, 0, NULL, 0);
353 	return ret;
354 }
355 
356 static int sfc_nand_rw_preset(void)
357 {
358 	int ret;
359 	struct rk_sfc_op op;
360 
361 	op.sfcmd.d32 = 0;
362 	op.sfcmd.b.cmd = 0xff;
363 	op.sfcmd.b.cs = 2;
364 
365 	op.sfctrl.d32 = 0;
366 	op.sfctrl.b.datalines = 2;
367 	op.sfctrl.b.cmdlines = 2;
368 	op.sfctrl.b.addrlines = 2;
369 
370 	ret = sfc_request(&op, 0, NULL, 0);
371 	return ret;
372 }
373 
374 static int sfc_nand_read_feature(u8 addr, u8 *data)
375 {
376 	int ret;
377 	struct rk_sfc_op op;
378 
379 	op.sfcmd.d32 = 0;
380 	op.sfcmd.b.cmd = 0x0F;
381 	op.sfcmd.b.addrbits = SFC_ADDR_XBITS;
382 
383 	op.sfctrl.d32 = 0;
384 	op.sfctrl.b.addrbits = 8;
385 
386 	*data = 0;
387 
388 	ret = sfc_request(&op, addr, data, 1);
389 
390 	if (ret != SFC_OK)
391 		return ret;
392 
393 	return SFC_OK;
394 }
395 
396 static int sfc_nand_write_feature(u32 addr, u8 status)
397 {
398 	int ret;
399 	struct rk_sfc_op op;
400 
401 	sfc_nand_write_en();
402 
403 	op.sfcmd.d32 = 0;
404 	op.sfcmd.b.cmd = 0x1F;
405 	op.sfcmd.b.addrbits = SFC_ADDR_XBITS;
406 	op.sfcmd.b.rw = SFC_WRITE;
407 
408 	op.sfctrl.d32 = 0;
409 	op.sfctrl.b.addrbits = 8;
410 
411 	ret = sfc_request(&op, addr, &status, 1);
412 
413 	if (ret != SFC_OK)
414 		return ret;
415 
416 	return ret;
417 }
418 
419 static int sfc_nand_wait_busy(u8 *data, int timeout)
420 {
421 	int ret;
422 	int i;
423 	u8 status;
424 
425 	*data = 0;
426 
427 	for (i = 0; i < timeout; i++) {
428 		ret = sfc_nand_read_feature(0xC0, &status);
429 
430 		if (ret != SFC_OK)
431 			return ret;
432 
433 		*data = status;
434 
435 		if (!(status & (1 << 0)))
436 			return SFC_OK;
437 
438 		sfc_delay(1);
439 	}
440 
441 	return SFC_NAND_WAIT_TIME_OUT;
442 }
443 
444 /*
445  * ecc default:
446  * ecc bits: 0xC0[4,5]
447  * 0b00, No bit errors were detected
448  * 0b01, Bit errors were detected and corrected.
449  * 0b10, Multiple bit errors were detected and not corrected.
450  * 0b11, Bits errors were detected and corrected, bit error count
451  *	reach the bit flip detection threshold
452  */
453 static u32 sfc_nand_get_ecc_status0(void)
454 {
455 	u32 ret;
456 	u32 i;
457 	u8 ecc;
458 	u8 status;
459 	u32 timeout = 1000 * 1000;
460 
461 	for (i = 0; i < timeout; i++) {
462 		ret = sfc_nand_read_feature(0xC0, &status);
463 
464 		if (ret != SFC_OK)
465 			return SFC_NAND_ECC_ERROR;
466 
467 		if (!(status & (1 << 0)))
468 			break;
469 
470 		sfc_delay(1);
471 	}
472 
473 	ecc = (status >> 4) & 0x03;
474 
475 	if (ecc <= 1)
476 		ret = SFC_NAND_ECC_OK;
477 	else if (ecc == 2)
478 		ret = (u32)SFC_NAND_ECC_ERROR;
479 	else
480 		ret = SFC_NAND_ECC_REFRESH;
481 
482 	return ret;
483 }
484 
485 /*
486  * ecc spectial type1:
487  * ecc bits: 0xC0[4,5]
488  * 0b00, No bit errors were detected;
489  * 0b01, Bits errors were detected and corrected, bit error count
490  *	may reach the bit flip detection threshold;
491  * 0b10, Multiple bit errors were detected and not corrected;
492  * 0b11, Reserved.
493  */
494 static u32 sfc_nand_get_ecc_status1(void)
495 {
496 	u32 ret;
497 	u32 i;
498 	u8 ecc;
499 	u8 status;
500 	u32 timeout = 1000 * 1000;
501 
502 	for (i = 0; i < timeout; i++) {
503 		ret = sfc_nand_read_feature(0xC0, &status);
504 
505 		if (ret != SFC_OK)
506 			return SFC_NAND_ECC_ERROR;
507 
508 		if (!(status & (1 << 0)))
509 			break;
510 
511 		sfc_delay(1);
512 	}
513 
514 	ecc = (status >> 4) & 0x03;
515 
516 	if (ecc == 0)
517 		ret = SFC_NAND_ECC_OK;
518 	else if (ecc == 1)
519 		ret = SFC_NAND_ECC_REFRESH;
520 	else
521 		ret = (u32)SFC_NAND_ECC_ERROR;
522 
523 	return ret;
524 }
525 
526 /*
527  * ecc spectial type2:
528  * ecc bits: 0xC0[4,5] 0xF0[4,5]
529  * [0b0000, 0b0011], No bit errors were detected;
530  * [0b0100, 0b0111], Bit errors were detected and corrected. Not
531  *	reach Flipping Bits;
532  * [0b1000, 0b1011], Multiple bit errors were detected and
533  *	not corrected.
534  * [0b1100, 0b1111], reserved.
535  */
536 static u32 sfc_nand_get_ecc_status2(void)
537 {
538 	u32 ret;
539 	u32 i;
540 	u8 ecc;
541 	u8 status, status1;
542 	u32 timeout = 1000 * 1000;
543 
544 	for (i = 0; i < timeout; i++) {
545 		ret = sfc_nand_read_feature(0xC0, &status);
546 
547 		if (ret != SFC_OK)
548 			return SFC_NAND_ECC_ERROR;
549 
550 		ret = sfc_nand_read_feature(0xF0, &status1);
551 
552 		if (ret != SFC_OK)
553 			return SFC_NAND_ECC_ERROR;
554 
555 		if (!(status & (1 << 0)))
556 			break;
557 
558 		sfc_delay(1);
559 	}
560 
561 	ecc = (status >> 4) & 0x03;
562 	ecc = (ecc << 2) | ((status1 >> 4) & 0x03);
563 
564 	if (ecc < 7)
565 		ret = SFC_NAND_ECC_OK;
566 	else if (ecc == 7)
567 		ret = SFC_NAND_ECC_REFRESH;
568 	else
569 		ret = (u32)SFC_NAND_ECC_ERROR;
570 
571 	return ret;
572 }
573 
574 /*
575  * ecc spectial type3:
576  * ecc bits: 0xC0[4,5] 0xF0[4,5]
577  * [0b0000, 0b0011], No bit errors were detected;
578  * [0b0100, 0b0111], Bit errors were detected and corrected. Not
579  *	reach Flipping Bits;
580  * [0b1000, 0b1011], Multiple bit errors were detected and
581  *	not corrected.
582  * [0b1100, 0b1111], Bit error count equals the bit flip
583  *	detectio nthreshold
584  */
585 static u32 sfc_nand_get_ecc_status3(void)
586 {
587 	u32 ret;
588 	u32 i;
589 	u8 ecc;
590 	u8 status, status1;
591 	u32 timeout = 1000 * 1000;
592 
593 	for (i = 0; i < timeout; i++) {
594 		ret = sfc_nand_read_feature(0xC0, &status);
595 
596 		if (ret != SFC_OK)
597 			return SFC_NAND_ECC_ERROR;
598 
599 		ret = sfc_nand_read_feature(0xF0, &status1);
600 
601 		if (ret != SFC_OK)
602 			return SFC_NAND_ECC_ERROR;
603 
604 		if (!(status & (1 << 0)))
605 			break;
606 
607 		sfc_delay(1);
608 	}
609 
610 	ecc = (status >> 4) & 0x03;
611 	ecc = (ecc << 2) | ((status1 >> 4) & 0x03);
612 
613 	if (ecc < 7)
614 		ret = SFC_NAND_ECC_OK;
615 	else if (ecc == 7 || ecc >= 12)
616 		ret = SFC_NAND_ECC_REFRESH;
617 	else
618 		ret = (u32)SFC_NAND_ECC_ERROR;
619 
620 	return ret;
621 }
622 
623 /*
624  * ecc spectial type4:
625  * ecc bits: 0xC0[2,5]
626  * [0b0000], No bit errors were detected;
627  * [0b0001, 0b0111], Bit errors were detected and corrected. Not
628  *	reach Flipping Bits;
629  * [0b1000], Multiple bit errors were detected and
630  *	not corrected.
631  * [0b1100], Bit error count equals the bit flip
632  *	detection threshold
633  * else, reserved
634  */
635 static u32 sfc_nand_get_ecc_status4(void)
636 {
637 	u32 ret;
638 	u32 i;
639 	u8 ecc;
640 	u8 status;
641 	u32 timeout = 1000 * 1000;
642 
643 	for (i = 0; i < timeout; i++) {
644 		ret = sfc_nand_read_feature(0xC0, &status);
645 
646 		if (ret != SFC_OK)
647 			return SFC_NAND_ECC_ERROR;
648 
649 		if (!(status & (1 << 0)))
650 			break;
651 
652 		sfc_delay(1);
653 	}
654 
655 	ecc = (status >> 2) & 0x0f;
656 
657 	if (ecc < 7)
658 		ret = SFC_NAND_ECC_OK;
659 	else if (ecc == 7 || ecc == 12)
660 		ret = SFC_NAND_ECC_REFRESH;
661 	else
662 		ret = (u32)SFC_NAND_ECC_ERROR;
663 
664 	return ret;
665 }
666 
667 /*
668  * ecc spectial type5:
669  * ecc bits: 0xC0[4,6]
670  * [0b000], No bit errors were detected;
671  * [0b001, 0b011], Bit errors were detected and corrected. Not
672  *	reach Flipping Bits;
673  * [0b100], Bit error count equals the bit flip
674  *	detection threshold
675  * [0b101, 0b110], Reserved;
676  * [0b111], Multiple bit errors were detected and
677  *	not corrected.
678  */
679 static u32 sfc_nand_get_ecc_status5(void)
680 {
681 	u32 ret;
682 	u32 i;
683 	u8 ecc;
684 	u8 status;
685 	u32 timeout = 1000 * 1000;
686 
687 	for (i = 0; i < timeout; i++) {
688 		ret = sfc_nand_read_feature(0xC0, &status);
689 
690 		if (ret != SFC_OK)
691 			return SFC_NAND_ECC_ERROR;
692 
693 		if (!(status & (1 << 0)))
694 			break;
695 
696 		sfc_delay(1);
697 	}
698 
699 	ecc = (status >> 4) & 0x07;
700 
701 	if (ecc < 4)
702 		ret = SFC_NAND_ECC_OK;
703 	else if (ecc == 4)
704 		ret = SFC_NAND_ECC_REFRESH;
705 	else
706 		ret = (u32)SFC_NAND_ECC_ERROR;
707 
708 	return ret;
709 }
710 
711 /*
712  * ecc spectial type6:
713  * ecc bits: 0xC0[4,6]
714  * [0b000], No bit errors were detected;
715  * [0b001], 1-3 Bit errors were detected and corrected. Not
716  *	reach Flipping Bits;
717  * [0b010], Multiple bit errors were detected and
718  *	not corrected.
719  * [0b011], 4-6 Bit errors were detected and corrected. Not
720  *	reach Flipping Bits;
721  * [0b101], Bit error count equals the bit flip
722  *	detectionthreshold
723  * others, Reserved.
724  */
725 static u32 sfc_nand_get_ecc_status6(void)
726 {
727 	u32 ret;
728 	u32 i;
729 	u8 ecc;
730 	u8 status;
731 	u32 timeout = 1000 * 1000;
732 
733 	for (i = 0; i < timeout; i++) {
734 		ret = sfc_nand_read_feature(0xC0, &status);
735 
736 		if (ret != SFC_OK)
737 			return SFC_NAND_ECC_ERROR;
738 
739 		if (!(status & (1 << 0)))
740 			break;
741 
742 		sfc_delay(1);
743 	}
744 
745 	ecc = (status >> 4) & 0x07;
746 
747 	if (ecc == 0 || ecc == 1 || ecc == 3)
748 		ret = SFC_NAND_ECC_OK;
749 	else if (ecc == 5)
750 		ret = SFC_NAND_ECC_REFRESH;
751 	else
752 		ret = (u32)SFC_NAND_ECC_ERROR;
753 
754 	return ret;
755 }
756 
757 /*
758  * ecc spectial type7:
759  * ecc bits: 0xC0[4,7]
760  * [0b0000], No bit errors were detected;
761  * [0b0001, 0b0111], 1-7 Bit errors were detected and corrected. Not
762  *	reach Flipping Bits;
763  * [0b1000], 8 Bit errors were detected and corrected. Bit error count
764  * 	equals the bit flip detectionthreshold;
765  * [0b1111], Bit errors greater than ECC capability(8 bits) and not corrected;
766  * others, Reserved.
767  */
768 static u32 sfc_nand_get_ecc_status7(void)
769 {
770 	u32 ret;
771 	u32 i;
772 	u8 ecc;
773 	u8 status;
774 	u32 timeout = 1000 * 1000;
775 
776 	for (i = 0; i < timeout; i++) {
777 		ret = sfc_nand_read_feature(0xC0, &status);
778 
779 		if (ret != SFC_OK)
780 			return SFC_NAND_ECC_ERROR;
781 
782 		if (!(status & (1 << 0)))
783 			break;
784 
785 		sfc_delay(1);
786 	}
787 
788 	ecc = (status >> 4) & 0xf;
789 
790 	if (ecc < 7)
791 		ret = SFC_NAND_ECC_OK;
792 	else if (ecc == 7 || ecc == 8)
793 		ret = SFC_NAND_ECC_REFRESH;
794 	else
795 		ret = (u32)SFC_NAND_ECC_ERROR;
796 
797 	return ret;
798 }
799 
800 /*
801  * ecc spectial type8:
802  * ecc bits: 0xC0[4,6]
803  * [0b000], No bit errors were detected;
804  * [0b001, 0b011], 1~3 Bit errors were detected and corrected. Not
805  *	reach Flipping Bits;
806  * [0b100], Bit error count equals the bit flip
807  *	detection threshold
808  * others, Reserved.
809  */
810 static u32 sfc_nand_get_ecc_status8(void)
811 {
812 	u32 ret;
813 	u32 i;
814 	u8 ecc;
815 	u8 status;
816 	u32 timeout = 1000 * 1000;
817 
818 	for (i = 0; i < timeout; i++) {
819 		ret = sfc_nand_read_feature(0xC0, &status);
820 
821 		if (ret != SFC_OK)
822 			return SFC_NAND_ECC_ERROR;
823 
824 		if (!(status & (1 << 0)))
825 			break;
826 
827 		sfc_delay(1);
828 	}
829 
830 	ecc = (status >> 4) & 0x07;
831 
832 	if (ecc < 4)
833 		ret = SFC_NAND_ECC_OK;
834 	else if (ecc == 4)
835 		ret = SFC_NAND_ECC_REFRESH;
836 	else
837 		ret = (u32)SFC_NAND_ECC_ERROR;
838 
839 	return ret;
840 }
841 
842 /*
843  * ecc spectial type9:
844  * ecc bits: 0xC0[4,5]
845  * 0b00, No bit errors were detected
846  * 0b01, 1-2Bit errors were detected and corrected.
847  * 0b10, 3-4Bit errors were detected and corrected.
848  * 0b11, 11 can be used as uncorrectable
849  */
850 static u32 sfc_nand_get_ecc_status9(void)
851 {
852 	u32 ret;
853 	u32 i;
854 	u8 ecc;
855 	u8 status;
856 	u32 timeout = 1000 * 1000;
857 
858 	for (i = 0; i < timeout; i++) {
859 		ret = sfc_nand_read_feature(0xC0, &status);
860 
861 		if (ret != SFC_OK)
862 			return SFC_NAND_ECC_ERROR;
863 
864 		if (!(status & (1 << 0)))
865 			break;
866 
867 		sfc_delay(1);
868 	}
869 
870 	ecc = (status >> 4) & 0x03;
871 
872 	if (ecc <= 1)
873 		ret = SFC_NAND_ECC_OK;
874 	else if (ecc == 2)
875 		ret = SFC_NAND_ECC_REFRESH;
876 	else
877 		ret = (u32)SFC_NAND_ECC_ERROR;
878 
879 	return ret;
880 }
881 
882 /*
883  * ecc spectial type8:
884  * ecc bits: 0xC0[4,6]
885  * [0b000], No bit errors were detected;
886  * [0b001, 0b101], 3~7 Bit errors were detected and corrected. Not
887  *	reach Flipping Bits;
888  * [0b110], Bit error count equals the bit flip detection threshold
889  * [0b111], Bit errors greater than ECC capability(8 bits) and not corrected;
890  */
891 static u32 sfc_nand_get_ecc_status10(void)
892 {
893 	u32 ret;
894 	u32 i;
895 	u8 ecc;
896 	u8 status;
897 	u32 timeout = 1000 * 1000;
898 
899 	for (i = 0; i < timeout; i++) {
900 		ret = sfc_nand_read_feature(0xC0, &status);
901 
902 		if (ret != SFC_OK)
903 			return SFC_NAND_ECC_ERROR;
904 
905 		if (!(status & (1 << 0)))
906 			break;
907 
908 		sfc_delay(1);
909 	}
910 
911 	ecc = (status >> 4) & 0x07;
912 
913 	if (ecc < 6)
914 		ret = SFC_NAND_ECC_OK;
915 	else if (ecc == 6)
916 		ret = SFC_NAND_ECC_REFRESH;
917 	else
918 		ret = (u32)SFC_NAND_ECC_ERROR;
919 
920 	return ret;
921 }
922 
923 u32 sfc_nand_erase_block(u8 cs, u32 addr)
924 {
925 	int ret;
926 	struct rk_sfc_op op;
927 	u8 status;
928 
929 	rkflash_print_dio("%s %x\n", __func__, addr);
930 	op.sfcmd.d32 = 0;
931 	op.sfcmd.b.cmd = 0xd8;
932 	op.sfcmd.b.addrbits = SFC_ADDR_24BITS;
933 	op.sfcmd.b.rw = SFC_WRITE;
934 
935 	op.sfctrl.d32 = 0;
936 
937 	sfc_nand_write_en();
938 	ret = sfc_request(&op, addr, NULL, 0);
939 
940 	if (ret != SFC_OK)
941 		return ret;
942 
943 	ret = sfc_nand_wait_busy(&status, 1000 * 1000);
944 
945 	if (status & (1 << 2))
946 		return SFC_NAND_PROG_ERASE_ERROR;
947 
948 	return ret;
949 }
950 
951 static u32 sfc_nand_read_cache(u32 row, u32 *p_page_buf, u32 column, u32 len)
952 {
953 	int ret;
954 	u32 plane;
955 	struct rk_sfc_op op;
956 
957 	op.sfcmd.d32 = 0;
958 	op.sfcmd.b.cmd = sfc_nand_dev.page_read_cmd;
959 	op.sfcmd.b.addrbits = SFC_ADDR_XBITS;
960 	op.sfcmd.b.dummybits = 8;
961 
962 	op.sfctrl.d32 = 0;
963 	op.sfctrl.b.datalines = sfc_nand_dev.read_lines;
964 	op.sfctrl.b.addrbits = 16;
965 
966 	plane = p_nand_info->plane_per_die == 2 ? ((row >> 6) & 0x1) << 12 : 0;
967 
968 	ret = sfc_request(&op, plane | column, p_page_buf, len);
969 	if (ret != SFC_OK)
970 		return SFC_NAND_HW_ERROR;
971 
972 	return ret;
973 }
974 
975 u32 sfc_nand_prog_page_raw(u8 cs, u32 addr, u32 *p_page_buf)
976 {
977 	int ret;
978 	u32 plane;
979 	struct rk_sfc_op op;
980 	u8 status;
981 	u32 page_size = SFC_NAND_SECTOR_FULL_SIZE * p_nand_info->sec_per_page;
982 	u32 data_area_size = SFC_NAND_SECTOR_SIZE * p_nand_info->sec_per_page;
983 
984 	rkflash_print_dio("%s %x %x\n", __func__, addr, p_page_buf[0]);
985 	sfc_nand_write_en();
986 
987 	if (sfc_nand_dev.prog_lines == DATA_LINES_X4 &&
988 	    p_nand_info->feature & FEA_SOFT_QOP_BIT &&
989 	    sfc_get_version() < SFC_VER_3)
990 		sfc_nand_rw_preset();
991 
992 	op.sfcmd.d32 = 0;
993 	op.sfcmd.b.cmd = sfc_nand_dev.page_prog_cmd;
994 	op.sfcmd.b.addrbits = SFC_ADDR_XBITS;
995 	op.sfcmd.b.rw = SFC_WRITE;
996 
997 	op.sfctrl.d32 = 0;
998 	op.sfctrl.b.datalines = sfc_nand_dev.prog_lines;
999 	op.sfctrl.b.addrbits = 16;
1000 	plane = p_nand_info->plane_per_die == 2 ? ((addr >> 6) & 0x1) << 12 : 0;
1001 	sfc_request(&op, plane, p_page_buf, page_size);
1002 
1003 	/*
1004 	 * At the moment of power lost or dev running in harsh environment, flash
1005 	 * maybe work in a unkonw state and result in bit flip, when this situation
1006 	 * is detected by cache recheck, it's better to wait a second for a reliable
1007 	 * hardware environment to avoid abnormal data written to flash array.
1008 	 */
1009 	if (p_nand_info->id0 == MID_GIGADEV) {
1010 		sfc_nand_read_cache(addr, (u32 *)sfc_nand_dev.recheck_buffer, 0, data_area_size);
1011 		if (memcmp(sfc_nand_dev.recheck_buffer, p_page_buf, data_area_size)) {
1012 			rkflash_print_error("%s %x cache bitflip\n", __func__, addr);
1013 			mdelay(1000);
1014 			sfc_request(&op, plane, p_page_buf, page_size);
1015 		}
1016 	}
1017 
1018 	op.sfcmd.d32 = 0;
1019 	op.sfcmd.b.cmd = 0x10;
1020 	op.sfcmd.b.addrbits = SFC_ADDR_24BITS;
1021 	op.sfcmd.b.rw = SFC_WRITE;
1022 
1023 	op.sfctrl.d32 = 0;
1024 	ret = sfc_request(&op, addr, p_page_buf, 0);
1025 
1026 	if (ret != SFC_OK)
1027 		return ret;
1028 
1029 	ret = sfc_nand_wait_busy(&status, 1000 * 1000);
1030 	if (status & (1 << 3))
1031 		return SFC_NAND_PROG_ERASE_ERROR;
1032 
1033 	return ret;
1034 }
1035 
1036 u32 sfc_nand_prog_page(u8 cs, u32 addr, u32 *p_data, u32 *p_spare)
1037 {
1038 	int ret;
1039 	u32 sec_per_page = p_nand_info->sec_per_page;
1040 	u32 data_size = sec_per_page * SFC_NAND_SECTOR_SIZE;
1041 	struct nand_mega_area *meta = &p_nand_info->meta;
1042 
1043 	memcpy(gp_page_buf, p_data, data_size);
1044 	memset(&gp_page_buf[data_size / 4], 0xff, sec_per_page * 16);
1045 	gp_page_buf[(data_size + meta->off0) / 4] = p_spare[0];
1046 	gp_page_buf[(data_size + meta->off1) / 4] = p_spare[1];
1047 
1048 	if (sec_per_page == 8) {
1049 		gp_page_buf[(data_size + meta->off2) / 4] = p_spare[2];
1050 		gp_page_buf[(data_size + meta->off3) / 4] = p_spare[3];
1051 	}
1052 
1053 	ret = sfc_nand_prog_page_raw(cs, addr, gp_page_buf);
1054 
1055 	return ret;
1056 }
1057 
1058 u32 sfc_nand_read(u32 row, u32 *p_page_buf, u32 column, u32 len)
1059 {
1060 	int ret;
1061 	u32 plane;
1062 	struct rk_sfc_op op;
1063 	u32 ecc_result;
1064 	u8 status;
1065 
1066 	op.sfcmd.d32 = 0;
1067 	op.sfcmd.b.cmd = 0x13;
1068 	op.sfcmd.b.rw = SFC_WRITE;
1069 	op.sfcmd.b.addrbits = SFC_ADDR_24BITS;
1070 
1071 	op.sfctrl.d32 = 0;
1072 
1073 	sfc_request(&op, row, p_page_buf, 0);
1074 
1075 	if (sfc_nand_dev.read_lines == DATA_LINES_X4 &&
1076 	    p_nand_info->feature & FEA_SOFT_QOP_BIT &&
1077 	    sfc_get_version() < SFC_VER_3)
1078 		sfc_nand_rw_preset();
1079 
1080 	sfc_nand_wait_busy(&status, 1000 * 1000);
1081 	if (sfc_nand_dev.manufacturer == 0x01 && status)
1082 		sfc_nand_wait_busy(&status, 1000 * 1000);
1083 
1084 	ecc_result = p_nand_info->ecc_status();
1085 
1086 	op.sfcmd.d32 = 0;
1087 	op.sfcmd.b.cmd = sfc_nand_dev.page_read_cmd;
1088 	op.sfcmd.b.addrbits = SFC_ADDR_XBITS;
1089 	op.sfcmd.b.dummybits = 8;
1090 
1091 	op.sfctrl.d32 = 0;
1092 	op.sfctrl.b.datalines = sfc_nand_dev.read_lines;
1093 	op.sfctrl.b.addrbits = 16;
1094 
1095 	plane = p_nand_info->plane_per_die == 2 ? ((row >> 6) & 0x1) << 12 : 0;
1096 	ret = sfc_request(&op, plane | column, p_page_buf, len);
1097 	rkflash_print_dio("%s %x %x\n", __func__, row, p_page_buf[0]);
1098 
1099 	if (ret != SFC_OK)
1100 		return SFC_NAND_HW_ERROR;
1101 
1102 	return ecc_result;
1103 }
1104 
1105 u32 sfc_nand_read_page_raw(u8 cs, u32 addr, u32 *p_page_buf)
1106 {
1107 	u32 page_size = SFC_NAND_SECTOR_FULL_SIZE * p_nand_info->sec_per_page;
1108 
1109 	return sfc_nand_read(addr, p_page_buf, 0, page_size);
1110 }
1111 
1112 u32 sfc_nand_read_page(u8 cs, u32 addr, u32 *p_data, u32 *p_spare)
1113 {
1114 	u32 ret;
1115 	u32 sec_per_page = p_nand_info->sec_per_page;
1116 	u32 data_size = sec_per_page * SFC_NAND_SECTOR_SIZE;
1117 	struct nand_mega_area *meta = &p_nand_info->meta;
1118 
1119 	ret = sfc_nand_read_page_raw(cs, addr, gp_page_buf);
1120 	memcpy(p_data, gp_page_buf, data_size);
1121 	p_spare[0] = gp_page_buf[(data_size + meta->off0) / 4];
1122 	p_spare[1] = gp_page_buf[(data_size + meta->off1) / 4];
1123 
1124 	if (p_nand_info->sec_per_page == 8) {
1125 		p_spare[2] = gp_page_buf[(data_size + meta->off2) / 4];
1126 		p_spare[3] = gp_page_buf[(data_size + meta->off3) / 4];
1127 	}
1128 
1129 	if (ret == SFC_NAND_HW_ERROR)
1130 		ret = SFC_NAND_ECC_ERROR;
1131 
1132 	if (ret != SFC_NAND_ECC_OK) {
1133 		rkflash_print_error("%s[0x%x], ret=0x%x\n", __func__, addr, ret);
1134 
1135 		if (p_data)
1136 			rkflash_print_hex("data:", p_data, 4, 8);
1137 
1138 		if (p_spare)
1139 			rkflash_print_hex("spare:", p_spare, 4, 2);
1140 	}
1141 
1142 	return ret;
1143 }
1144 
1145 u32 sfc_nand_check_bad_block(u8 cs, u32 addr)
1146 {
1147 	u32 ret;
1148 	u32 data_size = p_nand_info->sec_per_page * SFC_NAND_SECTOR_SIZE;
1149 	u32 marker = 0;
1150 
1151 	ret = sfc_nand_read(addr, &marker, data_size, 2);
1152 
1153 	/* unify with mtd framework */
1154 	if (ret == SFC_NAND_ECC_ERROR || (u16)marker != 0xffff)
1155 		rkflash_print_error("%s page= %x ret= %x spare= %x\n",
1156 				    __func__, addr, ret, marker);
1157 
1158 	/* Original bad block */
1159 	if ((u16)marker != 0xffff)
1160 		return true;
1161 
1162 	return false;
1163 }
1164 
1165 u32 sfc_nand_mark_bad_block(u8 cs, u32 addr)
1166 {
1167 	u32 ret;
1168 	u32 data_size = p_nand_info->sec_per_page * SFC_NAND_SECTOR_SIZE;
1169 
1170 	ret = sfc_nand_read_page_raw(cs, addr, gp_page_buf);
1171 
1172 	if (ret)
1173 		return SFC_NAND_HW_ERROR;
1174 
1175 	gp_page_buf[data_size / 4] = 0x0;
1176 	ret = sfc_nand_prog_page_raw(cs, addr, gp_page_buf);
1177 
1178 	if (ret)
1179 		return SFC_NAND_HW_ERROR;
1180 
1181 	return ret;
1182 }
1183 
1184 int sfc_nand_read_id(u8 *data)
1185 {
1186 	int ret;
1187 	struct rk_sfc_op op;
1188 
1189 	op.sfcmd.d32 = 0;
1190 	op.sfcmd.b.cmd = CMD_READ_JEDECID;
1191 	op.sfcmd.b.addrbits = SFC_ADDR_XBITS;
1192 
1193 	op.sfctrl.d32 = 0;
1194 	op.sfctrl.b.addrbits = 8;
1195 
1196 	ret = sfc_request(&op, 0, data, 3);
1197 
1198 	return ret;
1199 }
1200 
1201 /*
1202  * Read the 1st page's 1st byte of a phy_blk
1203  * If not FF, it's bad blk
1204  */
1205 static int sfc_nand_get_bad_block_list(u16 *table, u32 die)
1206 {
1207 	u32 bad_cnt, page;
1208 	u32 blk_per_die;
1209 	u16 blk;
1210 
1211 	rkflash_print_info("%s\n", __func__);
1212 
1213 	bad_cnt = 0;
1214 	blk_per_die = p_nand_info->plane_per_die *
1215 		      p_nand_info->blk_per_plane;
1216 
1217 	for (blk = 0; blk < blk_per_die; blk++) {
1218 		page = (blk + blk_per_die * die) *
1219 		       p_nand_info->page_per_blk;
1220 
1221 		if (sfc_nand_check_bad_block(die, page)) {
1222 			table[bad_cnt++] = blk;
1223 			rkflash_print_error("die[%d], bad_blk[%d]\n", die, blk);
1224 		}
1225 	}
1226 
1227 	return (int)bad_cnt;
1228 }
1229 
1230 void sfc_nand_ftl_ops_init(void)
1231 {
1232 	/* para init */
1233 	g_nand_phy_info.nand_type	= 1;
1234 	g_nand_phy_info.die_num		= 1;
1235 	g_nand_phy_info.plane_per_die	= p_nand_info->plane_per_die;
1236 	g_nand_phy_info.blk_per_plane	= p_nand_info->blk_per_plane;
1237 	g_nand_phy_info.page_per_blk	= p_nand_info->page_per_blk;
1238 	g_nand_phy_info.page_per_slc_blk = p_nand_info->page_per_blk;
1239 	g_nand_phy_info.byte_per_sec	= SFC_NAND_SECTOR_SIZE;
1240 	g_nand_phy_info.sec_per_page	= p_nand_info->sec_per_page;
1241 	g_nand_phy_info.sec_per_blk	= p_nand_info->sec_per_page *
1242 					  p_nand_info->page_per_blk;
1243 	g_nand_phy_info.reserved_blk	= 8;
1244 	g_nand_phy_info.blk_per_die	= p_nand_info->plane_per_die *
1245 					  p_nand_info->blk_per_plane;
1246 	g_nand_phy_info.ecc_bits	= p_nand_info->max_ecc_bits;
1247 
1248 	/* driver register */
1249 	g_nand_ops.get_bad_blk_list	= sfc_nand_get_bad_block_list;
1250 	g_nand_ops.erase_blk		= sfc_nand_erase_block;
1251 	g_nand_ops.prog_page		= sfc_nand_prog_page;
1252 	g_nand_ops.read_page		= sfc_nand_read_page;
1253 	g_nand_ops.bch_sel		= NULL;
1254 }
1255 
1256 static int sfc_nand_enable_QE(void)
1257 {
1258 	int ret = SFC_OK;
1259 	u8 status;
1260 
1261 	ret = sfc_nand_read_feature(0xB0, &status);
1262 
1263 	if (ret != SFC_OK)
1264 		return ret;
1265 
1266 	if (status & 1)   /* is QE bit set */
1267 		return SFC_OK;
1268 
1269 	status |= 1;
1270 
1271 	return sfc_nand_write_feature(0xB0, status);
1272 }
1273 
1274 u32 sfc_nand_init(void)
1275 {
1276 	u8 status, id_byte[8];
1277 
1278 	sfc_nand_read_id(id_byte);
1279 	rkflash_print_error("sfc_nand id: %x %x %x\n",
1280 			    id_byte[0], id_byte[1], id_byte[2]);
1281 
1282 	if (id_byte[0] == 0xFF || id_byte[0] == 0x00)
1283 		return (u32)FTL_NO_FLASH;
1284 
1285 	p_nand_info = sfc_nand_get_info(id_byte);
1286 
1287 	if (!p_nand_info) {
1288 		pr_err("The device not support yet!\n");
1289 
1290 		return (u32)FTL_UNSUPPORTED_FLASH;
1291 	}
1292 
1293 	sfc_nand_dev.manufacturer = id_byte[0];
1294 	sfc_nand_dev.mem_type = id_byte[1];
1295 	sfc_nand_dev.capacity = p_nand_info->density;
1296 	sfc_nand_dev.block_size = p_nand_info->page_per_blk * p_nand_info->sec_per_page;
1297 	sfc_nand_dev.page_size = p_nand_info->sec_per_page;
1298 
1299 	/* disable block lock */
1300 	sfc_nand_write_feature(0xA0, 0);
1301 	sfc_nand_dev.read_lines = DATA_LINES_X1;
1302 	sfc_nand_dev.prog_lines = DATA_LINES_X1;
1303 	sfc_nand_dev.page_read_cmd = 0x03;
1304 	sfc_nand_dev.page_prog_cmd = 0x02;
1305 	sfc_nand_dev.recheck_buffer = ftl_malloc(SFC_NAND_PAGE_MAX_SIZE);
1306 	if (!sfc_nand_dev.recheck_buffer) {
1307 		rkflash_print_error("%s recheck_buffer alloc failed\n", __func__);
1308 		return -1;
1309 	}
1310 
1311 	if (p_nand_info->feature & FEA_4BIT_READ) {
1312 		if ((p_nand_info->has_qe_bits && sfc_nand_enable_QE() == SFC_OK) ||
1313 		    !p_nand_info->has_qe_bits) {
1314 			sfc_nand_dev.read_lines = DATA_LINES_X4;
1315 			sfc_nand_dev.page_read_cmd = 0x6b;
1316 		}
1317 	}
1318 
1319 	if (p_nand_info->feature & FEA_4BIT_PROG &&
1320 	    sfc_nand_dev.read_lines == DATA_LINES_X4) {
1321 		sfc_nand_dev.prog_lines = DATA_LINES_X4;
1322 		sfc_nand_dev.page_prog_cmd = 0x32;
1323 	}
1324 
1325 	sfc_nand_read_feature(0xA0, &status);
1326 	rkflash_print_info("sfc_nand A0 = 0x%x\n", status);
1327 	sfc_nand_read_feature(0xB0, &status);
1328 	rkflash_print_info("sfc_nand B0 = 0x%x\n", status);
1329 	rkflash_print_info("read_lines = %x\n", sfc_nand_dev.read_lines);
1330 	rkflash_print_info("prog_lines = %x\n", sfc_nand_dev.prog_lines);
1331 	rkflash_print_info("page_read_cmd = %x\n", sfc_nand_dev.page_read_cmd);
1332 	rkflash_print_info("page_prog_cmd = %x\n", sfc_nand_dev.page_prog_cmd);
1333 
1334 	return SFC_OK;
1335 }
1336 
1337 void sfc_nand_deinit(void)
1338 {
1339 	/* to-do */
1340 	kfree(sfc_nand_dev.recheck_buffer);
1341 }
1342 
1343 struct SFNAND_DEV *sfc_nand_get_private_dev(void)
1344 {
1345 	return &sfc_nand_dev;
1346 }
1347 
1348