SiS 730 Works lsls

This commit is contained in:
Li-Ta Lo 2001-01-29 07:58:42 +00:00
commit f23356e68f
11 changed files with 1045 additions and 0 deletions

View file

@ -0,0 +1,11 @@
northsouthbridge sis/730
superio sis/950
option ENABLE_FIXED_AND_VARIABLE_MTRRS
option FINAL_MAINBOARD_FIXUP
option HAVE_PIRQ_TABLE
object mainboard.o
object irq_tables.o
keyboard pc80
cpu p5
cpu p6

View file

@ -0,0 +1,7 @@
/* Table for DLL Clock Control Register (0x8c - 0x8f), these
register values are very Mainboard specific */
# High Byte -> Register Low Byte -> Value
.word 0x8c46
.word 0x8d70
.word 0x8e87

View file

@ -0,0 +1,64 @@
#include <subr.h>
#ifndef SIS630S
#define CHECKSUM 0xe6
const struct irq_routing_table intel_irq_routing_table = {
PIRQ_SIGNATURE, /* u32 signature */
PIRQ_VERSION, /* u16 version */
32+16*5, /* there can be total 5 devices on the bus */
0x00, /* Bus 0 */
0x08, /* Device 1, Function 0 */
0x0A20, /* reserve IRQ 11, 9, 5, for PCI */
0x1039, /* Silicon Integrated System */
0x0008, /* SiS 85C503/5513 ISA Bridge */
0x00, /* u8 miniport_data - "crap" */
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* u8 rfu[11] */
CHECKSUM, /* u8 checksum - mod 256 checksum must give zero */
{
/* bus, devfn, {link, bitmap}, {link, bitmap}, {link, bitmap}, {link, bitmap}, slot, rfu */
{0x00, 0x58, {{0x43, 0xdef8}, {0x44, 0xdef8}, {0x41, 0xdef8}, {0x42, 0xdef8}},
0x01, 0x00},
{0x00, 0x60, {{0x44, 0xdef8}, {0x41, 0xdef8}, {0x42, 0xdef8}, {0x43, 0xdef8}},
0x02, 0x00},
{0x00, 0x01, {{0x61, 0xdef8}, {0x00, 0xdef8}, {0x00, 0xdef8}, {0x00, 0xdef8}},
0x00, 0x00},
{0x00, 0x10, {{0x41, 0xdef8}, {0x42, 0xdef8}, {0x43, 0xdef8}, {0x44, 0xdef8}},
0x00, 0x00},
{0x00, 0x0a, {{0x41, 0xdef8}, {0x42, 0xdef8}, {0x43, 0xdef8}, {0x44, 0xdef8}},
0x00, 0x00},
}
};
#else /* SIS630S */
#define CHECKSUM 0x21
const struct irq_routing_table intel_irq_routing_table = {
PIRQ_SIGNATURE, /* u32 signature */
PIRQ_VERSION, /* u16 version */
32+16*7, /* there can be total 5 devices on the bus */
0x00, /* Bus 0 */
0x08, /* Device 1, Function 0 */
0x1c20, /* reserve IRQ 12, 11, 9, 5, for PCI */
0x1039, /* Silicon Integrated System */
0x0008, /* SiS 85C503/5513 ISA Bridge */
0x00, /* u8 miniport_data - "crap" */
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* u8 rfu[11] */
CHECKSUM, /* u8 checksum - mod 256 checksum must give zero */
{
/* bus, devfn, {link, bitmap}, {link, bitmap}, {link, bitmap}, {link, bitmap}, slot, rfu */
{0x00, 0x48, {{0x42, 0xdef8}, {0x43, 0xdef8}, {0x44, 0xdef8}, {0x41, 0xdef8}},
0x01, 0x00},
{0x00, 0x58, {{0x43, 0xdef8}, {0x44, 0xdef8}, {0x41, 0xdef8}, {0x42, 0xdef8}},
0x02, 0x00},
{0x00, 0x68, {{0x44, 0xdef8}, {0x41, 0xdef8}, {0x42, 0xdef8}, {0x43, 0xdef8}},
0x03, 0x00},
{0x00, 0x78, {{0x41, 0xdef8}, {0x42, 0xdef8}, {0x43, 0xdef8}, {0x44, 0xdef8}},
0x04, 0x00},
{0x00, 0x01, {{0x61, 0xdef8}, {0x00, 0xdef8}, {0x00, 0xdef8}, {0x00, 0xdef8}},
0x00, 0x00},
{0x00, 0x10, {{0x41, 0xdef8}, {0x42, 0xdef8}, {0x43, 0xdef8}, {0x44, 0xdef8}},
0x00, 0x00},
{0x00, 0x0a, {{0x41, 0xdef8}, {0x42, 0xdef8}, {0x43, 0xdef8}, {0x44, 0xdef8}},
0x00, 0x00},
}
};
#endif /* SIS630S */

