2 * This file is part of the coreboot project.
4 * Copyright (C) 2007 Advanced Micro Devices, Inc.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 #include <cpu/x86/tsc.h>
24 static u32 get_vstime(u32 nodeid, u32 slam)
30 #if defined(__ROMCC__)
31 dev = NODE_PCI(nodeid, 3);
33 dev = get_node_pci(nodeid, 3);
36 val = pci_read_config32(dev, 0xd8);
42 case 4: v = 60; break;
43 case 5: v = 100; break;
44 case 6: v = 200; break;
45 case 7: v = 500; break;
47 v = (val+1)*10; // in us
53 static void udelay_tsc(u32 us)
55 /* Use TSC to delay because it is fixed, ie. it will not changed with p-states.
56 * Also, We use the APIC TIMER register is to hold flags for AP init.
59 tsc_t tsc, tsc1, tscd;
60 u32 d = 0x00000200; //800Mhz or 200Mhz or 1.6G or get the NBFID at first
61 u32 dn = 0x1000000/2; // howmany us need to use hi
64 tscd.lo = (us - tscd.hi * dn) * d;
67 dword = tsc1.lo + tscd.lo;
68 if((dword<tsc1.lo) || (dword<tscd.lo)) {
76 } while ((tsc.hi>tsc1.hi) || ((tsc.hi==tsc1.hi) && (tsc.lo>tsc1.lo)));
81 void udelay(u32 usecs)
87 static u32 set_vid(u32 newvid, u32 bit_offset, u32 nodeid, u32 coreid)
97 msr = rdmsr(0xc0010071);//status
98 curvid = (msr.lo >> bit_offset) & 0x7f; // seven bits
100 if(newvid == curvid) return curvid;
102 #if defined(__ROMCC__)
103 dev = NODE_PCI(nodeid, 3);
105 dev = get_node_pci(nodeid, 3);
108 val = pci_read_config32(dev, 0xa0);
110 slam = (val >> 29) & 1;
111 delay = get_vstime(nodeid, slam);
115 count = (curvid - newvid) * 2;
117 count = (newvid - curvid) * 2;
133 msr = rdmsr(0xc0010070); //control
134 msr.lo &= ~(0x7f<<bit_offset);
135 msr.lo |= (curvid<<bit_offset);
136 wrmsr(0xc0010070, msr); // how about all copys, APIC or PCI conf space?
140 msr = rdmsr(0xc0010071);//status
141 curvid = (msr.lo >> bit_offset) & 0x7f; // seven bits
143 if(curvid == newvid) break;
151 static u32 set_nb_vid(u32 newvid, u32 nodeid, u32 coreid)
153 return set_vid(newvid, 25, nodeid, coreid);
157 static u32 set_core_vid(u32 newvid, u32 nodeid, u32 coreid)
159 return set_vid(newvid, 9, nodeid, coreid);
163 static unsigned set_cof(u32 val, u32 mask, u32 nodeid, u32 coreid)
170 // FIXME: What is count for? Why 3 times? What about node and core id?
173 msr = rdmsr(0xc0010071);
175 if(msr.lo == val) break;
177 msr = rdmsr(0xc0010070);
180 wrmsr(0xc0010070, msr);
186 static u32 set_core_cof(u32 fid, u32 did, u32 nodeid, u32 coreid)
191 mask = (7<<6) | 0x3f;
192 val = ((did & 7)<<6) | (fid & 0x3f);
194 return set_cof(val, mask, nodeid, coreid);
199 static u32 set_nb_cof(u32 did, u32 nodeid, u32 coreid) // fid need warmreset
207 return set_cof(val, mask, nodeid, coreid);
212 /* set vid and cof for core and nb after warm reset is not started by BIOS */
213 static void set_core_nb_max_pstate_after_other_warm_reset(u32 nodeid, u32 coreid) // P0
222 msr = rdmsr(0xc0010064);
224 #if defined(__ROMCC__)
225 dev = NODE_PCI(nodeid, 3);
227 dev = get_node_pci(nodeid, 3);
230 val = pci_read_config32(dev, 0xa0);
231 if((val>>8) & 1) { // PVI
232 vid = (msr.lo >> 25) & 0x7f;
234 vid = (msr.lo >> 9) & 0x7f;
236 set_core_vid(vid, nodeid, coreid);
238 mask = (0x7<<6) | 0x3f;
240 set_cof(val, mask, nodeid, coreid);
243 did = (msr.lo >> 22) & 1;
244 vid = (msr.lo >> 25) & 0x7f;
246 set_nb_cof(did, nodeid, coreid);
247 set_nb_vid(vid, nodeid, coreid);
249 set_nb_vid(vid, nodeid, coreid);
250 set_nb_cof(did, nodeid, coreid);
256 wrmsr(0xc0010062, msr);
261 /* set vid and cof for core and nb after warm reset is not started by BIOS */
262 static void set_core_nb_min_pstate_after_other_warm_reset(u32 nodeid, u32 coreid) // Px
272 #if defined(__ROMCC__)
273 dev = NODE_PCI(nodeid, 3);
275 dev = get_node_pci(nodeid, 3);
279 val = pci_read_config32(dev, 0xdc); //PstateMaxVal
281 pstate = (val >> 8) & 0x7;
283 msr = rdmsr(0xc0010064 + pstate);
285 mask = (7<<6) | 0x3f;
287 set_cof(val, mask, nodeid, coreid);
289 val = pci_read_config32(dev, 0xa0);
290 if((val>>8) & 1) { // PVI
291 vid = (msr.lo>>25) & 0x7f;
293 vid = (msr.lo>>9) & 0x7f;
295 set_core_vid(vid, nodeid, coreid);
298 did = (msr.lo >> 22) & 1;
299 vid = (msr.lo >> 25) & 0x7f;
301 set_nb_cof(did, nodeid, coreid);
302 set_nb_vid(vid, nodeid, coreid);
304 set_nb_vid(vid, nodeid, coreid);
305 set_nb_cof(did, nodeid, coreid);
311 wrmsr(0xc0010062, msr);