g2200 support!

This commit is contained in:
Ronald G. Minnich 2002-03-04 18:21:50 +00:00
commit b9c4b06256
11 changed files with 1466 additions and 0 deletions

View file

@ -192,6 +192,12 @@
#define PCI_DEVICE_ID_NS_87415 0x0002
#define PCI_DEVICE_ID_NS_87560_LIO 0x000e
#define PCI_DEVICE_ID_NS_87560_USB 0x0012
#define PCI_DEVICE_ID_NS_SCx200_BRIDGE 0x0500
#define PCI_DEVICE_ID_NS_SCx200_SMI 0x0501
#define PCI_DEVICE_ID_NS_SCx200_IDE 0x0502
#define PCI_DEVICE_ID_NS_SCx200_AUDIO 0x0503
#define PCI_DEVICE_ID_NS_SCx200_VIDEO 0x0504
#define PCI_DEVICE_ID_NS_SCx200_XBUS 0x0505
#define PCI_DEVICE_ID_NS_87410 0xd001
#define PCI_VENDOR_ID_TSENG 0x100c

View file

@ -0,0 +1,243 @@
$Id$
--- linux-2.4.17-orig/drivers/ide/ide-pci.c Thu Oct 25 14:53:47 2001
+++ linux-2.4.17-smartcore/drivers/ide/ide-pci.c Wed Jan 9 11:03:18 2002
@@ -697,9 +697,20 @@
goto controller_ok;
if ((IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20262)) && (secondpdc++==1) && (port==1) )
goto controller_ok;
-
+#ifndef CONFIG_LINUXBIOS_FORCE_IDE_CONTROLLER_ON
if (e->reg && (pci_read_config_byte(dev, e->reg, &tmp) || (tmp & e->mask) != e->val))
continue; /* port not enabled */
+#else
+ /* force 'em on! */
+ if (e->reg) {
+ pci_read_config_byte(dev, e->reg, &tmp);
+ tmp |= e->val;
+ pci_write_config_byte(dev, e->reg, tmp);
+ printk("%s: LINUXBIOS, so Jammed the enable on!\n",
+ d->name);
+ }
+
+#endif
controller_ok:
if (IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT366) && (port) && (class_rev < 0x03))
return;
--- linux-2.4.17-orig/drivers/ide/ide-probe.c Mon Nov 26 06:29:17 2001
+++ linux-2.4.17-smartcore/drivers/ide/ide-probe.c Wed Jan 9 11:03:18 2002
@@ -310,6 +310,13 @@
if ((drive->media != ide_disk) && (cmd == WIN_IDENTIFY))
return 4;
}
+#ifdef CONFIG_LINUXBIOS_WAIT_HDA_SPINUP
+ if (! strncmp(drive->name, "hda", 3)) {
+ printk("jamming drive present for %s\n", drive->name);
+ drive->present = 1;
+ }
+#endif
+
#ifdef DEBUG
printk("probing for %s: present=%d, media=%d, probetype=%s\n",
drive->name, drive->present, drive->media,
--- linux-2.4.17-orig/arch/i386/config.in Fri Dec 21 10:41:53 2001
+++ linux-2.4.17-smartcore/arch/i386/config.in Wed Jan 9 11:03:18 2002
@@ -416,3 +416,13 @@
fi
endmenu
+
+mainmenu_option next_comment
+comment 'LinuxBIOS'
+
+tristate 'LinuxBIOS Support' CONFIG_LINUXBIOS
+if [ "$CONFIG_LINUXBIOS" != "n" ]; then
+ source arch/i386/Linuxbios.in
+fi
+
+endmenu
--- linux-2.4.17-orig/arch/i386/kernel/process.c Thu Oct 4 19:42:54 2001
+++ linux-2.4.17-smartcore/arch/i386/kernel/process.c Fri Jan 18 09:57:47 2002
@@ -49,6 +49,159 @@
#include <linux/irq.h>
+#define CONFIG_LINUXBIOS_PM
+#ifdef CONFIG_LINUXBIOS_PM
+#include <linux/pci.h>
+#ifdef CONFIG_LINUXBIOS_PM_SIS503
+void
+sis503_reset(struct pci_dev *dev)
+{
+ unsigned char b;
+ unsigned short acpi_base;
+
+ printk(KERN_ERR __FUNCTION__ ": starting reset operation. \n");
+
+ /* Enable ACPI by set B7 on Reg 0x40, LPC */
+ pci_read_config_byte(dev, 0x40, &b);
+ pci_write_config_byte(dev, 0x40, b | 0x80);
+ printk(KERN_ERR __FUNCTION__ ": enabled ACPI. \n");
+
+ /* get the ACPI base address for register 0x74,0x75 of LPC */
+ pci_read_config_word(dev, 0x74, &acpi_base);
+ printk(KERN_ERR __FUNCTION__ ":acpi base: %x\n", acpi_base);
+
+ /* Set software watchdog timer init value */
+ outb(0x03, 0x4a + acpi_base);
+ printk(KERN_ERR __FUNCTION__ ": set the dog. \n");
+
+ printk(KERN_ERR __FUNCTION__ ": enabling dog. \n");
+ /* Software watchdog enable, issue PCIRST# when time expire */
+ outb(0x8f, 0x4b + acpi_base);
+
+ printk(KERN_ERR __FUNCTION__ ": We should reset soon. \n");
+}
+
+void
+sis503_off(struct pci_dev *dev)
+{
+ unsigned char b;
+ unsigned short acpi_base;
+
+ printk(KERN_ERR __FUNCTION__ ": starting reset operation. \n");
+ /* Enable ACPI by set B7 on Reg 0x40, LPC */
+ pci_read_config_byte(dev, 0x40, &b);
+ pci_write_config_byte(dev, 0x40, b | 0x80);
+ printk(KERN_ERR __FUNCTION__ ": enabled ACPI. \n");
+
+ /* get the ACPI base address for register 0x74,0x75 of LPC */
+ pci_read_config_word(dev, 0x74, &acpi_base);
+ printk (KERN_ERR __FUNCTION__ ":acpi base: %x\n", acpi_base);
+
+ /* ACPI Register 5, Bit 10-12, Sleeping Type,
+ set to 101 -> S5, soft_off */
+ outb(0x14, 0x05 + acpi_base);
+ printk(KERN_ERR __FUNCTION__ ": DONE setting sleep type. \n");
+
+ /* ACPI Register 5, Bit 13, Sleep Enable */
+ outb(0x20 | 0x14, 0x05 + acpi_base);
+ printk(KERN_ERR __FUNCTION__ ": DONE sleep enable. \n");
+}
+#endif // CONFIG_LINUXBIOS_PM_SIS503
+#ifdef CONFIG_LINUXBIOS_PM_PIIX4E
+void
+piix4e_reset(struct pci_dev *dev)
+{
+ // simple on this part. outb 0x6 to 0xcf9
+
+ printk(KERN_ERR __FUNCTION__ ": starting reset operation. \n");
+ outb(0x6, 0xcf9);
+ printk(KERN_ERR __FUNCTION__ ": We should reset soon. \n");
+}
+
+void
+piix4e_off(struct pci_dev *dev)
+{
+ unsigned char b;
+ unsigned short acpi_base;
+
+ printk(KERN_ERR __FUNCTION__ ": no power off on this chip! \n");
+}
+#endif
+struct pci_dev * pci_find_device(unsigned int vendor, unsigned int device,
+ const struct pci_dev *from);
+
+struct linuxbios_control {
+ u_short vendor, device;
+ void (*poweroff)(struct pci_dev *);
+ void (*reset)(struct pci_dev *);
+};
+
+struct linuxbios_control controls[] = {
+#ifdef CONFIG_LINUXBIOS_PM_SIS503
+ {PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503, sis503_off, sis503_reset}
+#endif
+#ifdef CONFIG_LINUXBIOS_PM_PIIX4E
+ {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3,
+ piix4e_off, piix4e_reset},
+#endif
+ {0}
+};
+
+struct linuxbios_control *findcontrol(struct pci_dev **d)
+{
+ struct linuxbios_control *lb = controls, *retval = 0;
+ int i;
+
+ printk(KERN_ERR __FUNCTION__ ": Find vendor 0x%x device 0x%x\n",
+ lb->vendor, lb->device);
+ for(lb = controls, i = 0;
+ (i < sizeof(controls)/sizeof(controls[0])) && (! retval);
+ i++, lb++)
+ {
+ *d = pci_find_device(lb->vendor, lb->device, 0);
+ if (*d)
+ retval = lb;
+ }
+
+ printk(KERN_ERR __FUNCTION__ ": result of find is %p\n", retval);
+ return retval;
+}
+
+void
+linuxbios_poweroff(void)
+{
+ struct linuxbios_control *lb = 0;
+ struct pci_dev *dev;
+
+ printk(KERN_ERR __FUNCTION__ ": find an lb\n");
+ lb = findcontrol(&dev);
+
+ printk(KERN_ERR __FUNCTION__ ": found lb %p, call %p\n",
+ lb, lb ? lb->poweroff : 0);
+ if (lb && (lb->poweroff))
+ lb->poweroff(dev);
+ printk(KERN_ERR __FUNCTION__ ": Returning? Can't happen, I thought?\n");
+}
+
+void
+linuxbios_reset(void)
+{
+ struct linuxbios_control *lb = 0;
+ struct pci_dev *dev;
+
+ printk(KERN_ERR __FUNCTION__ ": find an lb\n");
+ lb = findcontrol(&dev);
+
+ printk(KERN_ERR __FUNCTION__ ": found lb %p, call %p\n",
+ lb, lb ? lb->reset : 0);
+ if (lb && (lb->reset))
+ lb->reset(dev);
+ printk(KERN_ERR __FUNCTION__ ": Returning? Can't happen, I thought?\n");
+}
+
+#endif
+
+
asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
int hlt_counter;
@@ -399,6 +552,9 @@
*/
smp_send_stop();
disable_IO_APIC();
+#endif
+#ifdef CONFIG_LINUXBIOS_PM
+ linuxbios_reset();
#endif
if(!reboot_thru_bios) {
--- linux-2.4.17-orig/arch/i386/Linuxbios.in Tue Jan 22 10:22:05 2002
+++ linux-2.4.17-smartcore/arch/i386/Linuxbios.in Fri Jan 18 10:03:05 2002
@@ -0,0 +1,10 @@
+mainmenu_option next_comment
+comment 'Linuxbios Options'
+bool 'Force IDE Controllers on?' CONFIG_LINUXBIOS_FORCE_IDE_CONTROLLER_ON
+bool 'Wait for HDA to spin up?' CONFIG_LINUXBIOS_WAIT_HDA_SPINUP
+bool 'Linuxbios Power Management support?' CONFIG_LINUXBIOS_PM
+if [ "$CONFIG_LINUXBIOS_PM" = "y" ]; then
+ bool ' SIS 503 support?' CONFIG_LINUXBIOS_PM_SIS503
+ bool ' PIIX4E support?' CONFIG_LINUXBIOS_PM_PIIX4E
+fi
+endmenu

View file

@ -0,0 +1,126 @@
# Copyright (c) 2002 Christer Weinigel <wingel@hack.org>
# This is a config file Nano Computer from Nano Computer Systems
# <URL:http://www.nano-system.com> (warning, the page is in Swedish,
# but the products link might be interesting)
# The NC is a National Semiconductor SC2200 based design with two
# NatSemi DP83815 ethernet chips, one PCI slot, an onboard Compact
# Flash and an external IDE connector. Other features are two serial
# ports, an I2C/SMBUS with two temperature sensors and a serial
# EEPROM, and an Intel StrataFlash (4,8 or 16MB) soldered to the
# board. Finally there is a VGA connector but that is mostly intended
# for debugging and not really for production use.
arch i386
mainboardinit cpu/i386/entry16.inc
mainboardinit cpu/i386/entry32.inc
ldscript cpu/i386/entry16.lds
ldscript cpu/i386/entry32.lds
mainboardinit cpu/i386/reset16.inc
ldscript cpu/i386/reset16.lds
########################################################################
# Where the Disk On Chip Chip Select pin is mapped in memory.
# See the SCx200 databook for more information.
option SCx200_DOCCS_BASE=0xc0000000
option SCx200_DOCCS_CTRL=0x070007ff
########################################################################
# If you want to use this as a reference for other SCx200 based boards
# be aware that the settings of the following registers are _very_
# important. PMR means Pin Multiplexing Register and the PMR togheter
# with the MCR are used to reconfigure the pin assignments of the
# processor, for example, the pins that drive a TFT screen can be used
# as an IDE port, so if you make a mistake here, the pins would source
# TTL voltages instead of TFT voltages and fry your, probably very
# expensive, TFT screen. So:
# DON'T MESS WITH THESE SETTINGS UNLESS YOU KNOW WHAT YOU ARE DOING!
# And don't blindly try this on any other SCx200 based hardware, first
# look at the schematics and then read, and understand, the SCx200
# data books.
#option SCx200_PMR=0x02060891
option SCx200_PMR=0x02860891
option SCx200_MCR=0x00000411
########################################################################
# Some constans, you probably don't need to change anything here.
# Where to put the SCx200 configuration block, the address 0x9000 is
# really mandated in a SCx200 errata, but you can change it.
option SCx200_CB_BASE=0x9000
# GX_BASE is the address of another configuration block, this one for
# the GX1 processor that is a part of the SCx200. You probably don't
# want to change this either, unless you have a very strange memory map.
option GX_BASE=0x40000000
########################################################################
# Super I/O configuration
# Does not do anything yet, the address is always hardcoded to 0x15c
#option SCx200_SIO_BASE=0x15c
# Serial port 1
option SCx200_SP1_BASE=0x3f8
option SCx200_SP1_IRQ=4
# Serial port 2
option SCx200_SP2_BASE=0x2f8
option SCx200_SP2_IRQ=3
# Serial port 3
option SCx200_SP3_BASE=0x3e8
option SCx200_SP3_IRQ=4
# Parallel port
option SCx200_PP_BASE=0x278
option SCx200_PP_IRQ=7
# ACCESS.bus 1
option SCx200_ACB1_BASE=0x8200
option SCx200_ACB1_IRQ=0
# ACCESS.bus 2
option SCx200_ACB2_BASE=0x8400
option SCx200_ACB2_IRQ=0
# Interrupt steering, same as a Cx5530
option SCx200_INTA=9
option SCx200_INTB=10
option SCx200_INTC=11
option SCx200_INTD=12
# This is probably the same as a Cx5530
option SCx200_PRIMARY_IDE
#option SCx200_SECONDARY_IDE
########################################################################
# Finally, the code
# This must be done before the serial port is initialized, so
# it has to be here.
mainboardinit northsouthbridge/NSC/scx200/chipset_setup.inc
mainboardinit pc80/serial.inc
mainboardinit arch/i386/lib/console.inc
northsouthbridge NSC/scx200
option NO_KEYBOARD
option FINAL_MAINBOARD_FIXUP=1
object mainboard.o
# The PIRQ table doesn't seem to work properly, so the PCI interrupts
# are set up in final_mainboard_fixup instead.
# FIXME -- build a working irq table
#option HAVE_PIRQ_TABLE=1
#object irq_tables.o
cpu p5
# Local variables:
# compile-command: "make -C /export/nano/bios/nano"
# End:

View file

@ -0,0 +1,51 @@
# Copyright (c) 2002 Christer Weinigel <wingel@hack.org>
# This is an example configuration file for the Nano Computer from
# Nano Computer Systems <URL:http://www.nano-system.com> (warning,
# the page is in Swedish, but the products link might be interesting)
# See src/mainboard/nano/nano/Config for more information
target nano
mainboard nano/nano
# Enable Serial Console for debugging
option SERIAL_CONSOLE=1
option TTYS0_BAUD=38400
option DEFAULT_CONSOLE_LOGLEVEL=9
option DEBUG
#option INBUF_COPY
option RAMTEST
#option BOOT_IDE=1
#option BOOT_TFTP=1
# I'm using the onboard Intel Strataflash to store LinuxBIOS and the
# Linux Kernel. I have also put LinuxBIOS in the BIOS ROM chip.
# The reason for using such a strange address as 0xc0000200 below is
# that the BIOS seems to do some kind of destructive probing of the
# DOC socket that causes it to write garbage to address 0x80 of the
# flash chip.
option USE_GENERIC_ROM=1
option ZKERNEL_START=0xc0000200
option ZKERNEL_MASK=0xffff
option ROM_SIZE=262144
# If you want a watdog timer initialized as early as possible. 30
# seconds might be a good choice, if the Linux kernel isn't up and
# running and has started the Linux Watchdog driver before then
# the system will do a hard reset.
#option SCx200_WATCHDOG=30
# Path to your kernel (vmlinux)
linux /export/nano/linux
# Kernel command line parameters
commandline root=/dev/hda2 console=ttyS0,38400
#commandline root=/dev/nfs ip=dhcp console=ttyS0,38400

View file

@ -0,0 +1,53 @@
#include <subr.h>
#include <arch/pirq_routing.h>
/*
* This table must be located between 0x000f0000 and 0x000fffff.
* By defining it as a const it gets located in the code segment
* and therefore inside the necessary 64K block. -tds
*/
#define CHECKSUM 0xd2
const struct irq_routing_table intel_irq_routing_table = {
PIRQ_SIGNATURE, /* u32 signature */
PIRQ_VERSION, /* u16 version */
32+16*3, /* u16 size - size of entire table struct */
0, /* u8 rtr_bus - router bus */
0x90, /* u8 rtr_devfn - router devfn */
0x1e00, /* u16 exclusive_irqs - mask of IRQs for PCI use */
0x100b, /* u16 rtr_vendor - router vendor id */
0x0500, /* u16 rtr_devfn - router device id */
0, /* 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 */
/* struct irq_info slots[0] */
{
/* bus, devfn, {link, bitmap}, {link, bitmap}, {link, bitmap}, {link, bitmap}, slot, rfu */
/* USB */
{0x00, 0x98, {{0x40, 0xdef8}, {0x41, 0xdef8}, {0x42, 0xdef8}, {0x43, 0xdef8}}, 0, 0 },
/* eth0 */
{0x00, 0x78, {{0x41, 0xdef8}, {0, 0}, {0, 0}, {0, 0}}, 0x01, 0x00},
/* eth1 */
{0x00, 0x80, {{0x41, 0xdef8}, {0, 0}, {0, 0}, {0, 0}}, 0x02, 0x00},
}
};
#ifdef CALC
#include <stdio.h>
int main()
{
int i;
unsigned char *p = (unsigned char *)&intel_irq_routing_table;
unsigned char sum = -CHECKSUM;
for (i = 0; i < sizeof(intel_irq_routing_table); ++i) {
sum += *p++;
}
printf("#define CHECKSUM 0x%x\n", (-sum) & 0xff);
return 0;
}
#endif
/*
gcc -D CALC -I ../../../arch/i386/include -I ../../../include irq_tables.c
*/

View file

@ -0,0 +1,81 @@
/* freebios/src/mainboard/nano/nano/mainboard.c
Copyright (c) 2002 Christer Weinigel <wingel@hack.org>
Nano Computer support.
*/
#include <printk.h>
#include <pci.h>
#include <pci_ids.h>
#include <cpu/p5/io.h>
#include <types.h>
void
mainboard_fixup()
{
}
void
final_mainboard_fixup()
{
struct pci_dev *dev;
int i;
void final_southbridge_fixup(void);
final_southbridge_fixup();
printk_info("Final mainboard fixup\n");
dev = pci_find_slot(0, PCI_DEVFN(0x0f, 0));
if (dev) {
printk_debug("nano: Setting eth0 IRQ to %d\n", SCx200_INTA);
pci_write_config_byte(dev, PCI_INTERRUPT_LINE, SCx200_INTA);
}
dev = pci_find_slot(0, PCI_DEVFN(0x10, 0));
if (dev) {
printk_debug("nano: Setting eth1 IRQ to %d\n", SCx200_INTA);
pci_write_config_byte(dev, PCI_INTERRUPT_LINE, SCx200_INTA);
}
for (i = 0; i < 7; i++) {
u8 pin;
int irq;
dev = pci_find_slot(0, PCI_DEVFN(0x11, i));
if (!dev)
break;
pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
if (!pin) {
continue;
}
switch (pin) {
case 1:
case 3:
irq = SCx200_INTC;
break;
case 2:
case 4:
irq = SCx200_INTB;
break;
default:
irq = 0;
}
if (irq) {
printk_info("nano: Setting PCI slot function %d IRQ to %d\n", i, irq);
pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
dev->irq = irq;
}
}
}
/*
Local variables:
compile-command: "make -C /export/nano/bios/nano"
c-basic-offset: 8
End:
*/

View file

@ -0,0 +1,8 @@
# freebios/src/northsouthbridge/NSC/scx200/Config
# Copyright (c) 2002 Christer Weinigel <wingel@hack.org>
raminit northsouthbridge/NSC/scx200/raminit.inc
object southbridge.o
object northbridge.o

View file

@ -0,0 +1,240 @@
/* freebios/src/northsouthbridge/NSC/scx200/chipset_setup.inc
Copyright (c) 2002 Christer Weinigel <wingel@hack.org>
Do chipset setup for a National Semiconductor SCx200 CPU.
*/
scx200_setup_start:
/* Configure F0 */
movl $f0_setup_table, %esi
movl $f0_setup_len, %ecx
movl $0x80009000, %ebx /* F0 Config Space */
f0_setup_loop:
movb (%esi), %bl
CALLSP(scx200_pci_read_config_byte)
incl %esi
andb (%esi), %al
incl %esi
orb (%esi), %al
CALLSP(scx200_pci_write_config_byte)
incl %esi
loopl f0_setup_loop
/* Configure F5 */
movl $f5_setup_table, %esi
movl $f5_setup_len, %ecx
movl $0x80009500, %ebx /* F5 Config Space */
f5_setup_loop:
movb (%esi), %bl
CALLSP(scx200_pci_read_config_byte)
incl %esi
andb (%esi), %al
incl %esi
orb (%esi), %al
CALLSP(scx200_pci_write_config_byte)
incl %esi
loopl f5_setup_loop
/* Configure the SIO address */
movw $0x6200, %dx /* I/O Control Register */
inl %dx, %eax
movl $0x0f040000, %eax /* SIO at 0x15c, Enable USB */
outl %eax, %dx
movw $0x15c, %dx /* Super I/O */
movb $0x20, %al /* Index 0x20, SIO Config */
outb %al, %dx
xorw $1, %dx
inb %dx, %al
cmpb $0xf5, %al /* SIO ID */
jnz scx200_setup_start
config_block_setup:
movw $0x2ea, %dx /* initial register to set address */
movw $SCx200_CB_BASE, %ax /* Config Block Base Address */
outw %ax, %dx
movw $SCx200_CB_BASE, %bx /* Config Block Base Address */
movw %bx, %dx
addw $0x30, %dx /* PMR */
movl $SCx200_PMR, %eax
outl %eax, %dx
movw %bx, %dx
addw $0x34, %dx /* MCR */
movl $SCx200_MCR, %eax
outl %eax, %dx
movw %bx, %dx
addw $0x12, %dx /* PPCR */
inb %dx, %al
andb $0xd1, %al /* Enable PLLs */
outb %al, %dx
#ifdef WATCHDOG_INIT
watchdog_setup:
movw $SCx200_CB_BASE, %bx /* Config Block Base Address */
movw %bx, %dx
addw $0x2, %dx /* WDCNFG */
movw $0xfa, %ax /* enable watchdog */
outw %ax, %dx
movw %bx, %dx /* WDTO */
movw $32*(WATCHDOG_INIT), %ax
outw %ax, %dx
#endif
/* RTC setup */
/* FIXME ought to do RTC setup here */
/* GPIO setup */
/* FIXME ought to do GPIO setup here */
/* Configure the SIO itself */
lea sio_setup_table, %esi
movl $sio_setup_size, %ecx
mov $0x15c, %dx
sio_setup_loop:
movb (%esi), %al
incl %esi
outb %al, %dx
xorb $1, %dl
loop sio_setup_loop
jmp scx200_setup_end
scx200_pci_read_config_byte:
movw $0xcf8, %dx
movl %ebx, %eax
outl %eax, %dx
movw %ax, %dx
andw $3, %dx
orw $0xcfc, %dx
inb %dx, %al
RETSP
scx200_pci_write_config_byte:
movw $0xcf8, %dx
xchgl %ebx, %eax
outl %eax, %dx
movw %ax, %dx
andw $3, %dx
orw $0xcfc, %dx
xchgl %ebx, %eax
outb %al, %dx
RETSP
f0_setup_table:
.byte 0x10, 0x00, 0x01 /* F0BAR0/GPIO = 0x00006401 */
.byte 0x11, 0x00, 0x64
.byte 0x12, 0x00, 0x00
.byte 0x13, 0x00, 0x00
.byte 0x47, 0xfb, 0x06 /* Enable F0BAR0/GPIO, F0BAR1/LPC */
.byte 0x5a, 0x00, 0x01 /* Enable RTC Positive Decode */
.byte 0x5b, 0x00, 0x01 /* Enable LPC Positive Decode */
#ifdef SCx200_DOCCS_BASE
.byte 0x78, 0x00, (SCx200_DOCCS_BASE>>0)&0xff
.byte 0x79, 0x00, (SCx200_DOCCS_BASE>>8)&0xff
.byte 0x7a, 0x00, (SCx200_DOCCS_BASE>>16)&0xff
.byte 0x7b, 0x00, (SCx200_DOCCS_BASE>>24)&0xff
.byte 0x7c, 0x00, (SCx200_DOCCS_CTRL>>0)&0xff
.byte 0x7d, 0x00, (SCx200_DOCCS_CTRL>>8)&0xff
.byte 0x7e, 0x00, (SCx200_DOCCS_CTRL>>16)&0xff
.byte 0x7f, 0x00, (SCx200_DOCCS_CTRL>>24)&0xff
#endif
f0_setup_len = (.-f0_setup_table) / 3
f5_setup_table:
.byte 0x40, 0x00, 0xc1 /* F5BAR0 Mask = 0xffffffc1 */
.byte 0x41, 0x00, 0xff
.byte 0x42, 0x00, 0xff
.byte 0x43, 0x00, 0xff
.byte 0x10, 0x00, 0x01 /* F5BAR0/X-Bus = 0x00006201 */
.byte 0x11, 0x00, 0x62
.byte 0x12, 0x00, 0x00
.byte 0x13, 0x00, 0x00
.byte 0x04, 0x00, 0x01 /* Enable F5 I/O Space */
f5_setup_len = (.-f5_setup_table) / 3
sio_setup_table:
.byte 0x07, 0x00 /* Device 0 -- RTC */
.byte 0x30, 0x00 /* Disable */
.byte 0x70, 0x08 /* Use IRQ 8 */
.byte 0x30, 0x01 /* Enable */
.byte 0x07, 0x01 /* Device 1 -- System Wake-Up Ctrl */
.byte 0x60, 0x08 /* I/O Base Address 0x860 */
.byte 0x61, 0x60
.byte 0x30, 0x01 /* Enable */
#ifdef SCx200_SP3_BASE
.byte 0x07, 0x02 /* Device 2 -- Serial port 3 */
.byte 0x30, 0x00 /* Disable */
.byte 0x60, SCx200_SP3_BASE>>8 /* I/O Base Address */
.byte 0x61, SCx200_SP3_BASE&0xff
.byte 0x70, SCx200_SP3_IRQ /* IRQ */
.byte 0xf0, 0x82 /* Serial Configuration Register */
.byte 0x30, 0x01 /* Enable */
#endif
#ifdef SCx200_SP1_BASE
.byte 0x07, 0x03 /* Device 3 -- Serial port 1 */
.byte 0x30, 0x00 /* Disable */
.byte 0x60, SCx200_SP1_BASE>>8 /* I/O Base Address */
.byte 0x61, SCx200_SP1_BASE&0xff
.byte 0x70, SCx200_SP1_IRQ /* IRQ */
.byte 0xf0, 0x82 /* Serial Configuration Register */
.byte 0x30, 0x01 /* Enable */
#endif
#ifdef SCx200_ACB1_BASE
.byte 0x07, 0x05 /* Device 5 -- ACCESS.bus 1 */
.byte 0x30, 0x00 /* Disable */
.byte 0x60, SCx200_ACB1_BASE>>8 /* I/O Base Address */
.byte 0x61, SCx200_ACB1_BASE&0xff
.byte 0x70, SCx200_ACB1_IRQ /* IRQ */
.byte 0x30, 0x01 /* Enable */
#endif
#ifdef SCx200_ACB2_BASE
.byte 0x07, 0x05 /* Device 6 -- ACCESS.bus 2 */
.byte 0x30, 0x00 /* Disable */
.byte 0x60, SCx200_ACB2_BASE>>8 /* I/O Base Address */
.byte 0x61, SCx200_ACB2_BASE&0xff
.byte 0x70, SCx200_ACB2_IRQ /* IRQ */
.byte 0x30, 0x01 /* Enable */
#endif
#ifdef SCx200_PP_BASE
.byte 0x07, 0x08 /* Device 7 -- Parallel Port */
.byte 0x30, 0x00 /* Disable */
.byte 0x60, SCx200_PP_BASE>>8 /* I/O Base Address */
.byte 0x61, SCx200_PP_BASE&0xff
.byte 0x70, SCx200_PP_IRQ /* IRQ */
.byte 0xf0, 0x82 /* Serial Configuration Register */
.byte 0x30, 0x01 /* Enable */
#endif
#ifdef SCx200_SP2_BASE
.byte 0x07, 0x08 /* Device 8 -- Serial port 2 */
.byte 0x30, 0x00 /* Disable */
.byte 0x60, SCx200_SP2_BASE>>8 /* I/O Base Address */
.byte 0x61, SCx200_SP2_BASE&0xff
.byte 0x70, SCx200_SP2_IRQ /* IRQ */
.byte 0xf0, 0x82 /* Serial Configuration Register */
.byte 0x30, 0x01 /* Enable */
#endif
sio_setup_size = .-sio_setup_table
scx200_setup_end:
/*
Local variables:
compile-command: "make -C /export/nano/bios/nano"
End:
*/

View file

@ -0,0 +1,48 @@
/* freebios/src/northsouthbridge/NSC/scx200/northbridge.c
Copyright (c) 2002 Christer Weinigel <wingel@hack.org>
Do chipset setup for a National Semiconductor SCx200 CPU.
*/
#include <printk.h>
#include <pci.h>
#include <pci_ids.h>
static unsigned calc_dimm(int index, unsigned cfg)
{
if (((cfg >> 4) & 7) == 7) {
printk_info("DIMM%d: empty\n", index);
return 0;
} else {
unsigned page_size = 1 << ((cfg >> 4) & 7);
unsigned dimm_size = 4 << ((cfg >> 8) & 7);
unsigned comp_bank = 2 << ((cfg >> 12) & 1);
unsigned module_bank = 1 << ((cfg >> 14) & 1);
printk_info("DIMM%d: %uMB (%ukB page size, %d component banks, %u module banks)\n",
index, dimm_size, page_size, comp_bank, module_bank);
return dimm_size * 1024;
}
}
unsigned long sizeram()
{
u32 mem_bank_cfg;
unsigned mem_size;
mem_bank_cfg = *(volatile unsigned long *)(GX_BASE+0x8408);
mem_size = 0;
mem_size += calc_dimm(0, mem_bank_cfg);
mem_size += calc_dimm(1, mem_bank_cfg >> 16);
return mem_size;
}
/*
Local variables:
compile-command: "make -C /export/nano/bios/nano"
c-basic-offset: 8
End:
*/

View file

@ -0,0 +1,518 @@
/* freebios/src/northsouthbridge/NSC/scx200/raminit.inc
Copyright (c) 2002 Christer Weinigel <wingel@hack.org>
Do memory sizing for a National Semiconductor SCx200 CPU.
FIXME -- this isn't completely stable, it fails to detect
any DIMMS every now and then. I ought to check the memory
timing I suppose. enable_dimms is a prime suspect.
*/
/**********************************************************************/
#define MC_MEM_CNTRL1 0x8400
#define SDCLK_START (1<<17)
#define TEST_REF (1<<4)
#define PROGRAM_SDRAM (1<<1)
#define MC_MEM_CNTRL2 0x8404
#define SDCLK_MASK 0x000003c0
#define SDCLKOUT_MASK 0x00000400
#define MC_BANK_CFG 0x8408
#define DIMM_PG_SZ 0x00000070
#define DIMM_SZ 0x00000700
#define DIMM_COMP_BNK 0x00001000
#define DIMM_MOD_BNK 0x00004000
#define MC_SYNC_TIM1 0x840c
/**********************************************************************/
#define TEST_DATA1 0x05A5A5A5A
#define TEST_DATA2 0x0DEADBEEF
#define NUM_REFRESH 8
/* Destroys EAX, high word of ECX and low word of EDI */
#define DO_REFRESH \
movw $MC_MEM_CNTRL1, %di ;\
movl %es:(%edi), %eax ;\
orb $TEST_REF, %al ;\
shll $16, %ecx /* save CX */ ;\
movw $NUM_REFRESH, %cx ;\
1: movl %eax, %es:(%edi) ;\
loopw 1b ;\
shrl $16, %ecx /* restore CX */ ;\
andb $~TEST_REF, %al ;\
movl %eax, %es:(%edi)
/* Destroys high word of ECX */
#define DO_DELAY(count) \
shll $16, %ecx /* save CX */ ;\
movw count, %cx ;\
1: outb %al, $0xed ;\
loopw 1b ;\
shrl $16, %ecx /* restore CX */
/**********************************************************************/
scx200_setup_ram:
CONSOLE_DEBUG_TX_STRING($str_setup_default_memory)
/* Initialize the GX1 configuration registers */
movl $cpu_init_len, %ecx
leal cpu_init_table, %esi
cpu_init_loop:
movw (%esi), %ax
addl $2, %esi
outb %al, $0x22
movb %ah, %al
outb %al, $0x23
loop cpu_init_loop
/* Set up Memory controller, note that all the code below
assumes that the high word of %edi contains GX_BASE */
movl $GX_BASE, %edi
movl $mem_init_len, %ecx
leal mem_init_table, %esi
mem_init_loop:
movw (%esi), %di
addl $2, %esi
movl (%esi), %eax
addl $4, %esi
movl %eax, (%edi)
loop mem_init_loop
CALLSP(enable_dimm) /* Program the DIMM's */
CONSOLE_DEBUG_TX_STRING($str_sizing_memory)
/* EBP will contain the DIMM configuration after we're done.
To begin with, it is set up for no DIMMs at all */
movl $0x00700070, %ebp
/* Parameters for DIMM0 */
movl $0x00705740, %edx /* DIMM0 is maxed, no DIMM0 */
movb $0, %cl /* Shift value DIMM0=0, DIMM1=16 */
dimm_loop:
movl %edx, %esi
CONSOLE_INFO_TX_STRING($str_probing)
movb %cl, %al
rorb $4, %al
addb $'0', %al
CONSOLE_INFO_TX_CHAR(%al)
CONSOLE_INFO_TX_STRING($str_nl)
movl %esi, %edx
/* First configure the memory with the new settings */
movw $MC_BANK_CFG, %di
movl %edx, (%edi)
DO_REFRESH
/* Write something to location 0 and read it back */
movl $TEST_DATA1, 0 /* Write data to location 0 */
movl $0, 0x100 /* Clear the bus */
movl 0, %eax /* Read data from location 0 */
movl $0, 0 /* Clear location 0 */
/* If we got the same value back, there is memory in the bank */
cmpl $TEST_DATA1, %eax
jne next_dimm
movl $TEST_DATA2, 0 /* Write data to location 0 */
movl $0, 0x100 /* Clear the bus */
movl 0, %eax /* Read data from location 0 */
movl $0, 0 /* Clear location 0 */
cmpl $TEST_DATA2, %eax
jne next_dimm
#ifdef DEBUG
movl %edx, %esi
CONSOLE_DEBUG_TX_STRING($str_found)
movb %cl, %al
rorb $4, %al
addb $'0', %al
CONSOLE_DEBUG_TX_CHAR(%al)
CONSOLE_DEBUG_TX_STRING($str_nl)
movl %esi, %edx
#endif
/* Do page size detection, read the NatSemi reference drivers for an
explanation of how it works */
movl $0x0040, %ebx /* MC_BANK_CFG for 16kB page size */
movl $0x2000, %esi /* Offset: 16kB/2 */
page_size_loop:
movl $TEST_DATA1, 0 /* Write data to location 0 */
movl $TEST_DATA2, (%esi) /* Write to page size/2 */
movl $0, 0x100 /* Clear the bus */
movl 0, %eax /* Read data from location 0 */
movl $0, 0 /* Clear location 0 */
cmpl $TEST_DATA1, %eax /* If no aliasing, we have found */
je page_size_found /* out the page size */
/* We had aliasing, so go to the next smaller setting */
movw $MC_BANK_CFG, %di
movl (%edi), %edx /* Get current MC_BANK_CFG settings */
movl $~DIMM_PG_SZ, %eax /* Mask for the page size */
roll %cl, %eax /* Shift for the right DIMM */
andl %eax, %edx /* Do the masking */
subl $0x10,%ebx /* Select the next smaller page size */
jc mem_sizing_failed /* Nothing matched, we've failed */
shll %cl, %ebx /* Shift for the right DIMM */
orl %ebx, %edx /* And merge it into the settings */
shrl %cl, %ebx /* And shift it back again */
shrl $1, %esi /* Divide test address by 2 */
movl %edx, (%edi) /* Use the new MC_BANK_CFG settings */
DO_REFRESH
jmp page_size_loop
page_size_found:
/* Save the page size we found in EBP */
movl $~DIMM_PG_SZ, %eax
roll %cl, %eax
andl %eax, %ebp
movl %ebx, %eax
shll %cl, %eax
or %eax, %ebp
#ifdef DEBUG
shll $1, %esi
movw %si, %di
movl %edx, %esi
CONSOLE_DEBUG_TX_STRING($str_page_size)
xorl %eax, %eax
movw %di, %ax
CONSOLE_DEBUG_TX_HEX32(%eax)
CONSOLE_DEBUG_TX_STRING($str_nl)
movl %esi, %edx
#endif
/* Do component banks detection */
movl $0x0800, %esi /* Smallest page = 1KB * 2 banks */
shll $16, %ecx /* Save DIMM shift */
movl %ebp, %eax /* Get the DIMM values */
shrl %cl, %eax /* shifted back */
movw %ax, %cx /* Use the MC_BANK_CFG */
shrw $4, %cx /* page size setting as */
andb $7, %cl /* a shift to calculate */
shll %cl, %esi /* the page size */
shrl $16, %ecx /* Restore DIMM shift */
movl $TEST_DATA1, 0 /* Write data to location 0 */
movl $TEST_DATA2, (%esi) /* Write to next page */
movl $0, 0x100 /* Clear the bus */
movl 0, %eax /* Read data from location 0 */
cmpl $TEST_DATA1, %eax /* If no aliasing, */
je component_banks_4 /* there are 4 banks */
/* Reconfigure the memory controller for 2 banks */
movw $MC_BANK_CFG, %di
movl (%edi), %edx
movl $~DIMM_COMP_BNK, %eax /* Mask for component banks */
roll %cl, %eax /* shifted */
andl %eax, %ebp /* clear the bit of EBP */
andl %eax, %edx /* clear the bit of EDX */
movl %edx, (%edi) /* Use new settings */
DO_REFRESH
#ifdef DEBUG
movw $'2',%di
#endif
jmp component_banks_done
component_banks_4:
movl $DIMM_COMP_BNK, %eax /* Set the bit of EBP */
roll %cl, %eax /* shifted */
orl %eax, %ebp
#ifdef DEBUG
movw $'4',%di
#endif
component_banks_done:
#ifdef DEBUG
movl %edx, %esi
CONSOLE_DEBUG_TX_STRING($str_component_banks)
movw %di, %ax
CONSOLE_DEBUG_TX_CHAR(%al)
CONSOLE_DEBUG_TX_STRING($str_nl)
movl %esi, %edx
#endif
/* Do module banks detection */
movl $0x0800, %esi /* Smallest page = 1KB * 2 banks */
shll $16, %ecx /* Save DIMM shift */
movl %ebp, %eax /* Get the DIMM values */
shrl %cl, %eax /* shifted back */
movw %ax, %cx /* Use the MC_BANK_CFG */
shrw $4, %cx /* page size setting as */
andb $7, %cl /* a shift to calculate */
shll %cl, %esi /* the page size */
movw %ax, %cx /* Use the MC_BANK_CFG */
shrw $12, %cx /* component bank setting */
andb $1, %cl /* a shift to calculate */
shll %cl, %esi /* the total bank size */
shrl $16, %ecx /* Restore DIMM shift */
movl $TEST_DATA1, 0 /* Write data to location 0 */
movl $TEST_DATA2, (%esi) /* Write to module bank 2 */
movl $0, 0x100 /* Clear the bus */
movl (%esi), %eax /* Read from module bank 2 */
cmpl $TEST_DATA2, %eax /* If good data, */
je module_banks_2 /* there are 2 module banks */
/* Reconfigure the memory controller for 1 module bank */
movw $MC_BANK_CFG, %di
movl (%edi), %edx
movl $~DIMM_MOD_BNK, %eax /* Mask for module banks */
roll %cl, %eax /* shifted */
andl %eax, %ebp /* clear the bit of EBP */
andl %eax, %edx /* clear the bit of EDX */
movl %edx, (%edi) /* Use new settings */
DO_REFRESH
#ifdef DEBUG
movw $'1',%di
#endif
jmp module_banks_done
module_banks_2:
movl $DIMM_MOD_BNK, %eax /* Set the bit of EBP */
roll %cl, %eax /* shifted */
orl %eax, %ebp
#ifdef DEBUG
movw $'2',%di
#endif
module_banks_done:
#ifdef DEBUG
movl %edx, %esi
CONSOLE_DEBUG_TX_STRING($str_module_banks)
movw %di, %ax
CONSOLE_DEBUG_TX_CHAR(%al)
CONSOLE_DEBUG_TX_STRING($str_nl)
movl %esi, %edx
#endif
/* Finally, figure out the size of the DIMM */
movl $0x0700, %ebx /* MC_BANK_CFG for 512MB */
movl $0x10000000, %esi /* Offset: 256MB */
dimm_size_loop:
movl $TEST_DATA1, 0 /* Write data to location 0 */
movl $TEST_DATA2, (%esi) /* Write to memory size/2 */
movl $0, 0x100 /* Clear the bus */
movl 0, %eax /* Read data from location 0 */
movl $0, 0 /* Clear location 0 */
cmpl $TEST_DATA1, %eax /* If no aliasing, we have found */
je dimm_size_found /* out the memory size */
/* We had aliasing, so go to the next smaller setting */
movw $MC_BANK_CFG, %di
movl (%edi), %edx /* Get current MC_BANK_CFG settings */
movl $~DIMM_SZ, %eax /* Mask for the DIMM size */
roll %cl, %eax /* Shift for the right DIMM */
and %eax, %edx /* Do the masking */
decb %bh /* Halve the memory size */
jc mem_sizing_failed /* Nothing matched, we've failed */
shll %cl, %ebx /* Shift for the right DIMM */
orl %ebx, %edx /* And merge it into the settings */
shrl %cl, %ebx /* And shift it back again */
shrl $1, %esi /* Divide test address by 2 */
movl %edx, (%edi) /* Use the new MC_BANK_CFG settings */
DO_REFRESH
jmp dimm_size_loop
dimm_size_found:
/* Save the page size we found in EBP */
movl $~DIMM_SZ, %eax
roll %cl, %eax
andl %eax, %ebp
movl %ebx, %eax
shll %cl, %eax
or %eax, %ebp
shrl $16-1, %esi
movw %si, %di
movl %edx, %esi
CONSOLE_INFO_TX_STRING($str_dimm_size)
movw %di, %ax
shll $16, %eax
CONSOLE_INFO_TX_HEX32(%eax)
CONSOLE_INFO_TX_STRING($str_nl)
movl %esi, %edx
next_dimm:
movl $0x12345678, 0 /* Write garbage to location 0 */
addb $16, %cl
movl $0x57400070, %edx /* No DIMM0, DIMM1 is maxed */
/* Try the two shift values 0, and 16 */
cmpb $32, %cl
jne dimm_loop
movl %edx, %esi
CONSOLE_DEBUG_TX_STRING($str_done)
CONSOLE_DEBUG_TX_HEX32(%ebp)
CONSOLE_DEBUG_TX_STRING($str_nl)
movl %esi, %edx
/* Finally use the MC_BANK_CFG settings we've calculated */
movw $MC_BANK_CFG, %di
movl %ebp, (%edi)
jmp scx200_setup_ram_end
mem_sizing_failed:
#ifdef DEBUG
movl %edx, %esi
CONSOLE_DEBUG_TX_STRING($str_failed)
movl %esi, %edx
#endif
movl $0xffff0000, %eax
roll %cl, %eax
andl %eax, %ebp
movl $0x00000070, %eax
shll %cl, %eax
orl %eax, %ebp
jmp next_dimm
str_setup_default_memory:
.string "Setting up default parameters for memory\r\n"
str_sizing_memory:
.string "Sizing memory\r\n"
str_sizing_done:
.string "Sizing done\r\n"
str_done:
.string "Memory sizing done, MC_BANK_CFG = 0x"
str_probing:
.string "Probing for DIMM"
str_found:
.string "Found DIMM"
str_failed:
.string " Failed to identify DIMM"
str_page_size:
.string " Page Size: "
str_component_banks:
.string " Component Banks: "
str_module_banks:
.string " Module Banks: "
str_dimm_size:
.string " DIMM size: "
str_nl:
.string "\r\n"
/**********************************************************************/
/* all these functions assume that the upper word of EDI contains
GX_BASE
*/
enable_dimm:
/* Start the SDCLK's */
movw $MC_MEM_CNTRL1, %di
movl (%edi), %eax
andl $~SDCLK_START, %eax
movl %eax, (%edi)
orl $SDCLK_START, %eax
movl %eax, (%edi)
/* Unmask the SDCLK's - may want to unmask only clocks used
for pwr savings */
movw $MC_MEM_CNTRL2, %di
movl (%edi), %eax
andl $~(SDCLK_MASK | SDCLKOUT_MASK), %eax
movl %eax, (%edi)
DO_DELAY($5000) /* Wait for clocks to unmask */
DO_REFRESH
/* Start the SDCLK's */
movw $MC_MEM_CNTRL1, %di
movl (%edi), %eax
andl $~PROGRAM_SDRAM, %eax
movl %eax, (%edi)
orl $PROGRAM_SDRAM | 0x00002000, %eax /* Set refresh timing */
movl %eax, (%edi)
andl $~PROGRAM_SDRAM, %eax
movl %eax, (%edi)
DO_REFRESH
DO_DELAY($2000)
RETSP
/**********************************************************************/
.align 2
cpu_init_table:
.byte 0xc1, 0x00 /* NO SMIs */
.byte 0xc3, 0x14 /* Enable CPU config register */
.byte 0x20, 0x00
.byte 0xb8, GX_BASE>>30 /* Enable GXBASE address */
.byte 0xe8, 0x98 /* Sets IORT to minimum setting */
.byte 0xc3, 0xf8 /* Enable CPU config register */
cpu_init_len = (.-cpu_init_table)/2
/* Memory timing parameters */
CNTRL1 = 0xFE960400 /* Clock divisor 3.5 */
.align 2
mem_init_table:
.word 0x8300 /* DC_UNLOCK */
.long 0x4758
.word 0x8304 /* DC_GENERAL_CFG */
.long 0x00000000
.word MC_MEM_CNTRL2
.long 0x00000060 /* Disable SDCLK0, Shift 2, ~FSTRDMSK */
.word MC_MEM_CNTRL1
.long CNTRL1 & ~(1<<17) /* ~SDCLKSTRT */
.word MC_BANK_CFG
.long 0x57405740 /* Largest possible memory
0x4000 -- 2 module banks
0x1000 -- 4 component banks
0x0700 -- DIMM size 512MB
0x0040 -- Page Size 16kB */
.word MC_SYNC_TIM1
.long 0x3A733225 /* LTMODE 3, RC 10, RAS 7, RP 3,
RCD 3, RRD 2, DPL 2 */
/* Unmask the SDCLKs */
.word MC_MEM_CNTRL2
.long 0x00003F20 & ~0x7c0 /* Enable all SDCLKs, Shift 2, ~FSTRDMSK */
/* Start the SDCLKs */
.word MC_MEM_CNTRL1
.long CNTRL1 | (1<<17) /* SDCLKSTRT */
mem_init_len = (.-mem_init_table)/6
scx200_setup_ram_end:
/*
Local variables:
compile-command: "make -C /export/nano/bios/nano"
End:
*/

View file

@ -0,0 +1,92 @@
/* freebios/src/northsouthbridge/NSC/scx200/northbridge.c
Copyright (c) 2002 Christer Weinigel <wingel@hack.org>
Do chipset setup for a National Semiconductor SCx200 CPU.
*/
#include <printk.h>
#include <pci.h>
#include <pci_ids.h>
#include <cpu/p5/io.h>
#include <types.h>
void nvram_on()
{
}
// simple fixup (which we hope can leave soon) for the sis southbridge part
void
final_southbridge_fixup()
{
struct pci_dev *dev;
u8 b;
u16 int_map;
int inta, intb, intc, intd;
u16 trig;
printk_info("Final southbridge fixup\n");
dev = pci_find_device(PCI_VENDOR_ID_NS,
PCI_DEVICE_ID_NS_SCx200_BRIDGE,
(void *)NULL);
if (!dev) {
printk_warning("scx200: Can't find PCI bridge\n");
return;
}
pci_read_config_word(dev, 0x5c, &int_map);
printk_debug("F0/5c: 0x%04x\n", int_map);
inta = SCx200_INTA;
intb = SCx200_INTB;
intc = SCx200_INTC;
intd = SCx200_INTD;
printk_info("scx200: PCI INTA=%d, INTB=%d, INTC=%d, INTD=%d\n",
inta, intb, intc, intd);
int_map = inta | (intb<<4) | (intc<<8) | (intd<<12);
pci_write_config_word(dev, 0x5c, int_map);
pci_read_config_word(dev, 0x5c, &int_map);
printk_debug("F0/5c: 0x%04x\n", int_map);
/* All PCI interrupts are level trigged, the rest are edge trigged */
printk_debug("4d0: 0x%02x\n", inb(0x4d0));
printk_debug("4d1: 0x%02x\n", inb(0x4d1));
trig = 0;
if (inta) trig |= (1<<inta);
if (intb) trig |= (1<<intb);
if (intc) trig |= (1<<intc);
if (intd) trig |= (1<<intd);
outb(trig, 0x4d0);
outb(trig >> 8, 0x4d1);
printk_debug("4d0: 0x%02x\n", inb(0x4d0));
printk_debug("4d1: 0x%02x\n", inb(0x4d1));
pci_read_config_byte(dev, 0x5b, &b);
printk_debug("F0/5b = 0x%02x\n", b);
#ifdef SCx200_PRIMARY_IDE
printk_info("scx200: Enabling Primary IDE Controller\n");
b |= 1<<3;
#endif
#ifdef SCx200_SECONDARY_IDE
printk_info("scx200: Enabling Secondary IDE Controller\n");
b |= 1<<4;
#endif
printk_debug("F0/5b = 0x%02x\n", b);
pci_write_config_byte(dev, 0x5b, b);
dev = pci_find_slot(0, PCI_DEVFN(0x13, 0));
if (dev) {
printk_debug("scx200: USB is on INTD, IRQ %d\n", intd);
pci_write_config_byte(dev, PCI_INTERRUPT_PIN, 4);
pci_write_config_byte(dev, PCI_INTERRUPT_LINE, intd);
}
}
/*
Local variables:
compile-command: "make -C /export/nano/bios/nano"
c-basic-offset: 8
End:
*/