View file

@ -0,0 +1,19 @@
#include <printk.h>
void
mainboard_fixup(void)
{
}
void
final_mainboard_fixup(void)
{
void final_southbridge_fixup(void);
void final_superio_fixup(void);
printk(KERN_INFO
"Winfast 6300 (and similar)...");
final_southbridge_fixup();
final_superio_fixup();
}

View file

@ -0,0 +1,108 @@
/*
* 730_regs.inc: Register Recommended Setting for SiS 730S
*
*
* 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 730S Specification
* 2. SiS 730S Register Recommended Setting
* Rev 1.0, Oct. 4, 2000
*
* $Id$
*/
northbridge_init_table:
# Reg. Value
/* generic PCI configuration space */
.byte 0x0D, 0x20 # Master Latency Timer = 32 PCI CLCK
/* SiS 730 specific registers. See SiS 730 Registers Recommended Setting */
/* Host Control Interface */
.byte 0x50, 0xC5 #
.byte 0x51, 0x10 #
/* DRAM Control */
.byte 0x52, 0x80 #
.byte 0x53, 0x00 #
.byte 0x54, 0x00 #
.byte 0x55, 0x01 #
.byte 0x57, 0x00 #
/* Pre-driver Slew Rate/Current Driving Control */
.byte 0x58, 0x00 #
.byte 0x59, 0x05 #
.byte 0x5A, 0x51 #
.byte 0x5B, 0x00 #
.byte 0x65, 0x00 # Use DIMM 0 for SMA
/* MISC Control */
.byte 0x6A, 0x66 #
.byte 0x6B, 0x1E # 0x00 -> 66/133 MHZ, 0x01 -> 100 MHZ
.byte 0x6C, 0x03 # 0x2E -> 66 MHZ, 0x20 -> 100 MHZ, 0x2C -> 133 MHZ
/* PCI Interface */
.byte 0x80, 0x72 #
.byte 0x81, 0x07 #
.byte 0x82, 0xFF #
.byte 0x83, 0xFF #
.byte 0x84, 0x83 #
.byte 0x85, 0x24 #
.byte 0x86, 0x00 #
.byte 0x87, 0x00 #
.byte 0x88, 0xF0 #
.byte 0x89, 0xF0 #
.byte 0x8A, 0xF0 #
.byte 0x8B, 0xF0 #
/* AGP GART Base Address */
.byte 0x90, 0x00
.byte 0x91, 0x00
.byte 0x92, 0x00
.byte 0x93, 0x00
/* Graphic Window Size */
.byte 0x94, 0x40 # Graphic Window Size == 64MB
.byte 0x95, 0x00 #
.byte 0x96, 0x00 #
.byte 0x97, 0x01 #
.byte 0x9C, 0x02 # CPU to VGA MEM Posted Write
/* DRAM Priority Timer Control REgister */
.byte 0xA0, 0x00
.byte 0xA1, 0x00
.byte 0xA2, 0x23
.byte 0xA3, 0x43
.byte 0xD0, 0x0A
.byte 0xD1, 0x60
.byte 0xD2, 0x60
.byte 0xD3, 0x88
.byte 0xD4, 0xFF
.byte 0xD5, 0xFF
.byte 0xD6, 0x88
.byte 0xD3, 0x11
northbridge_init_table_end:

View file

@ -0,0 +1,7 @@
option SIS730
option USE_DOC_MIL
docipl northsouthbridge/sis/730/ipl.S
raminit northsouthbridge/sis/730/raminit.inc
object southbridge.o
object northbridge.o

View file

