[PATCH wireless-next v3 02/10] bcma: pmu: init PLL and resources on BCM4352/BCM4360

Alessio Ferri alessio.ferri at mythread.it
Sat Oct 31 02:15:24 PDT 2026


Program the PMU as Broadcom's driver does (hndpmu.c):

- 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 <alessio.ferri at mythread.it>
---
 drivers/bcma/driver_chipcommon_pmu.c        | 81 +++++++++++++++++++++++++++++
 include/linux/bcma/bcma_driver_chipcommon.h | 14 +++++
 2 files changed, 95 insertions(+)

diff --git a/drivers/bcma/driver_chipcommon_pmu.c b/drivers/bcma/driver_chipcommon_pmu.c
index 263ef6fa1..7a226fcd2 100644
--- a/drivers/bcma/driver_chipcommon_pmu.c
+++ b/drivers/bcma/driver_chipcommon_pmu.c
@@ -11,6 +11,7 @@
 
 #include "bcma_private.h"
 #include <linux/export.h>
+#include <linux/math64.h>
 #include <linux/bcma/bcma.h>
 
 u32 bcma_chipco_pll_read(struct bcma_drv_cc *cc, u32 offset)
@@ -145,6 +146,78 @@ static void bcma_pmu2_pll_init0(struct bcma_drv_cc *cc, u32 xtalfreq)
 	/* TODO: Do we need to update OTP? */
 }
 
+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)
+		return;
+	/* 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;
+	}
+
+	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);
+}
+
+/* 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)
+{
+	u8 rev = cc->core->bus->chipinfo.rev;
+	bool init_mode0 = cc->status & BCMA_CC_CHIPST_4360_RSRC_INIT_MODE0;
+	unsigned int i;
+
+	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 (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);
+
+	if (rev >= 3)
+		*max_msk = 0x1ff;
+}
+
 static void bcma_pmu_pll_init(struct bcma_drv_cc *cc)
 {
 	struct bcma_bus *bus = cc->core->bus;
@@ -156,6 +229,10 @@ static void bcma_pmu_pll_init(struct bcma_drv_cc *cc)
 			xtalfreq = 20000;
 		bcma_pmu2_pll_init0(cc, xtalfreq);
 		break;
+	case BCMA_CHIP_ID_BCM4352:
+	case BCMA_CHIP_ID_BCM4360:
+		bcma_pmu_4360_pll_init(cc);
+		break;
 	}
 }
 
@@ -188,6 +265,10 @@ static void bcma_pmu_resources_init(struct bcma_drv_cc *cc)
 			  BCMA_RES_4314_WL_CORE_READY;
 		max_msk = 0x3FFFFFFF;
 		break;
+	case BCMA_CHIP_ID_BCM4352:
+	case BCMA_CHIP_ID_BCM4360:
+		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",
 			   bus->chipinfo.id);
diff --git a/include/linux/bcma/bcma_driver_chipcommon.h b/include/linux/bcma/bcma_driver_chipcommon.h
index 0cb6638b5..525155658 100644
--- a/include/linux/bcma/bcma_driver_chipcommon.h
+++ b/include/linux/bcma/bcma_driver_chipcommon.h
@@ -107,6 +107,7 @@
 #define  BCMA_CC_CHIPST_4706_PCIE1_DISABLE	BIT(5) /* PCIE1 enable strap pin */
 #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_JCMD			0x0030		/* Rev >= 10 only */
 #define  BCMA_CC_JCMD_START		0x80000000
 #define  BCMA_CC_JCMD_BUSY		0x80000000
@@ -500,6 +501,16 @@
 #define BCMA_CC_PMU_PLL_CTL3		3
 #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
@@ -527,6 +538,9 @@
 #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 */

-- 
2.34.1




More information about the b43-dev mailing list