diff options
Diffstat (limited to 'src/southbridge')
20 files changed, 1122 insertions, 0 deletions
diff --git a/src/southbridge/intel/i82801er/Config.lb b/src/southbridge/intel/i82801er/Config.lb new file mode 100644 index 0000000000..cc77c755a7 --- /dev/null +++ b/src/southbridge/intel/i82801er/Config.lb @@ -0,0 +1,11 @@ +config i82801er.h +driver i82801er.o +driver i82801er_usb.o +driver i82801er_lpc.o +driver i82801er_ide.o +driver i82801er_sata.o +driver i82801er_usb2.o +driver i82801er_ac97.o +#driver i82801er_nic.o +#driver i82801er_pci.o +object i82801er_reset.o diff --git a/src/southbridge/intel/i82801er/cmos_failover.c b/src/southbridge/intel/i82801er/cmos_failover.c new file mode 100644 index 0000000000..9702313f9c --- /dev/null +++ b/src/southbridge/intel/i82801er/cmos_failover.c @@ -0,0 +1,16 @@ +//kind of cmos_err for ich5 +#define RTC_FAILED (1 <<2) +#define GEN_PMCON_3 0xa4 +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/i82801er/i82801er.c b/src/southbridge/intel/i82801er/i82801er.c new file mode 100644 index 0000000000..565d672260 --- /dev/null +++ b/src/southbridge/intel/i82801er/i82801er.c @@ -0,0 +1,57 @@ +#include <console/console.h> +#include <device/device.h> +#include <device/pci.h> +#include <device/pci_ids.h> +#include <device/chip.h> +#include "i82801er.h" + +void i82801er_enable(device_t dev) +{ + device_t lpc_dev; + unsigned int index; + uint16_t reg_old, reg; + +// all 82801er device ares in bus 0 + unsigned int devfn; + devfn = PCI_DEVFN(0x1f, 0); // lpc + lpc_dev = dev_find_slot(0, devfn); // 0 + if (!lpc_dev ) { + return; + } +#if 0 + if ((lpc_dev->vendor != PCI_VENDOR_ID_INTEL) || + (lpc_dev->device != PCI_DEVICE_ID_INTEL_82801ER_1F0)) { + uint32_t id; + id = pci_read_config32(lpc_dev, PCI_VENDOR_ID); + if (id != (PCI_VENDOR_ID_INTEL | (PCI_DEVICE_ID_INTEL_82801ER_1F0 << 16))) { + return; + } + } +#endif + + index = (dev->path.u.pci.devfn & 7); + if((dev->path.u.pci.devfn & ~0x7)==devfn) { // D=0x1f + if(index==0){ //1f0 + index = 14; + } + } else { // D=0x1d + index += 8; + } + + reg_old = pci_read_config16(lpc_dev, FUNC_DIS); + reg = reg_old; + reg &= ~(1<<index); // enable it + if (!dev->enabled) { + reg |= (1<<index); // disable it + } + if (reg != reg_old) { + pci_write_config16(lpc_dev, FUNC_DIS, reg); + } + reg = pci_read_config16(lpc_dev, FUNC_DIS); + +} + +struct chip_control southbridge_intel_i82801er_control = { + .name = "Intel 82801er Southbridge", + .enable_dev = i82801er_enable, +}; diff --git a/src/southbridge/intel/i82801er/i82801er.h b/src/southbridge/intel/i82801er/i82801er.h new file mode 100644 index 0000000000..85dce4ecb7 --- /dev/null +++ b/src/southbridge/intel/i82801er/i82801er.h @@ -0,0 +1,81 @@ +#ifndef I82801ER_H +#define I82801ER_H + +struct southbridge_intel_i82801er_config +{ +}; +struct chip_control; +extern struct chip_control southbridge_intel_i82801er_control; + +extern void i82801er_enable(device_t dev); + +/* +000 = Non-combined. P0 is primary master. P1 is secondary master. +001 = Non-combined. P0 is secondary master. P1 is primary master. +100 = Combined. P0 is primary master. P1 is primary slave. IDE is secondary; Primary IDE channel +disabled. +101 = Combined. P0 is primary slave. P1 is primary master. IDE is secondary. +110 = Combined. IDE is primary. P0 is secondary master. P1 is secondary slave; Secondary IDE +channel disabled. +111 = Combined. IDE is primary. P0 is secondary slave. P1 is secondary master. +*/ + +#define ICH5_SATA_ADDRESS_MAP 0 + + +#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 ACPI_CNTL 0x44 +#define BIOS_CNTL 0x4E +#define GPIO_BASE 0x58 +#define GPIO_CNTL 0x5C +#define PIRQA_ROUT 0x60 +#define PIRQE_ROUT 0x68 +#define COM_DEC 0xE0 +#define LPC_EN 0xE6 +#define FUNC_DIS 0xF2 + +/* 1e f0 244e */ + +#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 + +#define RTC_FAILED (1 <<2) + + +#define SMBUS_IO_BASE 0x1000 + +#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 + +/* Between 1-10 seconds, We should never timeout normally + * Longer than this is just painful when a timeout condition occurs. + */ +#define SMBUS_TIMEOUT (100*1000) + +#endif /* I82801ER_H */ diff --git a/src/southbridge/intel/i82801er/i82801er_ac97.c b/src/southbridge/intel/i82801er/i82801er_ac97.c new file mode 100644 index 0000000000..d16ab84fd9 --- /dev/null +++ b/src/southbridge/intel/i82801er/i82801er_ac97.c @@ -0,0 +1,41 @@ +/* + * (C) 2003 Linux Networx + */ +#include <console/console.h> +#include <device/device.h> +#include <device/pci.h> +#include <device/pci_ids.h> +#include <device/pci_ops.h> +#include "i82801er.h" + + +static struct device_operations ac97audio_ops = { + .read_resources = pci_dev_read_resources, + .set_resources = pci_dev_set_resources, + .enable_resources = pci_dev_enable_resources, + .enable = i82801er_enable, + .init = 0, + .scan_bus = 0, +}; + +static struct pci_driver ac97audio_driver __pci_driver = { + .ops = &ac97audio_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_82801ER_1F5, +}; + + +static struct device_operations ac97modem_ops = { + .read_resources = pci_dev_read_resources, + .set_resources = pci_dev_set_resources, + .enable_resources = pci_dev_enable_resources, + .enable = i82801er_enable, + .init = 0, + .scan_bus = 0, +}; + +static struct pci_driver ac97modem_driver __pci_driver = { + .ops = &ac97modem_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_82801ER_1F6, +}; diff --git a/src/southbridge/intel/i82801er/i82801er_early_smbus.c b/src/southbridge/intel/i82801er/i82801er_early_smbus.c new file mode 100644 index 0000000000..ed014f1a86 --- /dev/null +++ b/src/southbridge/intel/i82801er/i82801er_early_smbus.c @@ -0,0 +1,156 @@ + +//#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 + +/* Between 1-10 seconds, We should never timeout normally + * Longer than this is just painful when a timeout condition occurs. + */ +#define SMBUS_TIMEOUT (100*1000*10) + +static void enable_smbus(void) +{ + device_t dev; + dev = pci_locate_device(PCI_ID(0x8086, 0x24d3), 0); + if (dev == PCI_DEV_INVALID) { + die("SMBUS controller not found\r\n"); + } + + print_debug("SMBus controller enabled\r\n"); + /* set smbus iobase */ + pci_write_config32(dev, 0x20, SMBUS_IO_BASE | 1); + /* Set smbus enable */ + pci_write_config8(dev, 0x40, 0x01); + /* Set smbus iospace enable */ + pci_write_config16(dev, 0x4, 0x01); + /* Disable interrupt generation */ + outb(0, SMBUS_IO_BASE + SMBHSTCTL); + /* clear any lingering errors, so the transaction will run */ + outb(inb(SMBUS_IO_BASE + SMBHSTSTAT), SMBUS_IO_BASE + SMBHSTSTAT); +} + + +static inline void smbus_delay(void) +{ + outb(0x80, 0x80); +} + +static int smbus_wait_until_ready(void) +{ + unsigned long loops; + loops = SMBUS_TIMEOUT; + do { + unsigned char val; + smbus_delay(); + val = inb(SMBUS_IO_BASE + SMBHSTSTAT); + if ((val & 1) == 0) { + break; + } + if(loops == (SMBUS_TIMEOUT / 2)) { + outb(inb(SMBUS_IO_BASE + SMBHSTSTAT), + SMBUS_IO_BASE + SMBHSTSTAT); + } + } while(--loops); + return loops?0:-2; +} + +static int smbus_wait_until_done(void) +{ + unsigned long loops; + loops = SMBUS_TIMEOUT; + do { + unsigned char val; + smbus_delay(); + + val = inb(SMBUS_IO_BASE + SMBHSTSTAT); + if ( (val & 1) == 0) { + break; + } + if ((val & ~((1<<6)|(1<<0)) ) != 0 ) { + break; + } + } while(--loops); + return loops?0:-3; +} + +static int smbus_read_byte(unsigned device, unsigned address) +{ + unsigned char global_control_register; + unsigned char global_status_register; + unsigned char byte; + + if (smbus_wait_until_ready() < 0) { + return -2; + } + + /* setup transaction */ + /* disable interrupts */ + outb(inb(SMBUS_IO_BASE + SMBHSTCTL) & 0xfe, 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 a byte read, with interrupts disabled */ + outb((inb(SMBUS_IO_BASE + SMBHSTCTL) | 0x40), SMBUS_IO_BASE + SMBHSTCTL); + + + /* poll for transaction completion */ + if (smbus_wait_until_done() < 0) { + return -3; + } + + global_status_register = inb(SMBUS_IO_BASE + SMBHSTSTAT) & ~(1<<6); /* Ignore the In Use Status... */ + + /* read results of transaction */ + byte = inb(SMBUS_IO_BASE + SMBHSTDAT0); + + if (global_status_register != 2) { + return -1; + } + return byte; +} +#if 0 +static void smbus_write_byte(unsigned device, unsigned address, unsigned char val) +{ + if (smbus_wait_until_ready() < 0) { + return; + } + + /* by LYH */ + outb(0x37,SMBUS_IO_BASE + SMBHSTSTAT); + /* set the device I'm talking too */ + outw(((device & 0x7f) << 1) | 0, SMBUS_IO_BASE + SMBHSTADDR); + + /* data to send */ + outb(val, SMBUS_IO_BASE + SMBHSTDAT); + + outb(address & 0xFF, SMBUS_IO_BASE + SMBHSTCMD); + + /* start the command */ + outb(0xa, SMBUS_IO_BASE + SMBHSTCTL); + + /* poll for transaction completion */ + smbus_wait_until_done(); + return; +} +#endif diff --git a/src/southbridge/intel/i82801er/i82801er_ide.c b/src/southbridge/intel/i82801er/i82801er_ide.c new file mode 100644 index 0000000000..b33a0b0f09 --- /dev/null +++ b/src/southbridge/intel/i82801er/i82801er_ide.c @@ -0,0 +1,53 @@ +#include <console/console.h> +#include <device/device.h> +#include <device/pci.h> +#include <device/pci_ids.h> +#include <device/pci_ops.h> +#include "i82801er.h" + + +static void ide_init(struct device *dev) +{ +#if ICH5_SATA_ADDRESS_MAP<=1 + /* Enable ide devices so the linux ide driver will work */ + uint16_t word; + uint8_t byte; + int enable_a=1, enable_b=1; + + + word = pci_read_config16(dev, 0x40); + word &= ~((1 << 15)); + if (enable_a) { + /* Enable first ide interface */ + word |= (1<<15); + printk_debug("IDE0 "); + } + pci_write_config16(dev, 0x40, word); + + word = pci_read_config16(dev, 0x42); + word &= ~((1 << 15)); + if (enable_a) { + /* Enable secondary ide interface */ + word |= (1<<15); + printk_debug("IDE1 "); + } + pci_write_config16(dev, 0x42, word); +#endif + +} + +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 = i82801er_enable, +}; + +static struct pci_driver ide_driver __pci_driver = { + .ops = &ide_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_82801ER_1F1, +}; + diff --git a/src/southbridge/intel/i82801er/i82801er_lpc.c b/src/southbridge/intel/i82801er/i82801er_lpc.c new file mode 100644 index 0000000000..c1ee7410ed --- /dev/null +++ b/src/southbridge/intel/i82801er/i82801er_lpc.c @@ -0,0 +1,219 @@ +/* + * (C) 2003 Linux Networx, SuSE Linux AG + * (C) 2004 Tyan Computer + */ +#include <console/console.h> +#include <device/device.h> +#include <device/pci.h> +#include <device/pci_ids.h> +#include <device/pci_ops.h> +#include <device/chip.h> +#include <pc80/mc146818rtc.h> +#include "i82801er.h" + +void isa_dma_init(void); /* from /pc80/isa-dma.c */ + +#define NMI_OFF 0 + +void i82801er_enable_ioapic( struct device *dev) +{ + uint32_t dword; + volatile uint32_t *ioapic_sba = (volatile uint32_t *)0xfec00000; + volatile uint32_t *ioapic_sbd = (volatile uint32_t *)0xfec00010; + + dword = pci_read_config32(dev, GEN_CNTL); + dword |= (3 << 7); /* enable ioapic */ + dword |= (1 <<13); /* coprocessor error enable */ + dword |= (1 << 1); /* delay transaction enable */ + dword |= (1 << 2); /* DMA collection buf enable */ + pci_write_config32(dev, GEN_CNTL, dword); + printk_debug("ioapic southbridge enabled %x\n",dword); + *ioapic_sba=0; + *ioapic_sbd=(2<<24); + //lyh *ioapic_sba=3; + //lyh *ioapic_sbd=1; + *ioapic_sba=0; + dword=*ioapic_sbd; + printk_debug("Southbridge apic id = %x\n",dword); + if(dword!=(2<<24)) + for(;;); + //lyh *ioapic_sba=3; + //lyh dword=*ioapic_sbd; + //lyh printk_debug("Southbridge apic DT = %x\n",dword); + //lyh if(dword!=1) + //lyh for(;;); + + +} +void i82801er_enable_serial_irqs( struct device *dev) +{ + pci_write_config8(dev, SERIRQ_CNTL, (1 << 7)|(1 << 6)|((21 - 17) << 2)|(0<< 0)); +} +void i82801er_lpc_route_dma( struct device *dev, uint8_t mask) +{ + uint16_t word; + int i; + word = pci_read_config8(dev, PCI_DMA_CFG); + word &= ((1 << 10) - (1 << 8)); + for(i = 0; i < 8; i++) { + if (i == 4) + continue; + word |= ((mask & (1 << i))? 3:1) << (i*2); + } + pci_write_config16(dev, PCI_DMA_CFG, word); +} +void i82801er_rtc_init(struct device *dev) +{ + uint8_t byte; + uint32_t dword; + int rtc_failed; + byte = pci_read_config8(dev, GEN_PMCON_3); + rtc_failed = byte & RTC_FAILED; + if (rtc_failed) { + byte &= ~(1 << 1); /* preserve the power fail state */ + pci_write_config8(dev, GEN_PMCON_3, byte); + } + dword = pci_read_config32(dev, GEN_STS); + rtc_failed |= dword & (1 << 2); + rtc_init(rtc_failed); +} + + +void i82801er_1f0_misc(struct device *dev) +{ + pci_write_config16(dev, PCICMD, 0x014f); + pci_write_config32(dev, PMBASE, 0x00001001); + pci_write_config8(dev, ACPI_CNTL, 0x10); + pci_write_config32(dev, GPIO_BASE, 0x00001181); + pci_write_config8(dev, GPIO_CNTL, 0x10); + pci_write_config32(dev, PIRQA_ROUT, 0x0A05030B); + pci_write_config8(dev, PIRQE_ROUT, 0x07); + pci_write_config8(dev, RTC_CONF, 0x04); + pci_write_config8(dev, COM_DEC, 0x10); //lyh E0-> + pci_write_config16(dev, LPC_EN, 0x000F); //LYH 000D-> +} + +static void enable_hpet(struct device *dev) +{ + const unsigned long hpet_address = 0xfed0000; + + uint32_t dword; + uint32_t code = (0 & 0x3); + + dword = pci_read_config32(dev, GEN_CNTL); + dword |= (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*/ + + dword &= ~(3 << 15); /* clear it */ + dword |= (code<<15); + + printk_debug("enabling HPET @0x%x\n", hpet_address | (code <<12) ); +} + +static void lpc_init(struct device *dev) +{ + uint8_t byte; + int pwr_on=-1; + int nmi_option; + + /* IO APIC initialization */ + i82801er_enable_ioapic(dev); + + i82801er_enable_serial_irqs(dev); + + /* posted memory write enable */ + byte = pci_read_config8(dev, 0x46); + pci_write_config8(dev, 0x46, byte | (1<<0)); + + /* 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 after power fail\n", pwr_on?"on":"off"); +#if 0 + /* Enable Error reporting */ + /* Set up sync flood detected */ + byte = pci_read_config8(dev, 0x47); + byte |= (1 << 1); + pci_write_config8(dev, 0x47, byte); +#endif + + /* Set up NMI on errors */ + byte = pci_read_config8(dev, 0x61); + byte |= (1 << 3); /* IOCHK# NMI Enable */ + byte |= (1 << 6); /* PCI SERR# Enable */ + pci_write_config8(dev, 0x61, byte); + byte = pci_read_config8(dev, 0x70); + nmi_option = NMI_OFF; + get_option(&nmi_option, "nmi"); + if (nmi_option) { + byte |= (1 << 7); /* set NMI */ + pci_write_config8(dev, 0x70, byte); + } + + /* Initialize the real time clock */ + i82801er_rtc_init(dev); + + i82801er_lpc_route_dma(dev, 0xff); + + /* Initialize isa dma */ + isa_dma_init(); + + i82801er_1f0_misc(dev); + /* Initialize the High Precision Event Timers */ + enable_hpet(dev); +} + +static void i82801er_lpc_read_resources(device_t dev) +{ + unsigned int reg; + + /* Get the normal pci resources of this device */ + pci_dev_read_resources(dev); + + /* Find my place in the resource list */ + reg = dev->resources; + + /* Add an extra subtractive resource for both memory and I/O */ + dev->resource[reg].base = 0; + dev->resource[reg].size = 0; + dev->resource[reg].align = 0; + dev->resource[reg].gran = 0; + dev->resource[reg].limit = 0; + dev->resource[reg].flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE | IORESOURCE_ASSIGNED; + dev->resource[reg].index = 0; + reg++; + + dev->resource[reg].base = 0; + dev->resource[reg].size = 0; + dev->resource[reg].align = 0; + dev->resource[reg].gran = 0; + dev->resource[reg].limit = 0; + dev->resource[reg].flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE | IORESOURCE_ASSIGNED; + dev->resource[reg].index = 0; + reg++; + + dev->resources = reg; +} + +static struct device_operations lpc_ops = { + .read_resources = i82801er_lpc_read_resources, + .set_resources = pci_dev_set_resources, + .enable_resources = pci_dev_enable_resources, + .init = lpc_init, + .scan_bus = scan_static_bus, + .enable = i82801er_enable, +}; + +static struct pci_driver lpc_driver __pci_driver = { + .ops = &lpc_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_82801ER_1F0, +}; diff --git a/src/southbridge/intel/i82801er/i82801er_nic.c b/src/southbridge/intel/i82801er/i82801er_nic.c new file mode 100644 index 0000000000..4815cf19e0 --- /dev/null +++ b/src/southbridge/intel/i82801er/i82801er_nic.c @@ -0,0 +1,21 @@ +#include <console/console.h> +#include <device/device.h> +#include <device/pci.h> +#include <device/pci_ids.h> +#include <device/pci_ops.h> +#include "i82801er.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 nic_driver __pci_driver = { + .ops = &nic_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = 0x1051, +}; diff --git a/src/southbridge/intel/i82801er/i82801er_pci.c b/src/southbridge/intel/i82801er/i82801er_pci.c new file mode 100644 index 0000000000..201cedb1a9 --- /dev/null +++ b/src/southbridge/intel/i82801er/i82801er_pci.c @@ -0,0 +1,33 @@ +#include <console/console.h> +#include <device/device.h> +#include <device/pci.h> +#include <device/pci_ids.h> +#include <device/pci_ops.h> +#include "i82801er.h" + +static void pci_init(struct device *dev) +{ + /* Enable pci error detecting */ + uint32_t dword; + /* System error enable */ + dword = pci_read_config32(dev, 0x04); + dword |= (1<<8); /* SERR# Enable */ + dword |= (1<<6); /* Parity Error Response */ + pci_write_config32(dev, 0x04, dword); + +} + +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 pci_driver __pci_driver = { + .ops = &pci_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_82801ER_1E0, +}; + diff --git a/src/southbridge/intel/i82801er/i82801er_reset.c b/src/southbridge/intel/i82801er/i82801er_reset.c new file mode 100644 index 0000000000..3d7a4b79b6 --- /dev/null +++ b/src/southbridge/intel/i82801er/i82801er_reset.c @@ -0,0 +1,7 @@ +#include <arch/io.h> + +void hard_reset(void) +{ + /* Try rebooting through port 0xcf9 */ + outb((0 <<3)|(1<<2)|(1<<1), 0xcf9); +} diff --git a/src/southbridge/intel/i82801er/i82801er_sata.c b/src/southbridge/intel/i82801er/i82801er_sata.c new file mode 100644 index 0000000000..b00231e459 --- /dev/null +++ b/src/southbridge/intel/i82801er/i82801er_sata.c @@ -0,0 +1,75 @@ +#include <console/console.h> +#include <device/device.h> +#include <device/pci.h> +#include <device/pci_ids.h> +#include <device/pci_ops.h> +#include "i82801er.h" + +static void sata_init(struct device *dev) +{ + + uint16_t word; + uint8_t byte; + int enable_c=1, enable_d=1; + int i; + + //Enable Serial ATA port + byte = pci_read_config8(dev,0x90); + byte &= 0xf8; + byte |= ICH5_SATA_ADDRESS_MAP & 7; + pci_write_config8(dev,0x90,byte); + +// for(i=0;i<10;i++) { + word = pci_read_config16(dev,0x92); + word &= 0xfffc; +// if( (word & 0x0003) == 0x0003) break; + word |= 0x0003; // enable P0/P1 + pci_write_config16(dev,0x92,word); +// } + +// for(i=0;i<10;i++) { + /* enable ide0 */ + word = pci_read_config16(dev, 0x40); + word &= ~(1 << 15); + if(enable_c==0) { +// if( (word & 0x8000) == 0x0000) break; + word |= 0x0000; + } + else { +// if( (word & 0x8000) == 0x8000) break; + word |= 0x8000; + } + pci_write_config16(dev, 0x40, word); +// } + /* enable ide1 */ +// for(i=0;i<10;i++) { + word = pci_read_config16(dev, 0x42); + word &= ~(1 << 15); + if(enable_d==0) { +// if( (word & 0x8000) == 0x0000) break; + word |= 0x0000; + } + else { +// if( (word & 0x8000) == 0x8000) break; + word |= 0x8000; + } + pci_write_config16(dev, 0x42, word); +// } + +} + +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 = i82801er_enable, +}; + +static struct pci_driver stat_driver __pci_driver = { + .ops = &sata_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_82801ER_1F2_R, +}; + diff --git a/src/southbridge/intel/i82801er/i82801er_smbus.c b/src/southbridge/intel/i82801er/i82801er_smbus.c new file mode 100644 index 0000000000..fd06871234 --- /dev/null +++ b/src/southbridge/intel/i82801er/i82801er_smbus.c @@ -0,0 +1,92 @@ +#include <smbus.h> +#include <pci.h> +#include <arch/io.h> + +#define PM_BUS 0 +#define PM_DEVFN PCI_DEVFN(0x1f,3) + +#define SMBUS_IO_BASE 0x1000 +#define SMBHSTSTAT 0 +#define SMBHSTCTL 2 +#define SMBHSTCMD 3 +#define SMBHSTADD 4 +#define SMBHSTDAT0 5 +#define SMBHSTDAT1 6 +#define SMBBLKDAT 7 + +void smbus_enable(void) +{ + unsigned char byte; + /* iobase addr */ + pcibios_write_config_dword(PM_BUS, PM_DEVFN, 0x20, SMBUS_IO_BASE | 1); + /* smbus enable */ + pcibios_write_config_byte(PM_BUS, PM_DEVFN, 0x40, 1); + /* iospace enable */ + pcibios_write_config_word(PM_BUS, PM_DEVFN, 0x4, 1); + + /* Disable interrupt generation */ + outb(0, SMBUS_IO_BASE + SMBHSTCTL); + +} + +void smbus_setup(void) +{ + outb(0, SMBUS_IO_BASE + SMBHSTSTAT); +} + +static void smbus_wait_until_ready(void) +{ + while((inb(SMBUS_IO_BASE + SMBHSTSTAT) & 1) == 1) { + /* nop */ + } +} + +static void smbus_wait_until_done(void) +{ + unsigned char byte; + do { + byte = inb(SMBUS_IO_BASE + SMBHSTSTAT); + } + while((byte &1) == 1); + while( (byte & ~1) == 0) { + byte = inb(SMBUS_IO_BASE + SMBHSTSTAT); + } +} + +int smbus_read_byte(unsigned device, unsigned address, unsigned char *result) +{ + unsigned char host_status_register; + unsigned char byte; + + smbus_wait_until_ready(); + + /* 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 + SMBHSTADD); + /* 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 */ + smbus_wait_until_done(); + + host_status_register = inb(SMBUS_IO_BASE + SMBHSTSTAT); + + /* read results of transaction */ + byte = inb(SMBUS_IO_BASE + SMBHSTDAT0); + + *result = byte; + return host_status_register != 0x02; +} diff --git a/src/southbridge/intel/i82801er/i82801er_usb.c b/src/southbridge/intel/i82801er/i82801er_usb.c new file mode 100644 index 0000000000..49c6263add --- /dev/null +++ b/src/southbridge/intel/i82801er/i82801er_usb.c @@ -0,0 +1,54 @@ +#include <console/console.h> +#include <device/device.h> +#include <device/pci.h> +#include <device/pci_ids.h> +#include <device/pci_ops.h> +#include "i82801er.h" + +static void usb_init(struct device *dev) +{ + uint32_t cmd; + +#if 0 + printk_debug("USB: Setting up controller.. "); + cmd = pci_read_config32(dev, PCI_COMMAND); + pci_write_config32(dev, PCI_COMMAND, + cmd | PCI_COMMAND_IO | PCI_COMMAND_MEMORY | + PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE); + + + printk_debug("done.\n"); +#endif + +} + +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 = i82801er_enable, +}; + +static struct pci_driver usb_driver_1 __pci_driver = { + .ops = &usb_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_82801ER_1D0, +}; +static struct pci_driver usb_driver_2 __pci_driver = { + .ops = &usb_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_82801ER_1D1, +}; +static struct pci_driver usb_driver_3 __pci_driver = { + .ops = &usb_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_82801ER_1D2, +}; +static struct pci_driver usb_driver_4 __pci_driver = { + .ops = &usb_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_82801ER_1D3, +}; + diff --git a/src/southbridge/intel/i82801er/i82801er_usb2.c b/src/southbridge/intel/i82801er/i82801er_usb2.c new file mode 100644 index 0000000000..551d4ed3e0 --- /dev/null +++ b/src/southbridge/intel/i82801er/i82801er_usb2.c @@ -0,0 +1,39 @@ +//2003 Copywright Tyan + +#include <console/console.h> +#include <device/device.h> +#include <device/pci.h> +#include <device/pci_ids.h> +#include <device/pci_ops.h> +#include "i82801er.h" + +static void usb2_init(struct device *dev) +{ + uint32_t cmd; + +#if 0 + printk_debug("USB: Setting up controller.. "); + cmd = pci_read_config32(dev, PCI_COMMAND); + pci_write_config32(dev, PCI_COMMAND, + cmd | PCI_COMMAND_IO | PCI_COMMAND_MEMORY | + PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE); + + + printk_debug("done.\n"); +#endif +} + +static struct device_operations usb2_ops = { + .read_resources = pci_dev_read_resources, + .set_resources = pci_dev_set_resources, + .enable_resources = pci_dev_enable_resources, + .init = usb2_init, + .scan_bus = 0, + .enable = i82801er_enable, +}; + +static struct pci_driver usb2_driver __pci_driver = { + .ops = &usb2_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_82801ER_1D7, +}; diff --git a/src/southbridge/intel/i82870/82870.h b/src/southbridge/intel/i82870/82870.h new file mode 100644 index 0000000000..f9289d4027 --- /dev/null +++ b/src/southbridge/intel/i82870/82870.h @@ -0,0 +1,10 @@ +/* for io apic 1461 */ +#define PCICMD 0x04 +#define SUBSYS 0x2c +#define MBAR 0x10 +#define ABAR 0x40 + +/* for pci bridge 1460 */ +#define MTT 0x042 +#define HCCR 0x0f0 +#define ACNF 0x0e0 diff --git a/src/southbridge/intel/i82870/Config.lb b/src/southbridge/intel/i82870/Config.lb new file mode 100644 index 0000000000..e6a96517f0 --- /dev/null +++ b/src/southbridge/intel/i82870/Config.lb @@ -0,0 +1,3 @@ +driver p64h2_ioapic.o +driver p64h2_pcibridge.o +#driver p64h2_pci_parity.o diff --git a/src/southbridge/intel/i82870/p64h2_ioapic.c b/src/southbridge/intel/i82870/p64h2_ioapic.c new file mode 100644 index 0000000000..e2bb33883d --- /dev/null +++ b/src/southbridge/intel/i82870/p64h2_ioapic.c @@ -0,0 +1,89 @@ +#include <console/console.h> +#include <device/device.h> +#include <device/pci.h> +#include <device/pci_ids.h> +#include <device/pci_ops.h> +#include <pc80/mc146818rtc.h> +#include "82870.h" + +static int ioapic_no = 0; + +static void p64h2_ioapic_enable(device_t dev) +{ + uint32_t dword; + uint16_t word; + + /* We have to enable MEM and Bus Master for IOAPIC */ + word = 0x0146; + pci_write_config16(dev, PCICMD, word); + dword = 0x358015d9; + pci_write_config32(dev, SUBSYS, dword); + + +} + +static void p64h2_ioapic_init(device_t dev) +{ + uint32_t dword; + uint16_t word; + int i, addr; + + volatile uint32_t *ioapic_a; /* io apic io memory space command address */ + volatile uint32_t *ioapic_d; /* io apic io memory space data address */ + + i = ioapic_no++; + + if(i<3) /* io apic address numbers are 3,4,5,&8 */ + addr=i+3; + else + addr=i+5; + /* Read the MBAR address for setting up the io apic in io memory space */ + dword = pci_read_config32(dev, PCI_BASE_ADDRESS_0); + ioapic_a = (uint32_t *) dword; + ioapic_d = ioapic_a +0x04; + printk_debug("IOAPIC %d at %02x:%02x.%01x MBAR = %x DataAddr = %x\n", + addr, dev->bus->secondary, + PCI_SLOT(dev->path.u.pci.devfn), PCI_FUNC(dev->path.u.pci.devfn), + ioapic_a, ioapic_d); + +#if 0 + dword = (u32)ioapic_a; + word = 0x8000 + ((dword >>8)&0x0fff); + pci_write_config_word(dev, ABAR, word); +#endif + /* Set up the io apic for the p64h2 - 1461 */ + *ioapic_a=0; + *ioapic_d=(addr<<24); /* Set the address number */ + *ioapic_a=3; + *ioapic_d=1; /* Enable the io apic */ + + /* This code test the setup to see if we really found the io apic */ + *ioapic_a=0; + dword=*ioapic_d; + printk_debug("PCI %d apic id = %x\n",addr,dword); + if(dword!=(addr<<24)) + for(;;); + *ioapic_a=3; + dword=*ioapic_d; + printk_debug("PCI %d apic DT = %x\n",addr,dword); + if(dword!=1) + for(;;); + + +} + +static struct device_operations ioapic_ops = { + .read_resources = pci_dev_read_resources, + .set_resources = pci_dev_set_resources, + .enable_resources = pci_dev_enable_resources, + .init = p64h2_ioapic_init, + .scan_bus = 0, + .enable = p64h2_ioapic_enable, +}; + +static struct pci_driver ioapic_driver __pci_driver = { + .ops = &ioapic_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_82870_1E0, + +}; diff --git a/src/southbridge/intel/i82870/p64h2_pci_parity.c b/src/southbridge/intel/i82870/p64h2_pci_parity.c new file mode 100644 index 0000000000..d80f9213c9 --- /dev/null +++ b/src/southbridge/intel/i82870/p64h2_pci_parity.c @@ -0,0 +1,26 @@ +#include <mem.h> +#include <pci.h> +#include <arch/io.h> +#include <printk.h> +# + +void p64h2_pci_parity_enable(void) +{ + uint8_t reg; + + /* 2SERREN - SERR enable for PCI bridge secondary device */ + /* 2PEREN - Parity error for PCI bridge secondary device */ + pcibios_read_config_byte(1, ((29 << 3) + (0 << 0)), 0x3e, ®); + reg |= ((1 << 1) + (1 << 0)); + pcibios_write_config_byte(1, ((29 << 3) + (0 << 0)), 0x3e, reg); + + /* 2SERREN - SERR enable for PCI bridge secondary device */ + /* 2PEREN - Parity error for PCI bridge secondary device */ + pcibios_read_config_byte(1, ((31 << 3) + (0 << 0)), 0x3e, ®); + reg |= ((1 << 1) + (1 << 0)); + pcibios_write_config_byte(1, ((31 << 3) + (0 << 0)), 0x3e, reg); + + return; +} + + diff --git a/src/southbridge/intel/i82870/p64h2_pcibridge.c b/src/southbridge/intel/i82870/p64h2_pcibridge.c new file mode 100644 index 0000000000..6f161e900b --- /dev/null +++ b/src/southbridge/intel/i82870/p64h2_pcibridge.c @@ -0,0 +1,39 @@ +#include <console/console.h> +#include <device/device.h> +#include <device/pci.h> +#include <device/pci_ids.h> +#include <device/pci_ops.h> +#include <pc80/mc146818rtc.h> +#include "82870.h" + +static void p64h2_pcix_init(device_t dev) +{ + uint32_t dword; + uint16_t word; + uint8_t byte; + + + /* The purpose of changes to HCCR, ACNF, and MTT is to speed up the + PCI bus for cards having high speed transfers. */ + dword = 0xc2040002; + pci_write_config32(dev, HCCR, dword); + dword = 0x0000c3bf; + pci_write_config32(dev, ACNF, dword); + byte = 0x08; + pci_write_config8(dev, MTT, byte); + +} +static struct device_operations pcix_ops = { + .read_resources = pci_bus_read_resources, + .set_resources = pci_dev_set_resources, + .enable_resources = pci_bus_enable_resources, + .init = p64h2_pcix_init, + .scan_bus = pci_scan_bridge, +}; + +static struct pci_driver pcix_driver __pci_driver = { + .ops = &pcix_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_82870_1F0, +}; + |