18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Broadcom specific AMBA 38c2ecf20Sopenharmony_ci * ChipCommon Power Management Unit driver 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright 2009, Michael Buesch <m@bues.ch> 68c2ecf20Sopenharmony_ci * Copyright 2007, 2011, Broadcom Corporation 78c2ecf20Sopenharmony_ci * Copyright 2011, 2012, Hauke Mehrtens <hauke@hauke-m.de> 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * Licensed under the GNU/GPL. See COPYING for details. 108c2ecf20Sopenharmony_ci */ 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#include "bcma_private.h" 138c2ecf20Sopenharmony_ci#include <linux/export.h> 148c2ecf20Sopenharmony_ci#include <linux/bcma/bcma.h> 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ciu32 bcma_chipco_pll_read(struct bcma_drv_cc *cc, u32 offset) 178c2ecf20Sopenharmony_ci{ 188c2ecf20Sopenharmony_ci bcma_pmu_write32(cc, BCMA_CC_PMU_PLLCTL_ADDR, offset); 198c2ecf20Sopenharmony_ci bcma_pmu_read32(cc, BCMA_CC_PMU_PLLCTL_ADDR); 208c2ecf20Sopenharmony_ci return bcma_pmu_read32(cc, BCMA_CC_PMU_PLLCTL_DATA); 218c2ecf20Sopenharmony_ci} 228c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(bcma_chipco_pll_read); 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_civoid bcma_chipco_pll_write(struct bcma_drv_cc *cc, u32 offset, u32 value) 258c2ecf20Sopenharmony_ci{ 268c2ecf20Sopenharmony_ci bcma_pmu_write32(cc, BCMA_CC_PMU_PLLCTL_ADDR, offset); 278c2ecf20Sopenharmony_ci bcma_pmu_read32(cc, BCMA_CC_PMU_PLLCTL_ADDR); 288c2ecf20Sopenharmony_ci bcma_pmu_write32(cc, BCMA_CC_PMU_PLLCTL_DATA, value); 298c2ecf20Sopenharmony_ci} 308c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(bcma_chipco_pll_write); 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_civoid bcma_chipco_pll_maskset(struct bcma_drv_cc *cc, u32 offset, u32 mask, 338c2ecf20Sopenharmony_ci u32 set) 348c2ecf20Sopenharmony_ci{ 358c2ecf20Sopenharmony_ci bcma_pmu_write32(cc, BCMA_CC_PMU_PLLCTL_ADDR, offset); 368c2ecf20Sopenharmony_ci bcma_pmu_read32(cc, BCMA_CC_PMU_PLLCTL_ADDR); 378c2ecf20Sopenharmony_ci bcma_pmu_maskset32(cc, BCMA_CC_PMU_PLLCTL_DATA, mask, set); 388c2ecf20Sopenharmony_ci} 398c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(bcma_chipco_pll_maskset); 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_civoid bcma_chipco_chipctl_maskset(struct bcma_drv_cc *cc, 428c2ecf20Sopenharmony_ci u32 offset, u32 mask, u32 set) 438c2ecf20Sopenharmony_ci{ 448c2ecf20Sopenharmony_ci bcma_pmu_write32(cc, BCMA_CC_PMU_CHIPCTL_ADDR, offset); 458c2ecf20Sopenharmony_ci bcma_pmu_read32(cc, BCMA_CC_PMU_CHIPCTL_ADDR); 468c2ecf20Sopenharmony_ci bcma_pmu_maskset32(cc, BCMA_CC_PMU_CHIPCTL_DATA, mask, set); 478c2ecf20Sopenharmony_ci} 488c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(bcma_chipco_chipctl_maskset); 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_civoid bcma_chipco_regctl_maskset(struct bcma_drv_cc *cc, u32 offset, u32 mask, 518c2ecf20Sopenharmony_ci u32 set) 528c2ecf20Sopenharmony_ci{ 538c2ecf20Sopenharmony_ci bcma_pmu_write32(cc, BCMA_CC_PMU_REGCTL_ADDR, offset); 548c2ecf20Sopenharmony_ci bcma_pmu_read32(cc, BCMA_CC_PMU_REGCTL_ADDR); 558c2ecf20Sopenharmony_ci bcma_pmu_maskset32(cc, BCMA_CC_PMU_REGCTL_DATA, mask, set); 568c2ecf20Sopenharmony_ci} 578c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(bcma_chipco_regctl_maskset); 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_cistatic u32 bcma_pmu_xtalfreq(struct bcma_drv_cc *cc) 608c2ecf20Sopenharmony_ci{ 618c2ecf20Sopenharmony_ci u32 ilp_ctl, alp_hz; 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci if (!(bcma_pmu_read32(cc, BCMA_CC_PMU_STAT) & 648c2ecf20Sopenharmony_ci BCMA_CC_PMU_STAT_EXT_LPO_AVAIL)) 658c2ecf20Sopenharmony_ci return 0; 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci bcma_pmu_write32(cc, BCMA_CC_PMU_XTAL_FREQ, 688c2ecf20Sopenharmony_ci BIT(BCMA_CC_PMU_XTAL_FREQ_MEASURE_SHIFT)); 698c2ecf20Sopenharmony_ci usleep_range(1000, 2000); 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci ilp_ctl = bcma_pmu_read32(cc, BCMA_CC_PMU_XTAL_FREQ); 728c2ecf20Sopenharmony_ci ilp_ctl &= BCMA_CC_PMU_XTAL_FREQ_ILPCTL_MASK; 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci bcma_pmu_write32(cc, BCMA_CC_PMU_XTAL_FREQ, 0); 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci alp_hz = ilp_ctl * 32768 / 4; 778c2ecf20Sopenharmony_ci return (alp_hz + 50000) / 100000 * 100; 788c2ecf20Sopenharmony_ci} 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_cistatic void bcma_pmu2_pll_init0(struct bcma_drv_cc *cc, u32 xtalfreq) 818c2ecf20Sopenharmony_ci{ 828c2ecf20Sopenharmony_ci struct bcma_bus *bus = cc->core->bus; 838c2ecf20Sopenharmony_ci u32 freq_tgt_target = 0, freq_tgt_current; 848c2ecf20Sopenharmony_ci u32 pll0, mask; 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci switch (bus->chipinfo.id) { 878c2ecf20Sopenharmony_ci case BCMA_CHIP_ID_BCM43142: 888c2ecf20Sopenharmony_ci /* pmu2_xtaltab0_adfll_485 */ 898c2ecf20Sopenharmony_ci switch (xtalfreq) { 908c2ecf20Sopenharmony_ci case 12000: 918c2ecf20Sopenharmony_ci freq_tgt_target = 0x50D52; 928c2ecf20Sopenharmony_ci break; 938c2ecf20Sopenharmony_ci case 20000: 948c2ecf20Sopenharmony_ci freq_tgt_target = 0x307FE; 958c2ecf20Sopenharmony_ci break; 968c2ecf20Sopenharmony_ci case 26000: 978c2ecf20Sopenharmony_ci freq_tgt_target = 0x254EA; 988c2ecf20Sopenharmony_ci break; 998c2ecf20Sopenharmony_ci case 37400: 1008c2ecf20Sopenharmony_ci freq_tgt_target = 0x19EF8; 1018c2ecf20Sopenharmony_ci break; 1028c2ecf20Sopenharmony_ci case 52000: 1038c2ecf20Sopenharmony_ci freq_tgt_target = 0x12A75; 1048c2ecf20Sopenharmony_ci break; 1058c2ecf20Sopenharmony_ci } 1068c2ecf20Sopenharmony_ci break; 1078c2ecf20Sopenharmony_ci } 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci if (!freq_tgt_target) { 1108c2ecf20Sopenharmony_ci bcma_err(bus, "Unknown TGT frequency for xtalfreq %d\n", 1118c2ecf20Sopenharmony_ci xtalfreq); 1128c2ecf20Sopenharmony_ci return; 1138c2ecf20Sopenharmony_ci } 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci pll0 = bcma_chipco_pll_read(cc, BCMA_CC_PMU15_PLL_PLLCTL0); 1168c2ecf20Sopenharmony_ci freq_tgt_current = (pll0 & BCMA_CC_PMU15_PLL_PC0_FREQTGT_MASK) >> 1178c2ecf20Sopenharmony_ci BCMA_CC_PMU15_PLL_PC0_FREQTGT_SHIFT; 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci if (freq_tgt_current == freq_tgt_target) { 1208c2ecf20Sopenharmony_ci bcma_debug(bus, "Target TGT frequency already set\n"); 1218c2ecf20Sopenharmony_ci return; 1228c2ecf20Sopenharmony_ci } 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci /* Turn off PLL */ 1258c2ecf20Sopenharmony_ci switch (bus->chipinfo.id) { 1268c2ecf20Sopenharmony_ci case BCMA_CHIP_ID_BCM43142: 1278c2ecf20Sopenharmony_ci mask = (u32)~(BCMA_RES_4314_HT_AVAIL | 1288c2ecf20Sopenharmony_ci BCMA_RES_4314_MACPHY_CLK_AVAIL); 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci bcma_pmu_mask32(cc, BCMA_CC_PMU_MINRES_MSK, mask); 1318c2ecf20Sopenharmony_ci bcma_pmu_mask32(cc, BCMA_CC_PMU_MAXRES_MSK, mask); 1328c2ecf20Sopenharmony_ci bcma_wait_value(cc->core, BCMA_CLKCTLST, 1338c2ecf20Sopenharmony_ci BCMA_CLKCTLST_HAVEHT, 0, 20000); 1348c2ecf20Sopenharmony_ci break; 1358c2ecf20Sopenharmony_ci } 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci pll0 &= ~BCMA_CC_PMU15_PLL_PC0_FREQTGT_MASK; 1388c2ecf20Sopenharmony_ci pll0 |= freq_tgt_target << BCMA_CC_PMU15_PLL_PC0_FREQTGT_SHIFT; 1398c2ecf20Sopenharmony_ci bcma_chipco_pll_write(cc, BCMA_CC_PMU15_PLL_PLLCTL0, pll0); 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci /* Flush */ 1428c2ecf20Sopenharmony_ci if (cc->pmu.rev >= 2) 1438c2ecf20Sopenharmony_ci bcma_pmu_set32(cc, BCMA_CC_PMU_CTL, BCMA_CC_PMU_CTL_PLL_UPD); 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci /* TODO: Do we need to update OTP? */ 1468c2ecf20Sopenharmony_ci} 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_cistatic void bcma_pmu_pll_init(struct bcma_drv_cc *cc) 1498c2ecf20Sopenharmony_ci{ 1508c2ecf20Sopenharmony_ci struct bcma_bus *bus = cc->core->bus; 1518c2ecf20Sopenharmony_ci u32 xtalfreq = bcma_pmu_xtalfreq(cc); 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci switch (bus->chipinfo.id) { 1548c2ecf20Sopenharmony_ci case BCMA_CHIP_ID_BCM43142: 1558c2ecf20Sopenharmony_ci if (xtalfreq == 0) 1568c2ecf20Sopenharmony_ci xtalfreq = 20000; 1578c2ecf20Sopenharmony_ci bcma_pmu2_pll_init0(cc, xtalfreq); 1588c2ecf20Sopenharmony_ci break; 1598c2ecf20Sopenharmony_ci } 1608c2ecf20Sopenharmony_ci} 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_cistatic void bcma_pmu_resources_init(struct bcma_drv_cc *cc) 1638c2ecf20Sopenharmony_ci{ 1648c2ecf20Sopenharmony_ci struct bcma_bus *bus = cc->core->bus; 1658c2ecf20Sopenharmony_ci u32 min_msk = 0, max_msk = 0; 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci switch (bus->chipinfo.id) { 1688c2ecf20Sopenharmony_ci case BCMA_CHIP_ID_BCM4313: 1698c2ecf20Sopenharmony_ci min_msk = 0x200D; 1708c2ecf20Sopenharmony_ci max_msk = 0xFFFF; 1718c2ecf20Sopenharmony_ci break; 1728c2ecf20Sopenharmony_ci case BCMA_CHIP_ID_BCM43142: 1738c2ecf20Sopenharmony_ci min_msk = BCMA_RES_4314_LPLDO_PU | 1748c2ecf20Sopenharmony_ci BCMA_RES_4314_PMU_SLEEP_DIS | 1758c2ecf20Sopenharmony_ci BCMA_RES_4314_PMU_BG_PU | 1768c2ecf20Sopenharmony_ci BCMA_RES_4314_CBUCK_LPOM_PU | 1778c2ecf20Sopenharmony_ci BCMA_RES_4314_CBUCK_PFM_PU | 1788c2ecf20Sopenharmony_ci BCMA_RES_4314_CLDO_PU | 1798c2ecf20Sopenharmony_ci BCMA_RES_4314_LPLDO2_LVM | 1808c2ecf20Sopenharmony_ci BCMA_RES_4314_WL_PMU_PU | 1818c2ecf20Sopenharmony_ci BCMA_RES_4314_LDO3P3_PU | 1828c2ecf20Sopenharmony_ci BCMA_RES_4314_OTP_PU | 1838c2ecf20Sopenharmony_ci BCMA_RES_4314_WL_PWRSW_PU | 1848c2ecf20Sopenharmony_ci BCMA_RES_4314_LQ_AVAIL | 1858c2ecf20Sopenharmony_ci BCMA_RES_4314_LOGIC_RET | 1868c2ecf20Sopenharmony_ci BCMA_RES_4314_MEM_SLEEP | 1878c2ecf20Sopenharmony_ci BCMA_RES_4314_MACPHY_RET | 1888c2ecf20Sopenharmony_ci BCMA_RES_4314_WL_CORE_READY; 1898c2ecf20Sopenharmony_ci max_msk = 0x3FFFFFFF; 1908c2ecf20Sopenharmony_ci break; 1918c2ecf20Sopenharmony_ci default: 1928c2ecf20Sopenharmony_ci bcma_debug(bus, "PMU resource config unknown or not needed for device 0x%04X\n", 1938c2ecf20Sopenharmony_ci bus->chipinfo.id); 1948c2ecf20Sopenharmony_ci } 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_ci /* Set the resource masks. */ 1978c2ecf20Sopenharmony_ci if (min_msk) 1988c2ecf20Sopenharmony_ci bcma_pmu_write32(cc, BCMA_CC_PMU_MINRES_MSK, min_msk); 1998c2ecf20Sopenharmony_ci if (max_msk) 2008c2ecf20Sopenharmony_ci bcma_pmu_write32(cc, BCMA_CC_PMU_MAXRES_MSK, max_msk); 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_ci /* 2038c2ecf20Sopenharmony_ci * Add some delay; allow resources to come up and settle. 2048c2ecf20Sopenharmony_ci * Delay is required for SoC (early init). 2058c2ecf20Sopenharmony_ci */ 2068c2ecf20Sopenharmony_ci usleep_range(2000, 2500); 2078c2ecf20Sopenharmony_ci} 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_ci/* Disable to allow reading SPROM. Don't know the adventages of enabling it. */ 2108c2ecf20Sopenharmony_civoid bcma_chipco_bcm4331_ext_pa_lines_ctl(struct bcma_drv_cc *cc, bool enable) 2118c2ecf20Sopenharmony_ci{ 2128c2ecf20Sopenharmony_ci struct bcma_bus *bus = cc->core->bus; 2138c2ecf20Sopenharmony_ci u32 val; 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_ci val = bcma_cc_read32(cc, BCMA_CC_CHIPCTL); 2168c2ecf20Sopenharmony_ci if (enable) { 2178c2ecf20Sopenharmony_ci val |= BCMA_CHIPCTL_4331_EXTPA_EN; 2188c2ecf20Sopenharmony_ci if (bus->chipinfo.pkg == 9 || bus->chipinfo.pkg == 11) 2198c2ecf20Sopenharmony_ci val |= BCMA_CHIPCTL_4331_EXTPA_ON_GPIO2_5; 2208c2ecf20Sopenharmony_ci else if (bus->chipinfo.rev > 0) 2218c2ecf20Sopenharmony_ci val |= BCMA_CHIPCTL_4331_EXTPA_EN2; 2228c2ecf20Sopenharmony_ci } else { 2238c2ecf20Sopenharmony_ci val &= ~BCMA_CHIPCTL_4331_EXTPA_EN; 2248c2ecf20Sopenharmony_ci val &= ~BCMA_CHIPCTL_4331_EXTPA_EN2; 2258c2ecf20Sopenharmony_ci val &= ~BCMA_CHIPCTL_4331_EXTPA_ON_GPIO2_5; 2268c2ecf20Sopenharmony_ci } 2278c2ecf20Sopenharmony_ci bcma_cc_write32(cc, BCMA_CC_CHIPCTL, val); 2288c2ecf20Sopenharmony_ci} 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_cistatic void bcma_pmu_workarounds(struct bcma_drv_cc *cc) 2318c2ecf20Sopenharmony_ci{ 2328c2ecf20Sopenharmony_ci struct bcma_bus *bus = cc->core->bus; 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_ci switch (bus->chipinfo.id) { 2358c2ecf20Sopenharmony_ci case BCMA_CHIP_ID_BCM4313: 2368c2ecf20Sopenharmony_ci /* 2378c2ecf20Sopenharmony_ci * enable 12 mA drive strenth for 4313 and set chipControl 2388c2ecf20Sopenharmony_ci * register bit 1 2398c2ecf20Sopenharmony_ci */ 2408c2ecf20Sopenharmony_ci bcma_chipco_chipctl_maskset(cc, 0, 2418c2ecf20Sopenharmony_ci ~BCMA_CCTRL_4313_12MA_LED_DRIVE, 2428c2ecf20Sopenharmony_ci BCMA_CCTRL_4313_12MA_LED_DRIVE); 2438c2ecf20Sopenharmony_ci break; 2448c2ecf20Sopenharmony_ci case BCMA_CHIP_ID_BCM4331: 2458c2ecf20Sopenharmony_ci case BCMA_CHIP_ID_BCM43431: 2468c2ecf20Sopenharmony_ci /* Ext PA lines must be enabled for tx on BCM4331 */ 2478c2ecf20Sopenharmony_ci bcma_chipco_bcm4331_ext_pa_lines_ctl(cc, true); 2488c2ecf20Sopenharmony_ci break; 2498c2ecf20Sopenharmony_ci case BCMA_CHIP_ID_BCM43224: 2508c2ecf20Sopenharmony_ci case BCMA_CHIP_ID_BCM43421: 2518c2ecf20Sopenharmony_ci /* 2528c2ecf20Sopenharmony_ci * enable 12 mA drive strenth for 43224 and set chipControl 2538c2ecf20Sopenharmony_ci * register bit 15 2548c2ecf20Sopenharmony_ci */ 2558c2ecf20Sopenharmony_ci if (bus->chipinfo.rev == 0) { 2568c2ecf20Sopenharmony_ci bcma_cc_maskset32(cc, BCMA_CC_CHIPCTL, 2578c2ecf20Sopenharmony_ci ~BCMA_CCTRL_43224_GPIO_TOGGLE, 2588c2ecf20Sopenharmony_ci BCMA_CCTRL_43224_GPIO_TOGGLE); 2598c2ecf20Sopenharmony_ci bcma_chipco_chipctl_maskset(cc, 0, 2608c2ecf20Sopenharmony_ci ~BCMA_CCTRL_43224A0_12MA_LED_DRIVE, 2618c2ecf20Sopenharmony_ci BCMA_CCTRL_43224A0_12MA_LED_DRIVE); 2628c2ecf20Sopenharmony_ci } else { 2638c2ecf20Sopenharmony_ci bcma_chipco_chipctl_maskset(cc, 0, 2648c2ecf20Sopenharmony_ci ~BCMA_CCTRL_43224B0_12MA_LED_DRIVE, 2658c2ecf20Sopenharmony_ci BCMA_CCTRL_43224B0_12MA_LED_DRIVE); 2668c2ecf20Sopenharmony_ci } 2678c2ecf20Sopenharmony_ci break; 2688c2ecf20Sopenharmony_ci default: 2698c2ecf20Sopenharmony_ci bcma_debug(bus, "Workarounds unknown or not needed for device 0x%04X\n", 2708c2ecf20Sopenharmony_ci bus->chipinfo.id); 2718c2ecf20Sopenharmony_ci } 2728c2ecf20Sopenharmony_ci} 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_civoid bcma_pmu_early_init(struct bcma_drv_cc *cc) 2758c2ecf20Sopenharmony_ci{ 2768c2ecf20Sopenharmony_ci struct bcma_bus *bus = cc->core->bus; 2778c2ecf20Sopenharmony_ci u32 pmucap; 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_ci if (cc->core->id.rev >= 35 && 2808c2ecf20Sopenharmony_ci cc->capabilities_ext & BCMA_CC_CAP_EXT_AOB_PRESENT) { 2818c2ecf20Sopenharmony_ci cc->pmu.core = bcma_find_core(bus, BCMA_CORE_PMU); 2828c2ecf20Sopenharmony_ci if (!cc->pmu.core) 2838c2ecf20Sopenharmony_ci bcma_warn(bus, "Couldn't find expected PMU core"); 2848c2ecf20Sopenharmony_ci } 2858c2ecf20Sopenharmony_ci if (!cc->pmu.core) 2868c2ecf20Sopenharmony_ci cc->pmu.core = cc->core; 2878c2ecf20Sopenharmony_ci 2888c2ecf20Sopenharmony_ci pmucap = bcma_pmu_read32(cc, BCMA_CC_PMU_CAP); 2898c2ecf20Sopenharmony_ci cc->pmu.rev = (pmucap & BCMA_CC_PMU_CAP_REVISION); 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_ci bcma_debug(bus, "Found rev %u PMU (capabilities 0x%08X)\n", cc->pmu.rev, 2928c2ecf20Sopenharmony_ci pmucap); 2938c2ecf20Sopenharmony_ci} 2948c2ecf20Sopenharmony_ci 2958c2ecf20Sopenharmony_civoid bcma_pmu_init(struct bcma_drv_cc *cc) 2968c2ecf20Sopenharmony_ci{ 2978c2ecf20Sopenharmony_ci if (cc->pmu.rev == 1) 2988c2ecf20Sopenharmony_ci bcma_pmu_mask32(cc, BCMA_CC_PMU_CTL, 2998c2ecf20Sopenharmony_ci ~BCMA_CC_PMU_CTL_NOILPONW); 3008c2ecf20Sopenharmony_ci else 3018c2ecf20Sopenharmony_ci bcma_pmu_set32(cc, BCMA_CC_PMU_CTL, 3028c2ecf20Sopenharmony_ci BCMA_CC_PMU_CTL_NOILPONW); 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_ci bcma_pmu_pll_init(cc); 3058c2ecf20Sopenharmony_ci bcma_pmu_resources_init(cc); 3068c2ecf20Sopenharmony_ci bcma_pmu_workarounds(cc); 3078c2ecf20Sopenharmony_ci} 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_ciu32 bcma_pmu_get_alp_clock(struct bcma_drv_cc *cc) 3108c2ecf20Sopenharmony_ci{ 3118c2ecf20Sopenharmony_ci struct bcma_bus *bus = cc->core->bus; 3128c2ecf20Sopenharmony_ci 3138c2ecf20Sopenharmony_ci switch (bus->chipinfo.id) { 3148c2ecf20Sopenharmony_ci case BCMA_CHIP_ID_BCM4313: 3158c2ecf20Sopenharmony_ci case BCMA_CHIP_ID_BCM43224: 3168c2ecf20Sopenharmony_ci case BCMA_CHIP_ID_BCM43225: 3178c2ecf20Sopenharmony_ci case BCMA_CHIP_ID_BCM43227: 3188c2ecf20Sopenharmony_ci case BCMA_CHIP_ID_BCM43228: 3198c2ecf20Sopenharmony_ci case BCMA_CHIP_ID_BCM4331: 3208c2ecf20Sopenharmony_ci case BCMA_CHIP_ID_BCM43421: 3218c2ecf20Sopenharmony_ci case BCMA_CHIP_ID_BCM43428: 3228c2ecf20Sopenharmony_ci case BCMA_CHIP_ID_BCM43431: 3238c2ecf20Sopenharmony_ci case BCMA_CHIP_ID_BCM4716: 3248c2ecf20Sopenharmony_ci case BCMA_CHIP_ID_BCM47162: 3258c2ecf20Sopenharmony_ci case BCMA_CHIP_ID_BCM4748: 3268c2ecf20Sopenharmony_ci case BCMA_CHIP_ID_BCM4749: 3278c2ecf20Sopenharmony_ci case BCMA_CHIP_ID_BCM5357: 3288c2ecf20Sopenharmony_ci case BCMA_CHIP_ID_BCM53572: 3298c2ecf20Sopenharmony_ci case BCMA_CHIP_ID_BCM6362: 3308c2ecf20Sopenharmony_ci /* always 20Mhz */ 3318c2ecf20Sopenharmony_ci return 20000 * 1000; 3328c2ecf20Sopenharmony_ci case BCMA_CHIP_ID_BCM4706: 3338c2ecf20Sopenharmony_ci case BCMA_CHIP_ID_BCM5356: 3348c2ecf20Sopenharmony_ci /* always 25Mhz */ 3358c2ecf20Sopenharmony_ci return 25000 * 1000; 3368c2ecf20Sopenharmony_ci case BCMA_CHIP_ID_BCM43460: 3378c2ecf20Sopenharmony_ci case BCMA_CHIP_ID_BCM4352: 3388c2ecf20Sopenharmony_ci case BCMA_CHIP_ID_BCM4360: 3398c2ecf20Sopenharmony_ci if (cc->status & BCMA_CC_CHIPST_4360_XTAL_40MZ) 3408c2ecf20Sopenharmony_ci return 40000 * 1000; 3418c2ecf20Sopenharmony_ci else 3428c2ecf20Sopenharmony_ci return 20000 * 1000; 3438c2ecf20Sopenharmony_ci default: 3448c2ecf20Sopenharmony_ci bcma_warn(bus, "No ALP clock specified for %04X device, pmu rev. %d, using default %d Hz\n", 3458c2ecf20Sopenharmony_ci bus->chipinfo.id, cc->pmu.rev, BCMA_CC_PMU_ALP_CLOCK); 3468c2ecf20Sopenharmony_ci } 3478c2ecf20Sopenharmony_ci return BCMA_CC_PMU_ALP_CLOCK; 3488c2ecf20Sopenharmony_ci} 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_ci/* Find the output of the "m" pll divider given pll controls that start with 3518c2ecf20Sopenharmony_ci * pllreg "pll0" i.e. 12 for main 6 for phy, 0 for misc. 3528c2ecf20Sopenharmony_ci */ 3538c2ecf20Sopenharmony_cistatic u32 bcma_pmu_pll_clock(struct bcma_drv_cc *cc, u32 pll0, u32 m) 3548c2ecf20Sopenharmony_ci{ 3558c2ecf20Sopenharmony_ci u32 tmp, div, ndiv, p1, p2, fc; 3568c2ecf20Sopenharmony_ci struct bcma_bus *bus = cc->core->bus; 3578c2ecf20Sopenharmony_ci 3588c2ecf20Sopenharmony_ci BUG_ON((pll0 & 3) || (pll0 > BCMA_CC_PMU4716_MAINPLL_PLL0)); 3598c2ecf20Sopenharmony_ci 3608c2ecf20Sopenharmony_ci BUG_ON(!m || m > 4); 3618c2ecf20Sopenharmony_ci 3628c2ecf20Sopenharmony_ci if (bus->chipinfo.id == BCMA_CHIP_ID_BCM5357 || 3638c2ecf20Sopenharmony_ci bus->chipinfo.id == BCMA_CHIP_ID_BCM4749) { 3648c2ecf20Sopenharmony_ci /* Detect failure in clock setting */ 3658c2ecf20Sopenharmony_ci tmp = bcma_cc_read32(cc, BCMA_CC_CHIPSTAT); 3668c2ecf20Sopenharmony_ci if (tmp & 0x40000) 3678c2ecf20Sopenharmony_ci return 133 * 1000000; 3688c2ecf20Sopenharmony_ci } 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_ci tmp = bcma_chipco_pll_read(cc, pll0 + BCMA_CC_PPL_P1P2_OFF); 3718c2ecf20Sopenharmony_ci p1 = (tmp & BCMA_CC_PPL_P1_MASK) >> BCMA_CC_PPL_P1_SHIFT; 3728c2ecf20Sopenharmony_ci p2 = (tmp & BCMA_CC_PPL_P2_MASK) >> BCMA_CC_PPL_P2_SHIFT; 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_ci tmp = bcma_chipco_pll_read(cc, pll0 + BCMA_CC_PPL_M14_OFF); 3758c2ecf20Sopenharmony_ci div = (tmp >> ((m - 1) * BCMA_CC_PPL_MDIV_WIDTH)) & 3768c2ecf20Sopenharmony_ci BCMA_CC_PPL_MDIV_MASK; 3778c2ecf20Sopenharmony_ci 3788c2ecf20Sopenharmony_ci tmp = bcma_chipco_pll_read(cc, pll0 + BCMA_CC_PPL_NM5_OFF); 3798c2ecf20Sopenharmony_ci ndiv = (tmp & BCMA_CC_PPL_NDIV_MASK) >> BCMA_CC_PPL_NDIV_SHIFT; 3808c2ecf20Sopenharmony_ci 3818c2ecf20Sopenharmony_ci /* Do calculation in Mhz */ 3828c2ecf20Sopenharmony_ci fc = bcma_pmu_get_alp_clock(cc) / 1000000; 3838c2ecf20Sopenharmony_ci fc = (p1 * ndiv * fc) / p2; 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_ci /* Return clock in Hertz */ 3868c2ecf20Sopenharmony_ci return (fc / div) * 1000000; 3878c2ecf20Sopenharmony_ci} 3888c2ecf20Sopenharmony_ci 3898c2ecf20Sopenharmony_cistatic u32 bcma_pmu_pll_clock_bcm4706(struct bcma_drv_cc *cc, u32 pll0, u32 m) 3908c2ecf20Sopenharmony_ci{ 3918c2ecf20Sopenharmony_ci u32 tmp, ndiv, p1div, p2div; 3928c2ecf20Sopenharmony_ci u32 clock; 3938c2ecf20Sopenharmony_ci 3948c2ecf20Sopenharmony_ci BUG_ON(!m || m > 4); 3958c2ecf20Sopenharmony_ci 3968c2ecf20Sopenharmony_ci /* Get N, P1 and P2 dividers to determine CPU clock */ 3978c2ecf20Sopenharmony_ci tmp = bcma_chipco_pll_read(cc, pll0 + BCMA_CC_PMU6_4706_PROCPLL_OFF); 3988c2ecf20Sopenharmony_ci ndiv = (tmp & BCMA_CC_PMU6_4706_PROC_NDIV_INT_MASK) 3998c2ecf20Sopenharmony_ci >> BCMA_CC_PMU6_4706_PROC_NDIV_INT_SHIFT; 4008c2ecf20Sopenharmony_ci p1div = (tmp & BCMA_CC_PMU6_4706_PROC_P1DIV_MASK) 4018c2ecf20Sopenharmony_ci >> BCMA_CC_PMU6_4706_PROC_P1DIV_SHIFT; 4028c2ecf20Sopenharmony_ci p2div = (tmp & BCMA_CC_PMU6_4706_PROC_P2DIV_MASK) 4038c2ecf20Sopenharmony_ci >> BCMA_CC_PMU6_4706_PROC_P2DIV_SHIFT; 4048c2ecf20Sopenharmony_ci 4058c2ecf20Sopenharmony_ci tmp = bcma_cc_read32(cc, BCMA_CC_CHIPSTAT); 4068c2ecf20Sopenharmony_ci if (tmp & BCMA_CC_CHIPST_4706_PKG_OPTION) 4078c2ecf20Sopenharmony_ci /* Low cost bonding: Fixed reference clock 25MHz and m = 4 */ 4088c2ecf20Sopenharmony_ci clock = (25000000 / 4) * ndiv * p2div / p1div; 4098c2ecf20Sopenharmony_ci else 4108c2ecf20Sopenharmony_ci /* Fixed reference clock 25MHz and m = 2 */ 4118c2ecf20Sopenharmony_ci clock = (25000000 / 2) * ndiv * p2div / p1div; 4128c2ecf20Sopenharmony_ci 4138c2ecf20Sopenharmony_ci if (m == BCMA_CC_PMU5_MAINPLL_SSB) 4148c2ecf20Sopenharmony_ci clock = clock / 4; 4158c2ecf20Sopenharmony_ci 4168c2ecf20Sopenharmony_ci return clock; 4178c2ecf20Sopenharmony_ci} 4188c2ecf20Sopenharmony_ci 4198c2ecf20Sopenharmony_ci/* query bus clock frequency for PMU-enabled chipcommon */ 4208c2ecf20Sopenharmony_ciu32 bcma_pmu_get_bus_clock(struct bcma_drv_cc *cc) 4218c2ecf20Sopenharmony_ci{ 4228c2ecf20Sopenharmony_ci struct bcma_bus *bus = cc->core->bus; 4238c2ecf20Sopenharmony_ci 4248c2ecf20Sopenharmony_ci switch (bus->chipinfo.id) { 4258c2ecf20Sopenharmony_ci case BCMA_CHIP_ID_BCM4716: 4268c2ecf20Sopenharmony_ci case BCMA_CHIP_ID_BCM4748: 4278c2ecf20Sopenharmony_ci case BCMA_CHIP_ID_BCM47162: 4288c2ecf20Sopenharmony_ci return bcma_pmu_pll_clock(cc, BCMA_CC_PMU4716_MAINPLL_PLL0, 4298c2ecf20Sopenharmony_ci BCMA_CC_PMU5_MAINPLL_SSB); 4308c2ecf20Sopenharmony_ci case BCMA_CHIP_ID_BCM5356: 4318c2ecf20Sopenharmony_ci return bcma_pmu_pll_clock(cc, BCMA_CC_PMU5356_MAINPLL_PLL0, 4328c2ecf20Sopenharmony_ci BCMA_CC_PMU5_MAINPLL_SSB); 4338c2ecf20Sopenharmony_ci case BCMA_CHIP_ID_BCM5357: 4348c2ecf20Sopenharmony_ci case BCMA_CHIP_ID_BCM4749: 4358c2ecf20Sopenharmony_ci return bcma_pmu_pll_clock(cc, BCMA_CC_PMU5357_MAINPLL_PLL0, 4368c2ecf20Sopenharmony_ci BCMA_CC_PMU5_MAINPLL_SSB); 4378c2ecf20Sopenharmony_ci case BCMA_CHIP_ID_BCM4706: 4388c2ecf20Sopenharmony_ci return bcma_pmu_pll_clock_bcm4706(cc, 4398c2ecf20Sopenharmony_ci BCMA_CC_PMU4706_MAINPLL_PLL0, 4408c2ecf20Sopenharmony_ci BCMA_CC_PMU5_MAINPLL_SSB); 4418c2ecf20Sopenharmony_ci case BCMA_CHIP_ID_BCM53572: 4428c2ecf20Sopenharmony_ci return 75000000; 4438c2ecf20Sopenharmony_ci default: 4448c2ecf20Sopenharmony_ci bcma_warn(bus, "No bus clock specified for %04X device, pmu rev. %d, using default %d Hz\n", 4458c2ecf20Sopenharmony_ci bus->chipinfo.id, cc->pmu.rev, BCMA_CC_PMU_HT_CLOCK); 4468c2ecf20Sopenharmony_ci } 4478c2ecf20Sopenharmony_ci return BCMA_CC_PMU_HT_CLOCK; 4488c2ecf20Sopenharmony_ci} 4498c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(bcma_pmu_get_bus_clock); 4508c2ecf20Sopenharmony_ci 4518c2ecf20Sopenharmony_ci/* query cpu clock frequency for PMU-enabled chipcommon */ 4528c2ecf20Sopenharmony_ciu32 bcma_pmu_get_cpu_clock(struct bcma_drv_cc *cc) 4538c2ecf20Sopenharmony_ci{ 4548c2ecf20Sopenharmony_ci struct bcma_bus *bus = cc->core->bus; 4558c2ecf20Sopenharmony_ci 4568c2ecf20Sopenharmony_ci if (bus->chipinfo.id == BCMA_CHIP_ID_BCM53572) 4578c2ecf20Sopenharmony_ci return 300000000; 4588c2ecf20Sopenharmony_ci 4598c2ecf20Sopenharmony_ci /* New PMUs can have different clock for bus and CPU */ 4608c2ecf20Sopenharmony_ci if (cc->pmu.rev >= 5) { 4618c2ecf20Sopenharmony_ci u32 pll; 4628c2ecf20Sopenharmony_ci switch (bus->chipinfo.id) { 4638c2ecf20Sopenharmony_ci case BCMA_CHIP_ID_BCM4706: 4648c2ecf20Sopenharmony_ci return bcma_pmu_pll_clock_bcm4706(cc, 4658c2ecf20Sopenharmony_ci BCMA_CC_PMU4706_MAINPLL_PLL0, 4668c2ecf20Sopenharmony_ci BCMA_CC_PMU5_MAINPLL_CPU); 4678c2ecf20Sopenharmony_ci case BCMA_CHIP_ID_BCM5356: 4688c2ecf20Sopenharmony_ci pll = BCMA_CC_PMU5356_MAINPLL_PLL0; 4698c2ecf20Sopenharmony_ci break; 4708c2ecf20Sopenharmony_ci case BCMA_CHIP_ID_BCM5357: 4718c2ecf20Sopenharmony_ci case BCMA_CHIP_ID_BCM4749: 4728c2ecf20Sopenharmony_ci pll = BCMA_CC_PMU5357_MAINPLL_PLL0; 4738c2ecf20Sopenharmony_ci break; 4748c2ecf20Sopenharmony_ci default: 4758c2ecf20Sopenharmony_ci pll = BCMA_CC_PMU4716_MAINPLL_PLL0; 4768c2ecf20Sopenharmony_ci break; 4778c2ecf20Sopenharmony_ci } 4788c2ecf20Sopenharmony_ci 4798c2ecf20Sopenharmony_ci return bcma_pmu_pll_clock(cc, pll, BCMA_CC_PMU5_MAINPLL_CPU); 4808c2ecf20Sopenharmony_ci } 4818c2ecf20Sopenharmony_ci 4828c2ecf20Sopenharmony_ci /* On old PMUs CPU has the same clock as the bus */ 4838c2ecf20Sopenharmony_ci return bcma_pmu_get_bus_clock(cc); 4848c2ecf20Sopenharmony_ci} 4858c2ecf20Sopenharmony_ci 4868c2ecf20Sopenharmony_cistatic void bcma_pmu_spuravoid_pll_write(struct bcma_drv_cc *cc, u32 offset, 4878c2ecf20Sopenharmony_ci u32 value) 4888c2ecf20Sopenharmony_ci{ 4898c2ecf20Sopenharmony_ci bcma_pmu_write32(cc, BCMA_CC_PMU_PLLCTL_ADDR, offset); 4908c2ecf20Sopenharmony_ci bcma_pmu_write32(cc, BCMA_CC_PMU_PLLCTL_DATA, value); 4918c2ecf20Sopenharmony_ci} 4928c2ecf20Sopenharmony_ci 4938c2ecf20Sopenharmony_civoid bcma_pmu_spuravoid_pllupdate(struct bcma_drv_cc *cc, int spuravoid) 4948c2ecf20Sopenharmony_ci{ 4958c2ecf20Sopenharmony_ci u32 tmp = 0; 4968c2ecf20Sopenharmony_ci u8 phypll_offset = 0; 4978c2ecf20Sopenharmony_ci u8 bcm5357_bcm43236_p1div[] = {0x1, 0x5, 0x5}; 4988c2ecf20Sopenharmony_ci u8 bcm5357_bcm43236_ndiv[] = {0x30, 0xf6, 0xfc}; 4998c2ecf20Sopenharmony_ci struct bcma_bus *bus = cc->core->bus; 5008c2ecf20Sopenharmony_ci 5018c2ecf20Sopenharmony_ci switch (bus->chipinfo.id) { 5028c2ecf20Sopenharmony_ci case BCMA_CHIP_ID_BCM5357: 5038c2ecf20Sopenharmony_ci case BCMA_CHIP_ID_BCM4749: 5048c2ecf20Sopenharmony_ci case BCMA_CHIP_ID_BCM53572: 5058c2ecf20Sopenharmony_ci /* 5357[ab]0, 43236[ab]0, and 6362b0 */ 5068c2ecf20Sopenharmony_ci 5078c2ecf20Sopenharmony_ci /* 5088c2ecf20Sopenharmony_ci * BCM5357 needs to touch PLL1_PLLCTL[02], 5098c2ecf20Sopenharmony_ci * so offset PLL0_PLLCTL[02] by 6 5108c2ecf20Sopenharmony_ci */ 5118c2ecf20Sopenharmony_ci phypll_offset = (bus->chipinfo.id == BCMA_CHIP_ID_BCM5357 || 5128c2ecf20Sopenharmony_ci bus->chipinfo.id == BCMA_CHIP_ID_BCM4749 || 5138c2ecf20Sopenharmony_ci bus->chipinfo.id == BCMA_CHIP_ID_BCM53572) ? 6 : 0; 5148c2ecf20Sopenharmony_ci 5158c2ecf20Sopenharmony_ci /* RMW only the P1 divider */ 5168c2ecf20Sopenharmony_ci bcma_pmu_write32(cc, BCMA_CC_PMU_PLLCTL_ADDR, 5178c2ecf20Sopenharmony_ci BCMA_CC_PMU_PLL_CTL0 + phypll_offset); 5188c2ecf20Sopenharmony_ci tmp = bcma_pmu_read32(cc, BCMA_CC_PMU_PLLCTL_DATA); 5198c2ecf20Sopenharmony_ci tmp &= (~(BCMA_CC_PMU1_PLL0_PC0_P1DIV_MASK)); 5208c2ecf20Sopenharmony_ci tmp |= (bcm5357_bcm43236_p1div[spuravoid] << BCMA_CC_PMU1_PLL0_PC0_P1DIV_SHIFT); 5218c2ecf20Sopenharmony_ci bcma_pmu_write32(cc, BCMA_CC_PMU_PLLCTL_DATA, tmp); 5228c2ecf20Sopenharmony_ci 5238c2ecf20Sopenharmony_ci /* RMW only the int feedback divider */ 5248c2ecf20Sopenharmony_ci bcma_pmu_write32(cc, BCMA_CC_PMU_PLLCTL_ADDR, 5258c2ecf20Sopenharmony_ci BCMA_CC_PMU_PLL_CTL2 + phypll_offset); 5268c2ecf20Sopenharmony_ci tmp = bcma_pmu_read32(cc, BCMA_CC_PMU_PLLCTL_DATA); 5278c2ecf20Sopenharmony_ci tmp &= ~(BCMA_CC_PMU1_PLL0_PC2_NDIV_INT_MASK); 5288c2ecf20Sopenharmony_ci tmp |= (bcm5357_bcm43236_ndiv[spuravoid]) << BCMA_CC_PMU1_PLL0_PC2_NDIV_INT_SHIFT; 5298c2ecf20Sopenharmony_ci bcma_pmu_write32(cc, BCMA_CC_PMU_PLLCTL_DATA, tmp); 5308c2ecf20Sopenharmony_ci 5318c2ecf20Sopenharmony_ci tmp = BCMA_CC_PMU_CTL_PLL_UPD; 5328c2ecf20Sopenharmony_ci break; 5338c2ecf20Sopenharmony_ci 5348c2ecf20Sopenharmony_ci case BCMA_CHIP_ID_BCM4331: 5358c2ecf20Sopenharmony_ci case BCMA_CHIP_ID_BCM43431: 5368c2ecf20Sopenharmony_ci if (spuravoid == 2) { 5378c2ecf20Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0, 5388c2ecf20Sopenharmony_ci 0x11500014); 5398c2ecf20Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2, 5408c2ecf20Sopenharmony_ci 0x0FC00a08); 5418c2ecf20Sopenharmony_ci } else if (spuravoid == 1) { 5428c2ecf20Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0, 5438c2ecf20Sopenharmony_ci 0x11500014); 5448c2ecf20Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2, 5458c2ecf20Sopenharmony_ci 0x0F600a08); 5468c2ecf20Sopenharmony_ci } else { 5478c2ecf20Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0, 5488c2ecf20Sopenharmony_ci 0x11100014); 5498c2ecf20Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2, 5508c2ecf20Sopenharmony_ci 0x03000a08); 5518c2ecf20Sopenharmony_ci } 5528c2ecf20Sopenharmony_ci tmp = BCMA_CC_PMU_CTL_PLL_UPD; 5538c2ecf20Sopenharmony_ci break; 5548c2ecf20Sopenharmony_ci 5558c2ecf20Sopenharmony_ci case BCMA_CHIP_ID_BCM43224: 5568c2ecf20Sopenharmony_ci case BCMA_CHIP_ID_BCM43225: 5578c2ecf20Sopenharmony_ci case BCMA_CHIP_ID_BCM43421: 5588c2ecf20Sopenharmony_ci if (spuravoid == 1) { 5598c2ecf20Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0, 5608c2ecf20Sopenharmony_ci 0x11500010); 5618c2ecf20Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL1, 5628c2ecf20Sopenharmony_ci 0x000C0C06); 5638c2ecf20Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2, 5648c2ecf20Sopenharmony_ci 0x0F600a08); 5658c2ecf20Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL3, 5668c2ecf20Sopenharmony_ci 0x00000000); 5678c2ecf20Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL4, 5688c2ecf20Sopenharmony_ci 0x2001E920); 5698c2ecf20Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5, 5708c2ecf20Sopenharmony_ci 0x88888815); 5718c2ecf20Sopenharmony_ci } else { 5728c2ecf20Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0, 5738c2ecf20Sopenharmony_ci 0x11100010); 5748c2ecf20Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL1, 5758c2ecf20Sopenharmony_ci 0x000c0c06); 5768c2ecf20Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2, 5778c2ecf20Sopenharmony_ci 0x03000a08); 5788c2ecf20Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL3, 5798c2ecf20Sopenharmony_ci 0x00000000); 5808c2ecf20Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL4, 5818c2ecf20Sopenharmony_ci 0x200005c0); 5828c2ecf20Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5, 5838c2ecf20Sopenharmony_ci 0x88888815); 5848c2ecf20Sopenharmony_ci } 5858c2ecf20Sopenharmony_ci tmp = BCMA_CC_PMU_CTL_PLL_UPD; 5868c2ecf20Sopenharmony_ci break; 5878c2ecf20Sopenharmony_ci 5888c2ecf20Sopenharmony_ci case BCMA_CHIP_ID_BCM4716: 5898c2ecf20Sopenharmony_ci case BCMA_CHIP_ID_BCM4748: 5908c2ecf20Sopenharmony_ci case BCMA_CHIP_ID_BCM47162: 5918c2ecf20Sopenharmony_ci if (spuravoid == 1) { 5928c2ecf20Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0, 5938c2ecf20Sopenharmony_ci 0x11500060); 5948c2ecf20Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL1, 5958c2ecf20Sopenharmony_ci 0x080C0C06); 5968c2ecf20Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2, 5978c2ecf20Sopenharmony_ci 0x0F600000); 5988c2ecf20Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL3, 5998c2ecf20Sopenharmony_ci 0x00000000); 6008c2ecf20Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL4, 6018c2ecf20Sopenharmony_ci 0x2001E924); 6028c2ecf20Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5, 6038c2ecf20Sopenharmony_ci 0x88888815); 6048c2ecf20Sopenharmony_ci } else { 6058c2ecf20Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0, 6068c2ecf20Sopenharmony_ci 0x11100060); 6078c2ecf20Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL1, 6088c2ecf20Sopenharmony_ci 0x080c0c06); 6098c2ecf20Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2, 6108c2ecf20Sopenharmony_ci 0x03000000); 6118c2ecf20Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL3, 6128c2ecf20Sopenharmony_ci 0x00000000); 6138c2ecf20Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL4, 6148c2ecf20Sopenharmony_ci 0x200005c0); 6158c2ecf20Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5, 6168c2ecf20Sopenharmony_ci 0x88888815); 6178c2ecf20Sopenharmony_ci } 6188c2ecf20Sopenharmony_ci 6198c2ecf20Sopenharmony_ci tmp = BCMA_CC_PMU_CTL_PLL_UPD | BCMA_CC_PMU_CTL_NOILPONW; 6208c2ecf20Sopenharmony_ci break; 6218c2ecf20Sopenharmony_ci 6228c2ecf20Sopenharmony_ci case BCMA_CHIP_ID_BCM43131: 6238c2ecf20Sopenharmony_ci case BCMA_CHIP_ID_BCM43217: 6248c2ecf20Sopenharmony_ci case BCMA_CHIP_ID_BCM43227: 6258c2ecf20Sopenharmony_ci case BCMA_CHIP_ID_BCM43228: 6268c2ecf20Sopenharmony_ci case BCMA_CHIP_ID_BCM43428: 6278c2ecf20Sopenharmony_ci /* LCNXN */ 6288c2ecf20Sopenharmony_ci /* 6298c2ecf20Sopenharmony_ci * PLL Settings for spur avoidance on/off mode, 6308c2ecf20Sopenharmony_ci * no on2 support for 43228A0 6318c2ecf20Sopenharmony_ci */ 6328c2ecf20Sopenharmony_ci if (spuravoid == 1) { 6338c2ecf20Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0, 6348c2ecf20Sopenharmony_ci 0x01100014); 6358c2ecf20Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL1, 6368c2ecf20Sopenharmony_ci 0x040C0C06); 6378c2ecf20Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2, 6388c2ecf20Sopenharmony_ci 0x03140A08); 6398c2ecf20Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL3, 6408c2ecf20Sopenharmony_ci 0x00333333); 6418c2ecf20Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL4, 6428c2ecf20Sopenharmony_ci 0x202C2820); 6438c2ecf20Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5, 6448c2ecf20Sopenharmony_ci 0x88888815); 6458c2ecf20Sopenharmony_ci } else { 6468c2ecf20Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0, 6478c2ecf20Sopenharmony_ci 0x11100014); 6488c2ecf20Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL1, 6498c2ecf20Sopenharmony_ci 0x040c0c06); 6508c2ecf20Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2, 6518c2ecf20Sopenharmony_ci 0x03000a08); 6528c2ecf20Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL3, 6538c2ecf20Sopenharmony_ci 0x00000000); 6548c2ecf20Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL4, 6558c2ecf20Sopenharmony_ci 0x200005c0); 6568c2ecf20Sopenharmony_ci bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5, 6578c2ecf20Sopenharmony_ci 0x88888815); 6588c2ecf20Sopenharmony_ci } 6598c2ecf20Sopenharmony_ci tmp = BCMA_CC_PMU_CTL_PLL_UPD; 6608c2ecf20Sopenharmony_ci break; 6618c2ecf20Sopenharmony_ci default: 6628c2ecf20Sopenharmony_ci bcma_err(bus, "Unknown spuravoidance settings for chip 0x%04X, not changing PLL\n", 6638c2ecf20Sopenharmony_ci bus->chipinfo.id); 6648c2ecf20Sopenharmony_ci break; 6658c2ecf20Sopenharmony_ci } 6668c2ecf20Sopenharmony_ci 6678c2ecf20Sopenharmony_ci tmp |= bcma_pmu_read32(cc, BCMA_CC_PMU_CTL); 6688c2ecf20Sopenharmony_ci bcma_pmu_write32(cc, BCMA_CC_PMU_CTL, tmp); 6698c2ecf20Sopenharmony_ci} 6708c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(bcma_pmu_spuravoid_pllupdate); 671