@ -0,0 +1,412 @@
/*
* ipl.S: Initial Program Loader (IPL) for SiS 730 and M-System DoC Millennium
*
*
* 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 730 Specification
* 2. System Management Bus Specification Rev 1.1
* 3. PC SDRAM Serial Presence Detect (SPD) Specification Rev 1.2B
* 4. Booting From the DiskOnChip Millennium, M-Systems Application Note Ap-DOC-044
* APR-2000, 93-SR-001-44-7L REV. 1.0
*
* $Id$
*/
#include "ipl.h"
.code16
#define SIZE_ALL
#define REALLY_COMPACT
sis730spd_start:
cli # Disables the maskable
# hardware interrupts.
movw %cs, %ax # makes data segment ==
movw %ax, %ds # code segment
movw $0x408a, %ax # ACPI Enable.
CALL_SP(write_lpc_register) # (for use of SMBus)
movw $0x7550, %ax # Store ACPI Base Address.
CALL_SP(write_lpc_register) # (for use of SMBus)
movw $0x5501, %ax # Mode# enable, this bit
CALL_SP(write_pci_register) # should be set before sizing.
#ifdef SIZE_ALL
xorw %bx, %bx # clear %fs, %fs is used as "bitmap" of
movw %bx, %fs # install DIMM slot
#endif /* SIZE_ALL */
spd_sizing_start:
#ifndef REALLY_COMPACT
movw $0x0320, %ax # Issue an SMB_Kill command to
CALL_BP(sis_set_smbus) # stop all SMBus operation
#endif /* REALLY_COMPACT */
movw $0x04a1, %ax # SPD is on SMBUS Address 1010 xyz1
# where xyz are DIMM Slot Number
#ifdef SIZE_ALL
addb %bh, %al # FIXME, %bh == 0 ??
addb %bh, %al # Select the DIMM to be SPD-sized.
#endif /* SIZE_ALL*/
CALL_BP(sis_set_smbus)
movb $0x02, %al # Read the RAM Type (SPD byte 2)
CALL_SP(read_spd) # of the dram on current DIMM.
cmpb $0x04, %bl # If the RAM Type = SDRAM ??
jne no_sdram # no, exit
movb $0x03, %al # Read the Row number (SPD byte 3)
CALL_SP(read_spd) # of the dram on current DIMM.
movb %bl, %ch # save the Row number in CH.
movb $0x04, %al # Read the Column number (SPD byte 4)
CALL_SP(read_spd) # of the dram on current DIMM.
movb %bl, %cl # Save the Column number in CL.
movb $0x11, %al # Read the Bank number (SPD byte 17)
CALL_SP(read_spd) # of the dram on current DIMM.
#ifdef SIZE_ALL
movb %bh, %ah # Save the current DIMM slot number in AH
#endif
cmpb $0x01, %bl
je one_bank
movw $sdram_type_bank_2, %si
jmp check_row_column
one_bank:
movw $sdram_type_bank_1, %si
check_row_column:
#ifdef SAFTY_CHECK
cmpb $0x0b, %ch # Row number too small, unsupported.
jb no_sdram
cmpb $0x0d, %ch # Row number too big, unsupported.
jl no_sdram
cmpb $0x08, %cl # Col number too small, unsupported.
jb no_sdram
cmpb $0x0b, %cl # Col number too big, unsupported.
jl no_sdram
#endif /* SAFTY_CHECK */
#if 1
subb $0x0b, %ch # row = row - 11
shlb $0x02, %ch # row * 4
addb %ch, %cl # column + row *4
movzbw %cl, %bx # Get the SDRAM type.
addw %bx, %si # sdram_type_bank[column + row * 4]
movb -8(%si), %cl # sdram_type_bank[column + row * 4 - 8]
#else
/* This one is DANGEROUS TOO, be careful about OVERFLOW !!! */
shlb $0x02, %ch # row * 4
addb %ch, %cl # column + row *4
xorb %ch, %ch
addw %cx, %si # sdram_type_bank[column + row * 4]
movb -52(%si), %cl # sdram_type_bank[column + row * 4 - 52]
#endif
#ifdef SIZE_ALL
movb %ah, %bh # Restore DIMM slot number from AH to BH
#endif /* SIZE_ALL */
#ifdef SAFTY_CHECK
cmpb $0xff, %cl # SDRAM type supported ??
je no_sdram # no, exit
#endif /* SAFTY_CHECK */
movb $0x05, %al # Read the Side number (SPD byte 5)
CALL_SP(read_spd) # of the dram on current DIMM.
cmpb $0x02, %bl # single or double sided ??
jne single_side
orb $0x20, %cl # set double side bit
# (reg 0x60~0x62 bit 5)
single_side:
movb %cl, %al # store DRAM type in al
movb $0x60, %ah # select register 0x60
#ifdef SIZE_ALL
addb %bh, %ah # select register 0x61, 0x62, accroding
# to DIMM slot number (in BH)
#endif /* SIZE_ALL */
CALL_SP(write_pci_register) # write register 0x60~0x62 for each
# DIMM slot
#ifdef SIZE_ALL
movw %fs, %ax # enable DIMMx on reg. 63h and save
# it in FS
movb $0x01, %bl
movb %bh, %cl
shlb %cl, %bl
orb %bl, %al
movw %ax, %fs
no_sdram:
incb %bh
cmpb $0x03, %bh # total 3 DIMM slots supported
jb spd_sizing_start
movw %fs, %ax
movb $0x63, %ah
#ifdef HAVE_FRAMEBUFFER
orb $0xA0, %al # enable SMA 8 MB for VGA
#endif /* HAVE_FRAMEBUFFER */
#else /* !SIZE_ALL */
no_sdram:
#ifdef HAVE_FRAMEBUFFER
# enable DIMM 0 and
movw $0x63A1, %ax # enable SMA 8 MB for VGA
#else /* HAVE_FRAMEBUFFER */
movw $0x6301, %ax # enable DIMM 0
#endif /* HAVE_FRAMEBUFFER */
#endif /* SIZE_ALL */
CALL_SP(write_pci_register) # write register 0x63
movw $pci_init_table, %si
init_sdram:
lodsw (%si), %ax
testw %ax, %ax
jz init_complete
CALL_SP(write_pci_register)
jmp init_sdram
init_complete:
sis730ipl_start:
/* O.K. we have DRAM now, so set up STACK for CALL/RET */
movw $DOC_STACK_SEG, %ax
movw %ax, %ss
movw $SPL_RAM_SEG, %ax
movw %ax, %es
movw $sis950_init_table, %si # unlock SiS 950 LPC
movw $0x05, %cx # select Clock Selection
movw $0x2e, %dx # and Flash ROM I/F
rep
outsb
movb $0xfd, %al # enable write, CLKIN = 24 MHZ
outb %al, $0x2f
xorw %sp, %sp # clear %sp
xorw %dx, %dx # clear %dx, start of RAM
movw $0x800, %si # point %si to CDSN Data area
movw $0x1000, %di # point %di to CDSN Control area
movw $DOC_SPL_START_BLK, %bp # start page of LinuxBIOS
movb $0x84, %al # Reset DOC Millennium
call doc_reset
movb $0x85, %al # Turn into Normal Mode
call doc_reset
read_next_page:
movw $0x1000, %di # point %di to CDSN Control area
flash_command:
movb $0x03, 0x04(%di) # start command cycle
movb $0x00, (%si) # issue flash command Read00
call doc_cycle_end
movw %bp, %bx # %bp is current page number
flash_address:
shll $0x08, %ebx
movb $0x03, %cl # this one is DANGEROUS but I am
# sure the upper 3 bytes == 0x00
movb $0x05, 0x04(%di) # start address cycle
0:
movb %bl, (%si) # write address to CDSNIO
shrw $0x08, %bx # shift next address byte
loop 0b
call doc_cycle_end
wait_for_flash_ready:
/* delay by reding NOP register before polling the FLASH READY bit,
this is inlined to save a call/ret pair */
doc_delay:
movb $0x04, %cl # this one is DANGEROUS but I am
# sure the upper 3 bytes == 0x00
0:
movb 0x20(%di), %al # read DOC NOP retisger
loop 0b # four times
testb $0x80, 0x04(%di) # is flash ready ?
jz wait_for_flash_ready
movb 0x1d(%di), %al # init read pipeline
movw $0x100, %cx # 1 page = 512 bytes
movw $0x800, %si # point %si to CDSN Data area
movw %dx, %di # restore saved current destination
rep
movsw
movw %di, %dx # save current destination
incw %bp # increse current page number
cmpw $128, %bp # moved 63 KB ??
jl read_next_page # no, read next page
sis730ipl_end:
movb $0x77, %al
outb %al,$0x80
jmp spl_vector # jump to SPL vector
/* ------------------------------------------------------------------------------------------*/
write_lpc_register:
/* Input: AH - register number. AL - register value. */
movl $LPC_BRIDGE_BASE_ADDR, %edx
jmp write_common
write_pci_register:
/* Input: AH - register number. AL - register value. */
movl $NORTH_BRIDGE_BASE_ADDR, %edx
write_common:
movw %ax, %cx # Save %ax to %cx.
movzbl %ch, %eax # add register address to
addl %edx, %eax # PCI base address
movw $PCI_COMMAND_PORT, %dx
outl %eax, %dx
movw $PCI_DATA_PORT, %dx
andb $0x03, %al
addb %al, %dl
movb %cl, %al
outb %al, %dx
RET_SP # End of write_[lpc|pci]_reg
read_spd:
/* Input: AH = 05h, AL = byte number of SPD to be read.
Output: BL = The value of specified SPD byte. */
movb $0x05, %ah
CALL_BP(sis_set_smbus)
movw $0x0312, %ax # Start, R/W byte Data
CALL_BP(sis_set_smbus)
wait_for_smbus_read:
movb $0x80, %dl # Read SMBus status
inb %dx, %al
testb $0x02, %al # if device errors
jnz read_spd_fail # then skip read SPD
testb $0x08, %al # if not complete
jz wait_for_smbus_read # then wait SPD data complete
read_spd_fail:
movb $0x08, %ah
sis_get_smbus:
/* Input: AH - register index.
Output: AL - register value. */
addb %ah, %dl # read SMBus byte 0
inb %dx, %al
movb %al, %bl # return result in BL
movw $0x00ff, %ax
CALL_BP(sis_set_smbus) # clear ACPI 80h status
RET_SP # End of read_spd
sis_set_smbus:
/* Input: AH - register index. AL - register value. */
movw $SMB_BASE_ADDR, %dx
addb %ah, %dl
outb %al, %dx
RET_BP # End of sis_set_smbus
doc_reset:
/* Input: AL = value write to DOC_CONTROL register
Clobberd: CX */
movb %al, 0x02(%di) # write DoC Control retister
movb %al, 0x02(%di) # twice
ret # End of doc_reset
doc_cycle_end:
movb $0x00, 0x1e(%di) # flush write pepeline
movb $0x01, 0x04(%di) # end command cycle
ret
sdram_type_bank_1:
# Column Number 8 9 10 11 Row Number
.byte 0b0000, 0b0100, 0b1000, 0xff # 11
.byte 0xff, 0xff, 0xff, 0xff # 12
.byte 0b0001, 0b0101, 0b1001, 0b1101 # 13
sdram_type_bank_2:
# Column Number 8 9 10 11 Row Number
.byte 0b1100, 0xff, 0xff, 0xff # 11
.byte 0b0010, 0b0110, 0b1010, 0b1110 # 12
.byte 0b0011, 0b0111, 0b1011, 0b1111 # 13
pci_init_table:
# High Byte -> Register Low Byte -> Value
#include "dll.inc"
.word 0x5280 #
.word 0x0407 # Turn on Bus Master
.word 0x5680 # Precharge
.word 0x5640 # Mode Register Set
.word 0x5620 # Refresh
.word 0x5620 # Refresh
.word 0x5620 # Refresh
.byte 0x5601 # CAS = 3T
.word 0x50c5 # Refresh Cycle Enable
.word 0x0000 /* Null, End of table */
.org 0x01f0
reset_vector:
.byte 0xea # jmp to fe00:0000, where IPL
.word 0x0000, DOC_WIN_SEG # starts in DoC
spl_vector:
.byte 0xea # jmp to 8000:0000, where SPL
.word 0x0000, SPL_RAM_SEG # (LinuxBIOS) starts in RAM
sis950_init_table:
.byte 0x87, 0x01, 0x55, 0x55, 0x24
end:
hlt

