From 42e38b5a3e10487797bb1291198e93f2000a5c78 Mon Sep 17 00:00:00 2001 From: Li-Ta Lo Date: Wed, 23 May 2001 02:48:26 +0000 Subject: [PATCH] add sis 540 support --- src/mainboard/sis/540/Config | 10 + src/mainboard/sis/540/dll.inc | 8 + src/mainboard/sis/540/irq_tables.c | 29 ++ src/mainboard/sis/540/mainboard.c | 21 ++ src/northsouthbridge/sis/540/540_regs.inc | 106 ++++++ src/northsouthbridge/sis/540/Config | 7 + src/northsouthbridge/sis/540/ipl.S | 408 +++++++++++++++++++++ src/northsouthbridge/sis/540/ipl.h | 37 ++ src/northsouthbridge/sis/540/northbridge.c | 111 ++++++ src/northsouthbridge/sis/540/raminit.inc | 75 ++++ src/northsouthbridge/sis/540/southbridge.c | 159 ++++++++ util/config/sis540.config | 16 + 12 files changed, 987 insertions(+) create mode 100644 src/mainboard/sis/540/Config create mode 100644 src/mainboard/sis/540/dll.inc create mode 100644 src/mainboard/sis/540/irq_tables.c create mode 100644 src/mainboard/sis/540/mainboard.c create mode 100644 src/northsouthbridge/sis/540/540_regs.inc create mode 100644 src/northsouthbridge/sis/540/Config create mode 100644 src/northsouthbridge/sis/540/ipl.S create mode 100644 src/northsouthbridge/sis/540/ipl.h create mode 100644 src/northsouthbridge/sis/540/northbridge.c create mode 100644 src/northsouthbridge/sis/540/raminit.inc create mode 100644 src/northsouthbridge/sis/540/southbridge.c create mode 100644 util/config/sis540.config diff --git a/src/mainboard/sis/540/Config b/src/mainboard/sis/540/Config new file mode 100644 index 0000000000..1013e49759 --- /dev/null +++ b/src/mainboard/sis/540/Config @@ -0,0 +1,10 @@ +northsouthbridge sis/540 +# superio sis/950 +nsuperio sis/950 com1={1} floppy=1 lpt=1 + +option FINAL_MAINBOARD_FIXUP +option HAVE_PIRQ_TABLE +object mainboard.o +object irq_tables.o +keyboard pc80 +cpu p5 diff --git a/src/mainboard/sis/540/dll.inc b/src/mainboard/sis/540/dll.inc new file mode 100644 index 0000000000..29f53946a3 --- /dev/null +++ b/src/mainboard/sis/540/dll.inc @@ -0,0 +1,8 @@ + /* Table for DLL Clock Control Register (0x8c - 0x8f), these + register values are very Mainboard specific */ + +# High Byte -> Register Low Byte -> Value + .word 0x8c44 # set Clock DLL control register + .word 0x8d86 # 0x8c ~ 0x8f, + .word 0x8ec1 # these values are very M/B + .word 0x8f46 # specific diff --git a/src/mainboard/sis/540/irq_tables.c b/src/mainboard/sis/540/irq_tables.c new file mode 100644 index 0000000000..35ac6a1eb6 --- /dev/null +++ b/src/mainboard/sis/540/irq_tables.c @@ -0,0 +1,29 @@ +#include + +#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}, + } +}; diff --git a/src/mainboard/sis/540/mainboard.c b/src/mainboard/sis/540/mainboard.c new file mode 100644 index 0000000000..32805afb41 --- /dev/null +++ b/src/mainboard/sis/540/mainboard.c @@ -0,0 +1,21 @@ +#include + +void +mainboard_fixup(void) +{ +} + +void +final_mainboard_fixup(void) +{ + void final_southbridge_fixup(void); + void final_superio_fixup(void); + + printk(KERN_INFO + "SiS 540 (and similar)..."); + + final_southbridge_fixup(); +#ifndef USE_NEW_SUPERIO_INTERFACE + final_superio_fixup(); +#endif +} diff --git a/src/northsouthbridge/sis/540/540_regs.inc b/src/northsouthbridge/sis/540/540_regs.inc new file mode 100644 index 0000000000..603adb7c07 --- /dev/null +++ b/src/northsouthbridge/sis/540/540_regs.inc @@ -0,0 +1,106 @@ +/* + * 630_regs.inc: Register Recommended Setting for SiS 630 [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$ + */ + +northbridge_init_table: +# Reg. Value + /* generic PCI configuration space */ + .byte 0x04, 0x07 # Turn on Bus Master, + .byte 0x05, 0x00 # Memory and I/O Space + .byte 0x06, 0x00 # clear PCI status + .byte 0x07, 0x00 # + .byte 0x0D, 0x20 # Master Latency Timer = 32 PCI CLCK + + .byte 0x13, 0xe0 + + /* SiS 540 specific registers. See SiS 540 Registers Recommended Setting */ + + /* Host Control Interface */ + .byte 0x50, 0xfe # + .byte 0x51, 0x08 # + + /* DRAM Control */ + .byte 0x52, 0xC5 # + .byte 0x53, 0xc0 # + + .byte 0x54, 0x08 # + .byte 0x55, 0x01 # + .byte 0x56, 0x00 # + .byte 0x57, 0x00 # + + /* Pre-driver Slew Rate/Current Driving Control */ + .byte 0x58, 0x00 # + .byte 0x59, 0x55 # + .byte 0x5A, 0x55 # + .byte 0x5B, 0x00 # + + .byte 0x65, 0x00 # Use DIMM 0 for SMA + + /* MISC Control */ +// .byte 0x6A, 0xC0 # +// .byte 0x6B, 0x01 # 0x00 -> 66/133 MHZ, 0x01 -> 100 MHZ +// .byte 0x6C, 0x20 # 0x2E -> 66 MHZ, 0x20 -> 100 MHZ, 0x2C -> 133 MHZ + + /* PCI Interface */ + .byte 0x80, 0x01 # + .byte 0x81, 0xd1 # + .byte 0x82, 0xce # + .byte 0x83, 0x1b # + + .byte 0x84, 0x60 # + .byte 0x85, 0x00 # + .byte 0x86, 0x03 # +// .byte 0x87, 0x00 # + .byte 0x88, 0x00 # + .byte 0x89, 0x08 # + + .byte 0x8a, 0x00 # + .byte 0x8b, 0x00 # + + /* 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 0x97, 0x01 # Page Table Cache Enable + .byte 0x98, 0x00 # + + /* DRAM Priority Timer Control Register */ + .byte 0xA0, 0x00 + .byte 0xA1, 0x00 + .byte 0xA2, 0x03 + .byte 0xA3, 0x01 + + /* AGP Command Register */ +// .byte 0xC8, 0x04 # AGP 4X +// .byte 0xC9, 0x00 # AGP Disabled + +northbridge_init_table_end: \ No newline at end of file diff --git a/src/northsouthbridge/sis/540/Config b/src/northsouthbridge/sis/540/Config new file mode 100644 index 0000000000..c1405c8685 --- /dev/null +++ b/src/northsouthbridge/sis/540/Config @@ -0,0 +1,7 @@ +option SIS540 +option USE_DOC_MIL +docipl northsouthbridge/sis/540/ipl.S +raminit northsouthbridge/sis/540/raminit.inc + +object southbridge.o +object northbridge.o diff --git a/src/northsouthbridge/sis/540/ipl.S b/src/northsouthbridge/sis/540/ipl.S new file mode 100644 index 0000000000..dbc8a66957 --- /dev/null +++ b/src/northsouthbridge/sis/540/ipl.S @@ -0,0 +1,408 @@ +/* + * ipl.S: Initial Program Loader (IPL) for SiS 630 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 630 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 + +sis630spd_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 $0x90, %al # enable SMA 4 MB for VGA +#endif /* HAVE_FRAMEBUFFER */ + +#else /* !SIZE_ALL */ + +no_sdram: +#ifdef HAVE_FRAMEBUFFER + # enable DIMM 0 and + movw $0x6391, %ax # enable SMA 4 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: +sis630ipl_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 + +sis630ipl_end: + 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 0x8c44 # Precharge + .word 0x8d86 # Mode Register Set + .word 0x8ec1 # Refresh + .word 0x8f46 # Refresh + + .word 0x5780 # Precharge + .word 0x5740 # Mode Register Set + .word 0x5720 # Refresh + .word 0x5720 # Refresh + .word 0x5720 # Refresh + .word 0x5201 # 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 diff --git a/src/northsouthbridge/sis/540/ipl.h b/src/northsouthbridge/sis/540/ipl.h new file mode 100644 index 0000000000..8b364da493 --- /dev/null +++ b/src/northsouthbridge/sis/540/ipl.h @@ -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 diff --git a/src/northsouthbridge/sis/540/northbridge.c b/src/northsouthbridge/sis/540/northbridge.c new file mode 100644 index 0000000000..4185beb348 --- /dev/null +++ b/src/northsouthbridge/sis/540/northbridge.c @@ -0,0 +1,111 @@ + +/* + * Bootstrap code for the INTEL + * $Id$ + * + */ + +#ifndef lint +static char rcsid[] = +"$Id$"; +#endif + + +#include +#include +#include +#include +#include +#include + +/* 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_630, NULL)) == NULL) +// return 0; + + if ((pcidev = pci_find_device(PCI_VENDOR_ID_SI, 0x0540, 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, ®val); + + /* 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 */ diff --git a/src/northsouthbridge/sis/540/raminit.inc b/src/northsouthbridge/sis/540/raminit.inc new file mode 100644 index 0000000000..3c690b090d --- /dev/null +++ b/src/northsouthbridge/sis/540/raminit.inc @@ -0,0 +1,75 @@ +/* + * raminit.inc: Setting registers to their recommended values for SiS 630. + * 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 630 Specification + * 2. SiS 630A1 Register Recommended Setting + * Rev 0.97, Jan 7, 2000 + * + * $Id$ + */ + +#define PCI_COMMAND_PORT 0xcf8 +#define PCI_DATA_PORT 0xcfc + +#define NORTH_BRIDGE_BASE_ADDR 0x80000000 + + /* set new stack */ + movl $_estack, %esp + +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 "540_regs.inc" + +register_setting_end: \ No newline at end of file diff --git a/src/northsouthbridge/sis/540/southbridge.c b/src/northsouthbridge/sis/540/southbridge.c new file mode 100644 index 0000000000..5999b8d44e --- /dev/null +++ b/src/northsouthbridge/sis/540/southbridge.c @@ -0,0 +1,159 @@ + +/* + * Bootstrap code for the INTEL + * $Id$ + * + */ + +#ifndef lint +static char rcsid[] = +"$Id$"; +#endif + + +#include +#include +#include +#include +#include +#include +#include + +void keyboard_on() +{ + u8 regval; + struct pci_dev *pcidev; + + /* turn on sis630 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, ®val); + /* 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 sis540 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_540, (void *)NULL); + DBG("device for SiS 540 is 0x%x\n", pcidev); + if (pcidev != NULL) { + /* read cycle goes to System Memory */ + /* write cycle goest to System Memory */ + pci_write_config_word(pcidev, 0x70, 0xFFFF); + pci_write_config_word(pcidev, 0x72, 0xFFFF); + pci_write_config_word(pcidev, 0x74, 0xFFFF); + pci_write_config_byte(pcidev, 0x76, 0xFF); + DBG("Shadow memory disabled in SiS 540\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; + + serial_irq_fixedup(); + acpi_fixup(); + + DBG("Southbridge fixup done for SIS 503\n"); +} diff --git a/util/config/sis540.config b/util/config/sis540.config new file mode 100644 index 0000000000..b54a2eefd7 --- /dev/null +++ b/util/config/sis540.config @@ -0,0 +1,16 @@ +# Sample config file for SiS 550 SoC with DoC Millennium (as root) +arch i386 +# This will make a target directory of ./winfast +target sis540 + +# SiS 550 SoC demo mainboard +mainboard sis/540 + +# Use the internal VGA frame buffer device +option HAVE_FRAMEBUFFER + +# Path to your kernel (vmlinux) +linux /usr/src/linux + +# Kernel command line parameters +commandline root=/dev/hda1 console=tty0 video=sisfb:1024x768-32@85,font:VGA8x16