Skip to contentSkip to conversation

bcma: add device tree support

RFC New Hauke Mehrtens 5 participants 22 messages Aug 24, 2014 – Sep 1, 2014

Subsystems (9)
lore
Share & tools
lore

Hauke Mehrtens

author maintainer
#0 lore raw

cover bcma: add device tree support

This adds device tree support to bcma. In addition it also provides the sprom needed by bcma through a device tree driver.
This is needed for the Broadcom BCM47XX/BCM53XX ARM SoCs (NorthStar).

bcma drives the system AIX bus. This bus is scanable, so we automatically detect the cores attached to this bus. We only have to provide the address of the first core, this can now be done through device tree.
It is not possible to find out what IRQ is associated to a specific core, we have to provide this through device tree.

Broadcom uses a nvram which is a key value store on the flash chip. This nvram contains the mac addresses to be used by the wifi and Ethernet devices, the configuration data for the switch, the calibration data for the wifi cores and some more stuff. Currently bcma assumes to get some sprom when it gets initialized on a SoC. This sprom is a structure with all the data which are originally stored in the nvram. When bcma is used on a PCIe wifi card this data is fetched from some eeporm on the card. The nvram could contains more than one sprom, in case there is a main Baordocm SoC and a Broadcom wifi card connected via PCIe this PCIe cards mostly use the nvram to store the sprom with the calibration data.

This patch series adds two drivers, the nvram driver which reads the nvram and provides an interface to fetch values by giving a key and a driver which creates a sprom based on a given nvram. These two things are no real drivers, they are just converting stuff. I made them drivers so they can be replaced with some other drivers which are fetching the sprom from other storages. I know that the BCM63XX SoCs are also using an sprom, but there it is stored in a file on the file system.

Some code was copied from the mips code at arch/mips/bcm47xx/ in the end I want to make this mips code also use these new drivers.

There is no device I know of which uses more than one nvram and I do not think there will ever be such a device. With this patch you have to provide a reference to the nvram you want to fetch data from which is a little bit annoying, should I remove this parameter and assume there is just one nvram driver in the system?

I am interested on comments if this architecture is correct or if there are some improvements I could do. I haven't fond similar code in the kernel.

Through which tree should I merge the final patches?

This is based on linus 3.17-rc1.

Log output:
bcma: bus0: Found chip with id 0xCF12, rev 0x00 and package 0x02
bcma: bus0: Core 0 found: ChipCommon (manuf 0x4BF, id 0x800, rev 0x2A, class 0x0)
bcma: bus0: Core 1 found: Chipcommon B (manuf 0x4BF, id 0x50B, rev 0x01, class 0x0)
bcma: bus0: Core 2 found: DMA (manuf 0x4BF, id 0x502, rev 0x01, class 0x0)
bcma: bus0: Core 3 found: GBit MAC (manuf 0x4BF, id 0x82D, rev 0x04, class 0x0)
bcma: bus0: Core 4 found: GBit MAC (manuf 0x4BF, id 0x82D, rev 0x04, class 0x0)
bcma: bus0: Core 5 found: GBit MAC (manuf 0x4BF, id 0x82D, rev 0x04, class 0x0)
bcma: bus0: Core 6 found: GBit MAC (manuf 0x4BF, id 0x82D, rev 0x04, class 0x0)
bcma: bus0: Core 7 found: PCIe Gen 2 (manuf 0x4BF, id 0x501, rev 0x01, class 0x0)
bcma: bus0: Core 8 found: PCIe Gen 2 (manuf 0x4BF, id 0x501, rev 0x01, class 0x0)
bcma: bus0: Core 9 found: ARM Cortex A9 core (ihost) (manuf 0x4BF, id 0x510, rev 0x01, class 0x0)
bcma: bus0: Core 10 found: USB 2.0 (manuf 0x4BF, id 0x504, rev 0x01, class 0x0)
bcma: bus0: Core 11 found: USB 3.0 (manuf 0x4BF, id 0x505, rev 0x01, class 0x0)
bcma: bus0: Core 12 found: SDIO3 (manuf 0x4BF, id 0x503, rev 0x01, class 0x0)
bcma: bus0: Core 13 found: ARM Cortex A9 JTAG (manuf 0x4BF, id 0x506, rev 0x01, class 0x0)
bcma: bus0: Core 14 found: Denali DDR2/DDR3 memory controller (manuf 0x4BF, id 0x507, rev 0x01, class 0x0)
bcma: bus0: Core 15 found: ROM (manuf 0x4BF, id 0x508, rev 0x01, class 0x0)
bcma: bus0: Core 16 found: NAND flash controller (manuf 0x4BF, id 0x509, rev 0x01, class 0x0)
bcma: bus0: Core 17 found: SPI flash controller (manuf 0x4BF, id 0x50A, rev 0x01, class 0x0)
bcma: bus0: Found sprom from device tree provider
bgmac bcma0:1: Found PHY addr: 30 (NOREGS)
bgmac bcma0:1: Support for Roboswitch not implemented
libphy: bgmac mii bus: probed
b53_common: found switch: BCM53011, rev 2
bgmac bcma0:2: Found PHY addr: 0
bgmac bcma0:2: Support for Roboswitch not implemented
libphy: bgmac mii bus: probed

Hauke Mehrtens (7):
MIPS: BCM47XX: move the nvram header file into common space
bcm47xx-nvram: add new broadcom nvram driver with dt support
bcm47xx-sprom: add Broadcom sprom parser driver
bcma: register bcma as device tree driver
bcma: get IRQ numbers from dt
bcma: get sprom from devicetree
ARM: BCM5301X: register bcma bus

 Documentation/devicetree/bindings/bus/bcma.txt     |  46 ++
 .../devicetree/bindings/misc/bcm47xx-nvram.txt     |  19 +
 .../devicetree/bindings/misc/bcm47xx-sprom.txt     |  16 +
 arch/arm/boot/dts/bcm4708.dtsi                     |  58 ++
 arch/mips/bcm47xx/board.c                          |  42 +-
 arch/mips/bcm47xx/nvram.c                          |   9 +-
 arch/mips/bcm47xx/setup.c                          |   6 +-
 arch/mips/bcm47xx/sprom.c                          |   6 +-
 arch/mips/bcm47xx/time.c                           |   4 +-
 arch/mips/include/asm/mach-bcm47xx/bcm47xx_nvram.h |  53 --
 drivers/bcma/host_soc.c                            |  70 +++
 drivers/bcma/main.c                                |  42 +-
 drivers/bcma/sprom.c                               |  51 +-
 drivers/misc/Kconfig                               |  27 +
 drivers/misc/Makefile                              |   2 +
 drivers/misc/bcm47xx-nvram.c                       | 215 +++++++
 drivers/misc/bcm47xx-sprom.c                       | 690 +++++++++++++++++++++
 drivers/net/ethernet/broadcom/b44.c                |  10 +-
 drivers/net/ethernet/broadcom/bgmac.c              |   7 +-
 drivers/ssb/driver_chipcommon_pmu.c                |   9 +-
 include/linux/bcm47xx_nvram.h                      |  71 +++
 include/linux/bcma/bcma.h                          |   2 +
 22 files changed, 1350 insertions(+), 105 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/bus/bcma.txt
 create mode 100644 Documentation/devicetree/bindings/misc/bcm47xx-nvram.txt
 create mode 100644 Documentation/devicetree/bindings/misc/bcm47xx-sprom.txt
 delete mode 100644 arch/mips/include/asm/mach-bcm47xx/bcm47xx_nvram.h
 create mode 100644 drivers/misc/bcm47xx-nvram.c
 create mode 100644 drivers/misc/bcm47xx-sprom.c
 create mode 100644 include/linux/bcm47xx_nvram.h
Signature · 1 line
1.9.1
author maintainer
#1 lore raw

cover bcma: add device tree support

This adds device tree support to bcma. In addition it also provides the sprom needed by bcma through a device tree driver.
This is needed for the Broadcom BCM47XX/BCM53XX ARM SoCs (NorthStar).

bcma drives the system AIX bus. This bus is scanable, so we automatically detect the cores attached to this bus. We only have to provide the address of the first core, this can now be done through device tree.
It is not possible to find out what IRQ is associated to a specific core, we have to provide this through device tree.

Broadcom uses a nvram which is a key value store on the flash chip. This nvram contains the mac addresses to be used by the wifi and Ethernet devices, the configuration data for the switch, the calibration data for the wifi cores and some more stuff. Currently bcma assumes to get some sprom when it gets initialized on a SoC. This sprom is a structure with all the data which are originally stored in the nvram. When bcma is used on a PCIe wifi card this data is fetched from some eeporm on the card. The nvram could contains more than one sprom, in case there is a main Baordocm SoC and a Broadcom wifi card connected via PCIe this PCIe cards mostly use the nvram to store the sprom with the calibration data.

This patch series adds two drivers, the nvram driver which reads the nvram and provides an interface to fetch values by giving a key and a driver which creates a sprom based on a given nvram. These two things are no real drivers, they are just converting stuff. I made them drivers so they can be replaced with some other drivers which are fetching the sprom from other storages. I know that the BCM63XX SoCs are also using an sprom, but there it is stored in a file on the file system.

Some code was copied from the mips code at arch/mips/bcm47xx/ in the end I want to make this mips code also use these new drivers.

