提交 63f4079b 编写于 作者: I Ivo Clarysse 提交者: Sascha Hauer

MXC: 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: NIvo Clarysse <ivo.clarysse@gmail.com>
Signed-off-by: NSascha Hauer <s.hauer@pengutronix.de>
上级 7422f27a
...@@ -38,7 +38,7 @@ ...@@ -38,7 +38,7 @@
#define DRIVER_NAME "mxc_nand" #define DRIVER_NAME "mxc_nand"
#define nfc_is_v21() (cpu_is_mx25() || cpu_is_mx35()) #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 */ /* Addresses for NFC registers */
#define NFC_BUF_SIZE 0xE00 #define NFC_BUF_SIZE 0xE00
...@@ -168,11 +168,7 @@ static irqreturn_t mxc_nfc_irq(int irq, void *dev_id) ...@@ -168,11 +168,7 @@ static irqreturn_t mxc_nfc_irq(int irq, void *dev_id)
{ {
struct mxc_nand_host *host = dev_id; struct mxc_nand_host *host = dev_id;
uint16_t tmp; disable_irq_nosync(irq);
tmp = readw(host->regs + NFC_CONFIG1);
tmp |= NFC_INT_MSK; /* Disable interrupt */
writew(tmp, host->regs + NFC_CONFIG1);
wake_up(&host->irq_waitq); wake_up(&host->irq_waitq);
...@@ -184,15 +180,13 @@ static irqreturn_t mxc_nfc_irq(int irq, void *dev_id) ...@@ -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) static void wait_op_done(struct mxc_nand_host *host, int useirq)
{ {
uint32_t tmp; uint16_t tmp;
int max_retries = 2000; int max_retries = 8000;
if (useirq) { if (useirq) {
if ((readw(host->regs + NFC_CONFIG2) & NFC_INT) == 0) { if ((readw(host->regs + NFC_CONFIG2) & NFC_INT) == 0) {
tmp = readw(host->regs + NFC_CONFIG1); enable_irq(host->irq);
tmp &= ~NFC_INT_MSK; /* Enable interrupt */
writew(tmp, host->regs + NFC_CONFIG1);
wait_event(host->irq_waitq, wait_event(host->irq_waitq,
readw(host->regs + NFC_CONFIG2) & NFC_INT); readw(host->regs + NFC_CONFIG2) & NFC_INT);
...@@ -226,8 +220,23 @@ static void send_cmd(struct mxc_nand_host *host, uint16_t cmd, int useirq) ...@@ -226,8 +220,23 @@ static void send_cmd(struct mxc_nand_host *host, uint16_t cmd, int useirq)
writew(cmd, host->regs + NFC_FLASH_CMD); writew(cmd, host->regs + NFC_FLASH_CMD);
writew(NFC_CMD, host->regs + NFC_CONFIG2); writew(NFC_CMD, host->regs + NFC_CONFIG2);
/* Wait for operation to complete */ if (cpu_is_mx21() && (cmd == NAND_CMD_RESET)) {
wait_op_done(host, useirq); 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 /* This function sends an address (or partial address) to the
...@@ -548,9 +557,9 @@ static void preset(struct mtd_info *mtd) ...@@ -548,9 +557,9 @@ static void preset(struct mtd_info *mtd)
struct mxc_nand_host *host = nand_chip->priv; struct mxc_nand_host *host = nand_chip->priv;
uint16_t tmp; uint16_t tmp;
/* disable interrupt, disable spare enable */ /* enable interrupt, disable spare enable */
tmp = readw(host->regs + NFC_CONFIG1); tmp = readw(host->regs + NFC_CONFIG1);
tmp |= NFC_INT_MSK; tmp &= ~NFC_INT_MSK;
tmp &= ~NFC_SP_EN; tmp &= ~NFC_SP_EN;
if (nand_chip->ecc.mode == NAND_ECC_HW) { if (nand_chip->ecc.mode == NAND_ECC_HW) {
tmp |= NFC_ECC_EN; tmp |= NFC_ECC_EN;
...@@ -819,7 +828,7 @@ static int __init mxcnd_probe(struct platform_device *pdev) ...@@ -819,7 +828,7 @@ static int __init mxcnd_probe(struct platform_device *pdev)
host->irq = platform_get_irq(pdev, 0); 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) if (err)
goto eirq; goto eirq;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册