summaryrefslogtreecommitdiff
path: root/drivers/mtd/nand
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd/nand')
-rw-r--r--drivers/mtd/nand/fsl_elbc_nand.c32
-rw-r--r--drivers/mtd/nand/fsl_upm.c16
-rw-r--r--drivers/mtd/nand/kirkwood_nand.c2
-rw-r--r--drivers/mtd/nand/mxc_nand.c32
-rw-r--r--drivers/mtd/nand/nand_base.c2
-rw-r--r--drivers/mtd/nand/nand_util.c29
6 files changed, 41 insertions, 72 deletions
diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c
index acdb431..4d1e527 100644
--- a/drivers/mtd/nand/fsl_elbc_nand.c
+++ b/drivers/mtd/nand/fsl_elbc_nand.c
@@ -85,7 +85,6 @@ struct fsl_elbc_ctrl {
unsigned int mdr; /* UPM/FCM Data Register value */
unsigned int use_mdr; /* Non zero if the MDR is to be set */
unsigned int oob; /* Non zero if operating on OOB data */
- uint8_t *oob_poi; /* Place to write ECC after read back */
};
/* These map to the positions used by the FCM hardware ECC generator */
@@ -436,7 +435,6 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
/* PAGEPROG reuses all of the setup from SEQIN and adds the length */
case NAND_CMD_PAGEPROG: {
- int full_page;
vdbg("fsl_elbc_cmdfunc: NAND_CMD_PAGEPROG "
"writing %d bytes.\n", ctrl->index);
@@ -445,34 +443,13 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
* write so the HW generates the ECC.
*/
if (ctrl->oob || ctrl->column != 0 ||
- ctrl->index != mtd->writesize + mtd->oobsize) {
+ ctrl->index != mtd->writesize + mtd->oobsize)
out_be32(&lbc->fbcr, ctrl->index);
- full_page = 0;
- } else {
+ else
out_be32(&lbc->fbcr, 0);
- full_page = 1;
- }
fsl_elbc_run_command(mtd);
- /* Read back the page in order to fill in the ECC for the
- * caller. Is this really needed?
- */
- if (full_page && ctrl->oob_poi) {
- out_be32(&lbc->fbcr, 3);
- set_addr(mtd, 6, page_addr, 1);
-
- ctrl->read_bytes = mtd->writesize + 9;
-
- fsl_elbc_do_read(chip, 1);
- fsl_elbc_run_command(mtd);
-
- memcpy_fromio(ctrl->oob_poi + 6,
- &ctrl->addr[ctrl->index], 3);
- ctrl->index += 3;
- }
-
- ctrl->oob_poi = NULL;
return;
}
@@ -680,13 +657,8 @@ static void fsl_elbc_write_page(struct mtd_info *mtd,
struct nand_chip *chip,
const uint8_t *buf)
{
- struct fsl_elbc_mtd *priv = chip->priv;
- struct fsl_elbc_ctrl *ctrl = priv->ctrl;
-
fsl_elbc_write_buf(mtd, buf, mtd->writesize);
fsl_elbc_write_buf(mtd, chip->oob_poi, mtd->oobsize);
-
- ctrl->oob_poi = chip->oob_poi;
}
static struct fsl_elbc_ctrl *elbc_ctrl;
diff --git a/drivers/mtd/nand/fsl_upm.c b/drivers/mtd/nand/fsl_upm.c
index c33e278..31c174b 100644
--- a/drivers/mtd/nand/fsl_upm.c
+++ b/drivers/mtd/nand/fsl_upm.c
@@ -124,14 +124,14 @@ static void fun_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
fun_wait(fun);
}
-static u8 nand_read_byte(struct mtd_info *mtd)
+static u8 upm_nand_read_byte(struct mtd_info *mtd)
{
struct nand_chip *chip = mtd->priv;
return in_8(chip->IO_ADDR_R);
}
-static void nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
+static void upm_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
{
int i;
struct nand_chip *chip = mtd->priv;
@@ -147,7 +147,7 @@ static void nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
fun_wait(fun);
}
-static void nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
+static void upm_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
{
int i;
struct nand_chip *chip = mtd->priv;
@@ -156,7 +156,7 @@ static void nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
buf[i] = in_8(chip->IO_ADDR_R);
}
-static int nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
+static int upm_nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
{
int i;
struct nand_chip *chip = mtd->priv;
@@ -191,10 +191,10 @@ int fsl_upm_nand_init(struct nand_chip *chip, struct fsl_upm_nand *fun)
#if CONFIG_SYS_NAND_MAX_CHIPS > 1
chip->select_chip = fun_select_chip;
#endif
- chip->read_byte = nand_read_byte;
- chip->read_buf = nand_read_buf;
- chip->write_buf = nand_write_buf;
- chip->verify_buf = nand_verify_buf;
+ chip->read_byte = upm_nand_read_byte;
+ chip->read_buf = upm_nand_read_buf;
+ chip->write_buf = upm_nand_write_buf;
+ chip->verify_buf = upm_nand_verify_buf;
if (fun->dev_ready)
chip->dev_ready = nand_dev_ready;
diff --git a/drivers/mtd/nand/kirkwood_nand.c b/drivers/mtd/nand/kirkwood_nand.c
index 376378e..bdab5aa 100644
--- a/drivers/mtd/nand/kirkwood_nand.c
+++ b/drivers/mtd/nand/kirkwood_nand.c
@@ -76,7 +76,7 @@ int board_nand_init(struct nand_chip *nand)
nand->options = NAND_COPYBACK | NAND_CACHEPRG | NAND_NO_PADDING;
nand->ecc.mode = NAND_ECC_SOFT;
nand->cmd_ctrl = kw_nand_hwcontrol;
- nand->chip_delay = 30;
+ nand->chip_delay = 40;
nand->select_chip = kw_nand_select_chip;
return 0;
}
diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c
index 2a8dd7e..35e89a0 100644
--- a/drivers/mtd/nand/mxc_nand.c
+++ b/drivers/mtd/nand/mxc_nand.c
@@ -350,7 +350,7 @@ static void send_addr(struct mxc_nand_host *host, uint16_t addr)
}
/*
- * This function requests the NANDFC to initate the transfer
+ * This function requests the NANDFC to initiate the transfer
* of data currently in the NANDFC RAM buffer to the NAND device.
*/
static void send_prog_page(struct mxc_nand_host *host, uint8_t buf_id,
@@ -394,7 +394,7 @@ static void send_prog_page(struct mxc_nand_host *host, uint8_t buf_id,
}
/*
- * Requests NANDFC to initated the transfer of data from the
+ * Requests NANDFC to initiate the transfer of data from the
* NAND device into in the NANDFC ram buffer.
*/
static void send_read_page(struct mxc_nand_host *host, uint8_t buf_id,
@@ -637,7 +637,7 @@ static int mxc_nand_read_page_syndrome(struct mtd_info *mtd,
MTDDEBUG(MTD_DEBUG_LEVEL1, "Reading page %u to buf %p oob %p\n",
host->page_addr, buf, oob);
- /* first read out the data area and the available portion of OOB */
+ /* first read the data area and the available portion of OOB */
for (n = 0; eccsteps; n++, eccsteps--, p += eccsize) {
int stat;
@@ -1179,7 +1179,7 @@ void mxc_nand_command(struct mtd_info *mtd, unsigned command,
/*
* before sending SEQIN command for partial write,
* we need read one page out. FSL NFC does not support
- * partial write. It alway send out 512+ecc+512+ecc ...
+ * partial write. It always sends out 512+ecc+512+ecc
* for large page nand flash. But for small page nand
* flash, it does support SPARE ONLY operation.
*/
@@ -1209,7 +1209,7 @@ void mxc_nand_command(struct mtd_info *mtd, unsigned command,
send_prog_page(host, 0, host->spare_only);
if (host->pagesize_2k && !is_mxc_nfc_11()) {
- /* data in 4 areas datas */
+ /* data in 4 areas */
send_prog_page(host, 1, host->spare_only);
send_prog_page(host, 2, host->spare_only);
send_prog_page(host, 3, host->spare_only);
@@ -1225,10 +1225,9 @@ void mxc_nand_command(struct mtd_info *mtd, unsigned command,
if (column != -1) {
/*
* MXC NANDFC can only perform full page+spare or
- * spare-only read/write. When the upper layers
- * layers perform a read/write buf operation,
- * we will used the saved column adress to index into
- * the full page.
+ * spare-only read/write. When the upper layers perform
+ * a read/write buffer operation, we will use the saved
+ * column address to index into the full page.
*/
send_addr(host, 0);
if (host->pagesize_2k)
@@ -1372,12 +1371,23 @@ int board_nand_init(struct nand_chip *this)
/* Blocks to be unlocked */
writew(0x0, &host->regs->nfc_unlockstart_blkaddr);
- writew(0x4000, &host->regs->nfc_unlockend_blkaddr);
+ /* Originally (Freescale LTIB 2.6.21) 0x4000 was written to the
+ * unlockend_blkaddr, but the magic 0x4000 does not always work
+ * when writing more than some 32 megabytes (on 2k page nands)
+ * However 0xFFFF doesn't seem to have this kind
+ * of limitation (tried it back and forth several times).
+ * The linux kernel driver sets this to 0xFFFF for the v2 controller
+ * only, but probably this was not tested there for v1.
+ * The very same limitation seems to apply to this kernel driver.
+ * This might be NAND chip specific and the i.MX31 datasheet is
+ * extremely vague about the semantics of this register.
+ */
+ writew(0xFFFF, &host->regs->nfc_unlockend_blkaddr);
/* Unlock Block Command for given address range */
writew(0x4, &host->regs->nfc_wrprot);
- /* NAND bus width determines access funtions used by upper layer */
+ /* NAND bus width determines access functions used by upper layer */
if (is_16bit_nand())
this->options |= NAND_BUSWIDTH_16;
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index e7dfcb1..6aac6a2 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -2224,7 +2224,7 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
/*
* heck if we have a bad block, we do not erase bad blocks !
*/
- if (nand_block_checkbad(mtd, ((loff_t) page) <<
+ if (!instr->scrub && nand_block_checkbad(mtd, ((loff_t) page) <<
chip->page_shift, 0, allowbbt)) {
printk(KERN_WARNING "nand_erase: attempt to erase a "
"bad block at page 0x%08x\n", page);
diff --git a/drivers/mtd/nand/nand_util.c b/drivers/mtd/nand/nand_util.c
index 81bf366..60c778e 100644
--- a/drivers/mtd/nand/nand_util.c
+++ b/drivers/mtd/nand/nand_util.c
@@ -57,12 +57,6 @@ typedef struct mtd_info mtd_info_t;
#define cpu_to_je16(x) (x)
#define cpu_to_je32(x) (x)
-/*****************************************************************************/
-static int nand_block_bad_scrub(struct mtd_info *mtd, loff_t ofs, int getchip)
-{
- return 0;
-}
-
/**
* nand_erase_opts: - erase NAND flash with support for various options
* (jffs2 formating)
@@ -82,7 +76,6 @@ int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts)
int bbtest = 1;
int result;
int percent_complete = -1;
- int (*nand_block_bad_old)(struct mtd_info *, loff_t, int) = NULL;
const char *mtd_device = meminfo->name;
struct mtd_oob_ops oob_opts;
struct nand_chip *chip = meminfo->priv;
@@ -110,17 +103,15 @@ int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts)
* and disable bad block table while erasing.
*/
if (opts->scrub) {
- struct nand_chip *priv_nand = meminfo->priv;
-
- nand_block_bad_old = priv_nand->block_bad;
- priv_nand->block_bad = nand_block_bad_scrub;
- /* we don't need the bad block table anymore...
+ erase.scrub = opts->scrub;
+ /*
+ * We don't need the bad block table anymore...
* after scrub, there are no bad blocks left!
*/
- if (priv_nand->bbt) {
- kfree(priv_nand->bbt);
+ if (chip->bbt) {
+ kfree(chip->bbt);
}
- priv_nand->bbt = NULL;
+ chip->bbt = NULL;
}
for (erased_length = 0;
@@ -204,12 +195,8 @@ int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts)
if (!opts->quiet)
printf("\n");
- if (nand_block_bad_old) {
- struct nand_chip *priv_nand = meminfo->priv;
-
- priv_nand->block_bad = nand_block_bad_old;
- priv_nand->scan_bbt(meminfo);
- }
+ if (opts->scrub)
+ chip->scan_bbt(meminfo);
return 0;
}