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:
parent
9d5da3a9b8
commit
d484018056
|
@ -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,
|
||||||
|
|
||||||
/* 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)
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
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;
|
||||||
|
|
Loading…
Reference in a new issue