aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/nand
diff options
context:
space:
mode:
authorDavid Brownell <dbrownell@users.sourceforge.net>2009-03-04 15:01:37 -0500
committerDavid Woodhouse <David.Woodhouse@intel.com>2009-03-20 08:32:19 -0400
commitff4569c752c577c7e71e03c9d59e6ef85ca763c0 (patch)
tree40e14bb1acb7f1261bb55e2d0abb44dfd32abef8 /drivers/mtd/nand
parent52ff49df7fab18e56fa31b43143c4150c2547836 (diff)
[MTD] [NAND] davinci_nand driver
This is a device driver for the NAND flash controller found on the various DaVinci family chips. It handles up to four SoC chipselects, and some flavors of secondary chipselect (e.g. based on upper bits of the address bus) as used with some multichip packages. (Including the 2 GiB chips used on some TI devel boards.) The 1-bit ECC hardware is supported (3 bytes ECC per 512 bytes data); but not yet the newer 4-bit ECC (10 bytes ECC per 512 bytes data), as available on chips like the DM355 or OMAP-L137 and needed with the more error-prone MLC NAND chips. This is a cleaned-up version of code that's been in use for several years now; sanity checked with the new drivers/mtd/tests. Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> Signed-off-by: Sudhakar Rajashekhara <sudhakar.raj@ti.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Diffstat (limited to 'drivers/mtd/nand')
-rw-r--r--drivers/mtd/nand/Kconfig7
-rw-r--r--drivers/mtd/nand/Makefile1
-rw-r--r--drivers/mtd/nand/davinci_nand.c584
3 files changed, 592 insertions, 0 deletions
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 8b12e6e109d3..30d6fbc30c35 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -427,4 +427,11 @@ config MTD_NAND_SH_FLCTL
427 Several Renesas SuperH CPU has FLCTL. This option enables support 427 Several Renesas SuperH CPU has FLCTL. This option enables support
428 for NAND Flash using FLCTL. This driver support SH7723. 428 for NAND Flash using FLCTL. This driver support SH7723.
429 429
430config MTD_NAND_DAVINCI
431 tristate "Support NAND on DaVinci SoC"
432 depends on ARCH_DAVINCI
433 help
434 Enable the driver for NAND flash chips on Texas Instruments
435 DaVinci processors.
436
430endif # MTD_NAND 437endif # MTD_NAND
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index b661586afbfc..26dc0bef68ae 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_MTD_NAND_AU1550) += au1550nd.o
14obj-$(CONFIG_MTD_NAND_BF5XX) += bf5xx_nand.o 14obj-$(CONFIG_MTD_NAND_BF5XX) += bf5xx_nand.o
15obj-$(CONFIG_MTD_NAND_PPCHAMELEONEVB) += ppchameleonevb.o 15obj-$(CONFIG_MTD_NAND_PPCHAMELEONEVB) += ppchameleonevb.o
16obj-$(CONFIG_MTD_NAND_S3C2410) += s3c2410.o 16obj-$(CONFIG_MTD_NAND_S3C2410) += s3c2410.o
17obj-$(CONFIG_MTD_NAND_DAVINCI) += davinci_nand.o
17obj-$(CONFIG_MTD_NAND_DISKONCHIP) += diskonchip.o 18obj-$(CONFIG_MTD_NAND_DISKONCHIP) += diskonchip.o
18obj-$(CONFIG_MTD_NAND_H1900) += h1910.o 19obj-$(CONFIG_MTD_NAND_H1900) += h1910.o
19obj-$(CONFIG_MTD_NAND_RTC_FROM4) += rtc_from4.o 20obj-$(CONFIG_MTD_NAND_RTC_FROM4) += rtc_from4.o
diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c
new file mode 100644
index 000000000000..4bedd8dec61e
--- /dev/null
+++ b/drivers/mtd/nand/davinci_nand.c
@@ -0,0 +1,584 @@
1/*
2 * davinci_nand.c - NAND Flash Driver for DaVinci family chips
3 *
4 * Copyright © 2006 Texas Instruments.
5 *
6 * Port to 2.6.23 Copyright © 2008 by:
7 * Sander Huijsen <Shuijsen@optelecom-nkf.com>
8 * Troy Kisky <troy.kisky@boundarydevices.com>
9 * Dirk Behme <Dirk.Behme@gmail.com>
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 */
25
26#include <linux/kernel.h>
27#include <linux/init.h>
28#include <linux/module.h>
29#include <linux/platform_device.h>
30#include <linux/err.h>
31#include <linux/clk.h>
32#include <linux/io.h>
33#include <linux/mtd/nand.h>
34#include <linux/mtd/partitions.h>
35
36#include <mach/cpu.h>
37#include <mach/nand.h>
38
39#include <asm/mach-types.h>
40
41
42#ifdef CONFIG_MTD_PARTITIONS
43static inline int mtd_has_partitions(void) { return 1; }
44#else
45static inline int mtd_has_partitions(void) { return 0; }
46#endif
47
48#ifdef CONFIG_MTD_CMDLINE_PARTS
49static inline int mtd_has_cmdlinepart(void) { return 1; }
50#else
51static inline int mtd_has_cmdlinepart(void) { return 0; }
52#endif
53
54
55/*
56 * This is a device driver for the NAND flash controller found on the
57 * various DaVinci family chips. It handles up to four SoC chipselects,
58 * and some flavors of secondary chipselect (e.g. based on A12) as used
59 * with multichip packages.
60 *
61 * The 1-bit ECC hardware is supported, but not yet the newer 4-bit ECC
62 * available on chips like the DM355 and OMAP-L137 and needed with the
63 * more error-prone MLC NAND chips.
64 *
65 * This driver assumes EM_WAIT connects all the NAND devices' RDY/nBUSY
66 * outputs in a "wire-AND" configuration, with no per-chip signals.
67 */
68struct davinci_nand_info {
69 struct mtd_info mtd;
70 struct nand_chip chip;
71
72 struct device *dev;
73 struct clk *clk;
74 bool partitioned;
75
76 void __iomem *base;
77 void __iomem *vaddr;
78
79 uint32_t ioaddr;
80 uint32_t current_cs;
81
82 uint32_t mask_chipsel;
83 uint32_t mask_ale;
84 uint32_t mask_cle;
85
86 uint32_t core_chipsel;
87};
88
89static DEFINE_SPINLOCK(davinci_nand_lock);
90
91#define to_davinci_nand(m) container_of(m, struct davinci_nand_info, mtd)
92
93
94static inline unsigned int davinci_nand_readl(struct davinci_nand_info *info,
95 int offset)
96{
97 return __raw_readl(info->base + offset);
98}
99
100static inline void davinci_nand_writel(struct davinci_nand_info *info,
101 int offset, unsigned long value)
102{
103 __raw_writel(value, info->base + offset);
104}
105
106/*----------------------------------------------------------------------*/
107
108/*
109 * Access to hardware control lines: ALE, CLE, secondary chipselect.
110 */
111
112static void nand_davinci_hwcontrol(struct mtd_info *mtd, int cmd,
113 unsigned int ctrl)
114{
115 struct davinci_nand_info *info = to_davinci_nand(mtd);
116 uint32_t addr = info->current_cs;
117 struct nand_chip *nand = mtd->priv;
118
119 /* Did the control lines change? */
120 if (ctrl & NAND_CTRL_CHANGE) {
121 if ((ctrl & NAND_CTRL_CLE) == NAND_CTRL_CLE)
122 addr |= info->mask_cle;
123 else if ((ctrl & NAND_CTRL_ALE) == NAND_CTRL_ALE)
124 addr |= info->mask_ale;
125
126 nand->IO_ADDR_W = (void __iomem __force *)addr;
127 }
128
129 if (cmd != NAND_CMD_NONE)
130 iowrite8(cmd, nand->IO_ADDR_W);
131}
132
133static void nand_davinci_select_chip(struct mtd_info *mtd, int chip)
134{
135 struct davinci_nand_info *info = to_davinci_nand(mtd);
136 uint32_t addr = info->ioaddr;
137
138 /* maybe kick in a second chipselect */
139 if (chip > 0)
140 addr |= info->mask_chipsel;
141 info->current_cs = addr;
142
143 info->chip.IO_ADDR_W = (void __iomem __force *)addr;
144 info->chip.IO_ADDR_R = info->chip.IO_ADDR_W;
145}
146
147/*----------------------------------------------------------------------*/
148
149/*
150 * 1-bit hardware ECC ... context maintained for each core chipselect
151 */
152
153static inline uint32_t nand_davinci_readecc_1bit(struct mtd_info *mtd)
154{
155 struct davinci_nand_info *info = to_davinci_nand(mtd);
156
157 return davinci_nand_readl(info, NANDF1ECC_OFFSET
158 + 4 * info->core_chipsel);
159}
160
161static void nand_davinci_hwctl_1bit(struct mtd_info *mtd, int mode)
162{
163 struct davinci_nand_info *info;
164 uint32_t nandcfr;
165 unsigned long flags;
166
167 info = to_davinci_nand(mtd);
168
169 /* Reset ECC hardware */
170 nand_davinci_readecc_1bit(mtd);
171
172 spin_lock_irqsave(&davinci_nand_lock, flags);
173
174 /* Restart ECC hardware */
175 nandcfr = davinci_nand_readl(info, NANDFCR_OFFSET);
176 nandcfr |= BIT(8 + info->core_chipsel);
177 davinci_nand_writel(info, NANDFCR_OFFSET, nandcfr);
178
179 spin_unlock_irqrestore(&davinci_nand_lock, flags);
180}
181
182/*
183 * Read hardware ECC value and pack into three bytes
184 */
185static int nand_davinci_calculate_1bit(struct mtd_info *mtd,
186 const u_char *dat, u_char *ecc_code)
187{
188 unsigned int ecc_val = nand_davinci_readecc_1bit(mtd);
189 unsigned int ecc24 = (ecc_val & 0x0fff) | ((ecc_val & 0x0fff0000) >> 4);
190
191 /* invert so that erased block ecc is correct */
192 ecc24 = ~ecc24;
193 ecc_code[0] = (u_char)(ecc24);
194 ecc_code[1] = (u_char)(ecc24 >> 8);
195 ecc_code[2] = (u_char)(ecc24 >> 16);
196
197 return 0;
198}
199
200static int nand_davinci_correct_1bit(struct mtd_info *mtd, u_char *dat,
201 u_char *read_ecc, u_char *calc_ecc)
202{
203 struct nand_chip *chip = mtd->priv;
204 uint32_t eccNand = read_ecc[0] | (read_ecc[1] << 8) |
205 (read_ecc[2] << 16);
206 uint32_t eccCalc = calc_ecc[0] | (calc_ecc[1] << 8) |
207 (calc_ecc[2] << 16);
208 uint32_t diff = eccCalc ^ eccNand;
209
210 if (diff) {
211 if ((((diff >> 12) ^ diff) & 0xfff) == 0xfff) {
212 /* Correctable error */
213 if ((diff >> (12 + 3)) < chip->ecc.size) {
214 dat[diff >> (12 + 3)] ^= BIT((diff >> 12) & 7);
215 return 1;
216 } else {
217 return -1;
218 }
219 } else if (!(diff & (diff - 1))) {
220 /* Single bit ECC error in the ECC itself,
221 * nothing to fix */
222 return 1;
223 } else {
224 /* Uncorrectable error */
225 return -1;
226 }
227
228 }
229 return 0;
230}
231
232/*----------------------------------------------------------------------*/
233
234/*
235 * NOTE: NAND boot requires ALE == EM_A[1], CLE == EM_A[2], so that's
236 * how these chips are normally wired. This translates to both 8 and 16
237 * bit busses using ALE == BIT(3) in byte addresses, and CLE == BIT(4).
238 *
239 * For now we assume that configuration, or any other one which ignores
240 * the two LSBs for NAND access ... so we can issue 32-bit reads/writes
241 * and have that transparently morphed into multiple NAND operations.
242 */
243static void nand_davinci_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
244{
245 struct nand_chip *chip = mtd->priv;
246
247 if ((0x03 & ((unsigned)buf)) == 0 && (0x03 & len) == 0)
248 ioread32_rep(chip->IO_ADDR_R, buf, len >> 2);
249 else if ((0x01 & ((unsigned)buf)) == 0 && (0x01 & len) == 0)
250 ioread16_rep(chip->IO_ADDR_R, buf, len >> 1);
251 else
252 ioread8_rep(chip->IO_ADDR_R, buf, len);
253}
254
255static void nand_davinci_write_buf(struct mtd_info *mtd,
256 const uint8_t *buf, int len)
257{
258 struct nand_chip *chip = mtd->priv;
259
260 if ((0x03 & ((unsigned)buf)) == 0 && (0x03 & len) == 0)
261 iowrite32_rep(chip->IO_ADDR_R, buf, len >> 2);
262 else if ((0x01 & ((unsigned)buf)) == 0 && (0x01 & len) == 0)
263 iowrite16_rep(chip->IO_ADDR_R, buf, len >> 1);
264 else
265 iowrite8_rep(chip->IO_ADDR_R, buf, len);
266}
267
268/*
269 * Check hardware register for wait status. Returns 1 if device is ready,
270 * 0 if it is still busy.
271 */
272static int nand_davinci_dev_ready(struct mtd_info *mtd)
273{
274 struct davinci_nand_info *info = to_davinci_nand(mtd);
275
276 return davinci_nand_readl(info, NANDFSR_OFFSET) & BIT(0);
277}
278
279static void __init nand_dm6446evm_flash_init(struct davinci_nand_info *info)
280{
281 uint32_t regval, a1cr;
282
283 /*
284 * NAND FLASH timings @ PLL1 == 459 MHz
285 * - AEMIF.CLK freq = PLL1/6 = 459/6 = 76.5 MHz
286 * - AEMIF.CLK period = 1/76.5 MHz = 13.1 ns
287 */
288 regval = 0
289 | (0 << 31) /* selectStrobe */
290 | (0 << 30) /* extWait (never with NAND) */
291 | (1 << 26) /* writeSetup 10 ns */
292 | (3 << 20) /* writeStrobe 40 ns */
293 | (1 << 17) /* writeHold 10 ns */
294 | (0 << 13) /* readSetup 10 ns */
295 | (3 << 7) /* readStrobe 60 ns */
296 | (0 << 4) /* readHold 10 ns */
297 | (3 << 2) /* turnAround ?? ns */
298 | (0 << 0) /* asyncSize 8-bit bus */
299 ;
300 a1cr = davinci_nand_readl(info, A1CR_OFFSET);
301 if (a1cr != regval) {
302 dev_dbg(info->dev, "Warning: NAND config: Set A1CR " \
303 "reg to 0x%08x, was 0x%08x, should be done by " \
304 "bootloader.\n", regval, a1cr);
305 davinci_nand_writel(info, A1CR_OFFSET, regval);
306 }
307}
308
309/*----------------------------------------------------------------------*/
310
311static int __init nand_davinci_probe(struct platform_device *pdev)
312{
313 struct davinci_nand_pdata *pdata = pdev->dev.platform_data;
314 struct davinci_nand_info *info;
315 struct resource *res1;
316 struct resource *res2;
317 void __iomem *vaddr;
318 void __iomem *base;
319 int ret;
320 uint32_t val;
321 nand_ecc_modes_t ecc_mode;
322
323 /* which external chipselect will we be managing? */
324 if (pdev->id < 0 || pdev->id > 3)
325 return -ENODEV;
326
327 info = kzalloc(sizeof(*info), GFP_KERNEL);
328 if (!info) {
329 dev_err(&pdev->dev, "unable to allocate memory\n");
330 ret = -ENOMEM;
331 goto err_nomem;
332 }
333
334 platform_set_drvdata(pdev, info);
335
336 res1 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
337 res2 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
338 if (!res1 || !res2) {
339 dev_err(&pdev->dev, "resource missing\n");
340 ret = -EINVAL;
341 goto err_nomem;
342 }
343
344 vaddr = ioremap(res1->start, res1->end - res1->start);
345 base = ioremap(res2->start, res2->end - res2->start);
346 if (!vaddr || !base) {
347 dev_err(&pdev->dev, "ioremap failed\n");
348 ret = -EINVAL;
349 goto err_ioremap;
350 }
351
352 info->dev = &pdev->dev;
353 info->base = base;
354 info->vaddr = vaddr;
355
356 info->mtd.priv = &info->chip;
357 info->mtd.name = dev_name(&pdev->dev);
358 info->mtd.owner = THIS_MODULE;
359
360 info->chip.IO_ADDR_R = vaddr;
361 info->chip.IO_ADDR_W = vaddr;
362 info->chip.chip_delay = 0;
363 info->chip.select_chip = nand_davinci_select_chip;
364
365 /* options such as NAND_USE_FLASH_BBT or 16-bit widths */
366 info->chip.options = pdata ? pdata->options : 0;
367
368 info->ioaddr = (uint32_t __force) vaddr;
369
370 info->current_cs = info->ioaddr;
371 info->core_chipsel = pdev->id;
372 info->mask_chipsel = pdata->mask_chipsel;
373
374 /* use nandboot-capable ALE/CLE masks by default */
375 if (pdata && pdata->mask_ale)
376 info->mask_ale = pdata->mask_cle;
377 else
378 info->mask_ale = MASK_ALE;
379 if (pdata && pdata->mask_cle)
380 info->mask_cle = pdata->mask_cle;
381 else
382 info->mask_cle = MASK_CLE;
383
384 /* Set address of hardware control function */
385 info->chip.cmd_ctrl = nand_davinci_hwcontrol;
386 info->chip.dev_ready = nand_davinci_dev_ready;
387
388 /* Speed up buffer I/O */
389 info->chip.read_buf = nand_davinci_read_buf;
390 info->chip.write_buf = nand_davinci_write_buf;
391
392 /* use board-specific ECC config; else, the best available */
393 if (pdata)
394 ecc_mode = pdata->ecc_mode;
395 else if (cpu_is_davinci_dm355())
396 ecc_mode = NAND_ECC_HW_SYNDROME;
397 else
398 ecc_mode = NAND_ECC_HW;
399
400 switch (ecc_mode) {
401 case NAND_ECC_NONE:
402 case NAND_ECC_SOFT:
403 break;
404 case NAND_ECC_HW:
405 info->chip.ecc.calculate = nand_davinci_calculate_1bit;
406 info->chip.ecc.correct = nand_davinci_correct_1bit;
407 info->chip.ecc.hwctl = nand_davinci_hwctl_1bit;
408 info->chip.ecc.size = 512;
409 info->chip.ecc.bytes = 3;
410 break;
411 case NAND_ECC_HW_SYNDROME:
412 /* FIXME implement */
413 info->chip.ecc.size = 512;
414 info->chip.ecc.bytes = 10;
415
416 dev_warn(&pdev->dev, "4-bit ECC nyet supported\n");
417 /* FALL THROUGH */
418 default:
419 ret = -EINVAL;
420 goto err_ecc;
421 }
422 info->chip.ecc.mode = ecc_mode;
423
424 info->clk = clk_get(&pdev->dev, "AEMIFCLK");
425 if (IS_ERR(info->clk)) {
426 ret = PTR_ERR(info->clk);
427 dev_dbg(&pdev->dev, "unable to get AEMIFCLK, err %d\n", ret);
428 goto err_clk;
429 }
430
431 ret = clk_enable(info->clk);
432 if (ret < 0) {
433 dev_dbg(&pdev->dev, "unable to enable AEMIFCLK, err %d\n", ret);
434 goto err_clk_enable;
435 }
436
437 /* EMIF timings should normally be set by the boot loader,
438 * especially after boot-from-NAND. The *only* reason to
439 * have this special casing for the DM6446 EVM is to work
440 * with boot-from-NOR ... with CS0 manually re-jumpered
441 * (after startup) so it addresses the NAND flash, not NOR.
442 * Even for dev boards, that's unusually rude...
443 */
444 if (machine_is_davinci_evm())
445 nand_dm6446evm_flash_init(info);
446
447 spin_lock_irq(&davinci_nand_lock);
448
449 /* put CSxNAND into NAND mode */
450 val = davinci_nand_readl(info, NANDFCR_OFFSET);
451 val |= BIT(info->core_chipsel);
452 davinci_nand_writel(info, NANDFCR_OFFSET, val);
453
454 spin_unlock_irq(&davinci_nand_lock);
455
456 /* Scan to find existence of the device(s) */
457 ret = nand_scan(&info->mtd, pdata->mask_chipsel ? 2 : 1);
458 if (ret < 0) {
459 dev_dbg(&pdev->dev, "no NAND chip(s) found\n");
460 goto err_scan;
461 }
462
463 if (mtd_has_partitions()) {
464 struct mtd_partition *mtd_parts = NULL;
465 int mtd_parts_nb = 0;
466
467 if (mtd_has_cmdlinepart()) {
468 static const char *probes[] __initconst =
469 { "cmdlinepart", NULL };
470
471 const char *master_name;
472
473 /* Set info->mtd.name = 0 temporarily */
474 master_name = info->mtd.name;
475 info->mtd.name = (char *)0;
476
477 /* info->mtd.name == 0, means: don't bother checking
478 <mtd-id> */
479 mtd_parts_nb = parse_mtd_partitions(&info->mtd, probes,
480 &mtd_parts, 0);
481
482 /* Restore info->mtd.name */
483 info->mtd.name = master_name;
484 }
485
486 if (mtd_parts_nb <= 0 && pdata) {
487 mtd_parts = pdata->parts;
488 mtd_parts_nb = pdata->nr_parts;
489 }
490
491 /* Register any partitions */
492 if (mtd_parts_nb > 0) {
493 ret = add_mtd_partitions(&info->mtd,
494 mtd_parts, mtd_parts_nb);
495 if (ret == 0)
496 info->partitioned = true;
497 }
498
499 } else if (pdata && pdata->nr_parts) {
500 dev_warn(&pdev->dev, "ignoring %d default partitions on %s\n",
501 pdata->nr_parts, info->mtd.name);
502 }
503
504 /* If there's no partition info, just package the whole chip
505 * as a single MTD device.
506 */
507 if (!info->partitioned)
508 ret = add_mtd_device(&info->mtd) ? -ENODEV : 0;
509
510 if (ret < 0)
511 goto err_scan;
512
513 val = davinci_nand_readl(info, NRCSR_OFFSET);
514 dev_info(&pdev->dev, "controller rev. %d.%d\n",
515 (val >> 8) & 0xff, val & 0xff);
516
517 return 0;
518
519err_scan:
520 clk_disable(info->clk);
521
522err_clk_enable:
523 clk_put(info->clk);
524
525err_ecc:
526err_clk:
527err_ioremap:
528 if (base)
529 iounmap(base);
530 if (vaddr)
531 iounmap(vaddr);
532
533err_nomem:
534 kfree(info);
535 return ret;
536}
537
538static int __exit nand_davinci_remove(struct platform_device *pdev)
539{
540 struct davinci_nand_info *info = platform_get_drvdata(pdev);
541 int status;
542
543 if (mtd_has_partitions() && info->partitioned)
544 status = del_mtd_partitions(&info->mtd);
545 else
546 status = del_mtd_device(&info->mtd);
547
548 iounmap(info->base);
549 iounmap(info->vaddr);
550
551 nand_release(&info->mtd);
552
553 clk_disable(info->clk);
554 clk_put(info->clk);
555
556 kfree(info);
557
558 return 0;
559}
560
561static struct platform_driver nand_davinci_driver = {
562 .remove = __exit_p(nand_davinci_remove),
563 .driver = {
564 .name = "davinci_nand",
565 },
566};
567MODULE_ALIAS("platform:davinci_nand");
568
569static int __init nand_davinci_init(void)
570{
571 return platform_driver_probe(&nand_davinci_driver, nand_davinci_probe);
572}
573module_init(nand_davinci_init);
574
575static void __exit nand_davinci_exit(void)
576{
577 platform_driver_unregister(&nand_davinci_driver);
578}
579module_exit(nand_davinci_exit);
580
581MODULE_LICENSE("GPL");
582MODULE_AUTHOR("Texas Instruments");
583MODULE_DESCRIPTION("Davinci NAND flash driver");
584