summaryrefslogtreecommitdiff
path: root/src/southbridge/amd
diff options
context:
space:
mode:
authorEric Biederman <ebiederm@xmission.com>2004-10-21 10:44:08 +0000
committerEric Biederman <ebiederm@xmission.com>2004-10-21 10:44:08 +0000
commitdbec2d4090e40d1d8e1fd06e8d4180d3fa685d4d (patch)
treee813d3f9dea80d35cbc29d6bf35995fec0a06ab9 /src/southbridge/amd
parentf3aa4707d3bef9f529a70a204dbc648968cf7c20 (diff)
- 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.c58
-rw-r--r--src/southbridge/amd/amd8111/amd8111_ac97.c15
-rw-r--r--src/southbridge/amd/amd8111/amd8111_acpi.c132
-rw-r--r--src/southbridge/amd/amd8111/amd8111_early_smbus.c117
-rw-r--r--src/southbridge/amd/amd8111/amd8111_enable_rom.c6
-rw-r--r--src/southbridge/amd/amd8111/amd8111_ide.c18
-rw-r--r--src/southbridge/amd/amd8111/amd8111_lpc.c44
-rw-r--r--src/southbridge/amd/amd8111/amd8111_nic.c2
-rw-r--r--src/southbridge/amd/amd8111/amd8111_pci.c5
-rw-r--r--src/southbridge/amd/amd8111/amd8111_smbus.c126
-rw-r--r--src/southbridge/amd/amd8111/amd8111_smbus.h224
-rw-r--r--src/southbridge/amd/amd8111/amd8111_usb.c47
-rw-r--r--src/southbridge/amd/amd8111/amd8111_usb2.c13
-rw-r--r--src/southbridge/amd/amd8111/chip.h3
-rw-r--r--src/southbridge/amd/amd8131/amd8131_bridge.c17
15 files changed, 501 insertions, 326 deletions
diff --git a/src/southbridge/amd/amd8111/amd8111.c b/src/southbridge/amd/amd8111/amd8111.c
index a9b132cdaf..6e7022cd77 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 36ed41feed..40f663d9b1 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 557e54f858..38c3269b1f 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 5157609639..8ad3589e63 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 468801a6c4..8c4e4da5da 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 a92274695d..167484401b 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 6441c86efe..b94b19baab 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 512b2683c5..b3792086a5 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 29d3fb88d8..9fe1f98d32 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 bfa78b3c8a..2fec77bb17 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 0000000000..b5799666e9
--- /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 680b610267..2fec77bb17 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 d3393ae4d3..8ec9dc8abf 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 d100e98060..a4ae278fb9 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 dc474fc7b0..357059d347 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 = {