1#include <common.h>
2#include <mpc8xx.h>
3#include <malloc.h>
4#include <galileo/gt64260R.h>
5#include <galileo/core.h>
6
7#define MAX_I2C_RETRYS 10
8#define I2C_DELAY 1000
9#undef DEBUG_I2C
10
11#ifdef DEBUG_I2C
12#define DP(x) x
13#else
14#define DP(x)
15#endif
16
17
18
19static void
20i2c_init(int speed, int slaveaddr)
21{
22 unsigned int n, m, freq, margin, power;
23 unsigned int actualn = 0, actualm = 0;
24 unsigned int control, status;
25 unsigned int minmargin = 0xffffffff;
26 unsigned int tclk = 125000000;
27
28 DP(puts("i2c_init\n"));
29
30 for (n = 0 ; n < 8 ; n++) {
31 for (m = 0 ; m < 16 ; m++) {
32 power = 2 << n;
33 freq = tclk / (10 * (m + 1) * power);
34 if (speed > freq)
35 margin = speed - freq;
36 else
37 margin = freq - speed;
38 if (margin < minmargin) {
39 minmargin = margin;
40 actualn = n;
41 actualm = m;
42 }
43 }
44 }
45
46 DP(puts("setup i2c bus\n"));
47
48
49
50 GT_REG_WRITE(I2C_SOFT_RESET, 0);
51
52 DP(puts("udelay...\n"));
53
54 udelay(I2C_DELAY);
55
56 DP(puts("set baudrate\n"));
57
58 GT_REG_WRITE(I2C_STATUS_BAUDE_RATE, (actualm << 3) | actualn);
59 GT_REG_WRITE(I2C_CONTROL, (0x1 << 2) | (0x1 << 6));
60
61 udelay(I2C_DELAY * 10);
62
63 DP(puts("read control, baudrate\n"));
64
65 GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status);
66 GT_REG_READ(I2C_CONTROL, &control);
67}
68
69static uchar
70i2c_start(void)
71{
72 unsigned int control, status;
73 int count = 0;
74
75 DP(puts("i2c_start\n"));
76
77
78
79 GT_REG_READ(I2C_CONTROL, &control);
80 control |= (0x1 << 5);
81 GT_REG_WRITE(I2C_CONTROL, control);
82
83 GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status);
84
85 count = 0;
86 while ((status & 0xff) != 0x08) {
87 udelay(I2C_DELAY);
88 if (count > 20) {
89 GT_REG_WRITE(I2C_CONTROL, (0x1 << 4));
90 return status;
91 }
92 GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status);
93 count++;
94 }
95
96 return 0;
97}
98
99static uchar
100i2c_select_device(uchar dev_addr, uchar read, int ten_bit)
101{
102 unsigned int status, data, bits = 7;
103 int count = 0;
104
105 DP(puts("i2c_select_device\n"));
106
107
108
109 if (ten_bit)
110 bits = 10;
111
112 data = (dev_addr << 1);
113
114 data |= read;
115 GT_REG_WRITE(I2C_DATA, data);
116
117 RESET_REG_BITS(I2C_CONTROL, BIT3);
118
119 udelay(I2C_DELAY);
120
121 GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status);
122 count = 0;
123 while (((status & 0xff) != 0x40) && ((status & 0xff) != 0x18)) {
124 udelay(I2C_DELAY);
125 if (count > 20) {
126 GT_REG_WRITE(I2C_CONTROL, (0x1 << 4));
127 return status;
128 }
129 GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status);
130 count++;
131 }
132
133 if (bits == 10) {
134 printf("10 bit I2C addressing not yet implemented\n");
135 return 0xff;
136 }
137
138 return 0;
139}
140
141static uchar
142i2c_get_data(uchar *return_data, int len) {
143
144 unsigned int data, status = 0;
145 int count = 0;
146
147 DP(puts("i2c_get_data\n"));
148
149 while (len) {
150
151
152
153 RESET_REG_BITS(I2C_CONTROL, (0x1 << 3));
154
155 udelay(I2C_DELAY * 5);
156
157 GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status);
158 count++;
159 while ((status & 0xff) != 0x50) {
160 udelay(I2C_DELAY);
161 if (count > 2) {
162 GT_REG_WRITE(I2C_CONTROL, (0x1 << 4));
163 return 0;
164 }
165 GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status);
166 count++;
167 }
168 GT_REG_READ(I2C_DATA, &data);
169 len--;
170 *return_data = (uchar)data;
171 return_data++;
172 }
173 RESET_REG_BITS(I2C_CONTROL, BIT2|BIT3);
174 while ((status & 0xff) != 0x58) {
175 udelay(I2C_DELAY);
176 if (count > 200) {
177 GT_REG_WRITE(I2C_CONTROL, (0x1 << 4));
178 return status;
179 }
180 GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status);
181 count++;
182 }
183 GT_REG_WRITE(I2C_CONTROL, (0x1 << 4));
184
185 return 0;
186}
187
188static uchar
189i2c_write_data(unsigned int data, int len)
190{
191 unsigned int status;
192 int count = 0;
193
194 DP(puts("i2c_write_data\n"));
195
196 if (len > 4)
197 return -1;
198
199 while (len) {
200
201
202 GT_REG_WRITE(I2C_DATA, (unsigned int)data);
203 RESET_REG_BITS(I2C_CONTROL, (0x1 << 3));
204
205 udelay(I2C_DELAY);
206
207 GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status);
208 count++;
209 while ((status & 0xff) != 0x28) {
210 udelay(I2C_DELAY);
211 if (count > 20) {
212 GT_REG_WRITE(I2C_CONTROL, (0x1 << 4));
213 return status;
214 }
215 GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status);
216 count++;
217 }
218 len--;
219 }
220 GT_REG_WRITE(I2C_CONTROL, (0x1 << 3) | (0x1 << 4));
221 GT_REG_WRITE(I2C_CONTROL, (0x1 << 4));
222
223 udelay(I2C_DELAY * 10);
224
225 return 0;
226}
227
228static uchar
229i2c_set_dev_offset(uchar dev_addr, unsigned int offset, int ten_bit)
230{
231 uchar status;
232
233 DP(puts("i2c_set_dev_offset\n"));
234
235 status = i2c_select_device(dev_addr, 0, ten_bit);
236 if (status) {
237#ifdef DEBUG_I2C
238 printf("Failed to select device setting offset: 0x%02x\n",
239 status);
240#endif
241 return status;
242 }
243
244 status = i2c_write_data(offset, 1);
245 if (status) {
246#ifdef DEBUG_I2C
247 printf("Failed to write data: 0x%02x\n", status);
248#endif
249 return status;
250 }
251
252 return 0;
253}
254
255uchar
256i2c_read(uchar dev_addr, unsigned int offset, int len, uchar *data,
257 int ten_bit)
258{
259 uchar status = 0;
260 unsigned int i2cfreq = 400000;
261
262 DP(puts("i2c_read\n"));
263
264 i2c_init(i2cfreq, 0);
265
266 status = i2c_start();
267
268 if (status) {
269#ifdef DEBUG_I2C
270 printf("Transaction start failed: 0x%02x\n", status);
271#endif
272 return status;
273 }
274
275 status = i2c_set_dev_offset(dev_addr, 0, 0);
276 if (status) {
277#ifdef DEBUG_I2C
278 printf("Failed to set offset: 0x%02x\n", status);
279#endif
280 return status;
281 }
282
283 i2c_init(i2cfreq, 0);
284
285 status = i2c_start();
286 if (status) {
287#ifdef DEBUG_I2C
288 printf("Transaction restart failed: 0x%02x\n", status);
289#endif
290 return status;
291 }
292
293 status = i2c_select_device(dev_addr, 1, ten_bit);
294 if (status) {
295#ifdef DEBUG_I2C
296 printf("Address not acknowledged: 0x%02x\n", status);
297#endif
298 return status;
299 }
300
301 status = i2c_get_data(data, len);
302 if (status) {
303#ifdef DEBUG_I2C
304 printf("Data not received: 0x%02x\n", status);
305#endif
306 return status;
307 }
308
309 return 0;
310}
311