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