bcm53xx: update bcma device tree intergeneration and fix nvram parsing
authorHauke Mehrtens <hauke@openwrt.org>
Sun, 24 Aug 2014 15:57:49 +0000 (15:57 +0000)
committerHauke Mehrtens <hauke@openwrt.org>
Sun, 24 Aug 2014 15:57:49 +0000 (15:57 +0000)
This fixes lots of sparse and checkpatch errors and extends the
documentation.

This also fixes a problem in the nvram parser, it now detects the
correct nvram on my Netgear R6250.

Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@42272 3c298f89-4303-0410-b956-a3cf2f4a3e73

14 files changed:
target/linux/bcm53xx/config-3.14
target/linux/bcm53xx/patches-3.14/110-bcm47xx-move-the-nvram-header-file-into-common-space.patch
target/linux/bcm53xx/patches-3.14/111-bcm47xx-nvram-add-new-nvram-driver-with-dt-support.patch
target/linux/bcm53xx/patches-3.14/112-bcm53xx-sprom-add-sprom-driver.patch
target/linux/bcm53xx/patches-3.14/120-bcma-register-bcma-as-device-tree-driver.patch
target/linux/bcm53xx/patches-3.14/121-bcma-get-irqs-from-dt.patch
target/linux/bcm53xx/patches-3.14/123-bcma-get-sprom-from-devicetree.patch
target/linux/bcm53xx/patches-3.14/130-ARM-BCM5301X-register-bcma-bus.patch
target/linux/bcm53xx/patches-3.14/140-bcma-only-map-wrap-if-it-is-not-null.patch
target/linux/bcm53xx/patches-3.14/141-bcma-store-more-alternative-addresses.patch
target/linux/bcm53xx/patches-3.14/142-bcma-add-support-for-chipcommon-B-core.patch
target/linux/bcm53xx/patches-3.14/150-pci-do-not-probe-too-early.patch
target/linux/bcm53xx/patches-3.14/160-bcma-add-PCI-IDs-for-more-devices.patch
target/linux/bcm53xx/patches-3.14/170-pcie2-bcma-add-new-PCIe2-driver-for-bcma.patch

index 2192b83..c6f1544 100644 (file)
@@ -42,7 +42,7 @@ CONFIG_B53=y
 # CONFIG_B53_PHY_DRIVER is not set
 CONFIG_B53_SRAB_DRIVER=y
 CONFIG_BCM47XX_NVRAM=y
-CONFIG_BCM53XX_SPROM=y
+CONFIG_BCM47XX_SPROM=y
 CONFIG_BCMA=y
 CONFIG_BCMA_BLOCKIO=y
 CONFIG_BCMA_DEBUG=y
index 85b9ab3..773ee46 100644 (file)
@@ -1,24 +1,32 @@
-From bd489dfe8c0d7495645cbc8b8c283217ba816fab Mon Sep 17 00:00:00 2001
+From 7063a1583166abe1a9cefed38c2f53a0e14a0005 Mon Sep 17 00:00:00 2001
 From: Hauke Mehrtens <hauke@hauke-m.de>
 Date: Sun, 4 May 2014 16:35:42 +0200
-Subject: [PATCH 02/15] bcm47xx: move the nvram header file into common space
+Subject: [PATCH 01/17] MIPS: BCM47XX: move the nvram header file into common
+ space
 
-Moving mach-bcm47xx/bcm47xx_nvram.h makes it possible to reuse this
-header on the arm bcm47xx (BCM5301X) devices. This way a driver gets
-the correct functions to access the nvram depending on the SoC it boots
-for.
+Moving mach-bcm47xx/bcm47xx_nvram.h to include/linux/bcm47xx_nvram.h
+makes it possible to reuse this header on the ARM based bcm47xx/bcm53xx
+SoCs (e.g. BCM5301X devices). Broadcom uses ARM CPUs in their new SoC
+form the bcm47xx and bcm53xx line, but many other things like nvram
+stayed the same.
+
+This is a preparation for adding a new nvram driver, which can be used
+by the ARM SoC and the MIPS SoC code. The device drivers accessing
+nvram do not have to care about ARM or MIPS SoC version.
+
+Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
 ---
  arch/mips/bcm47xx/board.c                          |  2 +-
  arch/mips/bcm47xx/nvram.c                          |  2 +-
  arch/mips/bcm47xx/setup.c                          |  2 +-
  arch/mips/bcm47xx/sprom.c                          |  2 +-
  arch/mips/bcm47xx/time.c                           |  2 +-
- arch/mips/include/asm/mach-bcm47xx/bcm47xx_nvram.h | 53 ------------------
+ arch/mips/include/asm/mach-bcm47xx/bcm47xx_nvram.h | 53 -----------------
  drivers/net/ethernet/broadcom/b44.c                |  8 +--
  drivers/net/ethernet/broadcom/bgmac.c              |  2 +-
  drivers/ssb/driver_chipcommon_pmu.c                |  6 +-
- include/linux/bcm47xx_nvram.h                      | 65 ++++++++++++++++++++++
- 10 files changed, 73 insertions(+), 71 deletions(-)
+ include/linux/bcm47xx_nvram.h                      | 66 ++++++++++++++++++++++
+ 10 files changed, 74 insertions(+), 71 deletions(-)
  delete mode 100644 arch/mips/include/asm/mach-bcm47xx/bcm47xx_nvram.h
  create mode 100644 include/linux/bcm47xx_nvram.h
 
