diff options
Diffstat (limited to 'src/southbridge/via/vt8231/vt8231_early_smbus.c')
-rw-r--r-- | src/southbridge/via/vt8231/vt8231_early_smbus.c | 260 |
1 files changed, 133 insertions, 127 deletions
diff --git a/src/southbridge/via/vt8231/vt8231_early_smbus.c b/src/southbridge/via/vt8231/vt8231_early_smbus.c index dbb6e213ae..056c4b5b11 100644 --- a/src/southbridge/via/vt8231/vt8231_early_smbus.c +++ b/src/southbridge/via/vt8231/vt8231_early_smbus.c @@ -12,12 +12,12 @@ #define SMBTRNSADD 0x9 #define SMBSLVDATA 0xa #define SMLINK_PIN_CTL 0xe -#define SMBUS_PIN_CTL 0xf +#define SMBUS_PIN_CTL 0xf /* Define register settings */ #define HOST_RESET 0xff -#define DIMM_BASE 0xa0 // 1010000 is base for DIMM in SMBus -#define READ_CMD 0x01 // 1 in the 0 bit of SMBHSTADD states to READ +#define DIMM_BASE 0xa0 // 1010000 is base for DIMM in SMBus +#define READ_CMD 0x01 // 1 in the 0 bit of SMBHSTADD states to READ #define SMBUS_TIMEOUT (100*1000*10) @@ -27,28 +27,29 @@ static void enable_smbus(void) device_t dev; unsigned char c; /* Power management controller */ - dev = pci_locate_device(PCI_ID(0x1106, 0x8235), 0); - + dev = pci_locate_device(PCI_ID(0x1106,0x8235), 0); + if (dev == PCI_DEV_INVALID) { die("SMBUS controller not found\r\n"); } + // set IO base address to SMBUS_IO_BASE - pci_write_config32(dev, 0x90, SMBUS_IO_BASE | 1); - + pci_write_config32(dev, 0x90, SMBUS_IO_BASE|1); + // Enable SMBus c = pci_read_config8(dev, 0xd2); c |= 5; pci_write_config8(dev, 0xd2, c); - + /* make it work for I/O ... */ - dev = pci_locate_device(PCI_ID(0x1106, 0x8231), 0); + dev = pci_locate_device(PCI_ID(0x1106,0x8231), 0); c = pci_read_config8(dev, 4); c |= 1; pci_write_config8(dev, 4, c); print_debug_hex8(c); print_debug(" is the comm register\r\n"); - + print_debug("SMBus controller enabled\r\n"); } @@ -60,51 +61,52 @@ static inline void smbus_delay(void) static int smbus_wait_until_active(void) { - unsigned long loops; - loops = SMBUS_TIMEOUT; - do { - unsigned char val; - smbus_delay(); - val = inb(SMBUS_IO_BASE + SMBHSTSTAT); - if ((val & 1)) { - break; - } - } while (--loops); - return loops ? 0 : -4; + unsigned long loops; + loops = SMBUS_TIMEOUT; + do { + unsigned char val; + smbus_delay(); + val = inb(SMBUS_IO_BASE + SMBHSTSTAT); + if ((val & 1)) { + break; + } + } while(--loops); + return loops?0:-4; } static int smbus_wait_until_ready(void) { - unsigned long loops; - loops = SMBUS_TIMEOUT; - do { - unsigned char val; - smbus_delay(); - val = inb(SMBUS_IO_BASE + SMBHSTSTAT); - if ((val & 1) == 0) { - break; - } - if (loops == (SMBUS_TIMEOUT / 2)) { - outb(inb(SMBUS_IO_BASE + SMBHSTSTAT), SMBUS_IO_BASE + SMBHSTSTAT); - } - } while (--loops); - return loops ? 0 : -2; + unsigned long loops; + loops = SMBUS_TIMEOUT; + do { + unsigned char val; + smbus_delay(); + val = inb(SMBUS_IO_BASE + SMBHSTSTAT); + if ((val & 1) == 0) { + break; + } + if(loops == (SMBUS_TIMEOUT / 2)) { + outb(inb(SMBUS_IO_BASE + SMBHSTSTAT), + SMBUS_IO_BASE + SMBHSTSTAT); + } + } while(--loops); + return loops?0:-2; } static int smbus_wait_until_done(void) { - unsigned long loops; - loops = SMBUS_TIMEOUT; - do { - unsigned char val; - smbus_delay(); - - val = inb(SMBUS_IO_BASE + SMBHSTSTAT); - if ((val & 1) == 0) { - break; - } - } while (--loops); - return loops ? 0 : -3; + unsigned long loops; + loops = SMBUS_TIMEOUT; + do { + unsigned char val; + smbus_delay(); + + val = inb(SMBUS_IO_BASE + SMBHSTSTAT); + if ( (val & 1) == 0) { + break; + } + } while(--loops); + return loops?0:-3; } void smbus_reset(void) @@ -113,13 +115,13 @@ void smbus_reset(void) outb(HOST_RESET, SMBUS_IO_BASE + SMBHSTSTAT); outb(HOST_RESET, SMBUS_IO_BASE + SMBHSTSTAT); outb(HOST_RESET, SMBUS_IO_BASE + SMBHSTSTAT); - + smbus_wait_until_ready(); print_debug("After reset status "); - print_debug_hex8(inb(SMBUS_IO_BASE + SMBHSTSTAT)); + print_debug_hex8( inb(SMBUS_IO_BASE + SMBHSTSTAT)); print_debug("\r\n"); } - + static void smbus_print_error(unsigned char host_status_register) { @@ -150,95 +152,96 @@ static void smbus_print_error(unsigned char host_status_register) */ static int smbus_read_byte(unsigned device, unsigned address) { - unsigned char global_control_register; - unsigned char global_status_register; - unsigned char byte; - - if (smbus_wait_until_ready() < 0) { - outb(inb(SMBUS_IO_BASE + SMBHSTSTAT), SMBUS_IO_BASE + SMBHSTSTAT); - if (smbus_wait_until_ready() < 0) { - return -2; - } - } - - /* setup transaction */ - /* disable interrupts */ - outb(inb(SMBUS_IO_BASE + SMBHSTCTL) & 0xfe, 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 a byte read, with interrupts disabled */ - outb((inb(SMBUS_IO_BASE + SMBHSTCTL) | 0x40), SMBUS_IO_BASE + SMBHSTCTL); - /* poll for it to start */ - if (smbus_wait_until_active() < 0) { - return -4; - } - - /* poll for transaction completion */ - if (smbus_wait_until_done() < 0) { - return -3; - } + unsigned char global_control_register; + unsigned char global_status_register; + unsigned char byte; + + if (smbus_wait_until_ready() < 0) { + outb(inb(SMBUS_IO_BASE + SMBHSTSTAT), SMBUS_IO_BASE + SMBHSTSTAT); + if ( smbus_wait_until_ready() < 0 ) { + return -2; + } + } + + /* setup transaction */ + /* disable interrupts */ + outb(inb(SMBUS_IO_BASE + SMBHSTCTL) & 0xfe, 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 a byte read, with interrupts disabled */ + outb((inb(SMBUS_IO_BASE + SMBHSTCTL) | 0x40), SMBUS_IO_BASE + SMBHSTCTL); + /* poll for it to start */ + if (smbus_wait_until_active() < 0) { + return -4; + } + + /* poll for transaction completion */ + if (smbus_wait_until_done() < 0) { + return -3; + } /* Ignore the Host Busy & Command Complete ? */ - global_status_register = inb(SMBUS_IO_BASE + SMBHSTSTAT) & ~((1 << 1) | (1 << 0)); + global_status_register = inb(SMBUS_IO_BASE + SMBHSTSTAT) & ~((1<<1)|(1<<0)); - /* read results of transaction */ - byte = inb(SMBUS_IO_BASE + SMBHSTDAT0); + /* read results of transaction */ + byte = inb(SMBUS_IO_BASE + SMBHSTDAT0); - if (global_status_register != 0) { - return -1; - } - return byte; + if (global_status_register != 0) { + return -1; + } + return byte; } #if 0 /* SMBus routines borrowed from VIA's Trident Driver */ /* this works, so I am not going to touch it for now -- rgm */ -static unsigned char smbus_read_byte(unsigned char devAdr, unsigned char bIndex) +static unsigned char smbus_read_byte(unsigned char devAdr, + unsigned char bIndex) { unsigned int i; - unsigned char bData; - unsigned char sts = 0; - + unsigned char bData; + unsigned char sts = 0; + /* clear host status */ outb(0xff, SMBUS_IO_BASE); - + /* check SMBUS ready */ - for (i = 0; i < SMBUS_TIMEOUT; i++) - if ((inb(SMBUS_IO_BASE) & 0x01) == 0) + for ( i = 0; i < SMBUS_TIMEOUT; i++ ) + if ( (inb(SMBUS_IO_BASE) & 0x01) == 0 ) break; /* set host command */ - outb(bIndex, SMBUS_IO_BASE + 3); - + outb(bIndex, SMBUS_IO_BASE+3); + /* set slave address */ - outb(devAdr | 0x01, SMBUS_IO_BASE + 4); - + outb(devAdr | 0x01, SMBUS_IO_BASE+4); + /* start */ - outb(0x48, SMBUS_IO_BASE + 2); - + outb(0x48, SMBUS_IO_BASE+2); + /* SMBUS Wait Ready */ - for (i = 0; i < SMBUS_TIMEOUT; i++) - if (((sts = inb(SMBUS_IO_BASE)) & 0x01) == 0) + for ( i = 0; i < SMBUS_TIMEOUT; i++ ) + if ( ((sts = inb(SMBUS_IO_BASE)) & 0x01) == 0 ) break; if ((sts & ~3) != 0) { smbus_print_error(sts); return 0; } - bData = inb(SMBUS_IO_BASE + 5); - + bData=inb(SMBUS_IO_BASE+5); + return bData; - + } #endif /* for reference, here is the fancier version which we will use at some @@ -249,11 +252,11 @@ int smbus_read_byte(unsigned device, unsigned address, unsigned char *result) { unsigned char host_status_register; unsigned char byte; - + reset(); - + smbus_wait_until_ready(); - + /* setup transaction */ /* disable interrupts */ outb(inb(SMBUS_IO_BASE + SMBHSTCTL) & (~1), SMBUS_IO_BASE + SMBHSTCTL); @@ -262,32 +265,35 @@ int smbus_read_byte(unsigned device, unsigned address, unsigned char *result) /* 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); - + 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... */ + + /* clear the data byte...*/ outb(0, SMBUS_IO_BASE + SMBHSTDAT0); - + /* start the command */ - outb((inb(SMBUS_IO_BASE + SMBHSTCTL) | 0x40), SMBUS_IO_BASE + SMBHSTCTL); - + outb((inb(SMBUS_IO_BASE + SMBHSTCTL) | 0x40), + SMBUS_IO_BASE + SMBHSTCTL); + /* poll for transaction completion */ smbus_wait_until_done(); - + 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); smbus_print_error(byte); - + *result = byte; return host_status_register != 0x02; } #endif + |