View file

@ -0,0 +1,37 @@
#define PCI_COMMAND_PORT 0xcf8
#define PCI_DATA_PORT 0xcfc
#define NORTH_BRIDGE_BASE_ADDR 0x80000000
#define LPC_BRIDGE_BASE_ADDR 0x80000800
#define SMB_BASE_ADDR 0x5080
#define DOC_WIN_SEG 0xfe00
#define DOC_STACK_SEG 0x0400
#define SPL_RAM_SEG 0x8000
#define DOC_SPL_START_BLK 2 /* 0,1 for IPL */
#define DOC_SPL_SIZE_IN_PAGE 126 /* 1 page = 512 bytes, total 63kB */
#define RET_LABEL(label) \
jmp label##_done
#define CALL_LABEL(label) \
jmp label ;\
label##_done:
#define CALL_SP(func) \
lea 0f, %sp ; \
jmp func ; \
0:
#define RET_SP \
jmp *%sp
#define CALL_BP(func) \
lea 0f, %bp ; \
jmp func ; \
0:
#define RET_BP \
jmp *%bp

View file

@ -0,0 +1,119 @@
/*
* Bootstrap code for the INTEL
* $Id$
*
*/
#ifndef lint
static char rcsid[] =
"$Id$";
#endif
#include <printk.h>
#include <pciconf.h>
#include <subr.h>
#include <pci.h>
#include <pci_ids.h>
#include <northsouthbridge/sis/630/param.h>
/* these functions query the hardware to figure out how much ram is in
* the machine. They then place that information in the parameter block.
* This is kind of schizophrenic, but we do it this way because the
* functions that actually set the registers are kind of hairy, and
* we're not sure they can carry the full burden of also passing on
* the size information to the rest of the bootstrap. Besides, querying
* hardware for ram sizes is trivial.
*/
/* table for calculate the DRAM size, the unit is Mega Bytes */
const static int ramsizes[16] =
{
8, 32, 32, 64, 16, 64, 64, 128,
32, 128, 128, 256, 16, 256, 256, 512
};
#define SIS630_BANKENABLE 0x63
#define SIS630_BANK0 0x60
#define SIS630_BANK1 0x61
#define SIS630_BANK2 0x62
#define SIS630_DIMM_LOCATION_FOR_SMA 0x65
unsigned long sizeram()
{
struct pci_dev *pcidev;
unsigned int dimm_slot, dimm_reg, sides;
unsigned long total_size;
u8 dram_status, dimm_status;
u8 sma_enable, sma_size, sma_size_bits, sma_location;
if ((pcidev = pci_find_device(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_730, NULL)) == NULL)
return 0;
pci_read_config_byte(pcidev, SIS630_BANKENABLE, &dram_status);
dimm_status = dram_status & 0x7;
sma_enable = dram_status & 0x80;
pci_read_config_byte(pcidev, SIS630_DIMM_LOCATION_FOR_SMA, &sma_location);
sma_location &= 0x03;
/* compute Shared Menory Area (SMA) size in Mega Bytes */
sma_size_bits = (dram_status >> 4) & 0x7;
if (sma_size_bits > 5)
// this is invalid!
sma_size = 0;
else {
sma_size = (2 << sma_size_bits);
}
for (dimm_slot = 0, total_size = 0, dimm_reg = SIS630_BANK0;
dimm_reg <= SIS630_BANK2; dimm_slot++, dimm_reg++) {
u8 regval;
if ((dimm_status & (1 << dimm_slot)) == 0)
/* this DIMM slot does not have SDRAM installed */
continue;
pci_read_config_byte(pcidev, dimm_reg, &regval);
/* is this DIMM single or double sided ?? */
if (regval & 0x20)
sides = 2;
else
sides = 1;
/* low-order 4 bits are a ram size */
total_size += (ramsizes[regval & 0xf] * sides);
}
/* the total memory visible to the system is physical memory installed minus the
amount used by VGA (sma_size) */
total_size -= sma_size;
/* return the memory size in KB */
total_size *= 1024;
return total_size;
}
#ifdef HAVE_FRAMEBUFFER
void framebuffer_on()
{
unsigned long devfn = PCI_DEVFN(0, 0);
u32 command;
/* enable legacy VGA register (0x3?4, 0x3?5), not actually needed */
devfn = PCI_DEVFN(2, 0);
pcibios_read_config_dword(0, devfn, 0x3e, &command);
command |= 0x08;
pcibios_write_config_dword(0, devfn, 0x3e, command);
}
#endif /* HAVE_FRAMEBUFFER */
#define RTABLE_DEST 0xf0000
void copy_irq_routing_table(void)
{
#ifdef USE_DOC_MIL
/* copy the PCI IRQ table to segment F, not neceressary for 512KB flash case */
memcpy((char *) RTABLE_DEST, &intel_irq_routing_table, intel_irq_routing_table.size);
#endif /* USE_DOC_MIL */
}

