Various coding style fixes, typo fixes, and other cosmetic changes (trivial).

Signed-off-by: Uwe Hermann <uwe@hermann-uwe.de>
Acked-by: Uwe Hermann <uwe@hermann-uwe.de>



git-svn-id: svn://coreboot.org/repository/LinuxBIOSv3@438 f3766cd6-281f-0410-b1cd-43a5c92072e9
This commit is contained in:
Uwe Hermann 2007-07-07 21:18:47 +00:00
commit 203bffe9e7
4 changed files with 341 additions and 313 deletions

View file

@ -22,10 +22,10 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/* This is a test for the idea of a cpu device. There is only ever
* going to be one CPU device, the bootstrap processor or BP; other
* processors will go through a different path. on Geode it is
* really simple, so we start with that. Later, it gets harder.
/* This is a test for the idea of a CPU device. There is only ever going to
* be one CPU device, the bootstrap processor or BP; other processors will
* go through a different path. On Geode it is really simple, so we start
* with that. Later, it gets harder.
*/
#include <console.h>
@ -35,35 +35,38 @@
#include <io.h>
#include <cpu.h>
/* TODO: better comment on vsm_end_post_smi, and define 0x05a2 down below */
/**
/* TODO: Better comment on vsm_end_post_smi, and define 0x05a2 down below. */
/**
* This is a call to the VSM.
* We need to know what it does.
*
* TODO: We need to know what it does.
*/
static void vsm_end_post_smi(void)
{
__asm__ volatile ("push %ax\n"
"mov $0x5000, %ax\n"
".byte 0x0f, 0x38\n" "pop %ax\n");
__asm__ volatile("push %ax\n"
"mov $0x5000, %ax\n"
".byte 0x0f, 0x38\n"
"pop %ax\n");
}
/**
* The very last steps in lx init. Turn on caching,
* tell vsm that we are done. Turn A20 back on in
* case VSM turned it off.
* @param dev struct device pointer
* The very last steps in LX init. Turn on caching, tell VSM that we are
* done. Turn A20 back on in case VSM turned it off.
*
* @param dev The device to use.
*/
static void lx_init(struct device *dev)
{
printk(BIOS_SPEW, "lx_init\n");
printk(BIOS_SPEW, "CPU lx_init\n");
/* Turn on caching if we haven't already */
/* Turn on caching if we haven't already. */
enable_cache();
// do VSA late init
/* Do VSA late init. */
vsm_end_post_smi();
// Set gate A20 (legacy vsm disables it in late init)
/* Set gate A20 (legacy VSM disables it in late init). */
printk(BIOS_SPEW, "A20 (0x92): %d\n", inb(0x92));
outb(0x02, 0x92);
printk(BIOS_SPEW, "A20 (0x92): %d\n", inb(0x92));
@ -71,30 +74,34 @@ static void lx_init(struct device *dev)
printk(BIOS_SPEW, "CPU lx_init DONE\n");
};
/* The only operations currently set up are the phase 6. We might,
* however, set up an op in phase3_scan to get the cpuinfo into a
* struct for all to see. On SMP, it would not be hard to have
* phase3 scan set up an array of such structs. Further, for systems
* which have multiple types of CPUs, you can compile in multiple CPU
* files and use the device id, at scan time, to pick which one is
* used. There is a lot of flexibility here!
/**
* The only operations currently set up are the phase 6. We might, however,
* set up an op in phase3_scan to get the cpuinfo into a struct for all to
* see. On SMP, it would not be hard to have phase3_scan set up an array of
* such structs.
*
* Further, for systems which have multiple types of CPUs, you can compile
* in multiple CPU files and use the device ID, at scan time, to pick which
* one is used. There is a lot of flexibility here!
*/
struct device_operations geodelx_cpuops = {
.constructor = default_device_constructor,
.phase3_scan = NULL,
.phase6_init = lx_init,
.constructor = default_device_constructor,
.phase3_scan = NULL,
.phase6_init = lx_init,
};
/* This is a constructor for a cpu. the PCI id works for now.
* Later, we might need to change it to use a different phase3 scan,
* and match on a cpu id. However, CPU IDs are known to be kind
* of weird, depending on date manufactured they can be all
* over the place (the Geode alone has had 3 vendors!) so
* we will have to be careful
*/
/**
* This is a constructor for a CPU.
*
* Later, we might need to change it to use a different phase3_scan, and
* match on a CPU ID. However, CPU IDs are known to be kind of weird,
* depending on date manufactured they can be all over the place (the Geode
* alone has had 3 vendors!) so we will have to be careful.
*/
struct constructor geodelx_constructors[] = {
{.id = {.type = DEVICE_ID_PCI,
.u = {.pci = {.vendor = X86_VENDOR_AMD,.device = 0x05A2}}},
.ops = &geodelx_cpuops},
{.ops = 0},
{.id = {.type = DEVICE_ID_PCI,
/* TODO: This is incorrect, these are _not_ PCI IDs! */
.u = {.pci = {.vendor = X86_VENDOR_AMD,.device = 0x05A2}}},
.ops = &geodelx_cpuops},
{.ops = 0},
};

