Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7422f27a authored by Ivo Clarysse's avatar Ivo Clarysse Committed by Sascha Hauer
Browse files

MXC: 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>
Signed-off-by: default avatarSascha Hauer <s.hauer@pengutronix.de>
parent 8bcc84ad
Loading
Loading
Loading
Loading
+48 −42
Original line number Original line Diff line number Diff line
@@ -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;
@@ -679,7 +718,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;


@@ -743,51 +781,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;


@@ -796,14 +800,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 */
@@ -817,6 +815,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)) {
	if (nand_scan_ident(mtd, 1)) {
		err = -ENXIO;
		err = -ENXIO;