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