xref: /aosp_15_r20/external/coreboot/src/soc/mediatek/common/pmif_clk.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <commonlib/helpers.h>
4 #include <console/console.h>
5 #include <soc/pmif_clk_common.h>
6 #include <soc/pmif_sw.h>
7 
pmif_ulposc_check(u32 current_clk,u32 target_clk)8 int pmif_ulposc_check(u32 current_clk, u32 target_clk)
9 {
10 	if (current_clk < (target_clk * (1000 - CAL_TOL_RATE) / 1000) ||
11 	    current_clk > (target_clk * (1000 + CAL_TOL_RATE) / 1000)) {
12 		printk(BIOS_WARNING,
13 		       "[%s] calibration fail: cur=%dM, CAL_RATE=%d, target=%dM\n",
14 		       __func__, current_clk, CAL_TOL_RATE, target_clk);
15 		return -1;
16 	}
17 
18 	printk(BIOS_DEBUG,
19 	       "[%s] calibration done: cur=%dM, CAL_RATE=%d, target=%dM\n",
20 	       __func__, current_clk, CAL_TOL_RATE, target_clk);
21 
22 	return 0;
23 }
24 
pmif_ulposc_cali(u32 target_val)25 int pmif_ulposc_cali(u32 target_val)
26 {
27 	u32 current_val, min = 0, max = CAL_MAX_VAL, middle;
28 	int diff_by_min, diff_by_max, cal_result;
29 
30 	do {
31 		middle = (min + max) / 2;
32 		if (middle == min)
33 			break;
34 
35 		current_val = pmif_get_ulposc_freq_mhz(middle);
36 		if (current_val > target_val)
37 			max = middle;
38 		else
39 			min = middle;
40 	} while (min <= max);
41 
42 	diff_by_min = pmif_get_ulposc_freq_mhz(min) - target_val;
43 	diff_by_min = ABS(diff_by_min);
44 
45 	diff_by_max = pmif_get_ulposc_freq_mhz(max) - target_val;
46 	diff_by_max = ABS(diff_by_max);
47 
48 	cal_result = (diff_by_min < diff_by_max) ? min : max;
49 	current_val = pmif_get_ulposc_freq_mhz(cal_result);
50 
51 	/* check if calibrated value is in the range of target value +- 15% */
52 	return pmif_ulposc_check(current_val, target_val);
53 }
54