[LinuxBIOS] r387 - in LinuxBIOSv3/arch/x86: . geodelx
svn at openbios.org
svn at openbios.org
Wed Jun 27 23:07:10 CEST 2007
Author: stepan
Date: 2007-06-27 23:07:10 +0200 (Wed, 27 Jun 2007)
New Revision: 387
Added:
LinuxBIOSv3/arch/x86/geodelx/geodelx.c
LinuxBIOSv3/arch/x86/geodelx/stage0.S
Removed:
LinuxBIOSv3/arch/x86/geodelx.c
LinuxBIOSv3/arch/x86/stage0_amd_geodelx.S
Modified:
LinuxBIOSv3/arch/x86/Makefile
Log:
make cpu code future proof
Signed-off-by: Stefan Reinauer <stepan at coresystems.de>
Acked-by: Ronald G. Minnich <rminnich at gmail.com>
Modified: LinuxBIOSv3/arch/x86/Makefile
===================================================================
--- LinuxBIOSv3/arch/x86/Makefile 2007-06-27 21:01:01 UTC (rev 386)
+++ LinuxBIOSv3/arch/x86/Makefile 2007-06-27 21:07:10 UTC (rev 387)
@@ -83,7 +83,7 @@
STAGE0_CAR_OBJ = stage0_i586.o
else
ifeq ($(CONFIG_CPU_AMD_GEODELX),y)
- STAGE0_CAR_OBJ = stage0_amd_geodelx.o
+ STAGE0_CAR_OBJ = geodelx/stage0.o
else
STAGE0_CAR_OBJ = stage0_i586.o
endif
@@ -181,4 +181,13 @@
$(Q)printf " AS $(subst $(shell pwd)/,,$(@))\n"
$(Q)$(AS) $(obj)/arch/x86/stage0_asm.s -o $@
+$(obj)/arch/x86/geodelx/stage0.o: $(src)/arch/x86/geodelx/stage0.S
+ $(Q)mkdir -p $(obj)/arch/x86/geodelx
+ $(Q)printf " CC $(subst $(shell pwd)/,,$(@))\n"
+ $(Q)$(CC) -E $(LINUXBIOSINCLUDE) $< \
+ -o $(obj)/arch/x86/stage0_asm.s -DBOOTBLK=0x1f00 \
+ -DRESRVED=0xf0 -DDATE=\"`date +%Y/%m/%d`\"
+ $(Q)printf " AS $(subst $(shell pwd)/,,$(@))\n"
+ $(Q)$(AS) $(obj)/arch/x86/stage0_asm.s -o $@
+
endif
Copied: LinuxBIOSv3/arch/x86/geodelx/geodelx.c (from rev 386, LinuxBIOSv3/arch/x86/geodelx.c)
===================================================================
--- LinuxBIOSv3/arch/x86/geodelx/geodelx.c (rev 0)
+++ LinuxBIOSv3/arch/x86/geodelx/geodelx.c 2007-06-27 21:07:10 UTC (rev 387)
@@ -0,0 +1,580 @@
+/*
+ * This file is part of the LinuxBIOS project.
+ *
+ * Copyright (C) 2006 Indrek Kruusa <indrek.kruusa at artecdesign.ee>
+ * Copyright (C) 2006 Ronald G. Minnich <rminnich at gmail.com>
+ * 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 <device/device.h>
+#include <device/pci.h>
+#include <string.h>
+#include <msr.h>
+#include <io.h>
+#include <amd_geodelx.h>
+#include <spd.h>
+
+/* all these functions used to be in a lot of fiddly little files. To
+ * make it easier to find functions, we are merging them here. This
+ * file is our first real cpu-specific support file and should serve
+ * as a model for v3 cpu-specific support. So, warning, you might
+ * think it makes sense to split this file up, but we've tried that,
+ * and it sucks.
+ */
+
+/**
+ * geodelx_msr_init Set up Geode LX registers for sane behaviour. Set
+ * all low memory (under 1MB) to write back. Do some setup for cache
+ * as ram as well.
+ */
+void geodelx_msr_init(void)
+{
+ msr_t msr;
+ /* Setup access to the cache for under 1MB. */
+ msr.hi = 0x24fffc02;
+ msr.lo = 0x1000A000; /* 0-A0000 write back */
+ wrmsr(CPU_RCONF_DEFAULT, msr);
+
+ msr.hi = 0x0; /* write back */
+ msr.lo = 0x0;
+ wrmsr(CPU_RCONF_A0_BF, msr);
+ wrmsr(CPU_RCONF_C0_DF, msr);
+ wrmsr(CPU_RCONF_E0_FF, msr);
+
+ /* Setup access to the cache for under 640K. Note MC not setup yet. */
+ msr.hi = 0x20000000;
+ msr.lo = 0xfff80;
+ wrmsr(MSR_GLIU0 + 0x20, msr);
+
+ msr.hi = 0x20000000;
+ msr.lo = 0x80fffe0;
+ wrmsr(MSR_GLIU0 + 0x21, msr);
+
+ msr.hi = 0x20000000;
+ msr.lo = 0xfff80;
+ wrmsr(MSR_GLIU1 + 0x20, msr);
+
+ msr.hi = 0x20000000;
+ msr.lo = 0x80fffe0;
+ wrmsr(MSR_GLIU1 + 0x21, msr);
+
+}
+
+
+/**
+ * start_time1 Starts Timer 1 for port 61 use. FIXME try to figure
+ * out what these values mean.
+ */
+void start_timer1(void)
+{
+ outb(0x56, 0x43);
+ outb(0x12, 0x41);
+}
+
+/**
+ * system_preinit Very early initialization needed for almost
+ * everything else. Currently, all we do is start timer1.
+ */
+void system_preinit(void)
+{
+ start_timer1();
+}
+
+/* cpu bug management */
+/**
+ *
+ * pci_deadlock Bugtool #465 and #609 PCI cache deadlock There is
+ * also fix code in cache and PCI functions. This bug is very is
+ * pervasive.
+ *
+ */
+static void pci_deadlock(void)
+{
+ msr_t msr;
+
+ /*
+ * forces serialization of all load misses. Setting this bit prevents the
+ * DM pipe from backing up if a read request has to be held up waiting
+ * for PCI writes to complete.
+ */
+ msr = rdmsr(CPU_DM_CONFIG0);
+ msr.lo |= DM_CONFIG0_LOWER_MISSER_SET;
+ wrmsr(CPU_DM_CONFIG0, msr);
+
+ /* write serialize memory hole to PCI. Need to unWS when something is
+ * shadowed regardless of cachablility.
+ */
+ msr.lo = 0x021212121;
+ msr.hi = 0x021212121;
+ wrmsr(CPU_RCONF_A0_BF, msr);
+ wrmsr(CPU_RCONF_C0_DF, msr);
+ wrmsr(CPU_RCONF_E0_FF, msr);
+}
+
+/** disable_memory_reorder PBZ 3659: The MC reordered transactions
+ * incorrectly and breaks coherency. Disable reording and take a
+ * potential performance hit. This is safe to do here and not in
+ * MC init since there is nothing to maintain coherency with and
+ * the cache is not enabled yet.
+ */
+/****************************************************************************/
+static void disable_memory_reorder(void)
+{
+ msr_t msr;
+
+ msr = rdmsr(MC_CF8F_DATA);
+ msr.hi |= CF8F_UPPER_REORDER_DIS_SET;
+ wrmsr(MC_CF8F_DATA, msr);
+}
+
+/**
+ * Fix up register settings to manage known CPU bugs. For cpu
+ * version C3. Should be the only released version
+ */
+void cpu_bug(void)
+{
+ pci_deadlock();
+ disable_memory_reorder();
+ printk(BIOS_DEBUG, "Done cpubug fixes \n");
+}
+
+/**
+ * Reset the phase locked loop hardware. After power on as part of
+ * this operation, we have to set the clock hardware and reboot. Thus,
+ * we have to know if we have been here before. To do this, we use the
+ * RSTPLL_LOWER_SWFLAGS_SHIFT flag in the msrGlcpSysRstpll. Also, the
+ * clocks can either be configured via passed-in parameters or
+ * hardware straps. Once set, we yank the hardware reset line and
+ * hlt. We should never reach the hlt, but one never knows.
+ *
+ * @param manualconf If non-zero, use passed-in parameters to
+ * determine how to configure pll -- manual or automagic.
+ * If manual, use passed-in parameters pll_hi and pll_lo
+ * @param pll_hi value to use for the high 32 bits of the pll msr
+ * @param pll_lo value to use for the low 32 bits of the pll msr
+ */
+void pll_reset(int manualconf, u32 pll_hi, u32 pll_lo)
+{
+ msr_t msrGlcpSysRstpll;
+
+ msrGlcpSysRstpll = rdmsr(GLCP_SYS_RSTPLL);
+
+ printk(BIOS_DEBUG,
+ "_MSR GLCP_SYS_RSTPLL (%08x) value is: %08x:%08x\n", msrGlcpSysRstpll.hi, msrGlcpSysRstpll.lo);
+ post_code(POST_PLL_INIT);
+
+ if (!(msrGlcpSysRstpll.lo & (1 << RSTPLL_LOWER_SWFLAGS_SHIFT))) {
+ printk(BIOS_DEBUG,"Configuring PLL\n");
+ if (manualconf) {
+ post_code(POST_PLL_MANUAL);
+ /* CPU and GLIU mult/div (GLMC_CLK = GLIU_CLK / 2) */
+ msrGlcpSysRstpll.hi = pll_hi;
+
+ /* Hold Count - how long we will sit in reset */
+ msrGlcpSysRstpll.lo = pll_lo;
+ } else {
+ /*automatic configuration (straps) */
+ post_code(POST_PLL_STRAP);
+ msrGlcpSysRstpll.lo &=
+ ~(0xFF << RSTPPL_LOWER_HOLD_COUNT_SHIFT);
+ msrGlcpSysRstpll.lo |=
+ (0xDE << RSTPPL_LOWER_HOLD_COUNT_SHIFT);
+ msrGlcpSysRstpll.lo &=
+ ~(RSTPPL_LOWER_COREBYPASS_SET |
+ RSTPPL_LOWER_MBBYPASS_SET);
+ msrGlcpSysRstpll.lo |=
+ RSTPPL_LOWER_COREPD_SET | RSTPPL_LOWER_CLPD_SET;
+ }
+ /* Use SWFLAGS to remember: "we've already been here" */
+ msrGlcpSysRstpll.lo |= (1 << RSTPLL_LOWER_SWFLAGS_SHIFT);
+
+ /* "reset the chip" value */
+ msrGlcpSysRstpll.lo |= RSTPPL_LOWER_CHIP_RESET_SET;
+ wrmsr(GLCP_SYS_RSTPLL, msrGlcpSysRstpll);
+
+ /* You should never get here..... The chip has reset. */
+ printk(BIOS_EMERG,"CONFIGURING PLL FAILURE -- HALT\n");
+ post_code(POST_PLL_RESET_FAIL);
+ __asm__ __volatile__("hlt\n");
+
+ }
+ printk(BIOS_DEBUG, "Done pll_reset\n");
+ return;
+}
+
+
+/**
+ * Return the CPU clock rate. Rates in this system are always returned
+ * as multkiples of 33 Mhz.
+ *
+ */
+u32 cpu_speed(void)
+{
+ u32 speed;
+ msr_t msr;
+
+ msr = rdmsr(GLCP_SYS_RSTPLL);
+ speed = ((((msr.hi >> RSTPLL_UPPER_CPUMULT_SHIFT) & 0x1F) + 1) * 333) / 10;
+ if ((((((msr.hi >> RSTPLL_UPPER_CPUMULT_SHIFT) & 0x1F) + 1) * 333) % 10) > 5) {
+ ++speed;
+ }
+ return (speed);
+}
+
+/**
+ * Return the Geode Link clock rate. Rates in this system are always
+ * returned as multkiples of 33 Mhz.
+ *
+ */
+u32 geode_link_speed(void)
+{
+ unsigned int speed;
+ msr_t msr;
+
+ msr = rdmsr(GLCP_SYS_RSTPLL);
+ speed = ((((msr.hi >> RSTPLL_UPPER_GLMULT_SHIFT) & 0x1F) + 1) * 333) / 10;
+ if ((((((msr.hi >> RSTPLL_UPPER_GLMULT_SHIFT) & 0x1F) + 1) * 333) % 10) > 5) {
+ ++speed;
+ }
+ return (speed);
+}
+
+
+/**
+ * Return the PCI bus clock rate. Rates in this system are always
+ * returned as multkiples of 33 Mhz.
+ *
+ */
+u32 pci_speed(void)
+{
+ msr_t msr;
+
+ msr = rdmsr(GLCP_SYS_RSTPLL);
+ if (msr.hi & (1 << RSTPPL_LOWER_PCISPEED_SHIFT)) {
+ return (66);
+ } else {
+ return (33);
+ }
+}
+
+/**
+ * set_delay_control. This is Black Magic DRAM timing
+ * juju(http://www.thefreedictionary.com/juju) Dram delay depends on
+ * cpu clock, memory bus clock, memory bus loading, memory bus
+ * termination, your middle initial (ha! caught you!), Geode Link
+ * clock rate, and dram timing specifications. From this the code
+ * computes a number which is "known to work". No, hardware is not an
+ * exact science. And, finally, if an FS2 (jtag debugger) is hooked
+ * up, then just don't to anything. This code was written by a master
+ * of the Dark Arts at AMD and should not be modified in any way.
+ *
+ * @param num_banks How many banks of DRAM there are
+ * @param dimm0 DIMM 0 SMBus address
+ * @param dimm1 DIMM 1 SMBus address
+ * @param sram_width Data width of the SDRAM
+ */
+
+void set_delay_control(u8 dimm0, u8 dimm1)
+{
+ u32 msrnum, glspeed;
+ u8 spdbyte0, spdbyte1;
+ int numdimms = 0;
+ msr_t msr;
+
+ glspeed = geode_link_speed();
+
+ /* fix delay controls for DM and IM arrays */
+ msrnum = CPU_BC_MSS_ARRAY_CTL0;
+ msr.hi = 0;
+ msr.lo = 0x2814D352;
+ wrmsr(msrnum, msr);
+
+ msrnum = CPU_BC_MSS_ARRAY_CTL1;
+ msr.hi = 0;
+ msr.lo = 0x1068334D;
+ wrmsr(msrnum, msr);
+
+ msrnum = CPU_BC_MSS_ARRAY_CTL2;
+ msr.hi = 0x00000106;
+ msr.lo = 0x83104104;
+ wrmsr(msrnum, msr);
+
+ msrnum = GLCP_FIFOCTL;
+ msr = rdmsr(msrnum);
+ msr.hi = 0x00000005;
+ wrmsr(msrnum, msr);
+
+ /* Enable setting */
+ msrnum = CPU_BC_MSS_ARRAY_CTL_ENA;
+ msr.hi = 0;
+ msr.lo = 0x00000001;
+ wrmsr(msrnum, msr);
+
+ /* Debug Delay Control Setup Check
+ *
+ * Leave it alone if it has been setup. FS2 or something is here.
+ */
+ msrnum = GLCP_DELAY_CONTROLS;
+ msr = rdmsr(msrnum);
+ if (msr.lo & ~(0x7C0)) {
+ return;
+ }
+
+ /*
+ * Delay Controls based on DIMM loading. UGH!
+ * # of Devices = Module Width (SPD6) / Device Width(SPD13) * Physical Banks(SPD5)
+ * Note - We only support module width of 64.
+ */
+ spdbyte0 = smbus_read_byte(dimm0, SPD_PRIMARY_SDRAM_WIDTH);
+ if (spdbyte0 != 0xFF) {
+ numdimms++;
+ spdbyte0 = (unsigned char)64 / spdbyte0 *
+ (unsigned char)(smbus_read_byte(dimm0, SPD_NUM_DIMM_BANKS));
+ } else {
+ spdbyte0 = 0;
+ }
+
+ spdbyte1 = smbus_read_byte(dimm1, SPD_PRIMARY_SDRAM_WIDTH);
+ if (spdbyte1 != 0xFF) {
+ numdimms++;
+ spdbyte1 = (unsigned char)64 / spdbyte1 *
+ (unsigned char)(smbus_read_byte(dimm1, SPD_NUM_DIMM_BANKS));
+ } else {
+ spdbyte1 = 0;
+ }
+
+/* The current thinking. Subject to change...
+
+; "FUTURE ROBUSTNESS" PROPOSAL
+; ----------------------------
+; DIMM Max MBUS MC 0x2000001A bits 26:24
+;DIMMs devices Frequency MCP 0x4C00000F Setting vvv
+;----- ------- --------- ---------------------- ----------
+;1 4 400MHz 0x82*100FF 0x56960004 4
+;1 8 400MHz 0x82*100AA 0x56960004 4
+;1 16 400MHz 0x82*10055 0x56960004 4
+;
+;2 4,4 400MHz 0x82710000 0x56960004 4
+;2 8,8 400MHz 0xC27100A5 0x56960004 4 *** OUT OF PUBLISHED ENVELOPE ***
+;
+;2 16,4 >333 0xB27100A5 0x56960004 4 *** OUT OF PUBLISHED ENVELOPE ***
+;2 16,8 >333 0xB27100A5 0x56960004 4 *** OUT OF PUBLISHED ENVELOPE ***
+;2 16,16 >333 0xB2710000 0x56960004 4 *** OUT OF PUBLISHED ENVELOPE ***
+;
+;1 4 <=333MHz 0x83*100FF 0x56960004 3
+;1 8 <=333MHz 0x83*100AA 0x56960004 3
+;1 16 <=333MHz 0x83*100AA 0x56960004 3
+;
+;2 4,4 <=333MHz 0x837100A5 0x56960004 3
+;2 8,8 <=333MHz 0x937100A5 0x56960004 3
+;
+;2 16,4 <=333MHz 0xB37100A5 0x56960004 3 *** OUT OF PUBLISHED ENVELOPE ***
+;2 16,8 <=333MHz 0xB37100A5 0x56960004 3 *** OUT OF PUBLISHED ENVELOPE ***
+;2 16,16 <=333MHz 0xB37100A5 0x56960004 3 *** OUT OF PUBLISHED ENVELOPE ***
+;=========================================================================
+;* - Bit 55 (disable SDCLK 1,3,5) should be set if there is a single DIMM in slot 0,
+; but it should be clear for all 2 DIMM settings and if a single DIMM is in slot 1.
+; Bits 54:52 should always be set to '111'.
+
+;No VTT termination
+;-------------------------------------
+;ADDR/CTL have 22 ohm series R
+;DQ/DQM/DQS have 33 ohm series R
+;
+; DIMM Max MBUS
+;DIMMs devices Frequency MCP 0x4C00000F Setting
+;----- ------- --------- ----------------------
+;1 4 400MHz 0xF2F100FF 0x56960004 4 The MC changes improve Salsa.
+;1 8 400MHz 0xF2F100FF 0x56960004 4 Delay controls no real change,
+;1 4 <=333MHz 0xF2F100FF 0x56960004 3 just fixing typo in left side.
+;1 8 <=333MHz 0xF2F100FF 0x56960004 3
+;1 16 <=333MHz 0xF2F100FF 0x56960004 3
+*/
+ msr.hi = msr.lo = 0;
+
+ if (spdbyte0 == 0 || spdbyte1 == 0) {
+ /* one dimm solution */
+ if (spdbyte1 == 0) {
+ msr.hi |= 0x000800000;
+ }
+ spdbyte0 += spdbyte1;
+ if (spdbyte0 > 8) {
+ /* large dimm */
+ if (glspeed < 334) {
+ msr.hi |= 0x0837100AA;
+ msr.lo |= 0x056960004;
+ } else {
+ msr.hi |= 0x082710055;
+ msr.lo |= 0x056960004;
+ }
+ } else if (spdbyte0 > 4) {
+ /* medium dimm */
+ if (glspeed < 334) {
+ msr.hi |= 0x0837100AA;
+ msr.lo |= 0x056960004;
+ } else {
+ msr.hi |= 0x0827100AA;
+ msr.lo |= 0x056960004;
+ }
+ } else {
+ /* small dimm */
+ if (glspeed < 334) {
+ msr.hi |= 0x0837100FF;
+ msr.lo |= 0x056960004;
+ } else {
+ msr.hi |= 0x0827100FF;
+ msr.lo |= 0x056960004;
+ }
+ }
+ } else {
+ /* two dimm solution */
+ spdbyte0 += spdbyte1;
+ if (spdbyte0 > 24) {
+ /* huge dimms */
+ if (glspeed < 334) {
+ msr.hi |= 0x0B37100A5;
+ msr.lo |= 0x056960004;
+ } else {
+ msr.hi |= 0x0B2710000;
+ msr.lo |= 0x056960004;
+ }
+ } else if (spdbyte0 > 16) {
+ /* large dimms */
+ if (glspeed < 334) {
+ msr.hi |= 0x0B37100A5;
+ msr.lo |= 0x056960004;
+ } else {
+ msr.hi |= 0x0B27100A5;
+ msr.lo |= 0x056960004;
+ }
+ } else if (spdbyte0 >= 8) {
+ /* medium dimms */
+ if (glspeed < 334) {
+ msr.hi |= 0x0937100A5;
+ msr.lo |= 0x056960004;
+ } else {
+ msr.hi |= 0x0C27100A5;
+ msr.lo |= 0x056960004;
+ }
+ } else {
+ /* small dimms */
+ if (glspeed < 334) {
+ msr.hi |= 0x0837100A5;
+ msr.lo |= 0x056960004;
+ } else {
+ msr.hi |= 0x082710000;
+ msr.lo |= 0x056960004;
+ }
+ }
+ }
+ wrmsr(GLCP_DELAY_CONTROLS, msr);
+ return;
+}
+
+/**
+ * cpu_reg_init. All cpu register settings, here in one place, and
+ * done in the proper order.
+ *
+ * @param debug_clock_disable Disable the debug clock to save power. Currently ignored, but we need to
+ * pick this up from a CMOS setting in future.
+ * @param dimm0 SMBus address of dimm0 (mainboard dependent)
+ * @param dimm1 SMBus address of dimm1 (mainboard dependent)
+ */
+void cpu_reg_init(int debug_clock_disable, u8 dimm0, u8 dimm1)
+{
+ int msrnum;
+ msr_t msr;
+
+ /* Castle 2.0 BTM periodic sync period. */
+ /* [40:37] 1 sync record per 256 bytes */
+ msrnum = CPU_PF_CONF;
+ msr = rdmsr(msrnum);
+ msr.hi |= (0x8 << 5);
+ wrmsr(msrnum, msr);
+
+ /*
+ ; Castle performance setting.
+ ; Enable Quack for fewer re-RAS on the MC
+ */
+ msrnum = GLIU0_ARB;
+ msr = rdmsr(msrnum);
+ msr.hi &= ~ARB_UPPER_DACK_EN_SET;
+ msr.hi |= ARB_UPPER_QUACK_EN_SET;
+ wrmsr(msrnum, msr);
+
+ msrnum = GLIU1_ARB;
+ msr = rdmsr(msrnum);
+ msr.hi &= ~ARB_UPPER_DACK_EN_SET;
+ msr.hi |= ARB_UPPER_QUACK_EN_SET;
+ wrmsr(msrnum, msr);
+
+ /* GLIU port active enable, limit south pole masters (AES and PCI) to one outstanding transaction. */
+ msrnum = GLIU1_PORT_ACTIVE;
+ msr = rdmsr(msrnum);
+ msr.lo &= ~0x880;
+ wrmsr(msrnum, msr);
+
+ /* Set the Delay Control in GLCP */
+ set_delay_control(dimm0, dimm1);
+
+ /* Enable RSDC */
+ msrnum = CPU_AC_SMM_CTL;
+ msr = rdmsr(msrnum);
+ msr.lo |= SMM_INST_EN_SET;
+ wrmsr(msrnum, msr);
+
+ /* FPU imprecise exceptions bit */
+ msrnum = CPU_FPU_MSR_MODE;
+ msr = rdmsr(msrnum);
+ msr.lo |= FPU_IE_SET;
+ wrmsr(msrnum, msr);
+
+ /* Power Savers (Do after BIST) */
+ /* Enable Suspend on HLT & PAUSE instructions */
+ msrnum = CPU_XC_CONFIG;
+ msr = rdmsr(msrnum);
+ msr.lo |= XC_CONFIG_SUSP_ON_HLT | XC_CONFIG_SUSP_ON_PAUSE;
+ wrmsr(msrnum, msr);
+
+ /* Enable SUSP and allow TSC to run in Suspend (keep speed detection happy) */
+ msrnum = CPU_BC_CONF_0;
+ msr = rdmsr(msrnum);
+ msr.lo |= TSC_SUSP_SET | SUSP_EN_SET;
+ msr.lo &= 0x0F0FFFFFF;
+ msr.lo |= 0x002000000; /* PBZ213: Set PAUSEDLY = 2 */
+ wrmsr(msrnum, msr);
+
+ /* Disable the debug clock to save power. */
+ /* NOTE: leave it enabled for fs2 debug */
+ if (debug_clock_disable && 0){
+ msrnum = GLCP_DBGCLKCTL;
+ msr.hi = 0;
+ msr.lo = 0;
+ wrmsr(msrnum, msr);
+ }
+
+ /* Setup throttling delays to proper mode if it is ever enabled. */
+ msrnum = GLCP_TH_OD;
+ msr.hi = 0;
+ msr.lo = 0x00000603C;
+ wrmsr(msrnum, msr);
+ /* fix cpu bugs */
+#warning testing fixing bugs in initram
+ cpu_bug();
+}
Copied: LinuxBIOSv3/arch/x86/geodelx/stage0.S (from rev 385, LinuxBIOSv3/arch/x86/stage0_amd_geodelx.S)
===================================================================
--- LinuxBIOSv3/arch/x86/geodelx/stage0.S (rev 0)
+++ LinuxBIOSv3/arch/x86/geodelx/stage0.S 2007-06-27 21:07:10 UTC (rev 387)
@@ -0,0 +1,443 @@
+##
+## This file is part of the LinuxBIOS project.
+##
+## Copyright (C) 2000,2007 Ronald G. Minnich <rminnich at gmail.com>
+## Copyright (C) 2005 Eswar Nallusamy, LANL
+## Copyright (C) 2005 Tyan
+## (Written by Yinghai Lu <yhlu at tyan.com> for Tyan)
+## Copyright (C) 2007 coresystems GmbH
+## (Written by Stefan Reinauer <stepan at coresystems.de> for coresystems GmbH)
+## 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; version 2 of the License.
+##
+## 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
+##
+
+/* Init code - Switch CPU to protected mode and enable Cache-as-Ram. */
+
+#include "../macros.h"
+#include <amd_geodelx.h>
+
+/* This is where the DCache will be mapped and be used as stack. It would be
+ * cool if it was the same base as LinuxBIOS normal stack.
+ */
+#define LX_STACK_BASE DCACHE_RAM_BASE
+#define LX_STACK_END LX_STACK_BASE+(DCACHE_RAM_SIZE-4)
+
+#define LX_NUM_CACHELINES 0x080 /* There are 128 lines per way. */
+#define LX_CACHELINE_SIZE 0x020 /* There are 32 bytes per line. */
+#define LX_CACHEWAY_SIZE (LX_NUM_CACHELINES * LX_CACHELINE_SIZE)
+#define CR0_CD 0x40000000 /* Bit 30 = Cache Disable */
+#define CR0_NW 0x20000000 /* Bit 29 = Not Write Through */
+
+#define ROM_CODE_SEG 0x08
+#define ROM_DATA_SEG 0x10
+
+#define CACHE_RAM_CODE_SEG 0x18
+#define CACHE_RAM_DATA_SEG 0x20
+
+ .code16
+ .globl _stage0
+_stage0:
+ cli
+
+ /* Save the BIST result. */
+ movl %eax, %ebp;
+
+ /* Thanks to kmliu at sis.com.tw for this TLB fix. */
+ /* IMMEDIATELY invalidate the translation lookaside buffer before
+ * executing any further code. Even though paging is disabled we
+ * could still get false address translations due to the TLB if we
+ * didn't invalidate it.
+ */
+
+ xorl %eax, %eax
+ movl %eax, %cr3 /* Invalidate TLB */
+
+ /* Switch to protected mode. */
+
+ /* NOTE: With GNU assembler version 2.15.94.0.2.2 (i386-redhat-linux)
+ * using BFD version 2.15.94.0.2.2 20041220 this works fine without
+ * all the ld hackery and so on. So leave it as is with this comment.
+ */
+
+ data32 lgdt %cs:gdtptr
+
+ movl %cr0, %eax
+ andl $0x7FFAFFD1, %eax /* PG, AM, WP, NE, TS, EM, MP = 0 */
+ orl $0x60000001, %eax /* CD, NW, PE = 1 */
+ movl %eax, %cr0
+
+ /* Restore BIST result. */
+ movl %ebp, %eax
+
+ // port80_post(0x23)
+
+ /* Now we are in protected mode. Jump to a 32 bit code segment. */
+ data32 ljmp $ROM_CODE_SEG, $protected_stage0
+ /* I am leaving this weird jump in here in the event that future gas
+ * bugs force it to be used.
+ */
+ #.byte 0x66
+ .code32
+ #ljmp $ROM_CODE_SEG, $protected_stage0
+
+ #.code16
+ .align 4
+ .globl gdt16
+gdt16 = . - _stage0
+gdt16x:
+ .word gdt16xend - gdt16x -1 /* Compute the table limit. */
+ .long gdt16x
+ .word 0
+
+ /* selgdt 0x08, flat code segment */
+ .word 0xffff, 0x0000
+ .byte 0x00, 0x9b, 0xcf, 0x00
+
+ /* selgdt 0x10, flat data segment */
+ .word 0xffff, 0x0000
+ .byte 0x00, 0x93, 0xcf, 0x00
+gdt16xend:
+
+ /* From now on we are 32bit. */
+ .code32
+
+ /* We have two gdts where we could have one. That is ok.
+ *
+ * Let's not worry about this -- optimizing gdt is pointless since
+ * we're only in it for a little bit.
+ *
+ * BTW note the trick below: The GDT points to ITSELF, and the first
+ * good descriptor is at offset 8. So you word-align the table, and
+ * then because you chose 8, you get a nice 64-bit aligned GDT entry,
+ * which is good as this is the size of the entry.
+ *
+ * Just in case you ever wonder why people do this.
+ */
+ .align 4
+ .globl gdtptr
+ .globl gdt_limit
+gdt_limit = gdt_end - gdt - 1 /* Compute the table limit. */
+
+gdt:
+gdtptr:
+ .word gdt_end - gdt -1 /* Compute the table limit. */
+ .long gdt /* We know the offset. */
+ .word 0
+
+ /* selgdt 0x08, flat code segment */
+ .word 0xffff, 0x0000
+ .byte 0x00, 0x9b, 0xcf, 0x00
+
+ /* selgdt 0x10, flat data segment */
+ .word 0xffff, 0x0000
+ .byte 0x00, 0x93, 0xcf, 0x00
+
+ /* selgdt 0x18, flat code segment for CAR */
+ .word 0xffff, 0x0000
+ .byte 0x00, 0x9b, 0xcf, 0x00
+
+ /* selgdt 0x20, flat data segment for CAR */
+ .word 0xffff, 0x0000
+ .byte 0x00, 0x93, 0xcf, 0x00
+gdt_end:
+
+ /*
+ * When we come here we are in protected mode. We expand the stack
+ * and copy the data segment from ROM to the memory.
+ *
+ * After that, we call the chipset bootstrap routine that
+ * does what is left of the chipset initialization.
+ *
+ * NOTE: Aligned to 4 so that we are sure that the prefetch
+ * cache will be reloaded.
+ */
+
+ .align 4
+ .globl protected_stage0
+protected_stage0:
+ // This code was used by v2. TODO
+ lgdt %cs:gdtptr
+ ljmp $ROM_CODE_SEG, $__protected_stage0
+
+.globl __protected_stage0
+__protected_stage0:
+ /* Save the BIST value. */
+ movl %eax, %ebp
+
+ port80_post(0x01)
+
+ movw $ROM_DATA_SEG, %ax
+ movw %ax, %ds
+ movw %ax, %es
+ movw %ax, %ss
+ movw %ax, %fs
+ movw %ax, %gs
+
+ /* Restore the BIST value to %eax. */
+ movl %ebp, %eax
+
+.align 4
+ /* Here begins CAR support. */
+ /* This particular code is straight from LinuxBIOS V2. */
+
+ /* DCacheSetup: Setup data cache for use as RAM for a stack. */
+DCacheSetup:
+
+ invd
+ /* Set cache properties. */
+ movl $CPU_RCONF_DEFAULT, %ecx
+ rdmsr
+ /* 1MB system memory in write back 1|00100|00. */
+ movl $0x010010000, %eax
+ wrmsr
+
+ /* In LX DCDIS is set after POR which disables the cache..., clear
+ * this bit.
+ */
+ movl CPU_DM_CONFIG0,%ecx
+ rdmsr
+ /* TODO: Make consistent with i$ init, either whole reg = 0, or just
+ * this bit...
+ */
+ andl $(~(DM_CONFIG0_LOWER_DCDIS_SET)), %eax
+ wrmsr
+
+ /* Get cache timing params from BIOS config data locations and apply. */
+ /* Fix delay controls for DM and IM arrays. */
+ movl $CPU_BC_MSS_ARRAY_CTL0, %ecx
+ xorl %edx, %edx
+ movl $0x2814D352, %eax
+ wrmsr
+
+ movl $CPU_BC_MSS_ARRAY_CTL1, %ecx
+ xorl %edx, %edx
+ movl $0x1068334D, %eax
+ wrmsr
+
+ movl $CPU_BC_MSS_ARRAY_CTL2, %ecx
+ movl $0x00000106, %edx
+ movl $0x83104104, %eax
+ wrmsr
+
+ movl $GLCP_FIFOCTL, %ecx
+ rdmsr
+ movl $0x00000005, %edx
+ wrmsr
+
+ /* Enable setting. */
+ movl $CPU_BC_MSS_ARRAY_CTL_ENA, %ecx
+ xorl %edx, %edx
+ movl $0x01, %eax
+ wrmsr
+
+ /* Get cleaned up. */
+ xorl %edi, %edi
+ xorl %esi, %esi
+ xorl %ebp, %ebp
+
+ /* DCache Ways0 through Ways7 will be tagged for
+ * LX_STACK_BASE + DCACHE_RAM_SIZE for holding stack.
+ */
+ /* Remember, there is NO stack yet... */
+
+ /* Tell cache we want to fill Way 0 starting at the top. */
+ xorl %edx, %edx
+ xorl %eax, %eax
+ movl $CPU_DC_INDEX, %ecx
+ wrmsr
+
+ /* Startaddress for tag of Way0: ebp will hold the incrementing
+ * address. dont destroy!
+ */
+ movl $LX_STACK_BASE, %ebp /* Init to start address. */
+ /* Set valid bit and tag for this Way (B[31:12] : Cache tag value for
+ * line/way curr. selected by CPU_DC_INDEX.
+ */
+ orl $1, %ebp
+
+ /* Start tag Ways 0 with 128 lines with 32 bytes each: edi will hold
+ * the line counter. dont destroy!
+ */
+ movl $LX_NUM_CACHELINES, %edi
+
+DCacheSetupFillWay:
+ /* Fill with dummy data: zero it so we can tell it from PCI memory
+ * space (returns FFs).
+ */
+ /* We will now store a line (32 bytes = 4 x 8 bytes = 4 quad-words). */
+ movw $0x04, %si
+ xorl %edx, %edx
+ xorl %eax, %eax
+ movl $CPU_DC_DATA, %ecx
+
+DCacheSetup_quadWordLoop:
+ wrmsr
+ decw %si
+ jnz DCacheSetup_quadWordLoop
+
+ /* Set the tag for this line, need to do this for every new cache
+ * line to validate it!
+ */
+ /* Accessing CPU_DC_TAG_I makes the LINE field in CPU_DC_INDEX
+ * increment and thus continue in the next cache line...
+ */
+ xorl %edx, %edx
+ movl %ebp, %eax
+ movl $CPU_DC_TAG, %ecx
+ wrmsr
+
+ /* Switch to next line. Lines are in Bits10:4. */
+ /* When index is crossing 0x7F -> 0x80 writing a RSVD bit as 0x80 is
+ * not a valid CL anymore!
+ */
+ movl $CPU_DC_INDEX, %ecx
+ rdmsr
+ /* TODO: Probably would be more elegant to calculate this from
+ * counter var edi...
+ */
+ addl $0x010, %eax
+ wrmsr
+
+ decl %edi
+ jnz DCacheSetupFillWay
+
+ /* 1 Way has been filled, forward start address for next Way,
+ * terminate if we have reached end of desired address range.
+ */
+ addl $LX_CACHEWAY_SIZE, %ebp
+ cmpl $LX_STACK_END, %ebp
+ jge leave_DCacheSetup
+ movl $LX_NUM_CACHELINES, %edi
+
+ /* Switch to next way. */
+ movl $CPU_DC_INDEX, %ecx
+ rdmsr
+ addl $0x01, %eax
+ /* Let's be sure: reset line index Bits10:4. */
+ andl $0xFFFFF80F, %eax
+ wrmsr
+
+ jmp DCacheSetupFillWay
+
+leave_DCacheSetup:
+ xorl %edi, %edi
+ xorl %esi, %esi
+ xorl %ebp, %ebp
+
+ /* Disable the cache, but... DO NOT INVALIDATE the tags. */
+ /* Memory reads and writes will all hit in the cache. */
+ /* Cache updates and memory write-backs will not occur! */
+ movl %cr0, %eax
+ orl $(CR0_CD + CR0_NW), %eax /* Set the CD and NW bits. */
+ movl %eax, %cr0
+
+ /* Now point sp to the cached stack. */
+ /* The stack will be fully functional at this location. No system
+ * memory is required at all!
+ */
+ /* Set up the stack pointer. */
+ movl $LX_STACK_END, %eax
+ movl %eax, %esp
+
+ /* Test the stack. */
+ movl $0x0F0F05A5A, %edx
+ pushl %edx
+ popl %ecx
+ cmpl %ecx, %edx
+ je DCacheSetupGood
+ movb $0xC5, %al
+ outb %al, $0x80
+
+DCacheSetupBad:
+ hlt /* Issues */
+ jmp DCacheSetupBad
+
+DCacheSetupGood:
+ /* If you wanted to maintain the stack in memory you would need to
+ * set the tags as dirty so the wbinvd would push out the old stack
+ * contents to memory.
+ */
+ /* Clear the cache, the following code from crt0.S.lb will setup
+ * a new stack.
+ */
+ wbinvd
+
+ /* At this point, CAR should be working. */
+ movl $(LX_STACK_END), %eax
+ movl %eax, %esp
+
+ /* Load a different set of data segments. */
+ movw $CACHE_RAM_DATA_SEG, %ax
+ movw %ax, %ds
+ movw %ax, %es
+ movw %ax, %ss
+
+lout:
+ /* Restore the BIST result. */
+ movl %ebp, %eax
+ /* We need to set ebp? No need. */
+ movl %esp, %ebp
+ pushl %eax /* BIST */
+ call stage1_main
+ /* We will not go back. */
+
+fixed_mtrr_msr:
+ .long 0x250, 0x258, 0x259
+ .long 0x268, 0x269, 0x26A
+ .long 0x26B, 0x26C, 0x26D
+ .long 0x26E, 0x26F
+var_mtrr_msr:
+ .long 0x200, 0x201, 0x202, 0x203
+ .long 0x204, 0x205, 0x206, 0x207
+ .long 0x208, 0x209, 0x20A, 0x20B
+ .long 0x20C, 0x20D, 0x20E, 0x20F
+ .long 0x000 /* NULL, end of table */
+
+# Reset vector.
+
+/*
+ * RVECTOR: size of reset vector, default is 0x10
+ * RESRVED: size of vpd code, default is 0xf0
+ * BOOTBLK: size of bootblock code, default is 0x1f00 (8k-256b)
+ */
+
+SEGMENT_SIZE = 0x10000
+RVECTOR = 0x00010
+
+# Due to YET ANOTHER BUG in GNU bintools, you can NOT have a code16 here.
+# I think we should leave it this way forever, as the bugs come and
+# go -- and come again.
+# .code16
+# .section ".rom.text"
+.section ".reset", "ax"
+ .globl _resetjump
+_resetjump:
+ /* GNU bintools bugs again. This jumps to stage0 - 2. Sigh. */
+# jmp _stage0
+ .byte 0xe9
+ .int _stage0 - ( . + 2 )
+ /* Note: The above jump is hand coded to work around bugs in binutils.
+ * 5 bytes are used for a 3 byte instruction. This works because x86
+ * is little endian and allows us to use supported 32 bit relocations
+ * instead of the weird 16 bit relocations that binutils does not
+ * handle consistenly between versions because they are used so rarely.
+ */
+.byte 0
+
+# Date? ID string? We might want to put something else in here.
+.ascii DATE
+
+# Checksum.
+#.word 0
Deleted: LinuxBIOSv3/arch/x86/geodelx.c
===================================================================
--- LinuxBIOSv3/arch/x86/geodelx.c 2007-06-27 21:01:01 UTC (rev 386)
+++ LinuxBIOSv3/arch/x86/geodelx.c 2007-06-27 21:07:10 UTC (rev 387)
@@ -1,580 +0,0 @@
-/*
- * This file is part of the LinuxBIOS project.
- *
- * Copyright (C) 2006 Indrek Kruusa <indrek.kruusa at artecdesign.ee>
- * Copyright (C) 2006 Ronald G. Minnich <rminnich at gmail.com>
- * 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 <device/device.h>
-#include <device/pci.h>
-#include <string.h>
-#include <msr.h>
-#include <io.h>
-#include <amd_geodelx.h>
-#include <spd.h>
-
-/* all these functions used to be in a lot of fiddly little files. To
- * make it easier to find functions, we are merging them here. This
- * file is our first real cpu-specific support file and should serve
- * as a model for v3 cpu-specific support. So, warning, you might
- * think it makes sense to split this file up, but we've tried that,
- * and it sucks.
- */
-
-/**
- * geodelx_msr_init Set up Geode LX registers for sane behaviour. Set
- * all low memory (under 1MB) to write back. Do some setup for cache
- * as ram as well.
- */
-void geodelx_msr_init(void)
-{
- msr_t msr;
- /* Setup access to the cache for under 1MB. */
- msr.hi = 0x24fffc02;
- msr.lo = 0x1000A000; /* 0-A0000 write back */
- wrmsr(CPU_RCONF_DEFAULT, msr);
-
- msr.hi = 0x0; /* write back */
- msr.lo = 0x0;
- wrmsr(CPU_RCONF_A0_BF, msr);
- wrmsr(CPU_RCONF_C0_DF, msr);
- wrmsr(CPU_RCONF_E0_FF, msr);
-
- /* Setup access to the cache for under 640K. Note MC not setup yet. */
- msr.hi = 0x20000000;
- msr.lo = 0xfff80;
- wrmsr(MSR_GLIU0 + 0x20, msr);
-
- msr.hi = 0x20000000;
- msr.lo = 0x80fffe0;
- wrmsr(MSR_GLIU0 + 0x21, msr);
-
- msr.hi = 0x20000000;
- msr.lo = 0xfff80;
- wrmsr(MSR_GLIU1 + 0x20, msr);
-
- msr.hi = 0x20000000;
- msr.lo = 0x80fffe0;
- wrmsr(MSR_GLIU1 + 0x21, msr);
-
-}
-
-
-/**
- * start_time1 Starts Timer 1 for port 61 use. FIXME try to figure
- * out what these values mean.
- */
-void start_timer1(void)
-{
- outb(0x56, 0x43);
- outb(0x12, 0x41);
-}
-
-/**
- * system_preinit Very early initialization needed for almost
- * everything else. Currently, all we do is start timer1.
- */
-void system_preinit(void)
-{
- start_timer1();
-}
-
-/* cpu bug management */
-/**
- *
- * pci_deadlock Bugtool #465 and #609 PCI cache deadlock There is
- * also fix code in cache and PCI functions. This bug is very is
- * pervasive.
- *
- */
-static void pci_deadlock(void)
-{
- msr_t msr;
-
- /*
- * forces serialization of all load misses. Setting this bit prevents the
- * DM pipe from backing up if a read request has to be held up waiting
- * for PCI writes to complete.
- */
- msr = rdmsr(CPU_DM_CONFIG0);
- msr.lo |= DM_CONFIG0_LOWER_MISSER_SET;
- wrmsr(CPU_DM_CONFIG0, msr);
-
- /* write serialize memory hole to PCI. Need to unWS when something is
- * shadowed regardless of cachablility.
- */
- msr.lo = 0x021212121;
- msr.hi = 0x021212121;
- wrmsr(CPU_RCONF_A0_BF, msr);
- wrmsr(CPU_RCONF_C0_DF, msr);
- wrmsr(CPU_RCONF_E0_FF, msr);
-}
-
-/** disable_memory_reorder PBZ 3659: The MC reordered transactions
- * incorrectly and breaks coherency. Disable reording and take a
- * potential performance hit. This is safe to do here and not in
- * MC init since there is nothing to maintain coherency with and
- * the cache is not enabled yet.
- */
-/****************************************************************************/
-static void disable_memory_reorder(void)
-{
- msr_t msr;
-
- msr = rdmsr(MC_CF8F_DATA);
- msr.hi |= CF8F_UPPER_REORDER_DIS_SET;
- wrmsr(MC_CF8F_DATA, msr);
-}
-
-/**
- * Fix up register settings to manage known CPU bugs. For cpu
- * version C3. Should be the only released version
- */
-void cpu_bug(void)
-{
- pci_deadlock();
- disable_memory_reorder();
- printk(BIOS_DEBUG, "Done cpubug fixes \n");
-}
-
-/**
- * Reset the phase locked loop hardware. After power on as part of
- * this operation, we have to set the clock hardware and reboot. Thus,
- * we have to know if we have been here before. To do this, we use the
- * RSTPLL_LOWER_SWFLAGS_SHIFT flag in the msrGlcpSysRstpll. Also, the
- * clocks can either be configured via passed-in parameters or
- * hardware straps. Once set, we yank the hardware reset line and
- * hlt. We should never reach the hlt, but one never knows.
- *
- * @param manualconf If non-zero, use passed-in parameters to
- * determine how to configure pll -- manual or automagic.
- * If manual, use passed-in parameters pll_hi and pll_lo
- * @param pll_hi value to use for the high 32 bits of the pll msr
- * @param pll_lo value to use for the low 32 bits of the pll msr
- */
-void pll_reset(int manualconf, u32 pll_hi, u32 pll_lo)
-{
- msr_t msrGlcpSysRstpll;
-
- msrGlcpSysRstpll = rdmsr(GLCP_SYS_RSTPLL);
-
- printk(BIOS_DEBUG,
- "_MSR GLCP_SYS_RSTPLL (%08x) value is: %08x:%08x\n", msrGlcpSysRstpll.hi, msrGlcpSysRstpll.lo);
- post_code(POST_PLL_INIT);
-
- if (!(msrGlcpSysRstpll.lo & (1 << RSTPLL_LOWER_SWFLAGS_SHIFT))) {
- printk(BIOS_DEBUG,"Configuring PLL\n");
- if (manualconf) {
- post_code(POST_PLL_MANUAL);
- /* CPU and GLIU mult/div (GLMC_CLK = GLIU_CLK / 2) */
- msrGlcpSysRstpll.hi = pll_hi;
-
- /* Hold Count - how long we will sit in reset */
- msrGlcpSysRstpll.lo = pll_lo;
- } else {
- /*automatic configuration (straps) */
- post_code(POST_PLL_STRAP);
- msrGlcpSysRstpll.lo &=
- ~(0xFF << RSTPPL_LOWER_HOLD_COUNT_SHIFT);
- msrGlcpSysRstpll.lo |=
- (0xDE << RSTPPL_LOWER_HOLD_COUNT_SHIFT);
- msrGlcpSysRstpll.lo &=
- ~(RSTPPL_LOWER_COREBYPASS_SET |
- RSTPPL_LOWER_MBBYPASS_SET);
- msrGlcpSysRstpll.lo |=
- RSTPPL_LOWER_COREPD_SET | RSTPPL_LOWER_CLPD_SET;
- }
- /* Use SWFLAGS to remember: "we've already been here" */
- msrGlcpSysRstpll.lo |= (1 << RSTPLL_LOWER_SWFLAGS_SHIFT);
-
- /* "reset the chip" value */
- msrGlcpSysRstpll.lo |= RSTPPL_LOWER_CHIP_RESET_SET;
- wrmsr(GLCP_SYS_RSTPLL, msrGlcpSysRstpll);
-
- /* You should never get here..... The chip has reset. */
- printk(BIOS_EMERG,"CONFIGURING PLL FAILURE -- HALT\n");
- post_code(POST_PLL_RESET_FAIL);
- __asm__ __volatile__("hlt\n");
-
- }
- printk(BIOS_DEBUG, "Done pll_reset\n");
- return;
-}
-
-
-/**
- * Return the CPU clock rate. Rates in this system are always returned
- * as multkiples of 33 Mhz.
- *
- */
-u32 cpu_speed(void)
-{
- u32 speed;
- msr_t msr;
-
- msr = rdmsr(GLCP_SYS_RSTPLL);
- speed = ((((msr.hi >> RSTPLL_UPPER_CPUMULT_SHIFT) & 0x1F) + 1) * 333) / 10;
- if ((((((msr.hi >> RSTPLL_UPPER_CPUMULT_SHIFT) & 0x1F) + 1) * 333) % 10) > 5) {
- ++speed;
- }
- return (speed);
-}
-
-/**
- * Return the Geode Link clock rate. Rates in this system are always
- * returned as multkiples of 33 Mhz.
- *
- */
-u32 geode_link_speed(void)
-{
- unsigned int speed;
- msr_t msr;
-
- msr = rdmsr(GLCP_SYS_RSTPLL);
- speed = ((((msr.hi >> RSTPLL_UPPER_GLMULT_SHIFT) & 0x1F) + 1) * 333) / 10;
- if ((((((msr.hi >> RSTPLL_UPPER_GLMULT_SHIFT) & 0x1F) + 1) * 333) % 10) > 5) {
- ++speed;
- }
- return (speed);
-}
-
-
-/**
- * Return the PCI bus clock rate. Rates in this system are always
- * returned as multkiples of 33 Mhz.
- *
- */
-u32 pci_speed(void)
-{
- msr_t msr;
-
- msr = rdmsr(GLCP_SYS_RSTPLL);
- if (msr.hi & (1 << RSTPPL_LOWER_PCISPEED_SHIFT)) {
- return (66);
- } else {
- return (33);
- }
-}
-
-/**
- * set_delay_control. This is Black Magic DRAM timing
- * juju(http://www.thefreedictionary.com/juju) Dram delay depends on
- * cpu clock, memory bus clock, memory bus loading, memory bus
- * termination, your middle initial (ha! caught you!), Geode Link
- * clock rate, and dram timing specifications. From this the code
- * computes a number which is "known to work". No, hardware is not an
- * exact science. And, finally, if an FS2 (jtag debugger) is hooked
- * up, then just don't to anything. This code was written by a master
- * of the Dark Arts at AMD and should not be modified in any way.
- *
- * @param num_banks How many banks of DRAM there are
- * @param dimm0 DIMM 0 SMBus address
- * @param dimm1 DIMM 1 SMBus address
- * @param sram_width Data width of the SDRAM
- */
-
-void set_delay_control(u8 dimm0, u8 dimm1)
-{
- u32 msrnum, glspeed;
- u8 spdbyte0, spdbyte1;
- int numdimms = 0;
- msr_t msr;
-
- glspeed = geode_link_speed();
-
- /* fix delay controls for DM and IM arrays */
- msrnum = CPU_BC_MSS_ARRAY_CTL0;
- msr.hi = 0;
- msr.lo = 0x2814D352;
- wrmsr(msrnum, msr);
-
- msrnum = CPU_BC_MSS_ARRAY_CTL1;
- msr.hi = 0;
- msr.lo = 0x1068334D;
- wrmsr(msrnum, msr);
-
- msrnum = CPU_BC_MSS_ARRAY_CTL2;
- msr.hi = 0x00000106;
- msr.lo = 0x83104104;
- wrmsr(msrnum, msr);
-
- msrnum = GLCP_FIFOCTL;
- msr = rdmsr(msrnum);
- msr.hi = 0x00000005;
- wrmsr(msrnum, msr);
-
- /* Enable setting */
- msrnum = CPU_BC_MSS_ARRAY_CTL_ENA;
- msr.hi = 0;
- msr.lo = 0x00000001;
- wrmsr(msrnum, msr);
-
- /* Debug Delay Control Setup Check
- *
- * Leave it alone if it has been setup. FS2 or something is here.
- */
- msrnum = GLCP_DELAY_CONTROLS;
- msr = rdmsr(msrnum);
- if (msr.lo & ~(0x7C0)) {
- return;
- }
-
- /*
- * Delay Controls based on DIMM loading. UGH!
- * # of Devices = Module Width (SPD6) / Device Width(SPD13) * Physical Banks(SPD5)
- * Note - We only support module width of 64.
- */
- spdbyte0 = smbus_read_byte(dimm0, SPD_PRIMARY_SDRAM_WIDTH);
- if (spdbyte0 != 0xFF) {
- numdimms++;
- spdbyte0 = (unsigned char)64 / spdbyte0 *
- (unsigned char)(smbus_read_byte(dimm0, SPD_NUM_DIMM_BANKS));
- } else {
- spdbyte0 = 0;
- }
-
- spdbyte1 = smbus_read_byte(dimm1, SPD_PRIMARY_SDRAM_WIDTH);
- if (spdbyte1 != 0xFF) {
- numdimms++;
- spdbyte1 = (unsigned char)64 / spdbyte1 *
- (unsigned char)(smbus_read_byte(dimm1, SPD_NUM_DIMM_BANKS));
- } else {
- spdbyte1 = 0;
- }
-
-/* The current thinking. Subject to change...
-
-; "FUTURE ROBUSTNESS" PROPOSAL
-; ----------------------------
-; DIMM Max MBUS MC 0x2000001A bits 26:24
-;DIMMs devices Frequency MCP 0x4C00000F Setting vvv
-;----- ------- --------- ---------------------- ----------
-;1 4 400MHz 0x82*100FF 0x56960004 4
-;1 8 400MHz 0x82*100AA 0x56960004 4
-;1 16 400MHz 0x82*10055 0x56960004 4
-;
-;2 4,4 400MHz 0x82710000 0x56960004 4
-;2 8,8 400MHz 0xC27100A5 0x56960004 4 *** OUT OF PUBLISHED ENVELOPE ***
-;
-;2 16,4 >333 0xB27100A5 0x56960004 4 *** OUT OF PUBLISHED ENVELOPE ***
-;2 16,8 >333 0xB27100A5 0x56960004 4 *** OUT OF PUBLISHED ENVELOPE ***
-;2 16,16 >333 0xB2710000 0x56960004 4 *** OUT OF PUBLISHED ENVELOPE ***
-;
-;1 4 <=333MHz 0x83*100FF 0x56960004 3
-;1 8 <=333MHz 0x83*100AA 0x56960004 3
-;1 16 <=333MHz 0x83*100AA 0x56960004 3
-;
-;2 4,4 <=333MHz 0x837100A5 0x56960004 3
-;2 8,8 <=333MHz 0x937100A5 0x56960004 3
-;
-;2 16,4 <=333MHz 0xB37100A5 0x56960004 3 *** OUT OF PUBLISHED ENVELOPE ***
-;2 16,8 <=333MHz 0xB37100A5 0x56960004 3 *** OUT OF PUBLISHED ENVELOPE ***
-;2 16,16 <=333MHz 0xB37100A5 0x56960004 3 *** OUT OF PUBLISHED ENVELOPE ***
-;=========================================================================
-;* - Bit 55 (disable SDCLK 1,3,5) should be set if there is a single DIMM in slot 0,
-; but it should be clear for all 2 DIMM settings and if a single DIMM is in slot 1.
-; Bits 54:52 should always be set to '111'.
-
-;No VTT termination
-;-------------------------------------
-;ADDR/CTL have 22 ohm series R
-;DQ/DQM/DQS have 33 ohm series R
-;
-; DIMM Max MBUS
-;DIMMs devices Frequency MCP 0x4C00000F Setting
-;----- ------- --------- ----------------------
-;1 4 400MHz 0xF2F100FF 0x56960004 4 The MC changes improve Salsa.
-;1 8 400MHz 0xF2F100FF 0x56960004 4 Delay controls no real change,
-;1 4 <=333MHz 0xF2F100FF 0x56960004 3 just fixing typo in left side.
-;1 8 <=333MHz 0xF2F100FF 0x56960004 3
-;1 16 <=333MHz 0xF2F100FF 0x56960004 3
-*/
- msr.hi = msr.lo = 0;
-
- if (spdbyte0 == 0 || spdbyte1 == 0) {
- /* one dimm solution */
- if (spdbyte1 == 0) {
- msr.hi |= 0x000800000;
- }
- spdbyte0 += spdbyte1;
- if (spdbyte0 > 8) {
- /* large dimm */
- if (glspeed < 334) {
- msr.hi |= 0x0837100AA;
- msr.lo |= 0x056960004;
- } else {
- msr.hi |= 0x082710055;
- msr.lo |= 0x056960004;
- }
- } else if (spdbyte0 > 4) {
- /* medium dimm */
- if (glspeed < 334) {
- msr.hi |= 0x0837100AA;
- msr.lo |= 0x056960004;
- } else {
- msr.hi |= 0x0827100AA;
- msr.lo |= 0x056960004;
- }
- } else {
- /* small dimm */
- if (glspeed < 334) {
- msr.hi |= 0x0837100FF;
- msr.lo |= 0x056960004;
- } else {
- msr.hi |= 0x0827100FF;
- msr.lo |= 0x056960004;
- }
- }
- } else {
- /* two dimm solution */
- spdbyte0 += spdbyte1;
- if (spdbyte0 > 24) {
- /* huge dimms */
- if (glspeed < 334) {
- msr.hi |= 0x0B37100A5;
- msr.lo |= 0x056960004;
- } else {
- msr.hi |= 0x0B2710000;
- msr.lo |= 0x056960004;
- }
- } else if (spdbyte0 > 16) {
- /* large dimms */
- if (glspeed < 334) {
- msr.hi |= 0x0B37100A5;
- msr.lo |= 0x056960004;
- } else {
- msr.hi |= 0x0B27100A5;
- msr.lo |= 0x056960004;
- }
- } else if (spdbyte0 >= 8) {
- /* medium dimms */
- if (glspeed < 334) {
- msr.hi |= 0x0937100A5;
- msr.lo |= 0x056960004;
- } else {
- msr.hi |= 0x0C27100A5;
- msr.lo |= 0x056960004;
- }
- } else {
- /* small dimms */
- if (glspeed < 334) {
- msr.hi |= 0x0837100A5;
- msr.lo |= 0x056960004;
- } else {
- msr.hi |= 0x082710000;
- msr.lo |= 0x056960004;
- }
- }
- }
- wrmsr(GLCP_DELAY_CONTROLS, msr);
- return;
-}
-
-/**
- * cpu_reg_init. All cpu register settings, here in one place, and
- * done in the proper order.
- *
- * @param debug_clock_disable Disable the debug clock to save power. Currently ignored, but we need to
- * pick this up from a CMOS setting in future.
- * @param dimm0 SMBus address of dimm0 (mainboard dependent)
- * @param dimm1 SMBus address of dimm1 (mainboard dependent)
- */
-void cpu_reg_init(int debug_clock_disable, u8 dimm0, u8 dimm1)
-{
- int msrnum;
- msr_t msr;
-
- /* Castle 2.0 BTM periodic sync period. */
- /* [40:37] 1 sync record per 256 bytes */
- msrnum = CPU_PF_CONF;
- msr = rdmsr(msrnum);
- msr.hi |= (0x8 << 5);
- wrmsr(msrnum, msr);
-
- /*
- ; Castle performance setting.
- ; Enable Quack for fewer re-RAS on the MC
- */
- msrnum = GLIU0_ARB;
- msr = rdmsr(msrnum);
- msr.hi &= ~ARB_UPPER_DACK_EN_SET;
- msr.hi |= ARB_UPPER_QUACK_EN_SET;
- wrmsr(msrnum, msr);
-
- msrnum = GLIU1_ARB;
- msr = rdmsr(msrnum);
- msr.hi &= ~ARB_UPPER_DACK_EN_SET;
- msr.hi |= ARB_UPPER_QUACK_EN_SET;
- wrmsr(msrnum, msr);
-
- /* GLIU port active enable, limit south pole masters (AES and PCI) to one outstanding transaction. */
- msrnum = GLIU1_PORT_ACTIVE;
- msr = rdmsr(msrnum);
- msr.lo &= ~0x880;
- wrmsr(msrnum, msr);
-
- /* Set the Delay Control in GLCP */
- set_delay_control(dimm0, dimm1);
-
- /* Enable RSDC */
- msrnum = CPU_AC_SMM_CTL;
- msr = rdmsr(msrnum);
- msr.lo |= SMM_INST_EN_SET;
- wrmsr(msrnum, msr);
-
- /* FPU imprecise exceptions bit */
- msrnum = CPU_FPU_MSR_MODE;
- msr = rdmsr(msrnum);
- msr.lo |= FPU_IE_SET;
- wrmsr(msrnum, msr);
-
- /* Power Savers (Do after BIST) */
- /* Enable Suspend on HLT & PAUSE instructions */
- msrnum = CPU_XC_CONFIG;
- msr = rdmsr(msrnum);
- msr.lo |= XC_CONFIG_SUSP_ON_HLT | XC_CONFIG_SUSP_ON_PAUSE;
- wrmsr(msrnum, msr);
-
- /* Enable SUSP and allow TSC to run in Suspend (keep speed detection happy) */
- msrnum = CPU_BC_CONF_0;
- msr = rdmsr(msrnum);
- msr.lo |= TSC_SUSP_SET | SUSP_EN_SET;
- msr.lo &= 0x0F0FFFFFF;
- msr.lo |= 0x002000000; /* PBZ213: Set PAUSEDLY = 2 */
- wrmsr(msrnum, msr);
-
- /* Disable the debug clock to save power. */
- /* NOTE: leave it enabled for fs2 debug */
- if (debug_clock_disable && 0){
- msrnum = GLCP_DBGCLKCTL;
- msr.hi = 0;
- msr.lo = 0;
- wrmsr(msrnum, msr);
- }
-
- /* Setup throttling delays to proper mode if it is ever enabled. */
- msrnum = GLCP_TH_OD;
- msr.hi = 0;
- msr.lo = 0x00000603C;
- wrmsr(msrnum, msr);
- /* fix cpu bugs */
-#warning testing fixing bugs in initram
- cpu_bug();
-}
Deleted: LinuxBIOSv3/arch/x86/stage0_amd_geodelx.S
===================================================================
--- LinuxBIOSv3/arch/x86/stage0_amd_geodelx.S 2007-06-27 21:01:01 UTC (rev 386)
+++ LinuxBIOSv3/arch/x86/stage0_amd_geodelx.S 2007-06-27 21:07:10 UTC (rev 387)
@@ -1,443 +0,0 @@
-##
-## This file is part of the LinuxBIOS project.
-##
-## Copyright (C) 2000,2007 Ronald G. Minnich <rminnich at gmail.com>
-## Copyright (C) 2005 Eswar Nallusamy, LANL
-## Copyright (C) 2005 Tyan
-## (Written by Yinghai Lu <yhlu at tyan.com> for Tyan)
-## Copyright (C) 2007 coresystems GmbH
-## (Written by Stefan Reinauer <stepan at coresystems.de> for coresystems GmbH)
-## 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; version 2 of the License.
-##
-## 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
-##
-
-/* Init code - Switch CPU to protected mode and enable Cache-as-Ram. */
-
-#include "macros.h"
-#include <amd_geodelx.h>
-
-/* This is where the DCache will be mapped and be used as stack. It would be
- * cool if it was the same base as LinuxBIOS normal stack.
- */
-#define LX_STACK_BASE DCACHE_RAM_BASE
-#define LX_STACK_END LX_STACK_BASE+(DCACHE_RAM_SIZE-4)
-
-#define LX_NUM_CACHELINES 0x080 /* There are 128 lines per way. */
-#define LX_CACHELINE_SIZE 0x020 /* There are 32 bytes per line. */
-#define LX_CACHEWAY_SIZE (LX_NUM_CACHELINES * LX_CACHELINE_SIZE)
-#define CR0_CD 0x40000000 /* Bit 30 = Cache Disable */
-#define CR0_NW 0x20000000 /* Bit 29 = Not Write Through */
-
-#define ROM_CODE_SEG 0x08
-#define ROM_DATA_SEG 0x10
-
-#define CACHE_RAM_CODE_SEG 0x18
-#define CACHE_RAM_DATA_SEG 0x20
-
- .code16
- .globl _stage0
-_stage0:
- cli
-
- /* Save the BIST result. */
- movl %eax, %ebp;
-
- /* Thanks to kmliu at sis.com.tw for this TLB fix. */
- /* IMMEDIATELY invalidate the translation lookaside buffer before
- * executing any further code. Even though paging is disabled we
- * could still get false address translations due to the TLB if we
- * didn't invalidate it.
- */
-
- xorl %eax, %eax
- movl %eax, %cr3 /* Invalidate TLB */
-
- /* Switch to protected mode. */
-
- /* NOTE: With GNU assembler version 2.15.94.0.2.2 (i386-redhat-linux)
- * using BFD version 2.15.94.0.2.2 20041220 this works fine without
- * all the ld hackery and so on. So leave it as is with this comment.
- */
-
- data32 lgdt %cs:gdtptr
-
- movl %cr0, %eax
- andl $0x7FFAFFD1, %eax /* PG, AM, WP, NE, TS, EM, MP = 0 */
- orl $0x60000001, %eax /* CD, NW, PE = 1 */
- movl %eax, %cr0
-
- /* Restore BIST result. */
- movl %ebp, %eax
-
- // port80_post(0x23)
-
- /* Now we are in protected mode. Jump to a 32 bit code segment. */
- data32 ljmp $ROM_CODE_SEG, $protected_stage0
- /* I am leaving this weird jump in here in the event that future gas
- * bugs force it to be used.
- */
- #.byte 0x66
- .code32
- #ljmp $ROM_CODE_SEG, $protected_stage0
-
- #.code16
- .align 4
- .globl gdt16
-gdt16 = . - _stage0
-gdt16x:
- .word gdt16xend - gdt16x -1 /* Compute the table limit. */
- .long gdt16x
- .word 0
-
- /* selgdt 0x08, flat code segment */
- .word 0xffff, 0x0000
- .byte 0x00, 0x9b, 0xcf, 0x00
-
- /* selgdt 0x10, flat data segment */
- .word 0xffff, 0x0000
- .byte 0x00, 0x93, 0xcf, 0x00
-gdt16xend:
-
- /* From now on we are 32bit. */
- .code32
-
- /* We have two gdts where we could have one. That is ok.
- *
- * Let's not worry about this -- optimizing gdt is pointless since
- * we're only in it for a little bit.
- *
- * BTW note the trick below: The GDT points to ITSELF, and the first
- * good descriptor is at offset 8. So you word-align the table, and
- * then because you chose 8, you get a nice 64-bit aligned GDT entry,
- * which is good as this is the size of the entry.
- *
- * Just in case you ever wonder why people do this.
- */
- .align 4
- .globl gdtptr
- .globl gdt_limit
-gdt_limit = gdt_end - gdt - 1 /* Compute the table limit. */
-
-gdt:
-gdtptr:
- .word gdt_end - gdt -1 /* Compute the table limit. */
- .long gdt /* We know the offset. */
- .word 0
-
- /* selgdt 0x08, flat code segment */
- .word 0xffff, 0x0000
- .byte 0x00, 0x9b, 0xcf, 0x00
-
- /* selgdt 0x10, flat data segment */
- .word 0xffff, 0x0000
- .byte 0x00, 0x93, 0xcf, 0x00
-
- /* selgdt 0x18, flat code segment for CAR */
- .word 0xffff, 0x0000
- .byte 0x00, 0x9b, 0xcf, 0x00
-
- /* selgdt 0x20, flat data segment for CAR */
- .word 0xffff, 0x0000
- .byte 0x00, 0x93, 0xcf, 0x00
-gdt_end:
-
- /*
- * When we come here we are in protected mode. We expand the stack
- * and copy the data segment from ROM to the memory.
- *
- * After that, we call the chipset bootstrap routine that
- * does what is left of the chipset initialization.
- *
- * NOTE: Aligned to 4 so that we are sure that the prefetch
- * cache will be reloaded.
- */
-
- .align 4
- .globl protected_stage0
-protected_stage0:
- // This code was used by v2. TODO
- lgdt %cs:gdtptr
- ljmp $ROM_CODE_SEG, $__protected_stage0
-
-.globl __protected_stage0
-__protected_stage0:
- /* Save the BIST value. */
- movl %eax, %ebp
-
- port80_post(0x01)
-
- movw $ROM_DATA_SEG, %ax
- movw %ax, %ds
- movw %ax, %es
- movw %ax, %ss
- movw %ax, %fs
- movw %ax, %gs
-
- /* Restore the BIST value to %eax. */
- movl %ebp, %eax
-
-.align 4
- /* Here begins CAR support. */
- /* This particular code is straight from LinuxBIOS V2. */
-
- /* DCacheSetup: Setup data cache for use as RAM for a stack. */
-DCacheSetup:
-
- invd
- /* Set cache properties. */
- movl $CPU_RCONF_DEFAULT, %ecx
- rdmsr
- /* 1MB system memory in write back 1|00100|00. */
- movl $0x010010000, %eax
- wrmsr
-
- /* In LX DCDIS is set after POR which disables the cache..., clear
- * this bit.
- */
- movl CPU_DM_CONFIG0,%ecx
- rdmsr
- /* TODO: Make consistent with i$ init, either whole reg = 0, or just
- * this bit...
- */
- andl $(~(DM_CONFIG0_LOWER_DCDIS_SET)), %eax
- wrmsr
-
- /* Get cache timing params from BIOS config data locations and apply. */
- /* Fix delay controls for DM and IM arrays. */
- movl $CPU_BC_MSS_ARRAY_CTL0, %ecx
- xorl %edx, %edx
- movl $0x2814D352, %eax
- wrmsr
-
- movl $CPU_BC_MSS_ARRAY_CTL1, %ecx
- xorl %edx, %edx
- movl $0x1068334D, %eax
- wrmsr
-
- movl $CPU_BC_MSS_ARRAY_CTL2, %ecx
- movl $0x00000106, %edx
- movl $0x83104104, %eax
- wrmsr
-
- movl $GLCP_FIFOCTL, %ecx
- rdmsr
- movl $0x00000005, %edx
- wrmsr
-
- /* Enable setting. */
- movl $CPU_BC_MSS_ARRAY_CTL_ENA, %ecx
- xorl %edx, %edx
- movl $0x01, %eax
- wrmsr
-
- /* Get cleaned up. */
- xorl %edi, %edi
- xorl %esi, %esi
- xorl %ebp, %ebp
-
- /* DCache Ways0 through Ways7 will be tagged for
- * LX_STACK_BASE + DCACHE_RAM_SIZE for holding stack.
- */
- /* Remember, there is NO stack yet... */
-
- /* Tell cache we want to fill Way 0 starting at the top. */
- xorl %edx, %edx
- xorl %eax, %eax
- movl $CPU_DC_INDEX, %ecx
- wrmsr
-
- /* Startaddress for tag of Way0: ebp will hold the incrementing
- * address. dont destroy!
- */
- movl $LX_STACK_BASE, %ebp /* Init to start address. */
- /* Set valid bit and tag for this Way (B[31:12] : Cache tag value for
- * line/way curr. selected by CPU_DC_INDEX.
- */
- orl $1, %ebp
-
- /* Start tag Ways 0 with 128 lines with 32 bytes each: edi will hold
- * the line counter. dont destroy!
- */
- movl $LX_NUM_CACHELINES, %edi
-
-DCacheSetupFillWay:
- /* Fill with dummy data: zero it so we can tell it from PCI memory
- * space (returns FFs).
- */
- /* We will now store a line (32 bytes = 4 x 8 bytes = 4 quad-words). */
- movw $0x04, %si
- xorl %edx, %edx
- xorl %eax, %eax
- movl $CPU_DC_DATA, %ecx
-
-DCacheSetup_quadWordLoop:
- wrmsr
- decw %si
- jnz DCacheSetup_quadWordLoop
-
- /* Set the tag for this line, need to do this for every new cache
- * line to validate it!
- */
- /* Accessing CPU_DC_TAG_I makes the LINE field in CPU_DC_INDEX
- * increment and thus continue in the next cache line...
- */
- xorl %edx, %edx
- movl %ebp, %eax
- movl $CPU_DC_TAG, %ecx
- wrmsr
-
- /* Switch to next line. Lines are in Bits10:4. */
- /* When index is crossing 0x7F -> 0x80 writing a RSVD bit as 0x80 is
- * not a valid CL anymore!
- */
- movl $CPU_DC_INDEX, %ecx
- rdmsr
- /* TODO: Probably would be more elegant to calculate this from
- * counter var edi...
- */
- addl $0x010, %eax
- wrmsr
-
- decl %edi
- jnz DCacheSetupFillWay
-
- /* 1 Way has been filled, forward start address for next Way,
- * terminate if we have reached end of desired address range.
- */
- addl $LX_CACHEWAY_SIZE, %ebp
- cmpl $LX_STACK_END, %ebp
- jge leave_DCacheSetup
- movl $LX_NUM_CACHELINES, %edi
-
- /* Switch to next way. */
- movl $CPU_DC_INDEX, %ecx
- rdmsr
- addl $0x01, %eax
- /* Let's be sure: reset line index Bits10:4. */
- andl $0xFFFFF80F, %eax
- wrmsr
-
- jmp DCacheSetupFillWay
-
-leave_DCacheSetup:
- xorl %edi, %edi
- xorl %esi, %esi
- xorl %ebp, %ebp
-
- /* Disable the cache, but... DO NOT INVALIDATE the tags. */
- /* Memory reads and writes will all hit in the cache. */
- /* Cache updates and memory write-backs will not occur! */
- movl %cr0, %eax
- orl $(CR0_CD + CR0_NW), %eax /* Set the CD and NW bits. */
- movl %eax, %cr0
-
- /* Now point sp to the cached stack. */
- /* The stack will be fully functional at this location. No system
- * memory is required at all!
- */
- /* Set up the stack pointer. */
- movl $LX_STACK_END, %eax
- movl %eax, %esp
-
- /* Test the stack. */
- movl $0x0F0F05A5A, %edx
- pushl %edx
- popl %ecx
- cmpl %ecx, %edx
- je DCacheSetupGood
- movb $0xC5, %al
- outb %al, $0x80
-
-DCacheSetupBad:
- hlt /* Issues */
- jmp DCacheSetupBad
-
-DCacheSetupGood:
- /* If you wanted to maintain the stack in memory you would need to
- * set the tags as dirty so the wbinvd would push out the old stack
- * contents to memory.
- */
- /* Clear the cache, the following code from crt0.S.lb will setup
- * a new stack.
- */
- wbinvd
-
- /* At this point, CAR should be working. */
- movl $(LX_STACK_END), %eax
- movl %eax, %esp
-
- /* Load a different set of data segments. */
- movw $CACHE_RAM_DATA_SEG, %ax
- movw %ax, %ds
- movw %ax, %es
- movw %ax, %ss
-
-lout:
- /* Restore the BIST result. */
- movl %ebp, %eax
- /* We need to set ebp? No need. */
- movl %esp, %ebp
- pushl %eax /* BIST */
- call stage1_main
- /* We will not go back. */
-
-fixed_mtrr_msr:
- .long 0x250, 0x258, 0x259
- .long 0x268, 0x269, 0x26A
- .long 0x26B, 0x26C, 0x26D
- .long 0x26E, 0x26F
-var_mtrr_msr:
- .long 0x200, 0x201, 0x202, 0x203
- .long 0x204, 0x205, 0x206, 0x207
- .long 0x208, 0x209, 0x20A, 0x20B
- .long 0x20C, 0x20D, 0x20E, 0x20F
- .long 0x000 /* NULL, end of table */
-
-# Reset vector.
-
-/*
- * RVECTOR: size of reset vector, default is 0x10
- * RESRVED: size of vpd code, default is 0xf0
- * BOOTBLK: size of bootblock code, default is 0x1f00 (8k-256b)
- */
-
-SEGMENT_SIZE = 0x10000
-RVECTOR = 0x00010
-
-# Due to YET ANOTHER BUG in GNU bintools, you can NOT have a code16 here.
-# I think we should leave it this way forever, as the bugs come and
-# go -- and come again.
-# .code16
-# .section ".rom.text"
-.section ".reset", "ax"
- .globl _resetjump
-_resetjump:
- /* GNU bintools bugs again. This jumps to stage0 - 2. Sigh. */
-# jmp _stage0
- .byte 0xe9
- .int _stage0 - ( . + 2 )
- /* Note: The above jump is hand coded to work around bugs in binutils.
- * 5 bytes are used for a 3 byte instruction. This works because x86
- * is little endian and allows us to use supported 32 bit relocations
- * instead of the weird 16 bit relocations that binutils does not
- * handle consistenly between versions because they are used so rarely.
- */
-.byte 0
-
-# Date? ID string? We might want to put something else in here.
-.ascii DATE
-
-# Checksum.
-#.word 0
More information about the coreboot
mailing list