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