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