aboutsummaryrefslogtreecommitdiff
path: root/arch/mips/bcm47xx
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/bcm47xx')
-rw-r--r--arch/mips/bcm47xx/Makefile2
-rw-r--r--arch/mips/bcm47xx/nvram.c163
-rw-r--r--arch/mips/bcm47xx/setup.c6
-rw-r--r--arch/mips/bcm47xx/sprom.c26
-rw-r--r--arch/mips/bcm47xx/wgt634u.c40
5 files changed, 156 insertions, 81 deletions
diff --git a/arch/mips/bcm47xx/Makefile b/arch/mips/bcm47xx/Makefile
index 1a3567f07e7..f3bf6d5bfb9 100644
--- a/arch/mips/bcm47xx/Makefile
+++ b/arch/mips/bcm47xx/Makefile
@@ -3,5 +3,5 @@
# under Linux.
#
-obj-y += irq.o nvram.o prom.o serial.o setup.o time.o sprom.o
+obj-y += irq.o nvram.o prom.o serial.o setup.o time.o sprom.o
obj-$(CONFIG_BCM47XX_SSB) += wgt634u.o
diff --git a/arch/mips/bcm47xx/nvram.c b/arch/mips/bcm47xx/nvram.c
index 48a4c70b384..cc40b74940f 100644
--- a/arch/mips/bcm47xx/nvram.c
+++ b/arch/mips/bcm47xx/nvram.c
@@ -3,10 +3,10 @@
*
* 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
+ * 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.
*/
@@ -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 4d54b58dbd3..b2246cd9ca1 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 289cc0a3863..ad03c931b90 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,18 +50,18 @@ 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;
}
#define NVRAM_READ_VAL(type) \
static void nvram_read_ ## type (const char *prefix, \
- const char *postfix, const char *name, \
- type *val, type allset, bool fallback) \
+ const char *postfix, const char *name, \
+ type *val, type allset, bool fallback) \
{ \
char buf[100]; \
int 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,
diff --git a/arch/mips/bcm47xx/wgt634u.c b/arch/mips/bcm47xx/wgt634u.c
index 9d111e8087e..c63a4c287b5 100644
--- a/arch/mips/bcm47xx/wgt634u.c
+++ b/arch/mips/bcm47xx/wgt634u.c
@@ -36,13 +36,13 @@ static struct gpio_led wgt634u_leds[] = {
};
static struct gpio_led_platform_data wgt634u_led_data = {
- .num_leds = ARRAY_SIZE(wgt634u_leds),
- .leds = wgt634u_leds,
+ .num_leds = ARRAY_SIZE(wgt634u_leds),
+ .leds = wgt634u_leds,
};
static struct platform_device wgt634u_gpio_leds = {
- .name = "leds-gpio",
- .id = -1,
+ .name = "leds-gpio",
+ .id = -1,
.dev = {
.platform_data = &wgt634u_led_data,
}
@@ -53,35 +53,35 @@ static struct platform_device wgt634u_gpio_leds = {
firmware. */
static struct mtd_partition wgt634u_partitions[] = {
{
- .name = "cfe",
- .offset = 0,
- .size = 0x60000, /* 384k */
- .mask_flags = MTD_WRITEABLE /* force read-only */
+ .name = "cfe",
+ .offset = 0,
+ .size = 0x60000, /* 384k */
+ .mask_flags = MTD_WRITEABLE /* force read-only */
},
{
- .name = "config",
+ .name = "config",
.offset = 0x60000,
- .size = 0x20000 /* 128k */
+ .size = 0x20000 /* 128k */
},
{
- .name = "linux",
+ .name = "linux",
.offset = 0x80000,
- .size = 0x140000 /* 1280k */
+ .size = 0x140000 /* 1280k */
},
{
- .name = "jffs",
+ .name = "jffs",
.offset = 0x1c0000,
- .size = 0x620000 /* 6272k */
+ .size = 0x620000 /* 6272k */
},
{
- .name = "nvram",
+ .name = "nvram",
.offset = 0x7e0000,
- .size = 0x20000 /* 128k */
+ .size = 0x20000 /* 128k */
},
};
static struct physmap_flash_data wgt634u_flash_data = {
- .parts = wgt634u_partitions,
+ .parts = wgt634u_partitions,
.nr_parts = ARRAY_SIZE(wgt634u_partitions)
};
@@ -90,9 +90,9 @@ static struct resource wgt634u_flash_resource = {
};
static struct platform_device wgt634u_flash = {
- .name = "physmap-flash",
- .id = 0,
- .dev = { .platform_data = &wgt634u_flash_data, },
+ .name = "physmap-flash",
+ .id = 0,
+ .dev = { .platform_data = &wgt634u_flash_data, },
.resource = &wgt634u_flash_resource,
.num_resources = 1,
};