added SiS 635/735 support.
Although the chipset support both SDR and DDR, the DRAM init code support DDR only
This commit is contained in:
parent
58cdd8b2e5
commit
5c7e5ad578
22 changed files with 2495 additions and 0 deletions
22
src/mainboard/sis/635/Config
Normal file
22
src/mainboard/sis/635/Config
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
arch i386
|
||||
mainboardinit cpu/i386/entry16.inc
|
||||
mainboardinit cpu/i386/entry32.inc
|
||||
ldscript cpu/i386/entry16.lds
|
||||
ldscript cpu/i386/entry32.lds
|
||||
|
||||
mainboardinit superio/sis/950/setup_serial.inc
|
||||
mainboardinit pc80/serial.inc
|
||||
mainboardinit arch/i386/lib/console.inc
|
||||
mainboardinit cpu/p6/earlymtrr.inc
|
||||
|
||||
northsouthbridge sis/635
|
||||
nsuperio sis/950 com1={1} floppy=1 lpt=1
|
||||
|
||||
option ENABLE_FIXED_AND_VARIABLE_MTRRS
|
||||
option FINAL_MAINBOARD_FIXUP
|
||||
option HAVE_PIRQ_TABLE=1
|
||||
object mainboard.o
|
||||
object irq_tables.o
|
||||
keyboard pc80
|
||||
cpu p5
|
||||
cpu p6
|
||||
79
src/mainboard/sis/635/irq_tables.c
Normal file
79
src/mainboard/sis/635/irq_tables.c
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
/* This file was generated by getpir.c, do not modify!
|
||||
(but if you do, please run checkpir on it to verify)
|
||||
Contains the IRQ Routing Table dumped directly from your memory , wich BIOS sets up
|
||||
|
||||
Documentation at : http://www.microsoft.com/hwdev/busbios/PCIIRQ.HTM
|
||||
*/
|
||||
|
||||
#include <arch/pirq_routing.h>
|
||||
|
||||
#ifdef AP_CIRCUIT
|
||||
/* This PIRQ table is constructed from
|
||||
* SiS- 635 Single Chipset for Pentium II/ III (Desktop PC)
|
||||
* Uniprocessor Reference Design Schematics Revision 0.94 (March 5, 2001)
|
||||
* unfortunatly this is not what the actual board do */
|
||||
const struct irq_routing_table intel_irq_routing_table = {
|
||||
PIRQ_SIGNATURE, /* u32 signature */
|
||||
PIRQ_VERSION, /* u16 version */
|
||||
32+16*10, /* there can be total 10 devices on the bus */
|
||||
0x00, /* Where the interrupt router lies, Bus 0 */
|
||||
0x10, /* Where the interrupt router lies, Device 2, Function 0 */
|
||||
0x0a20, /* IRQs devoted exclusively to PCI usage, IRQ 11, 10, 5, */
|
||||
0x1039, /* Vendor */
|
||||
0x0008, /* Device */
|
||||
0, /* Crap (miniport) */
|
||||
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* u8 rfu[11] */
|
||||
0x1c, /* u8 checksum , this hase to set to some value that would
|
||||
* give 0 after the sum of all bytes for this structure (including checksum) */
|
||||
{
|
||||
{0, 0x40, {{0x43, 0xdef8}, {0x44, 0xdef8}, {0x41, 0xdef8}, {0x42, 0xdef8}},
|
||||
0x1, 0},
|
||||
{0, 0x38, {{0x42, 0xdef8}, {0x43, 0xdef8}, {0x44, 0xdef8}, {0x41, 0xdef8}},
|
||||
0x2, 0},
|
||||
{0, 0x50, {{0x41, 0xdef8}, {0x42, 0xdef8}, {0x43, 0xdef8}, {0x44, 0xdef8}},
|
||||
0x3, 0},
|
||||
{0, 0x48, {{0x44, 0xdef8}, {0x41, 0xdef8}, {0x42, 0xdef8}, {0x43, 0xdef8}},
|
||||
0x4, 0},
|
||||
{0, 0x60, {{0x43, 0xdef8}, {0x44, 0xdef8}, {0x41, 0xdef8}, {0x42, 0xdef8}},
|
||||
0x5, 0},
|
||||
{0, 0x58, {{0x42, 0xdef8}, {0x43, 0xdef8}, {0x44, 0xdef8}, {0x41, 0xdef8}},
|
||||
0x6, 0},
|
||||
{0, 0x00, {{0x00, 0xdef8}, {0x00, 0xdef8}, {0x00, 0xdef8}, {0x00, 0xdef8}},
|
||||
0x0, 0},
|
||||
{0, 0x08, {{0x41, 0xdef8}, {0x42, 0xdef8}, {0x00, 0xdef8}, {0x00, 0xdef8}},
|
||||
0x0, 0},
|
||||
{0, 0x10, {{0x41, 0xdef8}, {0x42, 0xdef8}, {0x43, 0xdef8}, {0x44, 0xdef8}},
|
||||
0x0, 0},
|
||||
{0, 0x18, {{0x43, 0xdef8}, {0x00, 0xdef8}, {0x00, 0xdef8}, {0x00, 0xdef8}},
|
||||
0x0, 0},
|
||||
}
|
||||
};
|
||||
|
||||
#else
|
||||
const struct irq_routing_table intel_irq_routing_table = {
|
||||
PIRQ_SIGNATURE, /* u32 signature */
|
||||
PIRQ_VERSION, /* u16 version */
|
||||
32+16*9, /* there can be total 9 devices on the bus */
|
||||
0x00, /* Where the interrupt router lies (bus) */
|
||||
0x10, /* Where the interrupt router lies (dev) */
|
||||
0, /* IRQs devoted exclusively to PCI usage */
|
||||
0x1039, /* Vendor */
|
||||
0x0008, /* Device */
|
||||
0, /* Crap (miniport) */
|
||||
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* u8 rfu[11] */
|
||||
0x79, /* u8 checksum , this hase to set to some value that would give
|
||||
* 0 after the sum of all bytes for this structure (including checksum) */
|
||||
{
|
||||
{0,0x58, {{0x43, 0x16b8}, {0x44, 0x16b8}, {0x41, 0x16b8}, {0x42, 0x16b8}}, 0x1, 0},
|
||||
{0,0x48, {{0x42, 0x14b8}, {0x43, 0x16b8}, {0x44, 0x16b8}, {0x41, 0x16b8}}, 0x2, 0},
|
||||
{0,0x68, {{0x44, 0x16b8}, {0x41, 0x16b8}, {0x42, 0x16b8}, {0x43, 0x16b8}}, 0x3, 0},
|
||||
{0,0x00, {{0x00, 0xdef8}, {0x00, 0xdef8}, {0x00, 0xdef8}, {0x00, 0xdef8}}, 0x0, 0},
|
||||
{0,0x08, {{0x41, 0x16b8}, {0x42, 0x16b8}, {0x00, 0xdef8}, {0x00, 0xdef8}}, 0x0, 0},
|
||||
{0,0x10, {{0x41, 0x16b8}, {0x42, 0x16b8}, {0x43, 0x16b8}, {0x44, 0x16b8}}, 0x0, 0},
|
||||
{0,0x18, {{0x43, 0x16b8}, {0x00, 0xdef8}, {0x00, 0xdef8}, {0x00, 0xdef8}}, 0x0, 0},
|
||||
{0,0x20, {{0x43, 0x16b8}, {0x00, 0xdef8}, {0x00, 0xdef8}, {0x00, 0xdef8}}, 0x0, 0},
|
||||
{0,0x28, {{0x41, 0x16b8}, {0x00, 0xdef8}, {0x00, 0xdef8}, {0x00, 0xdef8}}, 0x0, 0},
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
16
src/mainboard/sis/635/mainboard.c
Normal file
16
src/mainboard/sis/635/mainboard.c
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
#include <printk.h>
|
||||
|
||||
void
|
||||
mainboard_fixup(void)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
final_mainboard_fixup(void)
|
||||
{
|
||||
void final_southbridge_fixup(void);
|
||||
|
||||
printk_info("SiS 635 (and similar)...");
|
||||
|
||||
final_southbridge_fixup();
|
||||
}
|
||||
23
src/mainboard/sis/735/Config
Normal file
23
src/mainboard/sis/735/Config
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
arch i386
|
||||
mainboardinit cpu/i386/entry16.inc
|
||||
mainboardinit cpu/i386/entry32.inc
|
||||
ldscript cpu/i386/entry16.lds
|
||||
ldscript cpu/i386/entry32.lds
|
||||
|
||||
mainboardinit superio/sis/950/setup_serial.inc
|
||||
mainboardinit pc80/serial.inc
|
||||
mainboardinit arch/i386/lib/console.inc
|
||||
mainboardinit cpu/k7/earlymtrr.inc
|
||||
|
||||
northsouthbridge sis/735
|
||||
nsuperio sis/950 com1={1} floppy=1 lpt=1
|
||||
|
||||
option ENABLE_FIXED_AND_VARIABLE_MTRRS
|
||||
option FINAL_MAINBOARD_FIXUP
|
||||
option HAVE_PIRQ_TABLE=1
|
||||
object mainboard.o
|
||||
object irq_tables.o
|
||||
keyboard pc80
|
||||
cpu p5
|
||||
cpu p6
|
||||
cpu k7
|
||||
69
src/mainboard/sis/735/irq_tables.c
Normal file
69
src/mainboard/sis/735/irq_tables.c
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
/* This file was generated by getpir.c, do not modify!
|
||||
(but if you do, please run checkpir on it to verify)
|
||||
Contains the IRQ Routing Table dumped directly from your memory , wich BIOS sets up
|
||||
|
||||
Documentation at : http://www.microsoft.com/hwdev/busbios/PCIIRQ.HTM
|
||||
*/
|
||||
|
||||
#include <arch/pirq_routing.h>
|
||||
|
||||
#ifdef AP_CIRCUIT
|
||||
/* This PIRQ table is constructed from
|
||||
* SiS-735 Single Chipset for AMD-K7 (Desktop PC)
|
||||
* Uniprocessor Reference Design Schematics Revision 0.91 (May 24, 2001)
|
||||
* unfortunatly this is not what the actual board do */
|
||||
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, /* Where the interrupt router lies, Bus 0 */
|
||||
0x10, /* Where the interrupt router lies, Device 2, Funxtion 0 */
|
||||
0x0a20, /* IRQs devoted exclusively to PCI usage */
|
||||
0x1039, /* Vendor */
|
||||
0x8, /* Device */
|
||||
0, /* Crap (miniport) */
|
||||
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* u8 rfu[11] */
|
||||
0xe4, /* u8 checksum , this hase to set to some value that would
|
||||
* give 0 after the sum of all bytes for this structure (including checksum) */
|
||||
{
|
||||
{0, 0x58, {{0x43, 0xdef8}, {0x44, 0xdef8}, {0x41, 0xdef8}, {0x42, 0xdef8}}, 0x1, 0},
|
||||
{0, 0x48, {{0x42, 0xdef8}, {0x43, 0xdef8}, {0x44, 0xdef8}, {0x41, 0xdef8}}, 0x2, 0},
|
||||
{0, 0x78, {{0x41, 0xdef8}, {0x42, 0xdef8}, {0x43, 0xdef8}, {0x44, 0xdef8}}, 0x3, 0},
|
||||
{0, 0x68, {{0x44, 0xdef8}, {0x41, 0xdef8}, {0x42, 0xdef8}, {0x43, 0xdef8}}, 0x4, 0},
|
||||
{0, 0x98, {{0x43, 0xdef8}, {0x44, 0xdef8}, {0x41, 0xdef8}, {0x42, 0xdef8}}, 0x5, 0},
|
||||
{0, 0x88, {{0x42, 0xdef8}, {0x43, 0xdef8}, {0x44, 0xdef8}, {0x41, 0xdef8}}, 0x6, 0},
|
||||
{0, 0x00, {{0x00, 0xdef8}, {0x00, 0xdef8}, {0x00, 0xdef8}, {0x00, 0xdef8}}, 0x0, 0},
|
||||
{0, 0x08, {{0x41, 0xdef8}, {0x42, 0xdef8}, {0x43, 0xdef8}, {0x44, 0xdef8}}, 0x0, 0},
|
||||
{0, 0x10, {{0x41, 0xdef8}, {0x42, 0xdef8}, {0x43, 0xdef8}, {0x44, 0xdef8}}, 0x0, 0},
|
||||
{0, 0x18, {{0x43, 0xdef8}, {0x00, 0xdef8}, {0x00, 0xdef8}, {0x00, 0xdef8}}, 0x0, 0},
|
||||
}
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
const struct irq_routing_table intel_irq_routing_table = {
|
||||
PIRQ_SIGNATURE, /* u32 signature */
|
||||
PIRQ_VERSION, /* u16 version */
|
||||
32+16*7, /* there can be total 9 devices on the bus */
|
||||
0x00, /* Where the interrupt router lies, Bus 0 */
|
||||
0x10, /* Where the interrupt router lies, Device 2, Function 0 */
|
||||
0x0a20, /* IRQs devoted exclusively to PCI usage, 5, 9, 11 */
|
||||
0x1039, /* Vendor */
|
||||
0x0008, /* Device */
|
||||
0, /* Crap (miniport) */
|
||||
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* u8 rfu[11] */
|
||||
0x41, /* u8 checksum , this hase to set to some value that would give
|
||||
* 0 after the sum of all bytes for this structure (including checksum) */
|
||||
{
|
||||
/* Mask = 0xdef8, allowing irq 3-7, 1-12, 14,15 */
|
||||
{0,0x58, {{0x43, 0xdef8}, {0x44, 0xdef8}, {0x41, 0xdef8}, {0x42, 0xdef8}}, 0x1, 0},
|
||||
{0,0x48, {{0x42, 0xdef8}, {0x43, 0xdef8}, {0x44, 0xdef8}, {0x41, 0xdef8}}, 0x2, 0},
|
||||
{0,0x68, {{0x44, 0xdef8}, {0x41, 0xdef8}, {0x42, 0xdef8}, {0x43, 0xdef8}}, 0x3, 0},
|
||||
{0,0x00, {{0x00, 0xdef8}, {0x00, 0xdef8}, {0x00, 0xdef8}, {0x00, 0xdef8}}, 0x0, 0},
|
||||
{0,0x08, {{0x41, 0xdef8}, {0x42, 0xdef8}, {0x00, 0xdef8}, {0x00, 0xdef8}}, 0x0, 0},
|
||||
{0,0x10, {{0x41, 0xdef8}, {0x42, 0xdef8}, {0x43, 0xdef8}, {0x44, 0xdef8}}, 0x0, 0},
|
||||
{0,0x18, {{0x43, 0xdef8}, {0x00, 0xdef8}, {0x00, 0xdef8}, {0x00, 0xdef8}}, 0x0, 0},
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
16
src/mainboard/sis/735/mainboard.c
Normal file
16
src/mainboard/sis/735/mainboard.c
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
#include <printk.h>
|
||||
|
||||
void
|
||||
mainboard_fixup(void)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
final_mainboard_fixup(void)
|
||||
{
|
||||
void final_southbridge_fixup(void);
|
||||
|
||||
printk_info("SiS 735 (and similar)...");
|
||||
|
||||
final_southbridge_fixup();
|
||||
}
|
||||
84
src/northsouthbridge/sis/635/635_regs.inc
Normal file
84
src/northsouthbridge/sis/635/635_regs.inc
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* 635_regs.inc: Register Recommended Setting for SiS 635
|
||||
*
|
||||
*
|
||||
* 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 635 Programming Giude, Rev. 1.0, Mar. 29, 2001
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
northbridge_init_table:
|
||||
# High Byte -> Register Low Byte -> Value
|
||||
/* Host Control */
|
||||
.word 0x50ff
|
||||
.word 0x5147
|
||||
.word 0x5271
|
||||
.word 0x5383
|
||||
.word 0x5403
|
||||
.word 0x5501
|
||||
.word 0x5688
|
||||
.word 0x5788
|
||||
|
||||
/* DRAM Control */
|
||||
.word 0x5800
|
||||
.word 0x5a08
|
||||
.word 0x5b03
|
||||
.word 0x5e03
|
||||
|
||||
/* ACPI Control */
|
||||
.word 0x6a26
|
||||
.word 0x6b00
|
||||
|
||||
/* PCI 33 Control */
|
||||
.word 0x8022
|
||||
.word 0x8142
|
||||
.word 0x8210
|
||||
.word 0x8303
|
||||
.word 0x8415
|
||||
.word 0x8500
|
||||
.word 0x8680
|
||||
.word 0x8701
|
||||
|
||||
/* EDB Control */
|
||||
.word 0x8820
|
||||
.word 0x8904
|
||||
.word 0x8b04
|
||||
|
||||
/* IO Buffer */
|
||||
.word 0x9b42
|
||||
.word 0x9f20
|
||||
.word 0xa042
|
||||
.word 0xa12a
|
||||
.word 0xa222
|
||||
.word 0xa301
|
||||
|
||||
/* PCI 66 Control */
|
||||
.word 0xd022
|
||||
.word 0xd142
|
||||
.word 0xd213
|
||||
.word 0xd405
|
||||
.word 0xd5ff
|
||||
.word 0xd6ff
|
||||
.word 0xd860
|
||||
.word 0xd960
|
||||
.word 0xdaaa
|
||||
.word 0xdd88
|
||||
northbridge_init_table_end:
|
||||
5
src/northsouthbridge/sis/635/Config
Normal file
5
src/northsouthbridge/sis/635/Config
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
option SIS635
|
||||
raminit northsouthbridge/sis/635/raminit.inc
|
||||
|
||||
object southbridge.o
|
||||
object northbridge.o
|
||||
493
src/northsouthbridge/sis/635/ipl.S
Normal file
493
src/northsouthbridge/sis/635/ipl.S
Normal file
|
|
@ -0,0 +1,493 @@
|
|||
/*
|
||||
* ipl.S: Initial Program Loader (IPL) for SiS 635
|
||||
*
|
||||
* Copyright 2002 Silicon Integrated Systems Corporation
|
||||
* Copyright 2002 International Business Machines
|
||||
*
|
||||
* 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 635 Programming Guide, Rev. 1.0, Mar. 29, 2001
|
||||
* 2. System Management Bus Specification Rev 1.1
|
||||
* 3. IBM Application Note, DDR SDRAM Module Serial Presence Detect Definitions
|
||||
* 4. JEDEC Standard, DDR SDRAM Speccification, JESD79, June 2000
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include "ipl.h"
|
||||
|
||||
.code16
|
||||
|
||||
#define SPD_SIZING
|
||||
#define SIZE_ALL
|
||||
#define REALLY_COMPACT
|
||||
|
||||
#ifdef STD_FLASH
|
||||
.org 0xfc00
|
||||
#endif
|
||||
|
||||
sis635spd_start:
|
||||
cli # Disables the maskable
|
||||
# hardware interrupts.
|
||||
|
||||
movw %cs, %ax # makes data segment ==
|
||||
movw %ax, %ds # code segment
|
||||
|
||||
movw $pre_dram_sizing_table, %si
|
||||
pre_dram_sizing_start:
|
||||
lodsw (%si), %ax
|
||||
testw %ax, %ax
|
||||
jz pre_dram_sizing_complete
|
||||
|
||||
CALL_SP(write_north_register)
|
||||
jmp pre_dram_sizing_start
|
||||
|
||||
pre_dram_sizing_complete:
|
||||
|
||||
/* According to JEDEC Spec, we have to drive CKE low for at least 200 mu sec
|
||||
* to stabilize DDR. Instead of using some kind of busy delay loop, we
|
||||
* insert some other init stuff before cke_give_up_low and cke_output_normal */
|
||||
cke_enable_low:
|
||||
movw $0x6C30, %ax # Bit 5, Enable CKE output
|
||||
CALL_BP(write_north_register_or) # Bit 4, CKE Force Low
|
||||
|
||||
acpi_enable:
|
||||
movw $0x408A, %ax # ACPI Enable.
|
||||
CALL_SP(write_lpc_register) # (for accessing CKE control)
|
||||
|
||||
movw $0x7550, %ax # Store ACPI Base Address.
|
||||
CALL_SP(write_lpc_register) # (for accessing CKE control)
|
||||
|
||||
movw $smbus_init_table, %si
|
||||
smbus_init_start: # inits SMBus Host Controller
|
||||
lodsw (%si), %ax # for accessing SMBus
|
||||
testw %ax, %ax
|
||||
jz smbus_init_complete
|
||||
|
||||
CALL_SP(write_smbus_register)
|
||||
jmp smbus_init_start
|
||||
|
||||
smbus_init_complete:
|
||||
|
||||
cke_give_up_low:
|
||||
movw $0x5056, %dx # ACPI 0x56 - legacy event control
|
||||
inb %dx, %al # Bit 6, Disable Auto-Reset
|
||||
orb $0x60, %al # Bit 5, CKE control bit for DDR SDRAM
|
||||
outb %al, %dx
|
||||
|
||||
cke_output_normal:
|
||||
mov $0x6C, %ah
|
||||
CALL_SP(read_north_register)
|
||||
and $0xEF, %al # Bit 4, CKE Normal
|
||||
CALL_SP(write_north_register)
|
||||
|
||||
/* -----------------------------------------------------------------------------------------*/
|
||||
|
||||
#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 $0x07, %bl # If the RAM Type == DDR 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 */
|
||||
|
||||
/* 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]
|
||||
|
||||
#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 */
|
||||
|
||||
orb $0x40, %cl # set DDR SDRAM bit
|
||||
# (reg 0x60~0x63 bit 6)
|
||||
|
||||
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~0x63 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 0x60~0x63, accroding
|
||||
# to DIMM slot number (in BH)
|
||||
#endif /* SIZE_ALL */
|
||||
CALL_SP(write_north_register) # write register 0x60~0x63 for each
|
||||
# DIMM slot
|
||||
|
||||
#ifdef SIZE_ALL
|
||||
movw %fs, %ax # enable DIMMx on reg. 0x64 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 $0x04, %bh # total 4 DIMM slots supported
|
||||
jb spd_sizing_start
|
||||
|
||||
movw %fs, %ax
|
||||
movb $0x64, %ah
|
||||
#else /* !SIZE_ALL */
|
||||
no_sdram:
|
||||
movw $0x6401, %ax # enable DIMM 0
|
||||
#endif /* SIZE_ALL */
|
||||
|
||||
CALL_SP(write_north_register) # write DRAM status register 0x64
|
||||
|
||||
/* -----------------------------------------------------------------------------------------*/
|
||||
|
||||
/* Start JEDEC DDR initialization sequence */
|
||||
jedec_ddr_init_seq:
|
||||
movb NO_OP, %bl
|
||||
CALL_BP(dram_ctrl_cmd)
|
||||
|
||||
movw $ddr_init_table, %si
|
||||
init_ddr_sdram:
|
||||
lodsb (%si), %al
|
||||
testb %al, %al
|
||||
jz ddr_init_complete
|
||||
|
||||
movb %al, %bl
|
||||
CALL_BP(dram_ctrl_cmd)
|
||||
jmp init_ddr_sdram
|
||||
|
||||
ddr_init_complete:
|
||||
|
||||
movw $post_dram_init_table, %si
|
||||
post_dram_init_start:
|
||||
lodsw (%si), %ax
|
||||
testw %ax, %ax
|
||||
jz post_dram_init_complete
|
||||
|
||||
CALL_SP(write_north_register)
|
||||
jmp post_dram_init_start
|
||||
|
||||
post_dram_init_complete:
|
||||
|
||||
/* -----------------------------------------------------------------------------------------*/
|
||||
|
||||
sis635ipl_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
|
||||
xorw %sp, %sp # clear %sp
|
||||
|
||||
#ifdef STD_FLASH
|
||||
#include "rom/std_flash.inc"
|
||||
#else /* !STD_FLASH */
|
||||
#include "unlock_flash.inc"
|
||||
#if defined(USE_DOC_MIL) || defined(USE_DOC_2000_TSOP)
|
||||
# include "rom/doc_mil.inc"
|
||||
#else defined(USE_DOC_MIL_PLUS)
|
||||
# include "rom/doc_mil_plus.inc"
|
||||
#endif
|
||||
#endif /* STD_FLASH */
|
||||
|
||||
sis635ipl_end:
|
||||
jmp spl_vector # jump to SPL vector
|
||||
|
||||
|
||||
/* -----------------------------------------------------------------------------------------*/
|
||||
|
||||
write_north_register:
|
||||
/* Input: AH - register number. AL - register value.
|
||||
Chnaged: CX, EDX */
|
||||
movl $NORTH_BRIDGE_BASE_ADDR, %edx
|
||||
jmp write_common
|
||||
|
||||
write_lpc_register:
|
||||
/* Input: AH - register number. AL - register value.
|
||||
Chnaged: CX, EDX */
|
||||
movl $LPC_BRIDGE_BASE_ADDR, %edx
|
||||
jmp write_common
|
||||
|
||||
write_smbus_register:
|
||||
/* Input: AH - register number. AL - register value.
|
||||
Chnaged: CX, EDX */
|
||||
movl $SMBUS_HOST_BASE_ADDR, %edx
|
||||
jmp write_common
|
||||
|
||||
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
|
||||
movw %cx, %ax
|
||||
outb %al, %dx
|
||||
RET_SP # End of write_[pci|smbus]_reg
|
||||
|
||||
/* -----------------------------------------------------------------------------------------*/
|
||||
read_north_register:
|
||||
/* Input: AH - register number.
|
||||
Output AL - register value.
|
||||
Chnaged: CX, EDX */
|
||||
movl $NORTH_BRIDGE_BASE_ADDR, %edx
|
||||
|
||||
read_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
|
||||
inb %dx, %al
|
||||
|
||||
movb %ch, %ah # Resotre register number to %ah
|
||||
|
||||
RET_SP # End of write_[pci|smb]
|
||||
|
||||
write_north_register_or:
|
||||
/* Input: AH - register number. AL - register mask.
|
||||
Chnaged: CX, EDX*/
|
||||
CALL_SP(read_north_register) # %cl == old %al
|
||||
orb %cl, %al
|
||||
CALL_SP(write_north_register)
|
||||
RET_BP
|
||||
|
||||
/* -----------------------------------------------------------------------------------------*/
|
||||
|
||||
dram_ctrl_cmd:
|
||||
/* Input: BL - DRAM COMMAND.
|
||||
Chnaged: AX, CX, EDX*/
|
||||
movb $0x5C, %ah # read 0x5C DRAM Init Control
|
||||
CALL_SP(read_north_register)
|
||||
andb $0x07, %al # Clear Command bits
|
||||
orb %bl, %al # Set DRAM command
|
||||
CALL_SP(write_north_register)
|
||||
orb $0x08, %al # Issue DRAM Command
|
||||
CALL_SP(write_north_register)
|
||||
RET_BP
|
||||
|
||||
/* -----------------------------------------------------------------------------------------*/
|
||||
|
||||
read_spd:
|
||||
/* Input: AH = 05h, AL = byte number of SPD to be read.
|
||||
Output: BL = The value of specified SPD byte. */
|
||||
movb $0x05, %ah # set SMB Command == byte address
|
||||
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: BL - 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
|
||||
|
||||
/* -----------------------------------------------------------------------------------------*/
|
||||
|
||||
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, 0xff # 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
|
||||
# FixMe: Bank 2 x Column 12 x Row 13 == 1GB
|
||||
|
||||
/* -----------------------------------------------------------------------------------------*/
|
||||
|
||||
pre_dram_sizing_table:
|
||||
# High Byte -> Register Low Byte -> Value
|
||||
/* DRAM Control */
|
||||
.word 0x5929 # CAS Latency = 2.5T
|
||||
.word 0x5c12 # MD/DQS Input Enable for DDR
|
||||
.word 0x5dc0 # Refresh Cycle Disabled
|
||||
|
||||
/* ACPI Control */
|
||||
.word 0x6801 # ACPI Enable.
|
||||
.word 0x6950 # Store ACPI Base Address.
|
||||
|
||||
/* IO Buffer */
|
||||
.word 0x9920 # DDR IO Input Mode ==> Differential
|
||||
.word 0x9ab8 # Enable DQS signal delay
|
||||
|
||||
.word 0x0000 /* Null, End of table */
|
||||
|
||||
post_dram_init_table:
|
||||
# High Byte -> Register Low Byte -> Value
|
||||
.word 0x0407 # Enable IO/MEM Space, BM DMA
|
||||
.word 0x0d20
|
||||
|
||||
/* DRAM Control */
|
||||
.word 0x5dc1 # Refresh Cycle Enabled
|
||||
|
||||
.word 0x0000 /* Null, End of table */
|
||||
|
||||
smbus_init_table:
|
||||
# High Byte -> Register Low Byte -> Value
|
||||
.word 0x0401 # enable IO space
|
||||
.word 0x2080 # SMBus Base address =
|
||||
.word 0x2150 # 0x5080
|
||||
.word 0x4001 # enable SMBus Host Controller
|
||||
.word 0x0000 /* Null, End of table */
|
||||
|
||||
ddr_init_table:
|
||||
.byte PALL # Percharge All
|
||||
.byte DLL_EN_N # DLL Enable Normal
|
||||
.byte DLL_RESET # DLL Reset
|
||||
.byte PALL # Precharge All
|
||||
.byte REF # Refresh
|
||||
.byte REF # Refresh
|
||||
.byte MRS # Mode Register Set
|
||||
.byte 0x0000 /* Null, End of table */
|
||||
|
||||
/* -----------------------------------------------------------------------------------------*/
|
||||
#ifdef STD_FLASH
|
||||
.org 0xfff0
|
||||
reset_vector:
|
||||
.byte 0xea # jmp to f000:fc00, where IPL
|
||||
.word 0xfc00, 0xf000 # starts in Standard Flash
|
||||
#else /* !STD_FLASH i.e. DoC Mil */
|
||||
#if defined(USE_DOC_MIL)
|
||||
.org 0x1f0
|
||||
#elif defined(USE_DOC_2000_TSOP) || defined(USE_DOC_MIL_PLUS)
|
||||
.org 0x3f0
|
||||
#endif
|
||||
reset_vector:
|
||||
.byte 0xea # jmp to fc00:0000, where IPL
|
||||
.word 0x0000, DOC_WIN_SEG # starts in DoC
|
||||
#endif /* STD_FLASH */
|
||||
|
||||
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
|
||||
67
src/northsouthbridge/sis/635/ipl.h
Normal file
67
src/northsouthbridge/sis/635/ipl.h
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
#define PCI_COMMAND_PORT 0xcf8
|
||||
#define PCI_DATA_PORT 0xcfc
|
||||
|
||||
#define NORTH_BRIDGE_BASE_ADDR 0x80000000 /* Bus 0, Device 0, Function 0 */
|
||||
#define LPC_BRIDGE_BASE_ADDR 0x80001000 /* Bus 0, Device 2, Function 0 */
|
||||
#define SMBUS_HOST_BASE_ADDR 0x80001100 /* Bus 0, Device 2, Function 1 */
|
||||
|
||||
#define ACPI_BASE_ADDR 0x5000
|
||||
#define SMB_BASE_ADDR 0x5080
|
||||
|
||||
/* DDR Initialization Register and Command */
|
||||
#define DRAM_INIT_REG 0x5c
|
||||
#define DQS_ENABLE 0x02
|
||||
#define DDR_CMD_ISSUE 0x08
|
||||
#define NO_OP 0x00
|
||||
#define PALL 0x10
|
||||
#define MRS 0x20
|
||||
#define REF 0x30
|
||||
#define DLL_EN_N 0x40
|
||||
#define DLL_EN_W 0x50
|
||||
#define DLL_RESET 0x60
|
||||
#define DLL_DISABLE 0x70
|
||||
|
||||
#define DDR_CMD DDR_CMD_ISSUE | DQS_ENABLE
|
||||
#define DDR_CMD_PALL (DRAM_INIT_REG << 8 | PALL | DDR_CMD)
|
||||
#define DDR_CMD_DLL_EN_N (DRAM_INIT_REG << 8 | DLL_EN_N | DDR_CMD)
|
||||
#define DDR_CMD_DLL_RESET (DRAM_INIT_REG << 8 | DLL_RESET | DDR_CMD)
|
||||
#define DDR_CMD_REF (DRAM_INIT_REG << 8 | REF | DDR_CMD)
|
||||
#define DDR_CMD_MRS (DRAM_INIT_REG << 8 | MRS | DDR_CMD)
|
||||
|
||||
#define ENABLE_FRESH_CYCLE 0x5d01
|
||||
|
||||
#define DOC_WIN_SEG 0xfe00
|
||||
#define DOC_STACK_SEG 0x0400
|
||||
#define SPL_RAM_SEG 0x8000
|
||||
|
||||
#if defined(USE_DOC_2000_TSOP)
|
||||
#define DOC_SPL_START_PAGE 4 /* 0-3 for IPL (each of 1KB size) */
|
||||
#else /* defined (USE_DOC_MIL) */
|
||||
#define DOC_SPL_START_PAGE 2 /* 0,1 for IPL (each of 512B size) */
|
||||
#endif
|
||||
|
||||
#define DOC_SPL_SIZE_IN_PAGE 128 - DOC_SPL_START_PAGE /* 1 page = 512 bytes, total 63kB */
|
||||
|
||||
/* Pseudo Call and Return macros */
|
||||
#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
|
||||
109
src/northsouthbridge/sis/635/northbridge.c
Normal file
109
src/northsouthbridge/sis/635/northbridge.c
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
/*
|
||||
* northbridge.c: SiS 635 Northbridge Initialization
|
||||
*
|
||||
* Copyright 2002 International Business Machines
|
||||
*
|
||||
* 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 635 Programing Guide
|
||||
*
|
||||
*/
|
||||
|
||||
#include <printk.h>
|
||||
#include <pciconf.h>
|
||||
#include <subr.h>
|
||||
#include <pci.h>
|
||||
#include <pci_ids.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, 1024, 256, 512
|
||||
};
|
||||
#define SIS635_BANKENABLE 0x64
|
||||
#define SIS635_BANK0 0x60
|
||||
#define SIS635_BANK1 0x61
|
||||
#define SIS635_BANK2 0x62
|
||||
#define SIS635_BANK3 0x63
|
||||
unsigned
|
||||
long sizeram()
|
||||
{
|
||||
struct pci_dev *pcidev;
|
||||
unsigned int dimm_slot, dimm_reg, sides;
|
||||
unsigned long total_size;
|
||||
u8 dram_status, dimm_status;
|
||||
|
||||
if ((pcidev = pci_find_device(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_635, NULL)) == NULL)
|
||||
return 0;
|
||||
|
||||
pci_read_config_byte(pcidev, SIS635_BANKENABLE, &dram_status);
|
||||
dimm_status = dram_status & 0xF;
|
||||
|
||||
for (dimm_slot = 0, total_size = 0, dimm_reg = SIS635_BANK0;
|
||||
dimm_reg <= SIS635_BANK3; 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);
|
||||
}
|
||||
|
||||
/* return the memory size in KB */
|
||||
total_size *= 1024;
|
||||
return total_size;
|
||||
}
|
||||
|
||||
#ifdef HAVE_FRAMEBUFFER
|
||||
void framebuffer_on()
|
||||
{
|
||||
unsigned long devfn;
|
||||
u16 command;
|
||||
|
||||
devfn = PCI_DEVFN(2, 0);
|
||||
|
||||
/* Enable VGA Palette Snoop */
|
||||
pcibios_read_config_word(0, devfn, 0x04, &command);
|
||||
command |= 0x20;
|
||||
pcibios_write_config_word(0, devfn, 0x04, command);
|
||||
|
||||
/* enable legacy VGA IO (0x3B0 - 0x3BB, 0x3C0 - 0x3DF) and MEM (0xA0000 - 0xBFFFF),
|
||||
needed for XFree86 3.3.6 */
|
||||
pcibios_read_config_word(0, devfn, 0x3e, &command);
|
||||
command |= 0x08;
|
||||
pcibios_write_config_word(0, devfn, 0x3e, command);
|
||||
}
|
||||
#endif /* HAVE_FRAMEBUFFER */
|
||||
66
src/northsouthbridge/sis/635/raminit.inc
Normal file
66
src/northsouthbridge/sis/635/raminit.inc
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* raminit.inc: Setting registers to their recommended values for SiS 635.
|
||||
* 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 635 Programming Guide, Rev. 1.0, Mar. 29, 2001
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#define PCI_COMMAND_PORT 0xcf8
|
||||
#define PCI_DATA_PORT 0xcfc
|
||||
|
||||
#define NORTH_BRIDGE_BASE_ADDR 0x80000000
|
||||
#define LPC_BRIDGE_BASE_ADDR 0x80000800
|
||||
|
||||
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
|
||||
|
||||
write_northbridge_register:
|
||||
/* Input: AH - register number. AL - register value. */
|
||||
movl $NORTH_BRIDGE_BASE_ADDR, %edx
|
||||
|
||||
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
|
||||
loopnz init_northbridge
|
||||
|
||||
jmp register_setting_end
|
||||
|
||||
#include "635_regs.inc"
|
||||
|
||||
register_setting_end:
|
||||
294
src/northsouthbridge/sis/635/southbridge.c
Normal file
294
src/northsouthbridge/sis/635/southbridge.c
Normal file
|
|
@ -0,0 +1,294 @@
|
|||
/*
|
||||
* southbridge.c: Southbridge Initialization For SiS 635
|
||||
*
|
||||
* Copyright 2002 International Business Machines
|
||||
*
|
||||
* 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 635 Programing Guide
|
||||
*/
|
||||
|
||||
#include <printk.h>
|
||||
#include <pciconf.h>
|
||||
#include <subr.h>
|
||||
#include <pci.h>
|
||||
#include <pci_ids.h>
|
||||
#include <cpu/p5/io.h>
|
||||
|
||||
#include <types.h>
|
||||
|
||||
#define BYTE sizeof(u8)
|
||||
#define WORD sizeof(u16)
|
||||
#define DBLE sizeof(u32)
|
||||
#define IDE_REG_EXTENDED_OFFSET (0x200u)
|
||||
#define IDE_REG_SECTOR_COUNT(base) ((base) + 2u)
|
||||
#define IDE_REG_CONTROL(base) ((base) + IDE_REG_EXTENDED_OFFSET + 6u)
|
||||
#define IDE_BASE1 (0x1F0u) /* primary controller */
|
||||
#define ASIZE(x) (sizeof(x)/sizeof((x)[0]))
|
||||
|
||||
typedef struct {
|
||||
u8 size;
|
||||
u8 regno;
|
||||
u32 andval;
|
||||
u32 orval;
|
||||
} initreg_t;
|
||||
|
||||
static const initreg_t ide_init[] = {
|
||||
/*
|
||||
* BUS(0), DEVICE(0), FUNCTION(1): IDE Interface. Bridge
|
||||
*/
|
||||
/* SIZE REG AND-MASK OR-MASK */
|
||||
{ WORD, 0x04, 0x00, 0x0007 }, /* Command Register. sets mem+ */
|
||||
{ WORD, 0x06, 0x00, 0x3000 }, /* Status reg, clear aborts. */
|
||||
{ WORD, 0x09, 0x0A, 0x00 }, /* Programming interface = Compatible mode. */
|
||||
{ BYTE, 0x0D, 0x00, 0x80 }, /* Latency Timer */
|
||||
/* We let the pci enumerator assign these. */
|
||||
// { DBLE, 0x10, 0x0, 0x1F1 }, /* Primary channel base addr. */
|
||||
// { DBLE, 0x14, 0x0, 0x3F5 }, /* Primary channel control base addr. */
|
||||
// { DBLE, 0x18, 0x0, 0x171 }, /* Secondary channel base addr. */
|
||||
// { DBLE, 0x1C, 0x0, 0x375 }, /* Secondary channel control base addr. */
|
||||
// { DBLE, 0x20, 0x0, 0x4001 }, /* Control register base addr. */
|
||||
{ WORD, 0x2C, 0x00, 0x1039 }, /* Subsystem vendor ID. */
|
||||
{ WORD, 0x2E, 0x00, 0x5513 }, /* Subsystem ID. */
|
||||
{ BYTE, 0x3c, 0x00, 0x0e }, /* reserved don't do this, sets irq 14 */
|
||||
{ BYTE, 0x40, 0x00, 0x44 }, /* Primary master data active/recovery time. PIO Mode 2 */
|
||||
{ BYTE, 0x41, 0x00, 0x85 }, /* Primary master UDMA cycle time. UDMA Mode 2 */
|
||||
{ BYTE, 0x42, 0x00, 0x00 }, /* Primary slave data recovery time. */
|
||||
{ BYTE, 0x43, 0x00, 0x00 }, /* Primary slave data active time. */
|
||||
{ BYTE, 0x44, 0x00, 0x00 }, /* Secondary master data recovery time. */
|
||||
{ BYTE, 0x45, 0x00, 0x00 }, /* Secondary master data active time. */
|
||||
{ BYTE, 0x46, 0x00, 0x00 }, /* Secondary slave data recovery time. */
|
||||
{ BYTE, 0x47, 0x00, 0x00 }, /* Secondary slave data active time. */
|
||||
{ BYTE, 0x48, 0x00, 0x08 }, /* Read/Write FIFO Threshold = 1/4 */
|
||||
{ BYTE, 0x4A, 0x40, 0xe6 }, /* Enable Bus Master, Fast postwrite, IDE 0,1 */
|
||||
{ BYTE, 0x4B, 0x00, 0x11 }, /* Enable Postwrite and Prefech for IDE0, Master */
|
||||
{ WORD, 0x4C, 0x00, 0x0200 }, /* Prefetch count of primary. */
|
||||
{ WORD, 0x4E, 0x00, 0x0200 }, /* Prefetch count of secondary. */
|
||||
{ BYTE, 0x52, 0xFF, 0x14 } /* Miscelaneous control (Only Doc). */
|
||||
};
|
||||
|
||||
void ide_fixup(void)
|
||||
{
|
||||
|
||||
struct pci_dev *dev = pci_find_device(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5513,
|
||||
(void *) NULL);
|
||||
int i;
|
||||
u8 val8;
|
||||
u16 val16;
|
||||
u32 val32;
|
||||
|
||||
int initlen = ASIZE(ide_init);
|
||||
const initreg_t * inittab = ide_init;
|
||||
|
||||
printk_info ("Entering the initregs process\n");
|
||||
|
||||
for (i = 0; i < initlen; ++i) {
|
||||
u16 regno = inittab[i].regno;
|
||||
switch (inittab[i].size) {
|
||||
case BYTE:
|
||||
pci_read_config_byte(dev, regno, &val8);
|
||||
val8 = (val8 & inittab[i].andval) | inittab[i].orval;
|
||||
pci_write_config_byte(dev, regno, val8);
|
||||
break;
|
||||
case WORD:
|
||||
pci_read_config_word(dev, regno, &val16);
|
||||
val16 = (val16 & inittab[i].andval) | inittab[i].orval;
|
||||
pci_write_config_word(dev, regno, val16);
|
||||
break;
|
||||
case DBLE:
|
||||
pci_read_config_dword(dev, regno, &val32);
|
||||
val32 = (val32 & inittab[i].andval) | inittab[i].orval;
|
||||
break;
|
||||
|
||||
default:
|
||||
outb_p(0xEE,0x80);
|
||||
while(1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void keyboard_on()
|
||||
{
|
||||
u8 regval;
|
||||
struct pci_dev *pcidev;
|
||||
void pc_keyboard_init(void);
|
||||
|
||||
/* turn on sis635 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;
|
||||
u8 tmp;
|
||||
|
||||
/* turn on sis635 nvram. */
|
||||
pcidev = pci_find_device(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503, (void *)NULL);
|
||||
|
||||
if (pcidev != NULL) {
|
||||
printk_info("Enabling nvram\n");
|
||||
/* Enable FFF80000 to FFFFFFFF decode. You have to also enable
|
||||
PCI Posted write for devices on sourthbridge */
|
||||
pci_read_config_byte(pcidev, 0x40, &tmp);
|
||||
tmp |= 0x3;
|
||||
pci_write_config_byte(pcidev, 0x40, tmp);
|
||||
}
|
||||
|
||||
#if !defined(STD_FLASH)
|
||||
/* 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_635, (void *)NULL);
|
||||
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);
|
||||
printk_debug("Shadow memory disabled in SiS 635\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, 0x69, 0x80);
|
||||
pci_write_config_byte(pcidev, 0x67, 0x10);
|
||||
}
|
||||
}
|
||||
|
||||
/* timer0_fixup: Fix up the Timer 0 of 8254 Programmable Timer
|
||||
*
|
||||
* The timer 0 is used to generate the 18.2 Hz, IRQ 0 timer event and used by system
|
||||
* to update date/time.
|
||||
*
|
||||
* FixME: Should be program timer 1 for DRAM refresh too ??
|
||||
*/
|
||||
static void
|
||||
timer0_fixup(void)
|
||||
{
|
||||
/* select Timer 0, 16 Bit Access, Mode 3, Binary */
|
||||
outb_p(0x43, 0x36);
|
||||
|
||||
/* Load LSB, 0x00 */
|
||||
outb_p(0x40, 0x00);
|
||||
|
||||
/* Load MSB, 0x00 */
|
||||
outb_p(0x40, 0x00);
|
||||
}
|
||||
|
||||
/* rtc_fixup: Fix up the Real Time Clock
|
||||
*
|
||||
* The Real Time Clock updates the day/time information in the CMOS RAM every second.
|
||||
* The clock diveder has to be programmed correctly or the RTC will update the CMOS
|
||||
* in incorrect time interval (i.e. more or less then 1Sec in "wall clock").
|
||||
*
|
||||
* FixME: Where does the CMOS stroe Y2K information and how does Linux handle it ??
|
||||
*/
|
||||
static void
|
||||
rtc_fixup(void)
|
||||
{
|
||||
volatile u8 dummy;
|
||||
u8 regval;
|
||||
struct pci_dev *isa_bridge;
|
||||
|
||||
isa_bridge = pci_find_device(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503,
|
||||
(void *)NULL);
|
||||
if (isa_bridge != NULL) {
|
||||
/* Register 0x48, Enable internal RTC */
|
||||
pci_read_config_byte(isa_bridge, 0x48, ®val);
|
||||
pci_write_config_byte(isa_bridge, 0x48, regval | 0x10);
|
||||
}
|
||||
|
||||
/* Select Normal Colok Divider, 978 us interrupt */
|
||||
outb_p(0x0A, 0x70);
|
||||
outb_p(0x26, 0x71);
|
||||
|
||||
/* Select 24 HR time */
|
||||
outb_p(0x0B, 0x70);
|
||||
outb_p(0x02, 0x71);
|
||||
|
||||
/* Clear Checksum Error */
|
||||
outb_p(0x0D, 0x70);
|
||||
dummy = inb_p(0x71);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
// 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_write_config_word(pcidev, 0x74, acpibase);
|
||||
|
||||
// now enable acpi
|
||||
pci_read_config_byte(pcidev, 0x40, &val);
|
||||
val |= 0x80;
|
||||
pci_write_config_byte(pcidev, 0x40, val);
|
||||
|
||||
/* Disable Auto-Reset */
|
||||
val = inb(acpibase + 0x56);
|
||||
outw(val | 0x40, acpibase + 0x56);
|
||||
/* Disable Software Watchdog */
|
||||
outb(0, acpibase + 0x4b);
|
||||
} else {
|
||||
printk_emerg("Can't find south bridge!\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// simple fixup (which we hope can leave soon) for the sis southbridge part
|
||||
void
|
||||
final_southbridge_fixup()
|
||||
{
|
||||
timer0_fixup();
|
||||
rtc_fixup();
|
||||
nvram_on();
|
||||
acpi_fixup();
|
||||
ide_fixup();
|
||||
|
||||
printk_debug("Southbridge fixup done for SIS 635\n");
|
||||
}
|
||||
|
||||
7
src/northsouthbridge/sis/635/unlock_flash.inc
Normal file
7
src/northsouthbridge/sis/635/unlock_flash.inc
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
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
|
||||
88
src/northsouthbridge/sis/735/735_regs.inc
Normal file
88
src/northsouthbridge/sis/735/735_regs.inc
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* 735_regs.inc: Register Recommended Setting for SiS 735
|
||||
*
|
||||
*
|
||||
* 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 735 Programming Guide, Rev. 1.0, Apr. 16, 2001
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
northbridge_init_table:
|
||||
# High Byte -> Register Low Byte -> Value
|
||||
/* BIU Control */
|
||||
.word 0x5007
|
||||
.word 0x51a4
|
||||
.word 0x5277
|
||||
.word 0x53f7
|
||||
.word 0x54aa
|
||||
.word 0x55d4
|
||||
.word 0x56e8
|
||||
.word 0x57f0
|
||||
|
||||
/* DRAM Control */
|
||||
.word 0x5a38
|
||||
.word 0x5b03
|
||||
.word 0x5e03
|
||||
|
||||
/* ACPI Control */
|
||||
.word 0x6a18
|
||||
.word 0x6b03
|
||||
|
||||
/* PCI 33 Control */
|
||||
.word 0x8002
|
||||
.word 0x8140
|
||||
.word 0x8210
|
||||
.word 0x8300
|
||||
.word 0x8415
|
||||
.word 0x8500
|
||||
.word 0x8680
|
||||
.word 0x8701
|
||||
|
||||
/* EDB Control */
|
||||
.word 0x8820
|
||||
.word 0x890c
|
||||
.word 0x8b04
|
||||
|
||||
/* IO Buffer */
|
||||
.word 0x9b40
|
||||
.word 0x9f10
|
||||
.word 0xa041
|
||||
.word 0xa111
|
||||
.word 0xa221
|
||||
.word 0xa301
|
||||
.word 0xa4aa
|
||||
.word 0xa5aa
|
||||
|
||||
/* S2K Interface */
|
||||
.word 0xb836
|
||||
.word 0xb99a
|
||||
.word 0xba48
|
||||
.word 0xbbfa
|
||||
.word 0xbc16
|
||||
|
||||
/* PCI 66 Control */
|
||||
.word 0xd002
|
||||
.word 0xd231
|
||||
.word 0xd409
|
||||
.word 0xd5ff
|
||||
.word 0xd6ff
|
||||
.word 0xdd88
|
||||
northbridge_init_table_end:
|
||||
5
src/northsouthbridge/sis/735/Config
Normal file
5
src/northsouthbridge/sis/735/Config
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
option SIS735
|
||||
raminit northsouthbridge/sis/735/raminit.inc
|
||||
|
||||
object southbridge.o
|
||||
object northbridge.o
|
||||
503
src/northsouthbridge/sis/735/ipl.S
Normal file
503
src/northsouthbridge/sis/735/ipl.S
Normal file
|
|
@ -0,0 +1,503 @@
|
|||
/*
|
||||
* ipl.S: Initial Program Loader (IPL) for SiS 735
|
||||
*
|
||||
* Copyright 2002 Silicon Integrated Systems Corporation
|
||||
* Copyright 2002 International Business Machines
|
||||
*
|
||||
* 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 735 Programming Guide, Rev. 1.0, Apr. 16, 2001
|
||||
* 2. System Management Bus Specification Rev 1.1
|
||||
* 3. IBM Application Note, DDR SDRAM Module Serial Presence Detect Definitions
|
||||
* 4. JEDEC Standard, DDR SDRAM Speccification, JESD79, June 2000
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include "ipl.h"
|
||||
|
||||
.code16
|
||||
|
||||
//#define SPD_SIZING
|
||||
#define SIZE_ALL
|
||||
#define REALLY_COMPACT
|
||||
|
||||
#ifdef STD_FLASH
|
||||
.org 0xfc00
|
||||
#endif
|
||||
|
||||
sis735spd_start:
|
||||
cli # Disables the maskable
|
||||
# hardware interrupts.
|
||||
|
||||
movw %cs, %ax # makes data segment ==
|
||||
movw %ax, %ds # code segment
|
||||
|
||||
movw $pre_dram_sizing_table, %si
|
||||
pre_dram_sizing_start:
|
||||
lodsw (%si), %ax
|
||||
testw %ax, %ax
|
||||
jz pre_dram_sizing_complete
|
||||
|
||||
CALL_SP(write_north_register)
|
||||
jmp pre_dram_sizing_start
|
||||
|
||||
pre_dram_sizing_complete:
|
||||
|
||||
/* According to JEDEC Spec, we have to drive CKE low for at least 200 mu sec
|
||||
* to stabilize DDR. Instead of using some kind of busy delay loop, we
|
||||
* insert some other init stuff before cke_give_up_low and cke_output_normal */
|
||||
cke_enable_low:
|
||||
movw $0x6B30, %ax # Bit 5, Enable CKE output
|
||||
CALL_BP(write_north_register_or) # Bit 4, CKE Force Low
|
||||
|
||||
acpi_enable:
|
||||
movw $0x408A, %ax # ACPI Enable.
|
||||
CALL_SP(write_lpc_register) # (for accessing CKE control)
|
||||
|
||||
movw $0x7550, %ax # Store ACPI Base Address.
|
||||
CALL_SP(write_lpc_register) # (for accessing CKE control)
|
||||
|
||||
movw $smbus_init_table, %si
|
||||
smbus_init_start: # inits SMBus Host Controller
|
||||
lodsw (%si), %ax # for accessing SMBus
|
||||
testw %ax, %ax
|
||||
jz smbus_init_complete
|
||||
|
||||
CALL_SP(write_smbus_register)
|
||||
jmp smbus_init_start
|
||||
|
||||
smbus_init_complete:
|
||||
|
||||
cke_give_up_low:
|
||||
movw $0x5056, %dx # ACPI 0x56 - legacy event control
|
||||
inb %dx, %al # Bit 6, Disable Auto-Reset
|
||||
orb $0x60, %al # Bit 5, CKE control bit for DDR SDRAM
|
||||
outb %al, %dx
|
||||
|
||||
cke_output_normal:
|
||||
mov $0x6B, %ah
|
||||
CALL_SP(read_north_register)
|
||||
and $0xEF, %al # Bit 4, CKE Normal
|
||||
CALL_SP(write_north_register)
|
||||
|
||||
/* -----------------------------------------------------------------------------------------*/
|
||||
#ifndef SPD_SIZING
|
||||
ddr_size:
|
||||
movw $0x614A, %ax
|
||||
CALL_SP(write_north_register)
|
||||
|
||||
movw $0x6402, %ax
|
||||
CALL_SP(write_north_register)
|
||||
#else
|
||||
|
||||
#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 $0x07, %bl # If the RAM Type == DDR 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 */
|
||||
|
||||
/* 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]
|
||||
|
||||
#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 */
|
||||
|
||||
orb $0x40, %cl # set DDR SDRAM bit
|
||||
# (reg 0x60~0x63 bit 6)
|
||||
|
||||
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~0x63 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 0x60~0x63, accroding
|
||||
# to DIMM slot number (in BH)
|
||||
#endif /* SIZE_ALL */
|
||||
CALL_SP(write_north_register) # write register 0x60~0x63 for each
|
||||
# DIMM slot
|
||||
|
||||
#ifdef SIZE_ALL
|
||||
movw %fs, %ax # enable DIMMx on reg. 0x64 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 $0x04, %bh # total 4 DIMM slots supported
|
||||
jb spd_sizing_start
|
||||
|
||||
movw %fs, %ax
|
||||
movb $0x64, %ah
|
||||
#else /* !SIZE_ALL */
|
||||
no_sdram:
|
||||
movw $0x6401, %ax # enable DIMM 0
|
||||
#endif /* SIZE_ALL */
|
||||
|
||||
CALL_SP(write_north_register) # write DRAM status register 0x64
|
||||
|
||||
#endif
|
||||
|
||||
/* -----------------------------------------------------------------------------------------*/
|
||||
|
||||
/* Start JEDEC DDR initialization sequence */
|
||||
jedec_ddr_init_seq:
|
||||
movb NO_OP, %bl
|
||||
CALL_BP(dram_ctrl_cmd)
|
||||
|
||||
movw $ddr_init_table, %si
|
||||
init_ddr_sdram:
|
||||
lodsb (%si), %al
|
||||
testb %al, %al
|
||||
jz ddr_init_complete
|
||||
|
||||
movb %al, %bl
|
||||
CALL_BP(dram_ctrl_cmd)
|
||||
jmp init_ddr_sdram
|
||||
|
||||
ddr_init_complete:
|
||||
|
||||
movw $post_dram_init_table, %si
|
||||
post_dram_init_start:
|
||||
lodsw (%si), %ax
|
||||
testw %ax, %ax
|
||||
jz post_dram_init_complete
|
||||
|
||||
CALL_SP(write_north_register)
|
||||
jmp post_dram_init_start
|
||||
|
||||
post_dram_init_complete:
|
||||
|
||||
/* -----------------------------------------------------------------------------------------*/
|
||||
|
||||
sis735ipl_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
|
||||
xorw %sp, %sp # clear %sp
|
||||
|
||||
#ifdef STD_FLASH
|
||||
#include "rom/std_flash.inc"
|
||||
#else /* !STD_FLASH */
|
||||
#include "unlock_flash.inc"
|
||||
#if defined(USE_DOC_MIL) || defined(USE_DOC_2000_TSOP)
|
||||
# include "rom/doc_mil.inc"
|
||||
#else defined(USE_DOC_MIL_PLUS)
|
||||
# include "rom/doc_mil_plus.inc"
|
||||
#endif
|
||||
#endif /* STD_FLASH */
|
||||
|
||||
sis735ipl_end:
|
||||
jmp spl_vector # jump to SPL vector
|
||||
|
||||
|
||||
/* -----------------------------------------------------------------------------------------*/
|
||||
|
||||
write_north_register:
|
||||
/* Input: AH - register number. AL - register value.
|
||||
Chnaged: CX, EDX */
|
||||
movl $NORTH_BRIDGE_BASE_ADDR, %edx
|
||||
jmp write_common
|
||||
|
||||
write_lpc_register:
|
||||
/* Input: AH - register number. AL - register value.
|
||||
Chnaged: CX, EDX */
|
||||
movl $LPC_BRIDGE_BASE_ADDR, %edx
|
||||
jmp write_common
|
||||
|
||||
write_smbus_register:
|
||||
/* Input: AH - register number. AL - register value.
|
||||
Chnaged: CX, EDX */
|
||||
movl $SMBUS_HOST_BASE_ADDR, %edx
|
||||
jmp write_common
|
||||
|
||||
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
|
||||
movw %cx, %ax
|
||||
outb %al, %dx
|
||||
RET_SP # End of write_[pci|smbus]_reg
|
||||
|
||||
/* -----------------------------------------------------------------------------------------*/
|
||||
read_north_register:
|
||||
/* Input: AH - register number.
|
||||
Output AL - register value.
|
||||
Chnaged: CX, EDX */
|
||||
movl $NORTH_BRIDGE_BASE_ADDR, %edx
|
||||
|
||||
read_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
|
||||
inb %dx, %al
|
||||
|
||||
movb %ch, %ah # Resotre register number to %ah
|
||||
|
||||
RET_SP # End of write_[pci|smb]
|
||||
|
||||
write_north_register_or:
|
||||
/* Input: AH - register number. AL - register mask.
|
||||
Chnaged: CX, EDX*/
|
||||
CALL_SP(read_north_register) # %cl == old %al
|
||||
orb %cl, %al
|
||||
CALL_SP(write_north_register)
|
||||
RET_BP
|
||||
|
||||
/* -----------------------------------------------------------------------------------------*/
|
||||
|
||||
dram_ctrl_cmd:
|
||||
/* Input: BL - DRAM COMMAND.
|
||||
Chnaged: AX, CX, EDX*/
|
||||
movb $0x5C, %ah # read 0x5C DRAM Init Control
|
||||
CALL_SP(read_north_register)
|
||||
andb $0x07, %al # Clear Command bits
|
||||
orb %bl, %al # Set DRAM command
|
||||
CALL_SP(write_north_register)
|
||||
orb $0x08, %al # Issue DRAM Command
|
||||
CALL_SP(write_north_register)
|
||||
RET_BP
|
||||
|
||||
/* -----------------------------------------------------------------------------------------*/
|
||||
|
||||
read_spd:
|
||||
/* Input: AH = 05h, AL = byte number of SPD to be read.
|
||||
Output: BL = The value of specified SPD byte. */
|
||||
movb $0x05, %ah # set SMB Command == byte address
|
||||
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: BL - 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
|
||||
|
||||
/* -----------------------------------------------------------------------------------------*/
|
||||
|
||||
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, 0xff # 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
|
||||
# FixMe: Bank 2 x Column 12 x Row 13 == 1GB
|
||||
|
||||
/* -----------------------------------------------------------------------------------------*/
|
||||
|
||||
pre_dram_sizing_table:
|
||||
# High Byte -> Register Low Byte -> Value
|
||||
/* DRAM Control */
|
||||
.word 0x5929 # CAS Latency = 2.5T
|
||||
.word 0x5c12 # MD/DQS Input Enable for DDR
|
||||
.word 0x5dc0 # Refresh Cycle Disabled
|
||||
|
||||
/* ACPI Control */
|
||||
.word 0x6801 # ACPI Enable.
|
||||
.word 0x6950 # Store ACPI Base Address.
|
||||
|
||||
/* IO Buffer */
|
||||
.word 0x9910 # DDR IO Input Mode ==> Differential
|
||||
.word 0x9ab8 # Enable DQS signal delay
|
||||
|
||||
.word 0x0000 /* Null, End of table */
|
||||
|
||||
post_dram_init_table:
|
||||
# High Byte -> Register Low Byte -> Value
|
||||
.word 0x0407 # Enable IO/MEM Space, BM DMA
|
||||
.word 0x0d20
|
||||
|
||||
/* DRAM Control */
|
||||
.word 0x5dc1 # Refresh Cycle Enabled
|
||||
|
||||
.word 0x0000 /* Null, End of table */
|
||||
|
||||
smbus_init_table:
|
||||
# High Byte -> Register Low Byte -> Value
|
||||
.word 0x0401 # enable IO space
|
||||
.word 0x2080 # SMBus Base address =
|
||||
.word 0x2150 # 0x5080
|
||||
.word 0x4001 # enable SMBus Host Controller
|
||||
.word 0x0000 /* Null, End of table */
|
||||
|
||||
ddr_init_table:
|
||||
.byte PALL # Percharge All
|
||||
.byte DLL_EN_N # DLL Enable Normal
|
||||
.byte DLL_RESET # DLL Reset
|
||||
.byte PALL # Precharge All
|
||||
.byte REF # Refresh
|
||||
.byte REF # Refresh
|
||||
.byte MRS # Mode Register Set
|
||||
.byte 0x0000 /* Null, End of table */
|
||||
|
||||
/* -----------------------------------------------------------------------------------------*/
|
||||
#ifdef STD_FLASH
|
||||
.org 0xfff0
|
||||
reset_vector:
|
||||
.byte 0xea # jmp to f000:fc00, where IPL
|
||||
.word 0xfc00, 0xf000 # starts in Standard Flash
|
||||
#else /* !STD_FLASH i.e. DoC Mil */
|
||||
#if defined(USE_DOC_MIL)
|
||||
.org 0x1f0
|
||||
#elif defined(USE_DOC_2000_TSOP) || defined(USE_DOC_MIL_PLUS)
|
||||
.org 0x3f0
|
||||
#endif
|
||||
reset_vector:
|
||||
.byte 0xea # jmp to fc00:0000, where IPL
|
||||
.word 0x0000, DOC_WIN_SEG # starts in DoC
|
||||
#endif /* STD_FLASH */
|
||||
|
||||
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
|
||||
67
src/northsouthbridge/sis/735/ipl.h
Normal file
67
src/northsouthbridge/sis/735/ipl.h
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
#define PCI_COMMAND_PORT 0xcf8
|
||||
#define PCI_DATA_PORT 0xcfc
|
||||
|
||||
#define NORTH_BRIDGE_BASE_ADDR 0x80000000 /* Bus 0, Device 0, Function 0 */
|
||||
#define LPC_BRIDGE_BASE_ADDR 0x80001000 /* Bus 0, Device 2, Function 0 */
|
||||
#define SMBUS_HOST_BASE_ADDR 0x80001100 /* Bus 0, Device 2, Function 1 */
|
||||
|
||||
#define ACPI_BASE_ADDR 0x5000
|
||||
#define SMB_BASE_ADDR 0x5080
|
||||
|
||||
/* DDR Initialization Register and Command */
|
||||
#define DRAM_INIT_REG 0x5c
|
||||
#define DQS_ENABLE 0x02
|
||||
#define DDR_CMD_ISSUE 0x08
|
||||
#define NO_OP 0x00
|
||||
#define PALL 0x10
|
||||
#define MRS 0x20
|
||||
#define REF 0x30
|
||||
#define DLL_EN_N 0x40
|
||||
#define DLL_EN_W 0x50
|
||||
#define DLL_RESET 0x60
|
||||
#define DLL_DISABLE 0x70
|
||||
|
||||
#define DDR_CMD DDR_CMD_ISSUE | DQS_ENABLE
|
||||
#define DDR_CMD_PALL (DRAM_INIT_REG << 8 | PALL | DDR_CMD)
|
||||
#define DDR_CMD_DLL_EN_N (DRAM_INIT_REG << 8 | DLL_EN_N | DDR_CMD)
|
||||
#define DDR_CMD_DLL_RESET (DRAM_INIT_REG << 8 | DLL_RESET | DDR_CMD)
|
||||
#define DDR_CMD_REF (DRAM_INIT_REG << 8 | REF | DDR_CMD)
|
||||
#define DDR_CMD_MRS (DRAM_INIT_REG << 8 | MRS | DDR_CMD)
|
||||
|
||||
#define ENABLE_FRESH_CYCLE 0x5d01
|
||||
|
||||
#define DOC_WIN_SEG 0xfe00
|
||||
#define DOC_STACK_SEG 0x0400
|
||||
#define SPL_RAM_SEG 0x8000
|
||||
|
||||
#if defined(USE_DOC_2000_TSOP)
|
||||
#define DOC_SPL_START_PAGE 4 /* 0-3 for IPL (each of 1KB size) */
|
||||
#else /* defined (USE_DOC_MIL) */
|
||||
#define DOC_SPL_START_PAGE 2 /* 0,1 for IPL (each of 512B size) */
|
||||
#endif
|
||||
|
||||
#define DOC_SPL_SIZE_IN_PAGE 128 - DOC_SPL_START_PAGE /* 1 page = 512 bytes, total 63kB */
|
||||
|
||||
/* Pseudo Call and Return macros */
|
||||
#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
|
||||
109
src/northsouthbridge/sis/735/northbridge.c
Normal file
109
src/northsouthbridge/sis/735/northbridge.c
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
/*
|
||||
* northbridge.c: SiS 735 Northbridge Initialization
|
||||
*
|
||||
* Copyright 2002 International Business Machines
|
||||
*
|
||||
* 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 735 Programing Guide
|
||||
*
|
||||
*/
|
||||
|
||||
#include <printk.h>
|
||||
#include <pciconf.h>
|
||||
#include <subr.h>
|
||||
#include <pci.h>
|
||||
#include <pci_ids.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, 1024, 256, 512
|
||||
};
|
||||
#define SIS735_BANKENABLE 0x64
|
||||
#define SIS735_BANK0 0x60
|
||||
#define SIS735_BANK1 0x61
|
||||
#define SIS735_BANK2 0x62
|
||||
#define SIS735_BANK3 0x63
|
||||
unsigned
|
||||
long sizeram()
|
||||
{
|
||||
struct pci_dev *pcidev;
|
||||
unsigned int dimm_slot, dimm_reg, sides;
|
||||
unsigned long total_size;
|
||||
u8 dram_status, dimm_status;
|
||||
|
||||
if ((pcidev = pci_find_device(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_735, NULL)) == NULL)
|
||||
return 0;
|
||||
|
||||
pci_read_config_byte(pcidev, SIS735_BANKENABLE, &dram_status);
|
||||
dimm_status = dram_status & 0xF;
|
||||
|
||||
for (dimm_slot = 0, total_size = 0, dimm_reg = SIS735_BANK0;
|
||||
dimm_reg <= SIS735_BANK3; 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);
|
||||
}
|
||||
|
||||
/* return the memory size in KB */
|
||||
total_size *= 1024;
|
||||
return total_size;
|
||||
}
|
||||
|
||||
#ifdef HAVE_FRAMEBUFFER
|
||||
void framebuffer_on()
|
||||
{
|
||||
unsigned long devfn;
|
||||
u16 command;
|
||||
|
||||
devfn = PCI_DEVFN(2, 0);
|
||||
|
||||
/* Enable VGA Palette Snoop */
|
||||
pcibios_read_config_word(0, devfn, 0x04, &command);
|
||||
command |= 0x20;
|
||||
pcibios_write_config_word(0, devfn, 0x04, command);
|
||||
|
||||
/* enable legacy VGA IO (0x3B0 - 0x3BB, 0x3C0 - 0x3DF) and MEM (0xA0000 - 0xBFFFF),
|
||||
needed for XFree86 3.3.6 */
|
||||
pcibios_read_config_word(0, devfn, 0x3e, &command);
|
||||
command |= 0x08;
|
||||
pcibios_write_config_word(0, devfn, 0x3e, command);
|
||||
}
|
||||
#endif /* HAVE_FRAMEBUFFER */
|
||||
67
src/northsouthbridge/sis/735/raminit.inc
Normal file
67
src/northsouthbridge/sis/735/raminit.inc
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* raminit.inc: Setting registers to their recommended values for SiS 735.
|
||||
* 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 735 Programming Guide, Rev. 1.0, Apr. 16, 2001
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#define PCI_COMMAND_PORT 0xcf8
|
||||
#define PCI_DATA_PORT 0xcfc
|
||||
|
||||
#define NORTH_BRIDGE_BASE_ADDR 0x80000000
|
||||
#define LPC_BRIDGE_BASE_ADDR 0x80000800
|
||||
|
||||
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
|
||||
|
||||
write_northbridge_register:
|
||||
/* Input: AH - register number. AL - register value. */
|
||||
movl $NORTH_BRIDGE_BASE_ADDR, %edx
|
||||
|
||||
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
|
||||
loopnz init_northbridge
|
||||
|
||||
jmp register_setting_end
|
||||
|
||||
#include "735_regs.inc"
|
||||
|
||||
register_setting_end:
|
||||
299
src/northsouthbridge/sis/735/southbridge.c
Normal file
299
src/northsouthbridge/sis/735/southbridge.c
Normal file
|
|
@ -0,0 +1,299 @@
|
|||
/*
|
||||
* southbridge.c: Southbridge Initialization For SiS 735
|
||||
*
|
||||
* Copyright 2002 International Business Machines
|
||||
*
|
||||
* 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 735 Programing Guide
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char rcsid[] =
|
||||
"$Id$";
|
||||
#endif
|
||||
|
||||
#include <printk.h>
|
||||
#include <pciconf.h>
|
||||
#include <subr.h>
|
||||
#include <pci.h>
|
||||
#include <pci_ids.h>
|
||||
#include <cpu/p5/io.h>
|
||||
|
||||
#include <types.h>
|
||||
|
||||
#define BYTE sizeof(u8)
|
||||
#define WORD sizeof(u16)
|
||||
#define DBLE sizeof(u32)
|
||||
#define IDE_REG_EXTENDED_OFFSET (0x200u)
|
||||
#define IDE_REG_SECTOR_COUNT(base) ((base) + 2u)
|
||||
#define IDE_REG_CONTROL(base) ((base) + IDE_REG_EXTENDED_OFFSET + 6u)
|
||||
#define IDE_BASE1 (0x1F0u) /* primary controller */
|
||||
#define ASIZE(x) (sizeof(x)/sizeof((x)[0]))
|
||||
|
||||
typedef struct {
|
||||
u8 size;
|
||||
u8 regno;
|
||||
u32 andval;
|
||||
u32 orval;
|
||||
} initreg_t;
|
||||
|
||||
static const initreg_t ide_init[] = {
|
||||
/*
|
||||
* BUS(0), DEVICE(0), FUNCTION(1): IDE Interface. Bridge
|
||||
*/
|
||||
/* SIZE REG AND-MASK OR-MASK */
|
||||
{ WORD, 0x04, 0x00, 0x0007 }, /* Command Register. sets mem+ */
|
||||
{ WORD, 0x06, 0x00, 0x3000 }, /* Status reg, clear aborts. */
|
||||
{ WORD, 0x09, 0x0A, 0x00 }, /* Programming interface = Compatible mode. */
|
||||
{ BYTE, 0x0D, 0x00, 0x80 }, /* Latency Timer */
|
||||
/* We let the pci enumerator assign these. */
|
||||
// { DBLE, 0x10, 0x0, 0x1F1 }, /* Primary channel base addr. */
|
||||
// { DBLE, 0x14, 0x0, 0x3F5 }, /* Primary channel control base addr. */
|
||||
// { DBLE, 0x18, 0x0, 0x171 }, /* Secondary channel base addr. */
|
||||
// { DBLE, 0x1C, 0x0, 0x375 }, /* Secondary channel control base addr. */
|
||||
// { DBLE, 0x20, 0x0, 0x4001 }, /* Control register base addr. */
|
||||
{ WORD, 0x2C, 0x00, 0x1039 }, /* Subsystem vendor ID. */
|
||||
{ WORD, 0x2E, 0x00, 0x5513 }, /* Subsystem ID. */
|
||||
{ BYTE, 0x3c, 0x00, 0x0e }, /* reserved don't do this, sets irq 14 */
|
||||
{ BYTE, 0x40, 0x00, 0x44 }, /* Primary master data active/recovery time. PIO Mode 2 */
|
||||
{ BYTE, 0x41, 0x00, 0x85 }, /* Primary master UDMA cycle time. UDMA Mode 2 */
|
||||
{ BYTE, 0x42, 0x00, 0x00 }, /* Primary slave data recovery time. */
|
||||
{ BYTE, 0x43, 0x00, 0x00 }, /* Primary slave data active time. */
|
||||
{ BYTE, 0x44, 0x00, 0x00 }, /* Secondary master data recovery time. */
|
||||
{ BYTE, 0x45, 0x00, 0x00 }, /* Secondary master data active time. */
|
||||
{ BYTE, 0x46, 0x00, 0x00 }, /* Secondary slave data recovery time. */
|
||||
{ BYTE, 0x47, 0x00, 0x00 }, /* Secondary slave data active time. */
|
||||
{ BYTE, 0x48, 0x00, 0x08 }, /* Read/Write FIFO Threshold = 1/4 */
|
||||
{ BYTE, 0x4A, 0x40, 0xe6 }, /* Enable Bus Master, Fast postwrite, IDE 0 */
|
||||
{ BYTE, 0x4B, 0x00, 0x11 }, /* Enable Postwrite and Prefech for IDE0, Master */
|
||||
{ WORD, 0x4C, 0x00, 0x0200 }, /* Prefetch count of primary. */
|
||||
{ WORD, 0x4E, 0x00, 0x0200 }, /* Prefetch count of secondary. */
|
||||
{ BYTE, 0x52, 0xFF, 0x14 } /* Miscelaneous control (Only Doc). */
|
||||
};
|
||||
|
||||
void ide_fixup(void)
|
||||
{
|
||||
|
||||
struct pci_dev *dev = pci_find_device(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5513,
|
||||
(void *) NULL);
|
||||
int i;
|
||||
u8 val8;
|
||||
u16 val16;
|
||||
u32 val32;
|
||||
|
||||
int initlen = ASIZE(ide_init);
|
||||
const initreg_t * inittab = ide_init;
|
||||
|
||||
printk_info ("Entering the initregs process\n");
|
||||
|
||||
for (i = 0; i < initlen; ++i) {
|
||||
u16 regno = inittab[i].regno;
|
||||
switch (inittab[i].size) {
|
||||
case BYTE:
|
||||
pci_read_config_byte(dev, regno, &val8);
|
||||
val8 = (val8 & inittab[i].andval) | inittab[i].orval;
|
||||
pci_write_config_byte(dev, regno, val8);
|
||||
break;
|
||||
case WORD:
|
||||
pci_read_config_word(dev, regno, &val16);
|
||||
val16 = (val16 & inittab[i].andval) | inittab[i].orval;
|
||||
pci_write_config_word(dev, regno, val16);
|
||||
break;
|
||||
case DBLE:
|
||||
pci_read_config_dword(dev, regno, &val32);
|
||||
val32 = (val32 & inittab[i].andval) | inittab[i].orval;
|
||||
break;
|
||||
|
||||
default:
|
||||
outb_p(0xEE,0x80);
|
||||
while(1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void keyboard_on()
|
||||
{
|
||||
u8 regval;
|
||||
struct pci_dev *pcidev;
|
||||
void pc_keyboard_init(void);
|
||||
|
||||
/* turn on sis735 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;
|
||||
u8 tmp;
|
||||
|
||||
/* turn on sis735 nvram. */
|
||||
pcidev = pci_find_device(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503, (void *)NULL);
|
||||
|
||||
if (pcidev != NULL) {
|
||||
printk_info("Enabling nvram\n");
|
||||
/* Enable FFF80000 to FFFFFFFF decode. You have to also enable
|
||||
PCI Posted write for devices on sourthbridge */
|
||||
pci_read_config_byte(pcidev, 0x40, &tmp);
|
||||
tmp |= 0x3;
|
||||
pci_write_config_byte(pcidev, 0x40, tmp);
|
||||
}
|
||||
|
||||
#if !defined(STD_FLASH)
|
||||
/* 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_735, (void *)NULL);
|
||||
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);
|
||||
printk_debug("Shadow memory disabled in SiS 735\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, 0x69, 0x80);
|
||||
pci_write_config_byte(pcidev, 0x67, 0x10);
|
||||
}
|
||||
}
|
||||
|
||||
/* timer0_fixup: Fix up the Timer 0 of 8254 Programmable Timer
|
||||
*
|
||||
* The timer 0 is used to generate the 18.2 Hz, IRQ 0 timer event and used by system
|
||||
* to update date/time.
|
||||
*
|
||||
* FixME: Should be program timer 1 for DRAM refresh too ??
|
||||
*/
|
||||
static void
|
||||
timer0_fixup(void)
|
||||
{
|
||||
/* select Timer 0, 16 Bit Access, Mode 3, Binary */
|
||||
outb_p(0x43, 0x36);
|
||||
|
||||
/* Load LSB, 0x00 */
|
||||
outb_p(0x40, 0x00);
|
||||
|
||||
/* Load MSB, 0x00 */
|
||||
outb_p(0x40, 0x00);
|
||||
}
|
||||
|
||||
/* rtc_fixup: Fix up the Real Time Clock
|
||||
*
|
||||
* The Real Time Clock updates the day/time information in the CMOS RAM every second.
|
||||
* The clock diveder has to be programmed correctly or the RTC will update the CMOS
|
||||
* in incorrect time interval (i.e. more or less then 1Sec in "wall clock").
|
||||
*
|
||||
* FixME: Where does the CMOS stroe Y2K information and how does Linux handle it ??
|
||||
*/
|
||||
static void
|
||||
rtc_fixup(void)
|
||||
{
|
||||
volatile u8 dummy;
|
||||
u8 regval;
|
||||
struct pci_dev *isa_bridge;
|
||||
|
||||
isa_bridge = pci_find_device(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503,
|
||||
(void *)NULL);
|
||||
if (isa_bridge != NULL) {
|
||||
/* Register 0x48, Enable internal RTC */
|
||||
pci_read_config_byte(isa_bridge, 0x48, ®val);
|
||||
pci_write_config_byte(isa_bridge, 0x48, regval | 0x10);
|
||||
}
|
||||
|
||||
/* Select Normal Colok Divider, 978 us interrupt */
|
||||
outb_p(0x0A, 0x70);
|
||||
outb_p(0x26, 0x71);
|
||||
|
||||
/* Select 24 HR time */
|
||||
outb_p(0x0B, 0x70);
|
||||
outb_p(0x02, 0x71);
|
||||
|
||||
/* Clear Checksum Error */
|
||||
outb_p(0x0D, 0x70);
|
||||
dummy = inb_p(0x71);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
// 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_write_config_word(pcidev, 0x74, acpibase);
|
||||
|
||||
// now enable acpi
|
||||
pci_read_config_byte(pcidev, 0x40, &val);
|
||||
val |= 0x80;
|
||||
pci_write_config_byte(pcidev, 0x40, val);
|
||||
|
||||
/* Disable Auto-Reset */
|
||||
val = inb(acpibase + 0x56);
|
||||
outw(val | 0x40, acpibase + 0x56);
|
||||
/* Disable Software Watchdog */
|
||||
outb(0, acpibase + 0x4b);
|
||||
} else {
|
||||
printk_emerg("Can't find south bridge!\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// simple fixup (which we hope can leave soon) for the sis southbridge part
|
||||
void
|
||||
final_southbridge_fixup()
|
||||
{
|
||||
timer0_fixup();
|
||||
rtc_fixup();
|
||||
nvram_on();
|
||||
acpi_fixup();
|
||||
ide_fixup();
|
||||
|
||||
printk_debug("Southbridge fixup done for SIS 735\n");
|
||||
}
|
||||
|
||||
7
src/northsouthbridge/sis/735/unlock_flash.inc
Normal file
7
src/northsouthbridge/sis/735/unlock_flash.inc
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
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
|
||||
Loading…
Add table
Add a link
Reference in a new issue