]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
[PATCH] ARM: OMAP: NAND flash driver model
authorLadislav Michl <ladis@linux-mips.org>
Wed, 30 Nov 2005 20:37:57 +0000 (12:37 -0800)
committerTony Lindgren <tony@atomide.com>
Wed, 30 Nov 2005 20:37:57 +0000 (12:37 -0800)
NAND flash driver model

arch/arm/mach-omap1/board-h2.c
arch/arm/mach-omap1/board-h3.c
arch/arm/mach-omap1/board-perseus2.c
drivers/mtd/nand/omap-nand-flash.c
include/asm-arm/arch-omap/board-h2.h
include/asm-arm/arch-omap/board-h3.h
include/asm-arm/arch-omap/board-perseus2.h
include/asm-arm/mach/flash.h

index a07e2c9307fa338896ecca300dc88033a8922885..0fc2e0f36e7c916e014d62e48314d612663a38b6 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/platform_device.h>
 #include <linux/delay.h>
 #include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
 #include <linux/mtd/partitions.h>
 
 #include <asm/hardware.h>
@@ -40,7 +41,7 @@
 
 extern int omap_gpio_init(void);
 
-static struct mtd_partition h2_partitions[] = {
+static struct mtd_partition h2_nor_partitions[] = {
        /* bootloader (U-Boot, etc) in first sector */
        {
              .name             = "bootloader",
@@ -71,26 +72,83 @@ static struct mtd_partition h2_partitions[] = {
        }
 };
 
-static struct flash_platform_data h2_flash_data = {
+static struct flash_platform_data h2_nor_data = {
        .map_name       = "cfi_probe",
        .width          = 2,
-       .parts          = h2_partitions,
-       .nr_parts       = ARRAY_SIZE(h2_partitions),
+       .parts          = h2_nor_partitions,
+       .nr_parts       = ARRAY_SIZE(h2_nor_partitions),
 };
 
-static struct resource h2_flash_resource = {
+static struct resource h2_nor_resource = {
        /* This is on CS3, wherever it's mapped */
        .flags          = IORESOURCE_MEM,
 };
 
-static struct platform_device h2_flash_device = {
+static struct platform_device h2_nor_device = {
        .name           = "omapflash",
        .id             = 0,
        .dev            = {
-               .platform_data  = &h2_flash_data,
+               .platform_data  = &h2_nor_data,
        },
        .num_resources  = 1,
-       .resource       = &h2_flash_resource,
+       .resource       = &h2_nor_resource,
+};
+
+static struct mtd_partition h2_nand_partitions[] = {
+#if 0
+       /* REVISIT:  enable these partitions if you make NAND BOOT
+        * work on your H2 (rev C or newer); published versions of
+        * x-load only support P2 and H3.
+        */
+       {
+               .name           = "xloader",
+               .offset         = 0,
+               .size           = 64 * 1024,
+               .mask_flags     = MTD_WRITEABLE,        /* force read-only */
+       },
+       {
+               .name           = "bootloader",
+               .offset         = MTDPART_OFS_APPEND,
+               .size           = 256 * 1024,
+               .mask_flags     = MTD_WRITEABLE,        /* force read-only */
+       },
+       {
+               .name           = "params",
+               .offset         = MTDPART_OFS_APPEND,
+               .size           = 192 * 1024,
+       },
+       {
+               .name           = "kernel",
+               .offset         = MTDPART_OFS_APPEND,
+               .size           = 2 * SZ_1M,
+       },
+#endif
+       {
+               .name           = "filesystem",
+               .size           = MTDPART_SIZ_FULL,
+               .offset         = MTDPART_OFS_APPEND,
+       },
+};
+
+/* dip switches control NAND chip access:  8 bit, 16 bit, or neither */
+static struct nand_platform_data h2_nand_data = {
+       .options        = NAND_SAMSUNG_LP_OPTIONS,
+       .parts          = h2_nand_partitions,
+       .nr_parts       = ARRAY_SIZE(h2_nand_partitions),
+};
+
+static struct resource h2_nand_resource = {
+       .flags          = IORESOURCE_MEM,
+};
+
+static struct platform_device h2_nand_device = {
+       .name           = "omapnand",
+       .id             = 0,
+       .dev            = {
+               .platform_data  = &h2_nand_data,
+       },
+       .num_resources  = 1,
+       .resource       = &h2_nand_resource,
 };
 
 static struct resource h2_smc91x_resources[] = {
@@ -114,7 +172,8 @@ static struct platform_device h2_smc91x_device = {
 };
 
 static struct platform_device *h2_devices[] __initdata = {
-       &h2_flash_device,
+       &h2_nor_device,
+       &h2_nand_device,
        &h2_smc91x_device,
 };
 
@@ -174,13 +233,34 @@ static struct omap_board_config_kernel h2_config[] = {
        { OMAP_TAG_LCD,         &h2_lcd_config },
 };
 
+#define H2_NAND_RB_GPIO_PIN    62
+
+static int h2_nand_dev_ready(struct nand_platform_data *data)
+{
+       return omap_get_gpio_datain(H2_NAND_RB_GPIO_PIN);
+}
+
 static void __init h2_init(void)
 {
-       /* NOTE: revC boards support NAND-boot, which can put NOR on CS2B
-        * and NAND (either 16bit or 8bit) on CS3.
+       /* Here we assume the NOR boot config:  NOR on CS3 (possibly swapped
+        * to address 0 by a dip switch), NAND on CS2B.  The NAND driver will
+        * notice whether a NAND chip is enabled at probe time.
+        *
+        * FIXME revC boards (and H3) support NAND-boot, with a dip switch to
+        * put NOR on CS2B and NAND (which on H2 may be 16bit) on CS3.  Try
+        * detecting that in code here, to avoid probing every possible flash
+        * configuration...
         */
-       h2_flash_resource.end = h2_flash_resource.start = omap_cs3_phys();
-       h2_flash_resource.end += SZ_32M - 1;
+       h2_nor_resource.end = h2_nor_resource.start = omap_cs3_phys();
+       h2_nor_resource.end += SZ_32M - 1;
+
+       h2_nand_resource.end = h2_nand_resource.start = OMAP_CS2B_PHYS;
+       h2_nand_resource.end += SZ_4K - 1;
+       if (!(omap_request_gpio(H2_NAND_RB_GPIO_PIN)))
+               h2_nand_data.dev_ready = h2_nand_dev_ready;
+
+       omap_cfg_reg(L3_1610_FLASH_CS2B_OE);
+       omap_cfg_reg(M8_1610_FLASH_CS2B_WE);
 
        /* MMC:  card detect and WP */
        // omap_cfg_reg(U19_ARMIO1);            /* CD */
index 668e278433c28701762f28b9531b0ecc489406f8..2953d38aedb0eb369048a97ec9473045f70ec50b 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/platform_device.h>
 #include <linux/errno.h>
 #include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
 #include <linux/mtd/partitions.h>
 
 #include <asm/setup.h>
@@ -41,7 +42,7 @@
 
 extern int omap_gpio_init(void);
 
-static struct mtd_partition h3_partitions[] = {
+static struct mtd_partition nor_partitions[] = {
        /* bootloader (U-Boot, etc) in first sector */
        {
              .name             = "bootloader",
@@ -72,26 +73,80 @@ static struct mtd_partition h3_partitions[] = {
        }
 };
 
-static struct flash_platform_data h3_flash_data = {
+static struct flash_platform_data nor_data = {
        .map_name       = "cfi_probe",
        .width          = 2,
-       .parts          = h3_partitions,
-       .nr_parts       = ARRAY_SIZE(h3_partitions),
+       .parts          = nor_partitions,
+       .nr_parts       = ARRAY_SIZE(nor_partitions),
 };
 
-static struct resource h3_flash_resource = {
+static struct resource nor_resource = {
        /* This is on CS3, wherever it's mapped */
        .flags          = IORESOURCE_MEM,
 };
 
-static struct platform_device flash_device = {
+static struct platform_device nor_device = {
        .name           = "omapflash",
        .id             = 0,
        .dev            = {
-               .platform_data  = &h3_flash_data,
+               .platform_data  = &nor_data,
        },
        .num_resources  = 1,
-       .resource       = &h3_flash_resource,
+       .resource       = &nor_resource,
+};
+
+static struct mtd_partition nand_partitions[] = {
+#if 0
+       /* REVISIT: enable these partitions if you make NAND BOOT work */
+       {
+               .name           = "xloader",
+               .offset         = 0,
+               .size           = 64 * 1024,
+               .mask_flags     = MTD_WRITEABLE,        /* force read-only */
+       },
+       {
+               .name           = "bootloader",
+               .offset         = MTDPART_OFS_APPEND,
+               .size           = 256 * 1024,
+               .mask_flags     = MTD_WRITEABLE,        /* force read-only */
+       },
+       {
+               .name           = "params",
+               .offset         = MTDPART_OFS_APPEND,
+               .size           = 192 * 1024,
+       },
+       {
+               .name           = "kernel",
+               .offset         = MTDPART_OFS_APPEND,
+               .size           = 2 * SZ_1M,
+       },
+#endif
+       {
+               .name           = "filesystem",
+               .size           = MTDPART_SIZ_FULL,
+               .offset         = MTDPART_OFS_APPEND,
+       },
+};
+
+/* dip switches control NAND chip access:  8 bit, 16 bit, or neither */
+static struct nand_platform_data nand_data = {
+       .options        = NAND_SAMSUNG_LP_OPTIONS,
+       .parts          = nand_partitions,
+       .nr_parts       = ARRAY_SIZE(nand_partitions),
+};
+
+static struct resource nand_resource = {
+       .flags          = IORESOURCE_MEM,
+};
+
+static struct platform_device nand_device = {
+       .name           = "omapnand",
+       .id             = 0,
+       .dev            = {
+               .platform_data  = &nand_data,
+       },
+       .num_resources  = 1,
+       .resource       = &nand_resource,
 };
 
 static struct resource smc91x_resources[] = {
@@ -139,7 +194,8 @@ static struct platform_device intlat_device = {
 };
 
 static struct platform_device *devices[] __initdata = {
-       &flash_device,
+       &nor_device,
+       &nand_device,
         &smc91x_device,
        &intlat_device,
 };
@@ -182,11 +238,36 @@ static struct omap_board_config_kernel h3_config[] = {
        { OMAP_TAG_LCD,         &h3_lcd_config },
 };
 
+#define H3_NAND_RB_GPIO_PIN    10
+
+static int nand_dev_ready(struct nand_platform_data *data)
+{
+       return omap_get_gpio_datain(H3_NAND_RB_GPIO_PIN);
+}
+
 static void __init h3_init(void)
 {
-       h3_flash_resource.end = h3_flash_resource.start = omap_cs3_phys();
-       h3_flash_resource.end += OMAP_CS3_SIZE - 1;
-       (void) platform_add_devices(devices, ARRAY_SIZE(devices));
+       /* Here we assume the NOR boot config:  NOR on CS3 (possibly swapped
+        * to address 0 by a dip switch), NAND on CS2B.  The NAND driver will
+        * notice whether a NAND chip is enabled at probe time.
+        *
+        * H3 support NAND-boot, with a dip switch to put NOR on CS2B and NAND
+        * (which on H2 may be 16bit) on CS3.  Try detecting that in code here,
+        * to avoid probing every possible flash configuration...
+        */
+       nor_resource.end = nor_resource.start = omap_cs3_phys();
+       nor_resource.end += SZ_32M - 1;
+
+       nand_resource.end = nand_resource.start = OMAP_CS2B_PHYS;
+       nand_resource.end += SZ_4K - 1;
+       if (!(omap_request_gpio(H3_NAND_RB_GPIO_PIN)))
+               nand_data.dev_ready = nand_dev_ready;
+
+       /* GPIO10 Func_MUX_CTRL reg bit 29:27, Configure V2 to mode1 as GPIO */
+       /* GPIO10 pullup/down register, Enable pullup on GPIO10 */
+       omap_cfg_reg(V2_1710_GPIO10);
+
+       platform_add_devices(devices, ARRAY_SIZE(devices));
        omap_board_config = h3_config;
        omap_board_config_size = ARRAY_SIZE(h3_config);
        omap_serial_init();
index bd900b7ab33cfdde0335252d376ad3209db16732..dd8069a4a4c6df15fba54b58dbd9c6c7c4456b80 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/platform_device.h>
 #include <linux/delay.h>
 #include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
 #include <linux/mtd/partitions.h>
 
 #include <asm/hardware.h>
@@ -44,7 +45,7 @@ static struct resource smc91x_resources[] = {
        },
 };
 
-static struct mtd_partition p2_partitions[] = {
+static struct mtd_partition nor_partitions[] = {
        /* bootloader (U-Boot, etc) in first sector */
        {
              .name             = "bootloader",
@@ -75,27 +76,47 @@ static struct mtd_partition p2_partitions[] = {
        },
 };
 
-static struct flash_platform_data p2_flash_data = {
+static struct flash_platform_data nor_data = {
        .map_name       = "cfi_probe",
        .width          = 2,
-       .parts          = p2_partitions,
-       .nr_parts       = ARRAY_SIZE(p2_partitions),
+       .parts          = nor_partitions,
+       .nr_parts       = ARRAY_SIZE(nor_partitions),
 };
 
-static struct resource p2_flash_resource = {
+static struct resource nor_resource = {
        .start          = OMAP_CS0_PHYS,
        .end            = OMAP_CS0_PHYS + SZ_32M - 1,
        .flags          = IORESOURCE_MEM,
 };
 
-static struct platform_device p2_flash_device = {
+static struct platform_device nor_device = {
        .name           = "omapflash",
        .id             = 0,
        .dev            = {
-               .platform_data  = &p2_flash_data,
+               .platform_data  = &nor_data,
        },
        .num_resources  = 1,
-       .resource       = &p2_flash_resource,
+       .resource       = &nor_resource,
+};
+
+static struct nand_platform_data nand_data = {
+       .options        = NAND_SAMSUNG_LP_OPTIONS,
+};
+
+static struct resource nand_resource = {
+       .start          = OMAP_CS3_PHYS,
+       .end            = OMAP_CS3_PHYS + SZ_4K - 1,
+       .flags          = IORESOURCE_MEM,
+};
+
+static struct platform_device nand_device = {
+       .name           = "omapnand",
+       .id             = 0,
+       .dev            = {
+               .platform_data  = &nand_data,
+       },
+       .num_resources  = 1,
+       .resource       = &nand_resource,
 };
 
 static struct platform_device smc91x_device = {
@@ -106,10 +127,18 @@ static struct platform_device smc91x_device = {
 };
 
 static struct platform_device *devices[] __initdata = {
-       &p2_flash_device,
+       &nor_device,
+       &nand_device,
        &smc91x_device,
 };
 
+#define P2_NAND_RB_GPIO_PIN    62
+
+static int nand_dev_ready(struct nand_platform_data *data)
+{
+       return omap_get_gpio_datain(P2_NAND_RB_GPIO_PIN);
+}
+
 static struct omap_uart_config perseus2_uart_config __initdata = {
        .enabled_uarts = ((1 << 0) | (1 << 1)),
 };
@@ -126,7 +155,13 @@ static struct omap_board_config_kernel perseus2_config[] = {
 
 static void __init omap_perseus2_init(void)
 {
-       (void) platform_add_devices(devices, ARRAY_SIZE(devices));
+       if (!(omap_request_gpio(P2_NAND_RB_GPIO_PIN)))
+               nand_data.dev_ready = nand_dev_ready;
+
+       omap_cfg_reg(L3_1610_FLASH_CS2B_OE);
+       omap_cfg_reg(M8_1610_FLASH_CS2B_WE);
+
+       platform_add_devices(devices, ARRAY_SIZE(devices));
 
        omap_board_config = perseus2_config;
        omap_board_config_size = ARRAY_SIZE(perseus2_config);
index d6972962f3eb41ceb29f7a3f7bb3f1557f8acfd2..3799be092786e55f340fee3b1ea48f7560ffaf80 100644 (file)
 /*
- *  drivers/mtd/nand/omap-nand-flash.c
+ * drivers/mtd/nand/omap-nand-flash.c
  *
- *  Copyright (c) 2004 Texas Instruments
- *  Jian Zhang <jzhang@ti.com>
- *  Copyright (c) 2004 David Brownell
- *
- *  Derived from drivers/mtd/autcpu12.c
- *
- *  Copyright (c) 2002 Thomas Gleixner <tgxl@linutronix.de>
+ * Copyright (c) 2004 Texas Instruments, Jian Zhang <jzhang@ti.com>
+ * Copyright (c) 2004 David Brownell
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
- *
- *  Overview:
- *   This is a device driver for the NAND flash device found on the
- *   TI H3/H2  boards. It supports 16-bit 32MiB Samsung k9f5616 chip.
- *
  */
 
-#include <linux/slab.h>
 #include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/types.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
 #include <linux/mtd/partitions.h>
+
 #include <asm/io.h>
-#include <asm/arch/hardware.h>
-#include <asm/arch/gpio.h>
-#include <asm/arch/mux.h>
-#include <asm/arch/tc.h>
-#include <asm/sizes.h>
+#include <asm/hardware.h>
 #include <asm/mach-types.h>
+#include <asm/mach/flash.h>
+#include <asm/arch/tc.h>
 
-#define H3_NAND_RB_GPIO_PIN            10
-#define H2_NAND_RB_GPIO_PIN            62
-#define P2_NAND_RB_GPIO_PIN            62
-#define NETSTAR_NAND_RB_GPIO_PIN        1
-/*
- * MTD structure for H3 board
- */
-static struct mtd_info *omap_nand_mtd = NULL;
-
-static void __iomem *omap_nand_flash_base;
+#include <asm/io.h>
+#include <asm/arch/hardware.h>
 
-/*
- * Define partitions for flash devices
- */
+#define        DRIVER_NAME     "omapnand"
 
 #ifdef CONFIG_MTD_PARTITIONS
-static struct mtd_partition static_partition[] = {
-       { .name = "Booting Image",
-         .offset =     0,
-         .size = 64 * 1024,
-         .mask_flags = MTD_WRITEABLE  /* force read-only */
-       },
-       { .name = "U-Boot",
-         .offset =     MTDPART_OFS_APPEND,
-         .size = 256 * 1024,
-          .mask_flags = MTD_WRITEABLE  /* force read-only */
-       },
-       { .name = "U-Boot Environment",
-         .offset =     MTDPART_OFS_APPEND,
-         .size = 192 * 1024
-       },
-       { .name = "Kernel",
-         .offset =     MTDPART_OFS_APPEND,
-         .size = 2 * SZ_1M
-       },
-       { .name = "File System",
-         .size = MTDPART_SIZ_FULL,
-         .offset =     MTDPART_OFS_APPEND,
-       },
-};
-
-const char *part_probes[] = { "cmdlinepart", NULL,  };
-
+static const char *part_probes[] = { "cmdlinepart", NULL };
 #endif
 
-/* H2/H3 maps two address LSBs to CLE and ALE; MSBs make CS_2B */
-#define        MASK_CLE        0x02
-#define        MASK_ALE        0x04
-
+struct omap_nand_info {
+       struct nand_platform_data *pdata;
+       struct mtd_partition    *parts;
+       struct mtd_info         mtd;
+       struct nand_chip        nand;
+};
 
-/* 
+/*
  *     hardware specific access to control-lines
-*/
+ *     NOTE:  boards may use different bits for these!!
+ */
+#define        MASK_CLE        0x02
+#define        MASK_ALE        0x04
 static void omap_nand_hwcontrol(struct mtd_info *mtd, int cmd)
 {
        struct nand_chip *this = mtd->priv;
-       u32 IO_ADDR_W = (u32) this->IO_ADDR_W;
+       unsigned long IO_ADDR_W = (unsigned long) this->IO_ADDR_W;
 
-       IO_ADDR_W &= ~(MASK_ALE|MASK_CLE);
-       switch(cmd){
+       switch (cmd) {
                case NAND_CTL_SETCLE: IO_ADDR_W |= MASK_CLE; break;
+               case NAND_CTL_CLRCLE: IO_ADDR_W &= ~MASK_CLE; break;
                case NAND_CTL_SETALE: IO_ADDR_W |= MASK_ALE; break;
+               case NAND_CTL_CLRALE: IO_ADDR_W &= ~MASK_ALE; break;
        }
        this->IO_ADDR_W = (void __iomem *) IO_ADDR_W;
 }
 
-/*
- *     chip busy R/B detection
- */
-static int omap_nand_ready(struct mtd_info *mtd)
-{
-       if (machine_is_omap_h3())
-               return omap_get_gpio_datain(H3_NAND_RB_GPIO_PIN);
-       if (machine_is_omap_h2())
-               return omap_get_gpio_datain(H2_NAND_RB_GPIO_PIN);
-       if (machine_is_omap_perseus2())
-               return omap_get_gpio_datain(H2_NAND_RB_GPIO_PIN);
-       if (machine_is_netstar())
-               return omap_get_gpio_datain(NETSTAR_NAND_RB_GPIO_PIN);
-       return 0;
-}
-
-/* Scan to find existance of the device at omap_nand_flash_base.
-   This also allocates oob and data internal buffers */
-static int __init probe_nand_chip(void)
+static int omap_nand_dev_ready(struct mtd_info *mtd)
 {
-        struct nand_chip *this;
-
-        this = (struct nand_chip *) (&omap_nand_mtd[1]);
-       
-       /* Initialize structures */
-        memset((char *) this, 0, sizeof(struct nand_chip));
-        
-       this->IO_ADDR_R = omap_nand_flash_base;
-        this->IO_ADDR_W = omap_nand_flash_base;
-        this->options = NAND_SAMSUNG_LP_OPTIONS;
-        this->hwcontrol = omap_nand_hwcontrol;
-        this->eccmode = NAND_ECC_SOFT;
-
-        /* try 16-bit chip first */
-       this->options |= NAND_BUSWIDTH_16;
-        if (nand_scan (omap_nand_mtd, 1)) {
-               if (machine_is_omap_h3()) 
-                       return -ENXIO;
+       struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, mtd);
 
-               /* then try 8-bit chip for H2 */
-               memset((char *) this, 0, sizeof(struct nand_chip));
-               this->IO_ADDR_R = omap_nand_flash_base;
-               this->IO_ADDR_W = omap_nand_flash_base;
-               this->options = NAND_SAMSUNG_LP_OPTIONS;
-               this->hwcontrol = omap_nand_hwcontrol;
-               this->eccmode = NAND_ECC_SOFT;
-                if (nand_scan (omap_nand_mtd, 1)) {
-                        return -ENXIO;
-                }
-        }
-
-       return 0;
+       return info->pdata->dev_ready(info->pdata);
 }
 
-static char nand1_name [] = "nand";
-
-/*
- * Main initialization routine
- */
-int __init omap_nand_init (void)
+static int __devinit omap_nand_probe(struct device *dev)
 {
-       struct nand_chip *this;
-       struct mtd_partition *dynamic_partition = 0;
-       int err = 0;
-       int nandboot = 0;
-
-       if (!(machine_is_omap_h2() || machine_is_omap_h3() || machine_is_netstar() || machine_is_omap_perseus2()))
-               return -ENODEV;
-
-       /* Allocate memory for MTD device structure and private data */
-       omap_nand_mtd = kmalloc (sizeof(struct mtd_info) + sizeof (struct nand_chip),
-                               GFP_KERNEL);
-       if (!omap_nand_mtd) {
-               printk (KERN_WARNING "Unable to allocate NAND MTD device structure.\n");
-               err = -ENOMEM;
-               goto out;
+       struct omap_nand_info           *info;
+       struct platform_device          *pdev = to_platform_device(dev);
+       struct nand_platform_data       *pdata = pdev->dev.platform_data;
+       struct resource                 *res = pdev->resource;
+       unsigned long                   size = res->end - res->start + 1;
+       int                             err;
+
+       info = kmalloc(sizeof(struct omap_nand_info), GFP_KERNEL);
+       if (!info)
+               return -ENOMEM;
+
+       memset(info, 0, sizeof(struct omap_nand_info));
+
+       if (!request_mem_region(res->start, size, dev->driver->name)) {
+               err = -EBUSY;
+               goto out_free_info;
        }
 
-       /* Get pointer to private data */
-       this = (struct nand_chip *) (&omap_nand_mtd[1]);
-
-       /* Initialize structures */
-       memset((char *) omap_nand_mtd, 0, sizeof(struct mtd_info) + sizeof(struct nand_chip));
-
-       /* Link the private data with the MTD structure */
-       omap_nand_mtd->priv = this;
-
-       if (machine_is_omap_h2() || machine_is_omap_perseus2()) {
-               /* FIXME on H2, R/B needs M7_1610_GPIO62 ... */
-               this->chip_delay = 15;
-               omap_cfg_reg(L3_1610_FLASH_CS2B_OE);
-               omap_cfg_reg(M8_1610_FLASH_CS2B_WE);
-       } else if (machine_is_omap_h3()) {
-               if (omap_request_gpio(H3_NAND_RB_GPIO_PIN) != 0) {
-                       printk(KERN_ERR "NAND: Unable to get GPIO pin for R/B, use delay\n");
-                       /* 15 us command delay time */
-                       this->chip_delay = 15;
-               } else {
-                       /* GPIO10 for input. it is in GPIO1 module */
-                       omap_set_gpio_direction(H3_NAND_RB_GPIO_PIN, 1);
-               
-                       /* GPIO10 Func_MUX_CTRL reg bit 29:27, Configure V2 to mode1 as GPIO */
-                       /* GPIO10 pullup/down register, Enable pullup on GPIO10 */
-                       omap_cfg_reg(V2_1710_GPIO10);
-
-                       this->dev_ready = omap_nand_ready;
-               }
-       } else if (machine_is_netstar()) {
-               if (omap_request_gpio(NETSTAR_NAND_RB_GPIO_PIN) != 0) {
-                       printk(KERN_ERR "NAND: Unable to get GPIO pin for R/B, use delay\n");
-                       /* 15 us command delay time */
-                       this->chip_delay = 15;
-               } else {
-                       omap_set_gpio_direction(NETSTAR_NAND_RB_GPIO_PIN, 1);
-                       this->dev_ready = omap_nand_ready;
-               }
+       info->nand.IO_ADDR_R = ioremap(res->start, size);
+       if (!info->nand.IO_ADDR_R) {
+               err = -ENOMEM;
+               goto out_release_mem_region;
        }
-
-        /* try the first address */
-       omap_nand_flash_base = ioremap(OMAP_NAND_FLASH_START1, SZ_4K);
-       omap_nand_mtd->name = nand1_name;
-       if (probe_nand_chip()){
-               nandboot = 1;
-               /* try the second address */
-               iounmap(omap_nand_flash_base);
-               omap_nand_flash_base = ioremap(OMAP_NAND_FLASH_START2, SZ_4K);
-               if (probe_nand_chip()){
-                       iounmap(omap_nand_flash_base);
-                        err = -ENXIO;
-                        goto out_mtd;
+       info->nand.IO_ADDR_W = info->nand.IO_ADDR_R;
+       info->nand.hwcontrol = omap_nand_hwcontrol;
+       info->nand.eccmode = NAND_ECC_SOFT;
+       info->nand.options = pdata->options;
+       if (pdata->dev_ready)
+               info->nand.dev_ready = omap_nand_dev_ready;
+       else
+               info->nand.chip_delay = 20;
+
+       info->mtd.name = pdev->dev.bus_id;
+       info->mtd.priv = &info->nand;
+
+       info->pdata = pdata;
+
+       /* DIP switches on H2 and some other boards change between 8 and 16 bit
+        * bus widths for flash.  Try the other width if the first try fails.
+        */
+       if (nand_scan(&info->mtd, 1)) {
+               info->nand.options ^= NAND_BUSWIDTH_16;
+               if (nand_scan(&info->mtd, 1)) {
+                       err = -ENXIO;
+                       goto out_iounmap;
                }
        }
+       info->mtd.owner = THIS_MODULE;
 
-       /* Register the partitions */
-       switch(omap_nand_mtd->size) {
-       case SZ_128M:
-               if (!(machine_is_netstar()))
-                       goto out_unsupported;
-               /* fall through */
-       case SZ_64M:
-               if (!(machine_is_netstar() || machine_is_omap_perseus2()))
-                       goto out_unsupported;
-               /* fall through */
-       case SZ_32M:
 #ifdef CONFIG_MTD_PARTITIONS
-               err = parse_mtd_partitions(omap_nand_mtd, part_probes,
-                                       &dynamic_partition, 0);
-               if (err > 0)
-                       err = add_mtd_partitions(omap_nand_mtd,
-                                       dynamic_partition, err);
-               else if (nandboot)
-                       err = add_mtd_partitions(omap_nand_mtd,
-                                       static_partition,
-                                       ARRAY_SIZE(static_partition));
-               else
+       err = parse_mtd_partitions(&info->mtd, part_probes, &info->parts, 0);
+       if (err > 0)
+               add_mtd_partitions(&info->mtd, info->parts, err);
+       else if (err < 0 && pdata->parts)
+               add_mtd_partitions(&info->mtd, pdata->parts, pdata->nr_parts);
+       else
 #endif
-                       err = add_mtd_device(omap_nand_mtd);
-               if (err)
-                       goto out_buf;
-               break;
-out_unsupported:
-       default:
-               printk(KERN_WARNING "Unsupported NAND device\n");
-               err = -ENXIO;
-               goto out_buf;
-       }
+               add_mtd_device(&info->mtd);
 
-       goto out;
+       dev_set_drvdata(&pdev->dev, info);
 
-out_buf:
-       nand_release (omap_nand_mtd);
-       if (this->dev_ready) {
-               if (machine_is_omap_h2())
-                       omap_free_gpio(H2_NAND_RB_GPIO_PIN);
-               else if (machine_is_omap_perseus2())
-                       omap_free_gpio(P2_NAND_RB_GPIO_PIN);
-               else if (machine_is_omap_h3())
-                       omap_free_gpio(H3_NAND_RB_GPIO_PIN);
-               else if (machine_is_netstar())
-                       omap_free_gpio(NETSTAR_NAND_RB_GPIO_PIN);
-       }
-       iounmap(omap_nand_flash_base);
+       return 0;
+
+out_iounmap:
+       iounmap(info->nand.IO_ADDR_R);
+out_release_mem_region:
+       release_mem_region(res->start, size);
+out_free_info:
+       kfree(info);
 
-out_mtd:
-       kfree (omap_nand_mtd);
-out:
        return err;
 }
 
-module_init(omap_nand_init);
+static int __devexit omap_nand_remove(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct omap_nand_info *info = dev_get_drvdata(&pdev->dev);
+
+       dev_set_drvdata(&pdev->dev, NULL);
+       /* Release NAND device, its internal structures and partitions */
+       nand_release(&info->mtd);
+       iounmap(info->nand.IO_ADDR_R);
+       kfree(info);
+       return 0;
+}
 
-/*
- * Clean up routine
- */
-static void __exit omap_nand_cleanup (void)
+static struct device_driver omap_nand_driver = {
+       .name   = DRIVER_NAME,
+       .bus    = &platform_bus_type,
+       .probe  = omap_nand_probe,
+       .remove = __devexit_p(omap_nand_remove),
+};
+MODULE_ALIAS(DRIVER_NAME);
+
+static int __init omap_nand_init(void)
 {
-        struct nand_chip *this = omap_nand_mtd->priv;
-       if (this->dev_ready) {
-               if (machine_is_omap_h2())
-                       omap_free_gpio(H2_NAND_RB_GPIO_PIN);
-               else if (machine_is_omap_h2())
-                       omap_free_gpio(H2_NAND_RB_GPIO_PIN);
-               else if (machine_is_omap_h3())
-                       omap_free_gpio(H3_NAND_RB_GPIO_PIN);
-               else if (machine_is_netstar())
-                       omap_free_gpio(NETSTAR_NAND_RB_GPIO_PIN);
-       }
+       return driver_register(&omap_nand_driver);
+}
 
-       /* nand_release frees MTD partitions, MTD structure
-          and nand internal buffers*/
-       nand_release (omap_nand_mtd);
-       kfree (omap_nand_mtd);
-       iounmap(omap_nand_flash_base);
+static void __exit omap_nand_exit(void)
+{
+       driver_unregister(&omap_nand_driver);
 }
 
-module_exit(omap_nand_cleanup);
+module_init(omap_nand_init);
+module_exit(omap_nand_exit);
 
 MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Jian Zhang <jzhang@ti.com>");
-MODULE_DESCRIPTION("Glue layer for NAND flash on H2/H3 boards");
+MODULE_AUTHOR("Jian Zhang <jzhang@ti.com> (and others)");
+MODULE_DESCRIPTION("Glue layer for NAND flash on TI OMAP boards");
+
index 39ca5a31aeea7144982c9c2658daa8bd154d72be..b2888ef9e9b4ada2a72ac22ae39ef6508cf6fe56 100644 (file)
@@ -34,9 +34,5 @@
 /* At OMAP1610 Innovator the Ethernet is directly connected to CS1 */
 #define OMAP1610_ETHR_START            0x04000300
 
-/* Samsung NAND flash at CS2B or CS3(NAND Boot) */
-#define OMAP_NAND_FLASH_START1           0x0A000000 /* CS2B */
-#define OMAP_NAND_FLASH_START2           0x0C000000 /* CS3 */
-
 #endif /*  __ASM_ARCH_OMAP_H2_H */
 
index 1b12c1dcc2faf54c30a0b2b211ce999e0fa3a2b2..761ea0a178972a961ca9e8a7ee4726bc1c30dcba 100644 (file)
 /* In OMAP1710 H3 the Ethernet is directly connected to CS1 */
 #define OMAP1710_ETHR_START            0x04000300
 
-/* Samsung NAND flash at CS2B or CS3(NAND Boot) */
-#define OMAP_NAND_FLASH_START1           0x0A000000 /* CS2B */
-#define OMAP_NAND_FLASH_START2           0x0C000000 /* CS3 */
-
 #define MAXIRQNUM                      (IH_BOARD_BASE)
 #define MAXFIQNUM                      MAXIRQNUM
 #define MAXSWINUM                      MAXIRQNUM
index 691e52a52b433f4fe5cf43e9feeabefdd03e04ee..eb74420cb43983ec4a8225614574fed82fbe0178 100644 (file)
@@ -42,8 +42,4 @@
 
 #define NR_IRQS                        (MAXIRQNUM + 1)
 
-/* Samsung NAND flash at CS2B or CS3(NAND Boot) */
-#define OMAP_NAND_FLASH_START1    0x0A000000 /* CS2B */
-#define OMAP_NAND_FLASH_START2    0x0C000000 /* CS3 */
-
 #endif
index 05b029ef6371c6203b1471897490bebce8920815..664b708d2576689a80a6bb5199cb247cebfb6ffd 100644 (file)
@@ -36,4 +36,18 @@ struct flash_platform_data {
        unsigned int    nr_parts;
 };
 
+/**
+ * struct nand_platform_data - platform data describing NAND flash banks
+ * @dev_ready: tests if the NAND flash is ready (READY signal is high)
+ * @options:   bitmask for nand_chip.options
+ * @parts:     optional array of mtd_partitions for static partitioning
+ * @nr_parts:  number of mtd_partitions for static partitoning
+ */
+struct nand_platform_data {
+       int             (*dev_ready)(struct nand_platform_data *data);
+       unsigned int    options;
+       struct mtd_partition *parts;
+       unsigned int    nr_parts;
+};
+
 #endif