brcm47xx: add initial support for kernel 3.8
[openwrt/svn-archive/archive.git] / target / linux / brcm47xx / patches-3.8 / 080-MIPS-BCM47XX-rewrite-nvram-probing.patch
diff --git a/target/linux/brcm47xx/patches-3.8/080-MIPS-BCM47XX-rewrite-nvram-probing.patch b/target/linux/brcm47xx/patches-3.8/080-MIPS-BCM47XX-rewrite-nvram-probing.patch
new file mode 100644 (file)
index 0000000..04c378f
--- /dev/null
@@ -0,0 +1,472 @@
+--- a/arch/mips/bcm47xx/nvram.c
++++ b/arch/mips/bcm47xx/nvram.c
+@@ -3,7 +3,7 @@
+  *
+  * Copyright (C) 2005 Broadcom Corporation
+  * Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>
+- * Copyright (C) 2010-2011 Hauke Mehrtens <hauke@hauke-m.de>
++ * Copyright (C) 2010-2012 Hauke Mehrtens <hauke@hauke-m.de>
+  *
+  * This program is free software; you can redistribute  it and/or modify it
+  * under  the terms of  the GNU General  Public License as published by the
+@@ -18,83 +18,168 @@
+ #include <linux/kernel.h>
+ #include <linux/string.h>
+ #include <asm/addrspace.h>
+-#include <asm/mach-bcm47xx/nvram.h>
++#include <bcm47xx_nvram.h>
+ #include <asm/mach-bcm47xx/bcm47xx.h>
+ static char nvram_buf[NVRAM_SPACE];
++static u32 find_nvram_size(u32 end)
++{
++      struct nvram_header *header;
++      u32 nvram_sizes[] = {0x8000, 0xF000, 0x10000};
++      int i;
++
++      for (i = 0; i < ARRAY_SIZE(nvram_sizes); i++) {
++              header = (struct nvram_header *)KSEG1ADDR(end - nvram_sizes[i]);
++              if (header->magic == NVRAM_HEADER)
++                      return nvram_sizes[i];
++      }
++
++      return 0;
++}
++
+ /* Probe for NVRAM header */
+-static void early_nvram_init(void)
++static int nvram_find_and_copy(u32 base, u32 lim)
+ {
+-#ifdef CONFIG_BCM47XX_SSB
+-      struct ssb_mipscore *mcore_ssb;
+-#endif
+-#ifdef CONFIG_BCM47XX_BCMA
+-      struct bcma_drv_cc *bcma_cc;
+-#endif
+       struct nvram_header *header;
+       int i;
+-      u32 base = 0;
+-      u32 lim = 0;
+       u32 off;
+       u32 *src, *dst;
++      u32 size;
+-      switch (bcm47xx_bus_type) {
+-#ifdef CONFIG_BCM47XX_SSB
+-      case BCM47XX_BUS_TYPE_SSB:
+-              mcore_ssb = &bcm47xx_bus.ssb.mipscore;
+-              base = mcore_ssb->pflash.window;
+-              lim = mcore_ssb->pflash.window_size;
+-              break;
+-#endif
+-#ifdef CONFIG_BCM47XX_BCMA
+-      case BCM47XX_BUS_TYPE_BCMA:
+-              bcma_cc = &bcm47xx_bus.bcma.bus.drv_cc;
+-              base = bcma_cc->pflash.window;
+-              lim = bcma_cc->pflash.window_size;
+-              break;
+-#endif
+-      }
+-
++      /* TODO: when nvram is on nand flash check for bad blocks first. */
+       off = FLASH_MIN;
+       while (off <= lim) {
+               /* Windowed flash access */
+-              header = (struct nvram_header *)
+-                      KSEG1ADDR(base + off - NVRAM_SPACE);
+-              if (header->magic == NVRAM_HEADER)
++              size = find_nvram_size(base + off);
++              if (size) {
++                      header = (struct nvram_header *)KSEG1ADDR(base + off -
++                                                                size);
+                       goto found;
++              }
+               off <<= 1;
+       }
+       /* Try embedded NVRAM at 4 KB and 1 KB as last resorts */
+       header = (struct nvram_header *) KSEG1ADDR(base + 4096);
+-      if (header->magic == NVRAM_HEADER)
++      if (header->magic == NVRAM_HEADER) {
++              size = NVRAM_SPACE;
+               goto found;
++      }
+       header = (struct nvram_header *) KSEG1ADDR(base + 1024);
+-      if (header->magic == NVRAM_HEADER)
++      if (header->magic == NVRAM_HEADER) {
++              size = NVRAM_SPACE;
+               goto found;
++      }
+-      return;
++      pr_err("no nvram found\n");
++      return -ENXIO;
+ found:
++
++      if (header->len > size)
++              pr_err("The nvram size accoridng to the header seems to be bigger than the partition on flash\n");
++      if (header->len > NVRAM_SPACE)
++              pr_err("nvram on flash (%i bytes) is bigger than the reserved space in memory, will just copy the first %i bytes\n",
++                     header->len, NVRAM_SPACE);
++
+       src = (u32 *) header;
+       dst = (u32 *) nvram_buf;
+       for (i = 0; i < sizeof(struct nvram_header); i += 4)
+               *dst++ = *src++;
+-      for (; i < header->len && i < NVRAM_SPACE; i += 4)
++      for (; i < header->len && i < NVRAM_SPACE && i < size; i += 4)
+               *dst++ = le32_to_cpu(*src++);
++      memset(dst, 0x0, NVRAM_SPACE - i);
++
++      return 0;
++}
++
++#ifdef CONFIG_BCM47XX_SSB
++static int nvram_init_ssb(void)
++{
++      struct ssb_mipscore *mcore = &bcm47xx_bus.ssb.mipscore;
++#ifdef CONFIG_SSB_SFLASH
++      struct ssb_chipcommon *chipco = &bcm47xx_bus.ssb.chipco;
++#endif
++      u32 base;
++      u32 lim;
++
++      if (mcore->pflash.present) {
++              base = mcore->pflash.window;
++              lim = mcore->pflash.window_size;
++#ifdef CONFIG_SSB_SFLASH
++      } else if (chipco->sflash.present) {
++              base = chipco->sflash.window;
++              lim = chipco->sflash.size;
++#endif
++      } else {
++              pr_err("Couldn't find supported flash memory\n");
++              return -ENXIO;
++      }
++
++      return nvram_find_and_copy(base, lim);
++}
++#endif
++
++#ifdef CONFIG_BCM47XX_BCMA
++static int nvram_init_bcma(void)
++{
++      struct bcma_drv_cc *cc = &bcm47xx_bus.bcma.bus.drv_cc;
++      u32 base;
++      u32 lim;
++
++#ifdef CONFIG_BCMA_NFLASH
++      if (cc->nflash.boot) {
++              base = BCMA_SOC_FLASH1;
++              lim = BCMA_SOC_FLASH1_SZ;
++      } else
++#endif
++      if (cc->pflash.present) {
++              base = cc->pflash.window;
++              lim = cc->pflash.window_size;
++#ifdef CONFIG_BCMA_SFLASH
++      } else if (cc->sflash.present) {
++              base = cc->sflash.window;
++              lim = cc->sflash.size;
++#endif
++      } else {
++              pr_err("Couldn't find supported flash memory\n");
++              return -ENXIO;
++      }
++
++      return nvram_find_and_copy(base, lim);
+ }
++#endif
+-int nvram_getenv(char *name, char *val, size_t val_len)
++static int nvram_init(void)
++{
++      switch (bcm47xx_bus_type) {
++#ifdef CONFIG_BCM47XX_SSB
++      case BCM47XX_BUS_TYPE_SSB:
++              return nvram_init_ssb();
++#endif
++#ifdef CONFIG_BCM47XX_BCMA
++      case BCM47XX_BUS_TYPE_BCMA:
++              return nvram_init_bcma();
++#endif
++      }
++      return -ENXIO;
++}
++
++int bcm47xx_nvram_getenv(char *name, char *val, size_t val_len)
+ {
+       char *var, *value, *end, *eq;
++      int err;
+       if (!name)
+-              return NVRAM_ERR_INV_PARAM;
++              return -EINVAL;
+-      if (!nvram_buf[0])
+-              early_nvram_init();
++      if (!nvram_buf[0]) {
++              err = nvram_init();
++              if (err)
++                      return err;
++      }
+       /* Look for name=value and return value */
+       var = &nvram_buf[sizeof(struct nvram_header)];
+@@ -110,6 +195,6 @@ int nvram_getenv(char *name, char *val,
+                       return snprintf(val, val_len, "%s", value);
+               }
+       }
+-      return NVRAM_ERR_ENVNOTFOUND;
++      return -ENOENT;
+ }
+-EXPORT_SYMBOL(nvram_getenv);
++EXPORT_SYMBOL(bcm47xx_nvram_getenv);
+--- a/arch/mips/bcm47xx/setup.c
++++ b/arch/mips/bcm47xx/setup.c
+@@ -35,7 +35,7 @@
+ #include <asm/reboot.h>
+ #include <asm/time.h>
+ #include <bcm47xx.h>
+-#include <asm/mach-bcm47xx/nvram.h>
++#include <bcm47xx_nvram.h>
+ union bcm47xx_bus bcm47xx_bus;
+ EXPORT_SYMBOL(bcm47xx_bus);
+@@ -115,7 +115,7 @@ static int bcm47xx_get_invariants(struct
+       memset(&iv->sprom, 0, sizeof(struct ssb_sprom));
+       bcm47xx_fill_sprom(&iv->sprom, NULL, false);
+-      if (nvram_getenv("cardbus", buf, sizeof(buf)) >= 0)
++      if (bcm47xx_nvram_getenv("cardbus", buf, sizeof(buf)) >= 0)
+               iv->has_cardbus_slot = !!simple_strtoul(buf, NULL, 10);
+       return 0;
+@@ -138,7 +138,7 @@ static void __init bcm47xx_register_ssb(
+               panic("Failed to initialize SSB bus (err %d)", err);
+       mcore = &bcm47xx_bus.ssb.mipscore;
+-      if (nvram_getenv("kernel_args", buf, sizeof(buf)) >= 0) {
++      if (bcm47xx_nvram_getenv("kernel_args", buf, sizeof(buf)) >= 0) {
+               if (strstr(buf, "console=ttyS1")) {
+                       struct ssb_serial_port port;
+--- a/arch/mips/bcm47xx/sprom.c
++++ b/arch/mips/bcm47xx/sprom.c
+@@ -27,7 +27,7 @@
+  */
+ #include <bcm47xx.h>
+-#include <nvram.h>
++#include <bcm47xx_nvram.h>
+ static void create_key(const char *prefix, const char *postfix,
+                      const char *name, char *buf, int len)
+@@ -50,10 +50,10 @@ static int get_nvram_var(const char *pre
+       create_key(prefix, postfix, name, key, sizeof(key));
+-      err = nvram_getenv(key, buf, len);
+-      if (fallback && err == NVRAM_ERR_ENVNOTFOUND && prefix) {
++      err = bcm47xx_nvram_getenv(key, buf, len);
++      if (fallback && err == -ENOENT && prefix) {
+               create_key(NULL, postfix, name, key, sizeof(key));
+-              err = nvram_getenv(key, buf, len);
++              err = bcm47xx_nvram_getenv(key, buf, len);
+       }
+       return err;
+ }
+@@ -144,7 +144,7 @@ static void nvram_read_macaddr(const cha
+       if (err < 0)
+               return;
+-      nvram_parse_macaddr(buf, *val);
++      bcm47xx_nvram_parse_macaddr(buf, *val);
+ }
+ static void nvram_read_alpha2(const char *prefix, const char *name,
+--- /dev/null
++++ b/arch/mips/include/asm/mach-bcm47xx/bcm47xx_nvram.h
+@@ -0,0 +1,51 @@
++/*
++ *  Copyright (C) 2005, Broadcom Corporation
++ *  Copyright (C) 2006, Felix Fietkau <nbd@openwrt.org>
++ *
++ *  This program is free software; you can redistribute  it and/or modify it
++ *  under  the terms of  the GNU General  Public License as published by the
++ *  Free Software Foundation;  either version 2 of the  License, or (at your
++ *  option) any later version.
++ */
++
++#ifndef __BCM47XX_NVRAM_H
++#define __BCM47XX_NVRAM_H
++
++#include <linux/types.h>
++#include <linux/kernel.h>
++
++struct nvram_header {
++      u32 magic;
++      u32 len;
++      u32 crc_ver_init;       /* 0:7 crc, 8:15 ver, 16:31 sdram_init */
++      u32 config_refresh;     /* 0:15 sdram_config, 16:31 sdram_refresh */
++      u32 config_ncdl;        /* ncdl values for memc */
++};
++
++#define NVRAM_HEADER          0x48534C46      /* 'FLSH' */
++#define NVRAM_VERSION         1
++#define NVRAM_HEADER_SIZE     20
++#define NVRAM_SPACE           0x8000
++
++#define FLASH_MIN             0x00020000      /* Minimum flash size */
++
++#define NVRAM_MAX_VALUE_LEN 255
++#define NVRAM_MAX_PARAM_LEN 64
++
++extern int bcm47xx_nvram_getenv(char *name, char *val, size_t val_len);
++
++static inline void bcm47xx_nvram_parse_macaddr(char *buf, u8 macaddr[6])
++{
++      if (strchr(buf, ':'))
++              sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &macaddr[0],
++                      &macaddr[1], &macaddr[2], &macaddr[3], &macaddr[4],
++                      &macaddr[5]);
++      else if (strchr(buf, '-'))
++              sscanf(buf, "%hhx-%hhx-%hhx-%hhx-%hhx-%hhx", &macaddr[0],
++                      &macaddr[1], &macaddr[2], &macaddr[3], &macaddr[4],
++                      &macaddr[5]);
++      else
++              printk(KERN_WARNING "Can not parse mac address: %s\n", buf);
++}
++
++#endif /* __BCM47XX_NVRAM_H */
+--- a/arch/mips/include/asm/mach-bcm47xx/nvram.h
++++ /dev/null
+@@ -1,54 +0,0 @@
+-/*
+- *  Copyright (C) 2005, Broadcom Corporation
+- *  Copyright (C) 2006, Felix Fietkau <nbd@openwrt.org>
+- *
+- *  This program is free software; you can redistribute  it and/or modify it
+- *  under  the terms of  the GNU General  Public License as published by the
+- *  Free Software Foundation;  either version 2 of the  License, or (at your
+- *  option) any later version.
+- */
+-
+-#ifndef __NVRAM_H
+-#define __NVRAM_H
+-
+-#include <linux/types.h>
+-#include <linux/kernel.h>
+-
+-struct nvram_header {
+-      u32 magic;
+-      u32 len;
+-      u32 crc_ver_init;       /* 0:7 crc, 8:15 ver, 16:31 sdram_init */
+-      u32 config_refresh;     /* 0:15 sdram_config, 16:31 sdram_refresh */
+-      u32 config_ncdl;        /* ncdl values for memc */
+-};
+-
+-#define NVRAM_HEADER          0x48534C46      /* 'FLSH' */
+-#define NVRAM_VERSION         1
+-#define NVRAM_HEADER_SIZE     20
+-#define NVRAM_SPACE           0x8000
+-
+-#define FLASH_MIN             0x00020000      /* Minimum flash size */
+-
+-#define NVRAM_MAX_VALUE_LEN 255
+-#define NVRAM_MAX_PARAM_LEN 64
+-
+-#define NVRAM_ERR_INV_PARAM   -8
+-#define NVRAM_ERR_ENVNOTFOUND -9
+-
+-extern int nvram_getenv(char *name, char *val, size_t val_len);
+-
+-static inline void nvram_parse_macaddr(char *buf, u8 macaddr[6])
+-{
+-      if (strchr(buf, ':'))
+-              sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &macaddr[0],
+-                      &macaddr[1], &macaddr[2], &macaddr[3], &macaddr[4],
+-                      &macaddr[5]);
+-      else if (strchr(buf, '-'))
+-              sscanf(buf, "%hhx-%hhx-%hhx-%hhx-%hhx-%hhx", &macaddr[0],
+-                      &macaddr[1], &macaddr[2], &macaddr[3], &macaddr[4],
+-                      &macaddr[5]);
+-      else
+-              printk(KERN_WARNING "Can not parse mac address: %s\n", buf);
+-}
+-
+-#endif
+--- a/drivers/mtd/bcm47xxpart.c
++++ b/drivers/mtd/bcm47xxpart.c
+@@ -14,7 +14,7 @@
+ #include <linux/slab.h>
+ #include <linux/mtd/mtd.h>
+ #include <linux/mtd/partitions.h>
+-#include <asm/mach-bcm47xx/nvram.h>
++#include <bcm47xx_nvram.h>
+ /* 10 parts were found on sflash on Netgear WNDR4500 */
+ #define BCM47XXPART_MAX_PARTS         12
+--- a/drivers/net/ethernet/broadcom/b44.c
++++ b/drivers/net/ethernet/broadcom/b44.c
+@@ -381,7 +381,7 @@ static void b44_set_flow_ctrl(struct b44
+ }
+ #ifdef CONFIG_BCM47XX
+-#include <asm/mach-bcm47xx/nvram.h>
++#include <bcm47xx_nvram.h>
+ static void b44_wap54g10_workaround(struct b44 *bp)
+ {
+       char buf[20];
+@@ -393,7 +393,7 @@ static void b44_wap54g10_workaround(stru
+        * see https://dev.openwrt.org/ticket/146
+        * check and reset bit "isolate"
+        */
+-      if (nvram_getenv("boardnum", buf, sizeof(buf)) < 0)
++      if (bcm47xx_nvram_getenv("boardnum", buf, sizeof(buf)) < 0)
+               return;
+       if (simple_strtoul(buf, NULL, 0) == 2) {
+               err = __b44_readphy(bp, 0, MII_BMCR, &val);
+--- a/drivers/ssb/driver_chipcommon_pmu.c
++++ b/drivers/ssb/driver_chipcommon_pmu.c
+@@ -14,7 +14,7 @@
+ #include <linux/delay.h>
+ #include <linux/export.h>
+ #ifdef CONFIG_BCM47XX
+-#include <asm/mach-bcm47xx/nvram.h>
++#include <bcm47xx_nvram.h>
+ #endif
+ #include "ssb_private.h"
+@@ -322,7 +322,7 @@ static void ssb_pmu_pll_init(struct ssb_
+       if (bus->bustype == SSB_BUSTYPE_SSB) {
+ #ifdef CONFIG_BCM47XX
+               char buf[20];
+-              if (nvram_getenv("xtalfreq", buf, sizeof(buf)) >= 0)
++              if (bcm47xx_nvram_getenv("xtalfreq", buf, sizeof(buf)) >= 0)
+                       crystalfreq = simple_strtoul(buf, NULL, 0);
+ #endif
+       }
+--- a/include/linux/ssb/ssb_driver_gige.h
++++ b/include/linux/ssb/ssb_driver_gige.h
+@@ -98,14 +98,14 @@ static inline bool ssb_gige_must_flush_p
+ }
+ #ifdef CONFIG_BCM47XX
+-#include <asm/mach-bcm47xx/nvram.h>
++#include <bcm47xx_nvram.h>
+ /* Get the device MAC address */
+ static inline void ssb_gige_get_macaddr(struct pci_dev *pdev, u8 *macaddr)
+ {
+       char buf[20];
+-      if (nvram_getenv("et0macaddr", buf, sizeof(buf)) < 0)
++      if (bcm47xx_nvram_getenv("et0macaddr", buf, sizeof(buf)) < 0)
+               return;
+-      nvram_parse_macaddr(buf, macaddr);
++      bcm47xx_nvram_parse_macaddr(buf, macaddr);
+ }
+ #else
+ static inline void ssb_gige_get_macaddr(struct pci_dev *pdev, u8 *macaddr)