xref: /rk3399_rockchip-uboot/drivers/rkflash/nandc.c (revision e7b5bb3cc9527752c2c01acb4325fc0721fb75aa)
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 "typedef.h"
15 
16 #define     CPU_DELAY_NS(n)	ndelay(n)
17 
18 #define	    NANDC_MASTER_EN
19 
20 void __iomem *nandc_base;
21 
22 static u32 g_nandc_ecc_bits;
23 #ifdef NANDC_MASTER_EN
24 static struct MASTER_INFO_T master;
25 static u32 *g_master_temp_buf;
26 #endif
27 
28 void nandc_init(void __iomem *nandc_addr)
29 {
30 	union FM_CTL_T ctl_reg;
31 
32 	nandc_base = nandc_addr;
33 
34 	ctl_reg.d32 = 0;
35 	ctl_reg.V6.wp = 1;
36 	nandc_writel(ctl_reg.d32, NANDC_FMCTL);
37 	nandc_writel(0, NANDC_RANDMZ_CFG);
38 	nandc_time_cfg(40);
39 
40 #ifdef NANDC_MASTER_EN
41 	if (!g_master_temp_buf)
42 		g_master_temp_buf = (u32 *)ftl_malloc(MAX_FLASH_PAGE_SIZE +
43 					      MAX_FLASH_PAGE_SIZE / 8);
44 	master.page_buf = &g_master_temp_buf[0];
45 	master.spare_buf = &g_master_temp_buf[MAX_FLASH_PAGE_SIZE / 4];
46 	master.mapped = 0;
47 #endif
48 }
49 
50 void nandc_flash_cs(u8 chip_sel)
51 {
52 	union FM_CTL_T tmp;
53 
54 	tmp.d32 = nandc_readl(NANDC_FMCTL);
55 	tmp.V6.cs = 0x01 << chip_sel;
56 	nandc_writel(tmp.d32, NANDC_FMCTL);
57 }
58 
59 void nandc_flash_de_cs(u8 chip_sel)
60 {
61 	union FM_CTL_T tmp;
62 
63 	tmp.d32 = nandc_readl(NANDC_FMCTL);
64 	tmp.V6.cs = 0;
65 	tmp.V6.flash_abort_clear = 0;
66 	nandc_writel(tmp.d32, NANDC_FMCTL);
67 }
68 
69 u32 nandc_delayns(u32 count)
70 {
71 	CPU_DELAY_NS(count);
72 	return 0;
73 }
74 
75 u32 nandc_wait_flash_ready(u8 chip_sel)
76 {
77 	union FM_CTL_T tmp;
78 	u32 status;
79 	u32 i;
80 
81 	status = 0;
82 	for (i = 0; i < 100000; i++) {
83 		nandc_delayns(100);
84 		tmp.d32 = nandc_readl(NANDC_FMCTL);
85 		if (tmp.V6.rdy != 0)
86 			break;
87 	}
88 
89 	if (i >= 100000)
90 		status = -1;
91 	return status;
92 }
93 
94 void nandc_randmz_sel(u8 chip_sel, u32 randmz_seed)
95 {
96 	nandc_writel(randmz_seed, NANDC_RANDMZ_CFG);
97 }
98 
99 void nandc_time_cfg(u32 ns)
100 {
101 	if (ns < 36)
102 		nandc_writel(0x1061, NANDC_FMWAIT);
103 	else if (ns >= 100)
104 		nandc_writel(0x2082, NANDC_FMWAIT);
105 	else
106 		nandc_writel(0x1081, NANDC_FMWAIT);
107 }
108 
109 void nandc_bch_sel(u8 bits)
110 {
111 	union BCH_CTL_T tmp;
112 	union FL_CTL_T fl_reg;
113 
114 	fl_reg.d32 = 0;
115 	fl_reg.V6.rst = 1;
116 	nandc_writel(fl_reg.d32, NANDC_FLCTL);
117 	g_nandc_ecc_bits = bits;
118 	tmp.d32 = 0;
119 	tmp.V6.addr = 0x10;
120 	tmp.V6.bch_mode1 = 0;
121 	if (bits == 16) {
122 		tmp.V6.bch_mode = 0;
123 	} else if (bits == 24) {
124 		tmp.V6.bch_mode = 1;
125 	} else {
126 		tmp.V6.bch_mode1 = 1;
127 		tmp.V6.bch_mode = 1;
128 		if (bits == 40)
129 			tmp.V6.bch_mode = 0;
130 	}
131 	tmp.V6.rst = 1;
132 	nandc_writel(tmp.d32, NANDC_BCHCTL);
133 }
134 
135 static void nandc_xfer_start(u8 chip_sel,
136 			     u8 dir,
137 			     u8 sector_count,
138 			     u8 st_buf,
139 			     u32 *p_data,
140 			     u32 *p_spare)
141 {
142 	union BCH_CTL_T bch_reg;
143 	union FL_CTL_T fl_reg;
144 	u8 bus_mode = (p_spare || p_data);
145 	u32 i;
146 	union MTRANS_CFG_T master_reg;
147 	u16 *p_spare_tmp = (u16 *)p_spare;
148 	u64 vir_addr;
149 
150 	fl_reg.d32 = 0;
151 	bch_reg.d32 = nandc_readl(NANDC_BCHCTL);
152 	bch_reg.V6.addr = 0x10;
153 	bch_reg.V6.power_down = 0;
154 	bch_reg.V6.region = chip_sel;
155 
156 	fl_reg.V6.rdn = dir;
157 	fl_reg.V6.dma = 1;
158 	fl_reg.V6.tr_count = 1;
159 	fl_reg.V6.async_tog_mix = 1;
160 	fl_reg.V6.cor_en = 1;
161 	fl_reg.V6.st_addr = st_buf / 2;
162 
163 	master_reg.d32 = nandc_readl(NANDC_MTRANS_CFG);
164 	master_reg.V6.bus_mode = 0;
165 	#ifdef NANDC_MASTER_EN
166 	if (bus_mode != 0 && dir != 0) {
167 		u32 spare_sz = 64;
168 
169 		for (i = 0; i < sector_count / 2; i++) {
170 			if (p_spare) {
171 				master.spare_buf[i * spare_sz / 4] =
172 				(p_spare_tmp[0]) | ((u32)p_spare_tmp[1] << 16);
173 				p_spare_tmp += 2;
174 			} else{
175 				master.spare_buf[i * spare_sz / 4] =
176 				0xffffffff;
177 			}
178 		}
179 	}
180 	fl_reg.V6.page_num = (sector_count + 1) / 2;
181 	master.page_vir = (u32 *)((p_data == (u32 *)NULL) ?
182 				  master.page_buf :
183 				  (u32 *)p_data);
184 	master.spare_vir = (u32 *)master.spare_buf;
185 
186 	master.page_phy = (u32)((unsigned long)master.page_vir);
187 	master.spare_phy = (u32)((unsigned long)master.spare_vir);
188 	vir_addr = ((unsigned long)master.page_phy);
189 	flush_dcache_range(vir_addr & (~0x3FuL),
190 			   ((vir_addr + 63) & (~0x3FuL)) +
191 				fl_reg.V6.page_num * 1024);
192 	vir_addr = ((unsigned long)master.spare_phy);
193 	flush_dcache_range(vir_addr & (~0x3FuL),
194 			   ((vir_addr + 63) & (~0x3FuL)) +
195 				fl_reg.V6.page_num * 128);
196 	master.mapped = 1;
197 	nandc_writel(master.page_phy, NANDC_MTRANS_SADDR0);
198 	nandc_writel(master.spare_phy, NANDC_MTRANS_SADDR1);
199 	master_reg.d32 = 0;
200 	master_reg.V6.incr_num = 16;
201 	master_reg.V6.burst = 7;
202 	if ((((unsigned long)p_data) & 0x03) == 0)
203 		master_reg.V6.hsize = 2;
204 	master_reg.V6.bus_mode = 1;
205 	master_reg.V6.ahb_wr = !dir;
206 	master_reg.V6.ahb_wr_st = 1;
207 	#endif
208 
209 	nandc_writel(master_reg.d32, NANDC_MTRANS_CFG);
210 	nandc_writel(bch_reg.d32, NANDC_BCHCTL);
211 	nandc_writel(fl_reg.d32, NANDC_FLCTL);
212 	fl_reg.V6.start = 1;
213 	nandc_writel(fl_reg.d32, NANDC_FLCTL);
214 }
215 
216 static void nandc_xfer_comp(u8 chip_sel)
217 {
218 	union FL_CTL_T fl_reg;
219 	union MTRANS_CFG_T master_reg;
220 
221 	master_reg.d32 = nandc_readl(NANDC_MTRANS_CFG);
222 	if (master_reg.V6.bus_mode != 0) {
223 		union MTRANS_STAT_T stat_reg;
224 
225 		if (master_reg.V6.ahb_wr != 0) {
226 			do {
227 				fl_reg.d32 = nandc_readl(NANDC_FLCTL);
228 				stat_reg.d32 = nandc_readl(NANDC_MTRANS_STAT);
229 			} while (stat_reg.V6.mtrans_cnt < fl_reg.V6.page_num);
230 		} else {
231 			do {
232 				fl_reg.d32 = nandc_readl(NANDC_FLCTL);
233 			} while (fl_reg.V6.tr_rdy == 0);
234 		}
235 	} else {
236 		do {
237 			fl_reg.d32 = nandc_readl(NANDC_FLCTL);
238 		} while ((fl_reg.V6.tr_rdy == 0));
239 	}
240 }
241 
242 u32 nandc_xfer_data(u8 chip_sel, u8 dir, u8 sector_count,
243 		    u32 *p_data, u32 *p_spare)
244 {
245 	u32 status = NAND_STS_OK;
246 	u32 i;
247 	u32 spare[16];
248 	union BCH_ST_T bch_st_reg;
249 
250 	if (dir == NANDC_WRITE && !p_spare) {
251 		p_spare = (u32 *)spare;
252 		memset(spare, 0xFF, sizeof(spare));
253 	}
254 	nandc_xfer_start(chip_sel, dir, sector_count, 0, p_data, p_spare);
255 	nandc_xfer_comp(chip_sel);
256 	if (dir == NANDC_READ) {
257 		if (p_spare) {
258 			u32 spare_sz = 64;
259 			u32 temp_data;
260 			u8 *p_spare_temp = (u8 *)p_spare;
261 
262 			for (i = 0; i < sector_count / 2; i++) {
263 				temp_data = master.spare_buf[i * spare_sz / 4];
264 				*p_spare_temp++ = (u8)temp_data;
265 				*p_spare_temp++ = (u8)(temp_data >> 8);
266 				*p_spare_temp++ = (u8)(temp_data >> 16);
267 				*p_spare_temp++ = (u8)(temp_data >> 24);
268 			}
269 		}
270 		for (i = 0; i < sector_count / 4 ; i++) {
271 			bch_st_reg.d32 = nandc_readl(NANDC_BCHST(i));
272 			if (bch_st_reg.V6.fail0 || bch_st_reg.V6.fail1) {
273 				status = NAND_STS_ECC_ERR;
274 			} else {
275 				u32 tmp = 0;
276 
277 				tmp =
278 				max(bch_st_reg.V6.err_bits0 |
279 				    ((u32)bch_st_reg.V6.err_bits0_5 << 5),
280 				    bch_st_reg.V6.err_bits1 |
281 				    ((u32)bch_st_reg.V6.err_bits1_5 << 5));
282 				status = max(tmp, status);
283 			}
284 		}
285 	}
286 	nandc_writel(0, NANDC_MTRANS_CFG);
287 	return status;
288 }
289 
290 void nandc_clean_irq(void)
291 {
292 }
293