1 // SPDX-License-Identifier: GPL-2.0 2 #if defined(__i386__) || defined(__x86_64__) 3 #include <unistd.h> 4 #include <errno.h> 5 #include <stdio.h> 6 #include <stdint.h> 7 8 #include <pci/pci.h> 9 10 #include "helpers/helpers.h" 11 12 #define MSR_AMD_PSTATE_STATUS 0xc0010063 13 #define MSR_AMD_PSTATE 0xc0010064 14 #define MSR_AMD_PSTATE_LIMIT 0xc0010061 15 16 union core_pstate { 17 /* pre fam 17h: */ 18 struct { 19 unsigned fid:6; 20 unsigned did:3; 21 unsigned vid:7; 22 unsigned res1:6; 23 unsigned nbdid:1; 24 unsigned res2:2; 25 unsigned nbvid:7; 26 unsigned iddval:8; 27 unsigned idddiv:2; 28 unsigned res3:21; 29 unsigned en:1; 30 } pstate; 31 /* since fam 17h: */ 32 struct { 33 unsigned fid:8; 34 unsigned did:6; 35 unsigned vid:8; 36 unsigned iddval:8; 37 unsigned idddiv:2; 38 unsigned res1:31; 39 unsigned en:1; 40 } pstatedef; 41 unsigned long long val; 42 }; 43 44 static int get_did(union core_pstate pstate) 45 { 46 int t; 47 48 if (cpupower_cpu_info.caps & CPUPOWER_CAP_AMD_PSTATEDEF) 49 t = pstate.pstatedef.did; 50 else if (cpupower_cpu_info.family == 0x12) 51 t = pstate.val & 0xf; 52 else 53 t = pstate.pstate.did; 54 55 return t; 56 } 57 58 static int get_cof(union core_pstate pstate) 59 { 60 int t; 61 int fid, did, cof; 62 63 did = get_did(pstate); 64 if (cpupower_cpu_info.caps & CPUPOWER_CAP_AMD_PSTATEDEF) { 65 fid = pstate.pstatedef.fid; 66 cof = 200 * fid / did; 67 } else { 68 t = 0x10; 69 fid = pstate.pstate.fid; 70 if (cpupower_cpu_info.family == 0x11) 71 t = 0x8; 72 cof = (100 * (fid + t)) >> did; 73 } 74 return cof; 75 } 76 77 /* Needs: 78 * cpu -> the cpu that gets evaluated 79 * boost_states -> how much boost states the machines support 80 * 81 * Fills up: 82 * pstates -> a pointer to an array of size MAX_HW_PSTATES 83 * must be initialized with zeros. 84 * All available HW pstates (including boost states) 85 * no -> amount of pstates above array got filled up with 86 * 87 * returns zero on success, -1 on failure 88 */ 89 int decode_pstates(unsigned int cpu, int boost_states, 90 unsigned long *pstates, int *no) 91 { 92 int i, psmax; 93 union core_pstate pstate; 94 unsigned long long val; 95 96 /* Only read out frequencies from HW if HW Pstate is supported, 97 * otherwise frequencies are exported via ACPI tables. 98 */ 99 if (!(cpupower_cpu_info.caps & CPUPOWER_CAP_AMD_HW_PSTATE)) 100 return -1; 101 102 if (read_msr(cpu, MSR_AMD_PSTATE_LIMIT, &val)) 103 return -1; 104 105 psmax = (val >> 4) & 0x7; 106 psmax += boost_states; 107 for (i = 0; i <= psmax; i++) { 108 if (i >= MAX_HW_PSTATES) { 109 fprintf(stderr, "HW pstates [%d] exceeding max [%d]\n", 110 psmax, MAX_HW_PSTATES); 111 return -1; 112 } 113 if (read_msr(cpu, MSR_AMD_PSTATE + i, &pstate.val)) 114 return -1; 115 116 /* The enabled bit (bit 63) is common for all families */ 117 if (!pstate.pstatedef.en) 118 continue; 119 120 pstates[i] = get_cof(pstate); 121 } 122 *no = i; 123 return 0; 124 } 125 126 int amd_pci_get_num_boost_states(int *active, int *states) 127 { 128 struct pci_access *pci_acc; 129 struct pci_dev *device; 130 uint8_t val = 0; 131 132 *active = *states = 0; 133 134 device = pci_slot_func_init(&pci_acc, 0x18, 4); 135 136 if (device == NULL) 137 return -ENODEV; 138 139 val = pci_read_byte(device, 0x15c); 140 if (val & 3) 141 *active = 1; 142 else 143 *active = 0; 144 *states = (val >> 2) & 7; 145 146 pci_cleanup(pci_acc); 147 return 0; 148 } 149 #endif /* defined(__i386__) || defined(__x86_64__) */ 150