[PATCH] OneNAND: Sync. Burst Read support
authorKyungmin Park <kyungmin.park@samsung.com>
Sat, 3 Sep 2005 06:07:19 +0000 (07:07 +0100)
committerThomas Gleixner <tglx@mtd.linutronix.de>
Sun, 6 Nov 2005 20:19:37 +0000 (21:19 +0100)
Add OneNAND Sync. Burst Read support
Tested with OMAP platform

Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
drivers/mtd/onenand/Kconfig
drivers/mtd/onenand/omap-onenand.c
drivers/mtd/onenand/onenand_base.c
include/linux/mtd/onenand.h
include/linux/mtd/onenand_regs.h

index 7d76ede984d86fecec1a810b629e8dc120e63ba1..186ea9dc094213cb96184ce808134ab81341b9d0 100644 (file)
@@ -29,4 +29,10 @@ config MTD_ONENAND_OMAP
        help
          Support for OneNAND flash on TI OMAP board.
 
+config MTD_ONENAND_SYNC_READ
+       bool "OneNAND Sync. Burst Read Support"
+       depends on ARCH_OMAP
+       help
+         This enables support for Sync. Burst Read.
+
 endmenu
index 56e1aec6b83542c73e352d0e502eb765b24d18a3..7c89549f7f585167c302238e67195d7584d634b1 100644 (file)
 #include <asm/arch/hardware.h>
 #include <asm/arch/tc.h>
 #include <asm/sizes.h>
+#include <asm/mach-types.h>
 
 #define OMAP_ONENAND_FLASH_START1      OMAP_CS2A_PHYS
-#define OMAP_ONENAND_FLASH_START2      OMAP_CS0_PHYS
+#define OMAP_ONENAND_FLASH_START2      omap_cs3_phys()
 /*
  * MTD structure for OMAP board
  */
@@ -68,10 +69,66 @@ static struct mtd_partition static_partition[] = {
        },
 };
 
-const char *part_probes[] = { "cmdlinepart", NULL,  };
+static const char *part_probes[] = { "cmdlinepart", NULL,  };
 
 #endif
 
+#ifdef CONFIG_MTD_ONENAND_SYNC_READ
+static unsigned int omap_emifs_cs;
+
+static void omap_find_emifs_cs(unsigned int addr)
+{
+       /* Check CS3 */
+       if (OMAP_EMIFS_CONFIG_REG & OMAP_EMIFS_CONFIG_BM && addr == 0x0) {
+               omap_emifs_cs = 3;
+       } else {
+               omap_emifs_cs = (addr >> 26);
+       }
+}
+
+/**
+ * omap_onenand_mmcontrol - Control OMAP EMIFS
+ */
+static void omap_onenand_mmcontrol(struct mtd_info *mtd, int sync_read)
+{
+       struct onenand_chip *this = mtd->priv;
+       static unsigned long omap_emifs_ccs, omap_emifs_acs;
+       static unsigned long onenand_sys_cfg1;
+       int config, emifs_ccs, emifs_acs;
+
+       if (sync_read) {
+               /*
+                * Note: BRL and RDWST is equal
+                */
+               omap_emifs_ccs = EMIFS_CCS(omap_emifs_cs);
+               omap_emifs_acs = EMIFS_ACS(omap_emifs_cs);
+               
+               emifs_ccs = 0x41141;
+               emifs_acs = 0x1;
+
+               /* OneNAND System Configuration 1 */
+               onenand_sys_cfg1 = this->read_word(this->base + ONENAND_REG_SYS_CFG1);
+               config = (onenand_sys_cfg1
+                       & ~(0x3f << ONENAND_SYS_CFG1_BL_SHIFT))
+                       | ONENAND_SYS_CFG1_SYNC_READ
+                       | ONENAND_SYS_CFG1_BRL_4
+                       | ONENAND_SYS_CFG1_BL_8;
+       } else {
+               emifs_ccs = omap_emifs_ccs;
+               emifs_acs = omap_emifs_acs;
+               config = onenand_sys_cfg1;
+       }
+
+       this->write_word(config, this->base + ONENAND_REG_SYS_CFG1);
+       EMIFS_CCS(omap_emifs_cs) = emifs_ccs;
+       EMIFS_ACS(omap_emifs_cs) = emifs_acs;
+}
+#else
+#define omap_find_emifs_cs(x)          do { } while (0)
+#define omap_onenand_mmcontrol         NULL
+#endif
+
+
 /* Scan to find existance of the device at base.
    This also allocates oob and data internal buffers */
 static char onenand_name[] = "onenand";
@@ -102,14 +159,19 @@ static int __init omap_onenand_init (void)
 
        /* Link the private data with the MTD structure */
        omap_onenand_mtd->priv = this;
+       this->mmcontrol = omap_onenand_mmcontrol;
 
         /* try the first address */
        this->base = ioremap(OMAP_ONENAND_FLASH_START1, SZ_128K);
