blob: 9158d94de25a36d2db217484ae49d2ff9ef21d63 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Sergey Kubushyne8f39122007-08-10 20:26:18 +02002/*
3 * NAND driver for TI DaVinci based boards.
4 *
5 * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net>
6 *
7 * Based on Linux DaVinci NAND driver by TI. Original copyright follows:
8 */
9
10/*
11 *
Miquel Raynal1f1ae152018-08-16 17:30:07 +020012 * linux/drivers/mtd/nand/raw/nand_davinci.c
Sergey Kubushyne8f39122007-08-10 20:26:18 +020013 *
14 * NAND Flash Driver
15 *
16 * Copyright (C) 2006 Texas Instruments.
17 *
18 * ----------------------------------------------------------------------------
19 *
Sergey Kubushyne8f39122007-08-10 20:26:18 +020020 * ----------------------------------------------------------------------------
21 *
22 * Overview:
23 * This is a device driver for the NAND flash device found on the
24 * DaVinci board which utilizes the Samsung k9k2g08 part.
25 *
26 Modifications:
27 ver. 1.0: Feb 2005, Vinod/Sudhakar
28 -
Sergey Kubushyne8f39122007-08-10 20:26:18 +020029 */
30
31#include <common.h>
Simon Glass0f2af882020-05-10 11:40:05 -060032#include <log.h>
Tom Rini3bde7e22021-09-22 14:50:35 -040033#include <linux/mtd/rawnand.h>
William Juul52c07962007-10-31 13:53:06 +010034#include <asm/io.h>
Sergey Kubushyne8f39122007-08-10 20:26:18 +020035#include <nand.h>
Bartosz Golaszewski8a14dfe2019-07-29 08:58:03 +020036#include <dm/uclass.h>
Khoronzhuk, Ivan753a00a2014-06-07 04:22:52 +030037#include <asm/ti-common/davinci_nand.h>
Sergey Kubushyne8f39122007-08-10 20:26:18 +020038
Sandeep Paulrajbfeb0fd2009-08-18 10:10:42 -040039/* Definitions for 4-bit hardware ECC */
40#define NAND_TIMEOUT 10240
41#define NAND_ECC_BUSY 0xC
42#define NAND_4BITECC_MASK 0x03FF03FF
Wolfgang Denk62fb2b42021-09-27 17:42:39 +020043#define EMIF_NANDFSR_ECC_STATE_MASK 0x00000F00
Sandeep Paulrajbfeb0fd2009-08-18 10:10:42 -040044#define ECC_STATE_NO_ERR 0x0
45#define ECC_STATE_TOO_MANY_ERRS 0x1
46#define ECC_STATE_ERR_CORR_COMP_P 0x2
47#define ECC_STATE_ERR_CORR_COMP_N 0x3
48
Nick Thompson27794722009-12-16 11:15:58 +000049/*
50 * Exploit the little endianness of the ARM to do multi-byte transfers
51 * per device read. This can perform over twice as quickly as individual
52 * byte transfers when buffer alignment is conducive.
53 *
54 * NOTE: This only works if the NAND is not connected to the 2 LSBs of
55 * the address bus. On Davinci EVM platforms this has always been true.
56 */
57static void nand_davinci_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
58{
Scott Wood17fed142016-05-30 13:57:56 -050059 struct nand_chip *chip = mtd_to_nand(mtd);
Nick Thompson27794722009-12-16 11:15:58 +000060 const u32 *nand = chip->IO_ADDR_R;
61
62 /* Make sure that buf is 32 bit aligned */
63 if (((int)buf & 0x3) != 0) {
64 if (((int)buf & 0x1) != 0) {
65 if (len) {
66 *buf = readb(nand);
67 buf += 1;
68 len--;
69 }
70 }
71
72 if (((int)buf & 0x3) != 0) {
73 if (len >= 2) {
74 *(u16 *)buf = readw(nand);
75 buf += 2;
76 len -= 2;
77 }
78 }
79 }
80
81 /* copy aligned data */
82 while (len >= 4) {
Cyril Chemparathyc4e72242010-03-17 10:03:10 -040083 *(u32 *)buf = __raw_readl(nand);
Nick Thompson27794722009-12-16 11:15:58 +000084 buf += 4;
85 len -= 4;
86 }
87
88 /* mop up any remaining bytes */
89 if (len) {
90 if (len >= 2) {
91 *(u16 *)buf = readw(nand);
92 buf += 2;
93 len -= 2;
94 }
95
96 if (len)
97 *buf = readb(nand);
98 }
99}
100
101static void nand_davinci_write_buf(struct mtd_info *mtd, const uint8_t *buf,
102 int len)
103{
Scott Wood17fed142016-05-30 13:57:56 -0500104 struct nand_chip *chip = mtd_to_nand(mtd);
Nick Thompson27794722009-12-16 11:15:58 +0000105 const u32 *nand = chip->IO_ADDR_W;
106
107 /* Make sure that buf is 32 bit aligned */
108 if (((int)buf & 0x3) != 0) {
109 if (((int)buf & 0x1) != 0) {
110 if (len) {
111 writeb(*buf, nand);
112 buf += 1;
113 len--;
114 }
115 }
116
117 if (((int)buf & 0x3) != 0) {
118 if (len >= 2) {
119 writew(*(u16 *)buf, nand);
120 buf += 2;
121 len -= 2;
122 }
123 }
124 }
125
126 /* copy aligned data */
127 while (len >= 4) {
Cyril Chemparathyc4e72242010-03-17 10:03:10 -0400128 __raw_writel(*(u32 *)buf, nand);
Nick Thompson27794722009-12-16 11:15:58 +0000129 buf += 4;
130 len -= 4;
131 }
132
133 /* mop up any remaining bytes */
134 if (len) {
135 if (len >= 2) {
136 writew(*(u16 *)buf, nand);
137 buf += 2;
138 len -= 2;
139 }
140
141 if (len)
142 writeb(*buf, nand);
143 }
144}
145
Cyril Chemparathyc4e72242010-03-17 10:03:10 -0400146static void nand_davinci_hwcontrol(struct mtd_info *mtd, int cmd,
147 unsigned int ctrl)
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200148{
Scott Wood17fed142016-05-30 13:57:56 -0500149 struct nand_chip *this = mtd_to_nand(mtd);
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200150 u_int32_t IO_ADDR_W = (u_int32_t)this->IO_ADDR_W;
151
William Juul52c07962007-10-31 13:53:06 +0100152 if (ctrl & NAND_CTRL_CHANGE) {
Nick Thompson27794722009-12-16 11:15:58 +0000153 IO_ADDR_W &= ~(MASK_ALE|MASK_CLE);
154
Cyril Chemparathyc4e72242010-03-17 10:03:10 -0400155 if (ctrl & NAND_CLE)
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200156 IO_ADDR_W |= MASK_CLE;
Cyril Chemparathyc4e72242010-03-17 10:03:10 -0400157 if (ctrl & NAND_ALE)
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200158 IO_ADDR_W |= MASK_ALE;
William Juul52c07962007-10-31 13:53:06 +0100159 this->IO_ADDR_W = (void __iomem *) IO_ADDR_W;
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200160 }
161
William Juul9e9c2c12007-11-09 13:32:30 +0100162 if (cmd != NAND_CMD_NONE)
Nick Thompson27794722009-12-16 11:15:58 +0000163 writeb(cmd, IO_ADDR_W);
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200164}
165
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200166#ifdef CONFIG_SYS_NAND_HW_ECC
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200167
Laurence Withers0357a762011-09-26 16:02:30 +0000168static u_int32_t nand_davinci_readecc(struct mtd_info *mtd)
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200169{
Laurence Withers0357a762011-09-26 16:02:30 +0000170 u_int32_t ecc = 0;
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200171
Laurence Withers0357a762011-09-26 16:02:30 +0000172 ecc = __raw_readl(&(davinci_emif_regs->nandfecc[
Cyril Chemparathyc4e72242010-03-17 10:03:10 -0400173 CONFIG_SYS_NAND_CS - 2]));
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200174
Laurence Withers0357a762011-09-26 16:02:30 +0000175 return ecc;
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200176}
177
Laurence Withers0357a762011-09-26 16:02:30 +0000178static void nand_davinci_enable_hwecc(struct mtd_info *mtd, int mode)
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200179{
Laurence Withers0357a762011-09-26 16:02:30 +0000180 u_int32_t val;
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200181
Laurence Withers0357a762011-09-26 16:02:30 +0000182 /* reading the ECC result register resets the ECC calculation */
183 nand_davinci_readecc(mtd);
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200184
Laurence Withers0357a762011-09-26 16:02:30 +0000185 val = __raw_readl(&davinci_emif_regs->nandfcr);
186 val |= DAVINCI_NANDFCR_NAND_ENABLE(CONFIG_SYS_NAND_CS);
187 val |= DAVINCI_NANDFCR_1BIT_ECC_START(CONFIG_SYS_NAND_CS);
188 __raw_writel(val, &davinci_emif_regs->nandfcr);
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200189}
190
Cyril Chemparathyc4e72242010-03-17 10:03:10 -0400191static int nand_davinci_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
192 u_char *ecc_code)
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200193{
194 u_int32_t tmp;
Hugo Villeneuve73dc0e42008-08-30 17:06:55 -0400195
Laurence Withers0357a762011-09-26 16:02:30 +0000196 tmp = nand_davinci_readecc(mtd);
Hugo Villeneuve73dc0e42008-08-30 17:06:55 -0400197
198 /* Squeeze 4 bytes ECC into 3 bytes by removing RESERVED bits
199 * and shifting. RESERVED bits are 31 to 28 and 15 to 12. */
200 tmp = (tmp & 0x00000fff) | ((tmp & 0x0fff0000) >> 4);
201
202 /* Invert so that erased block ECC is correct */
203 tmp = ~tmp;
204
205 *ecc_code++ = tmp;
206 *ecc_code++ = tmp >> 8;
207 *ecc_code++ = tmp >> 16;
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200208
David Brownell962d4c12009-04-28 13:19:53 -0700209 /* NOTE: the above code matches mainline Linux:
210 * .PQR.stu ==> ~PQRstu
211 *
212 * MontaVista/TI kernels encode those bytes differently, use
213 * complicated (and allegedly sometimes-wrong) correction code,
214 * and usually shipped with U-Boot that uses software ECC:
215 * .PQR.stu ==> PsQRtu
216 *
217 * If you need MV/TI compatible NAND I/O in U-Boot, it should
218 * be possible to (a) change the mangling above, (b) reverse
219 * that mangling in nand_davinci_correct_data() below.
220 */
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200221
David Brownell962d4c12009-04-28 13:19:53 -0700222 return 0;
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200223}
224
Cyril Chemparathyc4e72242010-03-17 10:03:10 -0400225static int nand_davinci_correct_data(struct mtd_info *mtd, u_char *dat,
226 u_char *read_ecc, u_char *calc_ecc)
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200227{
Scott Wood17fed142016-05-30 13:57:56 -0500228 struct nand_chip *this = mtd_to_nand(mtd);
Hugo Villeneuve73dc0e42008-08-30 17:06:55 -0400229 u_int32_t ecc_nand = read_ecc[0] | (read_ecc[1] << 8) |
230 (read_ecc[2] << 16);
231 u_int32_t ecc_calc = calc_ecc[0] | (calc_ecc[1] << 8) |
232 (calc_ecc[2] << 16);
233 u_int32_t diff = ecc_calc ^ ecc_nand;
234
235 if (diff) {
236 if ((((diff >> 12) ^ diff) & 0xfff) == 0xfff) {
237 /* Correctable error */
238 if ((diff >> (12 + 3)) < this->ecc.size) {
239 uint8_t find_bit = 1 << ((diff >> 12) & 7);
240 uint32_t find_byte = diff >> (12 + 3);
241
242 dat[find_byte] ^= find_bit;
Masahiro Yamadaf8a5d512017-10-18 00:10:48 +0900243 pr_debug("Correcting single "
Hugo Villeneuve73dc0e42008-08-30 17:06:55 -0400244 "bit ECC error at offset: %d, bit: "
245 "%d\n", find_byte, find_bit);
246 return 1;
247 } else {
Scott Wood52ab7ce2016-05-30 13:57:58 -0500248 return -EBADMSG;
Hugo Villeneuve73dc0e42008-08-30 17:06:55 -0400249 }
250 } else if (!(diff & (diff - 1))) {
251 /* Single bit ECC error in the ECC itself,
252 nothing to fix */
Masahiro Yamadaf8a5d512017-10-18 00:10:48 +0900253 pr_debug("Single bit ECC error in " "ECC.\n");
Hugo Villeneuve73dc0e42008-08-30 17:06:55 -0400254 return 1;
255 } else {
256 /* Uncorrectable error */
Masahiro Yamadaf8a5d512017-10-18 00:10:48 +0900257 pr_debug("ECC UNCORRECTED_ERROR 1\n");
Scott Wood52ab7ce2016-05-30 13:57:58 -0500258 return -EBADMSG;
Hugo Villeneuve73dc0e42008-08-30 17:06:55 -0400259 }
260 }
Cyril Chemparathyc4e72242010-03-17 10:03:10 -0400261 return 0;
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200262}
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200263#endif /* CONFIG_SYS_NAND_HW_ECC */
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200264
Sandeep Paulrajbfeb0fd2009-08-18 10:10:42 -0400265#ifdef CONFIG_SYS_NAND_4BIT_HW_ECC_OOBFIRST
266static struct nand_ecclayout nand_davinci_4bit_layout_oobfirst = {
Sandeep Paulrajd3482862009-11-19 23:04:42 -0500267#if defined(CONFIG_SYS_NAND_PAGE_2K)
Sandeep Paulrajbfeb0fd2009-08-18 10:10:42 -0400268 .eccbytes = 40,
Heiko Schocher56596e12013-09-06 05:21:23 +0200269#ifdef CONFIG_NAND_6BYTES_OOB_FREE_10BYTES_ECC
270 .eccpos = {
271 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
272 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
273 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
274 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
275 },
276 .oobfree = {
277 {2, 4}, {16, 6}, {32, 6}, {48, 6},
278 },
279#else
Sandeep Paulrajbfeb0fd2009-08-18 10:10:42 -0400280 .eccpos = {
281 24, 25, 26, 27, 28,
282 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
283 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
284 49, 50, 51, 52, 53, 54, 55, 56, 57, 58,
285 59, 60, 61, 62, 63,
286 },
287 .oobfree = {
288 {.offset = 2, .length = 22, },
289 },
Heiko Schocher56596e12013-09-06 05:21:23 +0200290#endif /* #ifdef CONFIG_NAND_6BYTES_OOB_FREE_10BYTES_ECC */
Sandeep Paulrajd3482862009-11-19 23:04:42 -0500291#elif defined(CONFIG_SYS_NAND_PAGE_4K)
292 .eccbytes = 80,
293 .eccpos = {
294 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
295 58, 59, 60, 61, 62, 63, 64, 65, 66, 67,
296 68, 69, 70, 71, 72, 73, 74, 75, 76, 77,
297 78, 79, 80, 81, 82, 83, 84, 85, 86, 87,
298 88, 89, 90, 91, 92, 93, 94, 95, 96, 97,
299 98, 99, 100, 101, 102, 103, 104, 105, 106, 107,
300 108, 109, 110, 111, 112, 113, 114, 115, 116, 117,
301 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
302 },
303 .oobfree = {
304 {.offset = 2, .length = 46, },
305 },
Sandeep Paulrajbfeb0fd2009-08-18 10:10:42 -0400306#endif
307};
Sandeep Paulrajbfeb0fd2009-08-18 10:10:42 -0400308
Khoronzhuk, Ivan2f64e472014-07-04 15:03:25 +0300309#if defined CONFIG_KEYSTONE_RBL_NAND
Khoronzhuk, Ivan2f64e472014-07-04 15:03:25 +0300310static struct nand_ecclayout nand_keystone_rbl_4bit_layout_oobfirst = {
Khoronzhuk, Ivan9016c6f2014-09-02 00:20:02 +0300311#if defined(CONFIG_SYS_NAND_PAGE_2K)
Khoronzhuk, Ivan2f64e472014-07-04 15:03:25 +0300312 .eccbytes = 40,
313 .eccpos = {
314 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
315 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
316 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
317 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
318 },
319 .oobfree = {
320 {.offset = 2, .length = 4, },
321 {.offset = 16, .length = 6, },
322 {.offset = 32, .length = 6, },
323 {.offset = 48, .length = 6, },
324 },
325#elif defined(CONFIG_SYS_NAND_PAGE_4K)
326 .eccbytes = 80,
327 .eccpos = {
328 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
329 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
330 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
331 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
332 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
333 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
334 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
335 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
336 },
337 .oobfree = {
338 {.offset = 2, .length = 4, },
339 {.offset = 16, .length = 6, },
340 {.offset = 32, .length = 6, },
341 {.offset = 48, .length = 6, },
342 {.offset = 64, .length = 6, },
343 {.offset = 80, .length = 6, },
344 {.offset = 96, .length = 6, },
345 {.offset = 112, .length = 6, },
346 },
347#endif
348};
349
350#ifdef CONFIG_SYS_NAND_PAGE_2K
Tom Rinidada0e32021-09-12 20:32:24 -0400351#define KEYSTONE_NAND_MAX_RBL_PAGE (0x100000 >> 11)
Khoronzhuk, Ivan2f64e472014-07-04 15:03:25 +0300352#elif defined(CONFIG_SYS_NAND_PAGE_4K)
Tom Rinidada0e32021-09-12 20:32:24 -0400353#define KEYSTONE_NAND_MAX_RBL_PAGE (0x100000 >> 12)
Khoronzhuk, Ivan2f64e472014-07-04 15:03:25 +0300354#endif
355
356/**
357 * nand_davinci_write_page - write one page
358 * @mtd: MTD device structure
359 * @chip: NAND chip descriptor
360 * @buf: the data to write
361 * @oob_required: must write chip->oob_poi to OOB
362 * @page: page number to write
Khoronzhuk, Ivan2f64e472014-07-04 15:03:25 +0300363 * @raw: use _raw version of write_page
364 */
365static int nand_davinci_write_page(struct mtd_info *mtd, struct nand_chip *chip,
Khoronzhuk, Ivand5c65802014-09-06 22:17:07 +0300366 uint32_t offset, int data_len,
Khoronzhuk, Ivan2f64e472014-07-04 15:03:25 +0300367 const uint8_t *buf, int oob_required,
Boris Brezillonb9bf43c2017-11-22 02:38:24 +0900368 int page, int raw)
Khoronzhuk, Ivan2f64e472014-07-04 15:03:25 +0300369{
370 int status;
371 int ret = 0;
372 struct nand_ecclayout *saved_ecc_layout;
373
374 /* save current ECC layout and assign Keystone RBL ECC layout */
Tom Rinidada0e32021-09-12 20:32:24 -0400375 if (page < KEYSTONE_NAND_MAX_RBL_PAGE) {
Khoronzhuk, Ivan2f64e472014-07-04 15:03:25 +0300376 saved_ecc_layout = chip->ecc.layout;
377 chip->ecc.layout = &nand_keystone_rbl_4bit_layout_oobfirst;
378 mtd->oobavail = chip->ecc.layout->oobavail;
379 }
380
381 chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page);
382
Scott Wood46e13102016-05-30 13:57:57 -0500383 if (unlikely(raw)) {
384 status = chip->ecc.write_page_raw(mtd, chip, buf,
385 oob_required, page);
386 } else {
387 status = chip->ecc.write_page(mtd, chip, buf,
388 oob_required, page);
389 }
Khoronzhuk, Ivan2f64e472014-07-04 15:03:25 +0300390
391 if (status < 0) {
392 ret = status;
393 goto err;
394 }
395
396 chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
397 status = chip->waitfunc(mtd, chip);
398
Khoronzhuk, Ivan2f64e472014-07-04 15:03:25 +0300399 if (status & NAND_STATUS_FAIL) {
400 ret = -EIO;
401 goto err;
402 }
403
Khoronzhuk, Ivan2f64e472014-07-04 15:03:25 +0300404err:
405 /* restore ECC layout */
Tom Rinidada0e32021-09-12 20:32:24 -0400406 if (page < KEYSTONE_NAND_MAX_RBL_PAGE) {
Khoronzhuk, Ivan2f64e472014-07-04 15:03:25 +0300407 chip->ecc.layout = saved_ecc_layout;
408 mtd->oobavail = saved_ecc_layout->oobavail;
409 }
410
411 return ret;
412}
413
414/**
415 * nand_davinci_read_page_hwecc - hardware ECC based page read function
416 * @mtd: mtd info structure
417 * @chip: nand chip info structure
418 * @buf: buffer to store read data
419 * @oob_required: caller requires OOB data read to chip->oob_poi
420 * @page: page number to read
421 *
422 * Not for syndrome calculating ECC controllers which need a special oob layout.
423 */
424static int nand_davinci_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
425 uint8_t *buf, int oob_required, int page)
426{
427 int i, eccsize = chip->ecc.size;
428 int eccbytes = chip->ecc.bytes;
429 int eccsteps = chip->ecc.steps;
430 uint32_t *eccpos;
431 uint8_t *p = buf;
432 uint8_t *ecc_code = chip->buffers->ecccode;
433 uint8_t *ecc_calc = chip->buffers->ecccalc;
434 struct nand_ecclayout *saved_ecc_layout = chip->ecc.layout;
435
436 /* save current ECC layout and assign Keystone RBL ECC layout */
Tom Rinidada0e32021-09-12 20:32:24 -0400437 if (page < KEYSTONE_NAND_MAX_RBL_PAGE) {
Khoronzhuk, Ivan2f64e472014-07-04 15:03:25 +0300438 chip->ecc.layout = &nand_keystone_rbl_4bit_layout_oobfirst;
439 mtd->oobavail = chip->ecc.layout->oobavail;
440 }
441
442 eccpos = chip->ecc.layout->eccpos;
443
444 /* Read the OOB area first */
445 chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page);
446 chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
447 chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page);
448
449 for (i = 0; i < chip->ecc.total; i++)
450 ecc_code[i] = chip->oob_poi[eccpos[i]];
451
452 for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
453 int stat;
454
455 chip->ecc.hwctl(mtd, NAND_ECC_READ);
456 chip->read_buf(mtd, p, eccsize);
457 chip->ecc.calculate(mtd, p, &ecc_calc[i]);
458
459 stat = chip->ecc.correct(mtd, p, &ecc_code[i], NULL);
460 if (stat < 0)
461 mtd->ecc_stats.failed++;
462 else
463 mtd->ecc_stats.corrected += stat;
464 }
465
466 /* restore ECC layout */
Tom Rinidada0e32021-09-12 20:32:24 -0400467 if (page < KEYSTONE_NAND_MAX_RBL_PAGE) {
Khoronzhuk, Ivan2f64e472014-07-04 15:03:25 +0300468 chip->ecc.layout = saved_ecc_layout;
469 mtd->oobavail = saved_ecc_layout->oobavail;
470 }
471
472 return 0;
473}
474#endif /* CONFIG_KEYSTONE_RBL_NAND */
475
Sandeep Paulrajbfeb0fd2009-08-18 10:10:42 -0400476static void nand_davinci_4bit_enable_hwecc(struct mtd_info *mtd, int mode)
477{
478 u32 val;
479
480 switch (mode) {
481 case NAND_ECC_WRITE:
482 case NAND_ECC_READ:
483 /*
484 * Start a new ECC calculation for reading or writing 512 bytes
485 * of data.
486 */
Cyril Chemparathyc4e72242010-03-17 10:03:10 -0400487 val = __raw_readl(&davinci_emif_regs->nandfcr);
Nick Thompson789c8872009-12-12 12:12:26 -0500488 val &= ~DAVINCI_NANDFCR_4BIT_ECC_SEL_MASK;
Nick Thompsonff641522009-12-12 12:13:10 -0500489 val |= DAVINCI_NANDFCR_NAND_ENABLE(CONFIG_SYS_NAND_CS);
Nick Thompson789c8872009-12-12 12:12:26 -0500490 val |= DAVINCI_NANDFCR_4BIT_ECC_SEL(CONFIG_SYS_NAND_CS);
491 val |= DAVINCI_NANDFCR_4BIT_ECC_START;
Cyril Chemparathyc4e72242010-03-17 10:03:10 -0400492 __raw_writel(val, &davinci_emif_regs->nandfcr);
Sandeep Paulrajbfeb0fd2009-08-18 10:10:42 -0400493 break;
494 case NAND_ECC_READSYN:
Cyril Chemparathyc4e72242010-03-17 10:03:10 -0400495 val = __raw_readl(&davinci_emif_regs->nand4bitecc[0]);
Sandeep Paulrajbfeb0fd2009-08-18 10:10:42 -0400496 break;
497 default:
498 break;
499 }
500}
501
502static u32 nand_davinci_4bit_readecc(struct mtd_info *mtd, unsigned int ecc[4])
503{
Cyril Chemparathyc4e72242010-03-17 10:03:10 -0400504 int i;
505
506 for (i = 0; i < 4; i++) {
507 ecc[i] = __raw_readl(&davinci_emif_regs->nand4bitecc[i]) &
508 NAND_4BITECC_MASK;
509 }
Sandeep Paulrajbfeb0fd2009-08-18 10:10:42 -0400510
511 return 0;
512}
513
514static int nand_davinci_4bit_calculate_ecc(struct mtd_info *mtd,
515 const uint8_t *dat,
516 uint8_t *ecc_code)
517{
Nick Thompson27794722009-12-16 11:15:58 +0000518 unsigned int hw_4ecc[4];
519 unsigned int i;
Sandeep Paulrajbfeb0fd2009-08-18 10:10:42 -0400520
521 nand_davinci_4bit_readecc(mtd, hw_4ecc);
522
523 /*Convert 10 bit ecc value to 8 bit */
Nick Thompson27794722009-12-16 11:15:58 +0000524 for (i = 0; i < 2; i++) {
525 unsigned int hw_ecc_low = hw_4ecc[i * 2];
526 unsigned int hw_ecc_hi = hw_4ecc[(i * 2) + 1];
Sandeep Paulrajbfeb0fd2009-08-18 10:10:42 -0400527
528 /* Take first 8 bits from val1 (count1=0) or val5 (count1=1) */
Nick Thompson27794722009-12-16 11:15:58 +0000529 *ecc_code++ = hw_ecc_low & 0xFF;
Sandeep Paulrajbfeb0fd2009-08-18 10:10:42 -0400530
531 /*
532 * Take 2 bits as LSB bits from val1 (count1=0) or val5
533 * (count1=1) and 6 bits from val2 (count1=0) or
534 * val5 (count1=1)
535 */
Nick Thompson27794722009-12-16 11:15:58 +0000536 *ecc_code++ =
537 ((hw_ecc_low >> 8) & 0x3) | ((hw_ecc_low >> 14) & 0xFC);
Sandeep Paulrajbfeb0fd2009-08-18 10:10:42 -0400538
539 /*
540 * Take 4 bits from val2 (count1=0) or val5 (count1=1) and
541 * 4 bits from val3 (count1=0) or val6 (count1=1)
542 */
Nick Thompson27794722009-12-16 11:15:58 +0000543 *ecc_code++ =
544 ((hw_ecc_low >> 22) & 0xF) | ((hw_ecc_hi << 4) & 0xF0);
Sandeep Paulrajbfeb0fd2009-08-18 10:10:42 -0400545
546 /*
547 * Take 6 bits from val3(count1=0) or val6 (count1=1) and
548 * 2 bits from val4 (count1=0) or val7 (count1=1)
549 */
Nick Thompson27794722009-12-16 11:15:58 +0000550 *ecc_code++ =
551 ((hw_ecc_hi >> 4) & 0x3F) | ((hw_ecc_hi >> 10) & 0xC0);
Sandeep Paulrajbfeb0fd2009-08-18 10:10:42 -0400552
553 /* Take 8 bits from val4 (count1=0) or val7 (count1=1) */
Nick Thompson27794722009-12-16 11:15:58 +0000554 *ecc_code++ = (hw_ecc_hi >> 18) & 0xFF;
Sandeep Paulrajbfeb0fd2009-08-18 10:10:42 -0400555 }
Nick Thompson27794722009-12-16 11:15:58 +0000556
Sandeep Paulrajbfeb0fd2009-08-18 10:10:42 -0400557 return 0;
558}
559
Sandeep Paulrajbfeb0fd2009-08-18 10:10:42 -0400560static int nand_davinci_4bit_correct_data(struct mtd_info *mtd, uint8_t *dat,
561 uint8_t *read_ecc, uint8_t *calc_ecc)
562{
Sandeep Paulrajbfeb0fd2009-08-18 10:10:42 -0400563 int i;
Nick Thompson27794722009-12-16 11:15:58 +0000564 unsigned int hw_4ecc[4];
565 unsigned int iserror;
566 unsigned short *ecc16;
Sandeep Paulrajbfeb0fd2009-08-18 10:10:42 -0400567 unsigned int numerrors, erroraddress, errorvalue;
568 u32 val;
569
570 /*
571 * Check for an ECC where all bytes are 0xFF. If this is the case, we
572 * will assume we are looking at an erased page and we should ignore
573 * the ECC.
574 */
575 for (i = 0; i < 10; i++) {
576 if (read_ecc[i] != 0xFF)
577 break;
578 }
579 if (i == 10)
580 return 0;
581
582 /* Convert 8 bit in to 10 bit */
Nick Thompson27794722009-12-16 11:15:58 +0000583 ecc16 = (unsigned short *)&read_ecc[0];
Sandeep Paulrajbfeb0fd2009-08-18 10:10:42 -0400584
Nick Thompson27794722009-12-16 11:15:58 +0000585 /*
586 * Write the parity values in the NAND Flash 4-bit ECC Load register.
587 * Write each parity value one at a time starting from 4bit_ecc_val8
588 * to 4bit_ecc_val1.
589 */
Sandeep Paulrajbfeb0fd2009-08-18 10:10:42 -0400590
Nick Thompson27794722009-12-16 11:15:58 +0000591 /*Take 2 bits from 8th byte and 8 bits from 9th byte */
Cyril Chemparathyc4e72242010-03-17 10:03:10 -0400592 __raw_writel(((ecc16[4]) >> 6) & 0x3FF,
593 &davinci_emif_regs->nand4biteccload);
Sandeep Paulrajbfeb0fd2009-08-18 10:10:42 -0400594
Nick Thompson27794722009-12-16 11:15:58 +0000595 /* Take 4 bits from 7th byte and 6 bits from 8th byte */
Cyril Chemparathyc4e72242010-03-17 10:03:10 -0400596 __raw_writel((((ecc16[3]) >> 12) & 0xF) | ((((ecc16[4])) << 4) & 0x3F0),
597 &davinci_emif_regs->nand4biteccload);
Sandeep Paulrajbfeb0fd2009-08-18 10:10:42 -0400598
Nick Thompson27794722009-12-16 11:15:58 +0000599 /* Take 6 bits from 6th byte and 4 bits from 7th byte */
Cyril Chemparathyc4e72242010-03-17 10:03:10 -0400600 __raw_writel((ecc16[3] >> 2) & 0x3FF,
601 &davinci_emif_regs->nand4biteccload);
Sandeep Paulrajbfeb0fd2009-08-18 10:10:42 -0400602
603 /* Take 8 bits from 5th byte and 2 bits from 6th byte */
Cyril Chemparathyc4e72242010-03-17 10:03:10 -0400604 __raw_writel(((ecc16[2]) >> 8) | ((((ecc16[3])) << 8) & 0x300),
605 &davinci_emif_regs->nand4biteccload);
Sandeep Paulrajbfeb0fd2009-08-18 10:10:42 -0400606
Nick Thompson27794722009-12-16 11:15:58 +0000607 /*Take 2 bits from 3rd byte and 8 bits from 4th byte */
Cyril Chemparathyc4e72242010-03-17 10:03:10 -0400608 __raw_writel((((ecc16[1]) >> 14) & 0x3) | ((((ecc16[2])) << 2) & 0x3FC),
609 &davinci_emif_regs->nand4biteccload);
Sandeep Paulrajbfeb0fd2009-08-18 10:10:42 -0400610
Nick Thompson27794722009-12-16 11:15:58 +0000611 /* Take 4 bits form 2nd bytes and 6 bits from 3rd bytes */
Cyril Chemparathyc4e72242010-03-17 10:03:10 -0400612 __raw_writel(((ecc16[1]) >> 4) & 0x3FF,
613 &davinci_emif_regs->nand4biteccload);
Sandeep Paulrajbfeb0fd2009-08-18 10:10:42 -0400614
Nick Thompson27794722009-12-16 11:15:58 +0000615 /* Take 6 bits from 1st byte and 4 bits from 2nd byte */
Cyril Chemparathyc4e72242010-03-17 10:03:10 -0400616 __raw_writel((((ecc16[0]) >> 10) & 0x3F) | (((ecc16[1]) << 6) & 0x3C0),
617 &davinci_emif_regs->nand4biteccload);
Sandeep Paulrajbfeb0fd2009-08-18 10:10:42 -0400618
Nick Thompson27794722009-12-16 11:15:58 +0000619 /* Take 10 bits from 0th and 1st bytes */
Cyril Chemparathyc4e72242010-03-17 10:03:10 -0400620 __raw_writel((ecc16[0]) & 0x3FF,
621 &davinci_emif_regs->nand4biteccload);
Sandeep Paulrajbfeb0fd2009-08-18 10:10:42 -0400622
623 /*
624 * Perform a dummy read to the EMIF Revision Code and Status register.
625 * This is required to ensure time for syndrome calculation after
626 * writing the ECC values in previous step.
627 */
628
Cyril Chemparathyc4e72242010-03-17 10:03:10 -0400629 val = __raw_readl(&davinci_emif_regs->nandfsr);
Sandeep Paulrajbfeb0fd2009-08-18 10:10:42 -0400630
631 /*
632 * Read the syndrome from the NAND Flash 4-Bit ECC 1-4 registers.
633 * A syndrome value of 0 means no bit errors. If the syndrome is
634 * non-zero then go further otherwise return.
635 */
636 nand_davinci_4bit_readecc(mtd, hw_4ecc);
637
Nick Thompson27794722009-12-16 11:15:58 +0000638 if (!(hw_4ecc[0] | hw_4ecc[1] | hw_4ecc[2] | hw_4ecc[3]))
Sandeep Paulrajbfeb0fd2009-08-18 10:10:42 -0400639 return 0;
640
641 /*
642 * Clear any previous address calculation by doing a dummy read of an
643 * error address register.
644 */
Cyril Chemparathyc4e72242010-03-17 10:03:10 -0400645 val = __raw_readl(&davinci_emif_regs->nanderradd1);
Sandeep Paulrajbfeb0fd2009-08-18 10:10:42 -0400646
647 /*
648 * Set the addr_calc_st bit(bit no 13) in the NAND Flash Control
649 * register to 1.
650 */
Ben Gardinerdfd19ea2010-10-14 17:26:17 -0400651 __raw_writel(DAVINCI_NANDFCR_4BIT_CALC_START,
652 &davinci_emif_regs->nandfcr);
Sandeep Paulrajbfeb0fd2009-08-18 10:10:42 -0400653
654 /*
Wolfram Sang328d0552010-09-09 13:54:41 +0200655 * Wait for the corr_state field (bits 8 to 11) in the
656 * NAND Flash Status register to be not equal to 0x0, 0x1, 0x2, or 0x3.
657 * Otherwise ECC calculation has not even begun and the next loop might
658 * fail because of a false positive!
659 */
660 i = NAND_TIMEOUT;
661 do {
662 val = __raw_readl(&davinci_emif_regs->nandfsr);
663 val &= 0xc00;
664 i--;
665 } while ((i > 0) && !val);
666
667 /*
668 * Wait for the corr_state field (bits 8 to 11) in the
Sandeep Paulrajbfeb0fd2009-08-18 10:10:42 -0400669 * NAND Flash Status register to be equal to 0x0, 0x1, 0x2, or 0x3.
670 */
671 i = NAND_TIMEOUT;
672 do {
Cyril Chemparathyc4e72242010-03-17 10:03:10 -0400673 val = __raw_readl(&davinci_emif_regs->nandfsr);
Sandeep Paulrajbfeb0fd2009-08-18 10:10:42 -0400674 val &= 0xc00;
675 i--;
676 } while ((i > 0) && val);
677
Cyril Chemparathyc4e72242010-03-17 10:03:10 -0400678 iserror = __raw_readl(&davinci_emif_regs->nandfsr);
Sandeep Paulrajbfeb0fd2009-08-18 10:10:42 -0400679 iserror &= EMIF_NANDFSR_ECC_STATE_MASK;
680 iserror = iserror >> 8;
681
682 /*
683 * ECC_STATE_TOO_MANY_ERRS (0x1) means errors cannot be
684 * corrected (five or more errors). The number of errors
685 * calculated (err_num field) differs from the number of errors
686 * searched. ECC_STATE_ERR_CORR_COMP_P (0x2) means error
687 * correction complete (errors on bit 8 or 9).
688 * ECC_STATE_ERR_CORR_COMP_N (0x3) means error correction
689 * complete (error exists).
690 */
691
692 if (iserror == ECC_STATE_NO_ERR) {
Cyril Chemparathyc4e72242010-03-17 10:03:10 -0400693 val = __raw_readl(&davinci_emif_regs->nanderrval1);
Sandeep Paulrajbfeb0fd2009-08-18 10:10:42 -0400694 return 0;
695 } else if (iserror == ECC_STATE_TOO_MANY_ERRS) {
Cyril Chemparathyc4e72242010-03-17 10:03:10 -0400696 val = __raw_readl(&davinci_emif_regs->nanderrval1);
Scott Wood52ab7ce2016-05-30 13:57:58 -0500697 return -EBADMSG;
Sandeep Paulrajbfeb0fd2009-08-18 10:10:42 -0400698 }
699
Cyril Chemparathyc4e72242010-03-17 10:03:10 -0400700 numerrors = ((__raw_readl(&davinci_emif_regs->nandfsr) >> 16)
701 & 0x3) + 1;
Sandeep Paulrajbfeb0fd2009-08-18 10:10:42 -0400702
703 /* Read the error address, error value and correct */
704 for (i = 0; i < numerrors; i++) {
705 if (i > 1) {
706 erroraddress =
Cyril Chemparathyc4e72242010-03-17 10:03:10 -0400707 ((__raw_readl(&davinci_emif_regs->nanderradd2) >>
Sandeep Paulrajbfeb0fd2009-08-18 10:10:42 -0400708 (16 * (i & 1))) & 0x3FF);
709 erroraddress = ((512 + 7) - erroraddress);
710 errorvalue =
Cyril Chemparathyc4e72242010-03-17 10:03:10 -0400711 ((__raw_readl(&davinci_emif_regs->nanderrval2) >>
Sandeep Paulrajbfeb0fd2009-08-18 10:10:42 -0400712 (16 * (i & 1))) & 0xFF);
713 } else {
714 erroraddress =
Cyril Chemparathyc4e72242010-03-17 10:03:10 -0400715 ((__raw_readl(&davinci_emif_regs->nanderradd1) >>
Sandeep Paulrajbfeb0fd2009-08-18 10:10:42 -0400716 (16 * (i & 1))) & 0x3FF);
717 erroraddress = ((512 + 7) - erroraddress);
718 errorvalue =
Cyril Chemparathyc4e72242010-03-17 10:03:10 -0400719 ((__raw_readl(&davinci_emif_regs->nanderrval1) >>
Sandeep Paulrajbfeb0fd2009-08-18 10:10:42 -0400720 (16 * (i & 1))) & 0xFF);
721 }
722 /* xor the corrupt data with error value */
723 if (erroraddress < 512)
724 dat[erroraddress] ^= errorvalue;
725 }
726
727 return numerrors;
728}
Scott Woodce630312009-09-28 16:33:18 -0500729#endif /* CONFIG_SYS_NAND_4BIT_HW_ECC_OOBFIRST */
Sandeep Paulrajbfeb0fd2009-08-18 10:10:42 -0400730
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200731static int nand_davinci_dev_ready(struct mtd_info *mtd)
732{
Cyril Chemparathyc4e72242010-03-17 10:03:10 -0400733 return __raw_readl(&davinci_emif_regs->nandfsr) & 0x1;
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200734}
735
Bartosz Golaszewski2d4e3302019-07-29 08:58:02 +0200736static void davinci_nand_init(struct nand_chip *nand)
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200737{
Khoronzhuk, Ivan2f64e472014-07-04 15:03:25 +0300738#if defined CONFIG_KEYSTONE_RBL_NAND
739 int i;
740 struct nand_ecclayout *layout;
741
742 layout = &nand_keystone_rbl_4bit_layout_oobfirst;
743 layout->oobavail = 0;
Heinrich Schuchardt397b0622019-07-30 23:29:21 +0200744 for (i = 0; i < ARRAY_SIZE(layout->oobfree) &&
745 layout->oobfree[i].length; i++)
Khoronzhuk, Ivan2f64e472014-07-04 15:03:25 +0300746 layout->oobavail += layout->oobfree[i].length;
747
748 nand->write_page = nand_davinci_write_page;
749 nand->ecc.read_page = nand_davinci_read_page_hwecc;
750#endif
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200751 nand->chip_delay = 0;
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200752#ifdef CONFIG_SYS_NAND_USE_FLASH_BBT
Sergey Lapin3a38a552013-01-14 03:46:50 +0000753 nand->bbt_options |= NAND_BBT_USE_FLASH;
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200754#endif
Karicheri, Muralidharanc1dc61b2014-04-04 13:16:50 -0400755#ifdef CONFIG_SYS_NAND_NO_SUBPAGE_WRITE
756 nand->options |= NAND_NO_SUBPAGE_WRITE;
757#endif
Fabien Parentddc00942016-11-29 14:31:29 +0100758#ifdef CONFIG_SYS_NAND_BUSWIDTH_16BIT
759 nand->options |= NAND_BUSWIDTH_16;
760#endif
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200761#ifdef CONFIG_SYS_NAND_HW_ECC
William Juul9e9c2c12007-11-09 13:32:30 +0100762 nand->ecc.mode = NAND_ECC_HW;
William Juul9e9c2c12007-11-09 13:32:30 +0100763 nand->ecc.size = 512;
764 nand->ecc.bytes = 3;
Sergey Lapin3a38a552013-01-14 03:46:50 +0000765 nand->ecc.strength = 1;
William Juul52c07962007-10-31 13:53:06 +0100766 nand->ecc.calculate = nand_davinci_calculate_ecc;
767 nand->ecc.correct = nand_davinci_correct_data;
William Juulb76ec382007-11-08 10:39:53 +0100768 nand->ecc.hwctl = nand_davinci_enable_hwecc;
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200769#else
William Juul9e9c2c12007-11-09 13:32:30 +0100770 nand->ecc.mode = NAND_ECC_SOFT;
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200771#endif /* CONFIG_SYS_NAND_HW_ECC */
Sandeep Paulrajbfeb0fd2009-08-18 10:10:42 -0400772#ifdef CONFIG_SYS_NAND_4BIT_HW_ECC_OOBFIRST
773 nand->ecc.mode = NAND_ECC_HW_OOB_FIRST;
774 nand->ecc.size = 512;
775 nand->ecc.bytes = 10;
Sergey Lapin3a38a552013-01-14 03:46:50 +0000776 nand->ecc.strength = 4;
Sandeep Paulrajbfeb0fd2009-08-18 10:10:42 -0400777 nand->ecc.calculate = nand_davinci_4bit_calculate_ecc;
778 nand->ecc.correct = nand_davinci_4bit_correct_data;
779 nand->ecc.hwctl = nand_davinci_4bit_enable_hwecc;
780 nand->ecc.layout = &nand_davinci_4bit_layout_oobfirst;
781#endif
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200782 /* Set address of hardware control function */
William Juul52c07962007-10-31 13:53:06 +0100783 nand->cmd_ctrl = nand_davinci_hwcontrol;
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200784
Nick Thompson27794722009-12-16 11:15:58 +0000785 nand->read_buf = nand_davinci_read_buf;
786 nand->write_buf = nand_davinci_write_buf;
787
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200788 nand->dev_ready = nand_davinci_dev_ready;
David Brownellf4b0b9d2009-05-10 15:43:01 -0700789}
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200790
Tom Rini98372452021-12-12 22:12:36 -0500791#if CONFIG_IS_ENABLED(SYS_NAND_SELF_INIT)
Bartosz Golaszewski8a14dfe2019-07-29 08:58:03 +0200792static int davinci_nand_probe(struct udevice *dev)
793{
794 struct nand_chip *nand = dev_get_priv(dev);
795 struct mtd_info *mtd = nand_to_mtd(nand);
796 int ret;
797
798 nand->IO_ADDR_R = (void __iomem *)CONFIG_SYS_NAND_BASE;
799 nand->IO_ADDR_W = (void __iomem *)CONFIG_SYS_NAND_BASE;
800
801 davinci_nand_init(nand);
802
803 ret = nand_scan(mtd, CONFIG_SYS_NAND_MAX_CHIPS);
804 if (ret)
805 return ret;
806
807 return nand_register(0, mtd);
808}
809
810static const struct udevice_id davinci_nand_ids[] = {
811 { .compatible = "ti,davinci-nand" },
812 { }
813};
814
815U_BOOT_DRIVER(davinci_nand) = {
816 .name = "davinci-nand",
817 .id = UCLASS_MTD,
818 .of_match = davinci_nand_ids,
819 .probe = davinci_nand_probe,
Simon Glass8a2b47f2020-12-03 16:55:17 -0700820 .priv_auto = sizeof(struct nand_chip),
Bartosz Golaszewski8a14dfe2019-07-29 08:58:03 +0200821};
822
823void board_nand_init(void)
824{
825 struct udevice *dev;
826 int ret;
David Brownellf4b0b9d2009-05-10 15:43:01 -0700827
Bartosz Golaszewski8a14dfe2019-07-29 08:58:03 +0200828 ret = uclass_get_device_by_driver(UCLASS_MTD,
Simon Glass65130cd2020-12-28 20:34:56 -0700829 DM_DRIVER_GET(davinci_nand), &dev);
Bartosz Golaszewski8a14dfe2019-07-29 08:58:03 +0200830 if (ret && ret != -ENODEV)
831 pr_err("Failed to initialize %s: %d\n", dev->name, ret);
832}
833#else
834int board_nand_init(struct nand_chip *chip) __attribute__((weak));
David Brownellf4b0b9d2009-05-10 15:43:01 -0700835int board_nand_init(struct nand_chip *chip)
836{
837 davinci_nand_init(chip);
838 return 0;
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200839}
Bartosz Golaszewski8a14dfe2019-07-29 08:58:03 +0200840#endif /* CONFIG_SYS_NAND_SELF_INIT */