brcm47xx: add initial support for kernel 3.9
[openwrt.git] / target / linux / brcm47xx / patches-3.6 / 080-MIPS-BCM47XX-rewrite-nvram-probing.patch
1 --- a/arch/mips/bcm47xx/nvram.c
2 +++ b/arch/mips/bcm47xx/nvram.c
3 @@ -3,7 +3,7 @@
4   *
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>
9   *
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
12 @@ -18,83 +18,168 @@
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>
19  
20  static char nvram_buf[NVRAM_SPACE];
21  
22 +static u32 find_nvram_size(u32 end)
23 +{
24 +       struct nvram_header *header;
25 +       u32 nvram_sizes[] = {0x8000, 0xF000, 0x10000};
26 +       int i;
27 +
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];
32 +       }
33 +
34 +       return 0;
35 +}
36 +
37  /* Probe for NVRAM header */
38 -static void early_nvram_init(void)
39 +static int nvram_find_and_copy(u32 base, u32 lim)
40  {
41 -#ifdef CONFIG_BCM47XX_SSB
42 -       struct ssb_mipscore *mcore_ssb;
43 -#endif
44 -#ifdef CONFIG_BCM47XX_BCMA
45 -       struct bcma_drv_cc *bcma_cc;
46 -#endif
47         struct nvram_header *header;
48         int i;
49 -       u32 base = 0;
50 -       u32 lim = 0;
51         u32 off;
52         u32 *src, *dst;
53 +       u32 size;
54  
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;
61 -               break;
62 -#endif
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;
68 -               break;
69 -#endif
70 -       }
71 -
72 +       /* TODO: when nvram is on nand flash check for bad blocks first. */
73         off = FLASH_MIN;
74         while (off <= lim) {
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);
80 +               if (size) {
81 +                       header = (struct nvram_header *)KSEG1ADDR(base + off -
82 +                                                                 size);
83                         goto found;
84 +               }
85                 off <<= 1;
86         }
87  
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) {
92 +               size = NVRAM_SPACE;
93                 goto found;
94 +       }
95  
96         header = (struct nvram_header *) KSEG1ADDR(base + 1024);
97 -       if (header->magic == NVRAM_HEADER)
98 +       if (header->magic == NVRAM_HEADER) {
99 +               size = NVRAM_SPACE;
100                 goto found;
101 +       }
102  
103 -       return;
104 +       pr_err("no nvram found\n");
105 +       return -ENXIO;
106  
107  found:
108 +
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);
114 +
115         src = (u32 *) header;
116         dst = (u32 *) nvram_buf;
117         for (i = 0; i < sizeof(struct nvram_header); i += 4)
118                 *dst++ = *src++;
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);
123 +
124 +       return 0;
125 +}
126 +
127 +#ifdef CONFIG_BCM47XX_SSB
128 +static int nvram_init_ssb(void)
129 +{
130 +       struct ssb_mipscore *mcore = &bcm47xx_bus.ssb.mipscore;
131 +#ifdef CONFIG_SSB_SFLASH
132 +       struct ssb_chipcommon *chipco = &bcm47xx_bus.ssb.chipco;
133 +#endif
134 +       u32 base;
135 +       u32 lim;
136 +
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;
144 +#endif
145 +       } else {
146 +               pr_err("Couldn't find supported flash memory\n");
147 +               return -ENXIO;
148 +       }
149 +
150 +       return nvram_find_and_copy(base, lim);
151 +}
152 +#endif
153 +
154 +#ifdef CONFIG_BCM47XX_BCMA
155 +static int nvram_init_bcma(void)
156 +{
157 +       struct bcma_drv_cc *cc = &bcm47xx_bus.bcma.bus.drv_cc;
158 +       u32 base;
159 +       u32 lim;
160 +
161 +#ifdef CONFIG_BCMA_NFLASH
162 +       if (cc->nflash.boot) {
163 +               base = BCMA_SOC_FLASH1;
164 +               lim = BCMA_SOC_FLASH1_SZ;
165 +       } else
166 +#endif
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;
174 +#endif
175 +       } else {
176 +               pr_err("Couldn't find supported flash memory\n");
177 +               return -ENXIO;
178 +       }
179 +
180 +       return nvram_find_and_copy(base, lim);
181  }
182 +#endif
183  
184 -int nvram_getenv(char *name, char *val, size_t val_len)
185 +static int nvram_init(void)
186 +{
187 +       switch (bcm47xx_bus_type) {
188 +#ifdef CONFIG_BCM47XX_SSB
189 +       case BCM47XX_BUS_TYPE_SSB:
190 +               return nvram_init_ssb();
191 +#endif
192 +#ifdef CONFIG_BCM47XX_BCMA
193 +       case BCM47XX_BUS_TYPE_BCMA:
194 +               return nvram_init_bcma();
195 +#endif
196 +       }
197 +       return -ENXIO;
198 +}
199 +
200 +int bcm47xx_nvram_getenv(char *name, char *val, size_t val_len)
201  {
202         char *var, *value, *end, *eq;
203 +       int err;
204  
205         if (!name)
206 -               return NVRAM_ERR_INV_PARAM;
207 +               return -EINVAL;
208  
209 -       if (!nvram_buf[0])
210 -               early_nvram_init();
211 +       if (!nvram_buf[0]) {
212 +               err = nvram_init();
213 +               if (err)
214 +                       return err;
215 +       }
216  
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);
221                 }
222         }
223 -       return NVRAM_ERR_ENVNOTFOUND;
224 +       return -ENOENT;
225  }
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
230 @@ -35,7 +35,7 @@
231  #include <asm/reboot.h>
232  #include <asm/time.h>
233  #include <bcm47xx.h>
234 -#include <asm/mach-bcm47xx/nvram.h>
235 +#include <bcm47xx_nvram.h>
236  
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);
242  
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);
246  
247         return 0;
248 @@ -138,7 +138,7 @@ static void __init bcm47xx_register_ssb(
249                 panic("Failed to initialize SSB bus (err %d)", err);
250  
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;
256  
257 --- a/arch/mips/bcm47xx/sprom.c
258 +++ b/arch/mips/bcm47xx/sprom.c
259 @@ -27,7 +27,7 @@
260   */
261  
262  #include <bcm47xx.h>
263 -#include <nvram.h>
264 +#include <bcm47xx_nvram.h>
265  
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
269  
270         create_key(prefix, postfix, name, key, sizeof(key));
271  
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);
279         }
280         return err;
281  }
282 @@ -144,7 +144,7 @@ static void nvram_read_macaddr(const cha
283         if (err < 0)
284                 return;
285  
286 -       nvram_parse_macaddr(buf, *val);
287 +       bcm47xx_nvram_parse_macaddr(buf, *val);
288  }
289  
290  static void nvram_read_alpha2(const char *prefix, const char *name,
291 --- /dev/null
292 +++ b/arch/mips/include/asm/mach-bcm47xx/bcm47xx_nvram.h
293 @@ -0,0 +1,51 @@
294 +/*
295 + *  Copyright (C) 2005, Broadcom Corporation
296 + *  Copyright (C) 2006, Felix Fietkau <nbd@openwrt.org>
297 + *
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.
302 + */
303 +
304 +#ifndef __BCM47XX_NVRAM_H
305 +#define __BCM47XX_NVRAM_H
306 +
307 +#include <linux/types.h>
308 +#include <linux/kernel.h>
309 +
310 +struct nvram_header {
311 +       u32 magic;
312 +       u32 len;
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 */
316 +};
317 +
318 +#define NVRAM_HEADER           0x48534C46      /* 'FLSH' */
319 +#define NVRAM_VERSION          1
320 +#define NVRAM_HEADER_SIZE      20
321 +#define NVRAM_SPACE            0x8000
322 +
323 +#define FLASH_MIN              0x00020000      /* Minimum flash size */
324 +
325 +#define NVRAM_MAX_VALUE_LEN 255
326 +#define NVRAM_MAX_PARAM_LEN 64
327 +
328 +extern int bcm47xx_nvram_getenv(char *name, char *val, size_t val_len);
329 +
330 +static inline void bcm47xx_nvram_parse_macaddr(char *buf, u8 macaddr[6])
331 +{
332 +       if (strchr(buf, ':'))
333 +               sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &macaddr[0],
334 +                       &macaddr[1], &macaddr[2], &macaddr[3], &macaddr[4],
335 +                       &macaddr[5]);
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],
339 +                       &macaddr[5]);
340 +       else
341 +               printk(KERN_WARNING "Can not parse mac address: %s\n", buf);
342 +}
343 +
344 +#endif /* __BCM47XX_NVRAM_H */
345 --- a/arch/mips/include/asm/mach-bcm47xx/nvram.h
346 +++ /dev/null
347 @@ -1,54 +0,0 @@
348 -/*
349 - *  Copyright (C) 2005, Broadcom Corporation
350 - *  Copyright (C) 2006, Felix Fietkau <nbd@openwrt.org>
351 - *
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.
356 - */
357 -
358 -#ifndef __NVRAM_H
359 -#define __NVRAM_H
360 -
361 -#include <linux/types.h>
362 -#include <linux/kernel.h>
363 -
364 -struct nvram_header {
365 -       u32 magic;
366 -       u32 len;
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 */
370 -};
371 -
372 -#define NVRAM_HEADER           0x48534C46      /* 'FLSH' */
373 -#define NVRAM_VERSION          1
374 -#define NVRAM_HEADER_SIZE      20
375 -#define NVRAM_SPACE            0x8000
376 -
377 -#define FLASH_MIN              0x00020000      /* Minimum flash size */
378 -
379 -#define NVRAM_MAX_VALUE_LEN 255
380 -#define NVRAM_MAX_PARAM_LEN 64
381 -
382 -#define NVRAM_ERR_INV_PARAM    -8
383 -#define NVRAM_ERR_ENVNOTFOUND  -9
384 -
385 -extern int nvram_getenv(char *name, char *val, size_t val_len);
386 -
387 -static inline void nvram_parse_macaddr(char *buf, u8 macaddr[6])
388 -{
389 -       if (strchr(buf, ':'))
390 -               sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &macaddr[0],
391 -                       &macaddr[1], &macaddr[2], &macaddr[3], &macaddr[4],
392 -                       &macaddr[5]);
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],
396 -                       &macaddr[5]);
397 -       else
398 -               printk(KERN_WARNING "Can not parse mac address: %s\n", buf);
399 -}
400 -
401 -#endif
402 --- a/drivers/net/ethernet/broadcom/b44.c
403 +++ b/drivers/net/ethernet/broadcom/b44.c
404 @@ -381,7 +381,7 @@ static void b44_set_flow_ctrl(struct b44
405  }
406  
407  #ifdef CONFIG_BCM47XX
408 -#include <asm/mach-bcm47xx/nvram.h>
409 +#include <bcm47xx_nvram.h>
410  static void b44_wap54g10_workaround(struct b44 *bp)
411  {
412         char buf[20];
413 @@ -393,7 +393,7 @@ static void b44_wap54g10_workaround(stru
414          * see https://dev.openwrt.org/ticket/146
415          * check and reset bit "isolate"
416          */
417 -       if (nvram_getenv("boardnum", buf, sizeof(buf)) < 0)
418 +       if (bcm47xx_nvram_getenv("boardnum", buf, sizeof(buf)) < 0)
419                 return;
420         if (simple_strtoul(buf, NULL, 0) == 2) {
421                 err = __b44_readphy(bp, 0, MII_BMCR, &val);
422 --- a/drivers/ssb/driver_chipcommon_pmu.c
423 +++ b/drivers/ssb/driver_chipcommon_pmu.c
424 @@ -14,7 +14,7 @@
425  #include <linux/delay.h>
426  #include <linux/export.h>
427  #ifdef CONFIG_BCM47XX
428 -#include <asm/mach-bcm47xx/nvram.h>
429 +#include <bcm47xx_nvram.h>
430  #endif
431  
432  #include "ssb_private.h"
433 @@ -322,7 +322,7 @@ static void ssb_pmu_pll_init(struct ssb_
434         if (bus->bustype == SSB_BUSTYPE_SSB) {
435  #ifdef CONFIG_BCM47XX
436                 char buf[20];
437 -               if (nvram_getenv("xtalfreq", buf, sizeof(buf)) >= 0)
438 +               if (bcm47xx_nvram_getenv("xtalfreq", buf, sizeof(buf)) >= 0)
439                         crystalfreq = simple_strtoul(buf, NULL, 0);
440  #endif
441         }
442 --- a/include/linux/ssb/ssb_driver_gige.h
443 +++ b/include/linux/ssb/ssb_driver_gige.h
444 @@ -98,14 +98,14 @@ static inline bool ssb_gige_must_flush_p
445  }
446  
447  #ifdef CONFIG_BCM47XX
448 -#include <asm/mach-bcm47xx/nvram.h>
449 +#include <bcm47xx_nvram.h>
450  /* Get the device MAC address */
451  static inline void ssb_gige_get_macaddr(struct pci_dev *pdev, u8 *macaddr)
452  {
453         char buf[20];
454 -       if (nvram_getenv("et0macaddr", buf, sizeof(buf)) < 0)
455 +       if (bcm47xx_nvram_getenv("et0macaddr", buf, sizeof(buf)) < 0)
456                 return;
457 -       nvram_parse_macaddr(buf, macaddr);
458 +       bcm47xx_nvram_parse_macaddr(buf, macaddr);
459  }
460  #else
461  static inline void ssb_gige_get_macaddr(struct pci_dev *pdev, u8 *macaddr)