0b793c37f97851e5356846969db487a53b9171d7
[coreboot.git] / src / southbridge / intel / esb6300 / esb6300_smbus.h
1 #include <device/smbus_def.h>
2
3 #define SMBHSTSTAT 0x0
4 #define SMBHSTCTL  0x2
5 #define SMBHSTCMD  0x3
6 #define SMBXMITADD 0x4
7 #define SMBHSTDAT0 0x5
8 #define SMBHSTDAT1 0x6
9 #define SMBBLKDAT  0x7
10 #define SMBTRNSADD 0x9
11 #define SMBSLVDATA 0xa
12 #define SMLINK_PIN_CTL 0xe
13 #define SMBUS_PIN_CTL  0xf 
14
15 #define SMBUS_TIMEOUT (100*1000*10)
16
17 static int smbus_wait_until_ready(unsigned smbus_io_base)
18 {
19         unsigned loops = SMBUS_TIMEOUT;
20         unsigned char byte;
21         do {
22                 udelay(100);
23                 if (--loops == 0)
24                         break;
25                 byte = inb(smbus_io_base + SMBHSTSTAT);
26         } while(byte & 1);
27         return loops?0:-1;
28 }
29
30 static int smbus_wait_until_done(unsigned smbus_io_base)
31 {
32         unsigned loops = SMBUS_TIMEOUT;
33         unsigned char byte;
34         do {
35                 udelay(100);
36                 if (--loops == 0)
37                        break;
38                 byte = inb(smbus_io_base + SMBHSTSTAT);
39         } while((byte & 1) || (byte & ~((1<<6)|(1<<0))) == 0);
40         return loops?0:-1;
41 }
42
43 static inline int smbus_wait_until_blk_done(unsigned smbus_io_base)
44 {
45         unsigned loops = SMBUS_TIMEOUT;
46         unsigned char byte;
47         do {
48                 udelay(100);
49                 if (--loops == 0)
50                        break;
51                 byte = inb(smbus_io_base + SMBHSTSTAT);
52         } while((byte&(1<<7)) == 0);
53         return loops?0:-1;
54 }
55
56 static int do_smbus_read_byte(unsigned smbus_io_base, unsigned device, unsigned address)
57 {
58         unsigned char global_status_register;
59         unsigned char byte;
60
61         if (smbus_wait_until_ready(smbus_io_base) < 0) {
62                 return SMBUS_WAIT_UNTIL_READY_TIMEOUT;
63         }
64         /* setup transaction */
65         /* disable interrupts */
66         outb(inb(smbus_io_base + SMBHSTCTL) & (~1), smbus_io_base + SMBHSTCTL);
67         /* set the device I'm talking too */
68         outb(((device & 0x7f) << 1) | 1, smbus_io_base + SMBXMITADD);
69         /* set the command/address... */
70         outb(address & 0xFF, smbus_io_base + SMBHSTCMD);
71         /* set up for a byte data read */
72         outb((inb(smbus_io_base + SMBHSTCTL) & 0xE3) | (0x2 << 2), smbus_io_base + SMBHSTCTL);
73         /* clear any lingering errors, so the transaction will run */
74         outb(inb(smbus_io_base + SMBHSTSTAT), smbus_io_base + SMBHSTSTAT);
75
76         /* clear the data byte...*/
77         outb(0, smbus_io_base + SMBHSTDAT0);
78
79         /* start the command */
80         outb((inb(smbus_io_base + SMBHSTCTL) | 0x40), smbus_io_base + SMBHSTCTL);
81
82         /* poll for transaction completion */
83         if (smbus_wait_until_done(smbus_io_base) < 0) {
84                 return SMBUS_WAIT_UNTIL_DONE_TIMEOUT;
85         }
86
87         global_status_register = inb(smbus_io_base + SMBHSTSTAT);
88
89         /* Ignore the In Use Status... */
90         global_status_register &= ~(3 << 5);
91
92         /* read results of transaction */
93         byte = inb(smbus_io_base + SMBHSTDAT0);
94         if (global_status_register != (1 << 1)) {
95                 return SMBUS_ERROR;
96         }
97         return byte;
98 }
99