davinci_nand.c revision 5e81e88a4c140586d9212999cea683bcd66a15c6
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>
35ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
36ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell#include <mach/nand.h>
37ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
38ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell#include <asm/mach-types.h>
39ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
40ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
41ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell/*
42ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell * This is a device driver for the NAND flash controller found on the
43ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell * various DaVinci family chips.  It handles up to four SoC chipselects,
44ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell * and some flavors of secondary chipselect (e.g. based on A12) as used
45ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell * with multichip packages.
46ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell *
476a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell * The 1-bit ECC hardware is supported, as well as the newer 4-bit ECC
48ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell * available on chips like the DM355 and OMAP-L137 and needed with the
49ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell * more error-prone MLC NAND chips.
50ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell *
51ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell * This driver assumes EM_WAIT connects all the NAND devices' RDY/nBUSY
52ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell * outputs in a "wire-AND" configuration, with no per-chip signals.
53ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell */
54ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownellstruct davinci_nand_info {
55ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	struct mtd_info		mtd;
56ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	struct nand_chip	chip;
576a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	struct nand_ecclayout	ecclayout;
58ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
59ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	struct device		*dev;
60ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	struct clk		*clk;
61ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	bool			partitioned;
62ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
636a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	bool			is_readmode;
646a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell
65ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	void __iomem		*base;
66ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	void __iomem		*vaddr;
67ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
68ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	uint32_t		ioaddr;
69ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	uint32_t		current_cs;
70ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
71ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	uint32_t		mask_chipsel;
72ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	uint32_t		mask_ale;
73ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	uint32_t		mask_cle;
74ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
75ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	uint32_t		core_chipsel;
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];
3136a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	unsigned num_errors, corrected;
3146a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell
3156a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	/* All bytes 0xff?  It's an erased page; ignore its ECC. */
3166a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	for (i = 0; i < 10; i++) {
3176a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		if (ecc_code[i] != 0xff)
3186a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell			goto compare;
3196a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	}
3206a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	return 0;
3216a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell
3226a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownellcompare:
3236a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	/* Unpack ten bytes into eight 10 bit values.  We know we're
3246a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	 * little-endian, and use type punning for less shifting/masking.
3256a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	 */
3266a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	if (WARN_ON(0x01 & (unsigned) ecc_code))
3276a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		return -EINVAL;
3286a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	ecc16 = (unsigned short *)ecc_code;
3296a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell
3306a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	ecc10[0] =  (ecc16[0] >>  0) & 0x3ff;
3316a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	ecc10[1] = ((ecc16[0] >> 10) & 0x3f) | ((ecc16[1] << 6) & 0x3c0);
3326a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	ecc10[2] =  (ecc16[1] >>  4) & 0x3ff;
3336a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	ecc10[3] = ((ecc16[1] >> 14) & 0x3)  | ((ecc16[2] << 2) & 0x3fc);
3346a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	ecc10[4] =  (ecc16[2] >>  8)         | ((ecc16[3] << 8) & 0x300);
3356a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	ecc10[5] =  (ecc16[3] >>  2) & 0x3ff;
3366a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	ecc10[6] = ((ecc16[3] >> 12) & 0xf)  | ((ecc16[4] << 4) & 0x3f0);
3376a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	ecc10[7] =  (ecc16[4] >>  6) & 0x3ff;
3386a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell
3396a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	/* Tell ECC controller about the expected ECC codes. */
3406a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	for (i = 7; i >= 0; i--)
3416a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		davinci_nand_writel(info, NAND_4BIT_ECC_LOAD_OFFSET, ecc10[i]);
3426a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell
3436a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	/* Allow time for syndrome calculation ... then read it.
3446a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	 * A syndrome of all zeroes 0 means no detected errors.
3456a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	 */
3466a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	davinci_nand_readl(info, NANDFSR_OFFSET);
3476a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	nand_davinci_readecc_4bit(info, syndrome);
3486a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	if (!(syndrome[0] | syndrome[1] | syndrome[2] | syndrome[3]))
3496a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		return 0;
3506a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell
351f12a9473283e68ae708e9ada37cb352ea2652397Sneha Narnakaje	/*
352f12a9473283e68ae708e9ada37cb352ea2652397Sneha Narnakaje	 * Clear any previous address calculation by doing a dummy read of an
353f12a9473283e68ae708e9ada37cb352ea2652397Sneha Narnakaje	 * error address register.
354f12a9473283e68ae708e9ada37cb352ea2652397Sneha Narnakaje	 */
355f12a9473283e68ae708e9ada37cb352ea2652397Sneha Narnakaje	davinci_nand_readl(info, NAND_ERR_ADD1_OFFSET);
356f12a9473283e68ae708e9ada37cb352ea2652397Sneha Narnakaje
3576a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	/* Start address calculation, and wait for it to complete.
3586a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	 * We _could_ start reading more data while this is working,
3596a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	 * to speed up the overall page read.
3606a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	 */
3616a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	davinci_nand_writel(info, NANDFCR_OFFSET,
3626a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell			davinci_nand_readl(info, NANDFCR_OFFSET) | BIT(13));
3636a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	for (;;) {
3646a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		u32	fsr = davinci_nand_readl(info, NANDFSR_OFFSET);
3656a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell
3666a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		switch ((fsr >> 8) & 0x0f) {
3676a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		case 0:		/* no error, should not happen */
368f12a9473283e68ae708e9ada37cb352ea2652397Sneha Narnakaje			davinci_nand_readl(info, NAND_ERR_ERRVAL1_OFFSET);
3696a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell			return 0;
3706a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		case 1:		/* five or more errors detected */
371f12a9473283e68ae708e9ada37cb352ea2652397Sneha Narnakaje			davinci_nand_readl(info, NAND_ERR_ERRVAL1_OFFSET);
3726a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell			return -EIO;
3736a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		case 2:		/* error addresses computed */
3746a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		case 3:
3756a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell			num_errors = 1 + ((fsr >> 16) & 0x03);
3766a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell			goto correct;
3776a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		default:	/* still working on it */
3786a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell			cpu_relax();
3796a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell			continue;
3806a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		}
3816a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	}
3826a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell
3836a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownellcorrect:
3846a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	/* correct each error */
3856a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	for (i = 0, corrected = 0; i < num_errors; i++) {
3866a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		int error_address, error_value;
3876a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell
3886a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		if (i > 1) {
3896a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell			error_address = davinci_nand_readl(info,
3906a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell						NAND_ERR_ADD2_OFFSET);
3916a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell			error_value = davinci_nand_readl(info,
3926a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell						NAND_ERR_ERRVAL2_OFFSET);
3936a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		} else {
3946a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell			error_address = davinci_nand_readl(info,
3956a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell						NAND_ERR_ADD1_OFFSET);
3966a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell			error_value = davinci_nand_readl(info,
3976a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell						NAND_ERR_ERRVAL1_OFFSET);
3986a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		}
3996a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell
4006a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		if (i & 1) {
4016a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell			error_address >>= 16;
4026a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell			error_value >>= 16;
4036a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		}
4046a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		error_address &= 0x3ff;
4056a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		error_address = (512 + 7) - error_address;
4066a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell
4076a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		if (error_address < 512) {
4086a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell			data[error_address] ^= error_value;
4096a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell			corrected++;
4106a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		}
4116a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	}
4126a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell
4136a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	return corrected;
4146a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell}
4156a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell
4166a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell/*----------------------------------------------------------------------*/
4176a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell
4186a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell/*
419ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell * NOTE:  NAND boot requires ALE == EM_A[1], CLE == EM_A[2], so that's
420ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell * how these chips are normally wired.  This translates to both 8 and 16
421ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell * bit busses using ALE == BIT(3) in byte addresses, and CLE == BIT(4).
422ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell *
423ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell * For now we assume that configuration, or any other one which ignores
424ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell * the two LSBs for NAND access ... so we can issue 32-bit reads/writes
425ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell * and have that transparently morphed into multiple NAND operations.
426ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell */
427ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownellstatic void nand_davinci_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
428ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell{
429ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	struct nand_chip *chip = mtd->priv;
430ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
431ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	if ((0x03 & ((unsigned)buf)) == 0 && (0x03 & len) == 0)
432ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		ioread32_rep(chip->IO_ADDR_R, buf, len >> 2);
433ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	else if ((0x01 & ((unsigned)buf)) == 0 && (0x01 & len) == 0)
434ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		ioread16_rep(chip->IO_ADDR_R, buf, len >> 1);
435ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	else
436ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		ioread8_rep(chip->IO_ADDR_R, buf, len);
437ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell}
438ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
439ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownellstatic void nand_davinci_write_buf(struct mtd_info *mtd,
440ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		const uint8_t *buf, int len)
441ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell{
442ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	struct nand_chip *chip = mtd->priv;
443ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
444ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	if ((0x03 & ((unsigned)buf)) == 0 && (0x03 & len) == 0)
445ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		iowrite32_rep(chip->IO_ADDR_R, buf, len >> 2);
446ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	else if ((0x01 & ((unsigned)buf)) == 0 && (0x01 & len) == 0)
447ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		iowrite16_rep(chip->IO_ADDR_R, buf, len >> 1);
448ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	else
449ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		iowrite8_rep(chip->IO_ADDR_R, buf, len);
450ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell}
451ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
452ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell/*
453ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell * Check hardware register for wait status. Returns 1 if device is ready,
454ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell * 0 if it is still busy.
455ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell */
456ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownellstatic int nand_davinci_dev_ready(struct mtd_info *mtd)
457ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell{
458ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	struct davinci_nand_info *info = to_davinci_nand(mtd);
459ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
460ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	return davinci_nand_readl(info, NANDFSR_OFFSET) & BIT(0);
461ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell}
462ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
463ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownellstatic void __init nand_dm6446evm_flash_init(struct davinci_nand_info *info)
464ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell{
465ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	uint32_t regval, a1cr;
466ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
467ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	/*
468ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	 * NAND FLASH timings @ PLL1 == 459 MHz
469ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	 *  - AEMIF.CLK freq   = PLL1/6 = 459/6 = 76.5 MHz
470ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	 *  - AEMIF.CLK period = 1/76.5 MHz = 13.1 ns
471ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	 */
472ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	regval = 0
473ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		| (0 << 31)           /* selectStrobe */
474ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		| (0 << 30)           /* extWait (never with NAND) */
475ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		| (1 << 26)           /* writeSetup      10 ns */
476ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		| (3 << 20)           /* writeStrobe     40 ns */
477ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		| (1 << 17)           /* writeHold       10 ns */
478ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		| (0 << 13)           /* readSetup       10 ns */
479ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		| (3 << 7)            /* readStrobe      60 ns */
480ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		| (0 << 4)            /* readHold        10 ns */
481ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		| (3 << 2)            /* turnAround      ?? ns */
482ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		| (0 << 0)            /* asyncSize       8-bit bus */
483ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		;
484ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	a1cr = davinci_nand_readl(info, A1CR_OFFSET);
485ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	if (a1cr != regval) {
486ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		dev_dbg(info->dev, "Warning: NAND config: Set A1CR " \
487ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		       "reg to 0x%08x, was 0x%08x, should be done by " \
488ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		       "bootloader.\n", regval, a1cr);
489ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		davinci_nand_writel(info, A1CR_OFFSET, regval);
490ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	}
491ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell}
492ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
493ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell/*----------------------------------------------------------------------*/
494ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
4956a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell/* An ECC layout for using 4-bit ECC with small-page flash, storing
4966a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell * ten ECC bytes plus the manufacturer's bad block marker byte, and
4976a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell * and not overlapping the default BBT markers.
4986a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell */
4996a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownellstatic struct nand_ecclayout hwecc4_small __initconst = {
5006a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	.eccbytes = 10,
5016a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	.eccpos = { 0, 1, 2, 3, 4,
5026a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		/* offset 5 holds the badblock marker */
5036a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		6, 7,
5046a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		13, 14, 15, },
5056a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	.oobfree = {
5066a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		{.offset = 8, .length = 5, },
5076a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		{.offset = 16, },
5086a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	},
5096a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell};
5106a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell
511f12a9473283e68ae708e9ada37cb352ea2652397Sneha Narnakaje/* An ECC layout for using 4-bit ECC with large-page (2048bytes) flash,
512f12a9473283e68ae708e9ada37cb352ea2652397Sneha Narnakaje * storing ten ECC bytes plus the manufacturer's bad block marker byte,
513f12a9473283e68ae708e9ada37cb352ea2652397Sneha Narnakaje * and not overlapping the default BBT markers.
514f12a9473283e68ae708e9ada37cb352ea2652397Sneha Narnakaje */
515f12a9473283e68ae708e9ada37cb352ea2652397Sneha Narnakajestatic struct nand_ecclayout hwecc4_2048 __initconst = {
516f12a9473283e68ae708e9ada37cb352ea2652397Sneha Narnakaje	.eccbytes = 40,
517f12a9473283e68ae708e9ada37cb352ea2652397Sneha Narnakaje	.eccpos = {
518f12a9473283e68ae708e9ada37cb352ea2652397Sneha Narnakaje		/* at the end of spare sector */
519f12a9473283e68ae708e9ada37cb352ea2652397Sneha Narnakaje		24, 25, 26, 27, 28, 29,	30, 31, 32, 33,
520f12a9473283e68ae708e9ada37cb352ea2652397Sneha Narnakaje		34, 35, 36, 37, 38, 39,	40, 41, 42, 43,
521f12a9473283e68ae708e9ada37cb352ea2652397Sneha Narnakaje		44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
522f12a9473283e68ae708e9ada37cb352ea2652397Sneha Narnakaje		54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
523f12a9473283e68ae708e9ada37cb352ea2652397Sneha Narnakaje		},
524f12a9473283e68ae708e9ada37cb352ea2652397Sneha Narnakaje	.oobfree = {
525f12a9473283e68ae708e9ada37cb352ea2652397Sneha Narnakaje		/* 2 bytes at offset 0 hold manufacturer badblock markers */
526f12a9473283e68ae708e9ada37cb352ea2652397Sneha Narnakaje		{.offset = 2, .length = 22, },
527f12a9473283e68ae708e9ada37cb352ea2652397Sneha Narnakaje		/* 5 bytes at offset 8 hold BBT markers */
528f12a9473283e68ae708e9ada37cb352ea2652397Sneha Narnakaje		/* 8 bytes at offset 16 hold JFFS2 clean markers */
529f12a9473283e68ae708e9ada37cb352ea2652397Sneha Narnakaje	},
530f12a9473283e68ae708e9ada37cb352ea2652397Sneha Narnakaje};
5316a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell
532ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownellstatic int __init nand_davinci_probe(struct platform_device *pdev)
533ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell{
534ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	struct davinci_nand_pdata	*pdata = pdev->dev.platform_data;
535ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	struct davinci_nand_info	*info;
536ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	struct resource			*res1;
537ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	struct resource			*res2;
538ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	void __iomem			*vaddr;
539ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	void __iomem			*base;
540ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	int				ret;
541ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	uint32_t			val;
542ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	nand_ecc_modes_t		ecc_mode;
543ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
544533a0149148ccaa0199a1ee6492cd860e3c8b456David Brownell	/* insist on board-specific configuration */
545533a0149148ccaa0199a1ee6492cd860e3c8b456David Brownell	if (!pdata)
546533a0149148ccaa0199a1ee6492cd860e3c8b456David Brownell		return -ENODEV;
547533a0149148ccaa0199a1ee6492cd860e3c8b456David Brownell
548ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	/* which external chipselect will we be managing? */
549ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	if (pdev->id < 0 || pdev->id > 3)
550ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		return -ENODEV;
551ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
552ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	info = kzalloc(sizeof(*info), GFP_KERNEL);
553ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	if (!info) {
554ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		dev_err(&pdev->dev, "unable to allocate memory\n");
555ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		ret = -ENOMEM;
556ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		goto err_nomem;
557ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	}
558ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
559ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	platform_set_drvdata(pdev, info);
560ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
561ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	res1 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
562ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	res2 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
563ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	if (!res1 || !res2) {
564ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		dev_err(&pdev->dev, "resource missing\n");
565ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		ret = -EINVAL;
566ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		goto err_nomem;
567ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	}
568ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
569d8bc55553c416c877267c1efd65b099164acbe3fH Hartley Sweeten	vaddr = ioremap(res1->start, resource_size(res1));
570d8bc55553c416c877267c1efd65b099164acbe3fH Hartley Sweeten	base = ioremap(res2->start, resource_size(res2));
571ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	if (!vaddr || !base) {
572ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		dev_err(&pdev->dev, "ioremap failed\n");
573ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		ret = -EINVAL;
574ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		goto err_ioremap;
575ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	}
576ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
577ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	info->dev		= &pdev->dev;
578ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	info->base		= base;
579ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	info->vaddr		= vaddr;
580ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
581ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	info->mtd.priv		= &info->chip;
582ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	info->mtd.name		= dev_name(&pdev->dev);
583ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	info->mtd.owner		= THIS_MODULE;
584ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
58587f39f0493edf7051b1b87c6e9eb7f9a74be8e85David Brownell	info->mtd.dev.parent	= &pdev->dev;
58687f39f0493edf7051b1b87c6e9eb7f9a74be8e85David Brownell
587ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	info->chip.IO_ADDR_R	= vaddr;
588ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	info->chip.IO_ADDR_W	= vaddr;
589ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	info->chip.chip_delay	= 0;
590ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	info->chip.select_chip	= nand_davinci_select_chip;
591ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
592ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	/* options such as NAND_USE_FLASH_BBT or 16-bit widths */
593533a0149148ccaa0199a1ee6492cd860e3c8b456David Brownell	info->chip.options	= pdata->options;
594f611a79fe9859a30f2a7ae94b4d24f8e2dd75c91Mark A. Greer	info->chip.bbt_td	= pdata->bbt_td;
595f611a79fe9859a30f2a7ae94b4d24f8e2dd75c91Mark A. Greer	info->chip.bbt_md	= pdata->bbt_md;
596ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
597ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	info->ioaddr		= (uint32_t __force) vaddr;
598ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
599ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	info->current_cs	= info->ioaddr;
600ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	info->core_chipsel	= pdev->id;
601ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	info->mask_chipsel	= pdata->mask_chipsel;
602ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
603ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	/* use nandboot-capable ALE/CLE masks by default */
6045cd0be8ec946ee3901e7f651a795225c6badff8fHemant Pedanekar	info->mask_ale		= pdata->mask_ale ? : MASK_ALE;
605533a0149148ccaa0199a1ee6492cd860e3c8b456David Brownell	info->mask_cle		= pdata->mask_cle ? : MASK_CLE;
606ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
607ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	/* Set address of hardware control function */
608ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	info->chip.cmd_ctrl	= nand_davinci_hwcontrol;
609ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	info->chip.dev_ready	= nand_davinci_dev_ready;
610ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
611ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	/* Speed up buffer I/O */
612ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	info->chip.read_buf     = nand_davinci_read_buf;
613ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	info->chip.write_buf    = nand_davinci_write_buf;
614ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
615533a0149148ccaa0199a1ee6492cd860e3c8b456David Brownell	/* Use board-specific ECC config */
616533a0149148ccaa0199a1ee6492cd860e3c8b456David Brownell	ecc_mode		= pdata->ecc_mode;
617ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
6186a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	ret = -EINVAL;
619ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	switch (ecc_mode) {
620ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	case NAND_ECC_NONE:
621ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	case NAND_ECC_SOFT:
6226a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		pdata->ecc_bits = 0;
623ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		break;
624ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	case NAND_ECC_HW:
6256a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		if (pdata->ecc_bits == 4) {
6266a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell			/* No sanity checks:  CPUs must support this,
6276a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell			 * and the chips may not use NAND_BUSWIDTH_16.
6286a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell			 */
6296a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell
6306a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell			/* No sharing 4-bit hardware between chipselects yet */
6316a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell			spin_lock_irq(&davinci_nand_lock);
6326a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell			if (ecc4_busy)
6336a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell				ret = -EBUSY;
6346a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell			else
6356a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell				ecc4_busy = true;
6366a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell			spin_unlock_irq(&davinci_nand_lock);
6376a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell
6386a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell			if (ret == -EBUSY)
6396a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell				goto err_ecc;
6406a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell
6416a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell			info->chip.ecc.calculate = nand_davinci_calculate_4bit;
6426a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell			info->chip.ecc.correct = nand_davinci_correct_4bit;
6436a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell			info->chip.ecc.hwctl = nand_davinci_hwctl_4bit;
6446a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell			info->chip.ecc.bytes = 10;
6456a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		} else {
6466a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell			info->chip.ecc.calculate = nand_davinci_calculate_1bit;
6476a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell			info->chip.ecc.correct = nand_davinci_correct_1bit;
6486a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell			info->chip.ecc.hwctl = nand_davinci_hwctl_1bit;
6496a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell			info->chip.ecc.bytes = 3;
6506a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		}
651ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		info->chip.ecc.size = 512;
652ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		break;
653ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	default:
654ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		ret = -EINVAL;
655ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		goto err_ecc;
656ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	}
657ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	info->chip.ecc.mode = ecc_mode;
658ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
659cd24f8c1e7e27a2c6051a9a338d4704a2431dbf0Kevin Hilman	info->clk = clk_get(&pdev->dev, "aemif");
660ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	if (IS_ERR(info->clk)) {
661ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		ret = PTR_ERR(info->clk);
662cd24f8c1e7e27a2c6051a9a338d4704a2431dbf0Kevin Hilman		dev_dbg(&pdev->dev, "unable to get AEMIF clock, err %d\n", ret);
663ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		goto err_clk;
664ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	}
665ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
666ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	ret = clk_enable(info->clk);
667ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	if (ret < 0) {
668cd24f8c1e7e27a2c6051a9a338d4704a2431dbf0Kevin Hilman		dev_dbg(&pdev->dev, "unable to enable AEMIF clock, err %d\n",
669cd24f8c1e7e27a2c6051a9a338d4704a2431dbf0Kevin Hilman			ret);
670ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		goto err_clk_enable;
671ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	}
672ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
673ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	/* EMIF timings should normally be set by the boot loader,
674ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	 * especially after boot-from-NAND.  The *only* reason to
675ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	 * have this special casing for the DM6446 EVM is to work
676ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	 * with boot-from-NOR ... with CS0 manually re-jumpered
677ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	 * (after startup) so it addresses the NAND flash, not NOR.
678ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	 * Even for dev boards, that's unusually rude...
679ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	 */
680ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	if (machine_is_davinci_evm())
681ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		nand_dm6446evm_flash_init(info);
682ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
683ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	spin_lock_irq(&davinci_nand_lock);
684ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
685ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	/* put CSxNAND into NAND mode */
686ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	val = davinci_nand_readl(info, NANDFCR_OFFSET);
687ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	val |= BIT(info->core_chipsel);
688ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	davinci_nand_writel(info, NANDFCR_OFFSET, val);
689ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
690ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	spin_unlock_irq(&davinci_nand_lock);
691ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
692ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	/* Scan to find existence of the device(s) */
6935e81e88a4c140586d9212999cea683bcd66a15c6David Woodhouse	ret = nand_scan_ident(&info->mtd, pdata->mask_chipsel ? 2 : 1, NULL);
694ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	if (ret < 0) {
695ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		dev_dbg(&pdev->dev, "no NAND chip(s) found\n");
696ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		goto err_scan;
697ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	}
698ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
6996a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	/* Update ECC layout if needed ... for 1-bit HW ECC, the default
7006a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	 * is OK, but it allocates 6 bytes when only 3 are needed (for
7016a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	 * each 512 bytes).  For the 4-bit HW ECC, that default is not
7026a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	 * usable:  10 bytes are needed, not 6.
7036a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	 */
7046a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	if (pdata->ecc_bits == 4) {
7056a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		int	chunks = info->mtd.writesize / 512;
7066a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell
7076a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		if (!chunks || info->mtd.oobsize < 16) {
7086a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell			dev_dbg(&pdev->dev, "too small\n");
7096a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell			ret = -EINVAL;
7106a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell			goto err_scan;
7116a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		}
7126a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell
7136a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		/* For small page chips, preserve the manufacturer's
7146a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		 * badblock marking data ... and make sure a flash BBT
7156a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		 * table marker fits in the free bytes.
7166a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		 */
7176a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		if (chunks == 1) {
7186a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell			info->ecclayout = hwecc4_small;
7196a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell			info->ecclayout.oobfree[1].length =
7206a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell				info->mtd.oobsize - 16;
7216a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell			goto syndrome_done;
7226a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		}
723f12a9473283e68ae708e9ada37cb352ea2652397Sneha Narnakaje		if (chunks == 4) {
724f12a9473283e68ae708e9ada37cb352ea2652397Sneha Narnakaje			info->ecclayout = hwecc4_2048;
725f12a9473283e68ae708e9ada37cb352ea2652397Sneha Narnakaje			info->chip.ecc.mode = NAND_ECC_HW_OOB_FIRST;
726f12a9473283e68ae708e9ada37cb352ea2652397Sneha Narnakaje			goto syndrome_done;
727f12a9473283e68ae708e9ada37cb352ea2652397Sneha Narnakaje		}
7286a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell
729f12a9473283e68ae708e9ada37cb352ea2652397Sneha Narnakaje		/* 4KiB page chips are not yet supported. The eccpos from
730f12a9473283e68ae708e9ada37cb352ea2652397Sneha Narnakaje		 * nand_ecclayout cannot hold 80 bytes and change to eccpos[]
731f12a9473283e68ae708e9ada37cb352ea2652397Sneha Narnakaje		 * breaks userspace ioctl interface with mtd-utils. Once we
732f12a9473283e68ae708e9ada37cb352ea2652397Sneha Narnakaje		 * resolve this issue, NAND_ECC_HW_OOB_FIRST mode can be used
733f12a9473283e68ae708e9ada37cb352ea2652397Sneha Narnakaje		 * for the 4KiB page chips.
7346a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		 */
7356a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		dev_warn(&pdev->dev, "no 4-bit ECC support yet "
736f12a9473283e68ae708e9ada37cb352ea2652397Sneha Narnakaje				"for 4KiB-page NAND\n");
7376a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		ret = -EIO;
7386a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		goto err_scan;
7396a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell
7406a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownellsyndrome_done:
7416a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		info->chip.ecc.layout = &info->ecclayout;
7426a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	}
7436a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell
7446a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	ret = nand_scan_tail(&info->mtd);
7456a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	if (ret < 0)
7466a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		goto err_scan;
7476a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell
748ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	if (mtd_has_partitions()) {
749ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		struct mtd_partition	*mtd_parts = NULL;
750ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		int			mtd_parts_nb = 0;
751ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
752ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		if (mtd_has_cmdlinepart()) {
753ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell			static const char *probes[] __initconst =
754ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell				{ "cmdlinepart", NULL };
755ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
756ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell			mtd_parts_nb = parse_mtd_partitions(&info->mtd, probes,
757ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell							    &mtd_parts, 0);
758ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		}
759ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
760533a0149148ccaa0199a1ee6492cd860e3c8b456David Brownell		if (mtd_parts_nb <= 0) {
761ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell			mtd_parts = pdata->parts;
762ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell			mtd_parts_nb = pdata->nr_parts;
763ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		}
764ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
765ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		/* Register any partitions */
766ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		if (mtd_parts_nb > 0) {
767ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell			ret = add_mtd_partitions(&info->mtd,
768ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell					mtd_parts, mtd_parts_nb);
769ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell			if (ret == 0)
770ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell				info->partitioned = true;
771ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		}
772ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
773533a0149148ccaa0199a1ee6492cd860e3c8b456David Brownell	} else if (pdata->nr_parts) {
774ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		dev_warn(&pdev->dev, "ignoring %d default partitions on %s\n",
775ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell				pdata->nr_parts, info->mtd.name);
776ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	}
777ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
778ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	/* If there's no partition info, just package the whole chip
779ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	 * as a single MTD device.
780ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	 */
781ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	if (!info->partitioned)
782ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		ret = add_mtd_device(&info->mtd) ? -ENODEV : 0;
783ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
784ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	if (ret < 0)
785ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		goto err_scan;
786ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
787ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	val = davinci_nand_readl(info, NRCSR_OFFSET);
788ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	dev_info(&pdev->dev, "controller rev. %d.%d\n",
789ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	       (val >> 8) & 0xff, val & 0xff);
790ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
791ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	return 0;
792ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
793ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownellerr_scan:
794ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	clk_disable(info->clk);
795ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
796ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownellerr_clk_enable:
797ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	clk_put(info->clk);
798ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
7996a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	spin_lock_irq(&davinci_nand_lock);
8006a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	if (ecc_mode == NAND_ECC_HW_SYNDROME)
8016a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		ecc4_busy = false;
8026a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	spin_unlock_irq(&davinci_nand_lock);
8036a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell
804ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownellerr_ecc:
805ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownellerr_clk:
806ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownellerr_ioremap:
807ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	if (base)
808ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		iounmap(base);
809ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	if (vaddr)
810ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		iounmap(vaddr);
811ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
812ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownellerr_nomem:
813ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	kfree(info);
814ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	return ret;
815ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell}
816ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
817ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownellstatic int __exit nand_davinci_remove(struct platform_device *pdev)
818ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell{
819ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	struct davinci_nand_info *info = platform_get_drvdata(pdev);
820ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	int status;
821ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
822ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	if (mtd_has_partitions() && info->partitioned)
823ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		status = del_mtd_partitions(&info->mtd);
824ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	else
825ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		status = del_mtd_device(&info->mtd);
826ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
8276a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	spin_lock_irq(&davinci_nand_lock);
8286a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	if (info->chip.ecc.mode == NAND_ECC_HW_SYNDROME)
8296a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell		ecc4_busy = false;
8306a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell	spin_unlock_irq(&davinci_nand_lock);
8316a4123e581b3112ff4ea7439ab9ae5cb271a9dbdDavid Brownell
832ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	iounmap(info->base);
833ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	iounmap(info->vaddr);
834ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
835ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	nand_release(&info->mtd);
836ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
837ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	clk_disable(info->clk);
838ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	clk_put(info->clk);
839ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
840ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	kfree(info);
841ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
842ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	return 0;
843ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell}
844ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
845ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownellstatic struct platform_driver nand_davinci_driver = {
846ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	.remove		= __exit_p(nand_davinci_remove),
847ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	.driver		= {
848ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell		.name	= "davinci_nand",
849ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	},
850ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell};
851ff4569c752c577c7e71e03c9d59e6ef85ca763c0David BrownellMODULE_ALIAS("platform:davinci_nand");
852ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
853ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownellstatic int __init nand_davinci_init(void)
854ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell{
855ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	return platform_driver_probe(&nand_davinci_driver, nand_davinci_probe);
856ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell}
857ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownellmodule_init(nand_davinci_init);
858ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
859ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownellstatic void __exit nand_davinci_exit(void)
860ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell{
861ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell	platform_driver_unregister(&nand_davinci_driver);
862ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell}
863ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownellmodule_exit(nand_davinci_exit);
864ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
865ff4569c752c577c7e71e03c9d59e6ef85ca763c0David BrownellMODULE_LICENSE("GPL");
866ff4569c752c577c7e71e03c9d59e6ef85ca763c0David BrownellMODULE_AUTHOR("Texas Instruments");
867ff4569c752c577c7e71e03c9d59e6ef85ca763c0David BrownellMODULE_DESCRIPTION("Davinci NAND flash driver");
868ff4569c752c577c7e71e03c9d59e6ef85ca763c0David Brownell
869