From 85a2836b287615b2249b52439af6e56458a30193 Mon Sep 17 00:00:00 2001 From: Steven James Date: Sat, 11 Jan 2003 20:03:46 +0000 Subject: [PATCH] initial checkin of alpha code --- src/southbridge/amd/amd768/Config | 14 ++ src/southbridge/amd/amd768/amd768_ide.c | 51 +++++ src/southbridge/amd/amd768/amd768_ioapic.c | 16 ++ src/southbridge/amd/amd768/amd768_lpc.c | 19 ++ src/southbridge/amd/amd768/amd768_mem.c | 15 ++ src/southbridge/amd/amd768/amd768_mouse.c | 15 ++ src/southbridge/amd/amd768/amd768_pm.c | 13 ++ src/southbridge/amd/amd768/amd768_power.c | 21 ++ src/southbridge/amd/amd768/amd768_reboot.c | 15 ++ src/southbridge/amd/amd768/amd768_reset.c | 39 ++++ src/southbridge/amd/amd768/amd768_usb.c | 17 ++ src/southbridge/amd/amd768/amd768_watchdog.c | 15 ++ .../amd/amd768/cmos_boot_failover.inc | 117 +++++++++++ .../amd/amd768/cmos_reset_failover.inc | 50 +++++ .../amd/amd768/disable_watchdog.inc | 10 + src/southbridge/amd/amd768/nvram.c | 17 ++ src/southbridge/amd/amd768/smbus.inc | 195 ++++++++++++++++++ src/southbridge/amd/amd768/southbridge.c | 7 + 18 files changed, 646 insertions(+) create mode 100644 src/southbridge/amd/amd768/Config create mode 100644 src/southbridge/amd/amd768/amd768_ide.c create mode 100644 src/southbridge/amd/amd768/amd768_ioapic.c create mode 100644 src/southbridge/amd/amd768/amd768_lpc.c create mode 100644 src/southbridge/amd/amd768/amd768_mem.c create mode 100644 src/southbridge/amd/amd768/amd768_mouse.c create mode 100644 src/southbridge/amd/amd768/amd768_pm.c create mode 100644 src/southbridge/amd/amd768/amd768_power.c create mode 100644 src/southbridge/amd/amd768/amd768_reboot.c create mode 100644 src/southbridge/amd/amd768/amd768_reset.c create mode 100644 src/southbridge/amd/amd768/amd768_usb.c create mode 100644 src/southbridge/amd/amd768/amd768_watchdog.c create mode 100644 src/southbridge/amd/amd768/cmos_boot_failover.inc create mode 100644 src/southbridge/amd/amd768/cmos_reset_failover.inc create mode 100644 src/southbridge/amd/amd768/disable_watchdog.inc create mode 100644 src/southbridge/amd/amd768/nvram.c create mode 100644 src/southbridge/amd/amd768/smbus.inc create mode 100644 src/southbridge/amd/amd768/southbridge.c diff --git a/src/southbridge/amd/amd768/Config b/src/southbridge/amd/amd768/Config new file mode 100644 index 0000000000..197397f69d --- /dev/null +++ b/src/southbridge/amd/amd768/Config @@ -0,0 +1,14 @@ +option CONFIG_UDELAY_TSC=1 +object southbridge.o +object nvram.o +object amd768_ioapic.o +object amd768_lpc.o +object amd768_mem.o +object amd768_mouse.o +object amd768_pm.o +object amd768_reset.o +object amd768_watchdog.o +object amd768_power.o +object amd768_reboot.o +object amd768_ide.o + diff --git a/src/southbridge/amd/amd768/amd768_ide.c b/src/southbridge/amd/amd768/amd768_ide.c new file mode 100644 index 0000000000..dd8f655ab6 --- /dev/null +++ b/src/southbridge/amd/amd768/amd768_ide.c @@ -0,0 +1,51 @@ +#include +#include +#include +#include +#include + +void amd766_enable_ide(int enable_a, int enable_b) +{ + struct pci_dev *dev; + dev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7441, 0); + if (dev != NULL) { + /* Enable ide devices so the linux ide driver will work */ + u16 word; + 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); + } + if (enable_a) { + /* Enable primary ide interface */ + word |= (1<<1); + } + pci_write_config_word(dev, 0x40, word); + /* The AMD766 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. + */ + pci_write_config_dword(dev, 0x20, 0xf01); +#if 0 + if (enable_a) { + ide_probe(0x1f0, 0); + } + if (enable_b) { + ide_probe(0x170, 2); + } +#endif +#if 0 + if (enable_a) { + ide_spinup(0x1f0, 0); + } + if (enable_b) { + ide_spinup(0x170, 2); + } +#endif + } else + printk_alert("Could not locate IDE controller\n"); + +} diff --git a/src/southbridge/amd/amd768/amd768_ioapic.c b/src/southbridge/amd/amd768/amd768_ioapic.c new file mode 100644 index 0000000000..58511ea837 --- /dev/null +++ b/src/southbridge/amd/amd768/amd768_ioapic.c @@ -0,0 +1,16 @@ +#include +#include +#include +#include + +void amd766_enable_ioapic(void) +{ + struct pci_dev *dev; + dev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7440,0); + if (dev != NULL) { + /* Enable the ioapic */ + pci_write_config_byte(dev, 0x4b, (0 << 3)|(0 <<2)|(0 << 1)|(1<< 0)); + } else + printk_alert("Could not locate IOAPIC!\n"); + +} diff --git a/src/southbridge/amd/amd768/amd768_lpc.c b/src/southbridge/amd/amd768/amd768_lpc.c new file mode 100644 index 0000000000..5f1136adc0 --- /dev/null +++ b/src/southbridge/amd/amd768/amd768_lpc.c @@ -0,0 +1,19 @@ +#include +#include +#include +#include + +void amd766_enable_serial_irqs(int continuous, unsigned frames, unsigned startclocks) +{ + struct pci_dev *dev; + unsigned value; + value = ((!!continuous) << 6)|((frames & 0xf) << 2)|((startclocks & 3) << 0); + + dev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7443,0); + if (dev != NULL) { + /* Setup serial irq's for the LPC bus. */ + pci_write_config_byte(dev, 0x4a, value); + } else + printk_alert("Could not locate ACPI bridge\n"); + +} diff --git a/src/southbridge/amd/amd768/amd768_mem.c b/src/southbridge/amd/amd768/amd768_mem.c new file mode 100644 index 0000000000..6531cf9480 --- /dev/null +++ b/src/southbridge/amd/amd768/amd768_mem.c @@ -0,0 +1,15 @@ +#include +#include +#include + +void amd766_posted_memory_write_enable(void) +{ + struct pci_dev *dev; + dev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7410, 0); + if (dev != NULL) { + unsigned char byte; + pci_read_config_byte(dev, 0x46, &byte); + pci_write_config_byte(dev, 0x46, byte | (1<<0)); + } + +} diff --git a/src/southbridge/amd/amd768/amd768_mouse.c b/src/southbridge/amd/amd768/amd768_mouse.c new file mode 100644 index 0000000000..52e2ccbed0 --- /dev/null +++ b/src/southbridge/amd/amd768/amd768_mouse.c @@ -0,0 +1,15 @@ +#include +#include +#include + +void amd766_mouse_sends_irq12(void) +{ + struct pci_dev *dev; + dev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7413, 0); + if (dev != NULL) { + unsigned short word; + /* Setup so irq12 is sent by the ps2 mouse port. */ + pci_read_config_word(dev, 0x46, &word); + pci_write_config_word(dev, 0x46, word | (1<<9)); + } +} diff --git a/src/southbridge/amd/amd768/amd768_pm.c b/src/southbridge/amd/amd768/amd768_pm.c new file mode 100644 index 0000000000..240ba3064d --- /dev/null +++ b/src/southbridge/amd/amd768/amd768_pm.c @@ -0,0 +1,13 @@ +#include +#include +#include + +void amd766_set_pm_classcode(void) +{ + struct pci_dev *dev; + dev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7413, 0); + if (dev != NULL) { + pci_write_config_dword(dev, 0x60, 0x06800000); + } + +} diff --git a/src/southbridge/amd/amd768/amd768_power.c b/src/southbridge/amd/amd768/amd768_power.c new file mode 100644 index 0000000000..af1a3b0495 --- /dev/null +++ b/src/southbridge/amd/amd768/amd768_power.c @@ -0,0 +1,21 @@ +#include +#include +#include + +void amd766_power_after_power_fail(int on) +{ + struct pci_dev *dev; + dev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7413, 0); + if (dev != NULL) { + unsigned char byte; + pci_read_config_byte(dev, 0x43, &byte); + if (on) { + byte &= ~(1<<6); + } + else { + byte |= (1<<6); + } + pci_write_config_byte(dev, 0x43, byte); + } + +} diff --git a/src/southbridge/amd/amd768/amd768_reboot.c b/src/southbridge/amd/amd768/amd768_reboot.c new file mode 100644 index 0000000000..66013dfcf5 --- /dev/null +++ b/src/southbridge/amd/amd768/amd768_reboot.c @@ -0,0 +1,15 @@ +#include +#include +#include +#include + + +void amd766_hard_reset(void) +{ + pci_set_method(); + /* Allow the watchdog timer to reboot us, and enable 0xcf9 */ + pcibios_write_config_byte(0, (AMD766_DEV >> 8) | 3, 0x41, (1<<5)|(1<<1)); + /* Try rebooting though port 0xcf9 */ + outb((0<<3)|(1<<2)|(1<<1), 0xcf9); + return; +} diff --git a/src/southbridge/amd/amd768/amd768_reset.c b/src/southbridge/amd/amd768/amd768_reset.c new file mode 100644 index 0000000000..3bbbad2cca --- /dev/null +++ b/src/southbridge/amd/amd768/amd768_reset.c @@ -0,0 +1,39 @@ +#include +#include +#include + +void amd766_enable_port92_reset(void) +{ + struct pci_dev *dev; + dev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7410, 0); + if (dev != NULL) { + unsigned char byte; + /* Enable reset using port 0x92 */ + pci_read_config_byte(dev, 0x41, &byte); + pci_write_config_byte(dev, 0x41, byte | (1<<5)); + } +} + +void amd766_cpu_reset_sends_init(void) +{ + struct pci_dev *dev; + dev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7410, 0); + if (dev != NULL) { + unsigned char byte; + pci_read_config_byte(dev, 0x47, &byte); + pci_write_config_byte(dev, 0x47, byte | (1<<7)); + } +} + +void amd766_decode_stop_grant(unsigned how) +{ + struct pci_dev *dev; + dev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7413, 0); + if (dev != NULL) { + unsigned char byte; + pci_read_config_byte(dev, 0x41, &byte); + pci_write_config_byte(dev, 0x41, byte | ((how & 1)<<1)); + } + + +} diff --git a/src/southbridge/amd/amd768/amd768_usb.c b/src/southbridge/amd/amd768/amd768_usb.c new file mode 100644 index 0000000000..d2f9cd8739 --- /dev/null +++ b/src/southbridge/amd/amd768/amd768_usb.c @@ -0,0 +1,17 @@ +#include +#include +#include + +void amd766_usb_setup(void) +{ + /* FIXME this is untested incomplete implementation. */ + struct pci_dev *dev; + dev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7414, 0); + if (dev) { + u32 cmd; + 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); + } +} diff --git a/src/southbridge/amd/amd768/amd768_watchdog.c b/src/southbridge/amd/amd768/amd768_watchdog.c new file mode 100644 index 0000000000..5cc3b9926b --- /dev/null +++ b/src/southbridge/amd/amd768/amd768_watchdog.c @@ -0,0 +1,15 @@ +#include +#include +#include + +void amd766_disable_watchdog(void) +{ + struct pci_dev *dev; + dev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7413, 0); + if (dev != NULL) { + unsigned char byte; + /* Disable the watchdog timer */ + pci_read_config_byte(dev, 0x49, &byte); + pci_write_config_byte(dev, 0x49, byte | (1<<2)); + } +} diff --git a/src/southbridge/amd/amd768/cmos_boot_failover.inc b/src/southbridge/amd/amd768/cmos_boot_failover.inc new file mode 100644 index 0000000000..04575ac7cf --- /dev/null +++ b/src/southbridge/amd/amd768/cmos_boot_failover.inc @@ -0,0 +1,117 @@ +/* The algorithm is as follows: + * + * Step 1: Test for cpu reset + * That is, did I just boot or is this a later boot since power on. + * The result of this test in %al + * %al == 1 -- We are rebooting + * %al == 0 -- This is the initial boot + * + * Step 2: Cpu filter + * On an initial boot if we are not the bootstrap CPU go to + * sleep. + * + * Step 3: Test for CMOS validity. + * On an initial boot if the CMOS checksum or the CMOS error + * condition is signaled clear the CMOS ram. + * + * Step 4: Test for which copy of linuxbios to boot. + * We use 2 bits of CMOS ram. + * Bit 0: Initial boot direction + * 0 - Boot the failsafe image. + * 1 - Boot the other image. + * Bit 1: Reboot direction + * 0 - Boot the failsafe image. + * 1 - Boot the other image. + * + * On initial boot we read bit0, and write it to bit1, and clear + * bit0. + * + * On a reboot the bits are not touched. + * + * Then the appropriate image is jumped to. + * + * + */ +#include +#include + + /* See if the CMOS error condition has been flagged */ + movb $RTC_REG_D, %al + outb %al, $0x70 + inb $0x71, %al + andb $RTC_VRT, %al + testb %al, %al + jz __rtc_failed + + /* Compute the cmos checksum, and see if it is valid */ + movb $PC_CKS_RANGE_START, %bl + xorl %ecx, %ecx +1: + movb %bl, %al + outb %al, $0x70 + xorl %eax, %eax + inb $0x71, %al + addl %eax, %ecx + incb %bl + cmpb $PC_CKS_RANGE_END, %bl + jbe 1b + + /* Compute the cmos checksum, and see if it is valid */ + /* Read the stored checksum */ + movb $(PC_CKS_LOC), %al + outb %al,$0x70 + inb $0x71, %al + movb %al, %bh + movb $(PC_CKS_LOC+1), %al + outb %al, $0x70 + inb $0x71, %al + movb %al, %bl + + /* Now finally test the checksum */ + xorw $0xffff, %cx + cmpw %cx, %bx + je __rtc_ok + + /* There are no impossible values, no checksums + * so just trust whatever value we have in the + * cmos, but clear the fallback bit. + */ +__rtc_failed: + movb $RTC_BOOT_BYTE, %al + outb %al, $0x70 + inb $0x71, %al + andb $0xfc, %al + outb %al, $0x71 + jmp __rtc_ok + + /* The byte is o.k. see where to go */ +__rtc_ok: + movb $RTC_BOOT_BYTE, %al + outb %al, $0x70 + inb $0x71, %al + + /* Transfer the boot bit from bit 0 to bit 1. + * And clear bit 0 so that unless we say it works we + * fallback to the other bios image immediately. + */ + movb %al, %bl + andb $0xfc, %al + andb $1, %bl + shlb %bl + orb %bl, %al + outb %al, $0x71 + + testb $(1<<1), %al + jz __failover_boot + + /* Enable 4MB rom access at 0xFFC00000 - 0xFFFFFFFF */ + movl $(0x80000000 | AMD766_DEV | 0x40), %eax + movw $0xcf8, %dx + outl %eax, %dx + movw $(0xcfc + 3), %dx + inb %dx, %al + orb $0x80, %al + outb %al, %dx + + jmp __normal_image +__failover_boot: diff --git a/src/southbridge/amd/amd768/cmos_reset_failover.inc b/src/southbridge/amd/amd768/cmos_reset_failover.inc new file mode 100644 index 0000000000..3816683f4a --- /dev/null +++ b/src/southbridge/amd/amd768/cmos_reset_failover.inc @@ -0,0 +1,50 @@ +/* The algorithm is as follows: + * + * Step 1: Test for cpu reset + * That is, did I just boot or is this a later boot since power on. + * The result of this test in %al + * %al == 1 -- We are rebooting + * %al == 0 -- This is the initial boot + * + * Step 2: Cpu filter + * On an initial boot if we are not the bootstrap CPU go to + * sleep. + * + * Step 3: Test for CMOS validity. + * On an initial boot if the CMOS checksum or the CMOS error + * condition is signaled clear the CMOS ram. + * + * Step 4: Test for which copy of linuxbios to boot. + * We use 2 bits of CMOS ram. + * Bit 0: Initial boot direction + * 0 - Boot the failsafe image. + * 1 - Boot the other image. + * Bit 1: Reboot direction + * 0 - Boot the failsafe image. + * 1 - Boot the other image. + * + * On initial boot we read bit0, and write it to bit1, and clear + * bit0. + * + * On a reboot the bits are not touched. + * + * Then the appropriate image is jumped to. + * + * + */ +#include +#include + + + testb %al, %al + jz __failover_boot + +__failover_reset: + movb $RTC_BOOT_BYTE, %al + outb %al, $0x70 + inb $0x71, %al + testb $(1<<1), %al + jnz __normal_image + jmp __cpu_reset + +__failover_boot: diff --git a/src/southbridge/amd/amd768/disable_watchdog.inc b/src/southbridge/amd/amd768/disable_watchdog.inc new file mode 100644 index 0000000000..f436beaf36 --- /dev/null +++ b/src/southbridge/amd/amd768/disable_watchdog.inc @@ -0,0 +1,10 @@ +#define PM_DEV_FN (AMD766_DEV + 0x300) + /* Disable the watchdog timer */ + movl $(0x80000000 | PM_DEV_FN | 0x48), %eax + movw $0xcf8, %dx + outl %eax, %dx + movw $0xcfd, %dx + inb %dx, %al + orb $0x8, %al + outb %al, %dx + diff --git a/src/southbridge/amd/amd768/nvram.c b/src/southbridge/amd/amd768/nvram.c new file mode 100644 index 0000000000..35c54555e5 --- /dev/null +++ b/src/southbridge/amd/amd768/nvram.c @@ -0,0 +1,17 @@ +#include +#include +#include +#include + +void nvram_on(void) +{ + struct pci_dev *dev; + dev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7410, 0); + if (dev != NULL) { + u8 segen; + pci_read_config_byte(dev, 0x43, &segen); + /* Enable 4MB rom access at 0xFFC00000 - 0xFFFFFFFF */ + segen |= 0x80; + pci_write_config_byte(dev, 0x43, segen); + } +} diff --git a/src/southbridge/amd/amd768/smbus.inc b/src/southbridge/amd/amd768/smbus.inc new file mode 100644 index 0000000000..71977c538f --- /dev/null +++ b/src/southbridge/amd/amd768/smbus.inc @@ -0,0 +1,195 @@ +jmp smbus_code_end + +#define PM_DEV_FN (AMD766_DEV + 0x300) + + +#define PM_BASE 0xDD00 +#define SMBUS_IO_BASE (PM_BASE + 0xE0) +#define SMB_GSTAT (SMBUS_IO_BASE + 0x0) +#define SMB_GCTL (SMBUS_IO_BASE + 0x2) +#define SMB_HOST_ADDR (SMBUS_IO_BASE + 0x4) +#define SMB_HOST_DAT (SMBUS_IO_BASE + 0x6) +#define SMB_HOST_CMD (SMBUS_IO_BASE + 0x8) +#define SMB_BLKDAT (SMBUS_IO_BASE + 0x9) +#define SMB_SLAVE_DAT (SMBUS_IO_BASE + 0xa) +#define SMB_SLAVE_DEV (SMBUS_IO_BASE + 0xc) +#define SMB_SLAVE_ADDR (SMBUS_IO_BASE + 0xe) +#define SMB_SNOOP_ADDR (SMBUS_IO_BASE + 0xf) + +#define SMB_GSTAT_ABORT (1 << 0) +#define SMB_GSTAT_COLLISION (1 << 1) +#define SMB_GSTAT_PROTO_ERROR (1 << 2) +#define SMB_GSTAT_HOST_BUSY (1 << 3) +#define SMB_GSTAT_COMPLETE (1 << 4) +#define SMB_GSTAT_TIMEOUT (1 << 5) +#define SMB_GSTAT_SNOOP_MATCH (1 << 8) +#define SMB_GSTAT_SLAVE_MATCH (1 << 9) +#define SMB_GSTAT_ALERT (1 << 10) +#define SMB_GSTAT_BUSY (1 << 11) + +/* The low bit of the address specifies read or write */ +#define SMB_GCTL_QUICK_COMMAND 0 +#define SMB_GCTL_SEND_RECV_BYTE 1 +#define SMB_GCTL_WRITE_READ_BYTE 2 +#define SMB_GCTL_WRITE_READ_WORD 3 +#define SMB_GCTL_PROCESS_CALL 4 +#define SMB_GCTL_WRITE_READ_BLOCK 5 + +#define SMB_GCTL_HOST_START (1 << 3) +#define SMB_GCTL_HOST_INTERRUPT (1 << 4) +#define SMB_GCTL_ABORT (1 << 5) +#define SMB_GCTL_SNOOP (1 << 8) +#define SMB_GCTL_SLAVE_INTERRUPT (1 << 9) +#define SMB_GCTL_ALERT_INTERRUPT (1 << 10) + +enable_string: .string "Enabling smbus\r\n" +setup_string: .string "Setting up smbus\r\n" + +enable_smbus: + CONSOLE_INFO_TX_STRING($enable_string) + /* Enable PM IO C3A41 */ + movl $(0x80000000 | PM_DEV_FN | 0x40), %eax + movw $0xcf8, %dx + outl %eax, %dx + movw $0xcfd, %dx + inb %dx, %al + orb $0x80, %al + outb %al, %dx + + /* Set the PM registers to 0xDD00 */ + movl $(0x80000000 | PM_DEV_FN | 0x58), %eax + mov $0xcf8, %dx + outl %eax, %dx + movw $0xcfc, %dx + movl $(PM_BASE | 0x01), %eax + outl %eax, %dx + + RET_LABEL(enable_smbus) + + /* + * Routine: setup_smbus + * Arguments: none + * Results: none + * Trashed: eax, edx + * Effects: The smbus is enabled + */ +setup_smbus: + CONSOLE_INFO_TX_STRING($setup_string) + movl $(SMB_GSTAT_ABORT | SMB_GSTAT_COLLISION | \ + SMB_GSTAT_PROTO_ERROR | SMB_GSTAT_COMPLETE | \ + SMB_GSTAT_TIMEOUT | SMB_GSTAT_SNOOP_MATCH | \ + SMB_GSTAT_SLAVE_MATCH | SMB_GSTAT_ALERT),%eax + movw $SMB_GSTAT, %dx + outb %al, %dx + RET_LABEL(setup_smbus) + + /* + * Routine: smbus_wait_until_ready + * Arguments: none + * Results: none + * Trashed: eax, edx + * Effects: Upon return the smbus is ready to accept commands + */ +smbus_wait_until_ready: + movl $SMB_GSTAT, %edx +1: inb %dx, %al + testb $SMB_GSTAT_HOST_BUSY, %al + jnz 1b + RET_LABEL(smbus_wait_until_ready) + + + /* + * Routine: smbus_wait_until_done + * Arguments: none + * Results: none + * Trashed: eax, edx + * Effects: Upon return the smbus has completed it's most recent transation + */ + +/* + *smbus_wait_until_done: + * movl $SMB_GSTAT, %edx + *1: inb %dx, %al + * testb $(SMB_GSTAT_HOST_BUSY), %al + * jnz 1b + *2: testb $(~(SMB_GSTAT_HOST_BUSY)), %al + * jnz 3f + * inb %dx, %al + * testb $(~(SMB_GSTAT_HOST_BUSY)), %al + * jz 2b + *3: RET_LABEL(smbus_wait_until_done) + * + */ + + /* + * Routine: smbus_read_byte + * Arguments: %esp return address + * %bl device on the smbus to read from + * %bh address on the smbus to read + * + * Results: zf clear + * byte read %eax + * On Error: + * zf set + * %eax trashed + * + * Trashed: %edx, %eax + * Effects: reads a byte off of the smbus + */ + +smbus_read_byte: + /* poll until the smbus is ready for commands */ + CALL_LABEL(smbus_wait_until_ready) + + /* clear any lingering errors, so that the transaction will run */ + movw $SMB_GSTAT, %dx + inw %dx, %ax + outw %ax, %dx + + /* set the device I'm talking to, and set the low bit for a read */ + movw $SMB_HOST_ADDR, %dx + xorl %eax, %eax + movb %bl /* device */, %al + shlb $1, %al + orb $1, %al + outw %ax, %dx + + /* set the command address... */ + movw $SMB_HOST_CMD, %dx + movb %bh /* address */, %al + outb %al, %dx + + /* clear the data byte */ + movw $SMB_HOST_DAT, %dx + xorl %eax, %eax + outw %ax, %dx + + /* start a byte read, with interrupts disabled */ + movw $SMB_GCTL, %dx + movl $(SMB_GCTL_HOST_START | SMB_GCTL_WRITE_READ_BYTE), %eax + outw %ax, %dx + + /* poll for transaction completion */ +# CALL_LABEL(smbus_wait_until_done) +# code copied since CALL_LABEL can only be used once! + movl $SMB_GSTAT, %edx +1: inb %dx, %al + testb $SMB_GSTAT_HOST_BUSY, %al + jnz 1b +#endcopy of smbus_wait_until_ready + + /* read the results and see if we succeded */ + movl $SMB_GSTAT, %edx + inb %dx, %al + testb $(SMB_GSTAT_COMPLETE), %al + jz 1f + movw $SMB_HOST_DAT, %dx + inb %dx, %al +1: + RETSP + + + +smbus_code_end: +CALL_LABEL(enable_smbus) +CALL_LABEL(setup_smbus) diff --git a/src/southbridge/amd/amd768/southbridge.c b/src/southbridge/amd/amd768/southbridge.c new file mode 100644 index 0000000000..aab2cd275f --- /dev/null +++ b/src/southbridge/amd/amd768/southbridge.c @@ -0,0 +1,7 @@ +void southbridge_fixup(void) +{ + +} + + +