@@ -202,7 +210,7 @@ for.
        switch (bus->chip_id) {
 --- /dev/null
 +++ b/include/linux/bcm47xx_nvram.h
-@@ -0,0 +1,65 @@
+@@ -0,0 +1,66 @@
 +/*
 + *  Copyright (C) 2005, Broadcom Corporation
 + *  Copyright (C) 2006, Felix Fietkau <nbd@openwrt.org>
@@ -243,7 +251,8 @@ for.
 +
 +int bcm47xx_nvram_gpio_pin(const char *name);
 +#else
-+static inline int bcm47xx_nvram_getenv(const char *name, char *val, size_t val_len)
++static inline int bcm47xx_nvram_getenv(const char *name, char *val,
++                                     size_t val_len)
 +{
 +      return -ENXIO;
 +}
index a53e86d..78997ed 100644 (file)
@@ -1,30 +1,64 @@
-From 60a413ed5bc7917f1612df441240f458163b10c1 Mon Sep 17 00:00:00 2001
+From 71a6bff8656a1713615ffdd9139a83d65ba46c6d Mon Sep 17 00:00:00 2001
 From: Hauke Mehrtens <hauke@hauke-m.de>
 Date: Sat, 3 May 2014 22:54:59 +0200
-Subject: [PATCH 03/15] bcm47xx-nvram: add new nvram driver with dt support
+Subject: [PATCH 02/17] bcm47xx-nvram: add new broadcom nvram driver with dt
+ support
 
-This adds a new nvrm driver which uses device tree to provide nvram
-access to other drivers. You have to specify the memory ranges where
-the flash chip is mapped and this driver will search there for some
-nvram and parse it. Other drivers can use this driver to access the
+This adds a new driver which searches at a given memory range for a
+nvram like it is used on the bcm47xx and bcm53xx SoCs with ARM and MIPS
+CPUs. This driver provides acces to this nvram to other device in the
+device tree. You have to specify the memory ranges where the content of
+the flash chip is memory mapped and this driver will search there for
+some nvram and parse it. Other drivers can use this driver to access the
 device nvram. The nvram is used to store board configurations like the
-mac address and also for configuration values in the vendor firmware.
+mac addresses, the switch configuration and the calibration data for
+the wifi devices.
+
+This was copied from arch/mips/bcm47xx/nvram.c and modified to interact
+with device tree. My plan is to make the MIPS bcm47xx also use this new
+driver some time later.
+
+Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
 ---
- arch/mips/bcm47xx/board.c             |  36 +++---
- arch/mips/bcm47xx/nvram.c             |   7 +-
- arch/mips/bcm47xx/setup.c             |   4 +-
- arch/mips/bcm47xx/sprom.c             |   4 +-
- arch/mips/bcm47xx/time.c              |   2 +-
- drivers/misc/Kconfig                  |   5 +
- drivers/misc/Makefile                 |   1 +
- drivers/misc/bcm47xx-nvram.c          | 211 ++++++++++++++++++++++++++++++++++
- drivers/net/ethernet/broadcom/b44.c   |   2 +-
- drivers/net/ethernet/broadcom/bgmac.c |   4 +-
- drivers/ssb/driver_chipcommon_pmu.c   |   2 +-
- include/linux/bcm47xx_nvram.h         |  16 ++-
- 12 files changed, 259 insertions(+), 35 deletions(-)
+ .../devicetree/bindings/misc/bcm47xx-nvram.txt     |  19 ++
+ arch/mips/bcm47xx/board.c                          |  40 ++--
+ arch/mips/bcm47xx/nvram.c                          |   7 +-
+ arch/mips/bcm47xx/setup.c                          |   4 +-
+ arch/mips/bcm47xx/sprom.c                          |   4 +-
+ arch/mips/bcm47xx/time.c                           |   2 +-
+ drivers/misc/Kconfig                               |   5 +
+ drivers/misc/Makefile                              |   1 +
+ drivers/misc/bcm47xx-nvram.c                       | 215 +++++++++++++++++++++
+ drivers/net/ethernet/broadcom/b44.c                |   2 +-
+ drivers/net/ethernet/broadcom/bgmac.c              |   5 +-
+ drivers/ssb/driver_chipcommon_pmu.c                |   3 +-
+ include/linux/bcm47xx_nvram.h                      |  17 +-
+ 13 files changed, 286 insertions(+), 38 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/misc/bcm47xx-nvram.txt
  create mode 100644 drivers/misc/bcm47xx-nvram.c
 
+--- /dev/null
++++ b/Documentation/devicetree/bindings/misc/bcm47xx-nvram.txt
+@@ -0,0 +1,19 @@
++Broadcom bcm47xx/bcm53xx nvram access driver
++
++This driver provides access to the nvram for other drivers.
++
++Required properties:
++
++- compatible : brcm,bcm47xx-nvram
++
++- reg : iomem address range
++
++On NorthStar ARM SoCs the NAND flash is available at 0x1c000000 and the
++NOR flash is at 0x1e000000
++
++Example:
++
++nvram0: nvram@0 {
++      compatible = "brcm,bcm47xx-nvram";
++      reg = <0x1c000000 0x01000000>;
++};
 --- a/arch/mips/bcm47xx/board.c
 +++ b/arch/mips/bcm47xx/board.c
 @@ -196,50 +196,50 @@ static __init const struct bcm47xx_board
@@ -226,7 +260,7 @@ mac address and also for configuration values in the vendor firmware.
 +obj-$(CONFIG_BCM47XX_NVRAM)   += bcm47xx-nvram.o
 --- /dev/null
 +++ b/drivers/misc/bcm47xx-nvram.c
-@@ -0,0 +1,211 @@
+@@ -0,0 +1,215 @@
 +/*
 + * BCM947xx nvram variable access
 + *
@@ -259,12 +293,12 @@ mac address and also for configuration values in the vendor firmware.
 +
 +static u32 find_nvram_size(void __iomem *end)
 +{
-+      struct nvram_header *header;
++      struct nvram_header __iomem *header;
 +      int i;
 +
 +      for (i = 0; i < ARRAY_SIZE(nvram_sizes); i++) {
-+              header = (struct nvram_header *)(end - nvram_sizes[i]);
-+              if (header->magic == NVRAM_HEADER)
++              header = (struct nvram_header __iomem *)(end - nvram_sizes[i]);
++              if (__raw_readl(&header->magic) == NVRAM_HEADER)
 +                      return nvram_sizes[i];
 +      }
 +
@@ -276,10 +310,11 @@ mac address and also for configuration values in the vendor firmware.
 +                             size_t len, char **nvram_buf,
 +                             size_t *nvram_len)
 +{
-+      struct nvram_header *header;
++      struct nvram_header __iomem *header;
 +      int i;
 +      u32 off;
-+      u32 *src, *dst;
++      u32 *dst;
++      __le32 __iomem *src;
 +      u32 size;
 +
 +      /* TODO: when nvram is on nand flash check for bad blocks first. */
@@ -288,21 +323,22 @@ mac address and also for configuration values in the vendor firmware.
 +              /* Windowed flash access */
 +              size = find_nvram_size(base + off);
 +              if (size) {
-+                      header = (struct nvram_header *)(base + off - size);
++                      header = (struct nvram_header __iomem *)
++                                      (base + off - size);
 +                      goto found;
 +              }
-+              off <<= 1;
++              off += 0x10000;
 +      }
 +
 +      /* Try embedded NVRAM at 4 KB and 1 KB as last resorts */
