diff options
author | Corey Osgood <corey.osgood@gmail.com> | 2007-06-14 06:10:57 +0000 |
---|---|---|
committer | Stefan Reinauer <stepan@openbios.org> | 2007-06-14 06:10:57 +0000 |
commit | e99bd105af97ad905114bd76ae09326a10def8cf (patch) | |
tree | 22ef962a20d86a4362bc6a2620b72e2a8a344457 /src | |
parent | bd88057f73b83e5bfd9d0fe57b28c87c98d73b12 (diff) |
This patch adds support for the Intel i82810 northbridge and various i82801xx
southbridges, along with the Asus MEW-VM. With this, my machine attempts to
boot linux, but does so very slowly and fails during the boot process, probably
because of the irq tables.
Signed-off-by: Corey Osgood <corey.osgood@gmail.com>
Acked-by: Joseph Smith <joe@smittys.pointclark.net>
Acked-by: Stefan Reinauer <stepan@coresystems.de>
git-svn-id: svn://svn.coreboot.org/coreboot/trunk@2719 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
Diffstat (limited to 'src')
28 files changed, 2307 insertions, 0 deletions
diff --git a/src/cpu/intel/model_6xx/model_6xx_init.c b/src/cpu/intel/model_6xx/model_6xx_init.c index cf0383f46a..ad56f8f639 100644 --- a/src/cpu/intel/model_6xx/model_6xx_init.c +++ b/src/cpu/intel/model_6xx/model_6xx_init.c @@ -44,6 +44,7 @@ static struct device_operations cpu_dev_ops = { .init = model_6xx_init, }; static struct cpu_device_id cpu_table[] = { + { X86_VENDOR_INTEL, 0x0665 }, /* Celeron (Mendocino) */ { X86_VENDOR_INTEL, 0x0672 }, { X86_VENDOR_INTEL, 0x0673 }, { X86_VENDOR_INTEL, 0x0681 }, diff --git a/src/mainboard/asus/mew-vm/Config.lb b/src/mainboard/asus/mew-vm/Config.lb new file mode 100644 index 0000000000..ade4ffd1ec --- /dev/null +++ b/src/mainboard/asus/mew-vm/Config.lb @@ -0,0 +1,182 @@ +## +## Compute the location and size of where this firmware image +## (linuxBIOS plus bootloader) will live in the boot rom chip. +## +if USE_FALLBACK_IMAGE + default ROM_SECTION_SIZE = FALLBACK_SIZE + default ROM_SECTION_OFFSET = ( ROM_SIZE - FALLBACK_SIZE ) +else + default ROM_SECTION_SIZE = ( ROM_SIZE - FALLBACK_SIZE ) + default ROM_SECTION_OFFSET = 0 +end + +## +## Compute the start location and size size of +## The linuxBIOS bootloader. +## +default CONFIG_ROM_PAYLOAD_START = (0xffffffff - ROM_SIZE + ROM_SECTION_OFFSET + 1) +default PAYLOAD_SIZE = ( ROM_SECTION_SIZE - ROM_IMAGE_SIZE ) + +## +## Compute where this copy of linuxBIOS will start in the boot rom +## +default _ROMBASE = ( CONFIG_ROM_PAYLOAD_START + PAYLOAD_SIZE ) + +## +## Compute a range of ROM that can cached to speed up linuxBIOS, +## execution speed. +## +## XIP_ROM_SIZE must be a power of 2. +## XIP_ROM_BASE must be a multiple of XIP_ROM_SIZE +## +default XIP_ROM_SIZE=65536 +default XIP_ROM_BASE = ( _ROMBASE + ROM_IMAGE_SIZE - XIP_ROM_SIZE ) + +## +## Set all of the defaults for an x86 architecture +## + +arch i386 end + +## +## Build the objects we have code for in this directory. +## + +driver mainboard.o + +if HAVE_PIRQ_TABLE object irq_tables.o end +#object reset.o + +## +## Romcc output +## +makerule ./failover.E + depends "$(MAINBOARD)/failover.c ./romcc" + action "./romcc -E -O --label-prefix=failover -I$(TOP)/src -I. $(CPPFLAGS) $(MAINBOARD)/failover.c -o $@" +end + +makerule ./failover.inc + depends "$(MAINBOARD)/failover.c ./romcc" + action "./romcc -O --label-prefix=failover -I$(TOP)/src -I. $(CPPFLAGS) $(MAINBOARD)/failover.c -o $@" +end + +makerule ./auto.E + depends "$(MAINBOARD)/auto.c option_table.h ./romcc" + action "./romcc -E -mcpu=p2 -O -I$(TOP)/src -I. $(CPPFLAGS) $(MAINBOARD)/auto.c -o $@" +end +makerule ./auto.inc + depends "$(MAINBOARD)/auto.c option_table.h ./romcc" + action "./romcc -mcpu=p2 -O -I$(TOP)/src -I. $(CPPFLAGS) $(MAINBOARD)/auto.c -o $@" +end + +## +## Build our 16 bit and 32 bit linuxBIOS entry code +## +mainboardinit cpu/x86/16bit/entry16.inc +mainboardinit cpu/x86/32bit/entry32.inc +ldscript /cpu/x86/16bit/entry16.lds +ldscript /cpu/x86/32bit/entry32.lds + +## +## Build our reset vector (This is where linuxBIOS is entered) +## +if USE_FALLBACK_IMAGE + mainboardinit cpu/x86/16bit/reset16.inc + ldscript /cpu/x86/16bit/reset16.lds +else + mainboardinit cpu/x86/32bit/reset32.inc + ldscript /cpu/x86/32bit/reset32.lds +end + +### Should this be in the northbridge code? +mainboardinit arch/i386/lib/cpu_reset.inc + +## +## Include an id string (For safe flashing) +## +mainboardinit arch/i386/lib/id.inc +ldscript /arch/i386/lib/id.lds + +### +### This is the early phase of linuxBIOS startup +### Things are delicate and we test to see if we should +### failover to another image. +### +if USE_FALLBACK_IMAGE + ldscript /arch/i386/lib/failover.lds + mainboardinit ./failover.inc +end + +### +### O.k. We aren't just an intermediary anymore! +### + +## +## Setup RAM +## +mainboardinit cpu/x86/fpu/enable_fpu.inc +mainboardinit cpu/x86/mmx/enable_mmx.inc +mainboardinit ./auto.inc +mainboardinit cpu/x86/mmx/disable_mmx.inc + +## +## Include the secondary Configuration files +## +dir /pc80 +config chip.h + +chip northbridge/intel/i82810 + device pci_domain 0 on + device pci 0.0 on end # Host bridge + device pci 1.0 on # Onboard Video + #chip drivers/pci/onboard + # device pci 1.0 on end + # register "rom_address" = "0xfff80000" + #end + end + chip southbridge/intel/i82801xx # Southbridge + device pci 1e.0 on # PCI Bridge + #chip drivers/pci/onboard + # device pci 1.0 on end + # register "rom_address" = "0xfff80000" + #end + end + device pci 1f.0 on # ISA/LPC? Bridge + chip superio/smsc/lpc47b272 + device pnp 2e.0 off # Floppy + io 0x60 = 0x3f0 + irq 0x70 = 6 + drq 0x74 = 2 + end + device pnp 2e.3 off # Parallel Port + io 0x60 = 0x378 + irq 0x70 = 7 + end + device pnp 2e.4 on # Com1 + io 0x60 = 0x3f8 + irq 0x70 = 4 + end + device pnp 2e.5 off # Com2 + io 0x60 = 0x2f8 + irq 0x70 = 3 + end + device pnp 2e.7 on # Keyboard + io 0x60 = 0x60 + io 0x62 = 0x64 + irq 0x70 = 1 # Keyboard interrupt + irq 0x72 = 12 # Mouse interrupt + end + device pnp 2e.a off end # ACPI + end + end + device pci 1f.1 on end # IDE + device pci 1f.2 on end # USB + device pci 1f.3 on end # SMBus + device pci 1f.5 off end # AC'97, no header on MEW-VM + device pci 1f.6 off end # AC'97 Modem (MC'97) + end + end + chip cpu/intel/socket_PGA370 + end +end + diff --git a/src/mainboard/asus/mew-vm/Options.lb b/src/mainboard/asus/mew-vm/Options.lb new file mode 100644 index 0000000000..d0d37b53a6 --- /dev/null +++ b/src/mainboard/asus/mew-vm/Options.lb @@ -0,0 +1,159 @@ +uses HAVE_MP_TABLE +uses HAVE_PIRQ_TABLE +uses USE_FALLBACK_IMAGE +uses HAVE_FALLBACK_BOOT +uses HAVE_HARD_RESET +uses HAVE_OPTION_TABLE +uses USE_OPTION_TABLE +uses CONFIG_ROM_PAYLOAD +uses IRQ_SLOT_COUNT +uses MAINBOARD +uses MAINBOARD_VENDOR +uses MAINBOARD_PART_NUMBER +uses LINUXBIOS_EXTRA_VERSION +uses ARCH +uses FALLBACK_SIZE +uses STACK_SIZE +uses HEAP_SIZE +uses ROM_SIZE +uses ROM_SECTION_SIZE +uses ROM_IMAGE_SIZE +uses ROM_SECTION_SIZE +uses ROM_SECTION_OFFSET +uses CONFIG_ROM_PAYLOAD_START +uses CONFIG_COMPRESSED_PAYLOAD_LZMA +uses PAYLOAD_SIZE +uses _ROMBASE +uses _RAMBASE +uses XIP_ROM_SIZE +uses XIP_ROM_BASE +uses HAVE_MP_TABLE +uses CROSS_COMPILE +uses CC +uses HOSTCC +uses OBJCOPY +uses DEFAULT_CONSOLE_LOGLEVEL +uses MAXIMUM_CONSOLE_LOGLEVEL +uses CONFIG_CONSOLE_SERIAL8250 +uses TTYS0_BAUD +uses TTYS0_BASE +uses TTYS0_LCS +uses CONFIG_UDELAY_TSC +uses CONFIG_IDE + +## ROM_SIZE is the size of boot ROM that this board will use. +default ROM_SIZE = 512*1024 + +### +### Build options +### + +## +## Build code for the fallback boot +## +default HAVE_FALLBACK_BOOT = 1 + +## +## no MP table +## +default HAVE_MP_TABLE = 0 + +## +## Build code to reset the motherboard from linuxBIOS +## +default HAVE_HARD_RESET = 0 + +## +## Build code to export a programmable irq routing table +## +default HAVE_PIRQ_TABLE = 1 +default IRQ_SLOT_COUNT = 4 + +## +## Build code to export a CMOS option table +## +default HAVE_OPTION_TABLE = 0 + +## IDE Support +default CONFIG_IDE = 1 + +### +### LinuxBIOS layout values +### + +## ROM_IMAGE_SIZE is the amount of space to allow linuxBIOS to occupy. +default ROM_IMAGE_SIZE = 65536 +default FALLBACK_SIZE = 131072 + +## +## Use a small 8K stack +## +default STACK_SIZE=0x2000 + +## +## Use a small 16K heap +## +default HEAP_SIZE=0x4000 + +## +## Only use the option table in a normal image +## +#default USE_OPTION_TABLE = !USE_FALLBACK_IMAGE +default USE_OPTION_TABLE = 0 + +default _RAMBASE = 0x00004000 + +default CONFIG_ROM_PAYLOAD = 1 + +## +## The default compiler +## +default CROSS_COMPILE="" +default CC="$(CROSS_COMPILE)gcc -m32" +default HOSTCC="gcc" + +## +## The Serial Console +## + +# To Enable the Serial Console +default CONFIG_CONSOLE_SERIAL8250=1 + +## Select the serial console baud rate +default TTYS0_BAUD=115200 +#default TTYS0_BAUD=57600 +#default TTYS0_BAUD=38400 +#default TTYS0_BAUD=19200 +#default TTYS0_BAUD=9600 +#default TTYS0_BAUD=4800 +#default TTYS0_BAUD=2400 +#default TTYS0_BAUD=1200 + +# Select the serial console base port +default TTYS0_BASE=0x3f8 + +# Select the serial protocol +# This defaults to 8 data bits, 1 stop bit, and no parity +default TTYS0_LCS=0x3 + +## +### Select the linuxBIOS loglevel +## +## EMERG 1 system is unusable +## ALERT 2 action must be taken immediately +## CRIT 3 critical conditions +## ERR 4 error conditions +## WARNING 5 warning conditions +## NOTICE 6 normal but significant condition +## INFO 7 informational +## DEBUG 8 debug-level messages +## SPEW 9 Way too many details + +## Request this level of debugging output +default DEFAULT_CONSOLE_LOGLEVEL=9 +## At a maximum only compile in this level of debugging +default MAXIMUM_CONSOLE_LOGLEVEL=9 + +default CONFIG_UDELAY_TSC=1 +end + diff --git a/src/mainboard/asus/mew-vm/auto.c b/src/mainboard/asus/mew-vm/auto.c new file mode 100644 index 0000000000..3c993f1fbe --- /dev/null +++ b/src/mainboard/asus/mew-vm/auto.c @@ -0,0 +1,106 @@ +/* + * This file is part of the LinuxBIOS project. + * + * Copyright (C) 2007 Corey Osgood <corey@slightlyhackish.com> + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#define ASSEMBLY 1 + +#include <stdint.h> +#include <device/pci_def.h> +#include <arch/io.h> +#include <device/pnp_def.h> +#include <arch/romcc_io.h> +#include <arch/hlt.h> +#include "pc80/serial.c" +#include "arch/i386/lib/console.c" +#include "ram/ramtest.c" +#include "superio/smsc/lpc47b272/lpc47b272_early_serial.c" +#include "northbridge/intel/i82810/raminit.h" +#include "cpu/x86/mtrr/earlymtrr.c" +#include "cpu/x86/bist.h" + +#define SERIAL_DEV PNP_DEV(0x2e, LPC47B272_SP1) + +#include "southbridge/intel/i82801xx/i82801xx_early_smbus.c" + +void udelay(int usecs) +{ + int i; + for(i = 0; i < usecs; i++) + outb(i&0xff, 0x80); +} + +#include "debug.c" +#include "lib/delay.c" + +#include "northbridge/intel/i82810/raminit.c" +#include "northbridge/intel/i82810/debug.c" +#include "sdram/generic_sdram.c" + +static void main(unsigned long bist) +{ + static const struct mem_controller memctrl[] = { + { + .d0 = PCI_DEV(0, 0, 0), + .channel0 = { + (0xa << 3) | 0, + (0xa << 3) | 1, + }, + } + }; + + if (bist == 0) { + early_mtrr_init(); + } + + enable_smbus(); + + lpc47b272_enable_serial(SERIAL_DEV, TTYS0_BASE); + uart_init(); + console_init(); + + /* Halt if there was a built in self test failure */ + report_bist_failure(bist); + + //enable_shadow_ram(); + + //dump_spd_registers(&memctrl[0]); + + /* sdram_initialize runs out of registers */ + //sdram_initialize(sizeof(memctrl) / sizeof(memctrl[0]), memctrl); + + sdram_set_registers(memctrl); + sdram_set_spd_registers(memctrl); + sdram_enable(0, memctrl); + + /* Check whether RAM is working. + * + * Do _not_ check the area from 640 KB - 1 MB, as that's not really + * RAM, but rather reserved for various other things: + * + * - 640 KB - 768 KB: Video Buffer Area + * - 768 KB - 896 KB: Expansion Area + * - 896 KB - 960 KB: Extended System BIOS Area + * - 960 KB - 1 MB: Memory (BIOS Area) - System BIOS Area + * + * Trying to check these areas will fail. + */ + /* TODO: This is currently hardcoded to check 64 MB. */ + //ram_check(0x00000000, 0x0009ffff); /* 0 - 640 KB */ + //ram_check(0x00100000, 0x007c0000); /* 1 MB - 64 MB */ +} diff --git a/src/mainboard/asus/mew-vm/chip.h b/src/mainboard/asus/mew-vm/chip.h new file mode 100644 index 0000000000..bcadf9e6fe --- /dev/null +++ b/src/mainboard/asus/mew-vm/chip.h @@ -0,0 +1,5 @@ +extern struct chip_operations mainboard_asus_mew_vm_ops; + +struct mainboard_asus_mew_vm_config { + int nothing; +}; diff --git a/src/mainboard/asus/mew-vm/cmos.layout b/src/mainboard/asus/mew-vm/cmos.layout new file mode 100644 index 0000000000..5ba4c032c1 --- /dev/null +++ b/src/mainboard/asus/mew-vm/cmos.layout @@ -0,0 +1,74 @@ +entries + +#start-bit length config config-ID name +#0 8 r 0 seconds +#8 8 r 0 alarm_seconds +#16 8 r 0 minutes +#24 8 r 0 alarm_minutes +#32 8 r 0 hours +#40 8 r 0 alarm_hours +#48 8 r 0 day_of_week +#56 8 r 0 day_of_month +#64 8 r 0 month +#72 8 r 0 year +#80 4 r 0 rate_select +#84 3 r 0 REF_Clock +#87 1 r 0 UIP +#88 1 r 0 auto_switch_DST +#89 1 r 0 24_hour_mode +#90 1 r 0 binary_values_enable +#91 1 r 0 square-wave_out_enable +#92 1 r 0 update_finished_enable +#93 1 r 0 alarm_interrupt_enable +#94 1 r 0 periodic_interrupt_enable +#95 1 r 0 disable_clock_updates +#96 288 r 0 temporary_filler +0 384 r 0 reserved_memory +384 1 e 4 boot_option +385 1 e 4 last_boot +386 1 e 1 ECC_memory +388 4 r 0 reboot_bits +392 3 e 5 baud_rate +400 1 e 1 power_on_after_fail +412 4 e 6 debug_level +416 4 e 7 boot_first +420 4 e 7 boot_second +424 4 e 7 boot_third +428 4 h 0 boot_index +432 8 h 0 boot_countdown +1008 16 h 0 check_sum + +enumerations + +#ID value text +1 0 Disable +1 1 Enable +2 0 Enable +2 1 Disable +4 0 Fallback +4 1 Normal +5 0 115200 +5 1 57600 +5 2 38400 +5 3 19200 +5 4 9600 +5 5 4800 +5 6 2400 +5 7 1200 +6 6 Notice +6 7 Info +6 8 Debug +6 9 Spew +7 0 Network +7 1 HDD +7 2 Floppy +7 8 Fallback_Network +7 9 Fallback_HDD +7 10 Fallback_Floppy +#7 3 ROM + +checksums + +checksum 392 1007 1008 + + diff --git a/src/mainboard/asus/mew-vm/debug.c b/src/mainboard/asus/mew-vm/debug.c new file mode 100644 index 0000000000..7eeabdef47 --- /dev/null +++ b/src/mainboard/asus/mew-vm/debug.c @@ -0,0 +1,66 @@ + +static void print_debug_pci_dev(unsigned dev) +{ + print_debug("PCI: "); + print_debug_hex8((dev >> 16) & 0xff); + print_debug_char(':'); + print_debug_hex8((dev >> 11) & 0x1f); + print_debug_char('.'); + print_debug_hex8((dev >> 8) & 7); +} + +static void print_pci_devices(void) +{ + device_t dev; + for(dev = PCI_DEV(0, 0, 0); + dev <= PCI_DEV(0, 0x1f, 0x7); + dev += PCI_DEV(0,0,1)) { + uint32_t id; + id = pci_read_config32(dev, PCI_VENDOR_ID); + if (((id & 0xffff) == 0x0000) || ((id & 0xffff) == 0xffff) || + (((id >> 16) & 0xffff) == 0xffff) || + (((id >> 16) & 0xffff) == 0x0000)) { + continue; + } + print_debug_pci_dev(dev); + print_debug("\r\n"); + } +} + +static void dump_pci_device(unsigned dev) +{ + int i; + print_debug_pci_dev(dev); + print_debug("\r\n"); + + for(i = 0; i <= 255; i++) { + unsigned char val; + if ((i & 0x0f) == 0) { + print_debug_hex8(i); + print_debug_char(':'); + } + val = pci_read_config8(dev, i); + print_debug_char(' '); + print_debug_hex8(val); + if ((i & 0x0f) == 0x0f) { + print_debug("\r\n"); + } + } +} + +static void dump_pci_devices(void) +{ + device_t dev; + for(dev = PCI_DEV(0, 0, 0); + dev <= PCI_DEV(0, 0x1f, 0x7); + dev += PCI_DEV(0,0,1)) { + uint32_t id; + id = pci_read_config32(dev, PCI_VENDOR_ID); + if (((id & 0xffff) == 0x0000) || ((id & 0xffff) == 0xffff) || + (((id >> 16) & 0xffff) == 0xffff) || + (((id >> 16) & 0xffff) == 0x0000)) { + continue; + } + dump_pci_device(dev); + } +} diff --git a/src/mainboard/asus/mew-vm/failover.c b/src/mainboard/asus/mew-vm/failover.c new file mode 100644 index 0000000000..bdcb9eaed2 --- /dev/null +++ b/src/mainboard/asus/mew-vm/failover.c @@ -0,0 +1,32 @@ +#define ASSEMBLY 1 +#include <stdint.h> +#include <device/pci_def.h> +#include <device/pci_ids.h> +#include <arch/io.h> +#include "arch/romcc_io.h" +#include "pc80/mc146818rtc_early.c" + +static unsigned long main(unsigned long bist) +{ + /* This is the primary cpu how should I boot? */ + if (do_normal_boot()) { + goto normal_image; + } + else { + goto fallback_image; + } + normal_image: + asm volatile ("jmp __normal_image" + : /* outputs */ + : "a" (bist) /* inputs */ + : /* clobbers */ + ); + cpu_reset: + asm volatile ("jmp __cpu_reset" + : /* outputs */ + : "a"(bist) /* inputs */ + : /* clobbers */ + ); + fallback_image: + return bist; +} diff --git a/src/mainboard/asus/mew-vm/irq_tables.c b/src/mainboard/asus/mew-vm/irq_tables.c new file mode 100644 index 0000000000..5794344137 --- /dev/null +++ b/src/mainboard/asus/mew-vm/irq_tables.c @@ -0,0 +1,42 @@ +/* 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, which BIOS sets up + * + * Documentation at : http://www.microsoft.com/hwdev/busbios/PCIIRQ.HTM +*/ + +#include <arch/pirq_routing.h> + +const struct irq_routing_table intel_irq_routing_table = { + PIRQ_SIGNATURE, /* u32 signature */ + PIRQ_VERSION, /* u16 version */ + 32+16*11, /* there can be total 11 devices on the bus */ + 0x00, /* Where the interrupt router lies (bus) */ + (0x11<<3)|0x0, /* Where the interrupt router lies (dev) */ + 0xe20, /* IRQs devoted exclusively to PCI usage */ + 0x8086, /* Vendor */ + 0x7120, /* Device */ + 0, /* Crap (miniport) */ + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* u8 rfu[11] */ + 0x89, /* u8 checksum , this has to set to some value +that would give 0 after the sum of all bytes for this structure (including checksum) */ + { + /* bus, dev|fn, {link, bitmap}, {link, bitmap}, {link, bitmap}, {link, bitmap}, slot, rfu */ + {0x00,(0x08<<3)|0x0, {{0x02, 0xdea0}, {0x03, 0xdea0}, {0x04, 0xdea0}, {0x01, 0x0dea0}}, 0x1, 0x0}, + {0x00,(0x09<<3)|0x0, {{0x03, 0xdea0}, {0x04, 0xdea0}, {0x01, 0xdea0}, {0x02, 0x0dea0}}, 0x2, 0x0}, + {0x00,(0x0a<<3)|0x0, {{0x04, 0xdea0}, {0x01, 0xdea0}, {0x02, 0xdea0}, {0x03, 0x0dea0}}, 0x3, 0x0}, + {0x00,(0x0b<<3)|0x0, {{0x04, 0xdea0}, {0x01, 0xdea0}, {0x02, 0xdea0}, {0x03, 0x0dea0}}, 0x4, 0x0}, + {0x00,(0x0c<<3)|0x0, {{0x01, 0xdea0}, {0x02, 0xdea0}, {0x03, 0xdea0}, {0x04, 0x0dea0}}, 0x5, 0x0}, + {0x00,(0x0d<<3)|0x0, {{0x01, 0xdea0}, {0x02, 0xdea0}, {0x03, 0xdea0}, {0x04, 0x0dea0}}, 0x6, 0x0}, + {0x00,(0x11<<3)|0x0, {{0x00, 0xdea0}, {0x00, 0xdea0}, {0x03, 0xdea0}, {0x04, 0x0dea0}}, 0x0, 0x0}, + {0x00,(0x0f<<3)|0x0, {{0x01, 0xdea0}, {0x02, 0xdea0}, {0x03, 0xdea0}, {0x04, 0x0dea0}}, 0x0, 0x0}, + {0x00,(0x01<<3)|0x0, {{0x01, 0xdea0}, {0x02, 0xdea0}, {0x03, 0xdea0}, {0x04, 0x0dea0}}, 0x0, 0x0}, + {0x00,(0x10<<3)|0x0, {{0x01, 0xdea0}, {0x02, 0xdea0}, {0x03, 0xdea0}, {0x04, 0x0dea0}}, 0x0, 0x0}, + {0x00,(0x12<<3)|0x0, {{0x01, 0xdea0}, {0x00, 0xdea0}, {0x00, 0xdea0}, {0x00, 0x0dea0}}, 0x0, 0x0}, + } +}; + +unsigned long write_pirq_routing_table(unsigned long addr) +{ + return copy_pirq_routing_table(addr); +} diff --git a/src/mainboard/asus/mew-vm/mainboard.c b/src/mainboard/asus/mew-vm/mainboard.c new file mode 100644 index 0000000000..62d18c2cfe --- /dev/null +++ b/src/mainboard/asus/mew-vm/mainboard.c @@ -0,0 +1,7 @@ +#include <device/device.h> +#include "chip.h" + +struct chip_operations mainboard_asus_mew_vm_ops = { + CHIP_NAME("ASUS MEW-VM Mainboard") +}; + diff --git a/src/southbridge/intel/i82801xx/Config.lb b/src/southbridge/intel/i82801xx/Config.lb new file mode 100644 index 0000000000..5f18ef89c3 --- /dev/null +++ b/src/southbridge/intel/i82801xx/Config.lb @@ -0,0 +1,30 @@ +## +## This file is part of the LinuxBIOS project. +## +## Copyright (C) 2007 Corey Osgood <corey.osgood@gmail.com> +## +## 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## +driver i82801xx.o +driver i82801xx_usb.o +driver i82801xx_lpc.o +driver i82801xx_ide.o +driver i82801xx_usb_ehci.o +driver i82801xx_ac97.o +driver i82801xx_nic.o +driver i82801xx_pci.o +driver i82801xx_sata.o +object i82801xx_reset.o +object i82801xx_watchdog.o diff --git a/src/southbridge/intel/i82801xx/chip.h b/src/southbridge/intel/i82801xx/chip.h new file mode 100644 index 0000000000..3c1a3fd6d9 --- /dev/null +++ b/src/southbridge/intel/i82801xx/chip.h @@ -0,0 +1,39 @@ +/* + * This file is part of the LinuxBIOS project. + * + * Copyright (C) 2007 Corey Osgood <corey_osgood@verizon.net> + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef IGNORE_I82801XX_DEVICE_LIST +#warning "The i82801xx code currently supports, on a testing/experimental basis," +#warning "these devices:" +#warning "i82801aa, i82801ab, i82801ba, i82801ca, i82801db, i82801dbm, i82801eb," +#warning "and i82801er." +#warning "Using this without modification on any other i82801 version will probably" +#warning "work until ram init, but will fail after that" +#endif + +#ifndef SOUTHBRIDGE_INTEL_I82801XX_CHIP_H +#define SOUTHBRIDGE_INTEL_I82801XX_CHIP_H + +struct southbridge_intel_i82801xx_config +{ +}; + +extern struct chip_operations southbridge_intel_i82801xx_ops; + +#endif /* SOUTHBRIDGE_INTEL_I82801XX_CHIP_H */ diff --git a/src/southbridge/intel/i82801xx/cmos_failover.c b/src/southbridge/intel/i82801xx/cmos_failover.c new file mode 100644 index 0000000000..2e1d84adb8 --- /dev/null +++ b/src/southbridge/intel/i82801xx/cmos_failover.c @@ -0,0 +1,32 @@ +/* + * This file is part of the LinuxBIOS project. + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "i82801xx.h" + +static void check_cmos_failed(void) +{ + uint8_t byte; + byte = pci_read_config8(PCI_DEV(0, 0x1f, 0), GEN_PMCON_3); + if( byte & RTC_FAILED) { + //clear bit 1 and bit 2 + byte = cmos_read(RTC_BOOT_BYTE); + byte &= 0x0c; + byte |= MAX_REBOOT_CNT << 4; + cmos_write(byte, RTC_BOOT_BYTE); + } +} diff --git a/src/southbridge/intel/i82801xx/i82801xx.c b/src/southbridge/intel/i82801xx/i82801xx.c new file mode 100644 index 0000000000..5cceab9b9b --- /dev/null +++ b/src/southbridge/intel/i82801xx/i82801xx.c @@ -0,0 +1,67 @@ +/* + * This file is part of the LinuxBIOS project. + * + * Copyright (C) 2005 Digital Design Corporation + * (Written by Steven J. Magnani <steve@digidescorp.com> for Digital Design Corp) + * Copyright (C) 2007 Corey Osgood <corey.osgood@gmail.com> + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <console/console.h> +#include <device/device.h> +#include <device/pci.h> +#include "i82801xx.h" + +void i82801xx_enable(device_t dev) +{ + unsigned int index = 0; + uint16_t cur_disable_mask, new_disable_mask; + + // All 82801 devices should be on bus 0 + unsigned int devfn = PCI_DEVFN(0x1f, 0); // lpc + device_t lpc_dev = dev_find_slot(0, devfn); // 0 + if (!lpc_dev) + return; + + /* We're going to assume, perhaps incorrectly, that if a function exists + it can be disabled. Workarounds for ICH variants that don't follow this + should be done by checking the device ID */ + + if (PCI_SLOT(dev->path.u.pci.devfn) == 31) { + index = PCI_FUNC(dev->path.u.pci.devfn); + } else if (PCI_SLOT(dev->path.u.pci.devfn) == 29) { + index = 8 + PCI_FUNC(dev->path.u.pci.devfn); + } + + /* Function 0 is a bit of an exception */ + if(index == 0) + { + index = 14; + } + cur_disable_mask = pci_read_config16(lpc_dev, FUNC_DIS); + new_disable_mask = cur_disable_mask & ~(1 << index); // enable it + if (!dev->enabled) { + new_disable_mask |= (1 << index); // disable it, if desired + } + if (new_disable_mask != cur_disable_mask) { + pci_write_config16(lpc_dev, FUNC_DIS, new_disable_mask); + } +} + +struct chip_operations southbridge_intel_i82801xx_ops = { + CHIP_NAME("Intel i82801 Series Southbridge") + .enable_dev = i82801xx_enable, +}; diff --git a/src/southbridge/intel/i82801xx/i82801xx.h b/src/southbridge/intel/i82801xx/i82801xx.h new file mode 100644 index 0000000000..273767949e --- /dev/null +++ b/src/southbridge/intel/i82801xx/i82801xx.h @@ -0,0 +1,106 @@ +/* + * This file is part of the LinuxBIOS project. + * + * Copyright (C) 2007 Corey Osgood <corey.osgood@gmail.com> + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef I82801XX_H +#define I82801XX_H + +#ifndef __ROMCC__ +#include "chip.h" +extern void i82801xx_enable(device_t dev); +#endif + +#define PCI_DMA_CFG 0x90 +#define SERIRQ_CNTL 0x64 +#define GEN_CNTL 0xd0 +#define GEN_STS 0xd4 +#define RTC_CONF 0xd8 +#define GEN_PMCON_3 0xa4 + +#define PCICMD 0x04 +#define PMBASE 0x40 +#define PM_BASE_ADDR 0x1100 +#define ACPI_CNTL 0x44 +#define BIOS_CNTL 0x4E +#define GPIO_BASE 0x58 +#define GPIO_BASE_ADDR 0x1180 +#define GPIO_CNTL 0x5C +#define PIRQA_ROUT 0x60 +#define PIRQE_ROUT 0x68 +#define COM_DEC 0xE0 +#define LPC_EN 0xE6 +#define FUNC_DIS 0xF2 + +#define CMD 0x04 +#define SBUS_NUM 0x19 +#define SUB_BUS_NUM 0x1A +#define SMLT 0x1B +#define IOBASE 0x1C +#define IOLIM 0x1D +#define MEMBASE 0x20 +#define MEMLIM 0x22 +#define CNF 0x50 +#define MTT 0x70 +#define PCI_MAST_STS 0x82 + +// GEN_PMCON_3 bits +#define RTC_BATTERY_DEAD (1 << 2) +#define RTC_POWER_FAILED (1 << 1) +#define SLEEP_AFTER_POWER_FAIL (1 << 0) + +// PCI Configuration Space (D31:F1) +#define IDE_TIM_PRI 0x40 // IDE timings, primary +#define IDE_TIM_SEC 0x42 // IDE timings, secondary + +// IDE_TIM bits +#define IDE_DECODE_ENABLE (1 << 15) + +// PCI Configuration Space (D31:F3) +#define SMB_BASE 0x20 +#define HOSTC 0x40 + +// HOSTC bits +#define I2C_EN (1 << 2) +#define SMB_SMI_EN (1 << 1) +#define HST_EN (1 << 0) + +// SMBus IO bits +/* TODO: Does it matter where we put the SMBus IO base, as long as we keep + consistent and don't interfere with anything else? */ +//#define SMBUS_IO_BASE 0x1000 +#define SMBUS_IO_BASE 0x0f00 + +#define SMBHSTSTAT 0x0 +#define SMBHSTCTL 0x2 +#define SMBHSTCMD 0x3 +#define SMBXMITADD 0x4 +#define SMBHSTDAT0 0x5 +#define SMBHSTDAT1 0x6 +#define SMBBLKDAT 0x7 +#define SMBTRNSADD 0x9 +#define SMBSLVDATA 0xa +#define SMLINK_PIN_CTL 0xe +#define SMBUS_PIN_CTL 0xf + +#define SMBUS_TIMEOUT (10 * 1000 * 100) + +//HPET, if present +#define HPET_ADDR 0xfed0000 + +#endif /* I82801XX_H */ diff --git a/src/southbridge/intel/i82801xx/i82801xx_ac97.c b/src/southbridge/intel/i82801xx/i82801xx_ac97.c new file mode 100644 index 0000000000..f61e069e96 --- /dev/null +++ b/src/southbridge/intel/i82801xx/i82801xx_ac97.c @@ -0,0 +1,113 @@ +/* + * This file is part of the LinuxBIOS project. + * + * Copyright (C) 2005 Tyan Computer + * (Written by Yinghai Lu <yinghailu@gmail.com> for Tyan Computer) + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <console/console.h> +#include <device/device.h> +#include <device/pci.h> +#include <device/pci_ids.h> +#include "i82801xx.h" + +static struct device_operations ac97_ops = { + .read_resources = pci_dev_read_resources, + .set_resources = pci_dev_set_resources, + .enable_resources = pci_dev_enable_resources, + .init = 0, + .scan_bus = 0, + .enable = i82801xx_enable, +}; + +/* i82801aa */ +static struct pci_driver i82801aa_ac97_audio __pci_driver = { + .ops = &ac97_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = 0x2415, +}; + +static struct pci_driver i82801aa_ac97_modem __pci_driver = { + .ops = &ac97_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = 0x2416, +}; + +/* i82801ab */ +static struct pci_driver i82801ab_ac97_audio __pci_driver = { + .ops = &ac97_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = 0x2425, +}; + +static struct pci_driver i82801ab_ac97_modem __pci_driver = { + .ops = &ac97_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = 0x2426, +}; + +/* i82801ba */ +static struct pci_driver i82801ba_ac97_audio __pci_driver = { + .ops = &ac97_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = 0x2445, +}; + +static struct pci_driver i82801ba_ac97_modem __pci_driver = { + .ops = &ac97_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = 0x2446, +}; + +/* i82801ca */ +static struct pci_driver i82801ca_ac97_audio __pci_driver = { + .ops = &ac97_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = 0x2485, +}; + +static struct pci_driver i82801ca_ac97_modem __pci_driver = { + .ops = &ac97_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = 0x2486, +}; + +/* i82801db & i82801dbm */ +static struct pci_driver i82801db_ac97_audio __pci_driver = { + .ops = &ac97_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = 0x24c5, +}; + +static struct pci_driver i82801db_ac97_modem __pci_driver = { + .ops = &ac97_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = 0x24c6, +}; + +/* i82801eb & i82801er */ +static struct pci_driver i82801ex_ac97_audio __pci_driver = { + .ops = &ac97_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = 0x24d5, +}; + +static struct pci_driver i82801ex_ac97_modem __pci_driver = { + .ops = &ac97_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = 0x24d6, +}; diff --git a/src/southbridge/intel/i82801xx/i82801xx_early_smbus.c b/src/southbridge/intel/i82801xx/i82801xx_early_smbus.c new file mode 100644 index 0000000000..070cc22a00 --- /dev/null +++ b/src/southbridge/intel/i82801xx/i82801xx_early_smbus.c @@ -0,0 +1,74 @@ +/* + * This file is part of the LinuxBIOS project. + * + * Copyright (C) 2005 Tyan Computer + * (Written by Yinghai Lu <yinghailu@gmail.com> for Tyan Computer) + * Copyright (C) 2007 Corey Osgood <corey.osgood@gmail.com> + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <device/pci_ids.h> +#include "i82801xx.h" +#include "i82801xx_smbus.h" + +static void enable_smbus(void) +{ + device_t dev; + uint16_t device_id; + + /* Set the SMBus device staticly */ + dev = PCI_DEV(0x0, 0x1f, 0x3); + + /* Check to make sure we've got the right device */ + device_id = pci_read_config16(dev, 0x2); + + /* Clear bits 7-4, since those are the only bits that vary between models */ + device_id &= 0xff0f; + + if(device_id != 0x2403) + { + die("Device not found, Corey probably screwed up!"); + } + + /* Set SMBus I/O base */ + pci_write_config32(dev, SMB_BASE, SMBUS_IO_BASE | PCI_BASE_ADDRESS_SPACE_IO); + /* Set SMBus enable */ + pci_write_config8(dev, HOSTC, HST_EN); + /* Set SMBus I/O space enable */ + pci_write_config16(dev, PCI_COMMAND, PCI_COMMAND_IO); + /* Disable interrupt generation */ + outb(0, SMBUS_IO_BASE + SMBHSTCTL); + /* Clear any lingering errors, so transactions can run */ + outb(inb(SMBUS_IO_BASE + SMBHSTSTAT), SMBUS_IO_BASE + SMBHSTSTAT); + print_debug("SMBus controller enabled\r\n"); +} + +static inline int smbus_read_byte(unsigned device, unsigned address) +{ + return do_smbus_read_byte(device, address); +} + +static void smbus_write_byte(unsigned device, unsigned address, unsigned char val) +{ + print_err("Unimplemented smbus_write_byte() called\r\n"); + return; +} + +static inline int smbus_write_block(unsigned device, unsigned length, unsigned cmd, + unsigned data1, unsigned data2) +{ + return do_smbus_write_block(device, length, cmd, data1, data2); +} diff --git a/src/southbridge/intel/i82801xx/i82801xx_ide.c b/src/southbridge/intel/i82801xx/i82801xx_ide.c new file mode 100644 index 0000000000..f9bb403014 --- /dev/null +++ b/src/southbridge/intel/i82801xx/i82801xx_ide.c @@ -0,0 +1,113 @@ +/* + * This file is part of the LinuxBIOS project. + * + * Copyright (C) 2005 Tyan Computer + * (Written by Yinghai Lu <yinghailu@gmail.com> for Tyan Computer) + * Copyright (C) 2005 Digital Design Corporation + * (Written by Steven J. Magnani <steve@digidescorp.com> for Digital Design Corp) + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <console/console.h> +#include <device/device.h> +#include <device/pci.h> +#include <device/pci_ids.h> +#include "i82801xx.h" + +static void ide_init(struct device *dev) +{ + /* TODO: Needs to be tested for compatibility with ICH5(R) */ + /* Enable ide devices so the linux ide driver will work */ + uint16_t ideTimingConfig; + int enable_primary = 1; + int enable_secondary = 1; + + ideTimingConfig = pci_read_config16(dev, IDE_TIM_PRI); + ideTimingConfig &= ~IDE_DECODE_ENABLE; + if (enable_primary) { + /* Enable primary ide interface */ + ideTimingConfig |= IDE_DECODE_ENABLE; + printk_debug("IDE0 "); + } + pci_write_config16(dev, IDE_TIM_PRI, ideTimingConfig); + + ideTimingConfig = pci_read_config16(dev, IDE_TIM_SEC); + ideTimingConfig &= ~IDE_DECODE_ENABLE; + if (enable_secondary) { + /* Enable secondary ide interface */ + ideTimingConfig |= IDE_DECODE_ENABLE; + printk_debug("IDE1 "); + } + pci_write_config16(dev, IDE_TIM_SEC, ideTimingConfig); +} + +static struct device_operations ide_ops = { + .read_resources = pci_dev_read_resources, + .set_resources = pci_dev_set_resources, + .enable_resources = pci_dev_enable_resources, + .init = ide_init, + .scan_bus = 0, + .enable = i82801xx_enable, +}; + +/* i82801aa */ +static struct pci_driver i82801aa_ide __pci_driver = { + .ops = &ide_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = 0x2411, +}; + +/* i82801ab */ +static struct pci_driver i82801ab_ide __pci_driver = { + .ops = &ide_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = 0x2421, +}; + +/* i82801ba */ +static struct pci_driver i82801ba_ide __pci_driver = { + .ops = &ide_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = 0x244b, +}; + +/* i82801ca */ +static struct pci_driver i82801ca_ide __pci_driver = { + .ops = &ide_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = 0x248b, +}; + +/* i82801db */ +static struct pci_driver i82801db_ide __pci_driver = { + .ops = &ide_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = 0x24cb, +}; + +/* i82801dbm */ +static struct pci_driver i82801dbm_ide __pci_driver = { + .ops = &ide_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = 0x24ca, +}; + +/* i82801eb & i82801er */ +static struct pci_driver i82801ex_ide __pci_driver = { + .ops = &ide_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = 0x24db, +}; diff --git a/src/southbridge/intel/i82801xx/i82801xx_lpc.c b/src/southbridge/intel/i82801xx/i82801xx_lpc.c new file mode 100644 index 0000000000..3f9044c87a --- /dev/null +++ b/src/southbridge/intel/i82801xx/i82801xx_lpc.c @@ -0,0 +1,289 @@ +/* + * This file is part of the LinuxBIOS project. + * + * Copyright (C) 2003 Linux Networx + * Copyright (C) 2003 SuSE Linux AG + * Copyright (C) 2005 Tyan Computer + * (Written by Yinghai Lu <yinghailu@gmail.com> for Tyan Computer) + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* from i82801dbm, needs to be fixed to support everything the i82801er does */ + +#include <console/console.h> +#include <device/device.h> +#include <device/pci.h> +#include <device/pci_ids.h> +#include <pc80/mc146818rtc.h> +#include <pc80/isa-dma.h> +#include <arch/io.h> +#include "i82801xx.h" + +#define NMI_OFF 0 + +void i82801xx_enable_ioapic( struct device *dev) +{ + uint32_t reg32; + volatile uint32_t *ioapic_index = (volatile uint32_t *)0xfec00000; + volatile uint32_t *ioapic_data = (volatile uint32_t *)0xfec00010; + + reg32 = pci_read_config32(dev, GEN_CNTL); + reg32 |= (3 << 7); /* Enable IOAPIC */ + reg32 |= (1 << 13); /* Coprocessor error enable */ + reg32 |= (1 << 1); /* Delayed transaction enable */ + reg32 |= (1 << 2); /* DMA collection buffer enable */ + pci_write_config32(dev, GEN_CNTL, reg32); + printk_debug("IOAPIC Southbridge enabled %x\n", reg32); + + *ioapic_index = 0; + *ioapic_data = (1 << 25); + + *ioapic_index = 0; + reg32 = *ioapic_data; + printk_debug("Southbridge APIC ID = %x\n", reg32); + if(reg32 != (1 << 25)) + die("APIC Error\n"); + + /* TODO: From i82801ca, needed/useful on other ICH? */ + *ioapic_index = 3; // Select Boot Configuration register + *ioapic_data = 1; // Use Processor System Bus to deliver interrupts +} + +void i82801xx_enable_serial_irqs( struct device *dev) +{ + /* set packet length and toggle silent mode bit */ + pci_write_config8(dev, SERIRQ_CNTL, (1 << 7)|(1 << 6)|((21 - 17) << 2)|(0 << 0)); + pci_write_config8(dev, SERIRQ_CNTL, (1 << 7)|(0 << 6)|((21 - 17) << 2)|(0 << 0)); + /* TODO: Explain/#define the real meaning of these magic numbers ^^^ */ +} + +void i82801xx_lpc_route_dma( struct device *dev, uint8_t mask) +{ + uint16_t reg16; + int i; + reg16 = pci_read_config16(dev, PCI_DMA_CFG); + reg16 &= 0x300; + for(i = 0; i < 8; i++) { + if (i == 4) + continue; + reg16 |= ((mask & (1 << i))? 3:1) << (i * 2); + } + pci_write_config16(dev, PCI_DMA_CFG, reg16); +} + +void i82801xx_rtc_init(struct device *dev) +{//todo:needs serious cleanup/comments + uint8_t reg8; + uint32_t reg32; + int rtc_failed; + byte = pci_read_config8(dev, GEN_PMCON_3); + rtc_failed = byte & RTC_BATTERY_DEAD; + if (rtc_failed) { + reg8 &= ~(1 << 1); /* preserve the power fail state */ + pci_write_config8(dev, GEN_PMCON_3, reg8); + } + reg32 = pci_read_config32(dev, GEN_STS); + rtc_failed |= reg32 & (1 << 2); + rtc_init(rtc_failed); +} + + +void i82801xx_1f0_misc(struct device *dev) +{ + /* TODO: break this down into smaller functions */ + + //move to acpi_enable or something + /* Set ACPI base address to 0x1100 (I/O space) */ + pci_write_config32(dev, PMBASE, PM_BASE_ADDR | 1); + /* Enable ACPI I/O and power management */ + pci_write_config8(dev, ACPI_CNTL, 0x10); + /* Set GPIO base address to 0x1180 (I/O space) */ + pci_write_config32(dev, GPIO_BASE, GPIO_BASE_ADDR | 1); + /* Enable GPIO */ + pci_write_config8(dev, GPIO_CNTL, 0x10); + + //get rid of? + /* Route PIRQA to IRQ11, PIRQB to IRQ3, PIRQC to IRQ5, PIRQD to IRQ10 */ + pci_write_config32(dev, PIRQA_ROUT, 0x0A05030B); + /* Route PIRQE to IRQ7. Leave PIRQF - PIRQH unrouted */ + pci_write_config8(dev, PIRQE_ROUT, 0x07); + + //move to i82801xx_init + /* Prevent LPC disabling, enable parity errors, and SERR# (System Error) */ + pci_write_config16(dev, PCI_COMMAND, 0x014f); + /* Enable access to the upper 128 byte bank of CMOS RAM */ + pci_write_config8(dev, RTC_CONF, 0x04); + /* Decode 0x3F8-0x3FF (COM1) for COMA port, 0x2F8-0x2FF (COM2) for COMB */ + pci_write_config8(dev, COM_DEC, 0x10); + /* LPT decode defaults to 0x378-0x37F and 0x778-0x77F + * Floppy decode defaults to 0x3F0-0x3F5, 0x3F7 */ + /* Enable: COMA, COMB, LPT, Floppy + * Disable: Microcontroller, Sound, Gameport */ + pci_write_config16(dev, LPC_EN, 0x000F); +} + +static void enable_hpet(struct device *dev) +{ +#ifdef HPET_PRESENT + uint32_t reg32; + uint32_t code = (0 & 0x3); + + reg32 = pci_read_config32(dev, GEN_CNTL); + reg32 |= (1 << 17); /* Enable HPET */ + /*Bits [16:15]Memory Address Range + 00 FED0_0000h - FED0_03FFh + 01 FED0_1000h - FED0_13FFh + 10 FED0_2000h - FED0_23FFh + 11 FED0_3000h - FED0_33FFh*/ + + reg32 &= ~(3 << 15); /* Clear it */ + reg32 |= (code << 15); + /* reg32 is never written to anywhere?? */ + printk_debug("Enabling HPET @0x%x\n", HPET_ADDR | (code << 12)); +#endif +} + + +static void lpc_init(struct device *dev) +{ + uint8_t byte; + int pwr_on = -1; + int nmi_option; + + /* IO APIC initialization */ + i82801xx_enable_ioapic(dev); + + i82801xx_enable_serial_irqs(dev); + + /* TODO: Find out if this is being used/works */ +#ifdef SUSPICIOUS_LOOKING_CODE + /* The ICH-4 datasheet does not mention this configuration register. */ + /* This code may have been inherited (incorrectly) from code for + the AMD 766 southbridge, which *does* support this functionality. */ + + /* Posted memory write enable */ + byte = pci_read_config8(dev, 0x46); + pci_write_config8(dev, 0x46, byte | (1<<0)); +#endif + + /* power after power fail */ + /* FIXME this doesn't work! */ + /* Which state do we want to goto after g3 (power restored)? + * 0 == S0 Full On + * 1 == S5 Soft Off + */ + pci_write_config8(dev, GEN_PMCON_3, pwr_on?0:1); + printk_info("Set power %s if power fails\n", pwr_on?"on":"off"); + + /* Set up NMI on errors */ + byte = inb(0x61); + byte &= ~(1 << 3); /* IOCHK# NMI Enable */ + byte &= ~(1 << 2); /* PCI SERR# Enable */ + outb(byte, 0x61); + byte = inb(0x70); + + nmi_option = NMI_OFF; + get_option(&nmi_option, "nmi"); + if (nmi_option) { + byte &= ~(1 << 7); /* set NMI */ + outb(byte, 0x70); + } + + /* Initialize the real time clock */ + i82801xx_rtc_init(dev); + + i82801xx_lpc_route_dma(dev, 0xff); + + /* Initialize isa dma */ + isa_dma_init(); + + i82801xx_1f0_misc(dev); + /* Initialize the High Precision Event Timers, if present */ + enable_hpet(dev); +} + +static void i82801xx_lpc_read_resources(device_t dev) +{ + struct resource *res; + + /* Get the normal pci resources of this device */ + pci_dev_read_resources(dev); + + /* Add an extra subtractive resource for both memory and I/O */ + res = new_resource(dev, IOINDEX_SUBTRACTIVE(0, 0)); + res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE | IORESOURCE_ASSIGNED; + + res = new_resource(dev, IOINDEX_SUBTRACTIVE(1, 0)); + res->flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE | IORESOURCE_ASSIGNED; +} + +static void i82801xx_lpc_enable_resources(device_t dev) +{ + pci_dev_enable_resources(dev); + enable_childrens_resources(dev); +} + +static struct device_operations lpc_ops = { + .read_resources = i82801xx_lpc_read_resources, + .set_resources = pci_dev_set_resources, + .enable_resources = i82801xx_lpc_enable_resources, + .init = lpc_init, + .scan_bus = scan_static_bus, + .enable = i82801xx_enable, +}; + +static struct pci_driver i82801aa_lpc __pci_driver = { + .ops = &lpc_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = 0x2410, +}; + +static struct pci_driver i82801ab_lpc __pci_driver = { + .ops = &lpc_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = 0x2420, +}; + +static struct pci_driver i82801ba_lpc __pci_driver = { + .ops = &lpc_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = 0x2440, +}; + +static struct pci_driver i82801ca_lpc __pci_driver = { + .ops = &lpc_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = 0x2480, +}; + +static struct pci_driver i82801db_lpc __pci_driver = { + .ops = &lpc_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = 0x24c0, +}; + +static struct pci_driver i82801dbm_lpc __pci_driver = { + .ops = &lpc_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = 0x24cc, +}; + +/* i82801eb and er */ +static struct pci_driver i82801ex_lpc __pci_driver = { + .ops = &lpc_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = 0x24d0, +}; diff --git a/src/southbridge/intel/i82801xx/i82801xx_nic.c b/src/southbridge/intel/i82801xx/i82801xx_nic.c new file mode 100644 index 0000000000..fe2ee9fbb3 --- /dev/null +++ b/src/southbridge/intel/i82801xx/i82801xx_nic.c @@ -0,0 +1,44 @@ +/* + * This file is part of the LinuxBIOS project. + * + * Copyright (C) 2007 Corey Osgood <corey.osgood@gmail.com> + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <console/console.h> +#include <device/device.h> +#include <device/pci.h> +#include <device/pci_ids.h> + +static struct device_operations nic_ops = { + .read_resources = pci_dev_read_resources, + .set_resources = pci_dev_set_resources, + .enable_resources = pci_dev_enable_resources, + .init = 0, + .scan_bus = 0, +}; + +static struct pci_driver i82801dbm_nic __pci_driver = { + .ops = &nic_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = 0x103a, +}; + +static struct pci_driver i82801ex_nic __pci_driver = { + .ops = &nic_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = 0x1051, +}; diff --git a/src/southbridge/intel/i82801xx/i82801xx_pci.c b/src/southbridge/intel/i82801xx/i82801xx_pci.c new file mode 100644 index 0000000000..3d27f7f545 --- /dev/null +++ b/src/southbridge/intel/i82801xx/i82801xx_pci.c @@ -0,0 +1,80 @@ +/* + * This file is part of the LinuxBIOS project. + * + * Copyright (C) 2005 Tyan Computer + * (Written by Yinghai Lu <yinghailu@gmail.com> for Tyan Computer) + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <console/console.h> +#include <device/device.h> +#include <device/pci.h> +#include <device/pci_ids.h> + +static void pci_init(struct device *dev) +{ + uint32_t reg32; + uint16_t reg16; + + /* Clear system errors */ + reg16 = pci_read_config16(dev, 0x06); + reg16 |= 0xf900; /* Clear possible errors */ + pci_write_config16(dev, 0x06, reg16); + + /* i82801er has this commented out, wonder why? */ + /* System error enable */ + reg32 = pci_read_config32(dev, 0x04); + reg32 |= (1 << 8); /* SERR# Enable */ + reg32 |= (1 << 6); /* Parity Error Response */ + pci_write_config32(dev, 0x04, reg32); + + reg16 = pci_read_config16(dev, 0x1e); + reg16 |= 0xf800; /* Clear possible errors */ + pci_write_config16(dev, 0x1e, reg16); +} + +static struct device_operations pci_ops = { + .read_resources = pci_bus_read_resources, + .set_resources = pci_dev_set_resources, + .enable_resources = pci_bus_enable_resources, + .init = pci_init, + .scan_bus = pci_scan_bridge, +}; + +static struct pci_driver i82801aa_pci __pci_driver = { + .ops = &pci_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = 0x2418, +}; + +static struct pci_driver i82801ab_pci __pci_driver = { + .ops = &pci_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = 0x2428, +}; + +/* i82801ba, ca, db, eb, and er */ +static struct pci_driver i82801misc_pci __pci_driver = { + .ops = &pci_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = 0x244e, +}; + +static struct pci_driver i82801dbm_pci __pci_driver = { + .ops = &pci_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = 0x2448, +}; diff --git a/src/southbridge/intel/i82801xx/i82801xx_reset.c b/src/southbridge/intel/i82801xx/i82801xx_reset.c new file mode 100644 index 0000000000..7a9f6de492 --- /dev/null +++ b/src/southbridge/intel/i82801xx/i82801xx_reset.c @@ -0,0 +1,27 @@ +/* + * This file is part of the LinuxBIOS project. + * + * Copyright (C) 2002 Eric Biederman <ebiederm@xmission.com> + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <arch/io.h> + +void hard_reset(void) +{ + /* Try rebooting through port 0xcf9 */ + outb((1 << 2)|(1 << 1), 0xcf9); +} diff --git a/src/southbridge/intel/i82801xx/i82801xx_sata.c b/src/southbridge/intel/i82801xx/i82801xx_sata.c new file mode 100644 index 0000000000..33dfc329ac --- /dev/null +++ b/src/southbridge/intel/i82801xx/i82801xx_sata.c @@ -0,0 +1,82 @@ +/* + * This file is part of the LinuxBIOS project. + * + * Copyright (C) 2005 Tyan Computer + * (Written by Yinghai Lu <yinghailu@gmail.com> for Tyan Computer) + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <console/console.h> +#include <device/device.h> +#include <device/pci.h> +#include <device/pci_ids.h> +#include <device/pci_ops.h> +#include "i82801xx.h" + +/* TODO: set dynamically, if the user only wants one sata channel or none at all */ + +static void sata_init(struct device *dev) +{ + /* SATA configuration */ + pci_write_config8(dev, 0x04, 0x07); + pci_write_config8(dev, 0x09, 0x8f); + + /* Set timmings */ + pci_write_config16(dev, 0x40, 0x0a307); + pci_write_config16(dev, 0x42, 0x0a307); + + /* Sync DMA */ + pci_write_config16(dev, 0x48, 0x000f); + pci_write_config16(dev, 0x4a, 0x1111); + + /* 66 mhz */ + pci_write_config16(dev, 0x54, 0xf00f); + + /* Combine ide - sata configuration */ + pci_write_config8(dev, 0x90, 0x0); + + /* port 0 & 1 enable */ + pci_write_config8(dev, 0x92, 0x33); + + /* initialize SATA */ + pci_write_config16(dev, 0xa0, 0x0018); + pci_write_config32(dev, 0xa4, 0x00000264); + pci_write_config16(dev, 0xa0, 0x0040); + pci_write_config32(dev, 0xa4, 0x00220043); +} + +static struct device_operations sata_ops = { + .read_resources = pci_dev_read_resources, + .set_resources = pci_dev_set_resources, + .enable_resources = pci_dev_enable_resources, + .init = sata_init, + .scan_bus = 0, + .enable = i82801xx_enable, +}; + +/* i82801eb */ +static struct pci_driver i82801eb_sata_driver __pci_driver = { + .ops = &sata_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = 0x24d1, +}; + +/* i82801er */ +static struct pci_driver i82801er_sata_driver __pci_driver = { + .ops = &sata_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = 0x24df, +}; diff --git a/src/southbridge/intel/i82801xx/i82801xx_smbus.c b/src/southbridge/intel/i82801xx/i82801xx_smbus.c new file mode 100644 index 0000000000..67a746666c --- /dev/null +++ b/src/southbridge/intel/i82801xx/i82801xx_smbus.c @@ -0,0 +1,94 @@ +/* + * This file is part of the LinuxBIOS project. + * + * Copyright (C) 2005 Yinghai Lu <yinghailu@gmail.com> + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <smbus.h> +#include <pci.h> +#include <arch/io.h> +#include "i82801_model_specific.h" +#include "i82801xx.h" +#include "i82801_smbus.h" + +static int smbus_read_byte(struct bus *bus, device_t dev, uint8_t address) +{ + unsigned device; + struct resource *res; + + device = dev->path.u.i2c.device; + res = find_resource(bus->dev, 0x20); + + return do_smbus_read_byte(res->base, device, address); +} + +static struct smbus_bus_operations lops_smbus_bus = { + .read_byte = smbus_read_byte, +}; + +static struct device_operations smbus_ops = { + .read_resources = pci_dev_read_resources, + .set_resources = pci_dev_set_resources, + .enable_resources = pci_dev_enable_resources, + .init = 0, + .scan_bus = scan_static_bus, + .enable = i82801er_enable, + .ops_smbus_bus = &lops_smbus_bus, +}; + +/* i82801aa */ +static struct pci_driver smbus_driver __pci_driver = { + .ops = &smbus_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = 0x2413, +}; + +/* i82801ab */ +static struct pci_driver smbus_driver __pci_driver = { + .ops = &smbus_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = 0x2423, +}; + +/* i82801ba */ +static struct pci_driver smbus_driver __pci_driver = { + .ops = &smbus_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = 0x2443, +}; + +/* i82801ca */ +static struct pci_driver smbus_driver __pci_driver = { + .ops = &smbus_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = 0x2483, +}; + +/* i82801db and i82801dbm */ +static struct pci_driver smbus_driver __pci_driver = { + .ops = &smbus_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = 0x24c3, +}; + +/* i82801eb and i82801er */ +static struct pci_driver smbus_driver __pci_driver = { + .ops = &smbus_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = 0x24d3, +}; + diff --git a/src/southbridge/intel/i82801xx/i82801xx_smbus.h b/src/southbridge/intel/i82801xx/i82801xx_smbus.h new file mode 100644 index 0000000000..d0226046da --- /dev/null +++ b/src/southbridge/intel/i82801xx/i82801xx_smbus.h @@ -0,0 +1,181 @@ +/* + * This file is part of the LinuxBIOS project. + * + * Copyright (C) 2005 Yinghai Lu <yinghailu@gmail.com> + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <device/smbus_def.h> + +static void smbus_delay(void) +{ + inb(0x80); +} + +static int smbus_wait_until_ready(void) +{ + unsigned loops = SMBUS_TIMEOUT; + unsigned char byte; + do { + smbus_delay(); + if (--loops == 0) + break; + byte = inb(SMBUS_IO_BASE + SMBHSTSTAT); + } while(byte & 1); + return loops?0:-1; +} + +static int smbus_wait_until_done(void) +{ + unsigned loops = SMBUS_TIMEOUT; + unsigned char byte; + do { + smbus_delay(); + if (--loops == 0) + break; + byte = inb(SMBUS_IO_BASE + SMBHSTSTAT); + } while((byte & 1) || (byte & ~((1<<6)|(1<<0))) == 0); + return loops?0:-1; +} + +static int smbus_wait_until_blk_done(void) +{ + unsigned loops = SMBUS_TIMEOUT; + unsigned char byte; + do { + smbus_delay(); + if (--loops == 0) + break; + byte = inb(SMBUS_IO_BASE + SMBHSTSTAT); + } while((byte & (1 << 7)) == 0); + return loops?0:-1; +} + +static int do_smbus_read_byte(unsigned device, unsigned address) +{ + unsigned char global_status_register; + unsigned char byte; + + if (smbus_wait_until_ready() < 0) { + return SMBUS_WAIT_UNTIL_READY_TIMEOUT; + } + /* Setup transaction */ + /* Disable interrupts */ + outb(inb(SMBUS_IO_BASE + SMBHSTCTL) & (~1), SMBUS_IO_BASE + SMBHSTCTL); + /* Set the device I'm talking too */ + outb(((device & 0x7f) << 1) | 1, SMBUS_IO_BASE + SMBXMITADD); + /* Set the command/address... */ + outb(address & 0xff, SMBUS_IO_BASE + SMBHSTCMD); + /* Set up for a byte data read */ + outb((inb(SMBUS_IO_BASE + SMBHSTCTL) & 0xe3) | (0x2 << 2), (SMBUS_IO_BASE + SMBHSTCTL)); + /* Clear any lingering errors, so the transaction will run */ + outb(inb(SMBUS_IO_BASE + SMBHSTSTAT), SMBUS_IO_BASE + SMBHSTSTAT); + + /* Clear the data byte...*/ + outb(0, SMBUS_IO_BASE + SMBHSTDAT0); + + /* Start the command */ + outb((inb(SMBUS_IO_BASE + SMBHSTCTL) | 0x40), SMBUS_IO_BASE + SMBHSTCTL); + + /* Poll for transaction completion */ + if (smbus_wait_until_done() < 0) { + return SMBUS_WAIT_UNTIL_DONE_TIMEOUT; + } + + global_status_register = inb(SMBUS_IO_BASE + SMBHSTSTAT); + + /* Ignore the "In Use" status... */ + global_status_register &= ~(3 << 5); + + /* Read results of transaction */ + byte = inb(SMBUS_IO_BASE + SMBHSTDAT0); + if (global_status_register != (1 << 1)) { + return SMBUS_ERROR; + } + return byte; +} + +/* This function is neither used nor tested by me (Corey Osgood), the author +(Yinghai) probably tested/used it on i82801er */ +static int do_smbus_write_block(unsigned device, unsigned length, unsigned cmd, + unsigned data1, unsigned data2) +{ +#warning "do_smbus_write_block is commented out" + print_err("Untested smbus_write_block called\r\n"); +#if 0 + unsigned char global_control_register; + unsigned char global_status_register; + unsigned char byte; + unsigned char stat; + int i; + + /* Clear the PM timeout flags, SECOND_TO_STS */ + outw(inw(0x0400 + 0x66), 0x0400 + 0x66); + + if (smbus_wait_until_ready(SMBUS_IO_BASE) < 0) { + return -2; + } + + /* Setup transaction */ + /* Obtain ownership */ + outb(inb(SMBUS_IO_BASE + SMBHSTSTAT), SMBUS_IO_BASE + SMBHSTSTAT); + for(stat = 0; (stat & 0x40) == 0; ) { + stat = inb(SMBUS_IO_BASE + SMBHSTSTAT); + } + /* Clear the done bit */ + outb(0x80, SMBUS_IO_BASE + SMBHSTSTAT); + /* Disable interrupts */ + outb(inb(SMBUS_IO_BASE + SMBHSTCTL) & (~1), SMBUS_IO_BASE + SMBHSTCTL); + + /* Set the device I'm talking too */ + outb(((device & 0x7f) << 1), SMBUS_IO_BASE + SMBXMITADD); + + /* Set the command address */ + outb(cmd & 0xff, SMBUS_IO_BASE + SMBHSTCMD); + + /* Set the block length */ + outb(length & 0xff, SMBUS_IO_BASE + SMBHSTDAT0); + + /* Try sending out the first byte of data here */ + byte = (data1 >> (0)) & 0x0ff; + outb(byte, SMBUS_IO_BASE + SMBBLKDAT); + /* Issue a block write command */ + outb((inb(SMBUS_IO_BASE + SMBHSTCTL) & 0xe3) | (0x5 << 2) | 0x40, + SMBUS_IO_BASE + SMBHSTCTL); + + for(i = 0;i < length; i++) { + + /* Poll for transaction completion */ + if (smbus_wait_until_blk_done(SMBUS_IO_BASE) < 0) { + return -3; + } + + /* Load the next byte */ + if(i > 3) + byte = (data2 >> (i % 4)) & 0x0ff; + else + byte = (data1 >> (i)) & 0x0ff; + outb(byte, SMBUS_IO_BASE + SMBBLKDAT); + + /* Clear the done bit */ + outb(inb(SMBUS_IO_BASE + SMBHSTSTAT), + SMBUS_IO_BASE + SMBHSTSTAT); + } + + print_debug("SMBUS Block complete\r\n"); + return 0; +#endif +} diff --git a/src/southbridge/intel/i82801xx/i82801xx_usb.c b/src/southbridge/intel/i82801xx/i82801xx_usb.c new file mode 100644 index 0000000000..27c09e089e --- /dev/null +++ b/src/southbridge/intel/i82801xx/i82801xx_usb.c @@ -0,0 +1,130 @@ +/* + * This file is part of the LinuxBIOS project. + * + * Copyright (C) 2007 Corey Osgood <corey.osgood@gmail.com> + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <console/console.h> +#include <device/device.h> +#include <device/pci.h> +#include <device/pci_ids.h> +#include <device/pci_ops.h> +#include "i82801xx.h" + +static void usb_init(struct device *dev) +{ +/* TODO: Any init needed? Some ports have it, others don't */ +} + +static struct device_operations usb_ops = { + .read_resources = pci_dev_read_resources, + .set_resources = pci_dev_set_resources, + .enable_resources = pci_dev_enable_resources, + .init = usb_init, + .scan_bus = 0, + .enable = i82801xx_enable, +}; + +/* i82801aa */ +static struct pci_driver i82801aa_usb_1 __pci_driver = { + .ops = &usb_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = 0x2412, +}; + +/* i82801ab */ +static struct pci_driver i82801ab_usb_1 __pci_driver = { + .ops = &usb_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = 0x2422, +}; + +/* i82801ba */ +static struct pci_driver i82801ba_usb_1 __pci_driver = { + .ops = &usb_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = 0x2442, +}; + +static struct pci_driver i82801ba_usb_2 __pci_driver = { + .ops = &usb_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = 0x2444, +}; + +/* i82801ca */ +static struct pci_driver i82801ca_usb_1 __pci_driver = { + .ops = &usb_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = 0x2482, +}; + +static struct pci_driver i82801ca_usb_2 __pci_driver = { + .ops = &usb_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = 0x2484, +}; + +static struct pci_driver i82801ca_usb_3 __pci_driver = { + .ops = &usb_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = 0x2487, +}; + +/* i82801db and i82801dbm */ +static struct pci_driver i82801db_usb_1 __pci_driver = { + .ops = &usb_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = 0x24c2, +}; + +static struct pci_driver i82801db_usb_2 __pci_driver = { + .ops = &usb_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = 0x24c4, +}; + +static struct pci_driver i82801db_usb_3 __pci_driver = { + .ops = &usb_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = 0x24c7, +}; + +/* i82801eb and i82801er */ +static struct pci_driver i82801ex_usb_1 __pci_driver = { + .ops = &usb_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = 0x24d2, +}; + +static struct pci_driver i82801ex_usb_2 __pci_driver = { + .ops = &usb_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = 0x24d4, +}; + +static struct pci_driver i82801ex_usb_3 __pci_driver = { + .ops = &usb_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = 0x24d7, +}; + +static struct pci_driver i82801ex_usb_4 __pci_driver = { + .ops = &usb_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = 0x24de, +}; diff --git a/src/southbridge/intel/i82801xx/i82801xx_usb_ehci.c b/src/southbridge/intel/i82801xx/i82801xx_usb_ehci.c new file mode 100644 index 0000000000..7577da19df --- /dev/null +++ b/src/southbridge/intel/i82801xx/i82801xx_usb_ehci.c @@ -0,0 +1,81 @@ +/* + * This file is part of the LinuxBIOS project. + * + * Copyright (C) 2005 Tyan Computer + * (Written by Yinghai Lu <yinghailu@gmail.com> for Tyan Computer> + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <console/console.h> +#include <device/device.h> +#include <device/pci.h> +#include <device/pci_ids.h> +#include <device/pci_ops.h> +#include "i82801xx.h" + +static void usb_ehci_init(struct device *dev) +{ + /* TODO: Is any special init really needed? */ + uint32_t cmd; + + printk_debug("EHCI: Setting up controller.. "); + cmd = pci_read_config32(dev, PCI_COMMAND); + pci_write_config32(dev, PCI_COMMAND, + cmd | PCI_COMMAND_MASTER); + + printk_debug("done.\n"); +} + +static void usb_ehci_set_subsystem(device_t dev, unsigned vendor, unsigned device) +{ + uint8_t access_cntl; + access_cntl = pci_read_config8(dev, 0x80); + /* Enable writes to protected registers */ + pci_write_config8(dev, 0x80, access_cntl | 1); + /* Write the subsystem vendor and device id */ + pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID, + ((device & 0xffff) << 16) | (vendor & 0xffff)); + /* Restore protection */ + pci_write_config8(dev, 0x80, access_cntl); +} + +static struct pci_operations lops_pci = { + .set_subsystem = &usb_ehci_set_subsystem, +}; + +static struct device_operations usb_ehci_ops = { + .read_resources = pci_dev_read_resources, + .set_resources = pci_dev_set_resources, + .enable_resources = pci_dev_enable_resources, + .init = usb_ehci_init, + .scan_bus = 0, + .enable = i82801xx_enable, + .ops_pci = &lops_pci, +}; + +/* i82801db and i82801dbm */ +static struct pci_driver i82801db_usb_ehci __pci_driver = { + .ops = &usb_ehci_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = 0x24cd, +}; + +/* i82801eb and i82801er */ +static struct pci_driver i82801ex_usb_ehci __pci_driver = { + .ops = &usb_ehci_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = 0x24dd, +}; diff --git a/src/southbridge/intel/i82801xx/i82801xx_watchdog.c b/src/southbridge/intel/i82801xx/i82801xx_watchdog.c new file mode 100644 index 0000000000..e2a95156eb --- /dev/null +++ b/src/southbridge/intel/i82801xx/i82801xx_watchdog.c @@ -0,0 +1,51 @@ +/* + * This file is part of the LinuxBIOS project. + * + * Copyright (C) 2006 John Dufresne <jon.dufresne@gmail.com> + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include <console/console.h> +#include <arch/io.h> +#include <device/device.h> +#include <device/pci.h> + +/* TODO: I'm fairly sure the same functionality is provided elsewhere */ + +void watchdog_off(void) +{ + device_t dev; + unsigned long value,base; + + /* turn off the ICH5 watchdog */ + dev = dev_find_slot(0, PCI_DEVFN(0x1f,0)); + + /* Enable I/O space */ + value = pci_read_config16(dev, 0x04); + value |= (1 << 10); + pci_write_config16(dev, 0x04, value); + /* Get TCO base */ + base = (pci_read_config32(dev, 0x40) & 0x0fffe) + 0x60; + /* Disable the watchdog timer */ + value = inw(base + 0x08); + value |= 1 << 11; + outw(value, base + 0x08); + /* Clear TCO timeout status */ + outw(0x0008, base + 0x04); + outw(0x0002, base + 0x06); + printk_debug("ICH Watchdog disabled\r\n"); +} + + |