initial checkin of alpha code

This commit is contained in:
Steven James 2003-01-11 20:03:46 +00:00
parent 258ccbd054
commit 85a2836b28
18 changed files with 646 additions and 0 deletions

View 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

View 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");
}

View 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");
}

View 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");
}

View 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));
}
}

View 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));
}
}

View 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);
}
}

View 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);
}
}

View 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;
}

View 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));
}
}

View 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);
}
}

View 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));
}
}

View 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:

View 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:

View 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

View 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);
}
}

View 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)

View file

@ -0,0 +1,7 @@
void southbridge_fixup(void)
{
}