diff options
Diffstat (limited to 'src/southbridge/sis/sis966/sis966_early_smbus.c')
-rw-r--r-- | src/southbridge/sis/sis966/sis966_early_smbus.c | 172 |
1 files changed, 170 insertions, 2 deletions
diff --git a/src/southbridge/sis/sis966/sis966_early_smbus.c b/src/southbridge/sis/sis966/sis966_early_smbus.c index 3d4954b64f..1c81bf16fd 100644 --- a/src/southbridge/sis/sis966/sis966_early_smbus.c +++ b/src/southbridge/sis/sis966/sis966_early_smbus.c @@ -23,6 +23,174 @@ #define SMBUS0_IO_BASE 0x8D0 +static inline void smbus_delay(void) +{ + outb(0x80, 0x80); +} + +int smbus_wait_until_ready(unsigned smbus_io_base) +{ + unsigned long loops; + loops = SMBUS_TIMEOUT; + do { + unsigned char val; + smbus_delay(); + val = inb(smbus_io_base + SMBHSTSTAT); + val &= 0x1f; + if (val == 0) { + return 0; + } + outb(val,smbus_io_base + SMBHSTSTAT); + } while(--loops); + return -2; +} + +int smbus_wait_until_done(unsigned smbus_io_base) +{ + unsigned long loops; + loops = SMBUS_TIMEOUT; + do { + unsigned char val; + smbus_delay(); + + val = inb(smbus_io_base + 0x00); + if ( (val & 0xff) != 0x02) { + return 0; + } + } while(--loops); + return -3; +} + +int do_smbus_recv_byte(unsigned smbus_io_base, unsigned device) +{ + unsigned char global_status_register; + unsigned char byte; + + /* set the device I'm talking too */ + outb(((device & 0x7f) << 1)|1 , smbus_io_base + SMBXMITADD); + smbus_delay(); + + /* byte data recv */ + outb(0x05, smbus_io_base + SMBHSTPRTCL); + smbus_delay(); + + /* poll for transaction completion */ + if (smbus_wait_until_done(smbus_io_base) < 0) { + return -3; + } + + global_status_register = inb(smbus_io_base + SMBHSTSTAT) & 0x80; /* lose check */ + + /* read results of transaction */ + byte = inb(smbus_io_base + SMBHSTCMD); + + if (global_status_register != 0x80) { // lose check, otherwise it should be 0 + return -1; + } + return byte; +} + +int do_smbus_send_byte(unsigned smbus_io_base, unsigned device, unsigned char val) +{ + unsigned global_status_register; + + outb(val, smbus_io_base + SMBHSTDAT0); + smbus_delay(); + + /* set the command... */ + outb(val, smbus_io_base + SMBHSTCMD); + smbus_delay(); + + /* set the device I'm talking too */ + outb(((device & 0x7f) << 1) | 0, smbus_io_base + SMBXMITADD); + smbus_delay(); + + /* set up for a byte data write */ + outb(0x04, smbus_io_base + SMBHSTPRTCL); + smbus_delay(); + + /* poll for transaction completion */ + if (smbus_wait_until_done(smbus_io_base) < 0) { + return -3; + } + global_status_register = inb(smbus_io_base + SMBHSTSTAT) & 0x80; /* lose check */; + + if (global_status_register != 0x80) { + return -1; + } + return 0; +} + +static inline int do_smbus_read_byte(unsigned smbus_io_base, unsigned device, unsigned address) +{ + unsigned char global_status_register; + unsigned char byte; + + outb(0xff, smbus_io_base + 0x00); + smbus_delay(); + outb(0x20, smbus_io_base + 0x03); + smbus_delay(); + + outb(((device & 0x7f) << 1)|1 , smbus_io_base + 0x04); + smbus_delay(); + outb(address & 0xff, smbus_io_base + 0x05); + smbus_delay(); + outb(0x12, smbus_io_base + 0x03); + smbus_delay(); + +int i,j; +for(i=0;i<0x1000;i++) +{ + if (inb(smbus_io_base + 0x00) != 0x08) + { smbus_delay(); + for(j=0;j<0xFFFF;j++); + } +}; + + global_status_register = inb(smbus_io_base + 0x00); + byte = inb(smbus_io_base + 0x08); + + if (global_status_register != 0x08) { // lose check, otherwise it should be 0 + print_debug("Fail");print_debug("\r\t"); + return -1; + } + print_debug("Success");print_debug("\r\t"); + return byte; +} + + +static inline int do_smbus_write_byte(unsigned smbus_io_base, unsigned device, unsigned address, unsigned char val) +{ + unsigned global_status_register; + + outb(val, smbus_io_base + SMBHSTDAT0); + smbus_delay(); + + /* set the device I'm talking too */ + outb(((device & 0x7f) << 1) | 0, smbus_io_base + SMBXMITADD); + smbus_delay(); + + outb(address & 0xff, smbus_io_base + SMBHSTCMD); + smbus_delay(); + + /* set up for a byte data write */ + outb(0x06, smbus_io_base + SMBHSTPRTCL); + smbus_delay(); + + /* poll for transaction completion */ + if (smbus_wait_until_done(smbus_io_base) < 0) { + return -3; + } + global_status_register = inb(smbus_io_base + SMBHSTSTAT) & 0x80; /* lose check */; + + if (global_status_register != 0x80) { + return -1; + } + return 0; +} + + + static const uint8_t SiS_LPC_init[34][3]={ {0x04, 0xF8, 0x07}, //Reg 0x04 {0x45, 0x00, 0x00}, //Reg 0x45 //Enable Rom Flash @@ -564,11 +732,11 @@ static void enable_smbus(void) printk(BIOS_DEBUG, "enable_smbus <--------\n"); } -static int smbus_read_byte(unsigned device, unsigned address) +int smbus_read_byte(unsigned device, unsigned address) { return do_smbus_read_byte(SMBUS0_IO_BASE, device, address); } -static int smbus_write_byte(unsigned device, unsigned address, unsigned char val) +int smbus_write_byte(unsigned device, unsigned address, unsigned char val) { return do_smbus_write_byte(SMBUS0_IO_BASE, device, address, val); } |