New files; these do result in a buildable l440gx+ linuxbios

This commit is contained in:
Ronald G. Minnich 2000-11-13 18:15:00 +00:00
parent 1cabbaa0dd
commit d496bf5e53
4 changed files with 1033 additions and 0 deletions

View file

@ -0,0 +1,8 @@
#include <printk.h>
#include <pci.h>
#include <cpu/p5/io.h>
void mainboard_fixup()
{
}

View file

@ -0,0 +1,30 @@
#include <pci.h>
unsigned long sizeram()
{
/*
* This is written for BX but should work also for GX.
*/
unsigned long totalmem;
unsigned char banks;
struct pci_dev *pcidev;
/* pci_find_device is way overkill for the host bridge!
* Plus the BX & GX have different device numbers so it
* prevents code sharing.
*/
pcidev = pci_find_slot(0, PCI_DEVFN(0,0));
pci_read_config_byte(pcidev, 0x67, &banks);
totalmem = (unsigned long) banks *8 * 1024;
if (banks == 0) {
totalmem = 0x80000000UL;
}
return totalmem;
}

View file

@ -0,0 +1,38 @@
#include <pci.h>
unsigned long sizeram()
{
/*
* This is written for BX but should work also for GX.
*/
unsigned long totalmem;
unsigned char banks;
struct pci_dev *pcidev;
/* pci_find_device is way overkill for the host bridge!
* Plus the BX & GX have different device numbers so it
* prevents code sharing.
*/
pcidev = pci_find_slot(0, PCI_DEVFN(0,0));
pci_read_config_byte(pcidev, 0x67, &banks);
totalmem = (unsigned long) banks *8 * 1024;
if (banks == 0) {
totalmem = 0x80000000UL;
}
return totalmem;
}
#ifdef HAVE_FRAMEBUFFER
void intel_framebuffer_on()
{
outl(0x8000a004, 0xcf8);
outb(0x03, 0xcfc);
}
#endif

View file

