430tx support (beginnings of)

This commit is contained in:
Ronald G. Minnich 2001-11-21 03:53:17 +00:00
parent 4dc5eb479e
commit 6f65f07fdf
3 changed files with 549 additions and 0 deletions

View file

@ -0,0 +1,5 @@
raminit northbridge/intel/430tx/raminit.inc
raminit sdram/generic_sdram.inc
raminit sdram/generic_sdram_enable.inc
object northbridge.o

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,514 @@
jmp intel_430_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
/* Default memory set to 0 */
#define DRB 0x00
/* The DRB register for the first row */
#define DRB_REG0 $0x60
/* The maximum allowed rows of memory banks */
#define MAX_ROWS $0x8
#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)
#define ENABLE_REFRESH() CALL_LABEL(spd_enable_refresh)
/* Default values for config registers */
#define SET_NBXCFG \
CS_WRITE_LONG(0x50, 0xff00a00c)
#define SET_DRAMC \
CS_WRITE_BYTE(0x57, 0x8) \
/* 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...
*/
#define SET_PAM \
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, DRB) ; \
CS_WRITE_BYTE(0x61, DRB) ; \
CS_WRITE_BYTE(0x62, DRB) ; \
CS_WRITE_BYTE(0x63, DRB) ; \
CS_WRITE_BYTE(0x64, DRB) ; \
CS_WRITE_BYTE(0x65, DRB) ; \
CS_WRITE_BYTE(0x66, DRB) ; \
CS_WRITE_BYTE(0x67, DRB)
#define SET_FDHC \
CS_WRITE_BYTE(0x68, 0x00)
#define SET_RPS \
CS_WRITE_WORD(0x74, 0x0000)
#define SET_SDRAMC \
CS_WRITE_BYTE(0x76, 0x00)
#define SET_PGPOL \
CS_WRITE_WORD(0x78, 0xff00)
/* PMCR - Power Management Control Register
Enable normal refresh operation and
the gated clock */
#define SET_PMCR \
CS_WRITE_BYTE(0x7a, 0x14)
ram_set_registers:
SET_NBXCFG
SET_DRAMC
SET_PAM
SET_DRB
SET_FDHC
SET_RPS
SET_SDRAMC
SET_PGPOL
SET_PMCR
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:
mov $0x1e, %al
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)
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)
smbus_wait_until_done:
movl $(SMBUS_IO_BASE + SMBHSTSTAT), %edx
1: inb %dx, %al
testb $1, %al
jnz 1b
testb $0xfe, %al
jz 1b /* wait until interrupt status is set */
RET_LABEL(smbus_wait_until_done)
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
mov $0x1e, %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 */
1: movl $(SMBUS_IO_BASE + SMBHSTSTAT), %edx
inb %dx, %al
testb $0x04, %al
jnz 1f
movl $(SMBUS_IO_BASE + SMBHSTDAT0), %edx
inb %dx, %al
1:
RETSP
configure_rps_pgpol_drb:
/* %bl is the row index */
xorl %ebx, %ebx
/* %si is the aggregation of bits for RPS */
xorl %esi, %esi
/* %di has bits to be set in PGPOL */
xorl %edi, %edi
/* %cx holds the cumulative memory size of DIMMs */
xorl %ecx, %ecx
next_row:
movzx %bl, %dx
shl $16, %ebx
shr $1, %dx
mov $((5 << 8) | SMBUS_MEM_DEVICE_0), %bx
or %dx, %bx
CALLSP(smbus_read_byte)
jnz shift_before_moving_on
shr $16, %ebx
testb $2, %al
jnz two_rows
testb $1, %bl
/* this used to be jnz but seems it should be jz */
jz ready_for_next_row
two_rows:
movzx %bl, %dx
shl $16, %ebx
shr $1, %dx
mov $((4 << 8) | SMBUS_MEM_DEVICE_0), %bx
or %dx, %bx
CALLSP(smbus_read_byte)
shr $16, %ebx
subb $8, %al
shrd $2, %ax, %si
movzx %bl, %dx
shl $16, %ebx
shr $1, %dx
mov $((17 << 8) | SMBUS_MEM_DEVICE_0), %bx
or %dx, %bx
CALLSP(smbus_read_byte)
shr $16, %ebx
cmpb $4, %al
sete %al
shrd $1, %ax, %di
movzx %bl, %dx
shl $16, %ebx
shr $1, %dx
mov $((31 << 8) | SMBUS_MEM_DEVICE_0), %bx
or %dx, %bx
CALLSP(smbus_read_byte)
shr $16, %ebx
shr $1, %al
xorb %ah, %ah
add %ax, %cx
movzx %cx, %edx
movzx %bl, %eax
addl $0x60, %eax
PCI_WRITE_CONFIG_BYTE
jmp 1f
shift_before_moving_on:
shr $16, %ebx
ready_for_next_row:
shr $2, %si
shr $1, %di
movzx %cx, %edx
movzx %bl, %eax
addl $0x60, %eax
PCI_WRITE_CONFIG_BYTE
1:
inc %bl
cmp MAX_ROWS, %bl
jb next_row
/* Now to finally write the RPS and PGPOL registers */
movzx %si, %ecx
movl $0x74, %eax
PCI_WRITE_CONFIG_WORD
mov %di, %cx
movzx %ch, %edx
movl $0x79, %eax
PCI_WRITE_CONFIG_BYTE
RET_LABEL(configure_rps_pgpol_drb)
configure_sdramc:
movl $((18 << 8) | SMBUS_MEM_DEVICE_0), %ebx
0: CALLSP(smbus_read_byte)
jnz 1f
testb $2, %al
jz 2f /* Default settings are OK if only CAS=3 is supported */
movl $0x06, %edx
movl $0x76, %eax
PCI_WRITE_CONFIG_BYTE
jmp 2f
1: addl $1, %ebx /* increment the device */
cmpb $SMBUS_MEM_DEVICE_3, %bl
jbe 0b
2:
RET_LABEL(configure_sdramc)
spd_set_dramc:
movl $((21 << 8) | SMBUS_MEM_DEVICE_0), %ebx
1: CALLSP(smbus_read_byte)
jnz 2f
andl $0x12, %eax
jmp spd_set_dramc_out
2: addl $1, %ebx /* increment the device */
cmpb $SMBUS_MEM_DEVICE_3, %bl
jbe 1b
jmp no_memory
spd_set_dramc_out:
testb $0x2, %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)
jnz 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
ja 1f
addl $refresh_rates, %eax
movb (%eax), %cl
jmp 2f
1: movb $0x05, %cl
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)
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 */
jnz 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
movl $((126 << 8) | SMBUS_MEM_DEVICE_0), %ebx
CALLSP(smbus_read_byte)
RET_LABEL(spd_set_nbxcfg)
ram_set_spd_registers:
CALL_LABEL(enable_smbus)
CALL_LABEL(setup_smbus)
CALL_LABEL(configure_sdramc)
CALL_LABEL(configure_rps_pgpol_drb)
CALL_LABEL(spd_set_dramc)
CALL_LABEL(spd_set_nbxcfg)
RET_LABEL(ram_set_spd_registers)
/* things that are not used */
#define FIRST_NORMAL_REFERENCE()
#define SPECIAL_FINISHUP()
intel_430_out: