new cache_as_ram support
[coreboot.git] / src / southbridge / nvidia / ck804 / ck804_smbus.h
1 /*
2  * Copyright 2004 Tyan Computer
3  *  by yhlu@tyan.com
4  */
5 #include <device/smbus_def.h>
6
7 #define SMBHSTSTAT 0x1
8 #define SMBHSTPRTCL  0x0
9 #define SMBHSTCMD  0x3
10 #define SMBXMITADD 0x2
11 #define SMBHSTDAT0 0x4
12 #define SMBHSTDAT1 0x5
13
14 /* Between 1-10 seconds, We should never timeout normally 
15  * Longer than this is just painful when a timeout condition occurs.
16  */
17 #define SMBUS_TIMEOUT (100*1000*10)
18
19 static inline void smbus_delay(void)
20 {
21         outb(0x80, 0x80);
22 }
23
24 static int smbus_wait_until_ready(unsigned smbus_io_base)
25 {
26         unsigned long loops;
27         loops = SMBUS_TIMEOUT;
28         do {
29                 unsigned char val;
30                 smbus_delay();
31                 val = inb(smbus_io_base + SMBHSTSTAT);
32                 val &= 0x1f;
33                 if (val == 0) {
34                         return 0;
35                 }
36                 outb(val,smbus_io_base + SMBHSTSTAT);
37         } while(--loops);
38         return -2;
39 }
40
41 static int smbus_wait_until_done(unsigned smbus_io_base)
42 {
43         unsigned long loops;
44         loops = SMBUS_TIMEOUT;
45         do {
46                 unsigned char val;
47                 smbus_delay();
48                 
49                 val = inb(smbus_io_base + SMBHSTSTAT);
50                 if ( (val & 0xff) != 0) {
51                         return 0;
52                 }
53         } while(--loops);
54         return -3;
55 }
56 static int do_smbus_recv_byte(unsigned smbus_io_base, unsigned device)
57 {
58         unsigned char global_status_register;
59         unsigned char byte;
60 #if 0 
61 // Don't need, when you write to PRTCL, the status will be cleared automatically
62         if (smbus_wait_until_ready(smbus_io_base) < 0) {
63                 return -2;
64         }
65 #endif
66
67         /* set the device I'm talking too */
68         outb(((device & 0x7f) << 1)|1 , smbus_io_base + SMBXMITADD);
69         smbus_delay();
70         /* set the command/address... */
71         outb(0, smbus_io_base + SMBHSTCMD);
72         smbus_delay();
73         /* byte data recv */
74         outb(0x05, smbus_io_base + SMBHSTPRTCL);
75         smbus_delay();
76
77         /* poll for transaction completion */
78         if (smbus_wait_until_done(smbus_io_base) < 0) {
79                 return -3;
80         }
81
82         global_status_register = inb(smbus_io_base + SMBHSTSTAT) & 0x80; /* lose check */
83
84         /* read results of transaction */
85         byte = inb(smbus_io_base + SMBHSTDAT0);
86
87         if (global_status_register != 0x80) { // lose check, otherwise it should be 0
88                 return -1;
89         }
90         return byte;
91 }
92 static int do_smbus_send_byte(unsigned smbus_io_base, unsigned device, unsigned char val)
93 {
94         unsigned global_status_register;
95
96 #if 0
97 // Don't need, when you write to PRTCL, the status will be cleared automatically
98         if (smbus_wait_until_ready(smbus_io_base) < 0) {
99                 return -2;
100         }
101 #endif
102
103         outb(val, smbus_io_base + SMBHSTDAT0);
104         smbus_delay();
105
106         /* set the device I'm talking too */
107         outb(((device & 0x7f) << 1) | 0, smbus_io_base + SMBXMITADD);
108         smbus_delay();
109
110         outb(0, smbus_io_base + SMBHSTCMD);
111         smbus_delay();
112
113         /* set up for a byte data write */
114         outb(0x04, smbus_io_base + SMBHSTPRTCL);
115         smbus_delay();
116
117         /* poll for transaction completion */
118         if (smbus_wait_until_done(smbus_io_base) < 0) {
119                 return -3;
120         }
121         global_status_register = inb(smbus_io_base + SMBHSTSTAT) & 0x80; /* lose check */;
122
123         if (global_status_register != 0x80) {
124                 return -1;
125         }
126         return 0;
127 }
128 static int do_smbus_read_byte(unsigned smbus_io_base, unsigned device, unsigned address)
129 {
130         unsigned char global_status_register;
131         unsigned char byte;
132 #if 0 
133 // Don't need, when you write to PRTCL, the status will be cleared automatically
134         if (smbus_wait_until_ready(smbus_io_base) < 0) {
135                 return -2;
136         }
137 #endif
138         
139         /* set the device I'm talking too */
140         outb(((device & 0x7f) << 1)|1 , smbus_io_base + SMBXMITADD);
141         smbus_delay();
142         /* set the command/address... */
143         outb(address & 0xff, smbus_io_base + SMBHSTCMD);
144         smbus_delay();
145         /* byte data read */
146         outb(0x07, smbus_io_base + SMBHSTPRTCL);
147         smbus_delay();
148
149         /* poll for transaction completion */
150         if (smbus_wait_until_done(smbus_io_base) < 0) {
151                 return -3;
152         }
153
154         global_status_register = inb(smbus_io_base + SMBHSTSTAT) & 0x80; /* lose check */
155
156         /* read results of transaction */
157         byte = inb(smbus_io_base + SMBHSTDAT0);
158
159         if (global_status_register != 0x80) { // lose check, otherwise it should be 0
160                 return -1;
161         }
162         return byte;
163 }
164
165
166 static int do_smbus_write_byte(unsigned smbus_io_base, unsigned device, unsigned address, unsigned char val)
167 {
168         unsigned global_status_register;
169
170 #if 0
171 // Don't need, when you write to PRTCL, the status will be cleared automatically
172         if (smbus_wait_until_ready(smbus_io_base) < 0) {
173                 return -2;
174         }
175 #endif
176
177         outb(val, smbus_io_base + SMBHSTDAT0);
178         smbus_delay();
179
180         /* set the device I'm talking too */
181         outb(((device & 0x7f) << 1) | 0, smbus_io_base + SMBXMITADD);
182         smbus_delay();
183
184         outb(address & 0xff, smbus_io_base + SMBHSTCMD);
185         smbus_delay();
186
187         /* set up for a byte data write */ 
188         outb(0x06, smbus_io_base + SMBHSTPRTCL);
189         smbus_delay();
190
191         /* poll for transaction completion */
192         if (smbus_wait_until_done(smbus_io_base) < 0) {
193                 return -3;
194         }
195         global_status_register = inb(smbus_io_base + SMBHSTSTAT) & 0x80; /* lose check */;
196
197         if (global_status_register != 0x80) {
198                 return -1;
199         }
200         return 0;
201 }
202