blob: 0d4f893b911e35184c5b689f6723ff128d650904 [file] [log] [blame]
Haojian Zhuang934ae712017-05-24 08:47:49 +08001/*
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
29struct 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
37struct 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
44struct 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
51struct 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
60unsigned 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
67struct 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
77struct acpu_dvfs_opp_para *acpu_dvfs_profile = hi6220_acpu_profile;
78struct acpu_dvfs_sram_stru *acpu_dvfs_sram_buf =
79 (struct acpu_dvfs_sram_stru *)MEMORY_AXI_ACPU_FREQ_VOL_ADDR;
80
81static 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
91static 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
101static 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
153static 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
185static 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
395static 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
619int 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
657static 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
705struct 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
714static 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
756void 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}