aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/bcm47xx
diff options
context:
space:
mode:
authorWaldemar Brodkorb <mips@waldemar-brodkorb.de>2010-06-08 13:06:01 -0400
committerRalf Baechle <ralf@linux-mips.org>2010-07-05 12:17:32 -0400
commit121915c4ee0812a14bc8d752bc210d0238d755c1 (patch)
tree76c12b34f0b97fbdc2ba627b6cc58327847a90d8 /arch/mips/bcm47xx
parent5df74352876c0835d2b41b53858c9ee779e0f12f (diff)
MIPS: BCM47xx: Add NVRAM support devices
When trying to netboot a Linksys WRT54GS WLAN router, the bootup fails, because of following error message: ... [ 0.424000] b44: b44.c:v2.0 [ 0.424000] b44: Invalid MAC address found in EEPROM [ 0.432000] b44 ssb0:1: Problem fetching invariants of chip,aborting [ 0.436000] b44: probe of ssb0:1 failed with error -22 ... The router uses a CFE bootloader, but most of the needed environment variables for network card initialization, are not available from CFE via printenv and even though not via cfe_getenv(). The required environment variables are saved in a special partition in flash memory. The attached patch implement nvram_getenv and enables bootup via NFS root on my router. Most of the patch is extracted from the OpenWrt subversion repository and stripped down and cleaned up to just fix this issue. [Ralf: sorted out header file inclusions. Lots of unneded headers and such that should have been included.] Signed-off-by: Waldemar Brodkorb <wbx@openadk.org> Reviewed-by: Phil Sutter <phil@nwl.cc> To: linux-mips@linux-mips.org Cc: Hauke Mehrtens <hauke@hauke-m.de> Patchwork: http://patchwork.linux-mips.org/patch/1359/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/bcm47xx')
-rw-r--r--arch/mips/bcm47xx/Makefile2
-rw-r--r--arch/mips/bcm47xx/nvram.c94
-rw-r--r--arch/mips/bcm47xx/setup.c39
3 files changed, 122 insertions, 13 deletions
diff --git a/arch/mips/bcm47xx/Makefile b/arch/mips/bcm47xx/Makefile
index 35294b12d638..7465e8a72d9a 100644
--- a/arch/mips/bcm47xx/Makefile
+++ b/arch/mips/bcm47xx/Makefile
@@ -3,4 +3,4 @@
3# under Linux. 3# under Linux.
4# 4#
5 5
6obj-y := gpio.o irq.o prom.o serial.o setup.o time.o wgt634u.o 6obj-y := gpio.o irq.o nvram.o prom.o serial.o setup.o time.o wgt634u.o
diff --git a/arch/mips/bcm47xx/nvram.c b/arch/mips/bcm47xx/nvram.c
new file mode 100644
index 000000000000..06e03b222f6d
--- /dev/null
+++ b/arch/mips/bcm47xx/nvram.c
@@ -0,0 +1,94 @@
1/*
2 * BCM947xx nvram variable access
3 *
4 * Copyright (C) 2005 Broadcom Corporation
5 * Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 */
12
13#include <linux/init.h>
14#include <linux/types.h>
15#include <linux/module.h>
16#include <linux/ssb/ssb.h>
17#include <linux/kernel.h>
18#include <linux/string.h>
19#include <asm/addrspace.h>
20#include <asm/mach-bcm47xx/nvram.h>
21#include <asm/mach-bcm47xx/bcm47xx.h>
22
23static char nvram_buf[NVRAM_SPACE];
24
25/* Probe for NVRAM header */
26static void __init early_nvram_init(void)
27{
28 struct ssb_mipscore *mcore = &ssb_bcm47xx.mipscore;
29 struct nvram_header *header;
30 int i;
31 u32 base, lim, off;
32 u32 *src, *dst;
33
34 base = mcore->flash_window;
35 lim = mcore->flash_window_size;
36
37 off = FLASH_MIN;
38 while (off <= lim) {
39 /* Windowed flash access */
40 header = (struct nvram_header *)
41 KSEG1ADDR(base + off - NVRAM_SPACE);
42 if (header->magic == NVRAM_HEADER)
43 goto found;
44 off <<= 1;
45 }
46
47 /* Try embedded NVRAM at 4 KB and 1 KB as last resorts */
48 header = (struct nvram_header *) KSEG1ADDR(base + 4096);
49 if (header->magic == NVRAM_HEADER)
50 goto found;
51
52 header = (struct nvram_header *) KSEG1ADDR(base + 1024);
53 if (header->magic == NVRAM_HEADER)
54 goto found;
55
56 return;
57
58found:
59 src = (u32 *) header;
60 dst = (u32 *) nvram_buf;
61 for (i = 0; i < sizeof(struct nvram_header); i += 4)
62 *dst++ = *src++;
63 for (; i < header->len && i < NVRAM_SPACE; i += 4)
64 *dst++ = le32_to_cpu(*src++);
65}
66
67int nvram_getenv(char *name, char *val, size_t val_len)
68{
69 char *var, *value, *end, *eq;
70
71 if (!name)
72 return 1;
73
74 if (!nvram_buf[0])
75 early_nvram_init();
76
77 /* Look for name=value and return value */
78 var = &nvram_buf[sizeof(struct nvram_header)];
79 end = nvram_buf + sizeof(nvram_buf) - 2;
80 end[0] = end[1] = '\0';
81 for (; *var; var = value + strlen(value) + 1) {
82 eq = strchr(var, '=');
83 if (!eq)
84 break;
85 value = eq + 1;
86 if ((eq - var) == strlen(name) &&
87 strncmp(var, name, (eq - var)) == 0) {
88 snprintf(val, val_len, "%s", value);
89 return 0;
90 }
91 }
92 return 1;
93}
94EXPORT_SYMBOL(nvram_getenv);
diff --git a/arch/mips/bcm47xx/setup.c b/arch/mips/bcm47xx/setup.c
index d442e11625fa..b1aee33efd11 100644
--- a/arch/mips/bcm47xx/setup.c
+++ b/arch/mips/bcm47xx/setup.c
@@ -1,8 +1,8 @@
1/* 1/*
2 * Copyright (C) 2004 Florian Schirmer <jolt@tuxbox.org> 2 * Copyright (C) 2004 Florian Schirmer <jolt@tuxbox.org>
3 * Copyright (C) 2005 Waldemar Brodkorb <wbx@openwrt.org>
4 * Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org> 3 * Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>
5 * Copyright (C) 2006 Michael Buesch <mb@bu3sch.de> 4 * Copyright (C) 2006 Michael Buesch <mb@bu3sch.de>
5 * Copyright (C) 2010 Waldemar Brodkorb <wbx@openadk.org>
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify it 7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the 8 * under the terms of the GNU General Public License as published by the
@@ -33,6 +33,7 @@
33#include <asm/time.h> 33#include <asm/time.h>
34#include <bcm47xx.h> 34#include <bcm47xx.h>
35#include <asm/fw/cfe/cfe_api.h> 35#include <asm/fw/cfe/cfe_api.h>
36#include <asm/mach-bcm47xx/nvram.h>
36 37
37struct ssb_bus ssb_bcm47xx; 38struct ssb_bus ssb_bcm47xx;
38EXPORT_SYMBOL(ssb_bcm47xx); 39EXPORT_SYMBOL(ssb_bcm47xx);
@@ -81,28 +82,42 @@ static int bcm47xx_get_invariants(struct ssb_bus *bus,
81 /* Fill boardinfo structure */ 82 /* Fill boardinfo structure */
82 memset(&(iv->boardinfo), 0 , sizeof(struct ssb_boardinfo)); 83 memset(&(iv->boardinfo), 0 , sizeof(struct ssb_boardinfo));
83 84
84 if (cfe_getenv("boardvendor", buf, sizeof(buf)) >= 0) 85 if (cfe_getenv("boardvendor", buf, sizeof(buf)) >= 0 ||
86 nvram_getenv("boardvendor", buf, sizeof(buf)) >= 0)
85 iv->boardinfo.type = (u16)simple_strtoul(buf, NULL, 0); 87 iv->boardinfo.type = (u16)simple_strtoul(buf, NULL, 0);
86 if (cfe_getenv("boardtype", buf, sizeof(buf)) >= 0) 88 if (cfe_getenv("boardtype", buf, sizeof(buf)) >= 0 ||
89 nvram_getenv("boardtype", buf, sizeof(buf)) >= 0)
87 iv->boardinfo.type = (u16)simple_strtoul(buf, NULL, 0); 90 iv->boardinfo.type = (u16)simple_strtoul(buf, NULL, 0);
88 if (cfe_getenv("boardrev", buf, sizeof(buf)) >= 0) 91 if (cfe_getenv("boardrev", buf, sizeof(buf)) >= 0 ||
92 nvram_getenv("boardrev", buf, sizeof(buf)) >= 0)
89 iv->boardinfo.rev = (u16)simple_strtoul(buf, NULL, 0); 93 iv->boardinfo.rev = (u16)simple_strtoul(buf, NULL, 0);
90 94
91 /* Fill sprom structure */ 95 /* Fill sprom structure */
92 memset(&(iv->sprom), 0, sizeof(struct ssb_sprom)); 96 memset(&(iv->sprom), 0, sizeof(struct ssb_sprom));
93 iv->sprom.revision = 3; 97 iv->sprom.revision = 3;
94 98
95 if (cfe_getenv("et0macaddr", buf, sizeof(buf)) >= 0) 99 if (cfe_getenv("et0macaddr", buf, sizeof(buf)) >= 0 ||
100 nvram_getenv("et0macaddr", buf, sizeof(buf)) >= 0)
96 str2eaddr(buf, iv->sprom.et0mac); 101 str2eaddr(buf, iv->sprom.et0mac);
97 if (cfe_getenv("et1macaddr", buf, sizeof(buf)) >= 0) 102
103 if (cfe_getenv("et1macaddr", buf, sizeof(buf)) >= 0 ||
104 nvram_getenv("et1macaddr", buf, sizeof(buf)) >= 0)
98 str2eaddr(buf, iv->sprom.et1mac); 105 str2eaddr(buf, iv->sprom.et1mac);
99 if (cfe_getenv("et0phyaddr", buf, sizeof(buf)) >= 0) 106
100 iv->sprom.et0phyaddr = simple_strtoul(buf, NULL, 10); 107 if (cfe_getenv("et0phyaddr", buf, sizeof(buf)) >= 0 ||
101 if (cfe_getenv("et1phyaddr", buf, sizeof(buf)) >= 0) 108 nvram_getenv("et0phyaddr", buf, sizeof(buf)) >= 0)
102 iv->sprom.et1phyaddr = simple_strtoul(buf, NULL, 10); 109 iv->sprom.et0phyaddr = simple_strtoul(buf, NULL, 0);
103 if (cfe_getenv("et0mdcport", buf, sizeof(buf)) >= 0) 110
111 if (cfe_getenv("et1phyaddr", buf, sizeof(buf)) >= 0 ||
112 nvram_getenv("et1phyaddr", buf, sizeof(buf)) >= 0)
113 iv->sprom.et1phyaddr = simple_strtoul(buf, NULL, 0);
114
115 if (cfe_getenv("et0mdcport", buf, sizeof(buf)) >= 0 ||
116 nvram_getenv("et0mdcport", buf, sizeof(buf)) >= 0)
104 iv->sprom.et0mdcport = simple_strtoul(buf, NULL, 10); 117 iv->sprom.et0mdcport = simple_strtoul(buf, NULL, 10);
105 if (cfe_getenv("et1mdcport", buf, sizeof(buf)) >= 0) 118
119 if (cfe_getenv("et1mdcport", buf, sizeof(buf)) >= 0 ||
120 nvram_getenv("et1mdcport", buf, sizeof(buf)) >= 0)
106 iv->sprom.et1mdcport = simple_strtoul(buf, NULL, 10); 121 iv->sprom.et1mdcport = simple_strtoul(buf, NULL, 10);
107 122
108 return 0; 123 return 0;