Browse Source

mac80211: add first brcmfmac patches for 14e4:4365 BCM4366 support

It's not really supported yet as it still fails with:
brcmfmac: brcmf_pcie_download_fw_nvram: FW failed to initialize

Signed-off-by: Rafał Miłecki <[email protected]>

SVN-Revision: 48640
Rafał Miłecki 9 years ago
parent
commit
d99cdd4fef

+ 51 - 0
package/kernel/mac80211/patches/323-0001-brcmfmac-analyze-descriptors-of-current-component-on.patch

@@ -0,0 +1,51 @@
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <[email protected]>
+Date: Tue, 26 Jan 2016 17:57:01 +0100
+Subject: [PATCH] brcmfmac: analyze descriptors of current component only
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+So far we were looking for address descriptors without a check for
+crossing current component border. In case of dealing with unsupported
+descriptor or descriptor missing at all the code would incorrectly get
+data from another component.
+
+Consider this binary-described component from BCM4366 EROM:
+4bf83b01	TAG==CI		CID==0x83b
+20080201	TAG==CI		PORTS==0+1	WRAPPERS==0+1
+18400035	TAG==ADDR	SZ_SZD		TYPE_SLAVE
+00050000
+18107085	TAG==ADDR	SZ_4K		TYPE_SWRAP
+
+Driver was assigning invalid base address to this core:
+brcmfmac:  [6 ] core 0x83b:32 base 0x18109000 wrap 0x18107000
+which came from totally different component defined in EROM:
+43b36701	TAG==CI		CID==0x367
+00000201	TAG==CI		PORTS==0+1	WRAPPERS==0+0
+18109005	TAG==ADDR	SZ_4K		TYPE_SLAVE
+
+This change will also allow us to support components without wrapper
+address in the future.
+
+Signed-off-by: Rafał Miłecki <[email protected]>
+Signed-off-by: Kalle Valo <[email protected]>
+---
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
+@@ -803,7 +803,14 @@ static int brcmf_chip_dmp_get_regaddr(st
+ 				*eromaddr -= 4;
+ 				return -EFAULT;
+ 			}
+-		} while (desc != DMP_DESC_ADDRESS);
++		} while (desc != DMP_DESC_ADDRESS &&
++			 desc != DMP_DESC_COMPONENT);
++
++		/* stop if we crossed current component border */
++		if (desc == DMP_DESC_COMPONENT) {
++			*eromaddr -= 4;
++			return 0;
++		}
+ 
+ 		/* skip upper 32-bit address descriptor */
+ 		if (val & DMP_DESC_ADDRSIZE_GT32)

+ 28 - 0
package/kernel/mac80211/patches/323-0002-brcmfmac-allow-storing-PMU-core-without-wrapper-addr.patch

