blob: 22a67fdcae1eec3bd7f6262d277733097ffd8ba0 [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
Haojian Zhuang934ae712017-05-24 08:47:49 +08007#include <assert.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +00008#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
Haojian Zhuang934ae712017-05-24 08:47:49 +080019#include <hi6220.h>
20#include <hi6553.h>
21#include <hisi_sram_map.h>
Haojian Zhuang934ae712017-05-24 08:47:49 +080022
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
32struct 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
40struct 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
47struct 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
54struct 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
63unsigned 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
70struct 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
80struct acpu_dvfs_opp_para *acpu_dvfs_profile = hi6220_acpu_profile;
81struct acpu_dvfs_sram_stru *acpu_dvfs_sram_buf =
82 (struct acpu_dvfs_sram_stru *)MEMORY_AXI_ACPU_FREQ_VOL_ADDR;
83
84static 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
94static 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
104static 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
156static 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
188static 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
398static 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
622int 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
660static 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
708struct 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
717static 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
759void 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}