162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * Broadcom specific AMBA 362306a36Sopenharmony_ci * ChipCommon Power Management Unit driver 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright 2009, Michael Buesch <m@bues.ch> 662306a36Sopenharmony_ci * Copyright 2007, 2011, Broadcom Corporation 762306a36Sopenharmony_ci * Copyright 2011, 2012, Hauke Mehrtens <hauke@hauke-m.de> 862306a36Sopenharmony_ci * 962306a36Sopenharmony_ci * Licensed under the GNU/GPL. See COPYING for details. 1062306a36Sopenharmony_ci */ 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#include "bcma_private.h" 1362306a36Sopenharmony_ci#include <linux/export.h> 1462306a36Sopenharmony_ci#include <linux/bcma/bcma.h> 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ciu32 bcma_chipco_pll_read(struct bcma_drv_cc *cc, u32 offset) 1762306a36Sopenharmony_ci{ 1862306a36Sopenharmony_ci bcma_pmu_write32(cc, BCMA_CC_PMU_PLLCTL_ADDR, offset); 1962306a36Sopenharmony_ci bcma_pmu_read32(cc, BCMA_CC_PMU_PLLCTL_ADDR); 2062306a36Sopenharmony_ci return bcma_pmu_read32(cc, BCMA_CC_PMU_PLLCTL_DATA); 2162306a36Sopenharmony_ci} 2262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(bcma_chipco_pll_read); 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_civoid bcma_chipco_pll_write(struct bcma_drv_cc *cc, u32 offset, u32 value) 2562306a36Sopenharmony_ci{ 2662306a36Sopenharmony_ci bcma_pmu_write32(cc, BCMA_CC_PMU_PLLCTL_ADDR, offset); 2762306a36Sopenharmony_ci bcma_pmu_read32(cc, BCMA_CC_PMU_PLLCTL_ADDR); 2862306a36Sopenharmony_ci bcma_pmu_write32(cc, BCMA_CC_PMU_PLLCTL_DATA, value); 2962306a36Sopenharmony_ci} 3062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(bcma_chipco_pll_write); 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_civoid bcma_chipco_pll_maskset(struct bcma_drv_cc *cc, u32 offset, u32 mask, 3362306a36Sopenharmony_ci u32 set) 3462306a36Sopenharmony_ci{ 3562306a36Sopenharmony_ci bcma_pmu_write32(cc, BCMA_CC_PMU_PLLCTL_ADDR, offset); 3662306a36Sopenharmony_ci bcma_pmu_read32(cc, BCMA_CC_PMU_PLLCTL_ADDR); 3762306a36Sopenharmony_ci bcma_pmu_maskset32(cc, BCMA_CC_PMU_PLLCTL_DATA, mask, set); 3862306a36Sopenharmony_ci} 3962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(bcma_chipco_pll_maskset); 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_civoid bcma_chipco_chipctl_maskset(struct bcma_drv_cc *cc, 4262306a36Sopenharmony_ci u32 offset, u32 mask, u32 set) 4362306a36Sopenharmony_ci{ 4462306a36Sopenharmony_ci bcma_pmu_write32(cc, BCMA_CC_PMU_CHIPCTL_ADDR, offset); 4562306a36Sopenharmony_ci bcma_pmu_read32(cc, BCMA_CC_PMU_CHIPCTL_ADDR); 4662306a36Sopenharmony_ci bcma_pmu_maskset32(cc, BCMA_CC_PMU_CHIPCTL_DATA, mask, set); 4762306a36Sopenharmony_ci} 4862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(bcma_chipco_chipctl_maskset); 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_civoid bcma_chipco_regctl_maskset(struct bcma_drv_cc *cc, u32 offset, u32 mask, 5162306a36Sopenharmony_ci u32 set) 5262306a36Sopenharmony_ci{ 5362306a36Sopenharmony_ci bcma_pmu_write32(cc, BCMA_CC_PMU_REGCTL_ADDR, offset); 5462306a36Sopenharmony_ci bcma_pmu_read32(cc, BCMA_CC_PMU_REGCTL_ADDR); 5562306a36Sopenharmony_ci bcma_pmu_maskset32(cc, BCMA_CC_PMU_REGCTL_DATA, mask, set); 5662306a36Sopenharmony_ci} 5762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(bcma_chipco_regctl_maskset); 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_cistatic u32 bcma_pmu_xtalfreq(struct bcma_drv_cc *cc) 6062306a36Sopenharmony_ci{ 6162306a36Sopenharmony_ci u32 ilp_ctl, alp_hz; 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci if (!(bcma_pmu_read32(cc, BCMA_CC_PMU_STAT) & 6462306a36Sopenharmony_ci BCMA_CC_PMU_STAT_EXT_LPO_AVAIL)) 6562306a36Sopenharmony_ci return 0; 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci bcma_pmu_write32(cc, BCMA_CC_PMU_XTAL_FREQ, 6862306a36Sopenharmony_ci BIT(BCMA_CC_PMU_XTAL_FREQ_MEASURE_SHIFT)); 6962306a36Sopenharmony_ci usleep_range(1000, 2000); 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci ilp_ctl = bcma_pmu_read32(cc, BCMA_CC_PMU_XTAL_FREQ); 7262306a36Sopenharmony_ci ilp_ctl &= BCMA_CC_PMU_XTAL_FREQ_ILPCTL_MASK; 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci bcma_pmu_write32(cc, BCMA_CC_PMU_XTAL_FREQ, 0); 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci alp_hz = ilp_ctl * 32768 / 4; 7762306a36Sopenharmony_ci return (alp_hz + 50000) / 100000 * 100; 7862306a36Sopenharmony_ci} 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_cistatic void bcma_pmu2_pll_init0(struct bcma_drv_cc *cc, u32 xtalfreq) 8162306a36Sopenharmony_ci{ 8262306a36Sopenharmony_ci struct bcma_bus *bus = cc->core->bus; 8362306a36Sopenharmony_ci u32 freq_tgt_target = 0, freq_tgt_current; 8462306a36Sopenharmony_ci u32 pll0, mask; 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci switch (bus->chipinfo.id) { 8762306a36Sopenharmony_ci case BCMA_CHIP_ID_BCM43142: 8862306a36Sopenharmony_ci /* pmu2_xtaltab0_adfll_485 */ 8962306a36Sopenharmony_ci switch (xtalfreq) { 9062306a36Sopenharmony_ci case 12000: 9162306a36Sopenharmony_ci freq_tgt_target = 0x50D52; 9262306a36Sopenharmony_ci break; 9362306a36Sopenharmony_ci case 20000: 9462306a36Sopenharmony_ci freq_tgt_target = 0x307FE; 9562306a36Sopenharmony_ci break; 9662306a36Sopenharmony_ci case 26000: 9762306a36Sopenharmony_ci freq_tgt_target = 0x254EA; 9862306a36Sopenharmony_ci break; 9962306a36Sopenharmony_ci case 37400: 10062306a36Sopenharmony_ci freq_tgt_target = 0x19EF8; 10162306a36Sopenharmony_ci break; 10262306a36Sopenharmony_ci case 52000: 10362306a36Sopenharmony_ci freq_tgt_target = 0x12A75; 10462306a36Sopenharmony_ci break; 10562306a36Sopenharmony_ci } 10662306a36Sopenharmony_ci break; 10762306a36Sopenharmony_ci } 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci if (!freq_tgt_target) { 11062306a36Sopenharmony_ci bcma_err(bus, "Unknown TGT frequency for xtalfreq %d\n", 11162306a36Sopenharmony_ci xtalfreq); 11262306a36Sopenharmony_ci return; 11362306a36Sopenharmony_ci } 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci pll0 = bcma_chipco_pll_read(cc, BCMA_CC_PMU15_PLL_PLLCTL0); 11662306a36Sopenharmony_ci freq_tgt_current = (pll0 & BCMA_CC_PMU15_PLL_PC0_FREQTGT_MASK) >> 11762306a36Sopenharmony_ci BCMA_CC_PMU15_PLL_PC0_FREQTGT_SHIFT; 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci if (freq_tgt_current == freq_tgt_target) { 12062306a36Sopenharmony_ci bcma_debug(bus, "Target TGT frequency already set\n"); 12162306a36Sopenharmony_ci return; 12262306a36Sopenharmony_ci } 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci /* Turn off PLL */ 12562306a36Sopenharmony_ci switch (bus->chipinfo.id) { 12662306a36Sopenharmony_ci case BCMA_CHIP_ID_BCM43142: 12762306a36Sopenharmony_ci mask = (u32)~(BCMA_RES_4314_HT_AVAIL | 12862306a36Sopenharmony_ci BCMA_RES_4314_MACPHY_CLK_AVAIL); 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci bcma_pmu_mask32(cc, BCMA_CC_PMU_MINRES_MSK, mask); 13162306a36Sopenharmony_ci bcma_pmu_mask32(cc, BCMA_CC_PMU_MAXRES_MSK, mask); 13262306a36Sopenharmony_ci bcma_wait_value(cc->core, BCMA_CLKCTLST, 13362306a36Sopenharmony_ci BCMA_CLKCTLST_HAVEHT, 0, 20000); 13462306a36Sopenharmony_ci break; 13562306a36Sopenharmony_ci } 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci pll0 &= ~BCMA_CC_PMU15_PLL_PC0_FREQTGT_MASK; 13862306a36Sopenharmony_ci pll0 |= freq_tgt_target << BCMA_CC_PMU15_PLL_PC0_FREQTGT_SHIFT; 13962306a36Sopenharmony_ci bcma_chipco_pll_write(cc, BCMA_CC_PMU15_PLL_PLLCTL0, pll0); 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci /* Flush */ 14262306a36Sopenharmony_ci if (cc->pmu.rev >= 2) 14362306a36Sopenharmony_ci bcma_pmu_set32(cc, BCMA_CC_PMU_CTL, BCMA_CC_PMU_CTL_PLL_UPD); 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci /* TODO: Do we need to update OTP? */ 14662306a36Sopenharmony_ci} 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_cistatic void bcma_pmu_pll_init(struct bcma_drv_cc *cc) 14962306a36Sopenharmony_ci{ 15062306a36Sopenharmony_ci struct bcma_bus *bus = cc->core->bus; 15162306a36Sopenharmony_ci u32 xtalfreq = bcma_pmu_xtalfreq(cc); 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci switch (bus->chipinfo.id) { 15462306a36Sopenharmony_ci case BCMA_CHIP_ID_BCM43142: 15562306a36Sopenharmony_ci if (xtalfreq == 0) 15662306a36Sopenharmony_ci xtalfreq = 20000; 15762306a36Sopenharmony_ci bcma_pmu2_pll_init0(cc, xtalfreq); 15862306a36Sopenharmony_ci break; 15962306a36Sopenharmony_ci } 16062306a36Sopenharmony_ci} 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_cistatic void bcma_pmu_resources_init(struct bcma_drv_cc *cc) 16362306a36Sopenharmony_ci{ 16462306a36Sopenharmony_ci struct bcma_bus *bus = cc->core->bus; 16562306a36Sopenharmony_ci u32 min_msk = 0, max_msk = 0; 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci switch (bus->chipinfo.id) { 16862306a36Sopenharmony_ci case BCMA_CHIP_ID_BCM4313: 16962306a36Sopenharmony_ci min_msk = 0x200D; 17062306a36Sopenharmony_ci max_msk = 0xFFFF; 17162306a36Sopenharmony_ci break; 17262306a36Sopenharmony_ci case BCMA_CHIP_ID_BCM43142: 17362306a36Sopenharmony_ci min_msk = BCMA_RES_4314_LPLDO_PU | 17462306a36Sopenharmony_ci BCMA_RES_4314_PMU_SLEEP_DIS | 17562306a36Sopenharmony_ci BCMA_RES_4314_PMU_BG_PU | 17662306a36Sopenharmony_ci BCMA_RES_4314_CBUCK_LPOM_PU | 17762306a36Sopenharmony_ci BCMA_RES_4314_CBUCK_PFM_PU | 17862306a36Sopenharmony_ci BCMA_RES_4314_CLDO_PU | 17962306a36Sopenharmony_ci BCMA_RES_4314_LPLDO2_LVM | 18062306a36Sopenharmony_ci BCMA_RES_4314_WL_PMU_PU | 18162306a36Sopenharmony_ci BCMA_RES_4314_LDO3P3_PU | 18262306a36Sopenharmony_ci BCMA_RES_4314_OTP_PU | 18362306a36Sopenharmony_ci BCMA_RES_4314_WL_PWRSW_PU | 18462306a36Sopenharmony_ci BCMA_RES_4314_LQ_AVAIL | 18562306a36Sopenharmony_ci BCMA_RES_4314_LOGIC_RET | 18662306a36Sopenharmony_ci BCMA_RES_4314_MEM_SLEEP | 18762306a36Sopenharmony_ci BCMA_RES_4314_MACPHY_RET | 18862306a36Sopenharmony_ci BCMA_RES_4314_WL_CORE_READY; 18962306a36Sopenharmony_ci max_msk = 0x3FFFFFFF; 19062306a36Sopenharmony_ci break; 19162306a36Sopenharmony_ci default: 19262306a36Sopenharmony_ci bcma_debug(bus, "PMU resource config unknown or not needed for device 0x%04X\n", 19362306a36Sopenharmony_ci bus->chipinfo.id); 19462306a36Sopenharmony_ci } 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ci /* Set the resource masks. */ 19762306a36Sopenharmony_ci if (min_msk) 19862306a36Sopenharmony_ci bcma_pmu_write32(cc, BCMA_CC_PMU_MINRES_MSK, min_msk); 19962306a36Sopenharmony_ci if (max_msk) 20062306a36Sopenharmony_ci bcma_pmu_write32(cc, BCMA_CC_PMU_MAXRES_MSK, max_msk); 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci /* 20362306a36Sopenharmony_ci * Add some delay; allow resources to come up and settle. 20462306a36Sopenharmony_ci * Delay is required for SoC (early init). 20562306a36Sopenharmony_ci */ 20662306a36Sopenharmony_ci usleep_range(2000, 2500); 20762306a36Sopenharmony_ci} 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_ci/* Disable to allow reading SPROM. Don't know the advantages of enabling it. */ 21062306a36Sopenharmony_civoid bcma_chipco_bcm4331_ext_pa_lines_ctl(struct bcma_drv_cc *cc, bool enable) 21162306a36Sopenharmony_ci{ 21262306a36Sopenharmony_ci struct bcma_bus *bus = cc->core->bus; 21362306a36Sopenharmony_ci u32 val; 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ci val = bcma_cc_read32(cc, BCMA_CC_CHIPCTL); 21662306a36Sopenharmony_ci if (enable) { 21762306a36Sopenharmony_ci val |= BCMA_CHIPCTL_4331_EXTPA_EN; 21862306a36Sopenharmony_ci if (bus->chipinfo.pkg == 9 || bus->chipinfo.pkg == 11) 21962306a36Sopenharmony_ci val |= BCMA_CHIPCTL_4331_EXTPA_ON_GPIO2_5; 22062306a36Sopenharmony_ci else if (bus->chipinfo.rev > 0) 22162306a36Sopenharmony_ci val |= BCMA_CHIPCTL_4331_EXTPA_EN2; 22262306a36Sopenharmony_ci } else { 22362306a36Sopenharmony_ci val &= ~BCMA_CHIPCTL_4331_EXTPA_EN; 22462306a36Sopenharmony_ci val &= ~BCMA_CHIPCTL_4331_EXTPA_EN2; 22562306a36Sopenharmony_ci val &= ~BCMA_CHIPCTL_4331_EXTPA_ON_GPIO2_5; 22662306a36Sopenharmony_ci } 22762306a36Sopenharmony_ci bcma_cc_write32(cc, BCMA_CC_CHIPCTL, val); 22862306a36Sopenharmony_ci} 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_cistatic void bcma_pmu_workarounds(struct bcma_drv_cc *cc) 23162306a36Sopenharmony_ci{ 23262306a36Sopenharmony_ci struct bcma_bus *bus = cc->core->bus; 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ci switch (bus->chipinfo.id) { 23562306a36Sopenharmony_ci case BCMA_CHIP_ID_BCM4313: 23662306a36Sopenharmony_ci /* 23762306a36Sopenharmony_ci * enable 12 mA drive strength for 4313 and set chipControl 23862306a36Sopenharmony_ci * register bit 1 23962306a36Sopenharmony_ci */ 24062306a36Sopenharmony_ci bcma_chipco_chipctl_maskset(cc, 0, 24162306a36Sopenharmony_ci ~BCMA_CCTRL_4313_12MA_LED_DRIVE, 24262306a36Sopenharmony_ci BCMA_CCTRL_4313_12MA_LED_DRIVE); 24362306a36Sopenharmony_ci break; 24462306a36Sopenharmony_ci case BCMA_CHIP_ID_BCM4331: 24562306a36Sopenharmony_ci case BCMA_CHIP_ID_BCM43431: 24662306a36Sopenharmony_ci /* Ext PA lines must be enabled for tx on BCM4331 */ 24762306a36Sopenharmony_ci bcma_chipco_bcm4331_ext_pa_lines_ctl(cc, true); 24862306a36Sopenharmony_ci break; 24962306a36Sopenharmony_ci case BCMA_CHIP_ID_BCM43224: 25062306a36Sopenharmony_ci case BCMA_CHIP_ID_BCM43421: 25162306a36Sopenharmony_ci /* 25262306a36Sopenharmony_ci * enable 12 mA drive strength for 43224 and set chipControl 25362306a36Sopenharmony_ci * register bit 15 25462306a36Sopenharmony_ci */ 25562306a36Sopenharmony_ci if (bus->chipinfo.rev == 0) { 25662306a36Sopenharmony_ci bcma_cc_maskset32(cc, BCMA_CC_CHIPCTL, 25762306a36Sopenharmony_ci ~BCMA_CCTRL_43224_GPIO_TOGGLE, 25862306a36Sopenharmony_ci BCMA_CCTRL_43224_GPIO_TOGGLE); 25962306a36Sopenharmony_ci bcma_chipco_chipctl_maskset(cc, 0, 26062306a36Sopenharmony_ci ~BCMA_CCTRL_43224A0_12MA_LED_DRIVE, 26162306a36Sopenharmony_ci BCMA_CCTRL_43224A0_12MA_LED_DRIVE); 26262306a36Sopenharmony_ci } else { 26362306a36Sopenharmony_ci bcma_chipco_chipctl_maskset(cc, 0, 26462306a36Sopenharmony_ci ~BCMA_CCTRL_43224B0_12MA_LED_DRIVE, 26562306a36Sopenharmony_ci BCMA_CCTRL_43224B0_12MA_LED_DRIVE); 26662306a36Sopenharmony_ci } 26762306a36Sopenharmony_ci break; 26862306a36Sopenharmony_ci default: 26962306a36Sopenharmony_ci bcma_debug(bus, "Workarounds unknown or not needed for device 0x%04X\n", 27062306a36Sopenharmony_ci bus->chipinfo.id); 27162306a36Sopenharmony_ci } 27262306a36Sopenharmony_ci} 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_civoid bcma_pmu_early_init(struct bcma_drv_cc *cc) 27562306a36Sopenharmony_ci{ 27662306a36Sopenharmony_ci struct bcma_bus *bus = cc->core->bus; 27762306a36Sopenharmony_ci u32 pmucap; 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ci if (cc->core->id.rev >= 35 && 28062306a36Sopenharmony_ci cc->capabilities_ext & BCMA_CC_CAP_EXT_AOB_PRESENT) { 28162306a36Sopenharmony_ci cc->pmu.core = bcma_find_core(bus, BCMA_CORE_PMU); 28262306a36Sopenharmony_ci if (!cc->pmu.core) 28362306a36Sopenharmony_ci bcma_warn(bus, "Couldn't find expected PMU core"); 28462306a36Sopenharmony_ci } 28562306a36Sopenharmony_ci if (!cc->pmu.core) 28662306a36Sopenharmony_ci cc->pmu.core = cc->core; 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci pmucap = bcma_pmu_read32(cc, BCMA_CC_PMU_CAP); 28962306a36Sopenharmony_ci cc->pmu.rev = (pmucap & BCMA_CC_PMU_CAP_REVISION); 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_ci bcma_debug(bus, "Found rev %u PMU (capabilities 0x%08X)\n", cc->pmu.rev, 29262306a36Sopenharmony_ci pmucap); 29362306a36Sopenharmony_ci} 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_civoid bcma_pmu_init(struct bcma_drv_cc *cc) 29662306a36Sopenharmony_ci{ 29762306a36Sopenharmony_ci if (cc->pmu.rev == 1) 29862306a36Sopenharmony_ci bcma_pmu_mask32(cc, BCMA_CC_PMU_CTL, 29962306a36Sopenharmony_ci ~BCMA_CC_PMU_CTL_NOILPONW); 30062306a36Sopenharmony_ci else 30162306a36Sopenharmony_ci bcma_pmu_set32(cc, BCMA_CC_PMU_CTL, 30262306a36Sopenharmony_ci BCMA_CC_PMU_CTL_NOILPONW); 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_ci bcma_pmu_pll_init(cc); 30562306a36Sopenharmony_ci bcma_pmu_resources_init(cc); 30662306a36Sopenharmony_ci bcma_pmu_workarounds(cc); 30762306a36Sopenharmony_ci} 30862306a36Sopenharmony_ci 30962306a36Sopenharmony_ciu32 bcma_pmu_get_alp_clock(struct bcma_drv_cc *cc) 31062306a36Sopenharmony_ci{ 31162306a36Sopenharmony_ci struct bcma_bus *bus = cc->core->bus; 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci switch (bus->chipinfo.id) { 31462306a36Sopenharmony_ci case BCMA_CHIP_ID_BCM4313: 31562306a36Sopenharmony_ci case BCMA_CHIP_ID_BCM43224: 31662306a36Sopenharmony_ci case BCMA_CHIP_ID_BCM43225: 31762306a36Sopenharmony_ci case BCMA_CHIP_ID_BCM43227: 31862306a36Sopenharmony_ci case BCMA_CHIP_ID_BCM43228: 31962306a36Sopenharmony_ci case BCMA_CHIP_ID_BCM4331: 32062306a36Sopenharmony_ci case BCMA_CHIP_ID_BCM43421: 32162306a36Sopenharmony_ci case BCMA_CHIP_ID_BCM43428: 32262306a36Sopenharmony_ci case BCMA_CHIP_ID_BCM43431: 32362306a36Sopenharmony_ci case BCMA_CHIP_ID_BCM4716: 32462306a36Sopenharmony_ci case BCMA_CHIP_ID_BCM47162: 32562306a36Sopenharmony_ci case BCMA_CHIP_ID_BCM4748: 32662306a36Sopenharmony_ci case BCMA_CHIP_ID_BCM4749: 32762306a36Sopenharmony_ci case BCMA_CHIP_ID_BCM5357: 32862306a36Sopenharmony_ci case BCMA_CHIP_ID_BCM53572: 32962306a36Sopenharmony_ci case BCMA_CHIP_ID_BCM6362: 33062306a36Sopenharmony_ci /* always 20Mhz */ 33162306a36Sopenharmony_ci return 20000 * 1000; 33262306a36Sopenharmony_ci case BCMA_CHIP_ID_BCM4706: 33362306a36Sopenharmony_ci case BCMA_CHIP_ID_BCM5356: 33462306a36Sopenharmony_ci /* always 25Mhz */ 33562306a36Sopenharmony_ci return 25000 * 1000; 33662306a36Sopenharmony_ci case BCMA_CHIP_ID_BCM43460: 33762306a36Sopenharmony_ci case BCMA_CHIP_ID_BCM4352: 33862306a36Sopenharmony_ci case BCMA_CHIP_ID_BCM4360: 33962306a36Sopenharmony_ci if (cc->status & BCMA_CC_CHIPST_4360_XTAL_40MZ) 34062306a36Sopenharmony_ci return 40000 * 1000; 34162306a36Sopenharmony_ci else 34262306a36Sopenharmony_ci return 20000 * 1000; 34362306a36Sopenharmony_ci default: 34462306a36Sopenharmony_ci bcma_warn(bus, "No ALP clock specified for %04X device, pmu rev. %d, using default %d Hz\n", 34562306a36Sopenharmony_ci bus->chipinfo.id, cc->pmu.rev, BCMA_CC_PMU_ALP_CLOCK); 34662306a36Sopenharmony_ci } 34762306a36Sopenharmony_ci return BCMA_CC_PMU_ALP_CLOCK; 34862306a36Sopenharmony_ci} 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_ci/* Find the output of the "m" pll divider given pll controls that start with 35162306a36Sopenharmony_ci * pllreg "pll0" i.e. 12 for main 6 for phy, 0 for misc. 35262306a36Sopenharmony_ci */ 35362306a36Sopenharmony_cistatic u32 bcma_pmu_pll_clock(struct bcma_drv_cc *cc, u32 pll0, u32 m) 35462306a36Sopenharmony_ci{ 35562306a36Sopenharmony_ci u32 tmp, div, ndiv, p1, p2, fc; 35662306a36Sopenharmony_ci struct bcma_bus *bus = cc->core->bus; 35762306a36Sopenharmony_ci 35862306a36Sopenharmony_ci BUG_ON((pll0 & 3) || (pll0 > BCMA_CC_PMU4716_MAINPLL_PLL0)); 35962306a36Sopenharmony_ci 36062306a36Sopenharmony_ci BUG_ON(!m || m > 4); 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_ci if (bus->chipinfo.id == BCMA_CHIP_ID_BCM5357 || 36362306a36Sopenharmony_ci bus->chipinfo.id == BCMA_CHIP_ID_BCM4749) { 36462306a36Sopenharmony_ci /* Detect failure in clock setting */ 36562306a36Sopenharmony_ci tmp = bcma_cc_read32(cc, BCMA_CC_CHIPSTAT); 36662306a36Sopenharmony_ci if (tmp & 0x40000) 36762306a36Sopenharmony_ci return 133 * 1000000; 36862306a36Sopenharmony_ci } 36962306a36Sopenharmony_ci 37062306a36Sopenharmony_ci tmp = bcma_chipco_pll_read(cc, pll0 + BCMA_CC_PPL_P1P2_OFF); 37162306a36Sopenharmony_ci p1 = (tmp & BCMA_CC_PPL_P1_MASK) >> BCMA_CC_PPL_P1_SHIFT; 37262306a36Sopenharmony_ci p2 = (tmp & BCMA_CC_PPL_P2_MASK) >> BCMA_CC_PPL_P2_SHIFT; 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_ci tmp = bcma_chipco_pll_read(cc, pll0 + BCMA_CC_PPL_M14_OFF); 37562306a36Sopenharmony_ci div = (tmp >> ((m - 1) * BCMA_CC_PPL_MDIV_WIDTH)) & 37662306a36Sopenharmony_ci BCMA_CC_PPL_MDIV_MASK; 37762306a36Sopenharmony_ci 37862306a36Sopenharmony_ci tmp = bcma_chipco_pll_read(cc, pll0 + BCMA_CC_PPL_NM5_OFF); 37962306a36Sopenharmony_ci ndiv = (tmp & BCMA_CC_PPL_NDIV_MASK) >> BCMA_CC_PPL_NDIV_SHIFT; 38062306a36Sopenharmony_ci 38162306a36Sopenharmony_ci /* Do calculation in Mhz */ 38262306a36Sopenharmony_ci fc = bcma_pmu_get_alp_clock(cc) / 1000000; 38362306a36Sopenharmony_ci fc = (p1 * ndiv * fc) / p2; 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_ci /* Return clock in Hertz */ 38662306a36Sopenharmony_ci return (fc / div) * 1000000; 38762306a36Sopenharmony_ci} 38862306a36Sopenharmony_ci 38962306a36Sopenharmony_cistatic u32 bcma_pmu_pll_clock_bcm4706(struct bcma_drv_cc *cc, u32 pll0, u32 m) 39062306a36Sopenharmony_ci{ 39162306a36Sopenharmony_ci u32 tmp, ndiv, p1div, p2div; 39262306a36Sopenharmony_ci u32 clock; 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_ci BUG_ON(!m || m > 4); 39562306a36Sopenharmony_ci 39662306a36Sopenharmony_ci /* Get N, P1 and P2 dividers to determine CPU clock */ 39762306a36Sopenharmony_ci tmp = bcma_chipco_pll_read(cc, pll0 + BCMA_CC_PMU6_4706_PROCPLL_OFF); 39862306a36Sopenharmony_ci ndiv = (tmp & BCMA_CC_PMU6_4706_PROC_NDIV_INT_MASK) 39962306a36Sopenharmony_ci >> BCMA_CC_PMU6_4706_PROC_NDIV_INT_SHIFT; 40062306a36Sopenharmony_ci p1div = (tmp & BCMA_CC_PMU6_4706_PROC_P1DIV_MASK) 40162306a36Sopenharmony_ci >> BCMA_CC_PMU6_4706_PROC_P1DIV_SHIFT; 40262306a36Sopenharmony_ci p2div = (tmp & BCMA_CC_PMU6_4706_PROC_P2DIV_MASK) 40362306a36Sopenharmony_ci >> BCMA_CC_PMU6_4706_PROC_P2DIV_SHIFT; 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_ci tmp = bcma_cc_read32(cc, BCMA_CC_CHIPSTAT); 40662306a36Sopenharmony_ci if (tmp & BCMA_CC_CHIPST_4706_PKG_OPTION) 40762306a36Sopenharmony_ci /* Low cost bonding: Fixed reference clock 25MHz and m = 4 */ 40862306a36Sopenharmony_ci clock = (25000000 / 4) * ndiv * p2div / p1div; 40962306a36Sopenharmony_ci else 41062306a36Sopenharmony_ci /* Fixed reference clock 25MHz and m = 2 */ 41162306a36Sopenharmony_ci clock = (25000000 / 2) * ndiv * p2div / p1div; 41262306a36Sopenharmony_ci 41362306a36Sopenharmony_ci if (m == BCMA_CC_PMU5_MAINPLL_SSB) 41462306a36Sopenharmony_ci clock = clock / 4; 41562306a36Sopenharmony_ci 41662306a36Sopenharmony_ci return clock; 41762306a36Sopenharmony_ci} 41862306a36Sopenharmony_ci 41962306a36Sopenharmony_ci/* query bus clock frequency for PMU-enabled chipcommon */ 42062306a36Sopenharmony_ciu32 bcma_pmu_get_bus_clock(struct bcma_drv_cc *cc) 42162306a36Sopenharmony_ci{ 42262306a36Sopenharmony_ci struct bcma_bus *bus = cc->core->bus; 42362306a36Sopenharmony_ci 42462306a36Sopenharmony_ci switch (bus->chipinfo.id) { 42562306a36Sopenharmony_ci case BCMA_CHIP_ID_BCM4716: 42662306a36Sopenharmony_ci case BCMA_CHIP_ID_BCM4748: 42762306a36Sopenharmony_ci case BCMA_CHIP_ID_BCM47162: 42862306a36Sopenharmony_ci return bcma_pmu_pll_clock(cc, BCMA_CC_PMU4716_MAINPLL_PLL0, 42962306a36Sopenharmony_ci BCMA_CC_PMU5_MAINPLL_SSB); 43062306a36Sopenharmony_ci case BCMA_CHIP_ID_BCM5356: 43162306a36Sopenharmony_ci return bcma_pmu_pll_clock(cc, BCMA_CC_PMU5356_MAINPLL_PLL0, 43262306a36Sopenharmony_ci BCMA_CC_PMU5_MAINPLL_SSB); 43362306a36Sopenharmony_ci case BCMA_CHIP_ID_BCM5357: 43462306a36Sopenharmony_ci case BCMA_CHIP_ID_BCM4749: 43562306a36Sopenharmony_ci return bcma_pmu_pll_clock(cc, BCMA_CC_PMU5357_MAINPLL_PLL0, 43662306a36Sopenharmony_ci BCMA_CC_PMU5_MAINPLL_SSB); 43762306a36Sopenharmony_ci case BCMA_CHIP_ID_BCM4706: 43862306a36Sopenharmony_ci return bcma_pmu_pll_clock_bcm4706(cc, 43962306a36Sopenharmony_ci BCMA_CC_PMU4706_MAINPLL_PLL0, 44062306a36Sopenharmony_ci BCMA_CC_PMU5_MAINPLL_SSB); 44162306a36Sopenharmony_ci case BCMA_CHIP_ID_BCM53572: 44262306a36Sopenharmony_ci return 75000000; 44362306a36Sopenharmony_ci default: 44462306a36Sopenharmony_ci bcma_warn(bus, "No bus clock specified for %04X device, pmu rev. %d, using default %d Hz\n", 44562306a36Sopenharmony_ci bus->chipinfo.id, cc->pmu.rev, BCMA_CC_PMU_HT_CLOCK); 44662306a36Sopenharmony_ci } 44762306a36Sopenharmony_ci return BCMA_CC_PMU_HT_CLOCK; 44862306a36Sopenharmony_ci} 44962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(bcma_pmu_get_bus_clock); 45062306a36Sopenharmony_ci 45162306a36Sopenharmony_ci/* query cpu clock frequency for PMU-enabled chipcommon */ 45262306a36Sopenharmony_ciu32 bcma_pmu_get_cpu_clock(struct bcma_drv_cc *cc) 45362306a36Sopenharmony_ci{ 45462306a36Sopenharmony_ci struct bcma_bus *bus = cc->core->bus; 45562306a36Sopenharmony_ci 45662306a36Sopenharmony_ci if (bus->chipinfo.id == BCMA_CHIP_ID_BCM53572) 45762306a36Sopenharmony_ci return 300000000; 45862306a36Sopenharmony_ci 45962306a36Sopenharmony_ci /* New PMUs can have different clock for bus and CPU */ 46062306a36Sopenharmony_ci if (cc->pmu.rev >= 5) { 46162306a36Sopenharmony_ci u32 pll; 46262306a36Sopenharmony_ci switch (bus->chipinfo.id) { 46362306a36Sopenharmony_ci case BCMA_CHIP_ID_BCM4706: 46462306a36Sopenharmony_ci return bcma_pmu_pll_clock_bcm4706(cc, 46562306a36Sopenharmony_ci BCMA_CC_PMU4706_MAINPLL_PLL0, 46662306a36Sopenharmony_ci BCMA_CC_PMU5_MAINPLL_CPU); 46762306a36Sopenharmony_ci case BCMA_CHIP_ID_BCM5356: 46862306a36Sopenharmony_ci pll = BCMA_CC_PMU5356_MAINPLL_PLL0; 46962306a36Sopenharmony_ci break; 47062306a36Sopenharmony_ci case BCMA_CHIP_ID_BCM5357: 47162306a36Sopenharmony_ci case BCMA_CHIP_ID_BCM4749: 47262306a36Sopenharmony_ci pll = BCMA_CC_PMU5357_MAINPLL_PLL0; 47362306a36Sopenharmony_ci break; 47462306a36Sopenharmony_ci default: 47562306a36Sopenharmony_ci pll = BCMA_CC_PMU4716_MAINPLL_PLL0; 47662306a36Sopenharmony_ci break; 47762306a36Sopenharmony_ci } 47862306a36Sopenharmony_ci 47962306a36Sopenharmony_ci return bcma_pmu_pll_clock(cc, pll, BCMA_CC_PMU5_MAINPLL_CPU); 48062306a36Sopenharmony_ci } 48162306a36Sopenharmony_ci 48262306a36Sopenharmony_ci /* On old PMUs CPU has the same clock as the bus */ 48362306a36Sopenharmony_ci return bcma_pmu_get_bus_clock(cc); 48462306a36Sopenharmony_ci} 48562306a36Sopenharmony_ci 48662306a36Sopenharmony_cistatic void bcma_pmu_spuravoid_pll_write(struct bcma_drv_cc *cc, u32 offset, 48762306a36Sopenharmony_ci u32 value) 48862306a36Sopenharmony_ci{ 48962306a36Sopenharmony_ci bcma_pmu_write32(cc, BCMA_CC_PMU_PLLCTL_ADDR, offset); 49062306a36Sopenharmony_ci bcma_pmu_write32(cc, BCMA_CC_PMU_PLLCTL_DATA, value); 49162306a36Sopenharmony_ci} 49262306a36Sopenharmony_ci 49362306a36Sopenharmony_civoid bcma_pmu_spuravoid_pllupdate(struct bcma_drv_cc *cc, int spuravoid) 49462306a36Sopenharmony_ci{ 49562306a36Sopenharmony_ci u32 tmp = 0; 49662306a36Sopenharmony_ci u8 phypll_offset = 0; 49762306a36Sopenharmony_ci u8 bcm5357_bcm43236_p1div[] = {0x1, 0x5, 0x5}; 49862306a36Sopenharmony_ci u8 bcm5357_bcm43236_ndiv[] = {0x30, 0xf6, 0xfc}; 49962306a36Sopenharmony_ci struct bcma_bus *bus = cc->core->bus; 50062306a36Sopenharmony_ci 50162306a36Sopenharmony_ci switch (bus->chipinfo.id) { 50262306a36Sopenharmony_ci case BCMA_CHIP_ID_BCM5357: 50362306a36Sopenharmony_ci case BCMA_CHIP_ID_BCM4749: 50462306a36Sopenharmony_ci case BCMA_CHIP_ID_BCM53572: 50562306a36Sopenharmony_ci /* 5357[ab]0, 43236[ab]0, and 6362b0 */ 50662306a36Sopenharmony_ci 50762306a36Sopenharmony_ci /* 50862306a36Sopenharmony_ci * BCM5357 needs to touch PLL1_PLLCTL[02], 50962306a36Sopenharmony_ci * so offset PLL0_PLLCTL[02] by 6 51062306a36Sopenharmony_ci */ 51162306a36Sopenharmony_ci phypll_offset = (bus->chipinfo.id == BCMA_CHIP_ID_BCM5357 || 51262306a36Sopenharmony_ci bus->chipinfo.id == BCMA_CHIP_ID_BCM4749 || 51362306a36Sopenharmony_ci bus->chipinfo.id == BCMA_CHIP_ID_BCM53572) ? 6 : 0; 51462306a36Sopenharmony_ci 51562306a36Sopenharmony_ci /* RMW only the P1 divider */ 51662306a36Sopenharmony_ci bcma_pmu_write32(cc, BCMA_CC_PMU_PLLCTL_ADDR, 51762306a36Sopenharmony_ci BCMA_CC_PMU_PLL_CTL0 + phypll_offset); 51862306a36Sopenharmony_ci tmp = bcma_pmu_read32(cc, BCMA_CC_PMU_PLLCTL_DATA); 51962306a36Sopenharmony_ci tmp &= (~(BCMA_CC_PMU1_PLL0_PC0_P1DIV_MASK)); 52062306a36Sopenharmony_ci tmp |= (bcm5357_bcm43236_p1div[spuravoid] << BCMA_CC_PMU1_PLL0_PC0_P1DIV_SHIFT); 52162306a36Sopenharmony_ci bcma_pmu_write32(cc, BCMA_CC_PMU_PLLCTL_DATA, tmp); 52262306a36Sopenharmony_ci 52362306a36Sopenharmony_ci /* RMW only the int feedback divider */ 52462306a36Sopenharmony_ci bcma_pmu_write32(cc, BCMA_CC_PMU_PLLCTL_ADDR, 52562306a36Sopenharmony_ci BCMA_CC_PMU_PLL_CTL2 + phypll_offset); 52662306a36Sopenharmony_ci tmp = bcma_pmu_read32(cc, BCMA_CC_PMU_PLLCTL_DATA); 52762306a36Sopenharmony_ci tmp &= ~(BCMA_CC_PMU1_PLL0_PC2_NDIV_INT_MASK); 52862306a36Sopenharmony_ci tmp |= (bcm5357_bcm43236_ndiv[spuravoid]) << BCMA_CC_PMU1_PLL0_PC2_NDIV_INT_SHIFT; 52962306a36Sopenharmony_ci bcma_pmu_write32(cc, BCMA_CC_PMU_PLLCTL_DATA, tmp); 53062306a36Sopenharmony_ci 53162306a36Sopenharmony_ci tmp = BCMA_CC_PMU_CTL_PLL_UPD; 53262306a36Sopenharmony_ci break; 53362306a36Sopenharmony_ci 53462306a36Sopenharmony_ci case BCMA_CHIP_ID_BCM4331: 53562306a36Sopenharmony_ci case BCMA_CHIP_ID_BCM43431: 53662306a36Sopenharmony_ci if (spuravoid == 2) { 53762306a36Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0, 53862306a36Sopenharmony_ci 0x11500014); 53962306a36Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2, 54062306a36Sopenharmony_ci 0x0FC00a08); 54162306a36Sopenharmony_ci } else if (spuravoid == 1) { 54262306a36Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0, 54362306a36Sopenharmony_ci 0x11500014); 54462306a36Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2, 54562306a36Sopenharmony_ci 0x0F600a08); 54662306a36Sopenharmony_ci } else { 54762306a36Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0, 54862306a36Sopenharmony_ci 0x11100014); 54962306a36Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2, 55062306a36Sopenharmony_ci 0x03000a08); 55162306a36Sopenharmony_ci } 55262306a36Sopenharmony_ci tmp = BCMA_CC_PMU_CTL_PLL_UPD; 55362306a36Sopenharmony_ci break; 55462306a36Sopenharmony_ci 55562306a36Sopenharmony_ci case BCMA_CHIP_ID_BCM43224: 55662306a36Sopenharmony_ci case BCMA_CHIP_ID_BCM43225: 55762306a36Sopenharmony_ci case BCMA_CHIP_ID_BCM43421: 55862306a36Sopenharmony_ci if (spuravoid == 1) { 55962306a36Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0, 56062306a36Sopenharmony_ci 0x11500010); 56162306a36Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL1, 56262306a36Sopenharmony_ci 0x000C0C06); 56362306a36Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2, 56462306a36Sopenharmony_ci 0x0F600a08); 56562306a36Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL3, 56662306a36Sopenharmony_ci 0x00000000); 56762306a36Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL4, 56862306a36Sopenharmony_ci 0x2001E920); 56962306a36Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5, 57062306a36Sopenharmony_ci 0x88888815); 57162306a36Sopenharmony_ci } else { 57262306a36Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0, 57362306a36Sopenharmony_ci 0x11100010); 57462306a36Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL1, 57562306a36Sopenharmony_ci 0x000c0c06); 57662306a36Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2, 57762306a36Sopenharmony_ci 0x03000a08); 57862306a36Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL3, 57962306a36Sopenharmony_ci 0x00000000); 58062306a36Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL4, 58162306a36Sopenharmony_ci 0x200005c0); 58262306a36Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5, 58362306a36Sopenharmony_ci 0x88888815); 58462306a36Sopenharmony_ci } 58562306a36Sopenharmony_ci tmp = BCMA_CC_PMU_CTL_PLL_UPD; 58662306a36Sopenharmony_ci break; 58762306a36Sopenharmony_ci 58862306a36Sopenharmony_ci case BCMA_CHIP_ID_BCM4716: 58962306a36Sopenharmony_ci case BCMA_CHIP_ID_BCM4748: 59062306a36Sopenharmony_ci case BCMA_CHIP_ID_BCM47162: 59162306a36Sopenharmony_ci if (spuravoid == 1) { 59262306a36Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0, 59362306a36Sopenharmony_ci 0x11500060); 59462306a36Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL1, 59562306a36Sopenharmony_ci 0x080C0C06); 59662306a36Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2, 59762306a36Sopenharmony_ci 0x0F600000); 59862306a36Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL3, 59962306a36Sopenharmony_ci 0x00000000); 60062306a36Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL4, 60162306a36Sopenharmony_ci 0x2001E924); 60262306a36Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5, 60362306a36Sopenharmony_ci 0x88888815); 60462306a36Sopenharmony_ci } else { 60562306a36Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0, 60662306a36Sopenharmony_ci 0x11100060); 60762306a36Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL1, 60862306a36Sopenharmony_ci 0x080c0c06); 60962306a36Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2, 61062306a36Sopenharmony_ci 0x03000000); 61162306a36Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL3, 61262306a36Sopenharmony_ci 0x00000000); 61362306a36Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL4, 61462306a36Sopenharmony_ci 0x200005c0); 61562306a36Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5, 61662306a36Sopenharmony_ci 0x88888815); 61762306a36Sopenharmony_ci } 61862306a36Sopenharmony_ci 61962306a36Sopenharmony_ci tmp = BCMA_CC_PMU_CTL_PLL_UPD | BCMA_CC_PMU_CTL_NOILPONW; 62062306a36Sopenharmony_ci break; 62162306a36Sopenharmony_ci 62262306a36Sopenharmony_ci case BCMA_CHIP_ID_BCM43131: 62362306a36Sopenharmony_ci case BCMA_CHIP_ID_BCM43217: 62462306a36Sopenharmony_ci case BCMA_CHIP_ID_BCM43227: 62562306a36Sopenharmony_ci case BCMA_CHIP_ID_BCM43228: 62662306a36Sopenharmony_ci case BCMA_CHIP_ID_BCM43428: 62762306a36Sopenharmony_ci /* LCNXN */ 62862306a36Sopenharmony_ci /* 62962306a36Sopenharmony_ci * PLL Settings for spur avoidance on/off mode, 63062306a36Sopenharmony_ci * no on2 support for 43228A0 63162306a36Sopenharmony_ci */ 63262306a36Sopenharmony_ci if (spuravoid == 1) { 63362306a36Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0, 63462306a36Sopenharmony_ci 0x01100014); 63562306a36Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL1, 63662306a36Sopenharmony_ci 0x040C0C06); 63762306a36Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2, 63862306a36Sopenharmony_ci 0x03140A08); 63962306a36Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL3, 64062306a36Sopenharmony_ci 0x00333333); 64162306a36Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL4, 64262306a36Sopenharmony_ci 0x202C2820); 64362306a36Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5, 64462306a36Sopenharmony_ci 0x88888815); 64562306a36Sopenharmony_ci } else { 64662306a36Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0, 64762306a36Sopenharmony_ci 0x11100014); 64862306a36Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL1, 64962306a36Sopenharmony_ci 0x040c0c06); 65062306a36Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2, 65162306a36Sopenharmony_ci 0x03000a08); 65262306a36Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL3, 65362306a36Sopenharmony_ci 0x00000000); 65462306a36Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL4, 65562306a36Sopenharmony_ci 0x200005c0); 65662306a36Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5, 65762306a36Sopenharmony_ci 0x88888815); 65862306a36Sopenharmony_ci } 65962306a36Sopenharmony_ci tmp = BCMA_CC_PMU_CTL_PLL_UPD; 66062306a36Sopenharmony_ci break; 66162306a36Sopenharmony_ci default: 66262306a36Sopenharmony_ci bcma_err(bus, "Unknown spuravoidance settings for chip 0x%04X, not changing PLL\n", 66362306a36Sopenharmony_ci bus->chipinfo.id); 66462306a36Sopenharmony_ci break; 66562306a36Sopenharmony_ci } 66662306a36Sopenharmony_ci 66762306a36Sopenharmony_ci tmp |= bcma_pmu_read32(cc, BCMA_CC_PMU_CTL); 66862306a36Sopenharmony_ci bcma_pmu_write32(cc, BCMA_CC_PMU_CTL, tmp); 66962306a36Sopenharmony_ci} 67062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(bcma_pmu_spuravoid_pllupdate); 671