+       omap_find_emifs_cs(OMAP_ONENAND_FLASH_START1);
+
        omap_onenand_mtd->name = onenand_name;
        if (onenand_scan(omap_onenand_mtd, 1)){
                /* try the second address */
                iounmap(this->base);
                this->base = ioremap(OMAP_ONENAND_FLASH_START2, SZ_128K);
+               omap_find_emifs_cs(OMAP_ONENAND_FLASH_START2);
+
                if (onenand_scan(omap_onenand_mtd, 1)) {
                        iounmap(this->base);
                         err = -ENXIO;
index bcce22ae3cb1536e217e8a06fd349db06ae40b10..e87489505772621e275650232c81b8a0af0a674e 100644 (file)
@@ -378,6 +378,35 @@ static int onenand_read_bufferram(struct mtd_info *mtd, int area,
        return 0;
 }
 
+/**
+ * onenand_sync_read_bufferram - [OneNAND Interface] Read the bufferram area with Sync. Burst mode
+ * @param mtd          MTD data structure
+ * @param area         BufferRAM area
+ * @param buffer       the databuffer to put/get data
+ * @param offset       offset to read from or write to
+ * @param count                number of bytes to read/write
+ *
+ * Read the BufferRAM area with Sync. Burst Mode
+ */
+static int onenand_sync_read_bufferram(struct mtd_info *mtd, int area,
+               unsigned char *buffer, int offset, size_t count)
+{
+       struct onenand_chip *this = mtd->priv;
+       void __iomem *bufferram;
+
+       bufferram = this->base + area;
+
+       bufferram += onenand_bufferram_offset(mtd, area);
+
+       this->mmcontrol(mtd, ONENAND_SYS_CFG1_SYNC_READ);
+
+       memcpy(buffer, bufferram + offset, count);
+
+       this->mmcontrol(mtd, 0);
+
+       return 0;
+}
+
 /**
  * onenand_write_bufferram - [OneNAND Interface] Write the bufferram area
  * @param mtd          MTD data structure
@@ -1273,8 +1302,8 @@ static int onenand_check_maf(int manuf)
                         break;
         }
 
-        printk(KERN_DEBUG "OneNAND Manufacturer: %s\n",
-                onenand_manuf_ids[i].name);
+        printk(KERN_DEBUG "OneNAND Manufacturer: %s (0x%0x)\n",
+                onenand_manuf_ids[i].name, manuf);
 
         return (i != ONENAND_MFR_UNKNOWN);
 }
@@ -1385,6 +1414,12 @@ int onenand_scan(struct mtd_info *mtd, int maxchips)
        if (onenand_probe(mtd))
                return -ENXIO;
 
+       /* Set Sync. Burst Read after probing */
+       if (this->mmcontrol) {
+               printk(KERN_INFO "OneNAND Sync. Burst Read support\n");
+               this->read_bufferram = onenand_sync_read_bufferram;
+       }
+
        this->state = FL_READY;
        init_waitqueue_head(&this->wq);
        spin_lock_init(&this->chip_lock);
index b9a64117d6464d06f35b28e1334ba1a8255c22ca..c557caa24a6c80b18c379da5e8309fdcafad177a 100644 (file)
@@ -95,6 +95,7 @@ struct onenand_chip {
                        const unsigned char *buffer, int offset, size_t count);
        unsigned short (*read_word)(void __iomem *addr);
        void (*write_word)(unsigned short value, void __iomem *addr);
+       void (*mmcontrol)(struct mtd_info *mtd, int sync_read);
 
        spinlock_t              chip_lock;
        wait_queue_head_t       wq;
index 4a2daad7d738ab3769069fd45b858ff19e9d9847..d7832ef8ed635e9bb37a182b3ffe766afaf6be3d 100644 (file)
  * System Configuration 1 Register F221h (R, R/W)
  */
 #define ONENAND_SYS_CFG1_SYNC_READ     (1 << 15)
-#define ONENAND_SYS_CFG1_BRL           (1 << 12)
-#define ONENAND_SYS_CFG1_BL            (1 << 9)
+#define ONENAND_SYS_CFG1_BRL_7         (7 << 12)
+#define ONENAND_SYS_CFG1_BRL_6         (6 << 12)
+#define ONENAND_SYS_CFG1_BRL_5         (5 << 12)
+#define ONENAND_SYS_CFG1_BRL_4         (4 << 12)
+#define ONENAND_SYS_CFG1_BRL_3         (3 << 12)
+#define ONENAND_SYS_CFG1_BRL_10                (2 << 12)
+#define ONENAND_SYS_CFG1_BRL_9         (1 << 12)
+#define ONENAND_SYS_CFG1_BRL_8         (0 << 12)
+#define ONENAND_SYS_CFG1_BRL_SHIFT     (12)
+#define ONENAND_SYS_CFG1_BL_32         (4 << 9)
+#define ONENAND_SYS_CFG1_BL_16         (3 << 9)
+#define ONENAND_SYS_CFG1_BL_8          (2 << 9)
+#define ONENAND_SYS_CFG1_BL_4          (1 << 9)
+#define ONENAND_SYS_CFG1_BL_CONT       (0 << 9)
+#define ONENAND_SYS_CFG1_BL_SHIFT      (9)
 #define ONENAND_SYS_CFG1_NO_ECC                (1 << 8)
 #define ONENAND_SYS_CFG1_RDY           (1 << 7)
 #define ONENAND_SYS_CFG1_INT           (1 << 6)