- O2, enums, and switch statements work in romcc

- Support for compiling romcc on non x86 platforms
  - new romc options -msse and -mmmx for specifying extra registers to use
  - Bug fixes to device the device disable/enable framework and an amd8111 implementation
  - Move the link specification to the chip specification instead of the path
  - Allow specifying devices with internal bridges.
  - Initial via epia support
 - Opteron errata fixes


git-svn-id: svn://svn.coreboot.org/coreboot/trunk@1200 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
This commit is contained in:
Eric Biederman
2003-10-11 06:20:25 +00:00
parent 080038bfbd
commit 83b991afff
90 changed files with 8036 additions and 1974 deletions

View File

@@ -124,6 +124,9 @@
#define DCH_MEMCLK_EN3 (1 << 29)
/* Function 3 */
#define MCA_NB_CONFIG 0x44
#define MNC_ECC_EN (1 << 22)
#define MNC_CHIPKILL_EN (1 << 23)
#define SCRUB_CONTROL 0x58
#define SCRUB_NONE 0
#define SCRUB_40ns 1
@@ -1127,23 +1130,6 @@ static void spd_set_ram_size(const struct mem_controller *ctrl)
}
}
//BY LYH //Fill next base reg with right value
static void fill_last(unsigned long node_id,unsigned long base)
{
unsigned i;
unsigned base_reg;
base &=0xffff0000;
device_t device;
for(device = PCI_DEV(0, 0x18, 1); device <= PCI_DEV(0, 0x1f, 1); device
+= PCI_DEV(0, 1, 0)) {
for(i=node_id+1;i<=7;i++) {
base_reg=0x40+(i<<3);
pci_write_config32(device,base_reg,base);
}
}
}
//BY LYH END
static void route_dram_accesses(const struct mem_controller *ctrl,
unsigned long base_k, unsigned long limit_k)
{
@@ -1177,7 +1163,12 @@ static void set_top_mem(unsigned tom_k)
{
/* Error if I don't have memory */
if (!tom_k) {
die("No memory");
set_bios_reset();
print_debug("No memory - reset");
/* enable cf9 */
pci_write_config8(PCI_DEV(0, 0x04, 3), 0x41, 0xf1);
/* reset */
outb(0x0e, 0x0cf9);
}
#if 1
@@ -1204,15 +1195,102 @@ static void set_top_mem(unsigned tom_k)
wrmsr(TOP_MEM, msr);
}
static void order_dimms(const struct mem_controller *ctrl)
static unsigned long interleave_chip_selects(const struct mem_controller *ctrl)
{
unsigned long tom, tom_k, base_k;
unsigned node_id;
/* 35 - 25 */
static const uint32_t csbase_low[] = {
/* 32MB */ (1 << (13 - 4)),
/* 64MB */ (1 << (14 - 4)),
/* 128MB */ (1 << (14 - 4)),
/* 256MB */ (1 << (15 - 4)),
/* 512MB */ (1 << (15 - 4)),
/* 1GB */ (1 << (16 - 4)),
/* 2GB */ (1 << (16 - 4)),
};
uint32_t csbase_inc;
int chip_selects, index;
int bits;
int dual_channel;
unsigned common_size;
uint32_t csbase, csmask;
/* Compute the memory base address address */
base_k = 0;
/* See if all of the memory chip selects are the same size
* and if so count them.
*/
chip_selects = 0;
common_size = 0;
for(index = 0; index < 8; index++) {
unsigned size;
uint32_t value;
value = pci_read_config32(ctrl->f2, DRAM_CSBASE + (index << 2));
/* Is it enabled? */
if (!(value & 1)) {
continue;
}
chip_selects++;
size = value >> 21;
if (common_size == 0) {
common_size = size;
}
/* The size differed fail */
if (common_size != size) {
return 0;
}
}
/* Chip selects can only be interleaved when there is
* more than one and their is a power of two of them.
*/
bits = log2(chip_selects);
if (((1 << bits) != chip_selects) || (bits < 1) || (bits > 3)) {
return 0;
}
/* Also we run out of address mask bits if we try and interleave 8 4GB dimms */
if ((bits == 3) && (common_size == (1 << (32 - 3)))) {
print_debug("8 4GB chip selects cannot be interleaved\r\n");
return 0;
}
/* Find the bits of csbase that we need to interleave on */
if (is_dual_channel(ctrl)) {
csbase_inc = csbase_low[log2(common_size) - 1] << 1;
} else {
csbase_inc = csbase_low[log2(common_size)];
}
/* Compute the initial values for csbase and csbask.
* In csbase just set the enable bit and the base to zero.
* In csmask set the mask bits for the size and page level interleave.
*/
csbase = 0 | 1;
csmask = (((common_size << bits) - 1) << 21);
csmask |= 0xfe00 & ~((csbase_inc << bits) - csbase_inc);
for(index = 0; index < 8; index++) {
uint32_t value;
value = pci_read_config32(ctrl->f2, DRAM_CSBASE + (index << 2));
/* Is it enabled? */
if (!(value & 1)) {
continue;
}
pci_write_config32(ctrl->f2, DRAM_CSBASE + (index << 2), csbase);
pci_write_config32(ctrl->f2, DRAM_CSMASK + (index << 2), csmask);
csbase += csbase_inc;
}
#if 1
print_debug("Interleaved\r\n");
#endif
/* Return the memory size in K */
return common_size << (15 + bits);
}
static unsigned long order_chip_selects(const struct mem_controller *ctrl)
{
unsigned long tom;
/* Remember which registers we have used in the high 8 bits of tom */
tom = base_k >> 15;
tom = 0;
for(;;) {
/* Find the largest remaining canidate */
unsigned index, canidate;
@@ -1270,8 +1348,19 @@ static void order_dimms(const struct mem_controller *ctrl)
pci_write_config32(ctrl->f2, DRAM_CSMASK + (canidate << 2), csmask);
}
tom_k = (tom & ~0xff000000) << 15;
/* Return the memory size in K */
return (tom & ~0xff000000) << 15;
}
static void order_dimms(const struct mem_controller *ctrl)
{
unsigned long tom, tom_k, base_k;
unsigned node_id;
tom_k = interleave_chip_selects(ctrl);
if (!tom_k) {
tom_k = order_chip_selects(ctrl);
}
/* Compute the memory base address */
base_k = 0;
for(node_id = 0; node_id < ctrl->node_id; node_id++) {
@@ -1287,18 +1376,13 @@ static void order_dimms(const struct mem_controller *ctrl)
}
tom_k += base_k;
#if 0
print_debug("tom: ");
print_debug_hex32(tom);
print_debug(" base_k: ");
print_debug("base_k: ");
print_debug_hex32(base_k);
print_debug(" tom_k: ");
print_debug_hex32(tom_k);
print_debug("\r\n");
#endif
route_dram_accesses(ctrl, base_k, tom_k);
//BY LYH
fill_last(ctrl->node_id, tom_k<<2);
//BY LYH END
set_top_mem(tom_k);
}
@@ -2063,6 +2147,10 @@ static void set_read_preamble(const struct mem_controller *ctrl, const struct me
/* 166Mhz, 7.5ns */
rdpreamble = ((7 << 1)+1);
}
else if (divisor == ((5 << 1)+0)) {
/* 200Mhz, 7ns */
rdpreamble = ((7 << 1)+0);
}
}
else {
int slots;
@@ -2175,6 +2263,8 @@ static void spd_set_dram_timing(const struct mem_controller *ctrl, const struct
{
int dimms;
int i;
int rc;
init_Tref(ctrl, param);
for(i = 0; (i < 4) && ctrl->channel0[i]; i++) {
int rc;
@@ -2247,13 +2337,16 @@ static void sdram_enable(int controllers, const struct mem_controller *ctrl)
print_debug_hex32(dcl);
print_debug("\r\n");
#endif
#warning "FIXME set the ECC type to perform"
#warning "FIXME initialize the scrub registers"
#if 1
if (dcl & DCL_DimmEccEn) {
uint32_t mnc;
print_debug("ECC enabled\r\n");
mnc = pci_read_config32(ctrl[i].f3, MCA_NB_CONFIG);
mnc |= MNC_ECC_EN;
if (dcl & DCL_128BitEn) {
mnc |= MNC_CHIPKILL_EN;
}
pci_write_config32(ctrl[i].f3, MCA_NB_CONFIG, mnc);
}
#endif
dcl |= DCL_DisDqsHys;
pci_write_config32(ctrl[i].f2, DRAM_CONFIG_LOW, dcl);
dcl &= ~DCL_DisDqsHys;
@@ -2280,29 +2373,148 @@ static void sdram_enable(int controllers, const struct mem_controller *ctrl)
} else {
print_debug(" done\r\n");
}
#if 0
if (dcl & DCL_DimmEccEn) {
print_debug("Clearing memory: ");
loops = 0;
dcl &= ~DCL_MemClrStatus;
pci_write_config32(ctrl[i].f2, DRAM_CONFIG_LOW, dcl);
do {
dcl = pci_read_config32(ctrl[i].f2, DRAM_CONFIG_LOW);
loops += 1;
if ((loops & 1023) == 0) {
print_debug(" ");
print_debug_hex32(loops);
}
} while(((dcl & DCL_MemClrStatus) == 0) && (loops < TIMEOUT_LOOPS));
if (loops >= TIMEOUT_LOOPS) {
print_debug("failed\r\n");
} else {
print_debug("done\r\n");
if (!is_cpu_pre_c0()) {
/* Wait until the automatic ram scrubber is finished */
dcl &= ~(DCL_MemClrStatus | DCL_DramEnable);
pci_write_config32(ctrl[i].f2, DRAM_CONFIG_LOW, dcl);
do {
dcl = pci_read_config32(ctrl[i].f2, DRAM_CONFIG_LOW);
} while(((dcl & DCL_MemClrStatus) == 0) || ((dcl & DCL_DramEnable) == 0) );
}
pci_write_config32(ctrl[i].f3, SCRUB_ADDR_LOW, 0);
pci_write_config32(ctrl[i].f3, SCRUB_ADDR_HIGH, 0);
}
uint32_t base, last_scrub_k, scrub_k;
uint32_t cnt,zstart,zend;
msr_t msr,msr_201;
/* First make certain the scrubber is disabled */
pci_write_config32(ctrl[i].f3, SCRUB_CONTROL,
(SCRUB_NONE << 16) | (SCRUB_NONE << 8) | (SCRUB_NONE << 0));
/* load the start and end for the memory block to clear */
msr_201 = rdmsr(0x201);
zstart = pci_read_config32(ctrl[0].f1, 0x40 + (i*8));
zend = pci_read_config32(ctrl[0].f1, 0x44 + (i*8));
zstart >>= 16;
zend >>=16;
#if 1
print_debug("addr ");
print_debug_hex32(zstart);
print_debug("-");
print_debug_hex32(zend);
print_debug("\r\n");
#endif
/* Disable fixed mtrrs */
msr = rdmsr(MTRRdefType_MSR);
msr.lo &= ~(1<<10);
wrmsr(MTRRdefType_MSR, msr);
/* turn on the wrap 32 disable */
msr = rdmsr(0xc0010015);
msr.lo |= (1<<17);
wrmsr(0xc0010015,msr);
for(;zstart<zend;zstart+=4) {
/* test for the last 64 meg of 4 gig space */
if(zstart == 0x0fc)
continue;
/* disable cache */
__asm__ volatile(
"movl %%cr0, %0\n\t"
"orl $0x40000000, %0\n\t"
"movl %0, %%cr0\n\t"
:"=r" (cnt)
);
/* Set the variable mtrrs to write combine */
msr.lo = 1 + ((zstart&0x0ff)<<24);
msr.hi = (zstart&0x0ff00)>>8;
wrmsr(0x200,msr);
/* Set the limit to 64 meg of ram */
msr.hi = 0x000000ff;
msr.lo = 0xfc000800;
wrmsr(0x201,msr);
/* enable cache */
__asm__ volatile(
"movl %%cr0, %0\n\t"
"andl $0x9fffffff, %0\n\t"
"movl %0, %%cr0\n\t"
:"=r" (cnt)
);
/* Set fs base address */
msr.lo = (zstart&0xff) << 24;
msr.hi = (zstart&0xff00) >> 8;
wrmsr(0xc0000100,msr);
print_debug_char((zstart > 0x0ff)?'+':'-');
/* clear memory 64meg */
__asm__ volatile(
"1: \n\t"
"movl %0, %%fs:(%1)\n\t"
"addl $4,%1\n\t"
"subl $1,%2\n\t"
"jnz 1b\n\t"
:
: "a" (0), "D" (0), "c" (0x01000000)
);
}
/* disable cache */
__asm__ volatile(
"movl %%cr0, %0\n\t"
"orl $0x40000000, %0\n\t"
"movl %0, %%cr0\n\t"
:"=r" (cnt)
);
/* restore msr registers */
msr = rdmsr(MTRRdefType_MSR);
msr.lo |= 0x0400;
wrmsr(MTRRdefType_MSR, msr);
/* Restore the variable mtrrs */
msr.lo = 6;
msr.hi = 0;
wrmsr(0x200,msr);
wrmsr(0x201,msr_201);
/* Set fs base to 0 */
msr.lo = 0;
msr.hi = 0;
wrmsr(0xc0000100,msr);
/* enable cache */
__asm__ volatile(
"movl %%cr0, %0\n\t"
"andl $0x9fffffff, %0\n\t"
"movl %0, %%cr0\n\t"
:"=r" (cnt)
);
/* turn off the wrap 32 disable */
msr = rdmsr(0xc0010015);
msr.lo &= ~(1<<17);
wrmsr(0xc0010015,msr);
/* Find the Srub base address for this cpu */
base = pci_read_config32(ctrl[i].f1, 0x40 + (ctrl[i].node_id << 3));
base &= 0xffff0000;
/* Set the scrub base address registers */
pci_write_config32(ctrl[i].f3, SCRUB_ADDR_LOW, base << 8);
pci_write_config32(ctrl[i].f3, SCRUB_ADDR_HIGH, base >> 24);
/* Enable scrubbing at the lowest possible rate */
pci_write_config32(ctrl[i].f3, SCRUB_CONTROL,
(SCRUB_84ms << 16) | (SCRUB_84ms << 8) | (SCRUB_84ms << 0));
print_debug("done\r\n");
}
}
}