diff options
Diffstat (limited to 'drivers/mtd/maps')
-rw-r--r-- | drivers/mtd/maps/Kconfig | 45 | ||||
-rw-r--r-- | drivers/mtd/maps/Makefile | 6 | ||||
-rw-r--r-- | drivers/mtd/maps/alchemy-flash.c | 14 | ||||
-rw-r--r-- | drivers/mtd/maps/intel_vr_nor.c | 298 | ||||
-rw-r--r-- | drivers/mtd/maps/lubbock-flash.c | 170 | ||||
-rw-r--r-- | drivers/mtd/maps/mainstone-flash.c | 181 | ||||
-rw-r--r-- | drivers/mtd/maps/nettel.c | 65 | ||||
-rw-r--r-- | drivers/mtd/maps/ocelot.c | 175 | ||||
-rw-r--r-- | drivers/mtd/maps/physmap_of.c | 350 | ||||
-rw-r--r-- | drivers/mtd/maps/pmcmsp-flash.c | 22 | ||||
-rw-r--r-- | drivers/mtd/maps/pmcmsp-ramroot.c | 1 | ||||
-rw-r--r-- | drivers/mtd/maps/pq2fads.c | 88 | ||||
-rw-r--r-- | drivers/mtd/maps/pxa2xx-flash.c | 200 | ||||
-rw-r--r-- | drivers/mtd/maps/tqm834x.c | 286 |
14 files changed, 745 insertions, 1156 deletions
diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig index cc6c73442435..2a2a125b0c76 100644 --- a/drivers/mtd/maps/Kconfig +++ b/drivers/mtd/maps/Kconfig @@ -163,20 +163,12 @@ config MTD_SBC_GXX More info at <http://www.arcomcontrols.com/products/icp/pc104/processors/SBC_GX1.htm>. -config MTD_LUBBOCK - tristate "CFI Flash device mapped on Intel Lubbock XScale eval board" - depends on ARCH_LUBBOCK && MTD_CFI_INTELEXT && MTD_PARTITIONS - help - This provides a driver for the on-board flash of the Intel - 'Lubbock' XScale evaluation board. - -config MTD_MAINSTONE - tristate "CFI Flash device mapped on Intel Mainstone XScale eval board" - depends on MACH_MAINSTONE && MTD_CFI_INTELEXT +config MTD_PXA2XX + tristate "CFI Flash device mapped on Intel XScale PXA2xx based boards" + depends on (PXA25x || PXA27x) && MTD_CFI_INTELEXT select MTD_PARTITIONS help - This provides a driver for the on-board flash of the Intel - 'Mainstone PXA27x evaluation board. + This provides a driver for the NOR flash attached to a PXA2xx chip. config MTD_OCTAGON tristate "JEDEC Flash device mapped on Octagon 5066 SBC" @@ -354,7 +346,7 @@ config MTD_CFI_FLAGADM config MTD_WALNUT tristate "Flash device mapped on IBM 405GP Walnut" - depends on MTD_JEDECPROBE && WALNUT + depends on MTD_JEDECPROBE && WALNUT && !PPC_MERGE help This enables access routines for the flash chips on the IBM 405GP Walnut board. If you have one of these boards and would like to @@ -362,7 +354,7 @@ config MTD_WALNUT config MTD_EBONY tristate "Flash devices mapped on IBM 440GP Ebony" - depends on MTD_JEDECPROBE && EBONY + depends on MTD_JEDECPROBE && EBONY && !PPC_MERGE help This enables access routines for the flash chips on the IBM 440GP Ebony board. If you have one of these boards and would like to @@ -370,7 +362,7 @@ config MTD_EBONY config MTD_OCOTEA tristate "Flash devices mapped on IBM 440GX Ocotea" - depends on MTD_CFI && OCOTEA + depends on MTD_CFI && OCOTEA && !PPC_MERGE help This enables access routines for the flash chips on the IBM 440GX Ocotea board. If you have one of these boards and would like to @@ -384,22 +376,6 @@ config MTD_REDWOOD Redwood board. If you have one of these boards and would like to use the flash chips on it, say 'Y'. -config MTD_TQM834x - tristate "Flash device mapped on TQ Components TQM834x Boards" - depends on MTD_CFI && TQM834x - help - This enables access routines for the flash chips on the - TQ Components TQM834x boards. If you have one of these boards - and would like to use the flash chips on it, say 'Y'. - -config MTD_OCELOT - tristate "Momenco Ocelot boot flash device" - depends on MOMENCO_OCELOT - help - This enables access routines for the boot flash device and for the - NVRAM on the Momenco Ocelot board. If you have one of these boards - and would like access to either of these, say 'Y'. - config MTD_SOLUTIONENGINE tristate "CFI Flash device mapped on Hitachi SolutionEngine" depends on SUPERH && MTD_CFI && MTD_REDBOOT_PARTS @@ -605,6 +581,13 @@ config MTD_SHARP_SL help This enables access to the flash chip on the Sharp SL Series of PDAs. +config MTD_INTEL_VR_NOR + tristate "NOR flash on Intel Vermilion Range Expansion Bus CS0" + depends on PCI + help + Map driver for a NOR flash bank located on the Expansion Bus of the + Intel Vermilion Range chipset. + config MTD_PLATRAM tristate "Map driver for platform device RAM (mtd-ram)" select MTD_RAM diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile index 970b189271a2..316382a1401b 100644 --- a/drivers/mtd/maps/Makefile +++ b/drivers/mtd/maps/Makefile @@ -20,8 +20,7 @@ obj-$(CONFIG_MTD_ESB2ROM) += esb2rom.o obj-$(CONFIG_MTD_ICHXROM) += ichxrom.o obj-$(CONFIG_MTD_CK804XROM) += ck804xrom.o obj-$(CONFIG_MTD_TSUNAMI) += tsunami_flash.o -obj-$(CONFIG_MTD_LUBBOCK) += lubbock-flash.o -obj-$(CONFIG_MTD_MAINSTONE) += mainstone-flash.o +obj-$(CONFIG_MTD_PXA2XX) += pxa2xx-flash.o obj-$(CONFIG_MTD_MBX860) += mbx860.o obj-$(CONFIG_MTD_CEIVA) += ceiva.o obj-$(CONFIG_MTD_OCTAGON) += octagon-5066.o @@ -43,7 +42,6 @@ obj-$(CONFIG_MTD_SUN_UFLASH) += sun_uflash.o obj-$(CONFIG_MTD_VMAX) += vmax301.o obj-$(CONFIG_MTD_SCx200_DOCFLASH)+= scx200_docflash.o obj-$(CONFIG_MTD_DBOX2) += dbox2-flash.o -obj-$(CONFIG_MTD_OCELOT) += ocelot.o obj-$(CONFIG_MTD_SOLUTIONENGINE)+= solutionengine.o obj-$(CONFIG_MTD_PCI) += pci.o obj-$(CONFIG_MTD_ALCHEMY) += alchemy-flash.o @@ -70,4 +68,4 @@ obj-$(CONFIG_MTD_SHARP_SL) += sharpsl-flash.o obj-$(CONFIG_MTD_PLATRAM) += plat-ram.o obj-$(CONFIG_MTD_OMAP_NOR) += omap_nor.o obj-$(CONFIG_MTD_MTX1) += mtx-1_flash.o -obj-$(CONFIG_MTD_TQM834x) += tqm834x.o +obj-$(CONFIG_MTD_INTEL_VR_NOR) += intel_vr_nor.o diff --git a/drivers/mtd/maps/alchemy-flash.c b/drivers/mtd/maps/alchemy-flash.c index 84fbe0e8c47e..82811bcb0436 100644 --- a/drivers/mtd/maps/alchemy-flash.c +++ b/drivers/mtd/maps/alchemy-flash.c @@ -75,13 +75,6 @@ #define BOARD_FLASH_WIDTH 2 /* 16-bits */ #endif -#ifdef CONFIG_MIPS_HYDROGEN3 -#define BOARD_MAP_NAME "Hydrogen3 Flash" -#define BOARD_FLASH_SIZE 0x02000000 /* 32MB */ -#define BOARD_FLASH_WIDTH 4 /* 32-bits */ -#define USE_LOCAL_ACCESSORS /* why? */ -#endif - #ifdef CONFIG_MIPS_BOSPORUS #define BOARD_MAP_NAME "Bosporus Flash" #define BOARD_FLASH_SIZE 0x01000000 /* 16MB */ @@ -130,13 +123,6 @@ int __init alchemy_mtd_init(void) window_addr = 0x20000000 - BOARD_FLASH_SIZE; window_size = BOARD_FLASH_SIZE; -#ifdef CONFIG_MIPS_MIRAGE_WHY - /* Boot ROM flash bank only; no user bank */ - window_addr = 0x1C000000; - window_size = 0x04000000; - /* USERFS from 0x1C00 0000 to 0x1FC00000 */ - alchemy_partitions[0].size = 0x03C00000; -#endif /* * Static partition definition selection diff --git a/drivers/mtd/maps/intel_vr_nor.c b/drivers/mtd/maps/intel_vr_nor.c new file mode 100644 index 000000000000..1e7814ae212a --- /dev/null +++ b/drivers/mtd/maps/intel_vr_nor.c @@ -0,0 +1,298 @@ +/* + * drivers/mtd/maps/intel_vr_nor.c + * + * An MTD map driver for a NOR flash bank on the Expansion Bus of the Intel + * Vermilion Range chipset. + * + * The Vermilion Range Expansion Bus supports four chip selects, each of which + * has 64MiB of address space. The 2nd BAR of the Expansion Bus PCI Device + * is a 256MiB memory region containing the address spaces for all four of the + * chip selects, with start addresses hardcoded on 64MiB boundaries. + * + * This map driver only supports NOR flash on chip select 0. The buswidth + * (either 8 bits or 16 bits) is determined by reading the Expansion Bus Timing + * and Control Register for Chip Select 0 (EXP_TIMING_CS0). This driver does + * not modify the value in the EXP_TIMING_CS0 register except to enable writing + * and disable boot acceleration. The timing parameters in the register are + * assumed to have been properly initialized by the BIOS. The reset default + * timing parameters are maximally conservative (slow), so access to the flash + * will be slower than it should be if the BIOS has not initialized the timing + * parameters. + * + * Author: Andy Lowe <alowe@mvista.com> + * + * 2006 (c) MontaVista Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/pci.h> +#include <linux/init.h> +#include <linux/mtd/mtd.h> +#include <linux/mtd/map.h> +#include <linux/mtd/partitions.h> +#include <linux/mtd/cfi.h> +#include <linux/mtd/flashchip.h> + +#define DRV_NAME "vr_nor" + +struct vr_nor_mtd { + void __iomem *csr_base; + struct map_info map; + struct mtd_info *info; + int nr_parts; + struct pci_dev *dev; +}; + +/* Expansion Bus Configuration and Status Registers are in BAR 0 */ +#define EXP_CSR_MBAR 0 +/* Expansion Bus Memory Window is BAR 1 */ +#define EXP_WIN_MBAR 1 +/* Maximum address space for Chip Select 0 is 64MiB */ +#define CS0_SIZE 0x04000000 +/* Chip Select 0 is at offset 0 in the Memory Window */ +#define CS0_START 0x0 +/* Chip Select 0 Timing Register is at offset 0 in CSR */ +#define EXP_TIMING_CS0 0x00 +#define TIMING_CS_EN (1 << 31) /* Chip Select Enable */ +#define TIMING_BOOT_ACCEL_DIS (1 << 8) /* Boot Acceleration Disable */ +#define TIMING_WR_EN (1 << 1) /* Write Enable */ +#define TIMING_BYTE_EN (1 << 0) /* 8-bit vs 16-bit bus */ +#define TIMING_MASK 0x3FFF0000 + +static void __devexit vr_nor_destroy_partitions(struct vr_nor_mtd *p) +{ + if (p->nr_parts > 0) { +#if defined(CONFIG_MTD_PARTITIONS) || defined(CONFIG_MTD_PARTITIONS_MODULE) + del_mtd_partitions(p->info); +#endif + } else + del_mtd_device(p->info); +} + +static int __devinit vr_nor_init_partitions(struct vr_nor_mtd *p) +{ + int err = 0; +#if defined(CONFIG_MTD_PARTITIONS) || defined(CONFIG_MTD_PARTITIONS_MODULE) + struct mtd_partition *parts; + static const char *part_probes[] = { "cmdlinepart", NULL }; +#endif + + /* register the flash bank */ +#if defined(CONFIG_MTD_PARTITIONS) || defined(CONFIG_MTD_PARTITIONS_MODULE) + /* partition the flash bank */ + p->nr_parts = parse_mtd_partitions(p->info, part_probes, &parts, 0); + if (p->nr_parts > 0) + err = add_mtd_partitions(p->info, parts, p->nr_parts); +#endif + if (p->nr_parts <= 0) + err = add_mtd_device(p->info); + + return err; +} + +static void __devexit vr_nor_destroy_mtd_setup(struct vr_nor_mtd *p) +{ + map_destroy(p->info); +} + +static int __devinit vr_nor_mtd_setup(struct vr_nor_mtd *p) +{ + static const char *probe_types[] = + { "cfi_probe", "jedec_probe", NULL }; + const char **type; + + for (type = probe_types; !p->info && *type; type++) + p->info = do_map_probe(*type, &p->map); + if (!p->info) + return -ENODEV; + + p->info->owner = THIS_MODULE; + + return 0; +} + +static void __devexit vr_nor_destroy_maps(struct vr_nor_mtd *p) +{ + unsigned int exp_timing_cs0; + + /* write-protect the flash bank */ + exp_timing_cs0 = readl(p->csr_base + EXP_TIMING_CS0); + exp_timing_cs0 &= ~TIMING_WR_EN; + writel(exp_timing_cs0, p->csr_base + EXP_TIMING_CS0); + + /* unmap the flash window */ + iounmap(p->map.virt); + + /* unmap the csr window */ + iounmap(p->csr_base); +} + +/* + * Initialize the map_info structure and map the flash. + * Returns 0 on success, nonzero otherwise. + */ +static int __devinit vr_nor_init_maps(struct vr_nor_mtd *p) +{ + unsigned long csr_phys, csr_len; + unsigned long win_phys, win_len; + unsigned int exp_timing_cs0; + int err; + + csr_phys = pci_resource_start(p->dev, EXP_CSR_MBAR); + csr_len = pci_resource_len(p->dev, EXP_CSR_MBAR); + win_phys = pci_resource_start(p->dev, EXP_WIN_MBAR); + win_len = pci_resource_len(p->dev, EXP_WIN_MBAR); + + if (!csr_phys || !csr_len || !win_phys || !win_len) + return -ENODEV; + + if (win_len < (CS0_START + CS0_SIZE)) + return -ENXIO; + + p->csr_base = ioremap_nocache(csr_phys, csr_len); + if (!p->csr_base) + return -ENOMEM; + + exp_timing_cs0 = readl(p->csr_base + EXP_TIMING_CS0); + if (!(exp_timing_cs0 & TIMING_CS_EN)) { + dev_warn(&p->dev->dev, "Expansion Bus Chip Select 0 " + "is disabled.\n"); + err = -ENODEV; + goto release; + } + if ((exp_timing_cs0 & TIMING_MASK) == TIMING_MASK) { + dev_warn(&p->dev->dev, "Expansion Bus Chip Select 0 " + "is configured for maximally slow access times.\n"); + } + p->map.name = DRV_NAME; + p->map.bankwidth = (exp_timing_cs0 & TIMING_BYTE_EN) ? 1 : 2; + p->map.phys = win_phys + CS0_START; + p->map.size = CS0_SIZE; + p->map.virt = ioremap_nocache(p->map.phys, p->map.size); + if (!p->map.virt) { + err = -ENOMEM; + goto release; + } + simple_map_init(&p->map); + + /* Enable writes to flash bank */ + exp_timing_cs0 |= TIMING_BOOT_ACCEL_DIS | TIMING_WR_EN; + writel(exp_timing_cs0, p->csr_base + EXP_TIMING_CS0); + + return 0; + + release: + iounmap(p->csr_base); + return err; +} + +static struct pci_device_id vr_nor_pci_ids[] = { + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x500D)}, + {0,} +}; + +static void __devexit vr_nor_pci_remove(struct pci_dev *dev) +{ + struct vr_nor_mtd *p = pci_get_drvdata(dev); + + pci_set_drvdata(dev, NULL); + vr_nor_destroy_partitions(p); + vr_nor_destroy_mtd_setup(p); + vr_nor_destroy_maps(p); + kfree(p); + pci_release_regions(dev); + pci_disable_device(dev); +} + +static int __devinit +vr_nor_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) +{ + struct vr_nor_mtd *p = NULL; + unsigned int exp_timing_cs0; + int err; + + err = pci_enable_device(dev); + if (err) + goto out; + + err = pci_request_regions(dev, DRV_NAME); + if (err) + goto disable_dev; + + p = kzalloc(sizeof(*p), GFP_KERNEL); + err = -ENOMEM; + if (!p) + goto release; + + p->dev = dev; + + err = vr_nor_init_maps(p); + if (err) + goto release; + + err = vr_nor_mtd_setup(p); + if (err) + goto destroy_maps; + + err = vr_nor_init_partitions(p); + if (err) + goto destroy_mtd_setup; + + pci_set_drvdata(dev, p); + + return 0; + + destroy_mtd_setup: + map_destroy(p->info); + + destroy_maps: + /* write-protect the flash bank */ + exp_timing_cs0 = readl(p->csr_base + EXP_TIMING_CS0); + exp_timing_cs0 &= ~TIMING_WR_EN; + writel(exp_timing_cs0, p->csr_base + EXP_TIMING_CS0); + + /* unmap the flash window */ + iounmap(p->map.virt); + + /* unmap the csr window */ + iounmap(p->csr_base); + + release: + kfree(p); + pci_release_regions(dev); + + disable_dev: + pci_disable_device(dev); + + out: + return err; +} + +static struct pci_driver vr_nor_pci_driver = { + .name = DRV_NAME, + .probe = vr_nor_pci_probe, + .remove = __devexit_p(vr_nor_pci_remove), + .id_table = vr_nor_pci_ids, +}; + +static int __init vr_nor_mtd_init(void) +{ + return pci_register_driver(&vr_nor_pci_driver); +} + +static void __exit vr_nor_mtd_exit(void) +{ + pci_unregister_driver(&vr_nor_pci_driver); +} + +module_init(vr_nor_mtd_init); +module_exit(vr_nor_mtd_exit); + +MODULE_AUTHOR("Andy Lowe"); +MODULE_DESCRIPTION("MTD map driver for NOR flash on Intel Vermilion Range"); +MODULE_LICENSE("GPL"); +MODULE_DEVICE_TABLE(pci, vr_nor_pci_ids); diff --git a/drivers/mtd/maps/lubbock-flash.c b/drivers/mtd/maps/lubbock-flash.c deleted file mode 100644 index 1aa0447c5e66..000000000000 --- a/drivers/mtd/maps/lubbock-flash.c +++ /dev/null @@ -1,170 +0,0 @@ -/* - * $Id: lubbock-flash.c,v 1.21 2005/11/07 11:14:27 gleixner Exp $ - * - * Map driver for the Lubbock developer platform. - * - * Author: Nicolas Pitre - * Copyright: (C) 2001 MontaVista Software Inc. - * - * 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. - */ - -#include <linux/module.h> -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/slab.h> - -#include <linux/dma-mapping.h> -#include <linux/mtd/mtd.h> -#include <linux/mtd/map.h> -#include <linux/mtd/partitions.h> - -#include <asm/io.h> -#include <asm/hardware.h> -#include <asm/arch/pxa-regs.h> -#include <asm/arch/lubbock.h> - - -#define ROM_ADDR 0x00000000 -#define FLASH_ADDR 0x04000000 - -#define WINDOW_SIZE 64*1024*1024 - -static void lubbock_map_inval_cache(struct map_info *map, unsigned long from, ssize_t len) -{ - consistent_sync((char *)map->cached + from, len, DMA_FROM_DEVICE); -} - -static struct map_info lubbock_maps[2] = { { - .size = WINDOW_SIZE, - .phys = 0x00000000, - .inval_cache = lubbock_map_inval_cache, -}, { - .size = WINDOW_SIZE, - .phys = 0x04000000, - .inval_cache = lubbock_map_inval_cache, -} }; - -static struct mtd_partition lubbock_partitions[] = { - { - .name = "Bootloader", - .size = 0x00040000, - .offset = 0, - .mask_flags = MTD_WRITEABLE /* force read-only */ - },{ - .name = "Kernel", - .size = 0x00100000, - .offset = 0x00040000, - },{ - .name = "Filesystem", - .size = MTDPART_SIZ_FULL, - .offset = 0x00140000 - } -}; - -static struct mtd_info *mymtds[2]; -static struct mtd_partition *parsed_parts[2]; -static int nr_parsed_parts[2]; - -static const char *probes[] = { "RedBoot", "cmdlinepart", NULL }; - -static int __init init_lubbock(void) -{ - int flashboot = (LUB_CONF_SWITCHES & 1); - int ret = 0, i; - - lubbock_maps[0].bankwidth = lubbock_maps[1].bankwidth = - (BOOT_DEF & 1) ? 2 : 4; - - /* Compensate for the nROMBT switch which swaps the flash banks */ - printk(KERN_NOTICE "Lubbock configured to boot from %s (bank %d)\n", - flashboot?"Flash":"ROM", flashboot); - - lubbock_maps[flashboot^1].name = "Lubbock Application Flash"; - lubbock_maps[flashboot].name = "Lubbock Boot ROM"; - - for (i = 0; i < 2; i++) { - lubbock_maps[i].virt = ioremap(lubbock_maps[i].phys, WINDOW_SIZE); - if (!lubbock_maps[i].virt) { - printk(KERN_WARNING "Failed to ioremap %s\n", lubbock_maps[i].name); - if (!ret) - ret = -ENOMEM; - continue; - } - lubbock_maps[i].cached = ioremap_cached(lubbock_maps[i].phys, WINDOW_SIZE); - if (!lubbock_maps[i].cached) - printk(KERN_WARNING "Failed to ioremap cached %s\n", lubbock_maps[i].name); - simple_map_init(&lubbock_maps[i]); - - printk(KERN_NOTICE "Probing %s at physical address 0x%08lx (%d-bit bankwidth)\n", - lubbock_maps[i].name, lubbock_maps[i].phys, - lubbock_maps[i].bankwidth * 8); - - mymtds[i] = do_map_probe("cfi_probe", &lubbock_maps[i]); - - if (!mymtds[i]) { - iounmap((void *)lubbock_maps[i].virt); - if (lubbock_maps[i].cached) - iounmap(lubbock_maps[i].cached); - if (!ret) - ret = -EIO; - continue; - } - mymtds[i]->owner = THIS_MODULE; - - ret = parse_mtd_partitions(mymtds[i], probes, - &parsed_parts[i], 0); - - if (ret > 0) - nr_parsed_parts[i] = ret; - } - - if (!mymtds[0] && !mymtds[1]) - return ret; - - for (i = 0; i < 2; i++) { - if (!mymtds[i]) { - printk(KERN_WARNING "%s is absent. Skipping\n", lubbock_maps[i].name); - } else if (nr_parsed_parts[i]) { - add_mtd_partitions(mymtds[i], parsed_parts[i], nr_parsed_parts[i]); - } else if (!i) { - printk("Using static partitions on %s\n", lubbock_maps[i].name); - add_mtd_partitions(mymtds[i], lubbock_partitions, ARRAY_SIZE(lubbock_partitions)); - } else { - printk("Registering %s as whole device\n", lubbock_maps[i].name); - add_mtd_device(mymtds[i]); - } - } - return 0; -} - -static void __exit cleanup_lubbock(void) -{ - int i; - for (i = 0; i < 2; i++) { - if (!mymtds[i]) - continue; - - if (nr_parsed_parts[i] || !i) - del_mtd_partitions(mymtds[i]); - else - del_mtd_device(mymtds[i]); - - map_destroy(mymtds[i]); - iounmap((void *)lubbock_maps[i].virt); - if (lubbock_maps[i].cached) - iounmap(lubbock_maps[i].cached); - - kfree(parsed_parts[i]); - } -} - -module_init(init_lubbock); -module_exit(cleanup_lubbock); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Nicolas Pitre <nico@cam.org>"); -MODULE_DESCRIPTION("MTD map driver for Intel Lubbock"); diff --git a/drivers/mtd/maps/mainstone-flash.c b/drivers/mtd/maps/mainstone-flash.c deleted file mode 100644 index eaa4bbb868a3..000000000000 --- a/drivers/mtd/maps/mainstone-flash.c +++ /dev/null @@ -1,181 +0,0 @@ -/* - * $Id: $ - * - * Map driver for the Mainstone developer platform. - * - * Author: Nicolas Pitre - * Copyright: (C) 2001 MontaVista Software Inc. - * - * 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. - */ - -#include <linux/module.h> -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/dma-mapping.h> -#include <linux/slab.h> - -#include <linux/mtd/mtd.h> -#include <linux/mtd/map.h> -#include <linux/mtd/partitions.h> - -#include <asm/io.h> -#include <asm/hardware.h> -#include <asm/arch/pxa-regs.h> -#include <asm/arch/mainstone.h> - - -#define ROM_ADDR 0x00000000 -#define FLASH_ADDR 0x04000000 - -#define WINDOW_SIZE 0x04000000 - -static void mainstone_map_inval_cache(struct map_info *map, unsigned long from, - ssize_t len) -{ - consistent_sync((char *)map->cached + from, len, DMA_FROM_DEVICE); -} - -static struct map_info mainstone_maps[2] = { { - .size = WINDOW_SIZE, - .phys = PXA_CS0_PHYS, - .inval_cache = mainstone_map_inval_cache, -}, { - .size = WINDOW_SIZE, - .phys = PXA_CS1_PHYS, - .inval_cache = mainstone_map_inval_cache, -} }; - -static struct mtd_partition mainstone_partitions[] = { - { - .name = "Bootloader", - .size = 0x00040000, - .offset = 0, - .mask_flags = MTD_WRITEABLE /* force read-only */ - },{ - .name = "Kernel", - .size = 0x00400000, - .offset = 0x00040000, - },{ - .name = "Filesystem", - .size = MTDPART_SIZ_FULL, - .offset = 0x00440000 - } -}; - -static struct mtd_info *mymtds[2]; -static struct mtd_partition *parsed_parts[2]; -static int nr_parsed_parts[2]; - -static const char *probes[] = { "RedBoot", "cmdlinepart", NULL }; - -static int __init init_mainstone(void) -{ - int SW7 = 0; /* FIXME: get from SCR (Mst doc section 3.2.1.1) */ - int ret = 0, i; - - mainstone_maps[0].bankwidth = (BOOT_DEF & 1) ? 2 : 4; - mainstone_maps[1].bankwidth = 4; - - /* Compensate for SW7 which swaps the flash banks */ - mainstone_maps[SW7].name = "processor flash"; - mainstone_maps[SW7 ^ 1].name = "main board flash"; - - printk(KERN_NOTICE "Mainstone configured to boot from %s\n", - mainstone_maps[0].name); - - for (i = 0; i < 2; i++) { - mainstone_maps[i].virt = ioremap(mainstone_maps[i].phys, - WINDOW_SIZE); - if (!mainstone_maps[i].virt) { - printk(KERN_WARNING "Failed to ioremap %s\n", - mainstone_maps[i].name); - if (!ret) - ret = -ENOMEM; - continue; - } - mainstone_maps[i].cached = - ioremap_cached(mainstone_maps[i].phys, WINDOW_SIZE); - if (!mainstone_maps[i].cached) - printk(KERN_WARNING "Failed to ioremap cached %s\n", - mainstone_maps[i].name); - simple_map_init(&mainstone_maps[i]); - - printk(KERN_NOTICE - "Probing %s at physical address 0x%08lx" - " (%d-bit bankwidth)\n", - mainstone_maps[i].name, mainstone_maps[i].phys, - mainstone_maps[i].bankwidth * 8); - - mymtds[i] = do_map_probe("cfi_probe", &mainstone_maps[i]); - - if (!mymtds[i]) { - iounmap((void *)mainstone_maps[i].virt); - if (mainstone_maps[i].cached) - iounmap(mainstone_maps[i].cached); - if (!ret) - ret = -EIO; - continue; - } - mymtds[i]->owner = THIS_MODULE; - - ret = parse_mtd_partitions(mymtds[i], probes, - &parsed_parts[i], 0); - - if (ret > 0) - nr_parsed_parts[i] = ret; - } - - if (!mymtds[0] && !mymtds[1]) - return ret; - - for (i = 0; i < 2; i++) { - if (!mymtds[i]) { - printk(KERN_WARNING "%s is absent. Skipping\n", - mainstone_maps[i].name); - } else if (nr_parsed_parts[i]) { - add_mtd_partitions(mymtds[i], parsed_parts[i], - nr_parsed_parts[i]); - } else if (!i) { - printk("Using static partitions on %s\n", - mainstone_maps[i].name); - add_mtd_partitions(mymtds[i], mainstone_partitions, - ARRAY_SIZE(mainstone_partitions)); - } else { - printk("Registering %s as whole device\n", - mainstone_maps[i].name); - add_mtd_device(mymtds[i]); - } - } - return 0; -} - -static void __exit cleanup_mainstone(void) -{ - int i; - for (i = 0; i < 2; i++) { - if (!mymtds[i]) - continue; - - if (nr_parsed_parts[i] || !i) - del_mtd_partitions(mymtds[i]); - else - del_mtd_device(mymtds[i]); - - map_destroy(mymtds[i]); - iounmap((void *)mainstone_maps[i].virt); - if (mainstone_maps[i].cached) - iounmap(mainstone_maps[i].cached); - kfree(parsed_parts[i]); - } -} - -module_init(init_mainstone); -module_exit(cleanup_mainstone); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Nicolas Pitre <nico@cam.org>"); -MODULE_DESCRIPTION("MTD map driver for Intel Mainstone"); diff --git a/drivers/mtd/maps/nettel.c b/drivers/mtd/maps/nettel.c index 7b96cd02f82b..0c9b305a72e0 100644 --- a/drivers/mtd/maps/nettel.c +++ b/drivers/mtd/maps/nettel.c @@ -158,68 +158,11 @@ static struct notifier_block nettel_notifier_block = { nettel_reboot_notifier, NULL, 0 }; -/* - * Erase the configuration file system. - * Used to support the software reset button. - */ -static void nettel_erasecallback(struct erase_info *done) -{ - wait_queue_head_t *wait_q = (wait_queue_head_t *)done->priv; - wake_up(wait_q); -} - -static struct erase_info nettel_erase; - -int nettel_eraseconfig(void) -{ - struct mtd_info *mtd; - DECLARE_WAITQUEUE(wait, current); - wait_queue_head_t wait_q; - int ret; - - init_waitqueue_head(&wait_q); - mtd = get_mtd_device(NULL, 2); - if (!IS_ERR(mtd)) { - nettel_erase.mtd = mtd; - nettel_erase.callback = nettel_erasecallback; - nettel_erase.callback = NULL; - nettel_erase.addr = 0; - nettel_erase.len = mtd->size; - nettel_erase.priv = (u_long) &wait_q; - nettel_erase.priv = 0; - - set_current_state(TASK_INTERRUPTIBLE); - add_wait_queue(&wait_q, &wait); - - ret = mtd->erase(mtd, &nettel_erase); - if (ret) { - set_current_state(TASK_RUNNING); - remove_wait_queue(&wait_q, &wait); - put_mtd_device(mtd); - return(ret); - } - - schedule(); /* Wait for erase to finish. */ - remove_wait_queue(&wait_q, &wait); - - put_mtd_device(mtd); - } - - return(0); -} - -#else - -int nettel_eraseconfig(void) -{ - return(0); -} - #endif /****************************************************************************/ -int __init nettel_init(void) +static int __init nettel_init(void) { volatile unsigned long *amdpar; unsigned long amdaddr, maxsize; @@ -421,10 +364,6 @@ int __init nettel_init(void) intel_mtd->owner = THIS_MODULE; -#ifndef CONFIG_BLK_DEV_INITRD - ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, 1); -#endif - num_intel_partitions = sizeof(nettel_intel_partitions) / sizeof(nettel_intel_partitions[0]); @@ -477,7 +416,7 @@ out_unmap2: /****************************************************************************/ -void __exit nettel_cleanup(void) +static void __exit nettel_cleanup(void) { #ifdef CONFIG_MTD_CFI_INTELEXT unregister_reboot_notifier(&nettel_notifier_block); diff --git a/drivers/mtd/maps/ocelot.c b/drivers/mtd/maps/ocelot.c deleted file mode 100644 index 6977963d7897..000000000000 --- a/drivers/mtd/maps/ocelot.c +++ /dev/null @@ -1,175 +0,0 @@ -/* - * $Id: ocelot.c,v 1.17 2005/11/07 11:14:27 gleixner Exp $ - * - * Flash on Momenco Ocelot - */ - -#include <linux/module.h> -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/init.h> -#include <asm/io.h> -#include <linux/mtd/mtd.h> -#include <linux/mtd/map.h> -#include <linux/mtd/partitions.h> - -#define OCELOT_PLD 0x2c000000 -#define FLASH_WINDOW_ADDR 0x2fc00000 -#define FLASH_WINDOW_SIZE 0x00080000 -#define FLASH_BUSWIDTH 1 -#define NVRAM_WINDOW_ADDR 0x2c800000 -#define NVRAM_WINDOW_SIZE 0x00007FF0 -#define NVRAM_BUSWIDTH 1 - -static unsigned int cacheflush = 0; - -static struct mtd_info *flash_mtd; -static struct mtd_info *nvram_mtd; - -static void ocelot_ram_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf) -{ - struct map_info *map = mtd->priv; - size_t done = 0; - - /* If we use memcpy, it does word-wide writes. Even though we told the - GT64120A that it's an 8-bit wide region, word-wide writes don't work. - We end up just writing the first byte of the four to all four bytes. - So we have this loop instead */ - *retlen = len; - while(len) { - __raw_writeb(*(unsigned char *) from, map->virt + to); - from++; - to++; - len--; - } -} - -static struct mtd_partition *parsed_parts; - -struct map_info ocelot_flash_map = { - .name = "Ocelot boot flash", - .size = FLASH_WINDOW_SIZE, - .bankwidth = FLASH_BUSWIDTH, - .phys = FLASH_WINDOW_ADDR, -}; - -struct map_info ocelot_nvram_map = { - .name = "Ocelot NVRAM", - .size = NVRAM_WINDOW_SIZE, - .bankwidth = NVRAM_BUSWIDTH, - .phys = NVRAM_WINDOW_ADDR, -}; - -static const char *probes[] = { "RedBoot", NULL }; - -static int __init init_ocelot_maps(void) -{ - void *pld; - int nr_parts; - unsigned char brd_status; - - printk(KERN_INFO "Momenco Ocelot MTD mappings: Flash 0x%x at 0x%x, NVRAM 0x%x at 0x%x\n", - FLASH_WINDOW_SIZE, FLASH_WINDOW_ADDR, NVRAM_WINDOW_SIZE, NVRAM_WINDOW_ADDR); - - /* First check whether the flash jumper is present */ - pld = ioremap(OCELOT_PLD, 0x10); - if (!pld) { - printk(KERN_NOTICE "Failed to ioremap Ocelot PLD\n"); - return -EIO; - } - brd_status = readb(pld+4); - iounmap(pld); - - /* Now ioremap the NVRAM space */ - ocelot_nvram_map.virt = ioremap_nocache(NVRAM_WINDOW_ADDR, NVRAM_WINDOW_SIZE); - if (!ocelot_nvram_map.virt) { - printk(KERN_NOTICE "Failed to ioremap Ocelot NVRAM space\n"); - return -EIO; - } - - simple_map_init(&ocelot_nvram_map); - - /* And do the RAM probe on it to get an MTD device */ - nvram_mtd = do_map_probe("map_ram", &ocelot_nvram_map); - if (!nvram_mtd) { - printk("NVRAM probe failed\n"); - goto fail_1; - } - nvram_mtd->owner = THIS_MODULE; - nvram_mtd->erasesize = 16; - /* Override the write() method */ - nvram_mtd->write = ocelot_ram_write; - - /* Now map the flash space */ - ocelot_flash_map.virt = ioremap_nocache(FLASH_WINDOW_ADDR, FLASH_WINDOW_SIZE); - if (!ocelot_flash_map.virt) { - printk(KERN_NOTICE "Failed to ioremap Ocelot flash space\n"); - goto fail_2; - } - /* Now the cached version */ - ocelot_flash_map.cached = (unsigned long)__ioremap(FLASH_WINDOW_ADDR, FLASH_WINDOW_SIZE, 0); - - simple_map_init(&ocelot_flash_map); - - /* Only probe for flash if the write jumper is present */ - if (brd_status & 0x40) { - flash_mtd = do_map_probe("jedec", &ocelot_flash_map); - } else { - printk(KERN_NOTICE "Ocelot flash write jumper not present. Treating as ROM\n"); - } - /* If that failed or the jumper's absent, pretend it's ROM */ - if (!flash_mtd) { - flash_mtd = do_map_probe("map_rom", &ocelot_flash_map); - /* If we're treating it as ROM, set the erase size */ - if (flash_mtd) - flash_mtd->erasesize = 0x10000; - } - if (!flash_mtd) - goto fail3; - - add_mtd_device(nvram_mtd); - - flash_mtd->owner = THIS_MODULE; - nr_parts = parse_mtd_partitions(flash_mtd, probes, &parsed_parts, 0); - - if (nr_parts > 0) - add_mtd_partitions(flash_mtd, parsed_parts, nr_parts); - else - add_mtd_device(flash_mtd); - - return 0; - - fail3: - iounmap((void *)ocelot_flash_map.virt); - if (ocelot_flash_map.cached) - iounmap((void *)ocelot_flash_map.cached); - fail_2: - map_destroy(nvram_mtd); - fail_1: - iounmap((void *)ocelot_nvram_map.virt); - - return -ENXIO; -} - -static void __exit cleanup_ocelot_maps(void) -{ - del_mtd_device(nvram_mtd); - map_destroy(nvram_mtd); - iounmap((void *)ocelot_nvram_map.virt); - - if (parsed_parts) - del_mtd_partitions(flash_mtd); - else - del_mtd_device(flash_mtd); - map_destroy(flash_mtd); - iounmap((void *)ocelot_flash_map.virt); - if (ocelot_flash_map.cached) - iounmap((void *)ocelot_flash_map.cached); -} - -module_init(init_ocelot_maps); -module_exit(cleanup_ocelot_maps); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Red Hat, Inc. - David Woodhouse <dwmw2@cambridge.redhat.com>"); -MODULE_DESCRIPTION("MTD map driver for Momenco Ocelot board"); diff --git a/drivers/mtd/maps/physmap_of.c b/drivers/mtd/maps/physmap_of.c index bbb42c35b69b..aeed9ea79714 100644 --- a/drivers/mtd/maps/physmap_of.c +++ b/drivers/mtd/maps/physmap_of.c @@ -1,9 +1,12 @@ /* - * Normal mappings of chips in physical memory for OF devices + * Flash mappings described by the OF (or flattened) device tree * * Copyright (C) 2006 MontaVista Software Inc. * Author: Vitaly Wool <vwool@ru.mvista.com> * + * Revised to handle newer style flash binding by: + * Copyright (C) 2007 David Gibson, IBM Corporation. + * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your @@ -12,102 +15,157 @@ #include <linux/module.h> #include <linux/types.h> -#include <linux/kernel.h> #include <linux/init.h> -#include <linux/slab.h> #include <linux/device.h> #include <linux/mtd/mtd.h> #include <linux/mtd/map.h> #include <linux/mtd/partitions.h> -#include <linux/mtd/physmap.h> -#include <asm/io.h> -#include <asm/prom.h> -#include <asm/of_device.h> -#include <asm/of_platform.h> +#include <linux/of.h> +#include <linux/of_platform.h> -struct physmap_flash_info { +struct of_flash { struct mtd_info *mtd; struct map_info map; struct resource *res; #ifdef CONFIG_MTD_PARTITIONS - int nr_parts; struct mtd_partition *parts; #endif }; -static const char *rom_probe_types[] = { "cfi_probe", "jedec_probe", "map_rom", NULL }; #ifdef CONFIG_MTD_PARTITIONS -static const char *part_probe_types[] = { "cmdlinepart", "RedBoot", NULL }; -#endif +#define OF_FLASH_PARTS(info) ((info)->parts) -#ifdef CONFIG_MTD_PARTITIONS -static int parse_flash_partitions(struct device_node *node, - struct mtd_partition **parts) +static int parse_obsolete_partitions(struct of_device *dev, + struct of_flash *info, + struct device_node *dp) { - int i, plen, retval = -ENOMEM; - const u32 *part; - const char *name; - - part = of_get_property(node, "partitions", &plen); - if (part == NULL) - goto err; - - retval = plen / (2 * sizeof(u32)); - *parts = kzalloc(retval * sizeof(struct mtd_partition), GFP_KERNEL); - if (*parts == NULL) { - printk(KERN_ERR "Can't allocate the flash partition data!\n"); - goto err; - } + int i, plen, nr_parts; + const struct { + u32 offset, len; + } *part; + const char *names; + + part = of_get_property(dp, "partitions", &plen); + if (!part) + return 0; /* No partitions found */ + + dev_warn(&dev->dev, "Device tree uses obsolete partition map binding\n"); + + nr_parts = plen / sizeof(part[0]); + + info->parts = kzalloc(nr_parts * sizeof(*info->parts), GFP_KERNEL); + if (!info->parts) + return -ENOMEM; - name = of_get_property(node, "partition-names", &plen); + names = of_get_property(dp, "partition-names", &plen); - for (i = 0; i < retval; i++) { - (*parts)[i].offset = *part++; - (*parts)[i].size = *part & ~1; - if (*part++ & 1) /* bit 0 set signifies read only partition */ - (*parts)[i].mask_flags = MTD_WRITEABLE; + for (i = 0; i < nr_parts; i++) { + info->parts[i].offset = part->offset; + info->parts[i].size = part->len & ~1; + if (part->len & 1) /* bit 0 set signifies read only partition */ + info->parts[i].mask_flags = MTD_WRITEABLE; - if (name != NULL && plen > 0) { - int len = strlen(name) + 1; + if (names && (plen > 0)) { + int len = strlen(names) + 1; - (*parts)[i].name = (char *)name; + info->parts[i].name = (char *)names; plen -= len; - name += len; - } else - (*parts)[i].name = "unnamed"; + names += len; + } else { + info->parts[i].name = "unnamed"; + } + + part++; } -err: - return retval; + + return nr_parts; } -#endif -static int of_physmap_remove(struct of_device *dev) +static int __devinit parse_partitions(struct of_flash *info, + struct of_device *dev) +{ + const char *partname; + static const char *part_probe_types[] + = { "cmdlinepart", "RedBoot", NULL }; + struct device_node *dp = dev->node, *pp; + int nr_parts, i; + + /* First look for RedBoot table or partitions on the command + * line, these take precedence over device tree information */ + nr_parts = parse_mtd_partitions(info->mtd, part_probe_types, + &info->parts, 0); + if (nr_parts > 0) { + add_mtd_partitions(info->mtd, info->parts, nr_parts); + return 0; + } + + /* First count the subnodes */ + nr_parts = 0; + for (pp = dp->child; pp; pp = pp->sibling) + nr_parts++; + + if (nr_parts == 0) + return parse_obsolete_partitions(dev, info, dp); + + info->parts = kzalloc(nr_parts * sizeof(*info->parts), + GFP_KERNEL); + if (!info->parts) + return -ENOMEM; + + for (pp = dp->child, i = 0; pp; pp = pp->sibling, i++) { + const u32 *reg; + int len; + + reg = of_get_property(pp, "reg", &len); + if (!reg || (len != 2*sizeof(u32))) { + dev_err(&dev->dev, "Invalid 'reg' on %s\n", + dp->full_name); + kfree(info->parts); + info->parts = NULL; + return -EINVAL; + } + info->parts[i].offset = reg[0]; + info->parts[i].size = reg[1]; + + partname = of_get_property(pp, "label", &len); + if (!partname) + partname = of_get_property(pp, "name", &len); + info->parts[i].name = (char *)partname; + + if (of_get_property(pp, "read-only", &len)) + info->parts[i].mask_flags = MTD_WRITEABLE; + } + + return nr_parts; +} +#else /* MTD_PARTITIONS */ +#define OF_FLASH_PARTS(info) (0) +#define parse_partitions(info, dev) (0) +#endif /* MTD_PARTITIONS */ + +static int of_flash_remove(struct of_device *dev) { - struct physmap_flash_info *info; + struct of_flash *info; info = dev_get_drvdata(&dev->dev); - if (info == NULL) + if (!info) return 0; dev_set_drvdata(&dev->dev, NULL); - if (info->mtd != NULL) { -#ifdef CONFIG_MTD_PARTITIONS - if (info->nr_parts) { + if (info->mtd) { + if (OF_FLASH_PARTS(info)) { del_mtd_partitions(info->mtd); - kfree(info->parts); + kfree(OF_FLASH_PARTS(info)); } else { del_mtd_device(info->mtd); } -#else - del_mtd_device(info->mtd); -#endif map_destroy(info->mtd); } - if (info->map.virt != NULL) + if (info->map.virt) iounmap(info->map.virt); - if (info->res != NULL) { + if (info->res) { release_resource(info->res); kfree(info->res); } @@ -115,48 +173,78 @@ static int of_physmap_remove(struct of_device *dev) return 0; } -static int __devinit of_physmap_probe(struct of_device *dev, const struct of_device_id *match) +/* Helper function to handle probing of the obsolete "direct-mapped" + * compatible binding, which has an extra "probe-type" property + * describing the type of flash probe necessary. */ +static struct mtd_info * __devinit obsolete_probe(struct of_device *dev, + struct map_info *map) { struct device_node *dp = dev->node; - struct resource res; - struct physmap_flash_info *info; - const char **probe_type; const char *of_probe; + struct mtd_info *mtd; + static const char *rom_probe_types[] + = { "cfi_probe", "jedec_probe", "map_rom"}; + int i; + + dev_warn(&dev->dev, "Device tree uses obsolete \"direct-mapped\" " + "flash binding\n"); + + of_probe = of_get_property(dp, "probe-type", NULL); + if (!of_probe) { + for (i = 0; i < ARRAY_SIZE(rom_probe_types); i++) { + mtd = do_map_probe(rom_probe_types[i], map); + if (mtd) + return mtd; + } + return NULL; + } else if (strcmp(of_probe, "CFI") == 0) { + return do_map_probe("cfi_probe", map); + } else if (strcmp(of_probe, "JEDEC") == 0) { + return do_map_probe("jedec_probe", map); + } else { + if (strcmp(of_probe, "ROM") != 0) + dev_warn(&dev->dev, "obsolete_probe: don't know probe " + "type '%s', mapping as rom\n", of_probe); + return do_map_probe("mtd_rom", map); + } +} + +static int __devinit of_flash_probe(struct of_device *dev, + const struct of_device_id *match) +{ + struct device_node *dp = dev->node; + struct resource res; + struct of_flash *info; + const char *probe_type = match->data; const u32 *width; int err; - + err = -ENXIO; if (of_address_to_resource(dp, 0, &res)) { - dev_err(&dev->dev, "Can't get the flash mapping!\n"); - err = -EINVAL; + dev_err(&dev->dev, "Can't get IO address from device tree\n"); goto err_out; } - dev_dbg(&dev->dev, "physmap flash device: %.8llx at %.8llx\n", - (unsigned long long)res.end - res.start + 1, - (unsigned long long)res.start); + dev_dbg(&dev->dev, "of_flash device: %.8llx-%.8llx\n", + (unsigned long long)res.start, (unsigned long long)res.end); - info = kzalloc(sizeof(struct physmap_flash_info), GFP_KERNEL); - if (info == NULL) { - err = -ENOMEM; + err = -ENOMEM; + info = kzalloc(sizeof(*info), GFP_KERNEL); + if (!info) goto err_out; - } - memset(info, 0, sizeof(*info)); dev_set_drvdata(&dev->dev, info); + err = -EBUSY; info->res = request_mem_region(res.start, res.end - res.start + 1, - dev->dev.bus_id); - if (info->res == NULL) { - dev_err(&dev->dev, "Could not reserve memory region\n"); - err = -ENOMEM; + dev->dev.bus_id); + if (!info->res) goto err_out; - } + err = -ENXIO; width = of_get_property(dp, "bank-width", NULL); - if (width == NULL) { - dev_err(&dev->dev, "Can't get the flash bank width!\n"); - err = -EINVAL; + if (!width) { + dev_err(&dev->dev, "Can't get bank width from device tree\n"); goto err_out; } @@ -165,91 +253,87 @@ static int __devinit of_physmap_probe(struct of_device *dev, const struct of_dev info->map.size = res.end - res.start + 1; info->map.bankwidth = *width; + err = -ENOMEM; info->map.virt = ioremap(info->map.phys, info->map.size); - if (info->map.virt == NULL) { - dev_err(&dev->dev, "Failed to ioremap flash region\n"); - err = EIO; + if (!info->map.virt) { + dev_err(&dev->dev, "Failed to ioremap() flash region\n"); goto err_out; } simple_map_init(&info->map); - of_probe = of_get_property(dp, "probe-type", NULL); - if (of_probe == NULL) { - probe_type = rom_probe_types; - for (; info->mtd == NULL && *probe_type != NULL; probe_type++) - info->mtd = do_map_probe(*probe_type, &info->map); - } else if (!strcmp(of_probe, "CFI")) - info->mtd = do_map_probe("cfi_probe", &info->map); - else if (!strcmp(of_probe, "JEDEC")) - info->mtd = do_map_probe("jedec_probe", &info->map); - else { - if (strcmp(of_probe, "ROM")) - dev_dbg(&dev->dev, "map_probe: don't know probe type " - "'%s', mapping as rom\n", of_probe); - info->mtd = do_map_probe("mtd_rom", &info->map); - } - if (info->mtd == NULL) { - dev_err(&dev->dev, "map_probe failed\n"); - err = -ENXIO; + if (probe_type) + info->mtd = do_map_probe(probe_type, &info->map); + else + info->mtd = obsolete_probe(dev, &info->map); + + err = -ENXIO; + if (!info->mtd) { + dev_err(&dev->dev, "do_map_probe() failed\n"); goto err_out; } info->mtd->owner = THIS_MODULE; -#ifdef CONFIG_MTD_PARTITIONS - err = parse_mtd_partitions(info->mtd, part_probe_types, &info->parts, 0); - if (err > 0) { - add_mtd_partitions(info->mtd, info->parts, err); - } else if ((err = parse_flash_partitions(dp, &info->parts)) > 0) { - dev_info(&dev->dev, "Using OF partition information\n"); - add_mtd_partitions(info->mtd, info->parts, err); - info->nr_parts = err; - } else -#endif + err = parse_partitions(info, dev); + if (err < 0) + goto err_out; + + if (err > 0) + add_mtd_partitions(info->mtd, OF_FLASH_PARTS(info), err); + else + add_mtd_device(info->mtd); - add_mtd_device(info->mtd); return 0; err_out: - of_physmap_remove(dev); + of_flash_remove(dev); return err; - - return 0; - - } -static struct of_device_id of_physmap_match[] = { +static struct of_device_id of_flash_match[] = { + { + .compatible = "cfi-flash", + .data = (void *)"cfi_probe", + }, + { + /* FIXME: JEDEC chips can't be safely and reliably + * probed, although the mtd code gets it right in + * practice most of the time. We should use the + * vendor and device ids specified by the binding to + * bypass the heuristic probe code, but the mtd layer + * provides, at present, no interface for doing so + * :(. */ + .compatible = "jedec-flash", + .data = (void *)"jedec_probe", + }, { .type = "rom", .compatible = "direct-mapped" }, { }, }; +MODULE_DEVICE_TABLE(of, of_flash_match); -MODULE_DEVICE_TABLE(of, of_physmap_match); - - -static struct of_platform_driver of_physmap_flash_driver = { - .name = "physmap-flash", - .match_table = of_physmap_match, - .probe = of_physmap_probe, - .remove = of_physmap_remove, +static struct of_platform_driver of_flash_driver = { + .name = "of-flash", + .match_table = of_flash_match, + .probe = of_flash_probe, + .remove = of_flash_remove, }; -static int __init of_physmap_init(void) +static int __init of_flash_init(void) { - return of_register_platform_driver(&of_physmap_flash_driver); + return of_register_platform_driver(&of_flash_driver); } -static void __exit of_physmap_exit(void) +static void __exit of_flash_exit(void) { - of_unregister_platform_driver(&of_physmap_flash_driver); + of_unregister_platform_driver(&of_flash_driver); } -module_init(of_physmap_init); -module_exit(of_physmap_exit); +module_init(of_flash_init); +module_exit(of_flash_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Vitaly Wool <vwool@ru.mvista.com>"); -MODULE_DESCRIPTION("Configurable MTD map driver for OF"); +MODULE_DESCRIPTION("Device tree based MTD map driver"); diff --git a/drivers/mtd/maps/pmcmsp-flash.c b/drivers/mtd/maps/pmcmsp-flash.c index 7e0377ec1c40..02bde8c982ec 100644 --- a/drivers/mtd/maps/pmcmsp-flash.c +++ b/drivers/mtd/maps/pmcmsp-flash.c @@ -73,13 +73,16 @@ int __init init_msp_flash(void) return -ENXIO; printk(KERN_NOTICE "Found %d PMC flash devices\n", fcnt); - msp_flash = (struct mtd_info **)kmalloc( - fcnt * sizeof(struct map_info *), GFP_KERNEL); - msp_parts = (struct mtd_partition **)kmalloc( - fcnt * sizeof(struct mtd_partition *), GFP_KERNEL); - msp_maps = (struct map_info *)kmalloc( - fcnt * sizeof(struct mtd_info), GFP_KERNEL); - memset(msp_maps, 0, fcnt * sizeof(struct mtd_info)); + + msp_flash = kmalloc(fcnt * sizeof(struct map_info *), GFP_KERNEL); + msp_parts = kmalloc(fcnt * sizeof(struct mtd_partition *), GFP_KERNEL); + msp_maps = kcalloc(fcnt, sizeof(struct mtd_info), GFP_KERNEL); + if (!msp_flash || !msp_parts || !msp_maps) { + kfree(msp_maps); + kfree(msp_parts); + kfree(msp_flash); + return -ENOMEM; + } /* loop over the flash devices, initializing each */ for (i = 0; i < fcnt; i++) { @@ -95,9 +98,8 @@ int __init init_msp_flash(void) continue; } - msp_parts[i] = (struct mtd_partition *)kmalloc( - pcnt * sizeof(struct mtd_partition), GFP_KERNEL); - memset(msp_parts[i], 0, pcnt * sizeof(struct mtd_partition)); + msp_parts[i] = kcalloc(pcnt, sizeof(struct mtd_partition), + GFP_KERNEL); /* now initialize the devices proper */ flash_name[5] = '0' + i; diff --git a/drivers/mtd/maps/pmcmsp-ramroot.c b/drivers/mtd/maps/pmcmsp-ramroot.c index 18049bceba8d..30de5c0c09a9 100644 --- a/drivers/mtd/maps/pmcmsp-ramroot.c +++ b/drivers/mtd/maps/pmcmsp-ramroot.c @@ -79,7 +79,6 @@ static int __init init_rrmap(void) rr_mtd->owner = THIS_MODULE; add_mtd_device(rr_mtd); - ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, rr_mtd->index); return 0; } diff --git a/drivers/mtd/maps/pq2fads.c b/drivers/mtd/maps/pq2fads.c deleted file mode 100644 index fb78d87cc130..000000000000 --- a/drivers/mtd/maps/pq2fads.c +++ /dev/null @@ -1,88 +0,0 @@ -/* - * drivers/mtd/maps/pq2fads.c - * - * Mapping for the flash SIMM on 8272ADS and PQ2FADS board - * - * Author: Vitaly Bordug <vbordug@ru.mvista.com> - * - * 2005 (c) MontaVista Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2. This program - * is licensed "as is" without any warranty of any kind, whether express - * or implied. - */ - -#include <linux/module.h> -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/init.h> -#include <asm/io.h> -#include <asm/ppcboot.h> -#include <linux/mtd/mtd.h> -#include <linux/mtd/map.h> -#include <linux/mtd/partitions.h> -#include <linux/mtd/physmap.h> - -/* - NOTE: bank width and interleave relative to the installed flash - should have been chosen within MTD_CFI_GEOMETRY options. - */ -#define PQ2FADS_BANK_WIDTH 4 - -static struct mtd_partition pq2fads_partitions[] = { - { -#ifdef CONFIG_ADS8272 - .name = "HRCW", - .size = 0x40000, - .offset = 0, - .mask_flags = MTD_WRITEABLE, /* force read-only */ - }, { - .name = "User FS", - .size = 0x5c0000, - .offset = 0x40000, -#else - .name = "User FS", - .size = 0x600000, - .offset = 0, -#endif - }, { - .name = "uImage", - .size = 0x100000, - .offset = 0x600000, - .mask_flags = MTD_WRITEABLE, /* force read-only */ - }, { - .name = "bootloader", - .size = 0x40000, - .offset = 0x700000, - .mask_flags = MTD_WRITEABLE, /* force read-only */ - }, { - .name = "bootloader env", - .size = 0x40000, - .offset = 0x740000, - .mask_flags = MTD_WRITEABLE, /* force read-only */ - } -}; - - -/* pointer to MPC885ADS board info data */ -extern unsigned char __res[]; - -static int __init init_pq2fads_mtd(void) -{ - bd_t *bd = (bd_t *)__res; - physmap_configure(bd->bi_flashstart, bd->bi_flashsize, PQ2FADS_BANK_WIDTH, NULL); - - physmap_set_partitions(pq2fads_partitions, - sizeof (pq2fads_partitions) / - sizeof (pq2fads_partitions[0])); - return 0; -} - -static void __exit cleanup_pq2fads_mtd(void) -{ -} - -module_init(init_pq2fads_mtd); -module_exit(cleanup_pq2fads_mtd); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("MTD map and partitions for MPC8272ADS boards"); diff --git a/drivers/mtd/maps/pxa2xx-flash.c b/drivers/mtd/maps/pxa2xx-flash.c new file mode 100644 index 000000000000..cb933ac475d5 --- /dev/null +++ b/drivers/mtd/maps/pxa2xx-flash.c @@ -0,0 +1,200 @@ +/* + * Map driver for Intel XScale PXA2xx platforms. + * + * Author: Nicolas Pitre + * Copyright: (C) 2001 MontaVista Software Inc. + * + * 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. + */ + +#include <linux/module.h> +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/dma-mapping.h> +#include <linux/mtd/mtd.h> +#include <linux/mtd/map.h> +#include <linux/mtd/partitions.h> + +#include <asm/io.h> +#include <asm/hardware.h> + +#include <asm/mach/flash.h> + +static void pxa2xx_map_inval_cache(struct map_info *map, unsigned long from, + ssize_t len) +{ + consistent_sync((char *)map->cached + from, len, DMA_FROM_DEVICE); +} + +struct pxa2xx_flash_info { + struct mtd_partition *parts; + int nr_parts; + struct mtd_info *mtd; + struct map_info map; +}; + + +static const char *probes[] = { "RedBoot", "cmdlinepart", NULL }; + + +static int __init pxa2xx_flash_probe(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct flash_platform_data *flash = pdev->dev.platform_data; + struct pxa2xx_flash_info *info; + struct mtd_partition *parts; + struct resource *res; + int ret = 0; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return -ENODEV; + + info = kmalloc(sizeof(struct pxa2xx_flash_info), GFP_KERNEL); + if (!info) + return -ENOMEM; + + memset(info, 0, sizeof(struct pxa2xx_flash_info)); + info->map.name = (char *) flash->name; + info->map.bankwidth = flash->width; + info->map.phys = res->start; + info->map.size = res->end - res->start + 1; + info->parts = flash->parts; + info->nr_parts = flash->nr_parts; + + info->map.virt = ioremap(info->map.phys, info->map.size); + if (!info->map.virt) { + printk(KERN_WARNING "Failed to ioremap %s\n", + info->map.name); + return -ENOMEM; + } + info->map.cached = + ioremap_cached(info->map.phys, info->map.size); + if (!info->map.cached) + printk(KERN_WARNING "Failed to ioremap cached %s\n", + info->map.name); + info->map.inval_cache = pxa2xx_map_inval_cache; + simple_map_init(&info->map); + + printk(KERN_NOTICE + "Probing %s at physical address 0x%08lx" + " (%d-bit bankwidth)\n", + info->map.name, (unsigned long)info->map.phys, + info->map.bankwidth * 8); + + info->mtd = do_map_probe(flash->map_name, &info->map); + + if (!info->mtd) { + iounmap((void *)info->map.virt); + if (info->map.cached) + iounmap(info->map.cached); + return -EIO; + } + info->mtd->owner = THIS_MODULE; + +#ifdef CONFIG_MTD_PARTITIONS + ret = parse_mtd_partitions(info->mtd, probes, &parts, 0); + + if (ret > 0) { + info->nr_parts = ret; + info->parts = parts; + } +#endif + + if (info->nr_parts) { + add_mtd_partitions(info->mtd, info->parts, + info->nr_parts); + } else { + printk("Registering %s as whole device\n", + info->map.name); + add_mtd_device(info->mtd); + } + + dev_set_drvdata(dev, info); + return 0; +} + +static int __exit pxa2xx_flash_remove(struct device *dev) +{ + struct pxa2xx_flash_info *info = dev_get_drvdata(dev); + + dev_set_drvdata(dev, NULL); + +#ifdef CONFIG_MTD_PARTITIONS + if (info->nr_parts) + del_mtd_partitions(info->mtd); + else +#endif + del_mtd_device(info->mtd); + + map_destroy(info->mtd); + iounmap(info->map.virt); + if (info->map.cached) + iounmap(info->map.cached); + kfree(info->parts); + kfree(info); + return 0; +} + +#ifdef CONFIG_PM +static int pxa2xx_flash_suspend(struct device *dev, pm_message_t state) +{ + struct pxa2xx_flash_info *info = dev_get_drvdata(dev); + int ret = 0; + + if (info->mtd && info->mtd->suspend) + ret = info->mtd->suspend(info->mtd); + return ret; +} + +static int pxa2xx_flash_resume(struct device *dev) +{ + struct pxa2xx_flash_info *info = dev_get_drvdata(dev); + + if (info->mtd && info->mtd->resume) + info->mtd->resume(info->mtd); + return 0; +} +static void pxa2xx_flash_shutdown(struct device *dev) +{ + struct pxa2xx_flash_info *info = dev_get_drvdata(dev); + + if (info && info->mtd->suspend(info->mtd) == 0) + info->mtd->resume(info->mtd); +} +#else +#define pxa2xx_flash_suspend NULL +#define pxa2xx_flash_resume NULL +#define pxa2xx_flash_shutdown NULL +#endif + +static struct device_driver pxa2xx_flash_driver = { + .name = "pxa2xx-flash", + .bus = &platform_bus_type, + .probe = pxa2xx_flash_probe, + .remove = __exit_p(pxa2xx_flash_remove), + .suspend = pxa2xx_flash_suspend, + .resume = pxa2xx_flash_resume, + .shutdown = pxa2xx_flash_shutdown, +}; + +static int __init init_pxa2xx_flash(void) +{ + return driver_register(&pxa2xx_flash_driver); +} + +static void __exit cleanup_pxa2xx_flash(void) +{ + driver_unregister(&pxa2xx_flash_driver); +} + +module_init(init_pxa2xx_flash); +module_exit(cleanup_pxa2xx_flash); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Nicolas Pitre <nico@cam.org>"); +MODULE_DESCRIPTION("MTD map driver for Intel XScale PXA2xx"); diff --git a/drivers/mtd/maps/tqm834x.c b/drivers/mtd/maps/tqm834x.c deleted file mode 100644 index 9adc970e55e6..000000000000 --- a/drivers/mtd/maps/tqm834x.c +++ /dev/null @@ -1,286 +0,0 @@ -/* - * drivers/mtd/maps/tqm834x.c - * - * MTD mapping driver for TQM834x boards - * - * Copyright 2005 Wolfgang Denk, DENX Software Engineering, <wd@denx.de>. - * - * This file is licensed under the terms of the GNU General Public License - * version 2. This program is licensed "as is" without any warranty of any - * kind, whether express or implied. - * - */ - -#include <linux/init.h> -#include <linux/module.h> -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/slab.h> -#include <asm/io.h> -#include <asm/ppcboot.h> - -#include <linux/mtd/mtd.h> -#include <linux/mtd/map.h> -#include <linux/mtd/partitions.h> - -#define FLASH_BANK_MAX 2 - -extern unsigned char __res[]; - -/* trivial struct to describe partition information */ -struct mtd_part_def -{ - int nums; - unsigned char *type; - struct mtd_partition* mtd_part; -}; - -static struct mtd_info* mtd_banks[FLASH_BANK_MAX]; -static struct map_info* map_banks[FLASH_BANK_MAX]; -static struct mtd_part_def part_banks[FLASH_BANK_MAX]; - -static unsigned long num_banks; -static unsigned long start_scan_addr; - -#ifdef CONFIG_MTD_PARTITIONS -/* - * The following defines the partition layout of TQM834x boards. - * - * See include/linux/mtd/partitions.h for definition of the - * mtd_partition structure. - * - * Assume minimal initial size of 4 MiB per bank, will be updated - * later in init_tqm834x_mtd() routine. - */ - -/* Partition definition for the first flash bank which is always present. */ -static struct mtd_partition tqm834x_partitions_bank1[] = { - { - .name = "u-boot", /* u-boot firmware */ - .offset = 0x00000000, - .size = 0x00040000, /* 256 KiB */ - /*mask_flags: MTD_WRITEABLE, * force read-only */ - }, - { - .name = "env", /* u-boot environment */ - .offset = 0x00040000, - .size = 0x00020000, /* 128 KiB */ - /*mask_flags: MTD_WRITEABLE, * force read-only */ - }, - { - .name = "kernel", /* linux kernel image */ - .offset = 0x00060000, - .size = 0x00100000, /* 1 MiB */ - /*mask_flags: MTD_WRITEABLE, * force read-only */ - }, - { - .name = "initrd", /* ramdisk image */ - .offset = 0x00160000, - .size = 0x00200000, /* 2 MiB */ - }, - { - .name = "user", /* user data */ - .offset = 0x00360000, - .size = 0x000a0000, /* remaining space */ - /* NOTE: this parttion size is re-calcated in */ - /* init_tqm834x_mtd() to cover actual remaining space. */ - }, -}; - -/* Partition definition for the second flash bank which may be present on some - * TQM834x boards. - */ -static struct mtd_partition tqm834x_partitions_bank2[] = { - { - .name = "jffs2", /* jffs2 filesystem */ - .offset = 0x00000000, - .size = 0x00400000, /* whole device */ - /* NOTE: this parttion size is re-calcated in */ - /* init_tqm834x_mtd() to cover actual device size. */ - }, -}; - -#endif /* CONFIG_MTD_PARTITIONS */ - -static int __init init_tqm834x_mtd(void) -{ - int idx = 0, ret = 0; - unsigned long flash_addr, flash_size, mtd_size = 0; - - /* pointer to TQM834x board info data */ - bd_t *bd = (bd_t *)__res; -#ifdef CONFIG_MTD_CMDLINE_PARTS - int n; - char mtdid[4]; - const char *part_probes[] = { "cmdlinepart", NULL }; -#endif - - flash_addr = bd->bi_flashstart; - flash_size = bd->bi_flashsize; - - /* request maximum flash size address space */ - start_scan_addr = (unsigned long)ioremap(flash_addr, flash_size); - if (!start_scan_addr) { - printk("%s: Failed to ioremap address: 0x%lx\n", - __FUNCTION__, flash_addr); - return -EIO; - } - - for(idx = 0 ; idx < FLASH_BANK_MAX ; idx++) { - if (mtd_size >= flash_size) - break; - - pr_debug("%s: chip probing count %d\n", __FUNCTION__, idx); - - map_banks[idx] = kzalloc(sizeof(struct map_info), GFP_KERNEL); - if (map_banks[idx] == NULL) { - ret = -ENOMEM; - goto error_mem; - } - map_banks[idx]->name = kzalloc(16, GFP_KERNEL); - if (map_banks[idx]->name == NULL) { - ret = -ENOMEM; - goto error_mem; - } - - sprintf(map_banks[idx]->name, "TQM834x-%d", idx); - map_banks[idx]->size = flash_size; - map_banks[idx]->bankwidth = 4; - - simple_map_init(map_banks[idx]); - - map_banks[idx]->virt = (void __iomem *) - (start_scan_addr + ((idx > 0) ? - (mtd_banks[idx-1] ? mtd_banks[idx-1]->size : 0) : 0)); - map_banks[idx]->phys = - flash_addr + ((idx > 0) ? - (mtd_banks[idx-1] ? mtd_banks[idx-1]->size : 0) : 0); - - /* start to probe flash chips */ - mtd_banks[idx] = do_map_probe("cfi_probe", map_banks[idx]); - if (mtd_banks[idx]) { - mtd_banks[idx]->owner = THIS_MODULE; - mtd_size += mtd_banks[idx]->size; - num_banks++; - pr_debug("%s: bank %ld, name: %s, size: %d bytes \n", - __FUNCTION__, num_banks, - mtd_banks[idx]->name, mtd_banks[idx]->size); - } - } - - /* no supported flash chips found */ - if (!num_banks) { - printk("TQM834x: No supported flash chips found!\n"); - ret = -ENXIO; - goto error_mem; - } - -#ifdef CONFIG_MTD_PARTITIONS - /* - * Select static partition definitions - */ - n = ARRAY_SIZE(tqm834x_partitions_bank1); - part_banks[0].mtd_part = tqm834x_partitions_bank1; - part_banks[0].type = "static image bank1"; - part_banks[0].nums = n; - - /* update last partition size to cover actual remaining space */ - tqm834x_partitions_bank1[n - 1].size = - mtd_banks[0]->size - - tqm834x_partitions_bank1[n - 1].offset; - - /* check if we have second bank? */ - if (num_banks == 2) { - n = ARRAY_SIZE(tqm834x_partitions_bank2); - part_banks[1].mtd_part = tqm834x_partitions_bank2; - part_banks[1].type = "static image bank2"; - part_banks[1].nums = n; - - /* update last partition size to cover actual remaining space */ - tqm834x_partitions_bank2[n - 1].size = - mtd_banks[1]->size - - tqm834x_partitions_bank2[n - 1].offset; - } - - for(idx = 0; idx < num_banks ; idx++) { -#ifdef CONFIG_MTD_CMDLINE_PARTS - sprintf(mtdid, "%d", idx); - n = parse_mtd_partitions(mtd_banks[idx], - part_probes, - &part_banks[idx].mtd_part, - 0); - pr_debug("%s: %d command line partitions on bank %s\n", - __FUNCTION__, n, mtdid); - if (n > 0) { - part_banks[idx].type = "command line"; - part_banks[idx].nums = n; - } -#endif /* CONFIG_MTD_CMDLINE_PARTS */ - if (part_banks[idx].nums == 0) { - printk(KERN_NOTICE - "TQM834x flash bank %d: no partition info " - "available, registering whole device\n", idx); - add_mtd_device(mtd_banks[idx]); - } else { - printk(KERN_NOTICE - "TQM834x flash bank %d: Using %s partition " - "definition\n", idx, part_banks[idx].type); - add_mtd_partitions(mtd_banks[idx], - part_banks[idx].mtd_part, - part_banks[idx].nums); - } - } -#else /* ! CONFIG_MTD_PARTITIONS */ - printk(KERN_NOTICE "TQM834x flash: registering %d flash banks " - "at once\n", num_banks); - - for(idx = 0 ; idx < num_banks ; idx++) - add_mtd_device(mtd_banks[idx]); - -#endif /* CONFIG_MTD_PARTITIONS */ - - return 0; -error_mem: - for (idx = 0 ; idx < FLASH_BANK_MAX ; idx++) { - if (map_banks[idx] != NULL) { - if (map_banks[idx]->name != NULL) { - kfree(map_banks[idx]->name); - map_banks[idx]->name = NULL; - } - kfree(map_banks[idx]); - map_banks[idx] = NULL; - } - } - - iounmap((void *)start_scan_addr); - - return ret; -} - -static void __exit cleanup_tqm834x_mtd(void) -{ - unsigned int idx = 0; - for(idx = 0 ; idx < num_banks ; idx++) { - /* destroy mtd_info previously allocated */ - if (mtd_banks[idx]) { - del_mtd_partitions(mtd_banks[idx]); - map_destroy(mtd_banks[idx]); - } - - /* release map_info not used anymore */ - kfree(map_banks[idx]->name); - kfree(map_banks[idx]); - } - - if (start_scan_addr) { - iounmap((void *)start_scan_addr); - start_scan_addr = 0; - } -} - -module_init(init_tqm834x_mtd); -module_exit(cleanup_tqm834x_mtd); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Wolfgang Denk <wd@denx.de>"); -MODULE_DESCRIPTION("MTD map driver for TQM834x boards"); |