printk_foo -> printk(BIOS_FOO, ...)
[coreboot.git] / src / southbridge / amd / sb600 / sb600_smbus.c
1 /*
2  * This file is part of the coreboot project.
3  *
4  * Copyright (C) 2008 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; version 2 of the License.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
18  */
19
20 #include "sb600_smbus.h"
21
22 static inline void smbus_delay(void)
23 {
24         outb(0x80, 0x80);
25 }
26
27 static int smbus_wait_until_ready(u32 smbus_io_base)
28 {
29         u32 loops;
30         loops = SMBUS_TIMEOUT;
31         do {
32                 u8 val;
33                 val = inb(smbus_io_base + SMBHSTSTAT);
34                 val &= 0x1f;
35                 if (val == 0) { /* ready now */
36                         return 0;
37                 }
38                 outb(val, smbus_io_base + SMBHSTSTAT);
39         } while (--loops);
40         return -2;              /* time out */
41 }
42
43 static int smbus_wait_until_done(u32 smbus_io_base)
44 {
45         u32 loops;
46         loops = SMBUS_TIMEOUT;
47         do {
48                 u8 val;
49
50                 val = inb(smbus_io_base + SMBHSTSTAT);
51                 val &= 0x1f;    /* mask off reserved bits */
52                 if (val & 0x1c) {
53                         return -5;      /* error */
54                 }
55                 if (val == 0x02) {
56                         outb(val, smbus_io_base + SMBHSTSTAT);  /* clear status */
57                         return 0;
58                 }
59         } while (--loops);
60         return -3;              /* timeout */
61 }
62
63 static int do_smbus_recv_byte(u32 smbus_io_base, u32 device)
64 {
65         u8 byte;
66
67         if (smbus_wait_until_ready(smbus_io_base) < 0) {
68                 return -2;      /* not ready */
69         }
70
71         /* set the device I'm talking too */
72         outb(((device & 0x7f) << 1) | 1, smbus_io_base + SMBHSTADDR);
73
74         byte = inb(smbus_io_base + SMBHSTCTRL);
75         byte &= 0xe3;           /* Clear [4:2] */
76         byte |= (1 << 2) | (1 << 6);    /* Byte data read/write command, start the command */
77         outb(byte, smbus_io_base + SMBHSTCTRL);
78
79         /* poll for transaction completion */
80         if (smbus_wait_until_done(smbus_io_base) < 0) {
81                 return -3;      /* timeout or error */
82         }
83
84         /* read results of transaction */
85         byte = inb(smbus_io_base + SMBHSTCMD);
86
87         return byte;
88 }
89
90 static int do_smbus_send_byte(u32 smbus_io_base, u32 device,
91                               u8 val)
92 {
93         u8 byte;
94
95         if (smbus_wait_until_ready(smbus_io_base) < 0) {
96                 return -2;      /* not ready */
97         }
98
99         /* set the command... */
100         outb(val, smbus_io_base + SMBHSTCMD);
101
102         /* set the device I'm talking too */
103         outb(((device & 0x7f) << 1) | 0, smbus_io_base + SMBHSTADDR);
104
105         byte = inb(smbus_io_base + SMBHSTCTRL);
106         byte &= 0xe3;           /* Clear [4:2] */
107         byte |= (1 << 2) | (1 << 6);    /* Byte data read/write command, start the command */
108         outb(byte, smbus_io_base + SMBHSTCTRL);
109
110         /* poll for transaction completion */
111         if (smbus_wait_until_done(smbus_io_base) < 0) {
112                 return -3;      /* timeout or error */
113         }
114
115         return 0;
116 }
117
118 int do_smbus_read_byte(u32 smbus_io_base, u32 device,
119                               u32 address)
120 {
121         u8 byte;
122
123         if (smbus_wait_until_ready(smbus_io_base) < 0) {
124                 return -2;      /* not ready */
125         }
126
127         /* set the command/address... */
128         outb(address & 0xff, smbus_io_base + SMBHSTCMD);
129
130         /* set the device I'm talking too */
131         outb(((device & 0x7f) << 1) | 1, smbus_io_base + SMBHSTADDR);
132
133         byte = inb(smbus_io_base + SMBHSTCTRL);
134         byte &= 0xe3;           /* Clear [4:2] */
135         byte |= (1 << 3) | (1 << 6);    /* Byte data read/write command, start the command */
136         outb(byte, smbus_io_base + SMBHSTCTRL);
137
138         /* poll for transaction completion */
139         if (smbus_wait_until_done(smbus_io_base) < 0) {
140                 return -3;      /* timeout or error */
141         }
142
143         /* read results of transaction */
144         byte = inb(smbus_io_base + SMBHSTDAT0);
145
146         return byte;
147 }
148
149 int do_smbus_write_byte(u32 smbus_io_base, u32 device,
150                                u32 address, u8 val)
151 {
152         u8 byte;
153
154         if (smbus_wait_until_ready(smbus_io_base) < 0) {
155                 return -2;      /* not ready */
156         }
157
158         /* set the command/address... */
159         outb(address & 0xff, smbus_io_base + SMBHSTCMD);
160
161         /* set the device I'm talking too */
162         outb(((device & 0x7f) << 1) | 0, smbus_io_base + SMBHSTADDR);
163
164         /* output value */
165         outb(val, smbus_io_base + SMBHSTDAT0);
166
167         byte = inb(smbus_io_base + SMBHSTCTRL);
168         byte &= 0xe3;           /* Clear [4:2] */
169         byte |= (1 << 3) | (1 << 6);    /* Byte data read/write command, start the command */
170         outb(byte, smbus_io_base + SMBHSTCTRL);
171
172         /* poll for transaction completion */
173         if (smbus_wait_until_done(smbus_io_base) < 0) {
174                 return -3;      /* timeout or error */
175         }
176
177         return 0;
178 }
179
180 static void alink_ab_indx(u32 reg_space, u32 reg_addr,
181                           u32 mask, u32 val)
182 {
183         u32 tmp;
184
185         outl((reg_space & 0x3) << 30 | reg_addr, AB_INDX);
186         tmp = inl(AB_DATA);
187
188         tmp &= ~mask;
189         tmp |= val;
190
191         /* printk(BIOS_DEBUG, "about write %x, index=%x", tmp, (reg_space&0x3)<<30 | reg_addr); */
192         outl((reg_space & 0x3) << 30 | reg_addr, AB_INDX);      /* probably we dont have to do it again. */
193         outl(tmp, AB_DATA);
194 }
195
196 /* space = 0: AX_INDXC, AX_DATAC
197 *   space = 1: AX_INDXP, AX_DATAP
198  */
199 static void alink_ax_indx(u32 space /*c or p? */ , u32 axindc,
200                           u32 mask, u32 val)
201 {
202         u32 tmp;
203
204         /* read axindc to tmp */
205         outl(space << 30 | space << 3 | 0x30, AB_INDX);
206         outl(axindc, AB_DATA);
207         outl(space << 30 | space << 3 | 0x34, AB_INDX);
208         tmp = inl(AB_DATA);
209
210         tmp &= ~mask;
211         tmp |= val;
212
213         /* write tmp */
214         outl(space << 30 | space << 3 | 0x30, AB_INDX);
215         outl(axindc, AB_DATA);
216         outl(space << 30 | space << 3 | 0x34, AB_INDX);
217         outl(tmp, AB_DATA);
218 }