mtd: mxc_nand: set NFC registers after reset

This patch allows the mxc_nand driver to reset the NAND
flash controller.  NFC registers are (re-)set after
completion of the reset, as a reset will have reverted
the NFC registers to their default values.

Signed-off-by: Ivo Clarysse <ivo.clarysse@gmail.com>
Acked-by: Sascha Hauer <s.hauer@pengutronix.de>
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
This commit is contained in:
Ivo Clarysse 2010-04-08 16:14:44 +02:00 committed by David Woodhouse
parent 9d5da3a9b8
commit d484018056

View File

@ -542,6 +542,41 @@ static void mxc_do_addr_cycle(struct mtd_info *mtd, int column, int page_addr)
}
}
static void preset(struct mtd_info *mtd)
{
struct nand_chip *nand_chip = mtd->priv;
struct mxc_nand_host *host = nand_chip->priv;
uint16_t tmp;
/* disable interrupt, disable spare enable */
tmp = readw(host->regs + NFC_CONFIG1);
tmp |= NFC_INT_MSK;
tmp &= ~NFC_SP_EN;
if (nand_chip->ecc.mode == NAND_ECC_HW) {
tmp |= NFC_ECC_EN;
} else {
tmp &= ~NFC_ECC_EN;
}
writew(tmp, host->regs + NFC_CONFIG1);
/* preset operation */
/* Unlock the internal RAM Buffer */
writew(0x2, host->regs + NFC_CONFIG);
/* Blocks to be unlocked */
if (nfc_is_v21()) {
writew(0x0, host->regs + NFC_V21_UNLOCKSTART_BLKADDR);
writew(0xffff, host->regs + NFC_V21_UNLOCKEND_BLKADDR);
} else if (nfc_is_v1()) {
writew(0x0, host->regs + NFC_V1_UNLOCKSTART_BLKADDR);
writew(0x4000, host->regs + NFC_V1_UNLOCKEND_BLKADDR);
} else
BUG();
/* Unlock Block Command for given address range */
writew(0x4, host->regs + NFC_WRPROT);
}
/* Used by the upper layer to write command to NAND Flash for
* different operations to be carried out on NAND Flash */
static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
@ -559,6 +594,10 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
/* Command pre-processing step */
switch (command) {
case NAND_CMD_RESET:
send_cmd(host, command, false);
preset(mtd);
break;
case NAND_CMD_STATUS:
host->buf_start = 0;
@ -680,7 +719,6 @@ static int __init mxcnd_probe(struct platform_device *pdev)
struct mxc_nand_platform_data *pdata = pdev->dev.platform_data;
struct mxc_nand_host *host;
struct resource *res;
uint16_t tmp;
int err = 0, nr_parts = 0;
struct nand_ecclayout *oob_smallpage, *oob_largepage;
@ -744,51 +782,17 @@ static int __init mxcnd_probe(struct platform_device *pdev)
host->spare_len = 64;
oob_smallpage = &nandv2_hw_eccoob_smallpage;
oob_largepage = &nandv2_hw_eccoob_largepage;
this->ecc.bytes = 9;
} else if (nfc_is_v1()) {
host->regs = host->base;
host->spare0 = host->base + 0x800;
host->spare_len = 16;
oob_smallpage = &nandv1_hw_eccoob_smallpage;
oob_largepage = &nandv1_hw_eccoob_largepage;
} else
BUG();
/* disable interrupt and spare enable */
tmp = readw(host->regs + NFC_CONFIG1);
tmp |= NFC_INT_MSK;
tmp &= ~NFC_SP_EN;
writew(tmp, host->regs + NFC_CONFIG1);
init_waitqueue_head(&host->irq_waitq);
host->irq = platform_get_irq(pdev, 0);
err = request_irq(host->irq, mxc_nfc_irq, 0, DRIVER_NAME, host);
if (err)
goto eirq;
/* Reset NAND */
this->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
/* preset operation */
/* Unlock the internal RAM Buffer */
writew(0x2, host->regs + NFC_CONFIG);
/* Blocks to be unlocked */
if (nfc_is_v21()) {
writew(0x0, host->regs + NFC_V21_UNLOCKSTART_BLKADDR);
writew(0xffff, host->regs + NFC_V21_UNLOCKEND_BLKADDR);
this->ecc.bytes = 9;
} else if (nfc_is_v1()) {
writew(0x0, host->regs + NFC_V1_UNLOCKSTART_BLKADDR);
writew(0x4000, host->regs + NFC_V1_UNLOCKEND_BLKADDR);
this->ecc.bytes = 3;
} else
BUG();
/* Unlock Block Command for given address range */
writew(0x4, host->regs + NFC_WRPROT);
this->ecc.size = 512;
this->ecc.layout = oob_smallpage;
@ -797,14 +801,8 @@ static int __init mxcnd_probe(struct platform_device *pdev)
this->ecc.hwctl = mxc_nand_enable_hwecc;
this->ecc.correct = mxc_nand_correct_data;
this->ecc.mode = NAND_ECC_HW;
tmp = readw(host->regs + NFC_CONFIG1);
tmp |= NFC_ECC_EN;
writew(tmp, host->regs + NFC_CONFIG1);
} else {
this->ecc.mode = NAND_ECC_SOFT;
tmp = readw(host->regs + NFC_CONFIG1);
tmp &= ~NFC_ECC_EN;
writew(tmp, host->regs + NFC_CONFIG1);
}
/* NAND bus width determines access funtions used by upper layer */
@ -818,6 +816,14 @@ static int __init mxcnd_probe(struct platform_device *pdev)
this->options |= NAND_USE_FLASH_BBT;
}
init_waitqueue_head(&host->irq_waitq);
host->irq = platform_get_irq(pdev, 0);
err = request_irq(host->irq, mxc_nfc_irq, 0, DRIVER_NAME, host);
if (err)
goto eirq;
/* first scan to find the device and get the page size */
if (nand_scan_ident(mtd, 1, NULL)) {
err = -ENXIO;