mirror of
https://github.com/fail0verflow/switch-coreboot.git
synced 2025-05-04 01:39:18 -04:00
initial checkin of alpha code
This commit is contained in:
parent
258ccbd054
commit
85a2836b28
18 changed files with 646 additions and 0 deletions
14
src/southbridge/amd/amd768/Config
Normal file
14
src/southbridge/amd/amd768/Config
Normal file
|
@ -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
|
||||
|
51
src/southbridge/amd/amd768/amd768_ide.c
Normal file
51
src/southbridge/amd/amd768/amd768_ide.c
Normal file
|
@ -0,0 +1,51 @@
|
|||
#include <pci.h>
|
||||
#include <pci_ids.h>
|
||||
#include <southbridge/amd/amd766.h>
|
||||
#include <pc80/ide.h>
|
||||
#include <printk.h>
|
||||
|
||||
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");
|
||||
|
||||
}
|
16
src/southbridge/amd/amd768/amd768_ioapic.c
Normal file
16
src/southbridge/amd/amd768/amd768_ioapic.c
Normal file
|
@ -0,0 +1,16 @@
|
|||
#include <pci.h>
|
||||
#include <pci_ids.h>
|
||||
#include <southbridge/amd/amd766.h>
|
||||
#include <printk.h>
|
||||
|
||||
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");
|
||||
|
||||
}
|
19
src/southbridge/amd/amd768/amd768_lpc.c
Normal file
19
src/southbridge/amd/amd768/amd768_lpc.c
Normal file
|
@ -0,0 +1,19 @@
|
|||
#include <pci.h>
|
||||
#include <pci_ids.h>
|
||||
#include <southbridge/amd/amd766.h>
|
||||
#include <printk.h>
|
||||
|
||||
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");
|
||||
|
||||
}
|
15
src/southbridge/amd/amd768/amd768_mem.c
Normal file
15
src/southbridge/amd/amd768/amd768_mem.c
Normal file
|
@ -0,0 +1,15 @@
|
|||
#include <pci.h>
|
||||
#include <pci_ids.h>
|
||||
#include <southbridge/amd/amd766.h>
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
}
|
15
src/southbridge/amd/amd768/amd768_mouse.c
Normal file
15
src/southbridge/amd/amd768/amd768_mouse.c
Normal file
|
@ -0,0 +1,15 @@
|
|||
#include <pci.h>
|
||||
#include <pci_ids.h>
|
||||
#include <southbridge/amd/amd766.h>
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
13
src/southbridge/amd/amd768/amd768_pm.c
Normal file
13
src/southbridge/amd/amd768/amd768_pm.c
Normal file
|
@ -0,0 +1,13 @@
|
|||
#include <pci.h>
|
||||
#include <pci_ids.h>
|
||||
#include <southbridge/amd/amd766.h>
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
21
src/southbridge/amd/amd768/amd768_power.c
Normal file
21
src/southbridge/amd/amd768/amd768_power.c
Normal file
|
@ -0,0 +1,21 @@
|
|||
#include <pci.h>
|
||||
#include <pci_ids.h>
|
||||
#include <southbridge/amd/amd766.h>
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
15
src/southbridge/amd/amd768/amd768_reboot.c
Normal file
15
src/southbridge/amd/amd768/amd768_reboot.c
Normal file
|
@ -0,0 +1,15 @@
|
|||
#include <pci.h>
|
||||
#include <pci_ids.h>
|
||||
#include <arch/io.h>
|
||||
#include <southbridge/amd/amd766.h>
|
||||
|
||||
|
||||
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;
|
||||
}
|
39
src/southbridge/amd/amd768/amd768_reset.c
Normal file
39
src/southbridge/amd/amd768/amd768_reset.c
Normal file
|
@ -0,0 +1,39 @@
|
|||
#include <pci.h>
|
||||
#include <pci_ids.h>
|
||||
#include <southbridge/amd/amd766.h>
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
|
||||
}
|
17
src/southbridge/amd/amd768/amd768_usb.c
Normal file
17
src/southbridge/amd/amd768/amd768_usb.c
Normal file
|
@ -0,0 +1,17 @@
|
|||
#include <pci.h>
|
||||
#include <pci_ids.h>
|
||||
#include <southbridge/amd/amd766.h>
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
15
src/southbridge/amd/amd768/amd768_watchdog.c
Normal file
15
src/southbridge/amd/amd768/amd768_watchdog.c
Normal file
|
@ -0,0 +1,15 @@
|
|||
#include <pci.h>
|
||||
#include <pci_ids.h>
|
||||
#include <southbridge/amd/amd766.h>
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
117
src/southbridge/amd/amd768/cmos_boot_failover.inc
Normal file
117
src/southbridge/amd/amd768/cmos_boot_failover.inc
Normal file
|
@ -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 <pc80/mc146818rtc.h>
|
||||
#include <part/fallback_boot.h>
|
||||
|
||||
/* 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:
|
50
src/southbridge/amd/amd768/cmos_reset_failover.inc
Normal file
50
src/southbridge/amd/amd768/cmos_reset_failover.inc
Normal file
|
@ -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 <pc80/mc146818rtc.h>
|
||||
#include <part/fallback_boot.h>
|
||||
|
||||
|
||||
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:
|
10
src/southbridge/amd/amd768/disable_watchdog.inc
Normal file
10
src/southbridge/amd/amd768/disable_watchdog.inc
Normal file
|
@ -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
|
||||
|
17
src/southbridge/amd/amd768/nvram.c
Normal file
17
src/southbridge/amd/amd768/nvram.c
Normal file
|
@ -0,0 +1,17 @@
|
|||
#include <pci_ids.h>
|
||||
#include <pci.h>
|
||||
#include <cpu/p5/io.h>
|
||||
#include <part/nvram.h>
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
195
src/southbridge/amd/amd768/smbus.inc
Normal file
195
src/southbridge/amd/amd768/smbus.inc
Normal file
|
@ -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)
|
7
src/southbridge/amd/amd768/southbridge.c
Normal file
7
src/southbridge/amd/amd768/southbridge.c
Normal file
|
@ -0,0 +1,7 @@
|
|||
void southbridge_fixup(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Add table
Reference in a new issue