1: a6088292acf9 = 1: 2dfd46178e4a bcma: core: clear only FORCEHT for BCMA_CLKMODE_DYNAMIC  2: 796f7c359d0a ! 2: d058e0deafdf bcma: pmu: init PLL and resources on BCM4352/BCM4360 @@ Metadata ## Commit message ## bcma: pmu: init PLL and resources on BCM4352/BCM4360  - On chip rev 3: + Program the PMU as Broadcom's driver does (hndpmu.c):  - - program PLLCTL2/3 for a 960.0098 MHz fractional VCO from the 40 MHz - crystal, except on a BCM4360 strapped for USB; - - set the up/down time of resource 6; - - with chipstatus RSRC_INIT_MODE0 clear, program PLLCTL6/14 and set - max_res_mask to 0x1ff. - - The values are those of Broadcom's driver on rev 3; other revisions are - left as they are. + - on chip rev 3 and later, set the BBPLL to a 960.0098 MHz fractional + VCO from the 40 MHz crystal, unless the backplane runs on HT already; + - set the resource up/down times and, on rev 4 and later, a min + resource mask of 0x103; + - with chipstatus RSRC_INIT_MODE0 clear, program PLL controls 6 and 14, + and on rev 4 and later 7 and 15 with REFCLK enabled in chipcontrol 1; + on rev 3 and later, set max_res_mask to 0x1ff.  Signed-off-by: Alessio Ferri   ## drivers/bcma/driver_chipcommon_pmu.c ## +@@ +  + #include "bcma_private.h" + #include  ++#include  + #include  +  + u32 bcma_chipco_pll_read(struct bcma_drv_cc *cc, u32 offset)  @@ drivers/bcma/driver_chipcommon_pmu.c: static void bcma_pmu2_pll_init0(struct bcma_drv_cc *cc, u32 xtalfreq) /* TODO: Do we need to update OTP? */ } @@ drivers/bcma/driver_chipcommon_pmu.c: static void bcma_pmu2_pll_init0(struct bcm  +static void bcma_pmu_4360_pll_init(struct bcma_drv_cc *cc)  +{  + struct bcma_bus *bus = cc->core->bus; ++ const u32 xtal_hz = 40000000, vco_hz = 960009800; ++ u32 ctl2;  + -+ if (bus->chipinfo.rev != 3) ++ if (bus->chipinfo.rev < 3)  + return; -+ if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4360 && -+ cc->status & BCMA_CC_CHIPST_4360_MODE_USB) ++ /* The backplane may be running from the BBPLL. */ ++ if (bcma_cc_read32(cc, BCMA_CLKCTLST) & BCMA_CLKCTLST_HAVEHT)  + return; ++ if (bcma_pmu_get_alp_clock(cc) != xtal_hz) { ++ bcma_warn(bus, "No 40 MHz crystal, BBPLL left as is\n"); ++ return; ++ }  + -+ /* Fractional VCO, 960.0098 MHz from a 40 MHz crystal. */ -+ bcma_chipco_pll_write(cc, BCMA_CC_PMU_PLL_CTL2, 0x0c31); -+ bcma_chipco_pll_write(cc, BCMA_CC_PMU_PLL_CTL3, 0x100e); ++ ctl2 = (vco_hz / xtal_hz) << BCMA_CC_PMU4360_NDIV_INT_SHIFT | ++ BCMA_CC_PMU4360_NDIV_MODE_FRAC << BCMA_CC_PMU4360_NDIV_MODE_SHIFT | ++ 1 << BCMA_CC_PMU4360_P1DIV_SHIFT; ++ bcma_chipco_pll_write(cc, BCMA_CC_PMU_PLL_CTL2, ctl2); ++ bcma_chipco_pll_write(cc, BCMA_CC_PMU_PLL_CTL3, ++ div_u64((u64)(vco_hz % xtal_hz) << 24, xtal_hz));  + bcma_pmu_set32(cc, BCMA_CC_PMU_CTL, BCMA_CC_PMU_CTL_PLL_UPD);  +}  + -+/* Returns the max resource mask to program, 0 to leave it alone. */ -+static u32 bcma_pmu_4360_resources_init(struct bcma_drv_cc *cc) ++/* Up/down times of resources 0-8 on chip rev 4 and later */ ++static const u32 bcma_pmu_4360b1_res_updown[] = { ++ 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00860002, ++ 0x00000000, 0x00020001, 0x00080001, 0x00000000, ++}; ++ ++static void bcma_pmu_4360_resources_init(struct bcma_drv_cc *cc, ++ u32 *min_msk, u32 *max_msk)  +{ -+ if (cc->core->bus->chipinfo.rev != 3) -+ return 0; ++ u8 rev = cc->core->bus->chipinfo.rev; ++ bool init_mode0 = cc->status & BCMA_CC_CHIPST_4360_RSRC_INIT_MODE0; ++ unsigned int i;  + -+ bcma_pmu_write32(cc, BCMA_CC_PMU_RES_TABSEL, 6); -+ bcma_pmu_write32(cc, BCMA_CC_PMU_RES_UPDNTM, 0x00200001); ++ if (rev < 4) { ++ bcma_pmu_write32(cc, BCMA_CC_PMU_RES_TABSEL, 6); ++ bcma_pmu_write32(cc, BCMA_CC_PMU_RES_UPDNTM, 0x00200001); ++ } else { ++ for (i = 0; i < ARRAY_SIZE(bcma_pmu_4360b1_res_updown); i++) { ++ bcma_pmu_write32(cc, BCMA_CC_PMU_RES_TABSEL, i); ++ bcma_pmu_write32(cc, BCMA_CC_PMU_RES_UPDNTM, ++ bcma_pmu_4360b1_res_updown[i]); ++ } ++ *min_msk = 0x103; ++ /* The max mask must cover the min mask before it is written. */ ++ bcma_pmu_set32(cc, BCMA_CC_PMU_MAXRES_MSK, *min_msk); ++ }  + -+ if (cc->status & BCMA_CC_CHIPST_4360_RSRC_INIT_MODE0) -+ return 0; -+ bcma_chipco_pll_write(cc, BCMA_CC_PMU_PLL_CTL6, 0x09048562); -+ bcma_chipco_pll_write(cc, BCMA_CC_PMU_PLL_CTL14, 0x09048562); ++ if (init_mode0) ++ return; ++ ++ if (rev < 4) { ++ bcma_chipco_pll_write(cc, BCMA_CC_PMU_PLL_CTL6, 0x09048562); ++ bcma_chipco_pll_write(cc, BCMA_CC_PMU_PLL_CTL14, 0x09048562); ++ } else { ++ bcma_chipco_chipctl_maskset(cc, 1, ~0, ++ BCMA_CHIPCTL1_4360_REFCLK_EN); ++ bcma_chipco_pll_write(cc, BCMA_CC_PMU_PLL_CTL6, 0x080004e2); ++ bcma_chipco_pll_write(cc, BCMA_CC_PMU_PLL_CTL7, 0xe); ++ bcma_chipco_pll_write(cc, BCMA_CC_PMU_PLL_CTL14, 0x080004e2); ++ bcma_chipco_pll_write(cc, BCMA_CC_PMU_PLL_CTL15, 0xe); ++ }  + bcma_pmu_set32(cc, BCMA_CC_PMU_CTL, BCMA_CC_PMU_CTL_PLL_UPD); -+ return 0x1ff; ++ ++ if (rev >= 3) ++ *max_msk = 0x1ff;  +}  + static void bcma_pmu_pll_init(struct bcma_drv_cc *cc) @@ drivers/bcma/driver_chipcommon_pmu.c: static void bcma_pmu_resources_init(struct break;  + case BCMA_CHIP_ID_BCM4352:  + case BCMA_CHIP_ID_BCM4360: -+ max_msk = bcma_pmu_4360_resources_init(cc); ++ bcma_pmu_4360_resources_init(cc, &min_msk, &max_msk);  + break; default: bcma_debug(bus, "PMU resource config unknown or not needed for device 0x%04X\n", @@ include/linux/bcma/bcma_driver_chipcommon.h #define BCMA_CC_CHIPST_5357_NAND_BOOT BIT(4) /* NAND boot, valid for CC rev 38 and/or BCM5357 */ #define BCMA_CC_CHIPST_4360_XTAL_40MZ 0x00000001  +#define BCMA_CC_CHIPST_4360_RSRC_INIT_MODE0 0x00000020 -+#define BCMA_CC_CHIPST_4360_MODE_USB 0x00000100 #define BCMA_CC_JCMD 0x0030 /* Rev >= 10 only */ #define BCMA_CC_JCMD_START 0x80000000 #define BCMA_CC_JCMD_BUSY 0x80000000 @@ include/linux/bcma/bcma_driver_chipcommon.h #define BCMA_CC_PMU_PLL_CTL4 4 #define BCMA_CC_PMU_PLL_CTL5 5  +#define BCMA_CC_PMU_PLL_CTL6 6 ++#define BCMA_CC_PMU_PLL_CTL7 7  +#define BCMA_CC_PMU_PLL_CTL14 14 ++#define BCMA_CC_PMU_PLL_CTL15 15 ++ ++/* BCM4360 PLL control 2 */ ++#define BCMA_CC_PMU4360_P1DIV_SHIFT 0 ++#define BCMA_CC_PMU4360_NDIV_MODE_SHIFT 4 ++#define BCMA_CC_PMU4360_NDIV_MODE_FRAC 3 ++#define BCMA_CC_PMU4360_NDIV_INT_SHIFT 7  #define BCMA_CC_PMU1_PLL0_PC0_P1DIV_MASK 0x00f00000 #define BCMA_CC_PMU1_PLL0_PC0_P1DIV_SHIFT 20 +@@ + #define BCMA_CHIPCTL_4331_BT_SHD0_ON_GPIO4 BIT(16) /* enable bt_shd0 at gpio4 */ + #define BCMA_CHIPCTL_4331_BT_SHD1_ON_GPIO5 BIT(17) /* enable bt_shd1 at gpio5 */ +  ++/* BCM4360 ChipControl 1 */ ++#define BCMA_CHIPCTL1_4360_REFCLK_EN BIT(11) ++ + /* 43224 chip-specific ChipControl register bits */ + #define BCMA_CCTRL_43224_GPIO_TOGGLE 0x8000 /* gpio[3:0] pins as btcoex or s/w gpio */ + #define BCMA_CCTRL_43224A0_12MA_LED_DRIVE 0x00F000F0 /* 12 mA drive strength */  3: b68912a53b32 ! 3: 963cd369fcf6 bcma: pcie2: request HT on BCM4352/BCM4360 @@ Metadata ## Commit message ## bcma: pcie2: request HT on BCM4352/BCM4360  - Set HAVEHTREQ in the PCIe2 core's clock control on chip rev 3, as - Broadcom's driver does. + Set HAVEHTREQ in the PCIe2 core's clock control on chip revs before 4, + as Broadcom's driver does.  Signed-off-by: Alessio Ferri   @@ drivers/bcma/driver_pcie2.c: void bcma_core_pcie2_init(struct bcma_drv_pcie2 *pc case BCMA_CHIP_ID_BCM4360: case BCMA_CHIP_ID_BCM4352: pcie2->reqsize = 1024; -+ if (ci->rev == 3) ++ if (ci->rev < 4)  + pcie2_set32(pcie2, BCMA_CLKCTLST,  + BCMA_CLKCTLST_HAVEHTREQ); break;  4: 1efec9261d87 = 4: e3c8a8ac0006 bcma: chipcommon: enable asynchronous GPIO interrupts  5: ace78e47aa23 ! 5: ede7efcb254d bcma: extract SPROM revision 11 @@ drivers/bcma/sprom.c: static void bcma_sprom_extract_r8(struct bcma_bus *bus, co  + SSB_SPROM8_TEMPDELTA_HYSTERESIS,  + SSB_SPROM8_TEMPDELTA_HYSTERESIS_SHIFT);  + -+ /* Whole dB in bits [5:0], sign-extended, quarter dB in bits [7:6]. */ -+ for (i = 0; i < 2; i++) { -+ u8 raw = i ? (sprom[SSB_SPROM11_AGBG2A0 / 2] >> 8) & 0xff -+ : sprom[SSB_SPROM11_AGBG10 / 2] & 0xff; -+ s8 gain = (s8)((raw & 0x3f) << 2) >> 2; -+ -+ bus->sprom.antenna_gain_qdb[i] = (s8)(4 * gain + (raw >> 6)); -+ } ++ bus->sprom.antenna_gain_qdb[0] = ++ ssb_sprom_antgain_qdb(sprom[SPOFF(SSB_SPROM11_AGBG10)] & 0xff); ++ bus->sprom.antenna_gain_qdb[1] = ++ ssb_sprom_antgain_qdb(sprom[SPOFF(SSB_SPROM11_AGBG2A0)] >> 8);  +}  + /* @@ include/linux/ssb/ssb.h: struct ssb_sprom {  + u16 tssifloor5g[4]; };  ++/* ++ * SROM rev 11 antenna gain byte, agbg0 or aga0, in quarter dB: whole dB in ++ * bits [5:0], signed, and quarter dB in bits [7:6]. ++ */ ++static inline s8 ssb_sprom_antgain_qdb(u8 raw) ++{ ++ s8 gain = (s8)((raw & 0x3f) << 2) >> 2; ++ ++ return 4 * gain + (raw >> 6); ++} ++ /* Information about the PCB the circuitry is soldered on. */ + struct ssb_boardinfo { + u16 vendor;  ## include/linux/ssb/ssb_regs.h ##  @@  -: ------------ > 6: 7a112defe8d8 firmware: bcm47xx_sprom: read the SPROM revision 11 fields from NVRAM  6: a03d620da9d5 ! 7: ae006a8496bc firmware: bcm47xx_sprom: read ledbh4..ledbh15 from NVRAM @@ Commit message firmware: bcm47xx_sprom: read ledbh4..ledbh15 from NVRAM  Add gpio_ext[] for the LED behaviours of GPIO 4-15 and fill it from - NVRAM ledbh4..ledbh15, both for a SPROM built from NVRAM and, through - the new bcm47xx_sprom_fill_bcma_nvram(), on top of a SPROM read from a - bcma device. The bcma prefix lookup moves into a helper shared by both - paths. + NVRAM ledbh4..ledbh15. + + bcm47xx_fill_sprom() is reached only through the SPROM fallback, so the + NVRAM of a bcma device with a SPROM of its own is never read. Add + bcm47xx_sprom_fill_bcma_nvram(), which bcma calls after extracting the + SPROM, to read the variables the SPROM has no word for on top of it. + The bcma prefix lookup moves into a helper shared by both paths.  Signed-off-by: Alessio Ferri    7: 62b3cd290824 < -: ------------ firmware: bcm47xx_sprom: read boardflags3 and AvVmid_c0..2 from NVRAM  -: ------------ > 8: c60d50b9d702 firmware: bcm47xx_sprom: read boardflags3 from NVRAM over the SPROM  8: 027005b86b3a ! 9: 7251c29830f0 bcma: add the BCM4352 PCI ID @@ Metadata Author: Alessio Ferri   ## Commit message ## - bcma: add the BCM4352 PCI ID + bcma: add the single-band BCM4352/BCM4360 PCI IDs  - Bind bcma-pci-bridge to the BCM4352, 0x43b3. + Bind bcma-pci-bridge to the 2.4 GHz and 5 GHz variants of the BCM4360 + (0x43a1, 0x43a2) and BCM4352 (0x43b2, 0x43b3), next to the dual-band + 0x43a0 and 0x43b1, and name the chip and band of each.  Signed-off-by: Alessio Ferri   ## drivers/bcma/host_pci.c ##  @@ drivers/bcma/host_pci.c: static const struct pci_device_id bcma_pci_bridge_tbl[] = { + { PCI_DEVICE_SUB(PCI_VENDOR_ID_BROADCOM, 0x4365, PCI_VENDOR_ID_DELL, 0x0018) }, + { PCI_DEVICE_SUB(PCI_VENDOR_ID_BROADCOM, 0x4365, PCI_VENDOR_ID_FOXCONN, 0xe092) }, + { PCI_DEVICE_SUB(PCI_VENDOR_ID_BROADCOM, 0x4365, PCI_VENDOR_ID_HP, 0x804a) }, +- { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x43a0) }, ++ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x43a0) }, /* BCM4360 */ ++ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x43a1) }, /* BCM4360, 2.4 GHz */ ++ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x43a2) }, /* BCM4360, 5 GHz */ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x43a9) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x43aa) }, - { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x43b1) }, -+ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x43b3) }, +- { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x43b1) }, ++ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x43b1) }, /* BCM4352 */ ++ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x43b2) }, /* BCM4352, 2.4 GHz */ ++ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x43b3) }, /* BCM4352, 5 GHz */ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4727) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 43227) }, /* 0xa8db, BCM43217 (sic!) */ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 43228) }, /* 0xa8dc */  -: ------------ > 10: 87e50b1c9f63 wifi: b43: add the 2.4 GHz BCM4352/BCM4360 to the supported bands