From 734daf699ceb8603f53003ab36eb85b8a76e3cf9 Mon Sep 17 00:00:00 2001 From: Marc Jones Date: Fri, 4 May 2007 18:58:42 +0000 Subject: This patch adds support for the northbridge integrated into the AMD Geode LX platform, including memory and graphics. (rediffed for whitespace) Signed-off-by: Marc Jones Acked-by: Stefan Reinauer git-svn-id: svn://svn.coreboot.org/coreboot/trunk@2630 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1 --- src/northbridge/amd/lx/northbridgeinit.c | 324 +++++++++++++++---------------- 1 file changed, 153 insertions(+), 171 deletions(-) (limited to 'src/northbridge/amd/lx/northbridgeinit.c') diff --git a/src/northbridge/amd/lx/northbridgeinit.c b/src/northbridge/amd/lx/northbridgeinit.c index 21d2736bcb..52fab514af 100644 --- a/src/northbridge/amd/lx/northbridgeinit.c +++ b/src/northbridge/amd/lx/northbridgeinit.c @@ -1,3 +1,9 @@ +/* +* +* Copyright (C) 2007 Advanced Micro Devices +* +*/ + #include #include #include @@ -13,7 +19,6 @@ #include #include -/* put this here for now, we are not sure where it belongs */ struct gliutable { unsigned long desc_name; @@ -36,9 +41,10 @@ struct gliutable gliu1table[] = { {.desc_name=MSR_GLIU1_BASE1,.desc_type= BM,.hi= MSR_GL0 + 0x0,.lo= 0x0FFF80}, /* 0-7FFFF to MC*/ {.desc_name=MSR_GLIU1_BASE2,.desc_type= BM,.hi= MSR_GL0 + 0x0,.lo= (0x80 << 20) +0x0FFFE0}, /* 80000-9ffff to Mc*/ {.desc_name=MSR_GLIU1_SHADOW,.desc_type= SC_SHADOW,.hi= MSR_GL0 + 0x0,.lo= 0x03}, /* C0000-Fffff split to MC and PCI (sub decode)*/ - {.desc_name=MSR_GLIU1_SYSMEM,.desc_type= R_SYSMEM,.hi= MSR_GL0,.lo= 0x0}, /* Cat0xc and fix dynamicly.*/ - {.desc_name=MSR_GLIU1_SMM,.desc_type= BM_SMM,.hi= MSR_GL0,.lo= 0x0}, /* Cat0xc and fix dynamicly.*/ + {.desc_name=MSR_GLIU1_SYSMEM,.desc_type= R_SYSMEM,.hi= MSR_GL0,.lo= 0x0}, /* Catch and fix dynamicly.*/ + {.desc_name=MSR_GLIU1_SMM,.desc_type= BM_SMM,.hi= MSR_GL0,.lo= 0x0}, /* Catch and fix dynamicly.*/ {.desc_name=GLIU1_GLD_MSR_COH,.desc_type= OTHER,.hi= 0x0,.lo= GL1_GLIU0}, + {.desc_name=MSR_GLIU1_FPU_TRAP,.desc_type= SCIO,.hi= (GL1_GLCP << 29) + 0x0,.lo= 0x033000F0}, /* FooGlue FPU 0xF0*/ {.desc_name=GL_END,.desc_type= GL_END,.hi= 0x0,.lo= 0x0}, }; @@ -51,54 +57,36 @@ struct msrinit { struct msrinit ClockGatingDefault [] = { {GLIU0_GLD_MSR_PM, {.hi=0x00,.lo=0x0005}}, - /* MC must stay off in SDR mode. It is turned on in CPUBug??? lotus #77.142*/ - {MC_GLD_MSR_PM, {.hi=0x00,.lo=0x0000}}, - {GLIU1_GLD_MSR_PM, {.hi=0x00,.lo=0x0005}}, - {VG_GLD_MSR_PM, {.hi=0x00,.lo=0x0000}}, /* lotus #77.163*/ + {MC_GLD_MSR_PM, {.hi=0x00,.lo=0x0001}}, + {VG_GLD_MSR_PM, {.hi=0x00,.lo=0x0015}}, {GP_GLD_MSR_PM, {.hi=0x00,.lo=0x0001}}, - /*{DF_GLD_MSR_PM, {.hi=0x00,.lo=0x0155}},*/ //GX3 - {GLCP_GLD_MSR_PM, {.hi=0x00,.lo=0x0015}}, + {DF_GLD_MSR_PM, {.hi=0x00,.lo=0x0555}}, + {GLIU1_GLD_MSR_PM, {.hi=0x00,.lo=0x0005}}, + {GLCP_GLD_MSR_PM, {.hi=0x00,.lo=0x0014}}, {GLPCI_GLD_MSR_PM, {.hi=0x00,.lo=0x0015}}, - /*{FG_GLD_MSR_PM, {.hi=0x00,.lo=0x0000}}, */ /* Always on*/ //GX3 + {VIP_GLD_MSR_PM, {.hi=0x00,.lo=0x0005}}, + {AES_GLD_MSR_PM, {.hi=0x00,.lo=0x0015}}, + {CPU_BC_PMODE_MSR, {.hi=0x00,.lo=0x70303}}, {0xffffffff, {0xffffffff, 0xffffffff}}, }; - /* All On*/ -struct msrinit ClockGatingAllOn[] = { - {GLIU0_GLD_MSR_PM, {.hi=0x00,.lo=0x0FFFFFFFF}}, - {MC_GLD_MSR_PM, {.hi=0x00,.lo=0x0FFFFFFFF}}, - {GLIU1_GLD_MSR_PM, {.hi=0x00,.lo=0x0FFFFFFFF}}, - {VG_GLD_MSR_PM, {.hi=0x00, .lo=0x00}}, - {GP_GLD_MSR_PM, {.hi=0x00,.lo=0x000000001}}, - /*{DF_GLD_MSR_PM, {.hi=0x00,.lo=0x0FFFFFFFF}}, */ //GX3 - {GLCP_GLD_MSR_PM, {.hi=0x00,.lo=0x0FFFFFFFF}}, - {GLPCI_GLD_MSR_PM, {.hi=0x00,.lo=0x0FFFFFFFF}}, - /*{FG_GLD_MSR_PM, {.hi=0x00,.lo=0x0000}}, */ //GX3 - {0xffffffff, {0xffffffff, 0xffffffff}}, -}; - /* Performance*/ -struct msrinit ClockGatingPerformance[] = { - {VG_GLD_MSR_PM, {.hi=0x00,.lo=0x0000}}, /* lotus #77.163*/ - {GP_GLD_MSR_PM, {.hi=0x00,.lo=0x0001}}, - /*{DF_GLD_MSR_PM, {.hi=0x00,.lo=0x0155}}, */ //GX3 - {GLCP_GLD_MSR_PM, {.hi=0x00,.lo=0x0015}}, - {0xffffffff, {0xffffffff, 0xffffffff}}, -}; /* */ /* SET GeodeLink PRIORITY*/ /* */ struct msrinit GeodeLinkPriorityTable [] = { - {CPU_GLD_MSR_CONFIG, {.hi=0x00,.lo=0x0220}}, /* CPU Priority.*/ - /*{DF_GLD_MSR_MASTER_CONF, {.hi=0x00,.lo=0x0000}},*/ /* DF Priority.*/ //GX3 - {VG_GLD_MSR_CONFIG, {.hi=0x00,.lo=0x0720}}, /* VG Primary and Secondary Priority.*/ - {GP_GLD_MSR_CONFIG, {.hi=0x00,.lo=0x0010}}, /* Graphics Priority.*/ - {GLPCI_GLD_MSR_CONFIG, {.hi=0x00,.lo=0x0027}}, /* GLPCI Priority + PID*/ - {GLCP_GLD_MSR_CONF, {.hi=0x00,.lo=0x0001}}, /* GLCP Priority + PID*/ - {VIP_GLD_MSR_CONFIG, {.hi=0x00,.lo=0x0622}}, /* VIP PID*/ - {AES_GLD_MSR_CONFIG, {.hi=0x00,.lo=0x0013}}, /* AES PID*/ + {CPU_GLD_MSR_CONFIG, {.hi=0x00,.lo=0x0220}}, + {DF_GLD_MSR_MASTER_CONF, {.hi=0x00,.lo=0x0000}}, + {VG_GLD_MSR_CONFIG, {.hi=0x00,.lo=0x0720}}, + {GP_GLD_MSR_CONFIG, {.hi=0x00,.lo=0x0010}}, + {GLPCI_GLD_MSR_CONFIG, {.hi=0x00,.lo=0x0017}}, + {GLCP_GLD_MSR_CONF, {.hi=0x00,.lo=0x0001}}, + {VIP_GLD_MSR_CONFIG, {.hi=0x00,.lo=0x0622}}, + {AES_GLD_MSR_CONFIG, {.hi=0x00,.lo=0x0013}}, {0x0FFFFFFFF, {0x0FFFFFFFF, 0x0FFFFFFFF}}, /* END*/ }; +extern int sizeram(void); + static void writeglmsr(struct gliutable *gl){ msr_t msr; @@ -106,10 +94,7 @@ writeglmsr(struct gliutable *gl){ msr.lo = gl->lo; msr.hi = gl->hi; wrmsr(gl->desc_name, msr); // MSR - see table above - // printk_debug("%s: write msr 0x%08x, val 0x%08x:0x%08x\n", __FUNCTION__, gl->desc_name, msr.hi, msr.lo); //GX3 - /* they do this, so we do this */ - msr = rdmsr(gl->desc_name); - // printk_debug("%s: AFTER write msr 0x%08x, val 0x%08x:0x%08x\n", __FUNCTION__, gl->desc_name, msr.hi, msr.lo); // GX3 + printk_debug("%s: MSR 0x%08x, val 0x%08x:0x%08x\n", __FUNCTION__, gl->desc_name, msr.hi, msr.lo); // GX3 } static void @@ -124,14 +109,8 @@ ShadowInit(struct gliutable *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) +static void SysmemInit(struct gliutable *gl) { msr_t msr; int sizembytes, sizebytes; @@ -141,51 +120,51 @@ SysmemInit(struct gliutable *gl) * system. We will adjust for SMM now and Frame Buffer later. */ sizembytes = sizeram(); - printk_debug("%s: enable for %dm bytes\n", __FUNCTION__, sizembytes); + printk_debug("%s: enable for %dMBytes\n", __FUNCTION__, sizembytes); sizebytes = sizembytes << 20; - sizebytes -= ((SMM_SIZE)<<10); + sizebytes -= ((SMM_SIZE * 1024) + 1); printk_debug("usable RAM: %d bytes\n", sizebytes); + /* 20 bit address The bottom 12 bits go into bits 20-31 in msr.lo + The top 8 bits go into 0-7 of msr.hi. */ + sizebytes--; msr.hi = (gl->hi & 0xFFFFFF00) | (sizebytes >> 24); - /* set up sizebytes to fit into msr.lo */ - sizebytes <<= 8; /* what? well, we want bits 23:12 in bits 31:20. */ + sizebytes <<= 8; /* move bits 23:12 in bits 31:20. */ sizebytes &= 0xfff00000; - sizebytes |= 0x100; + sizebytes |= 0x100; /* start at 1MB */ msr.lo = sizebytes; wrmsr(gl->desc_name, msr); // MSR - see table above - msr = rdmsr(gl->desc_name); - /* printk_debug("%s: AFTER write msr 0x%08x, val 0x%08x:0x%08x\n", __FUNCTION__, - gl->desc_name, msr.hi, msr.lo); */ // GX3 + printk_debug("%s: MSR 0x%08x, val 0x%08x:0x%08x\n", __FUNCTION__, + gl->desc_name, msr.hi, msr.lo); } -static void -SMMGL0Init(struct gliutable *gl) { +static void SMMGL0Init(struct gliutable *gl) { msr_t msr; int sizebytes = sizeram()<<20; long offset; - sizebytes -= ((SMM_SIZE)<<10); + sizebytes -= (SMM_SIZE*1024); printk_debug("%s: %d bytes\n", __FUNCTION__, sizebytes); + /* calculate the Two's complement offset */ offset = sizebytes - SMM_OFFSET; offset = (offset >> 12) & 0x000fffff; - printk_debug("%s: offset is 0x%08x\n", __FUNCTION__, offset); + printk_debug("%s: offset is 0x%08x\n", __FUNCTION__, SMM_OFFSET); - msr.hi = offset << 8 | MSR_MC; + msr.hi = offset << 8 | gl->hi; msr.hi |= SMM_OFFSET>>24; msr.lo = SMM_OFFSET << 8; msr.lo |= ((~(SMM_SIZE*1024)+1)>>12)&0xfffff; wrmsr(gl->desc_name, msr); // MSR - See table above - msr = rdmsr(gl->desc_name); - printk_debug("%s: AFTER write msr 0x%08x, val 0x%08x:0x%08x\n", __FUNCTION__, gl->desc_name, msr.hi, msr.lo); + printk_debug("%s: MSR 0x%08x, val 0x%08x:0x%08x\n", __FUNCTION__, gl->desc_name, msr.hi, msr.lo); } -static void -SMMGL1Init(struct gliutable *gl) { + +static void SMMGL1Init(struct gliutable *gl) { msr_t msr; printk_debug("%s:\n", __FUNCTION__ ); @@ -193,16 +172,14 @@ SMMGL1Init(struct gliutable *gl) { /* I don't think this is needed */ msr.hi &= 0xffffff00; msr.hi |= (SMM_OFFSET >> 24); - msr.lo = SMM_OFFSET << 8; + msr.lo = (SMM_OFFSET << 8) & 0xFFF00000; msr.lo |= ((~(SMM_SIZE*1024)+1)>>12)&0xfffff; wrmsr(gl->desc_name, msr); // MSR - See table above - msr = rdmsr(gl->desc_name); - printk_debug("%s: AFTER write msr 0x%08x, val 0x%08x:0x%08x\n", __FUNCTION__, gl->desc_name, msr.hi, msr.lo); + printk_debug("%s: MSR 0x%08x, val 0x%08x:0x%08x\n", __FUNCTION__, gl->desc_name, msr.hi, msr.lo); } -static void -GLIUInit(struct gliutable *gl){ +static void GLIUInit(struct gliutable *gl){ while (gl->desc_type != GL_END){ switch(gl->desc_type){ @@ -229,6 +206,7 @@ GLIUInit(struct gliutable *gl){ } } + /* ***************************************************************************/ /* **/ /* * GLPCIInit*/ @@ -255,8 +233,8 @@ static void GLPCIInit(void){ /* */ /* R0 - GLPCI settings for Conventional Memory space.*/ /* */ - msr.hi = (0x09F000 >> 12) << GLPCI_RC_UPPER_TOP_SHIFT /* 640*/; - msr.lo = 0 /* 0*/; + msr.hi = (0x09F000 >> 12) << GLPCI_RC_UPPER_TOP_SHIFT; /* 640 */ + msr.lo = 0; /* 0*/ msr.lo |= GLPCI_RC_LOWER_EN_SET+ GLPCI_RC_LOWER_PF_SET + GLPCI_RC_LOWER_WC_SET; msrnum = GLPCI_RC0; wrmsr(msrnum, msr); @@ -283,8 +261,7 @@ static void GLPCIInit(void){ /* So we need a high page aligned addresss (pah) and low page aligned address (pal) * pah is from msr.hi << 12 | msr.low >> 20. pal is msr.lo << 12 */ - printk_debug("GLPCI r1: system msr.lo 0x%08x msr.hi 0x%08x\n", msr.lo, msr.hi); - pah = ((msr.hi &0xff) << 12) | ((msr.lo >> 20) & 0xfff); + pah = ((msr.hi & 0xFF) << 12) | ((msr.lo >> 20) & 0xFFF); /* we have the page address. Now make it a page-aligned address */ pah <<= 12; @@ -292,24 +269,25 @@ static void GLPCIInit(void){ msr.hi = pah; msr.lo = pal; msr.lo |= GLPCI_RC_LOWER_EN_SET | GLPCI_RC_LOWER_PF_SET | GLPCI_RC_LOWER_WC_SET; - printk_debug("GLPCI r1: system msr.lo 0x%08x msr.hi 0x%08x\n", msr.lo, msr.hi); + printk_debug("GLPCI R1: system msr.lo 0x%08x msr.hi 0x%08x\n", msr.lo, msr.hi); msrnum = GLPCI_RC1; wrmsr(msrnum, msr); } /* */ - /* R2 - GLPCI settings for SMM space.*/ + /* R2 - GLPCI settings for SMM space */ /* */ msr.hi = ((SMM_OFFSET+(SMM_SIZE*1024-1)) >> 12) << GLPCI_RC_UPPER_TOP_SHIFT; msr.lo = (SMM_OFFSET >> 12) << GLPCI_RC_LOWER_BASE_SHIFT; msr.lo |= GLPCI_RC_LOWER_EN_SET | GLPCI_RC_LOWER_PF_SET; + printk_debug("GLPCI R2: system msr.lo 0x%08x msr.hi 0x%08x\n", msr.lo, msr.hi); msrnum = GLPCI_RC2; wrmsr(msrnum, msr); /* this is done elsewhere already, but it does no harm to do it more than once */ /* write serialize memory hole to PCI. Need to to unWS when something is shadowed regardless of cachablility.*/ - msr.lo = 0x021212121 /* cache disabled and write serialized*/; - msr.hi = 0x021212121 /* cache disabled and write serialized*/; + msr.lo = 0x021212121; /* cache disabled and write serialized */ + msr.hi = 0x021212121; /* cache disabled and write serialized */ msrnum = CPU_RCONF_A0_BF; wrmsr(msrnum, msr); @@ -340,17 +318,16 @@ static void GLPCIInit(void){ msrnum = CPU_DM_CONFIG0; msr = rdmsr(msrnum); msr.hi &= ~ (7 << DM_CONFIG0_UPPER_WSREQ_SHIFT); - msr.hi |= 2 << DM_CONFIG0_UPPER_WSREQ_SHIFT ; /* reduce to 1 for safe mode.*/ + msr.hi |= 2 << DM_CONFIG0_UPPER_WSREQ_SHIFT; /* reduce to 1 for safe mode */ wrmsr(msrnum, msr); /* we are ignoring the 5530 case for now, and perhaps forever. */ /* */ - /* 5535 NB Init*/ + /* 553x NB Init*/ /* */ /* Arbiter setup */ - enable_preempt = GLPCI_ARB_LOWER_PRE0_SET | GLPCI_ARB_LOWER_PRE1_SET | GLPCI_ARB_LOWER_PRE2_SET | GLPCI_ARB_LOWER_CPRE_SET; enable_cpu_override = GLPCI_ARB_LOWER_COV_SET; enable_bus_parking = GLPCI_ARB_LOWER_PARK_SET; @@ -392,10 +369,10 @@ static void GLPCIInit(void){ wrmsr(msrnum, msr); - /* Set GLPCI Latency Timer.*/ + /* Set GLPCI Latency Timer */ msrnum = GLPCI_CTRL; msr = rdmsr(msrnum); - msr.hi |= 0x1F << GLPCI_CTRL_UPPER_LAT_SHIFT; /* Change once 1.x is gone.*/ + msr.hi |= 0x1F << GLPCI_CTRL_UPPER_LAT_SHIFT; /* Change once 1.x is gone */ wrmsr(msrnum, msr); /* GLPCI_SPARE*/ @@ -404,7 +381,6 @@ static void GLPCIInit(void){ msr.lo &= ~ 0x7; 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; wrmsr(msrnum, msr); - } @@ -420,35 +396,13 @@ static void GLPCIInit(void){ /* * Modified:*/ /* **/ /* ***************************************************************************/ -static void -ClockGatingInit (void){ +static void ClockGatingInit (void){ msr_t msr; struct msrinit *gating = ClockGatingDefault; int i; -#if 0 - mov cx, TOKEN_CLK_GATE - NOSTACK bx, GetNVRAMValueBX - cmp al, TVALUE_CG_OFF - je gatingdone - - cmp al, TVALUE_CG_DEFAULT - jb allon - ja performance - lea si, ClockGatingDefault - jmp nextdevice - -allon: - lea si, ClockGatingAllOn - jmp nextdevice - -performance: - lea si, ClockGatingPerformance -#endif - for(i = 0; gating->msrnum != 0xffffffff; i++) { msr = rdmsr(gating->msrnum); - //printk_debug("%s: MSR 0x%08x is 0x%08x:0x%08x\n", __FUNCTION__, gating->msrnum, msr.hi, msr.lo); //GX3 msr.hi |= gating->msr.hi; msr.lo |= gating->msr.lo; /* printk_debug("%s: MSR 0x%08x will be set to 0x%08x:0x%08x\n", __FUNCTION__, @@ -459,15 +413,13 @@ performance: } -static void -GeodeLinkPriority(void){ +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%08x is 0x%08x:0x%08x\n", __FUNCTION__, prio->msrnum, msr.hi, msr.lo); // GX3 msr.hi |= prio->msr.hi; msr.lo &= ~0xfff; msr.lo |= prio->msr.lo; @@ -485,9 +437,9 @@ GeodeLinkPriority(void){ * If the setShadow function is used then all shadow descriptors * will stay sync'ed. */ -static uint64_t getShadow(void) -{ +static uint64_t getShadow(void){ msr_t msr; + msr = rdmsr(MSR_GLIU0_SHADOW); return ( ( (uint64_t) msr.hi ) << 32 ) | msr.lo; } @@ -499,8 +451,8 @@ static uint64_t getShadow(void) * This is part of the PCI lockup solution * Entry: EDX:EAX is the shadow settings */ -static void setShadowRCONF(uint32_t shadowHi, uint32_t shadowLo) -{ +static void setShadowRCONF(uint32_t shadowHi, uint32_t shadowLo){ + // ok this is whacky bit translation time. int bit; uint8_t shadowByte; @@ -557,7 +509,6 @@ static void setShadowGLPCI(uint32_t shadowHi, uint32_t shadowLo) msr_t msr; // Set the Enable Register. - msr = rdmsr(GLPCI_REN); msr.lo &= 0xFFFF00FF; msr.lo |= ( (shadowLo & 0xFFFF0000) >> 8); @@ -592,26 +543,13 @@ static void setShadow(uint64_t shadowSettings) msr.hi &= 0xFFFF0000; // maintain PDID in upper EDX msr.hi |= ((uint32_t) (shadowSettings >> 32)) & 0x0000FFFF; wrmsr(pTable->desc_name, msr); // MSR - See the table above - } } } } -/************************************************************************** - * - * shadowRom - * - * Set up a stack for ease of further testing - * - * Entry: - * Exit: - * Destroys: - * - **************************************************************************/ -static void -shadowRom(void) -{ +static void rom_shadow_settings(void){ + uint64_t shadowSettings = getShadow(); shadowSettings &= (uint64_t) 0xFFFF00000000FFFFULL; // Disable read & writes shadowSettings |= (uint64_t) 0x00000000F0000000ULL; // Enable reads for F0000-FFFFF @@ -623,7 +561,7 @@ shadowRom(void) /*************************************************************************** * - * RCONFInit + * L1Init * Set up RCONF_DEFAULT and any other RCONF registers needed * * DEVRC_RCONF_DEFAULT: @@ -639,14 +577,12 @@ shadowRom(void) #define ROMBASE_RCONF_DEFAULT 0xFFFC0000 #define ROMRC_RCONF_DEFAULT 0x25 -static void -RCONFInit(void) +static void enable_L1_cache(void) { struct gliutable *gl = 0; int i; msr_t msr; uint8_t SysMemCacheProp; - //uint8_t RegionProp; /* Locate SYSMEM entry in GLIU0table */ for(i = 0; gliu0table[i].desc_name != GL_END; i++) { @@ -661,11 +597,8 @@ RCONFInit(void) } // sysdescfound: - /* found the descriptor... get its contents */ msr = rdmsr(gl->desc_name); - printk_debug("SYSDESC: 0x%08X:0x%08X\n",msr.hi,msr.lo); - /* 20 bit address - The bottom 12 bits go into bits 20-31 in eax, the * top 8 bits go into 0-7 of edx. */ @@ -673,13 +606,11 @@ RCONFInit(void) msr.lo = ((msr.lo << 12) | (msr.lo >> 20)) & 0x000FFFFF; msr.lo <<= RCONF_DEFAULT_LOWER_SYSTOP_SHIFT; // 8 - printk_debug("RCONF LO: 0x%08X\n",msr.lo); - // Set Default SYSMEM region properties - msr.lo &= ~SYSMEM_RCONF_WRITETHROUGH; // 8 (or ~8) + msr.lo &= ~SYSMEM_RCONF_WRITETHROUGH; // NOT writethrough == writeback 8 (or ~8) // Set PCI space cache properties - msr.hi = (DEVRC_RCONF_DEFAULT >> 4); // only need the bottom bits and lets clean the rest of edx + msr.hi = (DEVRC_RCONF_DEFAULT >> 4); // setting is split betwwen hi and lo... msr.lo |= (DEVRC_RCONF_DEFAULT << 28); // Set the ROMBASE. This is usually FFFC0000h @@ -690,6 +621,7 @@ RCONFInit(void) // now program RCONF_DEFAULT wrmsr(CPU_RCONF_DEFAULT, msr); + printk_debug("CPU_RCONF_DEFAULT (1808): 0x%08X:0x%08X\n",msr.hi,msr.lo); // RCONF_BYPASS: Cache tablewalk properties and SMM/DMM header access properties. // Set to match system memory cache properties. @@ -699,21 +631,84 @@ RCONFInit(void) msr.lo = (msr.lo & 0xFFFF0000) | (SysMemCacheProp << 8) | SysMemCacheProp; wrmsr(CPU_RCONF_BYPASS, msr); - printk_debug("CPU_RCONF_SMM (180E) 0x%08x : 0x%08x\n", msr.hi, msr.lo); + printk_debug("CPU_RCONF_BYPASS (180A): 0x%08x : 0x%08x\n", msr.hi, msr.lo); } +static void enable_L2_cache(void) { + msr_t msr; + + /* Instruction Memory Configuration register + * set EBE bit, required when L2 cache is enabled + */ + msr = rdmsr(CPU_IM_CONFIG); + msr.lo |= 0x400; + wrmsr(CPU_IM_CONFIG, msr); + + /* Data Memory Subsystem Configuration register + * set EVCTONRPL bit, required when L2 cache is enabled in victim mode + */ + msr = rdmsr(CPU_DM_CONFIG0); + msr.lo |= 0x4000; + wrmsr(CPU_DM_CONFIG0, msr); + + /* invalidate L2 cache */ + msr.hi = 0x00; + msr.lo = 0x10; + wrmsr(CPU_BC_L2_CONF, msr); + + /* Enable L2 cache */ + msr.hi = 0x00; + msr.lo = 0x0f; + wrmsr(CPU_BC_L2_CONF, msr); + + printk_debug("L2 cache enabled\n"); +} + +static void setup_lx_cache(void) +{ + msr_t msr; + + enable_L1_cache(); + enable_L2_cache(); + + // Make sure all INVD instructions are treated as WBINVD. We do this + // because we've found some programs which require this behavior. + msr = rdmsr(CPU_DM_CONFIG0); + msr.lo |= DM_CONFIG0_LOWER_WBINVD_SET; + wrmsr(CPU_DM_CONFIG0, msr); + + x86_enable_cache(); + wbinvd(); +} + +uint32_t get_systop(void) { + struct gliutable *gl = 0; + uint32_t systop; + msr_t msr; + int i; + + for(i = 0; gliu0table[i].desc_name != GL_END; i++) { + if (gliu0table[i].desc_type == R_SYSMEM) { + gl = &gliu0table[i]; + break; + } + } + if (gl) { + msr = rdmsr(gl->desc_name); + systop = ((msr.hi & 0xFF) << 24) | ((msr.lo & 0xFFF00000) >> 8); + systop += 0x1000; /* 4K */ + }else{ + systop = ((sizeram() - CONFIG_VIDEO_MB) * 1024) - SMM_SIZE - 1024; + } + return systop; +} /****************************************************************************/ /* * northbridge_init_early */ /* **/ /* * Core Logic initialization: Host bridge*/ /* **/ -/* * Entry:*/ -/* * Exit:*/ -/* * Modified:*/ -/* **/ /* ***************************************************************************/ - void northbridge_init_early(void) { msr_t msr; @@ -723,34 +718,21 @@ void northbridge_init_early(void) for(i = 0; gliutables[i]; i++) GLIUInit(gliutables[i]); - GeodeLinkPriority(); - - shadowRom(); - - // GeodeROM ensures that the BIOS waits the required 1 second before - // allowing anything to access PCI - // PCIDelay(); - - RCONFInit(); - - // The cacheInit function in GeodeROM tests cache and, among other things, - // makes sure all INVD instructions are treated as WBINVD. We do this - // because we've found some programs which require this behavior. - // That subset of cacheInit() is implemented here: - - /* GX3 OK */ - msr = rdmsr(CPU_DM_CONFIG0); - msr.lo |= DM_CONFIG0_LOWER_WBINVD_SET; - wrmsr(CPU_DM_CONFIG0, msr); - /* Now that the descriptor to memory is set up.*/ /* The memory controller needs one read to synch its lines before it can be used.*/ i = *(int *) 0; + GeodeLinkPriority(); + + setup_lx_cache(); + + rom_shadow_settings(); + GLPCIInit(); + ClockGatingInit(); - __asm__("FINIT\n"); - /* CPUBugsFix -- called elsewhere */ + + __asm__ __volatile__("FINIT\n"); printk_debug("Exit %s\n", __FUNCTION__); } -- cgit v1.2.3