Use common GPL-header format in CK804 files, add missing ones (trivial).
[coreboot.git] / src / southbridge / nvidia / ck804 / ck804_smbus.h
1 /*
2  * This file is part of the coreboot project.
3  *
4  * Copyright (C) 2004 Tyan Computer
5  * Written by Yinghai Lu <yhlu@tyan.com> for Tyan Computer.
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; version 2 of the License.
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 #include <device/smbus_def.h>
22
23 #define SMBHSTSTAT  0x1
24 #define SMBHSTPRTCL 0x0
25 #define SMBHSTCMD   0x3
26 #define SMBXMITADD  0x2
27 #define SMBHSTDAT0  0x4
28 #define SMBHSTDAT1  0x5
29
30 /*
31  * Between 1-10 seconds, We should never timeout normally.
32  * Longer than this is just painful when a timeout condition occurs.
33  */
34 #define SMBUS_TIMEOUT (100 * 1000 * 10)
35
36 static inline void smbus_delay(void)
37 {
38         outb(0x80, 0x80);
39 }
40
41 #if 0
42 /* Not needed, upon write to PRTCL, the status will be auto-cleared. */
43 static int smbus_wait_until_ready(unsigned smbus_io_base)
44 {
45         unsigned long loops;
46         loops = SMBUS_TIMEOUT;
47         do {
48                 unsigned char val;
49                 smbus_delay();
50                 val = inb(smbus_io_base + SMBHSTSTAT);
51                 val &= 0x1f;
52                 if (val == 0)
53                         return 0;
54                 outb(val, smbus_io_base + SMBHSTSTAT);
55         } while (--loops);
56         return -2;
57 }
58 #endif
59
60 static int smbus_wait_until_done(unsigned smbus_io_base)
61 {
62         unsigned long loops;
63         loops = SMBUS_TIMEOUT;
64         do {
65                 unsigned char val;
66                 smbus_delay();
67                 val = inb(smbus_io_base + SMBHSTSTAT);
68                 if ((val & 0xff) != 0)
69                         return 0;
70         } while (--loops);
71         return -3;
72 }
73
74 #ifndef __PRE_RAM__
75 static int do_smbus_recv_byte(unsigned smbus_io_base, unsigned device)
76 {
77         unsigned char global_status_register, byte;
78
79 #if 0
80         /* Not needed, upon write to PRTCL, the status will be auto-cleared. */
81         if (smbus_wait_until_ready(smbus_io_base) < 0)
82                 return -2;
83 #endif
84
85         /* Set the device I'm talking to. */
86         outb(((device & 0x7f) << 1) | 1, smbus_io_base + SMBXMITADD);
87         smbus_delay();
88
89         /* Set the command/address. */
90         outb(0, smbus_io_base + SMBHSTCMD);
91         smbus_delay();
92
93         /* Byte data recv */
94         outb(0x05, smbus_io_base + SMBHSTPRTCL);
95         smbus_delay();
96
97         /* Poll for transaction completion. */
98         if (smbus_wait_until_done(smbus_io_base) < 0)
99                 return -3;
100
101         /* Lose check */
102         global_status_register = inb(smbus_io_base + SMBHSTSTAT) & 0x80;
103
104         /* Read results of transaction. */
105         byte = inb(smbus_io_base + SMBHSTDAT0);
106
107         /* Lose check, otherwise it should be 0. */
108         if (global_status_register != 0x80)
109                 return -1;
110
111         return byte;
112 }
113
114 static int do_smbus_send_byte(unsigned smbus_io_base, unsigned device,
115                               unsigned char val)
116 {
117         unsigned global_status_register;
118
119 #if 0
120         /* Not needed, upon write to PRTCL, the status will be auto-cleared. */
121         if (smbus_wait_until_ready(smbus_io_base) < 0)
122                 return -2;
123 #endif
124
125         outb(val, smbus_io_base + SMBHSTDAT0);
126         smbus_delay();
127
128         /* Set the device I'm talking to. */
129         outb(((device & 0x7f) << 1) | 0, smbus_io_base + SMBXMITADD);
130         smbus_delay();
131
132         outb(0, smbus_io_base + SMBHSTCMD);
133         smbus_delay();
134
135         /* Set up for a byte data write. */
136         outb(0x04, smbus_io_base + SMBHSTPRTCL);
137         smbus_delay();
138
139         /* Poll for transaction completion. */
140         if (smbus_wait_until_done(smbus_io_base) < 0)
141                 return -3;
142
143         /* Lose check */
144         global_status_register = inb(smbus_io_base + SMBHSTSTAT) & 0x80;
145
146         if (global_status_register != 0x80)
147                 return -1;
148
149         return 0;
150 }
151 #endif
152
153 static int do_smbus_read_byte(unsigned smbus_io_base, unsigned device,
154                               unsigned address)
155 {
156         unsigned char global_status_register, byte;
157
158 #if 0
159         /* Not needed, upon write to PRTCL, the status will be auto-cleared. */
160         if (smbus_wait_until_ready(smbus_io_base) < 0)
161                 return -2;
162 #endif
163
164         /* Set the device I'm talking to. */
165         outb(((device & 0x7f) << 1) | 1, smbus_io_base + SMBXMITADD);
166         smbus_delay();
167
168         /* Set the command/address. */
169         outb(address & 0xff, smbus_io_base + SMBHSTCMD);
170         smbus_delay();
171
172         /* Byte data read */
173         outb(0x07, smbus_io_base + SMBHSTPRTCL);
174         smbus_delay();
175
176         /* Poll for transaction completion. */
177         if (smbus_wait_until_done(smbus_io_base) < 0)
178                 return -3;
179
180         /* Lose check */
181         global_status_register = inb(smbus_io_base + SMBHSTSTAT) & 0x80;
182
183         /* Read results of transaction. */
184         byte = inb(smbus_io_base + SMBHSTDAT0);
185
186         /* Lose check, otherwise it should be 0. */
187         if (global_status_register != 0x80)
188                 return -1;
189
190         return byte;
191 }
192
193 static int do_smbus_write_byte(unsigned smbus_io_base, unsigned device,
194                                unsigned address, unsigned char val)
195 {
196         unsigned global_status_register;
197
198 #if 0
199         /* Not needed, upon write to PRTCL, the status will be auto-cleared. */
200         if (smbus_wait_until_ready(smbus_io_base) < 0)
201                 return -2;
202 #endif
203
204         outb(val, smbus_io_base + SMBHSTDAT0);
205         smbus_delay();
206
207         /* Set the device I'm talking to. */
208         outb(((device & 0x7f) << 1) | 0, smbus_io_base + SMBXMITADD);
209         smbus_delay();
210
211         outb(address & 0xff, smbus_io_base + SMBHSTCMD);
212         smbus_delay();
213
214         /* Set up for a byte data write. */
215         outb(0x06, smbus_io_base + SMBHSTPRTCL);
216         smbus_delay();
217
218         /* Poll for transaction completion. */
219         if (smbus_wait_until_done(smbus_io_base) < 0)
220                 return -3;
221
222         /* Lose check */
223         global_status_register = inb(smbus_io_base + SMBHSTSTAT) & 0x80;
224
225         if (global_status_register != 0x80)
226                 return -1;
227
228         return 0;
229 }