blob: 13fd631cb402f89021bcfeda78693becb8ab6210 [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
24#include <common.h>
25#include <malloc.h>
Simon Glass9bc15642020-02-03 07:36:16 -070026#include <dm/device_compat.h>
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +020027
28#include <linux/mtd/mtd.h>
Masahiro Yamada2b7a8732017-11-30 13:45:24 +090029#include <linux/mtd/rawnand.h>
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +020030#include <linux/mtd/partitions.h>
31
32#include <nand.h>
33#include <errno.h>
34#include <asm/io.h>
Lukasz Majewskia8f1a672018-12-03 10:24:51 +010035#if CONFIG_NAND_VF610_NFC_DT
36#include <dm.h>
37#include <linux/io.h>
38#include <linux/ioport.h>
39#endif
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +020040
41/* Register Offsets */
42#define NFC_FLASH_CMD1 0x3F00
43#define NFC_FLASH_CMD2 0x3F04
44#define NFC_COL_ADDR 0x3F08
45#define NFC_ROW_ADDR 0x3F0c
46#define NFC_ROW_ADDR_INC 0x3F14
47#define NFC_FLASH_STATUS1 0x3F18
48#define NFC_FLASH_STATUS2 0x3F1c
49#define NFC_CACHE_SWAP 0x3F28
50#define NFC_SECTOR_SIZE 0x3F2c
51#define NFC_FLASH_CONFIG 0x3F30
52#define NFC_IRQ_STATUS 0x3F38
53
54/* Addresses for NFC MAIN RAM BUFFER areas */
55#define NFC_MAIN_AREA(n) ((n) * 0x1000)
56
57#define PAGE_2K 0x0800
58#define OOB_64 0x0040
Stefan Agner59ae13a2015-10-13 22:11:42 -070059#define OOB_MAX 0x0100
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +020060
61/*
62 * NFC_CMD2[CODE] values. See section:
63 * - 31.4.7 Flash Command Code Description, Vybrid manual
64 * - 23.8.6 Flash Command Sequencer, MPC5125 manual
65 *
66 * Briefly these are bitmasks of controller cycles.
67 */
68#define READ_PAGE_CMD_CODE 0x7EE0
Stefan Agner4ce682a2015-05-08 19:07:13 +020069#define READ_ONFI_PARAM_CMD_CODE 0x4860
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +020070#define PROGRAM_PAGE_CMD_CODE 0x7FC0
71#define ERASE_CMD_CODE 0x4EC0
72#define READ_ID_CMD_CODE 0x4804
73#define RESET_CMD_CODE 0x4040
74#define STATUS_READ_CMD_CODE 0x4068
75
76/* NFC ECC mode define */
77#define ECC_BYPASS 0
78#define ECC_45_BYTE 6
Stefan Agnerfe10d3f2015-05-08 19:07:12 +020079#define ECC_60_BYTE 7
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +020080
81/*** Register Mask and bit definitions */
82
83/* NFC_FLASH_CMD1 Field */
84#define CMD_BYTE2_MASK 0xFF000000
85#define CMD_BYTE2_SHIFT 24
86
87/* NFC_FLASH_CM2 Field */
88#define CMD_BYTE1_MASK 0xFF000000
89#define CMD_BYTE1_SHIFT 24
90#define CMD_CODE_MASK 0x00FFFF00
91#define CMD_CODE_SHIFT 8
92#define BUFNO_MASK 0x00000006
93#define BUFNO_SHIFT 1
94#define START_BIT (1<<0)
95
96/* NFC_COL_ADDR Field */
97#define COL_ADDR_MASK 0x0000FFFF
98#define COL_ADDR_SHIFT 0
99
100/* NFC_ROW_ADDR Field */
101#define ROW_ADDR_MASK 0x00FFFFFF
102#define ROW_ADDR_SHIFT 0
103#define ROW_ADDR_CHIP_SEL_RB_MASK 0xF0000000
104#define ROW_ADDR_CHIP_SEL_RB_SHIFT 28
105#define ROW_ADDR_CHIP_SEL_MASK 0x0F000000
106#define ROW_ADDR_CHIP_SEL_SHIFT 24
107
108/* NFC_FLASH_STATUS2 Field */
109#define STATUS_BYTE1_MASK 0x000000FF
110
111/* NFC_FLASH_CONFIG Field */
Tom Rini40a35f52021-08-19 13:56:20 -0400112#define CFG_ECC_SRAM_ADDR_MASK 0x7FC00000
113#define CFG_ECC_SRAM_ADDR_SHIFT 22
114#define CFG_ECC_SRAM_REQ_BIT (1<<21)
115#define CFG_DMA_REQ_BIT (1<<20)
116#define CFG_ECC_MODE_MASK 0x000E0000
117#define CFG_ECC_MODE_SHIFT 17
118#define CFG_FAST_FLASH_BIT (1<<16)
119#define CFG_16BIT (1<<7)
120#define CFG_BOOT_MODE_BIT (1<<6)
121#define CFG_ADDR_AUTO_INCR_BIT (1<<5)
122#define CFG_BUFNO_AUTO_INCR_BIT (1<<4)
123#define CFG_PAGE_CNT_MASK 0xF
124#define CFG_PAGE_CNT_SHIFT 0
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200125
126/* NFC_IRQ_STATUS Field */
127#define IDLE_IRQ_BIT (1<<29)
128#define IDLE_EN_BIT (1<<20)
129#define CMD_DONE_CLEAR_BIT (1<<18)
130#define IDLE_CLEAR_BIT (1<<17)
131
132#define NFC_TIMEOUT (1000)
133
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200134/*
Stefan Agner59ae13a2015-10-13 22:11:42 -0700135 * ECC status - seems to consume 8 bytes (double word). The documented
136 * status byte is located in the lowest byte of the second word (which is
137 * the 4th or 7th byte depending on endianness).
138 * Calculate an offset to store the ECC status at the end of the buffer.
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200139 */
Stefan Agner59ae13a2015-10-13 22:11:42 -0700140#define ECC_SRAM_ADDR (PAGE_2K + OOB_MAX - 8)
141
142#define ECC_STATUS 0x4
143#define ECC_STATUS_MASK 0x80
144#define ECC_STATUS_ERR_COUNT 0x3F
145
146enum vf610_nfc_alt_buf {
147 ALT_BUF_DATA = 0,
148 ALT_BUF_ID = 1,
149 ALT_BUF_STAT = 2,
150 ALT_BUF_ONFI = 3,
151};
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200152
153struct vf610_nfc {
Stefan Agner59ae13a2015-10-13 22:11:42 -0700154 struct nand_chip chip;
Sean Andersonf716c532020-09-15 10:44:51 -0400155 /* NULL without CONFIG_NAND_VF610_NFC_DT */
156 struct udevice *dev;
Stefan Agner59ae13a2015-10-13 22:11:42 -0700157 void __iomem *regs;
158 uint buf_offset;
159 int write_sz;
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200160 /* Status and ID are in alternate locations. */
Stefan Agner59ae13a2015-10-13 22:11:42 -0700161 enum vf610_nfc_alt_buf alt_buf;
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200162};
163
Scott Wood17fed142016-05-30 13:57:56 -0500164#define mtd_to_nfc(_mtd) nand_get_controller_data(mtd_to_nand(_mtd))
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200165
Stefan Agnerfe10d3f2015-05-08 19:07:12 +0200166#if defined(CONFIG_SYS_NAND_VF610_NFC_45_ECC_BYTES)
167#define ECC_HW_MODE ECC_45_BYTE
168
169static struct nand_ecclayout vf610_nfc_ecc = {
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200170 .eccbytes = 45,
171 .eccpos = {19, 20, 21, 22, 23,
172 24, 25, 26, 27, 28, 29, 30, 31,
173 32, 33, 34, 35, 36, 37, 38, 39,
174 40, 41, 42, 43, 44, 45, 46, 47,
175 48, 49, 50, 51, 52, 53, 54, 55,
176 56, 57, 58, 59, 60, 61, 62, 63},
177 .oobfree = {
Stefan Agner59ae13a2015-10-13 22:11:42 -0700178 {.offset = 2,
179 .length = 17} }
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200180};
Stefan Agnerfe10d3f2015-05-08 19:07:12 +0200181#elif defined(CONFIG_SYS_NAND_VF610_NFC_60_ECC_BYTES)
182#define ECC_HW_MODE ECC_60_BYTE
183
184static struct nand_ecclayout vf610_nfc_ecc = {
185 .eccbytes = 60,
186 .eccpos = { 4, 5, 6, 7, 8, 9, 10, 11,
187 12, 13, 14, 15, 16, 17, 18, 19,
188 20, 21, 22, 23, 24, 25, 26, 27,
189 28, 29, 30, 31, 32, 33, 34, 35,
190 36, 37, 38, 39, 40, 41, 42, 43,
191 44, 45, 46, 47, 48, 49, 50, 51,
192 52, 53, 54, 55, 56, 57, 58, 59,
193 60, 61, 62, 63 },
194 .oobfree = {
195 {.offset = 2,
196 .length = 2} }
197};
198#endif
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200199
200static inline u32 vf610_nfc_read(struct mtd_info *mtd, uint reg)
201{
202 struct vf610_nfc *nfc = mtd_to_nfc(mtd);
203
204 return readl(nfc->regs + reg);
205}
206
207static inline void vf610_nfc_write(struct mtd_info *mtd, uint reg, u32 val)
208{
209 struct vf610_nfc *nfc = mtd_to_nfc(mtd);
210
211 writel(val, nfc->regs + reg);
212}
213
214static inline void vf610_nfc_set(struct mtd_info *mtd, uint reg, u32 bits)
215{
216 vf610_nfc_write(mtd, reg, vf610_nfc_read(mtd, reg) | bits);
217}
218
219static inline void vf610_nfc_clear(struct mtd_info *mtd, uint reg, u32 bits)
220{
221 vf610_nfc_write(mtd, reg, vf610_nfc_read(mtd, reg) & ~bits);
222}
223
224static inline void vf610_nfc_set_field(struct mtd_info *mtd, u32 reg,
225 u32 mask, u32 shift, u32 val)
226{
227 vf610_nfc_write(mtd, reg,
228 (vf610_nfc_read(mtd, reg) & (~mask)) | val << shift);
229}
230
231static inline void vf610_nfc_memcpy(void *dst, const void *src, size_t n)
232{
233 /*
Stefan Agner59ae13a2015-10-13 22:11:42 -0700234 * Use this accessor for the internal SRAM buffers. On the ARM
235 * Freescale Vybrid SoC it's known that the driver can treat
236 * the SRAM buffer as if it's memory. Other platform might need
237 * to treat the buffers differently.
238 *
239 * For the time being, use memcpy
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200240 */
241 memcpy(dst, src, n);
242}
243
244/* Clear flags for upcoming command */
245static inline void vf610_nfc_clear_status(void __iomem *regbase)
246{
247 void __iomem *reg = regbase + NFC_IRQ_STATUS;
248 u32 tmp = __raw_readl(reg);
249 tmp |= CMD_DONE_CLEAR_BIT | IDLE_CLEAR_BIT;
250 __raw_writel(tmp, reg);
251}
252
253/* Wait for complete operation */
Stefan Agner59ae13a2015-10-13 22:11:42 -0700254static void vf610_nfc_done(struct mtd_info *mtd)
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200255{
256 struct vf610_nfc *nfc = mtd_to_nfc(mtd);
257 uint start;
258
259 /*
260 * Barrier is needed after this write. This write need
261 * to be done before reading the next register the first
262 * time.
263 * vf610_nfc_set implicates such a barrier by using writel
264 * to write to the register.
265 */
266 vf610_nfc_set(mtd, NFC_FLASH_CMD2, START_BIT);
267
268 start = get_timer(0);
269
270 while (!(vf610_nfc_read(mtd, NFC_IRQ_STATUS) & IDLE_IRQ_BIT)) {
271 if (get_timer(start) > NFC_TIMEOUT) {
Stefan Agner59ae13a2015-10-13 22:11:42 -0700272 printf("Timeout while waiting for IDLE.\n");
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200273 return;
274 }
275 }
276 vf610_nfc_clear_status(nfc->regs);
277}
278
279static u8 vf610_nfc_get_id(struct mtd_info *mtd, int col)
280{
281 u32 flash_id;
282
283 if (col < 4) {
284 flash_id = vf610_nfc_read(mtd, NFC_FLASH_STATUS1);
Stefan Agner59ae13a2015-10-13 22:11:42 -0700285 flash_id >>= (3 - col) * 8;
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200286 } else {
287 flash_id = vf610_nfc_read(mtd, NFC_FLASH_STATUS2);
Stefan Agner59ae13a2015-10-13 22:11:42 -0700288 flash_id >>= 24;
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200289 }
Stefan Agner59ae13a2015-10-13 22:11:42 -0700290
291 return flash_id & 0xff;
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200292}
293
294static u8 vf610_nfc_get_status(struct mtd_info *mtd)
295{
296 return vf610_nfc_read(mtd, NFC_FLASH_STATUS2) & STATUS_BYTE1_MASK;
297}
298
299/* Single command */
300static void vf610_nfc_send_command(void __iomem *regbase, u32 cmd_byte1,
301 u32 cmd_code)
302{
303 void __iomem *reg = regbase + NFC_FLASH_CMD2;
304 u32 tmp;
305 vf610_nfc_clear_status(regbase);
306
307 tmp = __raw_readl(reg);
308 tmp &= ~(CMD_BYTE1_MASK | CMD_CODE_MASK | BUFNO_MASK);
309 tmp |= cmd_byte1 << CMD_BYTE1_SHIFT;
310 tmp |= cmd_code << CMD_CODE_SHIFT;
311 __raw_writel(tmp, reg);
312}
313
314/* Two commands */
315static void vf610_nfc_send_commands(void __iomem *regbase, u32 cmd_byte1,
316 u32 cmd_byte2, u32 cmd_code)
317{
318 void __iomem *reg = regbase + NFC_FLASH_CMD1;
319 u32 tmp;
320 vf610_nfc_send_command(regbase, cmd_byte1, cmd_code);
321
322 tmp = __raw_readl(reg);
323 tmp &= ~CMD_BYTE2_MASK;
324 tmp |= cmd_byte2 << CMD_BYTE2_SHIFT;
325 __raw_writel(tmp, reg);
326}
327
328static void vf610_nfc_addr_cycle(struct mtd_info *mtd, int column, int page)
329{
330 if (column != -1) {
331 struct vf610_nfc *nfc = mtd_to_nfc(mtd);
Stefan Agner7056fee2015-05-08 19:07:09 +0200332 if (nfc->chip.options & NAND_BUSWIDTH_16)
333 column = column / 2;
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200334 vf610_nfc_set_field(mtd, NFC_COL_ADDR, COL_ADDR_MASK,
335 COL_ADDR_SHIFT, column);
336 }
337 if (page != -1)
338 vf610_nfc_set_field(mtd, NFC_ROW_ADDR, ROW_ADDR_MASK,
339 ROW_ADDR_SHIFT, page);
340}
341
Stefan Agner7056fee2015-05-08 19:07:09 +0200342static inline void vf610_nfc_ecc_mode(struct mtd_info *mtd, int ecc_mode)
343{
344 vf610_nfc_set_field(mtd, NFC_FLASH_CONFIG,
Tom Rini40a35f52021-08-19 13:56:20 -0400345 CFG_ECC_MODE_MASK,
346 CFG_ECC_MODE_SHIFT, ecc_mode);
Stefan Agner7056fee2015-05-08 19:07:09 +0200347}
348
Stefan Agner11f1fa02015-03-24 17:54:20 +0100349static inline void vf610_nfc_transfer_size(void __iomem *regbase, int size)
350{
351 __raw_writel(size, regbase + NFC_SECTOR_SIZE);
352}
353
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200354/* Send command to NAND chip */
355static void vf610_nfc_command(struct mtd_info *mtd, unsigned command,
356 int column, int page)
357{
358 struct vf610_nfc *nfc = mtd_to_nfc(mtd);
Stefan Agner59ae13a2015-10-13 22:11:42 -0700359 int trfr_sz = nfc->chip.options & NAND_BUSWIDTH_16 ? 1 : 0;
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200360
Stefan Agner59ae13a2015-10-13 22:11:42 -0700361 nfc->buf_offset = max(column, 0);
362 nfc->alt_buf = ALT_BUF_DATA;
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200363
364 switch (command) {
Stefan Agner04213412015-05-08 19:07:07 +0200365 case NAND_CMD_SEQIN:
366 /* Use valid column/page from preread... */
367 vf610_nfc_addr_cycle(mtd, column, page);
Stefan Agner59ae13a2015-10-13 22:11:42 -0700368 nfc->buf_offset = 0;
369
Stefan Agner04213412015-05-08 19:07:07 +0200370 /*
371 * SEQIN => data => PAGEPROG sequence is done by the controller
372 * hence we do not need to issue the command here...
373 */
374 return;
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200375 case NAND_CMD_PAGEPROG:
Stefan Agner59ae13a2015-10-13 22:11:42 -0700376 trfr_sz += nfc->write_sz;
377 vf610_nfc_ecc_mode(mtd, ECC_HW_MODE);
378 vf610_nfc_transfer_size(nfc->regs, trfr_sz);
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200379 vf610_nfc_send_commands(nfc->regs, NAND_CMD_SEQIN,
380 command, PROGRAM_PAGE_CMD_CODE);
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200381 break;
382
383 case NAND_CMD_RESET:
Stefan Agner11f1fa02015-03-24 17:54:20 +0100384 vf610_nfc_transfer_size(nfc->regs, 0);
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200385 vf610_nfc_send_command(nfc->regs, command, RESET_CMD_CODE);
386 break;
Stefan Agner7056fee2015-05-08 19:07:09 +0200387
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200388 case NAND_CMD_READOOB:
Stefan Agner59ae13a2015-10-13 22:11:42 -0700389 trfr_sz += mtd->oobsize;
Stefan Agner7056fee2015-05-08 19:07:09 +0200390 column = mtd->writesize;
Stefan Agner59ae13a2015-10-13 22:11:42 -0700391 vf610_nfc_transfer_size(nfc->regs, trfr_sz);
Stefan Agner7056fee2015-05-08 19:07:09 +0200392 vf610_nfc_send_commands(nfc->regs, NAND_CMD_READ0,
393 NAND_CMD_READSTART, READ_PAGE_CMD_CODE);
394 vf610_nfc_addr_cycle(mtd, column, page);
395 vf610_nfc_ecc_mode(mtd, ECC_BYPASS);
396 break;
397
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200398 case NAND_CMD_READ0:
Stefan Agner59ae13a2015-10-13 22:11:42 -0700399 trfr_sz += mtd->writesize + mtd->oobsize;
400 vf610_nfc_transfer_size(nfc->regs, trfr_sz);
401 vf610_nfc_ecc_mode(mtd, ECC_HW_MODE);
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200402 vf610_nfc_send_commands(nfc->regs, NAND_CMD_READ0,
403 NAND_CMD_READSTART, READ_PAGE_CMD_CODE);
404 vf610_nfc_addr_cycle(mtd, column, page);
405 break;
406
Stefan Agner4ce682a2015-05-08 19:07:13 +0200407 case NAND_CMD_PARAM:
408 nfc->alt_buf = ALT_BUF_ONFI;
Stefan Agner59ae13a2015-10-13 22:11:42 -0700409 trfr_sz = 3 * sizeof(struct nand_onfi_params);
410 vf610_nfc_transfer_size(nfc->regs, trfr_sz);
Stefan Agner4ce682a2015-05-08 19:07:13 +0200411 vf610_nfc_send_command(nfc->regs, NAND_CMD_PARAM,
412 READ_ONFI_PARAM_CMD_CODE);
413 vf610_nfc_set_field(mtd, NFC_ROW_ADDR, ROW_ADDR_MASK,
414 ROW_ADDR_SHIFT, column);
415 vf610_nfc_ecc_mode(mtd, ECC_BYPASS);
416 break;
417
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200418 case NAND_CMD_ERASE1:
Stefan Agner11f1fa02015-03-24 17:54:20 +0100419 vf610_nfc_transfer_size(nfc->regs, 0);
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200420 vf610_nfc_send_commands(nfc->regs, command,
421 NAND_CMD_ERASE2, ERASE_CMD_CODE);
422 vf610_nfc_addr_cycle(mtd, column, page);
423 break;
424
425 case NAND_CMD_READID:
426 nfc->alt_buf = ALT_BUF_ID;
Stefan Agner59ae13a2015-10-13 22:11:42 -0700427 nfc->buf_offset = 0;
Stefan Agner11f1fa02015-03-24 17:54:20 +0100428 vf610_nfc_transfer_size(nfc->regs, 0);
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200429 vf610_nfc_send_command(nfc->regs, command, READ_ID_CMD_CODE);
Stefan Agner4ce682a2015-05-08 19:07:13 +0200430 vf610_nfc_set_field(mtd, NFC_ROW_ADDR, ROW_ADDR_MASK,
431 ROW_ADDR_SHIFT, column);
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200432 break;
433
434 case NAND_CMD_STATUS:
435 nfc->alt_buf = ALT_BUF_STAT;
Stefan Agner11f1fa02015-03-24 17:54:20 +0100436 vf610_nfc_transfer_size(nfc->regs, 0);
Stefan Agner59ae13a2015-10-13 22:11:42 -0700437 vf610_nfc_send_command(nfc->regs, command, STATUS_READ_CMD_CODE);
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200438 break;
439 default:
440 return;
441 }
442
443 vf610_nfc_done(mtd);
Stefan Agner59ae13a2015-10-13 22:11:42 -0700444
445 nfc->write_sz = 0;
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200446}
447
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200448/* Read data from NFC buffers */
449static void vf610_nfc_read_buf(struct mtd_info *mtd, u_char *buf, int len)
450{
451 struct vf610_nfc *nfc = mtd_to_nfc(mtd);
Stefan Agner59ae13a2015-10-13 22:11:42 -0700452 uint c = nfc->buf_offset;
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200453
Stefan Agner4ce682a2015-05-08 19:07:13 +0200454 /* Alternate buffers are only supported through read_byte */
455 if (nfc->alt_buf)
456 return;
457
458 vf610_nfc_memcpy(buf, nfc->regs + NFC_MAIN_AREA(0) + c, len);
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200459
Stefan Agner59ae13a2015-10-13 22:11:42 -0700460 nfc->buf_offset += len;
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200461}
462
463/* Write data to NFC buffers */
Stefan Agner59ae13a2015-10-13 22:11:42 -0700464static void vf610_nfc_write_buf(struct mtd_info *mtd, const uint8_t *buf,
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200465 int len)
466{
467 struct vf610_nfc *nfc = mtd_to_nfc(mtd);
Stefan Agner59ae13a2015-10-13 22:11:42 -0700468 uint c = nfc->buf_offset;
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200469 uint l;
470
Stefan Agner59ae13a2015-10-13 22:11:42 -0700471 l = min_t(uint, len, mtd->writesize + mtd->oobsize - c);
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200472 vf610_nfc_memcpy(nfc->regs + NFC_MAIN_AREA(0) + c, buf, l);
Stefan Agner59ae13a2015-10-13 22:11:42 -0700473
474 nfc->write_sz += l;
475 nfc->buf_offset += l;
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200476}
477
478/* Read byte from NFC buffers */
Stefan Agner59ae13a2015-10-13 22:11:42 -0700479static uint8_t vf610_nfc_read_byte(struct mtd_info *mtd)
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200480{
Stefan Agner4ce682a2015-05-08 19:07:13 +0200481 struct vf610_nfc *nfc = mtd_to_nfc(mtd);
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200482 u8 tmp;
Stefan Agner59ae13a2015-10-13 22:11:42 -0700483 uint c = nfc->buf_offset;
Stefan Agner4ce682a2015-05-08 19:07:13 +0200484
485 switch (nfc->alt_buf) {
486 case ALT_BUF_ID:
487 tmp = vf610_nfc_get_id(mtd, c);
488 break;
489 case ALT_BUF_STAT:
490 tmp = vf610_nfc_get_status(mtd);
491 break;
Stefan Agner4ce682a2015-05-08 19:07:13 +0200492#ifdef __LITTLE_ENDIAN
Stefan Agner59ae13a2015-10-13 22:11:42 -0700493 case ALT_BUF_ONFI:
Stefan Agner4ce682a2015-05-08 19:07:13 +0200494 /* Reverse byte since the controller uses big endianness */
Stefan Agner59ae13a2015-10-13 22:11:42 -0700495 c = nfc->buf_offset ^ 0x3;
496 /* fall-through */
Stefan Agner4ce682a2015-05-08 19:07:13 +0200497#endif
498 default:
499 tmp = *((u8 *)(nfc->regs + NFC_MAIN_AREA(0) + c));
500 break;
501 }
Stefan Agner59ae13a2015-10-13 22:11:42 -0700502 nfc->buf_offset++;
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200503 return tmp;
504}
505
506/* Read word from NFC buffers */
507static u16 vf610_nfc_read_word(struct mtd_info *mtd)
508{
509 u16 tmp;
Stefan Agner59ae13a2015-10-13 22:11:42 -0700510
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200511 vf610_nfc_read_buf(mtd, (u_char *)&tmp, sizeof(tmp));
512 return tmp;
513}
514
515/* If not provided, upper layers apply a fixed delay. */
516static int vf610_nfc_dev_ready(struct mtd_info *mtd)
517{
518 /* NFC handles R/B internally; always ready. */
519 return 1;
520}
521
522/*
523 * This function supports Vybrid only (MPC5125 would have full RB and four CS)
524 */
525static void vf610_nfc_select_chip(struct mtd_info *mtd, int chip)
526{
527#ifdef CONFIG_VF610
528 u32 tmp = vf610_nfc_read(mtd, NFC_ROW_ADDR);
529 tmp &= ~(ROW_ADDR_CHIP_SEL_RB_MASK | ROW_ADDR_CHIP_SEL_MASK);
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200530
Stefan Agner59ae13a2015-10-13 22:11:42 -0700531 if (chip >= 0) {
532 tmp |= 1 << ROW_ADDR_CHIP_SEL_RB_SHIFT;
533 tmp |= (1 << chip) << ROW_ADDR_CHIP_SEL_SHIFT;
534 }
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200535
536 vf610_nfc_write(mtd, NFC_ROW_ADDR, tmp);
537#endif
538}
539
540/* Count the number of 0's in buff upto max_bits */
541static inline int count_written_bits(uint8_t *buff, int size, int max_bits)
542{
543 uint32_t *buff32 = (uint32_t *)buff;
544 int k, written_bits = 0;
545
546 for (k = 0; k < (size / 4); k++) {
547 written_bits += hweight32(~buff32[k]);
548 if (written_bits > max_bits)
549 break;
550 }
551
552 return written_bits;
553}
554
Stefan Agner59ae13a2015-10-13 22:11:42 -0700555static inline int vf610_nfc_correct_data(struct mtd_info *mtd, uint8_t *dat,
556 uint8_t *oob, int page)
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200557{
558 struct vf610_nfc *nfc = mtd_to_nfc(mtd);
Stefan Agner59ae13a2015-10-13 22:11:42 -0700559 u32 ecc_status_off = NFC_MAIN_AREA(0) + ECC_SRAM_ADDR + ECC_STATUS;
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200560 u8 ecc_status;
561 u8 ecc_count;
Stefan Agner59ae13a2015-10-13 22:11:42 -0700562 int flips;
563 int flips_threshold = nfc->chip.ecc.strength / 2;
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200564
Stefan Agner59ae13a2015-10-13 22:11:42 -0700565 ecc_status = vf610_nfc_read(mtd, ecc_status_off) & 0xff;
566 ecc_count = ecc_status & ECC_STATUS_ERR_COUNT;
567
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200568 if (!(ecc_status & ECC_STATUS_MASK))
569 return ecc_count;
570
Stefan Agner59ae13a2015-10-13 22:11:42 -0700571 /* Read OOB without ECC unit enabled */
572 vf610_nfc_command(mtd, NAND_CMD_READOOB, 0, page);
573 vf610_nfc_read_buf(mtd, oob, mtd->oobsize);
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200574
Stefan Agner59ae13a2015-10-13 22:11:42 -0700575 /*
576 * On an erased page, bit count (including OOB) should be zero or
577 * at least less then half of the ECC strength.
578 */
579 flips = count_written_bits(dat, nfc->chip.ecc.size, flips_threshold);
580 flips += count_written_bits(oob, mtd->oobsize, flips_threshold);
581
582 if (unlikely(flips > flips_threshold))
583 return -EINVAL;
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200584
585 /* Erased page. */
586 memset(dat, 0xff, nfc->chip.ecc.size);
Stefan Agner59ae13a2015-10-13 22:11:42 -0700587 memset(oob, 0xff, mtd->oobsize);
588 return flips;
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200589}
590
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200591static int vf610_nfc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
592 uint8_t *buf, int oob_required, int page)
593{
594 int eccsize = chip->ecc.size;
595 int stat;
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200596
Stefan Agner59ae13a2015-10-13 22:11:42 -0700597 vf610_nfc_read_buf(mtd, buf, eccsize);
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200598 if (oob_required)
599 vf610_nfc_read_buf(mtd, chip->oob_poi, mtd->oobsize);
600
Stefan Agner59ae13a2015-10-13 22:11:42 -0700601 stat = vf610_nfc_correct_data(mtd, buf, chip->oob_poi, page);
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200602
Stefan Agner59ae13a2015-10-13 22:11:42 -0700603 if (stat < 0) {
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200604 mtd->ecc_stats.failed++;
Stefan Agner59ae13a2015-10-13 22:11:42 -0700605 return 0;
606 } else {
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200607 mtd->ecc_stats.corrected += stat;
Stefan Agner59ae13a2015-10-13 22:11:42 -0700608 return stat;
609 }
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200610}
611
612/*
613 * ECC will be calculated automatically
614 */
615static int vf610_nfc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
Scott Wood46e13102016-05-30 13:57:57 -0500616 const uint8_t *buf, int oob_required, int page)
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200617{
Stefan Agner59ae13a2015-10-13 22:11:42 -0700618 struct vf610_nfc *nfc = mtd_to_nfc(mtd);
619
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200620 vf610_nfc_write_buf(mtd, buf, mtd->writesize);
621 if (oob_required)
622 vf610_nfc_write_buf(mtd, chip->oob_poi, mtd->oobsize);
623
Stefan Agner59ae13a2015-10-13 22:11:42 -0700624 /* Always write whole page including OOB due to HW ECC */
625 nfc->write_sz = mtd->writesize + mtd->oobsize;
626
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200627 return 0;
628}
629
630struct vf610_nfc_config {
631 int hardware_ecc;
632 int width;
633 int flash_bbt;
634};
635
Sean Andersonf716c532020-09-15 10:44:51 -0400636static int vf610_nfc_nand_init(struct vf610_nfc *nfc, int devnum)
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200637{
Sean Andersonf716c532020-09-15 10:44:51 -0400638 struct nand_chip *chip = &nfc->chip;
639 struct mtd_info *mtd = nand_to_mtd(chip);
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200640 int err = 0;
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200641 struct vf610_nfc_config cfg = {
642 .hardware_ecc = 1,
643#ifdef CONFIG_SYS_NAND_BUSWIDTH_16BIT
644 .width = 16,
645#else
646 .width = 8,
647#endif
648 .flash_bbt = 1,
649 };
650
Scott Wood17fed142016-05-30 13:57:56 -0500651 nand_set_controller_data(chip, nfc);
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200652
Stefan Agner4ce682a2015-05-08 19:07:13 +0200653 if (cfg.width == 16)
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200654 chip->options |= NAND_BUSWIDTH_16;
Stefan Agner4ce682a2015-05-08 19:07:13 +0200655
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200656 chip->dev_ready = vf610_nfc_dev_ready;
657 chip->cmdfunc = vf610_nfc_command;
658 chip->read_byte = vf610_nfc_read_byte;
659 chip->read_word = vf610_nfc_read_word;
660 chip->read_buf = vf610_nfc_read_buf;
661 chip->write_buf = vf610_nfc_write_buf;
662 chip->select_chip = vf610_nfc_select_chip;
663
Stefan Agner59ae13a2015-10-13 22:11:42 -0700664 chip->options |= NAND_NO_SUBPAGE_WRITE;
665
666 chip->ecc.size = PAGE_2K;
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200667
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200668 /* Set configuration register. */
Tom Rini40a35f52021-08-19 13:56:20 -0400669 vf610_nfc_clear(mtd, NFC_FLASH_CONFIG, CFG_16BIT);
670 vf610_nfc_clear(mtd, NFC_FLASH_CONFIG, CFG_ADDR_AUTO_INCR_BIT);
671 vf610_nfc_clear(mtd, NFC_FLASH_CONFIG, CFG_BUFNO_AUTO_INCR_BIT);
672 vf610_nfc_clear(mtd, NFC_FLASH_CONFIG, CFG_BOOT_MODE_BIT);
673 vf610_nfc_clear(mtd, NFC_FLASH_CONFIG, CFG_DMA_REQ_BIT);
674 vf610_nfc_set(mtd, NFC_FLASH_CONFIG, CFG_FAST_FLASH_BIT);
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200675
Stefan Agner59ae13a2015-10-13 22:11:42 -0700676 /* Disable virtual pages, only one elementary transfer unit */
Tom Rini40a35f52021-08-19 13:56:20 -0400677 vf610_nfc_set_field(mtd, NFC_FLASH_CONFIG, CFG_PAGE_CNT_MASK,
678 CFG_PAGE_CNT_SHIFT, 1);
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200679
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200680 /* first scan to find the device and get the page size */
681 if (nand_scan_ident(mtd, CONFIG_SYS_MAX_NAND_DEVICE, NULL)) {
682 err = -ENXIO;
683 goto error;
684 }
685
Stefan Agner4ce682a2015-05-08 19:07:13 +0200686 if (cfg.width == 16)
Tom Rini40a35f52021-08-19 13:56:20 -0400687 vf610_nfc_set(mtd, NFC_FLASH_CONFIG, CFG_16BIT);
Stefan Agner4ce682a2015-05-08 19:07:13 +0200688
Stefan Agner59ae13a2015-10-13 22:11:42 -0700689 /* Bad block options. */
690 if (cfg.flash_bbt)
691 chip->bbt_options = NAND_BBT_USE_FLASH | NAND_BBT_NO_OOB |
692 NAND_BBT_CREATE;
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200693
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200694 /* Single buffer only, max 256 OOB minus ECC status */
Stefan Agner59ae13a2015-10-13 22:11:42 -0700695 if (mtd->writesize + mtd->oobsize > PAGE_2K + OOB_MAX - 8) {
696 dev_err(nfc->dev, "Unsupported flash page size\n");
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200697 err = -ENXIO;
698 goto error;
699 }
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200700
701 if (cfg.hardware_ecc) {
702 if (mtd->writesize != PAGE_2K && mtd->oobsize < 64) {
703 dev_err(nfc->dev, "Unsupported flash with hwecc\n");
704 err = -ENXIO;
705 goto error;
706 }
707
Stefan Agner59ae13a2015-10-13 22:11:42 -0700708 if (chip->ecc.size != mtd->writesize) {
709 dev_err(nfc->dev, "ecc size: %d\n", chip->ecc.size);
710 dev_err(nfc->dev, "Step size needs to be page size\n");
711 err = -ENXIO;
712 goto error;
713 }
714
Stefan Agnerfe10d3f2015-05-08 19:07:12 +0200715 /* Current HW ECC layouts only use 64 bytes of OOB */
716 if (mtd->oobsize > 64)
717 mtd->oobsize = 64;
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200718
719 /* propagate ecc.layout to mtd_info */
720 mtd->ecclayout = chip->ecc.layout;
721 chip->ecc.read_page = vf610_nfc_read_page;
722 chip->ecc.write_page = vf610_nfc_write_page;
723 chip->ecc.mode = NAND_ECC_HW;
724
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200725 chip->ecc.size = PAGE_2K;
Stefan Agnerfe10d3f2015-05-08 19:07:12 +0200726 chip->ecc.layout = &vf610_nfc_ecc;
727#if defined(CONFIG_SYS_NAND_VF610_NFC_45_ECC_BYTES)
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200728 chip->ecc.strength = 24;
Stefan Agnerfe10d3f2015-05-08 19:07:12 +0200729 chip->ecc.bytes = 45;
730#elif defined(CONFIG_SYS_NAND_VF610_NFC_60_ECC_BYTES)
731 chip->ecc.strength = 32;
732 chip->ecc.bytes = 60;
733#endif
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200734
Stefan Agner59ae13a2015-10-13 22:11:42 -0700735 /* Set ECC_STATUS offset */
736 vf610_nfc_set_field(mtd, NFC_FLASH_CONFIG,
Tom Rini40a35f52021-08-19 13:56:20 -0400737 CFG_ECC_SRAM_ADDR_MASK,
738 CFG_ECC_SRAM_ADDR_SHIFT,
Stefan Agner59ae13a2015-10-13 22:11:42 -0700739 ECC_SRAM_ADDR >> 3);
740
741 /* Enable ECC status in SRAM */
Tom Rini40a35f52021-08-19 13:56:20 -0400742 vf610_nfc_set(mtd, NFC_FLASH_CONFIG, CFG_ECC_SRAM_REQ_BIT);
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200743 }
744
745 /* second phase scan */
746 err = nand_scan_tail(mtd);
747 if (err)
748 return err;
749
Scott Wood2c1b7e12016-05-30 13:57:55 -0500750 err = nand_register(devnum, mtd);
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200751 if (err)
752 return err;
753
754 return 0;
755
756error:
757 return err;
758}
759
Lukasz Majewskia8f1a672018-12-03 10:24:51 +0100760#if CONFIG_NAND_VF610_NFC_DT
761static const struct udevice_id vf610_nfc_dt_ids[] = {
762 {
763 .compatible = "fsl,vf610-nfc",
764 },
765 { /* sentinel */ }
766};
767
768static int vf610_nfc_dt_probe(struct udevice *dev)
769{
770 struct resource res;
Sean Andersonf716c532020-09-15 10:44:51 -0400771 struct vf610_nfc *nfc = dev_get_priv(dev);
Lukasz Majewskia8f1a672018-12-03 10:24:51 +0100772 int ret;
773
774 ret = dev_read_resource(dev, 0, &res);
775 if (ret)
776 return ret;
777
Sean Andersonf716c532020-09-15 10:44:51 -0400778 nfc->regs = devm_ioremap(dev, res.start, resource_size(&res));
779 nfc->dev = dev;
780 return vf610_nfc_nand_init(nfc, 0);
Lukasz Majewskia8f1a672018-12-03 10:24:51 +0100781}
782
783U_BOOT_DRIVER(vf610_nfc_dt) = {
784 .name = "vf610-nfc-dt",
785 .id = UCLASS_MTD,
786 .of_match = vf610_nfc_dt_ids,
Simon Glass8a2b47f2020-12-03 16:55:17 -0700787 .priv_auto = sizeof(struct vf610_nfc),
Lukasz Majewskia8f1a672018-12-03 10:24:51 +0100788 .probe = vf610_nfc_dt_probe,
789};
790
791void board_nand_init(void)
792{
793 struct udevice *dev;
794 int ret;
795
796 ret = uclass_get_device_by_driver(UCLASS_MTD,
Simon Glass65130cd2020-12-28 20:34:56 -0700797 DM_DRIVER_GET(vf610_nfc_dt),
Lukasz Majewskia8f1a672018-12-03 10:24:51 +0100798 &dev);
799 if (ret && ret != -ENODEV)
800 pr_err("Failed to initialize NAND controller. (error %d)\n",
801 ret);
802}
803#else
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200804void board_nand_init(void)
805{
Sean Andersonf716c532020-09-15 10:44:51 -0400806 int err;
807 struct vf610_nfc *nfc;
808
809 nfc = calloc(1, sizeof(*nfc));
810 if (!nfc) {
811 printf("%s: Out of memory\n", __func__);
812 return;
813 }
814
815 nfc->regs = (void __iomem *)CONFIG_SYS_NAND_BASE;
816 err = vf610_nfc_nand_init(nfc, 0);
Stefan Agnerd6b1ccb2014-09-12 13:06:35 +0200817 if (err)
818 printf("VF610 NAND init failed (err %d)\n", err);
819}
Lukasz Majewskia8f1a672018-12-03 10:24:51 +0100820#endif /* CONFIG_NAND_VF610_NFC_DT */