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:
parent
588f740124
commit
203bffe9e7
4 changed files with 341 additions and 313 deletions
|
|
@ -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},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue