1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. 3*91f16700Schasinglulu * 4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 5*91f16700Schasinglulu */ 6*91f16700Schasinglulu 7*91f16700Schasinglulu #include <assert.h> 8*91f16700Schasinglulu #include <string.h> 9*91f16700Schasinglulu 10*91f16700Schasinglulu #include <platform_def.h> 11*91f16700Schasinglulu 12*91f16700Schasinglulu #include <arch_helpers.h> 13*91f16700Schasinglulu #include <common/bl_common.h> 14*91f16700Schasinglulu #include <common/debug.h> 15*91f16700Schasinglulu #include <drivers/console.h> 16*91f16700Schasinglulu #include <lib/mmio.h> 17*91f16700Schasinglulu #include <plat/common/platform.h> 18*91f16700Schasinglulu 19*91f16700Schasinglulu #include <hi6220.h> 20*91f16700Schasinglulu #include <hi6553.h> 21*91f16700Schasinglulu #include <hisi_sram_map.h> 22*91f16700Schasinglulu 23*91f16700Schasinglulu #define ACPU_FREQ_MAX_NUM 5 24*91f16700Schasinglulu #define ACPU_OPP_NUM 7 25*91f16700Schasinglulu 26*91f16700Schasinglulu #define ACPU_VALID_VOLTAGE_MAGIC (0x5A5AC5C5) 27*91f16700Schasinglulu 28*91f16700Schasinglulu #define ACPU_WAIT_TIMEOUT (200) 29*91f16700Schasinglulu #define ACPU_WAIT_FOR_WFI_TIMOUT (2000) 30*91f16700Schasinglulu #define ACPU_DFS_STATE_CNT (0x10000) 31*91f16700Schasinglulu 32*91f16700Schasinglulu struct acpu_dvfs_sram_stru { 33*91f16700Schasinglulu unsigned int magic; 34*91f16700Schasinglulu unsigned int support_freq_num; 35*91f16700Schasinglulu unsigned int support_freq_max; 36*91f16700Schasinglulu unsigned int start_prof; 37*91f16700Schasinglulu unsigned int vol[ACPU_OPP_NUM]; 38*91f16700Schasinglulu }; 39*91f16700Schasinglulu 40*91f16700Schasinglulu struct acpu_volt_cal_para { 41*91f16700Schasinglulu unsigned int freq; 42*91f16700Schasinglulu unsigned int ul_vol; 43*91f16700Schasinglulu unsigned int dl_vol; 44*91f16700Schasinglulu unsigned int core_ref_hpm; 45*91f16700Schasinglulu }; 46*91f16700Schasinglulu 47*91f16700Schasinglulu struct ddr_volt_cal_para { 48*91f16700Schasinglulu unsigned int freq; 49*91f16700Schasinglulu unsigned int ul_vol; 50*91f16700Schasinglulu unsigned int dl_vol; 51*91f16700Schasinglulu unsigned int ddr_ref_hpm; 52*91f16700Schasinglulu }; 53*91f16700Schasinglulu 54*91f16700Schasinglulu struct acpu_dvfs_opp_para { 55*91f16700Schasinglulu unsigned int freq; 56*91f16700Schasinglulu unsigned int acpu_clk_profile0; 57*91f16700Schasinglulu unsigned int acpu_clk_profile1; 58*91f16700Schasinglulu unsigned int acpu_vol_profile; 59*91f16700Schasinglulu unsigned int acpu_pll_freq; 60*91f16700Schasinglulu unsigned int acpu_pll_frac; 61*91f16700Schasinglulu }; 62*91f16700Schasinglulu 63*91f16700Schasinglulu unsigned int efuse_acpu_freq[] = { 64*91f16700Schasinglulu 1200000, 1250000, 1300000, 1350000, 65*91f16700Schasinglulu 1400000, 1450000, 1500000, 1550000, 66*91f16700Schasinglulu 1600000, 1650000, 1700000, 1750000, 67*91f16700Schasinglulu 1800000, 1850000, 1900000, 1950000, 68*91f16700Schasinglulu }; 69*91f16700Schasinglulu 70*91f16700Schasinglulu struct acpu_dvfs_opp_para hi6220_acpu_profile[] = { 71*91f16700Schasinglulu { 208000, 0x61E5, 0x022, 0x3A, 0x5220102B, 0x05555555 }, 72*91f16700Schasinglulu { 432000, 0x10A6, 0x121, 0x3A, 0x5120102D, 0x10000005 }, 73*91f16700Schasinglulu { 729000, 0x2283, 0x100, 0x4A, 0x51101026, 0x10000005 }, 74*91f16700Schasinglulu { 960000, 0x1211, 0x100, 0x5B, 0x51101032, 0x10000005 }, 75*91f16700Schasinglulu { 1200000, 0x1211, 0x100, 0x6B, 0x5110207D, 0x10000005 }, 76*91f16700Schasinglulu { 1400000, 0x1211, 0x100, 0x6B, 0x51101049, 0x10000005 }, 77*91f16700Schasinglulu { 1500000, 0x1211, 0x100, 0x6B, 0x51101049, 0x10000005 }, 78*91f16700Schasinglulu }; 79*91f16700Schasinglulu 80*91f16700Schasinglulu struct acpu_dvfs_opp_para *acpu_dvfs_profile = hi6220_acpu_profile; 81*91f16700Schasinglulu struct acpu_dvfs_sram_stru *acpu_dvfs_sram_buf = 82*91f16700Schasinglulu (struct acpu_dvfs_sram_stru *)MEMORY_AXI_ACPU_FREQ_VOL_ADDR; 83*91f16700Schasinglulu 84*91f16700Schasinglulu static inline void write_reg_mask(uintptr_t addr, 85*91f16700Schasinglulu uint32_t val, uint32_t mask) 86*91f16700Schasinglulu { 87*91f16700Schasinglulu uint32_t reg; 88*91f16700Schasinglulu 89*91f16700Schasinglulu reg = mmio_read_32(addr); 90*91f16700Schasinglulu reg = (reg & ~(mask)) | val; 91*91f16700Schasinglulu mmio_write_32(addr, reg); 92*91f16700Schasinglulu } 93*91f16700Schasinglulu 94*91f16700Schasinglulu static inline uint32_t read_reg_mask(uintptr_t addr, 95*91f16700Schasinglulu uint32_t mask, uint32_t offset) 96*91f16700Schasinglulu { 97*91f16700Schasinglulu uint32_t reg; 98*91f16700Schasinglulu 99*91f16700Schasinglulu reg = mmio_read_32(addr); 100*91f16700Schasinglulu reg &= (mask << offset); 101*91f16700Schasinglulu return (reg >> offset); 102*91f16700Schasinglulu } 103*91f16700Schasinglulu 104*91f16700Schasinglulu static int acpu_dvfs_syspll_cfg(unsigned int prof_id) 105*91f16700Schasinglulu { 106*91f16700Schasinglulu uint32_t reg0 = 0; 107*91f16700Schasinglulu uint32_t count = 0; 108*91f16700Schasinglulu uint32_t clk_div_status = 0; 109*91f16700Schasinglulu 110*91f16700Schasinglulu /* 111*91f16700Schasinglulu * step 1: 112*91f16700Schasinglulu * - ACPUSYSPLLCFG.acpu_subsys_clk_div_sw = 0x3; 113*91f16700Schasinglulu * - ACPUSYSPLLCFG.acpu_syspll_clken_cfg = 0x1; 114*91f16700Schasinglulu */ 115*91f16700Schasinglulu write_reg_mask(PMCTRL_ACPUSYSPLLCFG, 0x3 << 12, 0x3 << 12); 116*91f16700Schasinglulu write_reg_mask(PMCTRL_ACPUSYSPLLCFG, 0x1 << 4, 0x1 << 4); 117*91f16700Schasinglulu 118*91f16700Schasinglulu /* 119*91f16700Schasinglulu * step 2: 120*91f16700Schasinglulu * - ACPUSYSPLLCFG.acpu_syspll_div_cfg: 121*91f16700Schasinglulu * 208MHz, set to 0x5; 122*91f16700Schasinglulu * 500MHz, set to 0x2; 123*91f16700Schasinglulu * other opps set to 0x1 124*91f16700Schasinglulu */ 125*91f16700Schasinglulu if (prof_id == 0) 126*91f16700Schasinglulu write_reg_mask(PMCTRL_ACPUSYSPLLCFG, 0x5 << 0, 0x7 << 0); 127*91f16700Schasinglulu else if (prof_id == 1) 128*91f16700Schasinglulu write_reg_mask(PMCTRL_ACPUSYSPLLCFG, 0x2 << 0, 0x7 << 0); 129*91f16700Schasinglulu else 130*91f16700Schasinglulu write_reg_mask(PMCTRL_ACPUSYSPLLCFG, 0x1 << 0, 0x7 << 0); 131*91f16700Schasinglulu 132*91f16700Schasinglulu /* 133*91f16700Schasinglulu * step 3: 134*91f16700Schasinglulu * - Polling ACPU_SC_CPU_STAT.clk_div_status_vd == 0x3; 135*91f16700Schasinglulu * - ACPU_SC_VD_CTRL.tune_en_dif = 0 136*91f16700Schasinglulu * - ACPU_SC_VD_CTRL.tune_en_int = 0 137*91f16700Schasinglulu * - PMCTRL_ACPUCLKDIV.acpu_ddr_clk_div_cfg = 0x1 138*91f16700Schasinglulu * - PMCTRL_ACPUPLLSEL.acpu_pllsw_cfg = 0x1 139*91f16700Schasinglulu */ 140*91f16700Schasinglulu clk_div_status = 0x3; 141*91f16700Schasinglulu do { 142*91f16700Schasinglulu reg0 = read_reg_mask(ACPU_SC_CPU_STAT, 0x3, 20); 143*91f16700Schasinglulu if ((count++) > ACPU_DFS_STATE_CNT) { 144*91f16700Schasinglulu ERROR("%s: clk div status timeout!\n", __func__); 145*91f16700Schasinglulu return -1; 146*91f16700Schasinglulu } 147*91f16700Schasinglulu } while (clk_div_status != reg0); 148*91f16700Schasinglulu 149*91f16700Schasinglulu write_reg_mask(ACPU_SC_VD_CTRL, 0x0, (0x1 << 0) | (0x1 << 11)); 150*91f16700Schasinglulu write_reg_mask(PMCTRL_ACPUCLKDIV, 0x1 << 8, 0x3 << 8); 151*91f16700Schasinglulu write_reg_mask(PMCTRL_ACPUPLLSEL, 0x1 << 0, 0x1 << 0); 152*91f16700Schasinglulu 153*91f16700Schasinglulu return 0; 154*91f16700Schasinglulu } 155*91f16700Schasinglulu 156*91f16700Schasinglulu static void acpu_dvfs_clk_div_cfg(unsigned int prof_id, 157*91f16700Schasinglulu unsigned int *cpuext_cfg, 158*91f16700Schasinglulu unsigned int *acpu_ddr_cfg) 159*91f16700Schasinglulu { 160*91f16700Schasinglulu if (prof_id == 0) { 161*91f16700Schasinglulu write_reg_mask(PMCTRL_ACPUCLKDIV, 162*91f16700Schasinglulu (0x1 << SOC_PMCTRL_ACPUCLKDIV_cpuext_clk_div_cfg_START) | 163*91f16700Schasinglulu (0x1 << SOC_PMCTRL_ACPUCLKDIV_acpu_ddr_clk_div_cfg_START), 164*91f16700Schasinglulu (0x3 << SOC_PMCTRL_ACPUCLKDIV_cpuext_clk_div_cfg_START) | 165*91f16700Schasinglulu (0x3 << SOC_PMCTRL_ACPUCLKDIV_acpu_ddr_clk_div_cfg_START)); 166*91f16700Schasinglulu *cpuext_cfg = 0x1; 167*91f16700Schasinglulu *acpu_ddr_cfg = 0x1; 168*91f16700Schasinglulu } else if (prof_id == 1) { 169*91f16700Schasinglulu write_reg_mask(PMCTRL_ACPUCLKDIV, 170*91f16700Schasinglulu (0x1 << SOC_PMCTRL_ACPUCLKDIV_cpuext_clk_div_cfg_START) | 171*91f16700Schasinglulu (0x1 << SOC_PMCTRL_ACPUCLKDIV_acpu_ddr_clk_div_cfg_START), 172*91f16700Schasinglulu (0x3 << SOC_PMCTRL_ACPUCLKDIV_cpuext_clk_div_cfg_START) | 173*91f16700Schasinglulu (0x3 << SOC_PMCTRL_ACPUCLKDIV_acpu_ddr_clk_div_cfg_START)); 174*91f16700Schasinglulu *cpuext_cfg = 0x1; 175*91f16700Schasinglulu *acpu_ddr_cfg = 0x1; 176*91f16700Schasinglulu } else { 177*91f16700Schasinglulu /* ddr has not been inited */ 178*91f16700Schasinglulu write_reg_mask(PMCTRL_ACPUCLKDIV, 179*91f16700Schasinglulu (0x1 << SOC_PMCTRL_ACPUCLKDIV_cpuext_clk_div_cfg_START) | 180*91f16700Schasinglulu (0x0 << SOC_PMCTRL_ACPUCLKDIV_acpu_ddr_clk_div_cfg_START), 181*91f16700Schasinglulu (0x3 << SOC_PMCTRL_ACPUCLKDIV_cpuext_clk_div_cfg_START) | 182*91f16700Schasinglulu (0x3 << SOC_PMCTRL_ACPUCLKDIV_acpu_ddr_clk_div_cfg_START)); 183*91f16700Schasinglulu *cpuext_cfg = 0x1; 184*91f16700Schasinglulu *acpu_ddr_cfg = 0x0; 185*91f16700Schasinglulu } 186*91f16700Schasinglulu } 187*91f16700Schasinglulu 188*91f16700Schasinglulu static int acpu_dvfs_freq_ascend(unsigned int cur_prof, unsigned int tar_prof) 189*91f16700Schasinglulu { 190*91f16700Schasinglulu unsigned int reg0 = 0; 191*91f16700Schasinglulu unsigned int reg1 = 0; 192*91f16700Schasinglulu unsigned int reg2 = 0; 193*91f16700Schasinglulu unsigned int count = 0; 194*91f16700Schasinglulu unsigned int cpuext_cfg_val = 0; 195*91f16700Schasinglulu unsigned int acpu_ddr_cfg_val = 0; 196*91f16700Schasinglulu int ret = 0; 197*91f16700Schasinglulu 198*91f16700Schasinglulu /* 199*91f16700Schasinglulu * step 1: 200*91f16700Schasinglulu * - PMCTRL_ACPUSYSPLLCFG.acpu_subsys_clk_div_sw = 0x3; 201*91f16700Schasinglulu * - ACPUSYSPLLCFG.acpu_syspll_clken_cfg = 0x1; 202*91f16700Schasinglulu * 203*91f16700Schasinglulu * step 2: 204*91f16700Schasinglulu * - PMCTRL_ACPUSYSPLLCFG.acpu_syspll_div_cfg = 0x5 (208MHz) 205*91f16700Schasinglulu * - PMCTRL_ACPUSYSPLLCFG.acpu_syspll_div_cfg = 0x2 (500MHz) 206*91f16700Schasinglulu * - PMCTRL_ACPUSYSPLLCFG.acpu_syspll_div_cfg = 0x1 (Other OPPs) 207*91f16700Schasinglulu * 208*91f16700Schasinglulu * step 3: 209*91f16700Schasinglulu * - ACPU_SC_CPU_STAT.clk_div_status_vd = 0x3; 210*91f16700Schasinglulu * - ACPU_SC_VD_CTRL.tune_en_dif = 0x0; 211*91f16700Schasinglulu * - ACPU_SC_VD_CTRL.tune_en_int = 0x0; 212*91f16700Schasinglulu * - PMCTRL_ACPUCLKDIV.acpu_ddr_clk_div_cfg = 0x1; 213*91f16700Schasinglulu * - PMCTRL_ACPUPLLSEL.acpu_pllsw_cfg = 0x1 214*91f16700Schasinglulu */ 215*91f16700Schasinglulu ret = acpu_dvfs_syspll_cfg(cur_prof); 216*91f16700Schasinglulu if (ret) 217*91f16700Schasinglulu return -1; 218*91f16700Schasinglulu 219*91f16700Schasinglulu /* 220*91f16700Schasinglulu * step 4: 221*91f16700Schasinglulu * - Polling PMCTRL_ACPUPLLSEL.syspll_sw_stat == 0x1 222*91f16700Schasinglulu */ 223*91f16700Schasinglulu count = 0; 224*91f16700Schasinglulu do { 225*91f16700Schasinglulu reg0 = read_reg_mask(PMCTRL_ACPUPLLSEL, 0x1, 226*91f16700Schasinglulu SOC_PMCTRL_ACPUPLLSEL_syspll_sw_stat_START); 227*91f16700Schasinglulu if ((count++) > ACPU_DFS_STATE_CNT) { 228*91f16700Schasinglulu ERROR("%s: syspll sw status timeout\n", __func__); 229*91f16700Schasinglulu return -1; 230*91f16700Schasinglulu } 231*91f16700Schasinglulu } while (reg0 != 0x1); 232*91f16700Schasinglulu 233*91f16700Schasinglulu /* Enable VD functionality if > 800MHz */ 234*91f16700Schasinglulu if (acpu_dvfs_profile[tar_prof].freq > 800000) { 235*91f16700Schasinglulu 236*91f16700Schasinglulu write_reg_mask(ACPU_SC_VD_HPM_CTRL, 237*91f16700Schasinglulu HPM_OSC_DIV_VAL, HPM_OSC_DIV_MASK); 238*91f16700Schasinglulu 239*91f16700Schasinglulu /* 240*91f16700Schasinglulu * step 5: 241*91f16700Schasinglulu * - ACPU_SC_VD_HPM_CTRL.hpm_dly_exp = 0xC7A; 242*91f16700Schasinglulu * - ACPU_SC_VD_MASK_PATTERN_CTRL[12:0] = 0xCCB; 243*91f16700Schasinglulu */ 244*91f16700Schasinglulu write_reg_mask(ACPU_SC_VD_HPM_CTRL, 245*91f16700Schasinglulu HPM_DLY_EXP_VAL, HPM_DLY_EXP_MASK); 246*91f16700Schasinglulu write_reg_mask(ACPU_SC_VD_MASK_PATTERN_CTRL, 247*91f16700Schasinglulu ACPU_SC_VD_MASK_PATTERN_VAL, 248*91f16700Schasinglulu ACPU_SC_VD_MASK_PATTERN_MASK); 249*91f16700Schasinglulu 250*91f16700Schasinglulu /* 251*91f16700Schasinglulu * step 6: 252*91f16700Schasinglulu * - ACPU_SC_VD_DLY_TABLE0_CTRL = 0x1FFF; 253*91f16700Schasinglulu * - ACPU_SC_VD_DLY_TABLE1_CTRL = 0x1FFFFFF; 254*91f16700Schasinglulu * - ACPU_SC_VD_DLY_TABLE2_CTRL = 0x7FFFFFFF; 255*91f16700Schasinglulu * - ACPU_SC_VD_DLY_FIXED_CTRL = 0x1; 256*91f16700Schasinglulu */ 257*91f16700Schasinglulu mmio_write_32(ACPU_SC_VD_DLY_TABLE0_CTRL, 0x1FFF); 258*91f16700Schasinglulu mmio_write_32(ACPU_SC_VD_DLY_TABLE1_CTRL, 0x1FFFFFF); 259*91f16700Schasinglulu mmio_write_32(ACPU_SC_VD_DLY_TABLE2_CTRL, 0x7FFFFFFF); 260*91f16700Schasinglulu mmio_write_32(ACPU_SC_VD_DLY_FIXED_CTRL, 0x1); 261*91f16700Schasinglulu 262*91f16700Schasinglulu /* 263*91f16700Schasinglulu * step 7: 264*91f16700Schasinglulu * - ACPU_SC_VD_CTRL.shift_table0 = 0x1; 265*91f16700Schasinglulu * - ACPU_SC_VD_CTRL.shift_table1 = 0x3; 266*91f16700Schasinglulu * - ACPU_SC_VD_CTRL.shift_table2 = 0x5; 267*91f16700Schasinglulu * - ACPU_SC_VD_CTRL.shift_table3 = 0x6; 268*91f16700Schasinglulu * 269*91f16700Schasinglulu * step 8: 270*91f16700Schasinglulu * - ACPU_SC_VD_CTRL.tune = 0x7; 271*91f16700Schasinglulu */ 272*91f16700Schasinglulu write_reg_mask(ACPU_SC_VD_CTRL, 273*91f16700Schasinglulu ACPU_SC_VD_SHIFT_TABLE_TUNE_VAL, 274*91f16700Schasinglulu ACPU_SC_VD_SHIFT_TABLE_TUNE_MASK); 275*91f16700Schasinglulu } 276*91f16700Schasinglulu 277*91f16700Schasinglulu /* step 9: ACPUPLLCTRL.acpupll_en_cfg = 0x0 */ 278*91f16700Schasinglulu write_reg_mask(PMCTRL_ACPUPLLCTRL, 0x0, 279*91f16700Schasinglulu 0x1 << SOC_PMCTRL_ACPUPLLCTRL_acpupll_en_cfg_START); 280*91f16700Schasinglulu 281*91f16700Schasinglulu /* step 10: set PMCTRL_ACPUPLLFREQ and PMCTRL_ACPUPLLFRAC */ 282*91f16700Schasinglulu mmio_write_32(PMCTRL_ACPUPLLFREQ, 283*91f16700Schasinglulu acpu_dvfs_profile[tar_prof].acpu_pll_freq); 284*91f16700Schasinglulu mmio_write_32(PMCTRL_ACPUPLLFRAC, 285*91f16700Schasinglulu acpu_dvfs_profile[tar_prof].acpu_pll_frac); 286*91f16700Schasinglulu 287*91f16700Schasinglulu /* 288*91f16700Schasinglulu * step 11: 289*91f16700Schasinglulu * - wait for 1us; 290*91f16700Schasinglulu * - PMCTRL_ACPUPLLCTRL.acpupll_en_cfg = 0x1 291*91f16700Schasinglulu */ 292*91f16700Schasinglulu count = 0; 293*91f16700Schasinglulu while (count < ACPU_WAIT_TIMEOUT) 294*91f16700Schasinglulu count++; 295*91f16700Schasinglulu 296*91f16700Schasinglulu write_reg_mask(PMCTRL_ACPUPLLCTRL, 297*91f16700Schasinglulu 0x1 << SOC_PMCTRL_ACPUPLLCTRL_acpupll_en_cfg_START, 298*91f16700Schasinglulu 0x1 << SOC_PMCTRL_ACPUPLLCTRL_acpupll_en_cfg_START); 299*91f16700Schasinglulu 300*91f16700Schasinglulu /* step 12: PMCTRL_ACPUVOLPMUADDR = 0x100da */ 301*91f16700Schasinglulu mmio_write_32(PMCTRL_ACPUVOLPMUADDR, 0x100da); 302*91f16700Schasinglulu 303*91f16700Schasinglulu /* 304*91f16700Schasinglulu * step 13: 305*91f16700Schasinglulu * - PMCTRL_ACPUDESTVOL.acpu_dest_vol = 0x13 (208MHz); 306*91f16700Schasinglulu * - PMCTRL_ACPUDESTVOL.acpu_dest_vol = 0x13 (500MHz); 307*91f16700Schasinglulu * - PMCTRL_ACPUDESTVOL.acpu_dest_vol = 0x20 (798MHz); 308*91f16700Schasinglulu * - PMCTRL_ACPUDESTVOL.acpu_dest_vol = 0x3A (1300MHz); 309*91f16700Schasinglulu * - PMCTRL_ACPUDESTVOL.acpu_dest_vol = 0x3A (1500MHz); 310*91f16700Schasinglulu */ 311*91f16700Schasinglulu write_reg_mask(PMCTRL_ACPUDESTVOL, 312*91f16700Schasinglulu acpu_dvfs_profile[tar_prof].acpu_vol_profile, 313*91f16700Schasinglulu ((0x1 << (SOC_PMCTRL_ACPUDESTVOL_acpu_dest_vol_END + 1)) - 1)); 314*91f16700Schasinglulu 315*91f16700Schasinglulu /* 316*91f16700Schasinglulu * step 14: 317*91f16700Schasinglulu * - Polling PMCTRL_ACPUDESTVOL.acpu_vol_using == ACPUDESTVOL.acpu_dest_vol 318*91f16700Schasinglulu * - Polling ACPUVOLTIMEOUT.acpu_vol_timeout == 0x1 319*91f16700Schasinglulu * - Config PMCTRL_ACPUCLKDIV.acpu_ddr_clk_div_cfg 320*91f16700Schasinglulu * - Config ACPUCLKDIV.cpuext_clk_div_cfg; 321*91f16700Schasinglulu */ 322*91f16700Schasinglulu count = 0; 323*91f16700Schasinglulu do { 324*91f16700Schasinglulu reg0 = read_reg_mask(PMCTRL_ACPUDESTVOL, 0x7F, 325*91f16700Schasinglulu SOC_PMCTRL_ACPUDESTVOL_acpu_dest_vol_START); 326*91f16700Schasinglulu reg1 = read_reg_mask(PMCTRL_ACPUDESTVOL, 0x7F, 327*91f16700Schasinglulu SOC_PMCTRL_ACPUDESTVOL_acpu_vol_using_START); 328*91f16700Schasinglulu reg2 = read_reg_mask(PMCTRL_ACPUVOLTTIMEOUT, 0x1, 329*91f16700Schasinglulu SOC_PMCTRL_ACPUVOLTIMEOUT_acpu_vol_timeout_START); 330*91f16700Schasinglulu if ((count++) > ACPU_DFS_STATE_CNT) { 331*91f16700Schasinglulu ERROR("%s: acpu destvol cfg timeout.\n", __func__); 332*91f16700Schasinglulu return -1; 333*91f16700Schasinglulu } 334*91f16700Schasinglulu } while ((reg0 != reg1) || (reg2 != 0x1)); 335*91f16700Schasinglulu 336*91f16700Schasinglulu acpu_dvfs_clk_div_cfg(tar_prof, &cpuext_cfg_val, &acpu_ddr_cfg_val); 337*91f16700Schasinglulu 338*91f16700Schasinglulu /* 339*91f16700Schasinglulu * step 15: 340*91f16700Schasinglulu * - Polling PMCTRL_ACPUCLKDIV.cpuext_clk_div_stat; 341*91f16700Schasinglulu * - Polling ACPUCLKDIV.acpu_ddr_clk_div_stat; 342*91f16700Schasinglulu * - ACPUPLLCTRL.acpupll_timeout = 0x1; 343*91f16700Schasinglulu * - PMCTRL_ACPUPLLSEL.acpu_pllsw_cfg = 0x0; 344*91f16700Schasinglulu */ 345*91f16700Schasinglulu count = 0; 346*91f16700Schasinglulu do { 347*91f16700Schasinglulu reg0 = read_reg_mask(PMCTRL_ACPUCLKDIV, 0x3, 348*91f16700Schasinglulu SOC_PMCTRL_ACPUCLKDIV_acpu_ddr_clk_div_stat_START); 349*91f16700Schasinglulu reg1 = read_reg_mask(PMCTRL_ACPUCLKDIV, 0x3, 350*91f16700Schasinglulu SOC_PMCTRL_ACPUCLKDIV_cpuext_clk_div_stat_START); 351*91f16700Schasinglulu reg2 = read_reg_mask(PMCTRL_ACPUPLLCTRL, 0x1, 352*91f16700Schasinglulu SOC_PMCTRL_ACPUPLLCTRL_acpupll_timeout_START); 353*91f16700Schasinglulu if ((count++) > ACPU_DFS_STATE_CNT) { 354*91f16700Schasinglulu ERROR("%s: acpu clk div cfg timeout.\n", __func__); 355*91f16700Schasinglulu return -1; 356*91f16700Schasinglulu } 357*91f16700Schasinglulu } while ((reg1 != cpuext_cfg_val) || 358*91f16700Schasinglulu (reg0 != acpu_ddr_cfg_val) || 359*91f16700Schasinglulu (reg2 != 0x1)); 360*91f16700Schasinglulu 361*91f16700Schasinglulu write_reg_mask(PMCTRL_ACPUPLLSEL, 0x0, 362*91f16700Schasinglulu 0x1 << SOC_PMCTRL_ACPUPLLSEL_acpu_pllsw_cfg_START); 363*91f16700Schasinglulu 364*91f16700Schasinglulu /* 365*91f16700Schasinglulu * step 16: 366*91f16700Schasinglulu * - Polling PMCTRL_ACPUPLLSEL.acpupll_sw_stat == 0x1; 367*91f16700Schasinglulu * - ACPU_SC_VD_CTRL.force_clk_en = 0x0; 368*91f16700Schasinglulu * - ACPU_SC_VD_CTRL.clk_dis_cnt_en = 0x0; 369*91f16700Schasinglulu * - ACPU_SC_VD_CTRL.calibrate_en_ini = 0x0; 370*91f16700Schasinglulu * - ACPU_SC_VD_CTRL.calibrate_en_dif = 0x0; 371*91f16700Schasinglulu * - ACPU_SC_VD_CTRL.div_en_dif = 0x1; 372*91f16700Schasinglulu * - ACPU_SC_VD_CTRL.tune_en_int = 0x1; 373*91f16700Schasinglulu * - ACPU_SC_VD_CTRL.tune_en_dif = 0x1; 374*91f16700Schasinglulu * - PMCTRL_ACPUSYSPLLCFG.acpu_subsys_clk_div_sw = 0x0; 375*91f16700Schasinglulu * - ACPUSYSPLLCFG.acpu_syspll_clken_cfg = 0x0; 376*91f16700Schasinglulu */ 377*91f16700Schasinglulu count = 0; 378*91f16700Schasinglulu do { 379*91f16700Schasinglulu reg0 = read_reg_mask(PMCTRL_ACPUPLLSEL, 0x1, 380*91f16700Schasinglulu SOC_PMCTRL_ACPUPLLSEL_acpu_pllsw_stat_START); 381*91f16700Schasinglulu if ((count++) > ACPU_DFS_STATE_CNT) { 382*91f16700Schasinglulu ERROR("%s: acpu pll sw status timeout.\n", __func__); 383*91f16700Schasinglulu return -1; 384*91f16700Schasinglulu } 385*91f16700Schasinglulu } while (reg0 != 0x1); 386*91f16700Schasinglulu 387*91f16700Schasinglulu if (acpu_dvfs_profile[tar_prof].freq > 800000) 388*91f16700Schasinglulu write_reg_mask(ACPU_SC_VD_CTRL, 389*91f16700Schasinglulu ACPU_SC_VD_EN_ASIC_VAL, ACPU_SC_VD_EN_MASK); 390*91f16700Schasinglulu 391*91f16700Schasinglulu write_reg_mask(PMCTRL_ACPUSYSPLLCFG, 0x0, 392*91f16700Schasinglulu (0x3 << SOC_PMCTRL_ACPUSYSPLLCFG_acpu_subsys_clk_div_sw_START) | 393*91f16700Schasinglulu (0x1 << SOC_PMCTRL_ACPUSYSPLLCFG_acpu_syspll_clken_cfg_START)); 394*91f16700Schasinglulu 395*91f16700Schasinglulu return 0; 396*91f16700Schasinglulu } 397*91f16700Schasinglulu 398*91f16700Schasinglulu static int acpu_dvfs_freq_descend(unsigned int cur_prof, unsigned int tar_prof) 399*91f16700Schasinglulu { 400*91f16700Schasinglulu unsigned int reg0 = 0; 401*91f16700Schasinglulu unsigned int reg1 = 0; 402*91f16700Schasinglulu unsigned int reg2 = 0; 403*91f16700Schasinglulu unsigned int count = 0; 404*91f16700Schasinglulu unsigned int cpuext_cfg_val = 0; 405*91f16700Schasinglulu unsigned int acpu_ddr_cfg_val = 0; 406*91f16700Schasinglulu int ret = 0; 407*91f16700Schasinglulu 408*91f16700Schasinglulu ret = acpu_dvfs_syspll_cfg(tar_prof); 409*91f16700Schasinglulu if (ret) 410*91f16700Schasinglulu return -1; 411*91f16700Schasinglulu 412*91f16700Schasinglulu /* 413*91f16700Schasinglulu * step 4: 414*91f16700Schasinglulu * - Polling PMCTRL_ACPUPLLSEL.syspll_sw_stat == 0x1 415*91f16700Schasinglulu */ 416*91f16700Schasinglulu count = 0; 417*91f16700Schasinglulu do { 418*91f16700Schasinglulu reg0 = read_reg_mask(PMCTRL_ACPUPLLSEL, 0x1, 2); 419*91f16700Schasinglulu if ((count++) > ACPU_DFS_STATE_CNT) { 420*91f16700Schasinglulu ERROR("%s: syspll sw status timeout.\n", __func__); 421*91f16700Schasinglulu return -1; 422*91f16700Schasinglulu } 423*91f16700Schasinglulu } while (reg0 != 0x1); 424*91f16700Schasinglulu 425*91f16700Schasinglulu /* 426*91f16700Schasinglulu * Step 5: 427*91f16700Schasinglulu * - PMCTRL_ACPUPLLCTRL.acpupll_en_cfg = 0x0 428*91f16700Schasinglulu */ 429*91f16700Schasinglulu write_reg_mask(PMCTRL_ACPUPLLCTRL, 0x0, 0x1 << 0); 430*91f16700Schasinglulu 431*91f16700Schasinglulu /* 432*91f16700Schasinglulu * step 6 433*91f16700Schasinglulu * - Config PMCTRL_ACPUPLLFREQ and ACPUPLLFRAC 434*91f16700Schasinglulu */ 435*91f16700Schasinglulu mmio_write_32(PMCTRL_ACPUPLLFREQ, acpu_dvfs_profile[tar_prof].acpu_pll_freq); 436*91f16700Schasinglulu mmio_write_32(PMCTRL_ACPUPLLFRAC, acpu_dvfs_profile[tar_prof].acpu_pll_frac); 437*91f16700Schasinglulu 438*91f16700Schasinglulu /* 439*91f16700Schasinglulu * step 7: 440*91f16700Schasinglulu * - Wait 1us; 441*91f16700Schasinglulu * - Config PMCTRL_ACPUPLLCTRL.acpupll_en_cfg = 0x1 442*91f16700Schasinglulu */ 443*91f16700Schasinglulu count = 0; 444*91f16700Schasinglulu while (count < ACPU_WAIT_TIMEOUT) 445*91f16700Schasinglulu count++; 446*91f16700Schasinglulu 447*91f16700Schasinglulu write_reg_mask(PMCTRL_ACPUPLLCTRL, 448*91f16700Schasinglulu 0x1 << SOC_PMCTRL_ACPUPLLCTRL_acpupll_en_cfg_START, 449*91f16700Schasinglulu 0x1 << SOC_PMCTRL_ACPUPLLCTRL_acpupll_en_cfg_START); 450*91f16700Schasinglulu 451*91f16700Schasinglulu /* Enable VD functionality if > 800MHz */ 452*91f16700Schasinglulu if (acpu_dvfs_profile[tar_prof].freq > 800000) { 453*91f16700Schasinglulu 454*91f16700Schasinglulu write_reg_mask(ACPU_SC_VD_HPM_CTRL, 455*91f16700Schasinglulu HPM_OSC_DIV_VAL, HPM_OSC_DIV_MASK); 456*91f16700Schasinglulu 457*91f16700Schasinglulu /* 458*91f16700Schasinglulu * step 9: 459*91f16700Schasinglulu * - ACPU_SC_VD_HPM_CTRL.hpm_dly_exp = 0xC7A; 460*91f16700Schasinglulu * - ACPU_SC_VD_MASK_PATTERN_CTRL[12:0] = 0xCCB; 461*91f16700Schasinglulu */ 462*91f16700Schasinglulu write_reg_mask(ACPU_SC_VD_HPM_CTRL, 463*91f16700Schasinglulu HPM_DLY_EXP_VAL, HPM_DLY_EXP_MASK); 464*91f16700Schasinglulu write_reg_mask(ACPU_SC_VD_MASK_PATTERN_CTRL, 465*91f16700Schasinglulu ACPU_SC_VD_MASK_PATTERN_VAL, 466*91f16700Schasinglulu ACPU_SC_VD_MASK_PATTERN_MASK); 467*91f16700Schasinglulu 468*91f16700Schasinglulu /* 469*91f16700Schasinglulu * step 10: 470*91f16700Schasinglulu * - ACPU_SC_VD_DLY_TABLE0_CTRL = 0x1FFF; 471*91f16700Schasinglulu * - ACPU_SC_VD_DLY_TABLE1_CTRL = 0x1FFFFFF; 472*91f16700Schasinglulu * - ACPU_SC_VD_DLY_TABLE2_CTRL = 0x7FFFFFFF; 473*91f16700Schasinglulu * - ACPU_SC_VD_DLY_FIXED_CTRL = 0x1; 474*91f16700Schasinglulu */ 475*91f16700Schasinglulu mmio_write_32(ACPU_SC_VD_DLY_TABLE0_CTRL, 0x1FFF); 476*91f16700Schasinglulu mmio_write_32(ACPU_SC_VD_DLY_TABLE1_CTRL, 0x1FFFFFF); 477*91f16700Schasinglulu mmio_write_32(ACPU_SC_VD_DLY_TABLE2_CTRL, 0x7FFFFFFF); 478*91f16700Schasinglulu mmio_write_32(ACPU_SC_VD_DLY_FIXED_CTRL, 0x1); 479*91f16700Schasinglulu 480*91f16700Schasinglulu /* 481*91f16700Schasinglulu * step 11: 482*91f16700Schasinglulu * - ACPU_SC_VD_CTRL.shift_table0 = 0x1; 483*91f16700Schasinglulu * - ACPU_SC_VD_CTRL.shift_table1 = 0x3; 484*91f16700Schasinglulu * - ACPU_SC_VD_CTRL.shift_table2 = 0x5; 485*91f16700Schasinglulu * - ACPU_SC_VD_CTRL.shift_table3 = 0x6; 486*91f16700Schasinglulu * 487*91f16700Schasinglulu * step 12: 488*91f16700Schasinglulu * - ACPU_SC_VD_CTRL.tune = 0x7; 489*91f16700Schasinglulu */ 490*91f16700Schasinglulu write_reg_mask(ACPU_SC_VD_CTRL, 491*91f16700Schasinglulu ACPU_SC_VD_SHIFT_TABLE_TUNE_VAL, 492*91f16700Schasinglulu ACPU_SC_VD_SHIFT_TABLE_TUNE_MASK); 493*91f16700Schasinglulu } 494*91f16700Schasinglulu 495*91f16700Schasinglulu /* 496*91f16700Schasinglulu * step 13: 497*91f16700Schasinglulu * - Pollig PMCTRL_ACPUPLLCTRL.acpupll_timeout == 0x1; 498*91f16700Schasinglulu * - PMCTRL_ACPUPLLSEL.acpu_pllsw_cfg = 0x0; 499*91f16700Schasinglulu */ 500*91f16700Schasinglulu count = 0; 501*91f16700Schasinglulu do { 502*91f16700Schasinglulu reg0 = read_reg_mask(PMCTRL_ACPUPLLCTRL, 0x1, 503*91f16700Schasinglulu SOC_PMCTRL_ACPUPLLCTRL_acpupll_timeout_START); 504*91f16700Schasinglulu if ((count++) > ACPU_DFS_STATE_CNT) { 505*91f16700Schasinglulu ERROR("%s: acpupll timeout.\n", __func__); 506*91f16700Schasinglulu return -1; 507*91f16700Schasinglulu } 508*91f16700Schasinglulu } while (reg0 != 0x1); 509*91f16700Schasinglulu 510*91f16700Schasinglulu write_reg_mask(PMCTRL_ACPUPLLSEL, 0x0, 511*91f16700Schasinglulu 0x1 << SOC_PMCTRL_ACPUPLLSEL_acpu_pllsw_cfg_START); 512*91f16700Schasinglulu 513*91f16700Schasinglulu /* 514*91f16700Schasinglulu * step 14: 515*91f16700Schasinglulu * - Polling PMCTRL_ACPUPLLSEL.acpupll_sw_stat == 0x1; 516*91f16700Schasinglulu * - ACPU_SC_VD_CTRL.force_clk_en = 0x0; 517*91f16700Schasinglulu * - ACPU_SC_VD_CTRL.clk_dis_cnt_en = 0x0; 518*91f16700Schasinglulu * - ACPU_SC_VD_CTRL.calibrate_en_ini = 0x0; 519*91f16700Schasinglulu * - ACPU_SC_VD_CTRL.calibrate_en_dif = 0x0; 520*91f16700Schasinglulu * - ACPU_SC_VD_CTRL.div_en_dif = 0x1; 521*91f16700Schasinglulu * - ACPU_SC_VD_CTRL.tune_en_int = 0x1; 522*91f16700Schasinglulu * - ACPU_SC_VD_CTRL.tune_en_dif = 0x1; 523*91f16700Schasinglulu */ 524*91f16700Schasinglulu count = 0; 525*91f16700Schasinglulu do { 526*91f16700Schasinglulu reg0 = read_reg_mask(PMCTRL_ACPUPLLSEL, 0x1, 527*91f16700Schasinglulu SOC_PMCTRL_ACPUPLLSEL_acpu_pllsw_stat_START); 528*91f16700Schasinglulu if ((count++) > ACPU_DFS_STATE_CNT) { 529*91f16700Schasinglulu ERROR("%s: acpupll sw status timeout.\n", __func__); 530*91f16700Schasinglulu return -1; 531*91f16700Schasinglulu } 532*91f16700Schasinglulu } while (reg0 != 0x1); 533*91f16700Schasinglulu 534*91f16700Schasinglulu if (acpu_dvfs_profile[tar_prof].freq > 800000) 535*91f16700Schasinglulu write_reg_mask(ACPU_SC_VD_CTRL, 536*91f16700Schasinglulu ACPU_SC_VD_EN_ASIC_VAL, ACPU_SC_VD_EN_MASK); 537*91f16700Schasinglulu 538*91f16700Schasinglulu /* 539*91f16700Schasinglulu * step 15: 540*91f16700Schasinglulu * - PMCTRL_ACPUSYSPLLCFG.acpu_subsys_clk_div_sw = 0x0; 541*91f16700Schasinglulu * - ACPUSYSPLLCFG.acpu_syspll_clken_cfg = 0x0; 542*91f16700Schasinglulu */ 543*91f16700Schasinglulu write_reg_mask(PMCTRL_ACPUSYSPLLCFG, 0x0, 544*91f16700Schasinglulu (0x3 << SOC_PMCTRL_ACPUSYSPLLCFG_acpu_subsys_clk_div_sw_START) | 545*91f16700Schasinglulu (0x1 << SOC_PMCTRL_ACPUSYSPLLCFG_acpu_syspll_clken_cfg_START)); 546*91f16700Schasinglulu 547*91f16700Schasinglulu /* 548*91f16700Schasinglulu * step 16: 549*91f16700Schasinglulu * - Polling ACPU_SC_CPU_STAT.clk_div_status_vd == 0x0; 550*91f16700Schasinglulu */ 551*91f16700Schasinglulu count = 0; 552*91f16700Schasinglulu do { 553*91f16700Schasinglulu reg0 = read_reg_mask(ACPU_SC_CPU_STAT, 0x3, 554*91f16700Schasinglulu ACPU_SC_CPU_STAT_CLK_DIV_STATUS_VD_SHIFT); 555*91f16700Schasinglulu if ((count++) > ACPU_DFS_STATE_CNT) { 556*91f16700Schasinglulu ERROR("%s: clk div status timeout.\n", __func__); 557*91f16700Schasinglulu return -1; 558*91f16700Schasinglulu } 559*91f16700Schasinglulu } while (reg0 != 0x0); 560*91f16700Schasinglulu 561*91f16700Schasinglulu acpu_dvfs_clk_div_cfg(tar_prof, &cpuext_cfg_val, &acpu_ddr_cfg_val); 562*91f16700Schasinglulu 563*91f16700Schasinglulu /* 564*91f16700Schasinglulu * step 17: 565*91f16700Schasinglulu * - Polling PMCTRL_ACPUCLKDIV.cpuext_clk_div_stat; 566*91f16700Schasinglulu * - Polling ACPUCLKDIV.acpu_ddr_clk_div_stat; 567*91f16700Schasinglulu * - PMCTRL_ACPUVOLPMUADDR = 0x1006C; 568*91f16700Schasinglulu */ 569*91f16700Schasinglulu count = 0; 570*91f16700Schasinglulu do { 571*91f16700Schasinglulu reg0 = read_reg_mask(PMCTRL_ACPUCLKDIV, 0x3, 572*91f16700Schasinglulu SOC_PMCTRL_ACPUCLKDIV_cpuext_clk_div_stat_START); 573*91f16700Schasinglulu reg1 = read_reg_mask(PMCTRL_ACPUCLKDIV, 0x3, 574*91f16700Schasinglulu SOC_PMCTRL_ACPUCLKDIV_acpu_ddr_clk_div_stat_START); 575*91f16700Schasinglulu if ((count++) > ACPU_DFS_STATE_CNT) { 576*91f16700Schasinglulu ERROR("%s: acpu clk div cfg timeout.\n", __func__); 577*91f16700Schasinglulu return -1; 578*91f16700Schasinglulu } 579*91f16700Schasinglulu } while ((reg0 != cpuext_cfg_val) || (reg1 != acpu_ddr_cfg_val)); 580*91f16700Schasinglulu 581*91f16700Schasinglulu mmio_write_32(PMCTRL_ACPUVOLPMUADDR, 0x100da); 582*91f16700Schasinglulu 583*91f16700Schasinglulu /* 584*91f16700Schasinglulu * step 16: 585*91f16700Schasinglulu * - Polling PMCTRL_ACPUPLLSEL.acpupll_sw_stat == 0x1; 586*91f16700Schasinglulu * - ACPU_SC_VD_CTRL.force_clk_en = 0x0; 587*91f16700Schasinglulu * - ACPU_SC_VD_CTRL.clk_dis_cnt_en = 0x0; 588*91f16700Schasinglulu * - ACPU_SC_VD_CTRL.calibrate_en_ini = 0x0; 589*91f16700Schasinglulu * - ACPU_SC_VD_CTRL.calibrate_en_dif = 0x0; 590*91f16700Schasinglulu * - ACPU_SC_VD_CTRL.div_en_dif = 0x1; 591*91f16700Schasinglulu * - ACPU_SC_VD_CTRL.tune_en_int = 0x1; 592*91f16700Schasinglulu * - ACPU_SC_VD_CTRL.tune_en_dif = 0x1; 593*91f16700Schasinglulu * - PMCTRL_ACPUSYSPLLCFG.acpu_subsys_clk_div_sw = 0x0; 594*91f16700Schasinglulu * - ACPUSYSPLLCFG.acpu_syspll_clken_cfg = 0x0; 595*91f16700Schasinglulu */ 596*91f16700Schasinglulu write_reg_mask(PMCTRL_ACPUDESTVOL, 597*91f16700Schasinglulu acpu_dvfs_profile[tar_prof].acpu_vol_profile, 598*91f16700Schasinglulu ((0x1 << (SOC_PMCTRL_ACPUDESTVOL_acpu_dest_vol_END + 1)) - 1)); 599*91f16700Schasinglulu 600*91f16700Schasinglulu /* 601*91f16700Schasinglulu * step 19: 602*91f16700Schasinglulu * - Polling PMCTRL_ACPUDESTVOL.acpu_vol_using == ACPUDESTVOL.acpu_dest_vol 603*91f16700Schasinglulu * - ACPUVOLTIMEOUT.acpu_vol_timeout = 0x1; 604*91f16700Schasinglulu */ 605*91f16700Schasinglulu count = 0; 606*91f16700Schasinglulu do { 607*91f16700Schasinglulu reg0 = read_reg_mask(PMCTRL_ACPUDESTVOL, 0x7F, 608*91f16700Schasinglulu SOC_PMCTRL_ACPUDESTVOL_acpu_dest_vol_START); 609*91f16700Schasinglulu reg1 = read_reg_mask(PMCTRL_ACPUDESTVOL, 0x7F, 610*91f16700Schasinglulu SOC_PMCTRL_ACPUDESTVOL_acpu_vol_using_START); 611*91f16700Schasinglulu reg2 = read_reg_mask(PMCTRL_ACPUVOLTTIMEOUT, 0x1, 612*91f16700Schasinglulu SOC_PMCTRL_ACPUVOLTIMEOUT_acpu_vol_timeout_START); 613*91f16700Schasinglulu if ((count++) > ACPU_DFS_STATE_CNT) { 614*91f16700Schasinglulu ERROR("%s: acpu destvol cfg timeout.\n", __func__); 615*91f16700Schasinglulu return -1; 616*91f16700Schasinglulu } 617*91f16700Schasinglulu } while ((reg0 != reg1) || (reg2 != 0x1)); 618*91f16700Schasinglulu 619*91f16700Schasinglulu return 0; 620*91f16700Schasinglulu } 621*91f16700Schasinglulu 622*91f16700Schasinglulu int acpu_dvfs_target(unsigned int curr_prof, unsigned int target_prof) 623*91f16700Schasinglulu { 624*91f16700Schasinglulu int ret = 0; 625*91f16700Schasinglulu 626*91f16700Schasinglulu if (curr_prof == target_prof) { 627*91f16700Schasinglulu INFO("%s: target_prof is equal curr_prof: is %d!\n", 628*91f16700Schasinglulu __func__, curr_prof); 629*91f16700Schasinglulu return 0; 630*91f16700Schasinglulu } 631*91f16700Schasinglulu 632*91f16700Schasinglulu if ((curr_prof >= ACPU_FREQ_MAX_NUM) || 633*91f16700Schasinglulu (target_prof >= ACPU_FREQ_MAX_NUM)) { 634*91f16700Schasinglulu INFO("%s: invalid parameter %d %d\n", 635*91f16700Schasinglulu __func__, curr_prof, target_prof); 636*91f16700Schasinglulu return -1; 637*91f16700Schasinglulu } 638*91f16700Schasinglulu 639*91f16700Schasinglulu if (target_prof > acpu_dvfs_sram_buf->support_freq_num) 640*91f16700Schasinglulu target_prof = acpu_dvfs_sram_buf->support_freq_num; 641*91f16700Schasinglulu 642*91f16700Schasinglulu if (target_prof < curr_prof) 643*91f16700Schasinglulu ret = acpu_dvfs_freq_descend(curr_prof, target_prof); 644*91f16700Schasinglulu else if (target_prof > curr_prof) 645*91f16700Schasinglulu ret = acpu_dvfs_freq_ascend(curr_prof, target_prof); 646*91f16700Schasinglulu 647*91f16700Schasinglulu if (ret) { 648*91f16700Schasinglulu ERROR("%s: acpu_dvfs_target failed!\n", __func__); 649*91f16700Schasinglulu return -1; 650*91f16700Schasinglulu } 651*91f16700Schasinglulu 652*91f16700Schasinglulu /* Complete acpu dvfs setting and set magic number */ 653*91f16700Schasinglulu acpu_dvfs_sram_buf->start_prof = target_prof; 654*91f16700Schasinglulu acpu_dvfs_sram_buf->magic = ACPU_VALID_VOLTAGE_MAGIC; 655*91f16700Schasinglulu 656*91f16700Schasinglulu mmio_write_32(DDR_DFS_FREQ_ADDR, 800000); 657*91f16700Schasinglulu return 0; 658*91f16700Schasinglulu } 659*91f16700Schasinglulu 660*91f16700Schasinglulu static int acpu_dvfs_set_freq(void) 661*91f16700Schasinglulu { 662*91f16700Schasinglulu unsigned int i; 663*91f16700Schasinglulu unsigned int curr_prof; 664*91f16700Schasinglulu unsigned int target_prof; 665*91f16700Schasinglulu unsigned int max_freq = 0; 666*91f16700Schasinglulu 667*91f16700Schasinglulu max_freq = acpu_dvfs_sram_buf->support_freq_max; 668*91f16700Schasinglulu 669*91f16700Schasinglulu for (i = 0; i < acpu_dvfs_sram_buf->support_freq_num; i++) { 670*91f16700Schasinglulu 671*91f16700Schasinglulu if (max_freq == hi6220_acpu_profile[i].freq) { 672*91f16700Schasinglulu target_prof = i; 673*91f16700Schasinglulu break; 674*91f16700Schasinglulu } 675*91f16700Schasinglulu } 676*91f16700Schasinglulu 677*91f16700Schasinglulu if (i == acpu_dvfs_sram_buf->support_freq_num) { 678*91f16700Schasinglulu ERROR("%s: cannot found max freq profile\n", __func__); 679*91f16700Schasinglulu return -1; 680*91f16700Schasinglulu } 681*91f16700Schasinglulu 682*91f16700Schasinglulu curr_prof = 0; 683*91f16700Schasinglulu target_prof = i; 684*91f16700Schasinglulu 685*91f16700Schasinglulu /* if max freq is 208MHz, do nothing */ 686*91f16700Schasinglulu if (curr_prof == target_prof) 687*91f16700Schasinglulu return 0; 688*91f16700Schasinglulu 689*91f16700Schasinglulu if (acpu_dvfs_target(curr_prof, target_prof)) { 690*91f16700Schasinglulu ERROR("%s: set acpu freq failed!", __func__); 691*91f16700Schasinglulu return -1; 692*91f16700Schasinglulu } 693*91f16700Schasinglulu 694*91f16700Schasinglulu INFO("%s: support freq num is %d\n", 695*91f16700Schasinglulu __func__, acpu_dvfs_sram_buf->support_freq_num); 696*91f16700Schasinglulu INFO("%s: start prof is 0x%x\n", 697*91f16700Schasinglulu __func__, acpu_dvfs_sram_buf->start_prof); 698*91f16700Schasinglulu INFO("%s: magic is 0x%x\n", 699*91f16700Schasinglulu __func__, acpu_dvfs_sram_buf->magic); 700*91f16700Schasinglulu INFO("%s: voltage:\n", __func__); 701*91f16700Schasinglulu for (i = 0; i < acpu_dvfs_sram_buf->support_freq_num; i++) 702*91f16700Schasinglulu INFO(" - %d: 0x%x\n", i, acpu_dvfs_sram_buf->vol[i]); 703*91f16700Schasinglulu 704*91f16700Schasinglulu NOTICE("%s: set acpu freq success!", __func__); 705*91f16700Schasinglulu return 0; 706*91f16700Schasinglulu } 707*91f16700Schasinglulu 708*91f16700Schasinglulu struct acpu_dvfs_volt_setting { 709*91f16700Schasinglulu unsigned int magic; 710*91f16700Schasinglulu unsigned int support_freq_num; 711*91f16700Schasinglulu unsigned int support_freq_max; 712*91f16700Schasinglulu unsigned int start_prof; 713*91f16700Schasinglulu unsigned int vol[7]; 714*91f16700Schasinglulu unsigned int hmp_dly_threshold[7]; 715*91f16700Schasinglulu }; 716*91f16700Schasinglulu 717*91f16700Schasinglulu static void acpu_dvfs_volt_init(void) 718*91f16700Schasinglulu { 719*91f16700Schasinglulu struct acpu_dvfs_volt_setting *volt; 720*91f16700Schasinglulu 721*91f16700Schasinglulu /* 722*91f16700Schasinglulu * - set default voltage; 723*91f16700Schasinglulu * - set pmu address; 724*91f16700Schasinglulu * - set voltage up and down step; 725*91f16700Schasinglulu * - set voltage stable time; 726*91f16700Schasinglulu */ 727*91f16700Schasinglulu mmio_write_32(PMCTRL_ACPUDFTVOL, 0x4a); 728*91f16700Schasinglulu mmio_write_32(PMCTRL_ACPUVOLPMUADDR, 0xda); 729*91f16700Schasinglulu mmio_write_32(PMCTRL_ACPUVOLUPSTEP, 0x1); 730*91f16700Schasinglulu mmio_write_32(PMCTRL_ACPUVOLDNSTEP, 0x1); 731*91f16700Schasinglulu mmio_write_32(PMCTRL_ACPUPMUVOLUPTIME, 0x60); 732*91f16700Schasinglulu mmio_write_32(PMCTRL_ACPUPMUVOLDNTIME, 0x60); 733*91f16700Schasinglulu mmio_write_32(PMCTRL_ACPUCLKOFFCFG, 0x1000); 734*91f16700Schasinglulu 735*91f16700Schasinglulu volt = (void *)MEMORY_AXI_ACPU_FREQ_VOL_ADDR; 736*91f16700Schasinglulu volt->magic = 0x5a5ac5c5; 737*91f16700Schasinglulu volt->support_freq_num = 5; 738*91f16700Schasinglulu volt->support_freq_max = 1200000; 739*91f16700Schasinglulu volt->start_prof = 4; 740*91f16700Schasinglulu volt->vol[0] = 0x49; 741*91f16700Schasinglulu volt->vol[1] = 0x49; 742*91f16700Schasinglulu volt->vol[2] = 0x50; 743*91f16700Schasinglulu volt->vol[3] = 0x60; 744*91f16700Schasinglulu volt->vol[4] = 0x78; 745*91f16700Schasinglulu volt->vol[5] = 0x78; 746*91f16700Schasinglulu volt->vol[6] = 0x78; 747*91f16700Schasinglulu 748*91f16700Schasinglulu volt->hmp_dly_threshold[0] = 0x0; 749*91f16700Schasinglulu volt->hmp_dly_threshold[1] = 0x0; 750*91f16700Schasinglulu volt->hmp_dly_threshold[2] = 0x0; 751*91f16700Schasinglulu volt->hmp_dly_threshold[3] = 0x0e8b0e45; 752*91f16700Schasinglulu volt->hmp_dly_threshold[4] = 0x10691023; 753*91f16700Schasinglulu volt->hmp_dly_threshold[5] = 0x10691023; 754*91f16700Schasinglulu volt->hmp_dly_threshold[6] = 0x10691023; 755*91f16700Schasinglulu 756*91f16700Schasinglulu INFO("%s: success!\n", __func__); 757*91f16700Schasinglulu } 758*91f16700Schasinglulu 759*91f16700Schasinglulu void init_acpu_dvfs(void) 760*91f16700Schasinglulu { 761*91f16700Schasinglulu unsigned int i = 0; 762*91f16700Schasinglulu 763*91f16700Schasinglulu INFO("%s: pmic version %d\n", __func__, 764*91f16700Schasinglulu mmio_read_8(HI6553_VERSION_REG)); 765*91f16700Schasinglulu 766*91f16700Schasinglulu /* init parameters */ 767*91f16700Schasinglulu mmio_write_32(ACPU_CHIP_MAX_FREQ, efuse_acpu_freq[8]); 768*91f16700Schasinglulu INFO("%s: ACPU_CHIP_MAX_FREQ=0x%x.\n", 769*91f16700Schasinglulu __func__, mmio_read_32(ACPU_CHIP_MAX_FREQ)); 770*91f16700Schasinglulu 771*91f16700Schasinglulu /* set maximum support frequency to 1.2GHz */ 772*91f16700Schasinglulu for (i = 0; i < ACPU_FREQ_MAX_NUM; i++) 773*91f16700Schasinglulu acpu_dvfs_sram_buf->vol[i] = hi6220_acpu_profile[i].acpu_vol_profile; 774*91f16700Schasinglulu 775*91f16700Schasinglulu acpu_dvfs_sram_buf->support_freq_num = ACPU_FREQ_MAX_NUM; 776*91f16700Schasinglulu acpu_dvfs_sram_buf->support_freq_max = 1200000; 777*91f16700Schasinglulu 778*91f16700Schasinglulu /* init acpu dvfs */ 779*91f16700Schasinglulu acpu_dvfs_volt_init(); 780*91f16700Schasinglulu acpu_dvfs_set_freq(); 781*91f16700Schasinglulu } 782