There is no device I know of which uses more than one nvram and I do not think there will ever be such a device. With this patch you have to provide a reference to the nvram you want to fetch data from which is a little bit annoying, should I remove this parameter and assume there is just one nvram driver in the system?

I am interested on comments if this architecture is correct or if there are some improvements I could do. I haven't fond similar code in the kernel.

Through which tree should I merge the final patches?

This is based on linus 3.17-rc1.

Log output:
bcma: bus0: Found chip with id 0xCF12, rev 0x00 and package 0x02
bcma: bus0: Core 0 found: ChipCommon (manuf 0x4BF, id 0x800, rev 0x2A, class 0x0)
bcma: bus0: Core 1 found: Chipcommon B (manuf 0x4BF, id 0x50B, rev 0x01, class 0x0)
bcma: bus0: Core 2 found: DMA (manuf 0x4BF, id 0x502, rev 0x01, class 0x0)
bcma: bus0: Core 3 found: GBit MAC (manuf 0x4BF, id 0x82D, rev 0x04, class 0x0)
bcma: bus0: Core 4 found: GBit MAC (manuf 0x4BF, id 0x82D, rev 0x04, class 0x0)
bcma: bus0: Core 5 found: GBit MAC (manuf 0x4BF, id 0x82D, rev 0x04, class 0x0)
bcma: bus0: Core 6 found: GBit MAC (manuf 0x4BF, id 0x82D, rev 0x04, class 0x0)
bcma: bus0: Core 7 found: PCIe Gen 2 (manuf 0x4BF, id 0x501, rev 0x01, class 0x0)
bcma: bus0: Core 8 found: PCIe Gen 2 (manuf 0x4BF, id 0x501, rev 0x01, class 0x0)
bcma: bus0: Core 9 found: ARM Cortex A9 core (ihost) (manuf 0x4BF, id 0x510, rev 0x01, class 0x0)
bcma: bus0: Core 10 found: USB 2.0 (manuf 0x4BF, id 0x504, rev 0x01, class 0x0)
bcma: bus0: Core 11 found: USB 3.0 (manuf 0x4BF, id 0x505, rev 0x01, class 0x0)
bcma: bus0: Core 12 found: SDIO3 (manuf 0x4BF, id 0x503, rev 0x01, class 0x0)
bcma: bus0: Core 13 found: ARM Cortex A9 JTAG (manuf 0x4BF, id 0x506, rev 0x01, class 0x0)
bcma: bus0: Core 14 found: Denali DDR2/DDR3 memory controller (manuf 0x4BF, id 0x507, rev 0x01, class 0x0)
bcma: bus0: Core 15 found: ROM (manuf 0x4BF, id 0x508, rev 0x01, class 0x0)
bcma: bus0: Core 16 found: NAND flash controller (manuf 0x4BF, id 0x509, rev 0x01, class 0x0)
bcma: bus0: Core 17 found: SPI flash controller (manuf 0x4BF, id 0x50A, rev 0x01, class 0x0)
bcma: bus0: Found sprom from device tree provider
bgmac bcma0:1: Found PHY addr: 30 (NOREGS)
bgmac bcma0:1: Support for Roboswitch not implemented
libphy: bgmac mii bus: probed
b53_common: found switch: BCM53011, rev 2
bgmac bcma0:2: Found PHY addr: 0
bgmac bcma0:2: Support for Roboswitch not implemented
libphy: bgmac mii bus: probed

Hauke Mehrtens (7):
MIPS: BCM47XX: move the nvram header file into common space
bcm47xx-nvram: add new broadcom nvram driver with dt support
bcm47xx-sprom: add Broadcom sprom parser driver
bcma: register bcma as device tree driver
bcma: get IRQ numbers from dt
bcma: get sprom from devicetree
ARM: BCM5301X: register bcma bus

 Documentation/devicetree/bindings/bus/bcma.txt     |  46 ++
 .../devicetree/bindings/misc/bcm47xx-nvram.txt     |  19 +
 .../devicetree/bindings/misc/bcm47xx-sprom.txt     |  16 +
 arch/arm/boot/dts/bcm4708.dtsi                     |  58 ++
 arch/mips/bcm47xx/board.c                          |  42 +-
 arch/mips/bcm47xx/nvram.c                          |   9 +-
 arch/mips/bcm47xx/setup.c                          |   6 +-
 arch/mips/bcm47xx/sprom.c                          |   6 +-
 arch/mips/bcm47xx/time.c                           |   4 +-
 arch/mips/include/asm/mach-bcm47xx/bcm47xx_nvram.h |  53 --
 drivers/bcma/host_soc.c                            |  70 +++
 drivers/bcma/main.c                                |  42 +-
 drivers/bcma/sprom.c                               |  51 +-
 drivers/misc/Kconfig                               |  27 +
 drivers/misc/Makefile                              |   2 +
 drivers/misc/bcm47xx-nvram.c                       | 215 +++++++
 drivers/misc/bcm47xx-sprom.c                       | 690 +++++++++++++++++++++
 drivers/net/ethernet/broadcom/b44.c                |  10 +-
 drivers/net/ethernet/broadcom/bgmac.c              |   7 +-
 drivers/ssb/driver_chipcommon_pmu.c                |   9 +-
 include/linux/bcm47xx_nvram.h                      |  71 +++
 include/linux/bcma/bcma.h                          |   2 +
 22 files changed, 1350 insertions(+), 105 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/bus/bcma.txt
 create mode 100644 Documentation/devicetree/bindings/misc/bcm47xx-nvram.txt
 create mode 100644 Documentation/devicetree/bindings/misc/bcm47xx-sprom.txt
 delete mode 100644 arch/mips/include/asm/mach-bcm47xx/bcm47xx_nvram.h
 create mode 100644 drivers/misc/bcm47xx-nvram.c
 create mode 100644 drivers/misc/bcm47xx-sprom.c
 create mode 100644 include/linux/bcm47xx_nvram.h
Signature · 1 line
1.9.1
author maintainer
#2 lore raw

RFC 1/7 MIPS: BCM47XX: move the nvram header file into common space

In reply to Hauke Mehrtens

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.

---
 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 -----------------
 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                      | 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
arch/mips/bcm47xx/board.c +1 -1
index b3ae068..ec46fd7 100644
@@ -2,7 +2,7 @@
 #include <linux/export.h>
 #include <linux/string.h>
 #include <bcm47xx_board.h>
-#include <bcm47xx_nvram.h>
+#include <linux/bcm47xx_nvram.h>
 
 struct bcm47xx_board_type {
 	const enum bcm47xx_board board;
arch/mips/bcm47xx/nvram.c +1 -1
index 2bed73a..c47a4a8 100644
@@ -17,7 +17,7 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <asm/addrspace.h>
-#include <bcm47xx_nvram.h>
+#include <linux/bcm47xx_nvram.h>
 #include <asm/mach-bcm47xx/bcm47xx.h>
 
 static char nvram_buf[NVRAM_SPACE];
arch/mips/bcm47xx/setup.c +1 -1
index 2b63e7e..deadb71 100644
@@ -42,7 +42,7 @@
 #include <asm/reboot.h>
 #include <asm/time.h>
 #include <bcm47xx.h>
-#include <bcm47xx_nvram.h>
+#include <linux/bcm47xx_nvram.h>
 #include <bcm47xx_board.h>
 
 union bcm47xx_bus bcm47xx_bus;
arch/mips/bcm47xx/sprom.c +1 -1
index 41226b6..29ced12 100644
@@ -27,7 +27,7 @@
  */
 
 #include <bcm47xx.h>
-#include <bcm47xx_nvram.h>
+#include <linux/bcm47xx_nvram.h>
 #include <linux/if_ether.h>
 #include <linux/etherdevice.h>
 
arch/mips/bcm47xx/time.c +1 -1
index 2c85d92..c57a515 100644
@@ -27,7 +27,7 @@
 #include <linux/ssb/ssb.h>
 #include <asm/time.h>
 #include <bcm47xx.h>
-#include <bcm47xx_nvram.h>
+#include <linux/bcm47xx_nvram.h>
 #include <bcm47xx_board.h>
 
 void __init plat_time_init(void)
arch/mips/include/asm/mach-bcm47xx/bcm47xx_nvram.h deleted +0 -53

53 lines not on this page · raw message

drivers/net/ethernet/broadcom/b44.c +1 -7
index 4a7028d..d2714a2 100644
@@ -31,6 +31,7 @@
 #include <linux/ssb/ssb.h>
 #include <linux/slab.h>
 #include <linux/phy.h>
+#include <linux/bcm47xx_nvram.h>
 
 #include <asm/uaccess.h>
 #include <asm/io.h>
@@ -399,8 +400,6 @@ static void b44_set_flow_ctrl(struct b44 *bp, u32 local, u32 remote)
 	__b44_set_flow_ctrl(bp, pause_enab);
 }
 
-#ifdef CONFIG_BCM47XX
-#include <bcm47xx_nvram.h>
 static void b44_wap54g10_workaround(struct b44 *bp)
 {
 	char buf[20];
@@ -429,11 +428,6 @@ static void b44_wap54g10_workaround(struct b44 *bp)
 error:
 	pr_warning("PHY: cannot reset MII transceiver isolate bit\n");
 }
