1 #include <cpu/x86/tsc.h>
3 #define CLOCK_TICK_RATE 1193180U /* Underlying HZ */
4 #define CALIBRATE_INTERVAL ((20*CLOCK_TICK_RATE)/1000) /* 20ms */
5 #define CALIBRATE_DIVISOR (20*1000) /* 20ms / 20000 == 1usec */
7 static unsigned int calibrate_tsc(void)
9 /* Set the Gate high, disable speaker */
10 outb((inb(0x61) & ~0x02) | 0x01, 0x61);
13 * Now let's take care of CTC channel 2
15 * Set the Gate high, program CTC channel 2 for mode 0,
16 * (interrupt on terminal count mode), binary count,
17 * load 5 * LATCH count, (LSB and MSB) to begin countdown.
19 outb(0xb0, 0x43); /* binary, mode 0, LSB/MSB, Ch 2 */
20 outb(CALIBRATE_INTERVAL & 0xff, 0x42); /* LSB of count */
21 outb(CALIBRATE_INTERVAL >> 8, 0x42); /* MSB of count */
32 } while ((inb(0x61) & 0x20) == 0);
35 /* Error: ECTCNEVERSET */
39 /* 64-bit subtract - gcc just messes up with long longs */
40 __asm__("subl %2,%0\n\t"
42 :"=a" (end.lo), "=d" (end.hi)
43 :"g" (start.lo), "g" (start.hi),
44 "0" (end.lo), "1" (end.hi));
46 /* Error: ECPUTOOFAST */
51 /* Error: ECPUTOOSLOW */
52 if (end.lo <= CALIBRATE_DIVISOR)
55 return (end.lo + CALIBRATE_DIVISOR -1)/CALIBRATE_DIVISOR;
59 * The CTC wasn't reliable: we got a hit on the very first read,
60 * or the CPU was so fast/slow that the quotient wouldn't fit in
64 print_err("bad_ctc\n");
68 /* spll_raw_clk = SYSREF * FbDIV,
69 * GLIU Clock = spll_raw_clk / MDIV
70 * CPU Clock = sppl_raw_clk / VDIV
73 /* table for Feedback divisor to FbDiv register value */
74 static const unsigned char plldiv2fbdiv[] = {
75 0, 0, 0, 0, 0, 0, 15, 7, 3, 1, 0, 32, 16, 40, 20, 42, /* pll div 0 - 15 */
76 21, 10, 37, 50, 25, 12, 38, 19, 9, 4, 34, 17, 8, 36, 18, 41, /* pll div 16 - 31 */
77 52, 26, 45, 54, 27, 13, 6, 35, 49, 56, 28, 46, 23, 11, 05, 02, /* pll div 32 - 47 */
78 33, 48, 24, 44, 22, 43, 53, 58, 29, 14, 39, 51, 57, 60, 30, 47, /* pll div 48 - 63 */
81 /* table for FbDiv register value to Feedback divisor */
82 static const unsigned char fbdiv2plldiv[] = {
83 10, 9, 47, 8, 25, 46, 38, 7, 28, 24, 17, 45, 21, 37, 57, 6,
84 12, 27, 30, 23, 14, 16, 52, 44, 50, 20, 33, 36, 42, 56, 0, 0,
85 11, 48, 26, 39, 29, 18, 22, 58, 13, 31, 15, 53, 51, 34, 43, 0,
86 49, 40, 19, 59, 32, 54, 35, 0, 41, 60, 55, 0, 61, 0, 0, 0
89 static const unsigned char pci33_ddr_crt [] = {
90 /* FbDIV, VDIV, MDIV CPU/GeodeLink */
101 static unsigned int get_memory_speed(void)
103 unsigned char val, hi, lo;
105 val = spd_read_byte(0xA0, 9);
106 hi = (val >> 4) & 0x0f;
109 return 20000/(hi*10 + lo);
113 #define USE_GOODRICH_VERSION 1
115 #if USE_GOODRICH_VERSION
116 ///////////////////////////////////////////////////////////////////////////////
117 // Goodrich Version of pll_reset
119 // PLLCHECK_COMPLETED is the "we've already done this" flag
120 #define PLLCHECK_COMPLETED (1 << RSTPLL_LOWER_SWFLAGS_SHIFT)
122 #ifndef RSTPPL_LOWER_BYPASS_SET
123 #define RSTPPL_LOWER_BYPASS_SET (1 << GLCP_SYS_RSTPLL_BYPASS)
124 #endif // RSTPPL_LOWER_BYPASS_SET
126 #define DEFAULT_MDIV 3
127 #define DEFAULT_VDIV 2
128 #define DEFAULT_FBDIV 22 // 366/244 ; 24 400/266 018 ;300/200
130 static void pll_reset(void)
132 msr_t msrGlcpSysRstpll;
133 unsigned MDIV_VDIV_FBDIV;
134 unsigned SyncBits; // store the sync bits in up ebx
136 // clear the Bypass bit
138 // If the straps say we are in bypass and the syspll is not AND there are no software
139 // bits set then FS2 or something set up the PLL and we should not change it.
141 msrGlcpSysRstpll = rdmsr(GLCP_SYS_RSTPLL);
142 msrGlcpSysRstpll.lo &= ~RSTPPL_LOWER_BYPASS_SET;
143 wrmsr(GLCP_SYS_RSTPLL, msrGlcpSysRstpll);
145 // If the "we've already been here" flag is set, don't reconfigure the pll
146 if ( !(msrGlcpSysRstpll.lo & PLLCHECK_COMPLETED ) )
147 { // we haven't configured the PLL; do it now
149 // Store PCI33(0)/66(1), SDR(0)/DDR(1), and CRT(0)/TFT(1) in upper esi to get to the
150 // correct Strap Table.
151 post_code(POST_PLL_INIT);
154 msrGlcpSysRstpll.lo &= ~(1 << RSTPPL_LOWER_SDRMODE_SHIFT);
155 wrmsr(GLCP_SYS_RSTPLL, msrGlcpSysRstpll);
157 // Use Manual settings
159 post_code(POST_PLL_MANUAL);
161 // DIV settings manually entered.
162 // ax = VDIV, upper eax = MDIV, upper ecx = FbDIV
163 // use gs and fs since we don't need them.
166 // ax = VDIV, upper eax = MDIV, upper ecx = FbDIV
167 // move everything into ebx
169 MDIV_VDIV_FBDIV = ((DEFAULT_VDIV - 2) << RSTPLL_UPPER_VDIV_SHIFT);
172 MDIV_VDIV_FBDIV |= ((DEFAULT_MDIV - 2) << RSTPLL_UPPER_MDIV_SHIFT);
175 MDIV_VDIV_FBDIV |= (plldiv2fbdiv[DEFAULT_FBDIV] << RSTPLL_UPPER_FBDIV_SHIFT);
177 // write GLCP_SYS_RSTPPL (GLCP reg 0x14) with clock values
178 msrGlcpSysRstpll.lo &= ~(1 << RSTPPL_LOWER_SDRMODE_SHIFT);
179 wrmsr(GLCP_SYS_RSTPLL, msrGlcpSysRstpll);
181 msrGlcpSysRstpll.hi = MDIV_VDIV_FBDIV;
182 wrmsr(GLCP_SYS_RSTPLL, msrGlcpSysRstpll);
184 // Set Reset, LockWait, and SW flag
187 // CheckSemiSync proc
188 // Check for Semi-Sync in GeodeLink and CPU.
189 // We need to do this here since the strap settings don't account for these bits.
190 SyncBits = 0; // store the sync bits in up ebx
192 // Check for Bypass mode.
193 if (msrGlcpSysRstpll.lo & RSTPPL_LOWER_BYPASS_SET)
195 // If we are in BYPASS PCI may or may not be sync'd but CPU and GeodeLink will.
196 SyncBits |= RSTPPL_LOWER_CPU_SEMI_SYNC_SET;
201 // If FBdiv/Mdiv is evenly divisible then set the PCI semi-sync. FB is always greater
202 // look up the real divider... if we get a 0 we have serious problems
203 if ( !(fbdiv2plldiv[((msrGlcpSysRstpll.hi >> RSTPLL_UPPER_FBDIV_SHIFT) & 0x3f)] %
204 (((msrGlcpSysRstpll.hi >> RSTPLL_UPPER_MDIV_SHIFT) & 0x0F) + 2)) )
206 SyncBits |= RSTPPL_LOWER_PCI_SEMI_SYNC_SET;
210 // If Vdiv/Mdiv is evenly divisible then set the CPU semi-sync.
211 // CPU is always greater or equal.
212 if (!((((msrGlcpSysRstpll.hi >> RSTPLL_UPPER_MDIV_SHIFT) & 0x07) + 2) %
213 (((msrGlcpSysRstpll.hi >> RSTPLL_UPPER_VDIV_SHIFT) & 0x0F) + 2)))
215 SyncBits |= RSTPPL_LOWER_CPU_SEMI_SYNC_SET;
221 msrGlcpSysRstpll.lo &= ~(RSTPPL_LOWER_PCI_SEMI_SYNC_SET | RSTPPL_LOWER_CPU_SEMI_SYNC_SET);
222 msrGlcpSysRstpll.lo |= SyncBits;
223 wrmsr(GLCP_SYS_RSTPLL, msrGlcpSysRstpll);
224 // CheckSemiSync endp
226 // now we do the reset
227 // Set hold count to 99 (063h)
228 msrGlcpSysRstpll.lo &= ~(0x0FF << RSTPPL_LOWER_HOLD_COUNT_SHIFT);
229 msrGlcpSysRstpll.lo |= (0x0DE << RSTPPL_LOWER_HOLD_COUNT_SHIFT);
230 msrGlcpSysRstpll.lo |= PLLCHECK_COMPLETED; // Say we are done
231 wrmsr(GLCP_SYS_RSTPLL, msrGlcpSysRstpll);
233 // Don't want to use LOCKWAIT
234 msrGlcpSysRstpll.lo |= (RSTPPL_LOWER_PLL_RESET_SET + RSTPPL_LOWER_PD_SET);
235 msrGlcpSysRstpll.lo |= RSTPPL_LOWER_CHIP_RESET_SET;
236 wrmsr(GLCP_SYS_RSTPLL, msrGlcpSysRstpll);
238 // You should never get here..... The chip has reset.
239 post_code(POST_PLL_RESET_FAIL);
242 } // we haven't configured the PLL; do it now
245 // End of Goodrich version of pll_reset
246 ///////////////////////////////////////////////////////////////////////////////
248 #else // #if USE_GOODRICH_VERSION
250 static void pll_reset(void)
253 unsigned int sysref, spll_raw, cpu_core, gliu;
254 unsigned mdiv, vdiv, fbdiv;
256 /* get CPU core clock in MHZ */
257 cpu_core = calibrate_tsc();
258 print_debug("Cpu core is ");
259 print_debug_hex32(cpu_core);
262 msr = rdmsr(GLCP_SYS_RSTPLL);
263 if (msr.lo & (1 << GLCP_SYS_RSTPLL_BYPASS)) {
266 print_debug_hex32(GLCP_SYS_RSTPLL);
268 print_debug_hex32(msr.hi);
270 print_debug_hex32(msr.lo);
274 wrmsr(GLCP_SYS_RSTPLL, msr);
276 wrmsr(GLCP_SYS_RSTPLL, msr);
278 print_debug("Reset PLL\n");
281 wrmsr(GLCP_SYS_RSTPLL,msr);
282 print_debug("should not be here\n");
289 if (msr.lo & GLCP_SYS_RSTPLL_SWFLAGS_MASK) {
290 /* PLL is already set and we are reboot from PLL reset */
291 print_debug("reboot from BIOS reset\n");
295 /* get the sysref clock rate */
296 vdiv = (msr.hi >> GLCP_SYS_RSTPLL_VDIV_SHIFT) & 0x07;
298 fbdiv = (msr.hi >> GLCP_SYS_RSTPLL_FBDIV_SHIFT) & 0x3f;
299 fbdiv = fbdiv2plldiv[fbdiv];
300 spll_raw = cpu_core * vdiv;
301 sysref = spll_raw / fbdiv;
303 /* get target memory rate by SPD */
304 //gliu = get_memory_speed();
308 wrmsr(0x4c000014, msr);
309 msr.lo |= ((0xde << 16) | (1 << 26) | (1 << 24));
310 wrmsr(0x4c000014, msr);
312 print_debug("Reset PLL\n");
314 msr.lo |= ((1<<14) |(1<<13) | (1<<0));
315 wrmsr(0x4c000014,msr);
317 print_debug("should not be here\n");
319 #endif // #if USE_GOODRICH_VERSION