new stupid southbridge.
This commit is contained in:
parent
3765a83088
commit
fcd39ac7ad
21 changed files with 1235 additions and 0 deletions
58
src/southbridge/intel/82801db/82801.h
Normal file
58
src/southbridge/intel/82801db/82801.h
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
#define PCI_DMA_CFG 0x90
|
||||
#define SERIRQ_CNTL 0x64
|
||||
#define GEN_CNTL 0xd0
|
||||
#define GEN_STS 0xd4
|
||||
#define RTC_CONF 0xd8
|
||||
#define GEN_PMCON_3 0xa4
|
||||
|
||||
#define PCICMD 0x04
|
||||
#define PMBASE 0x40
|
||||
#define ACPI_CNTL 0x44
|
||||
#define BIOS_CNTL 0x4E
|
||||
#define GPIO_BASE 0x58
|
||||
#define GPIO_CNTL 0x5C
|
||||
#define PIRQA_ROUT 0x60
|
||||
#define PIRQE_ROUT 0x68
|
||||
#define COM_DEC 0xE0
|
||||
#define LPC_EN 0xE6
|
||||
#define FUNC_DIS 0xF2
|
||||
|
||||
/* 1e f0 244e */
|
||||
|
||||
#define CMD 0x04
|
||||
#define SBUS_NUM 0x19
|
||||
#define SUB_BUS_NUM 0x1A
|
||||
#define SMLT 0x1B
|
||||
#define IOBASE 0x1C
|
||||
#define IOLIM 0x1D
|
||||
#define MEMBASE 0x20
|
||||
#define MEMLIM 0x22
|
||||
#define CNF 0x50
|
||||
#define MTT 0x70
|
||||
#define PCI_MAST_STS 0x82
|
||||
|
||||
#define RTC_BUS 0
|
||||
#define RTC_DEVFN ((0x1f << 3) + 0)
|
||||
#define RTC_FAILED (1 <<2)
|
||||
|
||||
|
||||
#define SMBUS_BUS 0
|
||||
#define SMBUS_DEVFN ((0x1f << 3) + 3)
|
||||
#define SMBUS_IO_BASE 0x1000
|
||||
|
||||
#define SMBHSTSTAT 0x0
|
||||
#define SMBHSTCTL 0x2
|
||||
#define SMBHSTCMD 0x3
|
||||
#define SMBXMITADD 0x4
|
||||
#define SMBHSTDAT0 0x5
|
||||
#define SMBHSTDAT1 0x6
|
||||
#define SMBBLKDAT 0x7
|
||||
#define SMBTRNSADD 0x9
|
||||
#define SMBSLVDATA 0xa
|
||||
#define SMLINK_PIN_CTL 0xe
|
||||
#define SMBUS_PIN_CTL 0xf
|
||||
|
||||
/* Between 1-10 seconds, We should never timeout normally
|
||||
* Longer than this is just painful when a timeout condition occurs.
|
||||
*/
|
||||
#define SMBUS_TIMEOUT (100*1000)
|
||||
11
src/southbridge/intel/82801db/Config
Normal file
11
src/southbridge/intel/82801db/Config
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
object nvram.o
|
||||
object ich3_ioapic.o
|
||||
object ich3_lpc.o
|
||||
object ich3_ide.o
|
||||
object ich3_reset.o
|
||||
object ich3_smbus.o
|
||||
object ich3_cpu.o
|
||||
object ich3_rtc.o
|
||||
object ich3_power.o
|
||||
object ich3_1e0_misc.o
|
||||
object ich3_1f0_misc.o
|
||||
148
src/southbridge/intel/82801db/cmos_failover.inc
Normal file
148
src/southbridge/intel/82801db/cmos_failover.inc
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
/* 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 6 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.
|
||||
* Bits 4-7: Reboot count
|
||||
*
|
||||
* On initial boot we read bit0, and write it to bit1, and clear
|
||||
* bit0. Additionally we clear bit1 if we bit0 was initially set
|
||||
* and we have reached the maximum boot count.
|
||||
*
|
||||
* On a reboot the bits are not touched.
|
||||
*
|
||||
* Then the appropriate image is jumped to.
|
||||
*
|
||||
*/
|
||||
#include "82801.h"
|
||||
#include <pc80/mc146818rtc.h>
|
||||
#include <part/fallback_boot.h>
|
||||
|
||||
#ifndef MAX_REBOOT_CNT
|
||||
#error "MAX_REBOOT_CNT not defined"
|
||||
#endif
|
||||
#if MAX_REBOOT_CNT > 15
|
||||
#error "MAX_REBOOT_CNT to large"
|
||||
#endif
|
||||
|
||||
/* Intel systems magically stop the second cpu in hardware */
|
||||
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:
|
||||
/* See if the cmos clear jumper has been set */
|
||||
movl $((RTC_DEVFN << 8) | GEN_PMCON_3), %eax
|
||||
PCI_READ_CONFIG_DWORD
|
||||
testl $RTC_FAILED, %eax
|
||||
jz __cs_test
|
||||
|
||||
/* There are no impossible values, no checksums
|
||||
* so just trust whatever value we have in the
|
||||
* cmos.
|
||||
*/
|
||||
__rtc_failed:
|
||||
movb $RTC_BOOT_BYTE, %al
|
||||
outb %al, $0x70
|
||||
inb $0x71, %al
|
||||
andb $0xfc, %al
|
||||
outb %al, $0x71
|
||||
jmp __cs_test
|
||||
|
||||
/* test the checksum */
|
||||
__cs_test:
|
||||
movl $77,%ecx
|
||||
xor %ebx,%ebx
|
||||
movl $RTC_BOOT_BYTE, %edx
|
||||
1:
|
||||
addl $1, %edx
|
||||
movl %edx, %eax
|
||||
outb %al, $0x70
|
||||
inb $0x71, %al
|
||||
addl %eax,%ebx
|
||||
subl $1,%ecx
|
||||
jnz 1b
|
||||
not %ebx
|
||||
addl $1, %edx
|
||||
movl %edx, %eax
|
||||
outb %al, $0x70
|
||||
inb $0x71, %al
|
||||
movb %al,%ch
|
||||
addl $1, %edx
|
||||
movl %edx, %eax
|
||||
outb %al, $0x70
|
||||
inb $0x71, %al
|
||||
movb %ch,%ah
|
||||
cmpw %ax,%bx
|
||||
jz __rtc_ok
|
||||
/* Set to fall back mode */
|
||||
movb $RTC_BOOT_BYTE, %al
|
||||
outb %al, $0x70
|
||||
inb $0x71, %al
|
||||
andb $0xfc, %al
|
||||
outb %al, $0x71
|
||||
|
||||
/* The byte is o.k. see where to go */
|
||||
__rtc_ok:
|
||||
movb $RTC_BOOT_BYTE, %al
|
||||
outb %al, $0x70
|
||||
inb $0x71, %al
|
||||
|
||||
movb %al, %bl
|
||||
movb %al, %cl
|
||||
andb $0x0c, %al /* Remove the boot bits from %al */
|
||||
shrb $4, %cl /* Isolate the boot count */
|
||||
|
||||
/* If we are in fallback mode set the reboot count to max */
|
||||
testb $1, %bl
|
||||
jnz __reboot_cnt_read
|
||||
movb $MAX_REBOOT_CNT, %cl
|
||||
__reboot_cnt_read:
|
||||
/* Increment the reboot count and see if we have hit the limit */
|
||||
incb %cl
|
||||
cmpb $MAX_REBOOT_CNT, %cl
|
||||
jb __reboot_cnt_ok
|
||||
__reboot_cnt_bad:
|
||||
xorb %cl, %cl /* clear the boot count in fallback */
|
||||
xorb %bl, %bl /* clear the boot bits in fallback */
|
||||
jmp __reboot_cnt_set
|
||||
|
||||
__reboot_cnt_ok:
|
||||
movb $((1<<1)|(1<<0)), %bl /* Set boot_option=1 last_boot=1 */
|
||||
/* Save the new boot bits */
|
||||
__reboot_cnt_set:
|
||||
shlb $4, %cl
|
||||
orb %bl, %al
|
||||
orb %cl, %al
|
||||
outb %al, $0x71
|
||||
|
||||
testb $(1<<1), %al
|
||||
jnz __normal_image
|
||||
31
src/southbridge/intel/82801db/ich4_1e0_misc.c
Normal file
31
src/southbridge/intel/82801db/ich4_1e0_misc.c
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
#include <pci.h>
|
||||
#include <arch/io.h>
|
||||
#include <printk.h>
|
||||
#include <pci_ids.h>
|
||||
#include <southbridge/intel/82801.h>
|
||||
#include "82801.h"
|
||||
|
||||
void ich3_1e0_misc(void)
|
||||
{
|
||||
struct pci_dev *dev;
|
||||
|
||||
dev = pci_find_device(PCI_VENDOR_ID_INTEL,
|
||||
PCI_DEVICE_ID_INTEL_82801CA_1E0, 0);
|
||||
if (!dev) {
|
||||
printk_debug("*** ERROR Southbridge device %x not found\n",
|
||||
PCI_DEVICE_ID_INTEL_82801CA_1E0);
|
||||
return;
|
||||
}
|
||||
#if 0
|
||||
pci_write_config_word(dev, CMD, 0x0147);
|
||||
pci_write_config_byte(dev, SMLT, 0x40);
|
||||
pci_write_config_byte(dev, IOBASE, 0x20);
|
||||
pci_write_config_byte(dev, IOLIM, 0x20);
|
||||
pci_write_config_word(dev, MEMBASE, 0xd410);
|
||||
pci_write_config_word(dev, MEMLIM, 0xd5f0);
|
||||
pci_write_config_byte(dev, CNF, 0x02);
|
||||
pci_write_config_byte(dev, MTT, 0x40);
|
||||
pci_write_config_byte(dev, PCI_MAST_STS, 0x86);
|
||||
#endif
|
||||
|
||||
}
|
||||
30
src/southbridge/intel/82801db/ich4_1f0_misc.c
Normal file
30
src/southbridge/intel/82801db/ich4_1f0_misc.c
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
#include <pci.h>
|
||||
#include <arch/io.h>
|
||||
#include <printk.h>
|
||||
#include <pci_ids.h>
|
||||
#include <southbridge/intel/82801.h>
|
||||
#include "82801.h"
|
||||
|
||||
void ich3_1f0_misc(void)
|
||||
{
|
||||
struct pci_dev *dev;
|
||||
|
||||
dev = pci_find_device(PCI_VENDOR_ID_INTEL,
|
||||
PCI_DEVICE_ID_INTEL_82801CA_1F0, 0);
|
||||
if (!dev) {
|
||||
printk_debug("*** ERROR Southbridge device %x not found\n",
|
||||
PCI_DEVICE_ID_INTEL_82801CA_1F0);
|
||||
return;
|
||||
}
|
||||
pci_write_config_word(dev, PCICMD, 0x014f);
|
||||
pci_write_config_dword(dev, PMBASE, 0x00001001);
|
||||
pci_write_config_byte(dev, ACPI_CNTL, 0x10);
|
||||
pci_write_config_dword(dev, GPIO_BASE, 0x00001181);
|
||||
pci_write_config_byte(dev, GPIO_CNTL, 0x10);
|
||||
pci_write_config_dword(dev, PIRQA_ROUT, 0x0A05030B);
|
||||
pci_write_config_byte(dev, PIRQE_ROUT, 0x07);
|
||||
pci_write_config_byte(dev, RTC_CONF, 0x04);
|
||||
pci_write_config_byte(dev, COM_DEC, 0xE0);
|
||||
pci_write_config_word(dev, LPC_EN, 0x000D);
|
||||
pci_write_config_word(dev, FUNC_DIS, 0x8060);
|
||||
}
|
||||
37
src/southbridge/intel/82801db/ich4_cpu.c
Normal file
37
src/southbridge/intel/82801db/ich4_cpu.c
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
#include <pci.h>
|
||||
#include <pci_ids.h>
|
||||
#include <southbridge/intel/82801.h>
|
||||
#include <printk.h>
|
||||
#include <part/hard_reset.h>
|
||||
#include <part/fallback_boot.h>
|
||||
#include "82801.h"
|
||||
|
||||
void ich3_set_cpu_multiplier(unsigned multiplier)
|
||||
{
|
||||
u32 dword, old_dword;
|
||||
struct pci_dev *dev;
|
||||
unsigned old_multiplier;
|
||||
dev = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_1F0, 0);
|
||||
if (!dev) {
|
||||
printk_err("Cannot find device %08x:%08x\n",
|
||||
PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_1F0);
|
||||
return;
|
||||
}
|
||||
pci_read_config_dword(dev, GEN_STS, &old_dword);
|
||||
dword = old_dword;
|
||||
dword &= ~((1 << 12) - (1 << 8));
|
||||
#if 0
|
||||
dword |= (multiplier & 0xf) << 8;
|
||||
#else
|
||||
dword |= (0x0c) << 8;
|
||||
#endif
|
||||
if (dword != old_dword) {
|
||||
dword |= (1<<1);
|
||||
pci_write_config_dword(dev, GEN_STS, dword);
|
||||
printk_info("Rebooting to change the cpu multiplier\n");
|
||||
boot_successful();
|
||||
hard_reset();
|
||||
}
|
||||
dword |= (1<<1);
|
||||
pci_write_config_dword(dev, GEN_STS, dword);
|
||||
}
|
||||
24
src/southbridge/intel/82801db/ich4_ide.c
Normal file
24
src/southbridge/intel/82801db/ich4_ide.c
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
#include <pci.h>
|
||||
#include <pci_ids.h>
|
||||
#include <southbridge/intel/82801.h>
|
||||
|
||||
void ich3_enable_ide(int enable_a, int enable_b)
|
||||
{
|
||||
struct pci_dev *dev;
|
||||
dev = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_1F1, 0);
|
||||
if (dev != NULL) {
|
||||
/* Enable ide devices so the linux ide driver will work */
|
||||
u16 word;
|
||||
/* enable ide0 */
|
||||
pci_read_config_word(dev, 0x40, &word);
|
||||
word &= ~(1 << 15);
|
||||
word |= ((!!enable_a) << 15);
|
||||
pci_write_config_word(dev, 0x40, word);
|
||||
/* enable ide1 */
|
||||
pci_read_config_word(dev, 0x42, &word);
|
||||
word &= ~(1 << 15);
|
||||
word |= ((!!enable_b) << 15);
|
||||
pci_write_config_word(dev, 0x42, word);
|
||||
}
|
||||
|
||||
}
|
||||
45
src/southbridge/intel/82801db/ich4_ioapic.c
Normal file
45
src/southbridge/intel/82801db/ich4_ioapic.c
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
#include <pci.h>
|
||||
#include <arch/io.h>
|
||||
#include <printk.h>
|
||||
#include <pci_ids.h>
|
||||
#include <southbridge/intel/82801.h>
|
||||
#include "82801.h"
|
||||
|
||||
void ich3_enable_ioapic(void)
|
||||
{
|
||||
struct pci_dev *dev;
|
||||
u32 dword;
|
||||
volatile u32 *ioapic_sba = (volatile u32 *)0xfec00000;
|
||||
volatile u32 *ioapic_sbd = (volatile u32 *)0xfec00010;
|
||||
|
||||
dev = pci_find_device(PCI_VENDOR_ID_INTEL,
|
||||
PCI_DEVICE_ID_INTEL_82801CA_1F0, 0);
|
||||
if (!dev) {
|
||||
printk_debug("*** ERROR Southbridge device %x not found\n",
|
||||
PCI_DEVICE_ID_INTEL_82801CA_1F0);
|
||||
return;
|
||||
}
|
||||
pci_read_config_dword(dev, GEN_CNTL, &dword);
|
||||
dword |= (3 << 7); /* enable ioapic */
|
||||
dword |= (1 <<13); /* coprocessor error enable */
|
||||
dword |= (1 << 1); /* delay transaction enable */
|
||||
dword |= (1 << 2); /* DMA collection buf enable */
|
||||
pci_write_config_dword(dev, GEN_CNTL, dword);
|
||||
printk_debug("ioapic southbridge enabled %x\n",dword);
|
||||
*ioapic_sba=0;
|
||||
*ioapic_sbd=(2<<24);
|
||||
*ioapic_sba=3;
|
||||
*ioapic_sbd=1;
|
||||
*ioapic_sba=0;
|
||||
dword=*ioapic_sbd;
|
||||
printk_debug("Southbridge apic id = %x\n",dword);
|
||||
if(dword!=(2<<24))
|
||||
for(;;);
|
||||
*ioapic_sba=3;
|
||||
dword=*ioapic_sbd;
|
||||
printk_debug("Southbridge apic DT = %x\n",dword);
|
||||
if(dword!=1)
|
||||
for(;;);
|
||||
|
||||
|
||||
}
|
||||
33
src/southbridge/intel/82801db/ich4_lpc.c
Normal file
33
src/southbridge/intel/82801db/ich4_lpc.c
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
#include <pci.h>
|
||||
#include <pci_ids.h>
|
||||
#include <southbridge/intel/82801.h>
|
||||
#include "82801.h"
|
||||
|
||||
void ich3_enable_serial_irqs(void)
|
||||
{
|
||||
struct pci_dev *dev;
|
||||
dev = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_1F0, 0);
|
||||
if (!dev) {
|
||||
return;
|
||||
}
|
||||
pci_write_config_byte(dev, SERIRQ_CNTL, (1 << 7)|(1 << 6)|((21 - 17) << 2)|(0 << 0));
|
||||
}
|
||||
|
||||
void ich3_lpc_route_dma(unsigned char mask)
|
||||
{
|
||||
struct pci_dev *dev;
|
||||
u16 word;
|
||||
int i;
|
||||
dev = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_1F0, 0);
|
||||
if (!dev) {
|
||||
return;
|
||||
}
|
||||
pci_read_config_word(dev, PCI_DMA_CFG, &word);
|
||||
word &= ((1 << 10) - (1 << 8));
|
||||
for(i = 0; i < 8; i++) {
|
||||
if (i == 4)
|
||||
continue;
|
||||
word |= ((mask & (1 << i))? 3:1) << (i*2);
|
||||
}
|
||||
pci_write_config_word(dev, PCI_DMA_CFG, word);
|
||||
}
|
||||
21
src/southbridge/intel/82801db/ich4_power.c
Normal file
21
src/southbridge/intel/82801db/ich4_power.c
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
#include <southbridge/intel/82801.h>
|
||||
#include <pci.h>
|
||||
#include <pci_ids.h>
|
||||
#include <printk.h>
|
||||
#include "82801.h"
|
||||
|
||||
void ich3_power_after_power_fail(int on)
|
||||
{
|
||||
struct pci_dev *dev;
|
||||
dev = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_1F0, 0);
|
||||
if (!dev) {
|
||||
return;
|
||||
}
|
||||
/* FIXME this doesn't work! */
|
||||
/* Which state do we want to goto after g3 (power restored)?
|
||||
* 0 == S0 Full On
|
||||
* 1 == S5 Soft Off
|
||||
*/
|
||||
pci_write_config_byte(dev, GEN_PMCON_3, on?0:1);
|
||||
printk_info("set power %s after power fail\n", on?"on":"off");
|
||||
}
|
||||
9
src/southbridge/intel/82801db/ich4_reset.c
Normal file
9
src/southbridge/intel/82801db/ich4_reset.c
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
#include <arch/io.h>
|
||||
#include <southbridge/intel/82801.h>
|
||||
|
||||
void ich3_hard_reset(void)
|
||||
{
|
||||
/* Try rebooting through port 0xcf9 */
|
||||
outb((0 <<3)|(1<<2)|(1<<1), 0xcf9);
|
||||
}
|
||||
|
||||
23
src/southbridge/intel/82801db/ich4_rtc.c
Normal file
23
src/southbridge/intel/82801db/ich4_rtc.c
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
#include <southbridge/intel/82801.h>
|
||||
#include <pc80/mc146818rtc.h>
|
||||
#include <pci.h>
|
||||
#include <pci_ids.h>
|
||||
#include <printk.h>
|
||||
#include "82801.h"
|
||||
|
||||
|
||||
void ich3_rtc_init(void)
|
||||
{
|
||||
unsigned char byte;
|
||||
u32 dword;
|
||||
int rtc_failed;
|
||||
pcibios_read_config_byte(RTC_BUS, RTC_DEVFN, GEN_PMCON_3, &byte);
|
||||
rtc_failed = byte & RTC_FAILED;
|
||||
if (rtc_failed) {
|
||||
byte &= ~(1 << 1); /* preserve the power fail state */
|
||||
pcibios_write_config_byte(RTC_BUS, RTC_DEVFN, GEN_PMCON_3, byte);
|
||||
}
|
||||
pcibios_read_config_dword(RTC_BUS, RTC_DEVFN, GEN_STS, &dword);
|
||||
rtc_failed |= dword & (1 << 2);
|
||||
rtc_init(rtc_failed);
|
||||
}
|
||||
185
src/southbridge/intel/82801db/ich4_smbus.c
Normal file
185
src/southbridge/intel/82801db/ich4_smbus.c
Normal file
|
|
@ -0,0 +1,185 @@
|
|||
#include <smbus.h>
|
||||
#include <arch/io.h>
|
||||
#include <pci.h>
|
||||
#include <southbridge/intel/82801.h>
|
||||
#include "82801.h"
|
||||
|
||||
void smbus_setup(void)
|
||||
{
|
||||
pcibios_write_config_dword(SMBUS_BUS, SMBUS_DEVFN, 0x20, SMBUS_IO_BASE | 1);
|
||||
pcibios_write_config_byte(SMBUS_BUS, SMBUS_DEVFN, 0x40, 1);
|
||||
pcibios_write_config_word(SMBUS_BUS, SMBUS_DEVFN, 0x4, 1);
|
||||
|
||||
/* Disable interrupt generation */
|
||||
outb(0, SMBUS_IO_BASE + SMBHSTCTL);
|
||||
}
|
||||
|
||||
static inline void smbus_delay(void)
|
||||
{
|
||||
outb(0x80, 0x80);
|
||||
}
|
||||
|
||||
static int smbus_wait_until_ready(void)
|
||||
{
|
||||
unsigned loops = SMBUS_TIMEOUT;
|
||||
unsigned char byte;
|
||||
do {
|
||||
smbus_delay();
|
||||
if (--loops == 0)
|
||||
break;
|
||||
byte = inb(SMBUS_IO_BASE + SMBHSTSTAT);
|
||||
} while(byte & 1);
|
||||
return loops?0:-1;
|
||||
}
|
||||
|
||||
static int smbus_wait_until_done(void)
|
||||
{
|
||||
unsigned loops = SMBUS_TIMEOUT;
|
||||
unsigned char byte;
|
||||
do {
|
||||
smbus_delay();
|
||||
if (--loops == 0)
|
||||
break;
|
||||
byte = inb(SMBUS_IO_BASE + SMBHSTSTAT);
|
||||
} while((byte & 1) || (byte & ~((1<<6)|(1<<0))) == 0);
|
||||
return loops?0:-1;
|
||||
}
|
||||
|
||||
static int smbus_wait_until_next(void)
|
||||
{
|
||||
unsigned loops = SMBUS_TIMEOUT;
|
||||
unsigned char byte;
|
||||
do {
|
||||
smbus_delay();
|
||||
if (--loops == 0)
|
||||
break;
|
||||
byte = inb(SMBUS_IO_BASE + SMBHSTSTAT);
|
||||
} while((byte & ~((1<<6)|(1<<1)|(1<<0))) == 0);
|
||||
return loops?0:-1;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void smbus_print_error(unsigned char host_status_register)
|
||||
{
|
||||
|
||||
printk_debug("smbus_error: 0x%02x\n", host_status_register);
|
||||
if (host_status_register & (1 << 7)) {
|
||||
printk_debug("Byte Done Status\n");
|
||||
}
|
||||
if (host_status_register & (1 << 6)) {
|
||||
printk_debug("In Use Status\n");
|
||||
}
|
||||
if (host_status_register & (1 << 5)) {
|
||||
printk_debug("SMBus Alert Status\n");
|
||||
}
|
||||
if (host_status_register & (1 << 4)) {
|
||||
printk_debug("Interrup/SMI# was Failed Bus Transaction\n");
|
||||
}
|
||||
if (host_status_register & (1 << 3)) {
|
||||
printk_debug("Bus Error\n");
|
||||
}
|
||||
if (host_status_register & (1 << 2)) {
|
||||
printk_debug("Device Error\n");
|
||||
}
|
||||
if (host_status_register & (1 << 1)) {
|
||||
printk_debug("Interrupt/SMI# was Successful Completion\n");
|
||||
}
|
||||
if (host_status_register & (1 << 0)) {
|
||||
printk_debug("Host Busy\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int smbus_read_byte(unsigned device, unsigned address, unsigned char *result)
|
||||
{
|
||||
unsigned char host_status_register;
|
||||
unsigned char byte;
|
||||
|
||||
if (smbus_wait_until_ready() < 0)
|
||||
return -1;
|
||||
|
||||
/* 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 + SMBXMITADD);
|
||||
/* 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 */
|
||||
if (smbus_wait_until_done() < 0)
|
||||
return -1;
|
||||
|
||||
host_status_register = inb(SMBUS_IO_BASE + SMBHSTSTAT);
|
||||
|
||||
/* Ignore the In Use Status... */
|
||||
host_status_register &= ~(1 << 6);
|
||||
|
||||
/* read results of transaction */
|
||||
byte = inb(SMBUS_IO_BASE + SMBHSTDAT0);
|
||||
|
||||
*result = byte;
|
||||
return host_status_register != 0x02;
|
||||
}
|
||||
|
||||
#if 0
|
||||
int smbus_read_block(unsigned device, unsigned address, unsigned bytes, unsigned char *results)
|
||||
{
|
||||
unsigned char host_status_register;
|
||||
unsigned char byte;
|
||||
int count;
|
||||
|
||||
if (smbus_wait_until_ready() < 0)
|
||||
return 0;
|
||||
|
||||
/* 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 + SMBXMITADD);
|
||||
/* set the command/address... */
|
||||
outb(address & 0xFF, SMBUS_IO_BASE + SMBHSTCMD);
|
||||
/* set up for a block data read/write */
|
||||
outb((inb(SMBUS_IO_BASE + SMBHSTCTL) & 0xE3) | (0x5 << 2), SMBUS_IO_BASE + SMBHSTCTL);
|
||||
|
||||
/* set the block count */
|
||||
outb(bytes & 0xff, SMBUS_IO_BASE + SMBHSTDAT0);
|
||||
|
||||
/* clear any lingering errors, so the transaction will run */
|
||||
outb(inb(SMBUS_IO_BASE + SMBHSTSTAT), SMBUS_IO_BASE + SMBHSTSTAT);
|
||||
|
||||
/* start the command */
|
||||
outb((inb(SMBUS_IO_BASE + SMBHSTCTL) | 0x40), SMBUS_IO_BASE + SMBHSTCTL);
|
||||
|
||||
for(count = 0; count < bytes; count++) {
|
||||
/* Wait until the controller has more data ready */
|
||||
if (smbus_wait_until_next() < 0) {
|
||||
break;
|
||||
}
|
||||
host_status_register = inb(SMBUS_IO_BASE + SMBHSTSTAT);
|
||||
|
||||
/* Test the status to see if an error occured */
|
||||
if (host_status_register & (1 << 7))
|
||||
break;
|
||||
|
||||
/* read the next byte */
|
||||
byte = inb(SMBUS_IO_BASE + SMBBLKDAT);
|
||||
results[count] = byte;
|
||||
|
||||
/* finish this byte read */
|
||||
outb((1<<7), SMBUS_IO_BASE + SMBHSTSTAT);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
#endif
|
||||
7
src/southbridge/intel/82801db/nvram.c
Normal file
7
src/southbridge/intel/82801db/nvram.c
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
#include <part/nvram.h>
|
||||
#include <printk.h>
|
||||
|
||||
void nvram_on(void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
129
src/southbridge/intel/82801db/smbus.inc
Normal file
129
src/southbridge/intel/82801db/smbus.inc
Normal file
|
|
@ -0,0 +1,129 @@
|
|||
/*
|
||||
* Copyright (C) 2002 Eric Biederman
|
||||
*/
|
||||
|
||||
#include "82801.h"
|
||||
|
||||
/* jump around these subrs */
|
||||
jmp smbus_end
|
||||
|
||||
/*
|
||||
* Routine: smbus_setup
|
||||
* Arguments: none
|
||||
* Results: none
|
||||
* Trashed: eax, edx, ecx
|
||||
* Effects: The smbus is enabled
|
||||
*/
|
||||
|
||||
smbus_setup:
|
||||
/* set smbus iobase */
|
||||
movl $((SMBUS_DEVFN << 8) + 0x20), %eax
|
||||
movl $(SMBUS_IO_BASE | 1), %ecx
|
||||
PCI_WRITE_CONFIG_DWORD
|
||||
|
||||
/* Set smbus enable */
|
||||
movl $((SMBUS_DEVFN << 8) + 0x40), %eax
|
||||
movl $1, %edx
|
||||
PCI_WRITE_CONFIG_BYTE
|
||||
|
||||
/* Set smbus iospace enable */
|
||||
movl $((SMBUS_DEVFN << 8) + 0x4), %eax
|
||||
movl $1, %ecx
|
||||
PCI_WRITE_CONFIG_WORD
|
||||
|
||||
/* Disable interrupt generation */
|
||||
movl $(SMBUS_IO_BASE + SMBHSTCTL), %edx
|
||||
xorl %eax, %eax
|
||||
outb %al, %dx
|
||||
|
||||
RET_LABEL(smbus_setup)
|
||||
|
||||
|
||||
/*
|
||||
* Routine: smbus_wait_until_ready
|
||||
* Arguments: none
|
||||
* Results: Carry set on timeout
|
||||
* Trashed: eax, edx
|
||||
* Effects: Upon return the smbus is ready to accept commands
|
||||
*/
|
||||
#define SMBUS_WAIT_UNTIL_READY() \
|
||||
movl $(SMBUS_TIMEOUT << 8), %eax ; \
|
||||
movl $(SMBUS_IO_BASE + SMBHSTSTAT), %edx ; \
|
||||
1: outb %al, $0x80 ; \
|
||||
inb %dx, %al ; \
|
||||
subl $0x00000100, %eax ; \
|
||||
testl $0xffffff00, %eax ; \
|
||||
stc ; \
|
||||
jz 2f ; \
|
||||
testb $(1<<0), %al ; \
|
||||
jnz 1b ; \
|
||||
clc ; \
|
||||
2:
|
||||
|
||||
/*
|
||||
* Routine: smbus_wait_until_done
|
||||
* Arguments: none
|
||||
* Results: carry set on timeout
|
||||
* Trashed: eax, edx
|
||||
* Effects: Upon return the smbus has completed it's most recent transation
|
||||
*/
|
||||
#define SMBUS_WAIT_UNTIL_DONE() \
|
||||
movl $(SMBUS_TIMEOUT << 8), %eax ; \
|
||||
movl $(SMBUS_IO_BASE + SMBHSTSTAT), %edx ; \
|
||||
1: outb %al, $0x80 ; \
|
||||
inb %dx, %al ; \
|
||||
subl $0x00000100, %eax ; \
|
||||
testl $0xffffff00, %eax ; \
|
||||
stc ; \
|
||||
jz 2f ; \
|
||||
testb $1, %al ; \
|
||||
jnz 1b ; \
|
||||
testb $~((1<<6)|(1<<0)), %al ; \
|
||||
jz 1b ; \
|
||||
clc ; \
|
||||
2:
|
||||
|
||||
/*
|
||||
* Routine: smbus_wait_until_next
|
||||
* Arguments: none
|
||||
* Results: al smbus status
|
||||
* edx status register addr
|
||||
* Trashed: eax, edx
|
||||
* Effects: Upon return the smbus is ready for the next byte
|
||||
*/
|
||||
#define SMBUS_WAIT_UNTIL_NEXT() \
|
||||
movl $(SMBUS_TIMEOUT << 8), %eax ; \
|
||||
movl $(SMBUS_IO_BASE + SMBHSTSTAT), %edx ; \
|
||||
1: outb %al, $0x80 ; \
|
||||
inb %dx, %al ; \
|
||||
subl $0x00000100, %eax ; \
|
||||
testl $0xffffff00, %eax ; \
|
||||
stc ; \
|
||||
jz 2f ; \
|
||||
testb $~((1<<6)|(1<<1)|(1<<0)), %al ; \
|
||||
jz 1b ; \
|
||||
clc ; \
|
||||
2:
|
||||
|
||||
/*
|
||||
* Routine: smbus_kill_command
|
||||
* Arguments: none
|
||||
* Results: none
|
||||
* Trashed: eax, edx, flags
|
||||
* Effects: Upon return the smbus is ready to accept commands
|
||||
*/
|
||||
|
||||
#define SMBUS_KILL_COMMAND() \
|
||||
movl $(SMBUS_IO_BASE + SMBHSTCTL), %edx ; \
|
||||
inb %dx, %al ; \
|
||||
orb $(1<<1), %al ; \
|
||||
outb %al, %dx ; \
|
||||
SMBUS_WAIT_UNTIL_DONE() ; \
|
||||
movl $(SMBUS_IO_BASE + SMBHSTCTL), %edx ; \
|
||||
inb %dx, %al ; \
|
||||
andb $~(1<<1), %al ; \
|
||||
outb %al, %dx
|
||||
|
||||
|
||||
smbus_end:
|
||||
CALL_LABEL(smbus_setup)
|
||||
83
src/southbridge/intel/82801db/smbus_noop_read_block.inc
Normal file
83
src/southbridge/intel/82801db/smbus_noop_read_block.inc
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
.section ".rom.data"
|
||||
|
||||
/* smbus read a block of data and discard it
|
||||
input: bl device, bh command, cl count,
|
||||
output: cf set on error
|
||||
*/
|
||||
smbus_noop_read_block:
|
||||
/* poll until the smbus is ready for commands */
|
||||
SMBUS_WAIT_UNTIL_READY()
|
||||
jc smbus_block_noop_read_error
|
||||
|
||||
/* setup transaction */
|
||||
/* disable interrupts */
|
||||
movl $(SMBUS_IO_BASE + SMBHSTCTL), %edx
|
||||
inb %dx, %al
|
||||
andb $0xFE, %al
|
||||
outb %al, %dx
|
||||
|
||||
/* set the device I'm talking to and specify a read */
|
||||
movl $(SMBUS_IO_BASE + SMBXMITADD), %edx
|
||||
movb %bl /* device */, %al
|
||||
shlb $1, %al
|
||||
orb $1, %al
|
||||
outb %al, %dx
|
||||
|
||||
/* set the command address... */
|
||||
movl $(SMBUS_IO_BASE + SMBHSTCMD), %edx
|
||||
movb %bh /* address */, %al
|
||||
outb %al, %dx
|
||||
|
||||
/* setup for a block data read/write */
|
||||
movl $(SMBUS_IO_BASE + SMBHSTCTL), %edx
|
||||
inb %dx, %al
|
||||
andb $0xE3, %al
|
||||
orb $(0x5 << 2), %al
|
||||
outb %al, %dx
|
||||
|
||||
/* set the block count */
|
||||
movl $(SMBUS_IO_BASE + SMBHSTDAT0), %edx
|
||||
movb %cl /* count */, %al
|
||||
outb %al, %dx
|
||||
|
||||
/* clear any lingering errors, so the transaction will run */
|
||||
movl $(SMBUS_IO_BASE + SMBHSTSTAT), %edx
|
||||
inb %dx, %al
|
||||
outb %al, %dx
|
||||
|
||||
/* start a block read, with interrupts disabled */
|
||||
movl $(SMBUS_IO_BASE + SMBHSTCTL), %edx
|
||||
inb %dx, %al
|
||||
orb $(1 << 6), %al
|
||||
outb %al, %dx
|
||||
|
||||
smbus_block_noop_read_next:
|
||||
/* wait until the controller has more data ready */
|
||||
SMBUS_WAIT_UNTIL_NEXT()
|
||||
jc smbus_block_noop_read_error
|
||||
|
||||
/* Test the results to see if we succeeded */
|
||||
testb $(1<<7), %al
|
||||
jz smbus_block_noop_read_error
|
||||
|
||||
/* read the next byte */
|
||||
movl $(SMBUS_IO_BASE + SMBBLKDAT), %edx
|
||||
inb %dx, %al
|
||||
|
||||
/* finish this byte read */
|
||||
movl $(SMBUS_IO_BASE + SMBHSTSTAT), %edx
|
||||
movb $(1<<7), %al
|
||||
outb %al, %dx
|
||||
decb %cl
|
||||
jnz smbus_block_noop_read_next
|
||||
|
||||
/* No error I am done */
|
||||
clc
|
||||
smbus_block_noop_read_end:
|
||||
RETSP
|
||||
smbus_block_noop_read_error:
|
||||
SMBUS_KILL_COMMAND()
|
||||
stc
|
||||
jmp smbus_block_noop_read_end
|
||||
|
||||
.previous
|
||||
86
src/southbridge/intel/82801db/smbus_print_block.inc
Normal file
86
src/southbridge/intel/82801db/smbus_print_block.inc
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
.section ".rom.data"
|
||||
|
||||
/* smbus print a block of data
|
||||
input: bl device, bh command, cl count,
|
||||
output: cf set on error
|
||||
trashed: eax,edx
|
||||
*/
|
||||
smbus_print_block:
|
||||
/* poll until the smbus is ready for commands */
|
||||
SMBUS_WAIT_UNTIL_READY()
|
||||
jc smbus_block_print_error
|
||||
|
||||
/* setup transaction */
|
||||
/* disable interrupts */
|
||||
movl $(SMBUS_IO_BASE + SMBHSTCTL), %edx
|
||||
inb %dx, %al
|
||||
andb $0xFE, %al
|
||||
outb %al, %dx
|
||||
|
||||
/* set the device I'm talking to and specify a read */
|
||||
movl $(SMBUS_IO_BASE + SMBXMITADD), %edx
|
||||
movb %bl /* device */, %al
|
||||
shlb $1, %al
|
||||
orb $1, %al
|
||||
outb %al, %dx
|
||||
|
||||
/* set the command address... */
|
||||
movl $(SMBUS_IO_BASE + SMBHSTCMD), %edx
|
||||
movb %bh /* address */, %al
|
||||
outb %al, %dx
|
||||
|
||||
/* setup for a block data read/write */
|
||||
movl $(SMBUS_IO_BASE + SMBHSTCTL), %edx
|
||||
inb %dx, %al
|
||||
andb $0xE3, %al
|
||||
orb $(0x5 << 2), %al
|
||||
outb %al, %dx
|
||||
|
||||
/* set the block count */
|
||||
movl $(SMBUS_IO_BASE + SMBHSTDAT0), %edx
|
||||
movb %cl /* count */, %al
|
||||
outb %al, %dx
|
||||
|
||||
/* clear any lingering errors, so the transaction will run */
|
||||
movl $(SMBUS_IO_BASE + SMBHSTSTAT), %edx
|
||||
inb %dx, %al
|
||||
outb %al, %dx
|
||||
|
||||
/* start a block read, with interrupts disabled */
|
||||
movl $(SMBUS_IO_BASE + SMBHSTCTL), %edx
|
||||
inb %dx, %al
|
||||
orb $(1 << 6), %al
|
||||
outb %al, %dx
|
||||
|
||||
smbus_block_print_next:
|
||||
/* wait until the controller has more data ready */
|
||||
SMBUS_WAIT_UNTIL_NEXT()
|
||||
jc smbus_block_print_error
|
||||
|
||||
/* Test the results to see if we succeeded */
|
||||
testb $(1<<7), %al
|
||||
jz smbus_block_print_error
|
||||
|
||||
/* read the next byte */
|
||||
movl $(SMBUS_IO_BASE + SMBBLKDAT), %edx
|
||||
inb %dx, %al
|
||||
CONSOLE_DEBUG_INLINE_TX_HEX8(%al)
|
||||
CONSOLE_DEBUG_INLINE_TX_CHAR($',')
|
||||
|
||||
/* finish this byte read */
|
||||
movl $(SMBUS_IO_BASE + SMBHSTSTAT), %edx
|
||||
movb $(1<<7), %al
|
||||
outb %al, %dx
|
||||
decb %cl
|
||||
jnz smbus_block_print_next
|
||||
|
||||
/* No error I am done */
|
||||
clc
|
||||
smbus_block_print_end:
|
||||
RETSP
|
||||
smbus_block_print_error:
|
||||
SMBUS_KILL_COMMAND()
|
||||
stc
|
||||
jmp smbus_block_print_end
|
||||
|
||||
.previous
|
||||
85
src/southbridge/intel/82801db/smbus_read_block.inc
Normal file
85
src/southbridge/intel/82801db/smbus_read_block.inc
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
.section ".rom.data"
|
||||
|
||||
/* smbus read a block of data
|
||||
input: bl device, bh command, cl count,
|
||||
esi pointer to data block
|
||||
output: cf set on error
|
||||
*/
|
||||
smbus_read_block:
|
||||
/* poll until the smbus is ready for commands */
|
||||
SMBUS_WAIT_UNTIL_READY()
|
||||
jc smbus_block_read_error
|
||||
|
||||
/* setup transaction */
|
||||
/* disable interrupts */
|
||||
movl $(SMBUS_IO_BASE + SMBHSTCTL), %edx
|
||||
inb %dx, %al
|
||||
andb $0xFE, %al
|
||||
outb %al, %dx
|
||||
|
||||
/* set the device I'm talking to and specify a read */
|
||||
movl $(SMBUS_IO_BASE + SMBXMITADD), %edx
|
||||
movb %bl /* device */, %al
|
||||
shlb $1, %al
|
||||
orb $1, %al
|
||||
outb %al, %dx
|
||||
|
||||
/* set the command address... */
|
||||
movl $(SMBUS_IO_BASE + SMBHSTCMD), %edx
|
||||
movb %bh /* address */, %al
|
||||
outb %al, %dx
|
||||
|
||||
/* setup for a block data read/write */
|
||||
movl $(SMBUS_IO_BASE + SMBHSTCTL), %edx
|
||||
inb %dx, %al
|
||||
andb $0xE3, %al
|
||||
orb $(0x5 << 2), %al
|
||||
outb %al, %dx
|
||||
|
||||
/* set the block count */
|
||||
movl $(SMBUS_IO_BASE + SMBHSTDAT0), %edx
|
||||
movb %cl /* count */, %al
|
||||
outb %al, %dx
|
||||
|
||||
/* clear any lingering errors, so the transaction will run */
|
||||
movl $(SMBUS_IO_BASE + SMBHSTSTAT), %edx
|
||||
inb %dx, %al
|
||||
outb %al, %dx
|
||||
|
||||
/* start a block read, with interrupts disabled */
|
||||
movl $(SMBUS_IO_BASE + SMBHSTCTL), %edx
|
||||
inb %dx, %al
|
||||
orb $(1 << 6), %al
|
||||
outb %al, %dx
|
||||
|
||||
smbus_block_read_next:
|
||||
/* wait until the controller has more data ready */
|
||||
SMBUS_WAIT_UNTIL_NEXT()
|
||||
jc smbus_block_read_error
|
||||
|
||||
/* Test the results to see if we succeeded */
|
||||
testb $(1<<7), %al
|
||||
jz smbus_block_read_error
|
||||
|
||||
/* read the next byte */
|
||||
movl $(SMBUS_IO_BASE + SMBBLKDAT), %edx
|
||||
inb %dx, %al
|
||||
stosb %al, (%esi)
|
||||
|
||||
/* finish this byte read */
|
||||
movl $(SMBUS_IO_BASE + SMBHSTSTAT), %edx
|
||||
movb $(1<<7), %al
|
||||
outb %al, %dx
|
||||
decb %cl
|
||||
jnz smbus_block_read_next
|
||||
|
||||
/* No error I am done */
|
||||
clc
|
||||
smbus_block_read_end:
|
||||
RETSP
|
||||
smbus_block_read_error:
|
||||
SMBUS_KILL_COMMAND()
|
||||
stc
|
||||
jmp smbus_block_noop_read_end
|
||||
|
||||
.previous
|
||||
91
src/southbridge/intel/82801db/smbus_read_byte.inc
Normal file
91
src/southbridge/intel/82801db/smbus_read_byte.inc
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
.section ".rom.data"
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#define SMBUS_READ_BYTE(device, address) \
|
||||
movl $( (device) | ((address) << 8)), %ebx ; \
|
||||
CALLSP(smbus_read_byte)
|
||||
|
||||
smbus_read_byte:
|
||||
/* poll until the smbus is ready for commands */
|
||||
SMBUS_WAIT_UNTIL_READY()
|
||||
jc smbus_read_byte_failed
|
||||
|
||||
/* setup transaction */
|
||||
/* disable interrupts */
|
||||
movl $(SMBUS_IO_BASE + SMBHSTCTL), %edx
|
||||
inb %dx, %al
|
||||
andb $0xFE, %al
|
||||
outb %al, %dx
|
||||
|
||||
/* set the device I'm talking to */
|
||||
movl $(SMBUS_IO_BASE + SMBXMITADD), %edx
|
||||
movb %bl /* device */, %al
|
||||
shlb $1, %al
|
||||
orb $1, %al
|
||||
outb %al, %dx
|
||||
|
||||
/* set the command address... */
|
||||
movl $(SMBUS_IO_BASE + SMBHSTCMD), %edx
|
||||
movb %bh /* address */, %al
|
||||
outb %al, %dx
|
||||
|
||||
/* setup for a byte data read */
|
||||
movl $(SMBUS_IO_BASE + SMBHSTCTL), %edx
|
||||
inb %dx, %al
|
||||
andb $0xE3, %al
|
||||
orb $(0x2 << 2), %al
|
||||
outb %al, %dx
|
||||
|
||||
/* clear any lingering errors, so the transaction will run */
|
||||
movl $(SMBUS_IO_BASE + SMBHSTSTAT), %edx
|
||||
inb %dx, %al
|
||||
outb %al, %dx
|
||||
|
||||
/* clear the data byte... */
|
||||
movl $(SMBUS_IO_BASE + SMBHSTDAT0), %edx
|
||||
xorl %eax, %eax
|
||||
outb %al, %dx
|
||||
|
||||
/* start a byte read, with interrupts disabled */
|
||||
movl $(SMBUS_IO_BASE + SMBHSTCTL), %edx
|
||||
inb %dx, %al
|
||||
orb $0x40, %al
|
||||
outb %al, %dx
|
||||
|
||||
/* poll for transaction completion */
|
||||
SMBUS_WAIT_UNTIL_DONE()
|
||||
jc smbus_read_byte_failed
|
||||
|
||||
/* read the results and see if we succeded */
|
||||
movl $(SMBUS_IO_BASE + SMBHSTSTAT), %edx
|
||||
inb %dx, %al
|
||||
andb $~(1 << 6), %al /* Ignore the In Use Status... */
|
||||
cmpb $0x02, %al
|
||||
jne smbus_read_byte_failed
|
||||
|
||||
movl $(SMBUS_IO_BASE + SMBHSTDAT0), %edx
|
||||
testl %edx, %edx /* clear zf */
|
||||
inb %dx, %al
|
||||
smbus_read_byte_done:
|
||||
RETSP
|
||||
smbus_read_byte_failed:
|
||||
SMBUS_KILL_COMMAND()
|
||||
xorl %eax, %eax /* set zf */
|
||||
jmp smbus_read_byte_done
|
||||
|
||||
.previous
|
||||
90
src/southbridge/intel/82801db/smbus_write_block.inc
Normal file
90
src/southbridge/intel/82801db/smbus_write_block.inc
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
.section ".rom.data"
|
||||
|
||||
/* smbus write a block of data
|
||||
input: bl device, bh command, cl count,
|
||||
esi pointer to data block
|
||||
output: cf set on error
|
||||
*/
|
||||
smbus_write_block:
|
||||
/* poll until the smbus is ready for commands */
|
||||
SMBUS_WAIT_UNTIL_READY()
|
||||
jc smbus_block_write_end
|
||||
|
||||
/* setup transaction */
|
||||
/* disable interrupts */
|
||||
movl $(SMBUS_IO_BASE + SMBHSTCTL), %edx
|
||||
inb %dx, %al
|
||||
andb $0xFE, %al
|
||||
outb %al, %dx
|
||||
|
||||
/* set the device I'm talking to, and specify a write */
|
||||
movl $(SMBUS_IO_BASE + SMBXMITADD), %edx
|
||||
movb %bl /* device */, %al
|
||||
shlb $1, %al
|
||||
orb $0, %al
|
||||
outb %al, %dx
|
||||
|
||||
/* set the command address... */
|
||||
movl $(SMBUS_IO_BASE + SMBHSTCMD), %edx
|
||||
movb %bh /* address */, %al
|
||||
outb %al, %dx
|
||||
|
||||
/* setup for block read/write */
|
||||
movl $(SMBUS_IO_BASE + SMBHSTCTL), %edx
|
||||
inb %dx, %al
|
||||
andb $0xE3, %al
|
||||
orb $(0x5 << 2), %al
|
||||
outb %al, %dx
|
||||
|
||||
/* set the block count */
|
||||
movl $(SMBUS_IO_BASE + SMBHSTDAT0), %edx
|
||||
movb %cl /* count */, %al
|
||||
outb %al, %dx
|
||||
|
||||
/* clear any lingering errors, so the transaction will run */
|
||||
movl $(SMBUS_IO_BASE + SMBHSTSTAT), %edx
|
||||
inb %dx, %al
|
||||
outb %al, %dx
|
||||
|
||||
/* load the data byte in the block data reg */
|
||||
cld
|
||||
movl $(SMBUS_IO_BASE + SMBBLKDAT), %edx
|
||||
lodsb (%esi), %al
|
||||
outb %al, %dx
|
||||
decb %cl
|
||||
|
||||
/* start a block write, with interrupts disabled */
|
||||
movl $(SMBUS_IO_BASE + SMBHSTCTL), %edx
|
||||
inb %dx, %al
|
||||
orb $0x40, %al
|
||||
outb %al, %dx
|
||||
|
||||
|
||||
smbus_block_write_next:
|
||||
/* wait until the controller is ready for more */
|
||||
SMBUS_WAIT_UNTIL_NEXT()
|
||||
jc smbus_block_write_end
|
||||
|
||||
/* Test the results to see if we succeeded */
|
||||
testb $(1<<7), %al
|
||||
stc
|
||||
jz smbus_block_write_end
|
||||
|
||||
/* load the next byte */
|
||||
movl $(SMBUS_IO_BASE + SMBBLKDAT), %edx
|
||||
lodsb (%esi), %al
|
||||
outb %al, %dx
|
||||
|
||||
/* start the next byte write */
|
||||
movl $(SMBUS_IO_BASE + SMBHSTSTAT), %edx
|
||||
movb $(1<<7), %al
|
||||
outb %al, %dx
|
||||
decb %cl
|
||||
jnz smbus_block_write_next
|
||||
|
||||
/* No error I am done */
|
||||
clc
|
||||
smbus_block_write_end:
|
||||
RETSP
|
||||
|
||||
.previous
|
||||
9
src/southbridge/intel/82801db/watchdog_disable.inc
Normal file
9
src/southbridge/intel/82801db/watchdog_disable.inc
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
/* Disable the TCO watch dog timer in the southbridge */
|
||||
/* bridge 0, device 1f, function 0, byte d4, bit 1 */
|
||||
|
||||
movl $0x8000f8d4,%eax
|
||||
movl $0x0cf8,%edx
|
||||
outl %eax,%dx
|
||||
movl $0x0cfc,%edx
|
||||
movb $2,%al
|
||||
outb %al,%dx
|
||||
Loading…
Add table
Add a link
Reference in a new issue