diff -urN linux.old/drivers/mtd/maps/Kconfig linux.dev/drivers/mtd/maps/Kconfig --- linux.old/drivers/mtd/maps/Kconfig 2007-01-07 13:15:25.000000000 +0100 +++ linux.dev/drivers/mtd/maps/Kconfig 2007-01-07 14:04:12.000000000 +0100 @@ -622,5 +622,17 @@ This selection automatically selects the map_ram driver. -endmenu +config MTD_AR531X + tristate "AR531X Flash device in physical memory map" + depends on MTD + help + Map driver for Atheros SoC AR531x + +config MTD_AR531X_SIZE + hex "Physical size" + depends on MTD_AR531X + default "0x400000" + help + Physical size flash +endmenu diff -urN linux.old/drivers/mtd/maps/Makefile linux.dev/drivers/mtd/maps/Makefile --- linux.old/drivers/mtd/maps/Makefile 2007-01-07 13:59:37.000000000 +0100 +++ linux.dev/drivers/mtd/maps/Makefile 2007-01-07 13:59:57.000000000 +0100 @@ -70,3 +70,4 @@ 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_AR531X) += ar531x_flash.o diff -urN linux.old/drivers/mtd/maps/ar531x_flash.c linux.dev/drivers/mtd/maps/ar531x_flash.c --- linux.old/drivers/mtd/maps/ar531x_flash.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.dev/drivers/mtd/maps/ar531x_flash.c 2007-01-08 00:34:02.000000000 +0100 @@ -0,0 +1,208 @@ +/* + * Normal mappings of chips in physical memory + */ + +#include +#include +#include +#include +#include +#include +#include +#include + + +#ifdef CONFIG_MTD_PARTITIONS +#include +#define MTDID "ar531x" +#endif + +#define WINDOW_ADDR 0xbe000000 +#define WINDOW_SIZE CONFIG_MTD_AR531X_SIZE + + +/* These ought to be somewhere common... */ + +#define AR531X_FLASHCTL 0x18400000 + +#define FLASHCTL_MW 0x30000000 /* Memory width */ +#define FLASHCTL_MWx8 0x00000000 /* Memory width x8 */ +#define FLASHCTL_MWx16 0x10000000 /* Memory width x16 */ +#define FLASHCTL_MWx32 0x20000000 /* Memory width x32 (not supported) */ + +#define sysRegRead(phys) __raw_readl(KSEG1ADDR(phys)) + + +static struct mtd_info *mymtd; + +#ifdef CONFIG_MTD_PARTITIONS +static const char *probes []={"cmdlinepart",NULL}; +#endif + +struct map_info ar531x_map = { + name: "ar531x", + size: WINDOW_SIZE +}; + +#ifdef CONFIG_MTD_PARTITIONS +static struct mtd_partition *mtd_parts = 0; +static int mtd_parts_nb = 0; + +struct img_info { + uint32_t lenght; + uint32_t CRC; + }; + +static struct mtd_partition ar531x_partitions[] = { + { + name: "bdata", + size: 0x10000, /* 64KB */ + offset: 0, + }, { + name: "boot", + size: 0x40000, /* 256KB */ + offset: MTDPART_OFS_APPEND, + }, { + name: "zImage", + size: 0x0, + offset: MTDPART_OFS_APPEND, + }, { + name: "root", + size: 0x0, + offset: MTDPART_OFS_APPEND, + }, { + name: "EEPROM", + size: 0x10000, /* 64KB */ + offset: MTDPART_OFS_APPEND, + } + +}; + +#define NUM_PARTITIONS (sizeof(ar531x_partitions)/sizeof(struct mtd_partition)) +#endif + + + +int __init init_ar531x(void) +{ + static const char *rom_probe_types[] = { "cfi_probe", "jedec_probe", "map_rom", 0 }; + const char **type; + unsigned int flashctl; + void *buf; + size_t retlen; + int ret; + struct img_info *image_info; + + + /* This is nasty, but needed as the new AR2312-01 parts only + * have an 8 bit bus to the flash; others have 16 + */ + + flashctl = sysRegRead(AR531X_FLASHCTL) & FLASHCTL_MW; + + if (flashctl == FLASHCTL_MWx8) + ar531x_map.bankwidth = 1; + else if (flashctl == FLASHCTL_MWx16) + ar531x_map.bankwidth = 2; + else { + printk(KERN_ERR "ar531x illegal flash buswidth (%#x)\n", + flashctl); + return -ENXIO; + } + +// printk(KERN_NOTICE "ar531x flash buswidth detected as %d\n", +// ar531x_map.bankwidth); + + /* + * Must make sure that WINDOW_ADDR is in kseg1 (uncached) + */ + ar531x_map.map_priv_1 = (WINDOW_ADDR | KSEG1); + + ar531x_map.phys = WINDOW_ADDR; + ar531x_map.virt = ioremap(WINDOW_ADDR,WINDOW_SIZE); + + if (!ar531x_map.virt) { + printk("Failed to ioremap\n"); + return -EIO; + } + + simple_map_init(&ar531x_map); + + mymtd = 0; + type = rom_probe_types; + for(; !mymtd && *type; type++) { + mymtd = do_map_probe(*type, &ar531x_map); + } + if (mymtd) { + mymtd->owner = THIS_MODULE; + add_mtd_device(mymtd); + printk(KERN_NOTICE "AR531x Flash device initialized: size 0x%x at 0x%x bankwidth 0x%x\n", + mymtd->size, WINDOW_ADDR, ar531x_map.bankwidth); + +#ifdef CONFIG_MTD_PARTITIONS + mtd_parts_nb = parse_mtd_partitions(mymtd, probes, &mtd_parts,0); + if (mtd_parts_nb > 0) + { + printk(KERN_NOTICE + "Using command line partition definition\n"); + add_mtd_partitions (mymtd, mtd_parts, mtd_parts_nb); + } + + else { + +/* Pokus o identifikaci openwrt firmware a jeho rozlozeni */ + + buf=vmalloc(mymtd->erasesize); + if (buf) { + ret=mymtd->read(mymtd,0,mymtd->erasesize, &retlen, buf); + if (ret) + goto out; + + if (retlen != mymtd->erasesize) + goto out; + + if (strstr(buf+0x10,"CA804.SOB")) { + image_info = buf+0x56; + ar531x_partitions[2].size = (image_info->lenght & 0xffff0000) + 0x10000; /* Velikost kernelu */ + ar531x_partitions[3].size = mymtd->size - ar531x_partitions[0].size + - ar531x_partitions[1].size + - ar531x_partitions[2].size + - ar531x_partitions[4].size; /* Velikost rootFS */ + if (NUM_PARTITIONS != 0) + { + printk(KERN_NOTICE "Using ar531x openwrt partition definition\n"); + add_mtd_partitions (mymtd, ar531x_partitions, NUM_PARTITIONS); + } + + } +out: + vfree(buf); + } + } +#endif + + return 0; + } + iounmap ((void *)ar531x_map.virt); + return -ENXIO; +} + +static void __exit cleanup_ar531x(void) +{ + if (mymtd) { + del_mtd_device(mymtd); + map_destroy(mymtd); + } + if (ar531x_map.virt) { + iounmap ((void *)ar531x_map.virt); + ar531x_map.virt=0; + } +} + +module_init(init_ar531x); +module_exit(cleanup_ar531x); + + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Tomas Dlabac"); +MODULE_DESCRIPTION("Atheros AR531x MTD map driver");