aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/bcm47xx
diff options
context:
space:
mode:
authorHauke Mehrtens <hauke@hauke-m.de>2012-12-26 14:51:13 -0500
committerJohn Crispin <blogic@openwrt.org>2013-02-15 13:01:56 -0500
commitf36738ddfeea02867b393e7f34da0cec48bafc54 (patch)
tree58172c4d59d237b90929ee654d4bfcbbba08d046 /arch/mips/bcm47xx
parente58da16f716c0e7822e64a5d8a1f413041bc912e (diff)
MIPS: BCM47XX: handle different nvram sizes
The old code just worked for nvram with a size of 0x8000 bytes. This patch adds support for reading nvram from partitions of 0xF000 and 0x10000 bytes. There is just 32KB space for the nvram, but most devices do not use the full size and this code reads the first 32KB in that case and prints a warning. Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de> Patchwork: http://patchwork.linux-mips.org/patch/4743/ Signed-off-by: John Crispin <blogic@openwrt.org>
Diffstat (limited to 'arch/mips/bcm47xx')
-rw-r--r--arch/mips/bcm47xx/nvram.c46
1 files changed, 39 insertions, 7 deletions
diff --git a/arch/mips/bcm47xx/nvram.c b/arch/mips/bcm47xx/nvram.c
index 6cf3ef29d844..b4a47fcb4f64 100644
--- a/arch/mips/bcm47xx/nvram.c
+++ b/arch/mips/bcm47xx/nvram.c
@@ -3,7 +3,7 @@
3 * 3 *
4 * Copyright (C) 2005 Broadcom Corporation 4 * Copyright (C) 2005 Broadcom Corporation
5 * Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org> 5 * Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>
6 * Copyright (C) 2010-2011 Hauke Mehrtens <hauke@hauke-m.de> 6 * Copyright (C) 2010-2012 Hauke Mehrtens <hauke@hauke-m.de>
7 * 7 *
8 * This program is free software; you can redistribute it and/or modify it 8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the 9 * under the terms of the GNU General Public License as published by the
@@ -23,42 +23,74 @@
23 23
24static char nvram_buf[NVRAM_SPACE]; 24static char nvram_buf[NVRAM_SPACE];
25 25
26static u32 find_nvram_size(u32 end)
27{
28 struct nvram_header *header;
29 u32 nvram_sizes[] = {0x8000, 0xF000, 0x10000};
30 int i;
31
32 for (i = 0; i < ARRAY_SIZE(nvram_sizes); i++) {
33 header = (struct nvram_header *)KSEG1ADDR(end - nvram_sizes[i]);
34 if (header->magic == NVRAM_HEADER)
35 return nvram_sizes[i];
36 }
37
38 return 0;
39}
40
41/* Probe for NVRAM header */
26static int nvram_find_and_copy(u32 base, u32 lim) 42static int nvram_find_and_copy(u32 base, u32 lim)
27{ 43{
28 struct nvram_header *header; 44 struct nvram_header *header;
29 int i; 45 int i;
30 u32 off; 46 u32 off;
31 u32 *src, *dst; 47 u32 *src, *dst;
48 u32 size;
32 49
33 /* TODO: when nvram is on nand flash check for bad blocks first. */ 50 /* TODO: when nvram is on nand flash check for bad blocks first. */
34 off = FLASH_MIN; 51 off = FLASH_MIN;
35 while (off <= lim) { 52 while (off <= lim) {
36 /* Windowed flash access */ 53 /* Windowed flash access */
37 header = (struct nvram_header *) 54 size = find_nvram_size(base + off);
38 KSEG1ADDR(base + off - NVRAM_SPACE); 55 if (size) {
39 if (header->magic == NVRAM_HEADER) 56 header = (struct nvram_header *)KSEG1ADDR(base + off -
57 size);
40 goto found; 58 goto found;
59 }
41 off <<= 1; 60 off <<= 1;
42 } 61 }
43 62
44 /* Try embedded NVRAM at 4 KB and 1 KB as last resorts */ 63 /* Try embedded NVRAM at 4 KB and 1 KB as last resorts */
45 header = (struct nvram_header *) KSEG1ADDR(base + 4096); 64 header = (struct nvram_header *) KSEG1ADDR(base + 4096);
46 if (header->magic == NVRAM_HEADER) 65 if (header->magic == NVRAM_HEADER) {
66 size = NVRAM_SPACE;
47 goto found; 67 goto found;
68 }
48 69
49 header = (struct nvram_header *) KSEG1ADDR(base + 1024); 70 header = (struct nvram_header *) KSEG1ADDR(base + 1024);
50 if (header->magic == NVRAM_HEADER) 71 if (header->magic == NVRAM_HEADER) {
72 size = NVRAM_SPACE;
51 goto found; 73 goto found;
74 }
52 75
76 pr_err("no nvram found\n");
53 return -ENXIO; 77 return -ENXIO;
54 78
55found: 79found:
80
81 if (header->len > size)
82 pr_err("The nvram size accoridng to the header seems to be bigger than the partition on flash\n");
83 if (header->len > NVRAM_SPACE)
84 pr_err("nvram on flash (%i bytes) is bigger than the reserved space in memory, will just copy the first %i bytes\n",
85 header->len, NVRAM_SPACE);
86
56 src = (u32 *) header; 87 src = (u32 *) header;
57 dst = (u32 *) nvram_buf; 88 dst = (u32 *) nvram_buf;
58 for (i = 0; i < sizeof(struct nvram_header); i += 4) 89 for (i = 0; i < sizeof(struct nvram_header); i += 4)
59 *dst++ = *src++; 90 *dst++ = *src++;
60 for (; i < header->len && i < NVRAM_SPACE; i += 4) 91 for (; i < header->len && i < NVRAM_SPACE && i < size; i += 4)
61 *dst++ = le32_to_cpu(*src++); 92 *dst++ = le32_to_cpu(*src++);
93 memset(dst, 0x0, NVRAM_SPACE - i);
62 94
63 return 0; 95 return 0;
64} 96}