diff --git a/src/include/pci_ids.h b/src/include/pci_ids.h index b1bdeb7a3f..17ecd080d7 100644 --- a/src/include/pci_ids.h +++ b/src/include/pci_ids.h @@ -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 diff --git a/src/kernel_patches/linux-2.4.17-ide-power b/src/kernel_patches/linux-2.4.17-ide-power new file mode 100644 index 0000000000..e94589e030 --- /dev/null +++ b/src/kernel_patches/linux-2.4.17-ide-power @@ -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 + ++#define CONFIG_LINUXBIOS_PM ++#ifdef CONFIG_LINUXBIOS_PM ++#include ++#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 diff --git a/src/mainboard/nano/nano/Config b/src/mainboard/nano/nano/Config new file mode 100644 index 0000000000..7d656f62e9 --- /dev/null +++ b/src/mainboard/nano/nano/Config @@ -0,0 +1,126 @@ +# Copyright (c) 2002 Christer Weinigel + +# This is a config file Nano Computer from Nano Computer Systems +# (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: diff --git a/src/mainboard/nano/nano/config.example b/src/mainboard/nano/nano/config.example new file mode 100644 index 0000000000..58187f53f6 --- /dev/null +++ b/src/mainboard/nano/nano/config.example @@ -0,0 +1,51 @@ +# Copyright (c) 2002 Christer Weinigel + +# This is an example configuration file for the Nano Computer from +# Nano Computer Systems (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 + + diff --git a/src/mainboard/nano/nano/irq_tables.c b/src/mainboard/nano/nano/irq_tables.c new file mode 100644 index 0000000000..44eeec7fe2 --- /dev/null +++ b/src/mainboard/nano/nano/irq_tables.c @@ -0,0 +1,53 @@ +#include +#include + +/* + * 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 +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 +*/ diff --git a/src/mainboard/nano/nano/mainboard.c b/src/mainboard/nano/nano/mainboard.c new file mode 100644 index 0000000000..2f0524ceba --- /dev/null +++ b/src/mainboard/nano/nano/mainboard.c @@ -0,0 +1,81 @@ +/* freebios/src/mainboard/nano/nano/mainboard.c + + Copyright (c) 2002 Christer Weinigel + + Nano Computer support. +*/ + +#include +#include +#include +#include + +#include + +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: +*/ diff --git a/src/northsouthbridge/NSC/scx200/Config b/src/northsouthbridge/NSC/scx200/Config new file mode 100644 index 0000000000..ec9722b768 --- /dev/null +++ b/src/northsouthbridge/NSC/scx200/Config @@ -0,0 +1,8 @@ +# freebios/src/northsouthbridge/NSC/scx200/Config +# Copyright (c) 2002 Christer Weinigel + +raminit northsouthbridge/NSC/scx200/raminit.inc + +object southbridge.o +object northbridge.o + diff --git a/src/northsouthbridge/NSC/scx200/chipset_setup.inc b/src/northsouthbridge/NSC/scx200/chipset_setup.inc new file mode 100644 index 0000000000..6721332aa2 --- /dev/null +++ b/src/northsouthbridge/NSC/scx200/chipset_setup.inc @@ -0,0 +1,240 @@ +/* freebios/src/northsouthbridge/NSC/scx200/chipset_setup.inc + + Copyright (c) 2002 Christer Weinigel + + 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: +*/ diff --git a/src/northsouthbridge/NSC/scx200/northbridge.c b/src/northsouthbridge/NSC/scx200/northbridge.c new file mode 100644 index 0000000000..f04ed37c34 --- /dev/null +++ b/src/northsouthbridge/NSC/scx200/northbridge.c @@ -0,0 +1,48 @@ +/* freebios/src/northsouthbridge/NSC/scx200/northbridge.c + + Copyright (c) 2002 Christer Weinigel + + Do chipset setup for a National Semiconductor SCx200 CPU. +*/ + +#include +#include +#include + +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: +*/ diff --git a/src/northsouthbridge/NSC/scx200/raminit.inc b/src/northsouthbridge/NSC/scx200/raminit.inc new file mode 100644 index 0000000000..2016db931c --- /dev/null +++ b/src/northsouthbridge/NSC/scx200/raminit.inc @@ -0,0 +1,518 @@ +/* freebios/src/northsouthbridge/NSC/scx200/raminit.inc + + Copyright (c) 2002 Christer Weinigel + + 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: +*/ diff --git a/src/northsouthbridge/NSC/scx200/southbridge.c b/src/northsouthbridge/NSC/scx200/southbridge.c new file mode 100644 index 0000000000..f37477b263 --- /dev/null +++ b/src/northsouthbridge/NSC/scx200/southbridge.c @@ -0,0 +1,92 @@ +/* freebios/src/northsouthbridge/NSC/scx200/northbridge.c + + Copyright (c) 2002 Christer Weinigel + + Do chipset setup for a National Semiconductor SCx200 CPU. +*/ + +#include +#include +#include +#include + +#include + +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<> 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: +*/