• 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 <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 
29 struct 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 
37 struct 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 
44 struct 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 
51 struct 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 
60 unsigned 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 
67 struct 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 
77 struct acpu_dvfs_opp_para *acpu_dvfs_profile = hi6220_acpu_profile;
78 struct acpu_dvfs_sram_stru *acpu_dvfs_sram_buf =
79 	(struct acpu_dvfs_sram_stru *)MEMORY_AXI_ACPU_FREQ_VOL_ADDR;
80 
write_reg_mask(uintptr_t addr,uint32_t val,uint32_t mask)81 static 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 
read_reg_mask(uintptr_t addr,uint32_t mask,uint32_t offset)91 static 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 
acpu_dvfs_syspll_cfg(unsigned int prof_id)101 static 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 
acpu_dvfs_clk_div_cfg(unsigned int prof_id,unsigned int * cpuext_cfg,unsigned int * acpu_ddr_cfg)153 static 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 
acpu_dvfs_freq_ascend(unsigned int cur_prof,unsigned int tar_prof)185 static 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 
acpu_dvfs_freq_descend(unsigned int cur_prof,unsigned int tar_prof)395 static 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 
acpu_dvfs_target(unsigned int curr_prof,unsigned int target_prof)619 int 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 
acpu_dvfs_set_freq(void)657 static 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 
705 struct 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 
acpu_dvfs_volt_init(void)714 static 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 
init_acpu_dvfs(void)756 void 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 }
779