1*a430fa06SMiquel Raynal // SPDX-License-Identifier: GPL-2.0+
2*a430fa06SMiquel Raynal /*
3*a430fa06SMiquel Raynal * Copyright (c) 2011 The Chromium OS Authors.
4*a430fa06SMiquel Raynal * (C) Copyright 2011 NVIDIA Corporation <www.nvidia.com>
5*a430fa06SMiquel Raynal * (C) Copyright 2006 Detlev Zundel, dzu@denx.de
6*a430fa06SMiquel Raynal * (C) Copyright 2006 DENX Software Engineering
7*a430fa06SMiquel Raynal */
8*a430fa06SMiquel Raynal
9*a430fa06SMiquel Raynal #include <common.h>
10*a430fa06SMiquel Raynal #include <asm/io.h>
11*a430fa06SMiquel Raynal #include <memalign.h>
12*a430fa06SMiquel Raynal #include <nand.h>
13*a430fa06SMiquel Raynal #include <asm/arch/clock.h>
14*a430fa06SMiquel Raynal #include <asm/arch/funcmux.h>
15*a430fa06SMiquel Raynal #include <asm/arch-tegra/clk_rst.h>
16*a430fa06SMiquel Raynal #include <linux/errno.h>
17*a430fa06SMiquel Raynal #include <asm/gpio.h>
18*a430fa06SMiquel Raynal #include <fdtdec.h>
19*a430fa06SMiquel Raynal #include <bouncebuf.h>
20*a430fa06SMiquel Raynal #include <dm.h>
21*a430fa06SMiquel Raynal #include "tegra_nand.h"
22*a430fa06SMiquel Raynal
23*a430fa06SMiquel Raynal DECLARE_GLOBAL_DATA_PTR;
24*a430fa06SMiquel Raynal
25*a430fa06SMiquel Raynal #define NAND_CMD_TIMEOUT_MS 10
26*a430fa06SMiquel Raynal
27*a430fa06SMiquel Raynal #define SKIPPED_SPARE_BYTES 4
28*a430fa06SMiquel Raynal
29*a430fa06SMiquel Raynal /* ECC bytes to be generated for tag data */
30*a430fa06SMiquel Raynal #define TAG_ECC_BYTES 4
31*a430fa06SMiquel Raynal
32*a430fa06SMiquel Raynal static const struct udevice_id tegra_nand_dt_ids[] = {
33*a430fa06SMiquel Raynal {
34*a430fa06SMiquel Raynal .compatible = "nvidia,tegra20-nand",
35*a430fa06SMiquel Raynal },
36*a430fa06SMiquel Raynal { /* sentinel */ }
37*a430fa06SMiquel Raynal };
38*a430fa06SMiquel Raynal
39*a430fa06SMiquel Raynal /* 64 byte oob block info for large page (== 2KB) device
40*a430fa06SMiquel Raynal *
41*a430fa06SMiquel Raynal * OOB flash layout for Tegra with Reed-Solomon 4 symbol correct ECC:
42*a430fa06SMiquel Raynal * Skipped bytes(4)
43*a430fa06SMiquel Raynal * Main area Ecc(36)
44*a430fa06SMiquel Raynal * Tag data(20)
45*a430fa06SMiquel Raynal * Tag data Ecc(4)
46*a430fa06SMiquel Raynal *
47*a430fa06SMiquel Raynal * Yaffs2 will use 16 tag bytes.
48*a430fa06SMiquel Raynal */
49*a430fa06SMiquel Raynal static struct nand_ecclayout eccoob = {
50*a430fa06SMiquel Raynal .eccbytes = 36,
51*a430fa06SMiquel Raynal .eccpos = {
52*a430fa06SMiquel Raynal 4, 5, 6, 7, 8, 9, 10, 11, 12,
53*a430fa06SMiquel Raynal 13, 14, 15, 16, 17, 18, 19, 20, 21,
54*a430fa06SMiquel Raynal 22, 23, 24, 25, 26, 27, 28, 29, 30,
55*a430fa06SMiquel Raynal 31, 32, 33, 34, 35, 36, 37, 38, 39,
56*a430fa06SMiquel Raynal },
57*a430fa06SMiquel Raynal .oobavail = 20,
58*a430fa06SMiquel Raynal .oobfree = {
59*a430fa06SMiquel Raynal {
60*a430fa06SMiquel Raynal .offset = 40,
61*a430fa06SMiquel Raynal .length = 20,
62*a430fa06SMiquel Raynal },
63*a430fa06SMiquel Raynal }
64*a430fa06SMiquel Raynal };
65*a430fa06SMiquel Raynal
66*a430fa06SMiquel Raynal enum {
67*a430fa06SMiquel Raynal ECC_OK,
68*a430fa06SMiquel Raynal ECC_TAG_ERROR = 1 << 0,
69*a430fa06SMiquel Raynal ECC_DATA_ERROR = 1 << 1
70*a430fa06SMiquel Raynal };
71*a430fa06SMiquel Raynal
72*a430fa06SMiquel Raynal /* Timing parameters */
73*a430fa06SMiquel Raynal enum {
74*a430fa06SMiquel Raynal FDT_NAND_MAX_TRP_TREA,
75*a430fa06SMiquel Raynal FDT_NAND_TWB,
76*a430fa06SMiquel Raynal FDT_NAND_MAX_TCR_TAR_TRR,
77*a430fa06SMiquel Raynal FDT_NAND_TWHR,
78*a430fa06SMiquel Raynal FDT_NAND_MAX_TCS_TCH_TALS_TALH,
79*a430fa06SMiquel Raynal FDT_NAND_TWH,
80*a430fa06SMiquel Raynal FDT_NAND_TWP,
81*a430fa06SMiquel Raynal FDT_NAND_TRH,
82*a430fa06SMiquel Raynal FDT_NAND_TADL,
83*a430fa06SMiquel Raynal
84*a430fa06SMiquel Raynal FDT_NAND_TIMING_COUNT
85*a430fa06SMiquel Raynal };
86*a430fa06SMiquel Raynal
87*a430fa06SMiquel Raynal /* Information about an attached NAND chip */
88*a430fa06SMiquel Raynal struct fdt_nand {
89*a430fa06SMiquel Raynal struct nand_ctlr *reg;
90*a430fa06SMiquel Raynal int enabled; /* 1 to enable, 0 to disable */
91*a430fa06SMiquel Raynal struct gpio_desc wp_gpio; /* write-protect GPIO */
92*a430fa06SMiquel Raynal s32 width; /* bit width, normally 8 */
93*a430fa06SMiquel Raynal u32 timing[FDT_NAND_TIMING_COUNT];
94*a430fa06SMiquel Raynal };
95*a430fa06SMiquel Raynal
96*a430fa06SMiquel Raynal struct nand_drv {
97*a430fa06SMiquel Raynal struct nand_ctlr *reg;
98*a430fa06SMiquel Raynal struct fdt_nand config;
99*a430fa06SMiquel Raynal };
100*a430fa06SMiquel Raynal
101*a430fa06SMiquel Raynal struct tegra_nand_info {
102*a430fa06SMiquel Raynal struct udevice *dev;
103*a430fa06SMiquel Raynal struct nand_drv nand_ctrl;
104*a430fa06SMiquel Raynal struct nand_chip nand_chip;
105*a430fa06SMiquel Raynal };
106*a430fa06SMiquel Raynal
107*a430fa06SMiquel Raynal /**
108*a430fa06SMiquel Raynal * Wait for command completion
109*a430fa06SMiquel Raynal *
110*a430fa06SMiquel Raynal * @param reg nand_ctlr structure
111*a430fa06SMiquel Raynal * @return
112*a430fa06SMiquel Raynal * 1 - Command completed
113*a430fa06SMiquel Raynal * 0 - Timeout
114*a430fa06SMiquel Raynal */
nand_waitfor_cmd_completion(struct nand_ctlr * reg)115*a430fa06SMiquel Raynal static int nand_waitfor_cmd_completion(struct nand_ctlr *reg)
116*a430fa06SMiquel Raynal {
117*a430fa06SMiquel Raynal u32 reg_val;
118*a430fa06SMiquel Raynal int running;
119*a430fa06SMiquel Raynal int i;
120*a430fa06SMiquel Raynal
121*a430fa06SMiquel Raynal for (i = 0; i < NAND_CMD_TIMEOUT_MS * 1000; i++) {
122*a430fa06SMiquel Raynal if ((readl(®->command) & CMD_GO) ||
123*a430fa06SMiquel Raynal !(readl(®->status) & STATUS_RBSY0) ||
124*a430fa06SMiquel Raynal !(readl(®->isr) & ISR_IS_CMD_DONE)) {
125*a430fa06SMiquel Raynal udelay(1);
126*a430fa06SMiquel Raynal continue;
127*a430fa06SMiquel Raynal }
128*a430fa06SMiquel Raynal reg_val = readl(®->dma_mst_ctrl);
129*a430fa06SMiquel Raynal /*
130*a430fa06SMiquel Raynal * If DMA_MST_CTRL_EN_A_ENABLE or DMA_MST_CTRL_EN_B_ENABLE
131*a430fa06SMiquel Raynal * is set, that means DMA engine is running.
132*a430fa06SMiquel Raynal *
133*a430fa06SMiquel Raynal * Then we have to wait until DMA_MST_CTRL_IS_DMA_DONE
134*a430fa06SMiquel Raynal * is cleared, indicating DMA transfer completion.
135*a430fa06SMiquel Raynal */
136*a430fa06SMiquel Raynal running = reg_val & (DMA_MST_CTRL_EN_A_ENABLE |
137*a430fa06SMiquel Raynal DMA_MST_CTRL_EN_B_ENABLE);
138*a430fa06SMiquel Raynal if (!running || (reg_val & DMA_MST_CTRL_IS_DMA_DONE))
139*a430fa06SMiquel Raynal return 1;
140*a430fa06SMiquel Raynal udelay(1);
141*a430fa06SMiquel Raynal }
142*a430fa06SMiquel Raynal return 0;
143*a430fa06SMiquel Raynal }
144*a430fa06SMiquel Raynal
145*a430fa06SMiquel Raynal /**
146*a430fa06SMiquel Raynal * Read one byte from the chip
147*a430fa06SMiquel Raynal *
148*a430fa06SMiquel Raynal * @param mtd MTD device structure
149*a430fa06SMiquel Raynal * @return data byte
150*a430fa06SMiquel Raynal *
151*a430fa06SMiquel Raynal * Read function for 8bit bus-width
152*a430fa06SMiquel Raynal */
read_byte(struct mtd_info * mtd)153*a430fa06SMiquel Raynal static uint8_t read_byte(struct mtd_info *mtd)
154*a430fa06SMiquel Raynal {
155*a430fa06SMiquel Raynal struct nand_chip *chip = mtd_to_nand(mtd);
156*a430fa06SMiquel Raynal struct nand_drv *info;
157*a430fa06SMiquel Raynal
158*a430fa06SMiquel Raynal info = (struct nand_drv *)nand_get_controller_data(chip);
159*a430fa06SMiquel Raynal
160*a430fa06SMiquel Raynal writel(CMD_GO | CMD_PIO | CMD_RX | CMD_CE0 | CMD_A_VALID,
161*a430fa06SMiquel Raynal &info->reg->command);
162*a430fa06SMiquel Raynal if (!nand_waitfor_cmd_completion(info->reg))
163*a430fa06SMiquel Raynal printf("Command timeout\n");
164*a430fa06SMiquel Raynal
165*a430fa06SMiquel Raynal return (uint8_t)readl(&info->reg->resp);
166*a430fa06SMiquel Raynal }
167*a430fa06SMiquel Raynal
168*a430fa06SMiquel Raynal /**
169*a430fa06SMiquel Raynal * Read len bytes from the chip into a buffer
170*a430fa06SMiquel Raynal *
171*a430fa06SMiquel Raynal * @param mtd MTD device structure
172*a430fa06SMiquel Raynal * @param buf buffer to store data to
173*a430fa06SMiquel Raynal * @param len number of bytes to read
174*a430fa06SMiquel Raynal *
175*a430fa06SMiquel Raynal * Read function for 8bit bus-width
176*a430fa06SMiquel Raynal */
read_buf(struct mtd_info * mtd,uint8_t * buf,int len)177*a430fa06SMiquel Raynal static void read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
178*a430fa06SMiquel Raynal {
179*a430fa06SMiquel Raynal int i, s;
180*a430fa06SMiquel Raynal unsigned int reg;
181*a430fa06SMiquel Raynal struct nand_chip *chip = mtd_to_nand(mtd);
182*a430fa06SMiquel Raynal struct nand_drv *info = (struct nand_drv *)nand_get_controller_data(chip);
183*a430fa06SMiquel Raynal
184*a430fa06SMiquel Raynal for (i = 0; i < len; i += 4) {
185*a430fa06SMiquel Raynal s = (len - i) > 4 ? 4 : len - i;
186*a430fa06SMiquel Raynal writel(CMD_PIO | CMD_RX | CMD_A_VALID | CMD_CE0 |
187*a430fa06SMiquel Raynal ((s - 1) << CMD_TRANS_SIZE_SHIFT) | CMD_GO,
188*a430fa06SMiquel Raynal &info->reg->command);
189*a430fa06SMiquel Raynal if (!nand_waitfor_cmd_completion(info->reg))
190*a430fa06SMiquel Raynal puts("Command timeout during read_buf\n");
191*a430fa06SMiquel Raynal reg = readl(&info->reg->resp);
192*a430fa06SMiquel Raynal memcpy(buf + i, ®, s);
193*a430fa06SMiquel Raynal }
194*a430fa06SMiquel Raynal }
195*a430fa06SMiquel Raynal
196*a430fa06SMiquel Raynal /**
197*a430fa06SMiquel Raynal * Check NAND status to see if it is ready or not
198*a430fa06SMiquel Raynal *
199*a430fa06SMiquel Raynal * @param mtd MTD device structure
200*a430fa06SMiquel Raynal * @return
201*a430fa06SMiquel Raynal * 1 - ready
202*a430fa06SMiquel Raynal * 0 - not ready
203*a430fa06SMiquel Raynal */
nand_dev_ready(struct mtd_info * mtd)204*a430fa06SMiquel Raynal static int nand_dev_ready(struct mtd_info *mtd)
205*a430fa06SMiquel Raynal {
206*a430fa06SMiquel Raynal struct nand_chip *chip = mtd_to_nand(mtd);
207*a430fa06SMiquel Raynal int reg_val;
208*a430fa06SMiquel Raynal struct nand_drv *info;
209*a430fa06SMiquel Raynal
210*a430fa06SMiquel Raynal info = (struct nand_drv *)nand_get_controller_data(chip);
211*a430fa06SMiquel Raynal
212*a430fa06SMiquel Raynal reg_val = readl(&info->reg->status);
213*a430fa06SMiquel Raynal if (reg_val & STATUS_RBSY0)
214*a430fa06SMiquel Raynal return 1;
215*a430fa06SMiquel Raynal else
216*a430fa06SMiquel Raynal return 0;
217*a430fa06SMiquel Raynal }
218*a430fa06SMiquel Raynal
219*a430fa06SMiquel Raynal /* Dummy implementation: we don't support multiple chips */
nand_select_chip(struct mtd_info * mtd,int chipnr)220*a430fa06SMiquel Raynal static void nand_select_chip(struct mtd_info *mtd, int chipnr)
221*a430fa06SMiquel Raynal {
222*a430fa06SMiquel Raynal switch (chipnr) {
223*a430fa06SMiquel Raynal case -1:
224*a430fa06SMiquel Raynal case 0:
225*a430fa06SMiquel Raynal break;
226*a430fa06SMiquel Raynal
227*a430fa06SMiquel Raynal default:
228*a430fa06SMiquel Raynal BUG();
229*a430fa06SMiquel Raynal }
230*a430fa06SMiquel Raynal }
231*a430fa06SMiquel Raynal
232*a430fa06SMiquel Raynal /**
233*a430fa06SMiquel Raynal * Clear all interrupt status bits
234*a430fa06SMiquel Raynal *
235*a430fa06SMiquel Raynal * @param reg nand_ctlr structure
236*a430fa06SMiquel Raynal */
nand_clear_interrupt_status(struct nand_ctlr * reg)237*a430fa06SMiquel Raynal static void nand_clear_interrupt_status(struct nand_ctlr *reg)
238*a430fa06SMiquel Raynal {
239*a430fa06SMiquel Raynal u32 reg_val;
240*a430fa06SMiquel Raynal
241*a430fa06SMiquel Raynal /* Clear interrupt status */
242*a430fa06SMiquel Raynal reg_val = readl(®->isr);
243*a430fa06SMiquel Raynal writel(reg_val, ®->isr);
244*a430fa06SMiquel Raynal }
245*a430fa06SMiquel Raynal
246*a430fa06SMiquel Raynal /**
247*a430fa06SMiquel Raynal * Send command to NAND device
248*a430fa06SMiquel Raynal *
249*a430fa06SMiquel Raynal * @param mtd MTD device structure
250*a430fa06SMiquel Raynal * @param command the command to be sent
251*a430fa06SMiquel Raynal * @param column the column address for this command, -1 if none
252*a430fa06SMiquel Raynal * @param page_addr the page address for this command, -1 if none
253*a430fa06SMiquel Raynal */
nand_command(struct mtd_info * mtd,unsigned int command,int column,int page_addr)254*a430fa06SMiquel Raynal static void nand_command(struct mtd_info *mtd, unsigned int command,
255*a430fa06SMiquel Raynal int column, int page_addr)
256*a430fa06SMiquel Raynal {
257*a430fa06SMiquel Raynal struct nand_chip *chip = mtd_to_nand(mtd);
258*a430fa06SMiquel Raynal struct nand_drv *info;
259*a430fa06SMiquel Raynal
260*a430fa06SMiquel Raynal info = (struct nand_drv *)nand_get_controller_data(chip);
261*a430fa06SMiquel Raynal
262*a430fa06SMiquel Raynal /*
263*a430fa06SMiquel Raynal * Write out the command to the device.
264*a430fa06SMiquel Raynal *
265*a430fa06SMiquel Raynal * Only command NAND_CMD_RESET or NAND_CMD_READID will come
266*a430fa06SMiquel Raynal * here before mtd->writesize is initialized.
267*a430fa06SMiquel Raynal */
268*a430fa06SMiquel Raynal
269*a430fa06SMiquel Raynal /* Emulate NAND_CMD_READOOB */
270*a430fa06SMiquel Raynal if (command == NAND_CMD_READOOB) {
271*a430fa06SMiquel Raynal assert(mtd->writesize != 0);
272*a430fa06SMiquel Raynal column += mtd->writesize;
273*a430fa06SMiquel Raynal command = NAND_CMD_READ0;
274*a430fa06SMiquel Raynal }
275*a430fa06SMiquel Raynal
276*a430fa06SMiquel Raynal /* Adjust columns for 16 bit bus-width */
277*a430fa06SMiquel Raynal if (column != -1 && (chip->options & NAND_BUSWIDTH_16))
278*a430fa06SMiquel Raynal column >>= 1;
279*a430fa06SMiquel Raynal
280*a430fa06SMiquel Raynal nand_clear_interrupt_status(info->reg);
281*a430fa06SMiquel Raynal
282*a430fa06SMiquel Raynal /* Stop DMA engine, clear DMA completion status */
283*a430fa06SMiquel Raynal writel(DMA_MST_CTRL_EN_A_DISABLE
284*a430fa06SMiquel Raynal | DMA_MST_CTRL_EN_B_DISABLE
285*a430fa06SMiquel Raynal | DMA_MST_CTRL_IS_DMA_DONE,
286*a430fa06SMiquel Raynal &info->reg->dma_mst_ctrl);
287*a430fa06SMiquel Raynal
288*a430fa06SMiquel Raynal /*
289*a430fa06SMiquel Raynal * Program and erase have their own busy handlers
290*a430fa06SMiquel Raynal * status and sequential in needs no delay
291*a430fa06SMiquel Raynal */
292*a430fa06SMiquel Raynal switch (command) {
293*a430fa06SMiquel Raynal case NAND_CMD_READID:
294*a430fa06SMiquel Raynal writel(NAND_CMD_READID, &info->reg->cmd_reg1);
295*a430fa06SMiquel Raynal writel(column & 0xFF, &info->reg->addr_reg1);
296*a430fa06SMiquel Raynal writel(CMD_GO | CMD_CLE | CMD_ALE | CMD_CE0,
297*a430fa06SMiquel Raynal &info->reg->command);
298*a430fa06SMiquel Raynal break;
299*a430fa06SMiquel Raynal case NAND_CMD_PARAM:
300*a430fa06SMiquel Raynal writel(NAND_CMD_PARAM, &info->reg->cmd_reg1);
301*a430fa06SMiquel Raynal writel(column & 0xFF, &info->reg->addr_reg1);
302*a430fa06SMiquel Raynal writel(CMD_GO | CMD_CLE | CMD_ALE | CMD_CE0,
303*a430fa06SMiquel Raynal &info->reg->command);
304*a430fa06SMiquel Raynal break;
305*a430fa06SMiquel Raynal case NAND_CMD_READ0:
306*a430fa06SMiquel Raynal writel(NAND_CMD_READ0, &info->reg->cmd_reg1);
307*a430fa06SMiquel Raynal writel(NAND_CMD_READSTART, &info->reg->cmd_reg2);
308*a430fa06SMiquel Raynal writel((page_addr << 16) | (column & 0xFFFF),
309*a430fa06SMiquel Raynal &info->reg->addr_reg1);
310*a430fa06SMiquel Raynal writel(page_addr >> 16, &info->reg->addr_reg2);
311*a430fa06SMiquel Raynal return;
312*a430fa06SMiquel Raynal case NAND_CMD_SEQIN:
313*a430fa06SMiquel Raynal writel(NAND_CMD_SEQIN, &info->reg->cmd_reg1);
314*a430fa06SMiquel Raynal writel(NAND_CMD_PAGEPROG, &info->reg->cmd_reg2);
315*a430fa06SMiquel Raynal writel((page_addr << 16) | (column & 0xFFFF),
316*a430fa06SMiquel Raynal &info->reg->addr_reg1);
317*a430fa06SMiquel Raynal writel(page_addr >> 16,
318*a430fa06SMiquel Raynal &info->reg->addr_reg2);
319*a430fa06SMiquel Raynal return;
320*a430fa06SMiquel Raynal case NAND_CMD_PAGEPROG:
321*a430fa06SMiquel Raynal return;
322*a430fa06SMiquel Raynal case NAND_CMD_ERASE1:
323*a430fa06SMiquel Raynal writel(NAND_CMD_ERASE1, &info->reg->cmd_reg1);
324*a430fa06SMiquel Raynal writel(NAND_CMD_ERASE2, &info->reg->cmd_reg2);
325*a430fa06SMiquel Raynal writel(page_addr, &info->reg->addr_reg1);
326*a430fa06SMiquel Raynal writel(CMD_GO | CMD_CLE | CMD_ALE |
327*a430fa06SMiquel Raynal CMD_SEC_CMD | CMD_CE0 | CMD_ALE_BYTES3,
328*a430fa06SMiquel Raynal &info->reg->command);
329*a430fa06SMiquel Raynal break;
330*a430fa06SMiquel Raynal case NAND_CMD_ERASE2:
331*a430fa06SMiquel Raynal return;
332*a430fa06SMiquel Raynal case NAND_CMD_STATUS:
333*a430fa06SMiquel Raynal writel(NAND_CMD_STATUS, &info->reg->cmd_reg1);
334*a430fa06SMiquel Raynal writel(CMD_GO | CMD_CLE | CMD_PIO | CMD_RX
335*a430fa06SMiquel Raynal | ((1 - 0) << CMD_TRANS_SIZE_SHIFT)
336*a430fa06SMiquel Raynal | CMD_CE0,
337*a430fa06SMiquel Raynal &info->reg->command);
338*a430fa06SMiquel Raynal break;
339*a430fa06SMiquel Raynal case NAND_CMD_RESET:
340*a430fa06SMiquel Raynal writel(NAND_CMD_RESET, &info->reg->cmd_reg1);
341*a430fa06SMiquel Raynal writel(CMD_GO | CMD_CLE | CMD_CE0,
342*a430fa06SMiquel Raynal &info->reg->command);
343*a430fa06SMiquel Raynal break;
344*a430fa06SMiquel Raynal case NAND_CMD_RNDOUT:
345*a430fa06SMiquel Raynal default:
346*a430fa06SMiquel Raynal printf("%s: Unsupported command %d\n", __func__, command);
347*a430fa06SMiquel Raynal return;
348*a430fa06SMiquel Raynal }
349*a430fa06SMiquel Raynal if (!nand_waitfor_cmd_completion(info->reg))
350*a430fa06SMiquel Raynal printf("Command 0x%02X timeout\n", command);
351*a430fa06SMiquel Raynal }
352*a430fa06SMiquel Raynal
353*a430fa06SMiquel Raynal /**
354*a430fa06SMiquel Raynal * Check whether the pointed buffer are all 0xff (blank).
355*a430fa06SMiquel Raynal *
356*a430fa06SMiquel Raynal * @param buf data buffer for blank check
357*a430fa06SMiquel Raynal * @param len length of the buffer in byte
358*a430fa06SMiquel Raynal * @return
359*a430fa06SMiquel Raynal * 1 - blank
360*a430fa06SMiquel Raynal * 0 - non-blank
361*a430fa06SMiquel Raynal */
blank_check(u8 * buf,int len)362*a430fa06SMiquel Raynal static int blank_check(u8 *buf, int len)
363*a430fa06SMiquel Raynal {
364*a430fa06SMiquel Raynal int i;
365*a430fa06SMiquel Raynal
366*a430fa06SMiquel Raynal for (i = 0; i < len; i++)
367*a430fa06SMiquel Raynal if (buf[i] != 0xFF)
368*a430fa06SMiquel Raynal return 0;
369*a430fa06SMiquel Raynal return 1;
370*a430fa06SMiquel Raynal }
371*a430fa06SMiquel Raynal
372*a430fa06SMiquel Raynal /**
373*a430fa06SMiquel Raynal * After a DMA transfer for read, we call this function to see whether there
374*a430fa06SMiquel Raynal * is any uncorrectable error on the pointed data buffer or oob buffer.
375*a430fa06SMiquel Raynal *
376*a430fa06SMiquel Raynal * @param reg nand_ctlr structure
377*a430fa06SMiquel Raynal * @param databuf data buffer
378*a430fa06SMiquel Raynal * @param a_len data buffer length
379*a430fa06SMiquel Raynal * @param oobbuf oob buffer
380*a430fa06SMiquel Raynal * @param b_len oob buffer length
381*a430fa06SMiquel Raynal * @return
382*a430fa06SMiquel Raynal * ECC_OK - no ECC error or correctable ECC error
383*a430fa06SMiquel Raynal * ECC_TAG_ERROR - uncorrectable tag ECC error
384*a430fa06SMiquel Raynal * ECC_DATA_ERROR - uncorrectable data ECC error
385*a430fa06SMiquel Raynal * ECC_DATA_ERROR + ECC_TAG_ERROR - uncorrectable data+tag ECC error
386*a430fa06SMiquel Raynal */
check_ecc_error(struct nand_ctlr * reg,u8 * databuf,int a_len,u8 * oobbuf,int b_len)387*a430fa06SMiquel Raynal static int check_ecc_error(struct nand_ctlr *reg, u8 *databuf,
388*a430fa06SMiquel Raynal int a_len, u8 *oobbuf, int b_len)
389*a430fa06SMiquel Raynal {
390*a430fa06SMiquel Raynal int return_val = ECC_OK;
391*a430fa06SMiquel Raynal u32 reg_val;
392*a430fa06SMiquel Raynal
393*a430fa06SMiquel Raynal if (!(readl(®->isr) & ISR_IS_ECC_ERR))
394*a430fa06SMiquel Raynal return ECC_OK;
395*a430fa06SMiquel Raynal
396*a430fa06SMiquel Raynal /*
397*a430fa06SMiquel Raynal * Area A is used for the data block (databuf). Area B is used for
398*a430fa06SMiquel Raynal * the spare block (oobbuf)
399*a430fa06SMiquel Raynal */
400*a430fa06SMiquel Raynal reg_val = readl(®->dec_status);
401*a430fa06SMiquel Raynal if ((reg_val & DEC_STATUS_A_ECC_FAIL) && databuf) {
402*a430fa06SMiquel Raynal reg_val = readl(®->bch_dec_status_buf);
403*a430fa06SMiquel Raynal /*
404*a430fa06SMiquel Raynal * If uncorrectable error occurs on data area, then see whether
405*a430fa06SMiquel Raynal * they are all FF. If all are FF, it's a blank page.
406*a430fa06SMiquel Raynal * Not error.
407*a430fa06SMiquel Raynal */
408*a430fa06SMiquel Raynal if ((reg_val & BCH_DEC_STATUS_FAIL_SEC_FLAG_MASK) &&
409*a430fa06SMiquel Raynal !blank_check(databuf, a_len))
410*a430fa06SMiquel Raynal return_val |= ECC_DATA_ERROR;
411*a430fa06SMiquel Raynal }
412*a430fa06SMiquel Raynal
413*a430fa06SMiquel Raynal if ((reg_val & DEC_STATUS_B_ECC_FAIL) && oobbuf) {
414*a430fa06SMiquel Raynal reg_val = readl(®->bch_dec_status_buf);
415*a430fa06SMiquel Raynal /*
416*a430fa06SMiquel Raynal * If uncorrectable error occurs on tag area, then see whether
417*a430fa06SMiquel Raynal * they are all FF. If all are FF, it's a blank page.
418*a430fa06SMiquel Raynal * Not error.
419*a430fa06SMiquel Raynal */
420*a430fa06SMiquel Raynal if ((reg_val & BCH_DEC_STATUS_FAIL_TAG_MASK) &&
421*a430fa06SMiquel Raynal !blank_check(oobbuf, b_len))
422*a430fa06SMiquel Raynal return_val |= ECC_TAG_ERROR;
423*a430fa06SMiquel Raynal }
424*a430fa06SMiquel Raynal
425*a430fa06SMiquel Raynal return return_val;
426*a430fa06SMiquel Raynal }
427*a430fa06SMiquel Raynal
428*a430fa06SMiquel Raynal /**
429*a430fa06SMiquel Raynal * Set GO bit to send command to device
430*a430fa06SMiquel Raynal *
431*a430fa06SMiquel Raynal * @param reg nand_ctlr structure
432*a430fa06SMiquel Raynal */
start_command(struct nand_ctlr * reg)433*a430fa06SMiquel Raynal static void start_command(struct nand_ctlr *reg)
434*a430fa06SMiquel Raynal {
435*a430fa06SMiquel Raynal u32 reg_val;
436*a430fa06SMiquel Raynal
437*a430fa06SMiquel Raynal reg_val = readl(®->command);
438*a430fa06SMiquel Raynal reg_val |= CMD_GO;
439*a430fa06SMiquel Raynal writel(reg_val, ®->command);
440*a430fa06SMiquel Raynal }
441*a430fa06SMiquel Raynal
442*a430fa06SMiquel Raynal /**
443*a430fa06SMiquel Raynal * Clear command GO bit, DMA GO bit, and DMA completion status
444*a430fa06SMiquel Raynal *
445*a430fa06SMiquel Raynal * @param reg nand_ctlr structure
446*a430fa06SMiquel Raynal */
stop_command(struct nand_ctlr * reg)447*a430fa06SMiquel Raynal static void stop_command(struct nand_ctlr *reg)
448*a430fa06SMiquel Raynal {
449*a430fa06SMiquel Raynal /* Stop command */
450*a430fa06SMiquel Raynal writel(0, ®->command);
451*a430fa06SMiquel Raynal
452*a430fa06SMiquel Raynal /* Stop DMA engine and clear DMA completion status */
453*a430fa06SMiquel Raynal writel(DMA_MST_CTRL_GO_DISABLE
454*a430fa06SMiquel Raynal | DMA_MST_CTRL_IS_DMA_DONE,
455*a430fa06SMiquel Raynal ®->dma_mst_ctrl);
456*a430fa06SMiquel Raynal }
457*a430fa06SMiquel Raynal
458*a430fa06SMiquel Raynal /**
459*a430fa06SMiquel Raynal * Set up NAND bus width and page size
460*a430fa06SMiquel Raynal *
461*a430fa06SMiquel Raynal * @param info nand_info structure
462*a430fa06SMiquel Raynal * @param *reg_val address of reg_val
463*a430fa06SMiquel Raynal * @return 0 if ok, -1 on error
464*a430fa06SMiquel Raynal */
set_bus_width_page_size(struct mtd_info * our_mtd,struct fdt_nand * config,u32 * reg_val)465*a430fa06SMiquel Raynal static int set_bus_width_page_size(struct mtd_info *our_mtd,
466*a430fa06SMiquel Raynal struct fdt_nand *config, u32 *reg_val)
467*a430fa06SMiquel Raynal {
468*a430fa06SMiquel Raynal if (config->width == 8)
469*a430fa06SMiquel Raynal *reg_val = CFG_BUS_WIDTH_8BIT;
470*a430fa06SMiquel Raynal else if (config->width == 16)
471*a430fa06SMiquel Raynal *reg_val = CFG_BUS_WIDTH_16BIT;
472*a430fa06SMiquel Raynal else {
473*a430fa06SMiquel Raynal debug("%s: Unsupported bus width %d\n", __func__,
474*a430fa06SMiquel Raynal config->width);
475*a430fa06SMiquel Raynal return -1;
476*a430fa06SMiquel Raynal }
477*a430fa06SMiquel Raynal
478*a430fa06SMiquel Raynal if (our_mtd->writesize == 512)
479*a430fa06SMiquel Raynal *reg_val |= CFG_PAGE_SIZE_512;
480*a430fa06SMiquel Raynal else if (our_mtd->writesize == 2048)
481*a430fa06SMiquel Raynal *reg_val |= CFG_PAGE_SIZE_2048;
482*a430fa06SMiquel Raynal else if (our_mtd->writesize == 4096)
483*a430fa06SMiquel Raynal *reg_val |= CFG_PAGE_SIZE_4096;
484*a430fa06SMiquel Raynal else {
485*a430fa06SMiquel Raynal debug("%s: Unsupported page size %d\n", __func__,
486*a430fa06SMiquel Raynal our_mtd->writesize);
487*a430fa06SMiquel Raynal return -1;
488*a430fa06SMiquel Raynal }
489*a430fa06SMiquel Raynal
490*a430fa06SMiquel Raynal return 0;
491*a430fa06SMiquel Raynal }
492*a430fa06SMiquel Raynal
493*a430fa06SMiquel Raynal /**
494*a430fa06SMiquel Raynal * Page read/write function
495*a430fa06SMiquel Raynal *
496*a430fa06SMiquel Raynal * @param mtd mtd info structure
497*a430fa06SMiquel Raynal * @param chip nand chip info structure
498*a430fa06SMiquel Raynal * @param buf data buffer
499*a430fa06SMiquel Raynal * @param page page number
500*a430fa06SMiquel Raynal * @param with_ecc 1 to enable ECC, 0 to disable ECC
501*a430fa06SMiquel Raynal * @param is_writing 0 for read, 1 for write
502*a430fa06SMiquel Raynal * @return 0 when successfully completed
503*a430fa06SMiquel Raynal * -EIO when command timeout
504*a430fa06SMiquel Raynal */
nand_rw_page(struct mtd_info * mtd,struct nand_chip * chip,uint8_t * buf,int page,int with_ecc,int is_writing)505*a430fa06SMiquel Raynal static int nand_rw_page(struct mtd_info *mtd, struct nand_chip *chip,
506*a430fa06SMiquel Raynal uint8_t *buf, int page, int with_ecc, int is_writing)
507*a430fa06SMiquel Raynal {
508*a430fa06SMiquel Raynal u32 reg_val;
509*a430fa06SMiquel Raynal int tag_size;
510*a430fa06SMiquel Raynal struct nand_oobfree *free = chip->ecc.layout->oobfree;
511*a430fa06SMiquel Raynal /* 4*128=512 (byte) is the value that our HW can support. */
512*a430fa06SMiquel Raynal ALLOC_CACHE_ALIGN_BUFFER(u32, tag_buf, 128);
513*a430fa06SMiquel Raynal char *tag_ptr;
514*a430fa06SMiquel Raynal struct nand_drv *info;
515*a430fa06SMiquel Raynal struct fdt_nand *config;
516*a430fa06SMiquel Raynal unsigned int bbflags;
517*a430fa06SMiquel Raynal struct bounce_buffer bbstate, bbstate_oob;
518*a430fa06SMiquel Raynal
519*a430fa06SMiquel Raynal if ((uintptr_t)buf & 0x03) {
520*a430fa06SMiquel Raynal printf("buf %p has to be 4-byte aligned\n", buf);
521*a430fa06SMiquel Raynal return -EINVAL;
522*a430fa06SMiquel Raynal }
523*a430fa06SMiquel Raynal
524*a430fa06SMiquel Raynal info = (struct nand_drv *)nand_get_controller_data(chip);
525*a430fa06SMiquel Raynal config = &info->config;
526*a430fa06SMiquel Raynal if (set_bus_width_page_size(mtd, config, ®_val))
527*a430fa06SMiquel Raynal return -EINVAL;
528*a430fa06SMiquel Raynal
529*a430fa06SMiquel Raynal /* Need to be 4-byte aligned */
530*a430fa06SMiquel Raynal tag_ptr = (char *)tag_buf;
531*a430fa06SMiquel Raynal
532*a430fa06SMiquel Raynal stop_command(info->reg);
533*a430fa06SMiquel Raynal
534*a430fa06SMiquel Raynal if (is_writing)
535*a430fa06SMiquel Raynal bbflags = GEN_BB_READ;
536*a430fa06SMiquel Raynal else
537*a430fa06SMiquel Raynal bbflags = GEN_BB_WRITE;
538*a430fa06SMiquel Raynal
539*a430fa06SMiquel Raynal bounce_buffer_start(&bbstate, (void *)buf, 1 << chip->page_shift,
540*a430fa06SMiquel Raynal bbflags);
541*a430fa06SMiquel Raynal writel((1 << chip->page_shift) - 1, &info->reg->dma_cfg_a);
542*a430fa06SMiquel Raynal writel(virt_to_phys(bbstate.bounce_buffer), &info->reg->data_block_ptr);
543*a430fa06SMiquel Raynal
544*a430fa06SMiquel Raynal /* Set ECC selection, configure ECC settings */
545*a430fa06SMiquel Raynal if (with_ecc) {
546*a430fa06SMiquel Raynal if (is_writing)
547*a430fa06SMiquel Raynal memcpy(tag_ptr, chip->oob_poi + free->offset,
548*a430fa06SMiquel Raynal chip->ecc.layout->oobavail + TAG_ECC_BYTES);
549*a430fa06SMiquel Raynal tag_size = chip->ecc.layout->oobavail + TAG_ECC_BYTES;
550*a430fa06SMiquel Raynal reg_val |= (CFG_SKIP_SPARE_SEL_4
551*a430fa06SMiquel Raynal | CFG_SKIP_SPARE_ENABLE
552*a430fa06SMiquel Raynal | CFG_HW_ECC_CORRECTION_ENABLE
553*a430fa06SMiquel Raynal | CFG_ECC_EN_TAG_DISABLE
554*a430fa06SMiquel Raynal | CFG_HW_ECC_SEL_RS
555*a430fa06SMiquel Raynal | CFG_HW_ECC_ENABLE
556*a430fa06SMiquel Raynal | CFG_TVAL4
557*a430fa06SMiquel Raynal | (tag_size - 1));
558*a430fa06SMiquel Raynal
559*a430fa06SMiquel Raynal if (!is_writing)
560*a430fa06SMiquel Raynal tag_size += SKIPPED_SPARE_BYTES;
561*a430fa06SMiquel Raynal bounce_buffer_start(&bbstate_oob, (void *)tag_ptr, tag_size,
562*a430fa06SMiquel Raynal bbflags);
563*a430fa06SMiquel Raynal } else {
564*a430fa06SMiquel Raynal tag_size = mtd->oobsize;
565*a430fa06SMiquel Raynal reg_val |= (CFG_SKIP_SPARE_DISABLE
566*a430fa06SMiquel Raynal | CFG_HW_ECC_CORRECTION_DISABLE
567*a430fa06SMiquel Raynal | CFG_ECC_EN_TAG_DISABLE
568*a430fa06SMiquel Raynal | CFG_HW_ECC_DISABLE
569*a430fa06SMiquel Raynal | (tag_size - 1));
570*a430fa06SMiquel Raynal bounce_buffer_start(&bbstate_oob, (void *)chip->oob_poi,
571*a430fa06SMiquel Raynal tag_size, bbflags);
572*a430fa06SMiquel Raynal }
573*a430fa06SMiquel Raynal writel(reg_val, &info->reg->config);
574*a430fa06SMiquel Raynal writel(virt_to_phys(bbstate_oob.bounce_buffer), &info->reg->tag_ptr);
575*a430fa06SMiquel Raynal writel(BCH_CONFIG_BCH_ECC_DISABLE, &info->reg->bch_config);
576*a430fa06SMiquel Raynal writel(tag_size - 1, &info->reg->dma_cfg_b);
577*a430fa06SMiquel Raynal
578*a430fa06SMiquel Raynal nand_clear_interrupt_status(info->reg);
579*a430fa06SMiquel Raynal
580*a430fa06SMiquel Raynal reg_val = CMD_CLE | CMD_ALE
581*a430fa06SMiquel Raynal | CMD_SEC_CMD
582*a430fa06SMiquel Raynal | (CMD_ALE_BYTES5 << CMD_ALE_BYTE_SIZE_SHIFT)
583*a430fa06SMiquel Raynal | CMD_A_VALID
584*a430fa06SMiquel Raynal | CMD_B_VALID
585*a430fa06SMiquel Raynal | (CMD_TRANS_SIZE_PAGE << CMD_TRANS_SIZE_SHIFT)
586*a430fa06SMiquel Raynal | CMD_CE0;
587*a430fa06SMiquel Raynal if (!is_writing)
588*a430fa06SMiquel Raynal reg_val |= (CMD_AFT_DAT_DISABLE | CMD_RX);
589*a430fa06SMiquel Raynal else
590*a430fa06SMiquel Raynal reg_val |= (CMD_AFT_DAT_ENABLE | CMD_TX);
591*a430fa06SMiquel Raynal writel(reg_val, &info->reg->command);
592*a430fa06SMiquel Raynal
593*a430fa06SMiquel Raynal /* Setup DMA engine */
594*a430fa06SMiquel Raynal reg_val = DMA_MST_CTRL_GO_ENABLE
595*a430fa06SMiquel Raynal | DMA_MST_CTRL_BURST_8WORDS
596*a430fa06SMiquel Raynal | DMA_MST_CTRL_EN_A_ENABLE
597*a430fa06SMiquel Raynal | DMA_MST_CTRL_EN_B_ENABLE;
598*a430fa06SMiquel Raynal
599*a430fa06SMiquel Raynal if (!is_writing)
600*a430fa06SMiquel Raynal reg_val |= DMA_MST_CTRL_DIR_READ;
601*a430fa06SMiquel Raynal else
602*a430fa06SMiquel Raynal reg_val |= DMA_MST_CTRL_DIR_WRITE;
603*a430fa06SMiquel Raynal
604*a430fa06SMiquel Raynal writel(reg_val, &info->reg->dma_mst_ctrl);
605*a430fa06SMiquel Raynal
606*a430fa06SMiquel Raynal start_command(info->reg);
607*a430fa06SMiquel Raynal
608*a430fa06SMiquel Raynal if (!nand_waitfor_cmd_completion(info->reg)) {
609*a430fa06SMiquel Raynal if (!is_writing)
610*a430fa06SMiquel Raynal printf("Read Page 0x%X timeout ", page);
611*a430fa06SMiquel Raynal else
612*a430fa06SMiquel Raynal printf("Write Page 0x%X timeout ", page);
613*a430fa06SMiquel Raynal if (with_ecc)
614*a430fa06SMiquel Raynal printf("with ECC");
615*a430fa06SMiquel Raynal else
616*a430fa06SMiquel Raynal printf("without ECC");
617*a430fa06SMiquel Raynal printf("\n");
618*a430fa06SMiquel Raynal return -EIO;
619*a430fa06SMiquel Raynal }
620*a430fa06SMiquel Raynal
621*a430fa06SMiquel Raynal bounce_buffer_stop(&bbstate_oob);
622*a430fa06SMiquel Raynal bounce_buffer_stop(&bbstate);
623*a430fa06SMiquel Raynal
624*a430fa06SMiquel Raynal if (with_ecc && !is_writing) {
625*a430fa06SMiquel Raynal memcpy(chip->oob_poi, tag_ptr,
626*a430fa06SMiquel Raynal SKIPPED_SPARE_BYTES);
627*a430fa06SMiquel Raynal memcpy(chip->oob_poi + free->offset,
628*a430fa06SMiquel Raynal tag_ptr + SKIPPED_SPARE_BYTES,
629*a430fa06SMiquel Raynal chip->ecc.layout->oobavail);
630*a430fa06SMiquel Raynal reg_val = (u32)check_ecc_error(info->reg, (u8 *)buf,
631*a430fa06SMiquel Raynal 1 << chip->page_shift,
632*a430fa06SMiquel Raynal (u8 *)(tag_ptr + SKIPPED_SPARE_BYTES),
633*a430fa06SMiquel Raynal chip->ecc.layout->oobavail);
634*a430fa06SMiquel Raynal if (reg_val & ECC_TAG_ERROR)
635*a430fa06SMiquel Raynal printf("Read Page 0x%X tag ECC error\n", page);
636*a430fa06SMiquel Raynal if (reg_val & ECC_DATA_ERROR)
637*a430fa06SMiquel Raynal printf("Read Page 0x%X data ECC error\n",
638*a430fa06SMiquel Raynal page);
639*a430fa06SMiquel Raynal if (reg_val & (ECC_DATA_ERROR | ECC_TAG_ERROR))
640*a430fa06SMiquel Raynal return -EIO;
641*a430fa06SMiquel Raynal }
642*a430fa06SMiquel Raynal return 0;
643*a430fa06SMiquel Raynal }
644*a430fa06SMiquel Raynal
645*a430fa06SMiquel Raynal /**
646*a430fa06SMiquel Raynal * Hardware ecc based page read function
647*a430fa06SMiquel Raynal *
648*a430fa06SMiquel Raynal * @param mtd mtd info structure
649*a430fa06SMiquel Raynal * @param chip nand chip info structure
650*a430fa06SMiquel Raynal * @param buf buffer to store read data
651*a430fa06SMiquel Raynal * @param page page number to read
652*a430fa06SMiquel Raynal * @return 0 when successfully completed
653*a430fa06SMiquel Raynal * -EIO when command timeout
654*a430fa06SMiquel Raynal */
nand_read_page_hwecc(struct mtd_info * mtd,struct nand_chip * chip,uint8_t * buf,int oob_required,int page)655*a430fa06SMiquel Raynal static int nand_read_page_hwecc(struct mtd_info *mtd,
656*a430fa06SMiquel Raynal struct nand_chip *chip, uint8_t *buf, int oob_required, int page)
657*a430fa06SMiquel Raynal {
658*a430fa06SMiquel Raynal return nand_rw_page(mtd, chip, buf, page, 1, 0);
659*a430fa06SMiquel Raynal }
660*a430fa06SMiquel Raynal
661*a430fa06SMiquel Raynal /**
662*a430fa06SMiquel Raynal * Hardware ecc based page write function
663*a430fa06SMiquel Raynal *
664*a430fa06SMiquel Raynal * @param mtd mtd info structure
665*a430fa06SMiquel Raynal * @param chip nand chip info structure
666*a430fa06SMiquel Raynal * @param buf data buffer
667*a430fa06SMiquel Raynal */
nand_write_page_hwecc(struct mtd_info * mtd,struct nand_chip * chip,const uint8_t * buf,int oob_required,int page)668*a430fa06SMiquel Raynal static int nand_write_page_hwecc(struct mtd_info *mtd,
669*a430fa06SMiquel Raynal struct nand_chip *chip, const uint8_t *buf, int oob_required,
670*a430fa06SMiquel Raynal int page)
671*a430fa06SMiquel Raynal {
672*a430fa06SMiquel Raynal nand_rw_page(mtd, chip, (uint8_t *)buf, page, 1, 1);
673*a430fa06SMiquel Raynal return 0;
674*a430fa06SMiquel Raynal }
675*a430fa06SMiquel Raynal
676*a430fa06SMiquel Raynal
677*a430fa06SMiquel Raynal /**
678*a430fa06SMiquel Raynal * Read raw page data without ecc
679*a430fa06SMiquel Raynal *
680*a430fa06SMiquel Raynal * @param mtd mtd info structure
681*a430fa06SMiquel Raynal * @param chip nand chip info structure
682*a430fa06SMiquel Raynal * @param buf buffer to store read data
683*a430fa06SMiquel Raynal * @param page page number to read
684*a430fa06SMiquel Raynal * @return 0 when successfully completed
685*a430fa06SMiquel Raynal * -EINVAL when chip->oob_poi is not double-word aligned
686*a430fa06SMiquel Raynal * -EIO when command timeout
687*a430fa06SMiquel Raynal */
nand_read_page_raw(struct mtd_info * mtd,struct nand_chip * chip,uint8_t * buf,int oob_required,int page)688*a430fa06SMiquel Raynal static int nand_read_page_raw(struct mtd_info *mtd,
689*a430fa06SMiquel Raynal struct nand_chip *chip, uint8_t *buf, int oob_required, int page)
690*a430fa06SMiquel Raynal {
691*a430fa06SMiquel Raynal return nand_rw_page(mtd, chip, buf, page, 0, 0);
692*a430fa06SMiquel Raynal }
693*a430fa06SMiquel Raynal
694*a430fa06SMiquel Raynal /**
695*a430fa06SMiquel Raynal * Raw page write function
696*a430fa06SMiquel Raynal *
697*a430fa06SMiquel Raynal * @param mtd mtd info structure
698*a430fa06SMiquel Raynal * @param chip nand chip info structure
699*a430fa06SMiquel Raynal * @param buf data buffer
700*a430fa06SMiquel Raynal */
nand_write_page_raw(struct mtd_info * mtd,struct nand_chip * chip,const uint8_t * buf,int oob_required,int page)701*a430fa06SMiquel Raynal static int nand_write_page_raw(struct mtd_info *mtd,
702*a430fa06SMiquel Raynal struct nand_chip *chip, const uint8_t *buf,
703*a430fa06SMiquel Raynal int oob_required, int page)
704*a430fa06SMiquel Raynal {
705*a430fa06SMiquel Raynal nand_rw_page(mtd, chip, (uint8_t *)buf, page, 0, 1);
706*a430fa06SMiquel Raynal return 0;
707*a430fa06SMiquel Raynal }
708*a430fa06SMiquel Raynal
709*a430fa06SMiquel Raynal /**
710*a430fa06SMiquel Raynal * OOB data read/write function
711*a430fa06SMiquel Raynal *
712*a430fa06SMiquel Raynal * @param mtd mtd info structure
713*a430fa06SMiquel Raynal * @param chip nand chip info structure
714*a430fa06SMiquel Raynal * @param page page number to read
715*a430fa06SMiquel Raynal * @param with_ecc 1 to enable ECC, 0 to disable ECC
716*a430fa06SMiquel Raynal * @param is_writing 0 for read, 1 for write
717*a430fa06SMiquel Raynal * @return 0 when successfully completed
718*a430fa06SMiquel Raynal * -EINVAL when chip->oob_poi is not double-word aligned
719*a430fa06SMiquel Raynal * -EIO when command timeout
720*a430fa06SMiquel Raynal */
nand_rw_oob(struct mtd_info * mtd,struct nand_chip * chip,int page,int with_ecc,int is_writing)721*a430fa06SMiquel Raynal static int nand_rw_oob(struct mtd_info *mtd, struct nand_chip *chip,
722*a430fa06SMiquel Raynal int page, int with_ecc, int is_writing)
723*a430fa06SMiquel Raynal {
724*a430fa06SMiquel Raynal u32 reg_val;
725*a430fa06SMiquel Raynal int tag_size;
726*a430fa06SMiquel Raynal struct nand_oobfree *free = chip->ecc.layout->oobfree;
727*a430fa06SMiquel Raynal struct nand_drv *info;
728*a430fa06SMiquel Raynal unsigned int bbflags;
729*a430fa06SMiquel Raynal struct bounce_buffer bbstate_oob;
730*a430fa06SMiquel Raynal
731*a430fa06SMiquel Raynal if (((int)chip->oob_poi) & 0x03)
732*a430fa06SMiquel Raynal return -EINVAL;
733*a430fa06SMiquel Raynal info = (struct nand_drv *)nand_get_controller_data(chip);
734*a430fa06SMiquel Raynal if (set_bus_width_page_size(mtd, &info->config, ®_val))
735*a430fa06SMiquel Raynal return -EINVAL;
736*a430fa06SMiquel Raynal
737*a430fa06SMiquel Raynal stop_command(info->reg);
738*a430fa06SMiquel Raynal
739*a430fa06SMiquel Raynal /* Set ECC selection */
740*a430fa06SMiquel Raynal tag_size = mtd->oobsize;
741*a430fa06SMiquel Raynal if (with_ecc)
742*a430fa06SMiquel Raynal reg_val |= CFG_ECC_EN_TAG_ENABLE;
743*a430fa06SMiquel Raynal else
744*a430fa06SMiquel Raynal reg_val |= (CFG_ECC_EN_TAG_DISABLE);
745*a430fa06SMiquel Raynal
746*a430fa06SMiquel Raynal reg_val |= ((tag_size - 1) |
747*a430fa06SMiquel Raynal CFG_SKIP_SPARE_DISABLE |
748*a430fa06SMiquel Raynal CFG_HW_ECC_CORRECTION_DISABLE |
749*a430fa06SMiquel Raynal CFG_HW_ECC_DISABLE);
750*a430fa06SMiquel Raynal writel(reg_val, &info->reg->config);
751*a430fa06SMiquel Raynal
752*a430fa06SMiquel Raynal if (is_writing && with_ecc)
753*a430fa06SMiquel Raynal tag_size -= TAG_ECC_BYTES;
754*a430fa06SMiquel Raynal
755*a430fa06SMiquel Raynal if (is_writing)
756*a430fa06SMiquel Raynal bbflags = GEN_BB_READ;
757*a430fa06SMiquel Raynal else
758*a430fa06SMiquel Raynal bbflags = GEN_BB_WRITE;
759*a430fa06SMiquel Raynal
760*a430fa06SMiquel Raynal bounce_buffer_start(&bbstate_oob, (void *)chip->oob_poi, tag_size,
761*a430fa06SMiquel Raynal bbflags);
762*a430fa06SMiquel Raynal writel(virt_to_phys(bbstate_oob.bounce_buffer), &info->reg->tag_ptr);
763*a430fa06SMiquel Raynal
764*a430fa06SMiquel Raynal writel(BCH_CONFIG_BCH_ECC_DISABLE, &info->reg->bch_config);
765*a430fa06SMiquel Raynal
766*a430fa06SMiquel Raynal writel(tag_size - 1, &info->reg->dma_cfg_b);
767*a430fa06SMiquel Raynal
768*a430fa06SMiquel Raynal nand_clear_interrupt_status(info->reg);
769*a430fa06SMiquel Raynal
770*a430fa06SMiquel Raynal reg_val = CMD_CLE | CMD_ALE
771*a430fa06SMiquel Raynal | CMD_SEC_CMD
772*a430fa06SMiquel Raynal | (CMD_ALE_BYTES5 << CMD_ALE_BYTE_SIZE_SHIFT)
773*a430fa06SMiquel Raynal | CMD_B_VALID
774*a430fa06SMiquel Raynal | CMD_CE0;
775*a430fa06SMiquel Raynal if (!is_writing)
776*a430fa06SMiquel Raynal reg_val |= (CMD_AFT_DAT_DISABLE | CMD_RX);
777*a430fa06SMiquel Raynal else
778*a430fa06SMiquel Raynal reg_val |= (CMD_AFT_DAT_ENABLE | CMD_TX);
779*a430fa06SMiquel Raynal writel(reg_val, &info->reg->command);
780*a430fa06SMiquel Raynal
781*a430fa06SMiquel Raynal /* Setup DMA engine */
782*a430fa06SMiquel Raynal reg_val = DMA_MST_CTRL_GO_ENABLE
783*a430fa06SMiquel Raynal | DMA_MST_CTRL_BURST_8WORDS
784*a430fa06SMiquel Raynal | DMA_MST_CTRL_EN_B_ENABLE;
785*a430fa06SMiquel Raynal if (!is_writing)
786*a430fa06SMiquel Raynal reg_val |= DMA_MST_CTRL_DIR_READ;
787*a430fa06SMiquel Raynal else
788*a430fa06SMiquel Raynal reg_val |= DMA_MST_CTRL_DIR_WRITE;
789*a430fa06SMiquel Raynal
790*a430fa06SMiquel Raynal writel(reg_val, &info->reg->dma_mst_ctrl);
791*a430fa06SMiquel Raynal
792*a430fa06SMiquel Raynal start_command(info->reg);
793*a430fa06SMiquel Raynal
794*a430fa06SMiquel Raynal if (!nand_waitfor_cmd_completion(info->reg)) {
795*a430fa06SMiquel Raynal if (!is_writing)
796*a430fa06SMiquel Raynal printf("Read OOB of Page 0x%X timeout\n", page);
797*a430fa06SMiquel Raynal else
798*a430fa06SMiquel Raynal printf("Write OOB of Page 0x%X timeout\n", page);
799*a430fa06SMiquel Raynal return -EIO;
800*a430fa06SMiquel Raynal }
801*a430fa06SMiquel Raynal
802*a430fa06SMiquel Raynal bounce_buffer_stop(&bbstate_oob);
803*a430fa06SMiquel Raynal
804*a430fa06SMiquel Raynal if (with_ecc && !is_writing) {
805*a430fa06SMiquel Raynal reg_val = (u32)check_ecc_error(info->reg, 0, 0,
806*a430fa06SMiquel Raynal (u8 *)(chip->oob_poi + free->offset),
807*a430fa06SMiquel Raynal chip->ecc.layout->oobavail);
808*a430fa06SMiquel Raynal if (reg_val & ECC_TAG_ERROR)
809*a430fa06SMiquel Raynal printf("Read OOB of Page 0x%X tag ECC error\n", page);
810*a430fa06SMiquel Raynal }
811*a430fa06SMiquel Raynal return 0;
812*a430fa06SMiquel Raynal }
813*a430fa06SMiquel Raynal
814*a430fa06SMiquel Raynal /**
815*a430fa06SMiquel Raynal * OOB data read function
816*a430fa06SMiquel Raynal *
817*a430fa06SMiquel Raynal * @param mtd mtd info structure
818*a430fa06SMiquel Raynal * @param chip nand chip info structure
819*a430fa06SMiquel Raynal * @param page page number to read
820*a430fa06SMiquel Raynal */
nand_read_oob(struct mtd_info * mtd,struct nand_chip * chip,int page)821*a430fa06SMiquel Raynal static int nand_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
822*a430fa06SMiquel Raynal int page)
823*a430fa06SMiquel Raynal {
824*a430fa06SMiquel Raynal chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page);
825*a430fa06SMiquel Raynal nand_rw_oob(mtd, chip, page, 0, 0);
826*a430fa06SMiquel Raynal return 0;
827*a430fa06SMiquel Raynal }
828*a430fa06SMiquel Raynal
829*a430fa06SMiquel Raynal /**
830*a430fa06SMiquel Raynal * OOB data write function
831*a430fa06SMiquel Raynal *
832*a430fa06SMiquel Raynal * @param mtd mtd info structure
833*a430fa06SMiquel Raynal * @param chip nand chip info structure
834*a430fa06SMiquel Raynal * @param page page number to write
835*a430fa06SMiquel Raynal * @return 0 when successfully completed
836*a430fa06SMiquel Raynal * -EINVAL when chip->oob_poi is not double-word aligned
837*a430fa06SMiquel Raynal * -EIO when command timeout
838*a430fa06SMiquel Raynal */
nand_write_oob(struct mtd_info * mtd,struct nand_chip * chip,int page)839*a430fa06SMiquel Raynal static int nand_write_oob(struct mtd_info *mtd, struct nand_chip *chip,
840*a430fa06SMiquel Raynal int page)
841*a430fa06SMiquel Raynal {
842*a430fa06SMiquel Raynal chip->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize, page);
843*a430fa06SMiquel Raynal
844*a430fa06SMiquel Raynal return nand_rw_oob(mtd, chip, page, 0, 1);
845*a430fa06SMiquel Raynal }
846*a430fa06SMiquel Raynal
847*a430fa06SMiquel Raynal /**
848*a430fa06SMiquel Raynal * Set up NAND memory timings according to the provided parameters
849*a430fa06SMiquel Raynal *
850*a430fa06SMiquel Raynal * @param timing Timing parameters
851*a430fa06SMiquel Raynal * @param reg NAND controller register address
852*a430fa06SMiquel Raynal */
setup_timing(unsigned timing[FDT_NAND_TIMING_COUNT],struct nand_ctlr * reg)853*a430fa06SMiquel Raynal static void setup_timing(unsigned timing[FDT_NAND_TIMING_COUNT],
854*a430fa06SMiquel Raynal struct nand_ctlr *reg)
855*a430fa06SMiquel Raynal {
856*a430fa06SMiquel Raynal u32 reg_val, clk_rate, clk_period, time_val;
857*a430fa06SMiquel Raynal
858*a430fa06SMiquel Raynal clk_rate = (u32)clock_get_periph_rate(PERIPH_ID_NDFLASH,
859*a430fa06SMiquel Raynal CLOCK_ID_PERIPH) / 1000000;
860*a430fa06SMiquel Raynal clk_period = 1000 / clk_rate;
861*a430fa06SMiquel Raynal reg_val = ((timing[FDT_NAND_MAX_TRP_TREA] / clk_period) <<
862*a430fa06SMiquel Raynal TIMING_TRP_RESP_CNT_SHIFT) & TIMING_TRP_RESP_CNT_MASK;
863*a430fa06SMiquel Raynal reg_val |= ((timing[FDT_NAND_TWB] / clk_period) <<
864*a430fa06SMiquel Raynal TIMING_TWB_CNT_SHIFT) & TIMING_TWB_CNT_MASK;
865*a430fa06SMiquel Raynal time_val = timing[FDT_NAND_MAX_TCR_TAR_TRR] / clk_period;
866*a430fa06SMiquel Raynal if (time_val > 2)
867*a430fa06SMiquel Raynal reg_val |= ((time_val - 2) << TIMING_TCR_TAR_TRR_CNT_SHIFT) &
868*a430fa06SMiquel Raynal TIMING_TCR_TAR_TRR_CNT_MASK;
869*a430fa06SMiquel Raynal reg_val |= ((timing[FDT_NAND_TWHR] / clk_period) <<
870*a430fa06SMiquel Raynal TIMING_TWHR_CNT_SHIFT) & TIMING_TWHR_CNT_MASK;
871*a430fa06SMiquel Raynal time_val = timing[FDT_NAND_MAX_TCS_TCH_TALS_TALH] / clk_period;
872*a430fa06SMiquel Raynal if (time_val > 1)
873*a430fa06SMiquel Raynal reg_val |= ((time_val - 1) << TIMING_TCS_CNT_SHIFT) &
874*a430fa06SMiquel Raynal TIMING_TCS_CNT_MASK;
875*a430fa06SMiquel Raynal reg_val |= ((timing[FDT_NAND_TWH] / clk_period) <<
876*a430fa06SMiquel Raynal TIMING_TWH_CNT_SHIFT) & TIMING_TWH_CNT_MASK;
877*a430fa06SMiquel Raynal reg_val |= ((timing[FDT_NAND_TWP] / clk_period) <<
878*a430fa06SMiquel Raynal TIMING_TWP_CNT_SHIFT) & TIMING_TWP_CNT_MASK;
879*a430fa06SMiquel Raynal reg_val |= ((timing[FDT_NAND_TRH] / clk_period) <<
880*a430fa06SMiquel Raynal TIMING_TRH_CNT_SHIFT) & TIMING_TRH_CNT_MASK;
881*a430fa06SMiquel Raynal reg_val |= ((timing[FDT_NAND_MAX_TRP_TREA] / clk_period) <<
882*a430fa06SMiquel Raynal TIMING_TRP_CNT_SHIFT) & TIMING_TRP_CNT_MASK;
883*a430fa06SMiquel Raynal writel(reg_val, ®->timing);
884*a430fa06SMiquel Raynal
885*a430fa06SMiquel Raynal reg_val = 0;
886*a430fa06SMiquel Raynal time_val = timing[FDT_NAND_TADL] / clk_period;
887*a430fa06SMiquel Raynal if (time_val > 2)
888*a430fa06SMiquel Raynal reg_val = (time_val - 2) & TIMING2_TADL_CNT_MASK;
889*a430fa06SMiquel Raynal writel(reg_val, ®->timing2);
890*a430fa06SMiquel Raynal }
891*a430fa06SMiquel Raynal
892*a430fa06SMiquel Raynal /**
893*a430fa06SMiquel Raynal * Decode NAND parameters from the device tree
894*a430fa06SMiquel Raynal *
895*a430fa06SMiquel Raynal * @param dev Driver model device
896*a430fa06SMiquel Raynal * @param config Device tree NAND configuration
897*a430fa06SMiquel Raynal * @return 0 if ok, -ve on error (FDT_ERR_...)
898*a430fa06SMiquel Raynal */
fdt_decode_nand(struct udevice * dev,struct fdt_nand * config)899*a430fa06SMiquel Raynal static int fdt_decode_nand(struct udevice *dev, struct fdt_nand *config)
900*a430fa06SMiquel Raynal {
901*a430fa06SMiquel Raynal int err;
902*a430fa06SMiquel Raynal
903*a430fa06SMiquel Raynal config->reg = (struct nand_ctlr *)dev_read_addr(dev);
904*a430fa06SMiquel Raynal config->enabled = dev_read_enabled(dev);
905*a430fa06SMiquel Raynal config->width = dev_read_u32_default(dev, "nvidia,nand-width", 8);
906*a430fa06SMiquel Raynal err = gpio_request_by_name(dev, "nvidia,wp-gpios", 0, &config->wp_gpio,
907*a430fa06SMiquel Raynal GPIOD_IS_OUT);
908*a430fa06SMiquel Raynal if (err)
909*a430fa06SMiquel Raynal return err;
910*a430fa06SMiquel Raynal err = dev_read_u32_array(dev, "nvidia,timing", config->timing,
911*a430fa06SMiquel Raynal FDT_NAND_TIMING_COUNT);
912*a430fa06SMiquel Raynal if (err < 0)
913*a430fa06SMiquel Raynal return err;
914*a430fa06SMiquel Raynal
915*a430fa06SMiquel Raynal return 0;
916*a430fa06SMiquel Raynal }
917*a430fa06SMiquel Raynal
tegra_probe(struct udevice * dev)918*a430fa06SMiquel Raynal static int tegra_probe(struct udevice *dev)
919*a430fa06SMiquel Raynal {
920*a430fa06SMiquel Raynal struct tegra_nand_info *tegra = dev_get_priv(dev);
921*a430fa06SMiquel Raynal struct nand_chip *nand = &tegra->nand_chip;
922*a430fa06SMiquel Raynal struct nand_drv *info = &tegra->nand_ctrl;
923*a430fa06SMiquel Raynal struct fdt_nand *config = &info->config;
924*a430fa06SMiquel Raynal struct mtd_info *our_mtd;
925*a430fa06SMiquel Raynal int ret;
926*a430fa06SMiquel Raynal
927*a430fa06SMiquel Raynal if (fdt_decode_nand(dev, config)) {
928*a430fa06SMiquel Raynal printf("Could not decode nand-flash in device tree\n");
929*a430fa06SMiquel Raynal return -1;
930*a430fa06SMiquel Raynal }
931*a430fa06SMiquel Raynal if (!config->enabled)
932*a430fa06SMiquel Raynal return -1;
933*a430fa06SMiquel Raynal info->reg = config->reg;
934*a430fa06SMiquel Raynal nand->ecc.mode = NAND_ECC_HW;
935*a430fa06SMiquel Raynal nand->ecc.layout = &eccoob;
936*a430fa06SMiquel Raynal
937*a430fa06SMiquel Raynal nand->options = LP_OPTIONS;
938*a430fa06SMiquel Raynal nand->cmdfunc = nand_command;
939*a430fa06SMiquel Raynal nand->read_byte = read_byte;
940*a430fa06SMiquel Raynal nand->read_buf = read_buf;
941*a430fa06SMiquel Raynal nand->ecc.read_page = nand_read_page_hwecc;
942*a430fa06SMiquel Raynal nand->ecc.write_page = nand_write_page_hwecc;
943*a430fa06SMiquel Raynal nand->ecc.read_page_raw = nand_read_page_raw;
944*a430fa06SMiquel Raynal nand->ecc.write_page_raw = nand_write_page_raw;
945*a430fa06SMiquel Raynal nand->ecc.read_oob = nand_read_oob;
946*a430fa06SMiquel Raynal nand->ecc.write_oob = nand_write_oob;
947*a430fa06SMiquel Raynal nand->ecc.strength = 1;
948*a430fa06SMiquel Raynal nand->select_chip = nand_select_chip;
949*a430fa06SMiquel Raynal nand->dev_ready = nand_dev_ready;
950*a430fa06SMiquel Raynal nand_set_controller_data(nand, &tegra->nand_ctrl);
951*a430fa06SMiquel Raynal
952*a430fa06SMiquel Raynal /* Disable subpage writes as we do not provide ecc->hwctl */
953*a430fa06SMiquel Raynal nand->options |= NAND_NO_SUBPAGE_WRITE;
954*a430fa06SMiquel Raynal
955*a430fa06SMiquel Raynal /* Adjust controller clock rate */
956*a430fa06SMiquel Raynal clock_start_periph_pll(PERIPH_ID_NDFLASH, CLOCK_ID_PERIPH, 52000000);
957*a430fa06SMiquel Raynal
958*a430fa06SMiquel Raynal /* Adjust timing for NAND device */
959*a430fa06SMiquel Raynal setup_timing(config->timing, info->reg);
960*a430fa06SMiquel Raynal
961*a430fa06SMiquel Raynal dm_gpio_set_value(&config->wp_gpio, 1);
962*a430fa06SMiquel Raynal
963*a430fa06SMiquel Raynal our_mtd = nand_to_mtd(nand);
964*a430fa06SMiquel Raynal ret = nand_scan_ident(our_mtd, CONFIG_SYS_NAND_MAX_CHIPS, NULL);
965*a430fa06SMiquel Raynal if (ret)
966*a430fa06SMiquel Raynal return ret;
967*a430fa06SMiquel Raynal
968*a430fa06SMiquel Raynal nand->ecc.size = our_mtd->writesize;
969*a430fa06SMiquel Raynal nand->ecc.bytes = our_mtd->oobsize;
970*a430fa06SMiquel Raynal
971*a430fa06SMiquel Raynal ret = nand_scan_tail(our_mtd);
972*a430fa06SMiquel Raynal if (ret)
973*a430fa06SMiquel Raynal return ret;
974*a430fa06SMiquel Raynal
975*a430fa06SMiquel Raynal ret = nand_register(0, our_mtd);
976*a430fa06SMiquel Raynal if (ret) {
977*a430fa06SMiquel Raynal dev_err(dev, "Failed to register MTD: %d\n", ret);
978*a430fa06SMiquel Raynal return ret;
979*a430fa06SMiquel Raynal }
980*a430fa06SMiquel Raynal
981*a430fa06SMiquel Raynal return 0;
982*a430fa06SMiquel Raynal }
983*a430fa06SMiquel Raynal
984*a430fa06SMiquel Raynal U_BOOT_DRIVER(tegra_nand) = {
985*a430fa06SMiquel Raynal .name = "tegra-nand",
986*a430fa06SMiquel Raynal .id = UCLASS_MTD,
987*a430fa06SMiquel Raynal .of_match = tegra_nand_dt_ids,
988*a430fa06SMiquel Raynal .probe = tegra_probe,
989*a430fa06SMiquel Raynal .priv_auto_alloc_size = sizeof(struct tegra_nand_info),
990*a430fa06SMiquel Raynal };
991*a430fa06SMiquel Raynal
board_nand_init(void)992*a430fa06SMiquel Raynal void board_nand_init(void)
993*a430fa06SMiquel Raynal {
994*a430fa06SMiquel Raynal struct udevice *dev;
995*a430fa06SMiquel Raynal int ret;
996*a430fa06SMiquel Raynal
997*a430fa06SMiquel Raynal ret = uclass_get_device_by_driver(UCLASS_MTD,
998*a430fa06SMiquel Raynal DM_GET_DRIVER(tegra_nand), &dev);
999*a430fa06SMiquel Raynal if (ret && ret != -ENODEV)
1000*a430fa06SMiquel Raynal pr_err("Failed to initialize %s. (error %d)\n", dev->name,
1001*a430fa06SMiquel Raynal ret);
1002*a430fa06SMiquel Raynal }
1003