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