-+      header = (struct nvram_header *)(base + 4096);
-+      if (header->magic == NVRAM_HEADER) {
++      header = (struct nvram_header __iomem *)(base + 4096);
++      if (__raw_readl(&header->magic) == NVRAM_HEADER) {
 +              size = NVRAM_SPACE;
 +              goto found;
 +      }
 +
-+      header = (struct nvram_header *)(base + 1024);
-+      if (header->magic == NVRAM_HEADER) {
++      header = (struct nvram_header __iomem *)(base + 1024);
++      if (__raw_readl(&header->magic) == NVRAM_HEADER) {
 +              size = NVRAM_SPACE;
 +              goto found;
 +      }
@@ -313,25 +349,26 @@ mac address and also for configuration values in the vendor firmware.
 +      return -ENXIO;
 +
 +found:
-+      if (header->len > size)
++      if (readl(&header->len) > size)
 +              pr_err("The nvram size accoridng to the header seems to be bigger than the partition on flash\n");
-+      *nvram_len = min_t(u32, header->len, size);
++      *nvram_len = min_t(u32, readl(&header->len), size);
 +
 +      *nvram_buf = devm_kzalloc(dev, *nvram_len, GFP_KERNEL);
 +      if (!*nvram_buf)
 +              return -ENOMEM;
 +
-+      src = (u32 *) header;
++      src = (__le32 __iomem *) header;
 +      dst = (u32 *) *nvram_buf;
 +      for (i = 0; i < sizeof(struct nvram_header); i += 4)
-+              *dst++ = *src++;
++              *dst++ = __raw_readl(src++);
 +      for (; i < *nvram_len; i += 4)
-+              *dst++ = le32_to_cpu(*src++);
++              *dst++ = readl(src++);
 +
 +      return 0;
 +}
 +
-+int bcm47xx_nvram_getenv(const struct device *dev, const char *name, char *val, size_t val_len)
++int bcm47xx_nvram_getenv(const struct device *dev, const char *name, char *val,
++                       size_t val_len)
 +{
 +      char *var, *value, *end, *eq;
 +      struct bcm47xx_nvram *nvram;
@@ -407,7 +444,8 @@ mac address and also for configuration values in the vendor firmware.
 +      if (!mmio)
 +              return -ENOMEM;
 +
-+      err = nvram_find_and_copy(dev, mmio, resource_size(&flash_mem), &nvram->nvram_buf, &nvram->nvram_len);
++      err = nvram_find_and_copy(dev, mmio, resource_size(&flash_mem),
++                                &nvram->nvram_buf, &nvram->nvram_len);
 +      if (err)
 +              goto err_unmap_mmio;
 +
@@ -451,16 +489,17 @@ mac address and also for configuration values in the vendor firmware.
                err = __b44_readphy(bp, 0, MII_BMCR, &val);
 --- a/drivers/net/ethernet/broadcom/bgmac.c
 +++ b/drivers/net/ethernet/broadcom/bgmac.c
-@@ -974,7 +974,7 @@ static void bgmac_chip_reset(struct bgma
+@@ -974,7 +974,8 @@ static void bgmac_chip_reset(struct bgma
                             BGMAC_CHIPCTL_1_IF_TYPE_MII;
                char buf[4];
  
 -              if (bcm47xx_nvram_getenv("et_swtype", buf, sizeof(buf)) > 0) {
-+              if (bcm47xx_nvram_getenv(NULL, "et_swtype", buf, sizeof(buf)) > 0) {
++              if (bcm47xx_nvram_getenv(NULL, "et_swtype", buf,
++                                       sizeof(buf)) > 0) {
                        if (kstrtou8(buf, 0, &et_swtype))
                                bgmac_err(bgmac, "Failed to parse et_swtype (%s)\n",
                                          buf);
-@@ -1534,7 +1534,7 @@ static int bgmac_probe(struct bcma_devic
+@@ -1534,7 +1535,7 @@ static int bgmac_probe(struct bcma_devic
        }
  
        bgmac->int_mask = BGMAC_IS_ERRMASK | BGMAC_IS_RX | BGMAC_IS_TX_MASK;
@@ -471,18 +510,19 @@ mac address and also for configuration values in the vendor firmware.
        /* TODO: reset the external phy. Specs are needed */
 --- a/drivers/ssb/driver_chipcommon_pmu.c
 +++ b/drivers/ssb/driver_chipcommon_pmu.c
-@@ -319,7 +319,7 @@ static void ssb_pmu_pll_init(struct ssb_
+@@ -319,7 +319,8 @@ static void ssb_pmu_pll_init(struct ssb_
  
        if (bus->bustype == SSB_BUSTYPE_SSB) {
                char buf[20];
 -              if (bcm47xx_nvram_getenv("xtalfreq", buf, sizeof(buf)) >= 0)
-+              if (bcm47xx_nvram_getenv(NULL, "xtalfreq", buf, sizeof(buf)) >= 0)
++              if (bcm47xx_nvram_getenv(NULL, "xtalfreq", buf,
++                                       sizeof(buf)) >= 0)
                        crystalfreq = simple_strtoul(buf, NULL, 0);
        }
  
 --- a/include/linux/bcm47xx_nvram.h
 +++ b/include/linux/bcm47xx_nvram.h
-@@ -15,6 +15,8 @@
+@@ -15,9 +15,11 @@
  #include <linux/types.h>
  #include <linux/kernel.h>
  
@@ -490,8 +530,12 @@ mac address and also for configuration values in the vendor firmware.
 +
  struct nvram_header {
        u32 magic;
-       u32 len;
-@@ -33,17 +35,21 @@ struct nvram_header {
+-      u32 len;
++      __le32 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 */
+@@ -33,18 +35,21 @@ struct nvram_header {
  #define NVRAM_MAX_VALUE_LEN 255
  #define NVRAM_MAX_PARAM_LEN 64
  
@@ -504,10 +548,10 @@ mac address and also for configuration values in the vendor firmware.
 -int bcm47xx_nvram_gpio_pin(const char *name);
 +int bcm47xx_nvram_gpio_pin(const struct device *dev, const char *name);
  #else
--static inline int bcm47xx_nvram_getenv(const char *name, char *val, size_t val_len)
+-static inline int bcm47xx_nvram_getenv(const char *name, char *val,
 +static inline int bcm47xx_nvram_getenv(const struct device *dev,
 +                                     const char *name, char *val,
-+                                     size_t val_len)
+                                      size_t val_len)
  {
        return -ENXIO;
  }
index d8cdeb5..e0698ec 100644 (file)
@@ -1,31 +1,61 @@
-From b113f9d3e140f18e63cbf3408b3dcde372242dc8 Mon Sep 17 00:00:00 2001
+From 4e0ab3269a6d260a41a3673157753147f5f71341 Mon Sep 17 00:00:00 2001
 From: Hauke Mehrtens <hauke@hauke-m.de>
 Date: Sun, 4 May 2014 13:19:20 +0200
-Subject: [PATCH 04/15] bcm53xx-sprom: add sprom driver
+Subject: [PATCH 03/17] bcm47xx-sprom: add Broadcom sprom parser driver
 
 This driver needs an nvram driver and fetches the sprom values from the
-sprom and provides it to any other driver. The calibration data for the
+nvram and provides it to any other driver. The calibration data for the
 wifi chip the mac address and some more board description data is
 stores in the sprom.
 
+This is based on a copy of arch/mips/bcm47xx/sprom.c and my plan is to
+make the bcm47xx MIPS SoCs also use this driver some time later.
+
 Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
 ---
- drivers/misc/Kconfig         |   5 +
- drivers/misc/Makefile        |   1 +
- drivers/misc/bcm53xx-sprom.c | 625 +++++++++++++++++++++++++++++++++++++++++++
- 3 files changed, 631 insertions(+)
- create mode 100644 drivers/misc/bcm53xx-sprom.c
+ .../devicetree/bindings/misc/bcm47xx-sprom.txt     |  16 +
+ drivers/misc/Kconfig                               |  11 +
+ drivers/misc/Makefile                              |   1 +
+ drivers/misc/bcm47xx-sprom.c                       | 690 +++++++++++++++++++++
+ 4 files changed, 718 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/misc/bcm47xx-sprom.txt
+ create mode 100644 drivers/misc/bcm47xx-sprom.c
 
+--- /dev/null
++++ b/Documentation/devicetree/bindings/misc/bcm47xx-sprom.txt
+@@ -0,0 +1,16 @@
++Broadcom bcm47xx/bcm53xx sprom converter
++
++This driver provbides an sprom based on a given nvram.
++
++Required properties:
++
++- compatible : brcm,bcm47xx-sprom
++
++- nvram : reference to a nvram driver, e.g. bcm47xx-nvram
++
++Example:
++
++sprom0: sprom@0 {
++      compatible = "brcm,bcm47xx-sprom";
++      nvram = <&nvram0>;
++};
 --- a/drivers/misc/Kconfig
 +++ b/drivers/misc/Kconfig
-@@ -520,6 +520,11 @@ config BCM47XX_NVRAM
+@@ -520,6 +520,17 @@ config BCM47XX_NVRAM
        help
                This adds support for the brcm47xx nvram driver.
  
-+config BCM53XX_SPROM
-+      tristate "BCM53XX sprom driver"
++config BCM47XX_SPROM
++      tristate "BCM47XX sprom driver"
 +      help
-+              This adds support for the brcm53xx sprom driver.
++        This driver parses the sprom from a given nvram which is found on
++        Broadcom bcm47xx and bcm53xx SoCs.
++
++        The sprom contains board configuration data like the
++        calibration data fro the wifi chips, the mac addresses used
++        by the board and many other board configuration data. This
++        driver will provide the sprom to bcma.
 +
  source "drivers/misc/c2port/Kconfig"
  source "drivers/misc/eeprom/Kconfig"
@@ -36,12 +66,12 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
  obj-y                         += mic/
  obj-$(CONFIG_GENWQE)          += genwqe/
  obj-$(CONFIG_BCM47XX_NVRAM)   += bcm47xx-nvram.o
-+obj-$(CONFIG_BCM53XX_SPROM)   += bcm53xx-sprom.o
++obj-$(CONFIG_BCM47XX_SPROM)   += bcm47xx-sprom.o
 --- /dev/null
-+++ b/drivers/misc/bcm53xx-sprom.c
-@@ -0,0 +1,625 @@
++++ b/drivers/misc/bcm47xx-sprom.c
+@@ -0,0 +1,690 @@
 +/*
-+ * BCM947xx nvram variable access
++ * BCM47xx/BCM53xx nvram variable access
 + *
 + * Copyright (C) 2005 Broadcom Corporation
 + * Copyright (C) 2004 Florian Schirmer <jolt@tuxbox.org>
@@ -67,11 +97,14 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
 +#include <linux/io.h>
 +#include <linux/ssb/ssb.h>
 +#include <linux/bcm47xx_nvram.h>
++#include <linux/if_ether.h>
++#include <linux/etherdevice.h>
 +
-+struct bcm53xx_sprom_fill {
++struct bcm47xx_sprom_fill {
 +      const char *prefix;
 +      bool fallback;
-+      int (*getenv)(const struct bcm53xx_sprom_fill *fill, const char *name, char *val, size_t val_len);
++      int (*getenv)(const struct bcm47xx_sprom_fill *fill, const char *name,
++                    char *val, size_t val_len);
 +      const void *priv;
 +};
 +
@@ -88,8 +121,9 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
 +              snprintf(buf, len, "%s", name);
 +}
 +
-+static int get_nvram_var(const struct bcm53xx_sprom_fill *fill, const char *postfix,
-+                       const char *name, char *buf, int len)
++static int get_nvram_var(const struct bcm47xx_sprom_fill *fill,
++                       const char *postfix, const char *name, char *buf,
++                       int len)
 +{
 +      char key[40];
 +      int err;
@@ -105,7 +139,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
 +}
 +
 +#define NVRAM_READ_VAL(type)                                          \
-+static void nvram_read_ ## type (const struct bcm53xx_sprom_fill *fill,       \
++static void nvram_read_ ## type (const struct bcm47xx_sprom_fill *fill,       \
 +                               const char *postfix, const char *name, \
 +                               type *val, type allset)                \
 +{                                                                     \
@@ -134,8 +168,8 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
 +
 +#undef NVRAM_READ_VAL
 +
-+static void nvram_read_u32_2(const struct bcm53xx_sprom_fill *fill, const char *name,
-+                           u16 *val_lo, u16 *val_hi)
++static void nvram_read_u32_2(const struct bcm47xx_sprom_fill *fill,
++                           const char *name, u16 *val_lo, u16 *val_hi)
 +{
 +      char buf[100];
 +      int err;
@@ -154,8 +188,9 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
 +      *val_hi = (val & 0xFFFF0000U) >> 16;
 +}
 +
-+static void nvram_read_leddc(const struct bcm53xx_sprom_fill *fill, const char *name,
-+                           u8 *leddc_on_time, u8 *leddc_off_time)
++static void nvram_read_leddc(const struct bcm47xx_sprom_fill *fill,
++                           const char *name, u8 *leddc_on_time,
++                           u8 *leddc_off_time)
 +{
 +      char buf[100];
 +      int err;
@@ -178,8 +213,8 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
 +      *leddc_off_time = (val >> 16) & 0xff;
 +}
 +
-+static void nvram_read_macaddr(const struct bcm53xx_sprom_fill *fill, const char *name,
-+                             u8 val[6])
++static void nvram_read_macaddr(const struct bcm47xx_sprom_fill *fill,
++                             const char *name, u8 val[6])
 +{
 +      char buf[100];
 +      int err;
@@ -191,8 +226,8 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
 +      bcm47xx_nvram_parse_macaddr(buf, val);
 +}
 +
-+static void nvram_read_alpha2(const struct bcm53xx_sprom_fill *fill, const char *name,
-+                           char val[2])
++static void nvram_read_alpha2(const struct bcm47xx_sprom_fill *fill,
++                            const char *name, char val[2])
 +{
 +      char buf[10];
 +      int err;
@@ -209,9 +244,10 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
 +      memcpy(val, buf, 2);
 +}
 +
-+static void bcm53xx_sprom_fill_r1234589(struct ssb_sprom *sprom,
-+                                      const struct bcm53xx_sprom_fill *fill)
++static void bcm47xx_sprom_fill_r1234589(struct ssb_sprom *sprom,
++                                      const struct bcm47xx_sprom_fill *fill)
 +{
++      nvram_read_u16(fill, NULL, "devid", &sprom->dev_id, 0);
 +      nvram_read_u8(fill, NULL, "ledbh0", &sprom->gpio0, 0xff);
 +      nvram_read_u8(fill, NULL, "ledbh1", &sprom->gpio1, 0xff);
 +      nvram_read_u8(fill, NULL, "ledbh2", &sprom->gpio2, 0xff);
@@ -223,8 +259,8 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
 +      nvram_read_alpha2(fill, "ccode", sprom->alpha2);
 +}
 +
-+static void bcm53xx_sprom_fill_r12389(struct ssb_sprom *sprom,
-+                                    const struct bcm53xx_sprom_fill *fill)
++static void bcm47xx_sprom_fill_r12389(struct ssb_sprom *sprom,
++                                    const struct bcm47xx_sprom_fill *fill)
 +{
 +      nvram_read_u16(fill, NULL, "pa0b0", &sprom->pa0b0, 0);
 +      nvram_read_u16(fill, NULL, "pa0b1", &sprom->pa0b1, 0);
@@ -238,15 +274,15 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
 +      nvram_read_u8(fill, NULL, "pa1maxpwr", &sprom->maxpwr_a, 0);
 +}
 +
-+static void bcm53xx_sprom_fill_r1(struct ssb_sprom *sprom,
-+                                const struct bcm53xx_sprom_fill *fill)
++static void bcm47xx_sprom_fill_r1(struct ssb_sprom *sprom,
++                                const struct bcm47xx_sprom_fill *fill)
 +{
 +      nvram_read_u16(fill, NULL, "boardflags", &sprom->boardflags_lo, 0);
 +      nvram_read_u8(fill, NULL, "cc", &sprom->country_code, 0);
 +}
 +
-+static void bcm53xx_sprom_fill_r2389(struct ssb_sprom *sprom,
-+                                   const struct bcm53xx_sprom_fill *fill)
++static void bcm47xx_sprom_fill_r2389(struct ssb_sprom *sprom,
++                                   const struct bcm47xx_sprom_fill *fill)
 +{
 +      nvram_read_u8(fill, NULL, "opo", &sprom->opo, 0);
 +      nvram_read_u16(fill, NULL, "pa1lob0", &sprom->pa1lob0, 0);
@@ -259,8 +295,8 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
 +      nvram_read_u8(fill, NULL, "pa1himaxpwr", &sprom->maxpwr_ah, 0);
 +}
 +
-+static void bcm53xx_sprom_fill_r389(struct ssb_sprom *sprom,
-+                                  const struct bcm53xx_sprom_fill *fill)
++static void bcm47xx_sprom_fill_r389(struct ssb_sprom *sprom,
++                                  const struct bcm47xx_sprom_fill *fill)
 +{
 +      nvram_read_u8(fill, NULL, "bxa2g", &sprom->bxa2g, 0);
 +      nvram_read_u8(fill, NULL, "rssisav2g", &sprom->rssisav2g, 0);
@@ -278,16 +314,16 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
 +      nvram_read_s8(fill, NULL, "rxpo5g", &sprom->rxpo5g, 0);
 +}
 +
-+static void bcm53xx_sprom_fill_r3(struct ssb_sprom *sprom,
-+                                const struct bcm53xx_sprom_fill *fill)
++static void bcm47xx_sprom_fill_r3(struct ssb_sprom *sprom,
++                                const struct bcm47xx_sprom_fill *fill)
 +{
 +      nvram_read_u8(fill, NULL, "regrev", &sprom->regrev, 0);
 +      nvram_read_leddc(fill, "leddc", &sprom->leddc_on_time,
 +                       &sprom->leddc_off_time);
 +}
 +
-+static void bcm53xx_sprom_fill_r4589(struct ssb_sprom *sprom,
-+                                   const struct bcm53xx_sprom_fill *fill)
++static void bcm47xx_sprom_fill_r4589(struct ssb_sprom *sprom,
++                                   const struct bcm47xx_sprom_fill *fill)
 +{
 +      nvram_read_u8(fill, NULL, "regrev", &sprom->regrev, 0);
 +      nvram_read_s8(fill, NULL, "ag2", &sprom->antenna_gain.a2, 0);
@@ -299,8 +335,8 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
 +                       &sprom->leddc_off_time);
 +}
 +
-+static void bcm53xx_sprom_fill_r458(struct ssb_sprom *sprom,
-+                                  const struct bcm53xx_sprom_fill *fill)
++static void bcm47xx_sprom_fill_r458(struct ssb_sprom *sprom,
++                                  const struct bcm47xx_sprom_fill *fill)
 +{
 +      nvram_read_u16(fill, NULL, "cck2gpo", &sprom->cck2gpo, 0);
 +      nvram_read_u32(fill, NULL, "ofdm2gpo", &sprom->ofdm2gpo, 0);
@@ -345,8 +381,8 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
 +      nvram_read_u16(fill, NULL, "mcs5ghpo7", &sprom->mcs5ghpo[7], 0);
 +}
 +
-+static void bcm53xx_sprom_fill_r45(struct ssb_sprom *sprom,
-+                                 const struct bcm53xx_sprom_fill *fill)
++static void bcm47xx_sprom_fill_r45(struct ssb_sprom *sprom,
++                                 const struct bcm47xx_sprom_fill *fill)
 +{
 +      nvram_read_u8(fill, NULL, "txpid2ga0", &sprom->txpid2g[0], 0);
 +      nvram_read_u8(fill, NULL, "txpid2ga1", &sprom->txpid2g[1], 0);
@@ -366,8 +402,8 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
 +      nvram_read_u8(fill, NULL, "txpid5gha3", &sprom->txpid5gh[3], 0);
 +}
 +
-+static void bcm53xx_sprom_fill_r89(struct ssb_sprom *sprom,
-+                                 const struct bcm53xx_sprom_fill *fill)
++static void bcm47xx_sprom_fill_r89(struct ssb_sprom *sprom,
++                                 const struct bcm47xx_sprom_fill *fill)
 +{
 +      nvram_read_u8(fill, NULL, "tssipos2g", &sprom->fem.ghz2.tssipos, 0);
 +      nvram_read_u8(fill, NULL, "extpagain2g", &sprom->fem.ghz2.extpa_gain, 0);
@@ -429,8 +465,8 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
 +      nvram_read_u8(fill, NULL, "pcieingress_war", &sprom->pcieingress_war, 0);
 +}
 +
-+static void bcm53xx_sprom_fill_r9(struct ssb_sprom *sprom,
-+                                const struct bcm53xx_sprom_fill *fill)
++static void bcm47xx_sprom_fill_r9(struct ssb_sprom *sprom,
++                                const struct bcm47xx_sprom_fill *fill)
 +{
 +      nvram_read_u16(fill, NULL, "cckbw202gpo", &sprom->cckbw202gpo, 0);
 +      nvram_read_u16(fill, NULL, "cckbw20ul2gpo", &sprom->cckbw20ul2gpo, 0);
@@ -460,14 +496,15 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
 +      nvram_read_u8(fill, NULL, "sar5g", &sprom->sar5g, 0);
 +}
 +
-+static void bcm53xx_sprom_fill_path_r4589(struct ssb_sprom *sprom,
-+                                        const struct bcm53xx_sprom_fill *fill)
++static void bcm47xx_sprom_fill_path_r4589(struct ssb_sprom *sprom,
++                                        const struct bcm47xx_sprom_fill *fill)
 +{
 +      char postfix[2];
 +      int i;
 +
 +      for (i = 0; i < ARRAY_SIZE(sprom->core_pwr_info); i++) {
 +              struct ssb_sprom_core_pwr_info *pwr_info = &sprom->core_pwr_info[i];
++
 +              snprintf(postfix, sizeof(postfix), "%i", i);
 +              nvram_read_u8(fill, postfix, "maxp2ga", &pwr_info->maxpwr_2g, 0);
 +              nvram_read_u8(fill, postfix, "itt2ga", &pwr_info->itssi_2g, 0);
@@ -490,14 +527,15 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
 +      }
 +}
 +
-+static void bcm53xx_sprom_fill_path_r45(struct ssb_sprom *sprom,
-+                                      const struct bcm53xx_sprom_fill *fill)
++static void bcm47xx_sprom_fill_path_r45(struct ssb_sprom *sprom,
++                                      const struct bcm47xx_sprom_fill *fill)
 +{
 +      char postfix[2];
 +      int i;
 +
 +      for (i = 0; i < ARRAY_SIZE(sprom->core_pwr_info); i++) {
 +              struct ssb_sprom_core_pwr_info *pwr_info = &sprom->core_pwr_info[i];
++
 +              snprintf(postfix, sizeof(postfix), "%i", i);
 +              nvram_read_u16(fill, postfix, "pa2gw3a", &pwr_info->pa_2g[3], 0);
 +              nvram_read_u16(fill, postfix, "pa5gw3a", &pwr_info->pa_5g[3], 0);
@@ -506,8 +544,39 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
 +      }
 +}
 +
-+static void bcm53xx_sprom_fill_ethernet(struct ssb_sprom *sprom,
-+                                      const struct bcm53xx_sprom_fill *fill)
++static bool bcm47xx_is_valid_mac(u8 *mac)
++{
++      return mac && !(mac[0] == 0x00 && mac[1] == 0x90 && mac[2] == 0x4c);
++}
++
++static int bcm47xx_increase_mac_addr(u8 *mac, u8 num)
++{
++      u8 *oui = mac + ETH_ALEN/2 - 1;
++      u8 *p = mac + ETH_ALEN - 1;
++
++      do {
++              (*p) += num;
++              if (*p > num)
++                      break;
++              p--;
++              num = 1;
++      } while (p != oui);
++
++      if (p == oui) {
++              pr_err("unable to fetch mac address\n");
++              return -ENOENT;
++      }
++      return 0;
++}
++
++/*
++ * This is a global counter because different instances of sprom will
++ * access the same nvram.
++ */
++static int mac_addr_used = 2;
++
++static void bcm47xx_sprom_fill_ethernet(struct ssb_sprom *sprom,
++                                      const struct bcm47xx_sprom_fill *fill)
 +{
 +      nvram_read_macaddr(fill, "et0macaddr", sprom->et0mac);
 +      nvram_read_u8(fill, NULL, "et0mdcport", &sprom->et0mdcport, 0);
@@ -519,10 +588,35 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
 +
 +      nvram_read_macaddr(fill, "macaddr", sprom->il0mac);
 +      nvram_read_macaddr(fill, "il0macaddr", sprom->il0mac);
++
++      /*
++       * The address prefix 00:90:4C is used by Broadcom in their initial
++       * configuration. When a mac address with the prefix 00:90:4C is used
++       * all devices from the same series are sharing the same mac address.
++       * To prevent mac address collisions we replace them with a mac address
++       * based on the base address.
++       */
++      if (!bcm47xx_is_valid_mac(sprom->il0mac)) {
++              u8 mac[6];
++              struct bcm47xx_sprom_fill fill_no_prefix;
++
++              memcpy(&fill_no_prefix, fill, sizeof(fill_no_prefix));
++              fill_no_prefix.prefix = NULL;
++
++              nvram_read_macaddr(&fill_no_prefix, "et0macaddr", mac);
++              if (bcm47xx_is_valid_mac(mac)) {
++                      int err = bcm47xx_increase_mac_addr(mac, mac_addr_used);
++
++                      if (!err) {
++                              ether_addr_copy(sprom->il0mac, mac);
++                              mac_addr_used++;
++                      }
++              }
++      }
 +}
 +
-+static void bcm53xx_sprom_fill_board_data(struct ssb_sprom *sprom,
-+                                        const struct bcm53xx_sprom_fill *fill)
++static void bcm47xx_sprom_fill_board_data(struct ssb_sprom *sprom,
++                                        const struct bcm47xx_sprom_fill *fill)
 +{
 +      nvram_read_u16(fill, NULL, "boardrev", &sprom->board_rev, 0);
 +      nvram_read_u16(fill, NULL, "boardnum", &sprom->board_num, 0);
@@ -533,72 +627,72 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
 +                       &sprom->boardflags2_hi);
 +}
 +
-+static void bcm53xx_sprom_fill(struct ssb_sprom *sprom,
-+                      const struct bcm53xx_sprom_fill *fill)
++static void bcm47xx_sprom_fill(struct ssb_sprom *sprom,
++                             const struct bcm47xx_sprom_fill *fill)
 +{
-+      bcm53xx_sprom_fill_ethernet(sprom, fill);
-+      bcm53xx_sprom_fill_board_data(sprom, fill);
++      bcm47xx_sprom_fill_ethernet(sprom, fill);
++      bcm47xx_sprom_fill_board_data(sprom, fill);
 +
 +      nvram_read_u8(fill, NULL, "sromrev", &sprom->revision, 0);
 +
 +      switch (sprom->revision) {
 +      case 1:
-+              bcm53xx_sprom_fill_r1234589(sprom, fill);
-+              bcm53xx_sprom_fill_r12389(sprom, fill);
-+              bcm53xx_sprom_fill_r1(sprom, fill);
++              bcm47xx_sprom_fill_r1234589(sprom, fill);
++              bcm47xx_sprom_fill_r12389(sprom, fill);
++              bcm47xx_sprom_fill_r1(sprom, fill);
 +              break;
 +      case 2:
-+              bcm53xx_sprom_fill_r1234589(sprom, fill);
-+              bcm53xx_sprom_fill_r12389(sprom, fill);
-+              bcm53xx_sprom_fill_r2389(sprom, fill);
++              bcm47xx_sprom_fill_r1234589(sprom, fill);
++              bcm47xx_sprom_fill_r12389(sprom, fill);
++              bcm47xx_sprom_fill_r2389(sprom, fill);
 +              break;
 +      case 3:
-+              bcm53xx_sprom_fill_r1234589(sprom, fill);
-+              bcm53xx_sprom_fill_r12389(sprom, fill);
-+              bcm53xx_sprom_fill_r2389(sprom, fill);
-+              bcm53xx_sprom_fill_r389(sprom, fill);
-+              bcm53xx_sprom_fill_r3(sprom, fill);
++              bcm47xx_sprom_fill_r1234589(sprom, fill);
++              bcm47xx_sprom_fill_r12389(sprom, fill);
++              bcm47xx_sprom_fill_r2389(sprom, fill);
++              bcm47xx_sprom_fill_r389(sprom, fill);
++              bcm47xx_sprom_fill_r3(sprom, fill);
 +              break;
 +      case 4:
 +      case 5:
-+              bcm53xx_sprom_fill_r1234589(sprom, fill);
-+              bcm53xx_sprom_fill_r4589(sprom, fill);
-+              bcm53xx_sprom_fill_r458(sprom, fill);
-+              bcm53xx_sprom_fill_r45(sprom, fill);
-+              bcm53xx_sprom_fill_path_r4589(sprom, fill);
-+              bcm53xx_sprom_fill_path_r45(sprom, fill);
++              bcm47xx_sprom_fill_r1234589(sprom, fill);
++              bcm47xx_sprom_fill_r4589(sprom, fill);
++              bcm47xx_sprom_fill_r458(sprom, fill);
++              bcm47xx_sprom_fill_r45(sprom, fill);
++              bcm47xx_sprom_fill_path_r4589(sprom, fill);
++              bcm47xx_sprom_fill_path_r45(sprom, fill);
 +              break;
 +      case 8:
-+              bcm53xx_sprom_fill_r1234589(sprom, fill);
-+              bcm53xx_sprom_fill_r12389(sprom, fill);
-+              bcm53xx_sprom_fill_r2389(sprom, fill);
-+              bcm53xx_sprom_fill_r389(sprom, fill);
-+              bcm53xx_sprom_fill_r4589(sprom, fill);
-+              bcm53xx_sprom_fill_r458(sprom, fill);
-+              bcm53xx_sprom_fill_r89(sprom, fill);
-+              bcm53xx_sprom_fill_path_r4589(sprom, fill);
++              bcm47xx_sprom_fill_r1234589(sprom, fill);
++              bcm47xx_sprom_fill_r12389(sprom, fill);
++              bcm47xx_sprom_fill_r2389(sprom, fill);
++              bcm47xx_sprom_fill_r389(sprom, fill);
++              bcm47xx_sprom_fill_r4589(sprom, fill);
++              bcm47xx_sprom_fill_r458(sprom, fill);
++              bcm47xx_sprom_fill_r89(sprom, fill);
++              bcm47xx_sprom_fill_path_r4589(sprom, fill);
 +              break;
 +      case 9:
-+              bcm53xx_sprom_fill_r1234589(sprom, fill);
-+              bcm53xx_sprom_fill_r12389(sprom, fill);
-+              bcm53xx_sprom_fill_r2389(sprom, fill);
-+              bcm53xx_sprom_fill_r389(sprom, fill);
-+              bcm53xx_sprom_fill_r4589(sprom, fill);
-+              bcm53xx_sprom_fill_r89(sprom, fill);
-+              bcm53xx_sprom_fill_r9(sprom, fill);
-+              bcm53xx_sprom_fill_path_r4589(sprom, fill);
++              bcm47xx_sprom_fill_r1234589(sprom, fill);
++              bcm47xx_sprom_fill_r12389(sprom, fill);
++              bcm47xx_sprom_fill_r2389(sprom, fill);
++              bcm47xx_sprom_fill_r389(sprom, fill);
++              bcm47xx_sprom_fill_r4589(sprom, fill);
++              bcm47xx_sprom_fill_r89(sprom, fill);
++              bcm47xx_sprom_fill_r9(sprom, fill);
++              bcm47xx_sprom_fill_path_r4589(sprom, fill);
 +              break;
 +      default:
 +              pr_warn("Unsupported SPROM revision %d detected. Will extract v1\n",
 +                      sprom->revision);
 +              sprom->revision = 1;
-+              bcm53xx_sprom_fill_r1234589(sprom, fill);
-+              bcm53xx_sprom_fill_r12389(sprom, fill);
-+              bcm53xx_sprom_fill_r1(sprom, fill);
++              bcm47xx_sprom_fill_r1234589(sprom, fill);
++              bcm47xx_sprom_fill_r12389(sprom, fill);
++              bcm47xx_sprom_fill_r1(sprom, fill);
 +      }
 +}
 +
-+static int bcm53xx_sprom_getenv(const struct bcm53xx_sprom_fill *fill,
++static int bcm47xx_sprom_getenv(const struct bcm47xx_sprom_fill *fill,
 +                              const char *name, char *val, size_t val_len)
 +{
 +      const struct platform_device *nvram_dev = fill->priv;
@@ -606,15 +700,15 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
 +      return bcm47xx_nvram_getenv(&nvram_dev->dev, name, val, val_len);
 +};
 +
-+static int bcm53xx_sprom_probe(struct platform_device *pdev)
++static int bcm47xx_sprom_probe(struct platform_device *pdev)
 +{
 +      struct device *dev = &pdev->dev;
 +      struct device_node *np = dev->of_node;
 +      struct ssb_sprom *sprom;
-+      const phandle *handle;
++      const __be32 *handle;
 +      struct device_node *nvram_node;
 +      struct platform_device *nvram_dev;
-+      struct bcm53xx_sprom_fill fill;
++      struct bcm47xx_sprom_fill fill;
 +
 +      /* Alloc */
 +      sprom = devm_kzalloc(dev, sizeof(*sprom), GFP_KERNEL);
@@ -633,35 +727,36 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
 +      if (!nvram_dev)
 +              return -ENOMEM;
 +
-+      fill.prefix = NULL;
++      fill.prefix = of_get_property(np, "prefix", NULL);
++
 +      fill.fallback = false;
-+      fill.getenv = bcm53xx_sprom_getenv;
++      fill.getenv = bcm47xx_sprom_getenv;
 +      fill.priv = nvram_dev;
 +
-+      bcm53xx_sprom_fill(sprom, &fill);
++      bcm47xx_sprom_fill(sprom, &fill);
 +
 +      platform_set_drvdata(pdev, sprom);
 +
 +      return 0;
 +}
 +
-+static const struct of_device_id bcm53xx_sprom_of_match_table[] = {
-+      { .compatible = "brcm,bcm53xx-sprom", },
++static const struct of_device_id bcm47xx_sprom_of_match_table[] = {
++      { .compatible = "brcm,bcm47xx-sprom", },
 +      {},
 +};
 +MODULE_DEVICE_TABLE(of, mvebu_pcie_of_match_table);
 +
-+static struct platform_driver bcm53xx_sprom_driver = {
++static struct platform_driver bcm47xx_sprom_driver = {
 +      .driver = {
 +              .owner = THIS_MODULE,
-+              .name = "bcm53xx-sprom",
-+              .of_match_table = bcm53xx_sprom_of_match_table,
++              .name = "bcm47xx-sprom",
++              .of_match_table = bcm47xx_sprom_of_match_table,
 +              /* driver unloading/unbinding currently not supported */
 +              .suppress_bind_attrs = true,
 +      },
-+      .probe = bcm53xx_sprom_probe,
++      .probe = bcm47xx_sprom_probe,
 +};
-+module_platform_driver(bcm53xx_sprom_driver);
++module_platform_driver(bcm47xx_sprom_driver);
 +
 +MODULE_AUTHOR("Hauke Mehrtens <hauke@hauke-m.de>");
-+MODULE_LICENSE("GPLv2");
++MODULE_LICENSE("GPL v2");
index 0db670a..317fbdc 100644 (file)
@@ -1,17 +1,69 @@
-From bb5d497aeceb8d9f36a1d990538389b54748dfcd Mon Sep 17 00:00:00 2001
+From 04b91da96d7c163fd39c0849d2034e2928103f4d Mon Sep 17 00:00:00 2001
 From: Hauke Mehrtens <hauke@hauke-m.de>
 Date: Mon, 6 Jan 2014 23:29:15 +0100
-Subject: [PATCH 05/15] bcma: register bcma as device tree driver
+Subject: [PATCH 04/17] bcma: register bcma as device tree driver
 
-This driver is used by the bcm53xx ARM SoC code.Now it is possible to
-give the address of the chipcommon core in device tree.
+This driver is used by the bcm53xx ARM SoC code. Now it is possible to
+give the address of the chipcommon core in device tree and bcma will
+search for all the other cores.
 
 Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
 ---
- drivers/bcma/host_soc.c   | 70 +++++++++++++++++++++++++++++++++++++++++++++++
- include/linux/bcma/bcma.h |  2 ++
- 2 files changed, 72 insertions(+)
+ Documentation/devicetree/bindings/bus/bcma.txt | 46 +++++++++++++++++
+ drivers/bcma/host_soc.c                        | 70 ++++++++++++++++++++++++++
+ include/linux/bcma/bcma.h                      |  2 +
+ 3 files changed, 118 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/bus/bcma.txt
 
+--- /dev/null
++++ b/Documentation/devicetree/bindings/bus/bcma.txt
+@@ -0,0 +1,46 @@
++Broadcom AIX bcma bus driver
++
++
++Required properties:
++
++- compatible : brcm,bus-aix
++
++- reg : iomem address range of chipcommon core
++
++Optional properties:
++
++- sprom: reference to a sprom driver. This is needed for sprom less devices.
++       Use bcm47xx_sprom for example.
++
++
++The cores on the AIX bus are auto detected by bcma. Detection of the
++IRQ number is not supported on BCM47xx/BCM53xx ARM SoCs, so it is
++possible to provide the IRQ number over device tree. The IRQ number and
++the device tree child entry will be added to the core with the matching
++reg address.
++
++Example:
++
++      aix@18000000 {
++              compatible = "brcm,bus-aix";
++              reg = <0x18000000 0x1000>;
++              ranges = <0x00000000 0x18000000 0x00100000>;
++              #address-cells = <1>;
++              #size-cells = <1>;
++              sprom = <&sprom0>;
++
++              gmac@0 {
++                      reg = <0x18024000 0x1000>;
++                      interrupts = <GIC_SPI 147 IRQ_TYPE_LEVEL_HIGH>;
++              };
++
++              gmac@1 {
++                      reg = <0x18025000 0x1000>;
++                      interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
++              };
++
++              pcie@0 {
++                      reg = <0x18012000 0x1000>;
++                      interrupts = <GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>;
++              };
++      };
 --- a/drivers/bcma/host_soc.c
 +++ b/drivers/bcma/host_soc.c
 @@ -7,6 +7,9 @@
index f81541f..d9a831c 100644 (file)
@@ -1,10 +1,14 @@
-From 3e59da41882a408064cd23f4c9124a7938bdb91f Mon Sep 17 00:00:00 2001
+From eaf1943a2c49cbc6eb0ffafa7b6ced45f2d328da Mon Sep 17 00:00:00 2001
 From: Hauke Mehrtens <hauke@hauke-m.de>
 Date: Thu, 9 Jan 2014 19:40:14 +0100
-Subject: [PATCH 06/15] bcma: get irqs from dt
+Subject: [PATCH 05/17] bcma: get IRQ numbers from dt
 
-If bcma was registered with device tree it will search for some nodes
-with the irq number and add it to the core configuration.
+It is not possible to auto detect the irq numbers used by the cores on
+an arm SoC. If bcma was registered with device tree it will search for
+some device tree nodes with the irq number and add it to the core
+configuration.
+
+Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
 ---
  drivers/bcma/main.c | 42 +++++++++++++++++++++++++++++++++++++++++-
  1 file changed, 41 insertions(+), 1 deletion(-)
@@ -35,7 +39,7 @@ with the irq number and add it to the core configuration.
 +              return NULL;
 +
 +      for_each_child_of_node(parent->dev.of_node, node) {
-+              reg = of_get_address(node, 0, &size, 0);
++              reg = of_get_address(node, 0, &size, NULL);
 +              if (!reg)
 +                      continue;
 +              if (be32_to_cpup(reg) == core->addr)
index 0bf1308..fbc75ce 100644 (file)
@@ -1,7 +1,7 @@
-From 5d94449a92e4121b408e7cb8931a47984135eeea Mon Sep 17 00:00:00 2001
+From bd9106f5907080b467026bdaaea979fac8c7badb Mon Sep 17 00:00:00 2001
 From: Hauke Mehrtens <hauke@hauke-m.de>
 Date: Sun, 4 May 2014 14:34:31 +0200
-Subject: [PATCH 07/15] bcma: get sprom from devicetree
+Subject: [PATCH 06/17] bcma: get sprom from devicetree
 
 This patch make it possible to device an sprom provider in device tree
 and get the sprom from this driver. Every time there is such a provider
@@ -31,7 +31,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
 +static int bcma_fill_sprom_with_dt(struct bcma_bus *bus,
 +                                 struct ssb_sprom *out)
 +{
-+      const phandle *handle;
++      const __be32 *handle;
 +      struct device_node *sprom_node;
 +      struct platform_device *sprom_dev;
 +      struct ssb_sprom *sprom;
index 9d01f33..3b8c7f4 100644 (file)
@@ -1,7 +1,7 @@
-From 23bcd5e7cb2aaee48ba8b2351f032a230d948b6f Mon Sep 17 00:00:00 2001
+From 414f0ad9b3a8e8ee6eaf09c6d79d5f448ac28630 Mon Sep 17 00:00:00 2001
 From: Hauke Mehrtens <hauke@hauke-m.de>
 Date: Sat, 25 Jan 2014 17:03:07 +0100
-Subject: [PATCH 08/15] ARM: BCM5301X: register bcma bus
+Subject: [PATCH 07/17] ARM: BCM5301X: register bcma bus
 
 ---
  arch/arm/boot/dts/bcm4708.dtsi | 58 ++++++++++++++++++++++++++++++++++++++++++
@@ -19,7 +19,7 @@ Subject: [PATCH 08/15] ARM: BCM5301X: register bcma bus
 +      };
 +
 +      sprom0: sprom@0 {
-+              compatible = "brcm,bcm53xx-sprom";
++              compatible = "brcm,bcm47xx-sprom";
 +              nvram = <&nvram0>;
 +      };
 +
index 30e03e3..719b161 100644 (file)
@@ -1,15 +1,39 @@
-From f8ea60bbaf880d8d8d99fde3b5155f472e00141f Mon Sep 17 00:00:00 2001
+From c6516d2c672450fb27783866397a487511d90bba Mon Sep 17 00:00:00 2001
 From: Hauke Mehrtens <hauke@hauke-m.de>
-Date: Mon, 12 May 2014 20:16:39 +0200
-Subject: [PATCH 09/15] bcma: only map wrap if it is not null
+Date: Fri, 22 Aug 2014 08:44:52 +0200
+Subject: [PATCH 08/17] bcma: only map wrapper if its address is available
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
 
-The chipcommon B core does not have a wrap address and it would fail here.
+The Chipcommon B core does not have a wrap address and it would fail here.
 
 Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
 ---
- drivers/bcma/scan.c | 11 +++++++----
- 1 file changed, 7 insertions(+), 4 deletions(-)
+ drivers/bcma/host_soc.c |  4 ++++
+ drivers/bcma/scan.c     | 11 +++++++----
+ 2 files changed, 11 insertions(+), 4 deletions(-)
 
+--- a/drivers/bcma/host_soc.c
++++ b/drivers/bcma/host_soc.c
+@@ -137,12 +137,16 @@ static void bcma_host_soc_block_write(st
+ static u32 bcma_host_soc_aread32(struct bcma_device *core, u16 offset)
+ {
++      if (WARN_ONCE(!core->io_wrap, "Accessed core has no wrapper/agent\n"))
++              return ~0;
+       return readl(core->io_wrap + offset);
+ }
+ static void bcma_host_soc_awrite32(struct bcma_device *core, u16 offset,
+                                 u32 value)
+ {
++      if (WARN_ONCE(!core->io_wrap, "Accessed core has no wrapper/agent\n"))
++              return;
+       writel(value, core->io_wrap + offset);
+ }
 --- a/drivers/bcma/scan.c
 +++ b/drivers/bcma/scan.c
 @@ -421,10 +421,13 @@ static int bcma_get_next_core(struct bcm
index bb3ce62..edb9969 100644 (file)
@@ -1,7 +1,7 @@
-From 9317024aa1d8df94d3b021bc23b57f02a435e96c Mon Sep 17 00:00:00 2001
+From f8c6045ee00b82c1bb3f8b3446d723c4d50e6b08 Mon Sep 17 00:00:00 2001
 From: Hauke Mehrtens <hauke@hauke-m.de>
 Date: Mon, 12 May 2014 21:57:53 +0200
-Subject: [PATCH 10/15] bcma: store more alternative addresses
+Subject: [PATCH 09/17] bcma: store more alternative addresses
 
 Each core could have more than one alternative address. There are cores
 with 8 alternative addresses for different functions. The PHY control
index 312f63b..c744e38 100644 (file)
@@ -1,7 +1,7 @@
-From 6c0df4a483e41ef129caa8948b3bcde7f91de197 Mon Sep 17 00:00:00 2001
+From 30e85c691b905f15ef55ab9e1aea98ac35f5e31a Mon Sep 17 00:00:00 2001
 From: Hauke Mehrtens <hauke@hauke-m.de>
 Date: Mon, 12 May 2014 20:33:15 +0200
-Subject: [PATCH 11/15] bcma: add support for chipcommon B core
+Subject: [PATCH 10/17] bcma: add support for chipcommon B core
 
 This core is used on BCM4708 to configure the PCIe and USB3 PHYs and it
 contains the addresses to the Device Management unit. This will be used
index 23e8a02..75dd2d1 100644 (file)
@@ -1,7 +1,7 @@
-From ea422113a5d2778347db6136d95f45a50e2f2d29 Mon Sep 17 00:00:00 2001
+From cf72936c001056de1cfcb27dd9a232f5484ec59c Mon Sep 17 00:00:00 2001
 From: Hauke Mehrtens <hauke@hauke-m.de>
 Date: Thu, 29 May 2014 20:54:15 +0200
-Subject: [PATCH 13/15] pci: do not probe too early
+Subject: [PATCH 12/17] pci: do not probe too early
 
 Probing is done before the PCIe bridge is fully activated and the
 address spaces does not get assigned to the PCIe devices. Without the
index 83b72b4..13c4e06 100644 (file)
@@ -1,15 +1,24 @@
-From a0d83e0ad20f6dde0a71ed07da12ca3be8bbdc01 Mon Sep 17 00:00:00 2001
+From 5274195ed2aefa21bcc69de7ecbd13a88bd3f357 Mon Sep 17 00:00:00 2001
 From: Hauke Mehrtens <hauke@hauke-m.de>
-Date: Sun, 18 May 2014 17:15:24 +0200
-Subject: [PATCH 12/15] bcma: add PCI IDs for more devices
+Date: Sat, 23 Aug 2014 17:58:11 +0200
+Subject: [PATCH 11/17] bcma: add PCI ID for spromless BCM43217
 
-This adds the PCI IDs for the BCM4360 and BCM43227.
-Both devices were found on a Netgear R6250 with a BCM4708 ARM SoC.
+This adds the PCI ID a BCM43217 without a sprom.
+This devices was found on a Netgear R6250 attached to a BCM4708 ARM SoC.
+
+bcma: bus1: Found chip with id 0xA8D1, rev 0x00 and package 0x08
+bcma: bus1: Core 0 found: ChipCommon (manuf 0x4BF, id 0x800, rev 0x27, class 0x0)
+bcma: bus1: Core 1 found: IEEE 802.11 (manuf 0x4BF, id 0x812, rev 0x1E, class 0x0)
+bcma: bus1: Core 2 found: PCIe (manuf 0x4BF, id 0x820, rev 0x14, class 0x0)
+
+b43-phy0: Broadcom 43217 WLAN found (core revision 30)
+b43-phy0: Found PHY: Analog 9, Type 4 (N), Revision 17
+b43-phy0: Found Radio: Manuf 0x17F, ID 0x2057, Revision 14, Version 1
 
 Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
 ---
- drivers/bcma/host_pci.c | 2 ++
- 1 file changed, 2 insertions(+)
+ drivers/bcma/host_pci.c | +
+ 1 file changed, 1 insertion(+)
 
 --- a/drivers/bcma/host_pci.c
 +++ b/drivers/bcma/host_pci.c
@@ -17,7 +26,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
        { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x43a9) },
        { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x43aa) },
        { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4727) },
-+      { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 43227) },
++      { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 43227) },  /* 0xA8DB */
        { 0, },
  };
  MODULE_DEVICE_TABLE(pci, bcma_pci_bridge_tbl);
index 4e32ed8..2cdfebf 100644 (file)
@@ -1,18 +1,18 @@
-From 7475eee716d11f487076f78f26a6e403c06d0c76 Mon Sep 17 00:00:00 2001
+From cc2cda651fcbc498bf513a6b802dca19944bcb37 Mon Sep 17 00:00:00 2001
 From: Hauke Mehrtens <hauke@hauke-m.de>
 Date: Mon, 12 May 2014 11:55:20 +0200
-Subject: [PATCH 14/15] pcie2-bcma: add new PCIe2 driver for bcma
+Subject: [PATCH 13/17] pcie2-bcma: add new PCIe2 driver for bcma
 
 This driver supports the PCIe controller found on the BCM4708 and
 similar SoCs. The controller itself is automatically detected by bcma.
 
 Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
 ---
- arch/arm/mach-bcm/Kconfig     |   1 +
+ arch/arm/mach-bcm/Kconfig     |   2 +
  drivers/pci/host/Kconfig      |   7 +
  drivers/pci/host/Makefile     |   1 +
- drivers/pci/host/pcie2-bcma.c | 594 ++++++++++++++++++++++++++++++++++++++++++
- 4 files changed, 603 insertions(+)
+ drivers/pci/host/pcie2-bcma.c | 591 ++++++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 601 insertions(+)
  create mode 100644 drivers/pci/host/pcie2-bcma.c
 
 --- a/arch/arm/mach-bcm/Kconfig
@@ -48,7 +48,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
 +obj-$(CONFIG_PCI_BCMA) += pcie2-bcma.o
 --- /dev/null
 +++ b/drivers/pci/host/pcie2-bcma.c
-@@ -0,0 +1,594 @@
+@@ -0,0 +1,591 @@
 +/*
 + * Northstar PCI-Express driver
 + * Only supports Root-Complex (RC) mode
@@ -133,15 +133,14 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
 +                      return 0;
 +              bcma_write32(bdev, SOC_PCIE_EXT_CFG_ADDR, where & 0xffc);
 +              return SOC_PCIE_EXT_CFG_DATA;
-+      } else {
-+              if (fn > 1)
-+                      return 0;
-+              addr_reg = (busno & 0xff) << 20 | (slot << 15) | (fn << 12) |
-+                         (where & 0xffc) | (1 & 0x3);
-+
-+              bcma_write32(bdev, SOC_PCIE_CFG_ADDR, addr_reg);
-+              return SOC_PCIE_CFG_DATA;
 +      }
++      if (fn > 1)
++              return 0;
++      addr_reg = (busno & 0xff) << 20 | (slot << 15) | (fn << 12) |
++                 (where & 0xffc) | (1 & 0x3);
++
++      bcma_write32(bdev, SOC_PCIE_CFG_ADDR, addr_reg);
++      return SOC_PCIE_CFG_DATA;
 +}
 +
 +static u32 bcma_pcie2_read_config(struct bcma_device *bdev, int busno,
@@ -149,6 +148,8 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
 +{
 +      u32 base;
 +      u32 data_reg;
++      u32 mask;
++      int shift;
 +
 +      base = bcma_pcie2_cfg_base(bdev, busno, devfn, where);
 +
@@ -171,13 +172,12 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
 +      }
 +      /* HEADER_TYPE=00 indicates the port in EP mode */
 +
-+      if (size == 4) {
++      if (size == 4)
 +              return data_reg;
-+      } else {
-+              u32 mask = (1 << (size * 8)) - 1;
-+              int shift = (where % 4) * 8;
-+              return (data_reg >> shift) & mask;
-+      }
++
++      mask = (1 << (size * 8)) - 1;
++      shift = (where % 4) * 8;
++      return (data_reg >> shift) & mask;
 +}
 +
 +static void bcma_pcie2_write_config(struct bcma_device *bdev, int busno,
@@ -195,6 +195,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
 +      if (size < 4) {
 +              u32 mask = (1 << (size * 8)) - 1;
 +              int shift = (where % 4) * 8;
++
 +              data_reg = bcma_read32(bdev, base);
 +              data_reg &= ~(mask << shift);
 +              data_reg |= (val & mask) << shift;
@@ -528,11 +529,9 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
 +
 +      /* create mem resource */
 +      res = devm_kzalloc(&bdev->dev, sizeof(*res), GFP_KERNEL);
-+      if (!res) {
-+              dev_info(&bdev->dev, "requesting resource at 0x%x failed\n",
-+                       bdev->addr_s[0]);
++      if (!res)
 +              return -EINVAL;
-+      }
++
 +      res->start = bdev->addr_s[0];
 +      res->end = res->start + SZ_128M - 1;
 +      res->name = "PCIe Configuration Space";
@@ -542,11 +541,9 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
 +
 +      /* This PCIe controller does not support IO Mem, so use a dummy one. */
 +      res = devm_kzalloc(&bdev->dev, sizeof(*res), GFP_KERNEL);
-+      if (!res) {
-+              dev_info(&bdev->dev, "requesting resource at 0x%x failed\n",
-+                       bdev->addr_s[0]);
++      if (!res)
 +              return -EINVAL;
-+      }
++
 +      res->start = bdev->addr_s[0];
 +      res->end = res->start + SZ_128M - 1;
 +      res->name = "PCIe Configuration Space";