diff options
Diffstat (limited to 'src/southbridge/intel/i82801dx')
-rw-r--r-- | src/southbridge/intel/i82801dx/Kconfig | 2 | ||||
-rw-r--r-- | src/southbridge/intel/i82801dx/Makefile.inc | 9 | ||||
-rw-r--r-- | src/southbridge/intel/i82801dx/chip.h | 27 | ||||
-rw-r--r-- | src/southbridge/intel/i82801dx/cmos_failover.c | 16 | ||||
-rw-r--r-- | src/southbridge/intel/i82801dx/i82801dx.c | 65 | ||||
-rw-r--r-- | src/southbridge/intel/i82801dx/i82801dx.h | 163 | ||||
-rw-r--r-- | src/southbridge/intel/i82801dx/i82801dx_ac97.c | 41 | ||||
-rw-r--r-- | src/southbridge/intel/i82801dx/i82801dx_early_smbus.c | 180 | ||||
-rw-r--r-- | src/southbridge/intel/i82801dx/i82801dx_ide.c | 53 | ||||
-rw-r--r-- | src/southbridge/intel/i82801dx/i82801dx_lpc.c | 226 | ||||
-rw-r--r-- | src/southbridge/intel/i82801dx/i82801dx_nic.c | 21 | ||||
-rw-r--r-- | src/southbridge/intel/i82801dx/i82801dx_pci.c | 33 | ||||
-rw-r--r-- | src/southbridge/intel/i82801dx/i82801dx_reset.c | 7 | ||||
-rw-r--r-- | src/southbridge/intel/i82801dx/i82801dx_sata.c | 75 | ||||
-rw-r--r-- | src/southbridge/intel/i82801dx/i82801dx_smbus.c | 95 | ||||
-rw-r--r-- | src/southbridge/intel/i82801dx/i82801dx_usb.c | 49 | ||||
-rw-r--r-- | src/southbridge/intel/i82801dx/i82801dx_usb2.c | 40 |
17 files changed, 1102 insertions, 0 deletions
diff --git a/src/southbridge/intel/i82801dx/Kconfig b/src/southbridge/intel/i82801dx/Kconfig new file mode 100644 index 0000000000..6a35691b5d --- /dev/null +++ b/src/southbridge/intel/i82801dx/Kconfig @@ -0,0 +1,2 @@ +config SOUTHBRIDGE_INTEL_I82801DX + bool diff --git a/src/southbridge/intel/i82801dx/Makefile.inc b/src/southbridge/intel/i82801dx/Makefile.inc new file mode 100644 index 0000000000..7167e1d391 --- /dev/null +++ b/src/southbridge/intel/i82801dx/Makefile.inc @@ -0,0 +1,9 @@ +driver-y += i82801dx.o +driver-y += i82801dx_usb.o +driver-y += i82801dx_lpc.o +driver-y += i82801dx_ide.o +driver-y += i82801dx_usb2.o +driver-y += i82801dx_ac97.o +#driver-y += i82801dx_nic.o +#driver-y += i82801dx_pci.o +obj-y += i82801dx_reset.o diff --git a/src/southbridge/intel/i82801dx/chip.h b/src/southbridge/intel/i82801dx/chip.h new file mode 100644 index 0000000000..fdbb7d2d0d --- /dev/null +++ b/src/southbridge/intel/i82801dx/chip.h @@ -0,0 +1,27 @@ +#ifndef I82801DX_CHIP_H +#define I82801DX_CHIP_H + +struct southbridge_intel_i82801dx_config +{ + int enable_usb; + int enable_native_ide; + /** + * Interrupt Routing configuration + * If bit7 is 1, the interrupt is disabled. + */ + uint8_t pirqa_routing; + uint8_t pirqb_routing; + uint8_t pirqc_routing; + uint8_t pirqd_routing; + uint8_t pirqe_routing; + uint8_t pirqf_routing; + uint8_t pirqg_routing; + uint8_t pirqh_routing; + + uint8_t ide0_enable; + uint8_t ide1_enable; +}; + +extern struct chip_operations southbridge_intel_i82801dx_ops; + +#endif /* I82801DBM_CHIP_H */ diff --git a/src/southbridge/intel/i82801dx/cmos_failover.c b/src/southbridge/intel/i82801dx/cmos_failover.c new file mode 100644 index 0000000000..4821fad3d2 --- /dev/null +++ b/src/southbridge/intel/i82801dx/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 |= CONFIG_MAX_REBOOT_CNT << 4; + cmos_write(byte, RTC_BOOT_BYTE); + } +} diff --git a/src/southbridge/intel/i82801dx/i82801dx.c b/src/southbridge/intel/i82801dx/i82801dx.c new file mode 100644 index 0000000000..abfd8c21cf --- /dev/null +++ b/src/southbridge/intel/i82801dx/i82801dx.c @@ -0,0 +1,65 @@ +#include <console/console.h> +#include <device/device.h> +#include <device/pci.h> +#include <device/pci_ids.h> +#include "i82801dx.h" + +void i82801dx_enable(device_t dev) +{ + unsigned int index = 0; + uint8_t bHasDisableBit = 0; + uint16_t cur_disable_mask, new_disable_mask; + +// all 82801dbm devices are in bus 0 + unsigned int devfn = PCI_DEVFN(0x1f, 0); // lpc + device_t lpc_dev = dev_find_slot(0, devfn); // 0 + if (!lpc_dev) + return; + + // Calculate disable bit position for specified device:function + // NOTE: For ICH-4, only the following devices can be disabled: + // D31: F0, F1, F3, F5, F6, + // D29: F0, F1, F2, F7 + + if (PCI_SLOT(dev->path.pci.devfn) == 31) { + index = PCI_FUNC(dev->path.pci.devfn); + + switch (index) { + case 0: + case 1: + case 3: + case 5: + case 6: + bHasDisableBit = 1; + break; + + default: + break; + }; + + if (index == 0) + index = 14; // D31:F0 bit is an exception + + } else if (PCI_SLOT(dev->path.pci.devfn) == 29) { + index = 8 + PCI_FUNC(dev->path.pci.devfn); + + if ((PCI_FUNC(dev->path.pci.devfn) < 3) || (PCI_FUNC(dev->path.pci.devfn) == 7)) + bHasDisableBit = 1; + } + + if (bHasDisableBit) { + 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 (new_disable_mask != cur_disable_mask) { + pci_write_config16(lpc_dev, FUNC_DIS, new_disable_mask); + } + } +} + +struct chip_operations southbridge_intel_i82801dx_ops = { + CHIP_NAME("Intel ICH4/ICH4-M (82801Dx) Series Southbridge") + .enable_dev = i82801dx_enable, +}; diff --git a/src/southbridge/intel/i82801dx/i82801dx.h b/src/southbridge/intel/i82801dx/i82801dx.h new file mode 100644 index 0000000000..d4e1aa0928 --- /dev/null +++ b/src/southbridge/intel/i82801dx/i82801dx.h @@ -0,0 +1,163 @@ +/* the problem: we have 82801dbm support in fb1, and 82801er in fb2. + * fb1 code is what we want, fb2 structure is needed however. + * so we need to get fb1 code for 82801dbm into fb2 structure. + */ +/* What I did: took the 80801er stuff from fb2, verify it against the + * db stuff in fb1, and made sure it was right. + */ + +#ifndef I82801DX_H +#define I82801DX_H + +#if !defined( __ROMCC__ ) && !defined(__PRE_RAM__) +#include "chip.h" +extern void i82801dx_enable(device_t dev); +#endif + +#define MAINBOARD_POWER_OFF 0 +#define MAINBOARD_POWER_ON 1 +#define MAINBOARD_POWER_KEEP 2 + +#ifndef CONFIG_MAINBOARD_POWER_ON_AFTER_POWER_FAIL +#define CONFIG_MAINBOARD_POWER_ON_AFTER_POWER_FAIL MAINBOARD_POWER_ON +#endif + +/* +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 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 PMBASE_ADDR 0x0400 +#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) + +#define PM1_STS 0x00 +#define WAK_STS (1 << 15) +#define PCIEXPWAK_STS (1 << 14) +#define PRBTNOR_STS (1 << 11) +#define RTC_STS (1 << 10) +#define PWRBTN_STS (1 << 8) +#define GBL_STS (1 << 5) +#define BM_STS (1 << 4) +#define TMROF_STS (1 << 0) +#define PM1_EN 0x02 +#define PCIEXPWAK_DIS (1 << 14) +#define RTC_EN (1 << 10) +#define PWRBTN_EN (1 << 8) +#define GBL_EN (1 << 5) +#define TMROF_EN (1 << 0) +#define PM1_CNT 0x04 +#define SLP_EN (1 << 13) +#define SLP_TYP (7 << 10) +#define GBL_RLS (1 << 2) +#define BM_RLD (1 << 1) +#define SCI_EN (1 << 0) +#define PM1_TMR 0x08 +#define PROC_CNT 0x10 +#define LV2 0x14 +#define LV3 0x15 +#define LV4 0x16 +#define PM2_CNT 0x20 // mobile only +#define GPE0_STS 0x28 +#define PME_B0_STS (1 << 13) +#define USB3_STS (1 << 12) +#define PME_STS (1 << 11) +#define BATLOW_STS (1 << 10) +#define GST_STS (1 << 9) +#define RI_STS (1 << 8) +#define SMB_WAK_STS (1 << 7) +#define TCOSCI_STS (1 << 6) +#define AC97_STS (1 << 5) +#define USB2_STS (1 << 4) +#define USB1_STS (1 << 3) +#define SWGPE_STS (1 << 2) +#define HOT_PLUG_STS (1 << 1) +#define THRM_STS (1 << 0) +#define GPE0_EN 0x2c +#define PME_B0_EN (1 << 13) +#define PME_EN (1 << 11) +#define SMI_EN 0x30 +#define EL_SMI_EN (1 << 25) // Intel Quick Resume Technology +#define INTEL_USB2_EN (1 << 18) // Intel-Specific USB2 SMI logic +#define LEGACY_USB2_EN (1 << 17) // Legacy USB2 SMI logic +#define PERIODIC_EN (1 << 14) // SMI on PERIODIC_STS in SMI_STS +#define TCO_EN (1 << 13) // Enable TCO Logic (BIOSWE et al) +#define MCSMI_EN (1 << 11) // Trap microcontroller range access +#define BIOS_RLS (1 << 7) // asserts SCI on bit set +#define SWSMI_TMR_EN (1 << 6) // start software smi timer on bit set +#define APMC_EN (1 << 5) // Writes to APM_CNT cause SMI# +#define SLP_SMI_EN (1 << 4) // Write to SLP_EN in PM1_CNT asserts SMI# +#define LEGACY_USB_EN (1 << 3) // Legacy USB circuit SMI logic +#define BIOS_EN (1 << 2) // Assert SMI# on setting GBL_RLS bit +#define EOS (1 << 1) // End of SMI (deassert SMI#) +#define GBL_SMI_EN (1 << 0) // SMI# generation at all? +#define SMI_STS 0x34 +#define ALT_GP_SMI_EN 0x38 +#define ALT_GP_SMI_STS 0x3a +#define GPE_CNTL 0x42 +#define DEVACT_STS 0x44 +#define SS_CNT 0x50 +#define C3_RES 0x54 + +#define TCOBASE 0x60 /* TCO Base Address Register */ +#define TCO1_CNT 0x08 /* TCO1 Control Register */ + +#endif /* I82801DX_H */ diff --git a/src/southbridge/intel/i82801dx/i82801dx_ac97.c b/src/southbridge/intel/i82801dx/i82801dx_ac97.c new file mode 100644 index 0000000000..752449865d --- /dev/null +++ b/src/southbridge/intel/i82801dx/i82801dx_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 "i82801dx.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 = i82801dx_enable, + .init = 0, + .scan_bus = 0, +}; + +static const struct pci_driver ac97audio_driver __pci_driver = { + .ops = &ac97audio_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_82801DBM_AC97_AUDIO, +}; + + +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 = i82801dx_enable, + .init = 0, + .scan_bus = 0, +}; + +static const struct pci_driver ac97modem_driver __pci_driver = { + .ops = &ac97modem_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_82801DBM_AC97_MODEM, +}; diff --git a/src/southbridge/intel/i82801dx/i82801dx_early_smbus.c b/src/southbridge/intel/i82801dx/i82801dx_early_smbus.c new file mode 100644 index 0000000000..0a0ff91f34 --- /dev/null +++ b/src/southbridge/intel/i82801dx/i82801dx_early_smbus.c @@ -0,0 +1,180 @@ + +//#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 = PCI_DEV(0x0, 0x1f, 0x3); + + 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_active(void) +{ + unsigned long loops; + loops = SMBUS_TIMEOUT; + do { + unsigned char val; + smbus_delay(); + val = inb(SMBUS_IO_BASE + SMBHSTSTAT); + if ((val & 1)) { + break; + } + } while(--loops); + return loops?0:-4; +} + +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; + + /*print_err("smbus_read_byte\r\n");*/ + if (smbus_wait_until_ready() < 0) { + print_err_hex8(-2); + 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 it to start */ + if (smbus_wait_until_active() < 0) { + print_err_hex8(-4); + return -4; + } + + /* poll for transaction completion */ + if (smbus_wait_until_done() < 0) { + print_err_hex8(-3); + 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) { + print_err_hex8(-1); + return -1; + } +/* + print_err("smbus_read_byte: "); + print_err_hex32(device); print_err(" ad "); print_err_hex32(address); + print_err("value "); print_err_hex8(byte); print_err("\r\n"); + */ + 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/i82801dx/i82801dx_ide.c b/src/southbridge/intel/i82801dx/i82801dx_ide.c new file mode 100644 index 0000000000..bb3510783d --- /dev/null +++ b/src/southbridge/intel/i82801dx/i82801dx_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 "i82801dx.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_b) { + /* 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 = i82801dx_enable, +}; + +static const struct pci_driver ide_driver __pci_driver = { + .ops = &ide_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_82801DBM_IDE, +}; + diff --git a/src/southbridge/intel/i82801dx/i82801dx_lpc.c b/src/southbridge/intel/i82801dx/i82801dx_lpc.c new file mode 100644 index 0000000000..59225d2c9a --- /dev/null +++ b/src/southbridge/intel/i82801dx/i82801dx_lpc.c @@ -0,0 +1,226 @@ +/* + * (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 <pc80/mc146818rtc.h> +#include <pc80/isa-dma.h> +#include <arch/io.h> +#include "i82801dx.h" + + + +#define NMI_OFF 0 + +void i82801dx_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)) + die(""); + //lyh *ioapic_sba=3; + //lyh dword=*ioapic_sbd; + //lyh printk_debug("Southbridge apic DT = %x\n",dword); + //lyh if(dword!=1) + //lyh die(""); + + +} +void i82801dx_enable_serial_irqs( struct device *dev) +{ + pci_write_config8(dev, SERIRQ_CNTL, (1 << 7)|(1 << 6)|((21 - 17) << 2)|(0<< 0)); +} +void i82801dx_lpc_route_dma( struct device *dev, uint8_t mask) +{ + uint16_t word; + int i; + word = pci_read_config16(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 i82801dx_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 i82801dx_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 */ + i82801dx_enable_ioapic(dev); + + i82801dx_enable_serial_irqs(dev); + +#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 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 = 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 */ + i82801dx_rtc_init(dev); + + i82801dx_lpc_route_dma(dev, 0xff); + + /* Initialize isa dma */ + isa_dma_init(); + + i82801dx_1f0_misc(dev); + /* Initialize the High Precision Event Timers */ + enable_hpet(dev); +} + +static void i82801dx_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->base = 0; + res->size = 0x1000; + res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE | + IORESOURCE_ASSIGNED | IORESOURCE_FIXED; + + res = new_resource(dev, IOINDEX_SUBTRACTIVE(1, 0)); + res->base = 0xff800000; + res->size = 0x00800000; /* 8 MB for flash */ + res->flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE | + IORESOURCE_ASSIGNED | IORESOURCE_FIXED; + + res = new_resource(dev, 3); /* IOAPIC */ + res->base = 0xfec00000; + res->size = 0x00001000; + res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED | IORESOURCE_FIXED; +} + +static void i82801dx_lpc_enable_resources(device_t dev) +{ + pci_dev_enable_resources(dev); + enable_childrens_resources(dev); +} + +static struct device_operations lpc_ops = { + .read_resources = i82801dx_lpc_read_resources, + .set_resources = pci_dev_set_resources, + .enable_resources = i82801dx_lpc_enable_resources, + .init = lpc_init, + .scan_bus = scan_static_bus, + .enable = i82801dx_enable, +}; + +static const struct pci_driver lpc_driver __pci_driver = { + .ops = &lpc_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_82801DBM_LPC, +}; diff --git a/src/southbridge/intel/i82801dx/i82801dx_nic.c b/src/southbridge/intel/i82801dx/i82801dx_nic.c new file mode 100644 index 0000000000..6221ba4889 --- /dev/null +++ b/src/southbridge/intel/i82801dx/i82801dx_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 "i82801dx.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 const struct pci_driver nic_driver __pci_driver = { + .ops = &nic_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = 0x103a, +}; diff --git a/src/southbridge/intel/i82801dx/i82801dx_pci.c b/src/southbridge/intel/i82801dx/i82801dx_pci.c new file mode 100644 index 0000000000..0c88bf2827 --- /dev/null +++ b/src/southbridge/intel/i82801dx/i82801dx_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 "i82801dx.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 const struct pci_driver pci_driver __pci_driver = { + .ops = &pci_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_82801DBM_PCI, +}; + diff --git a/src/southbridge/intel/i82801dx/i82801dx_reset.c b/src/southbridge/intel/i82801dx/i82801dx_reset.c new file mode 100644 index 0000000000..3d7a4b79b6 --- /dev/null +++ b/src/southbridge/intel/i82801dx/i82801dx_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/i82801dx/i82801dx_sata.c b/src/southbridge/intel/i82801dx/i82801dx_sata.c new file mode 100644 index 0000000000..22c6cd77fd --- /dev/null +++ b/src/southbridge/intel/i82801dx/i82801dx_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 "i82801dx.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 = i82801dx_enable, +}; + +static const struct pci_driver stat_driver __pci_driver = { + .ops = &sata_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_82801DBM_SATA, +}; + diff --git a/src/southbridge/intel/i82801dx/i82801dx_smbus.c b/src/southbridge/intel/i82801dx/i82801dx_smbus.c new file mode 100644 index 0000000000..e56a67c1e0 --- /dev/null +++ b/src/southbridge/intel/i82801dx/i82801dx_smbus.c @@ -0,0 +1,95 @@ +#include "i82801dx.h" +#include <smbus.h> +#include <pci.h> +#include <arch/io.h> + +#define PM_BUS 0 +#define PM_DEVFN PCI_DEVFN(0x1f,3) + +#if 0 +#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 +#endif + +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/i82801dx/i82801dx_usb.c b/src/southbridge/intel/i82801dx/i82801dx_usb.c new file mode 100644 index 0000000000..2e60193855 --- /dev/null +++ b/src/southbridge/intel/i82801dx/i82801dx_usb.c @@ -0,0 +1,49 @@ +#include <console/console.h> +#include <device/device.h> +#include <device/pci.h> +#include <device/pci_ids.h> +#include <device/pci_ops.h> +#include "i82801dx.h" + +static void usb_init(struct device *dev) +{ + + +#if 0 + uint32_t cmd; + 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 = i82801dx_enable, +}; + +static const struct pci_driver usb_driver_1 __pci_driver = { + .ops = &usb_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_82801DBM_USB1, +}; +static const struct pci_driver usb_driver_2 __pci_driver = { + .ops = &usb_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_82801DBM_USB2, +}; +static const struct pci_driver usb_driver_3 __pci_driver = { + .ops = &usb_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_82801DBM_USB3, +}; diff --git a/src/southbridge/intel/i82801dx/i82801dx_usb2.c b/src/southbridge/intel/i82801dx/i82801dx_usb2.c new file mode 100644 index 0000000000..ca13e92995 --- /dev/null +++ b/src/southbridge/intel/i82801dx/i82801dx_usb2.c @@ -0,0 +1,40 @@ +//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 "i82801dx.h" + +static void usb2_init(struct device *dev) +{ + + +#if 0 + uint32_t cmd; + 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 = i82801dx_enable, +}; + +static const struct pci_driver usb2_driver __pci_driver = { + .ops = &usb2_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_82801DBM_EHCI, +}; |