Enabling b43 wifi in Lantiq arch

Hi,

I'm currently porting a new device to OpenWRT (Arcadyan vrv9519bwac23). I could successfully boot a image and make gpio/leds/buttons/ethernet switch work. But now I'm having problems for getting wifi enabled.

I've seen that this is the first Lantiq device with broadcom wifi chipsets (Broadcom BCM43222 and Broadcom BCM4360). Most of the devices have ralink/atheros chipsets. So I basically tried to enable b43 and see what happens:

[   13.151866] b43-pci-bridge 0000:00:0e.0: enabling device (0000 -> 0002)
[   13.215799] ssb: Found chip with id 0xA8D6, rev 0x00 and package 0x08
[   13.291317] ssb: WARNING: Using fallback SPROM failed (err -2)
[   13.295812] b43-pci-bridge 0000:00:0e.0: Failed to register PCI version of SSB with error -2
[   13.304198] b43-pci-bridge: probe of 0000:00:0e.0 failed with error -2

The driver is able to detect the device but does not have access to the SPROM. lspci also can detect the device

root@OpenWrt:/sys/bus/pci# lspci -vv
00:0e.0 Network controller: Broadcom Inc. and subsidiaries Device a8d6
        Subsystem: Broadcom Inc. and subsidiaries Device a8d6
        Control: I/O- Mem+ BusMaster- SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx-
        Status: Cap- 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
        Interrupt: pin A routed to IRQ 30
        Region 0: Memory at 18000000 (32-bit, non-prefetchable) [size=16K]
lspci: Unable to load libkmod resources: error -12

I have been watching dts from bcm63xx arch seems to be adding sprom-related info via patch, for example:

+static struct board_info __initdata board_AV4202N = {
+	.name = "96368_Swiss_S1",
+	.expected_cpu_id = 0x6368,
+
+	.has_pci = 1,
+	.has_ohci0 = 1,
+	.has_ehci0 = 1,
+	.num_usbh_ports = 2,
+
+	.has_enetsw = 1,
+	.enetsw = {
+		.used_ports = {
+			[0] = {
+				.used = 1,
+				.phy_id = 1,
+				.name = "port1",
+			},
+			[1] = {
+				.used = 1,
+				.phy_id = 2,
+				.name = "port2",
+			},
+			[2] = {
+				.used = 1,
+				.phy_id = 3,
+				.name = "port3",
+			},
+			[3] = {
+				.used = 1,
+				.phy_id = 4,
+				.name = "port4",
+			},
+		},
+	},
+
+	.use_fallback_sprom = 1,
+	.fallback_sprom = {
+		.type = SPROM_BCM4322,
+		.pci_bus = 0,
+		.pci_dev = 1,
+	},
+};
+

I have not seen anything similar on lantiq architecture, and I'm getting a bit lost.

Does someone have any idea how to deal with this?

Thanks in advice,

What's more impressive is that the another Broadcomm chip (the 5GHz one) won't show on lspci... Can't figure out why...

Looks like Juan Rios dealed with this issue 6 years ago and figured out a way to make it working by making a patch to the b43 driver:

[LEDE-DEV] Arcadyan vrv9510kwac23 (mail-archive.com)

Unfortunetly I can't guess what he did. What's clear: the device has no SPROM, so fallback needs to be implemented

Basically the problem is: b43 driver contacts SSB using b43-bridge to retrive sprom data. SSB can't do it because there is no sprom so it tries to ask our arch for a fallback function, which does not exists (that's why it's returning that -2 at kernel log).

I found this at sprom.c on ssb drivers:

/**
 * ssb_arch_register_fallback_sprom - Registers a method providing a
 * fallback SPROM if no SPROM is found.
 *
 * @sprom_callback: The callback function.
 *
 * With this function the architecture implementation may register a
 * callback handler which fills the SPROM data structure. The fallback is
 * only used for PCI based SSB devices, where no valid SPROM can be found
 * in the shadow registers.
 *
 * This function is useful for weird architectures that have a half-assed
 * SSB device hardwired to their PCI bus.
 *
 * Note that it does only work with PCI attached SSB devices. PCMCIA
 * devices currently don't use this fallback.
 * Architectures must provide the SPROM for native SSB devices anyway, so
 * the fallback also isn't used for native devices.
 *
 * This function is available for architecture code, only. So it is not
 * exported.
 */
int ssb_arch_register_fallback_sprom(int (*sprom_callback)(struct ssb_bus *bus,
				     struct ssb_sprom *out))
{
	if (get_fallback_sprom)
		return -EEXIST;
	get_fallback_sprom = sprom_callback;

