1
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
16union msr_pstate {
17 struct {
18 unsigned fid:6;
19 unsigned did:3;
20 unsigned vid:7;
21 unsigned res1:6;
22 unsigned nbdid:1;
23 unsigned res2:2;
24 unsigned nbvid:7;
25 unsigned iddval:8;
26 unsigned idddiv:2;
27 unsigned res3:21;
28 unsigned en:1;
29 } bits;
30 struct {
31 unsigned fid:8;
32 unsigned did:6;
33 unsigned vid:8;
34 unsigned iddval:8;
35 unsigned idddiv:2;
36 unsigned res1:30;
37 unsigned en:1;
38 } fam17h_bits;
39 unsigned long long val;
40};
41
42static int get_did(int family, union msr_pstate pstate)
43{
44 int t;
45
46 if (family == 0x12)
47 t = pstate.val & 0xf;
48 else if (family == 0x17)
49 t = pstate.fam17h_bits.did;
50 else
51 t = pstate.bits.did;
52
53 return t;
54}
55
56static int get_cof(int family, union msr_pstate pstate)
57{
58 int t;
59 int fid, did, cof;
60
61 did = get_did(family, pstate);
62 if (family == 0x17) {
63 fid = pstate.fam17h_bits.fid;
64 cof = 200 * fid / did;
65 } else {
66 t = 0x10;
67 fid = pstate.bits.fid;
68 if (family == 0x11)
69 t = 0x8;
70 cof = (100 * (fid + t)) >> did;
71 }
72 return cof;
73}
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88int decode_pstates(unsigned int cpu, unsigned int cpu_family,
89 int boost_states, unsigned long *pstates, int *no)
90{
91 int i, psmax, pscur;
92 union msr_pstate pstate;
93 unsigned long long val;
94
95
96
97
98
99 if (cpu_family < 0x10 || cpu_family == 0x14)
100 return -1;
101
102 if (read_msr(cpu, MSR_AMD_PSTATE_LIMIT, &val))
103 return -1;
104
105 psmax = (val >> 4) & 0x7;
106
107 if (read_msr(cpu, MSR_AMD_PSTATE_STATUS, &val))
108 return -1;
109
110 pscur = val & 0x7;
111
112 pscur += boost_states;
113 psmax += boost_states;
114 for (i = 0; i <= psmax; i++) {
115 if (i >= MAX_HW_PSTATES) {
116 fprintf(stderr, "HW pstates [%d] exceeding max [%d]\n",
117 psmax, MAX_HW_PSTATES);
118 return -1;
119 }
120 if (read_msr(cpu, MSR_AMD_PSTATE + i, &pstate.val))
121 return -1;
122 pstates[i] = get_cof(cpu_family, pstate);
123 }
124 *no = i;
125 return 0;
126}
127
128int amd_pci_get_num_boost_states(int *active, int *states)
129{
130 struct pci_access *pci_acc;
131 struct pci_dev *device;
132 uint8_t val = 0;
133
134 *active = *states = 0;
135
136 device = pci_slot_func_init(&pci_acc, 0x18, 4);
137
138 if (device == NULL)
139 return -ENODEV;
140
141 val = pci_read_byte(device, 0x15c);
142 if (val & 3)
143 *active = 1;
144 else
145 *active = 0;
146 *states = (val >> 2) & 7;
147
148 pci_cleanup(pci_acc);
149 return 0;
150}
151#endif
152