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