-#else
-static inline void b44_wap54g10_workaround(struct b44 *bp)
-{
-}
-#endif
 
 static int b44_setup_phy(struct b44 *bp)
 {
drivers/net/ethernet/broadcom/bgmac.c +1 -1
index 05c6af6..bdda57b 100644
@@ -16,7 +16,7 @@
 #include <linux/phy.h>
 #include <linux/interrupt.h>
 #include <linux/dma-mapping.h>
-#include <bcm47xx_nvram.h>
+#include <linux/bcm47xx_nvram.h>
 
 static const struct bcma_device_id bgmac_bcma_tbl[] = {
 	BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_4706_MAC_GBIT, BCMA_ANY_REV, BCMA_ANY_CLASS),
drivers/ssb/driver_chipcommon_pmu.c +1 -5
index 1173a09..8d07d4d 100644
@@ -13,9 +13,7 @@
 #include <linux/ssb/ssb_driver_chipcommon.h>
 #include <linux/delay.h>
 #include <linux/export.h>
-#ifdef CONFIG_BCM47XX
-#include <bcm47xx_nvram.h>
-#endif
+#include <linux/bcm47xx_nvram.h>
 
 #include "ssb_private.h"
 
@@ -320,11 +318,9 @@ static void ssb_pmu_pll_init(struct ssb_chipcommon *cc)
 	u32 crystalfreq = 0; /* in kHz. 0 = keep default freq. */
 
 	if (bus->bustype == SSB_BUSTYPE_SSB) {
-#ifdef CONFIG_BCM47XX
 		char buf[20];
 		if (bcm47xx_nvram_getenv("xtalfreq", buf, sizeof(buf)) >= 0)
 			crystalfreq = simple_strtoul(buf, NULL, 0);
-#endif
 	}
 
 	switch (bus->chip_id) {
include/linux/bcm47xx_nvram.h new file +66 -0

66 lines not on this page · raw message

Signature · 1 line
1.9.1
author maintainer
#3 lore raw

RFC 2/7 bcm47xx-nvram: add new broadcom nvram driver with dt support

In reply to Hauke Mehrtens

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 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.

---
 .../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                               |  13 ++
 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, 294 insertions(+), 38 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/misc/bcm47xx-nvram.txt
 create mode 100644 drivers/misc/bcm47xx-nvram.c
Documentation/devicetree/bindings/misc/bcm47xx-nvram.txt new file +19 -0
new file mode 100644
index 0000000..ed979a8
@@ -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 at 0 {
+	compatible = "brcm,bcm47xx-nvram";
+	reg = <0x1c000000 0x01000000>;
+};
arch/mips/bcm47xx/board.c +20 -20
index ec46fd7..2c98f74 100644
@@ -218,36 +218,36 @@ static __init const struct bcm47xx_board_type *bcm47xx_board_get_nvram(void)
 	const struct bcm47xx_board_type_list2 *e2;
 	const struct bcm47xx_board_type_list3 *e3;
 
-	if (bcm47xx_nvram_getenv("model_name", buf1, sizeof(buf1)) >= 0) {
+	if (bcm47xx_nvram_getenv(NULL, "model_name", buf1, sizeof(buf1)) >= 0) {
 		for (e1 = bcm47xx_board_list_model_name; e1->value1; e1++) {
 			if (!strcmp(buf1, e1->value1))
 				return &e1->board;
 		}
 	}
 
-	if (bcm47xx_nvram_getenv("model_no", buf1, sizeof(buf1)) >= 0) {
+	if (bcm47xx_nvram_getenv(NULL, "model_no", buf1, sizeof(buf1)) >= 0) {
 		for (e1 = bcm47xx_board_list_model_no; e1->value1; e1++) {
 			if (strstarts(buf1, e1->value1))
 				return &e1->board;
 		}
 	}
 
-	if (bcm47xx_nvram_getenv("machine_name", buf1, sizeof(buf1)) >= 0) {
+	if (bcm47xx_nvram_getenv(NULL, "machine_name", buf1, sizeof(buf1)) >= 0) {
 		for (e1 = bcm47xx_board_list_machine_name; e1->value1; e1++) {
 			if (strstarts(buf1, e1->value1))
 				return &e1->board;
 		}
 	}
 
-	if (bcm47xx_nvram_getenv("hardware_version", buf1, sizeof(buf1)) >= 0) {
+	if (bcm47xx_nvram_getenv(NULL, "hardware_version", buf1, sizeof(buf1)) >= 0) {
 		for (e1 = bcm47xx_board_list_hardware_version; e1->value1; e1++) {
 			if (strstarts(buf1, e1->value1))
 				return &e1->board;
 		}
 	}
 
-	if (bcm47xx_nvram_getenv("hardware_version", buf1, sizeof(buf1)) >= 0 &&
-	    bcm47xx_nvram_getenv("boardtype", buf2, sizeof(buf2)) >= 0) {
+	if (bcm47xx_nvram_getenv(NULL, "hardware_version", buf1, sizeof(buf1)) >= 0 &&
+	    bcm47xx_nvram_getenv(NULL, "boardtype", buf2, sizeof(buf2)) >= 0) {
 		for (e2 = bcm47xx_board_list_boot_hw; e2->value1; e2++) {
 			if (!strstarts(buf1, e2->value1) &&
 			    !strcmp(buf2, e2->value2))
@@ -255,22 +255,22 @@ static __init const struct bcm47xx_board_type *bcm47xx_board_get_nvram(void)
 		}
 	}
 
-	if (bcm47xx_nvram_getenv("productid", buf1, sizeof(buf1)) >= 0) {
+	if (bcm47xx_nvram_getenv(NULL, "productid", buf1, sizeof(buf1)) >= 0) {
 		for (e1 = bcm47xx_board_list_productid; e1->value1; e1++) {
 			if (!strcmp(buf1, e1->value1))
 				return &e1->board;
 		}
 	}
 
-	if (bcm47xx_nvram_getenv("ModelId", buf1, sizeof(buf1)) >= 0) {
+	if (bcm47xx_nvram_getenv(NULL, "ModelId", buf1, sizeof(buf1)) >= 0) {
 		for (e1 = bcm47xx_board_list_ModelId; e1->value1; e1++) {
 			if (!strcmp(buf1, e1->value1))
 				return &e1->board;
 		}
 	}
 
-	if (bcm47xx_nvram_getenv("melco_id", buf1, sizeof(buf1)) >= 0 ||
-	    bcm47xx_nvram_getenv("buf1falo_id", buf1, sizeof(buf1)) >= 0) {
+	if (bcm47xx_nvram_getenv(NULL, "melco_id", buf1, sizeof(buf1)) >= 0 ||
+	    bcm47xx_nvram_getenv(NULL, "buf1falo_id", buf1, sizeof(buf1)) >= 0) {
 		/* buffalo hardware, check id for specific hardware matches */
 		for (e1 = bcm47xx_board_list_melco_id; e1->value1; e1++) {
 			if (!strcmp(buf1, e1->value1))
@@ -278,8 +278,8 @@ static __init const struct bcm47xx_board_type *bcm47xx_board_get_nvram(void)
 		}
 	}
 
-	if (bcm47xx_nvram_getenv("boot_hw_model", buf1, sizeof(buf1)) >= 0 &&
-	    bcm47xx_nvram_getenv("boot_hw_ver", buf2, sizeof(buf2)) >= 0) {
+	if (bcm47xx_nvram_getenv(NULL, "boot_hw_model", buf1, sizeof(buf1)) >= 0 &&
+	    bcm47xx_nvram_getenv(NULL, "boot_hw_ver", buf2, sizeof(buf2)) >= 0) {
 		for (e2 = bcm47xx_board_list_boot_hw; e2->value1; e2++) {
 			if (!strcmp(buf1, e2->value1) &&
 			    !strcmp(buf2, e2->value2))
@@ -287,16 +287,16 @@ static __init const struct bcm47xx_board_type *bcm47xx_board_get_nvram(void)
 		}
 	}
 
-	if (bcm47xx_nvram_getenv("board_id", buf1, sizeof(buf1)) >= 0) {
+	if (bcm47xx_nvram_getenv(NULL, "board_id", buf1, sizeof(buf1)) >= 0) {
 		for (e1 = bcm47xx_board_list_board_id; e1->value1; e1++) {
 			if (!strcmp(buf1, e1->value1))
 				return &e1->board;
 		}
 	}
 
-	if (bcm47xx_nvram_getenv("boardtype", buf1, sizeof(buf1)) >= 0 &&
-	    bcm47xx_nvram_getenv("boardnum", buf2, sizeof(buf2)) >= 0 &&
-	    bcm47xx_nvram_getenv("boardrev", buf3, sizeof(buf3)) >= 0) {
+	if (bcm47xx_nvram_getenv(NULL, "boardtype", buf1, sizeof(buf1)) >= 0 &&
+	    bcm47xx_nvram_getenv(NULL, "boardnum", buf2, sizeof(buf2)) >= 0 &&
+	    bcm47xx_nvram_getenv(NULL, "boardrev", buf3, sizeof(buf3)) >= 0) {
 		for (e3 = bcm47xx_board_list_board; e3->value1; e3++) {
 			if (!strcmp(buf1, e3->value1) &&
 			    !strcmp(buf2, e3->value2) &&
@@ -305,9 +305,9 @@ static __init const struct bcm47xx_board_type *bcm47xx_board_get_nvram(void)
 		}
 	}
 
-	if (bcm47xx_nvram_getenv("boardtype", buf1, sizeof(buf1)) >= 0 &&
-	    bcm47xx_nvram_getenv("boardrev", buf2, sizeof(buf2)) >= 0 &&
-	    bcm47xx_nvram_getenv("boardnum", buf3, sizeof(buf3)) ==  -ENOENT) {
+	if (bcm47xx_nvram_getenv(NULL, "boardtype", buf1, sizeof(buf1)) >= 0 &&
+	    bcm47xx_nvram_getenv(NULL, "boardrev", buf2, sizeof(buf2)) >= 0 &&
+	    bcm47xx_nvram_getenv(NULL, "boardnum", buf3, sizeof(buf3)) ==  -ENOENT) {
 		for (e2 = bcm47xx_board_list_board_type_rev; e2->value1; e2++) {
 			if (!strcmp(buf1, e2->value1) &&
 			    !strcmp(buf2, e2->value2))
@@ -327,7 +327,7 @@ void __init bcm47xx_board_detect(void)
 		return;
 
 	/* check if the nvram is available */
-	err = bcm47xx_nvram_getenv("boardtype", buf, sizeof(buf));
+	err = bcm47xx_nvram_getenv(NULL, "boardtype", buf, sizeof(buf));
 
 	/* init of nvram failed, probably too early now */
 	if (err == -ENXIO) {
arch/mips/bcm47xx/nvram.c +4 -3
index c47a4a8..b2112c7 100644
@@ -158,7 +158,8 @@ static int nvram_init(void)
 	return -ENXIO;
 }
 
-int bcm47xx_nvram_getenv(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;
 	int err;
@@ -190,7 +191,7 @@ int bcm47xx_nvram_getenv(char *name, char *val, size_t val_len)
 }
 EXPORT_SYMBOL(bcm47xx_nvram_getenv);
 
-int bcm47xx_nvram_gpio_pin(const char *name)
+int bcm47xx_nvram_gpio_pin(const struct device *dev, const char *name)
 {
 	int i, err;
 	char nvram_var[10];
@@ -200,7 +201,7 @@ int bcm47xx_nvram_gpio_pin(const char *name)
 		err = snprintf(nvram_var, sizeof(nvram_var), "gpio%i", i);
 		if (err <= 0)
 			continue;
-		err = bcm47xx_nvram_getenv(nvram_var, buf, sizeof(buf));
+		err = bcm47xx_nvram_getenv(dev, nvram_var, buf, sizeof(buf));
 		if (err <= 0)
 			continue;
 		if (!strcmp(name, buf))
arch/mips/bcm47xx/setup.c +2 -2
index deadb71..d87709d 100644
@@ -123,7 +123,7 @@ static int bcm47xx_get_invariants(struct ssb_bus *bus,
 	memset(&iv->sprom, 0, sizeof(struct ssb_sprom));
 	bcm47xx_fill_sprom(&iv->sprom, NULL, false);
 
-	if (bcm47xx_nvram_getenv("cardbus", buf, sizeof(buf)) >= 0)
+	if (bcm47xx_nvram_getenv(NULL, "cardbus", buf, sizeof(buf)) >= 0)
 		iv->has_cardbus_slot = !!simple_strtoul(buf, NULL, 10);
 
 	return 0;
@@ -146,7 +146,7 @@ static void __init bcm47xx_register_ssb(void)
 		panic("Failed to initialize SSB bus (err %d)", err);
 
 	mcore = &bcm47xx_bus.ssb.mipscore;
-	if (bcm47xx_nvram_getenv("kernel_args", buf, sizeof(buf)) >= 0) {
+	if (bcm47xx_nvram_getenv(NULL, "kernel_args", buf, sizeof(buf)) >= 0) {
 		if (strstr(buf, "console=ttyS1")) {
 			struct ssb_serial_port port;
 
arch/mips/bcm47xx/sprom.c +2 -2
index 29ced12..f88f49b 100644
@@ -52,10 +52,10 @@ static int get_nvram_var(const char *prefix, const char *postfix,
 
 	create_key(prefix, postfix, name, key, sizeof(key));
 
-	err = bcm47xx_nvram_getenv(key, buf, len);
+	err = bcm47xx_nvram_getenv(NULL, key, buf, len);
 	if (fallback && err == -ENOENT && prefix) {
 		create_key(NULL, postfix, name, key, sizeof(key));
-		err = bcm47xx_nvram_getenv(key, buf, len);
+		err = bcm47xx_nvram_getenv(NULL, key, buf, len);
 	}
 	return err;
 }
arch/mips/bcm47xx/time.c +1 -1
index c57a515..b2c3c7d 100644
@@ -61,7 +61,7 @@ void __init plat_time_init(void)
 	}
 
 	if (chip_id == 0x5354) {
-		len = bcm47xx_nvram_getenv("clkfreq", buf, sizeof(buf));
+		len = bcm47xx_nvram_getenv(NULL, "clkfreq", buf, sizeof(buf));
 		if (len >= 0 && !strncmp(buf, "200", 4))
 			hz = 100000000;
 	}
drivers/misc/Kconfig +13 -0
index b841180..b306c02 100644
@@ -515,6 +515,19 @@ config VEXPRESS_SYSCFG
 	  bus. System Configuration interface is one of the possible means
 	  of generating transactions on this bus.
 
+config BCM47XX_NVRAM
+	tristate "BCM47XX nvram driver"
+	depends on OF
+	help
+	  This driver parses the nvram from a given memory range and
+	  provides its values to other drivers.
+
+	  The nvram is a key value store used on bcm47xx/bcm53xx SoC 
+	  with ARM and MIPS CPUs. It contains the board specific 
+	  configuration.
+
+	  If unsure, say N.
+
 source "drivers/misc/c2port/Kconfig"
 source "drivers/misc/eeprom/Kconfig"
 source "drivers/misc/cb710/Kconfig"
drivers/misc/Makefile +1 -0
index 5497d02..2331208 100644
@@ -55,3 +55,4 @@ obj-y				+= mic/
 obj-$(CONFIG_GENWQE)		+= genwqe/
 obj-$(CONFIG_ECHO)		+= echo/
 obj-$(CONFIG_VEXPRESS_SYSCFG)	+= vexpress-syscfg.o
+obj-$(CONFIG_BCM47XX_NVRAM)	+= bcm47xx-nvram.o
drivers/misc/bcm47xx-nvram.c new file +215 -0

215 lines not on this page · raw message

drivers/net/ethernet/broadcom/b44.c +1 -1
index d2714a2..8340498 100644
@@ -411,7 +411,7 @@ static void b44_wap54g10_workaround(struct b44 *bp)
 	 * see https://dev.openwrt.org/ticket/146
 	 * check and reset bit "isolate"
 	 */
-	if (bcm47xx_nvram_getenv("boardnum", buf, sizeof(buf)) < 0)
+	if (bcm47xx_nvram_getenv(NULL, "boardnum", buf, sizeof(buf)) < 0)
 		return;
 	if (simple_strtoul(buf, NULL, 0) == 2) {
 		err = __b44_readphy(bp, 0, MII_BMCR, &val);
drivers/net/ethernet/broadcom/bgmac.c +3 -2
index bdda57b..1df7fb0 100644
@@ -952,7 +952,8 @@ static void bgmac_chip_reset(struct bgmac *bgmac)
 			     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 (kstrtou8(buf, 0, &et_swtype))
 				bgmac_err(bgmac, "Failed to parse et_swtype (%s)\n",
 					  buf);
@@ -1501,7 +1502,7 @@ static int bgmac_probe(struct bcma_device *core)
 	}
 
 	bgmac->int_mask = BGMAC_IS_ERRMASK | BGMAC_IS_RX | BGMAC_IS_TX_MASK;
-	if (bcm47xx_nvram_getenv("et0_no_txint", NULL, 0) == 0)
+	if (bcm47xx_nvram_getenv(NULL, "et0_no_txint", NULL, 0) == 0)
 		bgmac->int_mask &= ~BGMAC_IS_TX_MASK;
 
 	/* TODO: reset the external phy. Specs are needed */
drivers/ssb/driver_chipcommon_pmu.c +2 -1
index 8d07d4d..b611ea1 100644
@@ -319,7 +319,8 @@ static void ssb_pmu_pll_init(struct ssb_chipcommon *cc)
 
 	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)
 			crystalfreq = simple_strtoul(buf, NULL, 0);
 	}
 
include/linux/bcm47xx_nvram.h +11 -6
index 333d32c..515fc06 100644
@@ -15,9 +15,11 @@
 #include <linux/types.h>
 #include <linux/kernel.h>
 
+struct device;
+
 struct nvram_header {
 	u32 magic;
-	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
 
-#ifdef CONFIG_BCM47XX
-int bcm47xx_nvram_getenv(const char *name, char *val, size_t val_len);
+#if defined(CONFIG_BCM47XX) || defined(CONFIG_BCM47XX_NVRAM)
+int bcm47xx_nvram_getenv(const struct device *dev, const char *name, char *val,
+			 size_t val_len);
 
-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,
+static inline int bcm47xx_nvram_getenv(const struct device *dev,
+				       const char *name, char *val,
 				       size_t val_len)
 {
 	return -ENXIO;
 }
 
-static inline int bcm47xx_nvram_gpio_pin(const char *name)
+static inline int bcm47xx_nvram_gpio_pin(const struct device *dev,
+					 const char *name)
 {
 	return -ENXIO;
 }
Signature · 1 line
1.9.1
maintainer
#4 lore raw

RFC 2/7 bcm47xx-nvram: add new broadcom nvram driver with dt support

Quoted 3 lines · Hauke Mehrtens

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.

I don't like this.

First, you change API (_getenv call), without explanation why/if we really need this. We decided we're very unlikely to ever find devices with multiple (separated) NVRAMs. So what's the point of having nvram per device?

Secondly, don't duplicate the code. If you're going to switch bcm47xx to this new code, handle it smarter. Modify bcm47xx mode, move it to the "misc" and re-use in bcm53xx.

maintainer
#5 lore raw

RFC 2/7 bcm47xx-nvram: add new broadcom nvram driver with dt support

In reply to Hauke Mehrtens

Documentation/devicetree/bindings/misc/bcm47xx-nvram.txt line 19

Quoted 9 lines · Hauke Mehrtens
Documentation/devicetree/bindings/misc/bcm47xx-nvram.txt new file +9 -0
+On NorthStar ARM SoCs the NAND flash is available at 0x1c000000 and the
+NOR flash is at 0x1e000000
+
+Example:
+
+nvram0: nvram at 0 {
+       compatible = "brcm,bcm47xx-nvram";
+       reg = <0x1c000000 0x01000000>;
+};

Could we avoid that? Type of flash can easily be checked in the code. All we need to do is to read BCMA_IOST register of BCMA_CORE_NS_ROM core.

#6 lore raw

RFC 2/7 bcm47xx-nvram: add new broadcom nvram driver with dt support

Quoted 14 lines · Rafa? Mi?ecki

Documentation/devicetree/bindings/misc/bcm47xx-nvram.txt line 19

Quoted 9 lines · Hauke Mehrtens
Documentation/devicetree/bindings/misc/bcm47xx-nvram.txt new file +9 -0
+On NorthStar ARM SoCs the NAND flash is available at 0x1c000000 and the
+NOR flash is at 0x1e000000
+
+Example:
+
+nvram0: nvram at 0 {
+       compatible = "brcm,bcm47xx-nvram";
+       reg = <0x1c000000 0x01000000>;
+};

Could we avoid that? Type of flash can easily be checked in the code. All we need to do is to read BCMA_IOST register of BCMA_CORE_NS_ROM core.

So there is a boot status register you can read to tell what type of flash you booted from, but does that also give you the resource ranges for these type of flashes? Presumably they will be mapped into different addresses (at least bcm63xx is like that), that information needs to be listed somewhere.
--
Florian

maintainer
#7 lore raw

RFC 2/7 bcm47xx-nvram: add new broadcom nvram driver with dt support

Quoted 10 lines · Florian Fainelli
Quoted 3 lines · Rafa? Mi?ecki

Could we avoid that? Type of flash can easily be checked in the code. All we need to do is to read BCMA_IOST register of BCMA_CORE_NS_ROM core.

So there is a boot status register you can read to tell what type of flash you booted from, but does that also give you the resource ranges for these type of flashes? Presumably they will be mapped into different addresses (at least bcm63xx is like that), that information needs to be listed somewhere.

Take a look at find_nvram in nvram_rw.c. It scans the whole region which is up to 0x02000000 (SI_FLASH2_SZ) size.

In case of NAND limit is slightly different (nfl_boot_size function):
1) On ARM it's 0x800000 or 0x2600000
2) On MIPS it's 0x200000

Signature · 1 line
Rafa?
author maintainer
#8 lore raw

RFC 3/7 bcm47xx-sprom: add Broadcom sprom parser driver

In reply to Hauke Mehrtens

This driver needs an nvram driver and fetches the sprom values from 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.

---
 .../devicetree/bindings/misc/bcm47xx-sprom.txt     |  16 +
 drivers/misc/Kconfig                               |  14 +
 drivers/misc/Makefile                              |   1 +
 drivers/misc/bcm47xx-sprom.c                       | 690 +++++++++++++++++++++
 4 files changed, 721 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/misc/bcm47xx-sprom.txt
 create mode 100644 drivers/misc/bcm47xx-sprom.c
Documentation/devicetree/bindings/misc/bcm47xx-sprom.txt new file +16 -0
new file mode 100644
index 0000000..eed2a4a
@@ -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 at 0 {
+	compatible = "brcm,bcm47xx-sprom";
+	nvram = <&nvram0>;
+};
drivers/misc/Kconfig +14 -0
index b306c02..fe9e2f2 100644
@@ -528,6 +528,20 @@ config BCM47XX_NVRAM
 
 	  If unsure, say N.
 
+config BCM47XX_SPROM
+	tristate "BCM47XX sprom driver"
+	depends on OF
+	help
+	  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.
+
+	  If unsure, say N.
+
 source "drivers/misc/c2port/Kconfig"
 source "drivers/misc/eeprom/Kconfig"
 source "drivers/misc/cb710/Kconfig"
drivers/misc/Makefile +1 -0
index 2331208..e958e35 100644
@@ -56,3 +56,4 @@ obj-$(CONFIG_GENWQE)		+= genwqe/
 obj-$(CONFIG_ECHO)		+= echo/
 obj-$(CONFIG_VEXPRESS_SYSCFG)	+= vexpress-syscfg.o
 obj-$(CONFIG_BCM47XX_NVRAM)	+= bcm47xx-nvram.o
+obj-$(CONFIG_BCM47XX_SPROM)	+= bcm47xx-sprom.o
drivers/misc/bcm47xx-sprom.c new file +690 -0

690 lines not on this page · raw message

Signature · 1 line
1.9.1
maintainer
#9 lore raw

RFC 3/7 bcm47xx-sprom: add Broadcom sprom parser driver

Quoted 11 lines · On Sunday 24 August 2014 23:24:41 Hauke Mehrtens wrote:

This driver needs an nvram driver and fetches the sprom values from 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.

---
 .../devicetree/bindings/misc/bcm47xx-sprom.txt     |  16 +

I'd prefer not to list the binding in a 'misc' category. Maybe we can have a new category and move the misc/sram.txt into the same?

Quoted 3 lines
 drivers/misc/Kconfig                               |  14 +
 drivers/misc/Makefile                              |   1 +
 drivers/misc/bcm47xx-sprom.c                       | 690 +++++++++++++++++++++

On a similar note, putting the driver into drivers/misc seems
suboptimal: misc drivers should by definition be something that is for some odd hardware with no external dependencies on it, whereas your driver seems to be used by multiple other drivers.

Would it make sense to put it into drivers/bcma when that is the only bus it is used on?

Quoted 10 lines
 4 files changed, 721 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/misc/bcm47xx-sprom.txt
 create mode 100644 drivers/misc/bcm47xx-sprom.c
Documentation/devicetree/bindings/misc/bcm47xx-sprom.txt new file +0 -0
new file mode 100644
index 0000000..eed2a4a

Documentation/devicetree/bindings/misc/bcm47xx-sprom.txt line 7

Quoted 7 lines
Documentation/devicetree/bindings/misc/bcm47xx-sprom.txt new file +7 -0
@@ -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

Please use a specific SoC here as the compatible string, not something with 'x' in it as a wildcard.

Quoted 19 lines
Documentation/devicetree/bindings/misc/bcm47xx-sprom.txt new file +19 -0
+#define NVRAM_READ_VAL(type)						\
+static void nvram_read_ ## type (const struct bcm47xx_sprom_fill *fill,	\
+				 const char *postfix, const char *name, \
+				 type *val, type allset)		\
+{									\
+	char buf[100];							\
+	int err;							\
+	type var;							\
+									\
+	err = get_nvram_var(fill, postfix, name, buf, sizeof(buf));	\
+	if (err < 0)							\
+		return;							\
+	err = kstrto ## type(strim(buf), 0, &var);			\
+	if (err) {							\
+		pr_warn("can not parse nvram name %s%s%s with value %s got %i\n",	\
+			fill->prefix, name, postfix, buf, err);		\
+		return;							\
+	}								\
+	if (allset && var == allset)					\

Documentation/devicetree/bindings/misc/bcm47xx-sprom.txt

Quoted 10 lines
Documentation/devicetree/bindings/misc/bcm47xx-sprom.txt new file +10 -0
+		return;							\
+	*val = var;							\
+}
+
+NVRAM_READ_VAL(u8)
+NVRAM_READ_VAL(s8)
+NVRAM_READ_VAL(u16)
+NVRAM_READ_VAL(u32)
+
+#undef NVRAM_READ_VAL

Hmm, multiline macros are ugly. How about using one function to read into an s64 internally using kstrtoll, and simple inline wrappers around that for the smaller types, doing the appropriate range check?

Quoted 4 lines
Documentation/devicetree/bindings/misc/bcm47xx-sprom.txt new file +4 -0
+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);

Documentation/devicetree/bindings/misc/bcm47xx-sprom.txt

Quoted 10 lines
Documentation/devicetree/bindings/misc/bcm47xx-sprom.txt new file +10 -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);
+	nvram_read_u8(fill, NULL, "ledbh3", &sprom->gpio3, 0xff);
+	nvram_read_u8(fill, NULL, "aa2g", &sprom->ant_available_bg, 0);
+	nvram_read_u8(fill, NULL, "aa5g", &sprom->ant_available_a, 0);
+	nvram_read_s8(fill, NULL, "ag0", &sprom->antenna_gain.a0, 0);
+	nvram_read_s8(fill, NULL, "ag1", &sprom->antenna_gain.a1, 0);
+	nvram_read_alpha2(fill, "ccode", sprom->alpha2);
+}

Rather than calling the same set of functions multiple times, can you do this using a table driven approach for smaller code size and improved readability?

Quoted 10 lines
Documentation/devicetree/bindings/misc/bcm47xx-sprom.txt new file +10 -0
+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 __be32 *handle;
+	struct device_node *nvram_node;
+	struct platform_device *nvram_dev;
+	struct bcm47xx_sprom_fill fill;
+

Documentation/devicetree/bindings/misc/bcm47xx-sprom.txt

Quoted 10 lines
Documentation/devicetree/bindings/misc/bcm47xx-sprom.txt new file +10 -0
+	/* Alloc */
+	sprom = devm_kzalloc(dev, sizeof(*sprom), GFP_KERNEL);
+	if (!sprom)
+		return -ENOMEM;
+
+	handle = of_get_property(np, "nvram", NULL);
+	if (!handle)
+		return -ENOMEM;
+
+	nvram_node = of_find_node_by_phandle(be32_to_cpup(handle));

You can avoid the explicit be32_to_cpup here if you use of_property_read_u32 above.

Arnd

#10 lore raw

RFC 3/7 bcm47xx-sprom: add Broadcom sprom parser driver

Quoted 20 lines · Arnd Bergmann
Quoted 11 lines · On Sunday 24 August 2014 23:24:41 Hauke Mehrtens wrote:

This driver needs an nvram driver and fetches the sprom values from 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.

---
 .../devicetree/bindings/misc/bcm47xx-sprom.txt     |  16 +

I'd prefer not to list the binding in a 'misc' category. Maybe we can have a new category and move the misc/sram.txt into the same?

Quoted 3 lines
 drivers/misc/Kconfig                               |  14 +
 drivers/misc/Makefile                              |   1 +
 drivers/misc/bcm47xx-sprom.c                       | 690 +++++++++++++++++++++
Quoted 7 lines

On a similar note, putting the driver into drivers/misc seems
suboptimal: misc drivers should by definition be something that is for some odd hardware with no external dependencies on it, whereas your driver seems to be used by multiple other drivers.

Would it make sense to put it into drivers/bcma when that is the only bus it is used on?

If the driver will be used for bcm47xx/mips, it will be used for two busses, bcma and ssb, so it will need to be at a common location.

Jonas

author maintainer
#11 lore raw

RFC 3/7 bcm47xx-sprom: add Broadcom sprom parser driver

In reply to Arnd Bergmann
Quoted 20 lines · Arnd Bergmann
Quoted 11 lines · On Sunday 24 August 2014 23:24:41 Hauke Mehrtens wrote:

This driver needs an nvram driver and fetches the sprom values from 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.

---
 .../devicetree/bindings/misc/bcm47xx-sprom.txt     |  16 +

I'd prefer not to list the binding in a 'misc' category. Maybe we can have a new category and move the misc/sram.txt into the same?

Quoted 3 lines
 drivers/misc/Kconfig                               |  14 +
 drivers/misc/Makefile                              |   1 +
 drivers/misc/bcm47xx-sprom.c                       | 690 +++++++++++++++++++++
Quoted 7 lines

On a similar note, putting the driver into drivers/misc seems
suboptimal: misc drivers should by definition be something that is for some odd hardware with no external dependencies on it, whereas your driver seems to be used by multiple other drivers.

Would it make sense to put it into drivers/bcma when that is the only bus it is used on?

As Jonas already said this code should be used for the bcm53xx ARM code and the bcm47xx MIPS code and it is needed for drivers/bcma/ and drivers/ssb/ (ssb only for old mips devices). Do you have any better idea than putting this to drivers/misc/ ? For the mips SoC we need the code very early and will not use the driver interface but probably directly call the function name.

Quoted 5 lines
Quoted 5 lines
 4 files changed, 721 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/misc/bcm47xx-sprom.txt
 create mode 100644 drivers/misc/bcm47xx-sprom.c
Quoted 16 lines

Documentation/devicetree/bindings/misc/bcm47xx-sprom.txt line 7

Quoted 13 lines
Documentation/devicetree/bindings/misc/bcm47xx-sprom.txt new file +7 -0
new file mode 100644
index 0000000..eed2a4a
@@ -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

Please use a specific SoC here as the compatible string, not something with 'x' in it as a wildcard.

I will change that.

Quoted 26 lines
Quoted 26 lines
Documentation/devicetree/bindings/misc/bcm47xx-sprom.txt new file +25 -0
+#define NVRAM_READ_VAL(type)						\
+static void nvram_read_ ## type (const struct bcm47xx_sprom_fill *fill,	\
+				 const char *postfix, const char *name, \
+				 type *val, type allset)		\
+{									\
+	char buf[100];							\
+	int err;							\
+	type var;							\
+									\
+	err = get_nvram_var(fill, postfix, name, buf, sizeof(buf));	\
+	if (err < 0)							\
+		return;							\
+	err = kstrto ## type(strim(buf), 0, &var);			\
+	if (err) {							\
+		pr_warn("can not parse nvram name %s%s%s with value %s got %i\n",	\
+			fill->prefix, name, postfix, buf, err);		\
+		return;							\
+	}								\
+	if (allset && var == allset)					\
+		return;							\
+	*val = var;							\
+}
+
+NVRAM_READ_VAL(u8)
+NVRAM_READ_VAL(s8)
Quoted 8 lines

Documentation/devicetree/bindings/misc/bcm47xx-sprom.txt

Quoted 4 lines
Documentation/devicetree/bindings/misc/bcm47xx-sprom.txt new file +4 -0
+NVRAM_READ_VAL(u16)
+NVRAM_READ_VAL(u32)
+
+#undef NVRAM_READ_VAL

Hmm, multiline macros are ugly. How about using one function to read into an s64 internally using kstrtoll, and simple inline wrappers around that for the smaller types, doing the appropriate range check?

Yes that should work I will try it.

Quoted 10 lines
Quoted 10 lines
Documentation/devicetree/bindings/misc/bcm47xx-sprom.txt new file +10 -0
+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);
+	nvram_read_u8(fill, NULL, "ledbh3", &sprom->gpio3, 0xff);
+	nvram_read_u8(fill, NULL, "aa2g", &sprom->ant_available_bg, 0);
+	nvram_read_u8(fill, NULL, "aa5g", &sprom->ant_available_a, 0);
Quoted 8 lines

Documentation/devicetree/bindings/misc/bcm47xx-sprom.txt

Quoted 4 lines
Documentation/devicetree/bindings/misc/bcm47xx-sprom.txt new file +4 -0
+	nvram_read_s8(fill, NULL, "ag0", &sprom->antenna_gain.a0, 0);
+	nvram_read_s8(fill, NULL, "ag1", &sprom->antenna_gain.a1, 0);
+	nvram_read_alpha2(fill, "ccode", sprom->alpha2);
+}

Rather than calling the same set of functions multiple times, can you do this using a table driven approach for smaller code size and improved readability?

I will try to change that.

Quoted 15 lines
Quoted 15 lines
Documentation/devicetree/bindings/misc/bcm47xx-sprom.txt new file +15 -0
+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 __be32 *handle;
+	struct device_node *nvram_node;
+	struct platform_device *nvram_dev;
+	struct bcm47xx_sprom_fill fill;
+
+	/* Alloc */
+	sprom = devm_kzalloc(dev, sizeof(*sprom), GFP_KERNEL);
+	if (!sprom)
+		return -ENOMEM;
+
Quoted 8 lines

Documentation/devicetree/bindings/misc/bcm47xx-sprom.txt

Quoted 5 lines
Documentation/devicetree/bindings/misc/bcm47xx-sprom.txt new file +5 -0
+	handle = of_get_property(np, "nvram", NULL);
+	if (!handle)
+		return -ENOMEM;
+
+	nvram_node = of_find_node_by_phandle(be32_to_cpup(handle));

You can avoid the explicit be32_to_cpup here if you use of_property_read_u32 above.

Thanks for the hint.

Hauke

maintainer
#12 lore raw

RFC 3/7 bcm47xx-sprom: add Broadcom sprom parser driver

Quoted 14 lines · Hauke Mehrtens
Quoted 5 lines · Arnd Bergmann
Quoted 3 lines · On Sunday 24 August 2014 23:24:41 Hauke Mehrtens wrote:
 drivers/misc/Kconfig                               |  14 +
 drivers/misc/Makefile                              |   1 +
 drivers/misc/bcm47xx-sprom.c                       | 690 +++++++++++++++++++++
Quoted 7 lines

On a similar note, putting the driver into drivers/misc seems
suboptimal: misc drivers should by definition be something that is for some odd hardware with no external dependencies on it, whereas your driver seems to be used by multiple other drivers.

Would it make sense to put it into drivers/bcma when that is the only bus it is used on?

Quoted 6 lines

As Jonas already said this code should be used for the bcm53xx ARM code and the bcm47xx MIPS code and it is needed for drivers/bcma/ and drivers/ssb/ (ssb only for old mips devices). Do you have any better idea than putting this to drivers/misc/ ? For the mips SoC we need the code very early and will not use the driver interface but probably directly call the function name.

Ping? Does anyone have any better idea?

Both: nvram and sprom drivers will be used by bcm47xx (mips) and bcm53xx (arm). They can't be put in drivers/bcma, as they are used by drivers/ssb as well.

author maintainer
#13 lore raw

RFC 4/7 bcma: register bcma as device tree driver

In reply to Hauke Mehrtens

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.

---
 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
Documentation/devicetree/bindings/bus/bcma.txt new file +46 -0
new file mode 100644
index 0000000..52fb929
@@ -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 at 18000000 {
+		compatible = "brcm,bus-aix";
+		reg = <0x18000000 0x1000>;
+		ranges = <0x00000000 0x18000000 0x00100000>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		sprom = <&sprom0>;
+
+		gmac at 0 {
+			reg = <0x18024000 0x1000>;
+			interrupts = <GIC_SPI 147 IRQ_TYPE_LEVEL_HIGH>;
+		};
+
+		gmac at 1 {
+			reg = <0x18025000 0x1000>;
+			interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
+		};
+
+		pcie at 0 {
+			reg = <0x18012000 0x1000>;
+			interrupts = <GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>;
+		};
+	};
drivers/bcma/host_soc.c +70 -0

85 lines not on this page · raw message

include/linux/bcma/bcma.h +2 -0
index 0272e49..7a10d6d 100644
@@ -323,6 +323,8 @@ struct bcma_bus {
 		struct pci_dev *host_pci;
 		/* Pointer to the SDIO device (only for BCMA_HOSTTYPE_SDIO) */
 		struct sdio_func *host_sdio;
+		/* Pointer to platform device (only for BCMA_HOSTTYPE_SOC) */
+		struct platform_device *host_pdev;
 	};
 
 	struct bcma_chipinfo chipinfo;
Signature · 1 line
1.9.1
maintainer
#14 lore raw

RFC 4/7 bcma: register bcma as device tree driver

Quoted 5 lines · On Sunday 24 August 2014 23:24:42 Hauke Mehrtens wrote:

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.

Looks good to me overall. Two small comments:

Quoted 22 lines
 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
Documentation/devicetree/bindings/bus/bcma.txt new file +10 -0
new file mode 100644
index 0000000..52fb929
@@ -0,0 +1,46 @@
+Broadcom AIX bcma bus driver
+
+
+Required properties:
+
+- compatible : brcm,bus-aix
+
+- reg : iomem address range of chipcommon core
+
+Optional properties:

Documentation/devicetree/bindings/bus/bcma.txt line 20

Quoted 10 lines
Documentation/devicetree/bindings/bus/bcma.txt new file +10 -0
+
+- 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.

What is the problem with the interrupt numbers? Is that information missing completely from the data available to the brcm bus, or is it in an inconvenient format?

Quoted 4 lines
Documentation/devicetree/bindings/bus/bcma.txt new file +4 -0
+Example:
+
+       aix at 18000000 {
+               compatible = "brcm,bus-aix";

Documentation/devicetree/bindings/bus/bcma.txt line 35

Quoted 10 lines
Documentation/devicetree/bindings/bus/bcma.txt new file +10 -0
+               reg = <0x18000000 0x1000>;
+               ranges = <0x00000000 0x18000000 0x00100000>;
+               #address-cells = <1>;
+               #size-cells = <1>;
+               sprom = <&sprom0>;
+
+               gmac at 0 {
+                       reg = <0x18024000 0x1000>;
+                       interrupts = <GIC_SPI 147 IRQ_TYPE_LEVEL_HIGH>;
+               };

The @0 part seems wrong here: the address should generally match the first entry in the reg property, which would be gmac at 18024000.

Also, you probably mean ethernet@ not gmac at .

Documentation/devicetree/bindings/bus/bcma.txt line 46

Quoted 10 lines
Documentation/devicetree/bindings/bus/bcma.txt new file +10 -0
+               gmac at 1 {
+                       reg = <0x18025000 0x1000>;
+                       interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
+               };
+
+               pcie at 0 {
+                       reg = <0x18012000 0x1000>;
+                       interrupts = <GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>;
+               };
+       };

We may require additional properties for the pcie node, depending on whether we want to use the DT probing interfaces for it, or whether it should just hardcode the settings used on brcm based on the ID.

Arnd

author maintainer
#15 lore raw

RFC 4/7 bcma: register bcma as device tree driver

Quoted 37 lines · Arnd Bergmann
Quoted 5 lines · On Sunday 24 August 2014 23:24:42 Hauke Mehrtens wrote:

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.

Looks good to me overall. Two small comments:

Quoted 28 lines
 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
Documentation/devicetree/bindings/bus/bcma.txt new file +16 -0
new file mode 100644
index 0000000..52fb929
@@ -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
Quoted 8 lines

Documentation/devicetree/bindings/bus/bcma.txt line 20

Quoted 4 lines
Documentation/devicetree/bindings/bus/bcma.txt new file +4 -0
+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.

What is the problem with the interrupt numbers? Is that information missing completely from the data available to the brcm bus, or is it in an inconvenient format?

I do not have access to the datasheet, only to the vendor source code. The irq numbers are hard coded in the vendor code, see:
https://github.com/RMerl/asuswrt-merlin/blob/master/release/src-rt-6.x.4708/linux/linux-2.6.36/arch/arm/plat-brcm/bcm5301x_pcie.c#L286

On the mips SoCs it was possible to read them from some register in the mips core on the aix bus.

Quoted 19 lines
Quoted 5 lines
Documentation/devicetree/bindings/bus/bcma.txt new file +4 -0
+Example:
+
+       aix at 18000000 {
+               compatible = "brcm,bus-aix";

Documentation/devicetree/bindings/bus/bcma.txt line 35

Quoted 10 lines
Documentation/devicetree/bindings/bus/bcma.txt new file +10 -0
+               reg = <0x18000000 0x1000>;
+               ranges = <0x00000000 0x18000000 0x00100000>;
+               #address-cells = <1>;
+               #size-cells = <1>;
+               sprom = <&sprom0>;
+
+               gmac at 0 {
+                       reg = <0x18024000 0x1000>;
+                       interrupts = <GIC_SPI 147 IRQ_TYPE_LEVEL_HIGH>;
+               };

The @0 part seems wrong here: the address should generally match the first entry in the reg property, which would be gmac at 18024000.

Quoted 1 line

Also, you probably mean ethernet@ not gmac at .

Will change that.

Quoted 11 lines

Documentation/devicetree/bindings/bus/bcma.txt line 46

Quoted 10 lines
Documentation/devicetree/bindings/bus/bcma.txt new file +10 -0
+               gmac at 1 {
+                       reg = <0x18025000 0x1000>;
+                       interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
+               };
+
+               pcie at 0 {
+                       reg = <0x18012000 0x1000>;
+                       interrupts = <GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>;
+               };
+       };
Quoted 3 lines

We may require additional properties for the pcie node, depending on whether we want to use the DT probing interfaces for it, or whether it should just hardcode the settings used on brcm based on the ID.

I wrote a driver for the PCIe host controller and it also automatically detects all needed memory addresses, it just had to provide the IRQ number through device tree.

Quoted 3 lines

Arnd

author maintainer
#16 lore raw

RFC 5/7 bcma: get IRQ numbers from dt

In reply to Hauke Mehrtens

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.

---
 drivers/bcma/main.c | 42 +++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 41 insertions(+), 1 deletion(-)
drivers/bcma/main.c +41 -1
index 0ff8d58..3f75776 100644
@@ -10,6 +10,8 @@
 #include <linux/platform_device.h>
 #include <linux/bcma/bcma.h>
 #include <linux/slab.h>
+#include <linux/of_irq.h>
+#include <linux/of_address.h>
 
 MODULE_DESCRIPTION("Broadcom's specific AMBA driver");
 MODULE_LICENSE("GPL");
@@ -120,6 +122,38 @@ static void bcma_release_core_dev(struct device *dev)
 	kfree(core);
 }
 
+static struct device_node *bcma_of_find_child_device(struct platform_device *parent,
+						     struct bcma_device *core)
+{
+	struct device_node *node;
+	u64 size;
+	const __be32 *reg;
+
+	if (!parent || !parent->dev.of_node)
+		return NULL;
+
+	for_each_child_of_node(parent->dev.of_node, node) {
+		reg = of_get_address(node, 0, &size, NULL);
+		if (!reg)
+			continue;
+		if (be32_to_cpup(reg) == core->addr)
+			return node;
+	}
+	return NULL;
+}
+
+static void bcma_of_fill_device(struct platform_device *parent,
+				struct bcma_device *core)
+{
+	struct device_node *node;
+
+	node = bcma_of_find_child_device(parent, core);
+	if (!node)
+		return;
+	core->dev.of_node = node;
+	core->irq = irq_of_parse_and_map(node, 0);
+}
+
 static int bcma_register_cores(struct bcma_bus *bus)
 {
 	struct bcma_device *core;
@@ -155,7 +189,13 @@ static int bcma_register_cores(struct bcma_bus *bus)
 			break;
 		case BCMA_HOSTTYPE_SOC:
 			core->dev.dma_mask = &core->dev.coherent_dma_mask;
-			core->dma_dev = &core->dev;
+			if (bus->host_pdev) {
+				core->dma_dev = &bus->host_pdev->dev;
+				core->dev.parent = &bus->host_pdev->dev;
+				bcma_of_fill_device(bus->host_pdev, core);
+			} else {
+				core->dma_dev = &core->dev;
+			}
 			break;
 		case BCMA_HOSTTYPE_SDIO:
 			break;
Signature · 1 line
1.9.1
maintainer
#17 lore raw

RFC 5/7 bcma: get IRQ numbers from dt

Quoted 7 lines · On Sunday 24 August 2014 23:24:43 Hauke Mehrtens wrote:

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.

author maintainer
#18 lore raw

RFC 6/7 bcma: get sprom from devicetree

In reply to Hauke Mehrtens

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 it gets asked for a sprom.

---
 drivers/bcma/sprom.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 50 insertions(+), 1 deletion(-)
drivers/bcma/sprom.c +50 -1
index efb037f..ebe495d 100644
@@ -15,6 +15,8 @@
 #include <linux/io.h>
 #include <linux/dma-mapping.h>
 #include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
 
 static int(*get_fallback_sprom)(struct bcma_bus *dev, struct ssb_sprom *out);
 
@@ -46,6 +48,46 @@ int bcma_arch_register_fallback_sprom(int (*sprom_callback)(struct bcma_bus *bus
 	return 0;
 }
 
+#ifdef CONFIG_OF
+static int bcma_fill_sprom_with_dt(struct bcma_bus *bus,
+				   struct ssb_sprom *out)
+{
+	const __be32 *handle;
+	struct device_node *sprom_node;
+	struct platform_device *sprom_dev;
+	struct ssb_sprom *sprom;
+
+	if (!bus->host_pdev || !bus->host_pdev->dev.of_node)
+		return -ENOENT;
+
+	handle = of_get_property(bus->host_pdev->dev.of_node, "sprom", NULL);
+	if (!handle)
+		return -ENOENT;
+
+	sprom_node = of_find_node_by_phandle(be32_to_cpup(handle));
+	if (!sprom_node)
+		return -ENOENT;
+
+	sprom_dev = of_find_device_by_node(sprom_node);
+	if (!sprom_dev)
+		return -ENOENT;
+
+	sprom = platform_get_drvdata(sprom_dev);
+	if (!sprom)
+		return -ENOENT;
+
+	memcpy(out, sprom, sizeof(*out));
+
+	return 0;
+}
+#else
+static int bcma_fill_sprom_with_dt(struct bcma_bus *bus,
+				   struct ssb_sprom *out)
+{
+	return -ENOENT;
+}
+#endif
+
 static int bcma_fill_sprom_with_fallback(struct bcma_bus *bus,
 					 struct ssb_sprom *out)
 {
@@ -580,7 +622,14 @@ int bcma_sprom_get(struct bcma_bus *bus)
 	u16 *sprom;
 	size_t sprom_sizes[] = { SSB_SPROMSIZE_WORDS_R4,
 				 SSB_SPROMSIZE_WORDS_R10, };
-	int i, err = 0;
+	int i, err;
+
+	err = bcma_fill_sprom_with_dt(bus, &bus->sprom);
+	if (err == 0) {
+		bcma_info(bus, "Found sprom from device tree provider\n");
+		return 0;
+	}
+	err = 0;
 
 	if (!bus->drv_cc.core)
 		return -EOPNOTSUPP;
Signature · 1 line
1.9.1
maintainer
#19 lore raw

RFC 6/7 bcma: get sprom from devicetree

drivers/bcma/sprom.c int bcma_arch_register_fallback_sprom(int (*sprom_callback)(struct bcma_bus *bus · line 61

Quoted 11 lines · On Sunday 24 August 2014 23:24:44 Hauke Mehrtens wrote:
drivers/bcma/sprom.c +11 -0
+#ifdef CONFIG_OF
+static int bcma_fill_sprom_with_dt(struct bcma_bus *bus,
+                                  struct ssb_sprom *out)
+{
+       const __be32 *handle;
+       struct device_node *sprom_node;
+       struct platform_device *sprom_dev;
+       struct ssb_sprom *sprom;
+
+       if (!bus->host_pdev || !bus->host_pdev->dev.of_node)
+               return -ENOENT;

You can remove the #ifdef above if you change this into

	if (!IS_ENABLED(CONFIG_OF) || !bus->host_pdev ||
	    !bus->host_pdev->dev.of_node)
		return -ENOENT;
Quoted 10 lines
drivers/bcma/sprom.c +10 -0
+       handle = of_get_property(bus->host_pdev->dev.of_node, "sprom", NULL);
+       if (!handle)
+               return -ENOENT;
+
+       sprom_node = of_find_node_by_phandle(be32_to_cpup(handle));
+       if (!sprom_node)
+               return -ENOENT;
+
+       sprom_dev = of_find_device_by_node(sprom_node);
+       if (!sprom_dev)

drivers/bcma/sprom.c int bcma_arch_register_fallback_sprom(int (*sprom_callback)(struct bcma_bus *bus · line 82

Quoted 10 lines
drivers/bcma/sprom.c +10 -0
+               return -ENOENT;
+
+       sprom = platform_get_drvdata(sprom_dev);
+       if (!sprom)
+               return -ENOENT;
+
+       memcpy(out, sprom, sizeof(*out));
+
+       return 0;
+}

missing of_node_put().

Arnd

author maintainer
#20 lore raw

RFC 7/7 ARM: BCM5301X: register bcma bus

In reply to Hauke Mehrtens
---
 arch/arm/boot/dts/bcm4708.dtsi | 58 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 58 insertions(+)
arch/arm/boot/dts/bcm4708.dtsi +58 -0
index 31141e8..7c240ab 100644
@@ -31,4 +31,62 @@
 		};
 	};
 
+	nvram0: nvram at 0 {
+		compatible = "brcm,bcm47xx-nvram";
+		reg = <0x1c000000 0x01000000>;
+	};
+
+	sprom0: sprom at 0 {
+		compatible = "brcm,bcm47xx-sprom";
+		nvram = <&nvram0>;
+	};
+
+	aix at 18000000 {
+		compatible = "brcm,bus-aix";
+		reg = <0x18000000 0x1000>;
+		ranges = <0x00000000 0x18000000 0x00100000>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		sprom = <&sprom0>;
+
+		usb2 at 0 {
+			reg = <0x18021000 0x1000>;
+			interrupts = <GIC_SPI 79 IRQ_TYPE_LEVEL_HIGH>;
+		};
+
+		usb3 at 0 {
+			reg = <0x18023000 0x1000>;
+			interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>;
+		};
+
+		gmac at 0 {
+			reg = <0x18024000 0x1000>;
+			interrupts = <GIC_SPI 147 IRQ_TYPE_LEVEL_HIGH>;
+		};
+
+		gmac at 1 {
+			reg = <0x18025000 0x1000>;
+			interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
+		};
+
+		gmac at 2 {
+			reg = <0x18026000 0x1000>;
+			interrupts = <GIC_SPI 149 IRQ_TYPE_LEVEL_HIGH>;
+		};
+
+		gmac at 3 {
+			reg = <0x18027000 0x1000>;
+			interrupts = <GIC_SPI 150 IRQ_TYPE_LEVEL_HIGH>;
+		};
+
+		pcie at 0 {
+			reg = <0x18012000 0x1000>;
+			interrupts = <GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>;
+		};
+
+		pcie at 1 {
+			reg = <0x18013000 0x1000>;
+			interrupts = <GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>;
+		};
+	};
 };
Signature · 1 line
1.9.1
#21 lore raw

RFC 7/7 ARM: BCM5301X: register bcma bus

Quoted 3 lines · Hauke Mehrtens
---
 arch/arm/boot/dts/bcm4708.dtsi | 58 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 58 insertions(+)

We probably want a compatible string for each of these aix subnodes you are adding, so we can match them.

Quoted 69 lines
arch/arm/boot/dts/bcm4708.dtsi +58 -0
index 31141e8..7c240ab 100644
@@ -31,4 +31,62 @@
 		};
 	};
 
+	nvram0: nvram at 0 {
+		compatible = "brcm,bcm47xx-nvram";
+		reg = <0x1c000000 0x01000000>;
+	};
+
+	sprom0: sprom at 0 {
+		compatible = "brcm,bcm47xx-sprom";
+		nvram = <&nvram0>;
+	};
+
+	aix at 18000000 {
+		compatible = "brcm,bus-aix";
+		reg = <0x18000000 0x1000>;
+		ranges = <0x00000000 0x18000000 0x00100000>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		sprom = <&sprom0>;
+
+		usb2 at 0 {
+			reg = <0x18021000 0x1000>;
+			interrupts = <GIC_SPI 79 IRQ_TYPE_LEVEL_HIGH>;
+		};
+
+		usb3 at 0 {
+			reg = <0x18023000 0x1000>;
+			interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>;
+		};
+
+		gmac at 0 {
+			reg = <0x18024000 0x1000>;
+			interrupts = <GIC_SPI 147 IRQ_TYPE_LEVEL_HIGH>;
+		};
+
+		gmac at 1 {
+			reg = <0x18025000 0x1000>;
+			interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
+		};
+
+		gmac at 2 {
+			reg = <0x18026000 0x1000>;
+			interrupts = <GIC_SPI 149 IRQ_TYPE_LEVEL_HIGH>;
+		};
+
+		gmac at 3 {
+			reg = <0x18027000 0x1000>;
+			interrupts = <GIC_SPI 150 IRQ_TYPE_LEVEL_HIGH>;
+		};
+
+		pcie at 0 {
+			reg = <0x18012000 0x1000>;
+			interrupts = <GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>;
+		};
+
+		pcie at 1 {
+			reg = <0x18013000 0x1000>;
+			interrupts = <GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>;
+		};
+	};
 };