diff options
14 files changed, 1171 insertions, 28 deletions
| diff --git a/target/linux/brcm47xx/config-3.2 b/target/linux/brcm47xx/config-3.2 index e4641ed10..39fac67ad 100644 --- a/target/linux/brcm47xx/config-3.2 +++ b/target/linux/brcm47xx/config-3.2 @@ -24,6 +24,7 @@ CONFIG_BCMA_DRIVER_PCI_HOSTMODE=y  CONFIG_BCMA_HOST_PCI=y  CONFIG_BCMA_HOST_PCI_POSSIBLE=y  CONFIG_BCMA_HOST_SOC=y +CONFIG_BCMA_NFLASH=y  CONFIG_BCMA_POSSIBLE=y  CONFIG_BCMA_SFLASH=y  CONFIG_CC_OPTIMIZE_FOR_SIZE=y @@ -94,6 +95,10 @@ CONFIG_MIPS_MT_DISABLED=y  CONFIG_MTD_BCM47XX_PARTS=y  CONFIG_MTD_BCM47XX_PFLASH=y  CONFIG_MTD_BCM47XX_SFLASH=y +CONFIG_MTD_NAND=y +CONFIG_MTD_NAND_BCM47XX=y +CONFIG_MTD_NAND_ECC=y +# CONFIG_MTD_SM_COMMON is not set  CONFIG_NEED_DMA_MAP_STATE=y  CONFIG_NEED_PER_CPU_KM=y  CONFIG_PAGEFLAGS_EXTENDED=y diff --git a/target/linux/brcm47xx/patches-3.2/030-bcm47xx-bcma-nandflash.patch b/target/linux/brcm47xx/patches-3.2/030-bcm47xx-bcma-nandflash.patch new file mode 100644 index 000000000..4f4386e93 --- /dev/null +++ b/target/linux/brcm47xx/patches-3.2/030-bcm47xx-bcma-nandflash.patch @@ -0,0 +1,1138 @@ +--- a/arch/mips/bcm47xx/bus.c ++++ b/arch/mips/bcm47xx/bus.c +@@ -2,6 +2,7 @@ +  * BCM947xx nvram variable access +  * +  * Copyright (C) 2011 Hauke Mehrtens <hauke@hauke-m.de> ++ * Copyright (C) 2011-2012 Tathagata Das <tathagata@alumnux.com> +  * +  * This program is free software; you can redistribute  it and/or modify it +  * under  the terms of  the GNU General  Public License as published by the +@@ -92,3 +93,9 @@ void bcm47xx_sflash_struct_ssb_init(stru + 	sflash->numblocks = scc->sflash.numblocks; + 	sflash->size = scc->sflash.size; + } ++ ++void bcm47xx_nflash_struct_bcma_init(struct bcm47xx_nflash *nflash, struct bcma_drv_cc *bcc) ++{ ++	nflash->nflash_type = BCM47XX_BUS_TYPE_BCMA; ++	nflash->bcc = bcc; ++} +--- a/arch/mips/bcm47xx/nvram.c ++++ b/arch/mips/bcm47xx/nvram.c +@@ -4,6 +4,7 @@ +  * Copyright (C) 2005 Broadcom Corporation +  * Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org> +  * Copyright (C) 2010-2011 Hauke Mehrtens <hauke@hauke-m.de> ++ * Copyright (C) 2011-2012 Tathagata Das <tathagata@alumnux.com> +  * +  * This program is free software; you can redistribute  it and/or modify it +  * under  the terms of  the GNU General  Public License as published by the +@@ -21,6 +22,7 @@ + #include <asm/mach-bcm47xx/nvram.h> + #include <asm/mach-bcm47xx/bcm47xx.h> + #include <asm/mach-bcm47xx/bus.h> ++#include <linux/mtd/bcm47xx_nand.h> +  + static char nvram_buf[NVRAM_SPACE]; +  +@@ -137,6 +139,51 @@ found: + 	return 0; + } +  ++static int early_nvram_init_nflash(void) ++{ ++	struct nvram_header *header; ++	u32 off; ++	int ret; ++	int len; ++	u32 flash_size = bcm47xx_nflash.size; ++	u8 tmpbuf[NFL_SECTOR_SIZE]; ++	int i; ++	u32 *src, *dst; ++ ++	/* check if the struct is already initilized */ ++	if (!flash_size) ++		return -1; ++	 ++	cfe_env = 0; ++ ++	off = FLASH_MIN; ++	while (off <= flash_size) { ++		ret = bcma_nflash_read(bcm47xx_nflash.bcc, off, NFL_SECTOR_SIZE, tmpbuf); ++		if (ret != NFL_SECTOR_SIZE) ++			goto done; ++		header = (struct nvram_header *)tmpbuf; ++		if (header->magic == NVRAM_HEADER) ++			goto found; ++		off <<= 1; ++	} ++ ++	ret = -1; ++	goto done; ++ ++found: ++	len = header->len; ++	header = (struct nvram_header *) KSEG1ADDR(NAND_FLASH1 + off); ++	src = (u32 *) header; ++	dst = (u32 *) nvram_buf; ++	for (i = 0; i < sizeof(struct nvram_header); i += 4) ++		*dst++ = *src++; ++	for (; i < len && i < NVRAM_SPACE; i += 4) ++		*dst++ = *src++; ++	ret = 0; ++done: ++	return ret; ++} ++ + static void early_nvram_init(void) + { + 	int err = 0; +@@ -163,6 +210,10 @@ static void early_nvram_init(void) + 			err = early_nvram_init_sflash(); + 			if (err < 0) + 				printk(KERN_WARNING "can not read from flash: %i\n", err); ++		} else if (bcm47xx_bus.bcma.bus.drv_cc.flash_type == BCMA_NFLASH) { ++			err = early_nvram_init_nflash(); ++			if (err < 0) ++				printk(KERN_WARNING "can not read from nflash: %i\n", err); + 		} else { + 			printk(KERN_WARNING "unknow flash type\n"); + 		} +--- a/arch/mips/bcm47xx/setup.c ++++ b/arch/mips/bcm47xx/setup.c +@@ -4,6 +4,7 @@ +  *  Copyright (C) 2006 Michael Buesch <m@bues.ch> +  *  Copyright (C) 2010 Waldemar Brodkorb <wbx@openadk.org> +  *  Copyright (C) 2010-2011 Hauke Mehrtens <hauke@hauke-m.de> ++ *  Copyright (C) 2011-2012 Tathagata Das <tathagata@alumnux.com> +  * +  *  This program is free software; you can redistribute  it and/or modify it +  *  under  the terms of  the GNU General  Public License as published by the +@@ -46,6 +47,7 @@ enum bcm47xx_bus_type bcm47xx_bus_type; + EXPORT_SYMBOL(bcm47xx_bus_type); +  + struct bcm47xx_sflash bcm47xx_sflash; ++struct bcm47xx_nflash bcm47xx_nflash; +  + static void bcm47xx_machine_restart(char *command) + { +@@ -325,6 +327,9 @@ static void __init bcm47xx_register_bcma +  + 	if (bcm47xx_bus.bcma.bus.drv_cc.flash_type == BCMA_SFLASH) + 		bcm47xx_sflash_struct_bcma_init(&bcm47xx_sflash, &bcm47xx_bus.bcma.bus.drv_cc); ++	 ++	if (bcm47xx_bus.bcma.bus.drv_cc.flash_type == BCMA_NFLASH) ++		bcm47xx_nflash_struct_bcma_init(&bcm47xx_nflash, &bcm47xx_bus.bcma.bus.drv_cc); + } + #endif +  +@@ -395,6 +400,19 @@ static struct platform_device bcm47xx_sf + 	.num_resources	= 1, + }; +  ++static struct resource bcm47xx_nflash_resource = { ++	.name	= "bcm47xx_nflash", ++	.start	= 0, ++	.end	= 0, ++	.flags  = 0, ++}; ++ ++static struct platform_device bcm47xx_nflash_dev = { ++	.name		= "bcm47xx_nflash", ++	.resource	= &bcm47xx_nflash_resource, ++	.num_resources	= 1, ++}; ++ + static int __init bcm47xx_register_flash(void) + { + #ifdef CONFIG_BCM47XX_SSB +@@ -429,6 +447,9 @@ static int __init bcm47xx_register_flash + 		} else if (drv_cc->flash_type == BCMA_SFLASH) { + 			bcm47xx_sflash_dev.dev.platform_data = &bcm47xx_sflash; + 			return platform_device_register(&bcm47xx_sflash_dev); ++		} else if (drv_cc->flash_type == BCMA_NFLASH) { ++			bcm47xx_nflash_dev.dev.platform_data = &bcm47xx_nflash; ++			return platform_device_register(&bcm47xx_nflash_dev); + 		} else { + 			printk(KERN_ERR "No flash device found\n"); + 			return -1; +--- a/arch/mips/include/asm/mach-bcm47xx/bus.h ++++ b/arch/mips/include/asm/mach-bcm47xx/bus.h +@@ -2,6 +2,7 @@ +  * BCM947xx nvram variable access +  * +  * Copyright (C) 2011 Hauke Mehrtens <hauke@hauke-m.de> ++ * Copyright (C) 2011-2012 Tathagata Das <tathagata@alumnux.com> +  * +  * This program is free software; you can redistribute  it and/or modify it +  * under  the terms of  the GNU General  Public License as published by the +@@ -13,6 +14,7 @@ + #include <linux/bcma/bcma.h> + #include <linux/mtd/mtd.h> + #include <bcm47xx.h> ++#include <linux/mtd/nand.h> +  + struct bcm47xx_sflash { + 	enum bcm47xx_bus_type sflash_type; +@@ -38,3 +40,18 @@ void bcm47xx_sflash_struct_bcma_init(str + void bcm47xx_sflash_struct_ssb_init(struct bcm47xx_sflash *sflash, struct ssb_chipcommon *scc); +  + extern struct bcm47xx_sflash bcm47xx_sflash; ++ ++struct bcm47xx_nflash { ++	enum bcm47xx_bus_type nflash_type; ++	struct bcma_drv_cc *bcc; ++ ++	u32 size;		/* Total size in bytes */ ++	u32 next_opcode; /* Next expected command from upper NAND layer */ ++ ++	struct mtd_info mtd; ++	struct nand_chip nand; ++}; ++ ++void bcm47xx_nflash_struct_bcma_init(struct bcm47xx_nflash *nflash, struct bcma_drv_cc *bcc); ++ ++extern struct bcm47xx_nflash bcm47xx_nflash; +--- a/drivers/bcma/bcma_private.h ++++ b/drivers/bcma/bcma_private.h +@@ -46,6 +46,11 @@ u32 bcma_pmu_get_clockcpu(struct bcma_dr + int bcma_sflash_init(struct bcma_drv_cc *cc); + #endif /* CONFIG_BCMA_SFLASH */ +  ++#ifdef CONFIG_BCMA_NFLASH ++/* driver_chipcommon_nflash.c */ ++int bcma_nflash_init(struct bcma_drv_cc *cc); ++#endif /* CONFIG_BCMA_NFLASH */ ++ + #ifdef CONFIG_BCMA_HOST_PCI + /* host_pci.c */ + extern int __init bcma_host_pci_init(void); +--- /dev/null ++++ b/drivers/bcma/driver_chipcommon_nflash.c +@@ -0,0 +1,154 @@ ++/* ++ * BCMA nand flash interface ++ * ++ * Copyright 2011, Tathagata Das <tathagata@alumnux.com> ++ * Copyright 2010, Broadcom Corporation ++ * ++ * Licensed under the GNU/GPL. See COPYING for details. ++ */ ++ ++#include <linux/bcma/bcma.h> ++#include <linux/bcma/bcma_driver_chipcommon.h> ++#include <linux/delay.h> ++#include <linux/mtd/bcm47xx_nand.h> ++#include <linux/mtd/nand.h> ++ ++#include "bcma_private.h" ++ ++/* Issue a nand flash command */ ++static inline void bcma_nflash_cmd(struct bcma_drv_cc *cc, u32 opcode) ++{ ++	bcma_cc_write32(cc, NAND_CMD_START, opcode); ++	bcma_cc_read32(cc,  NAND_CMD_START); ++} ++ ++/* Check offset and length */ ++static int bcma_nflash_offset_is_valid(struct bcma_drv_cc *cc, u32 offset, u32 len, u32 mask) ++{ ++	if ((offset & mask) != 0 || (len & mask) != 0) { ++		pr_err("%s(): Address is not aligned. offset: %x, len: %x, mask: %x\n", __func__, offset, len, mask); ++		return 1; ++	} ++ ++	if ((((offset + len) >> 20) >= cc->nflash.size) && ++		(((offset + len) & ((1 << 20) - 1)) != 0)) { ++		pr_err("%s(): Address is outside Flash memory region. offset: %x, len: %x, mask: %x\n", __func__, offset, len, mask); ++		return 1; ++	} ++ ++	return 0; ++} ++ ++/* Read len bytes starting at offset into buf. Returns number of bytes read. */ ++int bcma_nflash_read(struct bcma_drv_cc *cc, u32 offset, u32 len, u8 *buf) ++{ ++	u32 mask; ++	int i; ++	u32 *to, val, res; ++ ++	mask = NFL_SECTOR_SIZE - 1; ++	if (bcma_nflash_offset_is_valid(cc, offset, len, mask)) ++		return 0; ++ ++	to = (u32 *)buf; ++	res = len; ++	while (res > 0) { ++		bcma_cc_write32(cc, NAND_CMD_ADDR, offset); ++		bcma_nflash_cmd(cc, NCMD_PAGE_RD); ++		if (bcma_nflash_poll(cc) < 0) ++			break; ++		val = bcma_cc_read32(cc, NAND_INTFC_STATUS); ++		if ((val & NIST_CACHE_VALID) == 0) ++			break; ++		bcma_cc_write32(cc, NAND_CACHE_ADDR, 0); ++		for (i = 0; i < NFL_SECTOR_SIZE; i += 4, to++) { ++			*to = bcma_cc_read32(cc, NAND_CACHE_DATA); ++		} ++		res -= NFL_SECTOR_SIZE; ++		offset += NFL_SECTOR_SIZE; ++	} ++	return (len - res); ++} ++ ++#define NF_RETRIES   1000000 ++ ++/* Poll for command completion. Returns zero when complete. */ ++int bcma_nflash_poll(struct bcma_drv_cc *cc) ++{ ++	u32 retries = NF_RETRIES; ++	u32 pollmask = NIST_CTRL_READY|NIST_FLASH_READY; ++	u32 mask; ++ ++	while (retries--) { ++		mask = bcma_cc_read32(cc, NAND_INTFC_STATUS) & pollmask; ++		if (mask == pollmask) ++			return 0; ++		cpu_relax(); ++	} ++ ++	if (!retries) { ++		pr_err("bcma_nflash_poll: not ready\n"); ++		return -1; ++	} ++ ++	return 0; ++} ++ ++/* Write len bytes starting at offset into buf. Returns success (0) or failure (!0). ++ * Should poll for completion. ++ */ ++int bcma_nflash_write(struct bcma_drv_cc *cc, u32 offset, u32 len, ++			    const u8 *buf) ++{ ++	u32 mask; ++	int i; ++	u32 *from, res, reg; ++ ++	mask = cc->nflash.pagesize - 1; ++	if (bcma_nflash_offset_is_valid(cc, offset, len, mask)) ++		return 1; ++	 ++	/* disable partial page enable */ ++	reg = bcma_cc_read32(cc, NAND_ACC_CONTROL); ++	reg &= ~NAC_PARTIAL_PAGE_EN; ++	bcma_cc_write32(cc, NAND_ACC_CONTROL, reg); ++ ++	from = (u32 *)buf; ++	res = len; ++	while (res > 0) { ++		bcma_cc_write32(cc, NAND_CACHE_ADDR, 0); ++		for (i = 0; i < cc->nflash.pagesize; i += 4, from++) { ++			if (i % 512 == 0) ++				bcma_cc_write32(cc, NAND_CMD_ADDR, i); ++			bcma_cc_write32(cc, NAND_CACHE_DATA, *from); ++		} ++		bcma_cc_write32(cc, NAND_CMD_ADDR, offset + cc->nflash.pagesize - 512); ++		bcma_nflash_cmd(cc, NCMD_PAGE_PROG); ++		if (bcma_nflash_poll(cc) < 0) ++			break; ++		res -= cc->nflash.pagesize; ++		offset += cc->nflash.pagesize; ++	} ++ ++	if (res <= 0) ++		return 0; ++	else ++		return (len - res); ++} ++ ++/* Erase a region. Returns success (0) or failure (-1).  ++ * Poll for completion. ++ */ ++int bcma_nflash_erase(struct bcma_drv_cc *cc, u32 offset) ++{ ++	if ((offset >> 20) >= cc->nflash.size) ++		return -1; ++	if ((offset & (cc->nflash.blocksize - 1)) != 0) ++		return -1; ++ ++	bcma_cc_write32(cc, NAND_CMD_ADDR, offset); ++	bcma_nflash_cmd(cc, NCMD_BLOCK_ERASE); ++	if (bcma_nflash_poll(cc) < 0) ++		return -1; ++	return 0; ++} +--- a/drivers/bcma/driver_mips.c ++++ b/drivers/bcma/driver_mips.c +@@ -6,6 +6,7 @@ +  * Copyright 2006, 2007, Michael Buesch <mb@bu3sch.de> +  * Copyright 2010, Bernhard Loos <bernhardloos@googlemail.com> +  * Copyright 2011, Hauke Mehrtens <hauke@hauke-m.de> ++ * Copyright (C) 2011-2012 Tathagata Das <tathagata@alumnux.com> +  * +  * Licensed under the GNU/GPL. See COPYING for details. +  */ +@@ -182,6 +183,17 @@ static void bcma_core_mips_flash_detect( + { + 	struct bcma_bus *bus = mcore->core->bus; +  ++	if (bus->drv_cc.core->id.rev == 38  ++		&& (bus->drv_cc.status & (1 << 4)) != 0) { ++#ifdef CONFIG_BCMA_NFLASH ++		pr_info("found nand flash.\n"); ++		bus->drv_cc.flash_type = BCMA_NFLASH; ++#else ++		pr_info("NAND flash not supported.\n"); ++#endif ++		return; ++	} ++ + 	switch (bus->drv_cc.capabilities & BCMA_CC_CAP_FLASHT) { + 	case BCMA_CC_FLASHT_STSER: + 	case BCMA_CC_FLASHT_ATSER: +--- a/drivers/bcma/Kconfig ++++ b/drivers/bcma/Kconfig +@@ -43,6 +43,11 @@ config BCMA_SFLASH + 	depends on BCMA_DRIVER_MIPS + 	default y +  ++config BCMA_NFLASH ++	bool ++	depends on BCMA_DRIVER_MIPS ++	default y ++ + config BCMA_DRIVER_MIPS + 	bool "BCMA Broadcom MIPS core driver" + 	depends on BCMA && MIPS +--- a/drivers/bcma/Makefile ++++ b/drivers/bcma/Makefile +@@ -1,6 +1,7 @@ + bcma-y					+= main.o scan.o core.o sprom.o + bcma-y					+= driver_chipcommon.o driver_chipcommon_pmu.o + bcma-$(CONFIG_BCMA_SFLASH)		+= driver_chipcommon_sflash.o ++bcma-$(CONFIG_BCMA_NFLASH)		+= driver_chipcommon_nflash.o + bcma-y					+= driver_pci.o + bcma-$(CONFIG_BCMA_DRIVER_PCI_HOSTMODE)	+= driver_pci_host.o + bcma-$(CONFIG_BCMA_DRIVER_MIPS)		+= driver_mips.o +--- /dev/null ++++ b/drivers/mtd/nand/bcm47xx_nand.c +@@ -0,0 +1,506 @@ ++/* ++ * BCMA nand flash interface ++ * ++ * Copyright (C) 2011-2012 Tathagata Das <tathagata@alumnux.com> ++ * Copyright 2010, Broadcom Corporation ++ * ++ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY ++ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM ++ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS ++ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. ++ * ++ */ ++ ++#define pr_fmt(fmt) "bcm47xx_nflash: " fmt ++#include <linux/module.h> ++#include <linux/slab.h> ++#include <linux/ioport.h> ++#include <linux/sched.h> ++#include <linux/mtd/mtd.h> ++#include <linux/mtd/map.h> ++#include <linux/mtd/partitions.h> ++#include <linux/errno.h> ++#include <linux/delay.h> ++#include <linux/platform_device.h> ++#include <bcm47xx.h> ++#include <bus.h> ++#include <linux/cramfs_fs.h> ++#include <linux/romfs_fs.h> ++#include <linux/magic.h> ++#include <linux/byteorder/generic.h> ++#include <linux/mtd/bcm47xx_nand.h> ++#include <linux/mtd/nand.h> ++ ++static int bcm47xx_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip); ++static int bcm47xx_erase(struct mtd_info *mtd, unsigned int addr, unsigned int len); ++ ++/* Private Global variable */ ++static u32 read_offset = 0; ++static u32 write_offset; ++ ++static int ++nflash_mtd_poll(struct bcm47xx_nflash *nflash, unsigned int offset, int timeout) ++{ ++	unsigned long now = jiffies; ++	int ret = 0; ++ ++	for (;;) { ++		if (!bcma_nflash_poll(nflash->bcc)) { ++			ret = 0; ++			break; ++		} ++		if (time_after(jiffies, now + timeout)) { ++			pr_err("timeout while polling\n"); ++			ret = -ETIMEDOUT; ++			break; ++		} ++		udelay(1); ++	} ++ ++	return ret; ++} ++ ++static int ++bcm47xx_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) ++{ ++	struct nand_chip *nchip = (struct nand_chip *)mtd->priv; ++	struct bcm47xx_nflash *nflash = (struct bcm47xx_nflash *)nchip->priv; ++	int bytes, ret = 0; ++	u32 extra = 0; ++	u8 *tmpbuf = NULL; ++	int size; ++	u32 offset, blocksize, mask, off; ++	u32 skip_bytes = 0; ++	int need_copy = 0; ++	u8 *ptr = NULL; ++ ++	/* Check address range */ ++	if (!len) ++		return 0; ++	if ((from + len) > mtd->size) ++		return -EINVAL; ++	offset = from; ++	if ((offset & (NFL_SECTOR_SIZE - 1)) != 0) { ++		extra = offset & (NFL_SECTOR_SIZE - 1); ++		offset -= extra; ++		len += extra; ++		need_copy = 1; ++	} ++	size = (len + (NFL_SECTOR_SIZE - 1)) & ~(NFL_SECTOR_SIZE - 1); ++	if (size != len) { ++		need_copy = 1; ++	} ++	if (!need_copy) { ++		ptr = buf; ++	} else { ++		tmpbuf = (u8 *)kmalloc(size, GFP_KERNEL); ++		ptr = tmpbuf; ++	} ++ ++	blocksize = mtd->erasesize; ++	mask = blocksize - 1; ++	*retlen = 0; ++	while (len > 0) { ++		off = offset + skip_bytes; ++		if ((bytes = bcma_nflash_read(nflash->bcc, off, NFL_SECTOR_SIZE, ptr)) < 0) { ++			ret = bytes; ++			goto done; ++		} ++		if (bytes > len) ++			bytes = len; ++		offset += bytes; ++		len -= bytes; ++		ptr += bytes; ++		*retlen += bytes; ++	} ++ ++done: ++	if (tmpbuf) { ++		*retlen -= extra; ++		memcpy(buf, tmpbuf+extra, *retlen); ++		kfree(tmpbuf); ++	} ++ ++	return ret; ++} ++ ++static void bcm47xx_write(struct mtd_info *mtd, u32 to, const u_char *buf, u32 len) ++{ ++	struct nand_chip *nchip = (struct nand_chip *)mtd->priv; ++	struct bcm47xx_nflash *nflash = (struct bcm47xx_nflash *)nchip->priv; ++	u32 offset, blocksize, mask, off; ++	int read_len; ++	u32 copy_len, write_len, from; ++	u_char *write_ptr, *block; ++	const u_char *ptr; ++	int ret, bytes; ++ ++	/* Check address range */ ++	if (!len) { ++		pr_err("Error: Attempted to write too small data\n"); ++		return; ++	} ++ ++	if (!to) ++		return; ++ ++	if ((to + len) > mtd->size) { ++		pr_err("Error: Attempted to write too large data\n"); ++		return; ++	} ++ ++	ptr = buf; ++	block = NULL; ++	offset = to; ++	blocksize = mtd->erasesize; ++	if (!(block = kmalloc(blocksize, GFP_KERNEL))) ++		return; ++	mask = blocksize - 1; ++	while (len) { ++		/* Align offset */ ++		from = offset & ~mask; ++		/* Copy existing data into holding block if necessary */ ++		if (((offset & (blocksize-1)) != 0) || (len < blocksize)) { ++			if ((ret = bcm47xx_read(mtd, from, blocksize, &read_len, block))) ++				goto done; ++			if (read_len != blocksize) { ++				ret = -EINVAL; ++				goto done; ++			} ++		} ++	 ++		/* Copy input data into holding block */ ++		copy_len = min(len, blocksize - (offset & mask)); ++		memcpy(block + (offset & mask), ptr, copy_len); ++		off = (uint) from; ++		/* Erase block */ ++		if ((ret = bcm47xx_erase(mtd, off, blocksize)) < 0) ++			goto done; ++		/* Write holding block */ ++		write_ptr = block; ++		write_len = blocksize; ++		if ((bytes = bcma_nflash_write(nflash->bcc, (uint)from, (uint)write_len, (u8 *) write_ptr)) != 0) { ++			ret = bytes; ++			goto done; ++		} ++		offset += copy_len; ++		if (len < copy_len) ++			len = 0; ++		else ++			len -= copy_len; ++		ptr += copy_len; ++	} ++ ++done: ++	if (block) ++		kfree(block); ++	return; ++} ++ ++static int bcm47xx_erase(struct mtd_info *mtd, unsigned int addr, unsigned int len) ++{ ++	struct nand_chip *nchip = (struct nand_chip *)mtd->priv; ++	struct bcm47xx_nflash *nflash = (struct bcm47xx_nflash *)nchip->priv; ++ ++	/* Check address range */ ++	if (!len) ++		return 1; ++	if ((addr + len) > mtd->size) ++		return 1; ++ ++	if (bcma_nflash_erase(nflash->bcc, addr)) { ++		pr_err("ERASE: nflash erase error\n"); ++		return 1; ++	} ++ ++	if (nflash_mtd_poll(nflash, addr, 10 * HZ)) { ++		pr_err("ERASE: nflash_mtd_poll error\n"); ++		return 1; ++	} ++	 ++	return 0; ++} ++ ++/* This functions is used by upper layer to checks if device is ready */ ++static int bcm47xx_dev_ready(struct mtd_info *mtd) ++{ ++	return 1; ++} ++ ++/* Issue a nand flash command */ ++static inline void bcm47xx_nflash_cmd(struct bcma_drv_cc *cc, u32 opcode) ++{ ++	bcma_cc_write32(cc, NAND_CMD_START, opcode); ++	bcma_cc_read32(cc,  NAND_CMD_START); ++} ++ ++static void bcm47xx_command(struct mtd_info *mtd, unsigned command, ++				int column, int page_addr) ++{ ++	struct nand_chip *nchip = (struct nand_chip *)mtd->priv; ++	struct bcm47xx_nflash *nflash = (struct bcm47xx_nflash *)nchip->priv; ++	u32 pagesize = 1 << nchip->page_shift; ++ ++	/* Command pre-processing step */ ++	switch (command) { ++	case NAND_CMD_RESET: ++		bcm47xx_nflash_cmd(nflash->bcc, NCMD_FLASH_RESET); ++		break; ++ ++	case NAND_CMD_STATUS: ++		nflash->next_opcode = NAND_CMD_STATUS; ++		read_offset = 0; ++		write_offset = 0; ++		break; ++ ++	case NAND_CMD_READ0: ++		read_offset = page_addr * pagesize; ++		nflash->next_opcode = 0; ++		break; ++ ++	case NAND_CMD_READOOB: ++		read_offset = page_addr * pagesize; ++		nflash->next_opcode = 0; ++		break; ++ ++	case NAND_CMD_SEQIN: ++		write_offset = page_addr * pagesize; ++		nflash->next_opcode = 0; ++		break; ++ ++	case NAND_CMD_PAGEPROG: ++		nflash->next_opcode = 0; ++		break; ++ ++	case NAND_CMD_READID: ++		read_offset = column; ++		bcm47xx_nflash_cmd(nflash->bcc, NCMD_ID_RD); ++		nflash->next_opcode = NAND_DEVID; ++		break; ++ ++	case NAND_CMD_ERASE1: ++		nflash->next_opcode = 0; ++		bcm47xx_erase(mtd, page_addr*pagesize, pagesize); ++		break; ++	 ++	case NAND_CMD_ERASE2: ++		break; ++ ++	case NAND_CMD_RNDOUT: ++		if (column > mtd->writesize) ++			read_offset += (column - mtd->writesize); ++		else  ++			read_offset += column; ++		break; ++ ++	default: ++		pr_err("COMMAND not supported %x\n", command); ++		nflash->next_opcode = 0; ++		break; ++	} ++} ++ ++/* This function is used by upper layer for select and ++ * deselect of the NAND chip. ++ * It is dummy function. */ ++static void bcm47xx_select_chip(struct mtd_info *mtd, int chip) ++{ ++} ++ ++static u_char bcm47xx_read_byte(struct mtd_info *mtd) ++{ ++	struct nand_chip *nchip = mtd->priv; ++	struct bcm47xx_nflash *nflash = (struct bcm47xx_nflash *)nchip->priv; ++	uint8_t ret = 0; ++	static u32 id; ++ ++	if (nflash->next_opcode == 0) ++		return ret; ++ ++	if (nflash->next_opcode == NAND_CMD_STATUS) ++		return NAND_STATUS_WP;  ++ ++	id = bcma_cc_read32(nflash->bcc, nflash->next_opcode); ++ ++	if (nflash->next_opcode == NAND_DEVID) { ++		ret = (id >> (8*read_offset)) & 0xff; ++		read_offset++; ++	} ++ ++	return ret; ++} ++ ++static uint16_t bcm47xx_read_word(struct mtd_info *mtd) ++{ ++	loff_t from = read_offset; ++	uint16_t buf = 0; ++	int bytes; ++ ++	bcm47xx_read(mtd, from, sizeof(buf), &bytes, (u_char *)&buf); ++	return buf; ++} ++ ++/* Write data of length len to buffer buf. The data to be ++ * written on NAND Flash is first copied to RAMbuffer. After the Data Input ++ * Operation by the NFC, the data is written to NAND Flash */ ++static void bcm47xx_write_buf(struct mtd_info *mtd, ++				const u_char *buf, int len) ++{ ++	bcm47xx_write(mtd, write_offset, buf, len); ++} ++ ++/* Read the data buffer from the NAND Flash. To read the data from NAND ++ * Flash first the data output cycle is initiated by the NFC, which copies ++ * the data to RAMbuffer. This data of length len is then copied to buffer buf. ++ */ ++static void bcm47xx_read_buf(struct mtd_info *mtd, u_char *buf, int len) ++{ ++	loff_t from = read_offset; ++	int bytes; ++ ++	bcm47xx_read(mtd, from, len, &bytes, buf); ++} ++ ++/* Used by the upper layer to verify the data in NAND Flash ++ * with the data in the buf. */ ++static int bcm47xx_verify_buf(struct mtd_info *mtd, ++				const u_char *buf, int len) ++{ ++	return -EFAULT; ++} ++ ++static int bcm47xx_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip) ++{ ++	struct nand_chip *nchip = mtd->priv; ++	struct bcm47xx_nflash *nflash = (struct bcm47xx_nflash *)nchip->priv; ++	int i; ++	uint off; ++	u32 pagesize = 1 << nchip->page_shift; ++	u32 blocksize = mtd->erasesize; ++ ++	if ((ofs >> 20) >= nflash->size) ++		return 1; ++	if ((ofs & (blocksize - 1)) != 0) ++		return 1; ++ ++	for (i = 0; i < 2; i++) { ++		off = ofs + pagesize; ++		bcma_cc_write32(nflash->bcc, NAND_CMD_ADDR, off); ++		bcm47xx_nflash_cmd(nflash->bcc, NCMD_SPARE_RD); ++		if (bcma_nflash_poll(nflash->bcc) < 0) ++			break; ++		if ((bcma_cc_read32(nflash->bcc, NAND_INTFC_STATUS) & NIST_SPARE_VALID) != NIST_SPARE_VALID) ++			return 1; ++		if ((bcma_cc_read32(nflash->bcc, NAND_SPARE_RD0) & 0xff) != 0xff) ++			return 1; ++	} ++	return 0; ++} ++ ++const char *part_probes[] = { "cmdlinepart", NULL }; ++static int bcm47xx_probe(struct platform_device *pdev) ++{ ++	struct nand_chip *nchip; ++	struct mtd_info *mtd; ++	struct bcm47xx_nflash *nflash = dev_get_platdata(&pdev->dev); ++	int ret = 0; ++ ++	mtd = &nflash->mtd; ++	nchip = &nflash->nand; ++ ++	/* Register with MTD */ ++	mtd->priv = nchip; ++	mtd->owner = THIS_MODULE; ++	mtd->dev.parent = &pdev->dev; ++ ++	/* 50 us command delay time */ ++	nchip->chip_delay = 50; ++ ++	nchip->priv = nflash; ++	nchip->dev_ready = bcm47xx_dev_ready; ++	nchip->cmdfunc = bcm47xx_command; ++	nchip->select_chip = bcm47xx_select_chip; ++	nchip->read_byte = bcm47xx_read_byte; ++	nchip->read_word = bcm47xx_read_word; ++	nchip->write_buf = bcm47xx_write_buf; ++	nchip->read_buf = bcm47xx_read_buf; ++	nchip->verify_buf = bcm47xx_verify_buf; ++	nchip->block_bad = bcm47xx_block_bad; ++	nchip->options = NAND_SKIP_BBTSCAN; ++ ++	/* Not known */ ++	nchip->ecc.mode = NAND_ECC_NONE; ++ ++	/* first scan to find the device and get the page size */ ++	if (nand_scan_ident(mtd, 1, NULL)) { ++		pr_err("nand_scan_ident failed\n"); ++		ret = -ENXIO; ++		goto done; ++	} ++	nflash->bcc->nflash.size = mtd->size; ++	nflash->bcc->nflash.pagesize = 1 << nchip->page_shift; ++	nflash->bcc->nflash.blocksize = mtd->erasesize; ++	bcm47xx_nflash.size = mtd->size; ++ ++	/* second phase scan */ ++	if (nand_scan_tail(mtd)) { ++		pr_err("nand_scan_tail failed\n"); ++		ret = -ENXIO; ++		goto done; ++	} ++ ++	mtd->name = "bcm47xx-nflash"; ++	mtd->flags |= MTD_WRITEABLE; ++	ret = mtd_device_parse_register(mtd, part_probes, NULL, NULL, 0); ++ ++	if (ret) { ++		pr_err("mtd_device_register failed\n"); ++		return ret; ++	} ++	 ++	return 0; ++ ++done: ++	return ret; ++} ++ ++static int __devexit bcm47xx_remove(struct platform_device *pdev) ++{ ++	struct bcm47xx_nflash *nflash = dev_get_platdata(&pdev->dev); ++	struct mtd_info *mtd = &nflash->mtd; ++ ++	if (nflash) { ++		/* Release resources, unregister device */ ++		nand_release(mtd); ++	} ++ ++	return 0; ++} ++ ++static struct platform_driver bcm47xx_driver = { ++	.remove = __devexit_p(bcm47xx_remove), ++	.driver = { ++		.name = "bcm47xx_nflash", ++		.owner = THIS_MODULE, ++	}, ++}; ++ ++static int __init init_bcm47xx_nflash(void) ++{ ++	int ret = platform_driver_probe(&bcm47xx_driver, bcm47xx_probe); ++ ++	if (ret) ++		pr_err("error registering platform driver: %i\n", ret); ++	return ret; ++} ++ ++static void __exit exit_bcm47xx_nflash(void) ++{ ++	platform_driver_unregister(&bcm47xx_driver); ++} ++ ++module_init(init_bcm47xx_nflash); ++module_exit(exit_bcm47xx_nflash); ++ ++MODULE_LICENSE("GPL"); ++MODULE_DESCRIPTION("BCM47XX NAND flash driver"); +--- a/drivers/mtd/nand/Kconfig ++++ b/drivers/mtd/nand/Kconfig +@@ -537,4 +537,12 @@ config MTD_NAND_FSMC + 	  Enables support for NAND Flash chips on the ST Microelectronics + 	  Flexible Static Memory Controller (FSMC) +  ++config MTD_NAND_BCM47XX ++	tristate "bcm47xx nand flash support" ++	default y ++	depends on BCM47XX ++	select MTD_PARTITIONS ++	help ++	  Support for bcm47xx nand flash ++ + endif # MTD_NAND +--- a/drivers/mtd/nand/Makefile ++++ b/drivers/mtd/nand/Makefile +@@ -49,5 +49,6 @@ obj-$(CONFIG_MTD_NAND_MPC5121_NFC)	+= mp + obj-$(CONFIG_MTD_NAND_RICOH)		+= r852.o + obj-$(CONFIG_MTD_NAND_JZ4740)		+= jz4740_nand.o + obj-$(CONFIG_MTD_NAND_GPMI_NAND)	+= gpmi-nand/ ++obj-$(CONFIG_MTD_NAND_BCM47XX)		+= bcm47xx_nand.o +  + nand-objs := nand_base.o nand_bbt.o +--- a/include/linux/bcma/bcma_driver_chipcommon.h ++++ b/include/linux/bcma/bcma_driver_chipcommon.h +@@ -376,6 +376,7 @@ struct bcma_chipcommon_pmu { + enum bcma_flash_type { + 	BCMA_PFLASH, + 	BCMA_SFLASH, ++	BCMA_NFLASH, + }; +  + struct bcma_pflash { +@@ -392,6 +393,14 @@ struct bcma_sflash { + }; + #endif /* CONFIG_BCMA_SFLASH */ +  ++#ifdef CONFIG_BCMA_NFLASH ++struct bcma_nflash { ++	u32 blocksize;		/* Block size */ ++	u32 pagesize;		/* Page size */ ++	u32 size;		/* Total size in bytes */ ++}; ++#endif ++ + struct bcma_serial_port { + 	void *regs; + 	unsigned long clockspeed; +@@ -417,6 +426,9 @@ struct bcma_drv_cc { + #ifdef CONFIG_BCMA_SFLASH + 		struct bcma_sflash sflash; + #endif /* CONFIG_BCMA_SFLASH */ ++#ifdef CONFIG_BCMA_NFLASH ++		struct bcma_nflash nflash; ++#endif + 	}; +  + 	int nr_serial_ports; +@@ -483,4 +495,13 @@ int bcma_sflash_commit(struct bcma_drv_c + 			     const u8 *buf); + #endif /* CONFIG_BCMA_SFLASH */ +  ++#ifdef CONFIG_BCMA_NFLASH ++/* Chipcommon nflash support. */ ++int bcma_nflash_read(struct bcma_drv_cc *cc, u32 offset, u32 len, u8 *buf); ++int bcma_nflash_poll(struct bcma_drv_cc *cc); ++int bcma_nflash_write(struct bcma_drv_cc *cc, u32 offset, u32 len, const u8 *buf); ++int bcma_nflash_erase(struct bcma_drv_cc *cc, u32 offset); ++int bcma_nflash_commit(struct bcma_drv_cc *cc, u32 offset, u32 len, const u8 *buf); ++#endif ++ + #endif /* LINUX_BCMA_DRIVER_CC_H_ */ +--- /dev/null ++++ b/include/linux/mtd/bcm47xx_nand.h +@@ -0,0 +1,134 @@ ++/* ++ * Broadcom chipcommon NAND flash interface ++ * ++ * Copyright (C) 2011-2012 Tathagata Das <tathagata@alumnux.com> ++ * Copyright (C) 2009, Broadcom Corporation ++ * All Rights Reserved. ++ *  ++ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY ++ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM ++ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS ++ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. ++ * ++ */ ++ ++#ifndef _nflash_h_ ++#define _nflash_h_ ++ ++#define  NAND_FLASH1						0x1fc00000  /* MIPS Flash Region 1 */ ++ ++/* nand_cmd_start commands */ ++#define	NCMD_NULL						0 ++#define	NCMD_PAGE_RD					1 ++#define	NCMD_SPARE_RD					2 ++#define	NCMD_STATUS_RD					3 ++#define	NCMD_PAGE_PROG					4 ++#define	NCMD_SPARE_PROG				5 ++#define	NCMD_COPY_BACK					6 ++#define	NCMD_ID_RD						7 ++#define	NCMD_BLOCK_ERASE				8 ++#define	NCMD_FLASH_RESET				9 ++#define	NCMD_LOCK						0xa ++#define	NCMD_LOCK_DOWN					0xb ++#define	NCMD_UNLOCK						0xc ++#define	NCMD_LOCK_STATUS				0xd ++ ++/* nand_acc_control */ ++#define	NAC_RD_ECC_EN					0x80000000 ++#define	NAC_WR_ECC_EN					0x40000000 ++#define	NAC_RD_ECC_BLK0_EN			0x20000000 ++#define	NAC_FAST_PGM_RDIN				0x10000000 ++#define	NAC_RD_ERASED_ECC_EN			0x08000000 ++#define	NAC_PARTIAL_PAGE_EN			0x04000000 ++#define	NAC_PAGE_HIT_EN				0x01000000 ++#define	NAC_ECC_LEVEL0					0x00f00000 ++#define	NAC_ECC_LEVEL					0x000f0000 ++#define	NAC_SPARE_SIZE0				0x00003f00 ++#define	NAC_SPARE_SIZE					0x0000003f ++ ++/* nand_config */ ++#define	NCF_CONFIG_LOCK				0x80000000 ++#define	NCF_BLOCK_SIZE_MASK			0x70000000 ++#define	NCF_BLOCK_SIZE_SHIFT			28 ++#define	NCF_DEVICE_SIZE_MASK			0x0f000000 ++#define	NCF_DEVICE_SIZE_SHIFT		24 ++#define	NCF_DEVICE_WIDTH				0x00800000 ++#define	NCF_PAGE_SIZE_MASK			0x00300000 ++#define	NCF_PAGE_SIZE_SHIFT			20 ++#define	NCF_FULL_ADDR_BYTES_MASK	0x00070000 ++#define	NCF_FULL_ADDR_BYTES_SHIFT	16 ++#define	NCF_COL_ADDR_BYTES_MASK		0x00007000 ++#define	NCF_COL_ADDR_BYTES_SHIFT	12 ++#define	NCF_BLK_ADDR_BYTES_MASK		0x00000700 ++#define	NCF_BLK_ADDR_BYTES_SHIFT	8 ++ ++/* nand_intfc_status */ ++#define	NIST_CTRL_READY				0x80000000 ++#define	NIST_FLASH_READY				0x40000000 ++#define	NIST_CACHE_VALID				0x20000000 ++#define	NIST_SPARE_VALID				0x10000000 ++#define	NIST_ERASED						0x08000000 ++#define	NIST_STATUS						0x000000ff ++ ++#define	NFL_SECTOR_SIZE				512 ++ ++#define	NFL_TABLE_END					0xffffffff ++#define	NFL_BOOT_SIZE					0x200000 ++#define	NFL_BOOT_OS_SIZE				0x2000000 ++ ++/* Nand flash MLC controller registers (corerev >= 38) */ ++#define	NAND_REVISION					0xC00 ++#define	NAND_CMD_START					0xC04 ++#define	NAND_CMD_ADDR_X				0xC08 ++#define	NAND_CMD_ADDR					0xC0C ++#define	NAND_CMD_END_ADDR				0xC10 ++#define	NAND_CS_NAND_SELECT			0xC14 ++#define	NAND_CS_NAND_XOR				0xC18 ++#define	NAND_SPARE_RD0					0xC20 ++#define	NAND_SPARE_RD4					0xC24 ++#define	NAND_SPARE_RD8					0xC28 ++#define	NAND_SPARE_RD12				0xC2C ++#define	NAND_SPARE_WR0					0xC30 ++#define	NAND_SPARE_WR4					0xC34 ++#define	NAND_SPARE_WR8					0xC38 ++#define	NAND_SPARE_WR12				0xC3C ++#define	NAND_ACC_CONTROL				0xC40 ++#define	NAND_CONFIG						0xC48 ++#define	NAND_TIMING_1					0xC50 ++#define	NAND_TIMING_2					0xC54 ++#define	NAND_SEMAPHORE					0xC58 ++#define	NAND_DEVID						0xC60 ++#define	NAND_DEVID_X					0xC64 ++#define	NAND_BLOCK_LOCK_STATUS		0xC68 ++#define	NAND_INTFC_STATUS				0xC6C ++#define	NAND_ECC_CORR_ADDR_X			0xC70 ++#define	NAND_ECC_CORR_ADDR			0xC74 ++#define	NAND_ECC_UNC_ADDR_X			0xC78 ++#define	NAND_ECC_UNC_ADDR				0xC7C ++#define	NAND_READ_ERROR_COUNT		0xC80 ++#define	NAND_CORR_STAT_THRESHOLD	0xC84 ++#define	NAND_READ_ADDR_X				0xC90 ++#define	NAND_READ_ADDR					0xC94 ++#define	NAND_PAGE_PROGRAM_ADDR_X	0xC98 ++#define	NAND_PAGE_PROGRAM_ADDR		0xC9C ++#define	NAND_COPY_BACK_ADDR_X		0xCA0 ++#define	NAND_COPY_BACK_ADDR			0xCA4 ++#define	NAND_BLOCK_ERASE_ADDR_X		0xCA8 ++#define	NAND_BLOCK_ERASE_ADDR		0xCAC ++#define	NAND_INV_READ_ADDR_X			0xCB0 ++#define	NAND_INV_READ_ADDR			0xCB4 ++#define	NAND_BLK_WR_PROTECT			0xCC0 ++#define	NAND_ACC_CONTROL_CS1			0xCD0 ++#define	NAND_CONFIG_CS1				0xCD4 ++#define	NAND_TIMING_1_CS1				0xCD8 ++#define	NAND_TIMING_2_CS1				0xCDC ++#define	NAND_SPARE_RD16				0xD30 ++#define	NAND_SPARE_RD20				0xD34 ++#define	NAND_SPARE_RD24				0xD38 ++#define	NAND_SPARE_RD28				0xD3C ++#define	NAND_CACHE_ADDR				0xD40 ++#define	NAND_CACHE_DATA				0xD44 ++#define	NAND_CTRL_CONFIG				0xD48 ++#define	NAND_CTRL_STATUS				0xD4C ++ ++#endif /* _nflash_h_ */ diff --git a/target/linux/brcm47xx/patches-3.2/042-bcma-export-bcma_pcie_read.patch b/target/linux/brcm47xx/patches-3.2/042-bcma-export-bcma_pcie_read.patch index 70bb497bf..062a29d2f 100644 --- a/target/linux/brcm47xx/patches-3.2/042-bcma-export-bcma_pcie_read.patch +++ b/target/linux/brcm47xx/patches-3.2/042-bcma-export-bcma_pcie_read.patch @@ -13,9 +13,9 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>  --- a/drivers/bcma/bcma_private.h  +++ b/drivers/bcma/bcma_private.h -@@ -46,6 +46,8 @@ u32 bcma_pmu_get_clockcpu(struct bcma_dr - int bcma_sflash_init(struct bcma_drv_cc *cc); - #endif /* CONFIG_BCMA_SFLASH */ +@@ -51,6 +51,8 @@ int bcma_sflash_init(struct bcma_drv_cc + int bcma_nflash_init(struct bcma_drv_cc *cc); + #endif /* CONFIG_BCMA_NFLASH */  +u32 bcma_pcie_read(struct bcma_drv_pci *pc, u32 address);  + diff --git a/target/linux/brcm47xx/patches-3.2/043-bcma-make-some-functions-__devinit.patch b/target/linux/brcm47xx/patches-3.2/043-bcma-make-some-functions-__devinit.patch index 2534a3a6b..340172d44 100644 --- a/target/linux/brcm47xx/patches-3.2/043-bcma-make-some-functions-__devinit.patch +++ b/target/linux/brcm47xx/patches-3.2/043-bcma-make-some-functions-__devinit.patch @@ -28,7 +28,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>   void bcma_bus_unregister(struct bcma_bus *bus);   int __init bcma_bus_early_register(struct bcma_bus *bus,   				   struct bcma_device *core_cc, -@@ -55,7 +55,7 @@ extern void __exit bcma_host_pci_exit(vo +@@ -60,7 +60,7 @@ extern void __exit bcma_host_pci_exit(vo   #endif /* CONFIG_BCMA_HOST_PCI */   #ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE diff --git a/target/linux/brcm47xx/patches-3.2/044-bcma-add-PCIe-host-controller.patch b/target/linux/brcm47xx/patches-3.2/044-bcma-add-PCIe-host-controller.patch index 2afd09aee..850b52428 100644 --- a/target/linux/brcm47xx/patches-3.2/044-bcma-add-PCIe-host-controller.patch +++ b/target/linux/brcm47xx/patches-3.2/044-bcma-add-PCIe-host-controller.patch @@ -96,7 +96,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>  +}  --- a/drivers/bcma/bcma_private.h  +++ b/drivers/bcma/bcma_private.h -@@ -55,6 +55,7 @@ extern void __exit bcma_host_pci_exit(vo +@@ -60,6 +60,7 @@ extern void __exit bcma_host_pci_exit(vo   #endif /* CONFIG_BCMA_HOST_PCI */   #ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE diff --git a/target/linux/brcm47xx/patches-3.2/114-MIPS-BCM47xx-Setup-and-register-serial-early.patch b/target/linux/brcm47xx/patches-3.2/114-MIPS-BCM47xx-Setup-and-register-serial-early.patch index 12028c4a4..ddf257b55 100644 --- a/target/linux/brcm47xx/patches-3.2/114-MIPS-BCM47xx-Setup-and-register-serial-early.patch +++ b/target/linux/brcm47xx/patches-3.2/114-MIPS-BCM47xx-Setup-and-register-serial-early.patch @@ -15,7 +15,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>  --- a/arch/mips/bcm47xx/setup.c  +++ b/arch/mips/bcm47xx/setup.c -@@ -32,6 +32,8 @@ +@@ -33,6 +33,8 @@   #include <linux/ssb/ssb_embedded.h>   #include <linux/bcma/bcma_soc.h>   #include <linux/platform_device.h> @@ -24,7 +24,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>   #include <asm/bootinfo.h>   #include <asm/reboot.h>   #include <asm/time.h> -@@ -279,6 +281,31 @@ static int bcm47xx_get_invariants(struct +@@ -281,6 +283,31 @@ static int bcm47xx_get_invariants(struct   	return 0;   } @@ -56,7 +56,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>   static void __init bcm47xx_register_ssb(void)   {   	int err; -@@ -311,6 +338,10 @@ static void __init bcm47xx_register_ssb( +@@ -313,6 +340,10 @@ static void __init bcm47xx_register_ssb(   			memcpy(&mcore->serial_ports[1], &port, sizeof(port));   		}   	} diff --git a/target/linux/brcm47xx/patches-3.2/196-MIPS-BCM47XX-return-number-of-written-bytes-in-nvram.patch b/target/linux/brcm47xx/patches-3.2/196-MIPS-BCM47XX-return-number-of-written-bytes-in-nvram.patch index 926ec844c..ce226f36e 100644 --- a/target/linux/brcm47xx/patches-3.2/196-MIPS-BCM47XX-return-number-of-written-bytes-in-nvram.patch +++ b/target/linux/brcm47xx/patches-3.2/196-MIPS-BCM47XX-return-number-of-written-bytes-in-nvram.patch @@ -12,7 +12,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>  --- a/arch/mips/bcm47xx/nvram.c  +++ b/arch/mips/bcm47xx/nvram.c -@@ -192,8 +192,7 @@ int nvram_getenv(char *name, char *val, +@@ -243,8 +243,7 @@ int nvram_getenv(char *name, char *val,   		value = eq + 1;   		if ((eq - var) == strlen(name) &&   			strncmp(var, name, (eq - var)) == 0) { diff --git a/target/linux/brcm47xx/patches-3.2/198-MIPS-BCM47XX-move-and-extend-sprom-parsing.patch b/target/linux/brcm47xx/patches-3.2/198-MIPS-BCM47XX-move-and-extend-sprom-parsing.patch index a8272cd4c..b817d8adf 100644 --- a/target/linux/brcm47xx/patches-3.2/198-MIPS-BCM47XX-move-and-extend-sprom-parsing.patch +++ b/target/linux/brcm47xx/patches-3.2/198-MIPS-BCM47XX-move-and-extend-sprom-parsing.patch @@ -28,7 +28,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>   obj-$(CONFIG_BCM47XX_SSB)	+= wgt634u.o  --- a/arch/mips/bcm47xx/setup.c  +++ b/arch/mips/bcm47xx/setup.c -@@ -91,156 +91,7 @@ static void bcm47xx_machine_halt(void) +@@ -93,156 +93,7 @@ static void bcm47xx_machine_halt(void)   }   #ifdef CONFIG_BCM47XX_SSB diff --git a/target/linux/brcm47xx/patches-3.2/199-MIPS-BCM47XX-provide-sprom-to-bcma-bus.patch b/target/linux/brcm47xx/patches-3.2/199-MIPS-BCM47XX-provide-sprom-to-bcma-bus.patch index e3d252792..c96813c85 100644 --- a/target/linux/brcm47xx/patches-3.2/199-MIPS-BCM47XX-provide-sprom-to-bcma-bus.patch +++ b/target/linux/brcm47xx/patches-3.2/199-MIPS-BCM47XX-provide-sprom-to-bcma-bus.patch @@ -20,10 +20,10 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>    *  Copyright (C) 2010 Waldemar Brodkorb <wbx@openadk.org>  - *  Copyright (C) 2010-2011 Hauke Mehrtens <hauke@hauke-m.de>  + *  Copyright (C) 2010-2012 Hauke Mehrtens <hauke@hauke-m.de> +  *  Copyright (C) 2011-2012 Tathagata Das <tathagata@alumnux.com>    *    *  This program is free software; you can redistribute  it and/or modify it -  *  under  the terms of  the GNU General  Public License as published by the -@@ -91,7 +91,7 @@ static void bcm47xx_machine_halt(void) +@@ -93,7 +93,7 @@ static void bcm47xx_machine_halt(void)   }   #ifdef CONFIG_BCM47XX_SSB @@ -32,7 +32,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>   {   	char prefix[10]; -@@ -108,7 +108,7 @@ static int bcm47xx_get_sprom(struct ssb_ +@@ -110,7 +110,7 @@ static int bcm47xx_get_sprom(struct ssb_   }   static int bcm47xx_get_invariants(struct ssb_bus *bus, @@ -41,7 +41,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>   {   	char buf[20]; -@@ -163,7 +163,7 @@ static void __init bcm47xx_register_ssb( +@@ -165,7 +165,7 @@ static void __init bcm47xx_register_ssb(   	char buf[100];   	struct ssb_mipscore *mcore; @@ -50,7 +50,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>   	if (err)   		printk(KERN_WARNING "bcm47xx: someone else already registered"   			" a ssb SPROM callback handler (err %d)\n", err); -@@ -197,10 +197,41 @@ static void __init bcm47xx_register_ssb( +@@ -199,10 +199,41 @@ static void __init bcm47xx_register_ssb(   #endif   #ifdef CONFIG_BCM47XX_BCMA diff --git a/target/linux/brcm47xx/patches-3.2/231-bcma_reorder_sprom_fill.patch b/target/linux/brcm47xx/patches-3.2/231-bcma_reorder_sprom_fill.patch index c991ed313..ae7b7d4dc 100644 --- a/target/linux/brcm47xx/patches-3.2/231-bcma_reorder_sprom_fill.patch +++ b/target/linux/brcm47xx/patches-3.2/231-bcma_reorder_sprom_fill.patch @@ -1,6 +1,6 @@  --- a/arch/mips/bcm47xx/setup.c  +++ b/arch/mips/bcm47xx/setup.c -@@ -96,6 +96,7 @@ static int bcm47xx_get_sprom_ssb(struct +@@ -98,6 +98,7 @@ static int bcm47xx_get_sprom_ssb(struct   	char prefix[10];   	if (bus->bustype == SSB_BUSTYPE_PCI) { @@ -8,7 +8,7 @@   		snprintf(prefix, sizeof(prefix), "pci/%u/%u/",   			 bus->host_pci->bus->number + 1,   			 PCI_SLOT(bus->host_pci->devfn)); -@@ -124,6 +125,7 @@ static int bcm47xx_get_invariants(struct +@@ -126,6 +127,7 @@ static int bcm47xx_get_invariants(struct   	if (nvram_getenv("boardrev", buf, sizeof(buf)) >= 0)   		iv->boardinfo.rev = (u16)simple_strtoul(buf, NULL, 0); @@ -16,7 +16,7 @@   	bcm47xx_fill_sprom(&iv->sprom, NULL);   	if (nvram_getenv("cardbus", buf, sizeof(buf)) >= 0) -@@ -203,12 +205,14 @@ static int bcm47xx_get_sprom_bcma(struct +@@ -205,12 +207,14 @@ static int bcm47xx_get_sprom_bcma(struct   	struct bcma_device *core;   	if (bus->hosttype == BCMA_HOSTTYPE_PCI) { diff --git a/target/linux/brcm47xx/patches-3.2/400-arch-bcm47xx.patch b/target/linux/brcm47xx/patches-3.2/400-arch-bcm47xx.patch index 38a1fce64..df98b12d4 100644 --- a/target/linux/brcm47xx/patches-3.2/400-arch-bcm47xx.patch +++ b/target/linux/brcm47xx/patches-3.2/400-arch-bcm47xx.patch @@ -1,6 +1,6 @@  --- a/arch/mips/bcm47xx/nvram.c  +++ b/arch/mips/bcm47xx/nvram.c -@@ -198,3 +198,30 @@ int nvram_getenv(char *name, char *val, +@@ -249,3 +249,30 @@ int nvram_getenv(char *name, char *val,   	return NVRAM_ERR_ENVNOTFOUND;   }   EXPORT_SYMBOL(nvram_getenv); @@ -33,7 +33,7 @@  +EXPORT_SYMBOL(nvram_get);  --- a/arch/mips/bcm47xx/setup.c  +++ b/arch/mips/bcm47xx/setup.c -@@ -355,3 +355,20 @@ static int __init bcm47xx_register_flash +@@ -376,3 +376,20 @@ static int __init bcm47xx_register_flash   	return -1;   }   fs_initcall(bcm47xx_register_flash); diff --git a/target/linux/brcm47xx/patches-3.2/820-wgt634u-nvram-fix.patch b/target/linux/brcm47xx/patches-3.2/820-wgt634u-nvram-fix.patch index 3ccaa9557..3414ad731 100644 --- a/target/linux/brcm47xx/patches-3.2/820-wgt634u-nvram-fix.patch +++ b/target/linux/brcm47xx/patches-3.2/820-wgt634u-nvram-fix.patch @@ -245,8 +245,8 @@ out the configuration than the in kernel cfe config reader.  +  --- a/arch/mips/bcm47xx/nvram.c  +++ b/arch/mips/bcm47xx/nvram.c -@@ -23,6 +23,8 @@ - #include <asm/mach-bcm47xx/bus.h> +@@ -25,6 +25,8 @@ + #include <linux/mtd/bcm47xx_nand.h>   static char nvram_buf[NVRAM_SPACE];  +static int cfe_env; @@ -254,7 +254,7 @@ out the configuration than the in kernel cfe config reader.   /* Probe for NVRAM header */   static void early_nvram_init_pflash(void) -@@ -59,6 +61,25 @@ static void early_nvram_init_pflash(void +@@ -61,6 +63,25 @@ static void early_nvram_init_pflash(void   		break;   #endif   	} @@ -280,7 +280,7 @@ out the configuration than the in kernel cfe config reader.   	off = FLASH_MIN;   	while (off <= lim) { -@@ -181,6 +202,12 @@ int nvram_getenv(char *name, char *val, +@@ -232,6 +253,12 @@ int nvram_getenv(char *name, char *val,   	if (!nvram_buf[0])   		early_nvram_init(); @@ -293,7 +293,7 @@ out the configuration than the in kernel cfe config reader.   	/* Look for name=value and return value */   	var = &nvram_buf[sizeof(struct nvram_header)];   	end = nvram_buf + sizeof(nvram_buf) - 2; -@@ -209,6 +236,9 @@ char *nvram_get(const char *name) +@@ -260,6 +287,9 @@ char *nvram_get(const char *name)   	if (!nvram_buf[0])   		early_nvram_init(); diff --git a/target/linux/brcm47xx/patches-3.2/980-wnr834b_no_cardbus_invariant.patch b/target/linux/brcm47xx/patches-3.2/980-wnr834b_no_cardbus_invariant.patch index da43422d6..58dfd8afe 100644 --- a/target/linux/brcm47xx/patches-3.2/980-wnr834b_no_cardbus_invariant.patch +++ b/target/linux/brcm47xx/patches-3.2/980-wnr834b_no_cardbus_invariant.patch @@ -1,6 +1,6 @@  --- a/arch/mips/bcm47xx/setup.c  +++ b/arch/mips/bcm47xx/setup.c -@@ -131,6 +131,10 @@ static int bcm47xx_get_invariants(struct +@@ -133,6 +133,10 @@ static int bcm47xx_get_invariants(struct   	if (nvram_getenv("cardbus", buf, sizeof(buf)) >= 0)   		iv->has_cardbus_slot = !!simple_strtoul(buf, NULL, 10); diff --git a/target/linux/brcm47xx/patches-3.2/999-wl_exports.patch b/target/linux/brcm47xx/patches-3.2/999-wl_exports.patch index 5f8e8d350..550f4c968 100644 --- a/target/linux/brcm47xx/patches-3.2/999-wl_exports.patch +++ b/target/linux/brcm47xx/patches-3.2/999-wl_exports.patch @@ -1,8 +1,8 @@  --- a/arch/mips/bcm47xx/nvram.c  +++ b/arch/mips/bcm47xx/nvram.c -@@ -22,7 +22,8 @@ - #include <asm/mach-bcm47xx/bcm47xx.h> +@@ -24,7 +24,8 @@   #include <asm/mach-bcm47xx/bus.h> + #include <linux/mtd/bcm47xx_nand.h>  -static char nvram_buf[NVRAM_SPACE];  +char nvram_buf[NVRAM_SPACE]; | 
