diff options
Diffstat (limited to 'drivers/cpufreq/acpi-cpufreq.c')
-rw-r--r-- | drivers/cpufreq/acpi-cpufreq.c | 43 |
1 files changed, 37 insertions, 6 deletions
diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c index 56c6c6b4eb4d..067a61f06bb5 100644 --- a/drivers/cpufreq/acpi-cpufreq.c +++ b/drivers/cpufreq/acpi-cpufreq.c | |||
@@ -54,10 +54,12 @@ MODULE_LICENSE("GPL"); | |||
54 | enum { | 54 | enum { |
55 | UNDEFINED_CAPABLE = 0, | 55 | UNDEFINED_CAPABLE = 0, |
56 | SYSTEM_INTEL_MSR_CAPABLE, | 56 | SYSTEM_INTEL_MSR_CAPABLE, |
57 | SYSTEM_AMD_MSR_CAPABLE, | ||
57 | SYSTEM_IO_CAPABLE, | 58 | SYSTEM_IO_CAPABLE, |
58 | }; | 59 | }; |
59 | 60 | ||
60 | #define INTEL_MSR_RANGE (0xffff) | 61 | #define INTEL_MSR_RANGE (0xffff) |
62 | #define AMD_MSR_RANGE (0x7) | ||
61 | 63 | ||
62 | struct acpi_cpufreq_data { | 64 | struct acpi_cpufreq_data { |
63 | struct acpi_processor_performance *acpi_data; | 65 | struct acpi_processor_performance *acpi_data; |
@@ -82,6 +84,13 @@ static int check_est_cpu(unsigned int cpuid) | |||
82 | return cpu_has(cpu, X86_FEATURE_EST); | 84 | return cpu_has(cpu, X86_FEATURE_EST); |
83 | } | 85 | } |
84 | 86 | ||
87 | static int check_amd_hwpstate_cpu(unsigned int cpuid) | ||
88 | { | ||
89 | struct cpuinfo_x86 *cpu = &cpu_data(cpuid); | ||
90 | |||
91 | return cpu_has(cpu, X86_FEATURE_HW_PSTATE); | ||
92 | } | ||
93 | |||
85 | static unsigned extract_io(u32 value, struct acpi_cpufreq_data *data) | 94 | static unsigned extract_io(u32 value, struct acpi_cpufreq_data *data) |
86 | { | 95 | { |
87 | struct acpi_processor_performance *perf; | 96 | struct acpi_processor_performance *perf; |
@@ -101,7 +110,11 @@ static unsigned extract_msr(u32 msr, struct acpi_cpufreq_data *data) | |||
101 | int i; | 110 | int i; |
102 | struct acpi_processor_performance *perf; | 111 | struct acpi_processor_performance *perf; |
103 | 112 | ||
104 | msr &= INTEL_MSR_RANGE; | 113 | if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) |
114 | msr &= AMD_MSR_RANGE; | ||
115 | else | ||
116 | msr &= INTEL_MSR_RANGE; | ||
117 | |||
105 | perf = data->acpi_data; | 118 | perf = data->acpi_data; |
106 | 119 | ||
107 | for (i = 0; data->freq_table[i].frequency != CPUFREQ_TABLE_END; i++) { | 120 | for (i = 0; data->freq_table[i].frequency != CPUFREQ_TABLE_END; i++) { |
@@ -115,6 +128,7 @@ static unsigned extract_freq(u32 val, struct acpi_cpufreq_data *data) | |||
115 | { | 128 | { |
116 | switch (data->cpu_feature) { | 129 | switch (data->cpu_feature) { |
117 | case SYSTEM_INTEL_MSR_CAPABLE: | 130 | case SYSTEM_INTEL_MSR_CAPABLE: |
131 | case SYSTEM_AMD_MSR_CAPABLE: | ||
118 | return extract_msr(val, data); | 132 | return extract_msr(val, data); |
119 | case SYSTEM_IO_CAPABLE: | 133 | case SYSTEM_IO_CAPABLE: |
120 | return extract_io(val, data); | 134 | return extract_io(val, data); |
@@ -150,6 +164,7 @@ static void do_drv_read(void *_cmd) | |||
150 | 164 | ||
151 | switch (cmd->type) { | 165 | switch (cmd->type) { |
152 | case SYSTEM_INTEL_MSR_CAPABLE: | 166 | case SYSTEM_INTEL_MSR_CAPABLE: |
167 | case SYSTEM_AMD_MSR_CAPABLE: | ||
153 | rdmsr(cmd->addr.msr.reg, cmd->val, h); | 168 | rdmsr(cmd->addr.msr.reg, cmd->val, h); |
154 | break; | 169 | break; |
155 | case SYSTEM_IO_CAPABLE: | 170 | case SYSTEM_IO_CAPABLE: |
@@ -174,6 +189,9 @@ static void do_drv_write(void *_cmd) | |||
174 | lo = (lo & ~INTEL_MSR_RANGE) | (cmd->val & INTEL_MSR_RANGE); | 189 | lo = (lo & ~INTEL_MSR_RANGE) | (cmd->val & INTEL_MSR_RANGE); |
175 | wrmsr(cmd->addr.msr.reg, lo, hi); | 190 | wrmsr(cmd->addr.msr.reg, lo, hi); |
176 | break; | 191 | break; |
192 | case SYSTEM_AMD_MSR_CAPABLE: | ||
193 | wrmsr(cmd->addr.msr.reg, cmd->val, 0); | ||
194 | break; | ||
177 | case SYSTEM_IO_CAPABLE: | 195 | case SYSTEM_IO_CAPABLE: |
178 | acpi_os_write_port((acpi_io_address)cmd->addr.io.port, | 196 | acpi_os_write_port((acpi_io_address)cmd->addr.io.port, |
179 | cmd->val, | 197 | cmd->val, |
@@ -217,6 +235,10 @@ static u32 get_cur_val(const struct cpumask *mask) | |||
217 | cmd.type = SYSTEM_INTEL_MSR_CAPABLE; | 235 | cmd.type = SYSTEM_INTEL_MSR_CAPABLE; |
218 | cmd.addr.msr.reg = MSR_IA32_PERF_STATUS; | 236 | cmd.addr.msr.reg = MSR_IA32_PERF_STATUS; |
219 | break; | 237 | break; |
238 | case SYSTEM_AMD_MSR_CAPABLE: | ||
239 | cmd.type = SYSTEM_AMD_MSR_CAPABLE; | ||
240 | cmd.addr.msr.reg = MSR_AMD_PERF_STATUS; | ||
241 | break; | ||
220 | case SYSTEM_IO_CAPABLE: | 242 | case SYSTEM_IO_CAPABLE: |
221 | cmd.type = SYSTEM_IO_CAPABLE; | 243 | cmd.type = SYSTEM_IO_CAPABLE; |
222 | perf = per_cpu(acfreq_data, cpumask_first(mask))->acpi_data; | 244 | perf = per_cpu(acfreq_data, cpumask_first(mask))->acpi_data; |
@@ -326,6 +348,11 @@ static int acpi_cpufreq_target(struct cpufreq_policy *policy, | |||
326 | cmd.addr.msr.reg = MSR_IA32_PERF_CTL; | 348 | cmd.addr.msr.reg = MSR_IA32_PERF_CTL; |
327 | cmd.val = (u32) perf->states[next_perf_state].control; | 349 | cmd.val = (u32) perf->states[next_perf_state].control; |
328 | break; | 350 | break; |
351 | case SYSTEM_AMD_MSR_CAPABLE: | ||
352 | cmd.type = SYSTEM_AMD_MSR_CAPABLE; | ||
353 | cmd.addr.msr.reg = MSR_AMD_PERF_CTL; | ||
354 | cmd.val = (u32) perf->states[next_perf_state].control; | ||
355 | break; | ||
329 | case SYSTEM_IO_CAPABLE: | 356 | case SYSTEM_IO_CAPABLE: |
330 | cmd.type = SYSTEM_IO_CAPABLE; | 357 | cmd.type = SYSTEM_IO_CAPABLE; |
331 | cmd.addr.io.port = perf->control_register.address; | 358 | cmd.addr.io.port = perf->control_register.address; |
@@ -580,12 +607,16 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy) | |||
580 | break; | 607 | break; |
581 | case ACPI_ADR_SPACE_FIXED_HARDWARE: | 608 | case ACPI_ADR_SPACE_FIXED_HARDWARE: |
582 | pr_debug("HARDWARE addr space\n"); | 609 | pr_debug("HARDWARE addr space\n"); |
583 | if (!check_est_cpu(cpu)) { | 610 | if (check_est_cpu(cpu)) { |
584 | result = -ENODEV; | 611 | data->cpu_feature = SYSTEM_INTEL_MSR_CAPABLE; |
585 | goto err_unreg; | 612 | break; |
586 | } | 613 | } |
587 | data->cpu_feature = SYSTEM_INTEL_MSR_CAPABLE; | 614 | if (check_amd_hwpstate_cpu(cpu)) { |
588 | break; | 615 | data->cpu_feature = SYSTEM_AMD_MSR_CAPABLE; |
616 | break; | ||
617 | } | ||
618 | result = -ENODEV; | ||
619 | goto err_unreg; | ||
589 | default: | 620 | default: |
590 | pr_debug("Unknown addr space %d\n", | 621 | pr_debug("Unknown addr space %d\n", |
591 | (u32) (perf->control_register.space_id)); | 622 | (u32) (perf->control_register.space_id)); |