diff options
Diffstat (limited to 'drivers/mtd/maps/ocelot.c')
-rw-r--r-- | drivers/mtd/maps/ocelot.c | 175 |
1 files changed, 175 insertions, 0 deletions
diff --git a/drivers/mtd/maps/ocelot.c b/drivers/mtd/maps/ocelot.c new file mode 100644 index 00000000000..82c3070678c --- /dev/null +++ b/drivers/mtd/maps/ocelot.c @@ -0,0 +1,175 @@ +/* + * $Id: ocelot.c,v 1.16 2005/01/05 18:05:13 dwmw2 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"); |