blob: d2363a0662e274073679c1fcbac4a532acdb8b71 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +02002/*
Stefan Agner59ae13a2015-10-13 22:11:42 -07003 * Copyright 2009-2015 Freescale Semiconductor, Inc. and others
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +02004 *
5 * Description: MPC5125, VF610, MCF54418 and Kinetis K70 Nand driver.
6 * Ported to U-Boot by Stefan Agner
7 * Based on RFC driver posted on Kernel Mailing list by Bill Pringlemeir
8 * Jason ported to M54418TWR and MVFA5.
9 * Authors: Stefan Agner <stefan.agner@toradex.com>
10 * Bill Pringlemeir <bpringlemeir@nbsps.com>
11 * Shaohui Xie <b21989@freescale.com>
12 * Jason Jin <Jason.jin@freescale.com>
13 *
14 * Based on original driver mpc5121_nfc.c.
15 *
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +020016 * Limitations:
17 * - Untested on MPC5125 and M54418.
Stefan Agner59ae13a2015-10-13 22:11:42 -070018 * - DMA and pipelining not used.
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +020019 * - 2K pages or less.
Stefan Agner59ae13a2015-10-13 22:11:42 -070020 * - HW ECC: Only 2K page with 64+ OOB.
21 * - HW ECC: Only 24 and 32-bit error correction implemented.
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +020022 */
23
Tom Riniabb9a042024-05-18 20:20:43 -060024#include <common.h>
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +020025#include <malloc.h>
Simon Glass9bc15642020-02-03 07:36:16 -070026#include <dm/device_compat.h>
Simon Glassbdd5f812023-09-14 18:21:46 -060027#include <linux/printk.h>
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +020028
29#include <linux/mtd/mtd.h>
Masahiro Yamada2b7a8732017-11-30 13:45:24 +090030#include <linux/mtd/rawnand.h>
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +020031#include <linux/mtd/partitions.h>
32
33#include <nand.h>
34#include <errno.h>
35#include <asm/io.h>
Lukasz Majewskia8f1a672018-12-03 10:24:51 +010036#if CONFIG_NAND_VF610_NFC_DT
37#include <dm.h>
38#include <linux/io.h>
39#include <linux/ioport.h>
40#endif
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +020041
42/* Register Offsets */
43#define NFC_FLASH_CMD1 0x3F00
44#define NFC_FLASH_CMD2 0x3F04
45#define NFC_COL_ADDR 0x3F08
46#define NFC_ROW_ADDR 0x3F0c
47#define NFC_ROW_ADDR_INC 0x3F14
48#define NFC_FLASH_STATUS1 0x3F18
49#define NFC_FLASH_STATUS2 0x3F1c
50#define NFC_CACHE_SWAP 0x3F28
51#define NFC_SECTOR_SIZE 0x3F2c
52#define NFC_FLASH_CONFIG 0x3F30
53#define NFC_IRQ_STATUS 0x3F38
54
55/* Addresses for NFC MAIN RAM BUFFER areas */
56#define NFC_MAIN_AREA(n) ((n) * 0x1000)
57
58#define PAGE_2K 0x0800
59#define OOB_64 0x0040
Stefan Agner59ae13a2015-10-13 22:11:42 -070060#define OOB_MAX 0x0100
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +020061
62/*
63 * NFC_CMD2[CODE] values. See section:
64 * - 31.4.7 Flash Command Code Description, Vybrid manual
65 * - 23.8.6 Flash Command Sequencer, MPC5125 manual
66 *
67 * Briefly these are bitmasks of controller cycles.
68 */
69#define READ_PAGE_CMD_CODE 0x7EE0
Stefan Agner4ce682a2015-05-08 19:07:13 +020070#define READ_ONFI_PARAM_CMD_CODE 0x4860
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +020071#define PROGRAM_PAGE_CMD_CODE 0x7FC0
72#define ERASE_CMD_CODE 0x4EC0
73#define READ_ID_CMD_CODE 0x4804
74#define RESET_CMD_CODE 0x4040
75#define STATUS_READ_CMD_CODE 0x4068
76
77/* NFC ECC mode define */
78#define ECC_BYPASS 0
79#define ECC_45_BYTE 6
Stefan Agnerfe10d3f2015-05-08 19:07:12 +020080#define ECC_60_BYTE 7
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +020081
82/*** Register Mask and bit definitions */
83
84/* NFC_FLASH_CMD1 Field */
85#define CMD_BYTE2_MASK 0xFF000000
86#define CMD_BYTE2_SHIFT 24
87
88/* NFC_FLASH_CM2 Field */
89#define CMD_BYTE1_MASK 0xFF000000
90#define CMD_BYTE1_SHIFT 24
91#define CMD_CODE_MASK 0x00FFFF00
92#define CMD_CODE_SHIFT 8
93#define BUFNO_MASK 0x00000006
94#define BUFNO_SHIFT 1
95#define START_BIT (1<<0)
96
97/* NFC_COL_ADDR Field */
98#define COL_ADDR_MASK 0x0000FFFF
99#define COL_ADDR_SHIFT 0
100
101/* NFC_ROW_ADDR Field */
102#define ROW_ADDR_MASK 0x00FFFFFF
103#define ROW_ADDR_SHIFT 0
104#define ROW_ADDR_CHIP_SEL_RB_MASK 0xF0000000
105#define ROW_ADDR_CHIP_SEL_RB_SHIFT 28
106#define ROW_ADDR_CHIP_SEL_MASK 0x0F000000
107#define ROW_ADDR_CHIP_SEL_SHIFT 24
108
109/* NFC_FLASH_STATUS2 Field */
110#define STATUS_BYTE1_MASK 0x000000FF
111
112/* NFC_FLASH_CONFIG Field */
Tom Rini40a35f52021-08-19 13:56:20 -0400113#define CFG_ECC_SRAM_ADDR_MASK 0x7FC00000
114#define CFG_ECC_SRAM_ADDR_SHIFT 22
115#define CFG_ECC_SRAM_REQ_BIT (1<<21)
116#define CFG_DMA_REQ_BIT (1<<20)
117#define CFG_ECC_MODE_MASK 0x000E0000
118#define CFG_ECC_MODE_SHIFT 17
119#define CFG_FAST_FLASH_BIT (1<<16)
120#define CFG_16BIT (1<<7)
121#define CFG_BOOT_MODE_BIT (1<<6)
122#define CFG_ADDR_AUTO_INCR_BIT (1<<5)
123#define CFG_BUFNO_AUTO_INCR_BIT (1<<4)
124#define CFG_PAGE_CNT_MASK 0xF
125#define CFG_PAGE_CNT_SHIFT 0
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200126
127/* NFC_IRQ_STATUS Field */
128#define IDLE_IRQ_BIT (1<<29)
129#define IDLE_EN_BIT (1<<20)
130#define CMD_DONE_CLEAR_BIT (1<<18)
131#define IDLE_CLEAR_BIT (1<<17)
132
133#define NFC_TIMEOUT (1000)
134
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200135/*
Stefan Agner59ae13a2015-10-13 22:11:42 -0700136 * ECC status - seems to consume 8 bytes (double word). The documented
137 * status byte is located in the lowest byte of the second word (which is
138 * the 4th or 7th byte depending on endianness).
139 * Calculate an offset to store the ECC status at the end of the buffer.
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200140 */
Stefan Agner59ae13a2015-10-13 22:11:42 -0700141#define ECC_SRAM_ADDR (PAGE_2K + OOB_MAX - 8)
142
143#define ECC_STATUS 0x4
144#define ECC_STATUS_MASK 0x80
145#define ECC_STATUS_ERR_COUNT 0x3F
146
147enum vf610_nfc_alt_buf {
148 ALT_BUF_DATA = 0,
149 ALT_BUF_ID = 1,
150 ALT_BUF_STAT = 2,
151 ALT_BUF_ONFI = 3,
152};
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200153
154struct vf610_nfc {
Stefan Agner59ae13a2015-10-13 22:11:42 -0700155 struct nand_chip chip;
Sean Andersonf716c532020-09-15 10:44:51 -0400156 /* NULL without CONFIG_NAND_VF610_NFC_DT */
157 struct udevice *dev;
Stefan Agner59ae13a2015-10-13 22:11:42 -0700158 void __iomem *regs;
159 uint buf_offset;
160 int write_sz;
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200161 /* Status and ID are in alternate locations. */
Stefan Agner59ae13a2015-10-13 22:11:42 -0700162 enum vf610_nfc_alt_buf alt_buf;
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200163};
164
Scott Wood17fed142016-05-30 13:57:56 -0500165#define mtd_to_nfc(_mtd) nand_get_controller_data(mtd_to_nand(_mtd))
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200166
Stefan Agnerfe10d3f2015-05-08 19:07:12 +0200167#if defined(CONFIG_SYS_NAND_VF610_NFC_45_ECC_BYTES)
168#define ECC_HW_MODE ECC_45_BYTE
169
170static struct nand_ecclayout vf610_nfc_ecc = {
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200171 .eccbytes = 45,
172 .eccpos = {19, 20, 21, 22, 23,
173 24, 25, 26, 27, 28, 29, 30, 31,
174 32, 33, 34, 35, 36, 37, 38, 39,
175 40, 41, 42, 43, 44, 45, 46, 47,
176 48, 49, 50, 51, 52, 53, 54, 55,
177 56, 57, 58, 59, 60, 61, 62, 63},
178 .oobfree = {
Stefan Agner59ae13a2015-10-13 22:11:42 -0700179 {.offset = 2,
180 .length = 17} }
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200181};
Stefan Agnerfe10d3f2015-05-08 19:07:12 +0200182#elif defined(CONFIG_SYS_NAND_VF610_NFC_60_ECC_BYTES)
183#define ECC_HW_MODE ECC_60_BYTE
184
185static struct nand_ecclayout vf610_nfc_ecc = {
186 .eccbytes = 60,
187 .eccpos = { 4, 5, 6, 7, 8, 9, 10, 11,
188 12, 13, 14, 15, 16, 17, 18, 19,
189 20, 21, 22, 23, 24, 25, 26, 27,
190 28, 29, 30, 31, 32, 33, 34, 35,
191 36, 37, 38, 39, 40, 41, 42, 43,
192 44, 45, 46, 47, 48, 49, 50, 51,
193 52, 53, 54, 55, 56, 57, 58, 59,
194 60, 61, 62, 63 },
195 .oobfree = {
196 {.offset = 2,
197 .length = 2} }
198};
199#endif
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200200
201static inline u32 vf610_nfc_read(struct mtd_info *mtd, uint reg)
202{
203 struct vf610_nfc *nfc = mtd_to_nfc(mtd);
204
205 return readl(nfc->regs + reg);
206}
207
208static inline void vf610_nfc_write(struct mtd_info *mtd, uint reg, u32 val)
209{
210 struct vf610_nfc *nfc = mtd_to_nfc(mtd);
211
212 writel(val, nfc->regs + reg);
213}
214
215static inline void vf610_nfc_set(struct mtd_info *mtd, uint reg, u32 bits)
216{
217 vf610_nfc_write(mtd, reg, vf610_nfc_read(mtd, reg) | bits);
218}
219
220static inline void vf610_nfc_clear(struct mtd_info *mtd, uint reg, u32 bits)
221{
222 vf610_nfc_write(mtd, reg, vf610_nfc_read(mtd, reg) & ~bits);
223}
224
225static inline void vf610_nfc_set_field(struct mtd_info *mtd, u32 reg,
226 u32 mask, u32 shift, u32 val)
227{
228 vf610_nfc_write(mtd, reg,
229 (vf610_nfc_read(mtd, reg) & (~mask)) | val << shift);
230}
231
232static inline void vf610_nfc_memcpy(void *dst, const void *src, size_t n)
233{
234 /*
Stefan Agner59ae13a2015-10-13 22:11:42 -0700235 * Use this accessor for the internal SRAM buffers. On the ARM
236 * Freescale Vybrid SoC it's known that the driver can treat
237 * the SRAM buffer as if it's memory. Other platform might need
238 * to treat the buffers differently.
239 *
240 * For the time being, use memcpy
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200241 */
242 memcpy(dst, src, n);
243}
244
245/* Clear flags for upcoming command */
246static inline void vf610_nfc_clear_status(void __iomem *regbase)
247{
248 void __iomem *reg = regbase + NFC_IRQ_STATUS;
249 u32 tmp = __raw_readl(reg);
250 tmp |= CMD_DONE_CLEAR_BIT | IDLE_CLEAR_BIT;
251 __raw_writel(tmp, reg);
252}
253
254/* Wait for complete operation */
Stefan Agner59ae13a2015-10-13 22:11:42 -0700255static void vf610_nfc_done(struct mtd_info *mtd)
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200256{
257 struct vf610_nfc *nfc = mtd_to_nfc(mtd);
258 uint start;
259
260 /*
261 * Barrier is needed after this write. This write need
262 * to be done before reading the next register the first
263 * time.
264 * vf610_nfc_set implicates such a barrier by using writel
265 * to write to the register.
266 */
267 vf610_nfc_set(mtd, NFC_FLASH_CMD2, START_BIT);
268
269 start = get_timer(0);
270
271 while (!(vf610_nfc_read(mtd, NFC_IRQ_STATUS) & IDLE_IRQ_BIT)) {
272 if (get_timer(start) > NFC_TIMEOUT) {
Stefan Agner59ae13a2015-10-13 22:11:42 -0700273 printf("Timeout while waiting for IDLE.\n");
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200274 return;
275 }
276 }
277 vf610_nfc_clear_status(nfc->regs);
278}
279
280static u8 vf610_nfc_get_id(struct mtd_info *mtd, int col)
281{
282 u32 flash_id;
283
284 if (col < 4) {
285 flash_id = vf610_nfc_read(mtd, NFC_FLASH_STATUS1);
Stefan Agner59ae13a2015-10-13 22:11:42 -0700286 flash_id >>= (3 - col) * 8;
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200287 } else {
288 flash_id = vf610_nfc_read(mtd, NFC_FLASH_STATUS2);
Stefan Agner59ae13a2015-10-13 22:11:42 -0700289 flash_id >>= 24;
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200290 }
Stefan Agner59ae13a2015-10-13 22:11:42 -0700291
292 return flash_id & 0xff;
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200293}
294
295static u8 vf610_nfc_get_status(struct mtd_info *mtd)
296{
297 return vf610_nfc_read(mtd, NFC_FLASH_STATUS2) & STATUS_BYTE1_MASK;
298}
299
300/* Single command */
301static void vf610_nfc_send_command(void __iomem *regbase, u32 cmd_byte1,
302 u32 cmd_code)
303{
304 void __iomem *reg = regbase + NFC_FLASH_CMD2;
305 u32 tmp;
306 vf610_nfc_clear_status(regbase);
307
308 tmp = __raw_readl(reg);
309 tmp &= ~(CMD_BYTE1_MASK | CMD_CODE_MASK | BUFNO_MASK);
310 tmp |= cmd_byte1 << CMD_BYTE1_SHIFT;
311 tmp |= cmd_code << CMD_CODE_SHIFT;
312 __raw_writel(tmp, reg);
313}
314
315/* Two commands */
316static void vf610_nfc_send_commands(void __iomem *regbase, u32 cmd_byte1,
317 u32 cmd_byte2, u32 cmd_code)
318{
319 void __iomem *reg = regbase + NFC_FLASH_CMD1;
320 u32 tmp;
321 vf610_nfc_send_command(regbase, cmd_byte1, cmd_code);
322
323 tmp = __raw_readl(reg);
324 tmp &= ~CMD_BYTE2_MASK;
325 tmp |= cmd_byte2 << CMD_BYTE2_SHIFT;
326 __raw_writel(tmp, reg);
327}
328
329static void vf610_nfc_addr_cycle(struct mtd_info *mtd, int column, int page)
330{
331 if (column != -1) {
332 struct vf610_nfc *nfc = mtd_to_nfc(mtd);
Stefan Agner7056fee2015-05-08 19:07:09 +0200333 if (nfc->chip.options & NAND_BUSWIDTH_16)
334 column = column / 2;
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200335 vf610_nfc_set_field(mtd, NFC_COL_ADDR, COL_ADDR_MASK,
336 COL_ADDR_SHIFT, column);
337 }
338 if (page != -1)
339 vf610_nfc_set_field(mtd, NFC_ROW_ADDR, ROW_ADDR_MASK,
340 ROW_ADDR_SHIFT, page);
341}
342
Stefan Agner7056fee2015-05-08 19:07:09 +0200343static inline void vf610_nfc_ecc_mode(struct mtd_info *mtd, int ecc_mode)
344{
345 vf610_nfc_set_field(mtd, NFC_FLASH_CONFIG,
Tom Rini40a35f52021-08-19 13:56:20 -0400346 CFG_ECC_MODE_MASK,
347 CFG_ECC_MODE_SHIFT, ecc_mode);
Stefan Agner7056fee2015-05-08 19:07:09 +0200348}
349
Stefan Agner11f1fa02015-03-24 17:54:20 +0100350static inline void vf610_nfc_transfer_size(void __iomem *regbase, int size)
351{
352 __raw_writel(size, regbase + NFC_SECTOR_SIZE);
353}
354
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200355/* Send command to NAND chip */
356static void vf610_nfc_command(struct mtd_info *mtd, unsigned command,
357 int column, int page)
358{
359 struct vf610_nfc *nfc = mtd_to_nfc(mtd);
Stefan Agner59ae13a2015-10-13 22:11:42 -0700360 int trfr_sz = nfc->chip.options & NAND_BUSWIDTH_16 ? 1 : 0;
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200361
Stefan Agner59ae13a2015-10-13 22:11:42 -0700362 nfc->buf_offset = max(column, 0);
363 nfc->alt_buf = ALT_BUF_DATA;
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200364
365 switch (command) {
Stefan Agner04213412015-05-08 19:07:07 +0200366 case NAND_CMD_SEQIN:
367 /* Use valid column/page from preread... */
368 vf610_nfc_addr_cycle(mtd, column, page);
Stefan Agner59ae13a2015-10-13 22:11:42 -0700369 nfc->buf_offset = 0;
370
Stefan Agner04213412015-05-08 19:07:07 +0200371 /*
372 * SEQIN => data => PAGEPROG sequence is done by the controller
373 * hence we do not need to issue the command here...
374 */
375 return;
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200376 case NAND_CMD_PAGEPROG:
Stefan Agner59ae13a2015-10-13 22:11:42 -0700377 trfr_sz += nfc->write_sz;
378 vf610_nfc_ecc_mode(mtd, ECC_HW_MODE);
379 vf610_nfc_transfer_size(nfc->regs, trfr_sz);
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200380 vf610_nfc_send_commands(nfc->regs, NAND_CMD_SEQIN,
381 command, PROGRAM_PAGE_CMD_CODE);
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200382 break;
383
384 case NAND_CMD_RESET:
Stefan Agner11f1fa02015-03-24 17:54:20 +0100385 vf610_nfc_transfer_size(nfc->regs, 0);
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200386 vf610_nfc_send_command(nfc->regs, command, RESET_CMD_CODE);
387 break;
Stefan Agner7056fee2015-05-08 19:07:09 +0200388
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200389 case NAND_CMD_READOOB:
Stefan Agner59ae13a2015-10-13 22:11:42 -0700390 trfr_sz += mtd->oobsize;
Stefan Agner7056fee2015-05-08 19:07:09 +0200391 column = mtd->writesize;
Stefan Agner59ae13a2015-10-13 22:11:42 -0700392 vf610_nfc_transfer_size(nfc->regs, trfr_sz);
Stefan Agner7056fee2015-05-08 19:07:09 +0200393 vf610_nfc_send_commands(nfc->regs, NAND_CMD_READ0,
394 NAND_CMD_READSTART, READ_PAGE_CMD_CODE);
395 vf610_nfc_addr_cycle(mtd, column, page);
396 vf610_nfc_ecc_mode(mtd, ECC_BYPASS);
397 break;
398
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200399 case NAND_CMD_READ0:
Stefan Agner59ae13a2015-10-13 22:11:42 -0700400 trfr_sz += mtd->writesize + mtd->oobsize;
401 vf610_nfc_transfer_size(nfc->regs, trfr_sz);
402 vf610_nfc_ecc_mode(mtd, ECC_HW_MODE);
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200403 vf610_nfc_send_commands(nfc->regs, NAND_CMD_READ0,
404 NAND_CMD_READSTART, READ_PAGE_CMD_CODE);
405 vf610_nfc_addr_cycle(mtd, column, page);
406 break;
407
Stefan Agner4ce682a2015-05-08 19:07:13 +0200408 case NAND_CMD_PARAM:
409 nfc->alt_buf = ALT_BUF_ONFI;
Stefan Agner59ae13a2015-10-13 22:11:42 -0700410 trfr_sz = 3 * sizeof(struct nand_onfi_params);
411 vf610_nfc_transfer_size(nfc->regs, trfr_sz);
Stefan Agner4ce682a2015-05-08 19:07:13 +0200412 vf610_nfc_send_command(nfc->regs, NAND_CMD_PARAM,
413 READ_ONFI_PARAM_CMD_CODE);
414 vf610_nfc_set_field(mtd, NFC_ROW_ADDR, ROW_ADDR_MASK,
415 ROW_ADDR_SHIFT, column);
416 vf610_nfc_ecc_mode(mtd, ECC_BYPASS);
417 break;
418
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200419 case NAND_CMD_ERASE1:
Stefan Agner11f1fa02015-03-24 17:54:20 +0100420 vf610_nfc_transfer_size(nfc->regs, 0);
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200421 vf610_nfc_send_commands(nfc->regs, command,
422 NAND_CMD_ERASE2, ERASE_CMD_CODE);
423 vf610_nfc_addr_cycle(mtd, column, page);
424 break;
425
426 case NAND_CMD_READID:
427 nfc->alt_buf = ALT_BUF_ID;
Stefan Agner59ae13a2015-10-13 22:11:42 -0700428 nfc->buf_offset = 0;
Stefan Agner11f1fa02015-03-24 17:54:20 +0100429 vf610_nfc_transfer_size(nfc->regs, 0);
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200430 vf610_nfc_send_command(nfc->regs, command, READ_ID_CMD_CODE);
Stefan Agner4ce682a2015-05-08 19:07:13 +0200431 vf610_nfc_set_field(mtd, NFC_ROW_ADDR, ROW_ADDR_MASK,
432 ROW_ADDR_SHIFT, column);
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200433 break;
434
435 case NAND_CMD_STATUS:
436 nfc->alt_buf = ALT_BUF_STAT;
Stefan Agner11f1fa02015-03-24 17:54:20 +0100437 vf610_nfc_transfer_size(nfc->regs, 0);
Stefan Agner59ae13a2015-10-13 22:11:42 -0700438 vf610_nfc_send_command(nfc->regs, command, STATUS_READ_CMD_CODE);
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200439 break;
440 default:
441 return;
442 }
443
444 vf610_nfc_done(mtd);
Stefan Agner59ae13a2015-10-13 22:11:42 -0700445
446 nfc->write_sz = 0;
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200447}
448
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200449/* Read data from NFC buffers */
450static void vf610_nfc_read_buf(struct mtd_info *mtd, u_char *buf, int len)
451{
452 struct vf610_nfc *nfc = mtd_to_nfc(mtd);
Stefan Agner59ae13a2015-10-13 22:11:42 -0700453 uint c = nfc->buf_offset;
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200454
Stefan Agner4ce682a2015-05-08 19:07:13 +0200455 /* Alternate buffers are only supported through read_byte */
456 if (nfc->alt_buf)
457 return;
458
459 vf610_nfc_memcpy(buf, nfc->regs + NFC_MAIN_AREA(0) + c, len);
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200460
Stefan Agner59ae13a2015-10-13 22:11:42 -0700461 nfc->buf_offset += len;
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200462}
463
464/* Write data to NFC buffers */
Stefan Agner59ae13a2015-10-13 22:11:42 -0700465static void vf610_nfc_write_buf(struct mtd_info *mtd, const uint8_t *buf,
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200466 int len)
467{
468 struct vf610_nfc *nfc = mtd_to_nfc(mtd);
Stefan Agner59ae13a2015-10-13 22:11:42 -0700469 uint c = nfc->buf_offset;
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200470 uint l;
471
Stefan Agner59ae13a2015-10-13 22:11:42 -0700472 l = min_t(uint, len, mtd->writesize + mtd->oobsize - c);
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200473 vf610_nfc_memcpy(nfc->regs + NFC_MAIN_AREA(0) + c, buf, l);
Stefan Agner59ae13a2015-10-13 22:11:42 -0700474
475 nfc->write_sz += l;
476 nfc->buf_offset += l;
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200477}
478
479/* Read byte from NFC buffers */
Stefan Agner59ae13a2015-10-13 22:11:42 -0700480static uint8_t vf610_nfc_read_byte(struct mtd_info *mtd)
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200481{
Stefan Agner4ce682a2015-05-08 19:07:13 +0200482 struct vf610_nfc *nfc = mtd_to_nfc(mtd);
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200483 u8 tmp;
Stefan Agner59ae13a2015-10-13 22:11:42 -0700484 uint c = nfc->buf_offset;
Stefan Agner4ce682a2015-05-08 19:07:13 +0200485
486 switch (nfc->alt_buf) {
487 case ALT_BUF_ID:
488 tmp = vf610_nfc_get_id(mtd, c);
489 break;
490 case ALT_BUF_STAT:
491 tmp = vf610_nfc_get_status(mtd);
492 break;
Stefan Agner4ce682a2015-05-08 19:07:13 +0200493#ifdef __LITTLE_ENDIAN
Stefan Agner59ae13a2015-10-13 22:11:42 -0700494 case ALT_BUF_ONFI:
Stefan Agner4ce682a2015-05-08 19:07:13 +0200495 /* Reverse byte since the controller uses big endianness */
Stefan Agner59ae13a2015-10-13 22:11:42 -0700496 c = nfc->buf_offset ^ 0x3;
497 /* fall-through */
Stefan Agner4ce682a2015-05-08 19:07:13 +0200498#endif
499 default:
500 tmp = *((u8 *)(nfc->regs + NFC_MAIN_AREA(0) + c));
501 break;
502 }
Stefan Agner59ae13a2015-10-13 22:11:42 -0700503 nfc->buf_offset++;
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200504 return tmp;
505}
506
507/* Read word from NFC buffers */
508static u16 vf610_nfc_read_word(struct mtd_info *mtd)
509{
510 u16 tmp;
Stefan Agner59ae13a2015-10-13 22:11:42 -0700511
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200512 vf610_nfc_read_buf(mtd, (u_char *)&tmp, sizeof(tmp));
513 return tmp;
514}
515
516/* If not provided, upper layers apply a fixed delay. */
517static int vf610_nfc_dev_ready(struct mtd_info *mtd)
518{
519 /* NFC handles R/B internally; always ready. */
520 return 1;
521}
522
523/*
524 * This function supports Vybrid only (MPC5125 would have full RB and four CS)
525 */
526static void vf610_nfc_select_chip(struct mtd_info *mtd, int chip)
527{
528#ifdef CONFIG_VF610
529 u32 tmp = vf610_nfc_read(mtd, NFC_ROW_ADDR);
530 tmp &= ~(ROW_ADDR_CHIP_SEL_RB_MASK | ROW_ADDR_CHIP_SEL_MASK);
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200531
Stefan Agner59ae13a2015-10-13 22:11:42 -0700532 if (chip >= 0) {
533 tmp |= 1 << ROW_ADDR_CHIP_SEL_RB_SHIFT;
534 tmp |= (1 << chip) << ROW_ADDR_CHIP_SEL_SHIFT;
535 }
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200536
537 vf610_nfc_write(mtd, NFC_ROW_ADDR, tmp);
538#endif
539}
540
541/* Count the number of 0's in buff upto max_bits */
542static inline int count_written_bits(uint8_t *buff, int size, int max_bits)
543{
544 uint32_t *buff32 = (uint32_t *)buff;
545 int k, written_bits = 0;
546
547 for (k = 0; k < (size / 4); k++) {
548 written_bits += hweight32(~buff32[k]);
549 if (written_bits > max_bits)
550 break;
551 }
552
553 return written_bits;
554}
555
Stefan Agner59ae13a2015-10-13 22:11:42 -0700556static inline int vf610_nfc_correct_data(struct mtd_info *mtd, uint8_t *dat,
557 uint8_t *oob, int page)
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200558{
559 struct vf610_nfc *nfc = mtd_to_nfc(mtd);
Stefan Agner59ae13a2015-10-13 22:11:42 -0700560 u32 ecc_status_off = NFC_MAIN_AREA(0) + ECC_SRAM_ADDR + ECC_STATUS;
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200561 u8 ecc_status;
562 u8 ecc_count;
Stefan Agner59ae13a2015-10-13 22:11:42 -0700563 int flips;
564 int flips_threshold = nfc->chip.ecc.strength / 2;
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200565
Stefan Agner59ae13a2015-10-13 22:11:42 -0700566 ecc_status = vf610_nfc_read(mtd, ecc_status_off) & 0xff;
567 ecc_count = ecc_status & ECC_STATUS_ERR_COUNT;
568
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200569 if (!(ecc_status & ECC_STATUS_MASK))
570 return ecc_count;
571
Stefan Agner59ae13a2015-10-13 22:11:42 -0700572 /* Read OOB without ECC unit enabled */
573 vf610_nfc_command(mtd, NAND_CMD_READOOB, 0, page);
574 vf610_nfc_read_buf(mtd, oob, mtd->oobsize);
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200575
Stefan Agner59ae13a2015-10-13 22:11:42 -0700576 /*
577 * On an erased page, bit count (including OOB) should be zero or
578 * at least less then half of the ECC strength.
579 */
580 flips = count_written_bits(dat, nfc->chip.ecc.size, flips_threshold);
581 flips += count_written_bits(oob, mtd->oobsize, flips_threshold);
582
583 if (unlikely(flips > flips_threshold))
584 return -EINVAL;
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200585
586 /* Erased page. */
587 memset(dat, 0xff, nfc->chip.ecc.size);
Stefan Agner59ae13a2015-10-13 22:11:42 -0700588 memset(oob, 0xff, mtd->oobsize);
589 return flips;
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200590}
591
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200592static int vf610_nfc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
593 uint8_t *buf, int oob_required, int page)
594{
595 int eccsize = chip->ecc.size;
596 int stat;
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200597
Stefan Agner59ae13a2015-10-13 22:11:42 -0700598 vf610_nfc_read_buf(mtd, buf, eccsize);
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200599 if (oob_required)
600 vf610_nfc_read_buf(mtd, chip->oob_poi, mtd->oobsize);
601
Stefan Agner59ae13a2015-10-13 22:11:42 -0700602 stat = vf610_nfc_correct_data(mtd, buf, chip->oob_poi, page);
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200603
Stefan Agner59ae13a2015-10-13 22:11:42 -0700604 if (stat < 0) {
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200605 mtd->ecc_stats.failed++;
Stefan Agner59ae13a2015-10-13 22:11:42 -0700606 return 0;
607 } else {
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200608 mtd->ecc_stats.corrected += stat;
Stefan Agner59ae13a2015-10-13 22:11:42 -0700609 return stat;
610 }
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200611}
612
613/*
614 * ECC will be calculated automatically
615 */
616static int vf610_nfc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
Scott Wood46e13102016-05-30 13:57:57 -0500617 const uint8_t *buf, int oob_required, int page)
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200618{
Stefan Agner59ae13a2015-10-13 22:11:42 -0700619 struct vf610_nfc *nfc = mtd_to_nfc(mtd);
620
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200621 vf610_nfc_write_buf(mtd, buf, mtd->writesize);
622 if (oob_required)
623 vf610_nfc_write_buf(mtd, chip->oob_poi, mtd->oobsize);
624
Stefan Agner59ae13a2015-10-13 22:11:42 -0700625 /* Always write whole page including OOB due to HW ECC */
626 nfc->write_sz = mtd->writesize + mtd->oobsize;
627
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200628 return 0;
629}
630
631struct vf610_nfc_config {
632 int hardware_ecc;
633 int width;
634 int flash_bbt;
635};
636
Sean Andersonf716c532020-09-15 10:44:51 -0400637static int vf610_nfc_nand_init(struct vf610_nfc *nfc, int devnum)
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200638{
Sean Andersonf716c532020-09-15 10:44:51 -0400639 struct nand_chip *chip = &nfc->chip;
640 struct mtd_info *mtd = nand_to_mtd(chip);
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200641 int err = 0;
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200642 struct vf610_nfc_config cfg = {
643 .hardware_ecc = 1,
644#ifdef CONFIG_SYS_NAND_BUSWIDTH_16BIT
645 .width = 16,
646#else
647 .width = 8,
648#endif
649 .flash_bbt = 1,
650 };
651
Scott Wood17fed142016-05-30 13:57:56 -0500652 nand_set_controller_data(chip, nfc);
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200653
Stefan Agner4ce682a2015-05-08 19:07:13 +0200654 if (cfg.width == 16)
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200655 chip->options |= NAND_BUSWIDTH_16;
Stefan Agner4ce682a2015-05-08 19:07:13 +0200656
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200657 chip->dev_ready = vf610_nfc_dev_ready;
658 chip->cmdfunc = vf610_nfc_command;
659 chip->read_byte = vf610_nfc_read_byte;
660 chip->read_word = vf610_nfc_read_word;
661 chip->read_buf = vf610_nfc_read_buf;
662 chip->write_buf = vf610_nfc_write_buf;
663 chip->select_chip = vf610_nfc_select_chip;
664
Stefan Agner59ae13a2015-10-13 22:11:42 -0700665 chip->options |= NAND_NO_SUBPAGE_WRITE;
666
667 chip->ecc.size = PAGE_2K;
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200668
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200669 /* Set configuration register. */
Tom Rini40a35f52021-08-19 13:56:20 -0400670 vf610_nfc_clear(mtd, NFC_FLASH_CONFIG, CFG_16BIT);
671 vf610_nfc_clear(mtd, NFC_FLASH_CONFIG, CFG_ADDR_AUTO_INCR_BIT);
672 vf610_nfc_clear(mtd, NFC_FLASH_CONFIG, CFG_BUFNO_AUTO_INCR_BIT);
673 vf610_nfc_clear(mtd, NFC_FLASH_CONFIG, CFG_BOOT_MODE_BIT);
674 vf610_nfc_clear(mtd, NFC_FLASH_CONFIG, CFG_DMA_REQ_BIT);
675 vf610_nfc_set(mtd, NFC_FLASH_CONFIG, CFG_FAST_FLASH_BIT);
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200676
Stefan Agner59ae13a2015-10-13 22:11:42 -0700677 /* Disable virtual pages, only one elementary transfer unit */
Tom Rini40a35f52021-08-19 13:56:20 -0400678 vf610_nfc_set_field(mtd, NFC_FLASH_CONFIG, CFG_PAGE_CNT_MASK,
679 CFG_PAGE_CNT_SHIFT, 1);
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200680
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200681 /* first scan to find the device and get the page size */
682 if (nand_scan_ident(mtd, CONFIG_SYS_MAX_NAND_DEVICE, NULL)) {
683 err = -ENXIO;
684 goto error;
685 }
686
Stefan Agner4ce682a2015-05-08 19:07:13 +0200687 if (cfg.width == 16)
Tom Rini40a35f52021-08-19 13:56:20 -0400688 vf610_nfc_set(mtd, NFC_FLASH_CONFIG, CFG_16BIT);
Stefan Agner4ce682a2015-05-08 19:07:13 +0200689
Stefan Agner59ae13a2015-10-13 22:11:42 -0700690 /* Bad block options. */
691 if (cfg.flash_bbt)
692 chip->bbt_options = NAND_BBT_USE_FLASH | NAND_BBT_NO_OOB |
693 NAND_BBT_CREATE;
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200694
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200695 /* Single buffer only, max 256 OOB minus ECC status */
Stefan Agner59ae13a2015-10-13 22:11:42 -0700696 if (mtd->writesize + mtd->oobsize > PAGE_2K + OOB_MAX - 8) {
697 dev_err(nfc->dev, "Unsupported flash page size\n");
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200698 err = -ENXIO;
699 goto error;
700 }
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200701
702 if (cfg.hardware_ecc) {
703 if (mtd->writesize != PAGE_2K && mtd->oobsize < 64) {
704 dev_err(nfc->dev, "Unsupported flash with hwecc\n");
705 err = -ENXIO;
706 goto error;
707 }
708
Stefan Agner59ae13a2015-10-13 22:11:42 -0700709 if (chip->ecc.size != mtd->writesize) {
710 dev_err(nfc->dev, "ecc size: %d\n", chip->ecc.size);
711 dev_err(nfc->dev, "Step size needs to be page size\n");
712 err = -ENXIO;
713 goto error;
714 }
715
Stefan Agnerfe10d3f2015-05-08 19:07:12 +0200716 /* Current HW ECC layouts only use 64 bytes of OOB */
717 if (mtd->oobsize > 64)
718 mtd->oobsize = 64;
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200719
720 /* propagate ecc.layout to mtd_info */
721 mtd->ecclayout = chip->ecc.layout;
722 chip->ecc.read_page = vf610_nfc_read_page;
723 chip->ecc.write_page = vf610_nfc_write_page;
724 chip->ecc.mode = NAND_ECC_HW;
725
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200726 chip->ecc.size = PAGE_2K;
Stefan Agnerfe10d3f2015-05-08 19:07:12 +0200727 chip->ecc.layout = &vf610_nfc_ecc;
728#if defined(CONFIG_SYS_NAND_VF610_NFC_45_ECC_BYTES)
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200729 chip->ecc.strength = 24;
Stefan Agnerfe10d3f2015-05-08 19:07:12 +0200730 chip->ecc.bytes = 45;
731#elif defined(CONFIG_SYS_NAND_VF610_NFC_60_ECC_BYTES)
732 chip->ecc.strength = 32;
733 chip->ecc.bytes = 60;
734#endif
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200735
Stefan Agner59ae13a2015-10-13 22:11:42 -0700736 /* Set ECC_STATUS offset */
737 vf610_nfc_set_field(mtd, NFC_FLASH_CONFIG,
Tom Rini40a35f52021-08-19 13:56:20 -0400738 CFG_ECC_SRAM_ADDR_MASK,
739 CFG_ECC_SRAM_ADDR_SHIFT,
Stefan Agner59ae13a2015-10-13 22:11:42 -0700740 ECC_SRAM_ADDR >> 3);
741
742 /* Enable ECC status in SRAM */
Tom Rini40a35f52021-08-19 13:56:20 -0400743 vf610_nfc_set(mtd, NFC_FLASH_CONFIG, CFG_ECC_SRAM_REQ_BIT);
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200744 }
745
746 /* second phase scan */
747 err = nand_scan_tail(mtd);
748 if (err)
749 return err;
750
Scott Wood2c1b7e12016-05-30 13:57:55 -0500751 err = nand_register(devnum, mtd);
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200752 if (err)
753 return err;
754
755 return 0;
756
757error:
758 return err;
759}
760
Lukasz Majewskia8f1a672018-12-03 10:24:51 +0100761#if CONFIG_NAND_VF610_NFC_DT
762static const struct udevice_id vf610_nfc_dt_ids[] = {
763 {
764 .compatible = "fsl,vf610-nfc",
765 },
766 { /* sentinel */ }
767};
768
769static int vf610_nfc_dt_probe(struct udevice *dev)
770{
771 struct resource res;
Sean Andersonf716c532020-09-15 10:44:51 -0400772 struct vf610_nfc *nfc = dev_get_priv(dev);
Lukasz Majewskia8f1a672018-12-03 10:24:51 +0100773 int ret;
774
775 ret = dev_read_resource(dev, 0, &res);
776 if (ret)
777 return ret;
778
Sean Andersonf716c532020-09-15 10:44:51 -0400779 nfc->regs = devm_ioremap(dev, res.start, resource_size(&res));
780 nfc->dev = dev;
781 return vf610_nfc_nand_init(nfc, 0);
Lukasz Majewskia8f1a672018-12-03 10:24:51 +0100782}
783
784U_BOOT_DRIVER(vf610_nfc_dt) = {
785 .name = "vf610-nfc-dt",
786 .id = UCLASS_MTD,
787 .of_match = vf610_nfc_dt_ids,
Simon Glass8a2b47f2020-12-03 16:55:17 -0700788 .priv_auto = sizeof(struct vf610_nfc),
Lukasz Majewskia8f1a672018-12-03 10:24:51 +0100789 .probe = vf610_nfc_dt_probe,
790};
791
792void board_nand_init(void)
793{
794 struct udevice *dev;
795 int ret;
796
797 ret = uclass_get_device_by_driver(UCLASS_MTD,
Simon Glass65130cd2020-12-28 20:34:56 -0700798 DM_DRIVER_GET(vf610_nfc_dt),
Lukasz Majewskia8f1a672018-12-03 10:24:51 +0100799 &dev);
800 if (ret && ret != -ENODEV)
801 pr_err("Failed to initialize NAND controller. (error %d)\n",
802 ret);
803}
804#else
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200805void board_nand_init(void)
806{
Sean Andersonf716c532020-09-15 10:44:51 -0400807 int err;
808 struct vf610_nfc *nfc;
809
810 nfc = calloc(1, sizeof(*nfc));
811 if (!nfc) {
812 printf("%s: Out of memory\n", __func__);
813 return;
814 }
815
Tom Rinib4213492022-11-12 17:36:51 -0500816 nfc->regs = (void __iomem *)CFG_SYS_NAND_BASE;
Sean Andersonf716c532020-09-15 10:44:51 -0400817 err = vf610_nfc_nand_init(nfc, 0);
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200818 if (err)
819 printf("VF610 NAND init failed (err %d)\n", err);
820}
Lukasz Majewskia8f1a672018-12-03 10:24:51 +0100821#endif /* CONFIG_NAND_VF610_NFC_DT */