	return 0;
}

int ssb_fill_sprom_with_fallback(struct ssb_bus *bus, struct ssb_sprom *out)
{
	if (!get_fallback_sprom)
		return -ENOENT;

	return get_fallback_sprom(bus, out);
}

SSB provides a mechanism to allow architectures to implement custom fallback procedure in that case, so when sprom can't be read we can do a workaround. For example, bmips architecture has defined sprom mapping hardcoded:

static u16 bcm43222_sprom_map[] = {
	0x2001, 0x0000, 0x04d4, 0x14e4, 0x4351, 0x8000, 0x0002, 0x0000,
	0x1730, 0x1800, 0x0000, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff,
	0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
	0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
	0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
	0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
	0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
	0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
	0x5372, 0x2305, 0x0200, 0x0000, 0x2400, 0x0000, 0x0000, 0x0000,
	0x0000, 0x0000, 0x0000, 0xffff, 0xffff, 0xffff, 0x0303, 0x0202,
	0xffff, 0x0033, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x0325,
	0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
	0x204c, 0xfea6, 0x1717, 0xfa6d, 0xffff, 0xffff, 0xffff, 0xffff,
	0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
	0x204c, 0xfeb8, 0x167c, 0xfa9e, 0xffff, 0xffff, 0xffff, 0xffff,
	0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
	0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
	0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
	0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
	0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
	0x0000, 0x3333, 0x3333, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
	0x0000, 0x3333, 0x3333, 0x3333, 0x3333, 0x3333, 0x3333, 0x3333,
	0x3333, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
	0x0000, 0x0000, 0x0000, 0x0004, 0x0000, 0xffff, 0xffff, 0xffff,
	0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
	0xffff, 0xffff, 0xffff, 0x0008,
};

and defines it's own fallback function to provide this data to the requested bus (or at least that's why I think it does)

#if defined(CONFIG_SSB_PCIHOST)
int b43_get_fallback_ssb_sprom(struct ssb_bus *bus, struct ssb_sprom *out)
{
	struct b43_sprom *priv = &b43_sprom;

	if (bus->bustype == SSB_BUSTYPE_PCI) {
		if (bus->host_pci->bus->number != priv->pci_bus ||
		    PCI_SLOT(bus->host_pci->devfn) != priv->pci_dev)
			pr_warn("ssb_fallback_sprom: pci bus/device num "
				"mismatch: expected %i/%i, but got %i/%i\n",
				priv->pci_bus, priv->pci_dev,
				bus->host_pci->bus->number,
				PCI_SLOT(bus->host_pci->devfn));
		if (priv->devid_override)
			bus->host_pci->device = priv->sprom.dev_id;
		memcpy(out, &priv->sprom, sizeof(struct ssb_sprom));
		return 0;
	} else {
		pr_err("%s: unable to fill SPROM for given bustype.\n",
		       __func__);
		return -EINVAL;
	}
}

The just simply call the fallback register function to tell to use that function:

ret = ssb_arch_register_fallback_sprom(&b43_get_fallback_ssb_sprom);

Maybe I can use this approach, but I'm not sure if I will know how to do those modifications to my device...

bmips architecture provides a generic b43 fallback driver.

// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * B43 Fallback SPROM Driver
 *
 * Copyright (C) 2020 Álvaro Fernández Rojas <noltari@gmail.com>
 * Copyright (C) 2014 Jonas Gorski <jonas.gorski@gmail.com>
 * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
 * Copyright (C) 2008 Florian Fainelli <f.fainelli@gmail.com>
 */

After some headaches I managed to make it work on the lantiq architecture. The good news is that the driver seems to be working!

[   10.306065] b43-sprom bcm43222-sprom: patching SPROM with 6 fixups...
[   10.315824] b43-sprom bcm43222-sprom: random mac 72:ec:4f:4b:bc:ae

The bad news is that this is being executed AFTER the b43-pci-bridge, so I'm getting the same error.

0.486302] b43-pci-bridge 0000:00:0e.0: enabling device (0000 -> 0002)
[    0.548532] ssb: Found chip with id 0xA8D6, rev 0x00 and package 0x08
[    0.623997] ssb: WARNING: Using fallback SPROM failed (err -2)
[    0.629752] b43-pci-bridge 0000:00:0e.0: Failed to register PCI version of SSB with error -2
[    0.638205] b43-pci-bridge: probe of 0000:00:0e.0 failed with error -2

Now I need to figure out how to execute the b43 fallback driver first!

Playing with core_initcall and late_initcall on b43-sprom.c and b34_pci_bridge.c I managed to get it working...

Solved!

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.