resolve conflict
[coreboot.git] / src / northbridge / amd / gx2 / pll_reset.c
1 #include <cpu/x86/tsc.h>
2
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 */
6
7 static unsigned int calibrate_tsc(void)
8 {
9         /* Set the Gate high, disable speaker */
10         outb((inb(0x61) & ~0x02) | 0x01, 0x61);
11
12         /*
13          * Now let's take care of CTC channel 2
14          *
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.
18          */
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 */
22
23         {
24                 tsc_t start;
25                 tsc_t end;
26                 unsigned long count;
27
28                 start = rdtsc();
29                 count = 0;
30                 do {
31                         count++;
32                 } while ((inb(0x61) & 0x20) == 0);
33                 end = rdtsc();
34
35                 /* Error: ECTCNEVERSET */
36                 if (count <= 1)
37                         goto bad_ctc;
38
39                 /* 64-bit subtract - gcc just messes up with long longs */
40                 __asm__("subl %2,%0\n\t"
41                         "sbbl %3,%1"
42                         :"=a" (end.lo), "=d" (end.hi)
43                         :"g" (start.lo), "g" (start.hi),
44                          "0" (end.lo), "1" (end.hi));
45
46                 /* Error: ECPUTOOFAST */
47                 if (end.hi)
48                         goto bad_ctc;
49
50
51                 /* Error: ECPUTOOSLOW */
52                 if (end.lo <= CALIBRATE_DIVISOR)
53                         goto bad_ctc;
54
55                 return (end.lo + CALIBRATE_DIVISOR -1)/CALIBRATE_DIVISOR;
56         }
57
58         /*
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
61          * 32 bits..
62          */
63 bad_ctc:
64         print_err("bad_ctc\n");
65         return 0;
66 }
67
68 /* spll_raw_clk = SYSREF * FbDIV,
69  * GLIU Clock   = spll_raw_clk / MDIV
70  * CPU Clock    = sppl_raw_clk / VDIV
71  */
72
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 */
79 };
80
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
87 };
88
89 static const unsigned char pci33_ddr_crt [] = {
90         /* FbDIV, VDIV, MDIV               CPU/GeodeLink */
91              12,    2,    3,            // 200/133
92              16,    2,    3,            // 266/177
93              18,    2,    3,            // 300/200
94              20,    2,    3,            // 333/222
95              22,    2,    3,            // 366/244
96              24,    2,    3,            // 400/266
97              26,    2,    3             // 433/289
98 };
99
100 #if 0
101 static unsigned int get_memory_speed(void)
102 {
103         unsigned char val, hi, lo;
104
105         val = spd_read_byte(0xA0, 9);
106         hi = (val >> 4) & 0x0f;
107         lo = val & 0x0f;
108
109         return 20000/(hi*10 + lo);
110 }
111 #endif
112
113 static void pll_reset(void)
114 {
115         msr_t msr;
116         unsigned int sysref, spll_raw, cpu_core, gliu;
117         unsigned mdiv, vdiv, fbdiv;
118
119         /* get CPU core clock in MHZ */
120         cpu_core = calibrate_tsc();
121         print_debug("Cpu core is ");
122         print_debug_hex32(cpu_core);
123         print_debug("\n");
124
125         msr = rdmsr(GLCP_SYS_RSTPLL);
126         if (msr.lo & (1 << GLCP_SYS_RSTPLL_BYPASS)) {
127 #if 0
128                 print_debug("MSR ");
129                 print_debug_hex32(GLCP_SYS_RSTPLL);
130                 print_debug("is ");
131                 print_debug_hex32(msr.hi);
132                 print_debug(":");
133                 print_debug_hex32(msr.lo);
134
135                 msr.hi = PLLMSRhi;
136                 msr.lo = PLLMSRlo;
137                 wrmsr(GLCP_SYS_RSTPLL, msr);
138                 msr.lo |= PLLMSRlo1;
139                 wrmsr(GLCP_SYS_RSTPLL, msr);
140
141                 print_debug("Reset PLL\n\r");
142
143                 msr.lo |= PLLMSRlo2;
144                 wrmsr(GLCP_SYS_RSTPLL,msr);
145                 print_debug("should not be here\n\r");
146 #endif
147                 print_err("shit");
148                 while (1)
149                         ;
150         }
151
152         if (msr.lo & GLCP_SYS_RSTPLL_SWFLAGS_MASK) {
153                 /* PLL is already set and we are reboot from PLL reset */
154                 print_debug("reboot from BIOS reset\n\r");
155                 return;
156         }
157
158         /* get the sysref clock rate */
159         vdiv  = (msr.hi >> GLCP_SYS_RSTPLL_VDIV_SHIFT) & 0x07;
160         vdiv += 2;
161         fbdiv = (msr.hi >> GLCP_SYS_RSTPLL_FBDIV_SHIFT) & 0x3f;
162         fbdiv = fbdiv2plldiv[fbdiv];
163         spll_raw = cpu_core * vdiv;
164         sysref   = spll_raw / fbdiv;
165
166         /* get target memory rate by SPD */
167         //gliu = get_memory_speed();
168
169         msr.hi = 0x00000019;
170         msr.lo = 0x06de0378;
171         wrmsr(0x4c000014, msr);
172         msr.lo |= ((0xde << 16) | (1 << 26) | (1 << 24));
173         wrmsr(0x4c000014, msr);
174
175         print_debug("Reset PLL\n\r");
176
177         msr.lo |= ((1<<14) |(1<<13) | (1<<0));
178         wrmsr(0x4c000014,msr);
179
180         print_debug("should not be here\n\r");
181 }