bcm53xx: update bcma device tree intergeneration and fix nvram parsing

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>

SVN-Revision: 42272
owl
Hauke Mehrtens 2014-08-24 15:57:49 +00:00
parent befad7432b
commit 823659f458
14 changed files with 475 additions and 241 deletions

View File

@ -42,7 +42,7 @@ CONFIG_B53=y
# CONFIG_B53_PHY_DRIVER is not set # CONFIG_B53_PHY_DRIVER is not set
CONFIG_B53_SRAB_DRIVER=y CONFIG_B53_SRAB_DRIVER=y
CONFIG_BCM47XX_NVRAM=y CONFIG_BCM47XX_NVRAM=y
CONFIG_BCM53XX_SPROM=y CONFIG_BCM47XX_SPROM=y
CONFIG_BCMA=y CONFIG_BCMA=y
CONFIG_BCMA_BLOCKIO=y CONFIG_BCMA_BLOCKIO=y
CONFIG_BCMA_DEBUG=y CONFIG_BCMA_DEBUG=y

View 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> From: Hauke Mehrtens <hauke@hauke-m.de>
Date: Sun, 4 May 2014 16:35:42 +0200 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 Moving mach-bcm47xx/bcm47xx_nvram.h to include/linux/bcm47xx_nvram.h
header on the arm bcm47xx (BCM5301X) devices. This way a driver gets makes it possible to reuse this header on the ARM based bcm47xx/bcm53xx
the correct functions to access the nvram depending on the SoC it boots SoCs (e.g. BCM5301X devices). Broadcom uses ARM CPUs in their new SoC
for. 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/board.c | 2 +-
arch/mips/bcm47xx/nvram.c | 2 +- arch/mips/bcm47xx/nvram.c | 2 +-
arch/mips/bcm47xx/setup.c | 2 +- arch/mips/bcm47xx/setup.c | 2 +-
arch/mips/bcm47xx/sprom.c | 2 +- arch/mips/bcm47xx/sprom.c | 2 +-
arch/mips/bcm47xx/time.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/b44.c | 8 +--
drivers/net/ethernet/broadcom/bgmac.c | 2 +- drivers/net/ethernet/broadcom/bgmac.c | 2 +-
drivers/ssb/driver_chipcommon_pmu.c | 6 +- drivers/ssb/driver_chipcommon_pmu.c | 6 +-
include/linux/bcm47xx_nvram.h | 65 ++++++++++++++++++++++ include/linux/bcm47xx_nvram.h | 66 ++++++++++++++++++++++
10 files changed, 73 insertions(+), 71 deletions(-) 10 files changed, 74 insertions(+), 71 deletions(-)
delete mode 100644 arch/mips/include/asm/mach-bcm47xx/bcm47xx_nvram.h delete mode 100644 arch/mips/include/asm/mach-bcm47xx/bcm47xx_nvram.h
create mode 100644 include/linux/bcm47xx_nvram.h create mode 100644 include/linux/bcm47xx_nvram.h
@ -202,7 +210,7 @@ for.
switch (bus->chip_id) { switch (bus->chip_id) {
--- /dev/null --- /dev/null
+++ b/include/linux/bcm47xx_nvram.h +++ b/include/linux/bcm47xx_nvram.h
@@ -0,0 +1,65 @@ @@ -0,0 +1,66 @@
+/* +/*
+ * Copyright (C) 2005, Broadcom Corporation + * Copyright (C) 2005, Broadcom Corporation
+ * Copyright (C) 2006, Felix Fietkau <nbd@openwrt.org> + * Copyright (C) 2006, Felix Fietkau <nbd@openwrt.org>
@ -243,7 +251,8 @@ for.
+ +
+int bcm47xx_nvram_gpio_pin(const char *name); +int bcm47xx_nvram_gpio_pin(const char *name);
+#else +#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; + return -ENXIO;
+} +}

View 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> From: Hauke Mehrtens <hauke@hauke-m.de>
Date: Sat, 3 May 2014 22:54:59 +0200 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 This adds a new driver which searches at a given memory range for a
access to other drivers. You have to specify the memory ranges where nvram like it is used on the bcm47xx and bcm53xx SoCs with ARM and MIPS
the flash chip is mapped and this driver will search there for some CPUs. This driver provides acces to this nvram to other device in the
nvram and parse it. Other drivers can use this driver to access 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 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 +++--- .../devicetree/bindings/misc/bcm47xx-nvram.txt | 19 ++
arch/mips/bcm47xx/board.c | 40 ++--
arch/mips/bcm47xx/nvram.c | 7 +- arch/mips/bcm47xx/nvram.c | 7 +-
arch/mips/bcm47xx/setup.c | 4 +- arch/mips/bcm47xx/setup.c | 4 +-
arch/mips/bcm47xx/sprom.c | 4 +- arch/mips/bcm47xx/sprom.c | 4 +-
arch/mips/bcm47xx/time.c | 2 +- arch/mips/bcm47xx/time.c | 2 +-
drivers/misc/Kconfig | 5 + drivers/misc/Kconfig | 5 +
drivers/misc/Makefile | 1 + drivers/misc/Makefile | 1 +
drivers/misc/bcm47xx-nvram.c | 211 ++++++++++++++++++++++++++++++++++ drivers/misc/bcm47xx-nvram.c | 215 +++++++++++++++++++++
drivers/net/ethernet/broadcom/b44.c | 2 +- drivers/net/ethernet/broadcom/b44.c | 2 +-
drivers/net/ethernet/broadcom/bgmac.c | 4 +- drivers/net/ethernet/broadcom/bgmac.c | 5 +-
drivers/ssb/driver_chipcommon_pmu.c | 2 +- drivers/ssb/driver_chipcommon_pmu.c | 3 +-
include/linux/bcm47xx_nvram.h | 16 ++- include/linux/bcm47xx_nvram.h | 17 +-
12 files changed, 259 insertions(+), 35 deletions(-) 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 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 --- a/arch/mips/bcm47xx/board.c
+++ b/arch/mips/bcm47xx/board.c +++ b/arch/mips/bcm47xx/board.c
@@ -196,50 +196,50 @@ static __init const struct bcm47xx_board @@ -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 +obj-$(CONFIG_BCM47XX_NVRAM) += bcm47xx-nvram.o
--- /dev/null --- /dev/null
+++ b/drivers/misc/bcm47xx-nvram.c +++ b/drivers/misc/bcm47xx-nvram.c
@@ -0,0 +1,211 @@ @@ -0,0 +1,215 @@
+/* +/*
+ * BCM947xx nvram variable access + * 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) +static u32 find_nvram_size(void __iomem *end)
+{ +{
+ struct nvram_header *header; + struct nvram_header __iomem *header;
+ int i; + int i;
+ +
+ for (i = 0; i < ARRAY_SIZE(nvram_sizes); i++) { + for (i = 0; i < ARRAY_SIZE(nvram_sizes); i++) {
+ header = (struct nvram_header *)(end - nvram_sizes[i]); + header = (struct nvram_header __iomem *)(end - nvram_sizes[i]);
+ if (header->magic == NVRAM_HEADER) + if (__raw_readl(&header->magic) == NVRAM_HEADER)
+ return nvram_sizes[i]; + 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 len, char **nvram_buf,
+ size_t *nvram_len) + size_t *nvram_len)
+{ +{
+ struct nvram_header *header; + struct nvram_header __iomem *header;
+ int i; + int i;
+ u32 off; + u32 off;
+ u32 *src, *dst; + u32 *dst;
+ __le32 __iomem *src;
+ u32 size; + u32 size;
+ +
+ /* TODO: when nvram is on nand flash check for bad blocks first. */ + /* 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 */ + /* Windowed flash access */
+ size = find_nvram_size(base + off); + size = find_nvram_size(base + off);
+ if (size) { + if (size) {
+ header = (struct nvram_header *)(base + off - size); + header = (struct nvram_header __iomem *)
+ (base + off - size);
+ goto found; + goto found;
+ } + }
+ off <<= 1; + off += 0x10000;
+ } + }
+ +
+ /* Try embedded NVRAM at 4 KB and 1 KB as last resorts */ + /* Try embedded NVRAM at 4 KB and 1 KB as last resorts */
+ header = (struct nvram_header *)(base + 4096); + header = (struct nvram_header __iomem *)(base + 4096);
+ if (header->magic == NVRAM_HEADER) { + if (__raw_readl(&header->magic) == NVRAM_HEADER) {
+ size = NVRAM_SPACE; + size = NVRAM_SPACE;
+ goto found; + goto found;
+ } + }
+ +
+ header = (struct nvram_header *)(base + 1024); + header = (struct nvram_header __iomem *)(base + 1024);
+ if (header->magic == NVRAM_HEADER) { + if (__raw_readl(&header->magic) == NVRAM_HEADER) {
+ size = NVRAM_SPACE; + size = NVRAM_SPACE;
+ goto found; + goto found;
+ } + }
@ -313,25 +349,26 @@ mac address and also for configuration values in the vendor firmware.
+ return -ENXIO; + return -ENXIO;
+ +
+found: +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"); + 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); + *nvram_buf = devm_kzalloc(dev, *nvram_len, GFP_KERNEL);
+ if (!*nvram_buf) + if (!*nvram_buf)
+ return -ENOMEM; + return -ENOMEM;
+ +
+ src = (u32 *) header; + src = (__le32 __iomem *) header;
+ dst = (u32 *) *nvram_buf; + dst = (u32 *) *nvram_buf;
+ for (i = 0; i < sizeof(struct nvram_header); i += 4) + for (i = 0; i < sizeof(struct nvram_header); i += 4)
+ *dst++ = *src++; + *dst++ = __raw_readl(src++);
+ for (; i < *nvram_len; i += 4) + for (; i < *nvram_len; i += 4)
+ *dst++ = le32_to_cpu(*src++); + *dst++ = readl(src++);
+ +
+ return 0; + 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; + char *var, *value, *end, *eq;
+ struct bcm47xx_nvram *nvram; + struct bcm47xx_nvram *nvram;
@ -407,7 +444,8 @@ mac address and also for configuration values in the vendor firmware.
+ if (!mmio) + if (!mmio)
+ return -ENOMEM; + 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) + if (err)
+ goto err_unmap_mmio; + 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); err = __b44_readphy(bp, 0, MII_BMCR, &val);
--- a/drivers/net/ethernet/broadcom/bgmac.c --- a/drivers/net/ethernet/broadcom/bgmac.c
+++ b/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; BGMAC_CHIPCTL_1_IF_TYPE_MII;
char buf[4]; char buf[4];
- if (bcm47xx_nvram_getenv("et_swtype", buf, sizeof(buf)) > 0) { - 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)) if (kstrtou8(buf, 0, &et_swtype))
bgmac_err(bgmac, "Failed to parse et_swtype (%s)\n", bgmac_err(bgmac, "Failed to parse et_swtype (%s)\n",
buf); 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; 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 */ /* TODO: reset the external phy. Specs are needed */
--- a/drivers/ssb/driver_chipcommon_pmu.c --- a/drivers/ssb/driver_chipcommon_pmu.c
+++ b/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) { if (bus->bustype == SSB_BUSTYPE_SSB) {
char buf[20]; char buf[20];
- if (bcm47xx_nvram_getenv("xtalfreq", buf, sizeof(buf)) >= 0) - 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); crystalfreq = simple_strtoul(buf, NULL, 0);
} }
--- a/include/linux/bcm47xx_nvram.h --- a/include/linux/bcm47xx_nvram.h
+++ b/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/types.h>
#include <linux/kernel.h> #include <linux/kernel.h>
@ -490,8 +530,12 @@ mac address and also for configuration values in the vendor firmware.
+ +
struct nvram_header { struct nvram_header {
u32 magic; u32 magic;
u32 len; - u32 len;
@@ -33,17 +35,21 @@ struct nvram_header { + __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_VALUE_LEN 255
#define NVRAM_MAX_PARAM_LEN 64 #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 char *name);
+int bcm47xx_nvram_gpio_pin(const struct device *dev, const char *name); +int bcm47xx_nvram_gpio_pin(const struct device *dev, const char *name);
#else #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, +static inline int bcm47xx_nvram_getenv(const struct device *dev,
+ const char *name, char *val, + const char *name, char *val,
+ size_t val_len) size_t val_len)
{ {
return -ENXIO; return -ENXIO;
} }

View 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> From: Hauke Mehrtens <hauke@hauke-m.de>
Date: Sun, 4 May 2014 13:19:20 +0200 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 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 wifi chip the mac address and some more board description data is
stores in the sprom. 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> Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
--- ---
drivers/misc/Kconfig | 5 + .../devicetree/bindings/misc/bcm47xx-sprom.txt | 16 +
drivers/misc/Kconfig | 11 +
drivers/misc/Makefile | 1 + drivers/misc/Makefile | 1 +
drivers/misc/bcm53xx-sprom.c | 625 +++++++++++++++++++++++++++++++++++++++++++ drivers/misc/bcm47xx-sprom.c | 690 +++++++++++++++++++++
3 files changed, 631 insertions(+) 4 files changed, 718 insertions(+)
create mode 100644 drivers/misc/bcm53xx-sprom.c 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 --- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig
@@ -520,6 +520,11 @@ config BCM47XX_NVRAM @@ -520,6 +520,17 @@ config BCM47XX_NVRAM
help help
This adds support for the brcm47xx nvram driver. This adds support for the brcm47xx nvram driver.
+config BCM53XX_SPROM +config BCM47XX_SPROM
+ tristate "BCM53XX sprom driver" + tristate "BCM47XX sprom driver"
+ help + 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/c2port/Kconfig"
source "drivers/misc/eeprom/Kconfig" source "drivers/misc/eeprom/Kconfig"
@ -36,12 +66,12 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
obj-y += mic/ obj-y += mic/
obj-$(CONFIG_GENWQE) += genwqe/ obj-$(CONFIG_GENWQE) += genwqe/
obj-$(CONFIG_BCM47XX_NVRAM) += bcm47xx-nvram.o obj-$(CONFIG_BCM47XX_NVRAM) += bcm47xx-nvram.o
+obj-$(CONFIG_BCM53XX_SPROM) += bcm53xx-sprom.o +obj-$(CONFIG_BCM47XX_SPROM) += bcm47xx-sprom.o
--- /dev/null --- /dev/null
+++ b/drivers/misc/bcm53xx-sprom.c +++ b/drivers/misc/bcm47xx-sprom.c
@@ -0,0 +1,625 @@ @@ -0,0 +1,690 @@
+/* +/*
+ * BCM947xx nvram variable access + * BCM47xx/BCM53xx nvram variable access
+ * + *
+ * Copyright (C) 2005 Broadcom Corporation + * Copyright (C) 2005 Broadcom Corporation
+ * Copyright (C) 2004 Florian Schirmer <jolt@tuxbox.org> + * 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/io.h>
+#include <linux/ssb/ssb.h> +#include <linux/ssb/ssb.h>
+#include <linux/bcm47xx_nvram.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; + const char *prefix;
+ bool fallback; + 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; + const void *priv;
+}; +};
+ +
@ -88,8 +121,9 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+ snprintf(buf, len, "%s", name); + snprintf(buf, len, "%s", name);
+} +}
+ +
+static int get_nvram_var(const struct bcm53xx_sprom_fill *fill, const char *postfix, +static int get_nvram_var(const struct bcm47xx_sprom_fill *fill,
+ const char *name, char *buf, int len) + const char *postfix, const char *name, char *buf,
+ int len)
+{ +{
+ char key[40]; + char key[40];
+ int err; + int err;
@ -105,7 +139,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+} +}
+ +
+#define NVRAM_READ_VAL(type) \ +#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, \ + const char *postfix, const char *name, \
+ type *val, type allset) \ + type *val, type allset) \
+{ \ +{ \
@ -134,8 +168,8 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+ +
+#undef NVRAM_READ_VAL +#undef NVRAM_READ_VAL
+ +
+static void nvram_read_u32_2(const struct bcm53xx_sprom_fill *fill, const char *name, +static void nvram_read_u32_2(const struct bcm47xx_sprom_fill *fill,
+ u16 *val_lo, u16 *val_hi) + const char *name, u16 *val_lo, u16 *val_hi)
+{ +{
+ char buf[100]; + char buf[100];
+ int err; + int err;
@ -154,8 +188,9 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+ *val_hi = (val & 0xFFFF0000U) >> 16; + *val_hi = (val & 0xFFFF0000U) >> 16;
+} +}
+ +
+static void nvram_read_leddc(const struct bcm53xx_sprom_fill *fill, const char *name, +static void nvram_read_leddc(const struct bcm47xx_sprom_fill *fill,
+ u8 *leddc_on_time, u8 *leddc_off_time) + const char *name, u8 *leddc_on_time,
+ u8 *leddc_off_time)
+{ +{
+ char buf[100]; + char buf[100];
+ int err; + int err;
@ -178,8 +213,8 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+ *leddc_off_time = (val >> 16) & 0xff; + *leddc_off_time = (val >> 16) & 0xff;
+} +}
+ +
+static void nvram_read_macaddr(const struct bcm53xx_sprom_fill *fill, const char *name, +static void nvram_read_macaddr(const struct bcm47xx_sprom_fill *fill,
+ u8 val[6]) + const char *name, u8 val[6])
+{ +{
+ char buf[100]; + char buf[100];
+ int err; + int err;
@ -191,8 +226,8 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+ bcm47xx_nvram_parse_macaddr(buf, val); + bcm47xx_nvram_parse_macaddr(buf, val);
+} +}
+ +
+static void nvram_read_alpha2(const struct bcm53xx_sprom_fill *fill, const char *name, +static void nvram_read_alpha2(const struct bcm47xx_sprom_fill *fill,
+ char val[2]) + const char *name, char val[2])
+{ +{
+ char buf[10]; + char buf[10];
+ int err; + int err;
@ -209,9 +244,10 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+ memcpy(val, buf, 2); + memcpy(val, buf, 2);
+} +}
+ +
+static void bcm53xx_sprom_fill_r1234589(struct ssb_sprom *sprom, +static void bcm47xx_sprom_fill_r1234589(struct ssb_sprom *sprom,
+ const struct bcm53xx_sprom_fill *fill) + 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, "ledbh0", &sprom->gpio0, 0xff);
+ nvram_read_u8(fill, NULL, "ledbh1", &sprom->gpio1, 0xff); + nvram_read_u8(fill, NULL, "ledbh1", &sprom->gpio1, 0xff);
+ nvram_read_u8(fill, NULL, "ledbh2", &sprom->gpio2, 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); + nvram_read_alpha2(fill, "ccode", sprom->alpha2);
+} +}
+ +
+static void bcm53xx_sprom_fill_r12389(struct ssb_sprom *sprom, +static void bcm47xx_sprom_fill_r12389(struct ssb_sprom *sprom,
+ const struct bcm53xx_sprom_fill *fill) + const struct bcm47xx_sprom_fill *fill)
+{ +{
+ nvram_read_u16(fill, NULL, "pa0b0", &sprom->pa0b0, 0); + nvram_read_u16(fill, NULL, "pa0b0", &sprom->pa0b0, 0);
+ nvram_read_u16(fill, NULL, "pa0b1", &sprom->pa0b1, 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); + nvram_read_u8(fill, NULL, "pa1maxpwr", &sprom->maxpwr_a, 0);
+} +}
+ +
+static void bcm53xx_sprom_fill_r1(struct ssb_sprom *sprom, +static void bcm47xx_sprom_fill_r1(struct ssb_sprom *sprom,
+ const struct bcm53xx_sprom_fill *fill) + const struct bcm47xx_sprom_fill *fill)
+{ +{
+ nvram_read_u16(fill, NULL, "boardflags", &sprom->boardflags_lo, 0); + nvram_read_u16(fill, NULL, "boardflags", &sprom->boardflags_lo, 0);
+ nvram_read_u8(fill, NULL, "cc", &sprom->country_code, 0); + nvram_read_u8(fill, NULL, "cc", &sprom->country_code, 0);
+} +}
+ +
+static void bcm53xx_sprom_fill_r2389(struct ssb_sprom *sprom, +static void bcm47xx_sprom_fill_r2389(struct ssb_sprom *sprom,
+ const struct bcm53xx_sprom_fill *fill) + const struct bcm47xx_sprom_fill *fill)
+{ +{
+ nvram_read_u8(fill, NULL, "opo", &sprom->opo, 0); + nvram_read_u8(fill, NULL, "opo", &sprom->opo, 0);
+ nvram_read_u16(fill, NULL, "pa1lob0", &sprom->pa1lob0, 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); + nvram_read_u8(fill, NULL, "pa1himaxpwr", &sprom->maxpwr_ah, 0);
+} +}
+ +
+static void bcm53xx_sprom_fill_r389(struct ssb_sprom *sprom, +static void bcm47xx_sprom_fill_r389(struct ssb_sprom *sprom,
+ const struct bcm53xx_sprom_fill *fill) + const struct bcm47xx_sprom_fill *fill)
+{ +{
+ nvram_read_u8(fill, NULL, "bxa2g", &sprom->bxa2g, 0); + nvram_read_u8(fill, NULL, "bxa2g", &sprom->bxa2g, 0);
+ nvram_read_u8(fill, NULL, "rssisav2g", &sprom->rssisav2g, 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); + nvram_read_s8(fill, NULL, "rxpo5g", &sprom->rxpo5g, 0);
+} +}
+ +
+static void bcm53xx_sprom_fill_r3(struct ssb_sprom *sprom, +static void bcm47xx_sprom_fill_r3(struct ssb_sprom *sprom,
+ const struct bcm53xx_sprom_fill *fill) + const struct bcm47xx_sprom_fill *fill)
+{ +{
+ nvram_read_u8(fill, NULL, "regrev", &sprom->regrev, 0); + nvram_read_u8(fill, NULL, "regrev", &sprom->regrev, 0);
+ nvram_read_leddc(fill, "leddc", &sprom->leddc_on_time, + nvram_read_leddc(fill, "leddc", &sprom->leddc_on_time,
+ &sprom->leddc_off_time); + &sprom->leddc_off_time);
+} +}
+ +
+static void bcm53xx_sprom_fill_r4589(struct ssb_sprom *sprom, +static void bcm47xx_sprom_fill_r4589(struct ssb_sprom *sprom,
+ const struct bcm53xx_sprom_fill *fill) + const struct bcm47xx_sprom_fill *fill)
+{ +{
+ nvram_read_u8(fill, NULL, "regrev", &sprom->regrev, 0); + nvram_read_u8(fill, NULL, "regrev", &sprom->regrev, 0);
+ nvram_read_s8(fill, NULL, "ag2", &sprom->antenna_gain.a2, 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); + &sprom->leddc_off_time);
+} +}
+ +
+static void bcm53xx_sprom_fill_r458(struct ssb_sprom *sprom, +static void bcm47xx_sprom_fill_r458(struct ssb_sprom *sprom,
+ const struct bcm53xx_sprom_fill *fill) + const struct bcm47xx_sprom_fill *fill)
+{ +{
+ nvram_read_u16(fill, NULL, "cck2gpo", &sprom->cck2gpo, 0); + nvram_read_u16(fill, NULL, "cck2gpo", &sprom->cck2gpo, 0);
+ nvram_read_u32(fill, NULL, "ofdm2gpo", &sprom->ofdm2gpo, 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); + nvram_read_u16(fill, NULL, "mcs5ghpo7", &sprom->mcs5ghpo[7], 0);
+} +}
+ +
+static void bcm53xx_sprom_fill_r45(struct ssb_sprom *sprom, +static void bcm47xx_sprom_fill_r45(struct ssb_sprom *sprom,
+ const struct bcm53xx_sprom_fill *fill) + const struct bcm47xx_sprom_fill *fill)
+{ +{
+ nvram_read_u8(fill, NULL, "txpid2ga0", &sprom->txpid2g[0], 0); + nvram_read_u8(fill, NULL, "txpid2ga0", &sprom->txpid2g[0], 0);
+ nvram_read_u8(fill, NULL, "txpid2ga1", &sprom->txpid2g[1], 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); + nvram_read_u8(fill, NULL, "txpid5gha3", &sprom->txpid5gh[3], 0);
+} +}
+ +
+static void bcm53xx_sprom_fill_r89(struct ssb_sprom *sprom, +static void bcm47xx_sprom_fill_r89(struct ssb_sprom *sprom,
+ const struct bcm53xx_sprom_fill *fill) + const struct bcm47xx_sprom_fill *fill)
+{ +{
+ nvram_read_u8(fill, NULL, "tssipos2g", &sprom->fem.ghz2.tssipos, 0); + nvram_read_u8(fill, NULL, "tssipos2g", &sprom->fem.ghz2.tssipos, 0);
+ nvram_read_u8(fill, NULL, "extpagain2g", &sprom->fem.ghz2.extpa_gain, 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); + nvram_read_u8(fill, NULL, "pcieingress_war", &sprom->pcieingress_war, 0);
+} +}
+ +
+static void bcm53xx_sprom_fill_r9(struct ssb_sprom *sprom, +static void bcm47xx_sprom_fill_r9(struct ssb_sprom *sprom,
+ const struct bcm53xx_sprom_fill *fill) + const struct bcm47xx_sprom_fill *fill)
+{ +{
+ nvram_read_u16(fill, NULL, "cckbw202gpo", &sprom->cckbw202gpo, 0); + nvram_read_u16(fill, NULL, "cckbw202gpo", &sprom->cckbw202gpo, 0);
+ nvram_read_u16(fill, NULL, "cckbw20ul2gpo", &sprom->cckbw20ul2gpo, 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); + nvram_read_u8(fill, NULL, "sar5g", &sprom->sar5g, 0);
+} +}
+ +
+static void bcm53xx_sprom_fill_path_r4589(struct ssb_sprom *sprom, +static void bcm47xx_sprom_fill_path_r4589(struct ssb_sprom *sprom,
+ const struct bcm53xx_sprom_fill *fill) + const struct bcm47xx_sprom_fill *fill)
+{ +{
+ char postfix[2]; + char postfix[2];
+ int i; + int i;
+ +
+ for (i = 0; i < ARRAY_SIZE(sprom->core_pwr_info); 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]; + struct ssb_sprom_core_pwr_info *pwr_info = &sprom->core_pwr_info[i];
+
+ snprintf(postfix, sizeof(postfix), "%i", i); + snprintf(postfix, sizeof(postfix), "%i", i);
+ nvram_read_u8(fill, postfix, "maxp2ga", &pwr_info->maxpwr_2g, 0); + nvram_read_u8(fill, postfix, "maxp2ga", &pwr_info->maxpwr_2g, 0);
+ nvram_read_u8(fill, postfix, "itt2ga", &pwr_info->itssi_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, +static void bcm47xx_sprom_fill_path_r45(struct ssb_sprom *sprom,
+ const struct bcm53xx_sprom_fill *fill) + const struct bcm47xx_sprom_fill *fill)
+{ +{
+ char postfix[2]; + char postfix[2];
+ int i; + int i;
+ +
+ for (i = 0; i < ARRAY_SIZE(sprom->core_pwr_info); 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]; + struct ssb_sprom_core_pwr_info *pwr_info = &sprom->core_pwr_info[i];
+
+ snprintf(postfix, sizeof(postfix), "%i", i); + snprintf(postfix, sizeof(postfix), "%i", i);
+ nvram_read_u16(fill, postfix, "pa2gw3a", &pwr_info->pa_2g[3], 0); + nvram_read_u16(fill, postfix, "pa2gw3a", &pwr_info->pa_2g[3], 0);
+ nvram_read_u16(fill, postfix, "pa5gw3a", &pwr_info->pa_5g[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, +static bool bcm47xx_is_valid_mac(u8 *mac)
+ const struct bcm53xx_sprom_fill *fill) +{
+ 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_macaddr(fill, "et0macaddr", sprom->et0mac);
+ nvram_read_u8(fill, NULL, "et0mdcport", &sprom->et0mdcport, 0); + 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, "macaddr", sprom->il0mac);
+ nvram_read_macaddr(fill, "il0macaddr", 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, +static void bcm47xx_sprom_fill_board_data(struct ssb_sprom *sprom,
+ const struct bcm53xx_sprom_fill *fill) + const struct bcm47xx_sprom_fill *fill)
+{ +{
+ nvram_read_u16(fill, NULL, "boardrev", &sprom->board_rev, 0); + nvram_read_u16(fill, NULL, "boardrev", &sprom->board_rev, 0);
+ nvram_read_u16(fill, NULL, "boardnum", &sprom->board_num, 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); + &sprom->boardflags2_hi);
+} +}
+ +
+static void bcm53xx_sprom_fill(struct ssb_sprom *sprom, +static void bcm47xx_sprom_fill(struct ssb_sprom *sprom,
+ const struct bcm53xx_sprom_fill *fill) + const struct bcm47xx_sprom_fill *fill)
+{ +{
+ bcm53xx_sprom_fill_ethernet(sprom, fill); + bcm47xx_sprom_fill_ethernet(sprom, fill);
+ bcm53xx_sprom_fill_board_data(sprom, fill); + bcm47xx_sprom_fill_board_data(sprom, fill);
+ +
+ nvram_read_u8(fill, NULL, "sromrev", &sprom->revision, 0); + nvram_read_u8(fill, NULL, "sromrev", &sprom->revision, 0);
+ +
+ switch (sprom->revision) { + switch (sprom->revision) {
+ case 1: + case 1:
+ bcm53xx_sprom_fill_r1234589(sprom, fill); + bcm47xx_sprom_fill_r1234589(sprom, fill);
+ bcm53xx_sprom_fill_r12389(sprom, fill); + bcm47xx_sprom_fill_r12389(sprom, fill);
+ bcm53xx_sprom_fill_r1(sprom, fill); + bcm47xx_sprom_fill_r1(sprom, fill);
+ break; + break;
+ case 2: + case 2:
+ bcm53xx_sprom_fill_r1234589(sprom, fill); + bcm47xx_sprom_fill_r1234589(sprom, fill);
+ bcm53xx_sprom_fill_r12389(sprom, fill); + bcm47xx_sprom_fill_r12389(sprom, fill);
+ bcm53xx_sprom_fill_r2389(sprom, fill); + bcm47xx_sprom_fill_r2389(sprom, fill);
+ break; + break;
+ case 3: + case 3:
+ bcm53xx_sprom_fill_r1234589(sprom, fill); + bcm47xx_sprom_fill_r1234589(sprom, fill);
+ bcm53xx_sprom_fill_r12389(sprom, fill); + bcm47xx_sprom_fill_r12389(sprom, fill);
+ bcm53xx_sprom_fill_r2389(sprom, fill); + bcm47xx_sprom_fill_r2389(sprom, fill);
+ bcm53xx_sprom_fill_r389(sprom, fill); + bcm47xx_sprom_fill_r389(sprom, fill);
+ bcm53xx_sprom_fill_r3(sprom, fill); + bcm47xx_sprom_fill_r3(sprom, fill);
+ break; + break;
+ case 4: + case 4:
+ case 5: + case 5:
+ bcm53xx_sprom_fill_r1234589(sprom, fill); + bcm47xx_sprom_fill_r1234589(sprom, fill);
+ bcm53xx_sprom_fill_r4589(sprom, fill); + bcm47xx_sprom_fill_r4589(sprom, fill);
+ bcm53xx_sprom_fill_r458(sprom, fill); + bcm47xx_sprom_fill_r458(sprom, fill);
+ bcm53xx_sprom_fill_r45(sprom, fill); + bcm47xx_sprom_fill_r45(sprom, fill);
+ bcm53xx_sprom_fill_path_r4589(sprom, fill); + bcm47xx_sprom_fill_path_r4589(sprom, fill);
+ bcm53xx_sprom_fill_path_r45(sprom, fill); + bcm47xx_sprom_fill_path_r45(sprom, fill);
+ break; + break;
+ case 8: + case 8:
+ bcm53xx_sprom_fill_r1234589(sprom, fill); + bcm47xx_sprom_fill_r1234589(sprom, fill);
+ bcm53xx_sprom_fill_r12389(sprom, fill); + bcm47xx_sprom_fill_r12389(sprom, fill);
+ bcm53xx_sprom_fill_r2389(sprom, fill); + bcm47xx_sprom_fill_r2389(sprom, fill);
+ bcm53xx_sprom_fill_r389(sprom, fill); + bcm47xx_sprom_fill_r389(sprom, fill);
+ bcm53xx_sprom_fill_r4589(sprom, fill); + bcm47xx_sprom_fill_r4589(sprom, fill);
+ bcm53xx_sprom_fill_r458(sprom, fill); + bcm47xx_sprom_fill_r458(sprom, fill);
+ bcm53xx_sprom_fill_r89(sprom, fill); + bcm47xx_sprom_fill_r89(sprom, fill);
+ bcm53xx_sprom_fill_path_r4589(sprom, fill); + bcm47xx_sprom_fill_path_r4589(sprom, fill);
+ break; + break;
+ case 9: + case 9:
+ bcm53xx_sprom_fill_r1234589(sprom, fill); + bcm47xx_sprom_fill_r1234589(sprom, fill);
+ bcm53xx_sprom_fill_r12389(sprom, fill); + bcm47xx_sprom_fill_r12389(sprom, fill);
+ bcm53xx_sprom_fill_r2389(sprom, fill); + bcm47xx_sprom_fill_r2389(sprom, fill);
+ bcm53xx_sprom_fill_r389(sprom, fill); + bcm47xx_sprom_fill_r389(sprom, fill);
+ bcm53xx_sprom_fill_r4589(sprom, fill); + bcm47xx_sprom_fill_r4589(sprom, fill);
+ bcm53xx_sprom_fill_r89(sprom, fill); + bcm47xx_sprom_fill_r89(sprom, fill);
+ bcm53xx_sprom_fill_r9(sprom, fill); + bcm47xx_sprom_fill_r9(sprom, fill);
+ bcm53xx_sprom_fill_path_r4589(sprom, fill); + bcm47xx_sprom_fill_path_r4589(sprom, fill);
+ break; + break;
+ default: + default:
+ pr_warn("Unsupported SPROM revision %d detected. Will extract v1\n", + pr_warn("Unsupported SPROM revision %d detected. Will extract v1\n",
+ sprom->revision); + sprom->revision);
+ sprom->revision = 1; + sprom->revision = 1;
+ bcm53xx_sprom_fill_r1234589(sprom, fill); + bcm47xx_sprom_fill_r1234589(sprom, fill);
+ bcm53xx_sprom_fill_r12389(sprom, fill); + bcm47xx_sprom_fill_r12389(sprom, fill);
+ bcm53xx_sprom_fill_r1(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 char *name, char *val, size_t val_len)
+{ +{
+ const struct platform_device *nvram_dev = fill->priv; + 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); + 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 *dev = &pdev->dev;
+ struct device_node *np = dev->of_node; + struct device_node *np = dev->of_node;
+ struct ssb_sprom *sprom; + struct ssb_sprom *sprom;
+ const phandle *handle; + const __be32 *handle;
+ struct device_node *nvram_node; + struct device_node *nvram_node;
+ struct platform_device *nvram_dev; + struct platform_device *nvram_dev;
+ struct bcm53xx_sprom_fill fill; + struct bcm47xx_sprom_fill fill;
+ +
+ /* Alloc */ + /* Alloc */
+ sprom = devm_kzalloc(dev, sizeof(*sprom), GFP_KERNEL); + sprom = devm_kzalloc(dev, sizeof(*sprom), GFP_KERNEL);
@ -633,35 +727,36 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+ if (!nvram_dev) + if (!nvram_dev)
+ return -ENOMEM; + return -ENOMEM;
+ +
+ fill.prefix = NULL; + fill.prefix = of_get_property(np, "prefix", NULL);
+
+ fill.fallback = false; + fill.fallback = false;
+ fill.getenv = bcm53xx_sprom_getenv; + fill.getenv = bcm47xx_sprom_getenv;
+ fill.priv = nvram_dev; + fill.priv = nvram_dev;
+ +
+ bcm53xx_sprom_fill(sprom, &fill); + bcm47xx_sprom_fill(sprom, &fill);
+ +
+ platform_set_drvdata(pdev, sprom); + platform_set_drvdata(pdev, sprom);
+ +
+ return 0; + return 0;
+} +}
+ +
+static const struct of_device_id bcm53xx_sprom_of_match_table[] = { +static const struct of_device_id bcm47xx_sprom_of_match_table[] = {
+ { .compatible = "brcm,bcm53xx-sprom", }, + { .compatible = "brcm,bcm47xx-sprom", },
+ {}, + {},
+}; +};
+MODULE_DEVICE_TABLE(of, mvebu_pcie_of_match_table); +MODULE_DEVICE_TABLE(of, mvebu_pcie_of_match_table);
+ +
+static struct platform_driver bcm53xx_sprom_driver = { +static struct platform_driver bcm47xx_sprom_driver = {
+ .driver = { + .driver = {
+ .owner = THIS_MODULE, + .owner = THIS_MODULE,
+ .name = "bcm53xx-sprom", + .name = "bcm47xx-sprom",
+ .of_match_table = bcm53xx_sprom_of_match_table, + .of_match_table = bcm47xx_sprom_of_match_table,
+ /* driver unloading/unbinding currently not supported */ + /* driver unloading/unbinding currently not supported */
+ .suppress_bind_attrs = true, + .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_AUTHOR("Hauke Mehrtens <hauke@hauke-m.de>");
+MODULE_LICENSE("GPL v2"); +MODULE_LICENSE("GPL v2");

View 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> From: Hauke Mehrtens <hauke@hauke-m.de>
Date: Mon, 6 Jan 2014 23:29:15 +0100 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 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. 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> Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
--- ---
drivers/bcma/host_soc.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++ Documentation/devicetree/bindings/bus/bcma.txt | 46 +++++++++++++++++
include/linux/bcma/bcma.h | 2 ++ drivers/bcma/host_soc.c | 70 ++++++++++++++++++++++++++
2 files changed, 72 insertions(+) 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 --- a/drivers/bcma/host_soc.c
+++ b/drivers/bcma/host_soc.c +++ b/drivers/bcma/host_soc.c
@@ -7,6 +7,9 @@ @@ -7,6 +7,9 @@

View 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> From: Hauke Mehrtens <hauke@hauke-m.de>
Date: Thu, 9 Jan 2014 19:40:14 +0100 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 It is not possible to auto detect the irq numbers used by the cores on
with the irq number and add it to the core configuration. 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 +++++++++++++++++++++++++++++++++++++++++- drivers/bcma/main.c | 42 +++++++++++++++++++++++++++++++++++++++++-
1 file changed, 41 insertions(+), 1 deletion(-) 1 file changed, 41 insertions(+), 1 deletion(-)
@ -35,7 +39,7 @@ with the irq number and add it to the core configuration.
+ return NULL; + return NULL;
+ +
+ for_each_child_of_node(parent->dev.of_node, node) { + 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) + if (!reg)
+ continue; + continue;
+ if (be32_to_cpup(reg) == core->addr) + if (be32_to_cpup(reg) == core->addr)

View 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> From: Hauke Mehrtens <hauke@hauke-m.de>
Date: Sun, 4 May 2014 14:34:31 +0200 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 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 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, +static int bcma_fill_sprom_with_dt(struct bcma_bus *bus,
+ struct ssb_sprom *out) + struct ssb_sprom *out)
+{ +{
+ const phandle *handle; + const __be32 *handle;
+ struct device_node *sprom_node; + struct device_node *sprom_node;
+ struct platform_device *sprom_dev; + struct platform_device *sprom_dev;
+ struct ssb_sprom *sprom; + struct ssb_sprom *sprom;

View 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> From: Hauke Mehrtens <hauke@hauke-m.de>
Date: Sat, 25 Jan 2014 17:03:07 +0100 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 ++++++++++++++++++++++++++++++++++++++++++ arch/arm/boot/dts/bcm4708.dtsi | 58 ++++++++++++++++++++++++++++++++++++++++++
@ -19,7 +19,7 @@ Subject: [PATCH 08/15] ARM: BCM5301X: register bcma bus
+ }; + };
+ +
+ sprom0: sprom@0 { + sprom0: sprom@0 {
+ compatible = "brcm,bcm53xx-sprom"; + compatible = "brcm,bcm47xx-sprom";
+ nvram = <&nvram0>; + nvram = <&nvram0>;
+ }; + };
+ +

View File

@ -1,14 +1,38 @@
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> From: Hauke Mehrtens <hauke@hauke-m.de>
Date: Mon, 12 May 2014 20:16:39 +0200 Date: Fri, 22 Aug 2014 08:44:52 +0200
Subject: [PATCH 09/15] bcma: only map wrap if it is not null 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: Hauke Mehrtens <hauke@hauke-m.de>
Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
--- ---
drivers/bcma/host_soc.c | 4 ++++
drivers/bcma/scan.c | 11 +++++++---- drivers/bcma/scan.c | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-) 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 --- a/drivers/bcma/scan.c
+++ b/drivers/bcma/scan.c +++ b/drivers/bcma/scan.c

View 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> From: Hauke Mehrtens <hauke@hauke-m.de>
Date: Mon, 12 May 2014 21:57:53 +0200 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 Each core could have more than one alternative address. There are cores
with 8 alternative addresses for different functions. The PHY control with 8 alternative addresses for different functions. The PHY control

View 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> From: Hauke Mehrtens <hauke@hauke-m.de>
Date: Mon, 12 May 2014 20:33:15 +0200 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 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 contains the addresses to the Device Management unit. This will be used

View 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> From: Hauke Mehrtens <hauke@hauke-m.de>
Date: Thu, 29 May 2014 20:54:15 +0200 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 Probing is done before the PCIe bridge is fully activated and the
address spaces does not get assigned to the PCIe devices. Without the address spaces does not get assigned to the PCIe devices. Without the

View 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> From: Hauke Mehrtens <hauke@hauke-m.de>
Date: Sun, 18 May 2014 17:15:24 +0200 Date: Sat, 23 Aug 2014 17:58:11 +0200
Subject: [PATCH 12/15] bcma: add PCI IDs for more devices Subject: [PATCH 11/17] bcma: add PCI ID for spromless BCM43217
This adds the PCI IDs for the BCM4360 and BCM43227. This adds the PCI ID a BCM43217 without a sprom.
Both devices were found on a Netgear R6250 with a BCM4708 ARM SoC. 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> Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
--- ---
drivers/bcma/host_pci.c | 2 ++ drivers/bcma/host_pci.c | 1 +
1 file changed, 2 insertions(+) 1 file changed, 1 insertion(+)
--- a/drivers/bcma/host_pci.c --- a/drivers/bcma/host_pci.c
+++ b/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, 0x43a9) },
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x43aa) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x43aa) },
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4727) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4727) },
+ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 43227) }, + { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 43227) }, /* 0xA8DB */
{ 0, }, { 0, },
}; };
MODULE_DEVICE_TABLE(pci, bcma_pci_bridge_tbl); MODULE_DEVICE_TABLE(pci, bcma_pci_bridge_tbl);

