Since some people disapprove of white space cleanups mixed in regular commits
[coreboot.git] / src / southbridge / amd / amd8111 / amd8111_smbus.h
1 #include <device/smbus_def.h>
2
3 #define SMBGSTATUS 0xe0
4 #define SMBGCTL    0xe2
5 #define SMBHSTADDR 0xe4
6 #define SMBHSTDAT  0xe6
7 #define SMBHSTCMD  0xe8
8 #define SMBHSTFIFO 0xe9
9
10 #define SMBUS_TIMEOUT (100*1000*10)
11 #define SMBUS_STATUS_MASK 0xfbff
12
13 static inline void smbus_delay(void)
14 {
15         outb(0x80, 0x80);
16 }
17
18 static int smbus_wait_until_ready(unsigned smbus_io_base)
19 {
20         unsigned long loops;
21         loops = SMBUS_TIMEOUT;
22         do {
23                 unsigned short val;
24                 smbus_delay();
25                 val = inw(smbus_io_base + SMBGSTATUS);
26                 if ((val & 0x800) == 0) {
27                         break;
28                 }
29                 if(loops == (SMBUS_TIMEOUT / 2)) {
30                         outw(inw(smbus_io_base + SMBGSTATUS),
31                                 smbus_io_base + SMBGSTATUS);
32                 }
33         } while(--loops);
34         return loops?0:SMBUS_WAIT_UNTIL_READY_TIMEOUT;
35 }
36
37 static int smbus_wait_until_done(unsigned smbus_io_base)
38 {
39         unsigned long loops;
40         loops = SMBUS_TIMEOUT;
41         do {
42                 unsigned short val;
43                 smbus_delay();
44
45                 val = inw(smbus_io_base + SMBGSTATUS);
46                 if (((val & 0x8) == 0) | ((val & 0x0037) != 0)) {
47                         break;
48                 }
49         } while(--loops);
50         return loops?0:SMBUS_WAIT_UNTIL_DONE_TIMEOUT;
51 }
52
53 static int do_smbus_recv_byte(unsigned smbus_io_base, unsigned device)
54 {
55         unsigned global_status_register;
56         unsigned byte;
57
58         if (smbus_wait_until_ready(smbus_io_base) < 0) {
59                 return SMBUS_WAIT_UNTIL_READY_TIMEOUT;
60         }
61
62         /* setup transaction */
63         /* disable interrupts */
64         outw(inw(smbus_io_base + SMBGCTL) & ~((1<<10)|(1<<9)|(1<<8)|(1<<4)), smbus_io_base + SMBGCTL);
65         /* set the device I'm talking too */
66         outw(((device & 0x7f) << 1) | 1, smbus_io_base + SMBHSTADDR);
67         /* set the command/address... */
68         outb(0, smbus_io_base + SMBHSTCMD);
69         /* set up for a send byte */
70         outw((inw(smbus_io_base + SMBGCTL) & ~7) | (0x1), smbus_io_base + SMBGCTL);
71
72         /* clear any lingering errors, so the transaction will run */
73         /* Do I need to write the bits to a 1 to clear an error? */
74         outw(inw(smbus_io_base + SMBGSTATUS), smbus_io_base + SMBGSTATUS);
75
76         /* set the data word...*/
77         outw(0, smbus_io_base + SMBHSTDAT);
78
79         /* start the command */
80         outw((inw(smbus_io_base + SMBGCTL) | (1 << 3)), smbus_io_base + SMBGCTL);
81
82
83         /* poll for transaction completion */
84         if (smbus_wait_until_done(smbus_io_base) < 0) {
85                 return SMBUS_WAIT_UNTIL_DONE_TIMEOUT;
86         }
87
88         global_status_register = inw(smbus_io_base + SMBGSTATUS);
89
90         /* read results of transaction */
91         byte = inw(smbus_io_base + SMBHSTDAT) & 0xff;
92
93         if ((global_status_register & SMBUS_STATUS_MASK) != (1 << 4)) {
94                 return SMBUS_ERROR;
95         }
96         return byte;
97 }
98
99 static int do_smbus_send_byte(unsigned smbus_io_base, unsigned device, unsigned value)
100 {
101         unsigned global_status_register;
102
103         if (smbus_wait_until_ready(smbus_io_base) < 0) {
104                 return SMBUS_WAIT_UNTIL_READY_TIMEOUT;
105         }
106
107         /* setup transaction */
108         /* disable interrupts */
109         outw(inw(smbus_io_base + SMBGCTL) & ~((1<<10)|(1<<9)|(1<<8)|(1<<4)), smbus_io_base + SMBGCTL);
110         /* set the device I'm talking too */
111         outw(((device & 0x7f) << 1) | 0, smbus_io_base + SMBHSTADDR);
112         /* set the command/address... */
113         outb(0, smbus_io_base + SMBHSTCMD);
114         /* set up for a send byte */
115         outw((inw(smbus_io_base + SMBGCTL) & ~7) | (0x1), smbus_io_base + SMBGCTL);
116
117         /* clear any lingering errors, so the transaction will run */
118         /* Do I need to write the bits to a 1 to clear an error? */
119         outw(inw(smbus_io_base + SMBGSTATUS), smbus_io_base + SMBGSTATUS);
120
121         /* set the data word...*/
122         outw(value, smbus_io_base + SMBHSTDAT);
123
124         /* start the command */
125         outw((inw(smbus_io_base + SMBGCTL) | (1 << 3)), smbus_io_base + SMBGCTL);
126
127
128         /* poll for transaction completion */
129         if (smbus_wait_until_done(smbus_io_base) < 0) {
130                 return SMBUS_WAIT_UNTIL_DONE_TIMEOUT;
131         }
132         global_status_register = inw(smbus_io_base + SMBGSTATUS);
133
134         if ((global_status_register & SMBUS_STATUS_MASK) != (1 << 4)) {
135                 return SMBUS_ERROR;
136         }
137         return 0;
138 }
139
140
141 static int do_smbus_read_byte(unsigned smbus_io_base, unsigned device, unsigned address)
142 {
143         unsigned global_status_register;
144         unsigned byte;
145
146         if (smbus_wait_until_ready(smbus_io_base) < 0) {
147                 return SMBUS_WAIT_UNTIL_READY_TIMEOUT;
148         }
149
150         /* setup transaction */
151         /* disable interrupts */
152         outw(inw(smbus_io_base + SMBGCTL) & ~((1<<10)|(1<<9)|(1<<8)|(1<<4)), smbus_io_base + SMBGCTL);
153         /* set the device I'm talking too */
154         outw(((device & 0x7f) << 1) | 1, smbus_io_base + SMBHSTADDR);
155         /* set the command/address... */
156         outb(address & 0xFF, smbus_io_base + SMBHSTCMD);
157         /* set up for a byte data read */
158         outw((inw(smbus_io_base + SMBGCTL) & ~7) | (0x2), smbus_io_base + SMBGCTL);
159
160         /* clear any lingering errors, so the transaction will run */
161         /* Do I need to write the bits to a 1 to clear an error? */
162         outw(inw(smbus_io_base + SMBGSTATUS), smbus_io_base + SMBGSTATUS);
163
164         /* clear the data word...*/
165         outw(0, smbus_io_base + SMBHSTDAT);
166
167         /* start the command */
168         outw((inw(smbus_io_base + SMBGCTL) | (1 << 3)), smbus_io_base + SMBGCTL);
169
170
171         /* poll for transaction completion */
172         if (smbus_wait_until_done(smbus_io_base) < 0) {
173                 return SMBUS_WAIT_UNTIL_DONE_TIMEOUT;
174         }
175
176         global_status_register = inw(smbus_io_base + SMBGSTATUS);
177
178         /* read results of transaction */
179         byte = inw(smbus_io_base + SMBHSTDAT) & 0xff;
180
181         if ((global_status_register & SMBUS_STATUS_MASK) != (1 << 4)) {
182                 return SMBUS_ERROR;
183         }
184         return byte;
185 }
186
187 static int do_smbus_write_byte(unsigned smbus_io_base, unsigned device, unsigned address, unsigned char val)
188 {
189         unsigned global_status_register;
190
191         if (smbus_wait_until_ready(smbus_io_base) < 0) {
192                 return SMBUS_WAIT_UNTIL_READY_TIMEOUT;
193         }
194
195         /* setup transaction */
196         /* disable interrupts */
197         outw(inw(smbus_io_base + SMBGCTL) & ~((1<<10)|(1<<9)|(1<<8)|(1<<4)), smbus_io_base + SMBGCTL);
198         /* set the device I'm talking too */
199         outw(((device & 0x7f) << 1) | 0, smbus_io_base + SMBHSTADDR);
200         outb(address & 0xFF, smbus_io_base + SMBHSTCMD);
201         /* set up for a byte data write */ /* FIXME */
202         outw((inw(smbus_io_base + SMBGCTL) & ~7) | (0x2), smbus_io_base + SMBGCTL);
203         /* clear any lingering errors, so the transaction will run */
204         /* Do I need to write the bits to a 1 to clear an error? */
205         outw(inw(smbus_io_base + SMBGSTATUS), smbus_io_base + SMBGSTATUS);
206
207         /* write the data word...*/
208         outw(val, smbus_io_base + SMBHSTDAT);
209
210         /* start the command */
211         outw((inw(smbus_io_base + SMBGCTL) | (1 << 3)), smbus_io_base + SMBGCTL);
212
213         /* poll for transaction completion */
214         if (smbus_wait_until_done(smbus_io_base) < 0) {
215                 return SMBUS_WAIT_UNTIL_DONE_TIMEOUT;
216         }
217         global_status_register = inw(smbus_io_base + SMBGSTATUS);
218
219         if ((global_status_register & SMBUS_STATUS_MASK) != (1 << 4)) {
220                 return SMBUS_ERROR;
221         }
222         return 0;
223 }
224