diff options
| -rw-r--r-- | target/linux/adm5120-2.6/config/default | 25 | ||||
| -rw-r--r-- | target/linux/adm5120-2.6/files/drivers/mtd/maps/adm5120_mtd.c | 197 | 
2 files changed, 188 insertions, 34 deletions
| diff --git a/target/linux/adm5120-2.6/config/default b/target/linux/adm5120-2.6/config/default index e5894fc9c..bbf6d8b6a 100644 --- a/target/linux/adm5120-2.6/config/default +++ b/target/linux/adm5120-2.6/config/default @@ -76,26 +76,10 @@ CONFIG_CRYPTO_HASH=y  CONFIG_CRYPTO_HMAC=y  CONFIG_CRYPTO_SHA1=y  # CONFIG_DDB5477 is not set -# CONFIG_DEBUG_DRIVER is not set -# CONFIG_DEBUG_INFO is not set -CONFIG_DEBUG_KERNEL=y -# CONFIG_DEBUG_KOBJECT is not set -# CONFIG_DEBUG_LIST is not set -CONFIG_DEBUG_LOCKING_API_SELFTESTS=y -# CONFIG_DEBUG_LOCK_ALLOC is not set -# CONFIG_DEBUG_MUTEXES is not set -# CONFIG_DEBUG_RT_MUTEXES is not set -# CONFIG_DEBUG_RWSEMS is not set -# CONFIG_DEBUG_SLAB is not set -# CONFIG_DEBUG_SPINLOCK is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set -# CONFIG_DEBUG_STACK_USAGE is not set -# CONFIG_DEBUG_VM is not set  CONFIG_DEFAULT_CFQ=y  # CONFIG_DEFAULT_DEADLINE is not set  CONFIG_DEFAULT_IOSCHED="cfq"  CONFIG_DEFAULT_TCP_CONG="cubic" -CONFIG_DETECT_SOFTLOCKUP=y  # CONFIG_DM9000 is not set  CONFIG_DMA_NEED_PCI_MAP_STATE=y  CONFIG_DMA_NONCOHERENT=y @@ -103,7 +87,6 @@ CONFIG_ELF_CORE=y  # CONFIG_EXT2_FS is not set  # CONFIG_EXT3_FS is not set  CONFIG_FIRMWARE_EDID=y -CONFIG_FORCED_INLINING=y  CONFIG_FS_POSIX_ACL=y  CONFIG_FW_LOADER=m  CONFIG_GENERIC_ACL=y @@ -166,7 +149,6 @@ CONFIG_JFFS2_FS_SECURITY=y  CONFIG_JFFS2_FS_XATTR=y  CONFIG_JFFS2_SUMMARY=y  # CONFIG_JFS_FS is not set -# CONFIG_KGDB is not set  CONFIG_LEDS_CLASS=m  CONFIG_LEDS_TRIGGER_HEARTBEAT=m  CONFIG_LEDS_TRIGGER_TIMER=m @@ -206,7 +188,6 @@ CONFIG_MIPS_MT_DISABLED=y  # CONFIG_MIPS_PB1550 is not set  # CONFIG_MIPS_SEAD is not set  # CONFIG_MIPS_SIM is not set -# CONFIG_MIPS_UNCACHED is not set  # CONFIG_MIPS_VPE_LOADER is not set  # CONFIG_MIPS_XXS1500 is not set  CONFIG_MODULE_FORCE_UNLOAD=y @@ -320,7 +301,6 @@ CONFIG_PAGE_SIZE_4KB=y  # CONFIG_PARTITION_ADVANCED is not set  # CONFIG_PCCARD is not set  CONFIG_PCI_ADM5120=y -# CONFIG_PCI_DEBUG is not set  # CONFIG_PMC_YOSEMITE is not set  # CONFIG_PNX8550_JBS is not set  # CONFIG_PNX8550_V2PCI is not set @@ -333,16 +313,11 @@ CONFIG_PPPOE=y  # CONFIG_PPP_MPPE is not set  # CONFIG_PPP_MULTILINK is not set  # CONFIG_PPP_SYNC_TTY is not set -# CONFIG_PROVE_LOCKING is not set -# CONFIG_RCU_TORTURE_TEST is not set  # CONFIG_REISERFS_FS is not set  CONFIG_RELAY=y  # CONFIG_ROMFS_FS is not set  # CONFIG_RTC is not set -# CONFIG_RT_MUTEX_TESTER is not set -# CONFIG_RUNTIME_DEBUG is not set  CONFIG_RWSEM_GENERIC_SPINLOCK=y -# CONFIG_SCHEDSTATS is not set  CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y  # CONFIG_SCSI is not set  # CONFIG_SENSORS_ABITUGURU is not set diff --git a/target/linux/adm5120-2.6/files/drivers/mtd/maps/adm5120_mtd.c b/target/linux/adm5120-2.6/files/drivers/mtd/maps/adm5120_mtd.c index a9e97cb31..2bbb238c3 100644 --- a/target/linux/adm5120-2.6/files/drivers/mtd/maps/adm5120_mtd.c +++ b/target/linux/adm5120-2.6/files/drivers/mtd/maps/adm5120_mtd.c @@ -1,7 +1,8 @@  /*   *	Flash device on the ADM5120 board   * - *	Copyright Jeroen Vreeken (pe1rxq@amsat.org), 2005 + *	Copyright Florian Fainelli <florian@openwrt.org> + *      *   *	This program is free software; you can redistribute it and/or   *	modify it under the terms of the GNU General Public License version @@ -13,43 +14,221 @@  #include <linux/kernel.h>  #include <linux/mtd/mtd.h>  #include <linux/mtd/map.h> +#include <linux/mtd/partitions.h> +#include <linux/vmalloc.h> +  #define FLASH_PHYS_ADDR		0x1FC00000 -#define FLASH_SIZE 		0x200000   +#define FLASH_SIZE 		0x400000 + +#define IMAGE_LEN 		10                   	/* Length of Length Field */ +#define ADDRESS_LEN 		12                 	/* Length of Address field */ +#define EXTENDED_SIZE 		0xBFC00000       	/* Extended flash address */ +#define ROUNDUP(x, y) ((((x)+((y)-1))/(y))*(y)) +   static struct mtd_info *adm5120_mtd; +static struct mtd_partition *parsed_parts;  static struct map_info adm5120_mtd_map = { -	.name = "ADM5120", +	.name = "adm5120",  	.size = FLASH_SIZE,  	.bankwidth = 2,  	.phys = FLASH_PHYS_ADDR,  }; +static int parse_cfe_partitions( struct mtd_info *master, struct mtd_partition **pparts) +{ +	int nrparts = 2, curpart = 0; // CFE and NVRAM always present. +	struct adm5120_cfe_map { +		unsigned char tagVersion[4];                            // Version of the image tag +		unsigned char sig_1[20];                                // Company Line 1 +		unsigned char sig_2[14];                                // Company Line 2 +		unsigned char chipid[6];                                        // Chip this image is for +		unsigned char boardid[16];                              // Board name +		unsigned char bigEndian[2];                             // Map endianness -- 1 BE 0 LE +		unsigned char totalLength[IMAGE_LEN];           //Total length of image +		unsigned char cfeAddress[ADDRESS_LEN];  // Address in memory of CFE +		unsigned char cfeLength[IMAGE_LEN];             // Size of CFE +		unsigned char rootAddress[ADDRESS_LEN];         // Address in memory of rootfs +		unsigned char rootLength[IMAGE_LEN];            // Size of rootfs +		unsigned char kernelAddress[ADDRESS_LEN];       // Address in memory of kernel +		unsigned char kernelLength[IMAGE_LEN];  // Size of kernel +		unsigned char dualImage[2];                             // Unused at present +		unsigned char inactiveFlag[2];                  // Unused at present +		unsigned char reserved1[74];                            // Reserved area not in use +		unsigned char imageCRC[4];                              // CRC32 of images +		unsigned char reserved2[16];                            // Unused at present +		unsigned char headerCRC[4];                             // CRC32 of header excluding tagVersion +		unsigned char reserved3[16];                            // Unused at present +	} *buf; +	struct mtd_partition *parts; +	int ret; +	size_t retlen; +	unsigned int rootfsaddr, kerneladdr, spareaddr; +	unsigned int rootfslen, kernellen, sparelen, totallen; +	int namelen = 0; +	int i; +	// Allocate memory for buffer +	buf = vmalloc(sizeof(struct adm5120_cfe_map)); + +	if (!buf) +		return -ENOMEM; + +	// Get the tag +	ret = master->read(master,master->erasesize,sizeof(struct adm5120_cfe_map), &retlen, (void *)buf); + +	if (retlen != sizeof(struct adm5120_cfe_map)){ +		vfree(buf); +		return -EIO; +	}; + +	printk("adm5120: CFE boot tag found with version %s and board type %s.\n",buf->tagVersion,buf->boardid); +	// Get the values and calculate +	sscanf(buf->rootAddress,"%u", &rootfsaddr); +	rootfsaddr = rootfsaddr - EXTENDED_SIZE; +	sscanf(buf->rootLength, "%u", &rootfslen); +	sscanf(buf->kernelAddress, "%u", &kerneladdr); +	kerneladdr = kerneladdr - EXTENDED_SIZE; +	sscanf(buf->kernelLength, "%u", &kernellen); +	sscanf(buf->totalLength, "%u", &totallen); +	spareaddr = ROUNDUP(totallen,master->erasesize) + master->erasesize; +	sparelen = master->size - spareaddr - master->erasesize; +	// Determine number of partitions +	namelen = 8; +	if (rootfslen > 0){ +		nrparts++; +		namelen =+ 6; +	}; + +	if (kernellen > 0){ +		nrparts++; +		namelen =+ 6; +	}; +	if (sparelen > 0){ +		nrparts++; +		namelen =+ 6; +	}; +	// Ask kernel for more memory. +	parts = kmalloc(sizeof(*parts)*nrparts+10*nrparts, GFP_KERNEL); +	if (!parts){ +		vfree(buf); +		return -ENOMEM; +	}; +	memset(parts,0,sizeof(*parts)*nrparts+10*nrparts); +	// Start building partition list +	parts[curpart].name = "CFE"; +	parts[curpart].offset = 0; +	parts[curpart].size = master->erasesize; +	curpart++; +	if (kernellen > 0) { +		parts[curpart].name = "Kernel"; +		parts[curpart].offset = kerneladdr; +		parts[curpart].size = kernellen; +		curpart++; +	}; +	if (rootfslen > 0) { +		parts[curpart].name = "Rootfs"; +		parts[curpart].offset = rootfsaddr; +		parts[curpart].size = rootfslen; +		curpart++; +	}; +	if (sparelen > 0){ +		parts[curpart].name = "OpenWrt"; +		parts[curpart].offset = spareaddr; +		parts[curpart].size = sparelen; +		curpart++; +	}; +	parts[curpart].name = "NVRAM"; +	parts[curpart].offset = master->size - master->erasesize; +	parts[curpart].size = master->erasesize; +	for (i = 0; i < nrparts; i++) { +		printk("adm5120: Partition %d is %s offset %x and length %x\n", i, parts[i].name, parts[i].offset, parts[i].size); +	} +	*pparts = parts; +	vfree(buf); +	return nrparts; +}; + +static int adm5120_detect_cfe(struct mtd_info *master) +{ +	int idoffset = 0x4e0; +#ifdef CONFIG_CPU_BIG_ENDIAN +	static char idstring[8] = "CFE1CFE1"; +#else +	static char idstring[8] = "1EFC1EFC"; +#endif +	char buf[8]; +	int ret; +	size_t retlen; + +	ret = master->read(master, idoffset, 8, &retlen, (void *)buf); +	printk("adm5120: Read Signature value of %s\n", buf); +	return strcmp(idstring,buf); +} +  static int __init adm5120_mtd_init(void)  { -	printk(KERN_INFO "ADM5120 board flash (0x%x at 0x%x)\n", FLASH_SIZE, +	printk(KERN_INFO "ADM5120 board flash (0x%08x at 0x%08x)\n", FLASH_SIZE,  	    FLASH_PHYS_ADDR); -	adm5120_mtd_map.virt = ioremap_nocache(FLASH_PHYS_ADDR, FLASH_SIZE); + +	adm5120_mtd_map.virt = ioremap(FLASH_PHYS_ADDR, FLASH_SIZE); + +	if (!adm5120_mtd_map.virt) { +		printk("ADM5120: failed to ioremap\n"); +		return -EIO; +	} +		  	simple_map_init(&adm5120_mtd_map); +  	adm5120_mtd = do_map_probe("cfi_probe", &adm5120_mtd_map); +  	if (adm5120_mtd) {  		adm5120_mtd->owner = THIS_MODULE; -		add_mtd_device(adm5120_mtd); +		 +		if (adm5120_detect_cfe(adm5120_mtd) == 0) +		{ +			int parsed_nr_parts = 0; +			char * part_type; + +			printk("adm5120: CFE bootloader detected\n"); +			 +			if (parsed_nr_parts == 0) { +				int ret = parse_cfe_partitions(adm5120_mtd, &parsed_parts); +				 +				if (ret > 0) { +					part_type = "CFE"; +					parsed_nr_parts = ret; +				} +			} +			add_mtd_partitions(adm5120_mtd, parsed_parts, parsed_nr_parts); +			return 0; +		} else { +			add_mtd_device(adm5120_mtd); +		}  		return 0;  	} +	iounmap(adm5120_mtd);  	return -ENXIO;  }  static void __exit adm5120_mtd_exit(void)  { -	del_mtd_device(adm5120_mtd); -	map_destroy(adm5120_mtd); +	if (adm5120_mtd) { +		del_mtd_device(adm5120_mtd); +		map_destroy(adm5120_mtd); +	} + +	if (adm5120_mtd_map.virt) { +		iounmap(adm5120_mtd_map.virt); +		adm5120_mtd_map.virt = 0; +	} +	  }  module_init(adm5120_mtd_init);  module_exit(adm5120_mtd_exit);  MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Jeroen Vreeken (pe1rxq@amsat.org)"); +MODULE_AUTHOR("Florian Fainelli <florian@openwrt.org>");  MODULE_DESCRIPTION("MTD map driver for ADM5120 boards"); | 
