10 #if defined(__i386__) || defined(__x86_64__)
23 #define PCI_NON_PC0_OFFSET 0xb0
24 #define PCI_PC1_OFFSET 0xb4
25 #define PCI_PC6_OFFSET 0xb8
27 #define PCI_MONITOR_ENABLE_REG 0xe0
29 #define PCI_NON_PC0_ENABLE_BIT 0
30 #define PCI_PC1_ENABLE_BIT 1
31 #define PCI_PC6_ENABLE_BIT 2
33 #define PCI_NBP1_STAT_OFFSET 0x98
34 #define PCI_NBP1_ACTIVE_BIT 2
35 #define PCI_NBP1_ENTERED_BIT 1
37 #define PCI_NBP1_CAP_OFFSET 0x90
38 #define PCI_NBP1_CAPABLE_BIT 31
40 #define OVERFLOW_MS 343597
43 enum amd_fam14h_states {NON_PC0 = 0,
PC1,
PC6, NBP1,
44 AMD_FAM14H_STATE_NUM};
46 static int fam14h_get_count_percent(
unsigned int self_id,
double *
percent,
48 static int fam14h_nbp1_count(
unsigned int id,
unsigned long long *
count,
51 static cstate_t amd_fam14h_cstates[AMD_FAM14H_STATE_NUM] = {
54 .desc =
N_(
"Package in sleep state (PC1 or deeper)"),
57 .get_count_percent = fam14h_get_count_percent,
61 .desc =
N_(
"Processor Package C1"),
64 .get_count_percent = fam14h_get_count_percent,
68 .desc =
N_(
"Processor Package C6"),
71 .get_count_percent = fam14h_get_count_percent,
75 .desc =
N_(
"North Bridge P1 boolean counter (returns 0 or 1)"),
78 .get_count = fam14h_nbp1_count,
82 static struct pci_access *pci_acc;
83 static struct pci_dev *amd_fam14h_pci_dev;
84 static int nbp1_entered;
87 static unsigned long long timediff;
94 static unsigned long long *previous_count[AMD_FAM14H_STATE_NUM];
95 static unsigned long long *current_count[AMD_FAM14H_STATE_NUM];
97 static int amd_fam14h_get_pci_info(
struct cstate *
state,
98 unsigned int *pci_offset,
99 unsigned int *enable_bit,
104 *enable_bit = PCI_NON_PC0_ENABLE_BIT;
105 *pci_offset = PCI_NON_PC0_OFFSET;
108 *enable_bit = PCI_PC1_ENABLE_BIT;
109 *pci_offset = PCI_PC1_OFFSET;
112 *enable_bit = PCI_PC6_ENABLE_BIT;
113 *pci_offset = PCI_PC6_OFFSET;
116 *enable_bit = PCI_NBP1_ENTERED_BIT;
117 *pci_offset = PCI_NBP1_STAT_OFFSET;
125 static int amd_fam14h_init(
cstate_t *state,
unsigned int cpu)
127 int enable_bit, pci_offset,
ret;
130 ret = amd_fam14h_get_pci_info(state, &pci_offset, &enable_bit, cpu);
135 if (state->
id == NBP1) {
136 val = pci_read_long(amd_fam14h_pci_dev, pci_offset);
137 val |= 1 << enable_bit;
138 val = pci_write_long(amd_fam14h_pci_dev, pci_offset, val);
143 val = pci_read_long(amd_fam14h_pci_dev, PCI_MONITOR_ENABLE_REG);
144 dprint(
"Init %s: read at offset: 0x%x val: %u\n", state->
name,
145 PCI_MONITOR_ENABLE_REG, (
unsigned int) val);
146 val |= 1 << enable_bit;
147 pci_write_long(amd_fam14h_pci_dev, PCI_MONITOR_ENABLE_REG, val);
149 dprint(
"Init %s: offset: 0x%x enable_bit: %d - val: %u (%u)\n",
150 state->
name, PCI_MONITOR_ENABLE_REG, enable_bit,
151 (
unsigned int) val, cpu);
154 pci_write_long(amd_fam14h_pci_dev, pci_offset, 0);
155 previous_count[state->
id][
cpu] = 0;
160 static int amd_fam14h_disable(
cstate_t *state,
unsigned int cpu)
162 int enable_bit, pci_offset,
ret;
165 ret = amd_fam14h_get_pci_info(state, &pci_offset, &enable_bit, cpu);
169 val = pci_read_long(amd_fam14h_pci_dev, pci_offset);
170 dprint(
"%s: offset: 0x%x %u\n", state->
name, pci_offset, val);
171 if (state->
id == NBP1) {
173 nbp1_entered = (val & (1 << PCI_NBP1_ACTIVE_BIT)) |
174 (val & (1 << PCI_NBP1_ENTERED_BIT));
176 dprint(
"NBP1 was %sentered - 0x%x - enable_bit: "
177 "%d - pci_offset: 0x%x\n",
178 nbp1_entered ?
"" :
"not ",
179 val, enable_bit, pci_offset);
182 current_count[state->
id][
cpu] =
val;
184 dprint(
"%s: Current - %llu (%u)\n", state->
name,
185 current_count[state->
id][cpu], cpu);
186 dprint(
"%s: Previous - %llu (%u)\n", state->
name,
187 previous_count[state->
id][cpu], cpu);
189 val = pci_read_long(amd_fam14h_pci_dev, PCI_MONITOR_ENABLE_REG);
190 val &= ~(1 << enable_bit);
191 pci_write_long(amd_fam14h_pci_dev, PCI_MONITOR_ENABLE_REG, val);
196 static int fam14h_nbp1_count(
unsigned int id,
unsigned long long *
count,
208 static int fam14h_get_count_percent(
unsigned int id,
double *
percent,
213 if (
id >= AMD_FAM14H_STATE_NUM)
216 diff = current_count[
id][
cpu] - previous_count[
id][
cpu];
221 *percent = 100.0 * diff / timediff / 12.5;
223 dprint(
"Timediff: %llu - res~: %lu us - percent: %.2f %%\n",
224 timediff, diff * 10 / 125, *percent);
229 static int amd_fam14h_start(
void)
233 for (num = 0; num < AMD_FAM14H_STATE_NUM; num++) {
235 amd_fam14h_init(&amd_fam14h_cstates[num], cpu);
240 dprint(
"Enabling counters took: %lu us\n",
246 static int amd_fam14h_stop(
void)
253 for (num = 0; num < AMD_FAM14H_STATE_NUM; num++) {
255 amd_fam14h_disable(&amd_fam14h_cstates[num], cpu);
260 dprint(
"Disabling counters took: %lu ns\n", dbg_timediff);
263 if (timediff / 1000 > OVERFLOW_MS)
270 static int is_nbp1_capable(
void)
273 val = pci_read_long(amd_fam14h_pci_dev, PCI_NBP1_CAP_OFFSET);
274 return val & (1 << 31);
285 strncpy(amd_fam14h_monitor.name,
"Fam_14h",
288 strncpy(amd_fam14h_monitor.name,
"Fam_12h",
294 for (num = 0; num < AMD_FAM14H_STATE_NUM - 1; num++) {
295 previous_count[num] = calloc(cpu_count,
296 sizeof(
unsigned long long));
297 current_count[num] = calloc(cpu_count,
298 sizeof(
unsigned long long));
303 amd_fam14h_pci_dev = pci_slot_func_init(&pci_acc, 0x18, 6);
304 if (amd_fam14h_pci_dev ==
NULL || pci_acc ==
NULL)
307 if (!is_nbp1_capable())
308 amd_fam14h_monitor.hw_states_num = AMD_FAM14H_STATE_NUM - 1;
310 amd_fam14h_monitor.name_len =
strlen(amd_fam14h_monitor.name);
311 return &amd_fam14h_monitor;
314 static void amd_fam14h_unregister(
void)
317 for (num = 0; num < AMD_FAM14H_STATE_NUM - 1; num++) {
318 free(previous_count[num]);
319 free(current_count[num]);
321 pci_cleanup(pci_acc);
326 .hw_states = amd_fam14h_cstates,
327 .hw_states_num = AMD_FAM14H_STATE_NUM,
328 .start = amd_fam14h_start,
329 .stop = amd_fam14h_stop,
330 .do_register = amd_fam14h_register,
331 .unregister = amd_fam14h_unregister,
333 .overflow_s = OVERFLOW_MS / 1000,