add support for GLIUInit()

git-svn-id: svn://svn.coreboot.org/coreboot/trunk@2245 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
This commit is contained in:
Ronald G. Minnich 2006-04-07 16:55:20 +00:00
parent 40fedaf6a9
commit 4223188335
1 changed files with 249 additions and 22 deletions

View File

@ -45,6 +45,14 @@ struct gliutable gliu1table[] = {
{.desc_name=GL_END,.desc_type= GL_END,.hi= 0x0,.lo= 0x0}, {.desc_name=GL_END,.desc_type= GL_END,.hi= 0x0,.lo= 0x0},
}; };
struct gliutable *gliutables[] = {gliu0table, gliu1table, 0};
struct msrinit { struct msrinit {
unsigned long msrnum; unsigned long msrnum;
msr_t msr;}; msr_t msr;};
@ -99,34 +107,200 @@ struct msrinit GeodeLinkPriorityTable [] = {
{0x0FFFFFFFF, {0x0FFFFFFFF, 0x0FFFFFFFF}}, /* END*/ {0x0FFFFFFFF, {0x0FFFFFFFF, 0x0FFFFFFFF}}, /* END*/
}; };
/* do we have dmi or not? assume yes */
int havedmi = 1;
/* ***************************************************************************/ static void
/* **/ writeglmsr(struct gliutable *gl){
/* * northBridgeInit*/ msr_t msr;
/* **/
/* * Core Logic initialization: Host bridge*/
/* **/
/* * Entry:*/
/* * Exit:*/
/* * Modified:*/
/* **/
/* ***************************************************************************/
static void ClockGatingInit (void); msr.lo = gl->lo;
static void GLPCIInit(void); msr.hi = gl->hi;
void wrmsr(gl->desc_name, msr);
northbridgeinit(void){ printk_debug("%s: write msr 0x%x, val 0x%x:0x%x\n", __FUNCTION__, gl->desc_name, msr.hi, msr.lo);
printk_debug("Enter %s\n", __FUNCTION__); /* they do this, so we do this */
// post(POST_NORTHB_INIT); msr = rdmsr(gl->desc_name);
GLPCIInit(); printk_debug("%s: AFTER write msr 0x%x, val 0x%x:0x%x\n", __FUNCTION__, gl->desc_name, msr.hi, msr.lo);
ClockGatingInit();
__asm__("FINIT\n");
/* CPUBugsFix -- called elsewhere */
printk_debug("Exit %s\n", __FUNCTION__);
} }
static void
ShadowInit(struct gliutable *gl) {
msr_t msr;
msr = rdmsr(gl->desc_name);
if (msr.lo == 0) {
writeglmsr(gl);
}
}
/* NOTE: transcribed from assembly code. There is the usual redundant assembly nonsense in here.
* CLEAN ME UP
*/
/* yes, this duplicates later code, but it seems that is how they want it done.
*/
extern int sizeram(void);
static void
SysmemInit(struct gliutable *gl) {
msr_t msr;
int sizembytes, sizebytes;
sizembytes = sizeram();
printk_debug("%s: enable for %dm bytes\n", __FUNCTION__, sizembytes);
sizebytes = sizembytes << 20;
sizebytes -= SMM_SIZE*1024 +1;
if (havedmi)
sizebytes -= DMM_SIZE * 1024 + 1;
sizebytes -= 1;
msr.hi = gl->hi | (sizebytes >> 24);
/* set up sizebytes to fit into msr.lo */
sizebytes <<= 8; /* what? well, we want bits 23:12 in bytes 31:20. */
sizebytes &= 0xfff00000;
sizebytes |= 0x100;
msr.lo = sizebytes;
wrmsr(gl->desc_name, msr);
msr = rdmsr(gl->desc_name);
printk_debug("%s: AFTER write msr 0x%x, val 0x%x:0x%x\n", __FUNCTION__,
gl->desc_name, msr.hi, msr.lo);
}
static void
DMMGL0Init(struct gliutable *gl) {
msr_t msr;
int sizebytes = sizeram()<<20;
long offset;
if (! havedmi)
return;
printk_debug("%s: %d bytes\n", __FUNCTION__, sizebytes);
sizebytes -= DMM_SIZE*1024;
offset = sizebytes - DMM_OFFSET;
printk_debug("%s: offset is 0x%x\n", __FUNCTION__, offset);
offset >>= 12;
msr.hi = (gl->hi) | (offset << 8);
/* I don't think this is needed */
msr.hi &= 0xffffff00;
msr.hi |= (DMM_OFFSET >> 24);
msr.lo = DMM_OFFSET << 8;
msr.lo |= ((~(DMM_SIZE*1024)+1)>>12)&0xfffff;
wrmsr(gl->desc_name, msr);
msr = rdmsr(gl->desc_name);
printk_debug("%s: AFTER write msr 0x%x, val 0x%x:0x%x\n", __FUNCTION__, gl->desc_name, msr.hi, msr.lo);
}
static void
DMMGL1Init(struct gliutable *gl) {
msr_t msr;
if (! havedmi)
return;
printk_debug("%s:\n", __FUNCTION__ );
msr.hi = gl->hi;
/* I don't think this is needed */
msr.hi &= 0xffffff00;
msr.hi |= (DMM_OFFSET >> 24);
msr.lo = DMM_OFFSET << 8;
/* hmm. AMD source has SMM here ... SMM, not DMM? We think DMM */
printk_err("%s: warning, using DMM_SIZE even though AMD used SMM_SIZE\n", __FUNCTION__);
msr.lo |= ((~(DMM_SIZE*1024)+1)>>12)&0xfffff;
wrmsr(gl->desc_name, msr);
msr = rdmsr(gl->desc_name);
printk_debug("%s: AFTER write msr 0x%x, val 0x%x:0x%x\n", __FUNCTION__, gl->desc_name, msr.hi, msr.lo);
}
static void
SMMGL0Init(struct gliutable *gl) {
msr_t msr;
int sizebytes = sizeram()<<20;
long offset;
sizebytes -= SMM_SIZE*1024;
if (havedmi)
sizebytes -= DMM_SIZE * 1024;
printk_debug("%s: %d bytes\n", __FUNCTION__, sizebytes);
offset = sizebytes - SMM_OFFSET;
printk_debug("%s: offset is 0x%x\n", __FUNCTION__, offset);
offset >>= 12;
msr.hi = offset << 8;
msr.hi |= SMM_OFFSET>>24;
msr.lo = SMM_OFFSET << 8;
msr.lo |= ((~(SMM_SIZE*1024)+1)>>12)&0xfffff;
wrmsr(gl->desc_name, msr);
msr = rdmsr(gl->desc_name);
printk_debug("%s: AFTER write msr 0x%x, val 0x%x:0x%x\n", __FUNCTION__, gl->desc_name, msr.hi, msr.lo);
}
static void
SMMGL1Init(struct gliutable *gl) {
msr_t msr;
printk_debug("%s:\n", __FUNCTION__ );
msr.hi = gl->hi;
/* I don't think this is needed */
msr.hi &= 0xffffff00;
msr.hi |= (SMM_OFFSET >> 24);
msr.lo = SMM_OFFSET << 8;
msr.lo |= ((~(SMM_SIZE*1024)+1)>>12)&0xfffff;
wrmsr(gl->desc_name, msr);
msr = rdmsr(gl->desc_name);
printk_debug("%s: AFTER write msr 0x%x, val 0x%x:0x%x\n", __FUNCTION__, gl->desc_name, msr.hi, msr.lo);
}
static void
GLIUInit(struct gliutable *gl){
while (gl->desc_type != GL_END){
switch(gl->desc_type){
default:
printk_err("%s: name %x, type %x, hi %x, lo %x: unsupported type: ", __FUNCTION__,
gl->desc_name, gl->desc_type, gl->hi, gl->hi);
printk_err("Must be %x, %x, %x, %x, %x, or %x\n", SC_SHADOW,R_SYSMEM,BMO_DMM,
BM_DMM, BMO_SMM,BM_SMM);
case SC_SHADOW: /* Check for a Shadow entry*/
ShadowInit(gl);
break;
case R_SYSMEM: /* check for a SYSMEM entry*/
SysmemInit(gl);
break;
case BMO_DMM: /* check for a DMM entry*/
DMMGL0Init(gl);
break;
case BM_DMM : /* check for a DMM entry*/
DMMGL1Init(gl);
break;
case BMO_SMM : /* check for a SMM entry*/
SMMGL0Init(gl);
break;
case BM_SMM : /* check for a SMM entry*/
SMMGL1Init(gl);
break;
}
gl++;
}
}
/* ***************************************************************************/ /* ***************************************************************************/
/* **/ /* **/
/* * GLPCIInit*/ /* * GLPCIInit*/
@ -344,3 +518,56 @@ performance:
} }
} }
static void
GeodeLinkPriority(void){
msr_t msr;
struct msrinit *prio = GeodeLinkPriorityTable;
int i;
for(i = 0; prio->msrnum != 0xffffffff; i++) {
msr = rdmsr(prio->msrnum);
printk_debug("%s: MSR 0x%x is 0x%x:0x%x\n", __FUNCTION__, prio->msrnum, msr.hi, msr.lo);
msr.hi |= prio->msr.hi;
msr.lo &= ~0xfff;
msr.lo |= prio->msr.lo;
printk_debug("%s: MSR 0x%x will be set to 0x%x:0x%x\n", __FUNCTION__,
prio->msrnum, msr.hi, msr.lo);
wrmsr(prio->msrnum, msr);
}
}
/* ***************************************************************************/
/* **/
/* * northBridgeInit*/
/* **/
/* * Core Logic initialization: Host bridge*/
/* **/
/* * Entry:*/
/* * Exit:*/
/* * Modified:*/
/* **/
/* ***************************************************************************/
void
northbridgeinit(void){
int i;
printk_debug("Enter %s\n", __FUNCTION__);
// post(POST_NORTHB_INIT);
for(i = 0; gliutables[i]; i++)
GLIUInit(gliutables[i]);
GeodeLinkPriority();
/* Now that the descriptor to memory is set up.*/
/* The memory controller needs one read to synch it's lines before it can be used.*/
i = *(int *) 0;
GLPCIInit();
ClockGatingInit();
__asm__("FINIT\n");
/* CPUBugsFix -- called elsewhere */
printk_debug("Exit %s\n", __FUNCTION__);
}