I am porting LinuxBIOS to a board with an SIS 635 chipset. I started
with the 630 code and modified it according to the programmer's guide
and some SIS sample code, but RAM (DDR in this case) is not being
initialized. The relevant code is attached; can anyone offer hints about
what might be wrong?
Wes Felter
System Software Department
IBM Austin Research Lab
11400 Burnet Rd., Austin, TX 78758
Tel 512-838-7933
/*
* 635_regs.inc: Register Recommended Setting for SiS 635 [ABE][01]
*
*
* Copyright 2000 Silicon Integrated Systems Corporation
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*
* Reference:
* 1. SiS 630 Specification
* 2. SiS 630A1 Register Recommended Setting
* Rev 0.97, Jan 7, 2000
*
* $Id: 635_regs.inc,v 1.5 2001/10/18 21:08:31 wes Exp $
*/
northbridge_init_table:
# Reg. Value
/* generic PCI configuration space */
.byte 0x04, 0x07 # Turn on Bus Master,
.byte 0x05, 0x00 # Memory and I/O Space UNDOCUMENTED
.byte 0x07, 0x02 # Clear status 1s clear UNDOCUMENTED
.byte 0x0D, 0x20 # Master Latency Timer = 32 PCI CLCK
/* Host Control Interface */
.byte 0x50, 0xFF # various FSB & PCI settings
.byte 0x51, 0x07 # no MDA, no VGA, various other
.byte 0x52, 0x71 # bus priorities
.byte 0x53, 0x83 # PCI33 settings
.byte 0x54, 0x03 # PCI66 settings
.byte 0x55, 0x01 # CPU-Mem settings
.byte 0x56, 0x88 # PCI33 lock timers
.byte 0x57, 0x88 # PCI66 lock timers
.byte 0x58, 0x00 # SDRAM timings (conservative)
.byte 0x59, 0x29 # mem times: CAS 2
.byte 0x5A, 0x38 # mem lead-off (non-std), bypass enable
.byte 0x5B, 0x03 # read combine off, write combine on
# p. 9
.byte 0x5C, 0x00 # mem init cmd mode, MD/DQS (both non-std)
.byte 0x5D, 0xD1 # mem refresh Q=12 (non-std),
# mem clock=100, refresh cycle enable
.byte 0x5E, 0x03 # ahead refresh
.byte 0x5F, 0x00 # UNDOCUMENTED
.byte 0x6A, 0x26 #
# p. 10
.byte 0x6C, 0x20 # CKE (must) (non-std), ACPI on (non-std)
/* SiS 630 specific registers. See SiS 630 Registers Recommended Setting */
# .byte 0x70,0x00 #Disable C000-C7FF Shadow Read
# .byte 0x72,0x00 #Disable C000-C7FF Shadow Write
# .byte 0x71,0x9F #Disable E000-FFFF Shadow Read
# .byte 0x73,0x1F #Disable E000-FFFF Shadow Write
.byte 0x68, 0x01 # ACPI_IO_BASE UNDOCUMENTED
.byte 0x69, 0x80 # UNDOCUMENTED
.byte 0x80, 0x22
.byte 0x81, 0x02
.byte 0x82, 0x30
.byte 0x83, 0x03
.byte 0x84, 0x15
.byte 0x85, 0x00
.byte 0x86, 0x80
.byte 0x87, 0x01
.byte 0x88, 0x20
.byte 0x89, 0x04
.byte 0x8A, 0x00
.byte 0x8B, 0x04
# p.12
.byte 0x90, 0x00 # GART
.byte 0x91, 0x00 # UNDOCUMENTED
.byte 0x92, 0x00 # UNDOCUMENTED
.byte 0x93, 0x00 # UNDOCUMENTED
.byte 0x94, 0x40 # GART
.byte 0x95, 0x01 # GART
.byte 0x96, 0x00 # UNDOCUMENTED
.byte 0x97, 0x01 # GART
.byte 0x98, 0x00 # GART
.byte 0x99, 0x10 # docs incomplete
# p.13
.byte 0x9A, 0xbb # strobe signal: DDR, 2.4ns (100MHz?)
.byte 0x9B, 0x42 # AGP TCLK, CPUCLK/SDCLK agressive
# I don't know what's up with these,
# since they were just programmed above:
.byte 0x99, 0x20 # (must)
.byte 0x9A, 0x52 # (must)
.byte 0x9B, 0x42 # (must)
.byte 0xA0, 0x42
.byte 0xA1, 0x2A
.byte 0xA2, 0x22
.byte 0x9C, 0x00 # (must) double word MD signals hold time
.byte 0x9D, 0x00 # (must) DQM/MA signals hold time
.byte 0x9E, 0x00 # (must) CSA/CSB signals hold time
.byte 0x9F, 0x10 # (must) CKE setup time (100MHz?)
.byte 0xA3, 0x01
.byte 0xA4, 0x02
.byte 0xD0, 0x22
.byte 0xD1, 0x02
.byte 0xD2, 0x33
.byte 0xD3, 0x00
.byte 0xD4, 0x01
.byte 0xD5, 0xFF
.byte 0xD6, 0xFF
.byte 0xD8, 0x60
.byte 0xD9, 0x60
.byte 0xDA, 0xAA
.byte 0xDC, 0x00
.byte 0xDD, 0x88
northbridge_init_table_end:
/* $Id: 635_mem_size.inc,v 1.5 2001/10/11 22:35:45 wes Exp $
*
* based on ctmemsize.inc from SIS
*/
#define EDOPATTERN $0x055AA55AA
#define MPATTERN0 $0x012345678
#define MPATTERN1 $0x0FEDCBA98
#define IODELAY jmp 1f; 1: # not sure if this is right
#define Fail_Value $0xFF
Start_DRAM_Sizing:
mov $0x06C, %ah # CKE output enable control Reg6C b5=1
CALL_SP(read_northbridge_register)
or $0x20, %al
CALL_SP(write_northbridge_register)
#*************************************************
# check H/W Trap for SDR/DDR Reg7C b2= 0:SDR 1:DDR
#*************************************************
mov $0x07C, %ah
CALL_SP(read_northbridge_register)
test $0x04, %al
jnz DDR_Device
SDR_Device:
# should not be reached, since we do not have SDRAM
jmp .Lhlt
DDR_Device:
mov $0x05C, %ah # DDR MD/DQS input enable control Reg5C b1=1
CALL_SP(read_northbridge_register)
or $0x02, %al
CALL_SP(write_northbridge_register)
mov $0x0A0, %ah
CALL_SP(read_northbridge_register)
or $0x40, %al #S02
CALL_SP(write_northbridge_register)
# FIXME: I dont know ACPI_BASE_IO_ADDR, so this is commented out
#mov ACPI_BASE_IO_ADDR+$0x056, %dx # CKE Floating ACPI Reg56 b5=1
#in %dx, %al
#or $0x20, %al
#out %al, %dx
mov $0x09A, %ah # H/W recommand setting
CALL_SP(read_northbridge_register) #ying
or $0x10, %al #ying
CALL_SP(write_northbridge_register)
mov $0x05C, %ah
CALL_SP(read_northbridge_register) # Set REF Command
and $0x8F, %al
or $0x30, %al
CALL_SP(write_northbridge_register)
mov $0x10, %cl
Refresh_Loop:
mov $0x05C, %ah
CALL_SP(read_northbridge_register) # Command Enable
or $0x08, %al
CALL_SP(write_northbridge_register)
dec %cl
jnz Refresh_Loop
mov $0x05B, %ah # One Page Mode Enable Reg5B b2=1
CALL_SP(read_northbridge_register)
or $0x04, %al
CALL_SP(write_northbridge_register)
Test_DDR_Start:
#**********************************************
# tell Unbuffer DDR or Registered DDR
#**********************************************
mov $0x06D, %al #Set Dram type is UnbDDR
CALL_SP(Assume_All_Dimms_Type)
CALL_SP(Scan_All_Dimms)
jnz End_Dram_Sizing # clc-exists
mov $0x0ED, %al #Set Dram type is RegDDR (not reached)
CALL_SP(Assume_All_Dimms_Type)
CALL_SP(Scan_All_Dimms)
jnz End_Dram_Sizing # clc-exists
No_Dram:
mov $0x0DE, %al #no memory device on any dimm
out %al, $0x80
jmp .Lhlt
End_Dram_Sizing:
mov $0x05B, %ah # Disable One Page Control
CALL_SP(read_northbridge_register)
andb $0x0FB, %al
CALL_SP(write_northbridge_register)
mov $0x064, %ah
CALL_SP(read_northbridge_register)
mov %al, %bl
#xchg %bp, %sp
jmp mem_size_end
# ********************************************************;
# Assume_All_Dimms_Type;
# Input: AL ;
# Output: Set NB 60h~63h by AL ;
# ********************************************************;
Assume_All_Dimms_Type:
xchg %esp, %ebp
mov $0x0, %cl
43:
mov $0x060, %ah
addb %cl, %ah
CALL_SP(write_northbridge_register) #clobbers eax, ebx, edx
inc %cl
cmp $0x4, %cl
jb 43b
xchg %esp, %ebp
RET_SP
#**************************************************************************;
# CheckSizeMemory ;
# 1. Check Memory Device on Dimm or not ;
# 2. Find out the physical MA Table ;
#**************************************************************************;
Scan_All_Dimms:
mov %esp, %ebp #ying what does this do?
ror $0x10, %ebx #ying
mov $0x0, %esi # dimm index
Check_Memory_Loop:
mov $0x01, %bl
mov %si, %cx
shl %cl, %bl
mov $0x064, %ah # DRAM Status Register
mov %bl, %al
CALL_SP(write_northbridge_register)
mov $0x05D, %ah # Disable Refresh Cycle
CALL_SP(read_northbridge_register)
andb $0x0FE, %al
CALL_SP(write_northbridge_register)
# ************************* ;
# Check If DDR is Plugged ;
# ************************* ;
mov $0x060, %ah
mov $0x00, %edx # I hope edx is not being used
mov %ah, %dl # add the DIMM number (%esi) to the register number
add %esi, %edx
mov %dl, %ah
CALL_SP(read_northbridge_register)
test $0x040, %al # Reg.60~64 b6 = Switch of SDRAM/DDR
jz Check_SDRAM
mov $0x05C, %ah
CALL_SP(read_northbridge_register)
and $0x8F, %al
or $0x10, %al # PALL : Precharge ALL
CALL_SP(write_northbridge_register)
or $0x08, %al # Command Enable
CALL_SP(write_northbridge_register)
mov $0x05C, %ah
CALL_SP(read_northbridge_register)
and $0x8F, %al
or $0x40, %al # EMRS-N : DLL-Enable Normal
CALL_SP(write_northbridge_register)
or $0x08, %al # Command Enable
CALL_SP(write_northbridge_register)
mov $0x05C, %ah
CALL_SP(read_northbridge_register)
and $0x8F, %al
or $0x60, %al # DLL-Reset : DLL Reset
CALL_SP(write_northbridge_register)
or $0x08, %al # Command Enable
CALL_SP(write_northbridge_register)
Check_SDRAM:
mov $0x05C, %ah
CALL_SP(read_northbridge_register)
and $0x8F, %al
or $0x10, %al # PALL : Precharge ALL
CALL_SP(write_northbridge_register)
or $0x08, %al # Command Enable
CALL_SP(write_northbridge_register)
mov $0x05C, %ah
CALL_SP(read_northbridge_register)
and $0x8F, %al
or $0x20, %al # MRS : Mode Register Set
CALL_SP(write_northbridge_register)
or $0x08, %al # Command Enable
CALL_SP(write_northbridge_register)
mov $0x05C, %ah
CALL_SP(read_northbridge_register)
and $0x8F, %al
or $0x30, %al # REF : Refresh
CALL_SP(write_northbridge_register)
or $0x08, %al # Command Enable
CALL_SP(write_northbridge_register)
mov $0x05C, %ah
CALL_SP(read_northbridge_register)
and $0x8F, %al
or $0x30, %al # REF : Refresh
CALL_SP(write_northbridge_register)
or $0x08, %al # Command Enable
CALL_SP(write_northbridge_register)
mov $0x05D, %ah
CALL_SP(read_northbridge_register)
or $0x01, %al # Enable Refresh Cycle
CALL_SP(write_northbridge_register)
CALL_SP(Check_Memory_Plugged_Or_Not) # Check if Memory Plugged
jc No_Memory_Plugged_on_Dimm
CALL_SP(Test_MA) # Find out the real MA Type
# al = Test_MA output
cmp Fail_Value, %al
je No_Memory_Plugged_on_Dimm
mov %al, %bl # save al(MA-Type) to bl
and $0x0F, %bl # clear higher 4-bits in bl
CALL_SP(Test_Side) # determine Single/Double Side
jnz Memory_Single_Side
or $0x20, %bl # Set Double Side
Memory_Single_Side:
mov $0x060, %ah
mov $0x00, %edx # I hope edx is not being used
mov %ah, %dl # add the DIMM number (%esi) to the register number
add %esi, %edx
mov %dl, %ah
CALL_SP(read_northbridge_register)
and $0xC0, %al # reserve Reg60~63 bit-7,6
or %bl, %al
CALL_SP(write_northbridge_register)
mov $0x1, %bx
mov %si, %cx
shl %cl, %bx
ror $0x10, %esi
or %bx, %si
rol $0x10, %esi
No_Memory_Plugged_on_Dimm:
mov $0x05C, %ah
CALL_SP(read_northbridge_register)
and $0x8F, %al
or $0x10, %al # PALL : Precharge ALL
CALL_SP(write_northbridge_register)
or $0x08, %al # Command Enable
CALL_SP(write_northbridge_register)
inc %si
cmp $0x4, %si
jae All_Dimms_Determined
jmp Check_Memory_Loop
All_Dimms_Determined:
ror $0x10, %esi
mov $0x64, %cx
mov %si, %ax
CALL_SP(write_northbridge_register)
ror $0x10, %ebx #ying
mov %ebp, %esp #ying Avoid to destroy return address
cmp $0x0, %al #Set Flag
RET_SP
# ********************************************************;
# Check_Memory_Plugged_Or_Not ;
# stc : no memory device on dimm ;
# clc : memory device on dimm ;
# ********************************************************;
Check_Memory_Plugged_Or_Not:
movl MPATTERN0, %es:0x4 #write memory
IODELAY
movl EDOPATTERN, %es:0x8 #clear bus
IODELAY
movl EDOPATTERN, %es:0x8 #clear bus
IODELAY
movl EDOPATTERN, %es:0x8 #clear bus
IODELAY
movl EDOPATTERN, %es:0x8 #clear bus
IODELAY
movl EDOPATTERN, %es:0x8 #clear bus
IODELAY
movl EDOPATTERN, %es:0x8 #clear bus
IODELAY
movl EDOPATTERN, %es:0x8 #clear bus
IODELAY
movl EDOPATTERN, %es:0x8 #clear bus
IODELAY
cmpl MPATTERN0, %es:0x04 #memory exist?
je 44f
stc # not exist
RET_SP
44:
clc # exist
RET_SP
# **************************************************** ;
# Test_Side : Decide Single/Double Side ;
# ;
# ;
# **************************************************** ;
Test_Side:
mov $0x79999990, %edi # write 2048M-16
movl MPATTERN1, %es:(%edi)
IODELAY
movl EDOPATTERN, %es:0x8(%edi)
IODELAY
cmpl MPATTERN1, %es:(%edi)
RET_SP
#define MA_1_11_08 $0x0
#define MA_1_13_08 $0x1
#define MA_2_12_08 $0x2
#define MA_2_13_08 $0x3
#define MA_1_11_09 $0x4
#define MA_1_13_09 $0x5
#define MA_2_12_09 $0x6
#define MA_2_13_09 $0x7
#define MA_1_11_10 $0x8
#define MA_1_13_10 $0x9
#define MA_2_12_10 $0xa
#define MA_2_13_10 $0xb
#define MA_2_11_08 $0xc
#define MA_2_13_12 $0xd
#define MA_2_12_11 $0xe
#define MA_2_13_11 $0xf
Test_MA:
xor %edi, %edi
movl MPATTERN0, %es:(%edi)
#; Test COLUMN AD16
cmpl MPATTERN0, %es:0x10000(%edi)
jne Four_Banks
#*********************************
#; Start 2Banks Device Sizing
#; Test Row AD26
cmpl MPATTERN0, %es:0x4000000(%edi)
jne Test_Column_09
#; Column => 8
#; Test Column AD11
cmpl MPATTERN0, %es:0x800(%edi)
je Set_MA_1_11_08_Type
#; Test Column AD12
cmpl MPATTERN0, %es:0x1000(%edi)
jne Set_MA_1_11_10_Type
cmpl MPATTERN0, %es:0x8000(%edi) #Error check
je Error_MA_Type
mov MA_1_11_09, %al
RET_SP
Set_MA_1_11_10_Type:
mov MA_1_11_10, %al
RET_SP
Set_MA_1_11_08_Type:
cmpl MPATTERN0, %es:0x8000(%edi) #Error check
je Error_MA_Type
mov MA_1_11_08, %al
RET_SP
#*********************************
Test_Column_09:
#; Test Row AD 12
cmpl MPATTERN0, %es:0x1000(%edi)
jne Set_MA_1_13_10_Type
#; Column => 08
#; Test Row AD11
cmpl MPATTERN0, %es:0x800(%edi)
jne Set_MA_1_13_09_Type
cmpl MPATTERN0, %es:0x8000000(%edi) #Error check
je Error_MA_Type
mov MA_1_13_08, %al
RET_SP
Set_MA_1_13_09_Type:
mov MA_1_13_09, %al
RET_SP
Set_MA_1_13_10_Type:
mov MA_1_13_10, %al
RET_SP
#*********************************
Error_MA_Type:
mov Fail_Value, %al
RET_SP
#*********************************
Four_Banks:
#; Start 4Banks Device Sizing
#; Test Column AD12
cmpl MPATTERN0, %es:0x1000(%edi)
jne Test_Column_13
#; Column => 8
#; Test Row AD11
cmpl MPATTERN0, %es:0x800(%edi)
je Test_Row_13
#; Row => 14
#; Test Row AD27
cmpl MPATTERN0, %es:0x8000000(%edi)
jne Set_MA_2_13_09_Type
cmpl MPATTERN0, %es:0x4000000(%edi) #Error check
je Error_MA_Type
mov MA_2_12_09, %al
RET_SP
Set_MA_2_13_09_Type:
mov MA_2_13_09, %al
RET_SP
#*********************************
Test_Row_13:
#; Row => 13
#; Test Row AD26
cmpl MPATTERN0, %es:0x4000000(%edi)
je Set_MA_2_11_08_Type
#; Row => 14
#; Test Row AD27
cmpl MPATTERN0, %es:0x8000000(%edi)
jne Set_MA_2_13_08_Type
cmpl MPATTERN0, %es:0x10000(%edi) #Error check
je Error_MA_Type
mov MA_2_12_08, %al
RET_SP
Set_MA_2_13_08_Type:
mov MA_2_13_08, %al
RET_SP
Set_MA_2_11_08_Type:
cmpl MPATTERN0, %es:0x10000(%edi) #Error check
je Error_MA_Type
mov MA_2_11_08, %al
RET_SP
#*********************************
Test_Column_13:
#; Test Column AD13
cmpl MPATTERN0, %es:0x2000(%edi)
jne Test_Column_14
#; Row => 14
#; Test Row AD27
cmpl MPATTERN0, %es:0x8000000(%edi)
jne Set_MA_2_13_10_Type
cmpl MPATTERN0, %es:0x4000000(%edi) #Error check
je Error_MA_Type
mov MA_2_12_10, %al
RET_SP
Set_MA_2_13_10_Type:
mov MA_2_13_10, %al
RET_SP
#*********************************
Test_Column_14:
#; Test Column AD14
cmpl MPATTERN0, %es:0x4000(%edi)
jne Set_MA_2_13_12_Type
#; Row => 14
#; Test Row AD27
cmpl MPATTERN0, %es:0x8000000(%edi)
jne Set_MA_2_13_11_Type
cmpl MPATTERN0, %es:0x4000000(%edi) #Error check
je Error_MA_Type
mov MA_2_12_11, %al
RET_SP
Set_MA_2_13_11_Type:
mov MA_2_13_11, %al
RET_SP
Set_MA_2_13_12_Type:
mov MA_2_13_12, %al
RET_SP
mem_size_end: