This patch cleans up and clarifies Geode source code comments.
[coreboot.git] / src / cpu / amd / model_lx / cpureginit.c
1 /*
2  * This file is part of the LinuxBIOS project.
3  *
4  * Copyright (C) 2006 Indrek Kruusa <indrek.kruusa@artecdesign.ee>
5  * Copyright (C) 2006 Ronald G. Minnich <rminnich@gmail.com>
6  * Copyright (C) 2007 Advanced Micro Devices, Inc.
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
21  */
22
23 /**************************************************************************
24 ;*
25 ;*      SetDelayControl
26 ;*
27 ;*************************************************************************/
28 void SetDelayControl(void)
29 {
30         unsigned int msrnum, glspeed;
31         unsigned char spdbyte0, spdbyte1;
32         msr_t msr;
33
34         glspeed = GeodeLinkSpeed();
35
36         /* fix delay controls for DM and IM arrays */
37         msrnum = CPU_BC_MSS_ARRAY_CTL0;
38         msr.hi = 0;
39         msr.lo = 0x2814D352;
40         wrmsr(msrnum, msr);
41
42         msrnum = CPU_BC_MSS_ARRAY_CTL1;
43         msr.hi = 0;
44         msr.lo = 0x1068334D;
45         wrmsr(msrnum, msr);
46
47         msrnum = CPU_BC_MSS_ARRAY_CTL2;
48         msr.hi = 0x00000106;
49         msr.lo = 0x83104104;
50         wrmsr(msrnum, msr);
51
52         msrnum = GLCP_FIFOCTL;
53         msr = rdmsr(msrnum);
54         msr.hi = 0x00000005;
55         wrmsr(msrnum, msr);
56
57         /* Enable setting */
58         msrnum = CPU_BC_MSS_ARRAY_CTL_ENA;
59         msr.hi = 0;
60         msr.lo = 0x00000001;
61         wrmsr(msrnum, msr);
62
63         /* Debug Delay Control Setup Check
64            Leave it alone if it has been setup. FS2 or something is here. */
65         msrnum = GLCP_DELAY_CONTROLS;
66         msr = rdmsr(msrnum);
67         if (msr.lo & ~(0x7C0)) {
68                 return;
69         }
70
71         /*
72          * Delay Controls based on DIMM loading. UGH!
73          * # of Devices = Module Width (SPD6) / Device Width(SPD13) * Physical Banks(SPD5)
74          * Note - We only support module width of 64.
75          */
76         spdbyte0 = spd_read_byte(DIMM0, SPD_PRIMARY_SDRAM_WIDTH);
77         if (spdbyte0 != 0xFF) {
78                 spdbyte0 = (unsigned char)64 / spdbyte0 *
79                     (unsigned char)(spd_read_byte(DIMM0, SPD_NUM_DIMM_BANKS));
80         } else {
81                 spdbyte0 = 0;
82         }
83
84         spdbyte1 = spd_read_byte(DIMM1, SPD_PRIMARY_SDRAM_WIDTH);
85         if (spdbyte1 != 0xFF) {
86                 spdbyte1 = (unsigned char)64 / spdbyte1 *
87                     (unsigned char)(spd_read_byte(DIMM1, SPD_NUM_DIMM_BANKS));
88         } else {
89                 spdbyte1 = 0;
90         }
91
92 /* The current thinking. Subject to change...
93
94 ;                                                                  "FUTURE ROBUSTNESS" PROPOSAL
95 ;                                                                  ----------------------------
96 ;               DIMM     Max MBUS                                          MC 0x2000001A bits 26:24
97 ;DIMMs  devices  Frequency       MCP 0x4C00000F Setting          vvv
98 ;-----  -------  ---------       ----------------------  ----------
99 ;1               4               400MHz          0x82*100FF 0x56960004            4
100 ;1               8               400MHz          0x82*100AA 0x56960004            4
101 ;1               16              400MHz          0x82*10055 0x56960004            4
102 ;
103 ;2               4,4     400MHz          0x82710000 0x56960004            4
104 ;
105 ;1               4               <=333MHz        0x83*100FF 0x56960004            3
106 ;1               8               <=333MHz        0x83*100AA 0x56960004            3
107 ;1               16              <=333MHz        0x83*100AA 0x56960004            3
108 ;
109 ;2               4,4     <=333MHz        0x837100A5 0x56960004            3
110 ;2               8,8     <=333MHz        0x937100A5 0x56960004            3
111 ;
112 ;=========================================================================
113 ;* - Bit 55 (disable SDCLK 1,3,5) should be set if there is a single DIMM in slot 0,
114 ;        but it should be clear for all 2 DIMM settings and if a single DIMM is in slot 1.
115 ;        Bits 54:52 should always be set to '111'.
116
117 ;No VTT termination
118 ;-------------------------------------
119 ;ADDR/CTL have 22 ohm series R
120 ;DQ/DQM/DQS have 33 ohm series R
121 ;
122 ;               DIMM     Max MBUS
123 ;DIMMs  devices  Frequency       MCP 0x4C00000F Setting
124 ;-----  -------  ---------       ----------------------
125 ;1               4               400MHz          0xF2F100FF 0x56960004            4                     The No VTT changes improve timing.
126 ;1               8               400MHz          0xF2F100FF 0x56960004            4
127 ;1               4               <=333MHz        0xF2F100FF 0x56960004            3
128 ;1               8               <=333MHz        0xF2F100FF 0x56960004            3
129 ;1               16              <=333MHz        0xF2F100FF 0x56960004            3
130 */
131         msr.hi = msr.lo = 0;
132
133         if (spdbyte0 == 0 || spdbyte1 == 0) {
134                 /* one dimm solution */
135                 if (spdbyte1 == 0) {
136                         msr.hi |= 0x000800000;
137                 }
138                 spdbyte0 += spdbyte1;
139                 if (spdbyte0 > 8) {
140                         /* large dimm */
141                         if (glspeed < 334) {
142                                 msr.hi |= 0x0837100AA;
143                                 msr.lo |= 0x056960004;
144                         } else {
145                                 msr.hi |= 0x082710055;
146                                 msr.lo |= 0x056960004;
147                         }
148                 } else if (spdbyte0 > 4) {
149                         /* medium dimm */
150                         if (glspeed < 334) {
151                                 msr.hi |= 0x0837100AA;
152                                 msr.lo |= 0x056960004;
153                         } else {
154                                 msr.hi |= 0x0827100AA;
155                                 msr.lo |= 0x056960004;
156                         }
157                 } else {
158                         /* small dimm */
159                         if (glspeed < 334) {
160                                 msr.hi |= 0x0837100FF;
161                                 msr.lo |= 0x056960004;
162                         } else {
163                                 msr.hi |= 0x0827100FF;
164                                 msr.lo |= 0x056960004;
165                         }
166                 }
167         } else {
168                 /* two dimm solution */
169                 spdbyte0 += spdbyte1;
170                 if (spdbyte0 > 24) {
171                         /* huge dimms */
172                         if (glspeed < 334) {
173                                 msr.hi |= 0x0B37100A5;
174                                 msr.lo |= 0x056960004;
175                         } else {
176                                 msr.hi |= 0x0B2710000;
177                                 msr.lo |= 0x056960004;
178                         }
179                 } else if (spdbyte0 > 16) {
180                         /* large dimms */
181                         if (glspeed < 334) {
182                                 msr.hi |= 0x0B37100A5;
183                                 msr.lo |= 0x056960004;
184                         } else {
185                                 msr.hi |= 0x0B27100A5;
186                                 msr.lo |= 0x056960004;
187                         }
188                 } else if (spdbyte0 >= 8) {
189                         /* medium dimms */
190                         if (glspeed < 334) {
191                                 msr.hi |= 0x0937100A5;
192                                 msr.lo |= 0x056960004;
193                         } else {
194                                 msr.hi |= 0x0C27100A5;
195                                 msr.lo |= 0x056960004;
196                         }
197                 } else {
198                         /* small dimms */
199                         if (glspeed < 334) {
200                                 msr.hi |= 0x0837100A5;
201                                 msr.lo |= 0x056960004;
202                         } else {
203                                 msr.hi |= 0x082710000;
204                                 msr.lo |= 0x056960004;
205                         }
206                 }
207         }
208         wrmsr(GLCP_DELAY_CONTROLS, msr);
209         return;
210 }
211
212 /* ***************************************************************************/
213 /* *    cpuRegInit*/
214 /* ***************************************************************************/
215 void cpuRegInit(void)
216 {
217         int msrnum;
218         msr_t msr;
219
220         /* Castle 2.0 BTM periodic sync period. */
221         /*      [40:37] 1 sync record per 256 bytes */
222         msrnum = CPU_PF_CONF;
223         msr = rdmsr(msrnum);
224         msr.hi |= (0x8 << 5);
225         wrmsr(msrnum, msr);
226
227         /*
228          * LX performance setting.
229          * Enable Quack for fewer re-RAS on the MC
230          */
231         msrnum = GLIU0_ARB;
232         msr = rdmsr(msrnum);
233         msr.hi &= ~ARB_UPPER_DACK_EN_SET;
234         msr.hi |= ARB_UPPER_QUACK_EN_SET;
235         wrmsr(msrnum, msr);
236
237         msrnum = GLIU1_ARB;
238         msr = rdmsr(msrnum);
239         msr.hi &= ~ARB_UPPER_DACK_EN_SET;
240         msr.hi |= ARB_UPPER_QUACK_EN_SET;
241         wrmsr(msrnum, msr);
242
243         /*      GLIU port active enable, limit south pole masters (AES and PCI) to one outstanding transaction. */
244         msrnum = GLIU1_PORT_ACTIVE;
245         msr = rdmsr(msrnum);
246         msr.lo &= ~0x880;
247         wrmsr(msrnum, msr);
248
249         /* Set the Delay Control in GLCP */
250         SetDelayControl();
251
252         /*  Enable RSDC */
253         msrnum = CPU_AC_SMM_CTL;
254         msr = rdmsr(msrnum);
255         msr.lo |= SMM_INST_EN_SET;
256         wrmsr(msrnum, msr);
257
258         /* FPU imprecise exceptions bit */
259         msrnum = CPU_FPU_MSR_MODE;
260         msr = rdmsr(msrnum);
261         msr.lo |= FPU_IE_SET;
262         wrmsr(msrnum, msr);
263
264         /* Power Savers (Do after BIST) */
265         /* Enable Suspend on HLT & PAUSE instructions */
266         msrnum = CPU_XC_CONFIG;
267         msr = rdmsr(msrnum);
268         msr.lo |= XC_CONFIG_SUSP_ON_HLT | XC_CONFIG_SUSP_ON_PAUSE;
269         wrmsr(msrnum, msr);
270
271         /* Enable SUSP and allow TSC to run in Suspend (keep speed detection happy) */
272         msrnum = CPU_BC_CONF_0;
273         msr = rdmsr(msrnum);
274         msr.lo |= TSC_SUSP_SET | SUSP_EN_SET;
275         msr.lo &= 0x0F0FFFFFF;
276         msr.lo |= 0x002000000;  /* PBZ213: Set PAUSEDLY = 2 */
277         wrmsr(msrnum, msr);
278
279         /* Disable the debug clock to save power. */
280         /* NOTE: leave it enabled for fs2 debug */
281 #if 0
282         msrnum = GLCP_DBGCLKCTL;
283         msr.hi = 0;
284         msr.lo = 0;
285         wrmsr(msrnum, msr);
286 #endif
287
288         /* Setup throttling delays to proper mode if it is ever enabled. */
289         msrnum = GLCP_TH_OD;
290         msr.hi = 0;
291         msr.lo = 0x00000603C;
292         wrmsr(msrnum, msr);
293 }