diff options
author | Ronald G. Minnich <rminnich@gmail.com> | 2006-06-10 22:57:15 +0000 |
---|---|---|
committer | Ronald G. Minnich <rminnich@gmail.com> | 2006-06-10 22:57:15 +0000 |
commit | fb937496428272c5bc9001d98fb99a70961f7df4 (patch) | |
tree | b3185771903cc9c00fd38d87ab9f87698c2f42d3 /src/northbridge | |
parent | 890ee09a3224f1cfc832f7c8f03e6c2f076aeb20 (diff) |
changes from AMD for making OLPC video work.
git-svn-id: svn://svn.coreboot.org/coreboot/trunk@2316 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
Diffstat (limited to 'src/northbridge')
-rw-r--r-- | src/northbridge/amd/gx2/Config.lb | 1 | ||||
-rw-r--r-- | src/northbridge/amd/gx2/chipsetinit.c | 28 | ||||
-rw-r--r-- | src/northbridge/amd/gx2/northbridge.c | 77 | ||||
-rw-r--r-- | src/northbridge/amd/gx2/northbridgeinit.c | 362 |
4 files changed, 362 insertions, 106 deletions
diff --git a/src/northbridge/amd/gx2/Config.lb b/src/northbridge/amd/gx2/Config.lb index 567b5a939b..ee8cd206f9 100644 --- a/src/northbridge/amd/gx2/Config.lb +++ b/src/northbridge/amd/gx2/Config.lb @@ -2,3 +2,4 @@ config chip.h object northbridge.o object northbridgeinit.o object chipsetinit.o +object grphinit.o diff --git a/src/northbridge/amd/gx2/chipsetinit.c b/src/northbridge/amd/gx2/chipsetinit.c index 2a1688a014..a149d626ef 100644 --- a/src/northbridge/amd/gx2/chipsetinit.c +++ b/src/northbridge/amd/gx2/chipsetinit.c @@ -53,7 +53,7 @@ struct msrinit CS5536_CLOCK_GATING_TABLE[] = { { GLIU_SB_GLD_MSR_PM, {.hi=0,.lo=0x000000004}}, { GLPCI_SB_GLD_MSR_PM, {.hi=0,.lo=0x000000005}}, { GLCP_SB_GLD_MSR_PM, {.hi=0,.lo=0x000000004}}, - { MDD_SB_GLD_MSR_PM, {.hi=0,.lo=0x050554111}}, /* SMBus clock gating errata (PBZ 2226 & SiBZ 3977)*/ + { MDD_SB_GLD_MSR_PM, {.hi=0,.lo=0x050554111}}, /* SMBus clock gating errata (PBZ 2226 & SiBZ 3977)*/ { ATA_SB_GLD_MSR_PM, {.hi=0,.lo=0x000000005}}, { AC97_SB_GLD_MSR_PM, {.hi=0,.lo=0x000000005}}, {0,{0,0}} @@ -210,7 +210,6 @@ chipsetinit (void){ outb( P80_CHIPSET_INIT, 0x80); ChipsetGeodeLinkInit(); - #if 0 /* we hope NEVER to be in linuxbios when S3 resumes if (! IsS3Resume()) */ @@ -230,16 +229,17 @@ chipsetinit (void){ } #endif - /* for later ... if 5536 set_usb_20(); */ - - /* Setup USB. Need more details. #118.18*/ - msrnum = MSR_SB_USB1 + 8; - msr.lo = 0x00012090; - msr.hi = 0; - wrmsr(msrnum, msr); - msrnum = MSR_SB_USB2 + 8; - wrmsr(msrnum, msr); + if (!is_5536()) { + /* Setup USB. Need more details. #118.18*/ + msrnum = MSR_SB_USB1 + 8; + msr.lo = 0x00012090; + msr.hi = 0; + wrmsr(msrnum, msr); + msrnum = MSR_SB_USB2 + 8; + wrmsr(msrnum, msr); + } + /* set hd IRQ */ outl (GPIOL_2_SET, GPIOL_INPUT_ENABLE); outl (GPIOL_2_SET, GPIOL_IN_AUX1_SELECT); @@ -270,7 +270,7 @@ chipsetinit (void){ for(; csi->msrnum; csi++){ msr.lo = csi->msr.lo; msr.hi = csi->msr.hi; - wrmsr(csi->msrnum, msr); + wrmsr(csi->msrnum, msr); // MSR - see table above } @@ -288,12 +288,12 @@ chipsetinit (void){ if (is_5536()) csi = CS5536_CLOCK_GATING_TABLE; else - csi = CS5535_CLOCK_GATING_TABLE; + csi = CS5535_CLOCK_GATING_TABLE; for(; csi->msrnum; csi++){ msr.lo = csi->msr.lo; msr.hi = csi->msr.hi; - wrmsr(csi->msrnum, msr); + wrmsr(csi->msrnum, msr); // MSR - see table above } } diff --git a/src/northbridge/amd/gx2/northbridge.c b/src/northbridge/amd/gx2/northbridge.c index e70938dafb..fca31979dd 100644 --- a/src/northbridge/amd/gx2/northbridge.c +++ b/src/northbridge/amd/gx2/northbridge.c @@ -13,14 +13,11 @@ #include <cpu/x86/msr.h> #include <cpu/x86/cache.h> -#define NORTHBRIDGE_FILE "northbridge.c" +#define VIDEO_MB 8 -/* number of MB to take off the top of ram for VSM and display memory. - * FIXME -- make this configurable - */ -#define RAMADJUSTMB 9 -/* -*/ +extern void graphics_init(void); + +#define NORTHBRIDGE_FILE "northbridge.c" /* todo: add a resource record. We don't do this here because this may be called when * very little of the platform is actually working. @@ -115,24 +112,31 @@ struct msr_defaults { /* GLIU0 */ P2D_BM(0x10000020, 0x1, 0x0, 0x0, 0xfff80), P2D_BM(0x10000021, 0x1, 0x0, 0x80000, 0xfffe0), - P2D_SC(0x1000002c, 0x1, 0x0, 0x0, 0xff03, 0x3), + P2D_SC(0x1000002c, 0x1, 0x0, 0x0, 0xff03, 0xC0000), /* GLIU1 */ P2D_BM(0x40000020, 0x1, 0x0, 0x0, 0xfff80), P2D_BM(0x40000021, 0x1, 0x0, 0x80000, 0xfffe0), - P2D_SC(0x4000002d, 0x1, 0x0, 0x0, 0xff03, 0x3), + P2D_SC(0x4000002d, 0x1, 0x0, 0x0, 0xff03, 0xC0000), {0} }; +/* + * setup_gx2_cache + * + * Returns the amount of memory (in KB) available to the system. This is the + * total amount of memory less the amount of memory reserved for SMM use. + * + */ static int setup_gx2_cache(void) { msr_t msr; unsigned long long val; - int sizembytes, sizereg; + int sizekbytes, sizereg; - sizembytes = sizeram(); - printk_debug("enable_cache: enable for %dm bytes\n", sizembytes); + sizekbytes = sizeram() * 1024; + printk_debug("setup_gx2_cache: enable for %d KB\n", sizekbytes); /* build up the rconf word. */ /* the SYSTOP bits 27:8 are actually the top bits from 31:12. Book fails to say that */ /* set romrp */ @@ -142,54 +146,58 @@ setup_gx2_cache(void) val |= ((unsigned long long) 0xfff00)<<36; /* set the devrp properties */ val |= ((unsigned long long) DEVICE_PROPERTIES) << 28; - /* sigh. Take our TOM, RIGHT shift 12, since it page-aligned, then LEFT-shift 8 for reg. */ - /* yank off 8M for frame buffer and 1M for VSA */ - sizembytes -= RAMADJUSTMB; - sizereg = sizembytes; - sizereg *= 0x100000; + /* Take our TOM, RIGHT shift 12, since it page-aligned, then LEFT-shift 8 for reg. */ + /* yank off memory for the SMM handler */ + sizekbytes -= SMM_SIZE; + sizereg = sizekbytes; + sizereg *= 1024; // convert to bytes sizereg >>= 12; sizereg <<= 8; val |= sizereg; val |= RAM_PROPERTIES; msr.lo = val; msr.hi = (val >> 32); - printk_debug("msr will be set to %x:%x\n", msr.hi, msr.lo); + printk_debug("msr 0x%08X will be set to %08x:%08x\n", CPU_RCONF_DEFAULT, msr.hi, msr.lo); wrmsr(CPU_RCONF_DEFAULT, msr); enable_cache(); wbinvd(); - return sizembytes; + return sizekbytes; } -#define SMM_OFFSET 0x40400000 -#define SMM_SIZE 256 - /* we have to do this here. We have not found a nicer way to do it */ void setup_gx2(void) { int i; - unsigned long tmp, tmp2, tmp3; + unsigned long tmp, tmp2; msr_t msr; - unsigned long sizem, membytes; + unsigned long size_kb, membytes; - sizem = setup_gx2_cache(); + size_kb = setup_gx2_cache(); - membytes = sizem * 1048576; + membytes = size_kb * 1024; /* NOTE! setup_gx2_cache returns the SIZE OF RAM - RAMADJUST! * so it is safe to use. You should NOT at this point call * sizeram() directly. */ - /* we need to set 0x10000028 and 0x40000029 */ - printk_debug("sizem 0x%x, membytes 0x%x\n", sizem, membytes); + /* + * These two descriptors cover the range from 1 MB (0x100000) to + * SYSTOP (a.k.a. TOM, or Top of Memory) + */ + +#if 0 + /* This has already been done elsewhere */ + printk_debug("size_kb 0x%x, membytes 0x%x\n", size_kb, membytes); msr.hi = 0x20000000 | membytes>>24; msr.lo = 0x100 | ( ((membytes >>12) & 0xfff) << 20); wrmsr(0x10000028, msr); msr.hi = 0x20000000 | membytes>>24; msr.lo = 0x100 | ( ((membytes >>12) & 0xfff) << 20); wrmsr(0x40000029, msr); +#endif msr = rdmsr(0x10000028); printk_debug("MSR 0x%x is now 0x%x:0x%x\n", 0x10000028, msr.hi,msr.lo); msr = rdmsr(0x40000029); @@ -227,13 +235,15 @@ setup_gx2(void) msr = rdmsr(0x1808); printk_debug("MSR 0x%x is now 0x%x:0x%x\n", 0x1808, msr.hi, msr.lo); #endif +#if 0 // SDG - don't do this /* now do the default MSR values */ for(i = 0; msr_defaults[i].msr_no; i++) { msr_t msr; - wrmsr(msr_defaults[i].msr_no, msr_defaults[i].msr); + wrmsr(msr_defaults[i].msr_no, msr_defaults[i].msr); // MSR - see table above msr = rdmsr(msr_defaults[i].msr_no); - printk_debug("MSR 0x%x is now 0x%x:0x%x\n", msr_defaults[i].msr_no, msr.hi,msr.lo); + printk_debug("MSR 0x%08X is now 0x%08X:0x%08X\n", msr_defaults[i].msr_no, msr.hi,msr.lo); } +#endif } static void enable_shadow(device_t dev) @@ -325,9 +335,10 @@ static uint32_t find_pci_tolm(struct bus *bus) static void pci_domain_set_resources(device_t dev) { +#if 0 device_t mc_dev; uint32_t pci_tolm; -#if 0 + pci_tolm = find_pci_tolm(&dev->link[0]); mc_dev = dev->link[0].children; if (mc_dev) { @@ -421,13 +432,15 @@ static void enable_dev(struct device *dev) /* do this here for now -- this chip really breaks our device model */ setup_realmode_idt(); do_vsmbios(); + graphics_init(); dev->ops = &pci_domain_ops; pci_set_method(dev); - ram_resource(dev, 0, 0, (sizeram() - RAMADJUSTMB)*1024); + ram_resource(dev, 0, 0, ((sizeram() - VIDEO_MB) * 1024) - SMM_SIZE); } else if (dev->path.type == DEVICE_PATH_APIC_CLUSTER) { printk_debug("DEVICE_PATH_APIC_CLUSTER\n"); dev->ops = &cpu_bus_ops; } + printk_debug("gx2 north: end enable_dev\n"); } struct chip_operations northbridge_amd_gx2_ops = { diff --git a/src/northbridge/amd/gx2/northbridgeinit.c b/src/northbridge/amd/gx2/northbridgeinit.c index 724b4de4c4..6d32aa2a7f 100644 --- a/src/northbridge/amd/gx2/northbridgeinit.c +++ b/src/northbridge/amd/gx2/northbridgeinit.c @@ -22,21 +22,21 @@ struct gliutable { }; 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=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}, + {.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_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.*/ @@ -81,7 +81,7 @@ struct msrinit ClockGatingAllOn[] = { /* Performance*/ struct msrinit ClockGatingPerformance[] = { - {VG_GLD_MSR_PM, {.hi=0x00,.lo=0x0000}}, /* lotus #77.163*/ + {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}}, @@ -91,14 +91,14 @@ struct msrinit ClockGatingPerformance[] = { /* 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*/ + {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*/ }; @@ -111,11 +111,11 @@ writeglmsr(struct gliutable *gl){ msr.lo = gl->lo; msr.hi = gl->hi; - wrmsr(gl->desc_name, msr); - printk_debug("%s: write msr 0x%x, val 0x%x:0x%x\n", __FUNCTION__, gl->desc_name, msr.hi, msr.lo); + 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); /* they do this, so we do this */ 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); + printk_debug("%s: AFTER write msr 0x%08x, val 0x%08x:0x%08x\n", __FUNCTION__, gl->desc_name, msr.hi, msr.lo); } static void @@ -142,6 +142,10 @@ SysmemInit(struct gliutable *gl) msr_t msr; int sizembytes, sizebytes; + /* + * Figure out how much RAM is in the machine and alocate all to the + * system. We will adjust for SMM and DMM now and Frame Buffer later. + */ sizembytes = sizeram(); printk_debug("%s: enable for %dm bytes\n", __FUNCTION__, sizembytes); sizebytes = sizembytes << 20; @@ -152,15 +156,15 @@ SysmemInit(struct gliutable *gl) sizebytes -= DMM_SIZE * 1024 + 1; sizebytes -= 1; - msr.hi = gl->hi | (sizebytes >> 24); + 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 bytes 31:20. */ + sizebytes <<= 8; /* what? well, we want bits 23:12 in bits 31:20. */ sizebytes &= 0xfff00000; sizebytes |= 0x100; msr.lo = sizebytes; - wrmsr(gl->desc_name, msr); + wrmsr(gl->desc_name, msr); // MSR - see table above msr = rdmsr(gl->desc_name); - printk_debug("%s: AFTER write msr 0x%x, val 0x%x:0x%x\n", __FUNCTION__, + printk_debug("%s: AFTER write msr 0x%08x, val 0x%08x:0x%08x\n", __FUNCTION__, gl->desc_name, msr.hi, msr.lo); } @@ -177,7 +181,7 @@ DMMGL0Init(struct gliutable *gl) { sizebytes -= DMM_SIZE*1024; offset = sizebytes - DMM_OFFSET; - printk_debug("%s: offset is 0x%x\n", __FUNCTION__, offset); + printk_debug("%s: offset is 0x%08x\n", __FUNCTION__, offset); offset >>= 12; msr.hi = (gl->hi) | (offset << 8); /* I don't think this is needed */ @@ -186,9 +190,9 @@ DMMGL0Init(struct gliutable *gl) { msr.lo = DMM_OFFSET << 8; msr.lo |= ((~(DMM_SIZE*1024)+1)>>12)&0xfffff; - wrmsr(gl->desc_name, msr); + wrmsr(gl->desc_name, msr); // MSR - See table above 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); + printk_debug("%s: AFTER write msr 0x%08x, val 0x%08x:0x%08x\n", __FUNCTION__, gl->desc_name, msr.hi, msr.lo); } static void @@ -209,9 +213,9 @@ DMMGL1Init(struct gliutable *gl) { 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); + wrmsr(gl->desc_name, msr); // MSR - See table above 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); + printk_debug("%s: AFTER write msr 0x%08x, val 0x%08x:0x%08x\n", __FUNCTION__, gl->desc_name, msr.hi, msr.lo); } static void SMMGL0Init(struct gliutable *gl) { @@ -227,7 +231,7 @@ SMMGL0Init(struct gliutable *gl) { printk_debug("%s: %d bytes\n", __FUNCTION__, sizebytes); offset = sizebytes - SMM_OFFSET; - printk_debug("%s: offset is 0x%x\n", __FUNCTION__, offset); + printk_debug("%s: offset is 0x%08x\n", __FUNCTION__, offset); offset >>= 12; msr.hi = offset << 8; @@ -236,9 +240,9 @@ SMMGL0Init(struct gliutable *gl) { msr.lo = SMM_OFFSET << 8; msr.lo |= ((~(SMM_SIZE*1024)+1)>>12)&0xfffff; - wrmsr(gl->desc_name, msr); + wrmsr(gl->desc_name, msr); // MSR - See table above 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); + printk_debug("%s: AFTER write msr 0x%08x, val 0x%08x:0x%08x\n", __FUNCTION__, gl->desc_name, msr.hi, msr.lo); } static void SMMGL1Init(struct gliutable *gl) { @@ -252,9 +256,9 @@ SMMGL1Init(struct gliutable *gl) { msr.lo = SMM_OFFSET << 8; msr.lo |= ((~(SMM_SIZE*1024)+1)>>12)&0xfffff; - wrmsr(gl->desc_name, msr); + wrmsr(gl->desc_name, msr); // MSR - See table above 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); + printk_debug("%s: AFTER write msr 0x%08x, val 0x%08x:0x%08x\n", __FUNCTION__, gl->desc_name, msr.hi, msr.lo); } static void @@ -263,11 +267,15 @@ GLIUInit(struct gliutable *gl){ while (gl->desc_type != GL_END){ switch(gl->desc_type){ default: +#if 01 + /* For Unknown types: Write then read MSR */ + writeglmsr(gl); +#else 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); - +#endif case SC_SHADOW: /* Check for a Shadow entry*/ ShadowInit(gl); break; @@ -276,7 +284,7 @@ GLIUInit(struct gliutable *gl){ SysmemInit(gl); break; - case BMO_DMM: /* check for a DMM entry*/ + case BMO_DMM: /* check for a DMM entry*/ DMMGL0Init(gl); break; @@ -317,12 +325,12 @@ static void GLPCIInit(void){ 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 = 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); @@ -349,7 +357,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%x msr.hi 0x%x\n", msr.lo, msr.hi); + 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); /* we have the page address. Now make it a page-aligned address */ pah <<= 12; @@ -358,7 +366,7 @@ 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%x msr.hi 0x%x\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); } @@ -506,12 +514,12 @@ performance: 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); + printk_debug("%s: MSR 0x%08x is 0x%08x:0x%08x\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__, + printk_debug("%s: MSR 0x%08x will be set to 0x%08x:0x%08x\n", __FUNCTION__, gating->msrnum, msr.hi, msr.lo); - wrmsr(gating->msrnum, msr); + wrmsr(gating->msrnum, msr); // MSR - See the table above gating +=1; } @@ -525,32 +533,251 @@ GeodeLinkPriority(void){ 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); + printk_debug("%s: MSR 0x%08x is 0x%08x:0x%08x\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__, + printk_debug("%s: MSR 0x%08x will be set to 0x%08x:0x%08x\n", __FUNCTION__, prio->msrnum, msr.hi, msr.lo); - wrmsr(prio->msrnum, msr); + wrmsr(prio->msrnum, msr); // MSR - See the table above prio +=1; } } + + - /* ***************************************************************************/ - /* **/ - /* * northBridgeInit*/ - /* **/ - /* * Core Logic initialization: Host bridge*/ - /* **/ - /* * Entry:*/ - /* * Exit:*/ - /* * Modified:*/ - /* **/ - /* ***************************************************************************/ +/* + * Get the GLIU0 shadow register settings + * If the setShadow function is used then all shadow descriptors + * will stay sync'ed. + */ +static uint64_t getShadow(void) +{ + msr_t msr; + msr = rdmsr(MSR_GLIU0_SHADOW); + return ( ( (uint64_t) msr.hi ) << 32 ) | msr.lo; +} + + +/* + * Set the cache RConf registers for the memory hole. + * Keeps all cache shadow descriptors sync'ed. + * This is part of the PCI lockup solution + * Entry: EDX:EAX is the shadow settings + */ +static void setShadowRCONF(uint32_t shadowHi, uint32_t shadowLo) +{ + // ok this is whacky bit translation time. + int bit; + uint8_t shadowByte; + msr_t msr; + shadowByte = (uint8_t) (shadowLo >> 16); + + // load up D000 settings in edx. + for (bit = 8; (bit > 4); bit--) { + msr.hi <<= 8; + msr.hi |= 1; // cache disable PCI/Shadow memory + if (shadowByte && (1 << bit)) + msr.hi |= 0x20; // write serialize PCI memory + } + + // load up C000 settings in eax. + for ( ; bit; bit--) { + msr.lo <<= 8; + msr.lo |= 1; // cache disable PCI/Shadow memory + if (shadowByte && (1 << bit)) + msr.lo |= 0x20; // write serialize PCI memory + } + + wrmsr(CPU_RCONF_C0_DF, msr); + + shadowByte = (uint8_t) (shadowLo >> 24); + + // load up F000 settings in edx. + for (bit = 8; (bit > 4); bit--) { + msr.hi <<= 8; + msr.hi |= 1; // cache disable PCI/Shadow memory + if (shadowByte && (1 << bit)) + msr.hi |= 0x20; // write serialize PCI memory + } + + // load up E000 settings in eax. + for ( ; bit; bit--) { + msr.lo <<= 8; + msr.lo |= 1; // cache disable PCI/Shadow memory + if (shadowByte && (1 << bit)) + msr.lo |= 0x20; // write serialize PCI memory + } + + wrmsr(CPU_RCONF_E0_FF, msr); +} + + +/* + * Set the GLPCI registers for the memory hole. + * Keeps all cache shadow descriptors sync'ed. + * Entry: EDX:EAX is the shadow settings + */ +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); + wrmsr(GLPCI_REN, msr); +} + + +/* + * Set the GLIU SC register settings. Scans descriptor tables for SC_SHADOW. + * Keeps all shadow descriptors sync'ed. + * Entry: EDX:EAX is the shadow settings + */ +static void setShadow(uint64_t shadowSettings) +{ + int i; + msr_t msr; + struct gliutable* pTable; + uint32_t shadowLo, shadowHi; + + shadowLo = (uint32_t) shadowSettings; + shadowHi = (uint32_t) (shadowSettings >> 32); + + setShadowRCONF(shadowHi, shadowLo); + setShadowGLPCI(shadowHi, shadowLo); + + for(i = 0; gliutables[i]; i++) { + for (pTable = gliutables[i]; pTable->desc_type != GL_END; pTable++) { + if (pTable->desc_type == SC_SHADOW) { + + msr = rdmsr(pTable->desc_name); + msr.lo = (uint32_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) +{ + uint64_t shadowSettings = getShadow(); + shadowSettings &= (uint64_t) 0xFFFF00000000FFFFULL; // Disable read & writes + shadowSettings |= (uint64_t) 0x00000000F0000000ULL; // Enable reads for F0000-FFFFF + setShadow(shadowSettings); +} + + + +/*************************************************************************** + * + * RCONFInit + * Set up RCONF_DEFAULT and any other RCONF registers needed + * + * DEVRC_RCONF_DEFAULT: + * ROMRC(63:56) = 04h ; write protect ROMBASE + * ROMBASE(36:55) = 0FFFC0h ; Top of PCI/bottom of rom chipselect area + * DEVRC(35:28) = 39h ; cache disabled in PCI memory + WS bit on + Write Combine + write burst. + * SYSTOP(27:8) = top of system memory + * SYSRC(7:0) = 00h ; writeback, can set to 08h to make writethrough + * + ***************************************************************************/ +#define SYSMEM_RCONF_WRITETHROUGH 8 +#define DEVRC_RCONF_DEFAULT 0x21 +#define ROMBASE_RCONF_DEFAULT 0xFFFC0000 +#define ROMRC_RCONF_DEFAULT 0x25 + +static void +RCONFInit(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++) { + if (gliu0table[i].desc_type == R_SYSMEM) { + gl = &gliu0table[i]; + break; + } + } + if (gl == 0) { + post_code(0xCE); /* POST_RCONFInitError */ + while (1); + } + +// sysdescfound: + /* found the descriptor... get its contents */ + msr = rdmsr(gl->desc_name); + + /* 20 bit address - The bottom 12 bits go into bits 20-31 in eax, the + * top 8 bits go into 0-7 of edx. + */ + msr.lo = (msr.lo & 0xFFFFFF00) | (msr.hi & 0xFF); + msr.lo = ((msr.lo << 12) | (msr.lo >> 20)) & 0x000FFFFF; + msr.lo <<= RCONF_DEFAULT_LOWER_SYSTOP_SHIFT; // 8 + + // Set Default SYSMEM region properties + msr.lo &= ~SYSMEM_RCONF_WRITETHROUGH; // 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.lo |= (DEVRC_RCONF_DEFAULT << 28); + + // Set the ROMBASE. This is usually FFFC0000h + msr.hi |= (ROMBASE_RCONF_DEFAULT >> 12) << RCONF_DEFAULT_UPPER_ROMBASE_SHIFT; + + // Set ROMBASE cache properties. + msr.hi |= ((ROMRC_RCONF_DEFAULT >> 8) | (ROMRC_RCONF_DEFAULT << 24)); + + // now program RCONF_DEFAULT + wrmsr(CPU_RCONF_DEFAULT, msr); + + // RCONF_BYPASS: Cache tablewalk properties and SMM/DMM header access properties. + // Set to match system memory cache properties. + msr = rdmsr(CPU_RCONF_DEFAULT); + SysMemCacheProp = (uint8_t) (msr.lo & 0xFF); + msr = rdmsr(CPU_RCONF_BYPASS); + msr.lo = (msr.lo & 0xFFFF0000) | (SysMemCacheProp << 8) | SysMemCacheProp; + wrmsr(CPU_RCONF_BYPASS, msr); +} + + +/* ***************************************************************************/ +/* **/ +/* * northBridgeInit*/ +/* **/ +/* * Core Logic initialization: Host bridge*/ +/* **/ +/* * Entry:*/ +/* * Exit:*/ +/* * Modified:*/ +/* **/ +/* ***************************************************************************/ void northbridgeinit(void) { + msr_t msr; int i; printk_debug("Enter %s\n", __FUNCTION__); @@ -558,10 +785,25 @@ northbridgeinit(void) 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: + 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 it's lines before it can be used.*/ + /* The memory controller needs one read to synch its lines before it can be used.*/ i = *(int *) 0; GLPCIInit(); |