View file

@ -0,0 +1,72 @@
/*
* raminit.inc: Setting registers to their recommended values for SiS 730.
* Since we have inited the DRAM in IPL it is not neceressary
* to do "raminit" here any more.
*
*
* 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 730S Specification
* 2. SiS 730S Register Recommended Setting
* Rev 1.0, Oct. 4, 2000
*
* $Id$
*/
#define PCI_COMMAND_PORT 0xcf8
#define PCI_DATA_PORT 0xcfc
#define NORTH_BRIDGE_BASE_ADDR 0x80000000
register_setting_start:
movl $northbridge_init_table, %esi
movl $(northbridge_init_table_end - northbridge_init_table), %ecx
shrl $0x01, %ecx
init_northbridge:
lodsw (%esi), %ax # load the register address/value to %ax
xchgb %al, %ah # exchange address/values for write_common
call write_northbridge_register
loopnz init_northbridge
jmp register_setting_end
write_northbridge_register:
/* Input: AH - register number. AL - register value. */
movl $NORTH_BRIDGE_BASE_ADDR, %edx
write_common:
movl %eax, %ebx # Save %eax to %ebx.
movzbl %bh, %eax # add register address to
addl %edx, %eax # PCI base address
movw $PCI_COMMAND_PORT, %dx
outl %eax, %dx
movw $PCI_DATA_PORT, %dx
andb $0x03, %al
addb %al, %dl
movb %bl, %al
outb %al, %dx
ret # End of write_[lpc|pci]_reg
#include "730s_regs.inc"
register_setting_end:

