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