diff options
Diffstat (limited to 'drivers/mtd/maps/sa1100-flash.c')
| -rw-r--r-- | drivers/mtd/maps/sa1100-flash.c | 276 |
1 files changed, 62 insertions, 214 deletions
diff --git a/drivers/mtd/maps/sa1100-flash.c b/drivers/mtd/maps/sa1100-flash.c index 52385705da0..8fc06bf111c 100644 --- a/drivers/mtd/maps/sa1100-flash.c +++ b/drivers/mtd/maps/sa1100-flash.c @@ -1,11 +1,8 @@ /* * Flash memory access on SA11x0 based devices - * - * (C) 2000 Nicolas Pitre <nico@cam.org> - * - * $Id: sa1100-flash.c,v 1.47 2004/11/01 13:44:36 rmk Exp $ + * + * (C) 2000 Nicolas Pitre <nico@fluxnic.net> */ -#include <linux/config.h> #include <linux/module.h> #include <linux/types.h> #include <linux/ioport.h> @@ -13,137 +10,48 @@ #include <linux/init.h> #include <linux/errno.h> #include <linux/slab.h> -#include <linux/device.h> +#include <linux/platform_device.h> #include <linux/err.h> +#include <linux/io.h> #include <linux/mtd/mtd.h> #include <linux/mtd/map.h> #include <linux/mtd/partitions.h> #include <linux/mtd/concat.h> -#include <asm/mach-types.h> -#include <asm/io.h> +#include <mach/hardware.h> #include <asm/sizes.h> #include <asm/mach/flash.h> -#if 0 -/* - * This is here for documentation purposes only - until these people - * submit their machine types. It will be gone January 2005. - */ -static struct mtd_partition consus_partitions[] = { - { - .name = "Consus boot firmware", - .offset = 0, - .size = 0x00040000, - .mask_flags = MTD_WRITABLE, /* force read-only */ - }, { - .name = "Consus kernel", - .offset = 0x00040000, - .size = 0x00100000, - .mask_flags = 0, - }, { - .name = "Consus disk", - .offset = 0x00140000, - /* The rest (up to 16M) for jffs. We could put 0 and - make it find the size automatically, but right now - i have 32 megs. jffs will use all 32 megs if given - the chance, and this leads to horrible problems - when you try to re-flash the image because blob - won't erase the whole partition. */ - .size = 0x01000000 - 0x00140000, - .mask_flags = 0, - }, { - /* this disk is a secondary disk, which can be used as - needed, for simplicity, make it the size of the other - consus partition, although realistically it could be - the remainder of the disk (depending on the file - system used) */ - .name = "Consus disk2", - .offset = 0x01000000, - .size = 0x01000000 - 0x00140000, - .mask_flags = 0, - } -}; - -/* Frodo has 2 x 16M 28F128J3A flash chips in bank 0: */ -static struct mtd_partition frodo_partitions[] = -{ - { - .name = "bootloader", - .size = 0x00040000, - .offset = 0x00000000, - .mask_flags = MTD_WRITEABLE - }, { - .name = "bootloader params", - .size = 0x00040000, - .offset = MTDPART_OFS_APPEND, - .mask_flags = MTD_WRITEABLE - }, { - .name = "kernel", - .size = 0x00100000, - .offset = MTDPART_OFS_APPEND, - .mask_flags = MTD_WRITEABLE - }, { - .name = "ramdisk", - .size = 0x00400000, - .offset = MTDPART_OFS_APPEND, - .mask_flags = MTD_WRITEABLE - }, { - .name = "file system", - .size = MTDPART_SIZ_FULL, - .offset = MTDPART_OFS_APPEND - } -}; - -static struct mtd_partition jornada56x_partitions[] = { - { - .name = "bootldr", - .size = 0x00040000, - .offset = 0, - .mask_flags = MTD_WRITEABLE, - }, { - .name = "rootfs", - .size = MTDPART_SIZ_FULL, - .offset = MTDPART_OFS_APPEND, - } -}; - -static void jornada56x_set_vpp(int vpp) -{ - if (vpp) - GPSR = GPIO_GPIO26; - else - GPCR = GPIO_GPIO26; - GPDR |= GPIO_GPIO26; -} - -/* - * Machine Phys Size set_vpp - * Consus : SA1100_CS0_PHYS SZ_32M - * Frodo : SA1100_CS0_PHYS SZ_32M - * Jornada56x: SA1100_CS0_PHYS SZ_32M jornada56x_set_vpp - */ -#endif - struct sa_subdev_info { char name[16]; struct map_info map; struct mtd_info *mtd; - struct flash_platform_data *data; + struct flash_platform_data *plat; }; struct sa_info { - struct mtd_partition *parts; struct mtd_info *mtd; int num_subdev; struct sa_subdev_info subdev[0]; }; +static DEFINE_SPINLOCK(sa1100_vpp_lock); +static int sa1100_vpp_refcnt; static void sa1100_set_vpp(struct map_info *map, int on) { struct sa_subdev_info *subdev = container_of(map, struct sa_subdev_info, map); - subdev->data->set_vpp(on); + unsigned long flags; + + spin_lock_irqsave(&sa1100_vpp_lock, flags); + if (on) { + if (++sa1100_vpp_refcnt == 1) /* first nested 'on' */ + subdev->plat->set_vpp(1); + } else { + if (--sa1100_vpp_refcnt == 0) /* last nested 'off' */ + subdev->plat->set_vpp(0); + } + spin_unlock_irqrestore(&sa1100_vpp_lock, flags); } static void sa1100_destroy_subdev(struct sa_subdev_info *subdev) @@ -187,7 +95,7 @@ static int sa1100_probe_subdev(struct sa_subdev_info *subdev, struct resource *r goto out; } - if (subdev->data->set_vpp) + if (subdev->plat->set_vpp) subdev->map.set_vpp = sa1100_set_vpp; subdev->map.phys = phys; @@ -204,15 +112,15 @@ static int sa1100_probe_subdev(struct sa_subdev_info *subdev, struct resource *r * Now let's probe for the actual flash. Do it here since * specific machine settings might have been set above. */ - subdev->mtd = do_map_probe(subdev->data->map_name, &subdev->map); + subdev->mtd = do_map_probe(subdev->plat->map_name, &subdev->map); if (subdev->mtd == NULL) { ret = -ENXIO; goto err; } subdev->mtd->owner = THIS_MODULE; - printk(KERN_INFO "SA1100 flash: CFI device at 0x%08lx, %dMiB, " - "%d-bit\n", phys, subdev->mtd->size >> 20, + printk(KERN_INFO "SA1100 flash: CFI device at 0x%08lx, %uMiB, %d-bit\n", + phys, (unsigned)(subdev->mtd->size >> 20), subdev->map.bankwidth * 8); return 0; @@ -223,29 +131,26 @@ static int sa1100_probe_subdev(struct sa_subdev_info *subdev, struct resource *r return ret; } -static void sa1100_destroy(struct sa_info *info) +static void sa1100_destroy(struct sa_info *info, struct flash_platform_data *plat) { int i; if (info->mtd) { - del_mtd_partitions(info->mtd); - -#ifdef CONFIG_MTD_CONCAT + mtd_device_unregister(info->mtd); if (info->mtd != info->subdev[0].mtd) mtd_concat_destroy(info->mtd); -#endif } - if (info->parts) - kfree(info->parts); - for (i = info->num_subdev - 1; i >= 0; i--) sa1100_destroy_subdev(&info->subdev[i]); kfree(info); + + if (plat->exit) + plat->exit(); } -static struct sa_info *__init -sa1100_setup_mtd(struct platform_device *pdev, struct flash_platform_data *flash) +static struct sa_info *sa1100_setup_mtd(struct platform_device *pdev, + struct flash_platform_data *plat) { struct sa_info *info; int nr, size, i, ret = 0; @@ -267,13 +172,17 @@ sa1100_setup_mtd(struct platform_device *pdev, struct flash_platform_data *flash /* * Allocate the map_info structs in one go. */ - info = kmalloc(size, GFP_KERNEL); + info = kzalloc(size, GFP_KERNEL); if (!info) { ret = -ENOMEM; goto out; } - memset(info, 0, size); + if (plat->init) { + ret = plat->init(); + if (ret) + goto err; + } /* * Claim and then map the memory regions. @@ -287,8 +196,8 @@ sa1100_setup_mtd(struct platform_device *pdev, struct flash_platform_data *flash break; subdev->map.name = subdev->name; - sprintf(subdev->name, "sa1100-%d", i); - subdev->data = flash; + sprintf(subdev->name, "%s-%d", plat->name, i); + subdev->plat = plat; ret = sa1100_probe_subdev(subdev, res); if (ret) @@ -309,11 +218,10 @@ sa1100_setup_mtd(struct platform_device *pdev, struct flash_platform_data *flash * otherwise fail. Either way, it'll be called "sa1100". */ if (info->num_subdev == 1) { - strcpy(info->subdev[0].name, "sa1100"); + strcpy(info->subdev[0].name, plat->name); info->mtd = info->subdev[0].mtd; ret = 0; } else if (info->num_subdev > 1) { -#ifdef CONFIG_MTD_CONCAT struct mtd_info *cdev[nr]; /* * We detected multiple devices. Concatenate them together. @@ -322,40 +230,32 @@ sa1100_setup_mtd(struct platform_device *pdev, struct flash_platform_data *flash cdev[i] = info->subdev[i].mtd; info->mtd = mtd_concat_create(cdev, info->num_subdev, - "sa1100"); + plat->name); if (info->mtd == NULL) ret = -ENXIO; -#else - printk(KERN_ERR "SA1100 flash: multiple devices " - "found but MTD concat support disabled.\n"); - ret = -ENXIO; -#endif } if (ret == 0) return info; err: - sa1100_destroy(info); + sa1100_destroy(info, plat); out: return ERR_PTR(ret); } -static const char *part_probes[] = { "cmdlinepart", "RedBoot", NULL }; +static const char * const part_probes[] = { "cmdlinepart", "RedBoot", NULL }; -static int __init sa1100_mtd_probe(struct device *dev) +static int sa1100_mtd_probe(struct platform_device *pdev) { - struct platform_device *pdev = to_platform_device(dev); - struct flash_platform_data *flash = pdev->dev.platform_data; - struct mtd_partition *parts; - const char *part_type = NULL; + struct flash_platform_data *plat = dev_get_platdata(&pdev->dev); struct sa_info *info; - int err, nr_parts = 0; + int err; - if (!flash) + if (!plat) return -ENODEV; - info = sa1100_setup_mtd(pdev, flash); + info = sa1100_setup_mtd(pdev, plat); if (IS_ERR(info)) { err = PTR_ERR(info); goto out; @@ -364,90 +264,38 @@ static int __init sa1100_mtd_probe(struct device *dev) /* * Partition selection stuff. */ -#ifdef CONFIG_MTD_PARTITIONS - nr_parts = parse_mtd_partitions(info->mtd, part_probes, &parts, 0); - if (nr_parts > 0) { - info->parts = parts; - part_type = "dynamic"; - } else -#endif - { - parts = flash->parts; - nr_parts = flash->nr_parts; - part_type = "static"; - } - - if (nr_parts == 0) { - printk(KERN_NOTICE "SA1100 flash: no partition info " - "available, registering whole flash\n"); - add_mtd_device(info->mtd); - } else { - printk(KERN_NOTICE "SA1100 flash: using %s partition " - "definition\n", part_type); - add_mtd_partitions(info->mtd, parts, nr_parts); - } + mtd_device_parse_register(info->mtd, part_probes, NULL, plat->parts, + plat->nr_parts); - dev_set_drvdata(dev, info); + platform_set_drvdata(pdev, info); err = 0; out: return err; } -static int __exit sa1100_mtd_remove(struct device *dev) -{ - struct sa_info *info = dev_get_drvdata(dev); - dev_set_drvdata(dev, NULL); - sa1100_destroy(info); - return 0; -} - -#ifdef CONFIG_PM -static int sa1100_mtd_suspend(struct device *dev, pm_message_t state, u32 level) +static int __exit sa1100_mtd_remove(struct platform_device *pdev) { - struct sa_info *info = dev_get_drvdata(dev); - int ret = 0; + struct sa_info *info = platform_get_drvdata(pdev); + struct flash_platform_data *plat = dev_get_platdata(&pdev->dev); - if (info && level == SUSPEND_SAVE_STATE) - ret = info->mtd->suspend(info->mtd); + sa1100_destroy(info, plat); - return ret; -} - -static int sa1100_mtd_resume(struct device *dev, u32 level) -{ - struct sa_info *info = dev_get_drvdata(dev); - if (info && level == RESUME_RESTORE_STATE) - info->mtd->resume(info->mtd); return 0; } -#else -#define sa1100_mtd_suspend NULL -#define sa1100_mtd_resume NULL -#endif - -static struct device_driver sa1100_mtd_driver = { - .name = "flash", - .bus = &platform_bus_type, + +static struct platform_driver sa1100_mtd_driver = { .probe = sa1100_mtd_probe, .remove = __exit_p(sa1100_mtd_remove), - .suspend = sa1100_mtd_suspend, - .resume = sa1100_mtd_resume, + .driver = { + .name = "sa1100-mtd", + .owner = THIS_MODULE, + }, }; -static int __init sa1100_mtd_init(void) -{ - return driver_register(&sa1100_mtd_driver); -} - -static void __exit sa1100_mtd_exit(void) -{ - driver_unregister(&sa1100_mtd_driver); -} - -module_init(sa1100_mtd_init); -module_exit(sa1100_mtd_exit); +module_platform_driver(sa1100_mtd_driver); MODULE_AUTHOR("Nicolas Pitre"); MODULE_DESCRIPTION("SA1100 CFI map driver"); MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:sa1100-mtd"); |
