Commit d4840180 authored by Ivo Clarysse's avatar Ivo Clarysse Committed by David Woodhouse

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: default avatarIvo Clarysse <ivo.clarysse@gmail.com>
Acked-by: default avatarSascha Hauer <s.hauer@pengutronix.de>
Signed-off-by: default avatarDavid Woodhouse <David.Woodhouse@intel.com>
parent 9d5da3a9
...@@ -542,6 +542,41 @@ static void mxc_do_addr_cycle(struct mtd_info *mtd, int column, int page_addr) ...@@ -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 /* Used by the upper layer to write command to NAND Flash for
* different operations to be carried out on NAND Flash */ * different operations to be carried out on NAND Flash */
static void mxc_nand_command(struct mtd_info *mtd, unsigned command, 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, ...@@ -559,6 +594,10 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
/* Command pre-processing step */ /* Command pre-processing step */
switch (command) { switch (command) {
case NAND_CMD_RESET:
send_cmd(host, command, false);
preset(mtd);
break;
case NAND_CMD_STATUS: case NAND_CMD_STATUS:
host->buf_start = 0; host->buf_start = 0;
...@@ -680,7 +719,6 @@ static int __init mxcnd_probe(struct platform_device *pdev) ...@@ -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_platform_data *pdata = pdev->dev.platform_data;
struct mxc_nand_host *host; struct mxc_nand_host *host;
struct resource *res; struct resource *res;
uint16_t tmp;
int err = 0, nr_parts = 0; int err = 0, nr_parts = 0;
struct nand_ecclayout *oob_smallpage, *oob_largepage; struct nand_ecclayout *oob_smallpage, *oob_largepage;
...@@ -744,51 +782,17 @@ static int __init mxcnd_probe(struct platform_device *pdev) ...@@ -744,51 +782,17 @@ static int __init mxcnd_probe(struct platform_device *pdev)
host->spare_len = 64; host->spare_len = 64;
oob_smallpage = &nandv2_hw_eccoob_smallpage; oob_smallpage = &nandv2_hw_eccoob_smallpage;
oob_largepage = &nandv2_hw_eccoob_largepage; oob_largepage = &nandv2_hw_eccoob_largepage;
this->ecc.bytes = 9;
} else if (nfc_is_v1()) { } else if (nfc_is_v1()) {
host->regs = host->base; host->regs = host->base;
host->spare0 = host->base + 0x800; host->spare0 = host->base + 0x800;
host->spare_len = 16; host->spare_len = 16;
oob_smallpage = &nandv1_hw_eccoob_smallpage; oob_smallpage = &nandv1_hw_eccoob_smallpage;
oob_largepage = &nandv1_hw_eccoob_largepage; 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; this->ecc.bytes = 3;
} else } else
BUG(); BUG();
/* Unlock Block Command for given address range */
writew(0x4, host->regs + NFC_WRPROT);
this->ecc.size = 512; this->ecc.size = 512;
this->ecc.layout = oob_smallpage; this->ecc.layout = oob_smallpage;
...@@ -797,14 +801,8 @@ static int __init mxcnd_probe(struct platform_device *pdev) ...@@ -797,14 +801,8 @@ static int __init mxcnd_probe(struct platform_device *pdev)
this->ecc.hwctl = mxc_nand_enable_hwecc; this->ecc.hwctl = mxc_nand_enable_hwecc;
this->ecc.correct = mxc_nand_correct_data; this->ecc.correct = mxc_nand_correct_data;
this->ecc.mode = NAND_ECC_HW; this->ecc.mode = NAND_ECC_HW;
tmp = readw(host->regs + NFC_CONFIG1);
tmp |= NFC_ECC_EN;
writew(tmp, host->regs + NFC_CONFIG1);
} else { } else {
this->ecc.mode = NAND_ECC_SOFT; 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 */ /* NAND bus width determines access funtions used by upper layer */
...@@ -818,6 +816,14 @@ static int __init mxcnd_probe(struct platform_device *pdev) ...@@ -818,6 +816,14 @@ static int __init mxcnd_probe(struct platform_device *pdev)
this->options |= NAND_USE_FLASH_BBT; 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 */ /* first scan to find the device and get the page size */
if (nand_scan_ident(mtd, 1, NULL)) { if (nand_scan_ident(mtd, 1, NULL)) {
err = -ENXIO; err = -ENXIO;
......
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