xref: /OK3568_Linux_fs/u-boot/drivers/rkflash/nandc.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/compat.h>
9*4882a593Smuzhiyun #include <linux/delay.h>
10*4882a593Smuzhiyun 
11*4882a593Smuzhiyun #include "flash.h"
12*4882a593Smuzhiyun #include "flash_com.h"
13*4882a593Smuzhiyun #include "nandc.h"
14*4882a593Smuzhiyun #include "rk_sftl.h"
15*4882a593Smuzhiyun 
16*4882a593Smuzhiyun #define     CPU_DELAY_NS(n)	ndelay(n)
17*4882a593Smuzhiyun #define     usleep_range(a, b)	udelay((b))
18*4882a593Smuzhiyun 
19*4882a593Smuzhiyun #define	    NANDC_MASTER_EN
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun void __iomem *nandc_base;
22*4882a593Smuzhiyun static u8 g_nandc_ver;
23*4882a593Smuzhiyun 
24*4882a593Smuzhiyun static u32 g_nandc_ecc_bits;
25*4882a593Smuzhiyun #ifdef NANDC_MASTER_EN
26*4882a593Smuzhiyun static struct MASTER_INFO_T master;
27*4882a593Smuzhiyun static u32 *g_master_temp_buf;
28*4882a593Smuzhiyun #endif
29*4882a593Smuzhiyun 
nandc_get_version(void)30*4882a593Smuzhiyun u8 nandc_get_version(void)
31*4882a593Smuzhiyun {
32*4882a593Smuzhiyun 	return g_nandc_ver;
33*4882a593Smuzhiyun }
34*4882a593Smuzhiyun 
nandc_init(void __iomem * nandc_addr)35*4882a593Smuzhiyun void nandc_init(void __iomem *nandc_addr)
36*4882a593Smuzhiyun {
37*4882a593Smuzhiyun 	union FM_CTL_T ctl_reg;
38*4882a593Smuzhiyun 
39*4882a593Smuzhiyun 	nandc_base = nandc_addr;
40*4882a593Smuzhiyun 
41*4882a593Smuzhiyun 	ctl_reg.d32 = 0;
42*4882a593Smuzhiyun 	g_nandc_ver = 6;
43*4882a593Smuzhiyun 	if (nandc_readl(NANDC_V9_NANDC_VER) == RK3326_NANDC_VER)
44*4882a593Smuzhiyun 		g_nandc_ver = 9;
45*4882a593Smuzhiyun 	if (g_nandc_ver == 9) {
46*4882a593Smuzhiyun 		ctl_reg.V9.wp = 1;
47*4882a593Smuzhiyun 		ctl_reg.V9.sif_read_delay = 2;
48*4882a593Smuzhiyun 		nandc_writel(ctl_reg.d32, NANDC_V9_FMCTL);
49*4882a593Smuzhiyun 		nandc_writel(0, NANDC_V9_RANDMZ_CFG);
50*4882a593Smuzhiyun 		nandc_writel(0x1041, NANDC_V9_FMWAIT);
51*4882a593Smuzhiyun 	} else {
52*4882a593Smuzhiyun 		ctl_reg.V6.wp = 1;
53*4882a593Smuzhiyun 		nandc_writel(ctl_reg.d32, NANDC_FMCTL);
54*4882a593Smuzhiyun 		nandc_writel(0, NANDC_RANDMZ_CFG);
55*4882a593Smuzhiyun 		nandc_writel(0x1061, NANDC_FMWAIT);
56*4882a593Smuzhiyun 	}
57*4882a593Smuzhiyun 	nandc_time_cfg(40);
58*4882a593Smuzhiyun 
59*4882a593Smuzhiyun #ifdef NANDC_MASTER_EN
60*4882a593Smuzhiyun 	if (!g_master_temp_buf)
61*4882a593Smuzhiyun 		g_master_temp_buf = (u32 *)ftl_malloc(MAX_FLASH_PAGE_SIZE +
62*4882a593Smuzhiyun 					      MAX_FLASH_PAGE_SIZE / 8);
63*4882a593Smuzhiyun 	master.page_buf = &g_master_temp_buf[0];
64*4882a593Smuzhiyun 	master.spare_buf = &g_master_temp_buf[MAX_FLASH_PAGE_SIZE / 4];
65*4882a593Smuzhiyun 	master.mapped = 0;
66*4882a593Smuzhiyun #endif
67*4882a593Smuzhiyun }
68*4882a593Smuzhiyun 
nandc_flash_cs(u8 chip_sel)69*4882a593Smuzhiyun void nandc_flash_cs(u8 chip_sel)
70*4882a593Smuzhiyun {
71*4882a593Smuzhiyun 	union FM_CTL_T tmp;
72*4882a593Smuzhiyun 
73*4882a593Smuzhiyun 	tmp.d32 = nandc_readl(NANDC_FMCTL);
74*4882a593Smuzhiyun 	tmp.V6.cs = 0x01 << chip_sel;
75*4882a593Smuzhiyun 	nandc_writel(tmp.d32, NANDC_FMCTL);
76*4882a593Smuzhiyun }
77*4882a593Smuzhiyun 
nandc_flash_de_cs(u8 chip_sel)78*4882a593Smuzhiyun void nandc_flash_de_cs(u8 chip_sel)
79*4882a593Smuzhiyun {
80*4882a593Smuzhiyun 	union FM_CTL_T tmp;
81*4882a593Smuzhiyun 
82*4882a593Smuzhiyun 	tmp.d32 = nandc_readl(NANDC_FMCTL);
83*4882a593Smuzhiyun 	tmp.V6.cs = 0;
84*4882a593Smuzhiyun 	tmp.V6.flash_abort_clear = 0;
85*4882a593Smuzhiyun 	nandc_writel(tmp.d32, NANDC_FMCTL);
86*4882a593Smuzhiyun }
87*4882a593Smuzhiyun 
nandc_delayns(u32 count)88*4882a593Smuzhiyun u32 nandc_delayns(u32 count)
89*4882a593Smuzhiyun {
90*4882a593Smuzhiyun 	CPU_DELAY_NS(count);
91*4882a593Smuzhiyun 	return 0;
92*4882a593Smuzhiyun }
93*4882a593Smuzhiyun 
nandc_wait_flash_ready(u8 chip_sel)94*4882a593Smuzhiyun u32 nandc_wait_flash_ready(u8 chip_sel)
95*4882a593Smuzhiyun {
96*4882a593Smuzhiyun 	union FM_CTL_T tmp;
97*4882a593Smuzhiyun 	u32 status;
98*4882a593Smuzhiyun 	u32 i;
99*4882a593Smuzhiyun 
100*4882a593Smuzhiyun 	status = 0;
101*4882a593Smuzhiyun 	for (i = 0; i < 100000; i++) {
102*4882a593Smuzhiyun 		nandc_delayns(100);
103*4882a593Smuzhiyun 		tmp.d32 = nandc_readl(NANDC_FMCTL);
104*4882a593Smuzhiyun 		if (tmp.V6.rdy != 0)
105*4882a593Smuzhiyun 			break;
106*4882a593Smuzhiyun 	}
107*4882a593Smuzhiyun 
108*4882a593Smuzhiyun 	if (i >= 100000)
109*4882a593Smuzhiyun 		status = -1;
110*4882a593Smuzhiyun 	return status;
111*4882a593Smuzhiyun }
112*4882a593Smuzhiyun 
nandc_randmz_sel(u8 chip_sel,u32 randmz_seed)113*4882a593Smuzhiyun void nandc_randmz_sel(u8 chip_sel, u32 randmz_seed)
114*4882a593Smuzhiyun {
115*4882a593Smuzhiyun 	nandc_writel(randmz_seed, NANDC_RANDMZ_CFG);
116*4882a593Smuzhiyun }
117*4882a593Smuzhiyun 
nandc_time_cfg(u32 ns)118*4882a593Smuzhiyun void nandc_time_cfg(u32 ns)
119*4882a593Smuzhiyun {
120*4882a593Smuzhiyun 	if (g_nandc_ver == 9) {
121*4882a593Smuzhiyun 		if (ns < 36)
122*4882a593Smuzhiyun 			nandc_writel(0x1041, NANDC_V9_FMWAIT);
123*4882a593Smuzhiyun 		else if (ns >= 100)
124*4882a593Smuzhiyun 			nandc_writel(0x2082, NANDC_V9_FMWAIT);
125*4882a593Smuzhiyun 		else
126*4882a593Smuzhiyun 			nandc_writel(0x1061, NANDC_V9_FMWAIT);
127*4882a593Smuzhiyun 	} else {
128*4882a593Smuzhiyun 		if (ns < 36)
129*4882a593Smuzhiyun 			nandc_writel(0x1061, NANDC_FMWAIT);
130*4882a593Smuzhiyun 		else if (ns >= 100)
131*4882a593Smuzhiyun 			nandc_writel(0x2082, NANDC_FMWAIT);
132*4882a593Smuzhiyun 		else
133*4882a593Smuzhiyun 			nandc_writel(0x1081, NANDC_FMWAIT);
134*4882a593Smuzhiyun 	}
135*4882a593Smuzhiyun }
136*4882a593Smuzhiyun 
nandc_bch_sel(u8 bits)137*4882a593Smuzhiyun void nandc_bch_sel(u8 bits)
138*4882a593Smuzhiyun {
139*4882a593Smuzhiyun 	union BCH_CTL_T tmp;
140*4882a593Smuzhiyun 	union FL_CTL_T fl_reg;
141*4882a593Smuzhiyun 	u8 bch_config;
142*4882a593Smuzhiyun 
143*4882a593Smuzhiyun 	fl_reg.d32 = 0;
144*4882a593Smuzhiyun 	fl_reg.V6.rst = 1;
145*4882a593Smuzhiyun 	g_nandc_ecc_bits = bits;
146*4882a593Smuzhiyun 	if (g_nandc_ver == 9) {
147*4882a593Smuzhiyun 		nandc_writel(fl_reg.d32, NANDC_V9_FLCTL);
148*4882a593Smuzhiyun 		if (bits == 70)
149*4882a593Smuzhiyun 			bch_config = 0;
150*4882a593Smuzhiyun 		else if (bits == 60)
151*4882a593Smuzhiyun 			bch_config = 3;
152*4882a593Smuzhiyun 		else if (bits == 40)
153*4882a593Smuzhiyun 			bch_config = 2;
154*4882a593Smuzhiyun 		else
155*4882a593Smuzhiyun 			bch_config = 1;
156*4882a593Smuzhiyun 		tmp.d32 = 0;
157*4882a593Smuzhiyun 		tmp.V9.bchmode = bch_config;
158*4882a593Smuzhiyun 		tmp.V9.bchrst = 1;
159*4882a593Smuzhiyun 		nandc_writel(tmp.d32, NANDC_V9_BCHCTL);
160*4882a593Smuzhiyun 	} else {
161*4882a593Smuzhiyun 		nandc_writel(fl_reg.d32, NANDC_FLCTL);
162*4882a593Smuzhiyun 		tmp.d32 = 0;
163*4882a593Smuzhiyun 		tmp.V6.addr = 0x10;
164*4882a593Smuzhiyun 		tmp.V6.bch_mode1 = 0;
165*4882a593Smuzhiyun 		if (bits == 16) {
166*4882a593Smuzhiyun 			tmp.V6.bch_mode = 0;
167*4882a593Smuzhiyun 		} else if (bits == 24) {
168*4882a593Smuzhiyun 			tmp.V6.bch_mode = 1;
169*4882a593Smuzhiyun 		} else {
170*4882a593Smuzhiyun 			tmp.V6.bch_mode1 = 1;
171*4882a593Smuzhiyun 			tmp.V6.bch_mode = 1;
172*4882a593Smuzhiyun 			if (bits == 40)
173*4882a593Smuzhiyun 				tmp.V6.bch_mode = 0;
174*4882a593Smuzhiyun 		}
175*4882a593Smuzhiyun 		tmp.V6.rst = 1;
176*4882a593Smuzhiyun 		nandc_writel(tmp.d32, NANDC_BCHCTL);
177*4882a593Smuzhiyun 	}
178*4882a593Smuzhiyun }
179*4882a593Smuzhiyun 
180*4882a593Smuzhiyun /*
181*4882a593Smuzhiyun  *Nandc xfer data transmission
182*4882a593Smuzhiyun  *1. set bch register except nandc version equals 9
183*4882a593Smuzhiyun  *2. set internal transfer control register
184*4882a593Smuzhiyun  *3. set bus transfer
185*4882a593Smuzhiyun  *	a. target memory data address
186*4882a593Smuzhiyun  *	b. ahb setting
187*4882a593Smuzhiyun  *4. configure register orderly and start transmission
188*4882a593Smuzhiyun  */
nandc_xfer_start(u8 dir,u8 n_sec,u32 * data,u32 * spare)189*4882a593Smuzhiyun static void nandc_xfer_start(u8 dir, u8 n_sec, u32 *data, u32 *spare)
190*4882a593Smuzhiyun {
191*4882a593Smuzhiyun 	union BCH_CTL_T bch_reg;
192*4882a593Smuzhiyun 	union FL_CTL_T fl_reg;
193*4882a593Smuzhiyun 	u32 i;
194*4882a593Smuzhiyun 	union MTRANS_CFG_T master_reg;
195*4882a593Smuzhiyun 	u16 *p_spare_tmp = (u16 *)spare;
196*4882a593Smuzhiyun 	unsigned long vir_addr;
197*4882a593Smuzhiyun 
198*4882a593Smuzhiyun 	fl_reg.d32 = 0;
199*4882a593Smuzhiyun 	if (g_nandc_ver == 9) {
200*4882a593Smuzhiyun 		fl_reg.V9.flash_rdn = dir;
201*4882a593Smuzhiyun 		fl_reg.V9.bypass = 1;
202*4882a593Smuzhiyun 		fl_reg.V9.tr_count = 1;
203*4882a593Smuzhiyun 		fl_reg.V9.async_tog_mix = 1;
204*4882a593Smuzhiyun 		fl_reg.V9.cor_able = 1;
205*4882a593Smuzhiyun 		fl_reg.V9.st_addr = 0;
206*4882a593Smuzhiyun 		fl_reg.V9.page_num = (n_sec + 1) / 2;
207*4882a593Smuzhiyun 		/* dma start transfer data do care flash rdy */
208*4882a593Smuzhiyun 		fl_reg.V9.flash_st_mod = 1;
209*4882a593Smuzhiyun 
210*4882a593Smuzhiyun 		if (dir != 0) {
211*4882a593Smuzhiyun 			for (i = 0; i < n_sec / 2; i++) {
212*4882a593Smuzhiyun 				if (spare) {
213*4882a593Smuzhiyun 					master.spare_buf[i] =
214*4882a593Smuzhiyun 						(p_spare_tmp[0]) |
215*4882a593Smuzhiyun 						((u32)p_spare_tmp[1] << 16);
216*4882a593Smuzhiyun 					p_spare_tmp += 2;
217*4882a593Smuzhiyun 				} else {
218*4882a593Smuzhiyun 					master.spare_buf[i] = 0xffffffff;
219*4882a593Smuzhiyun 				}
220*4882a593Smuzhiyun 			}
221*4882a593Smuzhiyun 		} else {
222*4882a593Smuzhiyun 			master.spare_buf[0] = 1;
223*4882a593Smuzhiyun 		}
224*4882a593Smuzhiyun 		master.page_vir = (u32 *)((data == (u32 *)NULL) ?
225*4882a593Smuzhiyun 					  master.page_buf :
226*4882a593Smuzhiyun 					  (u32 *)data);
227*4882a593Smuzhiyun 		master.spare_vir = (u32 *)master.spare_buf;
228*4882a593Smuzhiyun 
229*4882a593Smuzhiyun 		master.page_phy = (u32)((unsigned long)master.page_vir);
230*4882a593Smuzhiyun 		master.spare_phy = (u32)((unsigned long)master.spare_vir);
231*4882a593Smuzhiyun 		vir_addr = ((unsigned long)master.page_phy);
232*4882a593Smuzhiyun 		flush_dcache_range(vir_addr & (~0x3FuL),
233*4882a593Smuzhiyun 				   ((vir_addr + 63) & (~0x3FuL)) +
234*4882a593Smuzhiyun 					fl_reg.V6.page_num * 1024);
235*4882a593Smuzhiyun 		vir_addr = ((unsigned long)master.spare_phy);
236*4882a593Smuzhiyun 		flush_dcache_range(vir_addr & (~0x3FuL),
237*4882a593Smuzhiyun 				   ((vir_addr + 63) & (~0x3FuL)) +
238*4882a593Smuzhiyun 					fl_reg.V6.page_num * 128);
239*4882a593Smuzhiyun 		master.mapped = 1;
240*4882a593Smuzhiyun 		nandc_writel(master.page_phy, NANDC_V9_MTRANS_SADDR0);
241*4882a593Smuzhiyun 		nandc_writel(master.spare_phy, NANDC_V9_MTRANS_SADDR1);
242*4882a593Smuzhiyun 
243*4882a593Smuzhiyun 		master_reg.d32 =  nandc_readl(NANDC_V9_MTRANS_CFG);
244*4882a593Smuzhiyun 		master_reg.V9.incr_num = 16;
245*4882a593Smuzhiyun 		master_reg.V9.burst = 7;
246*4882a593Smuzhiyun 		master_reg.V9.hsize = 2;
247*4882a593Smuzhiyun 		master_reg.V9.bus_mode = 1;
248*4882a593Smuzhiyun 		master_reg.V9.ahb_wr = !dir;
249*4882a593Smuzhiyun 		master_reg.V9.ahb_wr_st = 1;
250*4882a593Smuzhiyun 		master_reg.V9.redundance_size = 0;
251*4882a593Smuzhiyun 
252*4882a593Smuzhiyun 		nandc_writel(master_reg.d32, NANDC_V9_MTRANS_CFG);
253*4882a593Smuzhiyun 		nandc_writel(fl_reg.d32, NANDC_V9_FLCTL);
254*4882a593Smuzhiyun 		fl_reg.V9.flash_st = 1;
255*4882a593Smuzhiyun 		nandc_writel(fl_reg.d32, NANDC_V9_FLCTL);
256*4882a593Smuzhiyun 	} else {
257*4882a593Smuzhiyun 		bch_reg.d32 = nandc_readl(NANDC_BCHCTL);
258*4882a593Smuzhiyun 		bch_reg.V6.addr = 0x10;
259*4882a593Smuzhiyun 		bch_reg.V6.power_down = 0;
260*4882a593Smuzhiyun 		bch_reg.V6.region = 0;
261*4882a593Smuzhiyun 
262*4882a593Smuzhiyun 		fl_reg.V6.rdn = dir;
263*4882a593Smuzhiyun 		fl_reg.V6.dma = 1;
264*4882a593Smuzhiyun 		fl_reg.V6.tr_count = 1;
265*4882a593Smuzhiyun 		fl_reg.V6.async_tog_mix = 1;
266*4882a593Smuzhiyun 		fl_reg.V6.cor_en = 1;
267*4882a593Smuzhiyun 		fl_reg.V6.st_addr = 0;
268*4882a593Smuzhiyun 
269*4882a593Smuzhiyun 		master_reg.d32 = nandc_readl(NANDC_MTRANS_CFG);
270*4882a593Smuzhiyun 		master_reg.V6.bus_mode = 0;
271*4882a593Smuzhiyun 		if (dir != 0) {
272*4882a593Smuzhiyun 			u32 spare_sz = 64;
273*4882a593Smuzhiyun 
274*4882a593Smuzhiyun 			for (i = 0; i < n_sec / 2; i++) {
275*4882a593Smuzhiyun 				if (spare) {
276*4882a593Smuzhiyun 					master.spare_buf[i * spare_sz / 4] =
277*4882a593Smuzhiyun 					(p_spare_tmp[0]) |
278*4882a593Smuzhiyun 					((u32)p_spare_tmp[1] << 16);
279*4882a593Smuzhiyun 					p_spare_tmp += 2;
280*4882a593Smuzhiyun 				} else {
281*4882a593Smuzhiyun 					master.spare_buf[i * spare_sz / 4] =
282*4882a593Smuzhiyun 					0xffffffff;
283*4882a593Smuzhiyun 				}
284*4882a593Smuzhiyun 			}
285*4882a593Smuzhiyun 		}
286*4882a593Smuzhiyun 		fl_reg.V6.page_num = (n_sec + 1) / 2;
287*4882a593Smuzhiyun 		master.page_vir = (u32 *)((data == (u32 *)NULL) ?
288*4882a593Smuzhiyun 					  master.page_buf :
289*4882a593Smuzhiyun 					  (u32 *)data);
290*4882a593Smuzhiyun 		master.spare_vir = (u32 *)master.spare_buf;
291*4882a593Smuzhiyun 
292*4882a593Smuzhiyun 		master.page_phy = (u32)((unsigned long)master.page_vir);
293*4882a593Smuzhiyun 		master.spare_phy = (u32)((unsigned long)master.spare_vir);
294*4882a593Smuzhiyun 		vir_addr = ((unsigned long)master.page_phy);
295*4882a593Smuzhiyun 		flush_dcache_range(vir_addr & (~0x3FuL),
296*4882a593Smuzhiyun 				   ((vir_addr + 63) & (~0x3FuL)) +
297*4882a593Smuzhiyun 					fl_reg.V6.page_num * 1024);
298*4882a593Smuzhiyun 		vir_addr = ((unsigned long)master.spare_phy);
299*4882a593Smuzhiyun 		flush_dcache_range(vir_addr & (~0x3FuL),
300*4882a593Smuzhiyun 				   ((vir_addr + 63) & (~0x3FuL)) +
301*4882a593Smuzhiyun 					fl_reg.V6.page_num * 128);
302*4882a593Smuzhiyun 		master.mapped = 1;
303*4882a593Smuzhiyun 		nandc_writel(master.page_phy, NANDC_MTRANS_SADDR0);
304*4882a593Smuzhiyun 		nandc_writel(master.spare_phy, NANDC_MTRANS_SADDR1);
305*4882a593Smuzhiyun 		master_reg.d32 = 0;
306*4882a593Smuzhiyun 		master_reg.V6.incr_num = 16;
307*4882a593Smuzhiyun 		master_reg.V6.burst = 7;
308*4882a593Smuzhiyun 		master_reg.V6.hsize = 2;
309*4882a593Smuzhiyun 		master_reg.V6.bus_mode = 1;
310*4882a593Smuzhiyun 		master_reg.V6.ahb_wr = !dir;
311*4882a593Smuzhiyun 		master_reg.V6.ahb_wr_st = 1;
312*4882a593Smuzhiyun 
313*4882a593Smuzhiyun 		nandc_writel(master_reg.d32, NANDC_MTRANS_CFG);
314*4882a593Smuzhiyun 		nandc_writel(bch_reg.d32, NANDC_BCHCTL);
315*4882a593Smuzhiyun 		nandc_writel(fl_reg.d32, NANDC_FLCTL);
316*4882a593Smuzhiyun 		fl_reg.V6.start = 1;
317*4882a593Smuzhiyun 		nandc_writel(fl_reg.d32, NANDC_FLCTL);
318*4882a593Smuzhiyun 	}
319*4882a593Smuzhiyun }
320*4882a593Smuzhiyun 
321*4882a593Smuzhiyun /*
322*4882a593Smuzhiyun  * Wait for the end of data transmission
323*4882a593Smuzhiyun  */
nandc_xfer_done(void)324*4882a593Smuzhiyun static void nandc_xfer_done(void)
325*4882a593Smuzhiyun {
326*4882a593Smuzhiyun 	union FL_CTL_T fl_reg;
327*4882a593Smuzhiyun 	union MTRANS_CFG_T master_reg;
328*4882a593Smuzhiyun 
329*4882a593Smuzhiyun 	if (g_nandc_ver == 9) {
330*4882a593Smuzhiyun 		union MTRANS_STAT_T stat_reg;
331*4882a593Smuzhiyun 
332*4882a593Smuzhiyun 		master_reg.d32 = nandc_readl(NANDC_V9_MTRANS_CFG);
333*4882a593Smuzhiyun 		if (master_reg.V9.ahb_wr != 0) {
334*4882a593Smuzhiyun 			do {
335*4882a593Smuzhiyun 				fl_reg.d32 = nandc_readl(NANDC_V9_FLCTL);
336*4882a593Smuzhiyun 				stat_reg.d32 = nandc_readl(NANDC_V9_MTRANS_STAT);
337*4882a593Smuzhiyun 				usleep_range(20, 30);
338*4882a593Smuzhiyun 			} while (stat_reg.V9.mtrans_cnt < fl_reg.V9.page_num ||
339*4882a593Smuzhiyun 				 fl_reg.V9.tr_rdy == 0);
340*4882a593Smuzhiyun 			udelay(5);
341*4882a593Smuzhiyun 		} else {
342*4882a593Smuzhiyun 			do {
343*4882a593Smuzhiyun 				fl_reg.d32 = nandc_readl(NANDC_V9_FLCTL);
344*4882a593Smuzhiyun 				usleep_range(20, 30);
345*4882a593Smuzhiyun 			} while (fl_reg.V9.tr_rdy == 0);
346*4882a593Smuzhiyun 		}
347*4882a593Smuzhiyun 	} else {
348*4882a593Smuzhiyun 		master_reg.d32 = nandc_readl(NANDC_MTRANS_CFG);
349*4882a593Smuzhiyun 		if (master_reg.V6.bus_mode != 0) {
350*4882a593Smuzhiyun 			union MTRANS_STAT_T stat_reg;
351*4882a593Smuzhiyun 
352*4882a593Smuzhiyun 		if (master_reg.V6.ahb_wr != 0) {
353*4882a593Smuzhiyun 			do {
354*4882a593Smuzhiyun 				fl_reg.d32 = nandc_readl(NANDC_FLCTL);
355*4882a593Smuzhiyun 				stat_reg.d32 = nandc_readl(NANDC_MTRANS_STAT);
356*4882a593Smuzhiyun 				usleep_range(20, 30);
357*4882a593Smuzhiyun 			} while (stat_reg.V6.mtrans_cnt < fl_reg.V6.page_num ||
358*4882a593Smuzhiyun 				 fl_reg.V6.tr_rdy == 0);
359*4882a593Smuzhiyun 		} else {
360*4882a593Smuzhiyun 			do {
361*4882a593Smuzhiyun 				fl_reg.d32 = nandc_readl(NANDC_FLCTL);
362*4882a593Smuzhiyun 				usleep_range(20, 30);
363*4882a593Smuzhiyun 			} while (fl_reg.V6.tr_rdy == 0);
364*4882a593Smuzhiyun 			}
365*4882a593Smuzhiyun 		} else {
366*4882a593Smuzhiyun 			do {
367*4882a593Smuzhiyun 				fl_reg.d32 = nandc_readl(NANDC_FLCTL);
368*4882a593Smuzhiyun 			} while ((fl_reg.V6.tr_rdy == 0));
369*4882a593Smuzhiyun 		}
370*4882a593Smuzhiyun 	}
371*4882a593Smuzhiyun }
372*4882a593Smuzhiyun 
nandc_xfer_data(u8 chip_sel,u8 dir,u8 n_sec,u32 * p_data,u32 * p_spare)373*4882a593Smuzhiyun u32 nandc_xfer_data(u8 chip_sel, u8 dir, u8 n_sec,
374*4882a593Smuzhiyun 		    u32 *p_data, u32 *p_spare)
375*4882a593Smuzhiyun {
376*4882a593Smuzhiyun 	u32 status = NAND_STS_OK;
377*4882a593Smuzhiyun 	u32 i;
378*4882a593Smuzhiyun 	u32 spare[16];
379*4882a593Smuzhiyun 	union BCH_ST_T bch_st_reg;
380*4882a593Smuzhiyun 
381*4882a593Smuzhiyun 	if (dir == NANDC_WRITE && !p_spare) {
382*4882a593Smuzhiyun 		p_spare = (u32 *)spare;
383*4882a593Smuzhiyun 		memset(spare, 0xFF, sizeof(spare));
384*4882a593Smuzhiyun 	}
385*4882a593Smuzhiyun 	nandc_xfer_start(dir, n_sec, p_data, p_spare);
386*4882a593Smuzhiyun 	nandc_xfer_done();
387*4882a593Smuzhiyun 	if (dir == NANDC_READ) {
388*4882a593Smuzhiyun 		if (g_nandc_ver == 9) {
389*4882a593Smuzhiyun 			for (i = 0; i < n_sec / 4; i++) {
390*4882a593Smuzhiyun 				bch_st_reg.d32 = nandc_readl(NANDC_V9_BCHST(i));
391*4882a593Smuzhiyun 				if (n_sec > 2) {
392*4882a593Smuzhiyun 					if (bch_st_reg.V9.fail0 || bch_st_reg.V9.fail1) {
393*4882a593Smuzhiyun 						status = NAND_STS_ECC_ERR;
394*4882a593Smuzhiyun 					} else {
395*4882a593Smuzhiyun 						u32 tmp = max((u32)bch_st_reg.V9.err_bits0,
396*4882a593Smuzhiyun 							      (u32)bch_st_reg.V9.err_bits1);
397*4882a593Smuzhiyun 						status = max(tmp, status);
398*4882a593Smuzhiyun 					}
399*4882a593Smuzhiyun 				} else {
400*4882a593Smuzhiyun 					if (bch_st_reg.V9.fail0)
401*4882a593Smuzhiyun 						status = NAND_STS_ECC_ERR;
402*4882a593Smuzhiyun 					else
403*4882a593Smuzhiyun 						status = bch_st_reg.V9.err_bits0;
404*4882a593Smuzhiyun 				}
405*4882a593Smuzhiyun 			}
406*4882a593Smuzhiyun 			if (p_spare) {
407*4882a593Smuzhiyun 				for (i = 0; i < n_sec / 2; i++)
408*4882a593Smuzhiyun 					p_spare[i] = master.spare_buf[i];
409*4882a593Smuzhiyun 			}
410*4882a593Smuzhiyun 		} else {
411*4882a593Smuzhiyun 			for (i = 0; i < n_sec / 4 ; i++) {
412*4882a593Smuzhiyun 				bch_st_reg.d32 = nandc_readl(NANDC_BCHST(i));
413*4882a593Smuzhiyun 				if (bch_st_reg.V6.fail0 || bch_st_reg.V6.fail1) {
414*4882a593Smuzhiyun 					status = NAND_STS_ECC_ERR;
415*4882a593Smuzhiyun 				} else {
416*4882a593Smuzhiyun 					u32 tmp = 0;
417*4882a593Smuzhiyun 
418*4882a593Smuzhiyun 					tmp =
419*4882a593Smuzhiyun 					max(bch_st_reg.V6.err_bits0 |
420*4882a593Smuzhiyun 					    ((u32)bch_st_reg.V6.err_bits0_5 << 5),
421*4882a593Smuzhiyun 					    bch_st_reg.V6.err_bits1 |
422*4882a593Smuzhiyun 					    ((u32)bch_st_reg.V6.err_bits1_5 << 5));
423*4882a593Smuzhiyun 					status = max(tmp, status);
424*4882a593Smuzhiyun 				}
425*4882a593Smuzhiyun 			}
426*4882a593Smuzhiyun 			if (p_spare) {
427*4882a593Smuzhiyun 				u32 spare_sz = 64;
428*4882a593Smuzhiyun 				u32 temp_data;
429*4882a593Smuzhiyun 				u8 *p_spare_temp = (u8 *)p_spare;
430*4882a593Smuzhiyun 
431*4882a593Smuzhiyun 				for (i = 0; i < n_sec / 2; i++) {
432*4882a593Smuzhiyun 					temp_data = master.spare_buf[i * spare_sz / 4];
433*4882a593Smuzhiyun 					*p_spare_temp++ = (u8)temp_data;
434*4882a593Smuzhiyun 					*p_spare_temp++ = (u8)(temp_data >> 8);
435*4882a593Smuzhiyun 					*p_spare_temp++ = (u8)(temp_data >> 16);
436*4882a593Smuzhiyun 					*p_spare_temp++ = (u8)(temp_data >> 24);
437*4882a593Smuzhiyun 				}
438*4882a593Smuzhiyun 			}
439*4882a593Smuzhiyun 			nandc_writel(0, NANDC_MTRANS_CFG);
440*4882a593Smuzhiyun 		}
441*4882a593Smuzhiyun 	}
442*4882a593Smuzhiyun 	return status;
443*4882a593Smuzhiyun }
444*4882a593Smuzhiyun 
nandc_clean_irq(void)445*4882a593Smuzhiyun void nandc_clean_irq(void)
446*4882a593Smuzhiyun {
447*4882a593Smuzhiyun }
448