summaryrefslogtreecommitdiffstats
path: root/target/linux/brcm47xx/patches-3.3/029-bcm47xx-read-nvram-from-sflash.patch
blob: b3d13df39ff10ac762c0166724ac551a401161b9 (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
--- 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,110 @@ 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 early_nvram_init_sflash(void)
+{
+	struct nvram_header header;
+	u32 off;
+	int ret;
+	char *dst;
+	int len;
+
+	/* check if the struct is already initilized */
+	if (!bcm47xx_sflash.size)
+		return -1;
+
+	off = FLASH_MIN;
+	while (off <= bcm47xx_sflash.size) {
+		ret = bcm47xx_sflash.read(&bcm47xx_sflash, off - NVRAM_SPACE, sizeof(header), (u8 *)&header);
+		if (ret != sizeof(header))
+			return ret;
+		if (header.magic == NVRAM_HEADER)
+			goto found;
+		off <<= 1;
+	}
+
+	off = FLASH_MIN;
+	while (off <= bcm47xx_sflash.size) {
+		ret = bcm47xx_sflash.read(&bcm47xx_sflash, off - (2 * NVRAM_SPACE), sizeof(header), (u8 *)&header);
+		if (ret != sizeof(header))
+			return ret;
+		if (header.magic == NVRAM_HEADER)
+			goto found;
+		off <<= 1;
+	}
+	return -1;
+
+found:
+	len = NVRAM_SPACE;
+	dst = nvram_buf;
+	while (len) {
+		ret = bcm47xx_sflash.read(&bcm47xx_sflash, off - (2 * NVRAM_SPACE), 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)