hisi_dvfs.c 22 KB

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