Commit 07190aa9 authored by David Brownell's avatar David Brownell Committed by Kevin Hilman

davinci_nand: cleanup

More cleanup of the NAND driver; mostly just comments but including
one small bugfix to the 1-bit ECC computation for nonzero chipselects.

This should get the driver most of the way to seeming reasonable for
an upstream merge ... but, no 4-bit ECC support yet.
Signed-off-by: default avatarDavid Brownell <dbrownell@users.sourceforge.net>
parent b2efdf9e
...@@ -3,13 +3,11 @@ ...@@ -3,13 +3,11 @@
* *
* Copyright (C) 2006 Texas Instruments. * Copyright (C) 2006 Texas Instruments.
* *
* ported to 2.6.23 (C) 2008 by * Port to 2.6.23 Copyright (C) 2008 by:
* Sander Huijsen <Shuijsen@optelecom-nkf.com> * Sander Huijsen <Shuijsen@optelecom-nkf.com>
* Troy Kisky <troy.kisky@boundarydevices.com> * Troy Kisky <troy.kisky@boundarydevices.com>
* Dirk Behme <Dirk.Behme@gmail.com> * Dirk Behme <Dirk.Behme@gmail.com>
* *
* --------------------------------------------------------------------------
*
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or * the Free Software Foundation; either version 2 of the License, or
...@@ -23,16 +21,6 @@ ...@@ -23,16 +21,6 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
* --------------------------------------------------------------------------
*
* Overview:
* This is a device driver for the NAND flash device found on the
* DaVinci DM6446 EVM board which utilizes the Samsung k9k2g08 part.
* (small page NAND). It should work for some other DaVinci NAND
* configurations, but it ignores the dm355 4-bit ECC hardware.
*
* Currently assumes EM_WAIT connects all of the NAND devices in
* a "wire-OR" configuration.
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
...@@ -42,18 +30,13 @@ ...@@ -42,18 +30,13 @@
#include <linux/err.h> #include <linux/err.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/spinlock.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h> #include <linux/mtd/nand.h>
#include <linux/mtd/partitions.h> #include <linux/mtd/partitions.h>
#include <mach/cpu.h> #include <mach/cpu.h>
#include <mach/hardware.h>
#include <mach/nand.h> #include <mach/nand.h>
#include <mach/mux.h>
#include <asm/mach-types.h> #include <asm/mach-types.h>
#include <asm/mach/flash.h>
#ifdef CONFIG_MTD_PARTITIONS #ifdef CONFIG_MTD_PARTITIONS
...@@ -69,6 +52,19 @@ static inline int mtd_has_cmdlinepart(void) { return 0; } ...@@ -69,6 +52,19 @@ static inline int mtd_has_cmdlinepart(void) { return 0; }
#endif #endif
/*
* 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 A12) as used
* with multichip packages.
*
* The 1-bit ECC hardware is supported, but not yet the newer 4-bit ECC
* available on chips like the DM355 and OMAP-L137 and needed with the
* more error-prone MLC NAND chips.
*
* This driver assumes EM_WAIT connects all the NAND devices' RDY/nBUSY
* outputs in a "wire-AND" configuration, with no per-chip signals.
*/
struct davinci_nand_info { struct davinci_nand_info {
struct mtd_info mtd; struct mtd_info mtd;
struct nand_chip chip; struct nand_chip chip;
...@@ -107,11 +103,12 @@ static inline void davinci_nand_writel(struct davinci_nand_info *info, ...@@ -107,11 +103,12 @@ static inline void davinci_nand_writel(struct davinci_nand_info *info,
__raw_writel(value, info->base + offset); __raw_writel(value, info->base + offset);
} }
/*----------------------------------------------------------------------*/
/* /*
* Hardware specific access to control-lines * Access to hardware control lines: ALE, CLE, secondary chipselect.
*
* REVISIT avoid casting addresses
*/ */
static void nand_davinci_hwcontrol(struct mtd_info *mtd, int cmd, static void nand_davinci_hwcontrol(struct mtd_info *mtd, int cmd,
unsigned int ctrl) unsigned int ctrl)
{ {
...@@ -153,6 +150,14 @@ static void nand_davinci_select_chip(struct mtd_info *mtd, int chip) ...@@ -153,6 +150,14 @@ static void nand_davinci_select_chip(struct mtd_info *mtd, int chip)
* 1-bit hardware ECC ... context maintained for each core chipselect * 1-bit hardware ECC ... context maintained for each core chipselect
*/ */
static inline u32 nand_davinci_readecc_1bit(struct mtd_info *mtd)
{
struct davinci_nand_info *info = to_davinci_nand(mtd);
return davinci_nand_readl(info, NANDF1ECC_OFFSET
+ 4 * info->core_chipsel);
}
static void nand_davinci_hwctl_1bit(struct mtd_info *mtd, int mode) static void nand_davinci_hwctl_1bit(struct mtd_info *mtd, int mode)
{ {
struct davinci_nand_info *info; struct davinci_nand_info *info;
...@@ -162,8 +167,7 @@ static void nand_davinci_hwctl_1bit(struct mtd_info *mtd, int mode) ...@@ -162,8 +167,7 @@ static void nand_davinci_hwctl_1bit(struct mtd_info *mtd, int mode)
info = to_davinci_nand(mtd); info = to_davinci_nand(mtd);
/* Reset ECC hardware */ /* Reset ECC hardware */
retval = davinci_nand_readl(info, NANDF1ECC_OFFSET nand_davinci_readecc_1bit(mtd);
+ 4 * info->core_chipsel);
spin_lock_irqsave(&davinci_nand_lock, flags); spin_lock_irqsave(&davinci_nand_lock, flags);
...@@ -176,25 +180,14 @@ static void nand_davinci_hwctl_1bit(struct mtd_info *mtd, int mode) ...@@ -176,25 +180,14 @@ static void nand_davinci_hwctl_1bit(struct mtd_info *mtd, int mode)
} }
/* /*
* Read DaVinci ECC register * Read hardware ECC value and pack into three bytes
*/
static inline u32 nand_davinci_readecc_1bit(struct mtd_info *mtd)
{
struct davinci_nand_info *info = to_davinci_nand(mtd);
/* Read register ECC and clear it */
return davinci_nand_readl(info, NANDF1ECC_OFFSET);
}
/*
* Read DaVinci ECC registers and rework into MTD format
*/ */
static int nand_davinci_calculate_1bit(struct mtd_info *mtd, static int nand_davinci_calculate_1bit(struct mtd_info *mtd,
const u_char *dat, u_char *ecc_code) const u_char *dat, u_char *ecc_code)
{ {
unsigned int ecc_val = nand_davinci_readecc_1bit(mtd); unsigned int ecc_val = nand_davinci_readecc_1bit(mtd);
/* squeeze 0 middle bits out so that it fits in 3 bytes */
unsigned int tmp = (ecc_val & 0x0fff) | ((ecc_val & 0x0fff0000) >> 4); unsigned int tmp = (ecc_val & 0x0fff) | ((ecc_val & 0x0fff0000) >> 4);
/* invert so that erased block ecc is correct */ /* invert so that erased block ecc is correct */
tmp = ~tmp; tmp = ~tmp;
ecc_code[0] = (u_char)(tmp); ecc_code[0] = (u_char)(tmp);
...@@ -225,7 +218,7 @@ static int nand_davinci_correct_1bit(struct mtd_info *mtd, u_char *dat, ...@@ -225,7 +218,7 @@ static int nand_davinci_correct_1bit(struct mtd_info *mtd, u_char *dat,
} }
} else if (!(diff & (diff - 1))) { } else if (!(diff & (diff - 1))) {
/* Single bit ECC error in the ECC itself, /* Single bit ECC error in the ECC itself,
nothing to fix */ * nothing to fix */
return 1; return 1;
} else { } else {
/* Uncorrectable error */ /* Uncorrectable error */
...@@ -405,15 +398,6 @@ static int __init nand_davinci_probe(struct platform_device *pdev) ...@@ -405,15 +398,6 @@ static int __init nand_davinci_probe(struct platform_device *pdev)
else else
ecc_mode = NAND_ECC_HW; ecc_mode = NAND_ECC_HW;
/*
* REVISIT dm355 adds an ECC mode that corrects up to 4 error
* bits, using 10 ECC bytes every 512 bytes of data. And that
* is what TI's original LSP uses... along with quite a hacked
* up "inline OOB" scheme storing those ECC bytes, which happens
* to use (in good blocks) bytes used by factory bad-block marks
* (in bad blocks). There was evidently a technical issue (now
* fixed?): Linux seemed to limit ECC data to 32 bytes.
*/
switch (ecc_mode) { switch (ecc_mode) {
case NAND_ECC_NONE: case NAND_ECC_NONE:
case NAND_ECC_SOFT: case NAND_ECC_SOFT:
...@@ -520,10 +504,6 @@ static int __init nand_davinci_probe(struct platform_device *pdev) ...@@ -520,10 +504,6 @@ static int __init nand_davinci_probe(struct platform_device *pdev)
/* If there's no partition info, just package the whole chip /* If there's no partition info, just package the whole chip
* as a single MTD device. * as a single MTD device.
*
* NOTE: When using the DM355 with large block NAND chips, don't
* use this driver to change data the ROM Boot Loader (RBL) reads
* from one of the first 24 blocks. See DM355 errata for details.
*/ */
if (!info->partitioned) if (!info->partitioned)
ret = add_mtd_device(&info->mtd) ? -ENODEV : 0; ret = add_mtd_device(&info->mtd) ? -ENODEV : 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment