Since some people disapprove of white space cleanups mixed in regular commits
[coreboot.git] / src / southbridge / amd / cs5536 / cs5536_smbus2.h
1 /*
2  * This file is part of the coreboot project.
3  *
4  * Copyright (C) 2007 Advanced Micro Devices, Inc.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
19  */
20
21 #define SMBUS_ERROR -1
22 #define SMBUS_WAIT_UNTIL_READY_TIMEOUT -2
23 #define SMBUS_WAIT_UNTIL_DONE_TIMEOUT  -3
24
25 #define SMB_SDA         0x00
26 #define SMB_STS         0x01
27 #define SMB_CTRL_STS    0x02
28 #define SMB_CTRL1       0x03
29 #define SMB_ADD         0x04
30 #define SMB_CTRL2       0x05
31 #define SMB_CTRL3       0x06
32
33 #define SMB_STS_SLVSTP  (0x01 << 7)
34 #define SMB_STS_SDAST   (0x01 << 6)
35 #define SMB_STS_BER     (0x01 << 5)
36 #define SMB_STS_NEGACK  (0x01 << 4)
37 #define SMB_STS_STASTR  (0x01 << 3)
38 #define SMB_STS_NMATCH  (0x01 << 2)
39 #define SMB_STS_MASTER  (0x01 << 1)
40 #define SMB_STS_XMIT    (0x01 << 0)
41
42 #define SMB_CSTS_TGSCL  (0x01 << 5)
43 #define SMB_CSTS_TSDA   (0x01 << 4)
44 #define SMB_CSTS_GCMTCH (0x01 << 3)
45 #define SMB_CSTS_MATCH  (0x01 << 2)
46 #define SMB_CSTS_BB     (0x01 << 1)
47 #define SMB_CSTS_BUSY   (0x01 << 0)
48
49 #define SMB_CTRL1_STASTRE (0x01 << 7)
50 #define SMB_CTRL1_NMINTE  (0x01 << 6)
51 #define SMB_CTRL1_GCMEN   (0x01 << 5)
52 #define SMB_CTRL1_ACK     (0x01 << 4)
53 #define SMB_CTRL1_RSVD    (0x01 << 3)
54 #define SMB_CTRL1_INTEN   (0x01 << 2)
55 #define SMB_CTRL1_STOP    (0x01 << 1)
56 #define SMB_CTRL1_START   (0x01 << 0)
57
58 #define SMB_ADD_SAEN      (0x01 << 7)
59
60 #define SMB_CTRL2_ENABLE  0x01
61
62 #define SMBUS_TIMEOUT (100*1000*10)
63 #define SMBUS_STATUS_MASK 0xfbff
64
65 static void smbus_delay(void)
66 {
67         inb(0x80);
68 }
69
70 static int smbus_wait(unsigned smbus_io_base)
71 {
72         unsigned long loops = SMBUS_TIMEOUT;
73         unsigned char val;
74
75         do {
76                 smbus_delay();
77                 val = inb(smbus_io_base + SMB_STS);
78                 if ((val & SMB_STS_SDAST) != 0)
79                         break;
80                 if (val & (SMB_STS_BER | SMB_STS_NEGACK)) {
81                         printk(BIOS_DEBUG, "SMBUS WAIT ERROR %x\n", val);
82                         return SMBUS_ERROR;
83                 }
84         } while (--loops);
85
86         outb(0, smbus_io_base + SMB_STS);
87         return loops ? 0 : SMBUS_WAIT_UNTIL_READY_TIMEOUT;
88 }
89
90 static int smbus_write(unsigned smbus_io_base, unsigned char byte)
91 {
92
93         outb(byte, smbus_io_base + SMB_SDA);
94         return smbus_wait(smbus_io_base);
95 }
96
97 /* generate a smbus start condition */
98 static int smbus_start_condition(unsigned smbus_io_base)
99 {
100         unsigned char val;
101
102         /* issue a START condition */
103         val = inb(smbus_io_base + SMB_CTRL1);
104         outb(val | SMB_CTRL1_START, smbus_io_base + SMB_CTRL1);
105
106         /* check for bus conflict */
107         val = inb(smbus_io_base + SMB_STS);
108         if ((val & SMB_STS_BER) != 0)
109                 return SMBUS_ERROR;
110
111         return smbus_wait(smbus_io_base);
112 }
113
114 static int smbus_check_stop_condition(unsigned smbus_io_base)
115 {
116         unsigned char val;
117         unsigned long loops;
118         loops = SMBUS_TIMEOUT;
119         /* check for SDA status */
120         do {
121                 smbus_delay();
122                 val = inb(smbus_io_base + SMB_CTRL1);
123                 if ((val & SMB_CTRL1_STOP) == 0) {
124                         break;
125                 }
126         } while (--loops);
127         return loops ? 0 : SMBUS_WAIT_UNTIL_READY_TIMEOUT;
128
129         /* Make sure everything is cleared and ready to go */
130
131         val = inb(smbus_io_base + SMB_CTRL1);
132         outb(val & ~(SMB_CTRL1_STASTRE | SMB_CTRL1_NMINTE),
133              smbus_io_base + SMB_CTRL1);
134
135         outb(SMB_STS_BER | SMB_STS_NEGACK | SMB_STS_STASTR,
136              smbus_io_base + SMB_STS);
137
138         val = inb(smbus_io_base + SMB_CTRL_STS);
139         outb(val | SMB_CSTS_BB, smbus_io_base + SMB_CTRL_STS);
140 }
141
142 static int smbus_stop_condition(unsigned smbus_io_base)
143 {
144         unsigned char val;
145         val = inb(smbus_io_base + SMB_CTRL1);
146         outb(SMB_CTRL1_STOP, smbus_io_base + SMB_CTRL1);
147
148         return 0;
149 }
150
151 static int smbus_ack(unsigned smbus_io_base, int state)
152 {
153         unsigned char val = inb(smbus_io_base + SMB_CTRL1);
154
155         if (state)
156                 outb(val | SMB_CTRL1_ACK, smbus_io_base + SMB_CTRL1);
157         else
158                 outb(val & ~SMB_CTRL1_ACK, smbus_io_base + SMB_CTRL1);
159
160         return 0;
161 }
162
163 static int smbus_send_slave_address(unsigned smbus_io_base,
164                                     unsigned char device)
165 {
166         unsigned char val;
167
168         /* send the slave address */
169         outb(device, smbus_io_base + SMB_SDA);
170
171         /* check for bus conflict and NACK */
172         val = inb(smbus_io_base + SMB_STS);
173         if (((val & SMB_STS_BER) != 0) || ((val & SMB_STS_NEGACK) != 0)) {
174                 printk(BIOS_DEBUG, "SEND SLAVE ERROR (%x)\n", val);
175                 return SMBUS_ERROR;
176         }
177         return smbus_wait(smbus_io_base);
178 }
179
180 static int smbus_send_command(unsigned smbus_io_base, unsigned char command)
181 {
182         unsigned char val;
183
184         /* send the command */
185         outb(command, smbus_io_base + SMB_SDA);
186
187         /* check for bus conflict and NACK */
188         val = inb(smbus_io_base + SMB_STS);
189         if (((val & SMB_STS_BER) != 0) || ((val & SMB_STS_NEGACK) != 0))
190                 return SMBUS_ERROR;
191
192         return smbus_wait(smbus_io_base);
193 }
194
195 static void _doread(unsigned smbus_io_base, unsigned char device,
196                     unsigned char address, unsigned char *data, int count)
197 {
198         int ret;
199         int index = 0;
200         unsigned char val;
201
202         if ((ret = smbus_check_stop_condition(smbus_io_base)))
203                 goto err;
204
205         index++;
206
207         if ((ret = smbus_start_condition(smbus_io_base)))
208                 goto err;
209
210         index++;                /* 2 */
211         if ((ret = smbus_send_slave_address(smbus_io_base, device)))
212                 goto err;
213
214         index++;
215         if ((ret = smbus_send_command(smbus_io_base, address)))
216                 goto err;
217
218         index++;
219         if ((ret = smbus_start_condition(smbus_io_base)))
220                 goto err;
221
222         /* Clear the ack for multiple byte reads */
223         smbus_ack(smbus_io_base, (count == 1) ? 1 : 0);
224
225         index++;
226         if ((ret = smbus_send_slave_address(smbus_io_base, device | 0x01)))
227                 goto err;
228
229         while (count) {
230                 /* Set the ACK if this is the next to last byte */
231                 smbus_ack(smbus_io_base, (count == 2) ? 1 : 0);
232
233                 /* Set the stop bit if this is the last byte to read */
234
235                 if (count == 1)
236                         smbus_stop_condition(smbus_io_base);
237
238                 val = inb(smbus_io_base + SMB_SDA);
239                 *data++ = val;
240
241                 if (count > 1) {
242                         ret = smbus_wait(smbus_io_base);
243                         if (ret)
244                                 return;
245                 }
246
247                 count--;
248         }
249
250         return;
251
252       err:
253         printk(BIOS_DEBUG, "SMBUS READ ERROR (%d): %d\n", index, ret);
254 }
255
256 static inline unsigned char do_smbus_read_byte(unsigned smbus_io_base,
257                 unsigned char device, unsigned char address)
258 {
259         unsigned char val = 0;
260         _doread(smbus_io_base, device, address, &val, sizeof(val));
261         return val;
262 }
263
264 static inline unsigned short do_smbus_read_word(unsigned smbus_io_base,
265                  unsigned char device, unsigned char address)
266 {
267         unsigned short val = 0;
268         _doread(smbus_io_base, device, address, (unsigned char *)&val,
269                 sizeof(val));
270         return val;
271 }
272
273 static int _dowrite(unsigned smbus_io_base, unsigned char device,
274                     unsigned char address, unsigned char *data, int count)
275 {
276
277         int ret;
278
279         if ((ret = smbus_check_stop_condition(smbus_io_base)))
280                 goto err;
281
282         if ((ret = smbus_start_condition(smbus_io_base)))
283                 goto err;
284
285         if ((ret = smbus_send_slave_address(smbus_io_base, device)))
286                 goto err;
287
288         if ((ret = smbus_send_command(smbus_io_base, address)))
289                 goto err;
290
291         while (count) {
292                 if ((ret = smbus_write(smbus_io_base, *data++)))
293                         goto err;
294                 count--;
295         }
296
297         smbus_stop_condition(smbus_io_base);
298         return 0;
299
300       err:
301         printk(BIOS_DEBUG, "SMBUS WRITE ERROR: %d\n", ret);
302         return -1;
303 }
304
305 static inline int do_smbus_write_byte(unsigned smbus_io_base,
306                 unsigned char device, unsigned char address, unsigned char data)
307 {
308         return _dowrite(smbus_io_base, device, address,
309                         (unsigned char *)&data, 1);
310 }
311
312 static inline int do_smbus_write_word(unsigned smbus_io_base,
313                 unsigned char device, unsigned char address, unsigned short data)
314 {
315         return _dowrite(smbus_io_base, device, address, (unsigned char *)&data,
316                         2);
317 }