From 2763c508a3c8f8ec5d6df4e8c63d5e2a5a7d3954 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Fri, 17 Jul 2009 17:54:14 +0200 Subject: mtd: physmap_of: use resource_size Signed-off-by: Wolfram Sang Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse --- drivers/mtd/maps/physmap_of.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers/mtd/maps') diff --git a/drivers/mtd/maps/physmap_of.c b/drivers/mtd/maps/physmap_of.c index 39d357b2eb4..f223f3fec3a 100644 --- a/drivers/mtd/maps/physmap_of.c +++ b/drivers/mtd/maps/physmap_of.c @@ -190,6 +190,7 @@ static int __devinit of_flash_probe(struct of_device *dev, const u32 *p; int reg_tuple_size; struct mtd_info **mtd_list = NULL; + resource_size_t res_size; reg_tuple_size = (of_n_addr_cells(dp) + of_n_size_cells(dp)) * sizeof(u32); @@ -233,8 +234,8 @@ static int __devinit of_flash_probe(struct of_device *dev, (unsigned long long)res.end); err = -EBUSY; - info->list[i].res = request_mem_region(res.start, res.end - - res.start + 1, + res_size = resource_size(&res); + info->list[i].res = request_mem_region(res.start, res_size, dev_name(&dev->dev)); if (!info->list[i].res) goto err_out; @@ -249,7 +250,7 @@ static int __devinit of_flash_probe(struct of_device *dev, info->list[i].map.name = dev_name(&dev->dev); info->list[i].map.phys = res.start; - info->list[i].map.size = res.end - res.start + 1; + info->list[i].map.size = res_size; info->list[i].map.bankwidth = *width; err = -ENOMEM; -- cgit v1.2.3-70-g09d2 From 76d6a4791609e4d14b411a513c7648b19b258d8f Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Fri, 17 Jul 2009 17:47:37 +0200 Subject: mtd: plat-ram: use resource_size Signed-off-by: Wolfram Sang Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse --- drivers/mtd/maps/plat-ram.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/mtd/maps') diff --git a/drivers/mtd/maps/plat-ram.c b/drivers/mtd/maps/plat-ram.c index 49c9ece7647..dafb91944e7 100644 --- a/drivers/mtd/maps/plat-ram.c +++ b/drivers/mtd/maps/plat-ram.c @@ -175,7 +175,7 @@ static int platram_probe(struct platform_device *pdev) /* setup map parameters */ info->map.phys = res->start; - info->map.size = (res->end - res->start) + 1; + info->map.size = resource_size(res); info->map.name = pdata->mapname != NULL ? (char *)pdata->mapname : (char *)pdev->name; info->map.bankwidth = pdata->bankwidth; -- cgit v1.2.3-70-g09d2 From ad4fbc7921bd7cca108ecc1340a014e91ecc8536 Mon Sep 17 00:00:00 2001 From: vimal singh Date: Thu, 30 Jul 2009 20:54:27 +0530 Subject: mtd: physmap_of: fix incorrect check This patch fixes a spelling error that has resulted from copy and pasting. The location of the error was found using a semantic patch but the semantic patch was not trying to find these errors. After looking things over it seemed logical that this change was needed. The patch also makes sure mtd_list is not being freed if it has not been allocated Signed-off-by: Stoyan Gaydarov Signed-off-by: Vimal Singh Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse --- drivers/mtd/maps/physmap_of.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'drivers/mtd/maps') diff --git a/drivers/mtd/maps/physmap_of.c b/drivers/mtd/maps/physmap_of.c index f223f3fec3a..e828d58910f 100644 --- a/drivers/mtd/maps/physmap_of.c +++ b/drivers/mtd/maps/physmap_of.c @@ -205,7 +205,7 @@ static int __devinit of_flash_probe(struct of_device *dev, dev_err(&dev->dev, "Malformed reg property on %s\n", dev->node->full_name); err = -EINVAL; - goto err_out; + goto err_flash_remove; } count /= reg_tuple_size; @@ -213,14 +213,14 @@ static int __devinit of_flash_probe(struct of_device *dev, info = kzalloc(sizeof(struct of_flash) + sizeof(struct of_flash_list) * count, GFP_KERNEL); if (!info) - goto err_out; - - mtd_list = kzalloc(sizeof(struct mtd_info) * count, GFP_KERNEL); - if (!info) - goto err_out; + goto err_flash_remove; dev_set_drvdata(&dev->dev, info); + mtd_list = kzalloc(sizeof(struct mtd_info) * count, GFP_KERNEL); + if (!mtd_list) + goto err_flash_remove; + for (i = 0; i < count; i++) { err = -ENXIO; if (of_address_to_resource(dp, i, &res)) { @@ -339,6 +339,7 @@ static int __devinit of_flash_probe(struct of_device *dev, err_out: kfree(mtd_list); +err_flash_remove: of_flash_remove(dev); return err; -- cgit v1.2.3-70-g09d2 From 2c78c44362bc9b7c715a3c2119b89a407c1cb739 Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Mon, 10 Aug 2009 10:16:37 +0200 Subject: mtd: pmcmsp-flash: fix error paths in init_msp_flash Cleanin up after errors in init_msp_flash(). Also cleanup_msp_flash() attempts to determine the size of msp_flash with `sizeof(msp_flash) / sizeof(struct mtd_info **)' This will not work since msp_flash is not an array. Signed-off-by: Roel Kluin Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse --- drivers/mtd/maps/pmcmsp-flash.c | 76 ++++++++++++++++++++++++++++++++--------- 1 file changed, 59 insertions(+), 17 deletions(-) (limited to 'drivers/mtd/maps') diff --git a/drivers/mtd/maps/pmcmsp-flash.c b/drivers/mtd/maps/pmcmsp-flash.c index 4768bd5459d..c8fd8da4bc8 100644 --- a/drivers/mtd/maps/pmcmsp-flash.c +++ b/drivers/mtd/maps/pmcmsp-flash.c @@ -50,7 +50,7 @@ static int fcnt; static int __init init_msp_flash(void) { - int i, j; + int i, j, ret = -ENOMEM; int offset, coff; char *env; int pcnt; @@ -75,14 +75,16 @@ static int __init init_msp_flash(void) printk(KERN_NOTICE "Found %d PMC flash devices\n", fcnt); msp_flash = kmalloc(fcnt * sizeof(struct map_info *), GFP_KERNEL); + if (!msp_flash) + return -ENOMEM; + msp_parts = kmalloc(fcnt * sizeof(struct mtd_partition *), GFP_KERNEL); + if (!msp_parts) + goto free_msp_flash; + 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; - } + if (!msp_maps) + goto free_msp_parts; /* loop over the flash devices, initializing each */ for (i = 0; i < fcnt; i++) { @@ -100,13 +102,18 @@ static int __init init_msp_flash(void) msp_parts[i] = kcalloc(pcnt, sizeof(struct mtd_partition), GFP_KERNEL); + if (!msp_parts[i]) + goto cleanup_loop; /* now initialize the devices proper */ flash_name[5] = '0' + i; env = prom_getenv(flash_name); - if (sscanf(env, "%x:%x", &addr, &size) < 2) - return -ENXIO; + if (sscanf(env, "%x:%x", &addr, &size) < 2) { + ret = -ENXIO; + kfree(msp_parts[i]); + goto cleanup_loop; + } addr = CPHYSADDR(addr); printk(KERN_NOTICE @@ -122,13 +129,23 @@ static int __init init_msp_flash(void) */ if (size > CONFIG_MSP_FLASH_MAP_LIMIT) size = CONFIG_MSP_FLASH_MAP_LIMIT; + msp_maps[i].virt = ioremap(addr, size); + if (msp_maps[i].virt == NULL) { + ret = -ENXIO; + kfree(msp_parts[i]); + goto cleanup_loop; + } + msp_maps[i].bankwidth = 1; - msp_maps[i].name = strncpy(kmalloc(7, GFP_KERNEL), - flash_name, 7); + msp_maps[i].name = kmalloc(7, GFP_KERNEL); + if (!msp_maps[i].name) { + iounmap(msp_maps[i].virt); + kfree(msp_parts[i]); + goto cleanup_loop; + } - if (msp_maps[i].virt == NULL) - return -ENXIO; + msp_maps[i].name = strncpy(msp_maps[i].name, flash_name, 7); for (j = 0; j < pcnt; j++) { part_name[5] = '0' + i; @@ -136,8 +153,14 @@ static int __init init_msp_flash(void) env = prom_getenv(part_name); - if (sscanf(env, "%x:%x:%n", &offset, &size, &coff) < 2) - return -ENXIO; + if (sscanf(env, "%x:%x:%n", &offset, &size, + &coff) < 2) { + ret = -ENXIO; + kfree(msp_maps[i].name); + iounmap(msp_maps[i].virt); + kfree(msp_parts[i]); + goto cleanup_loop; + } msp_parts[i][j].size = size; msp_parts[i][j].offset = offset; @@ -152,18 +175,37 @@ static int __init init_msp_flash(void) add_mtd_partitions(msp_flash[i], msp_parts[i], pcnt); } else { printk(KERN_ERR "map probe failed for flash\n"); - return -ENXIO; + ret = -ENXIO; + kfree(msp_maps[i].name); + iounmap(msp_maps[i].virt); + kfree(msp_parts[i]); + goto cleanup_loop; } } return 0; + +cleanup_loop: + while (i--) { + del_mtd_partitions(msp_flash[i]); + map_destroy(msp_flash[i]); + kfree(msp_maps[i].name); + iounmap(msp_maps[i].virt); + kfree(msp_parts[i]); + } + kfree(msp_maps); +free_msp_parts: + kfree(msp_parts); +free_msp_flash: + kfree(msp_flash); + return ret; } static void __exit cleanup_msp_flash(void) { int i; - for (i = 0; i < sizeof(msp_flash) / sizeof(struct mtd_info **); i++) { + for (i = 0; i < fcnt; i++) { del_mtd_partitions(msp_flash[i]); map_destroy(msp_flash[i]); iounmap((void *)msp_maps[i].virt); -- cgit v1.2.3-70-g09d2 From 3ff230a742b8fc196c1fe69875a57a429877cacb Mon Sep 17 00:00:00 2001 From: Timofei Bondarenko Date: Wed, 20 May 2009 19:59:02 -0400 Subject: mtd/maps: uclinux: fix building when partition support is disabled The uClinux map driver doesn't even use partitions, so we shouldn't require it in order to work properly. Signed-off-by: Timofei Bondarenko Signed-off-by: Mike Frysinger Signed-off-by: Sonic Zhang CC: Greg Ungerer CC: uclinux-dev@uclinux.org CC: linux-mtd@lists.infradead.org Signed-off-by: David Woodhouse --- drivers/mtd/maps/uclinux.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/mtd/maps') diff --git a/drivers/mtd/maps/uclinux.c b/drivers/mtd/maps/uclinux.c index d4314fb8821..35009294b43 100644 --- a/drivers/mtd/maps/uclinux.c +++ b/drivers/mtd/maps/uclinux.c @@ -89,7 +89,11 @@ static int __init uclinux_mtd_init(void) mtd->priv = mapp; uclinux_ram_mtdinfo = mtd; +#ifdef CONFIG_MTD_PARTITIONS add_mtd_partitions(mtd, uclinux_romfs, NUM_PARTITIONS); +#else + add_mtd_device(mtd); +#endif return(0); } @@ -99,7 +103,11 @@ static int __init uclinux_mtd_init(void) static void __exit uclinux_mtd_cleanup(void) { if (uclinux_ram_mtdinfo) { +#ifdef CONFIG_MTD_PARTITIONS del_mtd_partitions(uclinux_ram_mtdinfo); +#else + del_mtd_device(uclinux_ram_mtdinfo); +#endif map_destroy(uclinux_ram_mtdinfo); uclinux_ram_mtdinfo = NULL; } -- cgit v1.2.3-70-g09d2 From 1b533d227e5f8356d2f009f90b8c8c1f02eb71b8 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Tue, 9 Jun 2009 10:37:18 +0000 Subject: mtd/maps: uclinux: depend on MTD_RAM being built into the kernel If MTD_RAM is built as a module, the uClinux map does not work since it can only be built in to the kernel. Signed-off-by: Mike Frysinger Signed-off-by: David Woodhouse --- drivers/mtd/maps/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/mtd/maps') diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig index 7a58bd5522f..0f314eb430c 100644 --- a/drivers/mtd/maps/Kconfig +++ b/drivers/mtd/maps/Kconfig @@ -486,7 +486,7 @@ config MTD_BFIN_ASYNC config MTD_UCLINUX bool "Generic uClinux RAM/ROM filesystem support" - depends on MTD_PARTITIONS && MTD_RAM && !MMU + depends on MTD_PARTITIONS && MTD_RAM=y && !MMU help Map driver to support image based filesystems for uClinux. -- cgit v1.2.3-70-g09d2 From d79c326c048246b855b83a0092e6324df0717735 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Wed, 20 May 2009 12:04:09 -0400 Subject: mtd/maps: gpio-addr-flash: new driver for GPIO assisted flash addressing This driver lets people use GPIO's for additional address lines in case their processor does not have enough address lines already. Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu Signed-off-by: David Woodhouse --- drivers/mtd/maps/Kconfig | 10 ++ drivers/mtd/maps/Makefile | 3 +- drivers/mtd/maps/gpio-addr-flash.c | 311 +++++++++++++++++++++++++++++++++++++ 3 files changed, 322 insertions(+), 2 deletions(-) create mode 100644 drivers/mtd/maps/gpio-addr-flash.c (limited to 'drivers/mtd/maps') diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig index 0f314eb430c..3a9a960644b 100644 --- a/drivers/mtd/maps/Kconfig +++ b/drivers/mtd/maps/Kconfig @@ -484,6 +484,16 @@ config MTD_BFIN_ASYNC If compiled as a module, it will be called bfin-async-flash. +config MTD_GPIO_ADDR + tristate "GPIO-assisted Flash Chip Support" + depends on MTD_COMPLEX_MAPPINGS + select MTD_PARTITIONS + help + Map driver which allows flashes to be partially physically addressed + and assisted by GPIOs. + + If compiled as a module, it will be called gpio-addr-flash. + config MTD_UCLINUX bool "Generic uClinux RAM/ROM filesystem support" depends on MTD_PARTITIONS && MTD_RAM=y && !MMU diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile index 5beb0662d72..1d5cf863672 100644 --- a/drivers/mtd/maps/Makefile +++ b/drivers/mtd/maps/Makefile @@ -58,5 +58,4 @@ obj-$(CONFIG_MTD_PLATRAM) += plat-ram.o obj-$(CONFIG_MTD_OMAP_NOR) += omap_nor.o obj-$(CONFIG_MTD_INTEL_VR_NOR) += intel_vr_nor.o obj-$(CONFIG_MTD_BFIN_ASYNC) += bfin-async-flash.o -obj-$(CONFIG_MTD_RBTX4939) += rbtx4939-flash.o -obj-$(CONFIG_MTD_VMU) += vmu-flash.o +obj-$(CONFIG_MTD_GPIO_ADDR) += gpio-addr-flash.o diff --git a/drivers/mtd/maps/gpio-addr-flash.c b/drivers/mtd/maps/gpio-addr-flash.c new file mode 100644 index 00000000000..44ef9a49a86 --- /dev/null +++ b/drivers/mtd/maps/gpio-addr-flash.c @@ -0,0 +1,311 @@ +/* + * drivers/mtd/maps/gpio-addr-flash.c + * + * Handle the case where a flash device is mostly addressed using physical + * line and supplemented by GPIOs. This way you can hook up say a 8MiB flash + * to a 2MiB memory range and use the GPIOs to select a particular range. + * + * Copyright © 2000 Nicolas Pitre + * Copyright © 2005-2009 Analog Devices Inc. + * + * Enter bugs at http://blackfin.uclinux.org/ + * + * Licensed under the GPL-2 or later. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define pr_devinit(fmt, args...) ({ static const __devinitconst char __fmt[] = fmt; printk(__fmt, ## args); }) + +#define DRIVER_NAME "gpio-addr-flash" +#define PFX DRIVER_NAME ": " + +/** + * struct async_state - keep GPIO flash state + * @mtd: MTD state for this mapping + * @map: MTD map state for this flash + * @gpio_count: number of GPIOs used to address + * @gpio_addrs: array of GPIOs to twiddle + * @gpio_values: cached GPIO values + * @win_size: dedicated memory size (if no GPIOs) + */ +struct async_state { + struct mtd_info *mtd; + struct map_info map; + size_t gpio_count; + unsigned *gpio_addrs; + int *gpio_values; + unsigned long win_size; +}; +#define gf_map_info_to_state(mi) ((struct async_state *)(mi)->map_priv_1) + +/** + * gf_set_gpios() - set GPIO address lines to access specified flash offset + * @state: GPIO flash state + * @ofs: desired offset to access + * + * Rather than call the GPIO framework every time, cache the last-programmed + * value. This speeds up sequential accesses (which are by far the most common + * type). We rely on the GPIO framework to treat non-zero value as high so + * that we don't have to normalize the bits. + */ +static void gf_set_gpios(struct async_state *state, unsigned long ofs) +{ + size_t i = 0; + int value; + ofs /= state->win_size; + do { + value = ofs & (1 << i); + if (state->gpio_values[i] != value) { + gpio_set_value(state->gpio_addrs[i], value); + state->gpio_values[i] = value; + } + } while (++i < state->gpio_count); +} + +/** + * gf_read() - read a word at the specified offset + * @map: MTD map state + * @ofs: desired offset to read + */ +static map_word gf_read(struct map_info *map, unsigned long ofs) +{ + struct async_state *state = gf_map_info_to_state(map); + uint16_t word; + map_word test; + + gf_set_gpios(state, ofs); + + word = readw(map->virt + (ofs % state->win_size)); + test.x[0] = word; + return test; +} + +/** + * gf_copy_from() - copy a chunk of data from the flash + * @map: MTD map state + * @to: memory to copy to + * @from: flash offset to copy from + * @len: how much to copy + * + * We rely on the MTD layer to chunk up copies such that a single request here + * will not cross a window size. This allows us to only wiggle the GPIOs once + * before falling back to a normal memcpy. Reading the higher layer code shows + * that this is indeed the case, but add a BUG_ON() to future proof. + */ +static void gf_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) +{ + struct async_state *state = gf_map_info_to_state(map); + + gf_set_gpios(state, from); + + /* BUG if operation crosses the win_size */ + BUG_ON(!((from + len) % state->win_size <= (from + len))); + + /* operation does not cross the win_size, so one shot it */ + memcpy_fromio(to, map->virt + (from % state->win_size), len); +} + +/** + * gf_write() - write a word at the specified offset + * @map: MTD map state + * @ofs: desired offset to write + */ +static void gf_write(struct map_info *map, map_word d1, unsigned long ofs) +{ + struct async_state *state = gf_map_info_to_state(map); + uint16_t d; + + gf_set_gpios(state, ofs); + + d = d1.x[0]; + writew(d, map->virt + (ofs % state->win_size)); +} + +/** + * gf_copy_to() - copy a chunk of data to the flash + * @map: MTD map state + * @to: flash offset to copy to + * @from: memory to copy from + * @len: how much to copy + * + * See gf_copy_from() caveat. + */ +static void gf_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) +{ + struct async_state *state = gf_map_info_to_state(map); + + gf_set_gpios(state, to); + + /* BUG if operation crosses the win_size */ + BUG_ON(!((to + len) % state->win_size <= (to + len))); + + /* operation does not cross the win_size, so one shot it */ + memcpy_toio(map->virt + (to % state->win_size), from, len); +} + +#ifdef CONFIG_MTD_PARTITIONS +static const char *part_probe_types[] = { "cmdlinepart", "RedBoot", NULL }; +#endif + +/** + * gpio_flash_probe() - setup a mapping for a GPIO assisted flash + * @pdev: platform device + * + * The platform resource layout expected looks something like: + * struct mtd_partition partitions[] = { ... }; + * struct physmap_flash_data flash_data = { ... }; + * unsigned flash_gpios[] = { GPIO_XX, GPIO_XX, ... }; + * struct resource flash_resource[] = { + * { + * .name = "cfi_probe", + * .start = 0x20000000, + * .end = 0x201fffff, + * .flags = IORESOURCE_MEM, + * }, { + * .start = (unsigned long)flash_gpios, + * .end = ARRAY_SIZE(flash_gpios), + * .flags = IORESOURCE_IRQ, + * } + * }; + * struct platform_device flash_device = { + * .name = "gpio-addr-flash", + * .dev = { .platform_data = &flash_data, }, + * .num_resources = ARRAY_SIZE(flash_resource), + * .resource = flash_resource, + * ... + * }; + */ +static int __devinit gpio_flash_probe(struct platform_device *pdev) +{ + int ret; + size_t i, arr_size; + struct physmap_flash_data *pdata; + struct resource *memory; + struct resource *gpios; + struct async_state *state; + + pdata = pdev->dev.platform_data; + memory = platform_get_resource(pdev, IORESOURCE_MEM, 0); + gpios = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + + if (!memory || !gpios || !gpios->end) + return -EINVAL; + + arr_size = sizeof(int) * gpios->end; + state = kzalloc(sizeof(*state) + arr_size, GFP_KERNEL); + if (!state) + return -ENOMEM; + + state->gpio_count = gpios->end; + state->gpio_addrs = (void *)gpios->start; + state->gpio_values = (void *)(state + 1); + state->win_size = memory->end - memory->start + 1; + memset(state->gpio_values, 0xff, arr_size); + + state->map.name = DRIVER_NAME; + state->map.read = gf_read; + state->map.copy_from = gf_copy_from; + state->map.write = gf_write; + state->map.copy_to = gf_copy_to; + state->map.bankwidth = pdata->width; + state->map.size = state->win_size * (1 << state->gpio_count); + state->map.virt = (void __iomem *)memory->start; + state->map.phys = NO_XIP; + state->map.map_priv_1 = (unsigned long)state; + + platform_set_drvdata(pdev, state); + + i = 0; + do { + if (gpio_request(state->gpio_addrs[i], DRIVER_NAME)) { + pr_devinit(KERN_ERR PFX "failed to request gpio %d\n", + state->gpio_addrs[i]); + while (i--) + gpio_free(state->gpio_addrs[i]); + kfree(state); + return -EBUSY; + } + gpio_direction_output(state->gpio_addrs[i], 0); + } while (++i < state->gpio_count); + + pr_devinit(KERN_NOTICE PFX "probing %d-bit flash bus\n", + state->map.bankwidth * 8); + state->mtd = do_map_probe(memory->name, &state->map); + if (!state->mtd) { + for (i = 0; i < state->gpio_count; ++i) + gpio_free(state->gpio_addrs[i]); + kfree(state); + return -ENXIO; + } + +#ifdef CONFIG_MTD_PARTITIONS + ret = parse_mtd_partitions(state->mtd, part_probe_types, &pdata->parts, 0); + if (ret > 0) { + pr_devinit(KERN_NOTICE PFX "Using commandline partition definition\n"); + add_mtd_partitions(state->mtd, pdata->parts, ret); + kfree(pdata->parts); + + } else if (pdata->nr_parts) { + pr_devinit(KERN_NOTICE PFX "Using board partition definition\n"); + add_mtd_partitions(state->mtd, pdata->parts, pdata->nr_parts); + + } else +#endif + { + pr_devinit(KERN_NOTICE PFX "no partition info available, registering whole flash at once\n"); + add_mtd_device(state->mtd); + } + + return 0; +} + +static int __devexit gpio_flash_remove(struct platform_device *pdev) +{ + struct async_state *state = platform_get_drvdata(pdev); + size_t i = 0; + do { + gpio_free(state->gpio_addrs[i]); + } while (++i < state->gpio_count); +#ifdef CONFIG_MTD_PARTITIONS + del_mtd_partitions(state->mtd); +#endif + map_destroy(state->mtd); + kfree(state); + return 0; +} + +static struct platform_driver gpio_flash_driver = { + .probe = gpio_flash_probe, + .remove = __devexit_p(gpio_flash_remove), + .driver = { + .name = DRIVER_NAME, + }, +}; + +static int __init gpio_flash_init(void) +{ + return platform_driver_register(&gpio_flash_driver); +} +module_init(gpio_flash_init); + +static void __exit gpio_flash_exit(void) +{ + platform_driver_unregister(&gpio_flash_driver); +} +module_exit(gpio_flash_exit); + +MODULE_AUTHOR("Mike Frysinger "); +MODULE_DESCRIPTION("MTD map driver for flashes addressed physically and with gpios"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3-70-g09d2 From fc28c39f0ef59bfb649ddfd633275be8e45c0f9c Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Fri, 17 Jul 2009 14:39:23 +0200 Subject: mtd: maps: add mtd-ram support to physmap_of MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use physmap_of to access RAMs as mtd and add documenation for it. This approach is a lot less intrusive as adding an of-wrapper around plat-ram.c. As most extensions of plat-ram.c (e.g. custom map-functions) can't be mapped to the device tree anyhow, extending physmap_of seems to be the cleanest approach. Tested with a phyCORE-MPC5121e. Signed-off-by: Wolfram Sang Cc: Vitaly Wool Cc: Artem Bityutskiy Cc: Ken MacLeod Cc: Albrecht Dreß Acked-by: Grant Likely Signed-off-by: David Woodhouse --- Documentation/powerpc/dts-bindings/mtd-physmap.txt | 42 +++++++++++++--------- drivers/mtd/maps/physmap_of.c | 4 +++ 2 files changed, 30 insertions(+), 16 deletions(-) (limited to 'drivers/mtd/maps') diff --git a/Documentation/powerpc/dts-bindings/mtd-physmap.txt b/Documentation/powerpc/dts-bindings/mtd-physmap.txt index 667c9bde869..80152cb567d 100644 --- a/Documentation/powerpc/dts-bindings/mtd-physmap.txt +++ b/Documentation/powerpc/dts-bindings/mtd-physmap.txt @@ -1,18 +1,19 @@ -CFI or JEDEC memory-mapped NOR flash +CFI or JEDEC memory-mapped NOR flash, MTD-RAM (NVRAM...) Flash chips (Memory Technology Devices) are often used for solid state file systems on embedded devices. - - compatible : should contain the specific model of flash chip(s) - used, if known, followed by either "cfi-flash" or "jedec-flash" - - reg : Address range(s) of the flash chip(s) + - compatible : should contain the specific model of mtd chip(s) + used, if known, followed by either "cfi-flash", "jedec-flash" + or "mtd-ram". + - reg : Address range(s) of the mtd chip(s) It's possible to (optionally) define multiple "reg" tuples so that - non-identical NOR chips can be described in one flash node. - - bank-width : Width (in bytes) of the flash bank. Equal to the + non-identical chips can be described in one node. + - bank-width : Width (in bytes) of the bank. Equal to the device width times the number of interleaved chips. - - device-width : (optional) Width of a single flash chip. If + - device-width : (optional) Width of a single mtd chip. If omitted, assumed to be equal to 'bank-width'. - - #address-cells, #size-cells : Must be present if the flash has + - #address-cells, #size-cells : Must be present if the device has sub-nodes representing partitions (see below). In this case both #address-cells and #size-cells must be equal to 1. @@ -22,24 +23,24 @@ are defined: - vendor-id : Contains the flash chip's vendor id (1 byte). - device-id : Contains the flash chip's device id (1 byte). -In addition to the information on the flash bank itself, the +In addition to the information on the mtd bank itself, the device tree may optionally contain additional information -describing partitions of the flash address space. This can be +describing partitions of the address space. This can be used on platforms which have strong conventions about which -portions of the flash are used for what purposes, but which don't +portions of a flash are used for what purposes, but which don't use an on-flash partition table such as RedBoot. -Each partition is represented as a sub-node of the flash device. +Each partition is represented as a sub-node of the mtd device. Each node's name represents the name of the corresponding -partition of the flash device. +partition of the mtd device. Flash partitions - - reg : The partition's offset and size within the flash bank. - - label : (optional) The label / name for this flash partition. + - reg : The partition's offset and size within the mtd bank. + - label : (optional) The label / name for this partition. If omitted, the label is taken from the node name (excluding the unit address). - read-only : (optional) This parameter, if present, is a hint to - Linux that this flash partition should only be mounted + Linux that this partition should only be mounted read-only. This is usually used for flash partitions containing early-boot firmware images or data which should not be clobbered. @@ -78,3 +79,12 @@ Here an example with multiple "reg" tuples: reg = <0 0x04000000>; }; }; + +An example using SRAM: + + sram@2,0 { + compatible = "samsung,k6f1616u6a", "mtd-ram"; + reg = <2 0 0x00200000>; + bank-width = <2>; + }; + diff --git a/drivers/mtd/maps/physmap_of.c b/drivers/mtd/maps/physmap_of.c index e828d58910f..61e4eb48bb2 100644 --- a/drivers/mtd/maps/physmap_of.c +++ b/drivers/mtd/maps/physmap_of.c @@ -361,6 +361,10 @@ static struct of_device_id of_flash_match[] = { .compatible = "jedec-flash", .data = (void *)"jedec_probe", }, + { + .compatible = "mtd-ram", + .data = (void *)"map_ram", + }, { .type = "rom", .compatible = "direct-mapped" -- cgit v1.2.3-70-g09d2