aboutsummaryrefslogtreecommitdiff
path: root/drivers/mtd/nand
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd/nand')
-rw-r--r--drivers/mtd/nand/alauda.c11
-rw-r--r--drivers/mtd/nand/atmel_nand.c4
-rw-r--r--drivers/mtd/nand/davinci_nand.c2
-rw-r--r--drivers/mtd/nand/excite_nandflash.c2
-rw-r--r--drivers/mtd/nand/fsl_elbc_nand.c86
-rw-r--r--drivers/mtd/nand/fsl_upm.c2
-rw-r--r--drivers/mtd/nand/mxc_nand.c2
-rw-r--r--drivers/mtd/nand/nand_base.c141
-rw-r--r--drivers/mtd/nand/nand_ecc.c25
-rw-r--r--drivers/mtd/nand/pxa3xx_nand.c4
-rw-r--r--drivers/mtd/nand/s3c2410.c2
-rw-r--r--drivers/mtd/nand/txx9ndfmc.c3
12 files changed, 204 insertions, 80 deletions
diff --git a/drivers/mtd/nand/alauda.c b/drivers/mtd/nand/alauda.c
index 6d9649159a18..2d6773281fd9 100644
--- a/drivers/mtd/nand/alauda.c
+++ b/drivers/mtd/nand/alauda.c
@@ -372,15 +372,6 @@ static int alauda_read_oob(struct mtd_info *mtd, loff_t from, void *oob)
return __alauda_read_page(mtd, from, ignore_buf, oob);
}
-static int popcount8(u8 c)
-{
- int ret = 0;
-
- for ( ; c; c>>=1)
- ret += c & 1;
- return ret;
-}
-
static int alauda_isbad(struct mtd_info *mtd, loff_t ofs)
{
u8 oob[16];
@@ -391,7 +382,7 @@ static int alauda_isbad(struct mtd_info *mtd, loff_t ofs)
return err;
/* A block is marked bad if two or more bits are zero */
- return popcount8(oob[5]) >= 7 ? 0 : 1;
+ return hweight8(oob[5]) >= 7 ? 0 : 1;
}
static int alauda_bounce_read(struct mtd_info *mtd, loff_t from, size_t len,
diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
index 4f62d207b87b..524e6c9e0672 100644
--- a/drivers/mtd/nand/atmel_nand.c
+++ b/drivers/mtd/nand/atmel_nand.c
@@ -463,7 +463,7 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
if (host->board->det_pin) {
if (gpio_get_value(host->board->det_pin)) {
printk(KERN_INFO "No SmartMedia card inserted.\n");
- res = ENXIO;
+ res = -ENXIO;
goto err_no_card;
}
}
@@ -534,7 +534,7 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
if ((!partitions) || (num_partitions == 0)) {
printk(KERN_ERR "atmel_nand: No partitions defined, or unsupported device.\n");
- res = ENXIO;
+ res = -ENXIO;
goto err_no_partitions;
}
diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c
index 68cc9247fdb0..fe3eba87de40 100644
--- a/drivers/mtd/nand/davinci_nand.c
+++ b/drivers/mtd/nand/davinci_nand.c
@@ -591,6 +591,8 @@ static int __init nand_davinci_probe(struct platform_device *pdev)
/* options such as NAND_USE_FLASH_BBT or 16-bit widths */
info->chip.options = pdata->options;
+ info->chip.bbt_td = pdata->bbt_td;
+ info->chip.bbt_md = pdata->bbt_md;
info->ioaddr = (uint32_t __force) vaddr;
diff --git a/drivers/mtd/nand/excite_nandflash.c b/drivers/mtd/nand/excite_nandflash.c
index 72446fb48d4b..af6a6a5399e1 100644
--- a/drivers/mtd/nand/excite_nandflash.c
+++ b/drivers/mtd/nand/excite_nandflash.c
@@ -128,7 +128,7 @@ static int excite_nand_devready(struct mtd_info *mtd)
* The binding to the mtd and all allocated
* resources are released.
*/
-static int __exit excite_nand_remove(struct platform_device *dev)
+static int __devexit excite_nand_remove(struct platform_device *dev)
{
struct excite_nand_drvdata * const this = platform_get_drvdata(dev);
diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c
index ddd37d2554ed..ae30fb6eed97 100644
--- a/drivers/mtd/nand/fsl_elbc_nand.c
+++ b/drivers/mtd/nand/fsl_elbc_nand.c
@@ -237,12 +237,15 @@ static int fsl_elbc_run_command(struct mtd_info *mtd)
ctrl->use_mdr = 0;
- dev_vdbg(ctrl->dev,
- "fsl_elbc_run_command: stat=%08x mdr=%08x fmr=%08x\n",
- ctrl->status, ctrl->mdr, in_be32(&lbc->fmr));
+ if (ctrl->status != LTESR_CC) {
+ dev_info(ctrl->dev,
+ "command failed: fir %x fcr %x status %x mdr %x\n",
+ in_be32(&lbc->fir), in_be32(&lbc->fcr),
+ ctrl->status, ctrl->mdr);
+ return -EIO;
+ }
- /* returns 0 on success otherwise non-zero) */
- return ctrl->status == LTESR_CC ? 0 : -EIO;
+ return 0;
}
static void fsl_elbc_do_read(struct nand_chip *chip, int oob)
@@ -253,17 +256,17 @@ static void fsl_elbc_do_read(struct nand_chip *chip, int oob)
if (priv->page_size) {
out_be32(&lbc->fir,
- (FIR_OP_CW0 << FIR_OP0_SHIFT) |
+ (FIR_OP_CM0 << FIR_OP0_SHIFT) |
(FIR_OP_CA << FIR_OP1_SHIFT) |
(FIR_OP_PA << FIR_OP2_SHIFT) |
- (FIR_OP_CW1 << FIR_OP3_SHIFT) |
+ (FIR_OP_CM1 << FIR_OP3_SHIFT) |
(FIR_OP_RBW << FIR_OP4_SHIFT));
out_be32(&lbc->fcr, (NAND_CMD_READ0 << FCR_CMD0_SHIFT) |
(NAND_CMD_READSTART << FCR_CMD1_SHIFT));
} else {
out_be32(&lbc->fir,
- (FIR_OP_CW0 << FIR_OP0_SHIFT) |
+ (FIR_OP_CM0 << FIR_OP0_SHIFT) |
(FIR_OP_CA << FIR_OP1_SHIFT) |
(FIR_OP_PA << FIR_OP2_SHIFT) |
(FIR_OP_RBW << FIR_OP3_SHIFT));
@@ -332,7 +335,7 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
case NAND_CMD_READID:
dev_vdbg(ctrl->dev, "fsl_elbc_cmdfunc: NAND_CMD_READID.\n");
- out_be32(&lbc->fir, (FIR_OP_CW0 << FIR_OP0_SHIFT) |
+ out_be32(&lbc->fir, (FIR_OP_CM0 << FIR_OP0_SHIFT) |
(FIR_OP_UA << FIR_OP1_SHIFT) |
(FIR_OP_RBW << FIR_OP2_SHIFT));
out_be32(&lbc->fcr, NAND_CMD_READID << FCR_CMD0_SHIFT);
@@ -359,16 +362,20 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
dev_vdbg(ctrl->dev, "fsl_elbc_cmdfunc: NAND_CMD_ERASE2.\n");
out_be32(&lbc->fir,
- (FIR_OP_CW0 << FIR_OP0_SHIFT) |
+ (FIR_OP_CM0 << FIR_OP0_SHIFT) |
(FIR_OP_PA << FIR_OP1_SHIFT) |
- (FIR_OP_CM1 << FIR_OP2_SHIFT));
+ (FIR_OP_CM2 << FIR_OP2_SHIFT) |
+ (FIR_OP_CW1 << FIR_OP3_SHIFT) |
+ (FIR_OP_RS << FIR_OP4_SHIFT));
out_be32(&lbc->fcr,
(NAND_CMD_ERASE1 << FCR_CMD0_SHIFT) |
- (NAND_CMD_ERASE2 << FCR_CMD1_SHIFT));
+ (NAND_CMD_STATUS << FCR_CMD1_SHIFT) |
+ (NAND_CMD_ERASE2 << FCR_CMD2_SHIFT));
out_be32(&lbc->fbcr, 0);
ctrl->read_bytes = 0;
+ ctrl->use_mdr = 1;
fsl_elbc_run_command(mtd);
return;
@@ -383,40 +390,41 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
ctrl->column = column;
ctrl->oob = 0;
+ ctrl->use_mdr = 1;
- if (priv->page_size) {
- fcr = (NAND_CMD_SEQIN << FCR_CMD0_SHIFT) |
- (NAND_CMD_PAGEPROG << FCR_CMD1_SHIFT);
+ fcr = (NAND_CMD_STATUS << FCR_CMD1_SHIFT) |
+ (NAND_CMD_SEQIN << FCR_CMD2_SHIFT) |
+ (NAND_CMD_PAGEPROG << FCR_CMD3_SHIFT);
+ if (priv->page_size) {
out_be32(&lbc->fir,
- (FIR_OP_CW0 << FIR_OP0_SHIFT) |
+ (FIR_OP_CM2 << FIR_OP0_SHIFT) |
(FIR_OP_CA << FIR_OP1_SHIFT) |
(FIR_OP_PA << FIR_OP2_SHIFT) |
(FIR_OP_WB << FIR_OP3_SHIFT) |
- (FIR_OP_CW1 << FIR_OP4_SHIFT));
+ (FIR_OP_CM3 << FIR_OP4_SHIFT) |
+ (FIR_OP_CW1 << FIR_OP5_SHIFT) |
+ (FIR_OP_RS << FIR_OP6_SHIFT));
} else {
- fcr = (NAND_CMD_PAGEPROG << FCR_CMD1_SHIFT) |
- (NAND_CMD_SEQIN << FCR_CMD2_SHIFT);
-
out_be32(&lbc->fir,
- (FIR_OP_CW0 << FIR_OP0_SHIFT) |
+ (FIR_OP_CM0 << FIR_OP0_SHIFT) |
(FIR_OP_CM2 << FIR_OP1_SHIFT) |
(FIR_OP_CA << FIR_OP2_SHIFT) |
(FIR_OP_PA << FIR_OP3_SHIFT) |
(FIR_OP_WB << FIR_OP4_SHIFT) |
- (FIR_OP_CW1 << FIR_OP5_SHIFT));
+ (FIR_OP_CM3 << FIR_OP5_SHIFT) |
+ (FIR_OP_CW1 << FIR_OP6_SHIFT) |
+ (FIR_OP_RS << FIR_OP7_SHIFT));
if (column >= mtd->writesize) {
/* OOB area --> READOOB */
column -= mtd->writesize;
fcr |= NAND_CMD_READOOB << FCR_CMD0_SHIFT;
ctrl->oob = 1;
- } else if (column < 256) {
+ } else {
+ WARN_ON(column != 0);
/* First 256 bytes --> READ0 */
fcr |= NAND_CMD_READ0 << FCR_CMD0_SHIFT;
- } else {
- /* Second 256 bytes --> READ1 */
- fcr |= NAND_CMD_READ1 << FCR_CMD0_SHIFT;
}
}
@@ -628,22 +636,6 @@ static int fsl_elbc_wait(struct mtd_info *mtd, struct nand_chip *chip)
{
struct fsl_elbc_mtd *priv = chip->priv;
struct fsl_elbc_ctrl *ctrl = priv->ctrl;
- struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
-
- if (ctrl->status != LTESR_CC)
- return NAND_STATUS_FAIL;
-
- /* Use READ_STATUS command, but wait for the device to be ready */
- ctrl->use_mdr = 0;
- out_be32(&lbc->fir,
- (FIR_OP_CW0 << FIR_OP0_SHIFT) |
- (FIR_OP_RBW << FIR_OP1_SHIFT));
- out_be32(&lbc->fcr, NAND_CMD_STATUS << FCR_CMD0_SHIFT);
- out_be32(&lbc->fbcr, 1);
- set_addr(mtd, 0, 0, 0);
- ctrl->read_bytes = 1;
-
- fsl_elbc_run_command(mtd);
if (ctrl->status != LTESR_CC)
return NAND_STATUS_FAIL;
@@ -651,8 +643,7 @@ static int fsl_elbc_wait(struct mtd_info *mtd, struct nand_chip *chip)
/* The chip always seems to report that it is
* write-protected, even when it is not.
*/
- setbits8(ctrl->addr, NAND_STATUS_WP);
- return fsl_elbc_read_byte(mtd);
+ return (ctrl->mdr & 0xff) | NAND_STATUS_WP;
}
static int fsl_elbc_chip_init_tail(struct mtd_info *mtd)
@@ -946,6 +937,13 @@ static int __devinit fsl_elbc_ctrl_init(struct fsl_elbc_ctrl *ctrl)
{
struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
+ /*
+ * NAND transactions can tie up the bus for a long time, so set the
+ * bus timeout to max by clearing LBCR[BMT] (highest base counter
+ * value) and setting LBCR[BMTPS] to the highest prescaler value.
+ */
+ clrsetbits_be32(&lbc->lbcr, LBCR_BMT, 15);
+
/* clear event registers */
setbits32(&lbc->ltesr, LTESR_NAND_MASK);
out_be32(&lbc->lteatr, 0);
diff --git a/drivers/mtd/nand/fsl_upm.c b/drivers/mtd/nand/fsl_upm.c
index d120cd8d7267..071a60cb4204 100644
--- a/drivers/mtd/nand/fsl_upm.c
+++ b/drivers/mtd/nand/fsl_upm.c
@@ -112,7 +112,7 @@ static void fun_select_chip(struct mtd_info *mtd, int mchip_nr)
if (mchip_nr == -1) {
chip->cmd_ctrl(mtd, NAND_CMD_NONE, 0 | NAND_CTRL_CHANGE);
- } else if (mchip_nr >= 0) {
+ } else if (mchip_nr >= 0 && mchip_nr < NAND_MAX_CHIPS) {
fun->mchip_number = mchip_nr;
chip->IO_ADDR_R = fun->io_base + fun->mchip_offsets[mchip_nr];
chip->IO_ADDR_W = chip->IO_ADDR_R;
diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c
index 53e94121c26f..f7366e99fe1e 100644
--- a/drivers/mtd/nand/mxc_nand.c
+++ b/drivers/mtd/nand/mxc_nand.c
@@ -922,7 +922,7 @@ static struct platform_driver mxcnd_driver = {
.driver = {
.name = DRIVER_NAME,
},
- .remove = __exit_p(mxcnd_remove),
+ .remove = __devexit_p(mxcnd_remove),
.suspend = mxcnd_suspend,
.resume = mxcnd_resume,
};
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 2957cc70da3d..8f2958fe2148 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -428,6 +428,28 @@ static int nand_block_checkbad(struct mtd_info *mtd, loff_t ofs, int getchip,
return nand_isbad_bbt(mtd, ofs, allowbbt);
}
+/**
+ * panic_nand_wait_ready - [GENERIC] Wait for the ready pin after commands.
+ * @mtd: MTD device structure
+ * @timeo: Timeout
+ *
+ * Helper function for nand_wait_ready used when needing to wait in interrupt
+ * context.
+ */
+static void panic_nand_wait_ready(struct mtd_info *mtd, unsigned long timeo)
+{
+ struct nand_chip *chip = mtd->priv;
+ int i;
+
+ /* Wait for the device to get ready */
+ for (i = 0; i < timeo; i++) {
+ if (chip->dev_ready(mtd))
+ break;
+ touch_softlockup_watchdog();
+ mdelay(1);
+ }
+}
+
/*
* Wait for the ready pin, after a command
* The timeout is catched later.
@@ -437,6 +459,10 @@ void nand_wait_ready(struct mtd_info *mtd)
struct nand_chip *chip = mtd->priv;
unsigned long timeo = jiffies + 2;
+ /* 400ms timeout */
+ if (in_interrupt() || oops_in_progress)
+ return panic_nand_wait_ready(mtd, 400);
+
led_trigger_event(nand_led_trigger, LED_FULL);
/* wait until command is processed or timeout occures */
do {
@@ -672,6 +698,22 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command,
}
/**
+ * panic_nand_get_device - [GENERIC] Get chip for selected access
+ * @chip: the nand chip descriptor
+ * @mtd: MTD device structure
+ * @new_state: the state which is requested
+ *
+ * Used when in panic, no locks are taken.
+ */
+static void panic_nand_get_device(struct nand_chip *chip,
+ struct mtd_info *mtd, int new_state)
+{
+ /* Hardware controller shared among independend devices */
+ chip->controller->active = chip;
+ chip->state = new_state;
+}
+
+/**
* nand_get_device - [GENERIC] Get chip for selected access
* @chip: the nand chip descriptor
* @mtd: MTD device structure
@@ -698,8 +740,14 @@ nand_get_device(struct nand_chip *chip, struct mtd_info *mtd, int new_state)
return 0;
}
if (new_state == FL_PM_SUSPENDED) {
- spin_unlock(lock);
- return (chip->state == FL_PM_SUSPENDED) ? 0 : -EAGAIN;
+ if (chip->controller->active->state == FL_PM_SUSPENDED) {
+ chip->state = FL_PM_SUSPENDED;
+ spin_unlock(lock);
+ return 0;
+ } else {
+ spin_unlock(lock);
+ return -EAGAIN;
+ }
}
set_current_state(TASK_UNINTERRUPTIBLE);
add_wait_queue(wq, &wait);
@@ -710,6 +758,32 @@ nand_get_device(struct nand_chip *chip, struct mtd_info *mtd, int new_state)
}
/**
+ * panic_nand_wait - [GENERIC] wait until the command is done
+ * @mtd: MTD device structure
+ * @chip: NAND chip structure
+ * @timeo: Timeout
+ *
+ * Wait for command done. This is a helper function for nand_wait used when
+ * we are in interrupt context. May happen when in panic and trying to write
+ * an oops trough mtdoops.
+ */
+static void panic_nand_wait(struct mtd_info *mtd, struct nand_chip *chip,
+ unsigned long timeo)
+{
+ int i;
+ for (i = 0; i < timeo; i++) {
+ if (chip->dev_ready) {
+ if (chip->dev_ready(mtd))
+ break;
+ } else {
+ if (chip->read_byte(mtd) & NAND_STATUS_READY)
+ break;
+ }
+ mdelay(1);
+ }
+}
+
+/**
* nand_wait - [DEFAULT] wait until the command is done
* @mtd: MTD device structure
* @chip: NAND chip structure
@@ -740,15 +814,19 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip)
else
chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1);
- while (time_before(jiffies, timeo)) {
- if (chip->dev_ready) {
- if (chip->dev_ready(mtd))
- break;
- } else {
- if (chip->read_byte(mtd) & NAND_STATUS_READY)
- break;
+ if (in_interrupt() || oops_in_progress)
+ panic_nand_wait(mtd, chip, timeo);
+ else {
+ while (time_before(jiffies, timeo)) {
+ if (chip->dev_ready) {
+ if (chip->dev_ready(mtd))
+ break;
+ } else {
+ if (chip->read_byte(mtd) & NAND_STATUS_READY)
+ break;
+ }
+ cond_resched();
}
- cond_resched();
}
led_trigger_event(nand_led_trigger, LED_OFF);
@@ -1949,6 +2027,45 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
}
/**
+ * panic_nand_write - [MTD Interface] NAND write with ECC
+ * @mtd: MTD device structure
+ * @to: offset to write to
+ * @len: number of bytes to write
+ * @retlen: pointer to variable to store the number of written bytes
+ * @buf: the data to write
+ *
+ * NAND write with ECC. Used when performing writes in interrupt context, this
+ * may for example be called by mtdoops when writing an oops while in panic.
+ */
+static int panic_nand_write(struct mtd_info *mtd, loff_t to, size_t len,
+ size_t *retlen, const uint8_t *buf)
+{
+ struct nand_chip *chip = mtd->priv;
+ int ret;
+
+ /* Do not allow reads past end of device */
+ if ((to + len) > mtd->size)
+ return -EINVAL;
+ if (!len)
+ return 0;
+
+ /* Wait for the device to get ready. */
+ panic_nand_wait(mtd, chip, 400);
+
+ /* Grab the device. */
+ panic_nand_get_device(chip, mtd, FL_WRITING);
+
+ chip->ops.len = len;
+ chip->ops.datbuf = (uint8_t *)buf;
+ chip->ops.oobbuf = NULL;
+
+ ret = nand_do_write_ops(mtd, to, &chip->ops);
+
+ *retlen = chip->ops.retlen;
+ return ret;
+}
+
+/**
* nand_write - [MTD Interface] NAND write with ECC
* @mtd: MTD device structure
* @to: offset to write to
@@ -2645,7 +2762,8 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips)
type = nand_get_flash_type(mtd, chip, busw, &nand_maf_id);
if (IS_ERR(type)) {
- printk(KERN_WARNING "No NAND device found!!!\n");
+ if (!(chip->options & NAND_SCAN_SILENT_NODEV))
+ printk(KERN_WARNING "No NAND device found.\n");
chip->select_chip(mtd, -1);
return PTR_ERR(type);
}
@@ -2877,6 +2995,7 @@ int nand_scan_tail(struct mtd_info *mtd)
mtd->unpoint = NULL;
mtd->read = nand_read;
mtd->write = nand_write;
+ mtd->panic_write = panic_nand_write;
mtd->read_oob = nand_read_oob;
mtd->write_oob = nand_write_oob;
mtd->sync = nand_sync;
diff --git a/drivers/mtd/nand/nand_ecc.c b/drivers/mtd/nand/nand_ecc.c
index db7ae9d6a296..809fb53304ae 100644
--- a/drivers/mtd/nand/nand_ecc.c
+++ b/drivers/mtd/nand/nand_ecc.c
@@ -150,20 +150,19 @@ static const char addressbits[256] = {
};
/**
- * nand_calculate_ecc - [NAND Interface] Calculate 3-byte ECC for 256/512-byte
+ * __nand_calculate_ecc - [NAND Interface] Calculate 3-byte ECC for 256/512-byte
* block
- * @mtd: MTD block structure
* @buf: input buffer with raw data
+ * @eccsize: data bytes per ecc step (256 or 512)
* @code: output buffer with ECC
*/
-int nand_calculate_ecc(struct mtd_info *mtd, const unsigned char *buf,
+void __nand_calculate_ecc(const unsigned char *buf, unsigned int eccsize,
unsigned char *code)
{
int i;
const uint32_t *bp = (uint32_t *)buf;
/* 256 or 512 bytes/ecc */
- const uint32_t eccsize_mult =
- (((struct nand_chip *)mtd->priv)->ecc.size) >> 8;
+ const uint32_t eccsize_mult = eccsize >> 8;
uint32_t cur; /* current value in buffer */
/* rp0..rp15..rp17 are the various accumulated parities (per byte) */
uint32_t rp0, rp1, rp2, rp3, rp4, rp5, rp6, rp7;
@@ -412,6 +411,22 @@ int nand_calculate_ecc(struct mtd_info *mtd, const unsigned char *buf,
(invparity[par & 0x55] << 2) |
(invparity[rp17] << 1) |
(invparity[rp16] << 0);
+}
+EXPORT_SYMBOL(__nand_calculate_ecc);
+
+/**
+ * nand_calculate_ecc - [NAND Interface] Calculate 3-byte ECC for 256/512-byte
+ * block
+ * @mtd: MTD block structure
+ * @buf: input buffer with raw data
+ * @code: output buffer with ECC
+ */
+int nand_calculate_ecc(struct mtd_info *mtd, const unsigned char *buf,
+ unsigned char *code)
+{
+ __nand_calculate_ecc(buf,
+ ((struct nand_chip *)mtd->priv)->ecc.size, code);
+
return 0;
}
EXPORT_SYMBOL(nand_calculate_ecc);
diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index 6ea520ae2410..75aa8713abd1 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -489,7 +489,7 @@ static int handle_data_pio(struct pxa3xx_nand_info *info)
switch (info->state) {
case STATE_PIO_WRITING:
__raw_writesl(info->mmio_base + NDDB, info->data_buff,
- info->data_size << 2);
+ info->data_size >> 2);
enable_int(info, NDSR_CS0_BBD | NDSR_CS0_CMDD);
@@ -501,7 +501,7 @@ static int handle_data_pio(struct pxa3xx_nand_info *info)
break;
case STATE_PIO_READING:
__raw_readsl(info->mmio_base + NDDB, info->data_buff,
- info->data_size << 2);
+ info->data_size >> 2);
break;
default:
printk(KERN_ERR "%s: invalid state %d\n", __func__,
diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c
index 11dc7e69c4fb..6e88bd3c02f5 100644
--- a/drivers/mtd/nand/s3c2410.c
+++ b/drivers/mtd/nand/s3c2410.c
@@ -774,7 +774,7 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info,
chip->select_chip = s3c2410_nand_select_chip;
chip->chip_delay = 50;
chip->priv = nmtd;
- chip->options = 0;
+ chip->options = set->options;
chip->controller = &info->controller;
switch (info->cpu_type) {
diff --git a/drivers/mtd/nand/txx9ndfmc.c b/drivers/mtd/nand/txx9ndfmc.c
index 73af8324d0d0..863513c3b69a 100644
--- a/drivers/mtd/nand/txx9ndfmc.c
+++ b/drivers/mtd/nand/txx9ndfmc.c
@@ -429,11 +429,10 @@ static int __exit txx9ndfmc_remove(struct platform_device *dev)
chip = mtd->priv;
txx9_priv = chip->priv;
+ nand_release(mtd);
#ifdef CONFIG_MTD_PARTITIONS
- del_mtd_partitions(mtd);
kfree(drvdata->parts[i]);
#endif
- del_mtd_device(mtd);
kfree(txx9_priv->mtdname);
kfree(txx9_priv);
}