diff options
Diffstat (limited to 'target/linux/brcm47xx/patches-3.8/080-MIPS-BCM47XX-rewrite-nvram-probing.patch')
-rw-r--r-- | target/linux/brcm47xx/patches-3.8/080-MIPS-BCM47XX-rewrite-nvram-probing.patch | 472 |
1 files changed, 472 insertions, 0 deletions
diff --git a/target/linux/brcm47xx/patches-3.8/080-MIPS-BCM47XX-rewrite-nvram-probing.patch b/target/linux/brcm47xx/patches-3.8/080-MIPS-BCM47XX-rewrite-nvram-probing.patch new file mode 100644 index 0000000000..04c378f33e --- /dev/null +++ b/target/linux/brcm47xx/patches-3.8/080-MIPS-BCM47XX-rewrite-nvram-probing.patch @@ -0,0 +1,472 @@ +--- a/arch/mips/bcm47xx/nvram.c ++++ b/arch/mips/bcm47xx/nvram.c +@@ -3,7 +3,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) 2010-2012 Hauke Mehrtens <hauke@hauke-m.de> + * + * 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 +@@ -18,83 +18,168 @@ + #include <linux/kernel.h> + #include <linux/string.h> + #include <asm/addrspace.h> +-#include <asm/mach-bcm47xx/nvram.h> ++#include <bcm47xx_nvram.h> + #include <asm/mach-bcm47xx/bcm47xx.h> + + static char nvram_buf[NVRAM_SPACE]; + ++static u32 find_nvram_size(u32 end) ++{ ++ struct nvram_header *header; ++ u32 nvram_sizes[] = {0x8000, 0xF000, 0x10000}; ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(nvram_sizes); i++) { ++ header = (struct nvram_header *)KSEG1ADDR(end - nvram_sizes[i]); ++ if (header->magic == NVRAM_HEADER) ++ return nvram_sizes[i]; ++ } ++ ++ return 0; ++} ++ + /* Probe for NVRAM header */ +-static void early_nvram_init(void) ++static int nvram_find_and_copy(u32 base, u32 lim) + { +-#ifdef CONFIG_BCM47XX_SSB +- struct ssb_mipscore *mcore_ssb; +-#endif +-#ifdef CONFIG_BCM47XX_BCMA +- struct bcma_drv_cc *bcma_cc; +-#endif + struct nvram_header *header; + int i; +- u32 base = 0; +- u32 lim = 0; + u32 off; + u32 *src, *dst; ++ u32 size; + +- switch (bcm47xx_bus_type) { +-#ifdef CONFIG_BCM47XX_SSB +- case BCM47XX_BUS_TYPE_SSB: +- mcore_ssb = &bcm47xx_bus.ssb.mipscore; +- base = mcore_ssb->pflash.window; +- lim = mcore_ssb->pflash.window_size; +- break; +-#endif +-#ifdef CONFIG_BCM47XX_BCMA +- case BCM47XX_BUS_TYPE_BCMA: +- bcma_cc = &bcm47xx_bus.bcma.bus.drv_cc; +- base = bcma_cc->pflash.window; +- lim = bcma_cc->pflash.window_size; +- break; +-#endif +- } +- ++ /* TODO: when nvram is on nand flash check for bad blocks first. */ + off = FLASH_MIN; + while (off <= lim) { + /* Windowed flash access */ +- header = (struct nvram_header *) +- KSEG1ADDR(base + off - NVRAM_SPACE); +- if (header->magic == NVRAM_HEADER) ++ size = find_nvram_size(base + off); ++ if (size) { ++ header = (struct nvram_header *)KSEG1ADDR(base + off - ++ size); + goto found; ++ } + off <<= 1; + } + + /* Try embedded NVRAM at 4 KB and 1 KB as last resorts */ + header = (struct nvram_header *) KSEG1ADDR(base + 4096); +- if (header->magic == NVRAM_HEADER) ++ if (header->magic == NVRAM_HEADER) { ++ size = NVRAM_SPACE; + goto found; ++ } + + header = (struct nvram_header *) KSEG1ADDR(base + 1024); +- if (header->magic == NVRAM_HEADER) ++ if (header->magic == NVRAM_HEADER) { ++ size = NVRAM_SPACE; + goto found; ++ } + +- return; ++ pr_err("no nvram found\n"); ++ return -ENXIO; + + found: ++ ++ if (header->len > size) ++ pr_err("The nvram size accoridng to the header seems to be bigger than the partition on flash\n"); ++ if (header->len > NVRAM_SPACE) ++ pr_err("nvram on flash (%i bytes) is bigger than the reserved space in memory, will just copy the first %i bytes\n", ++ header->len, NVRAM_SPACE); ++ + src = (u32 *) header; + dst = (u32 *) nvram_buf; + for (i = 0; i < sizeof(struct nvram_header); i += 4) + *dst++ = *src++; +- for (; i < header->len && i < NVRAM_SPACE; i += 4) ++ for (; i < header->len && i < NVRAM_SPACE && i < size; i += 4) + *dst++ = le32_to_cpu(*src++); ++ memset(dst, 0x0, NVRAM_SPACE - i); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_BCM47XX_SSB ++static int nvram_init_ssb(void) ++{ ++ struct ssb_mipscore *mcore = &bcm47xx_bus.ssb.mipscore; ++#ifdef CONFIG_SSB_SFLASH ++ struct ssb_chipcommon *chipco = &bcm47xx_bus.ssb.chipco; ++#endif ++ u32 base; ++ u32 lim; ++ ++ if (mcore->pflash.present) { ++ base = mcore->pflash.window; ++ lim = mcore->pflash.window_size; ++#ifdef CONFIG_SSB_SFLASH ++ } else if (chipco->sflash.present) { ++ base = chipco->sflash.window; ++ lim = chipco->sflash.size; ++#endif ++ } else { ++ pr_err("Couldn't find supported flash memory\n"); ++ return -ENXIO; ++ } ++ ++ return nvram_find_and_copy(base, lim); ++} ++#endif ++ ++#ifdef CONFIG_BCM47XX_BCMA ++static int nvram_init_bcma(void) ++{ ++ struct bcma_drv_cc *cc = &bcm47xx_bus.bcma.bus.drv_cc; ++ u32 base; ++ u32 lim; ++ ++#ifdef CONFIG_BCMA_NFLASH ++ if (cc->nflash.boot) { ++ base = BCMA_SOC_FLASH1; ++ lim = BCMA_SOC_FLASH1_SZ; ++ } else ++#endif ++ if (cc->pflash.present) { ++ base = cc->pflash.window; ++ lim = cc->pflash.window_size; ++#ifdef CONFIG_BCMA_SFLASH ++ } else if (cc->sflash.present) { ++ base = cc->sflash.window; ++ lim = cc->sflash.size; ++#endif ++ } else { ++ pr_err("Couldn't find supported flash memory\n"); ++ return -ENXIO; ++ } ++ ++ return nvram_find_and_copy(base, lim); + } ++#endif + +-int nvram_getenv(char *name, char *val, size_t val_len) ++static int nvram_init(void) ++{ ++ switch (bcm47xx_bus_type) { ++#ifdef CONFIG_BCM47XX_SSB ++ case BCM47XX_BUS_TYPE_SSB: ++ return nvram_init_ssb(); ++#endif ++#ifdef CONFIG_BCM47XX_BCMA ++ case BCM47XX_BUS_TYPE_BCMA: ++ return nvram_init_bcma(); ++#endif ++ } ++ return -ENXIO; ++} ++ ++int bcm47xx_nvram_getenv(char *name, char *val, size_t val_len) + { + char *var, *value, *end, *eq; ++ int err; + + if (!name) +- return NVRAM_ERR_INV_PARAM; ++ return -EINVAL; + +- if (!nvram_buf[0]) +- early_nvram_init(); ++ if (!nvram_buf[0]) { ++ err = nvram_init(); ++ if (err) ++ return err; ++ } + + /* Look for name=value and return value */ + var = &nvram_buf[sizeof(struct nvram_header)]; +@@ -110,6 +195,6 @@ int nvram_getenv(char *name, char *val, + return snprintf(val, val_len, "%s", value); + } + } +- return NVRAM_ERR_ENVNOTFOUND; ++ return -ENOENT; + } +-EXPORT_SYMBOL(nvram_getenv); ++EXPORT_SYMBOL(bcm47xx_nvram_getenv); +--- a/arch/mips/bcm47xx/setup.c ++++ b/arch/mips/bcm47xx/setup.c +@@ -35,7 +35,7 @@ + #include <asm/reboot.h> + #include <asm/time.h> + #include <bcm47xx.h> +-#include <asm/mach-bcm47xx/nvram.h> ++#include <bcm47xx_nvram.h> + + union bcm47xx_bus bcm47xx_bus; + EXPORT_SYMBOL(bcm47xx_bus); +@@ -115,7 +115,7 @@ static int bcm47xx_get_invariants(struct + memset(&iv->sprom, 0, sizeof(struct ssb_sprom)); + bcm47xx_fill_sprom(&iv->sprom, NULL, false); + +- if (nvram_getenv("cardbus", buf, sizeof(buf)) >= 0) ++ if (bcm47xx_nvram_getenv("cardbus", buf, sizeof(buf)) >= 0) + iv->has_cardbus_slot = !!simple_strtoul(buf, NULL, 10); + + return 0; +@@ -138,7 +138,7 @@ static void __init bcm47xx_register_ssb( + panic("Failed to initialize SSB bus (err %d)", err); + + mcore = &bcm47xx_bus.ssb.mipscore; +- if (nvram_getenv("kernel_args", buf, sizeof(buf)) >= 0) { ++ if (bcm47xx_nvram_getenv("kernel_args", buf, sizeof(buf)) >= 0) { + if (strstr(buf, "console=ttyS1")) { + struct ssb_serial_port port; + +--- a/arch/mips/bcm47xx/sprom.c ++++ b/arch/mips/bcm47xx/sprom.c +@@ -27,7 +27,7 @@ + */ + + #include <bcm47xx.h> +-#include <nvram.h> ++#include <bcm47xx_nvram.h> + + static void create_key(const char *prefix, const char *postfix, + const char *name, char *buf, int len) +@@ -50,10 +50,10 @@ static int get_nvram_var(const char *pre + + create_key(prefix, postfix, name, key, sizeof(key)); + +- err = nvram_getenv(key, buf, len); +- if (fallback && err == NVRAM_ERR_ENVNOTFOUND && prefix) { ++ err = bcm47xx_nvram_getenv(key, buf, len); ++ if (fallback && err == -ENOENT && prefix) { + create_key(NULL, postfix, name, key, sizeof(key)); +- err = nvram_getenv(key, buf, len); ++ err = bcm47xx_nvram_getenv(key, buf, len); + } + return err; + } +@@ -144,7 +144,7 @@ static void nvram_read_macaddr(const cha + if (err < 0) + return; + +- nvram_parse_macaddr(buf, *val); ++ bcm47xx_nvram_parse_macaddr(buf, *val); + } + + static void nvram_read_alpha2(const char *prefix, const char *name, +--- /dev/null ++++ b/arch/mips/include/asm/mach-bcm47xx/bcm47xx_nvram.h +@@ -0,0 +1,51 @@ ++/* ++ * Copyright (C) 2005, Broadcom Corporation ++ * Copyright (C) 2006, Felix Fietkau <nbd@openwrt.org> ++ * ++ * 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 ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. ++ */ ++ ++#ifndef __BCM47XX_NVRAM_H ++#define __BCM47XX_NVRAM_H ++ ++#include <linux/types.h> ++#include <linux/kernel.h> ++ ++struct nvram_header { ++ u32 magic; ++ u32 len; ++ u32 crc_ver_init; /* 0:7 crc, 8:15 ver, 16:31 sdram_init */ ++ u32 config_refresh; /* 0:15 sdram_config, 16:31 sdram_refresh */ ++ u32 config_ncdl; /* ncdl values for memc */ ++}; ++ ++#define NVRAM_HEADER 0x48534C46 /* 'FLSH' */ ++#define NVRAM_VERSION 1 ++#define NVRAM_HEADER_SIZE 20 ++#define NVRAM_SPACE 0x8000 ++ ++#define FLASH_MIN 0x00020000 /* Minimum flash size */ ++ ++#define NVRAM_MAX_VALUE_LEN 255 ++#define NVRAM_MAX_PARAM_LEN 64 ++ ++extern int bcm47xx_nvram_getenv(char *name, char *val, size_t val_len); ++ ++static inline void bcm47xx_nvram_parse_macaddr(char *buf, u8 macaddr[6]) ++{ ++ if (strchr(buf, ':')) ++ sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &macaddr[0], ++ &macaddr[1], &macaddr[2], &macaddr[3], &macaddr[4], ++ &macaddr[5]); ++ else if (strchr(buf, '-')) ++ sscanf(buf, "%hhx-%hhx-%hhx-%hhx-%hhx-%hhx", &macaddr[0], ++ &macaddr[1], &macaddr[2], &macaddr[3], &macaddr[4], ++ &macaddr[5]); ++ else ++ printk(KERN_WARNING "Can not parse mac address: %s\n", buf); ++} ++ ++#endif /* __BCM47XX_NVRAM_H */ +--- a/arch/mips/include/asm/mach-bcm47xx/nvram.h ++++ /dev/null +@@ -1,54 +0,0 @@ +-/* +- * Copyright (C) 2005, Broadcom Corporation +- * Copyright (C) 2006, Felix Fietkau <nbd@openwrt.org> +- * +- * 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 +- * Free Software Foundation; either version 2 of the License, or (at your +- * option) any later version. +- */ +- +-#ifndef __NVRAM_H +-#define __NVRAM_H +- +-#include <linux/types.h> +-#include <linux/kernel.h> +- +-struct nvram_header { +- u32 magic; +- u32 len; +- u32 crc_ver_init; /* 0:7 crc, 8:15 ver, 16:31 sdram_init */ +- u32 config_refresh; /* 0:15 sdram_config, 16:31 sdram_refresh */ +- u32 config_ncdl; /* ncdl values for memc */ +-}; +- +-#define NVRAM_HEADER 0x48534C46 /* 'FLSH' */ +-#define NVRAM_VERSION 1 +-#define NVRAM_HEADER_SIZE 20 +-#define NVRAM_SPACE 0x8000 +- +-#define FLASH_MIN 0x00020000 /* Minimum flash size */ +- +-#define NVRAM_MAX_VALUE_LEN 255 +-#define NVRAM_MAX_PARAM_LEN 64 +- +-#define NVRAM_ERR_INV_PARAM -8 +-#define NVRAM_ERR_ENVNOTFOUND -9 +- +-extern int nvram_getenv(char *name, char *val, size_t val_len); +- +-static inline void nvram_parse_macaddr(char *buf, u8 macaddr[6]) +-{ +- if (strchr(buf, ':')) +- sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &macaddr[0], +- &macaddr[1], &macaddr[2], &macaddr[3], &macaddr[4], +- &macaddr[5]); +- else if (strchr(buf, '-')) +- sscanf(buf, "%hhx-%hhx-%hhx-%hhx-%hhx-%hhx", &macaddr[0], +- &macaddr[1], &macaddr[2], &macaddr[3], &macaddr[4], +- &macaddr[5]); +- else +- printk(KERN_WARNING "Can not parse mac address: %s\n", buf); +-} +- +-#endif +--- a/drivers/mtd/bcm47xxpart.c ++++ b/drivers/mtd/bcm47xxpart.c +@@ -14,7 +14,7 @@ + #include <linux/slab.h> + #include <linux/mtd/mtd.h> + #include <linux/mtd/partitions.h> +-#include <asm/mach-bcm47xx/nvram.h> ++#include <bcm47xx_nvram.h> + + /* 10 parts were found on sflash on Netgear WNDR4500 */ + #define BCM47XXPART_MAX_PARTS 12 +--- a/drivers/net/ethernet/broadcom/b44.c ++++ b/drivers/net/ethernet/broadcom/b44.c +@@ -381,7 +381,7 @@ static void b44_set_flow_ctrl(struct b44 + } + + #ifdef CONFIG_BCM47XX +-#include <asm/mach-bcm47xx/nvram.h> ++#include <bcm47xx_nvram.h> + static void b44_wap54g10_workaround(struct b44 *bp) + { + char buf[20]; +@@ -393,7 +393,7 @@ static void b44_wap54g10_workaround(stru + * see https://dev.openwrt.org/ticket/146 + * check and reset bit "isolate" + */ +- if (nvram_getenv("boardnum", buf, sizeof(buf)) < 0) ++ if (bcm47xx_nvram_getenv("boardnum", buf, sizeof(buf)) < 0) + return; + if (simple_strtoul(buf, NULL, 0) == 2) { + err = __b44_readphy(bp, 0, MII_BMCR, &val); +--- a/drivers/ssb/driver_chipcommon_pmu.c ++++ b/drivers/ssb/driver_chipcommon_pmu.c +@@ -14,7 +14,7 @@ + #include <linux/delay.h> + #include <linux/export.h> + #ifdef CONFIG_BCM47XX +-#include <asm/mach-bcm47xx/nvram.h> ++#include <bcm47xx_nvram.h> + #endif + + #include "ssb_private.h" +@@ -322,7 +322,7 @@ static void ssb_pmu_pll_init(struct ssb_ + if (bus->bustype == SSB_BUSTYPE_SSB) { + #ifdef CONFIG_BCM47XX + char buf[20]; +- if (nvram_getenv("xtalfreq", buf, sizeof(buf)) >= 0) ++ if (bcm47xx_nvram_getenv("xtalfreq", buf, sizeof(buf)) >= 0) + crystalfreq = simple_strtoul(buf, NULL, 0); + #endif + } +--- a/include/linux/ssb/ssb_driver_gige.h ++++ b/include/linux/ssb/ssb_driver_gige.h +@@ -98,14 +98,14 @@ static inline bool ssb_gige_must_flush_p + } + + #ifdef CONFIG_BCM47XX +-#include <asm/mach-bcm47xx/nvram.h> ++#include <bcm47xx_nvram.h> + /* Get the device MAC address */ + static inline void ssb_gige_get_macaddr(struct pci_dev *pdev, u8 *macaddr) + { + char buf[20]; +- if (nvram_getenv("et0macaddr", buf, sizeof(buf)) < 0) ++ if (bcm47xx_nvram_getenv("et0macaddr", buf, sizeof(buf)) < 0) + return; +- nvram_parse_macaddr(buf, macaddr); ++ bcm47xx_nvram_parse_macaddr(buf, macaddr); + } + #else + static inline void ssb_gige_get_macaddr(struct pci_dev *pdev, u8 *macaddr) |