a18942539574e27e27a5ab532a1d7d9710e04cc5
[coreboot.git] / src / southbridge / intel / i82371eb / i82371eb_smbus.h
1 #include <device/smbus_def.h>
2
3 #define SMBHST_STATUS   0x0
4 #define SMBHST_CTL      0x2
5 #define SMBHST_CMD      0x3
6 #define SMBHST_ADDR     0x4
7 #define SMBHST_DAT      0x5
8
9 #define SMBUS_TIMEOUT (100*1000*10)
10 #define SMBUS_STATUS_MASK 0x1e
11 #define SMBUS_ERROR_FLAG (1<<2)
12
13 static inline void smbus_delay(void)
14 {
15         outb(0x80, 0x80);
16         outb(0x80, 0x80);
17         outb(0x80, 0x80);
18         outb(0x80, 0x80);
19         outb(0x80, 0x80);
20         outb(0x80, 0x80);
21 }
22
23 static int smbus_wait_until_ready(unsigned smbus_io_base)
24 {
25         unsigned long loops;
26         loops = SMBUS_TIMEOUT;
27         do {
28                 unsigned char val;
29                 smbus_delay();
30                 val = inb(smbus_io_base + SMBHST_STATUS);
31                 if ((val & 0x1) == 0) {
32                         break;
33                 }
34 #if 0
35                 if(loops == (SMBUS_TIMEOUT / 2)) {
36                         outw(inw(smbus_io_base + SMBHST_STATUS),
37                                 smbus_io_base + SMBHST_STATUS);
38                 }
39 #endif
40         } while(--loops);
41         return loops?0:SMBUS_WAIT_UNTIL_READY_TIMEOUT;
42 }
43
44 static int smbus_wait_until_done(unsigned smbus_io_base)
45 {
46         unsigned long loops;
47         loops = SMBUS_TIMEOUT;
48         do {
49                 unsigned short val;
50                 smbus_delay();
51
52                 val = inb(smbus_io_base + SMBHST_STATUS);
53                 // Make sure the command is done
54                 if ((val & 0x1) != 0) {
55                         continue;
56                 }
57                 // Don't break out until one of the interrupt
58                 // flags is set.
59                 if (val & 0xfe) {
60                         break;
61                 }
62         } while(--loops);
63         return loops?0:SMBUS_WAIT_UNTIL_DONE_TIMEOUT;
64 }
65
66 static int do_smbus_read_byte(unsigned smbus_io_base, unsigned device, unsigned address)
67 {
68         unsigned status_register;
69         unsigned byte;
70
71         if (smbus_wait_until_ready(smbus_io_base) < 0) {
72                 return SMBUS_WAIT_UNTIL_READY_TIMEOUT;
73         }
74
75         /* setup transaction */
76
77         /* clear any lingering errors, so the transaction will run */
78         outb(0x1e, smbus_io_base + SMBHST_STATUS);
79
80         /* set the device I'm talking too */
81         outb(((device & 0x7f) << 1) | 1, smbus_io_base + SMBHST_ADDR);
82
83         /* set the command/address... */
84         outb(address & 0xff, smbus_io_base + SMBHST_CMD);
85
86         /* clear the data word...*/
87         outb(0, smbus_io_base + SMBHST_DAT);
88
89         /* start a byte read with interrupts disabled */
90         outb( (0x02 << 2)|(1<<6), smbus_io_base + SMBHST_CTL);
91
92         /* poll for transaction completion */
93         if (smbus_wait_until_done(smbus_io_base) < 0) {
94                 return SMBUS_WAIT_UNTIL_DONE_TIMEOUT;
95         }
96
97         status_register = inw(smbus_io_base + SMBHST_STATUS);
98
99         /* read results of transaction */
100         byte = inw(smbus_io_base + SMBHST_DAT) & 0xff;
101
102         if (status_register & 0x04) {
103 #if 0
104                 print_debug("Read fail ");
105                 print_debug_hex16(status_register);
106                 print_debug("\n");
107 #endif
108                 return SMBUS_ERROR;
109         }
110         return byte;
111 }
112