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