#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>
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",
}
};
-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[] = {
};
static struct platform_device *h2_devices[] __initdata = {
- &h2_flash_device,
+ &h2_nor_device,
+ &h2_nand_device,
&h2_smc91x_device,
};
{ 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 */
#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>
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",
}
};
-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[] = {
};
static struct platform_device *devices[] __initdata = {
- &flash_device,
+ &nor_device,
+ &nand_device,
&smc91x_device,
&intlat_device,
};
{ 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();
#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>
},
};
-static struct mtd_partition p2_partitions[] = {
+static struct mtd_partition nor_partitions[] = {
/* bootloader (U-Boot, etc) in first sector */
{
.name = "bootloader",
},
};
-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 = {
};
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)),
};
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);
/*
- * 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");
+