aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd
diff options
context:
space:
mode:
authorIvo Clarysse <ivo.clarysse@gmail.com>2010-04-08 10:16:51 -0400
committerDavid Woodhouse <David.Woodhouse@intel.com>2010-05-13 20:02:53 -0400
commita47bfd2eb66837653dc3b42541dfe4283dd41251 (patch)
treece4199d6c78acb4d9332af55f6415d74e1d3d862 /drivers/mtd
parentd484018056816178abffacb84b8c16628e880c83 (diff)
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: Ivo Clarysse <ivo.clarysse@gmail.com> Acked-by: Sascha Hauer <s.hauer@pengutronix.de> Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Diffstat (limited to 'drivers/mtd')
-rw-r--r--drivers/mtd/nand/mxc_nand.c41
1 files changed, 25 insertions, 16 deletions
diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c
index b527aa2d687d..35da3dc4bd17 100644
--- a/drivers/mtd/nand/mxc_nand.c
+++ b/drivers/mtd/nand/mxc_nand.c
@@ -38,7 +38,7 @@
38#define DRIVER_NAME "mxc_nand" 38#define DRIVER_NAME "mxc_nand"
39 39
40#define nfc_is_v21() (cpu_is_mx25() || cpu_is_mx35()) 40#define nfc_is_v21() (cpu_is_mx25() || cpu_is_mx35())
41#define nfc_is_v1() (cpu_is_mx31() || cpu_is_mx27()) 41#define nfc_is_v1() (cpu_is_mx31() || cpu_is_mx27() || cpu_is_mx21())
42 42
43/* Addresses for NFC registers */ 43/* Addresses for NFC registers */
44#define NFC_BUF_SIZE 0xE00 44#define NFC_BUF_SIZE 0xE00
@@ -168,11 +168,7 @@ static irqreturn_t mxc_nfc_irq(int irq, void *dev_id)
168{ 168{
169 struct mxc_nand_host *host = dev_id; 169 struct mxc_nand_host *host = dev_id;
170 170
171 uint16_t tmp; 171 disable_irq_nosync(irq);
172
173 tmp = readw(host->regs + NFC_CONFIG1);
174 tmp |= NFC_INT_MSK; /* Disable interrupt */
175 writew(tmp, host->regs + NFC_CONFIG1);
176 172
177 wake_up(&host->irq_waitq); 173 wake_up(&host->irq_waitq);
178 174
@@ -184,15 +180,13 @@ static irqreturn_t mxc_nfc_irq(int irq, void *dev_id)
184 */ 180 */
185static void wait_op_done(struct mxc_nand_host *host, int useirq) 181static void wait_op_done(struct mxc_nand_host *host, int useirq)
186{ 182{
187 uint32_t tmp; 183 uint16_t tmp;
188 int max_retries = 2000; 184 int max_retries = 8000;
189 185
190 if (useirq) { 186 if (useirq) {
191 if ((readw(host->regs + NFC_CONFIG2) & NFC_INT) == 0) { 187 if ((readw(host->regs + NFC_CONFIG2) & NFC_INT) == 0) {
192 188
193 tmp = readw(host->regs + NFC_CONFIG1); 189 enable_irq(host->irq);
194 tmp &= ~NFC_INT_MSK; /* Enable interrupt */
195 writew(tmp, host->regs + NFC_CONFIG1);
196 190
197 wait_event(host->irq_waitq, 191 wait_event(host->irq_waitq,
198 readw(host->regs + NFC_CONFIG2) & NFC_INT); 192 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 writew(cmd, host->regs + NFC_FLASH_CMD); 220 writew(cmd, host->regs + NFC_FLASH_CMD);
227 writew(NFC_CMD, host->regs + NFC_CONFIG2); 221 writew(NFC_CMD, host->regs + NFC_CONFIG2);
228 222
229 /* Wait for operation to complete */ 223 if (cpu_is_mx21() && (cmd == NAND_CMD_RESET)) {
230 wait_op_done(host, useirq); 224 int max_retries = 100;
225 /* Reset completion is indicated by NFC_CONFIG2 */
226 /* being set to 0 */
227 while (max_retries-- > 0) {
228 if (readw(host->regs + NFC_CONFIG2) == 0) {
229 break;
230 }
231 udelay(1);
232 }
233 if (max_retries < 0)
234 DEBUG(MTD_DEBUG_LEVEL0, "%s: RESET failed\n",
235 __func__);
236 } else {
237 /* Wait for operation to complete */
238 wait_op_done(host, useirq);
239 }
231} 240}
232 241
233/* This function sends an address (or partial address) to the 242/* This function sends an address (or partial address) to the
@@ -548,9 +557,9 @@ static void preset(struct mtd_info *mtd)
548 struct mxc_nand_host *host = nand_chip->priv; 557 struct mxc_nand_host *host = nand_chip->priv;
549 uint16_t tmp; 558 uint16_t tmp;
550 559
551 /* disable interrupt, disable spare enable */ 560 /* enable interrupt, disable spare enable */
552 tmp = readw(host->regs + NFC_CONFIG1); 561 tmp = readw(host->regs + NFC_CONFIG1);
553 tmp |= NFC_INT_MSK; 562 tmp &= ~NFC_INT_MSK;
554 tmp &= ~NFC_SP_EN; 563 tmp &= ~NFC_SP_EN;
555 if (nand_chip->ecc.mode == NAND_ECC_HW) { 564 if (nand_chip->ecc.mode == NAND_ECC_HW) {
556 tmp |= NFC_ECC_EN; 565 tmp |= NFC_ECC_EN;
@@ -820,7 +829,7 @@ static int __init mxcnd_probe(struct platform_device *pdev)
820 829
821 host->irq = platform_get_irq(pdev, 0); 830 host->irq = platform_get_irq(pdev, 0);
822 831
823 err = request_irq(host->irq, mxc_nfc_irq, 0, DRIVER_NAME, host); 832 err = request_irq(host->irq, mxc_nfc_irq, IRQF_DISABLED, DRIVER_NAME, host);
824 if (err) 833 if (err)
825 goto eirq; 834 goto eirq;
826 835