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