summaryrefslogtreecommitdiff
path: root/target/linux/brcm47xx/patches-3.3/029-bcm47xx-read-nvram-from-sflash.patch
blob: 1a994d9037bcafabeebd91760c1210714f636fb7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
--- a/arch/mips/bcm47xx/nvram.c
+++ b/arch/mips/bcm47xx/nvram.c
@@ -20,11 +20,12 @@
 #include <asm/addrspace.h>
 #include <asm/mach-bcm47xx/nvram.h>
 #include <asm/mach-bcm47xx/bcm47xx.h>
+#include <asm/mach-bcm47xx/bus.h>
 
 static char nvram_buf[NVRAM_SPACE];
 
 /* Probe for NVRAM header */
-static void early_nvram_init(void)
+static void early_nvram_init_pflash(void)
 {
 #ifdef CONFIG_BCM47XX_SSB
 	struct ssb_chipcommon *ssb_cc;
@@ -50,9 +51,6 @@ static void early_nvram_init(void)
 #ifdef CONFIG_BCM47XX_BCMA
 	case BCM47XX_BUS_TYPE_BCMA:
 		bcma_cc = &bcm47xx_bus.bcma.bus.drv_cc;
-		if (bcma_cc->flash_type != BCMA_PFLASH)
-			return;
-
 		base = bcma_cc->pflash.window;
 		lim = bcma_cc->pflash.window_size;
 		break;
@@ -86,7 +84,115 @@ found:
 	for (i = 0; i < sizeof(struct nvram_header); i += 4)
 		*dst++ = *src++;
 	for (; i < header->len && i < NVRAM_SPACE; i += 4)
-		*dst++ = le32_to_cpu(*src++);
+		*dst++ = *src++;
+}
+
+static int find_nvram_size(void)
+{
+	struct nvram_header header;
+	int nvram_sizes[] = {NVRAM_SPACE, 0xF000, 2 * NVRAM_SPACE};
+	int i;
+	int ret;
+
+	for (i = 0; i < sizeof(nvram_sizes); i++) {
+		ret = bcm47xx_sflash.read(&bcm47xx_sflash, bcm47xx_sflash.size - nvram_sizes[i], sizeof(header), (u8 *)&header);
+		if (ret != sizeof(header))
+			return ret;
+		if (header.magic == NVRAM_HEADER)
+			return nvram_sizes[i];
+	}
+	return -1;
+}
+
+static int early_nvram_init_sflash(void)
+{
+	u32 off;
+	int ret;
+	char *dst;
+	int len;
+	int size;
+
+	/* check if the struct is already initilized */
+	if (!bcm47xx_sflash.size)
+		return -1;
+
+	size = find_nvram_size();
+	if (size <= 0)
+		return size;
+
+	len = NVRAM_SPACE;
+	dst = nvram_buf;
+	off = bcm47xx_sflash.size;
+	if (size > len) {
+		printk(KERN_WARNING "nvram on flash is bigger than the reserved"
+		       " space in memory, will just copy the first %i bytes\n",
+		       len);
+	}
+	while (len) {
+		ret = bcm47xx_sflash.read(&bcm47xx_sflash, off - size, len, dst);
+		if (ret < 0)
+			return ret;
+		off += ret;
+		len -= ret;
+		dst += ret;
+	}
+	return 0;
+}
+
+#ifdef CONFIG_BCM47XX_SSB
+static void early_nvram_init_ssb(void)
+{
+	int err;
+
+	switch (bcm47xx_bus.ssb.chipco.flash_type) {
+	case SSB_PFLASH:
+		early_nvram_init_pflash();
+		break;
+	case SSB_SFLASH:
+		err = early_nvram_init_sflash();
+		if (err < 0)
+			printk(KERN_WARNING "can not read from flash: %i\n", err);
+		break;
+	default:
+		printk(KERN_WARNING "unknow flash type\n");
+	}
+}
+#endif
+
+#ifdef CONFIG_BCM47XX_BCMA
+static void early_nvram_init_bcma(void)
+{
+	int err;
+
+	switch (bcm47xx_bus.bcma.bus.drv_cc.flash_type) {
+	case BCMA_PFLASH:
+		early_nvram_init_pflash();
+		break;
+	case BCMA_SFLASH:
+		err = early_nvram_init_sflash();
+		if (err < 0)
+			printk(KERN_WARNING "can not read from flash: %i\n", err);
+		break;
+	default:
+		printk(KERN_WARNING "unknow flash type\n");
+	}
+}
+#endif
+
+static void early_nvram_init(void)
+{
+	switch (bcm47xx_bus_type) {
+#ifdef CONFIG_BCM47XX_SSB
+	case BCM47XX_BUS_TYPE_SSB:
+		early_nvram_init_ssb();
+		break;
+#endif
+#ifdef CONFIG_BCM47XX_BCMA
+	case BCM47XX_BUS_TYPE_BCMA:
+		early_nvram_init_bcma();
+		break;
+#endif
+	}
 }
 
 int nvram_getenv(char *name, char *val, size_t val_len)