aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386/kernel/cpu/cpufreq/powernow-k8.c
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2006-06-20 08:59:45 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2006-06-20 08:59:45 -0400
commitd59bf96cdde5b874a57bfd1425faa45da915d0b7 (patch)
tree351a40b72514d620e5bebea2de38c26f23277ffc /arch/i386/kernel/cpu/cpufreq/powernow-k8.c
parent28df955a2ad484d602314b30183ea8496a9aa34a (diff)
parent25f42b6af09e34c3f92107b36b5aa6edc2fdba2f (diff)
Merge branch 'master' of /home/trondmy/kernel/linux-2.6/
Diffstat (limited to 'arch/i386/kernel/cpu/cpufreq/powernow-k8.c')
-rw-r--r--arch/i386/kernel/cpu/cpufreq/powernow-k8.c344
1 files changed, 256 insertions, 88 deletions
diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c
index 71fffa174425..b4277f58f40c 100644
--- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c
+++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * (c) 2003, 2004, 2005 Advanced Micro Devices, Inc. 2 * (c) 2003-2006 Advanced Micro Devices, Inc.
3 * Your use of this code is subject to the terms and conditions of the 3 * Your use of this code is subject to the terms and conditions of the
4 * GNU general public license version 2. See "COPYING" or 4 * GNU general public license version 2. See "COPYING" or
5 * http://www.gnu.org/licenses/gpl.html 5 * http://www.gnu.org/licenses/gpl.html
@@ -14,13 +14,13 @@
14 * Based upon datasheets & sample CPUs kindly provided by AMD. 14 * Based upon datasheets & sample CPUs kindly provided by AMD.
15 * 15 *
16 * Valuable input gratefully received from Dave Jones, Pavel Machek, 16 * Valuable input gratefully received from Dave Jones, Pavel Machek,
17 * Dominik Brodowski, and others. 17 * Dominik Brodowski, Jacob Shin, and others.
18 * Originally developed by Paul Devriendt. 18 * Originally developed by Paul Devriendt.
19 * Processor information obtained from Chapter 9 (Power and Thermal Management) 19 * Processor information obtained from Chapter 9 (Power and Thermal Management)
20 * of the "BIOS and Kernel Developer's Guide for the AMD Athlon 64 and AMD 20 * of the "BIOS and Kernel Developer's Guide for the AMD Athlon 64 and AMD
21 * Opteron Processors" available for download from www.amd.com 21 * Opteron Processors" available for download from www.amd.com
22 * 22 *
23 * Tables for specific CPUs can be infrerred from 23 * Tables for specific CPUs can be inferred from
24 * http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/30430.pdf 24 * http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/30430.pdf
25 */ 25 */
26 26
@@ -46,7 +46,7 @@
46 46
47#define PFX "powernow-k8: " 47#define PFX "powernow-k8: "
48#define BFX PFX "BIOS error: " 48#define BFX PFX "BIOS error: "
49#define VERSION "version 1.60.2" 49#define VERSION "version 2.00.00"
50#include "powernow-k8.h" 50#include "powernow-k8.h"
51 51
52/* serialize freq changes */ 52/* serialize freq changes */
@@ -54,6 +54,8 @@ static DEFINE_MUTEX(fidvid_mutex);
54 54
55static struct powernow_k8_data *powernow_data[NR_CPUS]; 55static struct powernow_k8_data *powernow_data[NR_CPUS];
56 56
57static int cpu_family = CPU_OPTERON;
58
57#ifndef CONFIG_SMP 59#ifndef CONFIG_SMP
58static cpumask_t cpu_core_map[1]; 60static cpumask_t cpu_core_map[1];
59#endif 61#endif
@@ -64,16 +66,36 @@ static u32 find_freq_from_fid(u32 fid)
64 return 800 + (fid * 100); 66 return 800 + (fid * 100);
65} 67}
66 68
69
67/* Return a frequency in KHz, given an input fid */ 70/* Return a frequency in KHz, given an input fid */
68static u32 find_khz_freq_from_fid(u32 fid) 71static u32 find_khz_freq_from_fid(u32 fid)
69{ 72{
70 return 1000 * find_freq_from_fid(fid); 73 return 1000 * find_freq_from_fid(fid);
71} 74}
72 75
73/* Return a voltage in miliVolts, given an input vid */ 76/* Return a frequency in MHz, given an input fid and did */
74static u32 find_millivolts_from_vid(struct powernow_k8_data *data, u32 vid) 77static u32 find_freq_from_fiddid(u32 fid, u32 did)
78{
79 return 100 * (fid + 0x10) >> did;
80}
81
82static u32 find_khz_freq_from_fiddid(u32 fid, u32 did)
75{ 83{
76 return 1550-vid*25; 84 return 1000 * find_freq_from_fiddid(fid, did);
85}
86
87static u32 find_fid_from_pstate(u32 pstate)
88{
89 u32 hi, lo;
90 rdmsr(MSR_PSTATE_DEF_BASE + pstate, lo, hi);
91 return lo & HW_PSTATE_FID_MASK;
92}
93
94static u32 find_did_from_pstate(u32 pstate)
95{
96 u32 hi, lo;
97 rdmsr(MSR_PSTATE_DEF_BASE + pstate, lo, hi);
98 return (lo & HW_PSTATE_DID_MASK) >> HW_PSTATE_DID_SHIFT;
77} 99}
78 100
79/* Return the vco fid for an input fid 101/* Return the vco fid for an input fid
@@ -98,6 +120,9 @@ static int pending_bit_stuck(void)
98{ 120{
99 u32 lo, hi; 121 u32 lo, hi;
100 122
123 if (cpu_family)
124 return 0;
125
101 rdmsr(MSR_FIDVID_STATUS, lo, hi); 126 rdmsr(MSR_FIDVID_STATUS, lo, hi);
102 return lo & MSR_S_LO_CHANGE_PENDING ? 1 : 0; 127 return lo & MSR_S_LO_CHANGE_PENDING ? 1 : 0;
103} 128}
@@ -111,6 +136,14 @@ static int query_current_values_with_pending_wait(struct powernow_k8_data *data)
111 u32 lo, hi; 136 u32 lo, hi;
112 u32 i = 0; 137 u32 i = 0;
113 138
139 if (cpu_family) {
140 rdmsr(MSR_PSTATE_STATUS, lo, hi);
141 i = lo & HW_PSTATE_MASK;
142 rdmsr(MSR_PSTATE_DEF_BASE + i, lo, hi);
143 data->currfid = lo & HW_PSTATE_FID_MASK;
144 data->currdid = (lo & HW_PSTATE_DID_MASK) >> HW_PSTATE_DID_SHIFT;
145 return 0;
146 }
114 do { 147 do {
115 if (i++ > 10000) { 148 if (i++ > 10000) {
116 dprintk("detected change pending stuck\n"); 149 dprintk("detected change pending stuck\n");
@@ -175,7 +208,7 @@ static int write_new_fid(struct powernow_k8_data *data, u32 fid)
175 do { 208 do {
176 wrmsr(MSR_FIDVID_CTL, lo, data->plllock * PLL_LOCK_CONVERSION); 209 wrmsr(MSR_FIDVID_CTL, lo, data->plllock * PLL_LOCK_CONVERSION);
177 if (i++ > 100) { 210 if (i++ > 100) {
178 printk(KERN_ERR PFX "internal error - pending bit very stuck - no further pstate changes possible\n"); 211 printk(KERN_ERR PFX "Hardware error - pending bit very stuck - no further pstate changes possible\n");
179 return 1; 212 return 1;
180 } 213 }
181 } while (query_current_values_with_pending_wait(data)); 214 } while (query_current_values_with_pending_wait(data));
@@ -255,7 +288,15 @@ static int decrease_vid_code_by_step(struct powernow_k8_data *data, u32 reqvid,
255 return 0; 288 return 0;
256} 289}
257 290
258/* Change the fid and vid, by the 3 phases. */ 291/* Change hardware pstate by single MSR write */
292static int transition_pstate(struct powernow_k8_data *data, u32 pstate)
293{
294 wrmsr(MSR_PSTATE_CTRL, pstate, 0);
295 data->currfid = find_fid_from_pstate(pstate);
296 return 0;
297}
298
299/* Change Opteron/Athlon64 fid and vid, by the 3 phases. */
259static int transition_fid_vid(struct powernow_k8_data *data, u32 reqfid, u32 reqvid) 300static int transition_fid_vid(struct powernow_k8_data *data, u32 reqfid, u32 reqvid)
260{ 301{
261 if (core_voltage_pre_transition(data, reqvid)) 302 if (core_voltage_pre_transition(data, reqvid))
@@ -474,26 +515,35 @@ static int check_supported_cpu(unsigned int cpu)
474 goto out; 515 goto out;
475 516
476 eax = cpuid_eax(CPUID_PROCESSOR_SIGNATURE); 517 eax = cpuid_eax(CPUID_PROCESSOR_SIGNATURE);
477 if ((eax & CPUID_XFAM) != CPUID_XFAM_K8) 518 if (((eax & CPUID_XFAM) != CPUID_XFAM_K8) &&
519 ((eax & CPUID_XFAM) < CPUID_XFAM_10H))
478 goto out; 520 goto out;
479 521
480 if (((eax & CPUID_USE_XFAM_XMOD) != CPUID_USE_XFAM_XMOD) || 522 if ((eax & CPUID_XFAM) == CPUID_XFAM_K8) {
481 ((eax & CPUID_XMOD) > CPUID_XMOD_REV_G)) { 523 if (((eax & CPUID_USE_XFAM_XMOD) != CPUID_USE_XFAM_XMOD) ||
482 printk(KERN_INFO PFX "Processor cpuid %x not supported\n", eax); 524 ((eax & CPUID_XMOD) > CPUID_XMOD_REV_G)) {
483 goto out; 525 printk(KERN_INFO PFX "Processor cpuid %x not supported\n", eax);
484 } 526 goto out;
527 }
485 528
486 eax = cpuid_eax(CPUID_GET_MAX_CAPABILITIES); 529 eax = cpuid_eax(CPUID_GET_MAX_CAPABILITIES);
487 if (eax < CPUID_FREQ_VOLT_CAPABILITIES) { 530 if (eax < CPUID_FREQ_VOLT_CAPABILITIES) {
488 printk(KERN_INFO PFX 531 printk(KERN_INFO PFX
489 "No frequency change capabilities detected\n"); 532 "No frequency change capabilities detected\n");
490 goto out; 533 goto out;
491 } 534 }
492 535
493 cpuid(CPUID_FREQ_VOLT_CAPABILITIES, &eax, &ebx, &ecx, &edx); 536 cpuid(CPUID_FREQ_VOLT_CAPABILITIES, &eax, &ebx, &ecx, &edx);
494 if ((edx & P_STATE_TRANSITION_CAPABLE) != P_STATE_TRANSITION_CAPABLE) { 537 if ((edx & P_STATE_TRANSITION_CAPABLE) != P_STATE_TRANSITION_CAPABLE) {
495 printk(KERN_INFO PFX "Power state transitions not supported\n"); 538 printk(KERN_INFO PFX "Power state transitions not supported\n");
496 goto out; 539 goto out;
540 }
541 } else { /* must be a HW Pstate capable processor */
542 cpuid(CPUID_FREQ_VOLT_CAPABILITIES, &eax, &ebx, &ecx, &edx);
543 if ((edx & USE_HW_PSTATE) == USE_HW_PSTATE)
544 cpu_family = CPU_HW_PSTATE;
545 else
546 goto out;
497 } 547 }
498 548
499 rc = 1; 549 rc = 1;
@@ -547,12 +597,18 @@ static void print_basics(struct powernow_k8_data *data)
547{ 597{
548 int j; 598 int j;
549 for (j = 0; j < data->numps; j++) { 599 for (j = 0; j < data->numps; j++) {
550 if (data->powernow_table[j].frequency != CPUFREQ_ENTRY_INVALID) 600 if (data->powernow_table[j].frequency != CPUFREQ_ENTRY_INVALID) {
551 printk(KERN_INFO PFX " %d : fid 0x%x (%d MHz), vid 0x%x (%d mV)\n", j, 601 if (cpu_family) {
602 printk(KERN_INFO PFX " %d : fid 0x%x gid 0x%x (%d MHz)\n", j, (data->powernow_table[j].index & 0xff00) >> 8,
603 (data->powernow_table[j].index & 0xff0000) >> 16,
604 data->powernow_table[j].frequency/1000);
605 } else {
606 printk(KERN_INFO PFX " %d : fid 0x%x (%d MHz), vid 0x%x\n", j,
552 data->powernow_table[j].index & 0xff, 607 data->powernow_table[j].index & 0xff,
553 data->powernow_table[j].frequency/1000, 608 data->powernow_table[j].frequency/1000,
554 data->powernow_table[j].index >> 8, 609 data->powernow_table[j].index >> 8);
555 find_millivolts_from_vid(data, data->powernow_table[j].index >> 8)); 610 }
611 }
556 } 612 }
557 if (data->batps) 613 if (data->batps)
558 printk(KERN_INFO PFX "Only %d pstates on battery\n", data->batps); 614 printk(KERN_INFO PFX "Only %d pstates on battery\n", data->batps);
@@ -702,7 +758,7 @@ static int find_psb_table(struct powernow_k8_data *data)
702#ifdef CONFIG_X86_POWERNOW_K8_ACPI 758#ifdef CONFIG_X86_POWERNOW_K8_ACPI
703static void powernow_k8_acpi_pst_values(struct powernow_k8_data *data, unsigned int index) 759static void powernow_k8_acpi_pst_values(struct powernow_k8_data *data, unsigned int index)
704{ 760{
705 if (!data->acpi_data.state_count) 761 if (!data->acpi_data.state_count || cpu_family)
706 return; 762 return;
707 763
708 data->irt = (data->acpi_data.states[index].control >> IRT_SHIFT) & IRT_MASK; 764 data->irt = (data->acpi_data.states[index].control >> IRT_SHIFT) & IRT_MASK;
@@ -715,9 +771,8 @@ static void powernow_k8_acpi_pst_values(struct powernow_k8_data *data, unsigned
715 771
716static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data) 772static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data)
717{ 773{
718 int i;
719 int cntlofreq = 0;
720 struct cpufreq_frequency_table *powernow_table; 774 struct cpufreq_frequency_table *powernow_table;
775 int ret_val;
721 776
722 if (acpi_processor_register_performance(&data->acpi_data, data->cpu)) { 777 if (acpi_processor_register_performance(&data->acpi_data, data->cpu)) {
723 dprintk("register performance failed: bad ACPI data\n"); 778 dprintk("register performance failed: bad ACPI data\n");
@@ -746,6 +801,85 @@ static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data)
746 goto err_out; 801 goto err_out;
747 } 802 }
748 803
804 if (cpu_family)
805 ret_val = fill_powernow_table_pstate(data, powernow_table);
806 else
807 ret_val = fill_powernow_table_fidvid(data, powernow_table);
808 if (ret_val)
809 goto err_out_mem;
810
811 powernow_table[data->acpi_data.state_count].frequency = CPUFREQ_TABLE_END;
812 powernow_table[data->acpi_data.state_count].index = 0;
813 data->powernow_table = powernow_table;
814
815 /* fill in data */
816 data->numps = data->acpi_data.state_count;
817 print_basics(data);
818 powernow_k8_acpi_pst_values(data, 0);
819
820 /* notify BIOS that we exist */
821 acpi_processor_notify_smm(THIS_MODULE);
822
823 return 0;
824
825err_out_mem:
826 kfree(powernow_table);
827
828err_out:
829 acpi_processor_unregister_performance(&data->acpi_data, data->cpu);
830
831 /* data->acpi_data.state_count informs us at ->exit() whether ACPI was used */
832 data->acpi_data.state_count = 0;
833
834 return -ENODEV;
835}
836
837static int fill_powernow_table_pstate(struct powernow_k8_data *data, struct cpufreq_frequency_table *powernow_table)
838{
839 int i;
840
841 for (i = 0; i < data->acpi_data.state_count; i++) {
842 u32 index;
843 u32 hi = 0, lo = 0;
844 u32 fid;
845 u32 did;
846
847 index = data->acpi_data.states[i].control & HW_PSTATE_MASK;
848 if (index > MAX_HW_PSTATE) {
849 printk(KERN_ERR PFX "invalid pstate %d - bad value %d.\n", i, index);
850 printk(KERN_ERR PFX "Please report to BIOS manufacturer\n");
851 }
852 rdmsr(MSR_PSTATE_DEF_BASE + index, lo, hi);
853 if (!(hi & HW_PSTATE_VALID_MASK)) {
854 dprintk("invalid pstate %d, ignoring\n", index);
855 powernow_table[i].frequency = CPUFREQ_ENTRY_INVALID;
856 continue;
857 }
858
859 fid = lo & HW_PSTATE_FID_MASK;
860 did = (lo & HW_PSTATE_DID_MASK) >> HW_PSTATE_DID_SHIFT;
861
862 dprintk(" %d : fid 0x%x, did 0x%x\n", index, fid, did);
863
864 powernow_table[i].index = index | (fid << HW_FID_INDEX_SHIFT) | (did << HW_DID_INDEX_SHIFT);
865
866 powernow_table[i].frequency = find_khz_freq_from_fiddid(fid, did);
867
868 if (powernow_table[i].frequency != (data->acpi_data.states[i].core_frequency * 1000)) {
869 printk(KERN_INFO PFX "invalid freq entries %u kHz vs. %u kHz\n",
870 powernow_table[i].frequency,
871 (unsigned int) (data->acpi_data.states[i].core_frequency * 1000));
872 powernow_table[i].frequency = CPUFREQ_ENTRY_INVALID;
873 continue;
874 }
875 }
876 return 0;
877}
878
879static int fill_powernow_table_fidvid(struct powernow_k8_data *data, struct cpufreq_frequency_table *powernow_table)
880{
881 int i;
882 int cntlofreq = 0;
749 for (i = 0; i < data->acpi_data.state_count; i++) { 883 for (i = 0; i < data->acpi_data.state_count; i++) {
750 u32 fid; 884 u32 fid;
751 u32 vid; 885 u32 vid;
@@ -786,7 +920,7 @@ static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data)
786 if ((powernow_table[i].frequency != powernow_table[cntlofreq].frequency) || 920 if ((powernow_table[i].frequency != powernow_table[cntlofreq].frequency) ||
787 (powernow_table[i].index != powernow_table[cntlofreq].index)) { 921 (powernow_table[i].index != powernow_table[cntlofreq].index)) {
788 printk(KERN_ERR PFX "Too many lo freq table entries\n"); 922 printk(KERN_ERR PFX "Too many lo freq table entries\n");
789 goto err_out_mem; 923 return 1;
790 } 924 }
791 925
792 dprintk("double low frequency table entry, ignoring it.\n"); 926 dprintk("double low frequency table entry, ignoring it.\n");
@@ -804,31 +938,7 @@ static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data)
804 continue; 938 continue;
805 } 939 }
806 } 940 }
807
808 powernow_table[data->acpi_data.state_count].frequency = CPUFREQ_TABLE_END;
809 powernow_table[data->acpi_data.state_count].index = 0;
810 data->powernow_table = powernow_table;
811
812 /* fill in data */
813 data->numps = data->acpi_data.state_count;
814 print_basics(data);
815 powernow_k8_acpi_pst_values(data, 0);
816
817 /* notify BIOS that we exist */
818 acpi_processor_notify_smm(THIS_MODULE);
819
820 return 0; 941 return 0;
821
822err_out_mem:
823 kfree(powernow_table);
824
825err_out:
826 acpi_processor_unregister_performance(&data->acpi_data, data->cpu);
827
828 /* data->acpi_data.state_count informs us at ->exit() whether ACPI was used */
829 data->acpi_data.state_count = 0;
830
831 return -ENODEV;
832} 942}
833 943
834static void powernow_k8_cpu_exit_acpi(struct powernow_k8_data *data) 944static void powernow_k8_cpu_exit_acpi(struct powernow_k8_data *data)
@@ -844,20 +954,20 @@ static void powernow_k8_acpi_pst_values(struct powernow_k8_data *data, unsigned
844#endif /* CONFIG_X86_POWERNOW_K8_ACPI */ 954#endif /* CONFIG_X86_POWERNOW_K8_ACPI */
845 955
846/* Take a frequency, and issue the fid/vid transition command */ 956/* Take a frequency, and issue the fid/vid transition command */
847static int transition_frequency(struct powernow_k8_data *data, unsigned int index) 957static int transition_frequency_fidvid(struct powernow_k8_data *data, unsigned int index)
848{ 958{
849 u32 fid; 959 u32 fid = 0;
850 u32 vid; 960 u32 vid = 0;
851 int res, i; 961 int res, i;
852 struct cpufreq_freqs freqs; 962 struct cpufreq_freqs freqs;
853 963
854 dprintk("cpu %d transition to index %u\n", smp_processor_id(), index); 964 dprintk("cpu %d transition to index %u\n", smp_processor_id(), index);
855 965
966 /* fid/vid correctness check for k8 */
856 /* fid are the lower 8 bits of the index we stored into 967 /* fid are the lower 8 bits of the index we stored into
857 * the cpufreq frequency table in find_psb_table, vid are 968 * the cpufreq frequency table in find_psb_table, vid
858 * the upper 8 bits. 969 * are the upper 8 bits.
859 */ 970 */
860
861 fid = data->powernow_table[index].index & 0xFF; 971 fid = data->powernow_table[index].index & 0xFF;
862 vid = (data->powernow_table[index].index & 0xFF00) >> 8; 972 vid = (data->powernow_table[index].index & 0xFF00) >> 8;
863 973
@@ -881,22 +991,58 @@ static int transition_frequency(struct powernow_k8_data *data, unsigned int inde
881 991
882 dprintk("cpu %d, changing to fid 0x%x, vid 0x%x\n", 992 dprintk("cpu %d, changing to fid 0x%x, vid 0x%x\n",
883 smp_processor_id(), fid, vid); 993 smp_processor_id(), fid, vid);
884
885 freqs.cpu = data->cpu;
886 freqs.old = find_khz_freq_from_fid(data->currfid); 994 freqs.old = find_khz_freq_from_fid(data->currfid);
887 freqs.new = find_khz_freq_from_fid(fid); 995 freqs.new = find_khz_freq_from_fid(fid);
888 for_each_cpu_mask(i, cpu_core_map[data->cpu]) { 996
997 for_each_cpu_mask(i, *(data->available_cores)) {
889 freqs.cpu = i; 998 freqs.cpu = i;
890 cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); 999 cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
891 } 1000 }
892 1001
893 res = transition_fid_vid(data, fid, vid); 1002 res = transition_fid_vid(data, fid, vid);
894
895 freqs.new = find_khz_freq_from_fid(data->currfid); 1003 freqs.new = find_khz_freq_from_fid(data->currfid);
896 for_each_cpu_mask(i, cpu_core_map[data->cpu]) { 1004
1005 for_each_cpu_mask(i, *(data->available_cores)) {
897 freqs.cpu = i; 1006 freqs.cpu = i;
898 cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); 1007 cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
899 } 1008 }
1009 return res;
1010}
1011
1012/* Take a frequency, and issue the hardware pstate transition command */
1013static int transition_frequency_pstate(struct powernow_k8_data *data, unsigned int index)
1014{
1015 u32 fid = 0;
1016 u32 did = 0;
1017 u32 pstate = 0;
1018 int res, i;
1019 struct cpufreq_freqs freqs;
1020
1021 dprintk("cpu %d transition to index %u\n", smp_processor_id(), index);
1022
1023 /* get fid did for hardware pstate transition */
1024 pstate = index & HW_PSTATE_MASK;
1025 if (pstate > MAX_HW_PSTATE)
1026 return 0;
1027 fid = (index & HW_FID_INDEX_MASK) >> HW_FID_INDEX_SHIFT;
1028 did = (index & HW_DID_INDEX_MASK) >> HW_DID_INDEX_SHIFT;
1029 freqs.old = find_khz_freq_from_fiddid(data->currfid, data->currdid);
1030 freqs.new = find_khz_freq_from_fiddid(fid, did);
1031
1032 for_each_cpu_mask(i, *(data->available_cores)) {
1033 freqs.cpu = i;
1034 cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
1035 }
1036
1037 res = transition_pstate(data, pstate);
1038 data->currfid = find_fid_from_pstate(pstate);
1039 data->currdid = find_did_from_pstate(pstate);
1040 freqs.new = find_khz_freq_from_fiddid(data->currfid, data->currdid);
1041
1042 for_each_cpu_mask(i, *(data->available_cores)) {
1043 freqs.cpu = i;
1044 cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
1045 }
900 return res; 1046 return res;
901} 1047}
902 1048
@@ -933,18 +1079,21 @@ static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsi
933 dprintk("targ: cpu %d, %d kHz, min %d, max %d, relation %d\n", 1079 dprintk("targ: cpu %d, %d kHz, min %d, max %d, relation %d\n",
934 pol->cpu, targfreq, pol->min, pol->max, relation); 1080 pol->cpu, targfreq, pol->min, pol->max, relation);
935 1081
936 if (query_current_values_with_pending_wait(data)) { 1082 if (query_current_values_with_pending_wait(data))
937 ret = -EIO;
938 goto err_out; 1083 goto err_out;
939 }
940 1084
941 dprintk("targ: curr fid 0x%x, vid 0x%x\n", 1085 if (cpu_family)
1086 dprintk("targ: curr fid 0x%x, did 0x%x\n",
1087 data->currfid, data->currvid);
1088 else {
1089 dprintk("targ: curr fid 0x%x, vid 0x%x\n",
942 data->currfid, data->currvid); 1090 data->currfid, data->currvid);
943 1091
944 if ((checkvid != data->currvid) || (checkfid != data->currfid)) { 1092 if ((checkvid != data->currvid) || (checkfid != data->currfid)) {
945 printk(KERN_INFO PFX 1093 printk(KERN_INFO PFX
946 "error - out of sync, fix 0x%x 0x%x, vid 0x%x 0x%x\n", 1094 "error - out of sync, fix 0x%x 0x%x, vid 0x%x 0x%x\n",
947 checkfid, data->currfid, checkvid, data->currvid); 1095 checkfid, data->currfid, checkvid, data->currvid);
1096 }
948 } 1097 }
949 1098
950 if (cpufreq_frequency_table_target(pol, data->powernow_table, targfreq, relation, &newstate)) 1099 if (cpufreq_frequency_table_target(pol, data->powernow_table, targfreq, relation, &newstate))
@@ -954,7 +1103,11 @@ static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsi
954 1103
955 powernow_k8_acpi_pst_values(data, newstate); 1104 powernow_k8_acpi_pst_values(data, newstate);
956 1105
957 if (transition_frequency(data, newstate)) { 1106 if (cpu_family)
1107 ret = transition_frequency_pstate(data, newstate);
1108 else
1109 ret = transition_frequency_fidvid(data, newstate);
1110 if (ret) {
958 printk(KERN_ERR PFX "transition frequency failed\n"); 1111 printk(KERN_ERR PFX "transition frequency failed\n");
959 ret = 1; 1112 ret = 1;
960 mutex_unlock(&fidvid_mutex); 1113 mutex_unlock(&fidvid_mutex);
@@ -962,7 +1115,10 @@ static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsi
962 } 1115 }
963 mutex_unlock(&fidvid_mutex); 1116 mutex_unlock(&fidvid_mutex);
964 1117
965 pol->cur = find_khz_freq_from_fid(data->currfid); 1118 if (cpu_family)
1119 pol->cur = find_khz_freq_from_fiddid(data->currfid, data->currdid);
1120 else
1121 pol->cur = find_khz_freq_from_fid(data->currfid);
966 ret = 0; 1122 ret = 0;
967 1123
968err_out: 1124err_out:
@@ -1007,14 +1163,13 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol)
1007 * Use the PSB BIOS structure. This is only availabe on 1163 * Use the PSB BIOS structure. This is only availabe on
1008 * an UP version, and is deprecated by AMD. 1164 * an UP version, and is deprecated by AMD.
1009 */ 1165 */
1010
1011 if ((num_online_cpus() != 1) || (num_possible_cpus() != 1)) { 1166 if ((num_online_cpus() != 1) || (num_possible_cpus() != 1)) {
1012 printk(KERN_ERR PFX "MP systems not supported by PSB BIOS structure\n"); 1167 printk(KERN_ERR PFX "MP systems not supported by PSB BIOS structure\n");
1013 kfree(data); 1168 kfree(data);
1014 return -ENODEV; 1169 return -ENODEV;
1015 } 1170 }
1016 if (pol->cpu != 0) { 1171 if (pol->cpu != 0) {
1017 printk(KERN_ERR PFX "init not cpu 0\n"); 1172 printk(KERN_ERR PFX "No _PSS objects for CPU other than CPU0\n");
1018 kfree(data); 1173 kfree(data);
1019 return -ENODEV; 1174 return -ENODEV;
1020 } 1175 }
@@ -1042,20 +1197,28 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol)
1042 if (query_current_values_with_pending_wait(data)) 1197 if (query_current_values_with_pending_wait(data))
1043 goto err_out; 1198 goto err_out;
1044 1199
1045 fidvid_msr_init(); 1200 if (!cpu_family)
1201 fidvid_msr_init();
1046 1202
1047 /* run on any CPU again */ 1203 /* run on any CPU again */
1048 set_cpus_allowed(current, oldmask); 1204 set_cpus_allowed(current, oldmask);
1049 1205
1050 pol->governor = CPUFREQ_DEFAULT_GOVERNOR; 1206 pol->governor = CPUFREQ_DEFAULT_GOVERNOR;
1051 pol->cpus = cpu_core_map[pol->cpu]; 1207 if (cpu_family)
1208 pol->cpus = cpumask_of_cpu(pol->cpu);
1209 else
1210 pol->cpus = cpu_core_map[pol->cpu];
1211 data->available_cores = &(pol->cpus);
1052 1212
1053 /* Take a crude guess here. 1213 /* Take a crude guess here.
1054 * That guess was in microseconds, so multiply with 1000 */ 1214 * That guess was in microseconds, so multiply with 1000 */
1055 pol->cpuinfo.transition_latency = (((data->rvo + 8) * data->vstable * VST_UNITS_20US) 1215 pol->cpuinfo.transition_latency = (((data->rvo + 8) * data->vstable * VST_UNITS_20US)
1056 + (3 * (1 << data->irt) * 10)) * 1000; 1216 + (3 * (1 << data->irt) * 10)) * 1000;
1057 1217
1058 pol->cur = find_khz_freq_from_fid(data->currfid); 1218 if (cpu_family)
1219 pol->cur = find_khz_freq_from_fiddid(data->currfid, data->currdid);
1220 else
1221 pol->cur = find_khz_freq_from_fid(data->currfid);
1059 dprintk("policy current frequency %d kHz\n", pol->cur); 1222 dprintk("policy current frequency %d kHz\n", pol->cur);
1060 1223
1061 /* min/max the cpu is capable of */ 1224 /* min/max the cpu is capable of */
@@ -1069,8 +1232,12 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol)
1069 1232
1070 cpufreq_frequency_table_get_attr(data->powernow_table, pol->cpu); 1233 cpufreq_frequency_table_get_attr(data->powernow_table, pol->cpu);
1071 1234
1072 printk("cpu_init done, current fid 0x%x, vid 0x%x\n", 1235 if (cpu_family)
1073 data->currfid, data->currvid); 1236 dprintk("cpu_init done, current fid 0x%x, did 0x%x\n",
1237 data->currfid, data->currdid);
1238 else
1239 dprintk("cpu_init done, current fid 0x%x, vid 0x%x\n",
1240 data->currfid, data->currvid);
1074 1241
1075 powernow_data[pol->cpu] = data; 1242 powernow_data[pol->cpu] = data;
1076 1243
@@ -1156,8 +1323,9 @@ static int __cpuinit powernowk8_init(void)
1156 } 1323 }
1157 1324
1158 if (supported_cpus == num_online_cpus()) { 1325 if (supported_cpus == num_online_cpus()) {
1159 printk(KERN_INFO PFX "Found %d AMD Athlon 64 / Opteron " 1326 printk(KERN_INFO PFX "Found %d %s "
1160 "processors (" VERSION ")\n", supported_cpus); 1327 "processors (" VERSION ")\n", supported_cpus,
1328 boot_cpu_data.x86_model_id);
1161 return cpufreq_register_driver(&cpufreq_amd64_driver); 1329 return cpufreq_register_driver(&cpufreq_amd64_driver);
1162 } 1330 }
1163 1331