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