brcm47xx: various fixes and code cleanups for irq code
[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,166 @@
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 -int nvram_getenv(char *name, char *val, size_t val_len)
128 +#ifdef CONFIG_BCM47XX_SSB
129 +static int nvram_init_ssb(void)
130 +{
131 +       struct ssb_mipscore *mcore = &bcm47xx_bus.ssb.mipscore;
132 +       struct ssb_chipcommon *chipco = &bcm47xx_bus.ssb.chipco;
133 +       u32 base;
134 +       u32 lim;
135 +
136 +       if (mcore->pflash.present) {
137 +               base = mcore->pflash.window;
138 +               lim = mcore->pflash.window_size;
139 +#ifdef CONFIG_SSB_SFLASH
140 +       } else if (chipco->sflash.present) {
141 +               base = chipco->sflash.window;
142 +               lim = chipco->sflash.size;
143 +#endif
144 +       } else {
145 +               pr_err("Couldn't find supported flash memory\n");
146 +               return -ENXIO;
147 +       }
148 +
149 +       return nvram_find_and_copy(base, lim);
150 +}
151 +#endif
152 +
153 +#ifdef CONFIG_BCM47XX_BCMA
154 +static int nvram_init_bcma(void)
155 +{
156 +       struct bcma_drv_cc *cc = &bcm47xx_bus.bcma.bus.drv_cc;
157 +       u32 base;
158 +       u32 lim;
159 +
160 +#ifdef CONFIG_BCMA_NFLASH
161 +       if (cc->nflash.boot) {
162 +               base = BCMA_SOC_FLASH1;
163 +               lim = BCMA_SOC_FLASH1_SZ;
164 +       } else
165 +#endif
166 +       if (cc->pflash.present) {
167 +               base = cc->pflash.window;
168 +               lim = cc->pflash.window_size;
169 +#ifdef CONFIG_BCMA_SFLASH
170 +       } else if (cc->sflash.present) {
171 +               base = cc->sflash.window;
172 +               lim = cc->sflash.size;
173 +#endif
174 +       } else {
175 +               pr_err("Couldn't find supported flash memory\n");
176 +               return -ENXIO;
177 +       }
178 +
179 +       return nvram_find_and_copy(base, lim);
180 +}
181 +#endif
182 +
183 +static int nvram_init(void)
184 +{
185 +       switch (bcm47xx_bus_type) {
186 +#ifdef CONFIG_BCM47XX_SSB
187 +       case BCM47XX_BUS_TYPE_SSB:
188 +               return nvram_init_ssb();
189 +#endif
190 +#ifdef CONFIG_BCM47XX_BCMA
191 +       case BCM47XX_BUS_TYPE_BCMA:
192 +               return nvram_init_bcma();
193 +#endif
194 +       }
195 +       return -ENXIO;
196 +}
197 +
198 +int bcm47xx_nvram_getenv(char *name, char *val, size_t val_len)
199  {
200         char *var, *value, *end, *eq;
201 +       int err;
202  
203         if (!name)
204 -               return NVRAM_ERR_INV_PARAM;
205 +               return -EINVAL;
206  
207 -       if (!nvram_buf[0])
208 -               early_nvram_init();
209 +       if (!nvram_buf[0]) {
210 +               err = nvram_init();
211 +               if (err)
212 +                       return err;
213 +       }
214  
215         /* Look for name=value and return value */
216         var = &nvram_buf[sizeof(struct nvram_header)];
217 @@ -110,6 +193,6 @@ int nvram_getenv(char *name, char *val,
218                         return snprintf(val, val_len, "%s", value);
219                 }
220         }
221 -       return NVRAM_ERR_ENVNOTFOUND;
222 +       return -ENOENT;
223  }
224 -EXPORT_SYMBOL(nvram_getenv);
225 +EXPORT_SYMBOL(bcm47xx_nvram_getenv);
226 --- a/arch/mips/bcm47xx/setup.c
227 +++ b/arch/mips/bcm47xx/setup.c
228 @@ -35,7 +35,7 @@
229  #include <asm/reboot.h>
230  #include <asm/time.h>
231  #include <bcm47xx.h>
232 -#include <asm/mach-bcm47xx/nvram.h>
233 +#include <bcm47xx_nvram.h>
234  
235  union bcm47xx_bus bcm47xx_bus;
236  EXPORT_SYMBOL(bcm47xx_bus);
237 @@ -115,7 +115,7 @@ static int bcm47xx_get_invariants(struct
238         memset(&iv->sprom, 0, sizeof(struct ssb_sprom));
239         bcm47xx_fill_sprom(&iv->sprom, NULL, false);
240  
241 -       if (nvram_getenv("cardbus", buf, sizeof(buf)) >= 0)
242 +       if (bcm47xx_nvram_getenv("cardbus", buf, sizeof(buf)) >= 0)
243                 iv->has_cardbus_slot = !!simple_strtoul(buf, NULL, 10);
244  
245         return 0;
246 @@ -138,7 +138,7 @@ static void __init bcm47xx_register_ssb(
247                 panic("Failed to initialize SSB bus (err %d)", err);
248  
249         mcore = &bcm47xx_bus.ssb.mipscore;
250 -       if (nvram_getenv("kernel_args", buf, sizeof(buf)) >= 0) {
251 +       if (bcm47xx_nvram_getenv("kernel_args", buf, sizeof(buf)) >= 0) {
252                 if (strstr(buf, "console=ttyS1")) {
253                         struct ssb_serial_port port;
254  
255 --- a/arch/mips/bcm47xx/sprom.c
256 +++ b/arch/mips/bcm47xx/sprom.c
257 @@ -27,7 +27,7 @@
258   */
259  
260  #include <bcm47xx.h>
261 -#include <nvram.h>
262 +#include <bcm47xx_nvram.h>
263  
264  static void create_key(const char *prefix, const char *postfix,
265                        const char *name, char *buf, int len)
266 @@ -50,10 +50,10 @@ static int get_nvram_var(const char *pre
267  
268         create_key(prefix, postfix, name, key, sizeof(key));
269  
270 -       err = nvram_getenv(key, buf, len);
271 -       if (fallback && err == NVRAM_ERR_ENVNOTFOUND && prefix) {
272 +       err = bcm47xx_nvram_getenv(key, buf, len);
273 +       if (fallback && err == -ENOENT && prefix) {
274                 create_key(NULL, postfix, name, key, sizeof(key));
275 -               err = nvram_getenv(key, buf, len);
276 +               err = bcm47xx_nvram_getenv(key, buf, len);
277         }
278         return err;
279  }
280 @@ -144,7 +144,7 @@ static void nvram_read_macaddr(const cha
281         if (err < 0)
282                 return;
283  
284 -       nvram_parse_macaddr(buf, *val);
285 +       bcm47xx_nvram_parse_macaddr(buf, *val);
286  }
287  
288  static void nvram_read_alpha2(const char *prefix, const char *name,
289 --- /dev/null
290 +++ b/arch/mips/include/asm/mach-bcm47xx/bcm47xx_nvram.h
291 @@ -0,0 +1,51 @@
292 +/*
293 + *  Copyright (C) 2005, Broadcom Corporation
294 + *  Copyright (C) 2006, Felix Fietkau <nbd@openwrt.org>
295 + *
296 + *  This program is free software; you can redistribute  it and/or modify it
297 + *  under  the terms of  the GNU General  Public License as published by the
298 + *  Free Software Foundation;  either version 2 of the  License, or (at your
299 + *  option) any later version.
300 + */
301 +
302 +#ifndef __BCM47XX_NVRAM_H
303 +#define __BCM47XX_NVRAM_H
304 +
305 +#include <linux/types.h>
306 +#include <linux/kernel.h>
307 +
308 +struct nvram_header {
309 +       u32 magic;
310 +       u32 len;
311 +       u32 crc_ver_init;       /* 0:7 crc, 8:15 ver, 16:31 sdram_init */
312 +       u32 config_refresh;     /* 0:15 sdram_config, 16:31 sdram_refresh */
313 +       u32 config_ncdl;        /* ncdl values for memc */
314 +};
315 +
316 +#define NVRAM_HEADER           0x48534C46      /* 'FLSH' */
317 +#define NVRAM_VERSION          1
318 +#define NVRAM_HEADER_SIZE      20
319 +#define NVRAM_SPACE            0x8000
320 +
321 +#define FLASH_MIN              0x00020000      /* Minimum flash size */
322 +
323 +#define NVRAM_MAX_VALUE_LEN 255
324 +#define NVRAM_MAX_PARAM_LEN 64
325 +
326 +extern int bcm47xx_nvram_getenv(char *name, char *val, size_t val_len);
327 +
328 +static inline void bcm47xx_nvram_parse_macaddr(char *buf, u8 macaddr[6])
329 +{
330 +       if (strchr(buf, ':'))
331 +               sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &macaddr[0],
332 +                       &macaddr[1], &macaddr[2], &macaddr[3], &macaddr[4],
333 +                       &macaddr[5]);
334 +       else if (strchr(buf, '-'))
335 +               sscanf(buf, "%hhx-%hhx-%hhx-%hhx-%hhx-%hhx", &macaddr[0],
336 +                       &macaddr[1], &macaddr[2], &macaddr[3], &macaddr[4],
337 +                       &macaddr[5]);
338 +       else
339 +               printk(KERN_WARNING "Can not parse mac address: %s\n", buf);
340 +}
341 +
342 +#endif /* __BCM47XX_NVRAM_H */
343 --- a/arch/mips/include/asm/mach-bcm47xx/nvram.h
344 +++ /dev/null
345 @@ -1,54 +0,0 @@
346 -/*
347 - *  Copyright (C) 2005, Broadcom Corporation
348 - *  Copyright (C) 2006, Felix Fietkau <nbd@openwrt.org>
349 - *
350 - *  This program is free software; you can redistribute  it and/or modify it
351 - *  under  the terms of  the GNU General  Public License as published by the
352 - *  Free Software Foundation;  either version 2 of the  License, or (at your
353 - *  option) any later version.
354 - */
355 -
356 -#ifndef __NVRAM_H
357 -#define __NVRAM_H
358 -
359 -#include <linux/types.h>
360 -#include <linux/kernel.h>
361 -
362 -struct nvram_header {
363 -       u32 magic;
364 -       u32 len;
365 -       u32 crc_ver_init;       /* 0:7 crc, 8:15 ver, 16:31 sdram_init */
366 -       u32 config_refresh;     /* 0:15 sdram_config, 16:31 sdram_refresh */
367 -       u32 config_ncdl;        /* ncdl values for memc */
368 -};
369 -
370 -#define NVRAM_HEADER           0x48534C46      /* 'FLSH' */
371 -#define NVRAM_VERSION          1
372 -#define NVRAM_HEADER_SIZE      20
373 -#define NVRAM_SPACE            0x8000
374 -
375 -#define FLASH_MIN              0x00020000      /* Minimum flash size */
376 -
377 -#define NVRAM_MAX_VALUE_LEN 255
378 -#define NVRAM_MAX_PARAM_LEN 64
379 -
380 -#define NVRAM_ERR_INV_PARAM    -8
381 -#define NVRAM_ERR_ENVNOTFOUND  -9
382 -
383 -extern int nvram_getenv(char *name, char *val, size_t val_len);
384 -
385 -static inline void nvram_parse_macaddr(char *buf, u8 macaddr[6])
386 -{
387 -       if (strchr(buf, ':'))
388 -               sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &macaddr[0],
389 -                       &macaddr[1], &macaddr[2], &macaddr[3], &macaddr[4],
390 -                       &macaddr[5]);
391 -       else if (strchr(buf, '-'))
392 -               sscanf(buf, "%hhx-%hhx-%hhx-%hhx-%hhx-%hhx", &macaddr[0],
393 -                       &macaddr[1], &macaddr[2], &macaddr[3], &macaddr[4],
394 -                       &macaddr[5]);
395 -       else
396 -               printk(KERN_WARNING "Can not parse mac address: %s\n", buf);
397 -}
398 -
399 -#endif
400 --- a/drivers/net/ethernet/broadcom/b44.c
401 +++ b/drivers/net/ethernet/broadcom/b44.c
402 @@ -381,7 +381,7 @@ static void b44_set_flow_ctrl(struct b44
403  }
404  
405  #ifdef CONFIG_BCM47XX
406 -#include <asm/mach-bcm47xx/nvram.h>
407 +#include <bcm47xx_nvram.h>
408  static void b44_wap54g10_workaround(struct b44 *bp)
409  {
410         char buf[20];
411 @@ -393,7 +393,7 @@ static void b44_wap54g10_workaround(stru
412          * see https://dev.openwrt.org/ticket/146
413          * check and reset bit "isolate"
414          */
415 -       if (nvram_getenv("boardnum", buf, sizeof(buf)) < 0)
416 +       if (bcm47xx_nvram_getenv("boardnum", buf, sizeof(buf)) < 0)
417                 return;
418         if (simple_strtoul(buf, NULL, 0) == 2) {
419                 err = __b44_readphy(bp, 0, MII_BMCR, &val);
420 --- a/drivers/ssb/driver_chipcommon_pmu.c
421 +++ b/drivers/ssb/driver_chipcommon_pmu.c
422 @@ -14,7 +14,7 @@
423  #include <linux/delay.h>
424  #include <linux/export.h>
425  #ifdef CONFIG_BCM47XX
426 -#include <asm/mach-bcm47xx/nvram.h>
427 +#include <bcm47xx_nvram.h>
428  #endif
429  
430  #include "ssb_private.h"
431 @@ -322,7 +322,7 @@ static void ssb_pmu_pll_init(struct ssb_
432         if (bus->bustype == SSB_BUSTYPE_SSB) {
433  #ifdef CONFIG_BCM47XX
434                 char buf[20];
435 -               if (nvram_getenv("xtalfreq", buf, sizeof(buf)) >= 0)
436 +               if (bcm47xx_nvram_getenv("xtalfreq", buf, sizeof(buf)) >= 0)
437                         crystalfreq = simple_strtoul(buf, NULL, 0);
438  #endif
439         }
440 --- a/include/linux/ssb/ssb_driver_gige.h
441 +++ b/include/linux/ssb/ssb_driver_gige.h
442 @@ -98,14 +98,14 @@ static inline bool ssb_gige_must_flush_p
443  }
444  
445  #ifdef CONFIG_BCM47XX
446 -#include <asm/mach-bcm47xx/nvram.h>
447 +#include <bcm47xx_nvram.h>
448  /* Get the device MAC address */
449  static inline void ssb_gige_get_macaddr(struct pci_dev *pdev, u8 *macaddr)
450  {
451         char buf[20];
452 -       if (nvram_getenv("et0macaddr", buf, sizeof(buf)) < 0)
453 +       if (bcm47xx_nvram_getenv("et0macaddr", buf, sizeof(buf)) < 0)
454                 return;
455 -       nvram_parse_macaddr(buf, macaddr);
456 +       bcm47xx_nvram_parse_macaddr(buf, macaddr);
457  }
458  #else
459  static inline void ssb_gige_get_macaddr(struct pci_dev *pdev, u8 *macaddr)