blob: d5d105629369a5ae0def96fc3227e774c09a03ea [file] [log] [blame]
Vipin KUMAR6f2f5572012-05-22 00:15:54 +00001/*
2 * (C) Copyright 2010
3 * Vipin Kumar, ST Microelectronics, vipin.kumar@st.com.
4 *
5 * (C) Copyright 2012
6 * Amit Virdi, ST Microelectronics, amit.virdi@st.com.
7 *
Wolfgang Denkd79de1d2013-07-08 09:37:19 +02008 * SPDX-License-Identifier: GPL-2.0+
Vipin KUMAR6f2f5572012-05-22 00:15:54 +00009 */
10
11#include <common.h>
12#include <nand.h>
13#include <asm/io.h>
14#include <linux/bitops.h>
15#include <linux/err.h>
16#include <linux/mtd/nand_ecc.h>
17#include <linux/mtd/fsmc_nand.h>
18#include <asm/arch/hardware.h>
19
20static u32 fsmc_version;
21static struct fsmc_regs *const fsmc_regs_p = (struct fsmc_regs *)
22 CONFIG_SYS_FSMC_BASE;
23
24/*
25 * ECC4 and ECC1 have 13 bytes and 3 bytes of ecc respectively for 512 bytes of
26 * data. ECC4 can correct up to 8 bits in 512 bytes of data while ECC1 can
27 * correct 1 bit in 512 bytes
28 */
29
30static struct nand_ecclayout fsmc_ecc4_lp_layout = {
31 .eccbytes = 104,
32 .eccpos = { 2, 3, 4, 5, 6, 7, 8,
33 9, 10, 11, 12, 13, 14,
34 18, 19, 20, 21, 22, 23, 24,
35 25, 26, 27, 28, 29, 30,
36 34, 35, 36, 37, 38, 39, 40,
37 41, 42, 43, 44, 45, 46,
38 50, 51, 52, 53, 54, 55, 56,
39 57, 58, 59, 60, 61, 62,
40 66, 67, 68, 69, 70, 71, 72,
41 73, 74, 75, 76, 77, 78,
42 82, 83, 84, 85, 86, 87, 88,
43 89, 90, 91, 92, 93, 94,
44 98, 99, 100, 101, 102, 103, 104,
45 105, 106, 107, 108, 109, 110,
46 114, 115, 116, 117, 118, 119, 120,
47 121, 122, 123, 124, 125, 126
48 },
49 .oobfree = {
50 {.offset = 15, .length = 3},
51 {.offset = 31, .length = 3},
52 {.offset = 47, .length = 3},
53 {.offset = 63, .length = 3},
54 {.offset = 79, .length = 3},
55 {.offset = 95, .length = 3},
56 {.offset = 111, .length = 3},
57 {.offset = 127, .length = 1}
58 }
59};
60
61/*
62 * ECC4 layout for NAND of pagesize 4096 bytes & OOBsize 224 bytes. 13*8 bytes
63 * of OOB size is reserved for ECC, Byte no. 0 & 1 reserved for bad block & 118
64 * bytes are free for use.
65 */
66static struct nand_ecclayout fsmc_ecc4_224_layout = {
67 .eccbytes = 104,
68 .eccpos = { 2, 3, 4, 5, 6, 7, 8,
69 9, 10, 11, 12, 13, 14,
70 18, 19, 20, 21, 22, 23, 24,
71 25, 26, 27, 28, 29, 30,
72 34, 35, 36, 37, 38, 39, 40,
73 41, 42, 43, 44, 45, 46,
74 50, 51, 52, 53, 54, 55, 56,
75 57, 58, 59, 60, 61, 62,
76 66, 67, 68, 69, 70, 71, 72,
77 73, 74, 75, 76, 77, 78,
78 82, 83, 84, 85, 86, 87, 88,
79 89, 90, 91, 92, 93, 94,
80 98, 99, 100, 101, 102, 103, 104,
81 105, 106, 107, 108, 109, 110,
82 114, 115, 116, 117, 118, 119, 120,
83 121, 122, 123, 124, 125, 126
84 },
85 .oobfree = {
86 {.offset = 15, .length = 3},
87 {.offset = 31, .length = 3},
88 {.offset = 47, .length = 3},
89 {.offset = 63, .length = 3},
90 {.offset = 79, .length = 3},
91 {.offset = 95, .length = 3},
92 {.offset = 111, .length = 3},
93 {.offset = 127, .length = 97}
94 }
95};
96
97/*
98 * ECC placement definitions in oobfree type format
99 * There are 13 bytes of ecc for every 512 byte block and it has to be read
100 * consecutively and immediately after the 512 byte data block for hardware to
101 * generate the error bit offsets in 512 byte data
102 * Managing the ecc bytes in the following way makes it easier for software to
103 * read ecc bytes consecutive to data bytes. This way is similar to
104 * oobfree structure maintained already in u-boot nand driver
105 */
106static struct fsmc_eccplace fsmc_eccpl_lp = {
107 .eccplace = {
108 {.offset = 2, .length = 13},
109 {.offset = 18, .length = 13},
110 {.offset = 34, .length = 13},
111 {.offset = 50, .length = 13},
112 {.offset = 66, .length = 13},
113 {.offset = 82, .length = 13},
114 {.offset = 98, .length = 13},
115 {.offset = 114, .length = 13}
116 }
117};
118
119static struct nand_ecclayout fsmc_ecc4_sp_layout = {
120 .eccbytes = 13,
121 .eccpos = { 0, 1, 2, 3, 6, 7, 8,
122 9, 10, 11, 12, 13, 14
123 },
124 .oobfree = {
125 {.offset = 15, .length = 1},
126 }
127};
128
129static struct fsmc_eccplace fsmc_eccpl_sp = {
130 .eccplace = {
131 {.offset = 0, .length = 4},
132 {.offset = 6, .length = 9}
133 }
134};
135
136static struct nand_ecclayout fsmc_ecc1_layout = {
137 .eccbytes = 24,
138 .eccpos = {2, 3, 4, 18, 19, 20, 34, 35, 36, 50, 51, 52,
139 66, 67, 68, 82, 83, 84, 98, 99, 100, 114, 115, 116},
140 .oobfree = {
141 {.offset = 8, .length = 8},
142 {.offset = 24, .length = 8},
143 {.offset = 40, .length = 8},
144 {.offset = 56, .length = 8},
145 {.offset = 72, .length = 8},
146 {.offset = 88, .length = 8},
147 {.offset = 104, .length = 8},
148 {.offset = 120, .length = 8}
149 }
150};
151
152/* Count the number of 0's in buff upto a max of max_bits */
153static int count_written_bits(uint8_t *buff, int size, int max_bits)
154{
155 int k, written_bits = 0;
156
157 for (k = 0; k < size; k++) {
158 written_bits += hweight8(~buff[k]);
159 if (written_bits > max_bits)
160 break;
161 }
162
163 return written_bits;
164}
165
166static void fsmc_nand_hwcontrol(struct mtd_info *mtd, int cmd, uint ctrl)
167{
Scott Wood17fed142016-05-30 13:57:56 -0500168 struct nand_chip *this = mtd_to_nand(mtd);
Vipin KUMAR6f2f5572012-05-22 00:15:54 +0000169 ulong IO_ADDR_W;
170
171 if (ctrl & NAND_CTRL_CHANGE) {
172 IO_ADDR_W = (ulong)this->IO_ADDR_W;
173
174 IO_ADDR_W &= ~(CONFIG_SYS_NAND_CLE | CONFIG_SYS_NAND_ALE);
175 if (ctrl & NAND_CLE)
176 IO_ADDR_W |= CONFIG_SYS_NAND_CLE;
177 if (ctrl & NAND_ALE)
178 IO_ADDR_W |= CONFIG_SYS_NAND_ALE;
179
180 if (ctrl & NAND_NCE) {
181 writel(readl(&fsmc_regs_p->pc) |
182 FSMC_ENABLE, &fsmc_regs_p->pc);
183 } else {
184 writel(readl(&fsmc_regs_p->pc) &
185 ~FSMC_ENABLE, &fsmc_regs_p->pc);
186 }
187 this->IO_ADDR_W = (void *)IO_ADDR_W;
188 }
189
190 if (cmd != NAND_CMD_NONE)
191 writeb(cmd, this->IO_ADDR_W);
192}
193
194static int fsmc_bch8_correct_data(struct mtd_info *mtd, u_char *dat,
195 u_char *read_ecc, u_char *calc_ecc)
196{
197 /* The calculated ecc is actually the correction index in data */
198 u32 err_idx[8];
199 u32 num_err, i;
200 u32 ecc1, ecc2, ecc3, ecc4;
201
202 num_err = (readl(&fsmc_regs_p->sts) >> 10) & 0xF;
203
204 if (likely(num_err == 0))
205 return 0;
206
207 if (unlikely(num_err > 8)) {
208 /*
209 * This is a temporary erase check. A newly erased page read
210 * would result in an ecc error because the oob data is also
211 * erased to FF and the calculated ecc for an FF data is not
212 * FF..FF.
213 * This is a workaround to skip performing correction in case
214 * data is FF..FF
215 *
216 * Logic:
217 * For every page, each bit written as 0 is counted until these
218 * number of bits are greater than 8 (the maximum correction
219 * capability of FSMC for each 512 + 13 bytes)
220 */
221
222 int bits_ecc = count_written_bits(read_ecc, 13, 8);
223 int bits_data = count_written_bits(dat, 512, 8);
224
225 if ((bits_ecc + bits_data) <= 8) {
226 if (bits_data)
227 memset(dat, 0xff, 512);
228 return bits_data + bits_ecc;
229 }
230
231 return -EBADMSG;
232 }
233
234 ecc1 = readl(&fsmc_regs_p->ecc1);
235 ecc2 = readl(&fsmc_regs_p->ecc2);
236 ecc3 = readl(&fsmc_regs_p->ecc3);
237 ecc4 = readl(&fsmc_regs_p->sts);
238
239 err_idx[0] = (ecc1 >> 0) & 0x1FFF;
240 err_idx[1] = (ecc1 >> 13) & 0x1FFF;
241 err_idx[2] = (((ecc2 >> 0) & 0x7F) << 6) | ((ecc1 >> 26) & 0x3F);
242 err_idx[3] = (ecc2 >> 7) & 0x1FFF;
243 err_idx[4] = (((ecc3 >> 0) & 0x1) << 12) | ((ecc2 >> 20) & 0xFFF);
244 err_idx[5] = (ecc3 >> 1) & 0x1FFF;
245 err_idx[6] = (ecc3 >> 14) & 0x1FFF;
246 err_idx[7] = (((ecc4 >> 16) & 0xFF) << 5) | ((ecc3 >> 27) & 0x1F);
247
248 i = 0;
249 while (i < num_err) {
250 err_idx[i] ^= 3;
251
252 if (err_idx[i] < 512 * 8)
253 __change_bit(err_idx[i], dat);
254
255 i++;
256 }
257
258 return num_err;
259}
260
261static int fsmc_read_hwecc(struct mtd_info *mtd,
262 const u_char *data, u_char *ecc)
263{
264 u_int ecc_tmp;
265 int timeout = CONFIG_SYS_HZ;
266 ulong start;
267
268 switch (fsmc_version) {
269 case FSMC_VER8:
270 start = get_timer(0);
271 while (get_timer(start) < timeout) {
272 /*
273 * Busy waiting for ecc computation
274 * to finish for 512 bytes
275 */
276 if (readl(&fsmc_regs_p->sts) & FSMC_CODE_RDY)
277 break;
278 }
279
280 ecc_tmp = readl(&fsmc_regs_p->ecc1);
281 ecc[0] = (u_char) (ecc_tmp >> 0);
282 ecc[1] = (u_char) (ecc_tmp >> 8);
283 ecc[2] = (u_char) (ecc_tmp >> 16);
284 ecc[3] = (u_char) (ecc_tmp >> 24);
285
286 ecc_tmp = readl(&fsmc_regs_p->ecc2);
287 ecc[4] = (u_char) (ecc_tmp >> 0);
288 ecc[5] = (u_char) (ecc_tmp >> 8);
289 ecc[6] = (u_char) (ecc_tmp >> 16);
290 ecc[7] = (u_char) (ecc_tmp >> 24);
291
292 ecc_tmp = readl(&fsmc_regs_p->ecc3);
293 ecc[8] = (u_char) (ecc_tmp >> 0);
294 ecc[9] = (u_char) (ecc_tmp >> 8);
295 ecc[10] = (u_char) (ecc_tmp >> 16);
296 ecc[11] = (u_char) (ecc_tmp >> 24);
297
298 ecc_tmp = readl(&fsmc_regs_p->sts);
299 ecc[12] = (u_char) (ecc_tmp >> 16);
300 break;
301
302 default:
303 ecc_tmp = readl(&fsmc_regs_p->ecc1);
304 ecc[0] = (u_char) (ecc_tmp >> 0);
305 ecc[1] = (u_char) (ecc_tmp >> 8);
306 ecc[2] = (u_char) (ecc_tmp >> 16);
307 break;
308 }
309
310 return 0;
311}
312
313void fsmc_enable_hwecc(struct mtd_info *mtd, int mode)
314{
315 writel(readl(&fsmc_regs_p->pc) & ~FSMC_ECCPLEN_256,
316 &fsmc_regs_p->pc);
317 writel(readl(&fsmc_regs_p->pc) & ~FSMC_ECCEN,
318 &fsmc_regs_p->pc);
319 writel(readl(&fsmc_regs_p->pc) | FSMC_ECCEN,
320 &fsmc_regs_p->pc);
321}
322
323/*
324 * fsmc_read_page_hwecc
325 * @mtd: mtd info structure
326 * @chip: nand chip info structure
327 * @buf: buffer to store read data
Sergey Lapin3a38a552013-01-14 03:46:50 +0000328 * @oob_required: caller expects OOB data read to chip->oob_poi
Vipin KUMAR6f2f5572012-05-22 00:15:54 +0000329 * @page: page number to read
330 *
331 * This routine is needed for fsmc verison 8 as reading from NAND chip has to be
332 * performed in a strict sequence as follows:
333 * data(512 byte) -> ecc(13 byte)
334 * After this read, fsmc hardware generates and reports error data bits(upto a
335 * max of 8 bits)
336 */
337static int fsmc_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
Sergey Lapin3a38a552013-01-14 03:46:50 +0000338 uint8_t *buf, int oob_required, int page)
Vipin KUMAR6f2f5572012-05-22 00:15:54 +0000339{
340 struct fsmc_eccplace *fsmc_eccpl;
341 int i, j, s, stat, eccsize = chip->ecc.size;
342 int eccbytes = chip->ecc.bytes;
343 int eccsteps = chip->ecc.steps;
344 uint8_t *p = buf;
345 uint8_t *ecc_calc = chip->buffers->ecccalc;
346 uint8_t *ecc_code = chip->buffers->ecccode;
347 int off, len, group = 0;
348 uint8_t oob[13] __attribute__ ((aligned (2)));
349
350 /* Differentiate between small and large page ecc place definitions */
351 if (mtd->writesize == 512)
352 fsmc_eccpl = &fsmc_eccpl_sp;
353 else
354 fsmc_eccpl = &fsmc_eccpl_lp;
355
356 for (i = 0, s = 0; s < eccsteps; s++, i += eccbytes, p += eccsize) {
357
358 chip->cmdfunc(mtd, NAND_CMD_READ0, s * eccsize, page);
359 chip->ecc.hwctl(mtd, NAND_ECC_READ);
360 chip->read_buf(mtd, p, eccsize);
361
362 for (j = 0; j < eccbytes;) {
363 off = fsmc_eccpl->eccplace[group].offset;
364 len = fsmc_eccpl->eccplace[group].length;
365 group++;
366
367 /*
368 * length is intentionally kept a higher multiple of 2
369 * to read at least 13 bytes even in case of 16 bit NAND
370 * devices
371 */
372 if (chip->options & NAND_BUSWIDTH_16)
373 len = roundup(len, 2);
374 chip->cmdfunc(mtd, NAND_CMD_READOOB, off, page);
375 chip->read_buf(mtd, oob + j, len);
376 j += len;
377 }
378
379 memcpy(&ecc_code[i], oob, 13);
380 chip->ecc.calculate(mtd, p, &ecc_calc[i]);
381
382 stat = chip->ecc.correct(mtd, p, &ecc_code[i],
383 &ecc_calc[i]);
384 if (stat < 0)
385 mtd->ecc_stats.failed++;
386 else
387 mtd->ecc_stats.corrected += stat;
388 }
389
390 return 0;
391}
392
Stefan Roeseb2ef2322015-09-02 14:29:12 +0200393#ifndef CONFIG_SPL_BUILD
394/*
395 * fsmc_nand_switch_ecc - switch the ECC operation between different engines
396 *
397 * @eccstrength - the number of bits that could be corrected
398 * (1 - HW, 4 - SW BCH4)
399 */
Stefan Roese56b69022015-09-14 08:47:47 +0200400int fsmc_nand_switch_ecc(uint32_t eccstrength)
Stefan Roeseb2ef2322015-09-02 14:29:12 +0200401{
402 struct nand_chip *nand;
403 struct mtd_info *mtd;
404 int err;
405
Stefan Roese56b69022015-09-14 08:47:47 +0200406 /*
407 * This functions is only called on SPEAr600 platforms, supporting
408 * 1 bit HW ECC. The BCH8 HW ECC (FSMC_VER8) from the ST-Ericsson
409 * Nomadik SoC is currently supporting this fsmc_nand_switch_ecc()
410 * function, as it doesn't need to switch to a different ECC layout.
411 */
Grygorii Strashko69666252017-06-26 19:13:01 -0500412 mtd = get_nand_dev_by_index(nand_curr_device);
Scott Wood17fed142016-05-30 13:57:56 -0500413 nand = mtd_to_nand(mtd);
Stefan Roeseb2ef2322015-09-02 14:29:12 +0200414
415 /* Setup the ecc configurations again */
416 if (eccstrength == 1) {
417 nand->ecc.mode = NAND_ECC_HW;
418 nand->ecc.bytes = 3;
419 nand->ecc.strength = 1;
420 nand->ecc.layout = &fsmc_ecc1_layout;
Stefan Roese56b69022015-09-14 08:47:47 +0200421 nand->ecc.calculate = fsmc_read_hwecc;
Stefan Roeseb2ef2322015-09-02 14:29:12 +0200422 nand->ecc.correct = nand_correct_data;
Stefan Roese56b69022015-09-14 08:47:47 +0200423 } else if (eccstrength == 4) {
424 /*
425 * .calculate .correct and .bytes will be set in
426 * nand_scan_tail()
427 */
Stefan Roeseb2ef2322015-09-02 14:29:12 +0200428 nand->ecc.mode = NAND_ECC_SOFT_BCH;
Stefan Roeseb2ef2322015-09-02 14:29:12 +0200429 nand->ecc.strength = 4;
430 nand->ecc.layout = NULL;
Stefan Roese56b69022015-09-14 08:47:47 +0200431 } else {
432 printf("Error: ECC strength %d not supported!\n", eccstrength);
Stefan Roeseb2ef2322015-09-02 14:29:12 +0200433 }
434
435 /* Update NAND handling after ECC mode switch */
436 err = nand_scan_tail(mtd);
437
438 return err;
439}
440#endif /* CONFIG_SPL_BUILD */
441
Vipin KUMAR6f2f5572012-05-22 00:15:54 +0000442int fsmc_nand_init(struct nand_chip *nand)
443{
444 static int chip_nr;
445 struct mtd_info *mtd;
Vipin KUMAR6f2f5572012-05-22 00:15:54 +0000446 u32 peripid2 = readl(&fsmc_regs_p->peripid2);
447
448 fsmc_version = (peripid2 >> FSMC_REVISION_SHFT) &
449 FSMC_REVISION_MSK;
450
451 writel(readl(&fsmc_regs_p->ctrl) | FSMC_WP, &fsmc_regs_p->ctrl);
452
453#if defined(CONFIG_SYS_FSMC_NAND_16BIT)
454 writel(FSMC_DEVWID_16 | FSMC_DEVTYPE_NAND | FSMC_ENABLE | FSMC_WAITON,
455 &fsmc_regs_p->pc);
456#elif defined(CONFIG_SYS_FSMC_NAND_8BIT)
457 writel(FSMC_DEVWID_8 | FSMC_DEVTYPE_NAND | FSMC_ENABLE | FSMC_WAITON,
458 &fsmc_regs_p->pc);
459#else
460#error Please define CONFIG_SYS_FSMC_NAND_16BIT or CONFIG_SYS_FSMC_NAND_8BIT
461#endif
462 writel(readl(&fsmc_regs_p->pc) | FSMC_TCLR_1 | FSMC_TAR_1,
463 &fsmc_regs_p->pc);
464 writel(FSMC_THIZ_1 | FSMC_THOLD_4 | FSMC_TWAIT_6 | FSMC_TSET_0,
465 &fsmc_regs_p->comm);
466 writel(FSMC_THIZ_1 | FSMC_THOLD_4 | FSMC_TWAIT_6 | FSMC_TSET_0,
467 &fsmc_regs_p->attrib);
468
469 nand->options = 0;
470#if defined(CONFIG_SYS_FSMC_NAND_16BIT)
471 nand->options |= NAND_BUSWIDTH_16;
472#endif
473 nand->ecc.mode = NAND_ECC_HW;
474 nand->ecc.size = 512;
475 nand->ecc.calculate = fsmc_read_hwecc;
476 nand->ecc.hwctl = fsmc_enable_hwecc;
477 nand->cmd_ctrl = fsmc_nand_hwcontrol;
478 nand->IO_ADDR_R = nand->IO_ADDR_W =
479 (void __iomem *)CONFIG_SYS_NAND_BASE;
480 nand->badblockbits = 7;
481
Scott Wood17fed142016-05-30 13:57:56 -0500482 mtd = nand_to_mtd(nand);
Vipin KUMAR6f2f5572012-05-22 00:15:54 +0000483
484 switch (fsmc_version) {
485 case FSMC_VER8:
486 nand->ecc.bytes = 13;
Sergey Lapin3a38a552013-01-14 03:46:50 +0000487 nand->ecc.strength = 8;
Vipin KUMAR6f2f5572012-05-22 00:15:54 +0000488 nand->ecc.correct = fsmc_bch8_correct_data;
489 nand->ecc.read_page = fsmc_read_page_hwecc;
490 if (mtd->writesize == 512)
491 nand->ecc.layout = &fsmc_ecc4_sp_layout;
492 else {
493 if (mtd->oobsize == 224)
494 nand->ecc.layout = &fsmc_ecc4_224_layout;
495 else
496 nand->ecc.layout = &fsmc_ecc4_lp_layout;
497 }
498
499 break;
500 default:
501 nand->ecc.bytes = 3;
Sergey Lapin3a38a552013-01-14 03:46:50 +0000502 nand->ecc.strength = 1;
Vipin KUMAR6f2f5572012-05-22 00:15:54 +0000503 nand->ecc.layout = &fsmc_ecc1_layout;
504 nand->ecc.correct = nand_correct_data;
505 break;
506 }
507
508 /* Detect NAND chips */
509 if (nand_scan_ident(mtd, CONFIG_SYS_MAX_NAND_DEVICE, NULL))
510 return -ENXIO;
511
512 if (nand_scan_tail(mtd))
513 return -ENXIO;
514
Scott Wood2c1b7e12016-05-30 13:57:55 -0500515 if (nand_register(chip_nr++, mtd))
516 return -ENXIO;
Vipin KUMAR6f2f5572012-05-22 00:15:54 +0000517
518 return 0;
519}