mirror of
				git://git.openwrt.org/openwrt/openwrt.git
				synced 2025-11-03 22:44:27 -05:00 
			
		
		
		
	replace the custom mtd driver with a partition parser
Signed-off-by: Florian Fainelli <florian@openwrt.org> SVN-Revision: 34554
This commit is contained in:
		
							parent
							
								
									b516c8d89d
								
							
						
					
					
						commit
						1232f91efb
					
				@ -60,7 +60,8 @@ CONFIG_MIPS=y
 | 
				
			|||||||
CONFIG_MIPS_L1_CACHE_SHIFT=5
 | 
					CONFIG_MIPS_L1_CACHE_SHIFT=5
 | 
				
			||||||
# CONFIG_MIPS_MACHINE is not set
 | 
					# CONFIG_MIPS_MACHINE is not set
 | 
				
			||||||
CONFIG_MIPS_MT_DISABLED=y
 | 
					CONFIG_MIPS_MT_DISABLED=y
 | 
				
			||||||
CONFIG_MTD_ADM8668_NOR=y
 | 
					CONFIG_MTD_ADM8668_PARTS=y
 | 
				
			||||||
 | 
					CONFIG_MTD_PHYSMAP=y
 | 
				
			||||||
CONFIG_NEED_DMA_MAP_STATE=y
 | 
					CONFIG_NEED_DMA_MAP_STATE=y
 | 
				
			||||||
CONFIG_NEED_PER_CPU_KM=y
 | 
					CONFIG_NEED_PER_CPU_KM=y
 | 
				
			||||||
CONFIG_NO_EXCEPT_FILL=y
 | 
					CONFIG_NO_EXCEPT_FILL=y
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,6 @@
 | 
				
			|||||||
