Felix Held | a63f859 | 2023-03-24 16:30:55 +0100 | [diff] [blame^] | 1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
| 2 | |
| 3 | #include <amdblocks/cpu.h> |
| 4 | #include <console/console.h> |
| 5 | #include <soc/msr.h> |
| 6 | #include <types.h> |
| 7 | |
| 8 | #define PSTATE_DEF_FREQ_DIV_MIN 0x8 |
| 9 | #define PSTATE_DEF_EIGHTH_STEP_MAX 0x1A |
| 10 | #define PSTATE_DEF_FREQ_DIV_MAX 0x3E |
| 11 | #define PSTATE_DEF_CORE_FREQ_BASE 25 |
| 12 | |
| 13 | uint32_t get_pstate_core_freq(union pstate_msr pstate_reg) |
| 14 | { |
| 15 | uint32_t core_freq, core_freq_mul, core_freq_div; |
| 16 | bool valid_freq_divisor; |
| 17 | |
| 18 | /* Core frequency multiplier */ |
| 19 | core_freq_mul = pstate_reg.cpu_fid_0_7; |
| 20 | |
| 21 | /* Core frequency divisor ID */ |
| 22 | core_freq_div = pstate_reg.cpu_dfs_id; |
| 23 | |
| 24 | if (core_freq_div == 0) { |
| 25 | return 0; |
| 26 | } else if ((core_freq_div >= PSTATE_DEF_FREQ_DIV_MIN) |
| 27 | && (core_freq_div <= PSTATE_DEF_EIGHTH_STEP_MAX)) { |
| 28 | /* Allow 1/8 integer steps for this range */ |
| 29 | valid_freq_divisor = true; |
| 30 | } else if ((core_freq_div > PSTATE_DEF_EIGHTH_STEP_MAX) |
| 31 | && (core_freq_div <= PSTATE_DEF_FREQ_DIV_MAX) && !(core_freq_div & 0x1)) { |
| 32 | /* Only allow 1/4 integer steps for this range */ |
| 33 | valid_freq_divisor = true; |
| 34 | } else { |
| 35 | valid_freq_divisor = false; |
| 36 | } |
| 37 | |
| 38 | if (valid_freq_divisor) { |
| 39 | /* 25 * core_freq_mul / (core_freq_div / 8) */ |
| 40 | core_freq = |
| 41 | ((PSTATE_DEF_CORE_FREQ_BASE * core_freq_mul * 8) / (core_freq_div)); |
| 42 | } else { |
| 43 | printk(BIOS_WARNING, "Undefined core_freq_div %x used. Force to 1.\n", |
| 44 | core_freq_div); |
| 45 | core_freq = (PSTATE_DEF_CORE_FREQ_BASE * core_freq_mul); |
| 46 | } |
| 47 | return core_freq; |
| 48 | } |