Chameleon

Chameleon Svn Source Tree

Root/branches/cparm/i386/modules/CPUfreq/CPUfreq.c

1/*
2 * Copyright 2010,2011 valv, cparm <armelcadetpetit@gmail.com>. All rights reserved.
3 */
4#include "libsaio.h"
5#include "bootstruct.h"
6#include "modules.h"
7#include "Platform.h"
8#include "cpu.h"
9
10#define kFixFSB "FixFSB"
11#define MSR_FSB_FREQ0x000000cd
12#define AMD_10H_11H_CONFIG 0xc0010064
13#define kEnableCPUfreq"EnableCPUfreqModule"
14void CPUfreq_hook(void* arg1, void* arg2, void* arg3, void* arg4, void* arg5, void* arg6);
15
16void CPUfreq_hook(void* arg1, void* arg2, void* arg3, void* arg4, void* arg5, void* arg6)
17{
18int bus_ratio;
19uint64_tmsr , fsbFrequency , cpuFrequency , minfsb , maxfsb ;
20
21 uint8_t Model = (uint8_t)get_env(envModel);
22 uint32_tVendor = (uint32_t)get_env(envVendor);
23 uint8_t Family = (uint8_t)get_env(envFamily);
24
25 uint8_t MaxCoef = (uint8_t)get_env(envMaxCoef);
26 uint8_t MaxDiv = (uint8_t)get_env(envMaxDiv);
27 uint8_t CurrDiv = (uint8_t)get_env(envCurrDiv);
28 uint64_t FSBFrequency = get_env(envFSBFreq);
29 uint8_t CurrCoef = (uint8_t)get_env(envCurrCoef);
30 uint64_t CPUFrequency = get_env(envCPUFreq);
31
32
33if ((Vendor == CPUID_VENDOR_INTEL ) && ((Family == 0x06) || (Family == 0x0f)))
34{
35if ((Family == 0x06 && Model >= 0x0c) || (Family == 0x0f && Model >= 0x03))
36{
37
38if (Family == 0x06)
39{
40
41bus_ratio = 0;
42msr = rdmsr64(MSR_FSB_FREQ);
43fsbFrequency = 0;
44cpuFrequency = 0;
45minfsb = 183000000;
46maxfsb = 185000000;
47
48boolfix_fsb = false;
49uint16_t idlo;
50uint8_t crlo, crhi = 0;
51
52switch (Model) {
53case CPUID_MODEL_YONAH:// Core Duo/Solo, Pentium M DC
54case CPUID_MODEL_MEROM:// Core Xeon, Core 2 DC, 65nm
55case 0x16:// Celeron, Core 2 SC, 65nm
56case CPUID_MODEL_PENRYN:// Core 2 Duo/Extreme, Xeon, 45nm
57case CPUID_MODEL_ATOM:// Atom :)
58case 0x27:// Atom Lincroft, 45nm
59{
60getBoolForKey(kFixFSB, &fix_fsb, DEFAULT_BOOT_CONFIG);
61
62if (fix_fsb)
63{
64
65int bus = (msr >> 0) & 0x7;
66switch (bus) {
67case 0:
68fsbFrequency = 266666667;
69break;
70case 1:
71fsbFrequency = 133333333;
72break;
73case 2:
74fsbFrequency = 200000000;
75break;
76case 3:
77fsbFrequency = 166666667;
78break;
79case 4:
80fsbFrequency = 333333333;
81break;
82case 5:
83fsbFrequency = 100000000;
84break;
85case 6:
86fsbFrequency = 400000000;
87break;
88default:
89fsbFrequency = 200000000;
90break;
91}
92
93
94if (((fsbFrequency) > (minfsb) && (fsbFrequency) < (maxfsb)) || (!fsbFrequency))
95{
96fsbFrequency = 200000000;
97}
98 safe_set_env(envFSBFreq, fsbFrequency);
99}
100
101if (getIntForKey("MaxBusRatio", &bus_ratio, DEFAULT_BOOT_CONFIG))
102{
103msr = rdmsr64(MSR_IA32_PERF_STATUS);
104idlo = (msr >> 48) & 0xffff;
105crlo = (idlo >> 8) & 0xff;
106
107//printf("CPUfreq: MinCoef: 0x%x\n",crlo);
108
109
110
111if (MaxCoef)
112{
113if (MaxDiv)
114{
115crhi = (MaxCoef * 10) + 5;
116}
117else
118{
119crhi = MaxCoef * 10;
120}
121}
122if (crlo == 0 || crhi == crlo) goto out;
123
124if ((bus_ratio >= (crlo *10)) && (crhi >= bus_ratio) )
125//if (bus_ratio >= 60)
126{
127uint8_t currdiv = 0, currcoef = 0;
128
129currcoef = (int)(bus_ratio / 10);
130
131uint8_t fdiv = bus_ratio - (currcoef * 10);
132if (fdiv > 0)
133currdiv = 1;
134
135 safe_set_env(envCurrCoef,currcoef);
136 safe_set_env(envCurrDiv,currdiv);
137
138}
139
140
141}
142
143out:
144if (CurrDiv)
145{
146cpuFrequency = (FSBFrequency * ((CurrCoef * 2) + 1) / 2);
147}
148else
149{
150cpuFrequency = (FSBFrequency * CurrCoef);
151}
152
153 safe_set_env(envCPUFreq,cpuFrequency);
154
155verbose("CPU: FSBFreq changed to: %dMHz\n", (uint32_t)(get_env(envFSBFreq) / 1000000));
156verbose("CPU: CPUFreq changed to: %dMHz\n", (uint32_t)(get_env(envCPUFreq) / 1000000));
157
158break;
159}
160case 0x1d:// Xeon MP MP 7400
161default:
162break;
163}
164}
165}
166}
167else if(Vendor == CPUID_VENDOR_AMD && Family == 0x0f) // valv: work in progress
168{
169
170 uint8_t ExtFamily = get_env(envExtFamily);
171 uint64_tTSCFrequency = get_env(envTSCFreq);
172
173uint8_t bus_ratio_current = 0;
174
175if(ExtFamily == 0x00 /* K8 */)
176{
177
178msr = rdmsr64(K8_FIDVID_STATUS);
179bus_ratio_current = (msr & 0x3f) / 2 + 4;
180CurrDiv = (msr & 0x01) * 2;
181if (bus_ratio_current)
182{
183if (CurrDiv)
184{
185 safe_set_env(envFSBFreq,((TSCFrequency * CurrDiv)/bus_ratio_current)); // ?
186}
187else
188{
189 safe_set_env(envFSBFreq, (TSCFrequency/bus_ratio_current) );
190}
191//fsbFrequency = (tscFrequency / bus_ratio_max); // ?
192}
193}
194else if(ExtFamily >= 0x01 /* K10+ */)
195{
196
197msr = rdmsr64(AMD_10H_11H_CONFIG);
198bus_ratio_current = ((msr) & 0x3F);
199
200 safe_set_env(envCurrDiv,((2 << ((msr >> 6) & 0x07)) / 2));
201
202 safe_set_env(envFSBFreq,(CPUFrequency/bus_ratio_current));
203
204
205}
206
207if (!get_env(envFSBFreq))
208{
209 safe_set_env(envFSBFreq,(DEFAULT_FSB * 1000));
210verbose("0 ! using the default value for FSB !\n");
211}
212
213 safe_set_env(envCurrCoef, (bus_ratio_current / 10));
214
215safe_set_env(envCPUFreq,TSCFrequency);
216
217verbose("CPU (AMD): FSBFreq: %dMHz\n", (uint32_t)(get_env(envFSBFreq) / 1000000));
218verbose("CPU (AMD): CPUFreq: %dMHz\n", (uint32_t)(get_env(envCPUFreq) / 1000000));
219verbose("CPU (AMD): CurrCoef: 0x%x\n", (uint32_t)(get_env(envCurrCoef)));
220verbose("CPU (AMD): CurrDiv: 0x%x\n", (uint32_t)(get_env(envCurrDiv)));
221}
222
223}
224
225void CPUfreq_start(void);
226void CPUfreq_start(void)
227{
228bool enable = true;
229getBoolForKey(kEnableCPUfreq, &enable, DEFAULT_BOOT_CONFIG) ;
230
231if (enable)
232{
233if (get_env(envFeatures) & CPUID_FEATURE_MSR)
234{
235register_hook_callback("PreBoot", &CPUfreq_hook);
236}
237else
238{
239verbose ("Unsupported CPU: CPUfreq disabled !!!\n");
240}
241}
242}
243

Archive Download this file

Revision: 1840