2 * This file is part of the coreboot project.
4 * Copyright (C) 2007 Advanced Micro Devices, Inc.
5 * Copyright (C) 2010 Nils Jacobs
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
17 #include <console/console.h>
20 #include <device/device.h>
21 #include <device/pci.h>
22 #include <device/pci_ids.h>
25 #include "northbridge.h"
26 #include <cpu/amd/gx2def.h>
27 #include <cpu/x86/msr.h>
28 #include <cpu/x86/cache.h>
32 unsigned long desc_name
;
33 unsigned short desc_type
;
37 struct gliutable gliu0table
[] = {
38 {.desc_name
=GLIU0_P2D_BM_0
, .desc_type
= BM
,.hi
= MSR_MC
+ 0x0,.lo
= 0x0FFF80}, /* 0-7FFFF to MC */
39 {.desc_name
=GLIU0_P2D_BM_1
, .desc_type
= BM
,.hi
= MSR_MC
+ 0x0,.lo
=(0x80 << 20) + 0x0FFFE0}, /* 80000-9ffff to Mc */
40 {.desc_name
=GLIU0_P2D_SC_0
, .desc_type
= SC_SHADOW
,.hi
= MSR_MC
+ 0x0,.lo
= 0x03}, /* C0000-Fffff split to MC and PCI (sub decode) A0000-Bffff handled by SoftVideo */
41 {.desc_name
=GLIU0_P2D_R_0
, .desc_type
= R_SYSMEM
,.hi
= MSR_MC
,.lo
= 0x0}, /* Catch and fix dynamicly. */
42 {.desc_name
=GLIU0_P2D_BMO_0
, .desc_type
= BMO_SMM
,.hi
= MSR_MC
,.lo
= 0x0}, /* Catch and fix dynamicly. */
43 {.desc_name
=GLIU0_GLD_MSR_COH
, .desc_type
= OTHER
,.hi
= 0x0,.lo
= GL0_CPU
},
44 {.desc_name
=GL_END
, .desc_type
= GL_END
,.hi
= 0x0,.lo
= 0x0},
47 struct gliutable gliu1table
[] = {
48 {.desc_name
=GLIU1_P2D_BM_0
, .desc_type
= BM
,.hi
= MSR_GL0
+ 0x0,.lo
= 0x0FFF80}, /* 0-7FFFF to MC */
49 {.desc_name
=GLIU1_P2D_BM_1
, .desc_type
= BM
,.hi
= MSR_GL0
+ 0x0,.lo
= (0x80 << 20) + 0x0FFFE0},/* 80000-9ffff to Mc */
50 {.desc_name
=GLIU1_P2D_SC_0
, .desc_type
= SC_SHADOW
,.hi
= MSR_GL0
+ 0x0,.lo
= 0x03}, /* C0000-Fffff split to MC and PCI (sub decode) */
51 {.desc_name
=GLIU1_P2D_R_0
, .desc_type
= R_SYSMEM
,.hi
= MSR_GL0
,.lo
= 0x0}, /* Catch and fix dynamicly. */
52 {.desc_name
=GLIU1_P2D_BM_3
, .desc_type
= BM_SMM
,.hi
= MSR_GL0
,.lo
= 0x0}, /* Catch and fix dynamicly. */
53 {.desc_name
=GLIU1_GLD_MSR_COH
, .desc_type
= OTHER
,.hi
= 0x0,.lo
= GL1_GLIU0
},
54 {.desc_name
=GLIU1_IOD_SC_0
, .desc_type
= SCIO
,.hi
= (GL1_GLCP
<< 29) + 0x0,.lo
= 0x033000F0}, /* FooGlue FPU 0xF0 */
55 {.desc_name
=GL_END
, .desc_type
= GL_END
,.hi
= 0x0,.lo
= 0x0},
58 struct gliutable
*gliutables
[] = { gliu0table
, gliu1table
, 0 };
66 struct msrinit ClockGatingDefault
[] = {
67 {GLIU0_GLD_MSR_PM
, {.hi
=0x00,.lo
=0x0005}},
68 /* MC must stay off in SDR mode. It is turned on in CPUBug??? lotus #77.142 */
69 {MC_GLD_MSR_PM
, {.hi
=0x00,.lo
=0x0000}},
70 {GLIU1_GLD_MSR_PM
, {.hi
=0x00,.lo
=0x0005}},
71 {VG_GLD_MSR_PM
, {.hi
=0x00,.lo
=0x0000}}, /* lotus #77.163 */
72 {GP_GLD_MSR_PM
, {.hi
=0x00,.lo
=0x0001}},
73 {DF_GLD_MSR_PM
, {.hi
=0x00,.lo
=0x0155}},
74 {GLCP_GLD_MSR_PM
, {.hi
=0x00,.lo
=0x0015}},
75 {GLPCI_GLD_MSR_PM
, {.hi
=0x00,.lo
=0x0015}},
76 {FG_GLD_MSR_PM
, {.hi
=0x00,.lo
=0x0000}}, /* Always on */
77 {0xffffffff, {0xffffffff, 0xffffffff}},
81 struct msrinit ClockGatingAllOn
[] = {
82 {GLIU0_GLD_MSR_PM
, {.hi
=0x00,.lo
=0x0FFFFFFFF}},
83 {MC_GLD_MSR_PM
, {.hi
=0x00,.lo
=0x0FFFFFFFF}},
84 {GLIU1_GLD_MSR_PM
, {.hi
=0x00,.lo
=0x0FFFFFFFF}},
85 {VG_GLD_MSR_PM
, {.hi
=0x00, .lo
=0x00}},
86 {GP_GLD_MSR_PM
, {.hi
=0x00,.lo
=0x000000001}},
87 {DF_GLD_MSR_PM
, {.hi
=0x00,.lo
=0x0FFFFFFFF}},
88 {GLCP_GLD_MSR_PM
, {.hi
=0x00,.lo
=0x0FFFFFFFF}},
89 {GLPCI_GLD_MSR_PM
, {.hi
=0x00,.lo
=0x0FFFFFFFF}},
90 {FG_GLD_MSR_PM
, {.hi
=0x00,.lo
=0x0000}},
91 {0xffffffff, {0xffffffff, 0xffffffff}},
95 struct msrinit ClockGatingPerformance
[] = {
96 {VG_GLD_MSR_PM
, {.hi
=0x00,.lo
=0x0000}}, /* lotus #77.163 */
97 {GP_GLD_MSR_PM
, {.hi
=0x00,.lo
=0x0001}},
98 {DF_GLD_MSR_PM
, {.hi
=0x00,.lo
=0x0155}},
99 {GLCP_GLD_MSR_PM
, {.hi
=0x00,.lo
=0x0015}},
100 {0xffffffff, {0xffffffff, 0xffffffff}},
103 /* SET GeodeLink PRIORITY */
104 struct msrinit GeodeLinkPriorityTable
[] = {
105 {CPU_GLD_MSR_CONFIG
, {.hi
=0x00,.lo
=0x0220}}, /* CPU Priority. */
106 {DF_GLD_MSR_MASTER_CONF
, {.hi
=0x00,.lo
=0x0000}}, /* DF Priority. */
107 {VG_GLD_MSR_CONFIG
, {.hi
=0x00,.lo
=0x0720}}, /* VG Primary and Secondary Priority. */
108 {GP_GLD_MSR_CONFIG
, {.hi
=0x00,.lo
=0x0010}}, /* Graphics Priority. */
109 {GLPCI_GLD_MSR_CONFIG
, {.hi
=0x00,.lo
=0x0027}}, /* GLPCI Priority + PID */
110 {GLCP_GLD_MSR_CONF
, {.hi
=0x00,.lo
=0x0001}}, /* GLCP Priority + PID */
111 {FG_GLD_MSR_CONFIG
, {.hi
=0x00,.lo
=0x0622}}, /* FG PID */
112 {0x0FFFFFFFF, {0x0FFFFFFFF, 0x0FFFFFFFF}}, /* END */
115 static void writeglmsr(struct gliutable
*gl
)
121 wrmsr(gl
->desc_name
, msr
); /* MSR - see table above */
122 printk(BIOS_DEBUG
, "%s: MSR 0x%08lx, val 0x%08x:0x%08x\n", __func__
, gl
->desc_name
, msr
.hi
, msr
.lo
);
125 static void ShadowInit(struct gliutable
*gl
)
129 msr
= rdmsr(gl
->desc_name
);
136 static void SysmemInit(struct gliutable
*gl
)
139 int sizembytes
, sizebytes
;
141 /* Figure out how much RAM is in the machine and alocate all to the
142 * system. We will adjust for SMM now and Frame Buffer later.
144 sizembytes
= sizeram();
145 printk(BIOS_DEBUG
, "%s: enable for %dMBytes\n", __func__
, sizembytes
);
146 sizebytes
= sizembytes
<< 20;
148 sizebytes
-= ((SMM_SIZE
* 1024) + 1);
150 /* 20 bit address The bottom 12 bits go into bits 20-31 in msr.lo
151 The top 8 bits go into 0-7 of msr.hi. */
153 msr
.hi
= (gl
->hi
& 0xFFFFFF00) | (sizebytes
>> 24);
154 sizebytes
<<= 8; /* move bits 23:12 in bits 31:20. */
155 sizebytes
&= 0xfff00000;
156 sizebytes
|= 0x100; /* start at 1MB */
158 wrmsr(gl
->desc_name
, msr
); /* MSR - see table above */
159 printk(BIOS_DEBUG
, "%s: MSR 0x%08lx, val 0x%08x:0x%08x\n", __func__
,
160 gl
->desc_name
, msr
.hi
, msr
.lo
);
163 static void SMMGL0Init(struct gliutable
*gl
)
166 int sizebytes
= sizeram() << 20;
169 sizebytes
-= (SMM_SIZE
* 1024);
171 printk(BIOS_DEBUG
, "%s: %d bytes\n", __func__
, sizebytes
);
173 offset
= sizebytes
- SMM_OFFSET
;
174 offset
= (offset
>> 12) & 0x000fffff;
175 printk(BIOS_DEBUG
, "%s: offset is 0x%08x\n", __func__
, SMM_OFFSET
);
177 msr
.hi
= offset
<< 8 | gl
->hi
;
178 msr
.hi
|= SMM_OFFSET
>> 24;
180 msr
.lo
= SMM_OFFSET
<< 8;
181 msr
.lo
|= ((~(SMM_SIZE
* 1024) + 1) >> 12) & 0xfffff;
183 wrmsr(gl
->desc_name
, msr
); /* MSR - See table above */
184 printk(BIOS_DEBUG
, "%s: MSR 0x%08lx, val 0x%08x:0x%08x\n", __func__
, gl
->desc_name
, msr
.hi
, msr
.lo
);
187 static void SMMGL1Init(struct gliutable
*gl
)
190 printk(BIOS_DEBUG
, "%s:\n", __func__
);
193 /* I don't think this is needed */
194 msr
.hi
&= 0xffffff00;
195 msr
.hi
|= (SMM_OFFSET
>> 24);
196 msr
.lo
= (SMM_OFFSET
<< 8) & 0xfff00000;
197 msr
.lo
|= ((~(SMM_SIZE
* 1024) + 1) >> 12) & 0xfffff;
199 wrmsr(gl
->desc_name
, msr
); /* MSR - See table above */
200 printk(BIOS_DEBUG
, "%s: MSR 0x%08lx, val 0x%08x:0x%08x\n", __func__
, gl
->desc_name
, msr
.hi
, msr
.lo
);
203 static void GLIUInit(struct gliutable
*gl
)
205 while (gl
->desc_type
!= GL_END
) {
206 switch (gl
->desc_type
) {
209 case SC_SHADOW
: /* Check for a Shadow entry */
213 case R_SYSMEM
: /* check for a SYSMEM entry */
217 case BMO_SMM
: /* check for a SMM entry */
221 case BM_SMM
: /* check for a SMM entry */
229 /* Set up GLPCI settings for reads/write into memory.
232 * R1: 1MB - Top of System Memory
234 * R3: Framebuffer? - not set up yet
237 static void GLPCIInit(void)
239 struct gliutable
*gl
= 0;
244 /* R0 - GLPCI settings for Conventional Memory space. */
245 msr
.hi
= (0x09F000 >> 12) << GLPCI_RC_UPPER_TOP_SHIFT
; /* 640 */
247 msr
.lo
|= GLPCI_RC_LOWER_EN_SET
+ GLPCI_RC_LOWER_PF_SET
+ GLPCI_RC_LOWER_WC_SET
;
251 /* R1 - GLPCI settings for SysMem space. */
252 /* Get systop from GLIU0 SYSTOP Descriptor */
253 for (i
= 0; gliu0table
[i
].desc_name
!= GL_END
; i
++) {
254 if (gliu0table
[i
].desc_type
== R_SYSMEM
) {
260 unsigned long pah
, pal
;
261 msrnum
= gl
->desc_name
;
263 /* example R_SYSMEM value: 20:00:00:0f:fb:f0:01:00
264 * translates to a base of 0x00100000 and top of 0xffbf0000
265 * base of 1M and top of around 256M
267 /* we have to create a page-aligned (4KB page) address for base and top
268 * so we need a high page aligned addresss (pah) and low page aligned address (pal)
269 * pah is from msr.hi << 12 | msr.low >> 20. pal is msr.lo << 12
271 pah
= ((msr
.hi
& 0xff) << 12) | ((msr
.lo
>> 20) & 0xfff);
272 /* we have the page address. Now make it a page-aligned address */
278 msr
.lo
|= GLPCI_RC_LOWER_EN_SET
| GLPCI_RC_LOWER_PF_SET
| GLPCI_RC_LOWER_WC_SET
;
279 printk(BIOS_DEBUG
, "GLPCI R1: system msr.lo 0x%08x msr.hi 0x%08x\n", msr
.lo
, msr
.hi
);
284 /* R2 - GLPCI settings for SMM space. */
285 msr
.hi
= ((SMM_OFFSET
+ (SMM_SIZE
* 1024 - 1)) >> 12) << GLPCI_RC_UPPER_TOP_SHIFT
;
286 msr
.lo
= (SMM_OFFSET
>> 12) << GLPCI_RC_LOWER_BASE_SHIFT
;
287 msr
.lo
|= GLPCI_RC_LOWER_EN_SET
| GLPCI_RC_LOWER_PF_SET
;
288 printk(BIOS_DEBUG
, "GLPCI R2: system msr.lo 0x%08x msr.hi 0x%08x\n", msr
.lo
, msr
.hi
);
292 /* this is done elsewhere already, but it does no harm to do it more than once */
293 /* write serialize memory hole to PCI. Need to unWS when something is shadowed regardless of cachablility. */
294 msr
.lo
= 0x021212121; /* cache disabled and write serialized */
295 msr
.hi
= 0x021212121; /* cache disabled and write serialized */
297 msrnum
= CPU_RCONF_A0_BF
;
300 msrnum
= CPU_RCONF_C0_DF
;
303 msrnum
= CPU_RCONF_E0_FF
;
306 /* Set Non-Cacheable Read Only for NorthBound Transactions to Memory. The Enable bit is handled in the Shadow setup. */
307 msrnum
= GLPCI_A0_BF
;
312 msrnum
= GLPCI_C0_DF
;
317 msrnum
= GLPCI_E0_FF
;
323 msrnum
= CPU_DM_CONFIG0
;
325 msr
.hi
&= ~(7 << DM_CONFIG0_UPPER_WSREQ_SHIFT
);
326 msr
.hi
|= 2 << DM_CONFIG0_UPPER_WSREQ_SHIFT
; /* reduce to 1 for safe mode. */
329 /* we are ignoring the 5530 case for now, and perhaps forever. */
336 msr
.hi
|= GLPCI_ARB_UPPER_PRE0_SET
| GLPCI_ARB_UPPER_PRE1_SET
;
337 msr
.lo
|= GLPCI_ARB_LOWER_IIE_SET
;
343 msr
.lo
|= GLPCI_CTRL_LOWER_ME_SET
| GLPCI_CTRL_LOWER_OWC_SET
| GLPCI_CTRL_LOWER_PCD_SET
; /* (Out will be disabled in CPUBUG649 for < 2.0 parts .) */
344 msr
.lo
|= GLPCI_CTRL_LOWER_LDE_SET
;
346 msr
.lo
&= ~(0x03 << GLPCI_CTRL_LOWER_IRFC_SHIFT
);
347 msr
.lo
|= 0x02 << GLPCI_CTRL_LOWER_IRFC_SHIFT
;
349 msr
.lo
&= ~(0x07 << GLPCI_CTRL_LOWER_IRFT_SHIFT
);
350 msr
.lo
|= 0x06 << GLPCI_CTRL_LOWER_IRFT_SHIFT
;
352 msr
.hi
&= ~(0x0f << GLPCI_CTRL_UPPER_FTH_SHIFT
);
353 msr
.hi
|= 0x0F << GLPCI_CTRL_UPPER_FTH_SHIFT
;
355 msr
.hi
&= ~(0x0f << GLPCI_CTRL_UPPER_RTH_SHIFT
);
356 msr
.hi
|= 0x0F << GLPCI_CTRL_UPPER_RTH_SHIFT
;
358 msr
.hi
&= ~(0x0f << GLPCI_CTRL_UPPER_SBRTH_SHIFT
);
359 msr
.hi
|= 0x0F << GLPCI_CTRL_UPPER_SBRTH_SHIFT
;
361 msr
.hi
&= ~(0x03 << GLPCI_CTRL_UPPER_WTO_SHIFT
);
362 msr
.hi
|= 0x06 << GLPCI_CTRL_UPPER_WTO_SHIFT
;
364 msr
.hi
&= ~(0x03 << GLPCI_CTRL_UPPER_ILTO_SHIFT
);
365 msr
.hi
|= 0x00 << GLPCI_CTRL_UPPER_ILTO_SHIFT
;
368 /* Set GLPCI Latency Timer. */
371 msr
.hi
|= 0x1F << GLPCI_CTRL_UPPER_LAT_SHIFT
; /* Change once 1.x is gone. */
375 msrnum
= GLPCI_SPARE
;
378 msr
.lo
|= GLPCI_SPARE_LOWER_AILTO_SET
| GLPCI_SPARE_LOWER_PPD_SET
| GLPCI_SPARE_LOWER_PPC_SET
| GLPCI_SPARE_LOWER_MPC_SET
| GLPCI_SPARE_LOWER_NSE_SET
| GLPCI_SPARE_LOWER_SUPO_SET
;
382 /* Enable Clock Gating. */
383 static void ClockGatingInit(void)
386 struct msrinit
*gating
= ClockGatingDefault
;
389 for (i
= 0; gating
->msrnum
!= 0xffffffff; i
++) {
390 msr
= rdmsr(gating
->msrnum
);
391 msr
.hi
|= gating
->msr
.hi
;
392 msr
.lo
|= gating
->msr
.lo
;
393 wrmsr(gating
->msrnum
, msr
); /* MSR - See the table above */
398 static void GeodeLinkPriority(void)
400 msr_t msr
= { 0, 0 };
402 struct msrinit
*prio
= GeodeLinkPriorityTable
;
405 for (i
= 0; prio
->msrnum
!= 0xffffffff; i
++) {
406 msr
= rdmsr(prio
->msrnum
);
407 msr
.hi
|= prio
->msr
.hi
;
409 msr
.lo
|= prio
->msr
.lo
;
410 wrmsr(prio
->msrnum
, msr
); /* MSR - See the table above */
415 /* Get the GLIU0 shadow register settings.
417 * If the setShadow function is used then all shadow descriptors
420 static uint64_t getShadow(void)
422 msr_t msr
= { 0, 0 };
424 msr
= rdmsr(GLIU0_P2D_SC_0
);
425 return ( ( (uint64_t) msr
.hi
) << 32 ) | msr
.lo
;
428 /* Set the cache RConf registers for the memory hole.
430 * Keeps all cache shadow descriptors sync'ed.
431 * This is part of the PCI lockup solution.
433 * Entry: EDX:EAX is the shadow settings.
435 static void setShadowRCONF(uint32_t shadowHi
, uint32_t shadowLo
)
437 /* ok this is whacky bit translation time. */
440 msr_t msr
= { 0, 0 };
441 shadowByte
= (uint8_t) (shadowLo
>> 16);
443 /* load up D000 settings in edx. */
444 for (bit
= 8; (bit
> 4); bit
--) {
446 msr
.hi
|= 1; /* cache disable PCI/Shadow memory */
447 if (shadowByte
&& (1 << bit
))
448 msr
.hi
|= 0x20; /* write serialize PCI memory */
451 /* load up C000 settings in eax. */
454 msr
.lo
|= 1; /* cache disable PCI/Shadow memory */
455 if (shadowByte
&& (1 << bit
))
456 msr
.lo
|= 0x20; /* write serialize PCI memory */
459 wrmsr(CPU_RCONF_C0_DF
, msr
);
461 shadowByte
= (uint8_t) (shadowLo
>> 24);
463 /* load up F000 settings in edx. */
464 for (bit
= 8; (bit
> 4); bit
--) {
466 msr
.hi
|= 1; /* cache disable PCI/Shadow memory */
467 if (shadowByte
&& (1 << bit
))
468 msr
.hi
|= 0x20; /* write serialize PCI memory */
471 /* load up E000 settings in eax. */
474 msr
.lo
|= 1; /* cache disable PCI/Shadow memory */
475 if (shadowByte
&& (1 << bit
))
476 msr
.lo
|= 0x20; /* write serialize PCI memory */
479 wrmsr(CPU_RCONF_E0_FF
, msr
);
482 /* Set the GLPCI registers for the memory hole.
483 * Keeps all cache shadow descriptors sync'ed.
484 * Entry: EDX:EAX is the shadow settings
486 static void setShadowGLPCI(uint32_t shadowHi
, uint32_t shadowLo
)
490 /* Set the Enable Register. */
491 msr
= rdmsr(GLPCI_REN
);
492 msr
.lo
&= 0xFFFF00FF;
493 msr
.lo
|= ((shadowLo
& 0xFFFF0000) >> 8);
494 wrmsr(GLPCI_REN
, msr
);
497 /* Set the GLIU SC register settings. Scans descriptor tables for SC_SHADOW.
498 * Keeps all shadow descriptors sync'ed.
499 * Entry: EDX:EAX is the shadow settings
501 static void setShadow(uint64_t shadowSettings
)
505 struct gliutable
*pTable
;
506 uint32_t shadowLo
, shadowHi
;
508 shadowLo
= (uint32_t) shadowSettings
;
509 shadowHi
= (uint32_t) (shadowSettings
>> 32);
511 setShadowRCONF(shadowHi
, shadowLo
);
512 setShadowGLPCI(shadowHi
, shadowLo
);
514 for (i
= 0; gliutables
[i
]; i
++) {
515 for (pTable
= gliutables
[i
]; pTable
->desc_type
!= GL_END
; pTable
++) {
516 if (pTable
->desc_type
== SC_SHADOW
) {
518 msr
= rdmsr(pTable
->desc_name
);
519 msr
.lo
= (uint32_t) shadowSettings
;
520 msr
.hi
&= 0xFFFF0000; /* maintain PDID in upper EDX */
521 msr
.hi
|= ((uint32_t) (shadowSettings
>> 32)) & 0x0000FFFF;
522 wrmsr(pTable
->desc_name
, msr
); /* MSR - See the table above */
529 static void rom_shadow_settings(void)
531 uint64_t shadowSettings
= getShadow();
532 shadowSettings
&= (uint64_t) 0xFFFF00000000FFFFULL
; /* Disable read & writes */
533 shadowSettings
|= (uint64_t) 0x0000FFFFFFFF0000ULL
; /* Enable reads for C0000-FFFFF */
534 setShadow(shadowSettings
);
537 /* Set up RCONF_DEFAULT and any other RCONF registers needed.
539 * DEVRC_RCONF_DEFAULT:
540 * ROMRC(63:56) = 04h ; write protect ROMBASE
541 * ROMBASE(36:55) = 0FFFC0h ; Top of PCI/bottom of rom chipselect area
542 * DEVRC(35:28) = 39h ; cache disabled in PCI memory + WS bit on + Write Combine + write burst.
543 * SYSTOP(27:8) = top of system memory
544 * SYSRC(7:0) = 00h ; writeback, can set to 08h to make writethrough
546 #define SYSMEM_RCONF_WRITETHROUGH 8
547 #define DEVRC_RCONF_DEFAULT 0x21ul
548 #define ROMBASE_RCONF_DEFAULT 0xFFFC0000
549 #define ROMRC_RCONF_DEFAULT 0x25
551 static void enable_L_cache(void)
553 struct gliutable
*gl
= 0;
556 uint8_t SysMemCacheProp
;
558 /* Locate SYSMEM entry in GLIU0table */
559 for (i
= 0; gliu0table
[i
].desc_name
!= GL_END
; i
++) {
560 if (gliu0table
[i
].desc_type
== R_SYSMEM
) {
566 post_code(0xCE); /* POST_RCONFInitError */
571 msr
= rdmsr(gl
->desc_name
);
573 /* 20 bit address - The bottom 12 bits go into bits 20-31 in eax, the
574 * top 8 bits go into 0-7 of edx.
576 msr
.lo
= (msr
.lo
& 0xFFFFFF00) | (msr
.hi
& 0xFF);
577 msr
.lo
= ((msr
.lo
<< 12) | (msr
.lo
>> 20)) & 0x000FFFFF;
578 msr
.lo
<<= RCONF_DEFAULT_LOWER_SYSTOP_SHIFT
; /* 8 */
580 /* Set Default SYSMEM region properties */
581 msr
.lo
&= ~SYSMEM_RCONF_WRITETHROUGH
; /* NOT writethrough == writeback 8 (or ~8) */
583 /* Set PCI space cache properties */
584 msr
.hi
= (DEVRC_RCONF_DEFAULT
>> 4); /* setting is split betwwen hi and lo... */
585 msr
.lo
|= (DEVRC_RCONF_DEFAULT
<< 28);
587 /* Set the ROMBASE. This is usually FFFC0000h */
588 msr
.hi
|= (ROMBASE_RCONF_DEFAULT
>> 12) << RCONF_DEFAULT_UPPER_ROMBASE_SHIFT
;
590 /* Set ROMBASE cache properties. */
591 msr
.hi
|= ((ROMRC_RCONF_DEFAULT
>> 8) | (ROMRC_RCONF_DEFAULT
<< 24));
593 /* now program RCONF_DEFAULT */
594 wrmsr(CPU_RCONF_DEFAULT
, msr
);
595 printk(BIOS_DEBUG
, "CPU_RCONF_DEFAULT (1808): 0x%08X:0x%08X\n", msr
.hi
, msr
.lo
);
597 /* RCONF_BYPASS: Cache tablewalk properties and SMM header access properties. */
598 /* Set to match system memory cache properties. */
599 msr
= rdmsr(CPU_RCONF_DEFAULT
);
600 SysMemCacheProp
= (uint8_t) (msr
.lo
& 0xFF);
601 msr
= rdmsr(CPU_RCONF_BYPASS
);
602 msr
.lo
= (msr
.lo
& 0xFFFF0000) | (SysMemCacheProp
<< 8) | SysMemCacheProp
;
603 wrmsr(CPU_RCONF_BYPASS
, msr
);
604 printk(BIOS_DEBUG
, "CPU_RCONF_BYPASS (180A): 0x%08x : 0x%08x\n", msr
.hi
, msr
.lo
);
607 static void setup_gx2_cache(void)
613 /* Make sure all INVD instructions are treated as WBINVD. We do this
614 * because we've found some programs which require this behavior.
616 msr
= rdmsr(CPU_DM_CONFIG0
);
617 msr
.lo
|= DM_CONFIG0_LOWER_WBINVD_SET
;
618 wrmsr(CPU_DM_CONFIG0
, msr
);
624 uint32_t get_systop(void)
626 struct gliutable
*gl
= 0;
631 for (i
= 0; gliu0table
[i
].desc_name
!= GL_END
; i
++) {
632 if (gliu0table
[i
].desc_type
== R_SYSMEM
) {
638 msr
= rdmsr(gl
->desc_name
);
639 systop
= ((msr
.hi
& 0xFF) << 24) | ((msr
.lo
& 0xFFF00000) >> 8);
640 systop
+= 0x1000; /* 4K */
643 ((sizeram() - CONFIG_VIDEO_MB
) * 1024) - SMM_SIZE
- 1024;
648 /* Core Logic initialization: Host bridge. */
649 void northbridge_init_early(void)
652 printk(BIOS_DEBUG
, "Enter %s\n", __func__
);
654 for (i
= 0; gliutables
[i
]; i
++)
655 GLIUInit(gliutables
[i
]);
657 /* Now that the descriptor to memory is set up. */
658 /* The memory controller needs one read to synch its lines before it can be used. */
659 i
= *(volatile int *) 0;
665 rom_shadow_settings();
671 __asm__
__volatile__("FINIT\n");
672 printk(BIOS_DEBUG
, "Exit %s\n", __func__
);