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