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

Archive Download this file

Revision: 1913