cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

driver_chipcommon_pmu.c (19824B)


      1/*
      2 * Broadcom specific AMBA
      3 * ChipCommon Power Management Unit driver
      4 *
      5 * Copyright 2009, Michael Buesch <m@bues.ch>
      6 * Copyright 2007, 2011, Broadcom Corporation
      7 * Copyright 2011, 2012, Hauke Mehrtens <hauke@hauke-m.de>
      8 *
      9 * Licensed under the GNU/GPL. See COPYING for details.
     10 */
     11
     12#include "bcma_private.h"
     13#include <linux/export.h>
     14#include <linux/bcma/bcma.h>
     15
     16u32 bcma_chipco_pll_read(struct bcma_drv_cc *cc, u32 offset)
     17{
     18	bcma_pmu_write32(cc, BCMA_CC_PMU_PLLCTL_ADDR, offset);
     19	bcma_pmu_read32(cc, BCMA_CC_PMU_PLLCTL_ADDR);
     20	return bcma_pmu_read32(cc, BCMA_CC_PMU_PLLCTL_DATA);
     21}
     22EXPORT_SYMBOL_GPL(bcma_chipco_pll_read);
     23
     24void bcma_chipco_pll_write(struct bcma_drv_cc *cc, u32 offset, u32 value)
     25{
     26	bcma_pmu_write32(cc, BCMA_CC_PMU_PLLCTL_ADDR, offset);
     27	bcma_pmu_read32(cc, BCMA_CC_PMU_PLLCTL_ADDR);
     28	bcma_pmu_write32(cc, BCMA_CC_PMU_PLLCTL_DATA, value);
     29}
     30EXPORT_SYMBOL_GPL(bcma_chipco_pll_write);
     31
     32void bcma_chipco_pll_maskset(struct bcma_drv_cc *cc, u32 offset, u32 mask,
     33			     u32 set)
     34{
     35	bcma_pmu_write32(cc, BCMA_CC_PMU_PLLCTL_ADDR, offset);
     36	bcma_pmu_read32(cc, BCMA_CC_PMU_PLLCTL_ADDR);
     37	bcma_pmu_maskset32(cc, BCMA_CC_PMU_PLLCTL_DATA, mask, set);
     38}
     39EXPORT_SYMBOL_GPL(bcma_chipco_pll_maskset);
     40
     41void bcma_chipco_chipctl_maskset(struct bcma_drv_cc *cc,
     42				 u32 offset, u32 mask, u32 set)
     43{
     44	bcma_pmu_write32(cc, BCMA_CC_PMU_CHIPCTL_ADDR, offset);
     45	bcma_pmu_read32(cc, BCMA_CC_PMU_CHIPCTL_ADDR);
     46	bcma_pmu_maskset32(cc, BCMA_CC_PMU_CHIPCTL_DATA, mask, set);
     47}
     48EXPORT_SYMBOL_GPL(bcma_chipco_chipctl_maskset);
     49
     50void bcma_chipco_regctl_maskset(struct bcma_drv_cc *cc, u32 offset, u32 mask,
     51				u32 set)
     52{
     53	bcma_pmu_write32(cc, BCMA_CC_PMU_REGCTL_ADDR, offset);
     54	bcma_pmu_read32(cc, BCMA_CC_PMU_REGCTL_ADDR);
     55	bcma_pmu_maskset32(cc, BCMA_CC_PMU_REGCTL_DATA, mask, set);
     56}
     57EXPORT_SYMBOL_GPL(bcma_chipco_regctl_maskset);
     58
     59static u32 bcma_pmu_xtalfreq(struct bcma_drv_cc *cc)
     60{
     61	u32 ilp_ctl, alp_hz;
     62
     63	if (!(bcma_pmu_read32(cc, BCMA_CC_PMU_STAT) &
     64	      BCMA_CC_PMU_STAT_EXT_LPO_AVAIL))
     65		return 0;
     66
     67	bcma_pmu_write32(cc, BCMA_CC_PMU_XTAL_FREQ,
     68			 BIT(BCMA_CC_PMU_XTAL_FREQ_MEASURE_SHIFT));
     69	usleep_range(1000, 2000);
     70
     71	ilp_ctl = bcma_pmu_read32(cc, BCMA_CC_PMU_XTAL_FREQ);
     72	ilp_ctl &= BCMA_CC_PMU_XTAL_FREQ_ILPCTL_MASK;
     73
     74	bcma_pmu_write32(cc, BCMA_CC_PMU_XTAL_FREQ, 0);
     75
     76	alp_hz = ilp_ctl * 32768 / 4;
     77	return (alp_hz + 50000) / 100000 * 100;
     78}
     79
     80static void bcma_pmu2_pll_init0(struct bcma_drv_cc *cc, u32 xtalfreq)
     81{
     82	struct bcma_bus *bus = cc->core->bus;
     83	u32 freq_tgt_target = 0, freq_tgt_current;
     84	u32 pll0, mask;
     85
     86	switch (bus->chipinfo.id) {
     87	case BCMA_CHIP_ID_BCM43142:
     88		/* pmu2_xtaltab0_adfll_485 */
     89		switch (xtalfreq) {
     90		case 12000:
     91			freq_tgt_target = 0x50D52;
     92			break;
     93		case 20000:
     94			freq_tgt_target = 0x307FE;
     95			break;
     96		case 26000:
     97			freq_tgt_target = 0x254EA;
     98			break;
     99		case 37400:
    100			freq_tgt_target = 0x19EF8;
    101			break;
    102		case 52000:
    103			freq_tgt_target = 0x12A75;
    104			break;
    105		}
    106		break;
    107	}
    108
    109	if (!freq_tgt_target) {
    110		bcma_err(bus, "Unknown TGT frequency for xtalfreq %d\n",
    111			 xtalfreq);
    112		return;
    113	}
    114
    115	pll0 = bcma_chipco_pll_read(cc, BCMA_CC_PMU15_PLL_PLLCTL0);
    116	freq_tgt_current = (pll0 & BCMA_CC_PMU15_PLL_PC0_FREQTGT_MASK) >>
    117		BCMA_CC_PMU15_PLL_PC0_FREQTGT_SHIFT;
    118
    119	if (freq_tgt_current == freq_tgt_target) {
    120		bcma_debug(bus, "Target TGT frequency already set\n");
    121		return;
    122	}
    123
    124	/* Turn off PLL */
    125	switch (bus->chipinfo.id) {
    126	case BCMA_CHIP_ID_BCM43142:
    127		mask = (u32)~(BCMA_RES_4314_HT_AVAIL |
    128			      BCMA_RES_4314_MACPHY_CLK_AVAIL);
    129
    130		bcma_pmu_mask32(cc, BCMA_CC_PMU_MINRES_MSK, mask);
    131		bcma_pmu_mask32(cc, BCMA_CC_PMU_MAXRES_MSK, mask);
    132		bcma_wait_value(cc->core, BCMA_CLKCTLST,
    133				BCMA_CLKCTLST_HAVEHT, 0, 20000);
    134		break;
    135	}
    136
    137	pll0 &= ~BCMA_CC_PMU15_PLL_PC0_FREQTGT_MASK;
    138	pll0 |= freq_tgt_target << BCMA_CC_PMU15_PLL_PC0_FREQTGT_SHIFT;
    139	bcma_chipco_pll_write(cc, BCMA_CC_PMU15_PLL_PLLCTL0, pll0);
    140
    141	/* Flush */
    142	if (cc->pmu.rev >= 2)
    143		bcma_pmu_set32(cc, BCMA_CC_PMU_CTL, BCMA_CC_PMU_CTL_PLL_UPD);
    144
    145	/* TODO: Do we need to update OTP? */
    146}
    147
    148static void bcma_pmu_pll_init(struct bcma_drv_cc *cc)
    149{
    150	struct bcma_bus *bus = cc->core->bus;
    151	u32 xtalfreq = bcma_pmu_xtalfreq(cc);
    152
    153	switch (bus->chipinfo.id) {
    154	case BCMA_CHIP_ID_BCM43142:
    155		if (xtalfreq == 0)
    156			xtalfreq = 20000;
    157		bcma_pmu2_pll_init0(cc, xtalfreq);
    158		break;
    159	}
    160}
    161
    162static void bcma_pmu_resources_init(struct bcma_drv_cc *cc)
    163{
    164	struct bcma_bus *bus = cc->core->bus;
    165	u32 min_msk = 0, max_msk = 0;
    166
    167	switch (bus->chipinfo.id) {
    168	case BCMA_CHIP_ID_BCM4313:
    169		min_msk = 0x200D;
    170		max_msk = 0xFFFF;
    171		break;
    172	case BCMA_CHIP_ID_BCM43142:
    173		min_msk = BCMA_RES_4314_LPLDO_PU |
    174			  BCMA_RES_4314_PMU_SLEEP_DIS |
    175			  BCMA_RES_4314_PMU_BG_PU |
    176			  BCMA_RES_4314_CBUCK_LPOM_PU |
    177			  BCMA_RES_4314_CBUCK_PFM_PU |
    178			  BCMA_RES_4314_CLDO_PU |
    179			  BCMA_RES_4314_LPLDO2_LVM |
    180			  BCMA_RES_4314_WL_PMU_PU |
    181			  BCMA_RES_4314_LDO3P3_PU |
    182			  BCMA_RES_4314_OTP_PU |
    183			  BCMA_RES_4314_WL_PWRSW_PU |
    184			  BCMA_RES_4314_LQ_AVAIL |
    185			  BCMA_RES_4314_LOGIC_RET |
    186			  BCMA_RES_4314_MEM_SLEEP |
    187			  BCMA_RES_4314_MACPHY_RET |
    188			  BCMA_RES_4314_WL_CORE_READY;
    189		max_msk = 0x3FFFFFFF;
    190		break;
    191	default:
    192		bcma_debug(bus, "PMU resource config unknown or not needed for device 0x%04X\n",
    193			   bus->chipinfo.id);
    194	}
    195
    196	/* Set the resource masks. */
    197	if (min_msk)
    198		bcma_pmu_write32(cc, BCMA_CC_PMU_MINRES_MSK, min_msk);
    199	if (max_msk)
    200		bcma_pmu_write32(cc, BCMA_CC_PMU_MAXRES_MSK, max_msk);
    201
    202	/*
    203	 * Add some delay; allow resources to come up and settle.
    204	 * Delay is required for SoC (early init).
    205	 */
    206	usleep_range(2000, 2500);
    207}
    208
    209/* Disable to allow reading SPROM. Don't know the advantages of enabling it. */
    210void bcma_chipco_bcm4331_ext_pa_lines_ctl(struct bcma_drv_cc *cc, bool enable)
    211{
    212	struct bcma_bus *bus = cc->core->bus;
    213	u32 val;
    214
    215	val = bcma_cc_read32(cc, BCMA_CC_CHIPCTL);
    216	if (enable) {
    217		val |= BCMA_CHIPCTL_4331_EXTPA_EN;
    218		if (bus->chipinfo.pkg == 9 || bus->chipinfo.pkg == 11)
    219			val |= BCMA_CHIPCTL_4331_EXTPA_ON_GPIO2_5;
    220		else if (bus->chipinfo.rev > 0)
    221			val |= BCMA_CHIPCTL_4331_EXTPA_EN2;
    222	} else {
    223		val &= ~BCMA_CHIPCTL_4331_EXTPA_EN;
    224		val &= ~BCMA_CHIPCTL_4331_EXTPA_EN2;
    225		val &= ~BCMA_CHIPCTL_4331_EXTPA_ON_GPIO2_5;
    226	}
    227	bcma_cc_write32(cc, BCMA_CC_CHIPCTL, val);
    228}
    229
    230static void bcma_pmu_workarounds(struct bcma_drv_cc *cc)
    231{
    232	struct bcma_bus *bus = cc->core->bus;
    233
    234	switch (bus->chipinfo.id) {
    235	case BCMA_CHIP_ID_BCM4313:
    236		/*
    237		 * enable 12 mA drive strength for 4313 and set chipControl
    238		 * register bit 1
    239		 */
    240		bcma_chipco_chipctl_maskset(cc, 0,
    241					    ~BCMA_CCTRL_4313_12MA_LED_DRIVE,
    242					    BCMA_CCTRL_4313_12MA_LED_DRIVE);
    243		break;
    244	case BCMA_CHIP_ID_BCM4331:
    245	case BCMA_CHIP_ID_BCM43431:
    246		/* Ext PA lines must be enabled for tx on BCM4331 */
    247		bcma_chipco_bcm4331_ext_pa_lines_ctl(cc, true);
    248		break;
    249	case BCMA_CHIP_ID_BCM43224:
    250	case BCMA_CHIP_ID_BCM43421:
    251		/*
    252		 * enable 12 mA drive strength for 43224 and set chipControl
    253		 * register bit 15
    254		 */
    255		if (bus->chipinfo.rev == 0) {
    256			bcma_cc_maskset32(cc, BCMA_CC_CHIPCTL,
    257					  ~BCMA_CCTRL_43224_GPIO_TOGGLE,
    258					  BCMA_CCTRL_43224_GPIO_TOGGLE);
    259			bcma_chipco_chipctl_maskset(cc, 0,
    260						    ~BCMA_CCTRL_43224A0_12MA_LED_DRIVE,
    261						    BCMA_CCTRL_43224A0_12MA_LED_DRIVE);
    262		} else {
    263			bcma_chipco_chipctl_maskset(cc, 0,
    264						    ~BCMA_CCTRL_43224B0_12MA_LED_DRIVE,
    265						    BCMA_CCTRL_43224B0_12MA_LED_DRIVE);
    266		}
    267		break;
    268	default:
    269		bcma_debug(bus, "Workarounds unknown or not needed for device 0x%04X\n",
    270			   bus->chipinfo.id);
    271	}
    272}
    273
    274void bcma_pmu_early_init(struct bcma_drv_cc *cc)
    275{
    276	struct bcma_bus *bus = cc->core->bus;
    277	u32 pmucap;
    278
    279	if (cc->core->id.rev >= 35 &&
    280	    cc->capabilities_ext & BCMA_CC_CAP_EXT_AOB_PRESENT) {
    281		cc->pmu.core = bcma_find_core(bus, BCMA_CORE_PMU);
    282		if (!cc->pmu.core)
    283			bcma_warn(bus, "Couldn't find expected PMU core");
    284	}
    285	if (!cc->pmu.core)
    286		cc->pmu.core = cc->core;
    287
    288	pmucap = bcma_pmu_read32(cc, BCMA_CC_PMU_CAP);
    289	cc->pmu.rev = (pmucap & BCMA_CC_PMU_CAP_REVISION);
    290
    291	bcma_debug(bus, "Found rev %u PMU (capabilities 0x%08X)\n", cc->pmu.rev,
    292		   pmucap);
    293}
    294
    295void bcma_pmu_init(struct bcma_drv_cc *cc)
    296{
    297	if (cc->pmu.rev == 1)
    298		bcma_pmu_mask32(cc, BCMA_CC_PMU_CTL,
    299				~BCMA_CC_PMU_CTL_NOILPONW);
    300	else
    301		bcma_pmu_set32(cc, BCMA_CC_PMU_CTL,
    302			       BCMA_CC_PMU_CTL_NOILPONW);
    303
    304	bcma_pmu_pll_init(cc);
    305	bcma_pmu_resources_init(cc);
    306	bcma_pmu_workarounds(cc);
    307}
    308
    309u32 bcma_pmu_get_alp_clock(struct bcma_drv_cc *cc)
    310{
    311	struct bcma_bus *bus = cc->core->bus;
    312
    313	switch (bus->chipinfo.id) {
    314	case BCMA_CHIP_ID_BCM4313:
    315	case BCMA_CHIP_ID_BCM43224:
    316	case BCMA_CHIP_ID_BCM43225:
    317	case BCMA_CHIP_ID_BCM43227:
    318	case BCMA_CHIP_ID_BCM43228:
    319	case BCMA_CHIP_ID_BCM4331:
    320	case BCMA_CHIP_ID_BCM43421:
    321	case BCMA_CHIP_ID_BCM43428:
    322	case BCMA_CHIP_ID_BCM43431:
    323	case BCMA_CHIP_ID_BCM4716:
    324	case BCMA_CHIP_ID_BCM47162:
    325	case BCMA_CHIP_ID_BCM4748:
    326	case BCMA_CHIP_ID_BCM4749:
    327	case BCMA_CHIP_ID_BCM5357:
    328	case BCMA_CHIP_ID_BCM53572:
    329	case BCMA_CHIP_ID_BCM6362:
    330		/* always 20Mhz */
    331		return 20000 * 1000;
    332	case BCMA_CHIP_ID_BCM4706:
    333	case BCMA_CHIP_ID_BCM5356:
    334		/* always 25Mhz */
    335		return 25000 * 1000;
    336	case BCMA_CHIP_ID_BCM43460:
    337	case BCMA_CHIP_ID_BCM4352:
    338	case BCMA_CHIP_ID_BCM4360:
    339		if (cc->status & BCMA_CC_CHIPST_4360_XTAL_40MZ)
    340			return 40000 * 1000;
    341		else
    342			return 20000 * 1000;
    343	default:
    344		bcma_warn(bus, "No ALP clock specified for %04X device, pmu rev. %d, using default %d Hz\n",
    345			  bus->chipinfo.id, cc->pmu.rev, BCMA_CC_PMU_ALP_CLOCK);
    346	}
    347	return BCMA_CC_PMU_ALP_CLOCK;
    348}
    349
    350/* Find the output of the "m" pll divider given pll controls that start with
    351 * pllreg "pll0" i.e. 12 for main 6 for phy, 0 for misc.
    352 */
    353static u32 bcma_pmu_pll_clock(struct bcma_drv_cc *cc, u32 pll0, u32 m)
    354{
    355	u32 tmp, div, ndiv, p1, p2, fc;
    356	struct bcma_bus *bus = cc->core->bus;
    357
    358	BUG_ON((pll0 & 3) || (pll0 > BCMA_CC_PMU4716_MAINPLL_PLL0));
    359
    360	BUG_ON(!m || m > 4);
    361
    362	if (bus->chipinfo.id == BCMA_CHIP_ID_BCM5357 ||
    363	    bus->chipinfo.id == BCMA_CHIP_ID_BCM4749) {
    364		/* Detect failure in clock setting */
    365		tmp = bcma_cc_read32(cc, BCMA_CC_CHIPSTAT);
    366		if (tmp & 0x40000)
    367			return 133 * 1000000;
    368	}
    369
    370	tmp = bcma_chipco_pll_read(cc, pll0 + BCMA_CC_PPL_P1P2_OFF);
    371	p1 = (tmp & BCMA_CC_PPL_P1_MASK) >> BCMA_CC_PPL_P1_SHIFT;
    372	p2 = (tmp & BCMA_CC_PPL_P2_MASK) >> BCMA_CC_PPL_P2_SHIFT;
    373
    374	tmp = bcma_chipco_pll_read(cc, pll0 + BCMA_CC_PPL_M14_OFF);
    375	div = (tmp >> ((m - 1) * BCMA_CC_PPL_MDIV_WIDTH)) &
    376		BCMA_CC_PPL_MDIV_MASK;
    377
    378	tmp = bcma_chipco_pll_read(cc, pll0 + BCMA_CC_PPL_NM5_OFF);
    379	ndiv = (tmp & BCMA_CC_PPL_NDIV_MASK) >> BCMA_CC_PPL_NDIV_SHIFT;
    380
    381	/* Do calculation in Mhz */
    382	fc = bcma_pmu_get_alp_clock(cc) / 1000000;
    383	fc = (p1 * ndiv * fc) / p2;
    384
    385	/* Return clock in Hertz */
    386	return (fc / div) * 1000000;
    387}
    388
    389static u32 bcma_pmu_pll_clock_bcm4706(struct bcma_drv_cc *cc, u32 pll0, u32 m)
    390{
    391	u32 tmp, ndiv, p1div, p2div;
    392	u32 clock;
    393
    394	BUG_ON(!m || m > 4);
    395
    396	/* Get N, P1 and P2 dividers to determine CPU clock */
    397	tmp = bcma_chipco_pll_read(cc, pll0 + BCMA_CC_PMU6_4706_PROCPLL_OFF);
    398	ndiv = (tmp & BCMA_CC_PMU6_4706_PROC_NDIV_INT_MASK)
    399		>> BCMA_CC_PMU6_4706_PROC_NDIV_INT_SHIFT;
    400	p1div = (tmp & BCMA_CC_PMU6_4706_PROC_P1DIV_MASK)
    401		>> BCMA_CC_PMU6_4706_PROC_P1DIV_SHIFT;
    402	p2div = (tmp & BCMA_CC_PMU6_4706_PROC_P2DIV_MASK)
    403		>> BCMA_CC_PMU6_4706_PROC_P2DIV_SHIFT;
    404
    405	tmp = bcma_cc_read32(cc, BCMA_CC_CHIPSTAT);
    406	if (tmp & BCMA_CC_CHIPST_4706_PKG_OPTION)
    407		/* Low cost bonding: Fixed reference clock 25MHz and m = 4 */
    408		clock = (25000000 / 4) * ndiv * p2div / p1div;
    409	else
    410		/* Fixed reference clock 25MHz and m = 2 */
    411		clock = (25000000 / 2) * ndiv * p2div / p1div;
    412
    413	if (m == BCMA_CC_PMU5_MAINPLL_SSB)
    414		clock = clock / 4;
    415
    416	return clock;
    417}
    418
    419/* query bus clock frequency for PMU-enabled chipcommon */
    420u32 bcma_pmu_get_bus_clock(struct bcma_drv_cc *cc)
    421{
    422	struct bcma_bus *bus = cc->core->bus;
    423
    424	switch (bus->chipinfo.id) {
    425	case BCMA_CHIP_ID_BCM4716:
    426	case BCMA_CHIP_ID_BCM4748:
    427	case BCMA_CHIP_ID_BCM47162:
    428		return bcma_pmu_pll_clock(cc, BCMA_CC_PMU4716_MAINPLL_PLL0,
    429					  BCMA_CC_PMU5_MAINPLL_SSB);
    430	case BCMA_CHIP_ID_BCM5356:
    431		return bcma_pmu_pll_clock(cc, BCMA_CC_PMU5356_MAINPLL_PLL0,
    432					  BCMA_CC_PMU5_MAINPLL_SSB);
    433	case BCMA_CHIP_ID_BCM5357:
    434	case BCMA_CHIP_ID_BCM4749:
    435		return bcma_pmu_pll_clock(cc, BCMA_CC_PMU5357_MAINPLL_PLL0,
    436					  BCMA_CC_PMU5_MAINPLL_SSB);
    437	case BCMA_CHIP_ID_BCM4706:
    438		return bcma_pmu_pll_clock_bcm4706(cc,
    439						  BCMA_CC_PMU4706_MAINPLL_PLL0,
    440						  BCMA_CC_PMU5_MAINPLL_SSB);
    441	case BCMA_CHIP_ID_BCM53572:
    442		return 75000000;
    443	default:
    444		bcma_warn(bus, "No bus clock specified for %04X device, pmu rev. %d, using default %d Hz\n",
    445			  bus->chipinfo.id, cc->pmu.rev, BCMA_CC_PMU_HT_CLOCK);
    446	}
    447	return BCMA_CC_PMU_HT_CLOCK;
    448}
    449EXPORT_SYMBOL_GPL(bcma_pmu_get_bus_clock);
    450
    451/* query cpu clock frequency for PMU-enabled chipcommon */
    452u32 bcma_pmu_get_cpu_clock(struct bcma_drv_cc *cc)
    453{
    454	struct bcma_bus *bus = cc->core->bus;
    455
    456	if (bus->chipinfo.id == BCMA_CHIP_ID_BCM53572)
    457		return 300000000;
    458
    459	/* New PMUs can have different clock for bus and CPU */
    460	if (cc->pmu.rev >= 5) {
    461		u32 pll;
    462		switch (bus->chipinfo.id) {
    463		case BCMA_CHIP_ID_BCM4706:
    464			return bcma_pmu_pll_clock_bcm4706(cc,
    465						BCMA_CC_PMU4706_MAINPLL_PLL0,
    466						BCMA_CC_PMU5_MAINPLL_CPU);
    467		case BCMA_CHIP_ID_BCM5356:
    468			pll = BCMA_CC_PMU5356_MAINPLL_PLL0;
    469			break;
    470		case BCMA_CHIP_ID_BCM5357:
    471		case BCMA_CHIP_ID_BCM4749:
    472			pll = BCMA_CC_PMU5357_MAINPLL_PLL0;
    473			break;
    474		default:
    475			pll = BCMA_CC_PMU4716_MAINPLL_PLL0;
    476			break;
    477		}
    478
    479		return bcma_pmu_pll_clock(cc, pll, BCMA_CC_PMU5_MAINPLL_CPU);
    480	}
    481
    482	/* On old PMUs CPU has the same clock as the bus */
    483	return bcma_pmu_get_bus_clock(cc);
    484}
    485
    486static void bcma_pmu_spuravoid_pll_write(struct bcma_drv_cc *cc, u32 offset,
    487					 u32 value)
    488{
    489	bcma_pmu_write32(cc, BCMA_CC_PMU_PLLCTL_ADDR, offset);
    490	bcma_pmu_write32(cc, BCMA_CC_PMU_PLLCTL_DATA, value);
    491}
    492
    493void bcma_pmu_spuravoid_pllupdate(struct bcma_drv_cc *cc, int spuravoid)
    494{
    495	u32 tmp = 0;
    496	u8 phypll_offset = 0;
    497	u8 bcm5357_bcm43236_p1div[] = {0x1, 0x5, 0x5};
    498	u8 bcm5357_bcm43236_ndiv[] = {0x30, 0xf6, 0xfc};
    499	struct bcma_bus *bus = cc->core->bus;
    500
    501	switch (bus->chipinfo.id) {
    502	case BCMA_CHIP_ID_BCM5357:
    503	case BCMA_CHIP_ID_BCM4749:
    504	case BCMA_CHIP_ID_BCM53572:
    505		/* 5357[ab]0, 43236[ab]0, and 6362b0 */
    506
    507		/*
    508		 * BCM5357 needs to touch PLL1_PLLCTL[02],
    509		 * so offset PLL0_PLLCTL[02] by 6
    510		 */
    511		phypll_offset = (bus->chipinfo.id == BCMA_CHIP_ID_BCM5357 ||
    512		       bus->chipinfo.id == BCMA_CHIP_ID_BCM4749 ||
    513		       bus->chipinfo.id == BCMA_CHIP_ID_BCM53572) ? 6 : 0;
    514
    515		/* RMW only the P1 divider */
    516		bcma_pmu_write32(cc, BCMA_CC_PMU_PLLCTL_ADDR,
    517				BCMA_CC_PMU_PLL_CTL0 + phypll_offset);
    518		tmp = bcma_pmu_read32(cc, BCMA_CC_PMU_PLLCTL_DATA);
    519		tmp &= (~(BCMA_CC_PMU1_PLL0_PC0_P1DIV_MASK));
    520		tmp |= (bcm5357_bcm43236_p1div[spuravoid] << BCMA_CC_PMU1_PLL0_PC0_P1DIV_SHIFT);
    521		bcma_pmu_write32(cc, BCMA_CC_PMU_PLLCTL_DATA, tmp);
    522
    523		/* RMW only the int feedback divider */
    524		bcma_pmu_write32(cc, BCMA_CC_PMU_PLLCTL_ADDR,
    525				BCMA_CC_PMU_PLL_CTL2 + phypll_offset);
    526		tmp = bcma_pmu_read32(cc, BCMA_CC_PMU_PLLCTL_DATA);
    527		tmp &= ~(BCMA_CC_PMU1_PLL0_PC2_NDIV_INT_MASK);
    528		tmp |= (bcm5357_bcm43236_ndiv[spuravoid]) << BCMA_CC_PMU1_PLL0_PC2_NDIV_INT_SHIFT;
    529		bcma_pmu_write32(cc, BCMA_CC_PMU_PLLCTL_DATA, tmp);
    530
    531		tmp = BCMA_CC_PMU_CTL_PLL_UPD;
    532		break;
    533
    534	case BCMA_CHIP_ID_BCM4331:
    535	case BCMA_CHIP_ID_BCM43431:
    536		if (spuravoid == 2) {
    537			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0,
    538						     0x11500014);
    539			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2,
    540						     0x0FC00a08);
    541		} else if (spuravoid == 1) {
    542			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0,
    543						     0x11500014);
    544			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2,
    545						     0x0F600a08);
    546		} else {
    547			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0,
    548						     0x11100014);
    549			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2,
    550						     0x03000a08);
    551		}
    552		tmp = BCMA_CC_PMU_CTL_PLL_UPD;
    553		break;
    554
    555	case BCMA_CHIP_ID_BCM43224:
    556	case BCMA_CHIP_ID_BCM43225:
    557	case BCMA_CHIP_ID_BCM43421:
    558		if (spuravoid == 1) {
    559			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0,
    560						     0x11500010);
    561			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL1,
    562						     0x000C0C06);
    563			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2,
    564						     0x0F600a08);
    565			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL3,
    566						     0x00000000);
    567			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL4,
    568						     0x2001E920);
    569			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5,
    570						     0x88888815);
    571		} else {
    572			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0,
    573						     0x11100010);
    574			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL1,
    575						     0x000c0c06);
    576			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2,
    577						     0x03000a08);
    578			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL3,
    579						     0x00000000);
    580			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL4,
    581						     0x200005c0);
    582			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5,
    583						     0x88888815);
    584		}
    585		tmp = BCMA_CC_PMU_CTL_PLL_UPD;
    586		break;
    587
    588	case BCMA_CHIP_ID_BCM4716:
    589	case BCMA_CHIP_ID_BCM4748:
    590	case BCMA_CHIP_ID_BCM47162:
    591		if (spuravoid == 1) {
    592			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0,
    593						     0x11500060);
    594			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL1,
    595						     0x080C0C06);
    596			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2,
    597						     0x0F600000);
    598			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL3,
    599						     0x00000000);
    600			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL4,
    601						     0x2001E924);
    602			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5,
    603						     0x88888815);
    604		} else {
    605			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0,
    606						     0x11100060);
    607			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL1,
    608						     0x080c0c06);
    609			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2,
    610						     0x03000000);
    611			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL3,
    612						     0x00000000);
    613			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL4,
    614						     0x200005c0);
    615			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5,
    616						     0x88888815);
    617		}
    618
    619		tmp = BCMA_CC_PMU_CTL_PLL_UPD | BCMA_CC_PMU_CTL_NOILPONW;
    620		break;
    621
    622	case BCMA_CHIP_ID_BCM43131:
    623	case BCMA_CHIP_ID_BCM43217:
    624	case BCMA_CHIP_ID_BCM43227:
    625	case BCMA_CHIP_ID_BCM43228:
    626	case BCMA_CHIP_ID_BCM43428:
    627		/* LCNXN */
    628		/*
    629		 * PLL Settings for spur avoidance on/off mode,
    630		 * no on2 support for 43228A0
    631		 */
    632		if (spuravoid == 1) {
    633			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0,
    634						     0x01100014);
    635			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL1,
    636						     0x040C0C06);
    637			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2,
    638						     0x03140A08);
    639			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL3,
    640						     0x00333333);
    641			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL4,
    642						     0x202C2820);
    643			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5,
    644						     0x88888815);
    645		} else {
    646			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0,
    647						     0x11100014);
    648			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL1,
    649						     0x040c0c06);
    650			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2,
    651						     0x03000a08);
    652			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL3,
    653						     0x00000000);
    654			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL4,
    655						     0x200005c0);
    656			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5,
    657						     0x88888815);
    658		}
    659		tmp = BCMA_CC_PMU_CTL_PLL_UPD;
    660		break;
    661	default:
    662		bcma_err(bus, "Unknown spuravoidance settings for chip 0x%04X, not changing PLL\n",
    663			 bus->chipinfo.id);
    664		break;
    665	}
    666
    667	tmp |= bcma_pmu_read32(cc, BCMA_CC_PMU_CTL);
    668	bcma_pmu_write32(cc, BCMA_CC_PMU_CTL, tmp);
    669}
    670EXPORT_SYMBOL_GPL(bcma_pmu_spuravoid_pllupdate);