1 #include <device/smbus_def.h>
10 #define SMBTRNSADD 0x9
11 #define SMBSLVDATA 0xa
12 #define SMLINK_PIN_CTL 0xe
13 #define SMBUS_PIN_CTL 0xf
15 #define SMBUS_TIMEOUT (100*1000*10)
19 static int smbus_wait_until_ready(unsigned smbus_io_base)
21 unsigned loops = SMBUS_TIMEOUT;
27 byte = inb(smbus_io_base + SMBHSTSTAT);
32 static int smbus_wait_until_done(unsigned smbus_io_base)
34 unsigned loops = SMBUS_TIMEOUT;
40 byte = inb(smbus_io_base + SMBHSTSTAT);
41 } while((byte & 1) || (byte & ~((1<<6)|(1<<0))) == 0);
45 static inline int smbus_wait_until_blk_done(unsigned smbus_io_base)
47 unsigned loops = SMBUS_TIMEOUT;
53 byte = inb(smbus_io_base + SMBHSTSTAT);
54 } while((byte&(1<<7)) == 0);
58 static int do_smbus_read_byte(unsigned smbus_io_base, unsigned device, unsigned address)
60 unsigned char global_status_register;
63 if (smbus_wait_until_ready(smbus_io_base) < 0) {
64 return SMBUS_WAIT_UNTIL_READY_TIMEOUT;
66 /* setup transaction */
67 /* disable interrupts */
68 outb(inb(smbus_io_base + SMBHSTCTL) & (~1), smbus_io_base + SMBHSTCTL);
69 /* set the device I'm talking too */
70 outb(((device & 0x7f) << 1) | 1, smbus_io_base + SMBXMITADD);
71 /* set the command/address... */
72 outb(address & 0xFF, smbus_io_base + SMBHSTCMD);
73 /* set up for a byte data read */
74 outb((inb(smbus_io_base + SMBHSTCTL) & 0xE3) | (0x2 << 2), smbus_io_base + SMBHSTCTL);
75 /* clear any lingering errors, so the transaction will run */
76 outb(inb(smbus_io_base + SMBHSTSTAT), smbus_io_base + SMBHSTSTAT);
78 /* clear the data byte...*/
79 outb(0, smbus_io_base + SMBHSTDAT0);
81 /* start the command */
82 outb((inb(smbus_io_base + SMBHSTCTL) | 0x40), smbus_io_base + SMBHSTCTL);
84 /* poll for transaction completion */
85 if (smbus_wait_until_done(smbus_io_base) < 0) {
86 return SMBUS_WAIT_UNTIL_DONE_TIMEOUT;
89 global_status_register = inb(smbus_io_base + SMBHSTSTAT);
91 /* Ignore the In Use Status... */
92 global_status_register &= ~(3 << 5);
94 /* read results of transaction */
95 byte = inb(smbus_io_base + SMBHSTDAT0);
96 if (global_status_register != (1 << 1)) {