1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22#include <types.h>
23#include <device/smbus.h>
24#include <device/smbus_def.h>
25#include <device/pci_ids.h>
26#include <device/pci_ops.h>
27#include <device/pci.h>
28#include <device/device.h>
29#include <console.h>
30#include <io.h>
31#include "ck804_smbus.h"
32
33static inline void smbus_delay(void)
34{
35 outb(0x80, 0x80);
36}
37
38int smbus_wait_until_ready(unsigned smbus_io_base)
39{
40 unsigned long loops;
41 loops = SMBUS_TIMEOUT;
42 do {
43 unsigned char val;
44 smbus_delay();
45 val = inb(smbus_io_base + SMBHSTSTAT);
46 val &= 0x1f;
47 if (val == 0)
48 return 0;
49 outb(val, smbus_io_base + SMBHSTSTAT);
50 } while (--loops);
51 return -2;
52}
53
54int smbus_wait_until_done(unsigned smbus_io_base)
55{
56 unsigned long loops;
57 loops = SMBUS_TIMEOUT;
58 do {
59 unsigned char val;
60 smbus_delay();
61 val = inb(smbus_io_base + SMBHSTSTAT);
62 if ((val & 0xff) != 0)
63 return 0;
64 } while (--loops);
65 return -3;
66}
67
68int do_smbus_recv_byte(unsigned smbus_io_base, unsigned device)
69{
70 unsigned char global_status_register, byte;
71
72
73 outb(((device & 0x7f) << 1) | 1, smbus_io_base + SMBXMITADD);
74 smbus_delay();
75
76
77 outb(0, smbus_io_base + SMBHSTCMD);
78 smbus_delay();
79
80
81 outb(0x05, smbus_io_base + SMBHSTPRTCL);
82 smbus_delay();
83
84
85 if (smbus_wait_until_done(smbus_io_base) < 0)
86 return -3;
87
88
89 global_status_register = inb(smbus_io_base + SMBHSTSTAT) & 0x80;
90
91
92 byte = inb(smbus_io_base + SMBHSTDAT0);
93
94
95 if (global_status_register != 0x80)
96 return -1;
97
98 return byte;
99}
100
101int do_smbus_send_byte(unsigned smbus_io_base, unsigned device,
102 unsigned char val)
103{
104 unsigned global_status_register;
105
106 outb(val, smbus_io_base + SMBHSTDAT0);
107 smbus_delay();
108
109
110 outb(((device & 0x7f) << 1) | 0, smbus_io_base + SMBXMITADD);
111 smbus_delay();
112
113 outb(0, smbus_io_base + SMBHSTCMD);
114 smbus_delay();
115
116
117 outb(0x04, smbus_io_base + SMBHSTPRTCL);
118 smbus_delay();
119
120
121 if (smbus_wait_until_done(smbus_io_base) < 0)
122 return -3;
123
124
125 global_status_register = inb(smbus_io_base + SMBHSTSTAT) & 0x80;
126
127 if (global_status_register != 0x80)
128 return -1;
129
130 return 0;
131}
132
133int do_smbus_read_byte(unsigned smbus_io_base, unsigned device,
134 unsigned address)
135{
136 unsigned char global_status_register, byte;
137
138
139 outb(((device & 0x7f) << 1) | 1, smbus_io_base + SMBXMITADD);
140 smbus_delay();
141
142
143 outb(address & 0xff, smbus_io_base + SMBHSTCMD);
144 smbus_delay();
145
146
147 outb(0x07, smbus_io_base + SMBHSTPRTCL);
148 smbus_delay();
149
150
151 if (smbus_wait_until_done(smbus_io_base) < 0)
152 return -3;
153
154
155 global_status_register = inb(smbus_io_base + SMBHSTSTAT) & 0x80;
156
157
158 byte = inb(smbus_io_base + SMBHSTDAT0);
159
160
161 if (global_status_register != 0x80)
162 return -1;
163
164 return byte;
165}
166
167int do_smbus_write_byte(unsigned smbus_io_base, unsigned device,
168 unsigned address, unsigned char val)
169{
170 unsigned global_status_register;
171
172 outb(val, smbus_io_base + SMBHSTDAT0);
173 smbus_delay();
174
175
176 outb(((device & 0x7f) << 1) | 0, smbus_io_base + SMBXMITADD);
177 smbus_delay();
178
179 outb(address & 0xff, smbus_io_base + SMBHSTCMD);
180 smbus_delay();
181
182
183 outb(0x06, smbus_io_base + SMBHSTPRTCL);
184 smbus_delay();
185
186
187 if (smbus_wait_until_done(smbus_io_base) < 0)
188 return -3;
189
190
191 global_status_register = inb(smbus_io_base + SMBHSTSTAT) & 0x80;
192
193 if (global_status_register != 0x80)
194 return -1;
195
196 return 0;
197}
198