/*
 | 
					/*
 | 
				
			||||||
 | 
					 * Infineon/ADMTek 8668 (WildPass) platform devices support
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 * Copyright (C) 2010 Scott Nicholas <neutronscott@scottn.us>
 | 
					 * Copyright (C) 2010 Scott Nicholas <neutronscott@scottn.us>
 | 
				
			||||||
 * Copyright (C) 2012 Florian Fainelli <florian@openwrt.org>
 | 
					 * Copyright (C) 2012 Florian Fainelli <florian@openwrt.org>
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
@ -11,6 +13,7 @@
 | 
				
			|||||||
#include <linux/kernel.h>
 | 
					#include <linux/kernel.h>
 | 
				
			||||||
#include <linux/platform_device.h>
 | 
					#include <linux/platform_device.h>
 | 
				
			||||||
#include <linux/mtd/physmap.h>
 | 
					#include <linux/mtd/physmap.h>
 | 
				
			||||||
 | 
					#include <linux/mtd/partitions.h>
 | 
				
			||||||
#include <linux/pci.h>
 | 
					#include <linux/pci.h>
 | 
				
			||||||
#include <linux/slab.h>
 | 
					#include <linux/slab.h>
 | 
				
			||||||
#include <linux/ioport.h>
 | 
					#include <linux/ioport.h>
 | 
				
			||||||
@ -89,9 +92,33 @@ static struct platform_device adm8668_eth1_device = {
 | 
				
			|||||||
	.num_resources	= ARRAY_SIZE(eth1_resources),
 | 
						.num_resources	= ARRAY_SIZE(eth1_resources),
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const char *nor_probe_types[] = { "adm8668part", NULL };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct physmap_flash_data nor_flash_data = {
 | 
				
			||||||
 | 
						.width			= 2,
 | 
				
			||||||
 | 
						.part_probe_types	= nor_probe_types,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct resource nor_resources[] = {
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							.start	= ADM8668_SMEM1_BASE,
 | 
				
			||||||
 | 
							.end	= ADM8668_SMEM1_BASE + 0x800000 - 1,
 | 
				
			||||||
 | 
							.flags	= IORESOURCE_MEM,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct platform_device adm8668_nor_device = {
 | 
				
			||||||
 | 
						.name		= "physmap-flash",
 | 
				
			||||||
 | 
						.id		= -1,
 | 
				
			||||||
 | 
						.resource	= nor_resources,
 | 
				
			||||||
 | 
						.num_resources	= ARRAY_SIZE(nor_resources),
 | 
				
			||||||
 | 
						.dev.platform_data = &nor_flash_data,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct platform_device *adm8668_devs[] = {
 | 
					static struct platform_device *adm8668_devs[] = {
 | 
				
			||||||
	&adm8668_eth0_device,
 | 
						&adm8668_eth0_device,
 | 
				
			||||||
	&adm8668_eth1_device,
 | 
						&adm8668_eth1_device,
 | 
				
			||||||
 | 
						&adm8668_nor_device,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int __devinit adm8668_devs_register(void)
 | 
					int __devinit adm8668_devs_register(void)
 | 
				
			||||||
 | 
				
			|||||||
@ -1,8 +1,8 @@
 | 
				
			|||||||
/*
 | 
					/*
 | 
				
			||||||
 | 
					 * Infineon/ADMTek ADM8668 (WildPass) partition parser support
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 * Copyright (C) 2010 Scott Nicholas <neutronscott@scottn.us>
 | 
					 * Copyright (C) 2010 Scott Nicholas <neutronscott@scottn.us>
 | 
				
			||||||
 *  Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>
 | 
					 * Copyright (C) 2012 Florian Fainelli <florian@openwrt.org>
 | 
				
			||||||
 *  Copyright (C) 2005 Waldemar Brodkorb <wbx@openwrt.org>
 | 
					 | 
				
			||||||
 *  Copyright (C) 2004 Florian Schirmer (jolt@tuxbox.org)
 | 
					 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * original functions for finding root filesystem from Mike Baker
 | 
					 * original functions for finding root filesystem from Mike Baker
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
@ -34,9 +34,6 @@
 | 
				
			|||||||
 * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
 | 
					 * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
 | 
				
			||||||
 * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
 | 
					 * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
 | 
				
			||||||
 * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
 | 
					 * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Flash mapping for adm8668 boards
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <linux/module.h>
 | 
					#include <linux/module.h>
 | 
				
			||||||
@ -45,16 +42,13 @@
 | 
				
			|||||||
#include <linux/sched.h>
 | 
					#include <linux/sched.h>
 | 
				
			||||||
#include <linux/wait.h>
 | 
					#include <linux/wait.h>
 | 
				
			||||||
#include <linux/mtd/mtd.h>
 | 
					#include <linux/mtd/mtd.h>
 | 
				
			||||||
#include <linux/mtd/map.h>
 | 
					 | 
				
			||||||
#include <linux/slab.h>
 | 
					 | 
				
			||||||
#include <linux/mtd/partitions.h>
 | 
					#include <linux/mtd/partitions.h>
 | 
				
			||||||
 | 
					#include <linux/vmalloc.h>
 | 
				
			||||||
 | 
					#include <linux/slab.h>
 | 
				
			||||||
#include <linux/crc32.h>
 | 
					#include <linux/crc32.h>
 | 
				
			||||||
#include <linux/magic.h>
 | 
					#include <linux/magic.h>
 | 
				
			||||||
#include <asm/io.h>
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define WINDOW_ADDR	0x10000000
 | 
					#define PFX	"adm8668-part: "
 | 
				
			||||||
#define WINDOW_SIZE	0x800000
 | 
					 | 
				
			||||||
#define BANKWIDTH	2
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* first a little bit about the headers i need.. */
 | 
					/* first a little bit about the headers i need.. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -81,176 +75,122 @@ struct uboot_header {
 | 
				
			|||||||
	char		ih_name[32];	/* image name */
 | 
						char		ih_name[32];	/* image name */
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/************************************************/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static struct mtd_info *adm8668_mtd;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct map_info adm8668_map = {
 | 
					 | 
				
			||||||
	name: "adm8668-nor",
 | 
					 | 
				
			||||||
	size: WINDOW_SIZE,
 | 
					 | 
				
			||||||
	phys: WINDOW_ADDR,
 | 
					 | 
				
			||||||
	bankwidth: BANKWIDTH,
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * Copied from mtdblock.c
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Cache stuff...
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Since typical flash erasable sectors are much larger than what Linux's
 | 
					 | 
				
			||||||
 * buffer cache can handle, we must implement read-modify-write on flash
 | 
					 | 
				
			||||||
 * sectors for each block write requests.  To avoid over-erasing flash sectors
 | 
					 | 
				
			||||||
 * and to speed things up, we locally cache a whole flash sector while it is
 | 
					 | 
				
			||||||
 * being written to until a different sector is required.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void erase_callback(struct erase_info *done)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	wait_queue_head_t *wait_q = (wait_queue_head_t *)done->priv;
 | 
					 | 
				
			||||||
	wake_up(wait_q);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int erase_write (struct mtd_info *mtd, unsigned long pos,
 | 
					 | 
				
			||||||
			int len, const char *buf)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct erase_info erase;
 | 
					 | 
				
			||||||
	DECLARE_WAITQUEUE(wait, current);
 | 
					 | 
				
			||||||
	wait_queue_head_t wait_q;
 | 
					 | 
				
			||||||
	size_t retlen;
 | 
					 | 
				
			||||||
	int ret;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/*
 | 
					 | 
				
			||||||
	 * First, let's erase the flash block.
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	init_waitqueue_head(&wait_q);
 | 
					 | 
				
			||||||
	erase.mtd = mtd;
 | 
					 | 
				
			||||||
	erase.callback = erase_callback;
 | 
					 | 
				
			||||||
	erase.addr = pos;
 | 
					 | 
				
			||||||
	erase.len = len;
 | 
					 | 
				
			||||||
	erase.priv = (u_long)&wait_q;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	set_current_state(TASK_INTERRUPTIBLE);
 | 
					 | 
				
			||||||
	add_wait_queue(&wait_q, &wait);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ret = mtd->erase(mtd, &erase);
 | 
					 | 
				
			||||||
	if (ret) {
 | 
					 | 
				
			||||||
		set_current_state(TASK_RUNNING);
 | 
					 | 
				
			||||||
		remove_wait_queue(&wait_q, &wait);
 | 
					 | 
				
			||||||
		printk (KERN_WARNING "erase of region [0x%lx, 0x%x] "
 | 
					 | 
				
			||||||
				     "on \"%s\" failed\n",
 | 
					 | 
				
			||||||
			pos, len, mtd->name);
 | 
					 | 
				
			||||||
		return ret;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	schedule();  /* Wait for erase to finish. */
 | 
					 | 
				
			||||||
	remove_wait_queue(&wait_q, &wait);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/*
 | 
					 | 
				
			||||||
	 * Next, write data to flash.
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ret = mtd->write (mtd, pos, len, &retlen, buf);
 | 
					 | 
				
			||||||
	if (ret)
 | 
					 | 
				
			||||||
		return ret;
 | 
					 | 
				
			||||||
	if (retlen != len)
 | 
					 | 
				
			||||||
		return -EIO;
 | 
					 | 
				
			||||||
	return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* decent defaults in case... shrug */
 | 
					 | 
				
			||||||
static struct mtd_partition adm8668_parts[] = {
 | 
					 | 
				
			||||||
	{ name: "linux",	offset: 0x40000,	size: WINDOW_SIZE-0x40000, },
 | 
					 | 
				
			||||||
	{ name: "rootfs",	offset: 0xe0000,	size: 0x140000, },
 | 
					 | 
				
			||||||
	{ name: "uboot_env",	offset: 0x20000,	size: 0x20000, },
 | 
					 | 
				
			||||||
	{ name: NULL, },
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* in case i wanna change stuff later, and to clarify the math section... */
 | 
					/* in case i wanna change stuff later, and to clarify the math section... */
 | 
				
			||||||
#define	PART_LINUX	0
 | 
					#define	PART_LINUX	0
 | 
				
			||||||
#define	PART_ROOTFS	1
 | 
					#define	PART_ROOTFS	1
 | 
				
			||||||
 | 
					#define PART_UBOOT_ENV	2
 | 
				
			||||||
#define	NR_PARTS	3
 | 
					#define	NR_PARTS	3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int __init
 | 
					static int adm8668_parse_partitions(struct mtd_info *master,
 | 
				
			||||||
init_mtd_partitions(struct mtd_info *mtd, size_t size)
 | 
									    struct mtd_partition **pparts,
 | 
				
			||||||
 | 
									    struct mtd_part_parser_data *data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						int ret;
 | 
				
			||||||
	struct uboot_header uhdr;
 | 
						struct uboot_header uhdr;
 | 
				
			||||||
	int off, blocksize;
 | 
						int off, blocksize;
 | 
				
			||||||
	size_t len, linux_len;
 | 
						size_t len, linux_len;
 | 
				
			||||||
	struct squashfs_super_block shdr;
 | 
						struct squashfs_super_block shdr;
 | 
				
			||||||
 | 
						struct erase_info erase_info;
 | 
				
			||||||
 | 
						struct mtd_partition *adm8668_parts;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						memset(&erase_info, 0, sizeof(erase_info));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						blocksize = master->erasesize;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	blocksize = mtd->erasesize;
 | 
					 | 
				
			||||||
	if (blocksize < 0x10000)
 | 
						if (blocksize < 0x10000)
 | 
				
			||||||
		blocksize = 0x10000;
 | 
							blocksize = 0x10000;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						adm8668_parts = kzalloc(sizeof(*adm8668_parts) * NR_PARTS, GFP_KERNEL);
 | 
				
			||||||
 | 
						if (!adm8668_parts)
 | 
				
			||||||
 | 
							return -ENOMEM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						adm8668_parts[PART_LINUX].name = kstrdup("linux", GFP_KERNEL);
 | 
				
			||||||
 | 
						adm8668_parts[PART_LINUX].offset = 0x40000;
 | 
				
			||||||
 | 
						adm8668_parts[PART_LINUX].size = master->size - 0x40000;
 | 
				
			||||||
 | 
						adm8668_parts[PART_ROOTFS].name = kstrdup("rootfs", GFP_KERNEL);
 | 
				
			||||||
 | 
						adm8668_parts[PART_ROOTFS].offset = 0xe0000;
 | 
				
			||||||
 | 
						adm8668_parts[PART_ROOTFS].size = 0x140000;
 | 
				
			||||||
 | 
						adm8668_parts[PART_UBOOT_ENV].name = kstrdup("uboot_env", GFP_KERNEL);
 | 
				
			||||||
 | 
						adm8668_parts[PART_UBOOT_ENV].offset = 0x20000;
 | 
				
			||||||
 | 
						adm8668_parts[PART_UBOOT_ENV].size = 0x20000;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* now find squashfs */
 | 
						/* now find squashfs */
 | 
				
			||||||
	memset(&shdr, 0xe5, sizeof(shdr));
 | 
						memset(&shdr, 0xe5, sizeof(shdr));
 | 
				
			||||||
	for (off = adm8668_parts[PART_LINUX].offset; off < size; off += blocksize) {
 | 
					
 | 
				
			||||||
 | 
						for (off = 0x40000; off < master->size; off += blocksize) {
 | 
				
			||||||
		/*
 | 
							/*
 | 
				
			||||||
		 * Read into buffer
 | 
							 * Read into buffer
 | 
				
			||||||
		 */
 | 
							 */
 | 
				
			||||||
		if (mtd->read(mtd, off, sizeof(shdr), &len, (char *)&shdr) ||
 | 
							if (mtd_read(master, off, sizeof(shdr), &len, (char *)&shdr) ||
 | 
				
			||||||
		    len != sizeof(shdr))
 | 
							    len != sizeof(shdr))
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (shdr.s_magic == SQUASHFS_MAGIC) {
 | 
							if (shdr.s_magic == SQUASHFS_MAGIC) {
 | 
				
			||||||
			uint32_t fs_size = (uint32_t)shdr.bytes_used;
 | 
								uint32_t fs_size = (uint32_t)shdr.bytes_used;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			printk(KERN_INFO "%s: Filesystem type: squashfs, size=%dkB\n",
 | 
								pr_info(PFX "filesystem type: squashfs, size=%dkB\n",
 | 
				
			||||||
				mtd->name, fs_size>>10);
 | 
									fs_size >> 10);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			/* Update rootfs based on the superblock info, and
 | 
								/*
 | 
				
			||||||
			 * stretch to end of MTD. rootfs_split will split it */
 | 
								 * Update rootfs based on the superblock info, and
 | 
				
			||||||
 | 
								 * stretch to end of MTD. rootfs_split will split it
 | 
				
			||||||
 | 
								 */
 | 
				
			||||||
			adm8668_parts[PART_ROOTFS].offset = off;
 | 
								adm8668_parts[PART_ROOTFS].offset = off;
 | 
				
			||||||
			adm8668_parts[PART_ROOTFS].size = mtd->size -
 | 
								adm8668_parts[PART_ROOTFS].size = master->size -
 | 
				
			||||||
				adm8668_parts[PART_ROOTFS].offset;
 | 
									adm8668_parts[PART_ROOTFS].offset;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			/* kernel ends where rootfs starts
 | 
								/*
 | 
				
			||||||
			 * but we'll keep it full-length for upgrades */
 | 
								 * kernel ends where rootfs starts
 | 
				
			||||||
			linux_len = adm8668_parts[PART_LINUX+1].offset -
 | 
								 * but we'll keep it full-length for upgrades
 | 
				
			||||||
 | 
								 */
 | 
				
			||||||
 | 
								linux_len = adm8668_parts[PART_LINUX + 1].offset -
 | 
				
			||||||
				adm8668_parts[PART_LINUX].offset;
 | 
									adm8668_parts[PART_LINUX].offset;
 | 
				
			||||||
#if 1
 | 
					
 | 
				
			||||||
			adm8668_parts[PART_LINUX].size = mtd->size -
 | 
								adm8668_parts[PART_LINUX].size = master->size -
 | 
				
			||||||
				adm8668_parts[PART_LINUX].offset;
 | 
									adm8668_parts[PART_LINUX].offset;
 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
			adm8668_parts[PART_LINUX].size = linux_len;
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
			goto found;
 | 
								goto found;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	printk(KERN_NOTICE
 | 
						pr_err(PFX "could't find root filesystem\n");
 | 
				
			||||||
	       "%s: Couldn't find root filesystem\n",
 | 
					 | 
				
			||||||
	       mtd->name);
 | 
					 | 
				
			||||||
	return NR_PARTS;
 | 
						return NR_PARTS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 found:
 | 
					found:
 | 
				
			||||||
	if (mtd->read(mtd, adm8668_parts[PART_LINUX].offset, sizeof(uhdr), &len, (char *)&uhdr) ||
 | 
						if (mtd_read(master, adm8668_parts[PART_LINUX].offset, sizeof(uhdr), &len, (char *)&uhdr) ||
 | 
				
			||||||
	    len != sizeof(uhdr))
 | 
						    len != sizeof(uhdr)) {
 | 
				
			||||||
 | 
							pr_err(PFX "failed to read u-boot header\n");
 | 
				
			||||||
		return NR_PARTS;
 | 
							return NR_PARTS;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* that's odd. how'd ya boot it then */
 | 
						if (uhdr.ih_magic != IH_MAGIC) {
 | 
				
			||||||
	if (uhdr.ih_magic != IH_MAGIC)
 | 
							pr_info(PFX "invalid u-boot magic detected?!?!\n");
 | 
				
			||||||
		return NR_PARTS;
 | 
							return NR_PARTS;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (be32_to_cpu(uhdr.ih_size) != (linux_len - sizeof(uhdr))) {
 | 
						if (be32_to_cpu(uhdr.ih_size) != (linux_len - sizeof(uhdr))) {
 | 
				
			||||||
		unsigned char *block, *data;
 | 
							u32 data;
 | 
				
			||||||
 | 
							size_t data_len = 0;
 | 
				
			||||||
 | 
							unsigned char *block;
 | 
				
			||||||
		unsigned int offset;
 | 
							unsigned int offset;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		offset = adm8668_parts[PART_LINUX].offset +
 | 
							offset = adm8668_parts[PART_LINUX].offset +
 | 
				
			||||||
			 sizeof(struct uboot_header);
 | 
								 sizeof(struct uboot_header);
 | 
				
			||||||
		data = (unsigned char *)(WINDOW_ADDR | 0xA0000000 | offset);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		printk(KERN_NOTICE "Updating U-boot image:\n");
 | 
							pr_info(PFX "Updating U-boot image:\n");
 | 
				
			||||||
		printk(KERN_NOTICE "  old: [size: %8d crc32: 0x%08x]\n",
 | 
							pr_info(PFX "  old: [size: %8d crc32: 0x%08x]\n",
 | 
				
			||||||
			be32_to_cpu(uhdr.ih_size), be32_to_cpu(uhdr.ih_dcrc));
 | 
								be32_to_cpu(uhdr.ih_size), be32_to_cpu(uhdr.ih_dcrc));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (mtd_read(master, offset, sizeof(data), &data_len, (char *)&data)) {
 | 
				
			||||||
 | 
								pr_err(PFX "failed to read data\n");
 | 
				
			||||||
 | 
								goto out;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/* Update the data length & crc32 */
 | 
							/* Update the data length & crc32 */
 | 
				
			||||||
		uhdr.ih_size = cpu_to_be32(linux_len - sizeof(uhdr));
 | 
							uhdr.ih_size = cpu_to_be32(linux_len - sizeof(uhdr));
 | 
				
			||||||
		uhdr.ih_dcrc = crc32_le(~0, data, linux_len - sizeof(uhdr)) ^ (~0);
 | 
							uhdr.ih_dcrc = crc32_le(~0, (char *)&data, linux_len - sizeof(uhdr)) ^ (~0);
 | 
				
			||||||
		uhdr.ih_dcrc = cpu_to_be32(uhdr.ih_dcrc);
 | 
							uhdr.ih_dcrc = cpu_to_be32(uhdr.ih_dcrc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		printk(KERN_NOTICE "  new: [size: %8d crc32: 0x%08x]\n",
 | 
							pr_info(PFX "  new: [size: %8d crc32: 0x%08x]\n",
 | 
				
			||||||
			be32_to_cpu(uhdr.ih_size), be32_to_cpu(uhdr.ih_dcrc));
 | 
								be32_to_cpu(uhdr.ih_size), be32_to_cpu(uhdr.ih_dcrc));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/* update header's crc... */
 | 
							/* update header's crc... */
 | 
				
			||||||
@ -260,75 +200,64 @@ init_mtd_partitions(struct mtd_info *mtd, size_t size)
 | 
				
			|||||||
		uhdr.ih_hcrc = cpu_to_be32(uhdr.ih_hcrc);
 | 
							uhdr.ih_hcrc = cpu_to_be32(uhdr.ih_hcrc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/* read first eraseblock from the image */
 | 
							/* read first eraseblock from the image */
 | 
				
			||||||
		block = kmalloc(mtd->erasesize, GFP_KERNEL);
 | 
							block = vmalloc(master->erasesize);
 | 
				
			||||||
		if (mtd->read(mtd, adm8668_parts[PART_LINUX].offset, mtd->erasesize, &len, block) || len != mtd->erasesize) {
 | 
							if (!block)
 | 
				
			||||||
			printk("Error copying first eraseblock\n");
 | 
								return -ENOMEM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (mtd_read(master, adm8668_parts[PART_LINUX].offset, master->erasesize, &len, block)
 | 
				
			||||||
 | 
									|| len != master->erasesize) {
 | 
				
			||||||
 | 
								pr_err(PFX "error copying first eraseblock\n");
 | 
				
			||||||
			return 0;
 | 
								return 0;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/* Write updated header to the flash */
 | 
							/* Write updated header to the flash */
 | 
				
			||||||
		memcpy(block, &uhdr, sizeof(uhdr));
 | 
							memcpy(block, &uhdr, sizeof(uhdr));
 | 
				
			||||||
		if (mtd->unlock)
 | 
							if (master->unlock)
 | 
				
			||||||
			mtd->unlock(mtd, off, mtd->erasesize);
 | 
								master->unlock(master, off, master->erasesize);
 | 
				
			||||||
		erase_write(mtd, adm8668_parts[PART_LINUX].offset, mtd->erasesize, block);
 | 
					
 | 
				
			||||||
		if (mtd->sync)
 | 
							erase_info.mtd = master;
 | 
				
			||||||
			mtd->sync(mtd);
 | 
							erase_info.addr = (uint64_t)adm8668_parts[PART_LINUX].offset;
 | 
				
			||||||
		kfree(block);
 | 
							erase_info.len = master->erasesize;
 | 
				
			||||||
		printk(KERN_NOTICE "Done\n");
 | 
							ret = mtd_erase(master, &erase_info);
 | 
				
			||||||
 | 
							if (!ret) {
 | 
				
			||||||
 | 
								if (mtd_write(master, adm8668_parts[PART_LINUX].offset, master->erasesize,
 | 
				
			||||||
 | 
										&len, block))
 | 
				
			||||||
 | 
									pr_err(PFX "write failed");
 | 
				
			||||||
 | 
							} else
 | 
				
			||||||
 | 
								pr_err(PFX "erase failed");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							mtd_sync(master);
 | 
				
			||||||
 | 
					out:
 | 
				
			||||||
 | 
							if (block)
 | 
				
			||||||
 | 
								vfree(block);
 | 
				
			||||||
 | 
							pr_info(PFX "done\n");
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						*pparts = adm8668_parts;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return NR_PARTS;
 | 
						return NR_PARTS;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int __init init_adm8668_map(void)
 | 
					static struct mtd_part_parser adm8668_parser = {
 | 
				
			||||||
 | 
						.owner	= THIS_MODULE,
 | 
				
			||||||
 | 
						.parse_fn = adm8668_parse_partitions,
 | 
				
			||||||
 | 
						.name = "adm8668part",
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int __init adm8668_parser_init(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int nr_parts, ret;
 | 
						return register_mtd_parser(&adm8668_parser);
 | 
				
			||||||
 | 
					 | 
				
			||||||
	adm8668_map.virt = ioremap(WINDOW_ADDR, WINDOW_SIZE);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (!adm8668_map.virt) {
 | 
					 | 
				
			||||||
		printk(KERN_ERR "Failed to ioremap\n");
 | 
					 | 
				
			||||||
		return -EIO;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	simple_map_init(&adm8668_map);
 | 
					 | 
				
			||||||
	if (!(adm8668_mtd = do_map_probe("cfi_probe", &adm8668_map))) {
 | 
					 | 
				
			||||||
		printk(KERN_ERR "cfi_probe failed\n");
 | 
					 | 
				
			||||||
		iounmap((void *)adm8668_map.virt);
 | 
					 | 
				
			||||||
		return -ENXIO;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	adm8668_mtd->owner = THIS_MODULE;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	nr_parts = init_mtd_partitions(adm8668_mtd, adm8668_mtd->size);
 | 
					 | 
				
			||||||
	ret = mtd_device_register(adm8668_mtd, adm8668_parts, nr_parts);
 | 
					 | 
				
			||||||
	if (ret) {
 | 
					 | 
				
			||||||
		printk(KERN_ERR "Flash: mtd_device_register failed\n");
 | 
					 | 
				
			||||||
		goto fail;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 fail:
 | 
					 | 
				
			||||||
	if (adm8668_mtd)
 | 
					 | 
				
			||||||
		map_destroy(adm8668_mtd);
 | 
					 | 
				
			||||||
	if (adm8668_map.virt)
 | 
					 | 
				
			||||||
		iounmap((void *) adm8668_map.virt);
 | 
					 | 
				
			||||||
	adm8668_map.virt = 0;
 | 
					 | 
				
			||||||
	return ret;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void __exit cleanup_adm8668_map(void)
 | 
					static void __exit adm8668_parser_exit(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	mtd_device_unregister(adm8668_mtd);
 | 
						deregister_mtd_parser(&adm8668_parser);
 | 
				
			||||||
	map_destroy(adm8668_mtd);
 | 
					 | 
				
			||||||
	iounmap((void *) adm8668_map.virt);
 | 
					 | 
				
			||||||
	adm8668_map.virt = 0;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module_init(init_adm8668_map);
 | 
					module_init(adm8668_parser_init);
 | 
				
			||||||
module_exit(cleanup_adm8668_map);
 | 
					module_exit(adm8668_parser_exit);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MODULE_LICENSE("GPL");
 | 
					MODULE_LICENSE("GPL");
 | 
				
			||||||
MODULE_AUTHOR("Scott Nicholas <neutronscott@scottn.us>");
 | 
					MODULE_AUTHOR("Scott Nicholas <neutronscott@scottn.us>");
 | 
				
			||||||
MODULE_DESCRIPTION("MTD map driver for ADM8668 NOR Flash");
 | 
					MODULE_AUTHOR("Florian Fainelli <florian@openwrt.org>");
 | 
				
			||||||
 | 
					MODULE_DESCRIPTION("MTD partition parser for ADM8668");
 | 
				
			||||||
 | 
				
			|||||||
@ -4,11 +4,11 @@
 | 
				
			|||||||
 	default "0x02000000"
 | 
					 	default "0x02000000"
 | 
				
			||||||
 	depends on MSP_FLASH_MAP_LIMIT_32M
 | 
					 	depends on MSP_FLASH_MAP_LIMIT_32M
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
+config MTD_ADM8668_NOR
 | 
					+config MTD_ADM8668_PARTS
 | 
				
			||||||
+	tristate "ADM8668 NOR mapping"
 | 
					+	tristate "ADM8668 partition parser"
 | 
				
			||||||
+	depends on ADM8668 && MTD_CFI
 | 
					+	depends on ADM8668
 | 
				
			||||||
+	help
 | 
					+	help
 | 
				
			||||||
+	  mapping driver for ADM8668 NOR
 | 
					+	  Partition parser for the Infineon/ADMTek ADM8668 (WildPass).
 | 
				
			||||||
+
 | 
					+
 | 
				
			||||||
 config MTD_SUN_UFLASH
 | 
					 config MTD_SUN_UFLASH
 | 
				
			||||||
 	tristate "Sun Microsystems userflash support"
 | 
					 	tristate "Sun Microsystems userflash support"
 | 
				
			||||||
@ -19,7 +19,7 @@
 | 
				
			|||||||
 endif
 | 
					 endif
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
 # Chip mappings
 | 
					 # Chip mappings
 | 
				
			||||||
+obj-$(CONFIG_MTD_ADM8668_NOR)	+= adm8668.o
 | 
					+obj-$(CONFIG_MTD_ADM8668_PARTS)	+= adm8668.o
 | 
				
			||||||
 obj-$(CONFIG_MTD_CDB89712)	+= cdb89712.o
 | 
					 obj-$(CONFIG_MTD_CDB89712)	+= cdb89712.o
 | 
				
			||||||
 obj-$(CONFIG_MTD_CFI_FLAGADM)	+= cfi_flagadm.o
 | 
					 obj-$(CONFIG_MTD_CFI_FLAGADM)	+= cfi_flagadm.o
 | 
				
			||||||
 obj-$(CONFIG_MTD_DC21285)	+= dc21285.o
 | 
					 obj-$(CONFIG_MTD_DC21285)	+= dc21285.o
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user