blob: cfd1dbce6b232a1c3d2b77fc371289f2c8cd5cb9 [file] [log] [blame]
Rex-BC Chen3d6816a2021-05-03 16:25:49 +08001/* 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
Rex-BC Chen823dcea2022-07-14 14:15:43 +08008int 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,
Bo-Chen Chendcdbda52022-08-18 18:28:27 +080013 "[%s] calibration fail: cur=%dM, CAL_RATE=%d, target=%dM\n",
Rex-BC Chen823dcea2022-07-14 14:15:43 +080014 __func__, current_clk, CAL_TOL_RATE, target_clk);
15 return -1;
16 }
17
18 printk(BIOS_DEBUG,
Bo-Chen Chendcdbda52022-08-18 18:28:27 +080019 "[%s] calibration done: cur=%dM, CAL_RATE=%d, target=%dM\n",
Rex-BC Chen823dcea2022-07-14 14:15:43 +080020 __func__, current_clk, CAL_TOL_RATE, target_clk);
21
22 return 0;
23}
24
Rex-BC Chen3d6816a2021-05-03 16:25:49 +080025int 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% */
Rex-BC Chen823dcea2022-07-14 14:15:43 +080052 return pmif_ulposc_check(current_val, target_val);
Rex-BC Chen3d6816a2021-05-03 16:25:49 +080053}