1 --- a/arch/mips/bcm47xx/nvram.c
2 +++ b/arch/mips/bcm47xx/nvram.c
5 * Copyright (C) 2005 Broadcom Corporation
6 * Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>
7 - * Copyright (C) 2010-2011 Hauke Mehrtens <hauke@hauke-m.de>
8 + * Copyright (C) 2010-2012 Hauke Mehrtens <hauke@hauke-m.de>
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the
13 #include <linux/kernel.h>
14 #include <linux/string.h>
15 #include <asm/addrspace.h>
16 -#include <asm/mach-bcm47xx/nvram.h>
17 +#include <bcm47xx_nvram.h>
18 #include <asm/mach-bcm47xx/bcm47xx.h>
20 static char nvram_buf[NVRAM_SPACE];
22 +static u32 find_nvram_size(u32 end)
24 + struct nvram_header *header;
25 + u32 nvram_sizes[] = {0x8000, 0xF000, 0x10000};
28 + for (i = 0; i < ARRAY_SIZE(nvram_sizes); i++) {
29 + header = (struct nvram_header *)KSEG1ADDR(end - nvram_sizes[i]);
30 + if (header->magic == NVRAM_HEADER)
31 + return nvram_sizes[i];
37 /* Probe for NVRAM header */
38 -static void early_nvram_init(void)
39 +static int nvram_find_and_copy(u32 base, u32 lim)
41 -#ifdef CONFIG_BCM47XX_SSB
42 - struct ssb_mipscore *mcore_ssb;
44 -#ifdef CONFIG_BCM47XX_BCMA
45 - struct bcma_drv_cc *bcma_cc;
47 struct nvram_header *header;
55 - switch (bcm47xx_bus_type) {
56 -#ifdef CONFIG_BCM47XX_SSB
57 - case BCM47XX_BUS_TYPE_SSB:
58 - mcore_ssb = &bcm47xx_bus.ssb.mipscore;
59 - base = mcore_ssb->pflash.window;
60 - lim = mcore_ssb->pflash.window_size;
63 -#ifdef CONFIG_BCM47XX_BCMA
64 - case BCM47XX_BUS_TYPE_BCMA:
65 - bcma_cc = &bcm47xx_bus.bcma.bus.drv_cc;
66 - base = bcma_cc->pflash.window;
67 - lim = bcma_cc->pflash.window_size;
72 + /* TODO: when nvram is on nand flash check for bad blocks first. */
75 /* Windowed flash access */
76 - header = (struct nvram_header *)
77 - KSEG1ADDR(base + off - NVRAM_SPACE);
78 - if (header->magic == NVRAM_HEADER)
79 + size = find_nvram_size(base + off);
81 + header = (struct nvram_header *)KSEG1ADDR(base + off -
88 /* Try embedded NVRAM at 4 KB and 1 KB as last resorts */
89 header = (struct nvram_header *) KSEG1ADDR(base + 4096);
90 - if (header->magic == NVRAM_HEADER)
91 + if (header->magic == NVRAM_HEADER) {
96 header = (struct nvram_header *) KSEG1ADDR(base + 1024);
97 - if (header->magic == NVRAM_HEADER)
98 + if (header->magic == NVRAM_HEADER) {
104 + pr_err("no nvram found\n");
109 + if (header->len > size)
110 + pr_err("The nvram size accoridng to the header seems to be bigger than the partition on flash\n");
111 + if (header->len > NVRAM_SPACE)
112 + pr_err("nvram on flash (%i bytes) is bigger than the reserved space in memory, will just copy the first %i bytes\n",
113 + header->len, NVRAM_SPACE);
115 src = (u32 *) header;
116 dst = (u32 *) nvram_buf;
117 for (i = 0; i < sizeof(struct nvram_header); i += 4)
119 - for (; i < header->len && i < NVRAM_SPACE; i += 4)
120 + for (; i < header->len && i < NVRAM_SPACE && i < size; i += 4)
121 *dst++ = le32_to_cpu(*src++);
122 + memset(dst, 0x0, NVRAM_SPACE - i);
127 +#ifdef CONFIG_BCM47XX_SSB
128 +static int nvram_init_ssb(void)
130 + struct ssb_mipscore *mcore = &bcm47xx_bus.ssb.mipscore;
131 +#ifdef CONFIG_SSB_SFLASH
132 + struct ssb_chipcommon *chipco = &bcm47xx_bus.ssb.chipco;
137 + if (mcore->pflash.present) {
138 + base = mcore->pflash.window;
139 + lim = mcore->pflash.window_size;
140 +#ifdef CONFIG_SSB_SFLASH
141 + } else if (chipco->sflash.present) {
142 + base = chipco->sflash.window;
143 + lim = chipco->sflash.size;
146 + pr_err("Couldn't find supported flash memory\n");
150 + return nvram_find_and_copy(base, lim);
154 +#ifdef CONFIG_BCM47XX_BCMA
155 +static int nvram_init_bcma(void)
157 + struct bcma_drv_cc *cc = &bcm47xx_bus.bcma.bus.drv_cc;
161 +#ifdef CONFIG_BCMA_NFLASH
162 + if (cc->nflash.boot) {
163 + base = BCMA_SOC_FLASH1;
164 + lim = BCMA_SOC_FLASH1_SZ;
167 + if (cc->pflash.present) {
168 + base = cc->pflash.window;
169 + lim = cc->pflash.window_size;
170 +#ifdef CONFIG_BCMA_SFLASH
171 + } else if (cc->sflash.present) {
172 + base = cc->sflash.window;
173 + lim = cc->sflash.size;
176 + pr_err("Couldn't find supported flash memory\n");
180 + return nvram_find_and_copy(base, lim);
184 -int nvram_getenv(char *name, char *val, size_t val_len)
185 +static int nvram_init(void)
187 + switch (bcm47xx_bus_type) {
188 +#ifdef CONFIG_BCM47XX_SSB
189 + case BCM47XX_BUS_TYPE_SSB:
190 + return nvram_init_ssb();
192 +#ifdef CONFIG_BCM47XX_BCMA
193 + case BCM47XX_BUS_TYPE_BCMA:
194 + return nvram_init_bcma();
200 +int bcm47xx_nvram_getenv(char *name, char *val, size_t val_len)
202 char *var, *value, *end, *eq;
206 - return NVRAM_ERR_INV_PARAM;
210 - early_nvram_init();
211 + if (!nvram_buf[0]) {
212 + err = nvram_init();
217 /* Look for name=value and return value */
218 var = &nvram_buf[sizeof(struct nvram_header)];
219 @@ -110,6 +195,6 @@ int nvram_getenv(char *name, char *val,
220 return snprintf(val, val_len, "%s", value);
223 - return NVRAM_ERR_ENVNOTFOUND;
226 -EXPORT_SYMBOL(nvram_getenv);
227 +EXPORT_SYMBOL(bcm47xx_nvram_getenv);
228 --- a/arch/mips/bcm47xx/setup.c
229 +++ b/arch/mips/bcm47xx/setup.c
231 #include <asm/reboot.h>
232 #include <asm/time.h>
234 -#include <asm/mach-bcm47xx/nvram.h>
235 +#include <bcm47xx_nvram.h>
237 union bcm47xx_bus bcm47xx_bus;
238 EXPORT_SYMBOL(bcm47xx_bus);
239 @@ -115,7 +115,7 @@ static int bcm47xx_get_invariants(struct
240 memset(&iv->sprom, 0, sizeof(struct ssb_sprom));
241 bcm47xx_fill_sprom(&iv->sprom, NULL, false);
243 - if (nvram_getenv("cardbus", buf, sizeof(buf)) >= 0)
244 + if (bcm47xx_nvram_getenv("cardbus", buf, sizeof(buf)) >= 0)
245 iv->has_cardbus_slot = !!simple_strtoul(buf, NULL, 10);
248 @@ -138,7 +138,7 @@ static void __init bcm47xx_register_ssb(
249 panic("Failed to initialize SSB bus (err %d)", err);
251 mcore = &bcm47xx_bus.ssb.mipscore;
252 - if (nvram_getenv("kernel_args", buf, sizeof(buf)) >= 0) {
253 + if (bcm47xx_nvram_getenv("kernel_args", buf, sizeof(buf)) >= 0) {
254 if (strstr(buf, "console=ttyS1")) {
255 struct ssb_serial_port port;
257 --- a/arch/mips/bcm47xx/sprom.c
258 +++ b/arch/mips/bcm47xx/sprom.c
264 +#include <bcm47xx_nvram.h>
266 static void create_key(const char *prefix, const char *postfix,
267 const char *name, char *buf, int len)
268 @@ -50,10 +50,10 @@ static int get_nvram_var(const char *pre
270 create_key(prefix, postfix, name, key, sizeof(key));
272 - err = nvram_getenv(key, buf, len);
273 - if (fallback && err == NVRAM_ERR_ENVNOTFOUND && prefix) {
274 + err = bcm47xx_nvram_getenv(key, buf, len);
275 + if (fallback && err == -ENOENT && prefix) {
276 create_key(NULL, postfix, name, key, sizeof(key));
277 - err = nvram_getenv(key, buf, len);
278 + err = bcm47xx_nvram_getenv(key, buf, len);
282 @@ -144,7 +144,7 @@ static void nvram_read_macaddr(const cha
286 - nvram_parse_macaddr(buf, *val);
287 + bcm47xx_nvram_parse_macaddr(buf, *val);
290 static void nvram_read_alpha2(const char *prefix, const char *name,
292 +++ b/arch/mips/include/asm/mach-bcm47xx/bcm47xx_nvram.h
295 + * Copyright (C) 2005, Broadcom Corporation
296 + * Copyright (C) 2006, Felix Fietkau <nbd@openwrt.org>
298 + * This program is free software; you can redistribute it and/or modify it
299 + * under the terms of the GNU General Public License as published by the
300 + * Free Software Foundation; either version 2 of the License, or (at your
301 + * option) any later version.
304 +#ifndef __BCM47XX_NVRAM_H
305 +#define __BCM47XX_NVRAM_H
307 +#include <linux/types.h>
308 +#include <linux/kernel.h>
310 +struct nvram_header {
313 + u32 crc_ver_init; /* 0:7 crc, 8:15 ver, 16:31 sdram_init */
314 + u32 config_refresh; /* 0:15 sdram_config, 16:31 sdram_refresh */
315 + u32 config_ncdl; /* ncdl values for memc */
318 +#define NVRAM_HEADER 0x48534C46 /* 'FLSH' */
319 +#define NVRAM_VERSION 1
320 +#define NVRAM_HEADER_SIZE 20
321 +#define NVRAM_SPACE 0x8000
323 +#define FLASH_MIN 0x00020000 /* Minimum flash size */
325 +#define NVRAM_MAX_VALUE_LEN 255
326 +#define NVRAM_MAX_PARAM_LEN 64
328 +extern int bcm47xx_nvram_getenv(char *name, char *val, size_t val_len);
330 +static inline void bcm47xx_nvram_parse_macaddr(char *buf, u8 macaddr[6])
332 + if (strchr(buf, ':'))
333 + sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &macaddr[0],
334 + &macaddr[1], &macaddr[2], &macaddr[3], &macaddr[4],
336 + else if (strchr(buf, '-'))
337 + sscanf(buf, "%hhx-%hhx-%hhx-%hhx-%hhx-%hhx", &macaddr[0],
338 + &macaddr[1], &macaddr[2], &macaddr[3], &macaddr[4],
341 + printk(KERN_WARNING "Can not parse mac address: %s\n", buf);
344 +#endif /* __BCM47XX_NVRAM_H */
345 --- a/arch/mips/include/asm/mach-bcm47xx/nvram.h
349 - * Copyright (C) 2005, Broadcom Corporation
350 - * Copyright (C) 2006, Felix Fietkau <nbd@openwrt.org>
352 - * This program is free software; you can redistribute it and/or modify it
353 - * under the terms of the GNU General Public License as published by the
354 - * Free Software Foundation; either version 2 of the License, or (at your
355 - * option) any later version.
361 -#include <linux/types.h>
362 -#include <linux/kernel.h>
364 -struct nvram_header {
367 - u32 crc_ver_init; /* 0:7 crc, 8:15 ver, 16:31 sdram_init */
368 - u32 config_refresh; /* 0:15 sdram_config, 16:31 sdram_refresh */
369 - u32 config_ncdl; /* ncdl values for memc */
372 -#define NVRAM_HEADER 0x48534C46 /* 'FLSH' */
373 -#define NVRAM_VERSION 1
374 -#define NVRAM_HEADER_SIZE 20
375 -#define NVRAM_SPACE 0x8000
377 -#define FLASH_MIN 0x00020000 /* Minimum flash size */
379 -#define NVRAM_MAX_VALUE_LEN 255
380 -#define NVRAM_MAX_PARAM_LEN 64
382 -#define NVRAM_ERR_INV_PARAM -8
383 -#define NVRAM_ERR_ENVNOTFOUND -9
385 -extern int nvram_getenv(char *name, char *val, size_t val_len);
387 -static inline void nvram_parse_macaddr(char *buf, u8 macaddr[6])
389 - if (strchr(buf, ':'))
390 - sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &macaddr[0],
391 - &macaddr[1], &macaddr[2], &macaddr[3], &macaddr[4],
393 - else if (strchr(buf, '-'))
394 - sscanf(buf, "%hhx-%hhx-%hhx-%hhx-%hhx-%hhx", &macaddr[0],
395 - &macaddr[1], &macaddr[2], &macaddr[3], &macaddr[4],
398 - printk(KERN_WARNING "Can not parse mac address: %s\n", buf);
402 --- a/drivers/mtd/bcm47xxpart.c
403 +++ b/drivers/mtd/bcm47xxpart.c
405 #include <linux/slab.h>
406 #include <linux/mtd/mtd.h>
407 #include <linux/mtd/partitions.h>
408 -#include <asm/mach-bcm47xx/nvram.h>
409 +#include <bcm47xx_nvram.h>
411 /* 10 parts were found on sflash on Netgear WNDR4500 */
412 #define BCM47XXPART_MAX_PARTS 12
413 --- a/drivers/net/ethernet/broadcom/b44.c
414 +++ b/drivers/net/ethernet/broadcom/b44.c
415 @@ -381,7 +381,7 @@ static void b44_set_flow_ctrl(struct b44
418 #ifdef CONFIG_BCM47XX
419 -#include <asm/mach-bcm47xx/nvram.h>
420 +#include <bcm47xx_nvram.h>
421 static void b44_wap54g10_workaround(struct b44 *bp)
424 @@ -393,7 +393,7 @@ static void b44_wap54g10_workaround(stru
425 * see https://dev.openwrt.org/ticket/146
426 * check and reset bit "isolate"
428 - if (nvram_getenv("boardnum", buf, sizeof(buf)) < 0)
429 + if (bcm47xx_nvram_getenv("boardnum", buf, sizeof(buf)) < 0)
431 if (simple_strtoul(buf, NULL, 0) == 2) {
432 err = __b44_readphy(bp, 0, MII_BMCR, &val);
433 --- a/drivers/ssb/driver_chipcommon_pmu.c
434 +++ b/drivers/ssb/driver_chipcommon_pmu.c
436 #include <linux/delay.h>
437 #include <linux/export.h>
438 #ifdef CONFIG_BCM47XX
439 -#include <asm/mach-bcm47xx/nvram.h>
440 +#include <bcm47xx_nvram.h>
443 #include "ssb_private.h"
444 @@ -322,7 +322,7 @@ static void ssb_pmu_pll_init(struct ssb_
445 if (bus->bustype == SSB_BUSTYPE_SSB) {
446 #ifdef CONFIG_BCM47XX
448 - if (nvram_getenv("xtalfreq", buf, sizeof(buf)) >= 0)
449 + if (bcm47xx_nvram_getenv("xtalfreq", buf, sizeof(buf)) >= 0)
450 crystalfreq = simple_strtoul(buf, NULL, 0);
453 --- a/include/linux/ssb/ssb_driver_gige.h
454 +++ b/include/linux/ssb/ssb_driver_gige.h
455 @@ -98,14 +98,14 @@ static inline bool ssb_gige_must_flush_p
458 #ifdef CONFIG_BCM47XX
459 -#include <asm/mach-bcm47xx/nvram.h>
460 +#include <bcm47xx_nvram.h>
461 /* Get the device MAC address */
462 static inline void ssb_gige_get_macaddr(struct pci_dev *pdev, u8 *macaddr)
465 - if (nvram_getenv("et0macaddr", buf, sizeof(buf)) < 0)
466 + if (bcm47xx_nvram_getenv("et0macaddr", buf, sizeof(buf)) < 0)
468 - nvram_parse_macaddr(buf, macaddr);
469 + bcm47xx_nvram_parse_macaddr(buf, macaddr);
472 static inline void ssb_gige_get_macaddr(struct pci_dev *pdev, u8 *macaddr)