@ -0,0 +1,957 @@
jmp intel_440_out
#define USE_SPD 1
#define CS_WRITE_BYTE(addr, byte) \
movl $addr, %eax ; \
movl $byte, %edx ; \
PCI_WRITE_CONFIG_BYTE
#define CS_WRITE_WORD(addr, word) \
movl $addr, %eax ; \
movl $word, %ecx ; \
PCI_WRITE_CONFIG_WORD
#define CS_WRITE_LONG(addr, dword) \
movl $addr, %eax ; \
movl $dword, %ecx ; \
PCI_WRITE_CONFIG_DWORD
#if 0
#define DRB0 0x08
#define DRB1 0x10
#define DRB2 0x18
#define DRB3 0x20
#define DRB4 0x20
#define DRB5 0x20
#define DRB6 0x20
#define DRB7 0x20
#else
/* Conservative setting 8MB of ram on first DIMM... */
#define DRB0 0x01
#define DRB1 0x01
#define DRB2 0x01
#define DRB3 0x01
#define DRB4 0x01
#define DRB5 0x01
#define DRB6 0x01
#define DRB7 0x01
#endif
#define CAS_LATENCY 3
/* CAS latency 2 */
#if (CAS_LATENCY == 2)
#define CAS_NB 0x17
/*
* 7 == 0111
* 1 == 0001
*/
#define CAS_MODE 0x2a
/*
* a == 1010
* 2 == 0010
*/
#endif
/* CAS latency 3 */
#if (CAS_LATENCY == 3)
#define CAS_NB 0x13
/*
* 3 == 0011
* 1 == 0001
*/
#define CAS_MODE 0x3a
/*
* a == 1010
* 3 == 0011
*/
#endif
#ifndef CAS_NB
#error "Nothing defined"
#endif
#define RAM_READ 0x0400
#define DIMM0_BASE \
xorl %eax, %eax
#define DIMM_BASE(n) \
movl $(0x60 + ((n) -1)), %eax ; \
PCI_READ_CONFIG_BYTE ; \
andl $0xFF, %eax ; \
shll $23, %eax ; \
#define DIMM_READ \
addl %ebx, %eax ; \
movl (%eax), %edx ; \
xorl $0xdff8, %eax ; \
movl (%eax), %edx
#define DIMM0_READ DIMM0_BASE ; DIMM_READ
#define DIMM1_READ DIMM_BASE(1) ; DIMM_READ
#define DIMM2_READ DIMM_BASE(2) ; DIMM_READ
#define DIMM3_READ DIMM_BASE(3) ; DIMM_READ
#define DIMM4_READ DIMM_BASE(4) ; DIMM_READ
#define DIMM5_READ DIMM_BASE(5) ; DIMM_READ
#define DIMM6_READ DIMM_BASE(6) ; DIMM_READ
#define DIMM7_READ DIMM_BASE(7) ; DIMM_READ
#define DIMMS_READ_EBX_OFFSET \
DIMM0_READ ; \
DIMM1_READ ; \
DIMM2_READ ; \
DIMM3_READ ; \
DIMM4_READ ; \
DIMM5_READ ; \
DIMM6_READ ; \
DIMM7_READ
#define DIMMS_READ(offset) \
movl $offset, %ebx ; \
DIMMS_READ_EBX_OFFSET
#define RAM_COMMAND_NONE 0x0
#define RAM_COMMAND_NOP 0x1
#define RAM_COMMAND_PRECHARGE 0x2
#define RAM_COMMAND_MRS 0x3
#define RAM_COMMAND_CBR 0x4
#define SET_RAM_COMMAND(command) \
movl $0x76, %eax ; \
PCI_READ_CONFIG_BYTE ; \
andl $0x1F, %eax ; \
orl $((command) << 5), %eax ; \
movl %eax, %edx ; \
movl $0x76, %eax ; \
PCI_WRITE_CONFIG_BYTE
#define COMPUTE_CAS_MODE \
movl $0x76, %eax ; \
PCI_READ_CONFIG_BYTE ; \
andl $0x4, %eax ; \
xorl $0x4, %eax ; \
shll $2, %eax ; \
orl $0x2a, %eax ; \
#define SET_RAM_MODE_REGISTER \
SET_RAM_COMMAND(RAM_COMMAND_MRS) ; \
COMPUTE_CAS_MODE ; \
shll $3, %eax ; \
movl %eax, %ebx ; \
DIMMS_READ_EBX_OFFSET
#define ASSERT_RAM_COMMAND() DIMMS_READ(RAM_READ)
#define ASSERT_MRS_RAM_COMMAND(mode) DIMMS_READ(mode)
#if ! USE_SPD
#define ENABLE_REFRESH() CS_BIS_BYTE(0x57, 0x1)
#else /* USE_SPD */
#define ENABLE_REFRESH() CALL_LABEL(spd_enable_refresh)
#endif
/* Default values for config registers */
/* NBXCFG 0x50 - 0x53 */
/* f == 1111
* 0 == 0000
* 0 == 0000
* 0 == 0000
* 0 == 0000
* 1 == 0001
* 8 == 1000
* c == 1100
* SDRAM Row without ECC:
* row 0 == 1 No ECC
* row 1 == 1 No ECC
* row 2 == 1 No ECC
* row 3 == 1 No ECC
* row 4 == 1 No ECC
* row 5 == 1 No ECC
* row 6 == 1 No ECC
* row 7 == 1 No ECC
* Host Bus Fast Data Ready Enable == 0 Disabled
* IDSEL_REDIRECT == 0 (430TX compatibility disable?)
* WSC# Hanshake Disable == 0 enable (Use External IOAPIC)
* Host/DRAM Frequence == 00 100Mhz
* AGP to PCI Access Enable == 0 Disable
* PCI Agent to Aperture Access Disable == 0 Enable (Ignored)
* Aperture Access Global Enable == 0 Disable
* DRAM Data Integrity Mode == 11 (Error Checking/Correction)
* ECC Diagnostic Mode Enable == 0 Not Enabled
* MDA present == 0 Not Present
* USWC Write Post During During I/O Bridge Access Enable == 1 Enabled
* In Order Queue Depth (IQD) (RO) == ??
*/
#if 0
#define SET_NBXCFG \
CS_WRITE_LONG(0x50, 0xff00018c)
#else
#define SET_NBXCFG \
CS_WRITE_LONG(0x50, 0xff00000c)
#endif
#define SET_DRAMC \
/* DRAMC */ \
CS_WRITE_BYTE(0x57, 0x8) \
/* 0 == 0000 \
* 8 == 1000 \
* Not registered SDRAM \
* refresh disabled \
*/
#define SET_PAM \
/* PAM - Programmable Attribute Map Registers */ \
/* Ideally we want to enable all of these as DRAM and teach
* linux it is o.k. to use them...
*/
CS_WRITE_BYTE(0x59, 0x00) ; \
CS_WRITE_BYTE(0x5a, 0x00) ; \
CS_WRITE_BYTE(0x5b, 0x00) ; \
CS_WRITE_BYTE(0x5c, 0x00) ; \
CS_WRITE_BYTE(0x5d, 0x00) ; \
CS_WRITE_BYTE(0x5e, 0x00) ; \
CS_WRITE_BYTE(0x5f, 0x00)
#define SET_DRB \
/* DRB - DRAM Row Boundary Registers */ \
CS_WRITE_BYTE(0x60, DRB0) ; \
CS_WRITE_BYTE(0x61, DRB1) ; \
CS_WRITE_BYTE(0x62, DRB2) ; \
CS_WRITE_BYTE(0x63, DRB3) ; \
CS_WRITE_BYTE(0x64, DRB4) ; \
CS_WRITE_BYTE(0x65, DRB5) ; \
CS_WRITE_BYTE(0x66, DRB6) ; \
CS_WRITE_BYTE(0x67, DRB7)
/* FDHC */
#define SET_FDHC \
CS_WRITE_BYTE(0x68, 0x00)
#if 0
/* MBSC - Memory Buffer Strength Control */
/* 00c00003e820
* [47:44] 0 == 0000
* [43:40] 0 == 0000
* [39:36] c == 1100
* [35:32] 0 == 0000
* [31:28] 0 == 0000
* [27:24] 0 == 0000
* [23:20] 0 == 0000
* [19:16] 3 == 0011
* [15:12] e == 1110
* [11: 8] 8 == 1000
* [ 7: 4] 2 == 0010
* [ 3: 0] 0 == 0000
* MAA[14:0]#, WEA#, SRASA#, SCASA# Buffer Strengths == 3x
* MAB[14,13,10,12:11,9:0]#, WEB#, SRASB#, SCASB# Buffer Strengths == 1x
* MD[63:0]# Buffer Strength Control 2 == 1x
* MD[63:0]# Buffer Strength Control 1 == 1x
* MECC[7:0] Buffer Strength Control 2 == 1x
* MECC[7:0] Buffer Strength Control 1 == 1x
* CSB7# Buffer Strength == 1x
* CSA7# Buffer Strength == 1x
* CSB6# Buffer Strength == 1x
* CSA6# Buffer Strength == 1x
* CSA5#/CSB5# Buffer Strength == 1x
* CSA4#/CSB4# Buffer Strength == 1x
* CSA3#/CSB3# Buffer Strength == 2x
* CSA2#/CSB2# Buffer Strength == 2x
* CSA1#/CSB1# Buffer Strength == 2x
* CSA0#/CSB0# Buffer Strength == 2x
* DQMA5 Buffer Strength == 2x
* DQMA1 Buffer Strength == 2x
* DQMB5 Buffer Strength == 1x
* DQMB1 Buffer Strength == 1x
* DQMA[7:6,4:2,0] Buffer Strength == 2x
* GCKE Buffer Strength == 1x
* FENA Buffer Strength == 1x
*/
#define SET_MBSC \
CS_WRITE_BYTE(0x69, 0x20) ; \
CS_WRITE_BYTE(0x6a, 0xe8) ; \
CS_WRITE_BYTE(0x6b, 0x03) ; \
CS_WRITE_BYTE(0x6c, 0x00) ; \
CS_WRITE_BYTE(0x6d, 0xc0) ; \
CS_WRITE_BYTE(0x6e, 0x00)
#else
/* MBSC - Memory Buffer Strength Control */
/* 00c00003e820
* [47:44] 0 == 0000
* [43:40] 0 == 0000
* [39:36] c == 1100
* [35:32] 0 == 0000
* [31:28] 0 == 0000
* [27:24] 0 == 0000
* [23:20] 0 == 0000
* [19:16] 3 == 0011
* [15:12] e == 1110
* [11: 8] 8 == 1000
* [ 7: 4] 2 == 0010
* [ 3: 0] 0 == 0000
* MAA[14:0]#, WEA#, SRASA#, SCASA# Buffer Strengths == 3x
* MAB[14,13,10,12:11,9:0]#, WEB#, SRASB#, SCASB# Buffer Strengths == 3x
* MD[63:0]# Buffer Strength Control 2 == 3x
* MD[63:0]# Buffer Strength Control 1 == 3x
* MECC[7:0] Buffer Strength Control 2 == 3x
* MECC[7:0] Buffer Strength Control 1 == 3x
* CSB7# Buffer Strength == 3x
* CSA7# Buffer Strength == 3x
* CSB6# Buffer Strength == 3x
* CSA6# Buffer Strength == 3x
* CSA5#/CSB5# Buffer Strength == 2x
* CSA4#/CSB4# Buffer Strength == 2x
* CSA3#/CSB3# Buffer Strength == 2x
* CSA2#/CSB2# Buffer Strength == 2x
* CSA1#/CSB1# Buffer Strength == 2x
* CSA0#/CSB0# Buffer Strength == 2x
* DQMA5 Buffer Strength == 2x
* DQMA1 Buffer Strength == 3x
* DQMB5 Buffer Strength == 2x
* DQMB1 Buffer Strength == 2x
* DQMA[7:6,4:2,0] Buffer Strength == 3x
* GCKE Buffer Strength == 1x
* FENA Buffer Strength == 3x
*/
#define SET_MBSC \
CS_WRITE_BYTE(0x69, 0xB3) ; \
CS_WRITE_BYTE(0x6a, 0xee) ; \
CS_WRITE_BYTE(0x6b, 0xff) ; \
CS_WRITE_BYTE(0x6c, 0xff) ; \
CS_WRITE_BYTE(0x6d, 0xff) ; \
CS_WRITE_BYTE(0x6e, 0x03)
#endif
/* 0x72 SMRAM */
/* 1 == 0001
* a == 1010
* SMM Compatible base segment == 010 (Hardcoded value)
*/
#define SET_SMRAM
/* 0x73 ESMRAMC */
#define SET_ESRAMC
/* RPS - Row Page Size Register */
/* 0x0055
* [15:12] 0 == 0000
* [11: 8] 0 == 0000
* [ 7: 4] 5 == 0101
* [ 3: 0] 5 == 0101
* DRB[0] == 4KB
* DRB[1] == 4KB
* DRB[2] == 4KB
* DRB[3] == 4KB
* DRB[4] == 2KB
* DRB[5] == 2KB
* DRB[6] == 2KB
* DRB[7] == 2KB
*/
#define SET_RPS \
CS_WRITE_WORD(0x74, 0x0055)
/* SDRAMC */
#define SET_SDRAMC \
CS_WRITE_BYTE(0x76, CAS_NB)
/* PGPOL - Paging Policy Register */
/* 0xff07
* [15:12] f == 1111
* [11: 8] f == 1111
* [ 7: 4] 0 == 0000
* [ 3: 0] 7 == 0111
* row0 == 4banks
* row1 == 4banks
* row2 == 4banks
* row3 == 4banks
* row4 == 4banks
* row5 == 4banks
* row6 == 4banks
* row7 == 4banks
* Dram Idle Timer (DIT) == 32 clocks
*/
#define SET_PGPOL \
CS_WRITE_WORD(0x78, 0xff07)
/* MBFS - Memory Buffer Frequencey Select Register */
/* 0xffff7f
* [23:20] f == 1111
* [19:16] f == 1111
* [15:12] f == 1111
* [11: 8] f == 1111
* [ 7: 4] 7 == 0111
* [ 3: 0] f == 1111
* MAA[14:0], WEA#, SRASA#, SCASA# == 100Mhz Buffers Enabled
* MAB[14,13,10,12:11,9:0], WEB#, SRASB#, SCASB# == 100Mhz Buffers Enabled
* MD[63:0] Control 2 == 100 Mhz Buffer Enable
* MD[63:0] Control 1 == 100 Mhz B
* MECC[7:0] Control 2 == 100 Mhz B
*
*/
#define SET_MBFS \
CS_WRITE_BYTE(0xca, 0xff) ; \
CS_WRITE_BYTE(0xcb, 0xff) ; \
CS_WRITE_BYTE(0xcc, 0x7f)
/* DWTC - DRAM Write Thermal Throttle Control */
#define SET_DWTC \
CS_WRITE_BYTE(0xe0, 0xb4) ; \
CS_WRITE_BYTE(0xe1, 0xbe) ; \
CS_WRITE_BYTE(0xe2, 0xff) ; \
CS_WRITE_BYTE(0xe3, 0xd7) ; \
CS_WRITE_BYTE(0xe4, 0x97) ; \
CS_WRITE_BYTE(0xe5, 0x3e) ; \
CS_WRITE_BYTE(0xe6, 0x00) ; \
CS_WRITE_BYTE(0xe7, 0x80)
/* DRTC - DRAM Read Thermal Throttle Control */
#define SET_DRTC \
CS_WRITE_BYTE(0xe8, 0x2c) ; \
CS_WRITE_BYTE(0xe9, 0xd3) ; \
CS_WRITE_BYTE(0xea, 0xf7) ; \
CS_WRITE_BYTE(0xeb, 0xcf) ; \
CS_WRITE_BYTE(0xec, 0x9d) ; \
CS_WRITE_BYTE(0xed, 0x3e) ; \
CS_WRITE_BYTE(0xee, 0x00) ; \
CS_WRITE_BYTE(0xef, 0x00)
ram_set_registers:
SET_NBXCFG
SET_DRAMC
SET_PAM
SET_DRB
SET_FDHC
SET_MBSC
SET_SMRAM
SET_ESRAMC
SET_RPS
SET_SDRAMC
SET_PGPOL
SET_MBFS
SET_DWTC
SET_DRTC
RET_LABEL(ram_set_registers)
#define DEVFN(device, function) (((device) << 3) + (function))
#define CONFIG_ADDR(bus,devfn,where) (((bus) << 16) | ((devfn) << 8) | (where))
#define PM_FUNCTION CONFIG_ADDR(0, PIIX4_DEVFN+3, 0)
#define SMBUS_IO_BASE 0x1000
#define SMBHSTSTAT 0
#define SMBHSTCTL 2
#define SMBHSTCMD 3
#define SMBHSTADD 4
#define SMBHSTDAT0 5
#define SMBHSTDAT1 6
#define SMBBLKDAT 7
enable_smbus:
CS_WRITE_LONG(PM_FUNCTION + 0x90, SMBUS_IO_BASE | 1) /* iobase addr */
CS_WRITE_BYTE(PM_FUNCTION + 0xd2, (0x4 << 1) | 1) /* smbus enable */
CS_WRITE_WORD(PM_FUNCTION + 0x4, 1) /* iospace enable */
RET_LABEL(enable_smbus)
/*
* Routine: setup_smbus
* Arguments: none
* Results: none
* Trashed: eax, edx
* Effects: The smbus is enabled
*/
setup_smbus:
xor %eax,%eax
movl $(SMBUS_IO_BASE + SMBHSTSTAT), %edx
outb %al, %dx
RET_LABEL(setup_smbus)
#define SMBUS_MEM_DEVICE_0 (0xa << 3)
#define SMBUS_MEM_DEVICE_1 (SMBUS_MEM_DEVICE_0 +1)
#define SMBUS_MEM_DEVICE_2 (SMBUS_MEM_DEVICE_0 +2)
#define SMBUS_MEM_DEVICE_3 (SMBUS_MEM_DEVICE_0 +3)
/*
* Routine: smbus_wait_until_ready
* Arguments: none
* Results: none
* Trashed: eax, edx
* Effects: Upon return the smbus is ready to accept commands
*/
smbus_wait_until_ready:
movl $(SMBUS_IO_BASE + SMBHSTSTAT), %edx
1: inb %dx, %al
testb $1, %al
jnz 1b
RET_LABEL(smbus_wait_until_ready)
/*
* Routine: smbus_wait_until_done
* Arguments: none
* Results: none
* Trashed: eax, edx
* Effects: Upon return the smbus has completed it's most recent transation
*/
smbus_wait_until_done:
movl $(SMBUS_IO_BASE + SMBHSTSTAT), %edx
1: inb %dx, %al
testb $1, %al
jnz 1b
2: testb $0xFE, %al
jnz 3f
inb %dx, %al
testb $0xFE, %al
jz 2b
3: RET_LABEL(smbus_wait_until_done)
/*
* Routine: smbus_read_byte
* Arguments: %esp return address
* %bl device on the smbus to read from
* %bh address on the smbus to read
*
* Results: zf clear
* byte read %eax
* On Error:
* zf set
* %eax trashed
*
* Trashed: %edx, %eax
* Effects: reads a byte off of the smbus
*/
#define SMBUS_READ_BYTE(device, address) \
movl $( (device) | ((address) << 8)), %ebx ; \
CALLSP(smbus_read_byte)
smbus_read_byte:
/* poll until the smbus is ready for commands */
CALL_LABEL(smbus_wait_until_ready)
/* clear any lingering errors, so that the transaction will run */
movl $(SMBUS_IO_BASE + SMBHSTSTAT), %edx
inb %dx, %al
outb %al, %dx
/* set the device I'm talking to */
movl $(SMBUS_IO_BASE + SMBHSTADD), %edx
movb %bl /* device */, %al
shlb $1, %al
orb $1, %al
outb %al, %dx
/* set the command address... */
movl $(SMBUS_IO_BASE + SMBHSTCMD), %edx
movb %bh /* address */, %al
outb %al, %dx
/* clear the data byte */
movl $(SMBUS_IO_BASE + SMBHSTDAT0), %edx
xorl %eax, %eax
outb %al, %dx
/* start a byte read, with interrupts disabled */
movl $(SMBUS_IO_BASE + SMBHSTCTL), %edx
movl $((0x2 << 2) | (1 << 6)), %eax
outb %al, %dx
/* poll for transaction completion */
CALL_LABEL(smbus_wait_until_done)
/* read the results and see if we succeded */
movl $(SMBUS_IO_BASE + SMBHSTSTAT), %edx
inb %dx, %al
testb $0x02, %al
jz 1f
movl $(SMBUS_IO_BASE + SMBHSTDAT0), %edx
inb %dx, %al
1:
RETSP
/*
* Routine: spd_set_drb
* Arguments: None
*
* Trashed: %eax, %ebx, %ecx, %edx, %esi, %edi, %ebp, %esp, %eflags
* Effects: Uses serial presence detect to set the
* DRB registers which holds the ending memory address assigned
* to each DIMM.
* Notes: %ebp holds the currently detected end of memory.
* %ebx holds the configuration port & SMBUS_MEM_DEVICE for
* the current iteration through the loop.
* %edi holds the memory size for the first side of the DIMM.
* %esi holds the memory size for the second side of the DIMM.
* memory size is represent as a power of 2.
* An unset memory size is represented as -1 ie. 0xFFFFFFFF
*/
spd_set_drb:
#define SPD_SETUP_DIMM(SMBUS_MEM_DEVICE, CONFIG_PORT) \
xorl %ebp, %ebp /* clear the memory address */
movl $((0x60 << 16) |SMBUS_MEM_DEVICE_0), %ebx
spd_set_drb_loop_top:
xorl %edi, %edi
subl $1, %edi
xorl %esi, %esi
subl $1, %esi
movb $3, %bh /* rows */
CALLSP(smbus_read_byte)
jz 20f
andl $0xf, %eax
addl %eax, %edi
movb $4, %bh /* columns */
CALLSP(smbus_read_byte)
andl $0xf, %eax
addl %eax, %edi
movb $17, %bh /* banks */
CALLSP(smbus_read_byte)
andl $0xff, %eax
bsrl %eax, %ecx
addl %ecx, %edi
/* Get the module data width and convert it to a power of two */
movb $7, %bh /* (high byte) */
CALLSP(smbus_read_byte)
andl $0xff, %eax
movl %eax, %ecx
shll $8, %ecx
movb $6, %bh /* (low byte) */
CALLSP(smbus_read_byte)
andl $0xff, %eax
orl %eax, %ecx
bsrl %ecx, %eax
addl %eax, %edi
/* now I have the ram size in bits as a power of two (less 1) */
subl $25, %edi /* Make it multiples of 8MB */
/* side two */
movb $5, %bh /* number of physical banks */
CALLSP(smbus_read_byte)
cmp $1, %al
jbe 20f
/* for now only handle the symmetrical case */
movl %edi, %esi
/* Compute the end address for the DRB register */
cmpl $8, %edi
jae 20f
movl $1, %eax
movl %edi, %ecx
shll %cl, %eax
addl %eax, %ebp
20:
/* Write the comuputed value for the first half of the DIMM */
movl %ebp, %edx /* value to write into %edx */
movl %ebx, %eax
shrl $16, %eax /* port address into %eax */
PCI_WRITE_CONFIG_BYTE
/* Compute the end address for the DRB register */
cmpl $8, %esi
jae 30f
mov $1, %eax
movl %esi, %ecx
shll %cl, %eax
addl %eax, %ebp
30:
/* Write the comuputed value for the second half of the DIMM */
movl %ebp, %edx /* value to write into %edx */
movl %ebx, %eax
shrl $16, %eax /* port address into %eax */
addl $1, %eax /* The second half uses one port high */
PCI_WRITE_CONFIG_BYTE
addl $0x00020001, %ebx /* increment the smbus device & the config port */
cmpb $SMBUS_MEM_DEVICE_3, %bl /* see if I have reached the end */
jbe spd_set_drb_loop_top
/* o.k. I'm done return now */
RET_LABEL(spd_set_drb)
/*
* Routine: spd_set_dramc
* Arguments: None
*
* Trashed: %eax, %ebx, %edx, %esp, %eflags
* Effects: Uses serial presence detect to set the
* DRAMC register, which records if ram is registerd or not,
* and controls the refresh rate.
* The refresh rate is not set here, as memory refresh
* cannot be enbaled until after memory is initialized.
* see spd_enable_refresh.
* Notes:
* FIXME: Check for illegal/unsupported ram configurations and abort
*/
spd_set_dramc:
/* auto detect if ram is registered or not. */
/* The DRAMC register also contorls the refresh rate but we can't
* set that here because we must leave refresh disabled.
* see: spd_enable_refresh
*/
/* Find the first dimm and assume the rest are the same */
/* Load the smbus device and port int %ebx */
movl $((21 << 8) | SMBUS_MEM_DEVICE_0), %ebx
1: CALLSP(smbus_read_byte)
jz 2f
andl $0x12, %eax
jmp spd_set_dramc_out
2: addl $1, %ebx /* increment the device */
cmpb $SMBUS_MEM_DEVICE_3, %bl
jbe 1b
/* We couldn't find anything we must have no memory */
jmp no_memory
spd_set_dramc_out:
testb $0x12, %al
movl $8, %eax
jz 1f
movl $0x10, %eax
1: movl %eax, %edx
movl $0x57, %eax
PCI_WRITE_CONFIG_BYTE
RET_LABEL(spd_set_dramc)
/*
* Routine: spd_enable_refresh
* Arguments: None
*
* Trashed: %eax, %ebx, %ecx, %edx, %esp, %eflags
* Effects: Uses serial presence detect to set the
* refresh rate in the DRAMC register.
* see spd_set_dramc for the other values.
* FIXME: Check for illegal/unsupported ram configurations and abort
*/
refresh_rates:
.byte 0x01 /* Normal 15.625 us -> 15.6 us */
.byte 0x05 /* Reduced(.25X) 3.9 us -> 7.8 us */
.byte 0x05 /* Reduced(.5X) 7.8 us -> 7.8 us */
.byte 0x02 /* Extended(2x) 31.3 us -> 31.2 us */
.byte 0x03 /* Extended(4x) 62.5 us -> 62.4 us */
.byte 0x04 /* Extended(8x) 125 us -> 124.8 us */
spd_enable_refresh:
/* Find the first dimm and assume the rest are the same */
/* Load the smbus device and port int %ebx */
movl $((12 << 8) | SMBUS_MEM_DEVICE_0), %ebx
1: CALLSP(smbus_read_byte)
jz 2f
andl $0x7f, %eax
jmp spd_enable_refresh_out
2: addl $1, %ebx /* increment the device */
cmpb $SMBUS_MEM_DEVICE_3, %bl
jbe 1b
/* We couldn't find anything we must have no memory */
jmp no_memory
spd_enable_refresh_out:
cmpb $0x06, %al /* see if the ram refresh is a supported one */
ja 1f
addl $refresh_rates, %eax /* convert SPD refresh rates to 440GX refresh rates */
movb (%eax), %cl
jmp 2f
1: movb $0x05, %cl /* unknown ram refresh hard code it to something conservative */
2: movl $0x57, %eax
PCI_READ_CONFIG_BYTE
andb $0xf8, %al
orb %cl, %al
movb %al, %dl
movl $0x57, %eax
PCI_WRITE_CONFIG_BYTE
RET_LABEL(spd_enable_refresh)
/*
* Routine: spd_set_rps
* Arguments: None
*
* Trashed: %eax, %ebx, %ecx, %edx, %esi, %edi, %esp, %eflags
* Effects: Uses serial presence detect to set the row size
* on a given DIMM
* Notes: %esi accumulates the row sizes of all of the DIMMs
* %ecx holds the current bit into into %esi
* %bl holds the current SMBUS device
* FIXME: Check for illegal/unsupported ram configurations and abort
*/
spd_set_rps:
/* The RPS register holds the size of a ``page'' of DRAM on each DIMM */
/* default all page sizes to 2KB */
xorl %esi, %esi
/* Index into %esi of bit to set */
movl $0 , %ecx
/* Load the smbus device into %ebx */
movl $SMBUS_MEM_DEVICE_0, %ebx
1: movb $3, %bh
CALLSP(smbus_read_byte) /* row address bits */
jz 2f
andl $0xf, %eax
movl %eax, %edi
/* I now have the row page size as a power of 2 */
subl $11, %edi /* Now make it in multiples of 2Kb */
jbe 2f
/* FIXME: do something with page sizes greather than 8KB!! */
shll %cl, %edi
orl %edi, %esi
/* side two */
movb $5, %bh
CALLSP(smbus_read_byte) /* number of physical banks */
cmp $1, %al
jbe 2f
/* for now only handle the symmtrical case */
shll $2, %edi
shll %cl, %edi
orl %edi, %esi
2: addl $1, %ebx /* increment the device */
addl $4, %ecx /* increment the shift count */
cmpb $SMBUS_MEM_DEVICE_3, %bl
jbe 1b
movl $0x7f, %eax
PCI_WRITE_CONFIG_WORD
RET_LABEL(spd_set_rps)
/*
* Routine: spd_set_pgpol
* Arguments: None
*
* Trashed: %eax, %ebx, %ecx, %edx, %esi, %esp, %eflags
* Effects: Uses serial presence detect to set the number of banks
* on a given DIMM
* Notes: %esi accumulates the banks sizes of all of the DIMMs
* %ecx holds the current bit into into %esi
* %bl holds the current SMBUS device
* FIXME: Check for illegal/unsupported ram configurations and abort
*/
spd_set_pgpol:
/* The PGPOL register stores the number of logical banks per DIMM,
* and number of clocks the DRAM controller waits in the idle
* state.
*/
/* default all bank counts 2 */
xorl %esi, %esi
/* Index into %esi of bit to set */
movl $0 , %ecx
/* Load the smbus device into %ebx */
movl $SMBUS_MEM_DEVICE_0, %ebx
1: movb $17, %bh
CALLSP(smbus_read_byte) /* logical banks */
jz 2f
cmp $0x4, %eax
jl 2f
movl $0x1, %eax
shll %cl, %eax
orl %eax, %esi
/* side two */
movb $5, %bh
CALLSP(smbus_read_byte) /* number of physical banks */
cmp $1, %al
jbe 2f
/* for now only handle the symmtrical case */
movl $0x2, %eax
shll %cl, %eax
orl %eax, %esi
2: addl $1, %ebx /* increment the device */
addl $2, %ecx /* increment the shift count */
cmpb $SMBUS_MEM_DEVICE_3, %bl
jbe 1b
shll $8, %esi
orl $0x7, %esi /* 32 clocks idle time */
movl %esi, %ecx
movl $0x78, %eax
PCI_WRITE_CONFIG_WORD
RET_LABEL(spd_set_pgpol)
/*
* Routine: spd_enable_nbxcfg
* Arguments: None
*
* Trashed: %eax, %ebx, %ecx, %edx, %esi, %esp, %eflags
* Effects: Uses serial presence detect to set the
* ECC support flags in the NBXCFG register
* Notes: %esi accumulates the ECC support of the individual DIMMs.
* %ecx holds the bit that should be flipped for the current DIMM.
* %bl holds the smbus device that corresponds to the current DIMM.
* FIXME: Check for illegal/unsupported ram configurations and abort
*/
spd_set_nbxcfg:
/* say all dimms have no ECC support */
movl $0xFF, %esi
/* Index into %esi of bit to set */
movl $0 , %ecx
/* Load the smbus device into %ebx */
movl $SMBUS_MEM_DEVICE_0, %ebx
1: movb $11, %bh
CALLSP(smbus_read_byte) /* module error correction type */
jz 2f
cmp $0x2, %eax /* 0 == None, 1 == Parity, 2 == ECC */
jne 2f
movl $0x1, %eax
shll %cl, %eax
xorl %eax, %esi
/* side two */
movb $5, %bh
CALLSP(smbus_read_byte) /* number of physical banks */
cmp $1, %al
jbe 2f
/* The only is the symmtrical case */
movl $0x2, %eax
shll %cl, %eax
xorl %eax, %esi
2: addl $1, %ebx /* increment the device */
addl $2, %ecx /* increment the shift count */
cmpb $SMBUS_MEM_DEVICE_3, %bl
jbe 1b
movl %esi, %edx
movl $0x53, %eax
PCI_WRITE_CONFIG_BYTE
RET_LABEL(spd_set_nbxcfg)
spd_set_sdramc:
RET_LABEL(spd_set_sdramc)
/* PAM FDHC MBSC SMRAM ESRAMC MBFS DWTC DRTC */
ram_set_spd_registers:
#if USE_SPD
CALL_LABEL(enable_smbus)
CALL_LABEL(setup_smbus)
CALL_LABEL(spd_set_drb)
CALL_LABEL(spd_set_dramc)
CALL_LABEL(spd_set_rps)
CALL_LABEL(spd_set_sdramc)
CALL_LABEL(spd_set_pgpol)
CALL_LABEL(spd_set_nbxcfg)
#endif
RET_LABEL(ram_set_spd_registers)
intel_440_out: