From 526855741b6abb970024366316b941fb6b3d2cb6 Mon Sep 17 00:00:00 2001 From: Eric Biederman Date: Mon, 19 May 2003 19:16:21 +0000 Subject: - Cleanups on the romcc side including a pci interface that uses fewer registers, and is easier to hardcode. git-svn-id: svn://svn.coreboot.org/coreboot/trunk@838 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1 --- src/southbridge/amd/amd8111/amd8111_acpi.c | 53 ++++++++++++ src/southbridge/amd/amd8111/amd8111_ide.c | 65 ++++++++++++++ src/southbridge/amd/amd8111/amd8111_lpc.c | 130 ++++++++++++++++++++++++++++ src/southbridge/amd/amd8111/amd8111_smbus.c | 96 ++++++++++++++++++++ src/southbridge/amd/amd8111/amd8111_usb.c | 34 ++++++++ 5 files changed, 378 insertions(+) create mode 100644 src/southbridge/amd/amd8111/amd8111_acpi.c create mode 100644 src/southbridge/amd/amd8111/amd8111_ide.c create mode 100644 src/southbridge/amd/amd8111/amd8111_lpc.c create mode 100644 src/southbridge/amd/amd8111/amd8111_smbus.c create mode 100644 src/southbridge/amd/amd8111/amd8111_usb.c (limited to 'src/southbridge/amd') diff --git a/src/southbridge/amd/amd8111/amd8111_acpi.c b/src/southbridge/amd/amd8111/amd8111_acpi.c new file mode 100644 index 0000000000..120e0ee426 --- /dev/null +++ b/src/southbridge/amd/amd8111/amd8111_acpi.c @@ -0,0 +1,53 @@ +#include +#include +#include +#include +#include + +static void acpi_init(struct device *dev) +{ + uint8_t byte; + uint16_t word; + +#if 0 + printk_debug("ACPI: disabling NMI watchdog.. "); + pci_read_config_byte(dev, 0x49, &byte); + pci_write_config_byte(dev, 0x49, byte | (1<<2)); + + + pci_read_config_byte(dev, 0x41, &byte); + pci_write_config_byte(dev, 0x41, byte | (1<<6)|(1<<2)); + + /* added from sourceforge */ + pci_read_config_byte(dev, 0x48, &byte); + pci_write_config_byte(dev, 0x48, byte | (1<<3)); + + printk_debug("done.\n"); + + + printk_debug("ACPI: Routing IRQ 12 to PS2 port.. "); + pci_read_config_word(dev, 0x46, &word); + pci_write_config_word(dev, 0x46, word | (1<<9)); + printk_debug("done.\n"); + + + printk_debug("ACPI: setting PM class code.. "); + pci_write_config_dword(dev, 0x60, 0x06800000); + printk_debug("done.\n"); +#endif + +} + +static struct device_operations acpi_ops = { + .read_resources = pci_dev_read_resources, + .set_resources = pci_dev_set_resources, + .init = acpi_init, + .scan_bus = 0, +}; + +static struct pci_driver acpi_driver __pci_driver = { + .ops = &acpi_ops, + .vendor = PCI_VENDOR_ID_AMD, + .device = PCI_DEVICE_ID_AMD_8111_ACPI, +}; + diff --git a/src/southbridge/amd/amd8111/amd8111_ide.c b/src/southbridge/amd/amd8111/amd8111_ide.c new file mode 100644 index 0000000000..f351606989 --- /dev/null +++ b/src/southbridge/amd/amd8111/amd8111_ide.c @@ -0,0 +1,65 @@ +#include +#include +#include +#include +#include + +static void ide_init(struct device *dev) +{ + + /* Enable ide devices so the linux ide driver will work */ + uint16_t word; + int enable_a=1, enable_b=1; + + + printk_debug("ide_init\n"); + + pci_read_config_word(dev, 0x40, &word); + /* Ensure prefetch is disabled */ + word &= ~((1 << 15) | (1 << 13)); + if (enable_b) { + /* Enable secondary ide interface */ + word |= (1<<0); + printk_debug("IDE1 "); + } + if (enable_a) { + /* Enable primary ide interface */ + word |= (1<<1); + printk_debug("IDE0 "); + } + + word |= (1<<12); + word |= (1<<14); + + pci_write_config_word(dev, 0x40, word); + + word = 0x0f; + pci_write_config_word(dev, 0x42, word); + + /* The AMD768 has a bug where the BM DMA address must be + * 256 byte aligned while it is only 16 bytes long. + * Hard code this to a valid address below 0x1000 + * where automatic port address assignment starts. + * FIXME: I assume the 8111 does the same thing. We should + * clarify. stepan@suse.de + */ + pci_write_config_dword(dev, 0x20, 0xf01); + + pci_write_config_dword(dev, 0x48, 0x205e5e5e); + word = 0x06a; + pci_write_config_word(dev, 0x4c, word); +} + +static struct device_operations ide_ops = { + .read_resources = pci_dev_read_resources, + .set_resources = pci_dev_set_resources, + .init = ide_init, + .scan_bus = 0, +}; + +static struct pci_driver ide_driver __pci_driver = { + .ops = &ide_ops, + .vendor = PCI_VENDOR_ID_AMD, + .device = PCI_DEVICE_ID_AMD_8111_IDE, +}; + diff --git a/src/southbridge/amd/amd8111/amd8111_lpc.c b/src/southbridge/amd/amd8111/amd8111_lpc.c new file mode 100644 index 0000000000..d8b4ba1b77 --- /dev/null +++ b/src/southbridge/amd/amd8111/amd8111_lpc.c @@ -0,0 +1,130 @@ +#include +#include +#include +#include +#include + + +struct ioapicreg { + unsigned int reg; + unsigned int value_low, value_high; +}; + +static struct ioapicreg ioapicregvalues[] = { +#define ALL (0xff << 24) +#define NONE (0) +#define DISABLED (1 << 16) +#define ENABLED (0 << 16) +#define TRIGGER_EDGE (0 << 15) +#define TRIGGER_LEVEL (1 << 15) +#define POLARITY_HIGH (0 << 13) +#define POLARITY_LOW (1 << 13) +#define PHYSICAL_DEST (0 << 11) +#define LOGICAL_DEST (1 << 11) +#define ExtINT (7 << 8) +#define NMI (4 << 8) +#define SMI (2 << 8) +#define INT (1 << 8) + /* mask, trigger, polarity, destination, delivery, vector */ + {0x00, ENABLED | TRIGGER_EDGE | POLARITY_HIGH | PHYSICAL_DEST | ExtINT | 0, 0}, + {0x01, DISABLED, NONE}, + {0x02, ENABLED | TRIGGER_EDGE | POLARITY_HIGH | PHYSICAL_DEST | INT | 0, 0}, + {0x03, DISABLED, NONE}, + {0x04, DISABLED, NONE}, + {0x05, DISABLED, NONE}, + {0x06, DISABLED, NONE}, + {0x07, DISABLED, NONE}, + {0x08, DISABLED, NONE}, + {0x09, DISABLED, NONE}, + {0x0a, DISABLED, NONE}, + {0x0b, DISABLED, NONE}, + {0x0c, DISABLED, NONE}, + {0x0d, DISABLED, NONE}, + {0x0e, DISABLED, NONE}, + {0x0f, DISABLED, NONE}, + {0x10, DISABLED, NONE}, + {0x11, DISABLED, NONE}, + {0x12, DISABLED, NONE}, + {0x13, DISABLED, NONE}, + {0x14, DISABLED, NONE}, + {0x14, DISABLED, NONE}, + {0x15, DISABLED, NONE}, + {0x16, DISABLED, NONE}, + {0x17, DISABLED, NONE}, + {0x18, DISABLED, NONE}, + {0x19, DISABLED, NONE}, + {0x20, DISABLED, NONE}, + {0x21, DISABLED, NONE}, + {0x22, DISABLED, NONE}, + {0x23, DISABLED, NONE}, +}; + +static void setup_ioapic(void) +{ + int i; + unsigned long value_low, value_high; + unsigned long ioapic_base = 0xfec00000; + volatile unsigned long *l; + struct ioapicreg *a = ioapicregvalues; + + l = (unsigned long *) ioapic_base; + for (i = 0; i < sizeof(ioapicregvalues) / sizeof(ioapicregvalues[0]); + i++, a++) { + l[0] = (a->reg * 2) + 0x10; + l[4] = a->value_low; + value_low = l[4]; + l[0] = (a->reg *2) + 0x11; + l[4] = a->value_high; + value_high = l[4]; + if ((i==0) && (value_low == 0xffffffff)) { + printk_warning("IO APIC not responding.\n"); + return; + } + printk_spew("for IRQ, reg 0x%08x value 0x%08x 0x%08x\n", + a->reg, a->value_low, a->value_high); + } +} + +static void lpc_init(struct device *dev) +{ + uint8_t byte; + int pwr_on=-1; + + printk_debug("lpc_init\n"); + +#if 0 + /* IO APIC initialization */ + pci_read_config_byte(dev, 0x4B, &byte); + byte |= 1; + pci_write_config_byte(dev, 0x4B, byte); + setup_ioapic(); +#endif + + /* posted memory write enable */ + pci_read_config_byte(dev, 0x46, &byte); + pci_write_config_byte(dev, 0x46, byte | (1<<0)); + + /* power after power fail */ + pci_read_config_byte(dev, 0x43, &byte); + if (pwr_on) { + byte &= ~(1<<6); + } else { + byte |= (1<<6); + } + pci_write_config_byte(dev, 0x43, byte); + + +} + +static struct device_operations lpc_ops = { + .read_resources = pci_dev_read_resources, + .set_resources = pci_dev_set_resources, + .init = lpc_init, + .scan_bus = 0, +}; + +static struct pci_driver lpc_driver __pci_driver = { + .ops = &lpc_ops, + .vendor = PCI_VENDOR_ID_AMD, + .device = PCI_DEVICE_ID_AMD_8111_ISA, +}; diff --git a/src/southbridge/amd/amd8111/amd8111_smbus.c b/src/southbridge/amd/amd8111/amd8111_smbus.c new file mode 100644 index 0000000000..4b938d1eb7 --- /dev/null +++ b/src/southbridge/amd/amd8111/amd8111_smbus.c @@ -0,0 +1,96 @@ +#include +#include +#include + +#define PM_BUS 0 +#define PM_DEVFN (AMD8111_DEVFN+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; +#if 0 + /* iobase addr */ + pcibios_write_config_dword(PM_BUS, PM_DEVFN, 0x90, SMBUS_IO_BASE | 1); + /* smbus enable */ + pcibios_write_config_byte(PM_BUS, PM_DEVFN, 0xd2, (0x4 << 1) | 1); + /* iospace enable */ + pcibios_write_config_word(PM_BUS, PM_DEVFN, 0x4, 1); +#endif + /* Set PMIOEN, leaving default address 0xDD00 in 0x58 */ + byte=pcibios_read_config_byte(0,PCI_DEVFN(0x7,3), 0x41); + pcibios_write_config_byte(0,PCI_DEVFN(0x7,3), byte | 0x80 ); + + + /* cont reading 207 */ +} + +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/amd/amd8111/amd8111_usb.c b/src/southbridge/amd/amd8111/amd8111_usb.c new file mode 100644 index 0000000000..a6d3c4e9e1 --- /dev/null +++ b/src/southbridge/amd/amd8111/amd8111_usb.c @@ -0,0 +1,34 @@ +#include +#include +#include +#include +#include + +static void usb_init(struct device *dev) +{ + uint32_t cmd; + + printk_debug("USB: Setting up controller.. "); + pci_read_config_dword(dev, PCI_COMMAND, &cmd); + pci_write_config_dword(dev, PCI_COMMAND, + cmd | PCI_COMMAND_IO | PCI_COMMAND_MEMORY | + PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE); + + + printk_debug("done.\n"); + +} + +static struct device_operations usb_ops = { + .read_resources = pci_dev_read_resources, + .set_resources = pci_dev_set_resources, + .init = usb_init, + .scan_bus = 0, +}; + +static struct pci_driver usb_driver __pci_driver = { + .ops = &usb_ops, + .vendor = PCI_VENDOR_ID_AMD, + .device = PCI_DEVICE_ID_AMD_8111_USB, +}; + -- cgit v1.2.3