Author: rminnich Date: 2007-06-28 19:12:37 +0200 (Thu, 28 Jun 2007) New Revision: 401
Added: LinuxBIOSv3/northbridge/amd/geodelx/geodelxinit.c Removed: LinuxBIOSv3/northbridge/amd/geodelx/geodelx.h Modified: LinuxBIOSv3/northbridge/amd/geodelx/geodelx.c LinuxBIOSv3/northbridge/intel/i440bxemulation/i440bx.c Log: Remove no longer needed file. Add a needed file. remove misleading printk from i440bx.c Signed-off-by: Ronald G. Minnich rminnich@gmail.com Acked-by: Stefan Reinauer stepan@coresystems.de
Modified: LinuxBIOSv3/northbridge/amd/geodelx/geodelx.c =================================================================== --- LinuxBIOSv3/northbridge/amd/geodelx/geodelx.c 2007-06-28 17:07:19 UTC (rev 400) +++ LinuxBIOSv3/northbridge/amd/geodelx/geodelx.c 2007-06-28 17:12:37 UTC (rev 401) @@ -24,16 +24,18 @@ #include <post_code.h> #include <device/device.h> #include <device/pci.h> +#include <device/pci_ids.h> #include <string.h> #include <msr.h> #include <io.h> #include <amd_geodelx.h> -#include "geodelx.h"
/* here is programming for the various MSRs.*/ #define IM_QWAIT 0x100000
-#define DMCF_WRITE_SERIALIZE_REQUEST (2<<12) /* 2 outstanding */ /* set in high nibl */ +/* set in high nibl */ +#define DMCF_WRITE_SERIALIZE_REQUEST (2<<12) /* 2 outstanding */ + #define DMCF_SERIAL_LOAD_MISSES (2) /* enabled */
/* these are the 8-bit attributes for controlling RCONF registers @@ -63,7 +65,9 @@ #define RRCF_LOW_CD(base) RRCF_LOW(base, CACHE_DISABLE)
/* build initializer for P2D MSR */ -/* this is complex enough that you are going to need to RTFM if you really want to understand it. */ +/* this is complex enough that you are going to need to RTFM if you + * really want to understand it. + */ #define P2D_BM(msr, pdid1, bizarro, pbase, pmask) {msr, {.hi=(pdid1<<29)|(bizarro<<28)|(pbase>>24), .lo=(pbase<<8)|pmask}} #define P2D_BMO(msr, pdid1, bizarro, poffset, pbase, pmask) {msr, {.hi=(pdid1<<29)|(bizarro<<28)|(poffset<<8)|(pbase>>24), .lo=(pbase<<8)|pmask}} #define P2D_R(msr, pdid1, bizarro, pmax, pmin) {msr, {.hi=(pdid1<<29)|(bizarro<<28)|(pmax>>12), .lo=(pmax<<20)|pmin}} @@ -86,37 +90,38 @@
struct msr_defaults { int msr_no; - msr_t msr; + struct msr msr; } msr_defaults[] = { - { - 0x1700, { - .hi = 0,.lo = IM_QWAIT}}, { - 0x1800, { - .hi = DMCF_WRITE_SERIALIZE_REQUEST,.lo = - DMCF_SERIAL_LOAD_MISSES}}, - /* 1808 will be done down below, so we have to do 180a->1817 (well, 1813 really) */ - /* for 180a, for now, we assume VSM will configure it */ - /* 180b is left at reset value,a0000-bffff is non-cacheable */ - /* 180c, c0000-dffff is set to write serialize and non-cachable */ - /* oops, 180c will be set by cpu bug handling in cpubug.c */ - //{0x180c, {.hi = MSR_WS_CD_DEFAULT, .lo = MSR_WS_CD_DEFAULT}}, - /* 180d is left at default, e0000-fffff is non-cached */ - /* we will assume 180e, the ssm region configuration, is left at default or set by VSM */ - /* we will not set 0x180f, the DMM,yet */ - //{0x1810, {.hi=0xee7ff000, .lo=RRCF_LOW(0xee000000, WRITE_COMBINE|CACHE_DISABLE)}}, - //{0x1811, {.hi = 0xefffb000, .lo = RRCF_LOW_CD(0xefff8000)}}, - //{0x1812, {.hi = 0xefff7000, .lo = RRCF_LOW_CD(0xefff4000)}}, - //{0x1813, {.hi = 0xefff3000, .lo = RRCF_LOW_CD(0xefff0000)}}, - /* now for GLPCI routing */ - /* GLIU0 */ - P2D_BM(MSR_GLIU0_BASE1, 0x1, 0x0, 0x0, 0xfff80), - P2D_BM(MSR_GLIU0_BASE2, 0x1, 0x0, 0x80000, 0xfffe0), - P2D_SC(MSR_GLIU0_SHADOW, 0x1, 0x0, 0x0, 0xff03, 0xC0000), - /* GLIU1 */ - P2D_BM(MSR_GLIU1_BASE1, 0x1, 0x0, 0x0, 0xfff80), - P2D_BM(MSR_GLIU1_BASE2, 0x1, 0x0, 0x80000, 0xfffe0), - P2D_SC(MSR_GLIU1_SHADOW, 0x1, 0x0, 0x0, 0xff03, 0xC0000), { - 0} + {0x1700, {.hi = 0,.lo = IM_QWAIT}}, + {0x1800, {.hi = DMCF_WRITE_SERIALIZE_REQUEST, + .lo = DMCF_SERIAL_LOAD_MISSES}}, + /* 1808 will be done down below, so we have to do 180a->1817 + * (well, 1813 really) + */ + /* for 180a, for now, we assume VSM will configure it */ + /* 180b is left at reset value,a0000-bffff is non-cacheable */ + /* 180c, c0000-dffff is set to write serialize and non-cachable */ + /* oops, 180c will be set by cpu bug handling in cpubug.c */ + //{0x180c, {.hi = MSR_WS_CD_DEFAULT, .lo = MSR_WS_CD_DEFAULT}}, + /* 180d is left at default, e0000-fffff is non-cached */ + /* we will assume 180e, the ssm region configuration, is left + * at default or set by VSM */ + /* we will not set 0x180f, the DMM,yet + */ + //{0x1810, {.hi=0xee7ff000, .lo=RRCF_LOW(0xee000000, WRITE_COMBINE|CACHE_DISABLE)}}, + //{0x1811, {.hi = 0xefffb000, .lo = RRCF_LOW_CD(0xefff8000)}}, + //{0x1812, {.hi = 0xefff7000, .lo = RRCF_LOW_CD(0xefff4000)}}, + //{0x1813, {.hi = 0xefff3000, .lo = RRCF_LOW_CD(0xefff0000)}}, + /* now for GLPCI routing */ + /* GLIU0 */ + P2D_BM(MSR_GLIU0_BASE1, 0x1, 0x0, 0x0, 0xfff80), + P2D_BM(MSR_GLIU0_BASE2, 0x1, 0x0, 0x80000, 0xfffe0), + P2D_SC(MSR_GLIU0_SHADOW, 0x1, 0x0, 0x0, 0xff03, 0xC0000), + /* GLIU1 */ + P2D_BM(MSR_GLIU1_BASE1, 0x1, 0x0, 0x0, 0xfff80), + P2D_BM(MSR_GLIU1_BASE2, 0x1, 0x0, 0x80000, 0xfffe0), + P2D_SC(MSR_GLIU1_SHADOW, 0x1, 0x0, 0x0, 0xff03, 0xC0000), + {0} };
/** @@ -127,21 +132,23 @@ */ int sizeram(void) { - msr_t msr; + struct msr msr; int sizem = 0; unsigned short dimm;
- /* Get the RAM size from the memory controller as calculated and set by auto_size_dimm() */ + /* Get the RAM size from the memory controller as calculated + * and set by auto_size_dimm() + */ msr = rdmsr(MC_CF07_DATA); printk(BIOS_DEBUG,"sizeram: _MSR MC_CF07_DATA: %08x:%08x\n", msr.hi, msr.lo); - + /* dimm 0 */ dimm = msr.hi; /* installed? */ if ((dimm & 7) != 7) { /* 1:8MB, 2:16MB, 3:32MB, 4:64MB, ... 7:512MB, 8:1GB */ sizem = 4 << ((dimm >> 12) & 0x0F); } - + /* dimm 1 */ dimm = msr.hi >> 16; /* installed? */ @@ -165,12 +172,11 @@ /** * init the northbridge pci device. Right now this a no op. We leave * it here as a hook for later use. - * @param dev The nortbridge - * device. - */ + * @param dev The nortbridge device. + */ static void geodelx_northbridge_init(struct device * dev) { - //msr_t msr; + //struct msr msr;
printk(BIOS_SPEW,">> Entering northbridge.c: %s\n", __FUNCTION__);
@@ -202,23 +208,27 @@
for (resource = &dev->resource[0]; resource < last; resource++) {
- // andrei: do not change the base address, it will make the VSA virtual registers unusable + /* + * from AMD: do not change the base address, it will + * make the VSA virtual registers unusable + */ //pci_set_resource(dev, resource); // FIXME: static allocation may conflict with dynamic mappings! } - + for (link = 0; link < dev->links; link++) { struct bus *bus; bus = &dev->link[link]; if (bus->children) { - printk(BIOS_DEBUG, "my_dev_set_resources: phase4_assign_resources %d\n", bus); + printk(BIOS_DEBUG, + "my_dev_set_resources: phase4_assign_resources %d\n", bus); phase4_assign_resources(bus); } } - + /* set a default latency timer */ pci_write_config8(dev, PCI_LATENCY_TIMER, 0x40); - + /* set a default secondary latency timer */ if ((dev->hdr_type & 0x7f) == PCI_HEADER_TYPE_BRIDGE) { pci_write_config8(dev, PCI_SEC_LATENCY_TIMER, 0x40); @@ -251,13 +261,13 @@ resource = new_resource(dev, IOINDEX_SUBTRACTIVE(0, 0)); resource->limit = 0xffffUL; resource->flags = - IORESOURCE_IO | IORESOURCE_SUBTRACTIVE | IORESOURCE_ASSIGNED; + IORESOURCE_IO | IORESOURCE_SUBTRACTIVE | IORESOURCE_ASSIGNED;
/* Initialize the system wide memory resources constraints */ resource = new_resource(dev, IOINDEX_SUBTRACTIVE(1, 0)); resource->limit = 0xffffffffULL; resource->flags = - IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE | IORESOURCE_ASSIGNED; + IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE | IORESOURCE_ASSIGNED; }
/** @@ -280,7 +290,7 @@ resource->base = ((resource_t) basek) << 10; resource->size = ((resource_t) sizek) << 10; resource->flags = IORESOURCE_MEM | IORESOURCE_CACHEABLE | - IORESOURCE_FIXED | IORESOURCE_STORED | IORESOURCE_ASSIGNED; + IORESOURCE_FIXED | IORESOURCE_STORED | IORESOURCE_ASSIGNED; }
/** @@ -426,13 +436,13 @@ /* Domain ops and apic cluster ops and pci device ops are different */ struct constructor geodelx_north_constructors[] = { {.id = {.type = DEVICE_ID_PCI_DOMAIN, - .u = {.pci_domain = {.vendor = 0x8086,.device = 0x7190}}}, + .u = {.pci_domain = {.vendor = PCI_VENDOR_ID_AMD,.device = PCI_DEVICE_ID_AMD_LXBRIDGE}}}, &geodelx_pcidomainops}, {.id = {.type = DEVICE_ID_APIC_CLUSTER, - .u = {.apic_cluster = {.vendor = 0x8086,.device = 0x7190}}}, + .u = {.apic_cluster = {.vendor = PCI_VENDOR_ID_AMD,.device = PCI_DEVICE_ID_AMD_LXBRIDGE}}}, &geodelx_apicops}, {.id = {.type = DEVICE_ID_PCI, - .u = {.pci = {.vendor = 0x8086,.device = 0x7190}}}, + .u = {.pci = {.vendor = PCI_VENDOR_ID_AMD,.device = PCI_DEVICE_ID_AMD_LXBRIDGE}}}, &geodelx_pci_ops}, {.ops = 0}, };
Deleted: LinuxBIOSv3/northbridge/amd/geodelx/geodelx.h =================================================================== --- LinuxBIOSv3/northbridge/amd/geodelx/geodelx.h 2007-06-28 17:07:19 UTC (rev 400) +++ LinuxBIOSv3/northbridge/amd/geodelx/geodelx.h 2007-06-28 17:12:37 UTC (rev 401) @@ -1,25 +0,0 @@ -/* - * This file is part of the LinuxBIOS project. - * - * Copyright (C) 2007 Advanced Micro Devices, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef NORTHBRIDGE_AMD_GEODELX_GEODELX_H -#define NORTHBRIDGE_AMD_GEODELX_GEODELX_H - -/* TODO: Empty file, should be removed? */ - -#endif /* NORTHBRIDGE_AMD_GEODELX_GEODELX_H */
Added: LinuxBIOSv3/northbridge/amd/geodelx/geodelxinit.c =================================================================== --- LinuxBIOSv3/northbridge/amd/geodelx/geodelxinit.c (rev 0) +++ LinuxBIOSv3/northbridge/amd/geodelx/geodelxinit.c 2007-06-28 17:12:37 UTC (rev 401) @@ -0,0 +1,842 @@ +/* + * This file is part of the LinuxBIOS project. + * + * Copyright (C) 2007 Advanced Micro Devices, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <types.h> +#include <lib.h> +#include <console.h> +#include <post_code.h> +#include <device/device.h> +#include <device/pci.h> +#include <string.h> +#include <msr.h> +#include <io.h> +#include <cpu.h> +#include <amd_geodelx.h> + +struct gliutable { + unsigned long desc_name; + unsigned short desc_type; + unsigned long hi, lo; +}; + +struct gliutable gliu0table[] = { + /* 0-7FFFF to MC */ + {.desc_name = MSR_GLIU0_BASE1,.desc_type = BM,.hi = MSR_MC + 0x0, + .lo = 0x0FFF80}, + /* 80000-9ffff to Mc */ + {.desc_name = MSR_GLIU0_BASE2,.desc_type = BM,.hi = MSR_MC + 0x0, + .lo = (0x80 << 20) + 0x0FFFE0}, + /* C0000-Fffff split to MC and PCI (sub decode) A0000-Bffff + * handled by SoftVideo + */ + {.desc_name = MSR_GLIU0_SHADOW,.desc_type = SC_SHADOW, + .hi = MSR_MC + 0x0,.lo = 0x03}, + /* Catch and fix dynamicly. */ + {.desc_name = MSR_GLIU0_SYSMEM,.desc_type = R_SYSMEM, + .hi = MSR_MC,.lo = 0x0}, + /* Catch and fix dynamicly. */ + {.desc_name = MSR_GLIU0_SMM,.desc_type = BMO_SMM, + .hi = MSR_MC,.lo = 0x0}, + {.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[] = { + /* 0-7FFFF to MC */ + {.desc_name = MSR_GLIU1_BASE1,.desc_type = BM,.hi = MSR_GL0 + 0x0, + .lo = 0x0FFF80}, + /* 80000-9ffff to Mc */ + {.desc_name = MSR_GLIU1_BASE2,.desc_type = BM,.hi = MSR_GL0 + 0x0, + .lo = (0x80 << 20) + 0x0FFFE0}, + /* C0000-Fffff split to MC and PCI (sub decode) */ + {.desc_name = MSR_GLIU1_SHADOW,.desc_type = SC_SHADOW, + .hi = MSR_GL0 + 0x0,.lo = 0x03}, + /* Catch 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}, + {.desc_name = GLIU1_GLD_MSR_COH,.desc_type = OTHER, + .hi = 0x0,.lo = GL1_GLIU0}, + /* FooGlue FPU 0xF0 */ + {.desc_name = MSR_GLIU1_FPU_TRAP,.desc_type = SCIO, + .hi = (GL1_GLCP << 29) + 0x0,.lo = 0x033000F0}, + {.desc_name = GL_END,.desc_type = GL_END,.hi = 0x0,.lo = 0x0}, +}; + +struct gliutable *gliutables[] = { gliu0table, gliu1table, 0 }; + +struct msrinit { + unsigned long msrnum; + struct msr msr; +}; + +struct msrinit clock_gating_default[] = { + {GLIU0_GLD_MSR_PM, {.hi = 0x00,.lo = 0x0005}}, + {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 = 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}}, + {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}}, +}; + +/* */ +/* SET GeodeLink PRIORITY*/ +/* */ +struct msrinit geode_link_priority_table[] = { + {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); + +/** + * Write a GeodeLink MSR. + * @param gl A Geode Link table descriptor + */ +static void writeglmsr(struct gliutable *gl) +{ + struct msr msr; + + msr.lo = gl->lo; + msr.hi = gl->hi; + wrmsr(gl->desc_name, msr); // MSR - see table above + printk(BIOS_SPEW, + "%s: MSR 0x%08x, val 0x%08x:0x%08x\n", + __FUNCTION__, gl->desc_name, msr.hi, msr.lo); +} + +/** + * Read the MSR specified in the gl struct. If the low 32 bits is zero, + * indicating + * it has not been set, set it. + * @param gl A Geode Link table descriptor + */ +static void ShadowInit(struct gliutable *gl) +{ + struct msr msr; + + msr = rdmsr(gl->desc_name); + + if (msr.lo == 0) { + writeglmsr(gl); + } +} + +extern int sizeram(void); + +/** + * Set up the system memory registers, i.e. memory that can be used + * for non-VSM (or SMM) purposes. + * @param gl A Geode Link table descriptor + */ + +static void sysmem_init(struct gliutable *gl) +{ + struct msr msr; + int sizembytes, sizebytes; + + /* + * Figure out how much RAM is in the machine and alocate all to the + * system. We will adjust for SMM now and Frame Buffer later. + */ + sizembytes = sizeram(); + printk(BIOS_DEBUG, "%s: enable for %dMBytes\n", + __FUNCTION__, sizembytes); + sizebytes = sizembytes << 20; + + sizebytes -= ((SMM_SIZE * 1024) + 1); + printk(BIOS_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); + sizebytes <<= 8; /* move bits 23:12 in bits 31:20. */ + sizebytes &= 0xfff00000; + sizebytes |= 0x100; /* start at 1MB */ + msr.lo = sizebytes; + + wrmsr(gl->desc_name, msr); // MSR - see table above + printk(BIOS_DEBUG, "%s: MSR 0x%08x, val 0x%08x:0x%08x\n", __FUNCTION__, + gl->desc_name, msr.hi, msr.lo); +} + +/** + * Set up GL0 memory mapping. Again, SMM memory is subtracted. + * @param gl A Geode Link table descriptor + */ + +static void SMMGL0Init(struct gliutable *gl) +{ + struct msr msr; + int sizebytes = sizeram() << 20; + long offset; + + sizebytes -= (SMM_SIZE * 1024); + + printk(BIOS_DEBUG, "%s: %d bytes\n", __FUNCTION__, sizebytes); + + /* calculate the Two's complement offset */ + offset = sizebytes - SMM_OFFSET; + offset = (offset >> 12) & 0x000fffff; + printk(BIOS_DEBUG, "%s: offset is 0x%08x\n", __FUNCTION__, SMM_OFFSET); + + 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 + printk(BIOS_DEBUG, "%s: MSR 0x%08x, val 0x%08x:0x%08x\n", __FUNCTION__, + gl->desc_name, msr.hi, msr.lo); +} + +/** + * Set up GL1 memory mapping. Again, SMM memory is subtracted. + * @param gl A Geode Link table descriptor + */ + +static void SMMGL1Init(struct gliutable *gl) +{ + struct msr msr; + printk(BIOS_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) & 0xFFF00000; + msr.lo |= ((~(SMM_SIZE * 1024) + 1) >> 12) & 0xfffff; + + wrmsr(gl->desc_name, msr); // MSR - See table above + printk(BIOS_DEBUG, "%s: MSR 0x%08x, val 0x%08x:0x%08x\n", __FUNCTION__, + gl->desc_name, msr.hi, msr.lo); +} + +/** + * Set up all Geode Link Interfaces. Iterate over the table until done. + * Case out on the link type, and call the appropriate function. + * @param gl A Geode Link table descriptor + */ + +static void GLIUInit(struct gliutable *gl) +{ + + while (gl->desc_type != GL_END) { + switch (gl->desc_type) { + default: + /* For Unknown types: Write then read MSR */ + writeglmsr(gl); + case SC_SHADOW: /* Check for a Shadow entry */ + ShadowInit(gl); + break; + + case R_SYSMEM: /* check for a SYSMEM entry */ + sysmem_init(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++; + } + +} + +/** + * Set up the region config registers for the Geode Link PCI interface. + * R0: 0-640KB, + * R1: 1MB - Top of System Memory + * R2: SMM Memory + * R3: Framebuffer? - not set up yet + */ +static void GLPCI_init(void) +{ + struct gliutable *gl = 0; + int i; + struct msr msr; + int msrnum, enable_preempt, enable_cpu_override; + int nic_grants_control, enable_bus_parking; + + /* 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) { + unsigned long pah, pal; + msrnum = gl->desc_name; + msr = rdmsr(msrnum); + /* example R_SYSMEM value: 20:00:00:0f:fb:f0:01:00 + * translates to a base of 0x00100000 and top of 0xffbf0000 + * base of 1M and top of around 256M + */ + /* we have to create a page-aligned (4KB page) address + * for base and top */ + /* 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 + */ + pah = ((msr.hi & 0xFF) << 12) | ((msr.lo >> 20) & 0xFFF); + /* we have the page address. Now make it a + * page-aligned address */ + pah <<= 12; + + pal = msr.lo << 12; + msr.hi = pah; + msr.lo = pal; + msr.lo |= + GLPCI_RC_LOWER_EN_SET | GLPCI_RC_LOWER_PF_SET | + GLPCI_RC_LOWER_WC_SET; + printk(BIOS_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 */ + 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(BIOS_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 */ + + 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); + /* reduce to 1 for safe mode */ + msr.hi |= 2 << DM_CONFIG0_UPPER_WSREQ_SHIFT; + wrmsr(msrnum, msr); + + /* The following settings will not work with a CS5530 southbridge */ + /* we are ignoring the 5530 case for now, and perhaps forever. */ + + /* */ + /* 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; + nic_grants_control = + (0x4 << GLPCI_ARB_UPPER_R2_SHIFT) | (0x3 << + GLPCI_ARB_UPPER_H2_SHIFT); + + msrnum = GLPCI_ARB; + msr = rdmsr(msrnum); + + msr.hi |= nic_grants_control; + msr.lo |= enable_cpu_override | enable_preempt | enable_bus_parking; + wrmsr(msrnum, msr); + + msrnum = GLPCI_CTRL; + msr = rdmsr(msrnum); + /* (Out will be disabled in CPUBUG649 for < 2.0 parts .) */ + msr.lo |= GLPCI_CTRL_LOWER_ME_SET | GLPCI_CTRL_LOWER_OWC_SET + | GLPCI_CTRL_LOWER_PCD_SET; + 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); + /* Change once 1.x is gone */ + msr.hi |= 0x1F << GLPCI_CTRL_UPPER_LAT_SHIFT; + 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); +} + +/** + * Enable Clock Gating in ALL MSRs which relate to clocks. + */ +static void clock_gating_init(void) +{ + struct msr msr; + struct msrinit *gating = clock_gating_default; + int i; + + for (i = 0; gating->msrnum != 0xffffffff; i++) { + msr = rdmsr(gating->msrnum); + msr.hi |= gating->msr.hi; + msr.lo |= gating->msr.lo; + wrmsr(gating->msrnum, msr); // MSR - See the table above + gating += 1; + } + +} + +/** + * Set all Geode Link Priority register as determined by the + */ +static void geode_link_priority(void) +{ + struct msr msr; + struct msrinit *prio = geode_link_priority_table; + int i; + + for (i = 0; prio->msrnum != 0xffffffff; i++) { + msr = rdmsr(prio->msrnum); + msr.hi |= prio->msr.hi; + msr.lo &= ~0xfff; + msr.lo |= prio->msr.lo; + wrmsr(prio->msrnum, msr); // MSR - See the table above + prio += 1; + } +} + +/** + * Get the GLIU0 shadow register settings + * If the set_shadow function is used then all shadow descriptors + * will stay sync'ed. + */ +static u64 get_shadow(void) +{ + struct msr msr; + + msr = rdmsr(MSR_GLIU0_SHADOW); + return (((u64) 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 + * @param Hi the high 32 bits of the msr setting + * @param lo The low 32 bits of the msr setting + */ +static void set_shadowRCONF(u32 shadowHi, u32 shadowLo) +{ + + // ok this is whacky bit translation time. + int bit; + u8 shadowByte; + struct msr msr = { 0, 0 }; + shadowByte = (u8) (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 = (u8) (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. + * @param shadowhi the high 32 bits of the msr setting + * @param shadowlo The low 32 bits of the msr setting + */ +static void set_shadowGLPCI(u32 shadowhi, u32 shadowlo) +{ + struct msr 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. + * @param shadowSettings Shadow register settings + */ +static void set_shadow(u64 shadowSettings) +{ + int i; + struct msr msr; + struct gliutable *pTable; + u32 shadowLo, shadowHi; + + shadowLo = (u32) shadowSettings; + shadowHi = (u32) (shadowSettings >> 32); + + set_shadowRCONF(shadowHi, shadowLo); + set_shadowGLPCI(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 = (u32) shadowSettings; + /* maintain PDID in upper EDX*/ + msr.hi &= 0xFFFF0000; + msr.hi |= + ((u32) (shadowSettings >> 32)) & + 0x0000FFFF; + // MSR - See the table above + wrmsr(pTable->desc_name, msr); + } + } + } +} + +static void rom_shadow_settings(void) +{ + + u64 shadowSettings = get_shadow(); + // Disable read & writes + shadowSettings &= (u64) 0xFFFF00000000FFFFULL; + // Enable reads for F0000-FFFFF + shadowSettings |= (u64) 0x00000000F0000000ULL; + // Enable rw for C0000-CFFFF + shadowSettings |= (u64) 0x0000FFFFFFFF0000ULL; + set_shadow(shadowSettings); +} + +/** + * + * + * 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) = 0 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 enable_L1_cache(void) +{ + struct gliutable *gl = 0; + int i; + struct msr msr; + u8 SysMemCacheProp; + + /* 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: + 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 + // NOT writethrough == writeback 8 (or ~8) + msr.lo &= ~SYSMEM_RCONF_WRITETHROUGH; + + // Set PCI space cache properties + // setting is split betwwen hi and lo... + msr.hi = (DEVRC_RCONF_DEFAULT >> 4); + 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); + printk(BIOS_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. + msr = rdmsr(CPU_RCONF_DEFAULT); + SysMemCacheProp = (u8) (msr.lo & 0xFF); + msr = rdmsr(CPU_RCONF_BYPASS); + msr.lo = + (msr.lo & 0xFFFF0000) | (SysMemCacheProp << 8) | SysMemCacheProp; + wrmsr(CPU_RCONF_BYPASS, msr); + + printk(BIOS_DEBUG, "CPU_RCONF_BYPASS (180A): 0x%08x : 0x%08x\n", + msr.hi, msr.lo); +} + +/** + * Enable the L2 cache MSRs. + */ +static void enable_L2_cache(void) +{ + struct msr 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(BIOS_DEBUG, "L2 cache enabled\n"); +} + +#ifndef CONFIG_VIDEO_MB +#warning "CONFIG_VIDEO_MB was not defined" +#define CONFIG_VIDEO_MB 8 +#endif + +/** + * set up all LX cache registers, L1, L2, and x86. + */ +static void setup_lx_cache(void) +{ + struct msr 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); + + enable_cache(); + __asm__("wbinvd\n"); +} + +u32 get_systop(void) +{ + struct gliutable *gl = 0; + u32 systop; + struct msr 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 Do all the Nasty Bits that have to + * happen. These can be done once memory is up, but before much else + * is done. So we do them in Phase 2. + */ +void northbridge_init_early(void) +{ + struct msr msr; + int i; + printk(BIOS_DEBUG, "Enter %s\n", __FUNCTION__); + + for (i = 0; gliutables[i]; i++) + GLIUInit(gliutables[i]); + + /* 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; + + geode_link_priority(); + + setup_lx_cache(); + + rom_shadow_settings(); + + GLPCI_init(); + + clock_gating_init(); + + __asm__ __volatile__("FINIT\n"); + printk(BIOS_DEBUG, "Exit %s\n", __FUNCTION__); +}
Modified: LinuxBIOSv3/northbridge/intel/i440bxemulation/i440bx.c =================================================================== --- LinuxBIOSv3/northbridge/intel/i440bxemulation/i440bx.c 2007-06-28 17:07:19 UTC (rev 400) +++ LinuxBIOSv3/northbridge/intel/i440bxemulation/i440bx.c 2007-06-28 17:12:37 UTC (rev 401) @@ -91,9 +91,7 @@ struct northbridge_intel_i440bxemulation_config *device_configuration = dev->device_configuration; tolmk = device_configuration->ramsize * 1024; - printk(BIOS_DEBUG, "pci dom set re child is %p, confi %p tolmk %x\n", dev, device_configuration, tolmk); mc_dev = dev->link[0].children; - printk(BIOS_DEBUG, "child is %p\n", mc_dev); if (mc_dev) { idx = 10; ram_resource(dev, idx++, 0, tolmk);