]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/mtd/onenand/omap2.c
Merge current mainline tree into linux-omap tree
[linux-2.6-omap-h63xx.git] / drivers / mtd / onenand / omap2.c
index 43060bee5009356b6184b1de51f71c1be6fe4b38..28034ef08a82a4e83d8cbaaad0be3265de7b9806 100644 (file)
@@ -3,9 +3,9 @@
  *
  *  OneNAND driver for OMAP2 / OMAP3
  *
- *  Copyright (C) 2005-2006 Nokia Corporation
+ *  Copyright © 2005-2006 Nokia Corporation
  *
- *  Author: Jarkko Lavinen <jarkko.lavinen@nokia.com> and Juha Yrjola
+ *  Author: Jarkko Lavinen <jarkko.lavinen@nokia.com> and Juha Yrjölä
  *  IRQ and DMA support written by Timo Teras
  *
  * This program is free software; you can redistribute it and/or modify it
 
 #include <asm/io.h>
 #include <asm/mach/flash.h>
-#include <asm/arch/gpmc.h>
-#include <asm/arch/onenand.h>
-#include <asm/arch/gpio.h>
-#include <asm/arch/gpmc.h>
-#include <asm/arch/pm.h>
+#include <mach/gpmc.h>
+#include <mach/onenand.h>
+#include <mach/gpio.h>
+#include <mach/pm.h>
 
 #include <linux/dma-mapping.h>
 #include <asm/dma-mapping.h>
-#include <asm/arch/dma.h>
+#include <mach/dma.h>
 
-#include <asm/arch/board.h>
+#include <mach/board.h>
 
 #define DRIVER_NAME "omap2-onenand"
 
@@ -141,8 +140,13 @@ static int omap2_onenand_wait(struct mtd_info *mtd, int state)
 
                /* Turn interrupts on */
                syscfg = read_reg(c, ONENAND_REG_SYS_CFG1);
-               syscfg |= ONENAND_SYS_CFG1_IOBE;
-               write_reg(c, syscfg, ONENAND_REG_SYS_CFG1);
+               if (!(syscfg & ONENAND_SYS_CFG1_IOBE)) {
+                       syscfg |= ONENAND_SYS_CFG1_IOBE;
+                       write_reg(c, syscfg, ONENAND_REG_SYS_CFG1);
+                       if (cpu_is_omap34xx())
+                               /* Add a delay to let GPIO settle */
+                               syscfg = read_reg(c, ONENAND_REG_SYS_CFG1);
+               }
 
                INIT_COMPLETION(c->irq_done);
                if (c->gpio_irq) {
@@ -182,16 +186,36 @@ retry:
                        }
                }
        } else {
+               int retry_cnt = 0;
+
                /* Turn interrupts off */
                syscfg = read_reg(c, ONENAND_REG_SYS_CFG1);
                syscfg &= ~ONENAND_SYS_CFG1_IOBE;
                write_reg(c, syscfg, ONENAND_REG_SYS_CFG1);
 
                timeout = jiffies + msecs_to_jiffies(20);
-               while (time_before(jiffies, timeout)) {
-                       intr = read_reg(c, ONENAND_REG_INTERRUPT);
-                       if (intr & ONENAND_INT_MASTER)
+               while (1) {
+                       if (time_before(jiffies, timeout)) {
+                               intr = read_reg(c, ONENAND_REG_INTERRUPT);
+                               if (intr & ONENAND_INT_MASTER)
+                                       break;
+                       } else {
+                               /* Timeout after 20ms */
+                               ctrl = read_reg(c, ONENAND_REG_CTRL_STATUS);
+                               if (ctrl & ONENAND_CTRL_ONGO) {
+                                       /*
+                                        * The operation seems to be still going
+                                        * so give it some more time.
+                                        */
+                                       retry_cnt += 1;
+                                       if (retry_cnt < 3) {
+                                               timeout = jiffies +
+                                                         msecs_to_jiffies(20);
+                                               continue;
+                                       }
+                               }
                                break;
+                       }
                }
        }
 
@@ -291,7 +315,7 @@ static int omap3_onenand_read_bufferram(struct mtd_info *mtd, int area,
 
        dma_src = c->phys_base + bram_offset;
        dma_dst = dma_map_single(&c->pdev->dev, buf, count, DMA_FROM_DEVICE);
-       if (dma_mapping_error(dma_dst)) {
+       if (dma_mapping_error(&c->pdev->dev, dma_dst)) {
                dev_err(&c->pdev->dev,
                        "Couldn't DMA map a %d byte buffer\n",
                        count);
@@ -362,7 +386,7 @@ static int omap3_onenand_write_bufferram(struct mtd_info *mtd, int area,
 
        dma_src = dma_map_single(&c->pdev->dev, buf, count, DMA_TO_DEVICE);
        dma_dst = c->phys_base + bram_offset;
-       if (dma_mapping_error(dma_dst)) {
+       if (dma_mapping_error(&c->pdev->dev, dma_dst)) {
                dev_err(&c->pdev->dev,
                        "Couldn't DMA map a %d byte buffer\n",
                        count);
@@ -435,7 +459,7 @@ static int omap2_onenand_read_bufferram(struct mtd_info *mtd, int area,
        dma_src = c->phys_base + bram_offset;
        dma_dst = dma_map_single(&c->pdev->dev, buffer, count,
                                 DMA_FROM_DEVICE);
-       if (dma_mapping_error(dma_dst)) {
+       if (dma_mapping_error(&c->pdev->dev, dma_dst)) {
                dev_err(&c->pdev->dev,
                        "Couldn't DMA map a %d byte buffer\n",
                        count);
@@ -480,7 +504,7 @@ static int omap2_onenand_write_bufferram(struct mtd_info *mtd, int area,
        dma_src = dma_map_single(&c->pdev->dev, (void *) buffer, count,
                                 DMA_TO_DEVICE);
        dma_dst = c->phys_base + bram_offset;
-       if (dma_mapping_error(dma_dst)) {
+       if (dma_mapping_error(&c->pdev->dev, dma_dst)) {
                dev_err(&c->pdev->dev,
                        "Couldn't DMA map a %d byte buffer\n",
                        count);