View file

@ -28,71 +28,73 @@
#include <string.h>
#include <msr.h>
#include <io.h>
#include <hlt.h>
#include <amd_geodelx.h>
#include <spd.h>
#include <legacy.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.
*/
/* 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.
*/
/**
* Starts Timer 1 for port 61 use.
*
* The command 0x56 means write counter 1 lower 8 bits in next IO,
* set the counter mode to square wave generator (count down to 0
* from programmed value twice in a row, alternating the output signal)
* counting in 16-bit binary mode.
*
* 0x12 is counter/timer 1 and signals the PIT to do a RAM refresh
* approximately every 15us.
*
* The PIT typically is generating 1.19318 MHz
* Timer 1 was used for RAM refresh on XT/AT and can be read on port61.
* Port61 is used by many timing loops for calibration.
*/
/**
* Starts Timer 1 for port 61 use.
*
* The command 0x56 means write counter 1 lower 8 bits in next I/O, set the
* counter mode to square wave generator (count down to 0 from programmed
* value twice in a row, alternating the output signal) counting in 16-bit
* binary mode.
*
* 0x12 is counter/timer 1 and signals the PIT to do a RAM refresh
* approximately every 15us.
*
* The PIT typically is generating 1.19318 MHz.
*
* Timer 1 was used for RAM refresh on XT/AT and can be read on port 61.
* Port 61 is used by many timing loops for calibration.
*/
void start_timer1(void)
{
outb(0x56, I82C54_CONTROL_WORD_REGISTER);
outb(0x12, I82C54_COUNTER1);
}
/**
* system_preinit Very early initialization needed for almost
* everything else. Currently, all we do is start timer1.
*/
/**
* Very early initialization needed for almost everything else.
* Currently, all we do is start timer1.
*/
void system_preinit(void)
{
start_timer1();
}
/* CPU bug management */
/* cpu bug management */
/**
* Bugtool #465 and #609 PCI cache deadlock.
* TODO: URL?
*
* 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.
*
* There is also fix code in cache and PCI functions. This bug is very is
* pervasive.
*/
static void pci_deadlock(void)
{
struct msr msr;
struct msr 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.
/* 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
/* Write serialize memory hole to PCI. Need to unWS when something is
* shadowed regardless of cachablility.
*/
msr.lo = 0x021212121;
@ -102,16 +104,16 @@ static void pci_deadlock(void)
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.
*/
/****************************************************************************/
/**
* 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)
{
struct msr msr;
struct msr msr;
msr = rdmsr(MC_CF8F_DATA);
msr.hi |= CF8F_UPPER_REORDER_DIS_SET;
@ -119,55 +121,61 @@ static void disable_memory_reorder(void)
}
/**
* Fix up register settings to manage known CPU bugs. For cpu
* version C3. Should be the only released version
*/
* 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");
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.
* Reset the phase locked loop (PLL) hardware.
*
* @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
* 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)
{
struct msr msr_glcp_sys_pll; /* GeodeLink PLL control MSR */
struct msr msr_glcp_sys_pll; /* GeodeLink PLL control MSR */
msr_glcp_sys_pll = rdmsr(GLCP_SYS_RSTPLL);
printk(BIOS_DEBUG,
"_MSR GLCP_SYS_RSTPLL (%08x) value is: %08x:%08x\n", msr_glcp_sys_pll.hi, msr_glcp_sys_pll.lo);
printk(BIOS_DEBUG,
"_MSR GLCP_SYS_RSTPLL (%08x) value is: %08x:%08x\n",
msr_glcp_sys_pll.hi, msr_glcp_sys_pll.lo);
post_code(POST_PLL_INIT);
if (!(msr_glcp_sys_pll.lo & (1 << RSTPLL_LOWER_SWFLAGS_SHIFT))) {
printk(BIOS_DEBUG,"Configuring PLL\n");
printk(BIOS_DEBUG, "Configuring PLL\n");
if (manualconf) {
post_code(POST_PLL_MANUAL);
/* CPU and GLIU mult/div (GLMC_CLK = GLIU_CLK / 2) */
/* CPU and GLIU mult/div (GLMC_CLK = GLIU_CLK / 2) */
msr_glcp_sys_pll.hi = pll_hi;
/* Hold Count - how long we will sit in reset */
msr_glcp_sys_pll.lo = pll_lo;
} else {
/*automatic configuration (straps) */
/* Automatic configuration (straps) */
post_code(POST_PLL_STRAP);
/* Hold 0xDE * 16 clocks during reset. */
/* AMD recomended value for PLL reset from silicon validation. */
/* Hold 0xDE * 16 clocks during reset. AMD recomended
* value for PLL reset from silicon validation.
*/
msr_glcp_sys_pll.lo &=
~(0xFF << RSTPPL_LOWER_HOLD_COUNT_SHIFT);
msr_glcp_sys_pll.lo |=
@ -178,79 +186,81 @@ void pll_reset(int manualconf, u32 pll_hi, u32 pll_lo)
msr_glcp_sys_pll.lo |=
RSTPPL_LOWER_COREPD_SET | RSTPPL_LOWER_CLPD_SET;
}
/* Use SWFLAGS to remember: "we've already been here" */
/* Use SWFLAGS to remember: "we've already been here". */
msr_glcp_sys_pll.lo |= (1 << RSTPLL_LOWER_SWFLAGS_SHIFT);
/* "reset the chip" value */
/* "Reset the chip" value */
msr_glcp_sys_pll.lo |= RSTPPL_LOWER_CHIP_RESET_SET;
wrmsr(GLCP_SYS_RSTPLL, msr_glcp_sys_pll);
/* You should never get here..... The chip has reset. */
printk(BIOS_EMERG,"CONFIGURING PLL FAILURE -- HALT\n");
/* 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");
hlt();
}
printk(BIOS_DEBUG, "Done pll_reset\n");
return;
}
/**
* Return the CPU clock rate from the PLL MSR.
* @return CPU speed in MHz
*
* @return CPU speed in MHz.
*/
u32 cpu_speed(void)
{
u32 speed;
struct msr msr;
struct msr msr;
msr = rdmsr(GLCP_SYS_RSTPLL);
speed = ((((msr.hi >> RSTPLL_UPPER_CPUMULT_SHIFT) & RSTPLL_UPPER_CPUMULT_MASK) + 1) * 333) / 10;
if ((((((msr.hi >> RSTPLL_UPPER_CPUMULT_SHIFT) & RSTPLL_UPPER_CPUMULT_MASK) + 1) * 333) % 10) > 5) {
speed = ((((msr.hi >> RSTPLL_UPPER_CPUMULT_SHIFT)
& RSTPLL_UPPER_CPUMULT_MASK) + 1) * 333) / 10;
if ((((((msr.hi >> RSTPLL_UPPER_CPUMULT_SHIFT)
& RSTPLL_UPPER_CPUMULT_MASK) + 1) * 333) % 10) > 5) {
++speed;
}
return (speed);
return speed;
}
/**
* Return the GeodeLink clock rate from the PLL MSR.
* @return GeodeLink speed in MHz
*
* @return GeodeLink speed in MHz.
*/
u32 geode_link_speed(void)
{
unsigned int speed;
struct msr msr;
u32 speed;
struct msr msr;
msr = rdmsr(GLCP_SYS_RSTPLL);
speed = ((((msr.hi >> RSTPLL_UPPER_GLMULT_SHIFT) & RSTPLL_UPPER_GLMULT_MASK) + 1) * 333) / 10;
if ((((((msr.hi >> RSTPLL_UPPER_GLMULT_SHIFT) & RSTPLL_UPPER_GLMULT_MASK) + 1) * 333) % 10) > 5) {
speed = ((((msr.hi >> RSTPLL_UPPER_GLMULT_SHIFT)
& RSTPLL_UPPER_GLMULT_MASK) + 1) * 333) / 10;
if ((((((msr.hi >> RSTPLL_UPPER_GLMULT_SHIFT)
& RSTPLL_UPPER_GLMULT_MASK) + 1) * 333) % 10) > 5) {
++speed;
}
return (speed);
return speed;
}
/**
* Return the PCI bus clock rate from the PLL MSR.
* @return PCI speed in MHz
*
* @return PCI speed in MHz.
*/
u32 pci_speed(void)
{
struct msr msr;
struct msr msr = rdmsr(GLCP_SYS_RSTPLL);
msr = rdmsr(GLCP_SYS_RSTPLL);
if (msr.hi & (1 << RSTPPL_LOWER_PCISPEED_SHIFT)) {
return (66);
} else {
return (33);
}
if (msr.hi & (1 << RSTPPL_LOWER_PCISPEED_SHIFT))
return 66;
else
return 33;
}
/**
* Delay Control Settings Table from AMD (MCP 0x4C00000F)
* =========================================================================
* Delay Control Settings table from AMD (MCP 0x4C00000F).
*/
const struct delay_controls {
u8 dimms;
@ -259,55 +269,56 @@ const struct delay_controls {
u32 slow_low;
u32 fast_hi;
u32 fast_low;
} delay_control_table [] = {
} delay_control_table[] = {
/* DIMMs Devs Slow (<=333MHz) Fast (>334MHz) */
{ 1, 4, 0x0837100FF, 0x056960004, 0x0827100FF, 0x056960004 },
{ 1, 8, 0x0837100AA, 0x056960004, 0x0827100AA, 0x056960004 },
{ 1, 16, 0x0837100AA, 0x056960004, 0x082710055, 0x056960004 },
{ 2, 8, 0x0837100A5, 0x056960004, 0x082710000, 0x056960004 },
{ 2, 16, 0x0937100A5, 0x056960004, 0x0C27100A5, 0x056960004 },
{ 2, 20, 0x0B37100A5, 0x056960004, 0x0B27100A5, 0x056960004 },
{ 2, 24, 0x0B37100A5, 0x056960004, 0x0B27100A5, 0x056960004 },
{ 2, 32, 0x0B37100A5, 0x056960004, 0x0B2710000, 0x056960004 },
{ 1, 4, 0x0837100FF, 0x056960004, 0x0827100FF, 0x056960004 },
{ 1, 8, 0x0837100AA, 0x056960004, 0x0827100AA, 0x056960004 },
{ 1, 16, 0x0837100AA, 0x056960004, 0x082710055, 0x056960004 },
{ 2, 8, 0x0837100A5, 0x056960004, 0x082710000, 0x056960004 },
{ 2, 16, 0x0937100A5, 0x056960004, 0x0C27100A5, 0x056960004 },
{ 2, 20, 0x0B37100A5, 0x056960004, 0x0B27100A5, 0x056960004 },
{ 2, 24, 0x0B37100A5, 0x056960004, 0x0B27100A5, 0x056960004 },
{ 2, 32, 0x0B37100A5, 0x056960004, 0x0B2710000, 0x056960004 },
};
/**
* - 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'.
/*
* 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'.
*
* Settings for single DIMM and no VTT termination (Like db800 platform)
* 0xF2F100FF 0x56960004
* -------------------------------------
* ADDR/CTL have 22 ohm series R
* DQ/DQM/DQS have 33 ohm series R
* Settings for single DIMM and no VTT termination (like DB800 platform)
* 0xF2F100FF 0x56960004
* -------------------------------------
* ADDR/CTL have 22 ohm series R
* DQ/DQM/DQS have 33 ohm series R
*/
/**
* 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
* This is Black Magic DRAM timing juju[1].
*
* DRAM delay depends on CPU clock, memory bus clock, memory bus loading,
* memory bus termination, your middle initial (ha! caught you!), GeodeLink
* 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 do 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
* [1] (http://www.thefreedictionary.com/juju)
*
* @param dimm0 The SMBus address of DIMM 0 (mainboard dependent).
* @param dimm1 The SMBus address of DIMM 1 (mainboard dependent).
*/
void set_delay_control(u8 dimm0, u8 dimm1)
{
u32 msrnum, glspeed;
u8 spdbyte0, spdbyte1, dimms, i;
struct msr msr;
struct msr msr;
glspeed = geode_link_speed();
/* fix delay controls for DM and IM arrays */
/* Fix delay controls for DM and IM arrays. */
msrnum = CPU_BC_MSS_ARRAY_CTL0;
msr.hi = 0;
msr.lo = 0x2814D352;
@ -328,33 +339,32 @@ void set_delay_control(u8 dimm0, u8 dimm1)
msr.hi = 0x00000005;
wrmsr(msrnum, msr);
/* Enable setting */
/* 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.
*/
/* 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 & ~(DELAY_LOWER_STATUS_MASK)) {
if (msr.lo & ~(DELAY_LOWER_STATUS_MASK))
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.
/* Delay Controls based on DIMM loading. UGH!
* Number of devices = module width (SPD 6) / device width (SPD 13)
* * physical banks (SPD 5)
*
* Note: We only support a module width of 64.
*/
dimms = 0;
spdbyte0 = smbus_read_byte(dimm0, SPD_PRIMARY_SDRAM_WIDTH);
if (spdbyte0 != 0xFF) {
dimms++;
spdbyte0 = (unsigned char)64 / spdbyte0 *
(unsigned char)(smbus_read_byte(dimm0, SPD_NUM_DIMM_BANKS));
spdbyte0 = (u8)64 / spdbyte0 *
(u8)(smbus_read_byte(dimm0, SPD_NUM_DIMM_BANKS));
} else {
spdbyte0 = 0;
}
@ -362,25 +372,24 @@ void set_delay_control(u8 dimm0, u8 dimm1)
spdbyte1 = smbus_read_byte(dimm1, SPD_PRIMARY_SDRAM_WIDTH);
if (spdbyte1 != 0xFF) {
dimms++;
spdbyte1 = (unsigned char)64 / spdbyte1 *
(unsigned char)(smbus_read_byte(dimm1, SPD_NUM_DIMM_BANKS));
spdbyte1 = (u8)64 / spdbyte1 *
(u8)(smbus_read_byte(dimm1, SPD_NUM_DIMM_BANKS));
} else {
spdbyte1 = 0;
}
/* zero GLCP_DELAY_CONTROLS MSR */
/* Zero GLCP_DELAY_CONTROLS MSR */
msr.hi = msr.lo = 0;
/* save some power, disable clock to second DIMM if it is empty */
if (spdbyte1 == 0) {
/* Save some power, disable clock to second DIMM if it is empty. */
if (spdbyte1 == 0)
msr.hi |= DELAY_UPPER_DISABLE_CLK135;
}
spdbyte0 += spdbyte1;
for (i = 0; i < ARRAY_SIZE(delay_control_table); i++) {
if ((dimms == delay_control_table[i].dimms) &&
(spdbyte0 <= delay_control_table[i].devices)) {
(spdbyte0 <= delay_control_table[i].devices)) {
if (glspeed < 334) {
msr.hi |= delay_control_table[i].slow_hi;
msr.lo |= delay_control_table[i].slow_low;
@ -395,29 +404,28 @@ void set_delay_control(u8 dimm0, u8 dimm1)
}
/**
* cpu_reg_init. All cpu register settings, here in one place, and
* done in the proper order.
* 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)
* @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 DIMM 0 (mainboard dependent).
* @param dimm1 SMBus address of DIMM 1 (mainboard dependent).
*/
void cpu_reg_init(int debug_clock_disable, u8 dimm0, u8 dimm1)
{
int msrnum;
struct msr msr;
struct msr msr;
/* Castle 2.0 BTM periodic sync period. */
/* [40:37] 1 sync record per 256 bytes */
/* [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
/* Castle performance setting.
* Enable Quack for fewer re-RAS on the MC.
*/
msrnum = GLIU0_ARB;
msr = rdmsr(msrnum);
@ -431,45 +439,49 @@ void cpu_reg_init(int debug_clock_disable, u8 dimm0, u8 dimm1)
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. */
/* 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 the Delay Control in GLCP. */
set_delay_control(dimm0, dimm1);
/* Enable RSDC */
/* Enable RSDC. */
msrnum = CPU_AC_SMM_CTL;
msr = rdmsr(msrnum);
msr.lo |= SMM_INST_EN_SET;
wrmsr(msrnum, msr);
/* FPU imprecise exceptions bit */
/* 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 */
/* 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) */
/* 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 */
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){
/* Note: Leave it enabled for FS2 debug. */
if (debug_clock_disable && 0) {
msrnum = GLCP_DBGCLKCTL;
msr.hi = 0;
msr.lo = 0;
@ -481,7 +493,8 @@ void cpu_reg_init(int debug_clock_disable, u8 dimm0, u8 dimm1)
msr.hi = 0;
msr.lo = 0x00000603C;
wrmsr(msrnum, msr);
/* fix cpu bugs */
/* Fix CPU bugs. */
#warning testing fixing bugs in initram
cpu_bug();
}

View file

@ -1,29 +1,29 @@
##
## This file is part of the LinuxBIOS project.
##
## Copyright (C) 2000,2007 Ronald G. Minnich <rminnich@gmail.com>
## Copyright (C) 2005 Eswar Nallusamy, LANL
## Copyright (C) 2005 Tyan
## (Written by Yinghai Lu <yhlu@tyan.com> for Tyan)
## Copyright (C) 2007 coresystems GmbH
## (Written by Stefan Reinauer <stepan@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
##
/*
* This file is part of the LinuxBIOS project.
*
* Copyright (C) 2000,2007 Ronald G. Minnich <rminnich@gmail.com>
* Copyright (C) 2005 Eswar Nallusamy, LANL
* Copyright (C) 2005 Tyan
* (Written by Yinghai Lu <yhlu@tyan.com> for Tyan)
* Copyright (C) 2007 coresystems GmbH
* (Written by Stefan Reinauer <stepan@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. */
/* Init code - Switch CPU to protected mode and enable Cache-as-Ram (CAR). */
#include "../macros.h"
#include <amd_geodelx.h>
@ -31,20 +31,20 @@
/* 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_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 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 ROM_CODE_SEG 0x08
#define ROM_DATA_SEG 0x10
#define CACHE_RAM_CODE_SEG 0x18
#define CACHE_RAM_DATA_SEG 0x20
#define CACHE_RAM_CODE_SEG 0x18
#define CACHE_RAM_DATA_SEG 0x20
.code16
.globl _stage0
@ -54,21 +54,19 @@ _stage0:
/* Save the BIST result. */
movl %eax, %ebp;
/* Thanks to kmliu@sis.com.tw for this TLB fix. */
/* IMMEDIATELY invalidate the translation lookaside buffer before
/* IMMEDIATELY invalidate the translation lookaside buffer (TLB) 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 */
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.
* all the ld hackery and so on. So leave it as is with this comment.
*/
data32 lgdt %cs:gdtptr
@ -84,18 +82,19 @@ _stage0:
// port80_post(0x23)
/* Now we are in protected mode. Jump to a 32 bit code segment. */
data32 ljmp $ROM_CODE_SEG, $protected_stage0
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
/* .byte 0x66 */
.code32
#ljmp $ROM_CODE_SEG, $protected_stage0
/* ljmp $ROM_CODE_SEG, $protected_stage0 */
#.code16
.align 4
/* .code16 */
.align 4
.globl gdt16
gdt16 = . - _stage0
gdt16 = . - _stage0
gdt16x:
.word gdt16xend - gdt16x -1 /* Compute the table limit. */
.long gdt16x
@ -118,22 +117,22 @@ gdt16xend:
* 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
* 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.
* Just in case you ever wonder why people do this.
*/
.align 4
.align 4
.globl gdtptr
.globl gdt_limit
gdt_limit = gdt_end - gdt - 1 /* Compute the table 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 gdt_end - gdt -1 /* Compute the table limit. */
.long gdt /* We know the offset. */
.word 0
/* selgdt 0x08, flat code segment */
@ -153,21 +152,20 @@ gdtptr:
.byte 0x00, 0x93, 0xcf, 0x00
gdt_end:
/*
* When we come here we are in protected mode. We expand the stack
/* 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
* 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
/* This code was used by v2. TODO. */
lgdt %cs:gdtptr
ljmp $ROM_CODE_SEG, $__protected_stage0
@ -188,17 +186,18 @@ __protected_stage0:
/* Restore the BIST value to %eax. */
movl %ebp, %eax
.align 4
.align 4
/* Here begins CAR support. */
/* This particular code is straight from LinuxBIOS V2. */
/* 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
@ -208,6 +207,7 @@ DCacheSetup:
*/
movl CPU_DM_CONFIG0,%ecx
rdmsr
/* TODO: Make consistent with i$ init, either whole reg = 0, or just
* this bit...
*/
@ -258,17 +258,18 @@ DCacheSetup:
movl $CPU_DC_INDEX, %ecx
wrmsr
/* Startaddress for tag of Way0: ebp will hold the incrementing
* address. dont destroy!
/* Start address for tag of Way0: ebp will hold the incrementing
* address. Don't 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
/* 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!
* the line counter. Don't destroy!
*/
movl $LX_NUM_CACHELINES, %edi
@ -298,12 +299,13 @@ DCacheSetup_quadWordLoop:
movl $CPU_DC_TAG, %ecx
wrmsr
/* Switch to next line. Lines are in Bits10:4. */
/* Switch to next line. Lines are in bits 10: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...
*/
@ -325,7 +327,8 @@ DCacheSetup_quadWordLoop:
movl $CPU_DC_INDEX, %ecx
rdmsr
addl $0x01, %eax
/* Let's be sure: reset line index Bits10:4. */
/* Let's be sure: reset line index bits 10:4. */
andl $0xFFFFF80F, %eax
wrmsr
@ -371,6 +374,7 @@ DCacheSetupGood:
*/
/* Clear the cache, the following code from crt0.S.lb will setup
* a new stack.
* TODO: There is no crt0.S.lb (anymore?).
*/
wbinvd
@ -387,6 +391,7 @@ DCacheSetupGood:
lout:
/* Restore the BIST result. */
movl %ebp, %eax
/* We need to set ebp? No need. */
movl %esp, %ebp
pushl %eax /* BIST */
@ -394,40 +399,43 @@ lout:
/* We will not go back. */
fixed_mtrr_msr:
.long 0x250, 0x258, 0x259
.long 0x268, 0x269, 0x26A
.long 0x26B, 0x26C, 0x26D
.long 0x26E, 0x26F
.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 */
.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.
/* 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)
* 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"
/* 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 )
/* 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
@ -436,8 +444,8 @@ _resetjump:
*/
.byte 0
# Date? ID string? We might want to put something else in here.
/* Date? ID string? We might want to put something else in here. */
.ascii DATE
# Checksum.
#.word 0
/* Checksum. */
/* .word 0 */

View file

@ -32,13 +32,15 @@
#include <spd.h>
/**
* 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.
*/
* Set up Geode LX registers for sane behaviour.
*
* Set all low memory (under 1MB) to write back. Do some setup for Cache
* as Ram (CAR) as well.
*/
void geodelx_msr_init(void)
{
struct msr msr;
struct msr msr;
/* Setup access to the cache for under 1MB. */
msr.hi = 0x24fffc02;
msr.lo = 0x1000A000; /* 0-A0000 write back */
@ -51,7 +53,7 @@ void geodelx_msr_init(void)
wrmsr(CPU_RCONF_E0_FF, msr);
/* Setup access to the cache for under 640K. */
/* Note memory controler not setup yet. */
/* Note: Memory controller not setup yet. */
msr.hi = 0x20000000;
msr.lo = 0x000fff80; /* 0-0x7FFFF */
wrmsr(MSR_GLIU0_BASE1, msr);
@ -67,6 +69,4 @@ void geodelx_msr_init(void)
msr.hi = 0x20000000;
msr.lo = 0x080fffe0; /* 0x80000-0x9FFFF */
wrmsr(MSR_GLIU0_BASE2, msr);
}