diff options
Diffstat (limited to 'src/northbridge/amd/gx2/northbridgeinit.c')
-rw-r--r-- | src/northbridge/amd/gx2/northbridgeinit.c | 346 |
1 files changed, 346 insertions, 0 deletions
diff --git a/src/northbridge/amd/gx2/northbridgeinit.c b/src/northbridge/amd/gx2/northbridgeinit.c new file mode 100644 index 0000000000..b358812881 --- /dev/null +++ b/src/northbridge/amd/gx2/northbridgeinit.c @@ -0,0 +1,346 @@ +#include <console/console.h> +#include <arch/io.h> +#include <stdint.h> +#include <device/device.h> +#include <device/pci.h> +#include <device/pci_ids.h> +#include <stdlib.h> +#include <string.h> +#include <bitops.h> +#include "chip.h" +#include "northbridge.h" +#include <cpu/amd/gx2def.h> +#include <cpu/x86/msr.h> +#include <cpu/x86/cache.h> + +/* put this here for now, we are not sure where it belongs */ + +struct gliutable { + unsigned long desc_name; + unsigned short desc_type; + unsigned long hi, lo; +}; + +struct gliutable gliu0table[] = { + {.desc_name=MSR_GLIU0_BASE1,.desc_type= BM,.hi= MSR_MC + 0x0,.lo= 0x0FFF80}, /* 0-7FFFF to MC*/ + {.desc_name=MSR_GLIU0_BASE2,.desc_type= BM,.hi= MSR_MC + 0x0,.lo=(0x80 << 20) + 0x0FFFE0}, /* 80000-9ffff to Mc*/ + {.desc_name=MSR_GLIU0_SHADOW,.desc_type= SC_SHADOW,.hi= MSR_MC + 0x0,.lo= 0x03}, /* C0000-Fffff split to MC and PCI (sub decode) A0000-Bffff handled by SoftVideo*/ + {.desc_name=MSR_GLIU0_SYSMEM,.desc_type= R_SYSMEM,.hi= MSR_MC,.lo= 0x0}, /* Catch and fix dynamicly.*/ + {.desc_name=MSR_GLIU0_DMM,.desc_type= BMO_DMM,.hi= MSR_MC,.lo= 0x0}, /* Catch and fix dynamicly.*/ + {.desc_name=MSR_GLIU0_SMM,.desc_type= BMO_SMM,.hi= MSR_MC,.lo= 0x0}, /* Catch and fix dynamicly.*/ + {.desc_name=GLIU0_GLD_MSR_COH,.desc_type= OTHER,.hi= 0x0,.lo= GL0_CPU}, + {.desc_name=GL_END,.desc_type= GL_END,.hi= 0x0,.lo= 0x0}, +}; + + +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_DMM,.desc_type= BM_DMM,.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=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}, +}; + + struct msrinit { + unsigned long msrnum; + msr_t msr;}; + +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*/ + {GP_GLD_MSR_PM, {.hi=0x00,.lo=0x0001}}, + {DF_GLD_MSR_PM, {.hi=0x00,.lo=0x0155}}, + {GLCP_GLD_MSR_PM, {.hi=0x00,.lo=0x0015}}, + {GLPCI_GLD_MSR_PM, {.hi=0x00,.lo=0x0015}}, + {FG_GLD_MSR_PM, {.hi=0x00,.lo=0x0000}}, /* Always on*/ + {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}}, + {GLCP_GLD_MSR_PM, {.hi=0x00,.lo=0x0FFFFFFFF}}, + {GLPCI_GLD_MSR_PM, {.hi=0x00,.lo=0x0FFFFFFFF}}, + {FG_GLD_MSR_PM, {.hi=0x00,.lo=0x0000}}, + {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}}, + {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.*/ + {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=0x0017}}, /* 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*/ + {0x0FFFFFFFF, {0x0FFFFFFFF, 0x0FFFFFFFF}}, /* END*/ +}; + + + /* ***************************************************************************/ + /* **/ + /* * northBridgeInit*/ + /* **/ + /* * Core Logic initialization: Host bridge*/ + /* **/ + /* * Entry:*/ + /* * Exit:*/ + /* * Modified:*/ + /* **/ + /* ***************************************************************************/ + +static void ClockGatingInit (void); +static void GLPCIInit(void); +void +northbridgeinit(void){ + printk_debug("Enter %s\n", __FUNCTION__); +// post(POST_NORTHB_INIT); + GLPCIInit(); + ClockGatingInit(); + __asm__("FINIT\n"); + /* CPUBugsFix -- called elsewhere */ + printk_debug("Exit %s\n", __FUNCTION__); +} + + + + /* ***************************************************************************/ + /* **/ + /* * GLPCIInit*/ + /* **/ + /* * Set up GLPCI settings for reads/write into memory*/ + /* * R0: 0-640KB,*/ + /* * R1: 1MB - Top of System Memory*/ + /* * R2: SMM Memory*/ + /* * R3: Framebuffer? - not set up yet*/ + /* * R4: ??*/ + /* **/ + /* * Entry:*/ + /* * Exit:*/ + /* * Modified:*/ + /* **/ + /* ***************************************************************************/ +static void GLPCIInit(void){ + struct gliutable *gl = 0; + int i; + msr_t msr; + int msrnum; + unsigned long val; + /* */ + /* R0 - GLPCI settings for Conventional Memory space.*/ + /* */ + 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); + + /* */ + /* R1 - GLPCI settings for SysMem space.*/ + /* */ + + /* Get systop from GLIU0 SYSTOP Descriptor*/ + + for(i = 0; gliu0table[i].desc_name != GL_END; i++) { + if (gliu0table[i].desc_type == R_SYSMEM) { + gl = &gliu0table[i]; + break; + } + } + + if (gl) { + msrnum = gl->desc_name; + msr = rdmsr(msrnum); + + /* 20 bit address The bottom 12 bits go into bits 20-31 in eax. The top 8 bits go into 0-7 of edx.*/ + val = msr.hi & 0xff; /* EAX[31:20] = low 12 bits and EAX[7:0] upper 8 bits*/ + val <<= 12; /* EAX[31:20] = junk EAX[19:0] = 20 bit address*/ + val &= 0xfffff; + val <<= GLPCI_RC_UPPER_TOP_SHIFT; + msr.hi = val /* Top Set*/; + msr.lo = (0x100000 >> 12) << GLPCI_RC_LOWER_BASE_SHIFT /* 1MB >> =20bit address then shift into register*/; + msr.lo |= GLPCI_RC_LOWER_EN_SET + GLPCI_RC_LOWER_PF_SET + GLPCI_RC_LOWER_WC_SET; + msrnum = GLPCI_RC1; + wrmsr(msrnum, msr); + } + + /* */ + /* 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; + 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*/; + + msrnum = CPU_RCONF_A0_BF; + wrmsr(msrnum, msr); + + + msrnum = CPU_RCONF_C0_DF; + wrmsr(msrnum, msr); + + + msrnum = CPU_RCONF_E0_FF; + wrmsr(msrnum, msr); + + + + /* Set Non-Cacheable Read Only for NorthBound Transactions to Memory. The Enable bit is handled in the Shadow setup.*/ + msrnum = GLPCI_A0_BF; + msr.hi = 0x35353535; + msr.lo = 0x35353535; + wrmsr(msrnum, msr); + + msrnum = GLPCI_C0_DF; + msr.hi = 0x35353535; + msr.lo = 0x35353535; + wrmsr(msrnum, msr); + + msrnum = GLPCI_E0_FF; + msr.hi = 0x35353535; + msr.lo = 0x35353535; + wrmsr(msrnum, msr); + + /* Set WSREQ*/ + + 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.*/ + wrmsr(msrnum, msr); + + /* we are ignoring the 5530 case for now, and perhaps forever. */ + + /* */ + /* 5535 NB Init*/ + /* */ + msrnum = GLPCI_ARB; + msr = rdmsr(msrnum); + msr.hi |= GLPCI_ARB_UPPER_PRE0_SET | GLPCI_ARB_UPPER_PRE1_SET; + msr.lo |= GLPCI_ARB_LOWER_IIE_SET; + wrmsr(msrnum, msr); + + + msrnum = GLPCI_CTRL; + msr = rdmsr(msrnum); + + 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 .)*/ + msr.lo |= GLPCI_CTRL_LOWER_LDE_SET; + + msr.lo &= ~ (0x03 << GLPCI_CTRL_LOWER_IRFC_SHIFT); + msr.lo |= 0x02 << GLPCI_CTRL_LOWER_IRFC_SHIFT; + + msr.lo &= ~ (0x07 << GLPCI_CTRL_LOWER_IRFT_SHIFT); + msr.lo |= 0x06 << GLPCI_CTRL_LOWER_IRFT_SHIFT; + + msr.hi &= ~ (0x0f << GLPCI_CTRL_UPPER_FTH_SHIFT); + msr.hi |= 0x0F << GLPCI_CTRL_UPPER_FTH_SHIFT; + + msr.hi &= ~ (0x0f << GLPCI_CTRL_UPPER_RTH_SHIFT); + msr.hi |= 0x0F << GLPCI_CTRL_UPPER_RTH_SHIFT; + + msr.hi &= ~ (0x0f << GLPCI_CTRL_UPPER_SBRTH_SHIFT); + msr.hi |= 0x0F << GLPCI_CTRL_UPPER_SBRTH_SHIFT; + + msr.hi &= ~ (0x03 << GLPCI_CTRL_UPPER_WTO_SHIFT); + msr.hi |= 0x06 << GLPCI_CTRL_UPPER_WTO_SHIFT; + + msr.hi &= ~ (0x03 << GLPCI_CTRL_UPPER_ILTO_SHIFT); + msr.hi |= 0x00 << GLPCI_CTRL_UPPER_ILTO_SHIFT; + wrmsr(msrnum, msr); + + + /* Set GLPCI Latency Timer.*/ + msrnum = GLPCI_CTRL; + msr = rdmsr(msrnum); + msr.hi |= 0x1F << GLPCI_CTRL_UPPER_LAT_SHIFT; /* Change once 1.x is gone.*/ + wrmsr(msrnum, msr); + + /* GLPCI_SPARE*/ + msrnum = GLPCI_SPARE; + msr = rdmsr(msrnum); + 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); + +} + + + + /* ***************************************************************************/ + /* **/ + /* * ClockGatingInit*/ + /* **/ + /* * Enable Clock Gating.*/ + /* **/ + /* * Entry:*/ + /* * Exit:*/ + /* * Modified:*/ + /* **/ + /* ***************************************************************************/ +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%x is 0x%x:0x%x\n", __FUNCTION__, gating->msrnum, msr.hi, msr.lo); + msr.hi |= gating->msr.hi; + msr.lo |= gating->msr.lo; + printk_debug("%s: MSR 0x%x will be set to 0x%x:0x%x\n", __FUNCTION__, + gating->msrnum, msr.hi, msr.lo); + wrmsr(gating->msrnum, msr); + } + +} |