diff options
Diffstat (limited to 'arch/mips/bcm47xx')
-rw-r--r-- | arch/mips/bcm47xx/nvram.c | 159 | ||||
-rw-r--r-- | arch/mips/bcm47xx/setup.c | 6 | ||||
-rw-r--r-- | arch/mips/bcm47xx/sprom.c | 22 |
3 files changed, 131 insertions, 56 deletions
diff --git a/arch/mips/bcm47xx/nvram.c b/arch/mips/bcm47xx/nvram.c index c37419c11c92..cc40b74940f5 100644 --- 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,160 @@ #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; } -int nvram_getenv(char *name, char *val, size_t val_len) +#ifdef CONFIG_BCM47XX_SSB +static int nvram_init_ssb(void) +{ + struct ssb_mipscore *mcore = &bcm47xx_bus.ssb.mipscore; + u32 base; + u32 lim; + + if (mcore->pflash.present) { + base = mcore->pflash.window; + lim = mcore->pflash.window_size; + } 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 + +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 +187,6 @@ int nvram_getenv(char *name, char *val, size_t val_len) return snprintf(val, val_len, "%s", value); } } - return NVRAM_ERR_ENVNOTFOUND; + return -ENOENT; } -EXPORT_SYMBOL(nvram_getenv); +EXPORT_SYMBOL(bcm47xx_nvram_getenv); diff --git a/arch/mips/bcm47xx/setup.c b/arch/mips/bcm47xx/setup.c index 4d54b58dbd32..b2246cd9ca12 100644 --- 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 ssb_bus *bus, 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(void) 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; diff --git a/arch/mips/bcm47xx/sprom.c b/arch/mips/bcm47xx/sprom.c index b2a7c251e471..ad03c931b905 100644 --- 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 *prefix, const char *postfix, 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; } @@ -71,7 +71,7 @@ static void nvram_read_ ## type (const char *prefix, \ fallback); \ if (err < 0) \ return; \ - err = kstrto ## type (buf, 0, &var); \ + err = kstrto ## type(strim(buf), 0, &var); \ if (err) { \ pr_warn("can not parse nvram name %s%s%s with value %s got %i\n", \ prefix, name, postfix, buf, err); \ @@ -99,7 +99,7 @@ static void nvram_read_u32_2(const char *prefix, const char *name, err = get_nvram_var(prefix, NULL, name, buf, sizeof(buf), fallback); if (err < 0) return; - err = kstrtou32(buf, 0, &val); + err = kstrtou32(strim(buf), 0, &val); if (err) { pr_warn("can not parse nvram name %s%s with value %s got %i\n", prefix, name, buf, err); @@ -120,7 +120,7 @@ static void nvram_read_leddc(const char *prefix, const char *name, err = get_nvram_var(prefix, NULL, name, buf, sizeof(buf), fallback); if (err < 0) return; - err = kstrtou32(buf, 0, &val); + err = kstrtou32(strim(buf), 0, &val); if (err) { pr_warn("can not parse nvram name %s%s with value %s got %i\n", prefix, name, buf, err); @@ -144,7 +144,7 @@ static void nvram_read_macaddr(const char *prefix, const char *name, 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, @@ -652,12 +652,10 @@ static void bcm47xx_fill_sprom_ethernet(struct ssb_sprom *sprom, static void bcm47xx_fill_board_data(struct ssb_sprom *sprom, const char *prefix, bool fallback) { - nvram_read_u16(prefix, NULL, "boardrev", &sprom->board_rev, 0, - fallback); + nvram_read_u16(prefix, NULL, "boardrev", &sprom->board_rev, 0, true); nvram_read_u16(prefix, NULL, "boardnum", &sprom->board_num, 0, fallback); - nvram_read_u16(prefix, NULL, "boardtype", &sprom->board_type, 0, - fallback); + nvram_read_u16(prefix, NULL, "boardtype", &sprom->board_type, 0, true); nvram_read_u32_2(prefix, "boardflags", &sprom->boardflags_lo, &sprom->boardflags_hi, fallback); nvram_read_u32_2(prefix, "boardflags2", &sprom->boardflags2_lo, |