1ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell/*
2ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell * davinci_nand.c - NAND Flash Driver for DaVinci family chips
3ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell *
4ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell * Copyright © 2006 Texas Instruments.
5ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell *
6ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell * Port to 2.6.23 Copyright © 2008 by:
7ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell *   Sander Huijsen <Shuijsen@optelecom-nkf.com>
8ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell *   Troy Kisky <troy.kisky@boundarydevices.com>
9ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell *   Dirk Behme <Dirk.Behme@gmail.com>
10ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell *
11ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell * This program is free software; you can redistribute it and/or modify
12ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell * it under the terms of the GNU General Public License as published by
13ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell * the Free Software Foundation; either version 2 of the License, or
14ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell * (at your option) any later version.
15ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell *
16ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell * This program is distributed in the hope that it will be useful,
17ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell * but WITHOUT ANY WARRANTY; without even the implied warranty of
18ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell * GNU General Public License for more details.
20ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell *
21ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell * You should have received a copy of the GNU General Public License
22ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell * along with this program; if not, write to the Free Software
23ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell */
25ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
26ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell#include <linux/kernel.h>
27ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell#include <linux/init.h>
28ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell#include <linux/module.h>
29ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell#include <linux/platform_device.h>
30ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell#include <linux/err.h>
31ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell#include <linux/clk.h>
32ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell#include <linux/io.h>
33ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell#include <linux/mtd/nand.h>
34ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell#include <linux/mtd/partitions.h>
355a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
36ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
37ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell#include <mach/nand.h>
388060ef4da9e73f461adf2ba1922ea5400a61cf98Sekhar Nori#include <mach/aemif.h>
39ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
40ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell/*
41ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell * This is a device driver for the NAND flash controller found on the
42ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell * various DaVinci family chips.  It handles up to four SoC chipselects,
43ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell * and some flavors of secondary chipselect (e.g. based on A12) as used
44ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell * with multichip packages.
45ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell *
466a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell * The 1-bit ECC hardware is supported, as well as the newer 4-bit ECC
47ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell * available on chips like the DM355 and OMAP-L137 and needed with the
48ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell * more error-prone MLC NAND chips.
49ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell *
50ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell * This driver assumes EM_WAIT connects all the NAND devices' RDY/nBUSY
51ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell * outputs in a "wire-AND" configuration, with no per-chip signals.
52ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell */
53ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownellstruct davinci_nand_info {
54ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	struct mtd_info		mtd;
55ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	struct nand_chip	chip;
566a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	struct nand_ecclayout	ecclayout;
57ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
58ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	struct device		*dev;
59ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	struct clk		*clk;
60ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
616a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	bool			is_readmode;
626a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell
63ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	void __iomem		*base;
64ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	void __iomem		*vaddr;
65ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
66ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	uint32_t		ioaddr;
67ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	uint32_t		current_cs;
68ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
69ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	uint32_t		mask_chipsel;
70ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	uint32_t		mask_ale;
71ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	uint32_t		mask_cle;
72ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
73ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	uint32_t		core_chipsel;
74a88dbc5bfdd26132bbf0ad19dd672e036971d74dSekhar Nori
75a88dbc5bfdd26132bbf0ad19dd672e036971d74dSekhar Nori	struct davinci_aemif_timing	*timing;
76ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell};
77ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
78ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownellstatic DEFINE_SPINLOCK(davinci_nand_lock);
796a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownellstatic bool ecc4_busy;
80ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
81ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell#define to_davinci_nand(m) container_of(m, struct davinci_nand_info, mtd)
82ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
83ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
84ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownellstatic inline unsigned int davinci_nand_readl(struct davinci_nand_info *info,
85ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		int offset)
86ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell{
87ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	return __raw_readl(info->base + offset);
88ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell}
89ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
90ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownellstatic inline void davinci_nand_writel(struct davinci_nand_info *info,
91ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		int offset, unsigned long value)
92ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell{
93ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	__raw_writel(value, info->base + offset);
94ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell}
95ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
96ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell/*----------------------------------------------------------------------*/
97ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
98ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell/*
99ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell * Access to hardware control lines:  ALE, CLE, secondary chipselect.
100ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell */
101ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
102ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownellstatic void nand_davinci_hwcontrol(struct mtd_info *mtd, int cmd,
103ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell				   unsigned int ctrl)
104ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell{
105ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	struct davinci_nand_info	*info = to_davinci_nand(mtd);
106ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	uint32_t			addr = info->current_cs;
107ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	struct nand_chip		*nand = mtd->priv;
108ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
109ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	/* Did the control lines change? */
110ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	if (ctrl & NAND_CTRL_CHANGE) {
111ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		if ((ctrl & NAND_CTRL_CLE) == NAND_CTRL_CLE)
112ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell			addr |= info->mask_cle;
113ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		else if ((ctrl & NAND_CTRL_ALE) == NAND_CTRL_ALE)
114ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell			addr |= info->mask_ale;
115ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
116ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		nand->IO_ADDR_W = (void __iomem __force *)addr;
117ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	}
118ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
119ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	if (cmd != NAND_CMD_NONE)
120ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		iowrite8(cmd, nand->IO_ADDR_W);
121ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell}
122ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
123ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownellstatic void nand_davinci_select_chip(struct mtd_info *mtd, int chip)
124ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell{
125ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	struct davinci_nand_info	*info = to_davinci_nand(mtd);
126ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	uint32_t			addr = info->ioaddr;
127ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
128ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	/* maybe kick in a second chipselect */
129ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	if (chip > 0)
130ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		addr |= info->mask_chipsel;
131ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	info->current_cs = addr;
132ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
133ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	info->chip.IO_ADDR_W = (void __iomem __force *)addr;
134ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	info->chip.IO_ADDR_R = info->chip.IO_ADDR_W;
135ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell}
136ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
137ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell/*----------------------------------------------------------------------*/
138ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
139ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell/*
140ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell * 1-bit hardware ECC ... context maintained for each core chipselect
141ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell */
142ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
143ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownellstatic inline uint32_t nand_davinci_readecc_1bit(struct mtd_info *mtd)
144ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell{
145ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	struct davinci_nand_info *info = to_davinci_nand(mtd);
146ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
147ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	return davinci_nand_readl(info, NANDF1ECC_OFFSET
148ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell			+ 4 * info->core_chipsel);
149ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell}
150ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
151ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownellstatic void nand_davinci_hwctl_1bit(struct mtd_info *mtd, int mode)
152ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell{
153ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	struct davinci_nand_info *info;
154ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	uint32_t nandcfr;
155ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	unsigned long flags;
156ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
157ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	info = to_davinci_nand(mtd);
158ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
159ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	/* Reset ECC hardware */
160ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	nand_davinci_readecc_1bit(mtd);
161ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
162ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	spin_lock_irqsave(&davinci_nand_lock, flags);
163ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
164ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	/* Restart ECC hardware */
165ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	nandcfr = davinci_nand_readl(info, NANDFCR_OFFSET);
166ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	nandcfr |= BIT(8 + info->core_chipsel);
167ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	davinci_nand_writel(info, NANDFCR_OFFSET, nandcfr);
168ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
169ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	spin_unlock_irqrestore(&davinci_nand_lock, flags);
170ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell}
171ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
172ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell/*
173ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell * Read hardware ECC value and pack into three bytes
174ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell */
175ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownellstatic int nand_davinci_calculate_1bit(struct mtd_info *mtd,
176ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell				      const u_char *dat, u_char *ecc_code)
177ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell{
178ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	unsigned int ecc_val = nand_davinci_readecc_1bit(mtd);
179ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	unsigned int ecc24 = (ecc_val & 0x0fff) | ((ecc_val & 0x0fff0000) >> 4);
180ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
181ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	/* invert so that erased block ecc is correct */
182ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	ecc24 = ~ecc24;
183ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	ecc_code[0] = (u_char)(ecc24);
184ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	ecc_code[1] = (u_char)(ecc24 >> 8);
185ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	ecc_code[2] = (u_char)(ecc24 >> 16);
186ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
187ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	return 0;
188ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell}
189ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
190ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownellstatic int nand_davinci_correct_1bit(struct mtd_info *mtd, u_char *dat,
191ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell				     u_char *read_ecc, u_char *calc_ecc)
192ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell{
193ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	struct nand_chip *chip = mtd->priv;
194ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	uint32_t eccNand = read_ecc[0] | (read_ecc[1] << 8) |
195ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell					  (read_ecc[2] << 16);
196ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	uint32_t eccCalc = calc_ecc[0] | (calc_ecc[1] << 8) |
197ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell					  (calc_ecc[2] << 16);
198ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	uint32_t diff = eccCalc ^ eccNand;
199ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
200ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	if (diff) {
201ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		if ((((diff >> 12) ^ diff) & 0xfff) == 0xfff) {
202ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell			/* Correctable error */
203ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell			if ((diff >> (12 + 3)) < chip->ecc.size) {
204ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell				dat[diff >> (12 + 3)] ^= BIT((diff >> 12) & 7);
205ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell				return 1;
206ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell			} else {
207ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell				return -1;
208ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell			}
209ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		} else if (!(diff & (diff - 1))) {
210ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell			/* Single bit ECC error in the ECC itself,
211ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell			 * nothing to fix */
212ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell			return 1;
213ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		} else {
214ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell			/* Uncorrectable error */
215ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell			return -1;
216ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		}
217ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
218ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	}
219ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	return 0;
220ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell}
221ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
222ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell/*----------------------------------------------------------------------*/
223ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
224ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell/*
2256a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell * 4-bit hardware ECC ... context maintained over entire AEMIF
2266a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell *
2276a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell * This is a syndrome engine, but we avoid NAND_ECC_HW_SYNDROME
2286a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell * since that forces use of a problematic "infix OOB" layout.
2296a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell * Among other things, it trashes manufacturer bad block markers.
2306a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell * Also, and specific to this hardware, it ECC-protects the "prepad"
2316a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell * in the OOB ... while having ECC protection for parts of OOB would
2326a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell * seem useful, the current MTD stack sometimes wants to update the
2336a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell * OOB without recomputing ECC.
2346a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell */
2356a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell
2366a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownellstatic void nand_davinci_hwctl_4bit(struct mtd_info *mtd, int mode)
2376a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell{
2386a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	struct davinci_nand_info *info = to_davinci_nand(mtd);
2396a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	unsigned long flags;
2406a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	u32 val;
2416a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell
2426a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	spin_lock_irqsave(&davinci_nand_lock, flags);
2436a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell
2446a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	/* Start 4-bit ECC calculation for read/write */
2456a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	val = davinci_nand_readl(info, NANDFCR_OFFSET);
2466a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	val &= ~(0x03 << 4);
2476a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	val |= (info->core_chipsel << 4) | BIT(12);
2486a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	davinci_nand_writel(info, NANDFCR_OFFSET, val);
2496a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell
2506a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	info->is_readmode = (mode == NAND_ECC_READ);
2516a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell
2526a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	spin_unlock_irqrestore(&davinci_nand_lock, flags);
2536a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell}
2546a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell
2556a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell/* Read raw ECC code after writing to NAND. */
2566a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownellstatic void
2576a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownellnand_davinci_readecc_4bit(struct davinci_nand_info *info, u32 code[4])
2586a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell{
2596a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	const u32 mask = 0x03ff03ff;
2606a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell
2616a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	code[0] = davinci_nand_readl(info, NAND_4BIT_ECC1_OFFSET) & mask;
2626a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	code[1] = davinci_nand_readl(info, NAND_4BIT_ECC2_OFFSET) & mask;
2636a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	code[2] = davinci_nand_readl(info, NAND_4BIT_ECC3_OFFSET) & mask;
2646a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	code[3] = davinci_nand_readl(info, NAND_4BIT_ECC4_OFFSET) & mask;
2656a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell}
2666a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell
2676a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell/* Terminate read ECC; or return ECC (as bytes) of data written to NAND. */
2686a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownellstatic int nand_davinci_calculate_4bit(struct mtd_info *mtd,
2696a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		const u_char *dat, u_char *ecc_code)
2706a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell{
2716a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	struct davinci_nand_info *info = to_davinci_nand(mtd);
2726a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	u32 raw_ecc[4], *p;
2736a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	unsigned i;
2746a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell
2756a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	/* After a read, terminate ECC calculation by a dummy read
2766a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	 * of some 4-bit ECC register.  ECC covers everything that
2776a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	 * was read; correct() just uses the hardware state, so
2786a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	 * ecc_code is not needed.
2796a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	 */
2806a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	if (info->is_readmode) {
2816a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		davinci_nand_readl(info, NAND_4BIT_ECC1_OFFSET);
2826a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		return 0;
2836a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	}
2846a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell
2856a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	/* Pack eight raw 10-bit ecc values into ten bytes, making
2866a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	 * two passes which each convert four values (in upper and
2876a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	 * lower halves of two 32-bit words) into five bytes.  The
2886a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	 * ROM boot loader uses this same packing scheme.
2896a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	 */
2906a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	nand_davinci_readecc_4bit(info, raw_ecc);
2916a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	for (i = 0, p = raw_ecc; i < 2; i++, p += 2) {
2926a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		*ecc_code++ =   p[0]        & 0xff;
2936a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		*ecc_code++ = ((p[0] >>  8) & 0x03) | ((p[0] >> 14) & 0xfc);
2946a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		*ecc_code++ = ((p[0] >> 22) & 0x0f) | ((p[1] <<  4) & 0xf0);
2956a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		*ecc_code++ = ((p[1] >>  4) & 0x3f) | ((p[1] >> 10) & 0xc0);
2966a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		*ecc_code++ =  (p[1] >> 18) & 0xff;
2976a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	}
2986a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell
2996a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	return 0;
3006a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell}
3016a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell
3026a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell/* Correct up to 4 bits in data we just read, using state left in the
3036a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell * hardware plus the ecc_code computed when it was first written.
3046a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell */
3056a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownellstatic int nand_davinci_correct_4bit(struct mtd_info *mtd,
3066a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		u_char *data, u_char *ecc_code, u_char *null)
3076a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell{
3086a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	int i;
3096a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	struct davinci_nand_info *info = to_davinci_nand(mtd);
3106a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	unsigned short ecc10[8];
3116a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	unsigned short *ecc16;
3126a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	u32 syndrome[4];
3131c3275b656045aff9a75bb2c9f3251af1043ebb3Sudhakar Rajashekhara	u32 ecc_state;
3146a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	unsigned num_errors, corrected;
3152bdb053a8119355eada46dfab88782449a26b39dWolfram Sang	unsigned long timeo;
3166a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell
3176a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	/* All bytes 0xff?  It's an erased page; ignore its ECC. */
3186a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	for (i = 0; i < 10; i++) {
3196a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		if (ecc_code[i] != 0xff)
3206a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell			goto compare;
3216a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	}
3226a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	return 0;
3236a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell
3246a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownellcompare:
3256a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	/* Unpack ten bytes into eight 10 bit values.  We know we're
3266a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	 * little-endian, and use type punning for less shifting/masking.
3276a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	 */
3286a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	if (WARN_ON(0x01 & (unsigned) ecc_code))
3296a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		return -EINVAL;
3306a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	ecc16 = (unsigned short *)ecc_code;
3316a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell
3326a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	ecc10[0] =  (ecc16[0] >>  0) & 0x3ff;
3336a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	ecc10[1] = ((ecc16[0] >> 10) & 0x3f) | ((ecc16[1] << 6) & 0x3c0);
3346a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	ecc10[2] =  (ecc16[1] >>  4) & 0x3ff;
3356a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	ecc10[3] = ((ecc16[1] >> 14) & 0x3)  | ((ecc16[2] << 2) & 0x3fc);
3366a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	ecc10[4] =  (ecc16[2] >>  8)         | ((ecc16[3] << 8) & 0x300);
3376a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	ecc10[5] =  (ecc16[3] >>  2) & 0x3ff;
3386a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	ecc10[6] = ((ecc16[3] >> 12) & 0xf)  | ((ecc16[4] << 4) & 0x3f0);
3396a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	ecc10[7] =  (ecc16[4] >>  6) & 0x3ff;
3406a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell
3416a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	/* Tell ECC controller about the expected ECC codes. */
3426a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	for (i = 7; i >= 0; i--)
3436a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		davinci_nand_writel(info, NAND_4BIT_ECC_LOAD_OFFSET, ecc10[i]);
3446a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell
3456a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	/* Allow time for syndrome calculation ... then read it.
3466a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	 * A syndrome of all zeroes 0 means no detected errors.
3476a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	 */
3486a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	davinci_nand_readl(info, NANDFSR_OFFSET);
3496a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	nand_davinci_readecc_4bit(info, syndrome);
3506a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	if (!(syndrome[0] | syndrome[1] | syndrome[2] | syndrome[3]))
3516a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		return 0;
3526a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell
353f12a9473283e68ae708e9ada37cb352ea2652397Sneha Narnakaje	/*
354f12a9473283e68ae708e9ada37cb352ea2652397Sneha Narnakaje	 * Clear any previous address calculation by doing a dummy read of an
355f12a9473283e68ae708e9ada37cb352ea2652397Sneha Narnakaje	 * error address register.
356f12a9473283e68ae708e9ada37cb352ea2652397Sneha Narnakaje	 */
357f12a9473283e68ae708e9ada37cb352ea2652397Sneha Narnakaje	davinci_nand_readl(info, NAND_ERR_ADD1_OFFSET);
358f12a9473283e68ae708e9ada37cb352ea2652397Sneha Narnakaje
3596a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	/* Start address calculation, and wait for it to complete.
3606a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	 * We _could_ start reading more data while this is working,
3616a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	 * to speed up the overall page read.
3626a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	 */
3636a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	davinci_nand_writel(info, NANDFCR_OFFSET,
3646a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell			davinci_nand_readl(info, NANDFCR_OFFSET) | BIT(13));
3651c3275b656045aff9a75bb2c9f3251af1043ebb3Sudhakar Rajashekhara
3661c3275b656045aff9a75bb2c9f3251af1043ebb3Sudhakar Rajashekhara	/*
3671c3275b656045aff9a75bb2c9f3251af1043ebb3Sudhakar Rajashekhara	 * ECC_STATE field reads 0x3 (Error correction complete) immediately
3681c3275b656045aff9a75bb2c9f3251af1043ebb3Sudhakar Rajashekhara	 * after setting the 4BITECC_ADD_CALC_START bit. So if you immediately
3691c3275b656045aff9a75bb2c9f3251af1043ebb3Sudhakar Rajashekhara	 * begin trying to poll for the state, you may fall right out of your
3701c3275b656045aff9a75bb2c9f3251af1043ebb3Sudhakar Rajashekhara	 * loop without any of the correction calculations having taken place.
371eea116ed0497dc9c4a981b8c7017d758fc835dedWolfram Sang	 * The recommendation from the hardware team is to initially delay as
372eea116ed0497dc9c4a981b8c7017d758fc835dedWolfram Sang	 * long as ECC_STATE reads less than 4. After that, ECC HW has entered
373eea116ed0497dc9c4a981b8c7017d758fc835dedWolfram Sang	 * correction state.
3741c3275b656045aff9a75bb2c9f3251af1043ebb3Sudhakar Rajashekhara	 */
3752bdb053a8119355eada46dfab88782449a26b39dWolfram Sang	timeo = jiffies + usecs_to_jiffies(100);
3761c3275b656045aff9a75bb2c9f3251af1043ebb3Sudhakar Rajashekhara	do {
3771c3275b656045aff9a75bb2c9f3251af1043ebb3Sudhakar Rajashekhara		ecc_state = (davinci_nand_readl(info,
3781c3275b656045aff9a75bb2c9f3251af1043ebb3Sudhakar Rajashekhara				NANDFSR_OFFSET) >> 8) & 0x0f;
3791c3275b656045aff9a75bb2c9f3251af1043ebb3Sudhakar Rajashekhara		cpu_relax();
3801c3275b656045aff9a75bb2c9f3251af1043ebb3Sudhakar Rajashekhara	} while ((ecc_state < 4) && time_before(jiffies, timeo));
3811c3275b656045aff9a75bb2c9f3251af1043ebb3Sudhakar Rajashekhara
3826a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	for (;;) {
3836a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		u32	fsr = davinci_nand_readl(info, NANDFSR_OFFSET);
3846a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell
3856a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		switch ((fsr >> 8) & 0x0f) {
3866a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		case 0:		/* no error, should not happen */
387f12a9473283e68ae708e9ada37cb352ea2652397Sneha Narnakaje			davinci_nand_readl(info, NAND_ERR_ERRVAL1_OFFSET);
3886a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell			return 0;
3896a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		case 1:		/* five or more errors detected */
390f12a9473283e68ae708e9ada37cb352ea2652397Sneha Narnakaje			davinci_nand_readl(info, NAND_ERR_ERRVAL1_OFFSET);
3916a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell			return -EIO;
3926a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		case 2:		/* error addresses computed */
3936a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		case 3:
3946a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell			num_errors = 1 + ((fsr >> 16) & 0x03);
3956a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell			goto correct;
3966a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		default:	/* still working on it */
3976a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell			cpu_relax();
3986a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell			continue;
3996a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		}
4006a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	}
4016a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell
4026a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownellcorrect:
4036a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	/* correct each error */
4046a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	for (i = 0, corrected = 0; i < num_errors; i++) {
4056a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		int error_address, error_value;
4066a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell
4076a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		if (i > 1) {
4086a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell			error_address = davinci_nand_readl(info,
4096a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell						NAND_ERR_ADD2_OFFSET);
4106a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell			error_value = davinci_nand_readl(info,
4116a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell						NAND_ERR_ERRVAL2_OFFSET);
4126a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		} else {
4136a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell			error_address = davinci_nand_readl(info,
4146a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell						NAND_ERR_ADD1_OFFSET);
4156a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell			error_value = davinci_nand_readl(info,
4166a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell						NAND_ERR_ERRVAL1_OFFSET);
4176a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		}
4186a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell
4196a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		if (i & 1) {
4206a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell			error_address >>= 16;
4216a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell			error_value >>= 16;
4226a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		}
4236a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		error_address &= 0x3ff;
4246a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		error_address = (512 + 7) - error_address;
4256a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell
4266a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		if (error_address < 512) {
4276a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell			data[error_address] ^= error_value;
4286a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell			corrected++;
4296a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		}
4306a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	}
4316a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell
4326a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	return corrected;
4336a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell}
4346a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell
4356a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell/*----------------------------------------------------------------------*/
4366a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell
4376a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell/*
438ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell * NOTE:  NAND boot requires ALE == EM_A[1], CLE == EM_A[2], so that's
439ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell * how these chips are normally wired.  This translates to both 8 and 16
440ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell * bit busses using ALE == BIT(3) in byte addresses, and CLE == BIT(4).
441ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell *
442ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell * For now we assume that configuration, or any other one which ignores
443ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell * the two LSBs for NAND access ... so we can issue 32-bit reads/writes
444ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell * and have that transparently morphed into multiple NAND operations.
445ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell */
446ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownellstatic void nand_davinci_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
447ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell{
448ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	struct nand_chip *chip = mtd->priv;
449ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
450ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	if ((0x03 & ((unsigned)buf)) == 0 && (0x03 & len) == 0)
451ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		ioread32_rep(chip->IO_ADDR_R, buf, len >> 2);
452ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	else if ((0x01 & ((unsigned)buf)) == 0 && (0x01 & len) == 0)
453ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		ioread16_rep(chip->IO_ADDR_R, buf, len >> 1);
454ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	else
455ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		ioread8_rep(chip->IO_ADDR_R, buf, len);
456ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell}
457ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
458ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownellstatic void nand_davinci_write_buf(struct mtd_info *mtd,
459ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		const uint8_t *buf, int len)
460ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell{
461ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	struct nand_chip *chip = mtd->priv;
462ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
463ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	if ((0x03 & ((unsigned)buf)) == 0 && (0x03 & len) == 0)
464ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		iowrite32_rep(chip->IO_ADDR_R, buf, len >> 2);
465ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	else if ((0x01 & ((unsigned)buf)) == 0 && (0x01 & len) == 0)
466ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		iowrite16_rep(chip->IO_ADDR_R, buf, len >> 1);
467ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	else
468ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		iowrite8_rep(chip->IO_ADDR_R, buf, len);
469ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell}
470ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
471ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell/*
472ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell * Check hardware register for wait status. Returns 1 if device is ready,
473ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell * 0 if it is still busy.
474ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell */
475ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownellstatic int nand_davinci_dev_ready(struct mtd_info *mtd)
476ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell{
477ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	struct davinci_nand_info *info = to_davinci_nand(mtd);
478ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
479ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	return davinci_nand_readl(info, NANDFSR_OFFSET) & BIT(0);
480ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell}
481ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
482ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell/*----------------------------------------------------------------------*/
483ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
4846a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell/* An ECC layout for using 4-bit ECC with small-page flash, storing
4856a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell * ten ECC bytes plus the manufacturer's bad block marker byte, and
4866a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell * and not overlapping the default BBT markers.
4876a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell */
4886a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownellstatic struct nand_ecclayout hwecc4_small __initconst = {
4896a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	.eccbytes = 10,
4906a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	.eccpos = { 0, 1, 2, 3, 4,
4916a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		/* offset 5 holds the badblock marker */
4926a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		6, 7,
4936a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		13, 14, 15, },
4946a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	.oobfree = {
4956a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		{.offset = 8, .length = 5, },
4966a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		{.offset = 16, },
4976a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	},
4986a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell};
4996a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell
500f12a9473283e68ae708e9ada37cb352ea2652397Sneha Narnakaje/* An ECC layout for using 4-bit ECC with large-page (2048bytes) flash,
501f12a9473283e68ae708e9ada37cb352ea2652397Sneha Narnakaje * storing ten ECC bytes plus the manufacturer's bad block marker byte,
502f12a9473283e68ae708e9ada37cb352ea2652397Sneha Narnakaje * and not overlapping the default BBT markers.
503f12a9473283e68ae708e9ada37cb352ea2652397Sneha Narnakaje */
504f12a9473283e68ae708e9ada37cb352ea2652397Sneha Narnakajestatic struct nand_ecclayout hwecc4_2048 __initconst = {
505f12a9473283e68ae708e9ada37cb352ea2652397Sneha Narnakaje	.eccbytes = 40,
506f12a9473283e68ae708e9ada37cb352ea2652397Sneha Narnakaje	.eccpos = {
507f12a9473283e68ae708e9ada37cb352ea2652397Sneha Narnakaje		/* at the end of spare sector */
508f12a9473283e68ae708e9ada37cb352ea2652397Sneha Narnakaje		24, 25, 26, 27, 28, 29,	30, 31, 32, 33,
509f12a9473283e68ae708e9ada37cb352ea2652397Sneha Narnakaje		34, 35, 36, 37, 38, 39,	40, 41, 42, 43,
510f12a9473283e68ae708e9ada37cb352ea2652397Sneha Narnakaje		44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
511f12a9473283e68ae708e9ada37cb352ea2652397Sneha Narnakaje		54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
512f12a9473283e68ae708e9ada37cb352ea2652397Sneha Narnakaje		},
513f12a9473283e68ae708e9ada37cb352ea2652397Sneha Narnakaje	.oobfree = {
514f12a9473283e68ae708e9ada37cb352ea2652397Sneha Narnakaje		/* 2 bytes at offset 0 hold manufacturer badblock markers */
515f12a9473283e68ae708e9ada37cb352ea2652397Sneha Narnakaje		{.offset = 2, .length = 22, },
516f12a9473283e68ae708e9ada37cb352ea2652397Sneha Narnakaje		/* 5 bytes at offset 8 hold BBT markers */
517f12a9473283e68ae708e9ada37cb352ea2652397Sneha Narnakaje		/* 8 bytes at offset 16 hold JFFS2 clean markers */
518f12a9473283e68ae708e9ada37cb352ea2652397Sneha Narnakaje	},
519f12a9473283e68ae708e9ada37cb352ea2652397Sneha Narnakaje};
5206a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell
521ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownellstatic int __init nand_davinci_probe(struct platform_device *pdev)
522ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell{
523ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	struct davinci_nand_pdata	*pdata = pdev->dev.platform_data;
524ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	struct davinci_nand_info	*info;
525ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	struct resource			*res1;
526ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	struct resource			*res2;
527ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	void __iomem			*vaddr;
528ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	void __iomem			*base;
529ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	int				ret;
530ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	uint32_t			val;
531ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	nand_ecc_modes_t		ecc_mode;
532ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
533533a0149148ccaa0199a1ee6492cd860e3c8b456David Brownell	/* insist on board-specific configuration */
534533a0149148ccaa0199a1ee6492cd860e3c8b456David Brownell	if (!pdata)
535533a0149148ccaa0199a1ee6492cd860e3c8b456David Brownell		return -ENODEV;
536533a0149148ccaa0199a1ee6492cd860e3c8b456David Brownell
537ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	/* which external chipselect will we be managing? */
538ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	if (pdev->id < 0 || pdev->id > 3)
539ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		return -ENODEV;
540ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
541ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	info = kzalloc(sizeof(*info), GFP_KERNEL);
542ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	if (!info) {
543ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		dev_err(&pdev->dev, "unable to allocate memory\n");
544ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		ret = -ENOMEM;
545ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		goto err_nomem;
546ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	}
547ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
548ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	platform_set_drvdata(pdev, info);
549ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
550ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	res1 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
551ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	res2 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
552ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	if (!res1 || !res2) {
553ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		dev_err(&pdev->dev, "resource missing\n");
554ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		ret = -EINVAL;
555ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		goto err_nomem;
556ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	}
557ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
558d8bc55553c416c877267c1efd65b099164acbe3fH Hartley Sweeten	vaddr = ioremap(res1->start, resource_size(res1));
559d8bc55553c416c877267c1efd65b099164acbe3fH Hartley Sweeten	base = ioremap(res2->start, resource_size(res2));
560ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	if (!vaddr || !base) {
561ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		dev_err(&pdev->dev, "ioremap failed\n");
562ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		ret = -EINVAL;
563ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		goto err_ioremap;
564ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	}
565ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
566ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	info->dev		= &pdev->dev;
567ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	info->base		= base;
568ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	info->vaddr		= vaddr;
569ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
570ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	info->mtd.priv		= &info->chip;
571ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	info->mtd.name		= dev_name(&pdev->dev);
572ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	info->mtd.owner		= THIS_MODULE;
573ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
57487f39f0493edf7051b1b87c6e9eb7f9a74be8e85David Brownell	info->mtd.dev.parent	= &pdev->dev;
57587f39f0493edf7051b1b87c6e9eb7f9a74be8e85David Brownell
576ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	info->chip.IO_ADDR_R	= vaddr;
577ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	info->chip.IO_ADDR_W	= vaddr;
578ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	info->chip.chip_delay	= 0;
579ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	info->chip.select_chip	= nand_davinci_select_chip;
580ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
581bb9ebd4e714385a2592a482845865ef2d58b2868Brian Norris	/* options such as NAND_BBT_USE_FLASH */
582a40f73419f02e40555f692785ea1c1813d5b4c12Brian Norris	info->chip.bbt_options	= pdata->bbt_options;
583a40f73419f02e40555f692785ea1c1813d5b4c12Brian Norris	/* options such as 16-bit widths */
584533a0149148ccaa0199a1ee6492cd860e3c8b456David Brownell	info->chip.options	= pdata->options;
585f611a79fe9859a30f2a7ae94b4d24f8e2dd75c91Mark A. Greer	info->chip.bbt_td	= pdata->bbt_td;
586f611a79fe9859a30f2a7ae94b4d24f8e2dd75c91Mark A. Greer	info->chip.bbt_md	= pdata->bbt_md;
587a88dbc5bfdd26132bbf0ad19dd672e036971d74dSekhar Nori	info->timing		= pdata->timing;
588ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
589ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	info->ioaddr		= (uint32_t __force) vaddr;
590ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
591ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	info->current_cs	= info->ioaddr;
592ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	info->core_chipsel	= pdev->id;
593ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	info->mask_chipsel	= pdata->mask_chipsel;
594ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
595ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	/* use nandboot-capable ALE/CLE masks by default */
5965cd0be8ec946ee3901e7f651a795225c6badff8fHemant Pedanekar	info->mask_ale		= pdata->mask_ale ? : MASK_ALE;
597533a0149148ccaa0199a1ee6492cd860e3c8b456David Brownell	info->mask_cle		= pdata->mask_cle ? : MASK_CLE;
598ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
599ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	/* Set address of hardware control function */
600ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	info->chip.cmd_ctrl	= nand_davinci_hwcontrol;
601ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	info->chip.dev_ready	= nand_davinci_dev_ready;
602ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
603ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	/* Speed up buffer I/O */
604ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	info->chip.read_buf     = nand_davinci_read_buf;
605ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	info->chip.write_buf    = nand_davinci_write_buf;
606ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
607533a0149148ccaa0199a1ee6492cd860e3c8b456David Brownell	/* Use board-specific ECC config */
608533a0149148ccaa0199a1ee6492cd860e3c8b456David Brownell	ecc_mode		= pdata->ecc_mode;
609ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
6106a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	ret = -EINVAL;
611ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	switch (ecc_mode) {
612ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	case NAND_ECC_NONE:
613ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	case NAND_ECC_SOFT:
6146a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		pdata->ecc_bits = 0;
615ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		break;
616ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	case NAND_ECC_HW:
6176a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		if (pdata->ecc_bits == 4) {
6186a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell			/* No sanity checks:  CPUs must support this,
6196a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell			 * and the chips may not use NAND_BUSWIDTH_16.
6206a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell			 */
6216a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell
6226a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell			/* No sharing 4-bit hardware between chipselects yet */
6236a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell			spin_lock_irq(&davinci_nand_lock);
6246a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell			if (ecc4_busy)
6256a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell				ret = -EBUSY;
6266a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell			else
6276a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell				ecc4_busy = true;
6286a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell			spin_unlock_irq(&davinci_nand_lock);
6296a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell
6306a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell			if (ret == -EBUSY)
6316a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell				goto err_ecc;
6326a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell
6336a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell			info->chip.ecc.calculate = nand_davinci_calculate_4bit;
6346a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell			info->chip.ecc.correct = nand_davinci_correct_4bit;
6356a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell			info->chip.ecc.hwctl = nand_davinci_hwctl_4bit;
6366a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell			info->chip.ecc.bytes = 10;
6376a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		} else {
6386a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell			info->chip.ecc.calculate = nand_davinci_calculate_1bit;
6396a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell			info->chip.ecc.correct = nand_davinci_correct_1bit;
6406a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell			info->chip.ecc.hwctl = nand_davinci_hwctl_1bit;
6416a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell			info->chip.ecc.bytes = 3;
6426a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		}
643ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		info->chip.ecc.size = 512;
6446a918bade9dab40aaef80559bd1169c69e8d69cbMike Dunn		info->chip.ecc.strength = pdata->ecc_bits;
645ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		break;
646ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	default:
647ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		ret = -EINVAL;
648ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		goto err_ecc;
649ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	}
650ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	info->chip.ecc.mode = ecc_mode;
651ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
652cd24f8c1e7e27a2c6051a9a338d4704a2431dbf0Kevin Hilman	info->clk = clk_get(&pdev->dev, "aemif");
653ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	if (IS_ERR(info->clk)) {
654ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		ret = PTR_ERR(info->clk);
655cd24f8c1e7e27a2c6051a9a338d4704a2431dbf0Kevin Hilman		dev_dbg(&pdev->dev, "unable to get AEMIF clock, err %d\n", ret);
656ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		goto err_clk;
657ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	}
658ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
659ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	ret = clk_enable(info->clk);
660ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	if (ret < 0) {
661cd24f8c1e7e27a2c6051a9a338d4704a2431dbf0Kevin Hilman		dev_dbg(&pdev->dev, "unable to enable AEMIF clock, err %d\n",
662cd24f8c1e7e27a2c6051a9a338d4704a2431dbf0Kevin Hilman			ret);
663ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		goto err_clk_enable;
664ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	}
665ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
666a88dbc5bfdd26132bbf0ad19dd672e036971d74dSekhar Nori	/*
667a88dbc5bfdd26132bbf0ad19dd672e036971d74dSekhar Nori	 * Setup Async configuration register in case we did not boot from
668a88dbc5bfdd26132bbf0ad19dd672e036971d74dSekhar Nori	 * NAND and so bootloader did not bother to set it up.
669ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	 */
670a88dbc5bfdd26132bbf0ad19dd672e036971d74dSekhar Nori	val = davinci_nand_readl(info, A1CR_OFFSET + info->core_chipsel * 4);
671a88dbc5bfdd26132bbf0ad19dd672e036971d74dSekhar Nori
672a88dbc5bfdd26132bbf0ad19dd672e036971d74dSekhar Nori	/* Extended Wait is not valid and Select Strobe mode is not used */
673a88dbc5bfdd26132bbf0ad19dd672e036971d74dSekhar Nori	val &= ~(ACR_ASIZE_MASK | ACR_EW_MASK | ACR_SS_MASK);
674a88dbc5bfdd26132bbf0ad19dd672e036971d74dSekhar Nori	if (info->chip.options & NAND_BUSWIDTH_16)
675a88dbc5bfdd26132bbf0ad19dd672e036971d74dSekhar Nori		val |= 0x1;
676a88dbc5bfdd26132bbf0ad19dd672e036971d74dSekhar Nori
677a88dbc5bfdd26132bbf0ad19dd672e036971d74dSekhar Nori	davinci_nand_writel(info, A1CR_OFFSET + info->core_chipsel * 4, val);
678a88dbc5bfdd26132bbf0ad19dd672e036971d74dSekhar Nori
67947882d78250a8b92a9837d14bab32915622a9f12Heiko Schocher	ret = 0;
68047882d78250a8b92a9837d14bab32915622a9f12Heiko Schocher	if (info->timing)
68147882d78250a8b92a9837d14bab32915622a9f12Heiko Schocher		ret = davinci_aemif_setup_timing(info->timing, info->base,
682a88dbc5bfdd26132bbf0ad19dd672e036971d74dSekhar Nori							info->core_chipsel);
683a88dbc5bfdd26132bbf0ad19dd672e036971d74dSekhar Nori	if (ret < 0) {
684a88dbc5bfdd26132bbf0ad19dd672e036971d74dSekhar Nori		dev_dbg(&pdev->dev, "NAND timing values setup fail\n");
685a88dbc5bfdd26132bbf0ad19dd672e036971d74dSekhar Nori		goto err_timing;
686a88dbc5bfdd26132bbf0ad19dd672e036971d74dSekhar Nori	}
687ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
688ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	spin_lock_irq(&davinci_nand_lock);
689ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
690ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	/* put CSxNAND into NAND mode */
691ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	val = davinci_nand_readl(info, NANDFCR_OFFSET);
692ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	val |= BIT(info->core_chipsel);
693ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	davinci_nand_writel(info, NANDFCR_OFFSET, val);
694ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
695ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	spin_unlock_irq(&davinci_nand_lock);
696ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
697ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	/* Scan to find existence of the device(s) */
6985e81e88a4c140586d9212999cea683bcd66a15c6David Woodhouse	ret = nand_scan_ident(&info->mtd, pdata->mask_chipsel ? 2 : 1, NULL);
699ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	if (ret < 0) {
700ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		dev_dbg(&pdev->dev, "no NAND chip(s) found\n");
701ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		goto err_scan;
702ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	}
703ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
7046a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	/* Update ECC layout if needed ... for 1-bit HW ECC, the default
7056a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	 * is OK, but it allocates 6 bytes when only 3 are needed (for
7066a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	 * each 512 bytes).  For the 4-bit HW ECC, that default is not
7076a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	 * usable:  10 bytes are needed, not 6.
7086a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	 */
7096a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	if (pdata->ecc_bits == 4) {
7106a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		int	chunks = info->mtd.writesize / 512;
7116a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell
7126a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		if (!chunks || info->mtd.oobsize < 16) {
7136a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell			dev_dbg(&pdev->dev, "too small\n");
7146a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell			ret = -EINVAL;
7156a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell			goto err_scan;
7166a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		}
7176a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell
7186a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		/* For small page chips, preserve the manufacturer's
7196a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		 * badblock marking data ... and make sure a flash BBT
7206a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		 * table marker fits in the free bytes.
7216a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		 */
7226a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		if (chunks == 1) {
7236a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell			info->ecclayout = hwecc4_small;
7246a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell			info->ecclayout.oobfree[1].length =
7256a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell				info->mtd.oobsize - 16;
7266a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell			goto syndrome_done;
7276a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		}
728f12a9473283e68ae708e9ada37cb352ea2652397Sneha Narnakaje		if (chunks == 4) {
729f12a9473283e68ae708e9ada37cb352ea2652397Sneha Narnakaje			info->ecclayout = hwecc4_2048;
730f12a9473283e68ae708e9ada37cb352ea2652397Sneha Narnakaje			info->chip.ecc.mode = NAND_ECC_HW_OOB_FIRST;
731f12a9473283e68ae708e9ada37cb352ea2652397Sneha Narnakaje			goto syndrome_done;
732f12a9473283e68ae708e9ada37cb352ea2652397Sneha Narnakaje		}
7336a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell
734f12a9473283e68ae708e9ada37cb352ea2652397Sneha Narnakaje		/* 4KiB page chips are not yet supported. The eccpos from
735f12a9473283e68ae708e9ada37cb352ea2652397Sneha Narnakaje		 * nand_ecclayout cannot hold 80 bytes and change to eccpos[]
736f12a9473283e68ae708e9ada37cb352ea2652397Sneha Narnakaje		 * breaks userspace ioctl interface with mtd-utils. Once we
737f12a9473283e68ae708e9ada37cb352ea2652397Sneha Narnakaje		 * resolve this issue, NAND_ECC_HW_OOB_FIRST mode can be used
738f12a9473283e68ae708e9ada37cb352ea2652397Sneha Narnakaje		 * for the 4KiB page chips.
739cc26c3cd3d1cf40a07f2b19ac4c53d517bee52a5Brian Norris		 *
740cc26c3cd3d1cf40a07f2b19ac4c53d517bee52a5Brian Norris		 * TODO: Note that nand_ecclayout has now been expanded and can
741cc26c3cd3d1cf40a07f2b19ac4c53d517bee52a5Brian Norris		 *  hold plenty of OOB entries.
7426a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		 */
7436a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		dev_warn(&pdev->dev, "no 4-bit ECC support yet "
744f12a9473283e68ae708e9ada37cb352ea2652397Sneha Narnakaje				"for 4KiB-page NAND\n");
7456a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		ret = -EIO;
7466a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		goto err_scan;
7476a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell
7486a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownellsyndrome_done:
7496a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		info->chip.ecc.layout = &info->ecclayout;
7506a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	}
7516a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell
7526a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	ret = nand_scan_tail(&info->mtd);
7536a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	if (ret < 0)
7546a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		goto err_scan;
7556a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell
75642d7fbe223ab878b23de9e3b0166f8cd665a2aa5Artem Bityutskiy	ret = mtd_device_parse_register(&info->mtd, NULL, NULL, pdata->parts,
75742d7fbe223ab878b23de9e3b0166f8cd665a2aa5Artem Bityutskiy					pdata->nr_parts);
758ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
759ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	if (ret < 0)
760ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		goto err_scan;
761ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
762ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	val = davinci_nand_readl(info, NRCSR_OFFSET);
763ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	dev_info(&pdev->dev, "controller rev. %d.%d\n",
764ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	       (val >> 8) & 0xff, val & 0xff);
765ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
766ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	return 0;
767ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
768ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownellerr_scan:
769a88dbc5bfdd26132bbf0ad19dd672e036971d74dSekhar Norierr_timing:
770ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	clk_disable(info->clk);
771ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
772ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownellerr_clk_enable:
773ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	clk_put(info->clk);
774ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
7756a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	spin_lock_irq(&davinci_nand_lock);
7766a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	if (ecc_mode == NAND_ECC_HW_SYNDROME)
7776a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		ecc4_busy = false;
7786a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	spin_unlock_irq(&davinci_nand_lock);
7796a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell
780ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownellerr_ecc:
781ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownellerr_clk:
782ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownellerr_ioremap:
783ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	if (base)
784ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		iounmap(base);
785ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	if (vaddr)
786ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		iounmap(vaddr);
787ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
788ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownellerr_nomem:
789ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	kfree(info);
790ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	return ret;
791ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell}
792ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
793ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownellstatic int __exit nand_davinci_remove(struct platform_device *pdev)
794ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell{
795ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	struct davinci_nand_info *info = platform_get_drvdata(pdev);
796ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
7976a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	spin_lock_irq(&davinci_nand_lock);
7986a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	if (info->chip.ecc.mode == NAND_ECC_HW_SYNDROME)
7996a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		ecc4_busy = false;
8006a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	spin_unlock_irq(&davinci_nand_lock);
8016a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell
802ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	iounmap(info->base);
803ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	iounmap(info->vaddr);
804ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
805ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	nand_release(&info->mtd);
806ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
807ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	clk_disable(info->clk);
808ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	clk_put(info->clk);
809ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
810ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	kfree(info);
811ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
812ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	return 0;
813ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell}
814ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
815ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownellstatic struct platform_driver nand_davinci_driver = {
816ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	.remove		= __exit_p(nand_davinci_remove),
817ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	.driver		= {
818ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		.name	= "davinci_nand",
819ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	},
820ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell};
821ff4569c752c577c7e71e03c9d59e6ef85ca763c0David BrownellMODULE_ALIAS("platform:davinci_nand");
822ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
823ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownellstatic int __init nand_davinci_init(void)
824ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell{
825ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	return platform_driver_probe(&nand_davinci_driver, nand_davinci_probe);
826ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell}
827ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownellmodule_init(nand_davinci_init);
828ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
829ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownellstatic void __exit nand_davinci_exit(void)
830ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell{
831ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	platform_driver_unregister(&nand_davinci_driver);
832ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell}
833ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownellmodule_exit(nand_davinci_exit);
834ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
835ff4569c752c577c7e71e03c9d59e6ef85ca763c0David BrownellMODULE_LICENSE("GPL");
836ff4569c752c577c7e71e03c9d59e6ef85ca763c0David BrownellMODULE_AUTHOR("Texas Instruments");
837ff4569c752c577c7e71e03c9d59e6ef85ca763c0David BrownellMODULE_DESCRIPTION("Davinci NAND flash driver");
838ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
839