xref: /openbmc/u-boot/drivers/mtd/nand/raw/tegra_nand.c (revision a1588ac8)
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(&reg->command) & CMD_GO) ||
123*a430fa06SMiquel Raynal 				!(readl(&reg->status) & STATUS_RBSY0) ||
124*a430fa06SMiquel Raynal 				!(readl(&reg->isr) & ISR_IS_CMD_DONE)) {
125*a430fa06SMiquel Raynal 			udelay(1);
126*a430fa06SMiquel Raynal 			continue;
127*a430fa06SMiquel Raynal 		}
128*a430fa06SMiquel Raynal 		reg_val = readl(&reg->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, &reg, 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(&reg->isr);
243*a430fa06SMiquel Raynal 	writel(reg_val, &reg->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(&reg->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(&reg->dec_status);
401*a430fa06SMiquel Raynal 	if ((reg_val & DEC_STATUS_A_ECC_FAIL) && databuf) {
402*a430fa06SMiquel Raynal 		reg_val = readl(&reg->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(&reg->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(&reg->command);
438*a430fa06SMiquel Raynal 	reg_val |= CMD_GO;
439*a430fa06SMiquel Raynal 	writel(reg_val, &reg->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, &reg->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 		&reg->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, &reg_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, &reg_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, &reg->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, &reg->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