@@ -0,0 +1,28 @@
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <[email protected]>
+Date: Tue, 26 Jan 2016 17:57:02 +0100
+Subject: [PATCH] brcmfmac: allow storing PMU core without wrapper address
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Separated PMU core can be found in new devices and should be used for
+accessing PMU registers (which were routed through ChipCommon so far).
+This core is one of exceptions that doesn't have or need wrapper address
+to be still safely accessible.
+
+Signed-off-by: Rafał Miłecki <[email protected]>
+Signed-off-by: Kalle Valo <[email protected]>
+---
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
+@@ -883,7 +883,8 @@ int brcmf_chip_dmp_erom_scan(struct brcm
+ 		rev = (val & DMP_COMP_REVISION) >> DMP_COMP_REVISION_S;
+ 
+ 		/* need core with ports */
+-		if (nmw + nsw == 0)
++		if (nmw + nsw == 0 &&
++		    id != BCMA_CORE_PMU)
+ 			continue;
+ 
+ 		/* try to obtain register address info */

+ 43 - 0
package/kernel/mac80211/patches/323-0003-brcmfmac-read-extended-capabilities-of-ChipCommon-co.patch

@@ -0,0 +1,43 @@
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <[email protected]>
+Date: Tue, 26 Jan 2016 17:57:03 +0100
+Subject: [PATCH] brcmfmac: read extended capabilities of ChipCommon core
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This is an extra bitfield with info about some present hardware.
+
+Signed-off-by: Rafał Miłecki <[email protected]>
+Signed-off-by: Kalle Valo <[email protected]>
+---
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
+@@ -1025,6 +1025,9 @@ static int brcmf_chip_setup(struct brcmf
+ 	/* get chipcommon capabilites */
+ 	pub->cc_caps = chip->ops->read32(chip->ctx,
+ 					 CORE_CC_REG(base, capabilities));
++	pub->cc_caps_ext = chip->ops->read32(chip->ctx,
++					     CORE_CC_REG(base,
++							 capabilities_ext));
+ 
+ 	/* get pmu caps & rev */
+ 	if (pub->cc_caps & CC_CAP_PMU) {
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.h
+@@ -27,6 +27,7 @@
+  * @chip: chip identifier.
+  * @chiprev: chip revision.
+  * @cc_caps: chipcommon core capabilities.
++ * @cc_caps_ext: chipcommon core extended capabilities.
+  * @pmucaps: PMU capabilities.
+  * @pmurev: PMU revision.
+  * @rambase: RAM base address (only applicable for ARM CR4 chips).
+@@ -38,6 +39,7 @@ struct brcmf_chip {
+ 	u32 chip;
+ 	u32 chiprev;
+ 	u32 cc_caps;
++	u32 cc_caps_ext;
+ 	u32 pmucaps;
+ 	u32 pmurev;
+ 	u32 rambase;

+ 148 - 0
package/kernel/mac80211/patches/323-0004-brcmfmac-access-PMU-registers-using-standalone-PMU-c.patch

@@ -0,0 +1,148 @@
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <[email protected]>
+Date: Tue, 26 Jan 2016 17:57:04 +0100
+Subject: [PATCH] brcmfmac: access PMU registers using standalone PMU core if
+ available
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+On recent Broadcom chipsets PMU is present as separated core and it
+can't be accessed using ChipCommon anymore as it fails with e.g.:
+[   18.198412] Unhandled fault: imprecise external abort (0x1406) at 0xb6da200f
+
+Add a new helper function that will return a proper core that should be
+used for accessing PMU registers.
+
+Signed-off-by: Rafał Miłecki <[email protected]>
+Signed-off-by: Kalle Valo <[email protected]>
+---
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
+@@ -1014,6 +1014,7 @@ static int brcmf_chip_setup(struct brcmf
+ {
+ 	struct brcmf_chip *pub;
+ 	struct brcmf_core_priv *cc;
++	struct brcmf_core *pmu;
+ 	u32 base;
+ 	u32 val;
+ 	int ret = 0;
+@@ -1030,9 +1031,10 @@ static int brcmf_chip_setup(struct brcmf
+ 							 capabilities_ext));
+ 
+ 	/* get pmu caps & rev */
++	pmu = brcmf_chip_get_pmu(pub); /* after reading cc_caps_ext */
+ 	if (pub->cc_caps & CC_CAP_PMU) {
+ 		val = chip->ops->read32(chip->ctx,
+-					CORE_CC_REG(base, pmucapabilities));
++					CORE_CC_REG(pmu->base, pmucapabilities));
+ 		pub->pmurev = val & PCAP_REV_MASK;
+ 		pub->pmucaps = val;
+ 	}
+@@ -1131,6 +1133,23 @@ struct brcmf_core *brcmf_chip_get_chipco
+ 	return &cc->pub;
+ }
+ 
++struct brcmf_core *brcmf_chip_get_pmu(struct brcmf_chip *pub)
++{
++	struct brcmf_core *cc = brcmf_chip_get_chipcommon(pub);
++	struct brcmf_core *pmu;
++
++	/* See if there is separated PMU core available */
++	if (cc->rev >= 35 &&
++	    pub->cc_caps_ext & BCMA_CC_CAP_EXT_AOB_PRESENT) {
++		pmu = brcmf_chip_get_core(pub, BCMA_CORE_PMU);
++		if (pmu)
++			return pmu;
++	}
++
++	/* Fallback to ChipCommon core for older hardware */
++	return cc;
++}
++
+ bool brcmf_chip_iscoreup(struct brcmf_core *pub)
+ {
+ 	struct brcmf_core_priv *core;
+@@ -1301,6 +1320,7 @@ bool brcmf_chip_sr_capable(struct brcmf_
+ {
+ 	u32 base, addr, reg, pmu_cc3_mask = ~0;
+ 	struct brcmf_chip_priv *chip;
++	struct brcmf_core *pmu = brcmf_chip_get_pmu(pub);
+ 
+ 	brcmf_dbg(TRACE, "Enter\n");
+ 
+@@ -1320,9 +1340,9 @@ bool brcmf_chip_sr_capable(struct brcmf_
+ 	case BRCM_CC_4335_CHIP_ID:
+ 	case BRCM_CC_4339_CHIP_ID:
+ 		/* read PMU chipcontrol register 3 */
+-		addr = CORE_CC_REG(base, chipcontrol_addr);
++		addr = CORE_CC_REG(pmu->base, chipcontrol_addr);
+ 		chip->ops->write32(chip->ctx, addr, 3);
+-		addr = CORE_CC_REG(base, chipcontrol_data);
++		addr = CORE_CC_REG(pmu->base, chipcontrol_data);
+ 		reg = chip->ops->read32(chip->ctx, addr);
+ 		return (reg & pmu_cc3_mask) != 0;
+ 	case BRCM_CC_43430_CHIP_ID:
+@@ -1330,12 +1350,12 @@ bool brcmf_chip_sr_capable(struct brcmf_
+ 		reg = chip->ops->read32(chip->ctx, addr);
+ 		return reg != 0;
+ 	default:
+-		addr = CORE_CC_REG(base, pmucapabilities_ext);
++		addr = CORE_CC_REG(pmu->base, pmucapabilities_ext);
+ 		reg = chip->ops->read32(chip->ctx, addr);
+ 		if ((reg & PCAPEXT_SR_SUPPORTED_MASK) == 0)
+ 			return false;
+ 
+-		addr = CORE_CC_REG(base, retention_ctl);
++		addr = CORE_CC_REG(pmu->base, retention_ctl);
+ 		reg = chip->ops->read32(chip->ctx, addr);
+ 		return (reg & (PMU_RCTL_MACPHY_DISABLE_MASK |
+ 			       PMU_RCTL_LOGIC_DISABLE_MASK)) == 0;
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.h
+@@ -85,6 +85,7 @@ struct brcmf_chip *brcmf_chip_attach(voi
+ void brcmf_chip_detach(struct brcmf_chip *chip);
+ struct brcmf_core *brcmf_chip_get_core(struct brcmf_chip *chip, u16 coreid);
+ struct brcmf_core *brcmf_chip_get_chipcommon(struct brcmf_chip *chip);
++struct brcmf_core *brcmf_chip_get_pmu(struct brcmf_chip *pub);
+ bool brcmf_chip_iscoreup(struct brcmf_core *core);
+ void brcmf_chip_coredisable(struct brcmf_core *core, u32 prereset, u32 reset);
+ void brcmf_chip_resetcore(struct brcmf_core *core, u32 prereset, u32 reset,
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
+@@ -3615,7 +3615,6 @@ brcmf_sdio_drivestrengthinit(struct brcm
+ 	const struct sdiod_drive_str *str_tab = NULL;
+ 	u32 str_mask;
+ 	u32 str_shift;
+-	u32 base;
+ 	u32 i;
+ 	u32 drivestrength_sel = 0;
+ 	u32 cc_data_temp;
+@@ -3658,14 +3657,15 @@ brcmf_sdio_drivestrengthinit(struct brcm
+ 	}
+ 
+ 	if (str_tab != NULL) {
++		struct brcmf_core *pmu = brcmf_chip_get_pmu(ci);
++
+ 		for (i = 0; str_tab[i].strength != 0; i++) {
+ 			if (drivestrength >= str_tab[i].strength) {
+ 				drivestrength_sel = str_tab[i].sel;
+ 				break;
+ 			}
+ 		}
+-		base = brcmf_chip_get_chipcommon(ci)->base;
+-		addr = CORE_CC_REG(base, chipcontrol_addr);
++		addr = CORE_CC_REG(pmu->base, chipcontrol_addr);
+ 		brcmf_sdiod_regwl(sdiodev, addr, 1, NULL);
+ 		cc_data_temp = brcmf_sdiod_regrl(sdiodev, addr, NULL);
+ 		cc_data_temp &= ~str_mask;
+@@ -3835,8 +3835,7 @@ brcmf_sdio_probe_attach(struct brcmf_sdi
+ 		goto fail;
+ 
+ 	/* set PMUControl so a backplane reset does PMU state reload */
+-	reg_addr = CORE_CC_REG(brcmf_chip_get_chipcommon(bus->ci)->base,
+-			       pmucontrol);
++	reg_addr = CORE_CC_REG(brcmf_chip_get_pmu(bus->ci)->base, pmucontrol);
+ 	reg_val = brcmf_sdiod_regrl(bus->sdiodev, reg_addr, &err);
+ 	if (err)
+ 		goto fail;

+ 38 - 0
package/kernel/mac80211/patches/323-0005-brcmfmac-add-support-for-14e4-4365-PCI-ID-with-BCM43.patch

@@ -0,0 +1,38 @@
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <[email protected]>
+Date: Tue, 26 Jan 2016 17:57:05 +0100
+Subject: [PATCH] brcmfmac: add support for 14e4:4365 PCI ID with BCM4366
+ chipset
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+On Broadcom ARM routers BCM4366 cards are available with 14e4:4365 ID.
+Unfortunately this ID was already used by Broadcom for cards with
+BCM43142, a totally different chipset requiring SoftMAC driver. To avoid
+a conflict between brcmfmac and bcma use more specific ID entry with
+subvendor and subdevice specified.
+
+Signed-off-by: Rafał Miłecki <[email protected]>
+Signed-off-by: Kalle Valo <[email protected]>
+---
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
+@@ -1951,6 +1951,9 @@ static const struct dev_pm_ops brcmf_pci
+ 
+ #define BRCMF_PCIE_DEVICE(dev_id)	{ BRCM_PCIE_VENDOR_ID_BROADCOM, dev_id,\
+ 	PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_NETWORK_OTHER << 8, 0xffff00, 0 }
++#define BRCMF_PCIE_DEVICE_SUB(dev_id, subvend, subdev)	{ \
++	BRCM_PCIE_VENDOR_ID_BROADCOM, dev_id,\
++	subvend, subdev, PCI_CLASS_NETWORK_OTHER << 8, 0xffff00, 0 }
+ 
+ static struct pci_device_id brcmf_pcie_devid_table[] = {
+ 	BRCMF_PCIE_DEVICE(BRCM_PCIE_4350_DEVICE_ID),
+@@ -1966,6 +1969,7 @@ static struct pci_device_id brcmf_pcie_d
+ 	BRCMF_PCIE_DEVICE(BRCM_PCIE_4365_DEVICE_ID),
+ 	BRCMF_PCIE_DEVICE(BRCM_PCIE_4365_2G_DEVICE_ID),
+ 	BRCMF_PCIE_DEVICE(BRCM_PCIE_4365_5G_DEVICE_ID),
++	BRCMF_PCIE_DEVICE_SUB(0x4365, BRCM_PCIE_VENDOR_ID_BROADCOM, 0x4365),
+ 	BRCMF_PCIE_DEVICE(BRCM_PCIE_4366_DEVICE_ID),
+ 	BRCMF_PCIE_DEVICE(BRCM_PCIE_4366_2G_DEVICE_ID),
+ 	BRCMF_PCIE_DEVICE(BRCM_PCIE_4366_5G_DEVICE_ID),

+ 32 - 0
package/kernel/mac80211/patches/324-brcmfmac-treat-NULL-character-in-NVRAM-as-separator.patch

@@ -0,0 +1,32 @@
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <[email protected]>
+Date: Sun, 31 Jan 2016 12:14:34 +0100
+Subject: [PATCH] brcmfmac: treat NULL character in NVRAM as separator
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Platform NVRAM (stored on a flash partition) has entries separated by a
+NULL (\0) char. Our parsing code switches from VALUE state to IDLE
+whenever it meets a NULL (\0). When that happens our IDLE handler should
+simply consume it and analyze whatever is placed ahead.
+
+This fixes harmless warnings spamming debugging output:
+[  155.165624] brcmfmac: brcmf_nvram_handle_idle warning: ln=1:col=20: ignoring invalid character
+[  155.180806] brcmfmac: brcmf_nvram_handle_idle warning: ln=1:col=44: ignoring invalid character
+[  155.195971] brcmfmac: brcmf_nvram_handle_idle warning: ln=1:col=63: ignoring invalid character
+
+Signed-off-by: Rafał Miłecki <[email protected]>
+Signed-off-by: Kalle Valo <[email protected]>
+---
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
+@@ -93,7 +93,7 @@ static enum nvram_parser_state brcmf_nvr
+ 	c = nvp->data[nvp->pos];
+ 	if (c == '\n')
+ 		return COMMENT;
+-	if (is_whitespace(c))
++	if (is_whitespace(c) || c == '\0')
+ 		goto proceed;
+ 	if (c == '#')
+ 		return COMMENT;

+ 41 - 0
package/kernel/mac80211/patches/325-brcmfmac-sdio-Increase-the-default-timeouts-a-bit.patch

@@ -0,0 +1,41 @@
+From: Sjoerd Simons <[email protected]>
+Date: Mon, 25 Jan 2016 11:47:29 +0100
+Subject: [PATCH] brcmfmac: sdio: Increase the default timeouts a bit
+
+On a Radxa Rock2 board with a Ampak AP6335 (Broadcom 4339 core) it seems
+the card responds very quickly most of the time, unfortunately during
+initialisation it sometimes seems to take just a bit over 2 seconds to
+respond.
+
+This results intialization failing with message like:
+  brcmf_c_preinit_dcmds: Retreiving cur_etheraddr failed, -52
+  brcmf_bus_start: failed: -52
+  brcmf_sdio_firmware_callback: dongle is not responding
+
+Increasing the timeout to allow for a bit more headroom allows the
+card to initialize reliably.
+
+A quick search online after diagnosing/fixing this showed that Google
+has a similar patch in their ChromeOS tree, so this doesn't seem
+specific to the board I'm using.
+
+Signed-off-by: Sjoerd Simons <[email protected]>
+Reviewed-by: Julian Calaby <[email protected]>
+Acked-by: Arend van Spriel <[email protected]>
+Reviewed-by: Douglas Anderson <[email protected]>
+Signed-off-by: Kalle Valo <[email protected]>
+---
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
+@@ -45,8 +45,8 @@
+ #include "chip.h"
+ #include "firmware.h"
+ 
+-#define DCMD_RESP_TIMEOUT	msecs_to_jiffies(2000)
+-#define CTL_DONE_TIMEOUT	msecs_to_jiffies(2000)
++#define DCMD_RESP_TIMEOUT	msecs_to_jiffies(2500)
++#define CTL_DONE_TIMEOUT	msecs_to_jiffies(2500)
+ 
+ #ifdef DEBUG
+