diff options
author | Eric Biederman <ebiederm@xmission.com> | 2004-10-21 10:44:08 +0000 |
---|---|---|
committer | Eric Biederman <ebiederm@xmission.com> | 2004-10-21 10:44:08 +0000 |
commit | dbec2d4090e40d1d8e1fd06e8d4180d3fa685d4d (patch) | |
tree | e813d3f9dea80d35cbc29d6bf35995fec0a06ab9 /src/southbridge/amd | |
parent | f3aa4707d3bef9f529a70a204dbc648968cf7c20 (diff) | |
download | coreboot-staging-dbec2d4090e40d1d8e1fd06e8d4180d3fa685d4d.zip coreboot-staging-dbec2d4090e40d1d8e1fd06e8d4180d3fa685d4d.tar.gz |
- Bump the LinuxBIOS major version
- Rename chip_config chip_operations throughout the tree
- Fix Config.lb on most of the Opteron Ports
- Fix the amd 8000 chipset support for setting the subsystem vendor and device ids
- Add detection of devices that are on the motherboard (i.e. In Config.lb)
- Baby step in getting the resource limit handling correct, Ignore fixed resources
- Only call enable_childrens_resources on devices we know will have children
For some busses like i2c it is non-sense and we don't want it.
- Set the resource limits for pnp devices resources.
- Improve the resource size detection for pnp devices.
- Added a configuration register to amd8111_ide.c so we can enable/disable individual ide channels
- Added a header file to hold the prototype of isa_dma_init
- Fixed most of the superio chips so the should work now, the via superio pci device is the exception.
- The code compiles and runs so it is time for me to go to bed.
git-svn-id: svn://svn.coreboot.org/coreboot/trunk@1698 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
Diffstat (limited to 'src/southbridge/amd')
-rw-r--r-- | src/southbridge/amd/amd8111/amd8111.c | 58 | ||||
-rw-r--r-- | src/southbridge/amd/amd8111/amd8111_ac97.c | 15 | ||||
-rw-r--r-- | src/southbridge/amd/amd8111/amd8111_acpi.c | 132 | ||||
-rw-r--r-- | src/southbridge/amd/amd8111/amd8111_early_smbus.c | 117 | ||||
-rw-r--r-- | src/southbridge/amd/amd8111/amd8111_enable_rom.c | 6 | ||||
-rw-r--r-- | src/southbridge/amd/amd8111/amd8111_ide.c | 18 | ||||
-rw-r--r-- | src/southbridge/amd/amd8111/amd8111_lpc.c | 44 | ||||
-rw-r--r-- | src/southbridge/amd/amd8111/amd8111_nic.c | 2 | ||||
-rw-r--r-- | src/southbridge/amd/amd8111/amd8111_pci.c | 5 | ||||
-rw-r--r-- | src/southbridge/amd/amd8111/amd8111_smbus.c | 126 | ||||
-rw-r--r-- | src/southbridge/amd/amd8111/amd8111_smbus.h | 224 | ||||
-rw-r--r-- | src/southbridge/amd/amd8111/amd8111_usb.c | 47 | ||||
-rw-r--r-- | src/southbridge/amd/amd8111/amd8111_usb2.c | 13 | ||||
-rw-r--r-- | src/southbridge/amd/amd8111/chip.h | 3 | ||||
-rw-r--r-- | src/southbridge/amd/amd8131/amd8131_bridge.c | 17 |
15 files changed, 501 insertions, 326 deletions
diff --git a/src/southbridge/amd/amd8111/amd8111.c b/src/southbridge/amd/amd8111/amd8111.c index a9b132c..6e7022c 100644 --- a/src/southbridge/amd/amd8111/amd8111.c +++ b/src/southbridge/amd/amd8111/amd8111.c @@ -9,31 +9,32 @@ void amd8111_enable(device_t dev) device_t lpc_dev; device_t bus_dev; unsigned index; - uint32_t dword; - uint16_t reg_old, reg; - uint8_t byte; - + unsigned reg_old, reg; /* See if we are on the behind the amd8111 pci bridge */ bus_dev = dev->bus->dev; if ((bus_dev->vendor == PCI_VENDOR_ID_AMD) && - (bus_dev->device == PCI_DEVICE_ID_AMD_8111_PCI)) { + (bus_dev->device == PCI_DEVICE_ID_AMD_8111_PCI)) + { unsigned devfn; devfn = bus_dev->path.u.pci.devfn + (1 << 3); lpc_dev = dev_find_slot(bus_dev->bus->secondary, devfn); index = ((dev->path.u.pci.devfn & ~7) >> 3) + 8; + if (dev->path.u.pci.devfn == 2) { /* EHCI */ + index = 16; + } } else { unsigned devfn; devfn = (dev->path.u.pci.devfn) & ~7; lpc_dev = dev_find_slot(dev->bus->secondary, devfn); index = dev->path.u.pci.devfn & 7; } - - if ((!lpc_dev) || (index >= 16)) { + if ((!lpc_dev) || (index >= 17)) { return; } if ((lpc_dev->vendor != PCI_VENDOR_ID_AMD) || - (lpc_dev->device != PCI_DEVICE_ID_AMD_8111_ISA)) { + (lpc_dev->device != PCI_DEVICE_ID_AMD_8111_ISA)) + { uint32_t id; id = pci_read_config32(lpc_dev, PCI_VENDOR_ID); if (id != (PCI_VENDOR_ID_AMD | (PCI_DEVICE_ID_AMD_8111_ISA << 16))) { @@ -41,34 +42,29 @@ void amd8111_enable(device_t dev) } } - /* Now read the vendor and device id */ - dword= pci_read_config32(dev, PCI_VENDOR_ID); -#if 0 - printk_debug(" %s dev->vendor= %04x, dev->device= %04x, id = %08x\n", dev_path(dev), dev->vendor, dev->device, dword); -#endif - - if (dword == (PCI_VENDOR_ID_AMD | (PCI_DEVICE_ID_AMD_8111_USB2 << 16))) { - if(!dev->enabled) { - byte = pci_read_config8(lpc_dev, 0x47); - byte |= (1<<7); - pci_write_config8(lpc_dev, 0x47, byte); - return; + if (index < 16) { + reg = reg_old = pci_read_config16(lpc_dev, 0x48); + reg &= ~(1 << index); + if (dev->enabled) { + reg |= (1 << index); + } + if (reg != reg_old) { + pci_write_config16(lpc_dev, 0x48, reg); } - - } - - reg = reg_old = pci_read_config16(lpc_dev, 0x48); - reg &= ~(1 << index); - if (dev->enabled) { - reg |= (1 << index); } - if (reg != reg_old) { - pci_write_config16(lpc_dev, 0x48, reg); + else if (index == 16) { + reg = reg_old = pci_read_config8(lpc_dev, 0x47); + reg &= ~(1 << 7); + if (!dev->enabled) { + reg |= (1 << 7); + } + if (reg != reg_old) { + pci_write_config8(lpc_dev, 0x47, reg); + } } - } struct chip_operations southbridge_amd_amd8111_ops = { - .name = "AMD 8111 Southbridge", + .name = "AMD 8111", .enable_dev = amd8111_enable, }; diff --git a/src/southbridge/amd/amd8111/amd8111_ac97.c b/src/southbridge/amd/amd8111/amd8111_ac97.c index 36ed41f..40f663d 100644 --- a/src/southbridge/amd/amd8111/amd8111_ac97.c +++ b/src/southbridge/amd/amd8111/amd8111_ac97.c @@ -8,14 +8,24 @@ #include <device/pci_ops.h> #include "amd8111.h" +static void lpci_set_subsystem(device_t dev, unsigned vendor, unsigned device) +{ + pci_write_config32(dev, 0x2c, + ((device & 0xffff) << 16) | (vendor & 0xffff)); +} + +static struct pci_operations lops_pci = { + .set_subsystem = lpci_set_subsystem, +}; 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 = amd8111_enable, + .enable = amd8111_enable, .init = 0, .scan_bus = 0, + .ops_pci = &lops_pci, }; static struct pci_driver ac97audio_driver __pci_driver = { @@ -29,9 +39,10 @@ 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 = amd8111_enable, + .enable = amd8111_enable, .init = 0, .scan_bus = 0, + .ops_pci = &lops_pci, }; static struct pci_driver ac97modem_driver __pci_driver = { diff --git a/src/southbridge/amd/amd8111/amd8111_acpi.c b/src/southbridge/amd/amd8111/amd8111_acpi.c index 557e54f..38c3269 100644 --- a/src/southbridge/amd/amd8111/amd8111_acpi.c +++ b/src/southbridge/amd/amd8111/amd8111_acpi.c @@ -3,10 +3,12 @@ #include <device/pci.h> #include <device/pci_ids.h> #include <device/pci_ops.h> +#include <device/smbus.h> #include <pc80/mc146818rtc.h> #include <bitops.h> #include <arch/io.h> #include "amd8111.h" +#include "amd8111_smbus.h" #define PREVIOUS_POWER_STATE 0x43 #define MAINBOARD_POWER_OFF 0 @@ -19,6 +21,51 @@ #endif +static int lsmbus_recv_byte(device_t dev) +{ + unsigned device; + struct resource *res; + + device = dev->path.u.i2c.device; + res = find_resource(dev->bus->dev, 0x20); + + return do_smbus_recv_byte(res->base, device); +} + +static int lsmbus_send_byte(device_t dev, uint8_t val) +{ + unsigned device; + struct resource *res; + + device = dev->path.u.i2c.device; + res = find_resource(dev->bus->dev, 0x20); + + return do_smbus_send_byte(res->base, device, val); +} + + +static int lsmbus_read_byte(device_t dev, uint8_t address) +{ + unsigned device; + struct resource *res; + + device = dev->path.u.i2c.device; + res = find_resource(dev->bus->dev, 0x20); + + return do_smbus_read_byte(res->base, device, address); +} + +static int lsmbus_write_byte(device_t dev, uint8_t address, uint8_t val) +{ + unsigned device; + struct resource *res; + + device = dev->path.u.i2c.device; + res = find_resource(dev->bus->dev, 0x20); + + return do_smbus_write_byte(res->base, device, address, val); +} + static void acpi_init(struct device *dev) { uint8_t byte; @@ -29,29 +76,26 @@ static void acpi_init(struct device *dev) #if 0 printk_debug("ACPI: disabling NMI watchdog.. "); - pci_read_config_byte(dev, 0x49, &byte); - pci_write_config_byte(dev, 0x49, byte | (1<<2)); + byte = pci_read_config8(dev, 0x49); + pci_write_config8(dev, 0x49, byte | (1<<2)); - pci_read_config_byte(dev, 0x41, &byte); - pci_write_config_byte(dev, 0x41, byte | (1<<6)|(1<<2)); + byte = pci_read_config8(dev, 0x41); + pci_write_config8(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)); + byte = pci_read_config8(dev, 0x48); + pci_write_config8(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)); + word = pci_read_config16(dev, 0x46); + pci_write_config16(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 on = MAINBOARD_POWER_ON_AFTER_POWER_FAIL; get_option(&on, "power_on_after_fail"); @@ -78,33 +122,63 @@ static void acpi_init(struct device *dev) static void acpi_read_resources(device_t dev) { + struct resource *resource; + /* Handle the generic bars */ pci_dev_read_resources(dev); - if ((dev->resources + 1) < MAX_RESOURCES) { - struct resource *resource = &dev->resource[dev->resources]; - dev->resources++; - resource->base = 0; - resource->size = 256; - resource->align = log2(256); - resource->gran = log2(256); - resource->limit = 65536; - resource->flags = IORESOURCE_IO; - resource->index = 0x58; - } - else { - printk_err("%s Unexpected resource shortage\n", - dev_path(dev)); - } + /* Add the ACPI/SMBUS bar */ + resource = new_resource(dev, 0x58); + resource->base = 0; + resource->size = 256; + resource->align = log2(256); + resource->gran = log2(256); + resource->limit = 65536; + resource->flags = IORESOURCE_IO; + resource->index = 0x58; } +static void acpi_enable_resources(device_t dev) +{ + uint8_t byte; + /* Enable the generic pci resources */ + pci_dev_enable_resources(dev); + + /* Enable the ACPI/SMBUS Bar */ + byte = pci_read_config8(dev, 0x41); + byte |= (1 << 7); + pci_write_config8(dev, 0x41, byte); + + /* Set the class code */ + pci_write_config32(dev, 0x60, 0x06800000); + +} + +static void lpci_set_subsystem(device_t dev, unsigned vendor, unsigned device) +{ + pci_write_config32(dev, 0x7c, + ((device & 0xffff) << 16) | (vendor & 0xffff)); +} + +static struct smbus_bus_operations lops_smbus_bus = { + .recv_byte = lsmbus_recv_byte, + .send_byte = lsmbus_send_byte, + .read_byte = lsmbus_read_byte, + .write_byte = lsmbus_write_byte, +}; +static struct pci_operations lops_pci = { + .set_subsystem = lpci_set_subsystem, +}; + static struct device_operations acpi_ops = { .read_resources = acpi_read_resources, .set_resources = pci_dev_set_resources, - .enable_resources = pci_dev_enable_resources, + .enable_resources = acpi_enable_resources, .init = acpi_init, - .scan_bus = 0, -// .enable = amd8111_enable, + .scan_bus = scan_static_bus, + .enable = amd8111_enable, + .ops_pci = &lops_pci, + .ops_smbus_bus = &lops_smbus_bus, }; static struct pci_driver acpi_driver __pci_driver = { diff --git a/src/southbridge/amd/amd8111/amd8111_early_smbus.c b/src/southbridge/amd/amd8111/amd8111_early_smbus.c index 5157609..8ad3589 100644 --- a/src/southbridge/amd/amd8111/amd8111_early_smbus.c +++ b/src/southbridge/amd/amd8111/amd8111_early_smbus.c @@ -1,13 +1,6 @@ -#define SMBUS_IO_BASE 0x0f00 - -#define SMBGSTATUS 0xe0 -#define SMBGCTL 0xe2 -#define SMBHSTADDR 0xe4 -#define SMBHSTDAT 0xe6 -#define SMBHSTCMD 0xe8 -#define SMBHSTFIFO 0xe9 +#include "amd8111_smbus.h" -#define SMBUS_TIMEOUT (100*1000*10) +#define SMBUS_IO_BASE 0x0f00 static void enable_smbus(void) { @@ -25,114 +18,22 @@ static void enable_smbus(void) outw(inw(SMBUS_IO_BASE + SMBGSTATUS), SMBUS_IO_BASE + SMBGSTATUS); } - -static inline void smbus_delay(void) -{ - outb(0x80, 0x80); -} - -static int smbus_wait_until_ready(void) +static int smbus_recv_byte(unsigned device) { - unsigned long loops; - loops = SMBUS_TIMEOUT; - do { - unsigned short val; - smbus_delay(); - val = inw(SMBUS_IO_BASE + SMBGSTATUS); - if ((val & 0x800) == 0) { - break; - } - if(loops == (SMBUS_TIMEOUT / 2)) { - outw(inw(SMBUS_IO_BASE + SMBGSTATUS), - SMBUS_IO_BASE + SMBGSTATUS); - } - } while(--loops); - return loops?0:-2; + return do_smbus_recv_byte(SMBUS_IO_BASE, device); } -static int smbus_wait_until_done(void) +static int smbus_send_byte(unsigned device, unsigned char val) { - unsigned long loops; - loops = SMBUS_TIMEOUT; - do { - unsigned short val; - smbus_delay(); - - val = inw(SMBUS_IO_BASE + SMBGSTATUS); - if (((val & 0x8) == 0) | ((val & 0x437) != 0)) { - break; - } - } while(--loops); - return loops?0:-3; + return do_smbus_send_byte(SMBUS_IO_BASE, device, val); } 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 */ - outw(inw(SMBUS_IO_BASE + SMBGCTL) & ~((1<<10)|(1<<9)|(1<<8)|(1<<4)), SMBUS_IO_BASE + SMBGCTL); - /* set the device I'm talking too */ - outw(((device & 0x7f) << 1) | 1, SMBUS_IO_BASE + SMBHSTADDR); - /* set the command/address... */ - outb(address & 0xFF, SMBUS_IO_BASE + SMBHSTCMD); - /* set up for a byte data read */ - outw((inw(SMBUS_IO_BASE + SMBGCTL) & ~7) | (0x2), SMBUS_IO_BASE + SMBGCTL); - - /* clear any lingering errors, so the transaction will run */ - /* Do I need to write the bits to a 1 to clear an error? */ - outw(inw(SMBUS_IO_BASE + SMBGSTATUS), SMBUS_IO_BASE + SMBGSTATUS); - - /* clear the data word...*/ - outw(0, SMBUS_IO_BASE + SMBHSTDAT); - - /* start the command */ - outw((inw(SMBUS_IO_BASE + SMBGCTL) | (1 << 3)), SMBUS_IO_BASE + SMBGCTL); - - - /* poll for transaction completion */ - if (smbus_wait_until_done() < 0) { - return -3; - } - - global_status_register = inw(SMBUS_IO_BASE + SMBGSTATUS); - - /* read results of transaction */ - byte = inw(SMBUS_IO_BASE + SMBHSTDAT) & 0xff; - - if (global_status_register != (1 << 4)) { - return -1; - } - return byte; + return do_smbus_read_byte(SMBUS_IO_BASE, device, address); } -static void smbus_write_byte(unsigned device, unsigned address, unsigned char val) +static int smbus_write_byte(unsigned device, unsigned address, unsigned char val) { - if (smbus_wait_until_ready() < 0) { - return; - } - - /* by LYH */ - outb(0x37,SMBUS_IO_BASE + SMBGSTATUS); - /* 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 + SMBGCTL); - - /* poll for transaction completion */ - smbus_wait_until_done(); - return; + return do_smbus_write_byte(SMBUS_IO_BASE, device, address, val); } diff --git a/src/southbridge/amd/amd8111/amd8111_enable_rom.c b/src/southbridge/amd/amd8111/amd8111_enable_rom.c index 468801a..8c4e4da 100644 --- a/src/southbridge/amd/amd8111/amd8111_enable_rom.c +++ b/src/southbridge/amd/amd8111/amd8111_enable_rom.c @@ -4,12 +4,12 @@ static void amd8111_enable_rom(void) unsigned char byte; device_t dev; - /* Enable 4MB rom access at 0xFFC00000 - 0xFFFFFFFF */ + /* Enable 5MB rom access at 0xFFB00000 - 0xFFFFFFFF */ /* Locate the amd8111 */ dev = pci_locate_device(PCI_ID(0x1022, 0x7468), 0); - /* Set the 4MB enable bit bit */ + /* Set the 5MB enable bits */ byte = pci_read_config8(dev, 0x43); - byte |= 0x80; + byte |= 0xC0; pci_write_config8(dev, 0x43, byte); } diff --git a/src/southbridge/amd/amd8111/amd8111_ide.c b/src/southbridge/amd/amd8111/amd8111_ide.c index a922746..1674844 100644 --- a/src/southbridge/amd/amd8111/amd8111_ide.c +++ b/src/southbridge/amd/amd8111/amd8111_ide.c @@ -7,21 +7,21 @@ static void ide_init(struct device *dev) { - + struct southbridge_amd_amd8111_config *conf; /* Enable ide devices so the linux ide driver will work */ uint16_t word; uint8_t byte; - int enable_a=1, enable_b=1; + conf = dev->chip_info; word = pci_read_config16(dev, 0x40); /* Ensure prefetch is disabled */ word &= ~((1 << 15) | (1 << 13)); - if (enable_b) { + if (conf->ide1_enable) { /* Enable secondary ide interface */ word |= (1<<0); printk_debug("IDE1 "); } - if (enable_a) { + if (conf->ide0_enable) { /* Enable primary ide interface */ word |= (1<<1); printk_debug("IDE0 "); @@ -40,12 +40,22 @@ static void ide_init(struct device *dev) pci_write_config16(dev, 0x42, word); } +static void lpci_set_subsystem(device_t dev, unsigned vendor, unsigned device) +{ + pci_write_config32(dev, 0x70, + ((device & 0xffff) << 16) | (vendor & 0xffff)); +} +static struct pci_operations lops_pci = { + .set_subsystem = lpci_set_subsystem, +}; 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 = amd8111_enable, + .ops_pci = &lops_pci }; static struct pci_driver ide_driver __pci_driver = { diff --git a/src/southbridge/amd/amd8111/amd8111_lpc.c b/src/southbridge/amd/amd8111/amd8111_lpc.c index 6441c86..b94b19b 100644 --- a/src/southbridge/amd/amd8111/amd8111_lpc.c +++ b/src/southbridge/amd/amd8111/amd8111_lpc.c @@ -7,10 +7,9 @@ #include <device/pci_ids.h> #include <device/pci_ops.h> #include <pc80/mc146818rtc.h> +#include <pc80/isa-dma.h> #include "amd8111.h" -void isa_dma_init(void); /* from /pc80/isa-dma.c */ - #define NMI_OFF 0 struct ioapicreg { @@ -85,7 +84,7 @@ static void setup_ioapic(void) return; } printk_spew("for IRQ, reg 0x%08x value 0x%08x 0x%08x\n", - a->reg, a->value_low, a->value_high); + a->reg, a->value_low, a->value_high); } } @@ -158,43 +157,36 @@ static void lpc_init(struct device *dev) static void amd8111_lpc_read_resources(device_t dev) { - unsigned int reg; + struct resource *res; /* 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++; + res = new_resource(dev, IOINDEX_SUBTRACTIVE(0, 0)); + res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE | IORESOURCE_ASSIGNED; - dev->resources = reg; + res = new_resource(dev, IOINDEX_SUBTRACTIVE(1, 0)); + res->flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE | IORESOURCE_ASSIGNED; } + +static void lpci_set_subsystem(device_t dev, unsigned vendor, unsigned device) +{ + pci_write_config32(dev, 0x70, + ((device & 0xffff) << 16) | (vendor & 0xffff)); +} +static struct pci_operations lops_pci = { + .set_subsystem = lpci_set_subsystem, +}; static struct device_operations lpc_ops = { .read_resources = amd8111_lpc_read_resources, .set_resources = pci_dev_set_resources, .enable_resources = pci_dev_enable_resources, .init = lpc_init, .scan_bus = scan_static_bus, -// .enable = amd8111_enable, + .enable = amd8111_enable, + .ops_pci = &lops_pci, }; static struct pci_driver lpc_driver __pci_driver = { diff --git a/src/southbridge/amd/amd8111/amd8111_nic.c b/src/southbridge/amd/amd8111/amd8111_nic.c index 512b268..b379208 100644 --- a/src/southbridge/amd/amd8111/amd8111_nic.c +++ b/src/southbridge/amd/amd8111/amd8111_nic.c @@ -13,7 +13,7 @@ static struct device_operations nic_ops = { .read_resources = pci_dev_read_resources, .set_resources = pci_dev_set_resources, .enable_resources = pci_dev_enable_resources, -// .enable = amd8111_enable, + .enable = amd8111_enable, .init = 0, .scan_bus = 0, }; diff --git a/src/southbridge/amd/amd8111/amd8111_pci.c b/src/southbridge/amd/amd8111/amd8111_pci.c index 29d3fb8..9fe1f98 100644 --- a/src/southbridge/amd/amd8111/amd8111_pci.c +++ b/src/southbridge/amd/amd8111/amd8111_pci.c @@ -45,12 +45,17 @@ static void pci_init(struct device *dev) pci_write_config32(dev, 0x1c, dword); } +static struct pci_operations lops_pci = { + .set_subsystem = 0, +}; + 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, + .ops_pci = &lops_pci, }; static struct pci_driver pci_driver __pci_driver = { diff --git a/src/southbridge/amd/amd8111/amd8111_smbus.c b/src/southbridge/amd/amd8111/amd8111_smbus.c index bfa78b3..2fec77b 100644 --- a/src/southbridge/amd/amd8111/amd8111_smbus.c +++ b/src/southbridge/amd/amd8111/amd8111_smbus.c @@ -1,96 +1,42 @@ -#include <smbus.h> -#include <pci.h> +/* + * (C) 2004 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 <device/chip.h> +#include <device/smbus.h> #include <arch/io.h> +#include "amd8111.h" -#define PM_BUS 0 -#define PM_DEVFN PCI_DEVFN(0x7,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) +static void lpci_set_subsystem(device_t dev, unsigned vendor, unsigned device) { - unsigned char byte; - do { - byte = inb(SMBUS_IO_BASE + SMBHSTSTAT); - } - while((byte &1) == 1); - while( (byte & ~1) == 0) { - byte = inb(SMBUS_IO_BASE + SMBHSTSTAT); - } + pci_write_config32(dev, 0x44, + ((device & 0xffff) << 16) | (vendor & 0xffff)); } -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; -} +static struct smbus_bus_operations lops_smbus_bus = { + /* I haven't seen the 2.0 SMBUS controller used yet. */ +}; +static struct pci_operations lops_pci = { + .set_subsystem = lpci_set_subsystem, +}; +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 = amd8111_enable, + .ops_pci = &lops_pci, + .ops_smbus_bus = &lops_smbus_bus, +}; + +static struct pci_driver smbus_driver __pci_driver = { + .ops = &smbus_ops, + .vendor = PCI_VENDOR_ID_AMD, + .device = PCI_DEVICE_ID_AMD_8111_SMB, +}; diff --git a/src/southbridge/amd/amd8111/amd8111_smbus.h b/src/southbridge/amd/amd8111/amd8111_smbus.h new file mode 100644 index 0000000..b579966 --- /dev/null +++ b/src/southbridge/amd/amd8111/amd8111_smbus.h @@ -0,0 +1,224 @@ +#include <device/smbus_def.h> + +#define SMBGSTATUS 0xe0 +#define SMBGCTL 0xe2 +#define SMBHSTADDR 0xe4 +#define SMBHSTDAT 0xe6 +#define SMBHSTCMD 0xe8 +#define SMBHSTFIFO 0xe9 + +#define SMBUS_TIMEOUT (100*1000*10) +#define SMBUS_STATUS_MASK 0xfbff + +static inline void smbus_delay(void) +{ + outb(0x80, 0x80); +} + +static int smbus_wait_until_ready(unsigned smbus_io_base) +{ + unsigned long loops; + loops = SMBUS_TIMEOUT; + do { + unsigned short val; + smbus_delay(); + val = inw(smbus_io_base + SMBGSTATUS); + if ((val & 0x800) == 0) { + break; + } + if(loops == (SMBUS_TIMEOUT / 2)) { + outw(inw(smbus_io_base + SMBGSTATUS), + smbus_io_base + SMBGSTATUS); + } + } while(--loops); + return loops?0:SMBUS_WAIT_UNTIL_READY_TIMEOUT; +} + +static int smbus_wait_until_done(unsigned smbus_io_base) +{ + unsigned long loops; + loops = SMBUS_TIMEOUT; + do { + unsigned short val; + smbus_delay(); + + val = inw(smbus_io_base + SMBGSTATUS); + if (((val & 0x8) == 0) | ((val & 0x0037) != 0)) { + break; + } + } while(--loops); + return loops?0:SMBUS_WAIT_UNTIL_DONE_TIMEOUT; +} + +static int do_smbus_recv_byte(unsigned smbus_io_base, unsigned device) +{ + unsigned global_status_register; + unsigned byte; + + if (smbus_wait_until_ready(smbus_io_base) < 0) { + return SMBUS_WAIT_UNTIL_READY_TIMEOUT; + } + + /* setup transaction */ + /* disable interrupts */ + outw(inw(smbus_io_base + SMBGCTL) & ~((1<<10)|(1<<9)|(1<<8)|(1<<4)), smbus_io_base + SMBGCTL); + /* set the device I'm talking too */ + outw(((device & 0x7f) << 1) | 1, smbus_io_base + SMBHSTADDR); + /* set the command/address... */ + outb(0, smbus_io_base + SMBHSTCMD); + /* set up for a send byte */ + outw((inw(smbus_io_base + SMBGCTL) & ~7) | (0x1), smbus_io_base + SMBGCTL); + + /* clear any lingering errors, so the transaction will run */ + /* Do I need to write the bits to a 1 to clear an error? */ + outw(inw(smbus_io_base + SMBGSTATUS), smbus_io_base + SMBGSTATUS); + + /* set the data word...*/ + outw(0, smbus_io_base + SMBHSTDAT); + + /* start the command */ + outw((inw(smbus_io_base + SMBGCTL) | (1 << 3)), smbus_io_base + SMBGCTL); + + + /* poll for transaction completion */ + if (smbus_wait_until_done(smbus_io_base) < 0) { + return SMBUS_WAIT_UNTIL_DONE_TIMEOUT; + } + + global_status_register = inw(smbus_io_base + SMBGSTATUS); + + /* read results of transaction */ + byte = inw(smbus_io_base + SMBHSTDAT) & 0xff; + + if ((global_status_register & SMBUS_STATUS_MASK) != (1 << 4)) { + return SMBUS_ERROR; + } + return byte; +} + +static int do_smbus_send_byte(unsigned smbus_io_base, unsigned device, unsigned value) +{ + unsigned global_status_register; + + if (smbus_wait_until_ready(smbus_io_base) < 0) { + return SMBUS_WAIT_UNTIL_READY_TIMEOUT; + } + + /* setup transaction */ + /* disable interrupts */ + outw(inw(smbus_io_base + SMBGCTL) & ~((1<<10)|(1<<9)|(1<<8)|(1<<4)), smbus_io_base + SMBGCTL); + /* set the device I'm talking too */ + outw(((device & 0x7f) << 1) | 0, smbus_io_base + SMBHSTADDR); + /* set the command/address... */ + outb(0, smbus_io_base + SMBHSTCMD); + /* set up for a send byte */ + outw((inw(smbus_io_base + SMBGCTL) & ~7) | (0x1), smbus_io_base + SMBGCTL); + + /* clear any lingering errors, so the transaction will run */ + /* Do I need to write the bits to a 1 to clear an error? */ + outw(inw(smbus_io_base + SMBGSTATUS), smbus_io_base + SMBGSTATUS); + + /* set the data word...*/ + outw(value, smbus_io_base + SMBHSTDAT); + + /* start the command */ + outw((inw(smbus_io_base + SMBGCTL) | (1 << 3)), smbus_io_base + SMBGCTL); + + + /* poll for transaction completion */ + if (smbus_wait_until_done(smbus_io_base) < 0) { + return SMBUS_WAIT_UNTIL_DONE_TIMEOUT; + } + global_status_register = inw(smbus_io_base + SMBGSTATUS); + + if ((global_status_register & SMBUS_STATUS_MASK) != (1 << 4)) { + return SMBUS_ERROR; + } + return 0; +} + + +static int do_smbus_read_byte(unsigned smbus_io_base, unsigned device, unsigned address) +{ + unsigned global_status_register; + unsigned byte; + + if (smbus_wait_until_ready(smbus_io_base) < 0) { + return SMBUS_WAIT_UNTIL_READY_TIMEOUT; + } + + /* setup transaction */ + /* disable interrupts */ + outw(inw(smbus_io_base + SMBGCTL) & ~((1<<10)|(1<<9)|(1<<8)|(1<<4)), smbus_io_base + SMBGCTL); + /* set the device I'm talking too */ + outw(((device & 0x7f) << 1) | 1, smbus_io_base + SMBHSTADDR); + /* set the command/address... */ + outb(address & 0xFF, smbus_io_base + SMBHSTCMD); + /* set up for a byte data read */ + outw((inw(smbus_io_base + SMBGCTL) & ~7) | (0x2), smbus_io_base + SMBGCTL); + + /* clear any lingering errors, so the transaction will run */ + /* Do I need to write the bits to a 1 to clear an error? */ + outw(inw(smbus_io_base + SMBGSTATUS), smbus_io_base + SMBGSTATUS); + + /* clear the data word...*/ + outw(0, smbus_io_base + SMBHSTDAT); + + /* start the command */ + outw((inw(smbus_io_base + SMBGCTL) | (1 << 3)), smbus_io_base + SMBGCTL); + + + /* poll for transaction completion */ + if (smbus_wait_until_done(smbus_io_base) < 0) { + return SMBUS_WAIT_UNTIL_DONE_TIMEOUT; + } + + global_status_register = inw(smbus_io_base + SMBGSTATUS); + + /* read results of transaction */ + byte = inw(smbus_io_base + SMBHSTDAT) & 0xff; + + if ((global_status_register & SMBUS_STATUS_MASK) != (1 << 4)) { + return SMBUS_ERROR; + } + return byte; +} + +static int do_smbus_write_byte(unsigned smbus_io_base, unsigned device, unsigned address, unsigned char val) +{ + unsigned global_status_register; + + if (smbus_wait_until_ready(smbus_io_base) < 0) { + return SMBUS_WAIT_UNTIL_READY_TIMEOUT; + } + + /* setup transaction */ + /* disable interrupts */ + outw(inw(smbus_io_base + SMBGCTL) & ~((1<<10)|(1<<9)|(1<<8)|(1<<4)), smbus_io_base + SMBGCTL); + /* set the device I'm talking too */ + outw(((device & 0x7f) << 1) | 0, smbus_io_base + SMBHSTADDR); + outb(address & 0xFF, smbus_io_base + SMBHSTCMD); + /* set up for a byte data write */ /* FIXME */ + outw((inw(smbus_io_base + SMBGCTL) & ~7) | (0x2), smbus_io_base + SMBGCTL); + /* clear any lingering errors, so the transaction will run */ + /* Do I need to write the bits to a 1 to clear an error? */ + outw(inw(smbus_io_base + SMBGSTATUS), smbus_io_base + SMBGSTATUS); + + /* write the data word...*/ + outw(val, smbus_io_base + SMBHSTDAT); + + /* start the command */ + outw((inw(smbus_io_base + SMBGCTL) | (1 << 3)), smbus_io_base + SMBGCTL); + + /* poll for transaction completion */ + if (smbus_wait_until_done(smbus_io_base) < 0) { + return SMBUS_WAIT_UNTIL_DONE_TIMEOUT; + } + global_status_register = inw(smbus_io_base + SMBGSTATUS); + + if ((global_status_register & SMBUS_STATUS_MASK) != (1 << 4)) { + return SMBUS_ERROR; + } + return 0; +} + diff --git a/src/southbridge/amd/amd8111/amd8111_usb.c b/src/southbridge/amd/amd8111/amd8111_usb.c index 680b610..2fec77b 100644 --- a/src/southbridge/amd/amd8111/amd8111_usb.c +++ b/src/southbridge/amd/amd8111/amd8111_usb.c @@ -1,39 +1,42 @@ +/* + * (C) 2004 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 <device/chip.h> +#include <device/smbus.h> +#include <arch/io.h> #include "amd8111.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 void lpci_set_subsystem(device_t dev, unsigned vendor, unsigned device) +{ + pci_write_config32(dev, 0x44, + ((device & 0xffff) << 16) | (vendor & 0xffff)); } -static struct device_operations usb_ops = { +static struct smbus_bus_operations lops_smbus_bus = { + /* I haven't seen the 2.0 SMBUS controller used yet. */ +}; +static struct pci_operations lops_pci = { + .set_subsystem = lpci_set_subsystem, +}; +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 = usb_init, - .scan_bus = 0, -// .enable = amd8111_enable, + .init = 0, + .scan_bus = scan_static_bus, + .enable = amd8111_enable, + .ops_pci = &lops_pci, + .ops_smbus_bus = &lops_smbus_bus, }; -static struct pci_driver usb_driver __pci_driver = { - .ops = &usb_ops, +static struct pci_driver smbus_driver __pci_driver = { + .ops = &smbus_ops, .vendor = PCI_VENDOR_ID_AMD, - .device = PCI_DEVICE_ID_AMD_8111_USB, + .device = PCI_DEVICE_ID_AMD_8111_SMB, }; - diff --git a/src/southbridge/amd/amd8111/amd8111_usb2.c b/src/southbridge/amd/amd8111/amd8111_usb2.c index d3393ae..8ec9dc8 100644 --- a/src/southbridge/amd/amd8111/amd8111_usb2.c +++ b/src/southbridge/amd/amd8111/amd8111_usb2.c @@ -23,13 +23,24 @@ static void usb2_init(struct device *dev) #endif } +static void lpci_set_subsystem(device_t dev, unsigned vendor, unsigned device) +{ + pci_write_config32(dev, 0x70, + ((device & 0xffff) << 16) | (vendor & 0xffff)); +} + +static struct pci_operations lops_pci = { + .set_subsystem = lpci_set_subsystem, +}; + 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 = amd8111_enable, + .enable = amd8111_enable, + .ops_pci = &lops_pci, }; static struct pci_driver usb2_driver __pci_driver = { diff --git a/src/southbridge/amd/amd8111/chip.h b/src/southbridge/amd/amd8111/chip.h index d100e98..a4ae278 100644 --- a/src/southbridge/amd/amd8111/chip.h +++ b/src/southbridge/amd/amd8111/chip.h @@ -3,7 +3,10 @@ struct southbridge_amd_amd8111_config { + unsigned int ide0_enable : 1; + unsigned int ide1_enable : 1; }; + struct chip_operations; extern struct chip_operations southbridge_amd_amd8111_ops; diff --git a/src/southbridge/amd/amd8131/amd8131_bridge.c b/src/southbridge/amd/amd8131/amd8131_bridge.c index dc474fc..357059d 100644 --- a/src/southbridge/amd/amd8131/amd8131_bridge.c +++ b/src/southbridge/amd/amd8131/amd8131_bridge.c @@ -1,5 +1,5 @@ /* - * (C) 2003 Linux Networx + * (C) 2003-2004 Linux Networx */ #include <console/console.h> #include <device/device.h> @@ -106,20 +106,19 @@ static void ioapic_enable(device_t dev) value &= ~((1 << 1) | (1 << 0)); } pci_write_config32(dev, 0x44, value); - - /* We have to enable MEM and Bus Master for IOAPIC */ - value = pci_read_config32(dev, 0x4); - value |= 6; - pci_write_config32(dev, 0x4, value); } +static struct pci_operations pci_ops_pci_dev = { + .set_subsystem = pci_dev_set_subsystem, +}; 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 = 0, - .scan_bus = 0, - .enable = ioapic_enable, + .init = 0, + .scan_bus = 0, + .enable = ioapic_enable, + .ops_pci = &pci_ops_pci_dev, }; static struct pci_driver ioapic_driver __pci_driver = { |