4f4ec5c9998dff51a0e428cd7993657d43e75c0f
[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 #include <delay.h>
18
19 static int smbus_wait_until_ready(unsigned smbus_io_base)
20 {
21         unsigned loops = SMBUS_TIMEOUT;
22         unsigned char byte;
23         do {
24                 udelay(100);
25                 if (--loops == 0)
26                         break;
27                 byte = inb(smbus_io_base + SMBHSTSTAT);
28         } while(byte & 1);
29         return loops?0:-1;
30 }
31
32 static int smbus_wait_until_done(unsigned smbus_io_base)
33 {
34         unsigned loops = SMBUS_TIMEOUT;
35         unsigned char byte;
36         do {
37                 udelay(100);
38                 if (--loops == 0)
39                        break;
40                 byte = inb(smbus_io_base + SMBHSTSTAT);
41         } while((byte & 1) || (byte & ~((1<<6)|(1<<0))) == 0);
42         return loops?0:-1;
43 }
44
45 static inline int smbus_wait_until_blk_done(unsigned smbus_io_base)
46 {
47         unsigned loops = SMBUS_TIMEOUT;
48         unsigned char byte;
49         do {
50                 udelay(100);
51                 if (--loops == 0)
52                        break;
53                 byte = inb(smbus_io_base + SMBHSTSTAT);
54         } while((byte&(1<<7)) == 0);
55         return loops?0:-1;
56 }
57
58 static int do_smbus_read_byte(unsigned smbus_io_base, unsigned device, unsigned address)
59 {
60         unsigned char global_status_register;
61         unsigned char byte;
62
63         if (smbus_wait_until_ready(smbus_io_base) < 0) {
64                 return SMBUS_WAIT_UNTIL_READY_TIMEOUT;
65         }
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);
77
78         /* clear the data byte...*/
79         outb(0, smbus_io_base + SMBHSTDAT0);
80
81         /* start the command */
82         outb((inb(smbus_io_base + SMBHSTCTL) | 0x40), smbus_io_base + SMBHSTCTL);
83
84         /* poll for transaction completion */
85         if (smbus_wait_until_done(smbus_io_base) < 0) {
86                 return SMBUS_WAIT_UNTIL_DONE_TIMEOUT;
87         }
88
89         global_status_register = inb(smbus_io_base + SMBHSTSTAT);
90
91         /* Ignore the In Use Status... */
92         global_status_register &= ~(3 << 5);
93
94         /* read results of transaction */
95         byte = inb(smbus_io_base + SMBHSTDAT0);
96         if (global_status_register != (1 << 1)) {
97                 return SMBUS_ERROR;
98         }
99         return byte;
100 }
101