View 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> From: Hauke Mehrtens <hauke@hauke-m.de>
Date: Mon, 12 May 2014 11:55:20 +0200 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 This driver supports the PCIe controller found on the BCM4708 and
similar SoCs. The controller itself is automatically detected by bcma. similar SoCs. The controller itself is automatically detected by bcma.
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de> 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/Kconfig | 7 +
drivers/pci/host/Makefile | 1 + drivers/pci/host/Makefile | 1 +
drivers/pci/host/pcie2-bcma.c | 594 ++++++++++++++++++++++++++++++++++++++++++ drivers/pci/host/pcie2-bcma.c | 591 ++++++++++++++++++++++++++++++++++++++++++
4 files changed, 603 insertions(+) 4 files changed, 601 insertions(+)
create mode 100644 drivers/pci/host/pcie2-bcma.c create mode 100644 drivers/pci/host/pcie2-bcma.c
--- a/arch/arm/mach-bcm/Kconfig --- 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 +obj-$(CONFIG_PCI_BCMA) += pcie2-bcma.o
--- /dev/null --- /dev/null
+++ b/drivers/pci/host/pcie2-bcma.c +++ b/drivers/pci/host/pcie2-bcma.c
@@ -0,0 +1,594 @@ @@ -0,0 +1,591 @@
+/* +/*
+ * Northstar PCI-Express driver + * Northstar PCI-Express driver
+ * Only supports Root-Complex (RC) mode + * Only supports Root-Complex (RC) mode
@ -133,7 +133,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+ return 0; + return 0;
+ bcma_write32(bdev, SOC_PCIE_EXT_CFG_ADDR, where & 0xffc); + bcma_write32(bdev, SOC_PCIE_EXT_CFG_ADDR, where & 0xffc);
+ return SOC_PCIE_EXT_CFG_DATA; + return SOC_PCIE_EXT_CFG_DATA;
+ } else { + }
+ if (fn > 1) + if (fn > 1)
+ return 0; + return 0;
+ addr_reg = (busno & 0xff) << 20 | (slot << 15) | (fn << 12) | + addr_reg = (busno & 0xff) << 20 | (slot << 15) | (fn << 12) |
@ -142,13 +142,14 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+ bcma_write32(bdev, SOC_PCIE_CFG_ADDR, addr_reg); + bcma_write32(bdev, SOC_PCIE_CFG_ADDR, addr_reg);
+ return SOC_PCIE_CFG_DATA; + return SOC_PCIE_CFG_DATA;
+} +}
+}
+ +
+static u32 bcma_pcie2_read_config(struct bcma_device *bdev, int busno, +static u32 bcma_pcie2_read_config(struct bcma_device *bdev, int busno,
+ unsigned int devfn, int where, int size) + unsigned int devfn, int where, int size)
+{ +{
+ u32 base; + u32 base;
+ u32 data_reg; + u32 data_reg;
+ u32 mask;
+ int shift;
+ +
+ base = bcma_pcie2_cfg_base(bdev, busno, devfn, where); + base = bcma_pcie2_cfg_base(bdev, busno, devfn, where);
+ +
@ -171,14 +172,13 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+ } + }
+ /* HEADER_TYPE=00 indicates the port in EP mode */ + /* HEADER_TYPE=00 indicates the port in EP mode */
+ +
+ if (size == 4) { + if (size == 4)
+ return data_reg; + return data_reg;
+ } else { +
+ u32 mask = (1 << (size * 8)) - 1; + mask = (1 << (size * 8)) - 1;
+ int shift = (where % 4) * 8; + shift = (where % 4) * 8;
+ return (data_reg >> shift) & mask; + return (data_reg >> shift) & mask;
+} +}
+}
+ +
+static void bcma_pcie2_write_config(struct bcma_device *bdev, int busno, +static void bcma_pcie2_write_config(struct bcma_device *bdev, int busno,
+ unsigned int devfn, int where, int size, + unsigned int devfn, int where, int size,
@ -195,6 +195,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+ if (size < 4) { + if (size < 4) {
+ u32 mask = (1 << (size * 8)) - 1; + u32 mask = (1 << (size * 8)) - 1;
+ int shift = (where % 4) * 8; + int shift = (where % 4) * 8;
+
+ data_reg = bcma_read32(bdev, base); + data_reg = bcma_read32(bdev, base);
+ data_reg &= ~(mask << shift); + data_reg &= ~(mask << shift);
+ data_reg |= (val & mask) << shift; + data_reg |= (val & mask) << shift;
@ -528,11 +529,9 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+ +
+ /* create mem resource */ + /* create mem resource */
+ res = devm_kzalloc(&bdev->dev, sizeof(*res), GFP_KERNEL); + res = devm_kzalloc(&bdev->dev, sizeof(*res), GFP_KERNEL);
+ if (!res) { + if (!res)
+ dev_info(&bdev->dev, "requesting resource at 0x%x failed\n",
+ bdev->addr_s[0]);
+ return -EINVAL; + return -EINVAL;
+ } +
+ res->start = bdev->addr_s[0]; + res->start = bdev->addr_s[0];
+ res->end = res->start + SZ_128M - 1; + res->end = res->start + SZ_128M - 1;
+ res->name = "PCIe Configuration Space"; + 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. */ + /* This PCIe controller does not support IO Mem, so use a dummy one. */
+ res = devm_kzalloc(&bdev->dev, sizeof(*res), GFP_KERNEL); + res = devm_kzalloc(&bdev->dev, sizeof(*res), GFP_KERNEL);
+ if (!res) { + if (!res)
+ dev_info(&bdev->dev, "requesting resource at 0x%x failed\n",
+ bdev->addr_s[0]);
+ return -EINVAL; + return -EINVAL;
+ } +
+ res->start = bdev->addr_s[0]; + res->start = bdev->addr_s[0];
+ res->end = res->start + SZ_128M - 1; + res->end = res->start + SZ_128M - 1;
+ res->name = "PCIe Configuration Space"; + res->name = "PCIe Configuration Space";