View file

@ -0,0 +1,189 @@
/*
* Bootstrap code for the INTEL
* $Id$
*
*/
#ifndef lint
static char rcsid[] =
"$Id$";
#endif
#include <printk.h>
#include <pciconf.h>
#include <subr.h>
#include <pci.h>
#include <pci_ids.h>
#include <northsouthbridge/sis/630/param.h>
#include <cpu/p5/io.h>
void keyboard_on()
{
u8 regval;
struct pci_dev *pcidev;
/* turn on sis730 keyboard/mouse controller */
pcidev = pci_find_device(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503, (void *)NULL);
if (pcidev != NULL) {
/* Register 0x47, Keyboard Controller */
pci_read_config_byte(pcidev, 0x47, &regval);
/* enable both integrated keyboard and PS/2 mouse controller */
regval |= 0x0c;
pci_write_config_byte(pcidev, 0x47, regval);
}
pc_keyboard_init();
}
void nvram_on()
{
struct pci_dev *pcidev;
/* turn on sis730 nvram. */
pcidev = pci_find_device(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503, (void *)NULL);
if (pcidev != NULL) {
/* Enable FFF80000 to FFFFFFFF decode. You have to also enable
PCI Posted write for devices on sourthbridge */
pci_write_config_byte(pcidev, 0x40, 0x33);
/* Flash can be flashed */
pci_write_config_byte(pcidev, 0x45, 0x40);
DBG("Enabled in SIS 503 regs 0x40 and 0x45\n");
}
DBG("Now try to turn off shadow\n");
#ifdef USE_DOC_MIL
/* turn off nvram shadow in 0xc0000 ~ 0xfffff, i.e. accessing segment C - F
is actually to the DRAM not NVRAM. For 512KB NVRAM case, this one should be
disabled */
pcidev = pci_find_device(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_730, (void *)NULL);
DBG("device for SiS 730 is 0x%x\n", pcidev);
if (pcidev != NULL) {
/* read cycle goes to System Memory */
pci_write_config_word(pcidev, 0x70, 0x1fff);
/* write cycle goest to System Memory */
pci_write_config_word(pcidev, 0x72, 0x1fff);
DBG("Shadow memory disabled in SiS 730\n");
}
#endif
}
/* serial_irq_fixup: Enable Serial Interrupt. Serial interrupt is the IRQ line from SiS 950
* LPC to Host Controller. Serial IRQ is neceressary for devices on SiS 950
* ie.e floppy, COM, LPT etc
*/
static void
serial_irq_fixedup(void)
{
struct pci_dev *pcidev;
pcidev = pci_find_device(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503, (void *)NULL);
if (pcidev != NULL) {
/* enable Serial Interrupt (SIRQ) */
pci_write_config_byte(pcidev, 0x70, 0x80);
// skip the SMI, inta, etc. stuff.
// enable IRQs 7 to 1
pci_write_config_byte(pcidev, 0x72, 0xfd);
// enable IRQs 15 to 8
pci_write_config_byte(pcidev, 0x73, 0xff);
}
}
static void
acpi_fixup(void)
{
struct pci_dev *pcidev;
pcidev = pci_find_device(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503, (void *)NULL);
if (pcidev != NULL) {
unsigned char val;
unsigned short acpibase = 0xc000, temp;
int i;
// the following is to turn off software watchdogs.
// we co-op the address space from c000-cfff here. Temporarily.
// Later, we need a better way to do this.
// But since Linux doesn't even understand this yet, no issue.
// Set a base address for ACPI of 0xc000
pci_read_config_word(pcidev, 0x74, &temp);
DBG("acpibase was 0x%x\n", temp);
pci_write_config_word(pcidev, 0x74, acpibase);
pci_read_config_word(pcidev, 0x74, &temp);
DBG("acpibase is 0x%x\n", temp);
// now enable acpi
pci_read_config_byte(pcidev, 0x40, &val);
DBG("acpi enable reg was 0x%x\n", val);
val |= 0x80;
pci_write_config_byte(pcidev, 0x40, val);
pci_read_config_byte(pcidev, 0x40, &val);
DBG("acpi enable reg after set is 0x%x\n", val);
DBG("acpi status: word at 0x56 is 0x%x\n",
inw(acpibase+0x56));
DBG("acpi status: byte at 0x4b is 0x%x\n",
inb(acpibase + 0x4b));
// now that it's on, get in there and call off the dogs.
// that's the recommended thing to do if MD40 iso on.
outw(0, acpibase + 0x56);
// does this help too?
outb(0, acpibase + 0x4b);
// ah ha! have to SET, NOT CLEAR!
outb(0x40, acpibase + 0x56);
DBG("acpibase + 0x56 is 0x%x\n",
inb(acpibase+0x56));
val &= (~0x80);
pci_write_config_byte(pcidev, 0x40, val);
pci_read_config_byte(pcidev, 0x40, &val);
DBG("acpi disable reg after set is 0x%x\n", val);
} else {
printk(KERN_EMERG "Can't find south bridge!\n");
}
}
// simple fixup (which we hope can leave soon) for the sis southbridge part
void
final_southbridge_fixup()
{
struct pci_dev *pcidev;
#ifdef OLD_KERNEL_HACK
pcidev = pci_find_device(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503, (void *)NULL);
if (pcidev != NULL) {
printk("Remapping IRQ on southbridge for OLD_KERNEL_HACK\n");
// remap IRQ for PCI -- this is exactly what the BIOS does now.
pci_write_config_byte(pcidev, 0x42, 0xa);
pci_write_config_byte(pcidev, 0x43, 0xb);
pci_write_config_byte(pcidev, 0x44, 0xc);
}
// ethernet fixup. This should all work, and doesn't, yet.
// so we hack it for now.
// need a manifest constant for the enet device.
pcidev = pci_find_device(PCI_VENDOR_ID_SI, 0x0900, (void *)NULL);
if (pcidev != NULL) {
u32 bar0 = 0xb001;
// set the BAR 0 to 0xb000. Safe, high value, known good.
// pci config set doesn't work for reasons we don't understand.
pci_write_config_dword(pcidev, PCI_BASE_ADDRESS_0, bar0);
// Make sure bus mastering is on. The tried-and-true probe in linuxpci.c
// doesn't set this for some reason.
pci_write_config_byte(pcidev, PCI_COMMAND,
PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
// set the interrupt to 'b'
pci_write_config_byte(pcidev, PCI_INTERRUPT_LINE, 0xb);
} else {
printk(KERN_ERR "Can't find ethernet interface\n");
}
#endif /* OLD_KERNEL_HACK */
serial_irq_fixedup();
acpi_fixup();
DBG("Southbridge fixup done for SIS 503\n");
}