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

Commit a47bfd2e authored by Ivo Clarysse's avatar Ivo Clarysse Committed by David Woodhouse
Browse files

mtd: mxc_nand: support i.MX21



On i.MX21 SoCs, if the NFC_CONFIG1:NFC_INT_MASK bit is set,
NFC_CONFIG2:NFC_INT always reads out zero, even if an
operation is completed.  This patch uses enable_irq and
disable_irq_nosync instead of NFC_CONFIG1:NFC_INT_MASK to
mask NFC interrupts.  This allows NFC_CONFIG2:NFC_INT to also
be used to detect operation completion on i.MX21.

The i.MX21 NFC does not signal reset completion using
NFC_CONFIG1:NFC_INT_MASK, so instead reset completion is
tested by checking if NFC_CONFIG2 becomes 0.

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 d4840180
Loading
Loading
Loading
Loading
+25 −16
Original line number Diff line number Diff line
@@ -38,7 +38,7 @@
#define DRIVER_NAME "mxc_nand"

#define nfc_is_v21()		(cpu_is_mx25() || cpu_is_mx35())
#define nfc_is_v1()		(cpu_is_mx31() || cpu_is_mx27())
#define nfc_is_v1()		(cpu_is_mx31() || cpu_is_mx27() || cpu_is_mx21())

/* Addresses for NFC registers */
#define NFC_BUF_SIZE		0xE00
@@ -168,11 +168,7 @@ static irqreturn_t mxc_nfc_irq(int irq, void *dev_id)
{
	struct mxc_nand_host *host = dev_id;

	uint16_t tmp;

	tmp = readw(host->regs + NFC_CONFIG1);
	tmp |= NFC_INT_MSK; /* Disable interrupt */
	writew(tmp, host->regs + NFC_CONFIG1);
	disable_irq_nosync(irq);

	wake_up(&host->irq_waitq);

@@ -184,15 +180,13 @@ static irqreturn_t mxc_nfc_irq(int irq, void *dev_id)
 */
static void wait_op_done(struct mxc_nand_host *host, int useirq)
{
	uint32_t tmp;
	int max_retries = 2000;
	uint16_t tmp;
	int max_retries = 8000;

	if (useirq) {
		if ((readw(host->regs + NFC_CONFIG2) & NFC_INT) == 0) {

			tmp = readw(host->regs + NFC_CONFIG1);
			tmp  &= ~NFC_INT_MSK;	/* Enable interrupt */
			writew(tmp, host->regs + NFC_CONFIG1);
			enable_irq(host->irq);

			wait_event(host->irq_waitq,
				readw(host->regs + NFC_CONFIG2) & NFC_INT);
@@ -226,9 +220,24 @@ static void send_cmd(struct mxc_nand_host *host, uint16_t cmd, int useirq)
	writew(cmd, host->regs + NFC_FLASH_CMD);
	writew(NFC_CMD, host->regs + NFC_CONFIG2);

	if (cpu_is_mx21() && (cmd == NAND_CMD_RESET)) {
		int max_retries = 100;
		/* Reset completion is indicated by NFC_CONFIG2 */
		/* being set to 0 */
		while (max_retries-- > 0) {
			if (readw(host->regs + NFC_CONFIG2) == 0) {
				break;
			}
			udelay(1);
		}
		if (max_retries < 0)
			DEBUG(MTD_DEBUG_LEVEL0, "%s: RESET failed\n",
			      __func__);
	} else {
		/* Wait for operation to complete */
		wait_op_done(host, useirq);
	}
}

/* This function sends an address (or partial address) to the
 * NAND device. The address is used to select the source/destination for
@@ -548,9 +557,9 @@ static void preset(struct mtd_info *mtd)
	struct mxc_nand_host *host = nand_chip->priv;
	uint16_t tmp;

	/* disable interrupt, disable spare enable */
	/* enable interrupt, disable spare enable */
	tmp = readw(host->regs + NFC_CONFIG1);
	tmp |= NFC_INT_MSK;
	tmp &= ~NFC_INT_MSK;
	tmp &= ~NFC_SP_EN;
	if (nand_chip->ecc.mode == NAND_ECC_HW) {
		tmp |= NFC_ECC_EN;
@@ -820,7 +829,7 @@ static int __init mxcnd_probe(struct platform_device *pdev)

	host->irq = platform_get_irq(pdev, 0);

	err = request_irq(host->irq, mxc_nfc_irq, 0, DRIVER_NAME, host);
	err = request_irq(host->irq, mxc_nfc_irq, IRQF_DISABLED, DRIVER_NAME, host);
	if (err)
		goto eirq;