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