mirror of
https://github.com/fail0verflow/switch-coreboot.git
synced 2025-05-04 01:39:18 -04:00
src/northbridge/intel/E7500/{sync the directory}
src/ram/ramtest.inc{Add movnti ... } src/southbridge/intel/82801ca/{sync the directory} src/southbridge/intel/82870/{sync the directory} src/southbridge/via/vt8231/southgbridge.c - Transform intel_conf_xxx into pcibios_xxxx src/southbridge/via/v82c686/southgbridge.c - Transform intel_conf_xxx into pcibios_xxxx src/winbond/w83627hf/Config - Enable the hardware monitor - Add support for turning on the power_led util/config/NLBConfig.py - Add support for object <something>.c - Add support for object <something>.S - recode how the list of source files is built up. util/lb-dump/dump_lb_table.c - Fix the memory size abreviations
This commit is contained in:
parent
53be537588
commit
65bfc16139
27 changed files with 2657 additions and 1325 deletions
|
@ -1,9 +1,9 @@
|
|||
mainboardinit arch/i386/lib/set_memory_size_noop.inc
|
||||
#mainboardinit cpu/i786/enable_sse.inc
|
||||
mainboardinit arch/i386/lib/cpu_reset.inc
|
||||
mainboardinit northbridge/intel/E7500/raminit.inc
|
||||
mainboardinit northbridge/intel/E7500/sdram_enable.inc
|
||||
mainboardinit sdram/generic_sdram.inc
|
||||
#mainboardinit cpu/i786/disable_sse.inc
|
||||
mainboardinit sdram/generic_cache_linuxbios.inc
|
||||
|
||||
object northbridge.o
|
||||
#object rdram_setup.o
|
||||
#object rdram_debug.o
|
||||
|
|
|
@ -3,23 +3,71 @@
|
|||
#include <arch/io.h>
|
||||
#include <part/sizeram.h>
|
||||
#include <printk.h>
|
||||
#include <pc80/mc146818rtc.h>
|
||||
|
||||
struct mem_range *sizeram(void)
|
||||
{
|
||||
static struct mem_range mem[4];
|
||||
uint16_t tolm, remapbase, remaplimit;
|
||||
uint16_t tolm, remapbase, remaplimit, drb16;
|
||||
uint16_t tolm_r, remapbase_r, remaplimit_r;
|
||||
uint8_t drb;
|
||||
int remap_high;
|
||||
|
||||
/* FIXME do some of the configuration here instead of
|
||||
* just reading it all out, and reporting it.
|
||||
/* Calculate and report the top of low memory and
|
||||
* any remapping.
|
||||
*/
|
||||
/* Read the ram configruation registers */
|
||||
pcibios_read_config_word(0, 0, 0xc4, &tolm);
|
||||
pcibios_read_config_word(0, 0, 0xc6, &remapbase);
|
||||
remapbase &= 0x1FF;
|
||||
pcibios_read_config_word(0, 0, 0xc8, &remaplimit);
|
||||
remaplimit &= 0x1FF;
|
||||
/* Test if the remap memory high option is set */
|
||||
remap_high = 0;
|
||||
if(get_option(&remap_high, "remap_memory_high")){
|
||||
remap_high = 0;
|
||||
}
|
||||
pcibios_read_config_byte(0, 0, 0x67, &drb);
|
||||
drb16 = (uint16_t)drb;
|
||||
if(remap_high && (drb16 > 0x08)) {
|
||||
/* We only come here if we have at least 512MB of memory,
|
||||
* so it is safe to hard code tolm.
|
||||
*/
|
||||
tolm = 0x2000;
|
||||
if(drb16 > 0x0040) {
|
||||
/* There is more than 4GB of memory put
|
||||
* the remap window at the end of ram.
|
||||
*/
|
||||
remapbase = drb16;
|
||||
remaplimit = remapbase + 0x38;
|
||||
}
|
||||
else {
|
||||
remapbase = 0x0040;
|
||||
remaplimit = remapbase + (drb16-8);
|
||||
}
|
||||
}
|
||||
else {
|
||||
tolm = (uint16_t)((pci_memory_base >> 16)&0x0f800);
|
||||
if((tolm>>8) >= (drb16<<2)) {
|
||||
tolm = (drb16<<10);
|
||||
remapbase = 0x3ff;
|
||||
remaplimit = 0;
|
||||
}
|
||||
else {
|
||||
remapbase = drb16;
|
||||
remaplimit = remapbase + ((0x0040-(tolm>>10))-1);
|
||||
}
|
||||
}
|
||||
/* Write the ram configruation registers,
|
||||
* preserving the reserved bits.
|
||||
*/
|
||||
pcibios_read_config_word(0, 0, 0xc4, &tolm_r);
|
||||
tolm |= (tolm_r & 0x7ff);
|
||||
pcibios_write_config_word(0, 0, 0xc4, tolm);
|
||||
pcibios_read_config_word(0, 0, 0xc6, &remapbase_r);
|
||||
remapbase |= (remapbase_r & 0xfc00);
|
||||
pcibios_write_config_word(0, 0, 0xc6, remapbase);
|
||||
pcibios_read_config_word(0, 0, 0xc8, &remaplimit_r);
|
||||
remaplimit |= (remaplimit_r & 0xfc00);
|
||||
pcibios_write_config_word(0, 0, 0xc8, remaplimit);
|
||||
|
||||
#if 0
|
||||
printk_debug("mem info tolm = %x, drb = %x, pci_memory_base = %x, remap = %x-%x\n",tolm,drb,pci_memory_base,remapbase,remaplimit);
|
||||
#endif
|
||||
|
||||
mem[0].basek = 0;
|
||||
mem[0].sizek = 640;
|
||||
|
@ -29,14 +77,14 @@ struct mem_range *sizeram(void)
|
|||
mem[2].basek = 0;
|
||||
mem[2].sizek = 0;
|
||||
if ((drb << 16) > (tolm << 6)) {
|
||||
mem[2].basek = 4096*1024;
|
||||
mem[2].sizek = (drb << 16) - mem[2].basek;
|
||||
/* I know that the remap window always immediately follows
|
||||
* the real top of memory.
|
||||
/* We don't need to consider the remap window
|
||||
* here because we put it immediately after the
|
||||
* rest of ram.
|
||||
* All we must do is calculate the amount
|
||||
* of unused memory and report it at 4GB.
|
||||
*/
|
||||
if (remapbase < remaplimit) {
|
||||
mem[2].sizek = (remaplimit << 16) - mem[2].basek;
|
||||
}
|
||||
mem[2].basek = 4096*1024;
|
||||
mem[2].sizek = (drb << 16) - (tolm << 6);
|
||||
}
|
||||
mem[3].basek = 0;
|
||||
mem[3].sizek = 0;
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,10 +1,10 @@
|
|||
#define MCH_RICM 0x94
|
||||
#define RICM_DONE (1 << 27)
|
||||
#define MCH_DRC 0x7C
|
||||
#define DRC_IC (1 << 29)
|
||||
/* If I have already booted once skip a bunch of initialization */
|
||||
/* To see if I have already booted I check to see if memory
|
||||
* has been enabled.
|
||||
*/
|
||||
movl $MCH_RICM, %eax
|
||||
movl $MCH_DRC, %eax
|
||||
PCI_READ_CONFIG_DWORD
|
||||
testl $RICM_DONE, %eax
|
||||
testl $DRC_IC, %eax
|
||||
setnz %al
|
||||
|
|
|
@ -1,10 +1,42 @@
|
|||
jmp sdram_enable_out
|
||||
|
||||
#ifndef RAM_NOP
|
||||
#error RAM_NOP not defined
|
||||
#endif
|
||||
|
||||
#ifndef RAM_PRECHARGE
|
||||
#error RAM_PRECHARGE not defined
|
||||
#endif
|
||||
|
||||
#ifndef RAM_EMRS
|
||||
#error RAM_EMRS not defined
|
||||
#endif
|
||||
|
||||
#ifndef RAM_MRS
|
||||
#error RAM_MRS not defined
|
||||
#endif
|
||||
|
||||
#ifndef RAM_CBR
|
||||
#error RAM_CBR not defined
|
||||
#endif
|
||||
|
||||
#ifndef RAM_NORMAL
|
||||
#error RAM_NORMAL not defined
|
||||
#endif
|
||||
|
||||
#if ASM_CONSOLE_LOGLEVEL > BIOS_DEBUG
|
||||
ram_enable_1: .string "Ram Enable 1\r\n"
|
||||
ram_enable_2: .string "Ram Enable 2\r\n"
|
||||
ram_enable_3: .string "Ram Enable 3\r\n"
|
||||
ram_enable_4: .string "Ram Enable 4\r\n"
|
||||
ram_enable_5: .string "Ram Enable 5\r\n"
|
||||
ram_enable_6: .string "Ram Enable 6\r\n"
|
||||
ram_enable_7: .string "Ram Enable 7\r\n"
|
||||
ram_enable_8: .string "Ram Enable 8\r\n"
|
||||
ram_enable_9: .string "Ram Enable 9\r\n"
|
||||
ram_enable_10: .string "Ram Enable 10\r\n"
|
||||
ram_enable_11: .string "Ram Enable 11\r\n"
|
||||
#endif
|
||||
|
||||
/* Estimate that SLOW_DOWN_IO takes about 50&76us*/
|
||||
/* delay for 200us */
|
||||
|
@ -16,103 +48,85 @@ ram_enable_5: .string "Ram Enable 5\r\n"
|
|||
jnz 1b
|
||||
|
||||
|
||||
#define EXTRA_DELAY DO_DELAY
|
||||
|
||||
enable_sdram:
|
||||
/* now the fun begins.
|
||||
turn on the dram and wait a while (this from the intel book)
|
||||
turn power on and set the nop bit too
|
||||
*/
|
||||
CONSOLE_DEBUG_TX_STRING($ram_enable_1)
|
||||
/* 1 & 2 Power up and start clocks */
|
||||
CONSOLE_DEBUG_TX_STRING($ram_enable_1)
|
||||
CONSOLE_DEBUG_TX_STRING($ram_enable_2)
|
||||
|
||||
/* A 200us delay is needed */
|
||||
|
||||
DO_DELAY
|
||||
DO_DELAY
|
||||
/* Apply NOP */
|
||||
EXTRA_DELAY
|
||||
|
||||
SET_RAM_COMMAND(RAM_COMMAND_NOP)
|
||||
|
||||
ASSERT_RAM_COMMAND() /* nop command */
|
||||
DO_DELAY
|
||||
/* 3. Apply NOP */
|
||||
CONSOLE_DEBUG_TX_STRING($ram_enable_3)
|
||||
RAM_NOP()
|
||||
EXTRA_DELAY
|
||||
|
||||
/* 4 Precharge all */
|
||||
SET_RAM_COMMAND(RAM_COMMAND_PRECHARGE)
|
||||
ASSERT_RAM_COMMAND()
|
||||
CONSOLE_DEBUG_TX_STRING($ram_enable_4)
|
||||
RAM_PRECHARGE()
|
||||
EXTRA_DELAY
|
||||
|
||||
/* wait until the all banks idle state... */
|
||||
|
||||
CONSOLE_DEBUG_TX_STRING($ram_enable_2)
|
||||
DO_DELAY
|
||||
|
||||
/* 5. Issue EMRS to enable DLL */
|
||||
SET_RAM_COMMAND(RAM_COMMAND_EMRS)
|
||||
movl (0x0000<<MD_SHIFT), %eax
|
||||
DO_DELAY
|
||||
CONSOLE_DEBUG_TX_STRING($ram_enable_5)
|
||||
RAM_EMRS()
|
||||
EXTRA_DELAY
|
||||
|
||||
/* 6. Reset DLL */
|
||||
SET_RAM_COMMAND(RAM_COMMAND_MRS)
|
||||
#if 1
|
||||
movl (((1<<8)|(0<<7)|(5<<4)|(1<<3)|(2<<0))<<MD_SHIFT), %eax
|
||||
#else
|
||||
movl (((1<<8)|(0<<7)|(2<<4)|(1<<3)|(3<<0))<<MD_SHIFT), %eax
|
||||
#endif
|
||||
CONSOLE_DEBUG_TX_STRING($ram_enable_6)
|
||||
RAM_MRS(1)
|
||||
EXTRA_DELAY
|
||||
|
||||
/* Ensure a 200us delay between the DLL reset in step 6 and the final
|
||||
* mode register set in step 9.
|
||||
* Infineon needs this before any other command is sent to the ram.
|
||||
*/
|
||||
DO_DELAY
|
||||
EXTRA_DELAY
|
||||
|
||||
/* 7 Precharge all */
|
||||
SET_RAM_COMMAND(RAM_COMMAND_PRECHARGE)
|
||||
ASSERT_RAM_COMMAND()
|
||||
CONSOLE_DEBUG_TX_STRING($ram_enable_7)
|
||||
RAM_PRECHARGE()
|
||||
EXTRA_DELAY
|
||||
|
||||
DO_DELAY
|
||||
|
||||
/* 8 Now we need 8 AUTO REFRESH / CBR cycles to be performed */
|
||||
#if 0
|
||||
SET_RAM_COMMAND(RAM_COMMAND_CBR)
|
||||
ASSERT_RAM_COMMAND()
|
||||
ASSERT_RAM_COMMAND()
|
||||
ASSERT_RAM_COMMAND()
|
||||
ASSERT_RAM_COMMAND()
|
||||
ASSERT_RAM_COMMAND()
|
||||
ASSERT_RAM_COMMAND()
|
||||
ASSERT_RAM_COMMAND()
|
||||
ASSERT_RAM_COMMAND()
|
||||
#else
|
||||
SET_RAM_COMMAND(RAM_COMMAND_CBR)
|
||||
ASSERT_RAM_COMMAND()
|
||||
DO_DELAY
|
||||
SET_RAM_COMMAND(RAM_COMMAND_CBR)
|
||||
ASSERT_RAM_COMMAND()
|
||||
DO_DELAY
|
||||
#endif
|
||||
|
||||
CONSOLE_DEBUG_TX_STRING($ram_enable_3)
|
||||
/* 8 Now we need 2 AUTO REFRESH / CBR cycles to be performed */
|
||||
CONSOLE_DEBUG_TX_STRING($ram_enable_8)
|
||||
RAM_CBR()
|
||||
EXTRA_DELAY
|
||||
RAM_CBR()
|
||||
EXTRA_DELAY
|
||||
/* And for good luck 6 more CBRs */
|
||||
RAM_CBR()
|
||||
EXTRA_DELAY
|
||||
RAM_CBR()
|
||||
EXTRA_DELAY
|
||||
RAM_CBR()
|
||||
EXTRA_DELAY
|
||||
RAM_CBR()
|
||||
EXTRA_DELAY
|
||||
RAM_CBR()
|
||||
EXTRA_DELAY
|
||||
RAM_CBR()
|
||||
EXTRA_DELAY
|
||||
|
||||
/* 9 mode register set */
|
||||
SET_RAM_COMMAND(RAM_COMMAND_MRS)
|
||||
#if 1
|
||||
movl (((0<<8)|(0<<7)|(5<<4)|(1<<3)|(2<<0))<<MD_SHIFT), %eax
|
||||
#else
|
||||
movl (((0<<8)|(0<<7)|(2<<4)|(1<<3)|(3<<0))<<MD_SHIFT), %eax
|
||||
#endif
|
||||
DO_DELAY
|
||||
CONSOLE_DEBUG_TX_STRING($ram_enable_9)
|
||||
RAM_MRS(0)
|
||||
EXTRA_DELAY
|
||||
|
||||
/* MAx[14:0] lines,
|
||||
* MAx[2:0 ] 010 == burst mode of 4
|
||||
* MAx[3:3 ] 1 == interleave wrap type
|
||||
* MAx[6:4 ] 110 == CAS# latency bits
|
||||
* MAx[7:7 ] 0 == mode normal
|
||||
* MAx[8:8 ] 0 == DLL reset no
|
||||
* MAx[13:13 ] 0 == MRS
|
||||
* MAx[others] 0 == reserved
|
||||
*/
|
||||
/* 10 DDR Receive FIFO RE-Sync */
|
||||
CONSOLE_DEBUG_TX_STRING($ram_enable_10)
|
||||
RAM_RESET_DDR_PTR()
|
||||
EXTRA_DELAY
|
||||
|
||||
/* 11 normal operation */
|
||||
CONSOLE_DEBUG_TX_STRING($ram_enable_11)
|
||||
RAM_NORMAL()
|
||||
|
||||
CONSOLE_DEBUG_TX_STRING($ram_enable_4)
|
||||
|
||||
/* normal operation */
|
||||
SET_RAM_COMMAND(RAM_COMMAND_NORMAL)
|
||||
|
||||
CONSOLE_DEBUG_TX_STRING($ram_enable_5)
|
||||
#if 0
|
||||
1: nop
|
||||
jmp 1b
|
||||
#endif
|
||||
RET_LABEL(enable_sdram)
|
||||
|
||||
sdram_enable_out:
|
||||
|
|
|
@ -3,8 +3,9 @@
|
|||
* test than a "Is my SDRAM faulty?" test. Not all bits
|
||||
* are tested. -Tyson
|
||||
*/
|
||||
|
||||
|
||||
jmp rt_skip
|
||||
#if RAMTEST
|
||||
.section ".rom.data"
|
||||
|
||||
rt_test: .string "Testing SDRAM : "
|
||||
|
@ -13,9 +14,10 @@ rt_verify: .string "SDRAM verify:\r\n"
|
|||
rt_toomany: .string "Too many errors.\r\n"
|
||||
rt_done: .string "Done.\r\n"
|
||||
.previous
|
||||
#endif
|
||||
|
||||
ramtest:
|
||||
#ifdef RAMTEST
|
||||
#if RAMTEST
|
||||
mov %eax, %esi
|
||||
mov %ebx, %edi
|
||||
mov %esp, %ebp
|
||||
|
@ -42,7 +44,14 @@ ramtest:
|
|||
CONSOLE_INFO_TX_HEX32(%ebx)
|
||||
CONSOLE_INFO_TX_CHAR($'\r')
|
||||
2:
|
||||
#if i786
|
||||
/* Use a non temporal store to go faster and
|
||||
* to bypass the cache.
|
||||
*/
|
||||
movnti %ebx, (%ebx)
|
||||
#else
|
||||
mov %ebx, (%ebx)
|
||||
#endif
|
||||
add $4, %ebx
|
||||
cmp %edi, %ebx
|
||||
jl 1b
|
||||
|
|
95
src/ram/spotcheck.inc
Normal file
95
src/ram/spotcheck.inc
Normal file
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* This is much more of a "Is my SDRAM properly configured?"
|
||||
* test than a "Is my SDRAM faulty?" test. Not all bits
|
||||
* are tested. -Tyson
|
||||
*
|
||||
* Non temporal store and conversion to a spot check
|
||||
* so systems with extremely bad memory will give a reasonable
|
||||
* error message instead of freaking out. - Eric
|
||||
*/
|
||||
|
||||
.section ".rom.data"
|
||||
#ifndef CONFIG_MAX_SPOTCHECK_ERRORS
|
||||
#define CONFIG_MAX_SPOTCHECK_ERRORS 20
|
||||
#endif
|
||||
spot_test: .string " Spot checking: "
|
||||
spot_error: .string "Blatant memory errors found.\r\n"
|
||||
|
||||
/*
|
||||
* Routine: spot_check
|
||||
* Arguments: eax starting memory address
|
||||
* ebx ending memory address
|
||||
* esp return address
|
||||
* Results: Returns if no errors are found.
|
||||
* Trashed: eax, ebx, edx, esi, edi, ebp
|
||||
* Effects:
|
||||
*/
|
||||
|
||||
spot_check:
|
||||
movl %eax, %esi
|
||||
movl %ebx, %edi
|
||||
movl %esp, %ebp
|
||||
|
||||
CONSOLE_INFO_TX_STRING($spot_test)
|
||||
CONSOLE_INFO_TX_HEX32(%esi)
|
||||
CONSOLE_INFO_TX_CHAR($'-')
|
||||
CONSOLE_INFO_TX_HEX32(%edi)
|
||||
CONSOLE_INFO_TX_CHAR($'\r')
|
||||
CONSOLE_INFO_TX_CHAR($'\n')
|
||||
|
||||
/* =========== Fill ram block ======== */
|
||||
|
||||
movl %esi, %ebx
|
||||
1:
|
||||
/* Use a non temporal store to go faster and
|
||||
* to bypass the cache.
|
||||
*/
|
||||
movnti %ebx, (%ebx)
|
||||
addl $4, %ebx
|
||||
cmpl %edi, %ebx
|
||||
jl 1b
|
||||
|
||||
/* ========= Verify ram block ========== */
|
||||
|
||||
movl %esi, %ebx
|
||||
/* Keep error count in %esi */
|
||||
xorl %esi, %esi
|
||||
|
||||
1:
|
||||
cmpl %ebx, (%ebx)
|
||||
jne 4f
|
||||
3:
|
||||
addl $4, %ebx
|
||||
cmpl %edi, %ebx
|
||||
jl 1b
|
||||
jmp 6f
|
||||
|
||||
4:
|
||||
/* Display address with error */
|
||||
|
||||
CONSOLE_INFO_TX_HEX32(%ebx)
|
||||
CONSOLE_INFO_TX_CHAR($':')
|
||||
|
||||
/* Display data in address with error */
|
||||
|
||||
CONSOLE_INFO_INLINE_TX_HEX32(0(%ebx))
|
||||
|
||||
CONSOLE_INFO_TX_CHAR($'\r')
|
||||
CONSOLE_INFO_TX_CHAR($'\n')
|
||||
incl %esi
|
||||
cmpl $CONFIG_MAX_SPOTCHECK_ERRORS, %esi
|
||||
jbe 3b
|
||||
5:
|
||||
CONSOLE_INFO_TX_STRING($spot_error)
|
||||
intel_chip_post_macro(0xf1)
|
||||
jmp .Lhlt
|
||||
|
||||
6:
|
||||
/* If any memory errors occured hlt */
|
||||
testl %esi, %esi
|
||||
jnz 5b
|
||||
mov %ebp, %esp
|
||||
|
||||
RETSP
|
||||
|
||||
.previous
|
37
src/sdram/generic_dump_smbus.inc
Normal file
37
src/sdram/generic_dump_smbus.inc
Normal file
|
@ -0,0 +1,37 @@
|
|||
dump_smbus_registers:
|
||||
movl $((0 << 8) | 0x00), %ebx
|
||||
dump_smbus_reg_dimm:
|
||||
CONSOLE_DEBUG_TX_CHAR($'\r')
|
||||
CONSOLE_DEBUG_TX_CHAR($'\n')
|
||||
CONSOLE_DEBUG_TX_CHAR($'d')
|
||||
CONSOLE_DEBUG_TX_CHAR($'i')
|
||||
CONSOLE_DEBUG_TX_CHAR($'m')
|
||||
CONSOLE_DEBUG_TX_CHAR($'m')
|
||||
CONSOLE_DEBUG_TX_CHAR($' ')
|
||||
CONSOLE_DEBUG_TX_HEX8(%bl)
|
||||
CONSOLE_DEBUG_TX_CHAR($'\r')
|
||||
CONSOLE_DEBUG_TX_CHAR($'\n')
|
||||
dump_smbus_reg_byte:
|
||||
CALLSP(smbus_read_byte)
|
||||
jz dump_smbus_reg_next_dimm
|
||||
|
||||
CONSOLE_DEBUG_TX_HEX8(%al)
|
||||
CONSOLE_DEBUG_TX_CHAR($' ')
|
||||
incb %bh
|
||||
testb $0x0F, %bh
|
||||
jnz dump_smbus_reg_next_byte
|
||||
CONSOLE_DEBUG_TX_CHAR($'\r')
|
||||
CONSOLE_DEBUG_TX_CHAR($'\n')
|
||||
|
||||
dump_smbus_reg_next_byte:
|
||||
cmpb $0, %bh
|
||||
jne dump_smbus_reg_byte
|
||||
|
||||
dump_smbus_reg_next_dimm:
|
||||
CONSOLE_DEBUG_TX_CHAR($'\r')
|
||||
CONSOLE_DEBUG_TX_CHAR($'\n')
|
||||
xorb %bh, %bh
|
||||
addb $1, %bl
|
||||
cmpb $0x80, %bl
|
||||
jne dump_smbus_reg_dimm
|
||||
dump_smbus_registers_out:
|
|
@ -51,3 +51,8 @@
|
|||
#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)
|
||||
|
|
|
@ -14,22 +14,48 @@ void smbus_setup(void)
|
|||
outb(0, SMBUS_IO_BASE + SMBHSTCTL);
|
||||
}
|
||||
|
||||
static void smbus_wait_until_ready(void)
|
||||
static inline void smbus_delay(void)
|
||||
{
|
||||
while((inb(SMBUS_IO_BASE + SMBHSTSTAT) & 1) == 1) {
|
||||
/* nop */
|
||||
}
|
||||
outb(0x80, 0x80);
|
||||
}
|
||||
|
||||
static void smbus_wait_until_done(void)
|
||||
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) == 1);
|
||||
while( (byte & ~((1<<6)|(1<<0))) == 0) {
|
||||
} 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
|
||||
|
@ -69,7 +95,8 @@ int smbus_read_byte(unsigned device, unsigned address, unsigned char *result)
|
|||
unsigned char host_status_register;
|
||||
unsigned char byte;
|
||||
|
||||
smbus_wait_until_ready();
|
||||
if (smbus_wait_until_ready() < 0)
|
||||
return -1;
|
||||
|
||||
/* setup transaction */
|
||||
/* disable interrupts */
|
||||
|
@ -91,7 +118,8 @@ int smbus_read_byte(unsigned device, unsigned address, unsigned char *result)
|
|||
outb((inb(SMBUS_IO_BASE + SMBHSTCTL) | 0x40), SMBUS_IO_BASE + SMBHSTCTL);
|
||||
|
||||
/* poll for transaction completion */
|
||||
smbus_wait_until_done();
|
||||
if (smbus_wait_until_done() < 0)
|
||||
return -1;
|
||||
|
||||
host_status_register = inb(SMBUS_IO_BASE + SMBHSTSTAT);
|
||||
|
||||
|
@ -104,3 +132,54 @@ int smbus_read_byte(unsigned device, unsigned address, unsigned char *result)
|
|||
*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
|
||||
|
|
|
@ -3,6 +3,5 @@
|
|||
|
||||
void nvram_on(void)
|
||||
{
|
||||
printk_notice("Please turn on nvram\n");
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ smbus_setup:
|
|||
movl $1, %ecx
|
||||
PCI_WRITE_CONFIG_WORD
|
||||
|
||||
/* Diable interrupt generation */
|
||||
/* Disable interrupt generation */
|
||||
movl $(SMBUS_IO_BASE + SMBHSTCTL), %edx
|
||||
xorl %eax, %eax
|
||||
outb %al, %dx
|
||||
|
@ -42,120 +42,88 @@ smbus_setup:
|
|||
/*
|
||||
* Routine: smbus_wait_until_ready
|
||||
* Arguments: none
|
||||
* Results: none
|
||||
* Results: Carry set on timeout
|
||||
* Trashed: eax, edx
|
||||
* Effects: Upon return the smbus is ready to accept commands
|
||||
*/
|
||||
smbus_wait_until_ready:
|
||||
movl $(SMBUS_IO_BASE + SMBHSTSTAT), %edx
|
||||
1: inb %dx, %al
|
||||
testb $1, %al
|
||||
jnz 1b
|
||||
RET_LABEL(smbus_wait_until_ready)
|
||||
#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: none
|
||||
* Results: carry set on timeout
|
||||
* Trashed: eax, edx
|
||||
* Effects: Upon return the smbus has completed it's most recent transation
|
||||
*/
|
||||
smbus_wait_until_done:
|
||||
movl $(SMBUS_IO_BASE + SMBHSTSTAT), %edx
|
||||
1: inb %dx, %al
|
||||
testb $1, %al
|
||||
jnz 1b
|
||||
jmp 3f
|
||||
2:
|
||||
inb %dx, %al
|
||||
3: testb $~((1<<6)|(1<<0)), %al
|
||||
jz 2b
|
||||
RET_LABEL(smbus_wait_until_done)
|
||||
|
||||
#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_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
|
||||
* 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_READ_BYTE(device, address) \
|
||||
movl $( (device) | ((address) << 8)), %ebx ; \
|
||||
CALLSP(smbus_read_byte)
|
||||
|
||||
smbus_read_byte:
|
||||
/* poll until the smbus is ready for commands */
|
||||
CALL_LABEL(smbus_wait_until_ready)
|
||||
|
||||
/* setup transaction */
|
||||
/* disable interrupts */
|
||||
movl $(SMBUS_IO_BASE + SMBHSTCTL), %edx
|
||||
inb %dx, %al
|
||||
andb $0xFE, %al
|
||||
#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
|
||||
|
||||
/* 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 */
|
||||
CALL_LABEL(smbus_wait_until_done)
|
||||
|
||||
/* 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
|
||||
sete %al
|
||||
testb %al, %al
|
||||
jz 1f
|
||||
|
||||
movl $(SMBUS_IO_BASE + SMBHSTDAT0), %edx
|
||||
inb %dx, %al
|
||||
1:
|
||||
RETSP
|
||||
|
||||
|
||||
|
||||
smbus_end:
|
||||
CALL_LABEL(smbus_setup)
|
||||
|
|
83
src/southbridge/intel/82801ca/smbus_noop_read_block.inc
Normal file
83
src/southbridge/intel/82801ca/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/82801ca/smbus_print_block.inc
Normal file
86
src/southbridge/intel/82801ca/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
|
91
src/southbridge/intel/82801ca/smbus_read_block.inc
Normal file
91
src/southbridge/intel/82801ca/smbus_read_block.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/82801ca/smbus_write_block.inc
Normal file
90
src/southbridge/intel/82801ca/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
|
|
@ -1,5 +1,10 @@
|
|||
/* for io apic 1461 */
|
||||
#define PCICMD 0x04
|
||||
#define SUBSYS 0x2c
|
||||
#define MBAR 0x10
|
||||
#define ABAR 0x40
|
||||
|
||||
/* for pci bridge 1460 */
|
||||
#define MTT 0x042
|
||||
#define HCCR 0x0f0
|
||||
#define ACNF 0x0e0
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
object p64h2_ioapic.o
|
||||
object p64h2_pcibridge.o
|
||||
|
|
|
@ -10,71 +10,62 @@ void p64h2_enable_ioapic(void)
|
|||
struct pci_dev *dev;
|
||||
u32 dword;
|
||||
u16 word;
|
||||
int i;
|
||||
volatile u32 *ioapic_1a=0xfec80000;
|
||||
volatile u32 *ioapic_1d=0xfec80010;
|
||||
volatile u32 *ioapic_2a=0xfec80400;
|
||||
volatile u32 *ioapic_2d=0xfec80410;
|
||||
int i,addr;
|
||||
|
||||
volatile u32 *ioapic_a; /* io apic io memory space command address */
|
||||
volatile u32 *ioapic_d; /* io apic io memory space data address */
|
||||
|
||||
|
||||
for(i=0,dev=0;i<4;i++) {
|
||||
for(i=0,dev=0;i<4;i++) {
|
||||
if(i<3) /* io apic address numbers are 3,4,5,&8 */
|
||||
addr=i+3;
|
||||
else
|
||||
addr=i+5;
|
||||
/* find the next pci io apic p64h2 - 1461 */
|
||||
dev = pci_find_device(PCI_VENDOR_ID_INTEL,
|
||||
PCI_DEVICE_ID_INTEL_82870_1F0, dev);
|
||||
PCI_DEVICE_ID_INTEL_82870_1E0, dev);
|
||||
if (!dev) {
|
||||
if(i<2)
|
||||
if(i<2) /* there should be at least 2 */
|
||||
printk_debug("*** ERROR Southbridge device %x not found\n",
|
||||
PCI_DEVICE_ID_INTEL_82870_1F0);
|
||||
PCI_DEVICE_ID_INTEL_82870_1E0);
|
||||
break;
|
||||
}
|
||||
// pci_read_config_dword(dev, GEN_CNTL, &dword);
|
||||
/* Read the MBAR address for setting up the io apic in io memory space */
|
||||
pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &dword);
|
||||
ioapic_a=dword;
|
||||
ioapic_d = ioapic_a +0x04;
|
||||
printk_debug("IOAPIC %d at %02x:%02x.%01x MBAR = %x DataAddr = %x\n",
|
||||
addr, dev->bus->secondary,
|
||||
PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn),
|
||||
ioapic_a, ioapic_d);
|
||||
word = 0x0146;
|
||||
pci_write_config_word(dev, PCICMD, word);
|
||||
dword = 0x358015d9;
|
||||
pci_write_config_dword(dev, SUBSYS, dword);
|
||||
if(i==0){
|
||||
dword = 0xfc100000;
|
||||
pci_write_config_dword(dev, MBAR, dword);
|
||||
word = 0x8804;
|
||||
pci_write_config_word(dev, ABAR, word);
|
||||
}
|
||||
if(i==1){
|
||||
dword = 0xfc101000;
|
||||
pci_write_config_dword(dev, MBAR, dword);
|
||||
word = 0x8800;
|
||||
pci_write_config_word(dev, ABAR, word);
|
||||
}
|
||||
#if 0
|
||||
/* writing to the ABAR is removed here because there is a hardware
|
||||
error on the super micro boards, and it is not needed. */
|
||||
dword = (u32)ioapic_a;
|
||||
word = 0x8000 + ((dword >>8)&0x0fff);
|
||||
pci_write_config_word(dev, ABAR, word);
|
||||
#endif
|
||||
/* Set up the io apic for the p64h2 - 1461 */
|
||||
*ioapic_a=0;
|
||||
*ioapic_d=(addr<<24); /* Set the address number */
|
||||
*ioapic_a=3;
|
||||
*ioapic_d=1; /* Enable the io apic */
|
||||
|
||||
/* This code test the setup to see if we really found the io apic */
|
||||
*ioapic_a=0;
|
||||
dword=*ioapic_d;
|
||||
printk_debug("PCI %d apic id = %x\n",addr,dword);
|
||||
if(dword!=(addr<<24))
|
||||
for(;;);
|
||||
*ioapic_a=3;
|
||||
dword=*ioapic_d;
|
||||
printk_debug("PCI %d apic DT = %x\n",addr,dword);
|
||||
if(dword!=1)
|
||||
for(;;);
|
||||
|
||||
}
|
||||
|
||||
*ioapic_1a=0;
|
||||
*ioapic_1d=(3<<24);
|
||||
*ioapic_1a=3;
|
||||
*ioapic_1d=1;
|
||||
*ioapic_1a=0;
|
||||
dword=*ioapic_1d;
|
||||
printk_debug("PCI 1 apic id = %x\n",dword);
|
||||
if(dword!=(3<<24))
|
||||
for(;;);
|
||||
*ioapic_1a=3;
|
||||
dword=*ioapic_1d;
|
||||
printk_debug("PCI 1 apic DT = %x\n",dword);
|
||||
if(dword!=1)
|
||||
for(;;);
|
||||
|
||||
*ioapic_2a=0;
|
||||
*ioapic_2d=(4<<24);
|
||||
*ioapic_2a=3;
|
||||
*ioapic_2d=1;
|
||||
*ioapic_2a=0;
|
||||
dword=*ioapic_2d;
|
||||
printk_debug("PCI 2 apic id = %x\n",dword);
|
||||
if(dword!=(4<<24))
|
||||
for(;;);
|
||||
*ioapic_2a=3;
|
||||
dword=*ioapic_2d;
|
||||
printk_debug("PCI 2 apic DT = %x\n",dword);
|
||||
if(dword!=1)
|
||||
for(;;);
|
||||
|
||||
|
||||
}
|
||||
|
|
38
src/southbridge/intel/82870/p64h2_pcibridge.c
Normal file
38
src/southbridge/intel/82870/p64h2_pcibridge.c
Normal file
|
@ -0,0 +1,38 @@
|
|||
#include <pci.h>
|
||||
#include <arch/io.h>
|
||||
#include <printk.h>
|
||||
#include <pci_ids.h>
|
||||
#include <southbridge/intel/82801.h>
|
||||
#include "82870.h"
|
||||
|
||||
void p64h2_setup_pcibridge(void)
|
||||
{
|
||||
struct pci_dev *dev;
|
||||
u32 dword;
|
||||
u16 word;
|
||||
u8 byte;
|
||||
int i;
|
||||
|
||||
|
||||
for(i=0,dev=0;i<4;i++) {
|
||||
/* find the next pci bridge p64h2 - 1460 */
|
||||
dev = pci_find_device(PCI_VENDOR_ID_INTEL,
|
||||
PCI_DEVICE_ID_INTEL_82870_1F0, dev);
|
||||
if (!dev) {
|
||||
if(i<2) /* there should be at least 2 */
|
||||
printk_debug("*** ERROR Southbridge device %x not found\n",
|
||||
PCI_DEVICE_ID_INTEL_82870_1F0);
|
||||
break;
|
||||
}
|
||||
/* The purpose of changes to HCCR, ACNF, and MTT is to speed up the
|
||||
PCI bus for cards having high speed transfers. */
|
||||
dword = 0xc2040002;
|
||||
pci_write_config_dword(dev, HCCR, dword);
|
||||
dword = 0x0000c3bf;
|
||||
pci_write_config_dword(dev, ACNF, dword);
|
||||
byte = 0x08;
|
||||
pci_write_config_byte(dev, MTT, byte);
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -6,24 +6,24 @@ void keyboard_on()
|
|||
{
|
||||
volatile unsigned char regval;
|
||||
|
||||
/* regval = intel_conf_readb(0x80008851); */
|
||||
/* pcibios_read_config_byte(0, 0x88, 0x51, ®val); */
|
||||
/*regval |= 0x01; */
|
||||
regval = 0xcf;
|
||||
intel_conf_writeb(0x80008851, regval);
|
||||
pcibios_write_config_byte(0, 0x88, 0x51, regval);
|
||||
|
||||
/* disable USB1 */
|
||||
intel_conf_writeb(0x80008A3C, 0x00);
|
||||
intel_conf_writeb(0x80008A04, 0x00);
|
||||
regval = intel_conf_readb(0x80008850);
|
||||
pcibios_write_config_byte(0, 0x8A, 0x3c, 0x00);
|
||||
pcibios_write_config_byte(0, 0x8A, 0x04, 0x00);
|
||||
pcibios_read_config_byte(0, 0x88, 0x50, ®val);
|
||||
regval |= 0x10;
|
||||
intel_conf_writeb(0x80008850, regval);
|
||||
pcibios_read_config_byte(0, 0x88, 0x50, regval);
|
||||
|
||||
/* disable USB2 */
|
||||
intel_conf_writeb(0x80008B3C, 0x00);
|
||||
intel_conf_writeb(0x80008B04, 0x00);
|
||||
regval = intel_conf_readb(0x80008850);
|
||||
pcibios_write_config_byte(0, 0x8B, 0x3c, 0x00);
|
||||
pcibios_write_config_byte(0, 0x8B, 0x04, 0x00);
|
||||
pcibios_read_config_byte(0, 0x88, 0x50, ®val);
|
||||
regval |= 0x20;
|
||||
intel_conf_writeb(0x80008850, regval);
|
||||
pcibios_write_config_byte(0, 0x88, 0x50, regval);
|
||||
|
||||
pc_keyboard_init();
|
||||
|
||||
|
@ -34,7 +34,7 @@ void nvram_on()
|
|||
/* the VIA 686A South has a very different nvram setup than the piix4e ... */
|
||||
/* turn on ProMedia nvram. */
|
||||
/* TO DO: use the PciWriteByte function here. */
|
||||
intel_conf_writeb(0x80008841, 0xFF);
|
||||
pcibios_write_config_byte(0, 0x88, 0x41, 0xff);
|
||||
}
|
||||
|
||||
void southbridge_fixup()
|
||||
|
|
|
@ -9,7 +9,7 @@ void keyboard_on()
|
|||
struct pci_dev *dev;
|
||||
|
||||
printk_debug("keyboard_on\n");
|
||||
/* regval = intel_conf_readb(0x8000385A); */
|
||||
/* pcibios_read_config_byte(0, 0x38, 0x5A, ®val); */
|
||||
/*regval |= 0x01; */
|
||||
regval = 0xff;
|
||||
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
dir /src/superio/generic
|
||||
object w83627hf_power.o
|
||||
object power_led.o
|
||||
|
|
22
src/superio/winbond/w83627hf/power_led.c
Normal file
22
src/superio/winbond/w83627hf/power_led.c
Normal file
|
@ -0,0 +1,22 @@
|
|||
#include <superio/generic.h>
|
||||
#include <superio/w83627hf.h>
|
||||
|
||||
void power_led(int state)
|
||||
{
|
||||
unsigned char byte;
|
||||
|
||||
w83627hf_enter_pnp(SIO_BASE);
|
||||
pnp_set_logical_device(SIO_BASE, GPIO_PORT3_DEVICE);
|
||||
pnp_set_enable(SIO_BASE, 1);
|
||||
|
||||
/* Enable power LED */
|
||||
byte = pnp_read_config(SIO_BASE, 0xf3);
|
||||
byte &= ~(3 << 6);
|
||||
byte |= state;
|
||||
pnp_write_config(SIO_BASE, byte, 0xf3);
|
||||
|
||||
w83627hf_exit_pnp(SIO_BASE);
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -111,6 +111,19 @@ static void setup_keyboard(struct superio *sio)
|
|||
}
|
||||
}
|
||||
|
||||
static void setup_hw_monitor(struct superio *sio)
|
||||
{
|
||||
unsigned iobase0 = HW_MONITOR_DEFAULT_IOBASE0;
|
||||
/* Select the device */
|
||||
pnp_set_logical_device(sio->port, HW_MONITOR_DEVICE);
|
||||
/* Disable it while initializing */
|
||||
pnp_set_enable(sio->port, 0);
|
||||
if (sio->hwmonitor) {
|
||||
pnp_set_iobase0(sio->port, iobase0);
|
||||
pnp_set_enable(sio->port, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
static void setup_acpi_registers(struct superio *sio)
|
||||
|
@ -177,8 +190,7 @@ static void enable_devices(struct superio *sio)
|
|||
pnp_set_enable(sio->port, sio->acpi);
|
||||
|
||||
/* enable/disable hw monitor */
|
||||
pnp_set_logical_device(sio->port, HW_MONITOR_DEVICE);
|
||||
pnp_set_enable(sio->port, sio->hwmonitor);
|
||||
setup_hw_monitor(sio);
|
||||
|
||||
#if 0
|
||||
/* setup acpi registers so I am certain to get
|
||||
|
|
|
@ -40,6 +40,7 @@ makerule_targets = []
|
|||
treetop = ''
|
||||
target_dir = ''
|
||||
|
||||
sources = []
|
||||
objectrules = []
|
||||
userdefines = []
|
||||
|
||||
|
@ -116,8 +117,8 @@ def add_main_rule_dependency(new_dependency):
|
|||
# and an optional rule (can be empty) for actually building
|
||||
# the object
|
||||
def addobject(object, sourcepath, rule, condition, variable):
|
||||
objectrules.append([object, topify(sourcepath),
|
||||
rule, condition, variable])
|
||||
sourcepath = topify(sourcepath)
|
||||
objectrules.append([object, sourcepath, rule, condition, variable])
|
||||
|
||||
# OK, let's face it, make sucks.
|
||||
# if you have a rule like this:
|
||||
|
@ -125,8 +126,26 @@ def addobject(object, sourcepath, rule, condition, variable):
|
|||
# make won't apply the .c.o rule. Toy!
|
||||
|
||||
def addobject_defaultrule(object, sourcepath, condition, variable):
|
||||
# defaultrule = "\t $(CC) -c $(CFLAGS) -o $@ $<"
|
||||
defaultrule = "\t@echo $(CC) ... -o $@ $<\n\t@$(CC) -c $(CFLAGS) -o $@ $<"
|
||||
# c_defaultrule = "$(CC) -c $(CFLAGS) -o $@ $<"
|
||||
c_defaultrule = "@echo $(CC) ... -o $@ $<\n\t@$(CC) -c $(CFLAGS) -o $@ $<"
|
||||
s_defaultrule = "@echo $(CC) ... -o $@ $<\n\t@$(CC) -c $(CPU_OPT) -o $@ $<"
|
||||
S_defaultrule = "@echo $(CPP) ... $< > $@\n\t@$(CPP) $(CPPFLAGS) $< >$@.new && mv $@.new $@"
|
||||
# Compute the source file name
|
||||
if (sourcepath[-2:] != '.c') and (sourcepath[-2:] != '.S'):
|
||||
base = object[:-2]
|
||||
sourcepath = os.path.join(sourcepath, base) + '.c'
|
||||
|
||||
sources.append(sourcepath)
|
||||
if (sourcepath[-2:] == '.c'):
|
||||
defaultrule = "\t" + c_defaultrule
|
||||
elif (sourcepath[-2:] == '.S'):
|
||||
base = os.path.basename(sourcepath)
|
||||
s_name = base[:-2] + '.s'
|
||||
mkrule(s_name, sourcepath, [ S_defaultrule ] )
|
||||
sourcepath = s_name
|
||||
defaultrule = "\t" + s_defaultrule
|
||||
else:
|
||||
fatal("Invalid object suffix")
|
||||
addobject(object, sourcepath, defaultrule, condition, variable)
|
||||
|
||||
|
||||
|
@ -426,7 +445,14 @@ def ldscript(dir, command):
|
|||
#
|
||||
def object(dir, command):
|
||||
(obj_name, condition) = match(splitargs_re, command)
|
||||
addobject_defaultrule(obj_name, dir, condition, 'OBJECTS')
|
||||
if (obj_name[-2:] == '.c') or (obj_name[-2:] == '.S'):
|
||||
source_name = os.path.join(dir, obj_name)
|
||||
obj_name = obj_name[:-2] + '.o'
|
||||
elif (obj_name[-2:] == '.o'):
|
||||
source_name = os.path.join(dir, obj_name[:-2] + '.c')
|
||||
else:
|
||||
fatal("Invalid object name")
|
||||
addobject_defaultrule(obj_name, source_name, condition, 'OBJECTS')
|
||||
|
||||
# COMMAND: driver <path-to-source> [<condition>]
|
||||
#
|
||||
|
@ -1053,6 +1079,8 @@ CPUFLAGS := $(foreach _var_,$(VARIABLES),$(call D_item,$(_var_)))
|
|||
|
||||
|
||||
file.write("\nSOURCES=\n")
|
||||
for source in sources:
|
||||
file.write("SOURCES += %s\n" % source)
|
||||
|
||||
# Print out the user defines.
|
||||
file.write("\n# userdefines:\n")
|
||||
|
@ -1074,10 +1102,6 @@ CPUFLAGS := $(foreach _var_,$(VARIABLES),$(call D_item,$(_var_)))
|
|||
file.write("\n# objectrules:\n")
|
||||
for objrule in objectrules:
|
||||
source = objrule[1]
|
||||
if (source[-2:] != '.c'): # no suffix. Build name.
|
||||
base = objrule[0][:-2]
|
||||
source = os.path.join(source, base) + ".c"
|
||||
file.write("\nSOURCES += %s\n" % source)
|
||||
file.write("%s: %s\n" % (objrule[0], source))
|
||||
file.write("%s\n" % objrule[2])
|
||||
|
||||
|
|
|
@ -107,16 +107,16 @@ void nop_print(struct lb_record *rec, unsigned long addr)
|
|||
|
||||
void pretty_print_number(FILE *stream, uint64_t value)
|
||||
{
|
||||
if (value > 1024ULL*1024*1024*1024*1024) {
|
||||
value /= 1024ULL*1024*1024*1024*1024;
|
||||
if (value > 1024ULL*1024*1024*1024*1024*1024) {
|
||||
value /= 1024ULL*1024*1024*1024*1024*1024;
|
||||
fprintf(stream, "%lldEB", value);
|
||||
}
|
||||
else if (value > 1024ULL*1024*1024*1024*1024) {
|
||||
value /= 1024ULL*1024*1024*1024*1024;
|
||||
fprintf(stream, "%lldPB", value);
|
||||
}
|
||||
else if (value > 1024ULL*1024*1024*1024) {
|
||||
value /= 1024ULL*1024*1024*1024;
|
||||
fprintf(stream, "%lldPB", value);
|
||||
}
|
||||
else if (value > 1024ULL*1024*1024) {
|
||||
value /= 1024ULL*1024*1024;
|
||||
fprintf(stream, "%lldTB", value);
|
||||
}
|
||||
else if (value > 1024ULL*1024*1024) {
|
||||
|
|
Loading…
Add table
Reference in a new issue