1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. 3*91f16700Schasinglulu * 4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 5*91f16700Schasinglulu */ 6*91f16700Schasinglulu 7*91f16700Schasinglulu #include <errno.h> 8*91f16700Schasinglulu 9*91f16700Schasinglulu #include <arch_helpers.h> 10*91f16700Schasinglulu #include <common/debug.h> 11*91f16700Schasinglulu #include <drivers/delay_timer.h> 12*91f16700Schasinglulu 13*91f16700Schasinglulu #include <apupwr_clkctl.h> 14*91f16700Schasinglulu #include <apupwr_clkctl_def.h> 15*91f16700Schasinglulu #include <mtk_plat_common.h> 16*91f16700Schasinglulu #include <platform_def.h> 17*91f16700Schasinglulu 18*91f16700Schasinglulu /* 8195 use PCW mode to change freq directly */ 19*91f16700Schasinglulu enum pll_set_rate_mode PLL_MODE = CON0_PCW; 20*91f16700Schasinglulu 21*91f16700Schasinglulu char *buck_domain_str[APUSYS_BUCK_DOMAIN_NUM] = { 22*91f16700Schasinglulu "V_VPU0", 23*91f16700Schasinglulu "V_VPU1", 24*91f16700Schasinglulu "V_MDLA0", 25*91f16700Schasinglulu "V_MDLA1", 26*91f16700Schasinglulu "V_APU_CONN", 27*91f16700Schasinglulu "V_TOP_IOMMU", 28*91f16700Schasinglulu "V_VCORE", 29*91f16700Schasinglulu }; 30*91f16700Schasinglulu 31*91f16700Schasinglulu uint32_t aacc_set[APUSYS_BUCK_DOMAIN_NUM] = { 32*91f16700Schasinglulu APU_ACC_CONFG_SET1, APU_ACC_CONFG_SET2, 33*91f16700Schasinglulu APU_ACC_CONFG_SET4, APU_ACC_CONFG_SET5, 34*91f16700Schasinglulu APU_ACC_CONFG_SET0, APU_ACC_CONFG_SET7 35*91f16700Schasinglulu }; 36*91f16700Schasinglulu 37*91f16700Schasinglulu uint32_t aacc_clr[APUSYS_BUCK_DOMAIN_NUM] = { 38*91f16700Schasinglulu APU_ACC_CONFG_CLR1, APU_ACC_CONFG_CLR2, 39*91f16700Schasinglulu APU_ACC_CONFG_CLR4, APU_ACC_CONFG_CLR5, 40*91f16700Schasinglulu APU_ACC_CONFG_CLR0, APU_ACC_CONFG_CLR7 41*91f16700Schasinglulu }; 42*91f16700Schasinglulu 43*91f16700Schasinglulu struct reg_seq { 44*91f16700Schasinglulu uint32_t address; 45*91f16700Schasinglulu uint32_t val; 46*91f16700Schasinglulu }; 47*91f16700Schasinglulu 48*91f16700Schasinglulu static const struct reg_seq init_acc_cfg[] = { 49*91f16700Schasinglulu { APU_ACC_CONFG_SET0, BIT(BIT_SEL_APU) }, 50*91f16700Schasinglulu { APU_ACC_CONFG_CLR0, BIT(BIT_CGEN_SOC) }, 51*91f16700Schasinglulu { APU_ACC_CONFG_SET0, BIT(BIT_SEL_APU_DIV2) }, 52*91f16700Schasinglulu { APU_ACC_CONFG_SET7, BIT(BIT_SEL_APU) }, 53*91f16700Schasinglulu { APU_ACC_CONFG_CLR7, BIT(BIT_CGEN_SOC) }, 54*91f16700Schasinglulu { APU_ACC_CONFG_SET7, BIT(BIT_SEL_APU_DIV2) }, 55*91f16700Schasinglulu { APU_ACC_CONFG_SET1, BIT(BIT_SEL_APU) }, 56*91f16700Schasinglulu { APU_ACC_CONFG_CLR1, BIT(BIT_CGEN_SOC) }, 57*91f16700Schasinglulu { APU_ACC_CONFG_SET1, BIT(BIT_SEL_APU_DIV2) }, 58*91f16700Schasinglulu { APU_ACC_CONFG_SET2, BIT(BIT_INVEN_OUT) }, 59*91f16700Schasinglulu { APU_ACC_CONFG_SET2, BIT(BIT_SEL_APU) }, 60*91f16700Schasinglulu { APU_ACC_CONFG_CLR2, BIT(BIT_CGEN_SOC) }, 61*91f16700Schasinglulu { APU_ACC_CONFG_SET2, BIT(BIT_SEL_APU_DIV2) }, 62*91f16700Schasinglulu { APU_ACC_CONFG_SET4, BIT(BIT_SEL_APU) }, 63*91f16700Schasinglulu { APU_ACC_CONFG_CLR4, BIT(BIT_CGEN_SOC) }, 64*91f16700Schasinglulu { APU_ACC_CONFG_SET4, BIT(BIT_SEL_APU_DIV2) }, 65*91f16700Schasinglulu { APU_ACC_CONFG_SET5, BIT(BIT_INVEN_OUT) }, 66*91f16700Schasinglulu { APU_ACC_CONFG_SET5, BIT(BIT_SEL_APU) }, 67*91f16700Schasinglulu { APU_ACC_CONFG_CLR5, BIT(BIT_CGEN_SOC) }, 68*91f16700Schasinglulu { APU_ACC_CONFG_SET5, BIT(BIT_SEL_APU_DIV2) }, 69*91f16700Schasinglulu }; 70*91f16700Schasinglulu 71*91f16700Schasinglulu int32_t apupwr_smc_acc_init_all(void) 72*91f16700Schasinglulu { 73*91f16700Schasinglulu int32_t i; 74*91f16700Schasinglulu 75*91f16700Schasinglulu for (i = 0; i < ARRAY_SIZE(init_acc_cfg); i++) { 76*91f16700Schasinglulu apupwr_writel(init_acc_cfg[i].val, 77*91f16700Schasinglulu init_acc_cfg[i].address); 78*91f16700Schasinglulu } 79*91f16700Schasinglulu 80*91f16700Schasinglulu /* Deault ACC will raise APU_DIV_2 */ 81*91f16700Schasinglulu apupwr_smc_pll_set_rate(BUCK_VCONN_DOMAIN_DEFAULT_FREQ, 82*91f16700Schasinglulu true, V_APU_CONN); 83*91f16700Schasinglulu 84*91f16700Schasinglulu apupwr_smc_pll_set_rate(BUCK_VCONN_DOMAIN_DEFAULT_FREQ, 85*91f16700Schasinglulu true, V_TOP_IOMMU); 86*91f16700Schasinglulu 87*91f16700Schasinglulu apupwr_smc_pll_set_rate(BUCK_VVPU_DOMAIN_DEFAULT_FREQ, 88*91f16700Schasinglulu true, V_VPU0); 89*91f16700Schasinglulu 90*91f16700Schasinglulu apupwr_smc_pll_set_rate(BUCK_VMDLA_DOMAIN_DEFAULT_FREQ, 91*91f16700Schasinglulu true, V_MDLA0); 92*91f16700Schasinglulu 93*91f16700Schasinglulu return 0; 94*91f16700Schasinglulu } 95*91f16700Schasinglulu 96*91f16700Schasinglulu void apupwr_smc_acc_top(bool enable) 97*91f16700Schasinglulu { 98*91f16700Schasinglulu if (enable) { 99*91f16700Schasinglulu apupwr_writel(BIT(BIT_CGEN_APU), aacc_set[V_APU_CONN]); 100*91f16700Schasinglulu apupwr_writel(BIT(BIT_CGEN_APU), aacc_set[V_TOP_IOMMU]); 101*91f16700Schasinglulu } else { 102*91f16700Schasinglulu apupwr_writel(BIT(BIT_CGEN_APU), aacc_clr[V_APU_CONN]); 103*91f16700Schasinglulu apupwr_writel(BIT(BIT_CGEN_APU), aacc_clr[V_TOP_IOMMU]); 104*91f16700Schasinglulu } 105*91f16700Schasinglulu } 106*91f16700Schasinglulu 107*91f16700Schasinglulu /* 108*91f16700Schasinglulu * acc_clk_set_parent:ACC MUX select 109*91f16700Schasinglulu * 0. freq parameters here, only ACC clksrc is valid 110*91f16700Schasinglulu * 1. Switch between APUPLL <=> Parking (F26M, PARK) 111*91f16700Schasinglulu * 2. Turn on/off CG_F26M, CG_PARK, CG_SOC, but no CG_APU 112*91f16700Schasinglulu * 3. Clear APU Div2 while Parking 113*91f16700Schasinglulu * 4. Only use clksrc of APUPLL while ACC CG_APU is on 114*91f16700Schasinglulu */ 115*91f16700Schasinglulu int32_t apupwr_smc_acc_set_parent(uint32_t freq, uint32_t domain) 116*91f16700Schasinglulu { 117*91f16700Schasinglulu uint32_t acc_set = 0; 118*91f16700Schasinglulu uint32_t acc_clr = 0; 119*91f16700Schasinglulu int32_t ret = 0; 120*91f16700Schasinglulu 121*91f16700Schasinglulu if (freq > DVFS_FREQ_ACC_APUPLL) { 122*91f16700Schasinglulu ERROR("%s wrong clksrc: %d\n", __func__, freq); 123*91f16700Schasinglulu ret = -EIO; 124*91f16700Schasinglulu goto err; 125*91f16700Schasinglulu } 126*91f16700Schasinglulu 127*91f16700Schasinglulu switch (domain) { 128*91f16700Schasinglulu case V_VPU1: 129*91f16700Schasinglulu case V_VPU0: 130*91f16700Schasinglulu case V_MDLA1: 131*91f16700Schasinglulu case V_MDLA0: 132*91f16700Schasinglulu case V_APU_CONN: 133*91f16700Schasinglulu case V_TOP_IOMMU: 134*91f16700Schasinglulu acc_set = aacc_set[domain]; 135*91f16700Schasinglulu acc_clr = aacc_clr[domain]; 136*91f16700Schasinglulu break; 137*91f16700Schasinglulu default: 138*91f16700Schasinglulu ret = -EIO; 139*91f16700Schasinglulu break; 140*91f16700Schasinglulu } 141*91f16700Schasinglulu 142*91f16700Schasinglulu /* Select park source */ 143*91f16700Schasinglulu switch (freq) { 144*91f16700Schasinglulu case DVFS_FREQ_ACC_PARKING: 145*91f16700Schasinglulu /* Select park source */ 146*91f16700Schasinglulu apupwr_writel(BIT(BIT_SEL_PARK), acc_set); 147*91f16700Schasinglulu apupwr_writel(BIT(BIT_SEL_F26M), acc_clr); 148*91f16700Schasinglulu /* Enable park cg */ 149*91f16700Schasinglulu apupwr_writel(BIT(BIT_CGEN_PARK), acc_set); 150*91f16700Schasinglulu apupwr_writel(BIT(BIT_CGEN_F26M) | BIT(BIT_CGEN_SOC), acc_clr); 151*91f16700Schasinglulu /* Select park path */ 152*91f16700Schasinglulu apupwr_writel(BIT(BIT_SEL_APU), acc_clr); 153*91f16700Schasinglulu /* clear apu div 2 */ 154*91f16700Schasinglulu apupwr_writel(BIT(BIT_SEL_APU_DIV2), acc_clr); 155*91f16700Schasinglulu break; 156*91f16700Schasinglulu 157*91f16700Schasinglulu case DVFS_FREQ_ACC_APUPLL: 158*91f16700Schasinglulu /* Select park path */ 159*91f16700Schasinglulu apupwr_writel(BIT(BIT_SEL_APU), acc_set); 160*91f16700Schasinglulu /* Clear park cg */ 161*91f16700Schasinglulu apupwr_writel(BIT(BIT_CGEN_PARK) | BIT(BIT_CGEN_F26M) | 162*91f16700Schasinglulu BIT(BIT_CGEN_SOC), acc_clr); 163*91f16700Schasinglulu break; 164*91f16700Schasinglulu 165*91f16700Schasinglulu case DVFS_FREQ_ACC_SOC: 166*91f16700Schasinglulu /* Select park source */ 167*91f16700Schasinglulu apupwr_writel(BIT(BIT_SEL_PARK), acc_clr); 168*91f16700Schasinglulu apupwr_writel(BIT(BIT_SEL_F26M), acc_clr); 169*91f16700Schasinglulu /* Enable park cg */ 170*91f16700Schasinglulu apupwr_writel(BIT(BIT_CGEN_SOC), acc_set); 171*91f16700Schasinglulu apupwr_writel(BIT(BIT_CGEN_F26M) | BIT(BIT_CGEN_PARK), acc_clr); 172*91f16700Schasinglulu /* Select park path */ 173*91f16700Schasinglulu apupwr_writel(BIT(BIT_SEL_APU), acc_clr); 174*91f16700Schasinglulu /* clear apu div 2 */ 175*91f16700Schasinglulu apupwr_writel(BIT(BIT_SEL_APU_DIV2), acc_clr); 176*91f16700Schasinglulu break; 177*91f16700Schasinglulu 178*91f16700Schasinglulu case DVFS_FREQ_ACC_26M: 179*91f16700Schasinglulu case DVFS_FREQ_NOT_SUPPORT: 180*91f16700Schasinglulu default: 181*91f16700Schasinglulu /* Select park source */ 182*91f16700Schasinglulu apupwr_writel(BIT(BIT_SEL_F26M), acc_set); 183*91f16700Schasinglulu apupwr_writel(BIT(BIT_SEL_PARK), acc_clr); 184*91f16700Schasinglulu /* Enable park cg */ 185*91f16700Schasinglulu apupwr_writel(BIT(BIT_CGEN_F26M), acc_set); 186*91f16700Schasinglulu apupwr_writel(BIT(BIT_CGEN_PARK) | BIT(BIT_CGEN_SOC), acc_clr); 187*91f16700Schasinglulu /* Select park path */ 188*91f16700Schasinglulu apupwr_writel(BIT(BIT_SEL_APU), acc_clr); 189*91f16700Schasinglulu /* clear apu div 2 */ 190*91f16700Schasinglulu apupwr_writel(BIT(BIT_SEL_APU_DIV2), acc_clr); 191*91f16700Schasinglulu ERROR("[APUPWR] %s wrong ACC clksrc : %d, force assign 26M\n", 192*91f16700Schasinglulu __func__, freq); 193*91f16700Schasinglulu break; 194*91f16700Schasinglulu } 195*91f16700Schasinglulu 196*91f16700Schasinglulu err: 197*91f16700Schasinglulu return ret; 198*91f16700Schasinglulu } 199*91f16700Schasinglulu 200*91f16700Schasinglulu int32_t apupwr_smc_pll_set_rate(uint32_t freq, bool div2, uint32_t domain) 201*91f16700Schasinglulu { 202*91f16700Schasinglulu int32_t ret = 0; 203*91f16700Schasinglulu uint32_t acc_set0 = 0, acc_set1 = 0; 204*91f16700Schasinglulu 205*91f16700Schasinglulu if (freq > DVFS_FREQ_MAX) { 206*91f16700Schasinglulu ERROR("%s wrong freq: %d\n", __func__, freq); 207*91f16700Schasinglulu ret = -EIO; 208*91f16700Schasinglulu goto err; 209*91f16700Schasinglulu } 210*91f16700Schasinglulu 211*91f16700Schasinglulu /* 212*91f16700Schasinglulu * Switch to Parking src 213*91f16700Schasinglulu * 1. Need to switch out all ACCs sharing the same apupll 214*91f16700Schasinglulu */ 215*91f16700Schasinglulu switch (domain) { 216*91f16700Schasinglulu case V_MDLA0: 217*91f16700Schasinglulu case V_MDLA1: 218*91f16700Schasinglulu acc_set0 = APU_ACC_CONFG_SET4; 219*91f16700Schasinglulu acc_set1 = APU_ACC_CONFG_SET5; 220*91f16700Schasinglulu ret = apupwr_smc_acc_set_parent(DVFS_FREQ_ACC_PARKING, 221*91f16700Schasinglulu V_MDLA0); 222*91f16700Schasinglulu ret = apupwr_smc_acc_set_parent(DVFS_FREQ_ACC_PARKING, 223*91f16700Schasinglulu V_MDLA1); 224*91f16700Schasinglulu break; 225*91f16700Schasinglulu case V_VPU0: 226*91f16700Schasinglulu case V_VPU1: 227*91f16700Schasinglulu acc_set0 = APU_ACC_CONFG_SET1; 228*91f16700Schasinglulu acc_set1 = APU_ACC_CONFG_SET2; 229*91f16700Schasinglulu ret = apupwr_smc_acc_set_parent(DVFS_FREQ_ACC_PARKING, 230*91f16700Schasinglulu V_VPU0); 231*91f16700Schasinglulu ret = apupwr_smc_acc_set_parent(DVFS_FREQ_ACC_PARKING, 232*91f16700Schasinglulu V_VPU1); 233*91f16700Schasinglulu break; 234*91f16700Schasinglulu case V_APU_CONN: 235*91f16700Schasinglulu acc_set0 = APU_ACC_CONFG_SET0; 236*91f16700Schasinglulu ret = apupwr_smc_acc_set_parent(DVFS_FREQ_ACC_PARKING, 237*91f16700Schasinglulu V_APU_CONN); 238*91f16700Schasinglulu break; 239*91f16700Schasinglulu case V_TOP_IOMMU: 240*91f16700Schasinglulu acc_set0 = APU_ACC_CONFG_SET7; 241*91f16700Schasinglulu ret = apupwr_smc_acc_set_parent(DVFS_FREQ_ACC_PARKING, 242*91f16700Schasinglulu V_TOP_IOMMU); 243*91f16700Schasinglulu break; 244*91f16700Schasinglulu default: 245*91f16700Schasinglulu ERROR("[APUPWR] %s %d invalid domain (%d)\n", 246*91f16700Schasinglulu __func__, __LINE__, domain); 247*91f16700Schasinglulu ret = -EIO; 248*91f16700Schasinglulu goto err; 249*91f16700Schasinglulu } 250*91f16700Schasinglulu 251*91f16700Schasinglulu anpu_pll_set_rate(domain, PLL_MODE, (div2) ? (freq * 2) : freq); 252*91f16700Schasinglulu 253*91f16700Schasinglulu if (div2) { 254*91f16700Schasinglulu apupwr_writel(BIT(BIT_SEL_APU_DIV2), acc_set0); 255*91f16700Schasinglulu if (acc_set1) { 256*91f16700Schasinglulu apupwr_writel(BIT(BIT_SEL_APU_DIV2), acc_set1); 257*91f16700Schasinglulu } 258*91f16700Schasinglulu } 259*91f16700Schasinglulu 260*91f16700Schasinglulu /* 261*91f16700Schasinglulu * Switch back to APUPLL 262*91f16700Schasinglulu * Only switch back to APUPLL while CG_APU on 263*91f16700Schasinglulu * And clksrc is not APUPLL 264*91f16700Schasinglulu */ 265*91f16700Schasinglulu switch (domain) { 266*91f16700Schasinglulu case V_VPU0: 267*91f16700Schasinglulu case V_VPU1: 268*91f16700Schasinglulu if ((apupwr_readl(acc_set0) & BIT(BIT_CGEN_APU)) && 269*91f16700Schasinglulu !(apupwr_readl(acc_set0) & BIT(BIT_SEL_APU))) { 270*91f16700Schasinglulu ret = apupwr_smc_acc_set_parent(DVFS_FREQ_ACC_APUPLL, 271*91f16700Schasinglulu V_VPU0); 272*91f16700Schasinglulu } 273*91f16700Schasinglulu if ((apupwr_readl(acc_set1) & BIT(BIT_CGEN_APU)) && 274*91f16700Schasinglulu !(apupwr_readl(acc_set1) & BIT(BIT_SEL_APU))) { 275*91f16700Schasinglulu ret = apupwr_smc_acc_set_parent(DVFS_FREQ_ACC_APUPLL, 276*91f16700Schasinglulu V_VPU1); 277*91f16700Schasinglulu } 278*91f16700Schasinglulu break; 279*91f16700Schasinglulu case V_MDLA0: 280*91f16700Schasinglulu case V_MDLA1: 281*91f16700Schasinglulu if ((apupwr_readl(acc_set0) & BIT(BIT_CGEN_APU)) && 282*91f16700Schasinglulu !(apupwr_readl(acc_set0) & BIT(BIT_SEL_APU))) { 283*91f16700Schasinglulu ret = apupwr_smc_acc_set_parent(DVFS_FREQ_ACC_APUPLL, 284*91f16700Schasinglulu V_MDLA0); 285*91f16700Schasinglulu } 286*91f16700Schasinglulu if ((apupwr_readl(acc_set1) & BIT(BIT_CGEN_APU)) && 287*91f16700Schasinglulu !(apupwr_readl(acc_set1) & BIT(BIT_SEL_APU))) { 288*91f16700Schasinglulu ret = apupwr_smc_acc_set_parent(DVFS_FREQ_ACC_APUPLL, 289*91f16700Schasinglulu V_MDLA1); 290*91f16700Schasinglulu } 291*91f16700Schasinglulu break; 292*91f16700Schasinglulu case V_APU_CONN: 293*91f16700Schasinglulu case V_TOP_IOMMU: 294*91f16700Schasinglulu if ((apupwr_readl(acc_set0) & BIT(BIT_CGEN_APU)) && 295*91f16700Schasinglulu !(apupwr_readl(acc_set0) & BIT(BIT_SEL_APU))) { 296*91f16700Schasinglulu ret = apupwr_smc_acc_set_parent(DVFS_FREQ_ACC_APUPLL, 297*91f16700Schasinglulu domain); 298*91f16700Schasinglulu } 299*91f16700Schasinglulu break; 300*91f16700Schasinglulu default: 301*91f16700Schasinglulu ERROR("[APUPWR] %s %d invalid domain (%d)\n", 302*91f16700Schasinglulu __func__, __LINE__, domain); 303*91f16700Schasinglulu ret = -EIO; 304*91f16700Schasinglulu break; 305*91f16700Schasinglulu } 306*91f16700Schasinglulu INFO("[%s][%d] set domain %d to freq %d\n", 307*91f16700Schasinglulu __func__, __LINE__, domain, (div2) ? (freq * 2) : freq); 308*91f16700Schasinglulu 309*91f16700Schasinglulu err: 310*91f16700Schasinglulu return ret; 311*91f16700Schasinglulu } 312*91f16700Schasinglulu 313*91f16700Schasinglulu int32_t apupwr_smc_bulk_pll(bool enable) 314*91f16700Schasinglulu { 315*91f16700Schasinglulu int32_t ret = 0; 316*91f16700Schasinglulu int32_t pll_idx; 317*91f16700Schasinglulu 318*91f16700Schasinglulu if (enable) { 319*91f16700Schasinglulu for (pll_idx = APUPLL; pll_idx < APUPLL_MAX; pll_idx++) { 320*91f16700Schasinglulu ret = apu_pll_enable(pll_idx, enable, false); 321*91f16700Schasinglulu if (ret != 0) { 322*91f16700Schasinglulu goto err; 323*91f16700Schasinglulu } 324*91f16700Schasinglulu } 325*91f16700Schasinglulu } else { 326*91f16700Schasinglulu for (pll_idx = APUPLL2; pll_idx >= APUPLL; pll_idx--) { 327*91f16700Schasinglulu ret = apu_pll_enable(pll_idx, enable, false); 328*91f16700Schasinglulu if (ret != 0) { 329*91f16700Schasinglulu goto err; 330*91f16700Schasinglulu } 331*91f16700Schasinglulu } 332*91f16700Schasinglulu } 333*91f16700Schasinglulu 334*91f16700Schasinglulu err: 335*91f16700Schasinglulu return ret; 336*91f16700Schasinglulu } 337*91f16700Schasinglulu 338*91f16700Schasinglulu void apupwr_smc_bus_prot_cg_on(void) 339*91f16700Schasinglulu { 340*91f16700Schasinglulu apupwr_clrbits(AO_MD32_MNOC_MASK, APU_CSR_DUMMY_0); 341*91f16700Schasinglulu } 342