]>
Commit | Line | Data |
---|---|---|
3a473b2a WD |
1 | /* |
2 | * (C) Copyright 2000 | |
3 | * Wolfgang Denk, DENX Software Engineering, wd@denx.de. | |
4 | * | |
5 | * See file CREDITS for list of people who contributed to this | |
6 | * project. | |
7 | * | |
8 | * This program is free software; you can redistribute it and/or | |
9 | * modify it under the terms of the GNU General Public License as | |
10 | * published by the Free Software Foundation; either version 2 of | |
11 | * the License, or (at your option) any later version. | |
12 | * | |
13 | * This program is distributed in the hope that it will be useful, | |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | * GNU General Public License for more details. | |
17 | * | |
18 | * You should have received a copy of the GNU General Public License | |
19 | * along with this program; if not, write to the Free Software | |
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | |
21 | * MA 02111-1307 USA | |
22 | * | |
23 | * Hacked for the DB64360 board by Ingo.Assmus@keymile.com | |
24 | * extra improvments by Brain Waite | |
25 | */ | |
26 | #include <common.h> | |
27 | #include <mpc8xx.h> | |
28 | #include <malloc.h> | |
29 | #include "../include/mv_gen_reg.h" | |
30 | #include "../include/core.h" | |
31 | ||
32 | #define MAX_I2C_RETRYS 10 | |
33 | #define I2C_DELAY 1000 /* Should be at least the # of MHz of Tclk */ | |
34 | #undef DEBUG_I2C | |
35 | /*#define DEBUG_I2C*/ | |
36 | ||
37 | #ifdef DEBUG_I2C | |
38 | #define DP(x) x | |
39 | #else | |
40 | #define DP(x) | |
41 | #endif | |
42 | ||
43 | /* Assuming that there is only one master on the bus (us) */ | |
44 | ||
45 | static void i2c_init (int speed, int slaveaddr) | |
46 | { | |
47 | unsigned int n, m, freq, margin, power; | |
48 | unsigned int actualN = 0, actualM = 0; | |
49 | unsigned int control, status; | |
50 | unsigned int minMargin = 0xffffffff; | |
51 | unsigned int tclk = CFG_TCLK; | |
52 | unsigned int i2cFreq = speed; /* 100000 max. Fast mode not supported */ | |
53 | ||
54 | DP (puts ("i2c_init\n")); | |
55 | /* gtI2cMasterInit */ | |
56 | for (n = 0; n < 8; n++) { | |
57 | for (m = 0; m < 16; m++) { | |
58 | power = 2 << n; /* power = 2^(n+1) */ | |
59 | freq = tclk / (10 * (m + 1) * power); | |
60 | if (i2cFreq > freq) | |
61 | margin = i2cFreq - freq; | |
62 | else | |
63 | margin = freq - i2cFreq; | |
64 | if (margin < minMargin) { | |
65 | minMargin = margin; | |
66 | actualN = n; | |
67 | actualM = m; | |
68 | } | |
69 | } | |
70 | } | |
71 | ||
72 | DP (puts ("setup i2c bus\n")); | |
73 | ||
74 | /* Setup bus */ | |
75 | /* gtI2cReset */ | |
76 | GT_REG_WRITE (I2C_SOFT_RESET, 0); | |
77 | ||
78 | DP (puts ("udelay...\n")); | |
79 | ||
80 | udelay (I2C_DELAY); | |
81 | ||
82 | DP (puts ("set baudrate\n")); | |
83 | ||
84 | GT_REG_WRITE (I2C_STATUS_BAUDE_RATE, (actualM << 3) | actualN); | |
85 | GT_REG_WRITE (I2C_CONTROL, (0x1 << 2) | (0x1 << 6)); | |
86 | ||
87 | udelay (I2C_DELAY * 10); | |
88 | ||
89 | DP (puts ("read control, baudrate\n")); | |
90 | ||
91 | GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status); | |
92 | GT_REG_READ (I2C_CONTROL, &control); | |
93 | } | |
94 | ||
95 | static uchar i2c_start (void) | |
96 | { /* DB64360 checked -> ok */ | |
97 | unsigned int control, status; | |
98 | int count = 0; | |
99 | ||
100 | DP (puts ("i2c_start\n")); | |
101 | ||
102 | /* Set the start bit */ | |
103 | ||
104 | /* gtI2cGenerateStartBit() */ | |
105 | ||
106 | GT_REG_READ (I2C_CONTROL, &control); | |
107 | control |= (0x1 << 5); /* generate the I2C_START_BIT */ | |
108 | GT_REG_WRITE (I2C_CONTROL, control); | |
109 | ||
110 | GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status); | |
111 | ||
112 | count = 0; | |
113 | while ((status & 0xff) != 0x08) { | |
114 | udelay (I2C_DELAY); | |
115 | if (count > 20) { | |
116 | GT_REG_WRITE (I2C_CONTROL, (0x1 << 4)); /*stop */ | |
117 | return (status); | |
118 | } | |
119 | GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status); | |
120 | count++; | |
121 | } | |
122 | ||
123 | return (0); | |
124 | } | |
125 | ||
126 | static uchar i2c_select_device (uchar dev_addr, uchar read, int ten_bit) | |
127 | { | |
128 | unsigned int status, data, bits = 7; | |
129 | int count = 0; | |
130 | ||
131 | DP (puts ("i2c_select_device\n")); | |
132 | ||
133 | /* Output slave address */ | |
134 | ||
135 | if (ten_bit) { | |
136 | bits = 10; | |
137 | } | |
138 | ||
139 | data = (dev_addr << 1); | |
140 | /* set the read bit */ | |
141 | data |= read; | |
142 | GT_REG_WRITE (I2C_DATA, data); | |
143 | /* assert the address */ | |
144 | RESET_REG_BITS (I2C_CONTROL, BIT3); | |
145 | ||
146 | udelay (I2C_DELAY); | |
147 | ||
148 | GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status); | |
149 | count = 0; | |
150 | while (((status & 0xff) != 0x40) && ((status & 0xff) != 0x18)) { | |
151 | udelay (I2C_DELAY); | |
152 | if (count > 20) { | |
153 | GT_REG_WRITE (I2C_CONTROL, (0x1 << 4)); /*stop */ | |
154 | return (status); | |
155 | } | |
156 | GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status); | |
157 | count++; | |
158 | } | |
159 | ||
160 | if (bits == 10) { | |
161 | printf ("10 bit I2C addressing not yet implemented\n"); | |
162 | return (0xff); | |
163 | } | |
164 | ||
165 | return (0); | |
166 | } | |
167 | ||
168 | static uchar i2c_get_data (uchar * return_data, int len) | |
169 | { | |
170 | ||
77ddac94 | 171 | unsigned int data, status = 0; |
3a473b2a WD |
172 | int count = 0; |
173 | ||
174 | DP (puts ("i2c_get_data\n")); | |
175 | ||
176 | while (len) { | |
177 | ||
178 | /* Get and return the data */ | |
179 | ||
180 | RESET_REG_BITS (I2C_CONTROL, (0x1 << 3)); | |
181 | ||
182 | udelay (I2C_DELAY * 5); | |
183 | ||
184 | GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status); | |
185 | count++; | |
186 | while ((status & 0xff) != 0x50) { | |
187 | udelay (I2C_DELAY); | |
188 | if (count > 2) { | |
189 | GT_REG_WRITE (I2C_CONTROL, (0x1 << 4)); /*stop */ | |
190 | return 0; | |
191 | } | |
192 | GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status); | |
193 | count++; | |
194 | } | |
195 | GT_REG_READ (I2C_DATA, &data); | |
196 | len--; | |
197 | *return_data = (uchar) data; | |
198 | return_data++; | |
199 | } | |
200 | RESET_REG_BITS (I2C_CONTROL, BIT2 | BIT3); | |
201 | while ((status & 0xff) != 0x58) { | |
202 | udelay (I2C_DELAY); | |
203 | if (count > 200) { | |
204 | GT_REG_WRITE (I2C_CONTROL, (0x1 << 4)); /*stop */ | |
205 | return (status); | |
206 | } | |
207 | GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status); | |
208 | count++; | |
209 | } | |
210 | GT_REG_WRITE (I2C_CONTROL, (0x1 << 4)); /* stop */ | |
211 | ||
212 | return (0); | |
213 | } | |
214 | ||
215 | static uchar i2c_write_data (unsigned int *data, int len) | |
216 | { | |
217 | unsigned int status; | |
218 | int count = 0; | |
219 | unsigned int temp; | |
220 | unsigned int *temp_ptr = data; | |
221 | ||
222 | DP (puts ("i2c_write_data\n")); | |
223 | ||
224 | while (len) { | |
225 | temp = (unsigned int) (*temp_ptr); | |
226 | GT_REG_WRITE (I2C_DATA, temp); | |
227 | RESET_REG_BITS (I2C_CONTROL, (0x1 << 3)); | |
228 | ||
229 | udelay (I2C_DELAY); | |
230 | ||
231 | GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status); | |
232 | count++; | |
233 | while ((status & 0xff) != 0x28) { | |
234 | udelay (I2C_DELAY); | |
235 | if (count > 20) { | |
236 | GT_REG_WRITE (I2C_CONTROL, (0x1 << 4)); /*stop */ | |
237 | return (status); | |
238 | } | |
239 | GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status); | |
240 | count++; | |
241 | } | |
242 | len--; | |
243 | temp_ptr++; | |
244 | } | |
245 | /* 11-14-2002 Paul Marchese */ | |
246 | /* Can't have the write issuing a stop command */ | |
247 | /* it's wrong to have a stop bit in read stream or write stream */ | |
248 | /* since we don't know if it's really the end of the command */ | |
249 | /* or whether we have just send the device address + offset */ | |
250 | /* we will push issuing the stop command off to the original */ | |
251 | /* calling function */ | |
252 | /* set the interrupt bit in the control register */ | |
253 | GT_REG_WRITE (I2C_CONTROL, (0x1 << 3)); | |
254 | udelay (I2C_DELAY * 10); | |
255 | return (0); | |
256 | } | |
257 | ||
258 | /* 11-14-2002 Paul Marchese */ | |
259 | /* created this function to get the i2c_write() */ | |
260 | /* function working properly. */ | |
261 | /* function to write bytes out on the i2c bus */ | |
262 | /* this is identical to the function i2c_write_data() */ | |
263 | /* except that it requires a buffer that is an */ | |
264 | /* unsigned character array. You can't use */ | |
265 | /* i2c_write_data() to send an array of unsigned characters */ | |
266 | /* since the byte of interest ends up on the wrong end of the bus */ | |
267 | /* aah, the joys of big endian versus little endian! */ | |
268 | /* */ | |
269 | /* returns 0 = success */ | |
270 | /* anything other than zero is failure */ | |
271 | static uchar i2c_write_byte (unsigned char *data, int len) | |
272 | { | |
273 | unsigned int status; | |
274 | int count = 0; | |
275 | unsigned int temp; | |
276 | unsigned char *temp_ptr = data; | |
277 | ||
278 | DP (puts ("i2c_write_byte\n")); | |
279 | ||
280 | while (len) { | |
281 | /* Set and assert the data */ | |
282 | temp = *temp_ptr; | |
283 | GT_REG_WRITE (I2C_DATA, temp); | |
284 | RESET_REG_BITS (I2C_CONTROL, (0x1 << 3)); | |
285 | ||
286 | udelay (I2C_DELAY); | |
287 | ||
288 | GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status); | |
289 | count++; | |
290 | while ((status & 0xff) != 0x28) { | |
291 | udelay (I2C_DELAY); | |
292 | if (count > 20) { | |
293 | GT_REG_WRITE (I2C_CONTROL, (0x1 << 4)); /*stop */ | |
294 | return (status); | |
295 | } | |
296 | GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status); | |
297 | count++; | |
298 | } | |
299 | len--; | |
300 | temp_ptr++; | |
301 | } | |
302 | /* Can't have the write issuing a stop command */ | |
303 | /* it's wrong to have a stop bit in read stream or write stream */ | |
304 | /* since we don't know if it's really the end of the command */ | |
305 | /* or whether we have just send the device address + offset */ | |
306 | /* we will push issuing the stop command off to the original */ | |
307 | /* calling function */ | |
308 | /* GT_REG_WRITE(I2C_CONTROL, (0x1 << 3) | (0x1 << 4)); | |
309 | GT_REG_WRITE(I2C_CONTROL, (0x1 << 4)); */ | |
310 | /* set the interrupt bit in the control register */ | |
311 | GT_REG_WRITE (I2C_CONTROL, (0x1 << 3)); | |
312 | udelay (I2C_DELAY * 10); | |
313 | ||
314 | return (0); | |
315 | } | |
316 | ||
317 | static uchar | |
318 | i2c_set_dev_offset (uchar dev_addr, unsigned int offset, int ten_bit, | |
319 | int alen) | |
320 | { | |
321 | uchar status; | |
322 | unsigned int table[2]; | |
323 | ||
324 | /* initialize the table of address offset bytes */ | |
325 | /* utilized for 2 byte address offsets */ | |
326 | /* NOTE: the order is high byte first! */ | |
327 | table[1] = offset & 0xff; /* low byte */ | |
328 | table[0] = offset / 0x100; /* high byte */ | |
329 | ||
330 | DP (puts ("i2c_set_dev_offset\n")); | |
331 | ||
332 | status = i2c_select_device (dev_addr, 0, ten_bit); | |
333 | if (status) { | |
334 | #ifdef DEBUG_I2C | |
335 | printf ("Failed to select device setting offset: 0x%02x\n", | |
336 | status); | |
337 | #endif | |
338 | return status; | |
339 | } | |
340 | /* check the address offset length */ | |
341 | if (alen == 0) | |
342 | /* no address offset */ | |
343 | return (0); | |
344 | else if (alen == 1) { | |
345 | /* 1 byte address offset */ | |
346 | status = i2c_write_data (&offset, 1); | |
347 | if (status) { | |
348 | #ifdef DEBUG_I2C | |
349 | printf ("Failed to write data: 0x%02x\n", status); | |
350 | #endif | |
351 | return status; | |
352 | } | |
353 | } else if (alen == 2) { | |
354 | /* 2 bytes address offset */ | |
355 | status = i2c_write_data (table, 2); | |
356 | if (status) { | |
357 | #ifdef DEBUG_I2C | |
358 | printf ("Failed to write data: 0x%02x\n", status); | |
359 | #endif | |
360 | return status; | |
361 | } | |
362 | } else { | |
363 | /* address offset unknown or not supported */ | |
364 | printf ("Address length offset %d is not supported\n", alen); | |
365 | return 1; | |
366 | } | |
367 | return 0; /* sucessful completion */ | |
368 | } | |
369 | ||
370 | uchar | |
371 | i2c_read (uchar dev_addr, unsigned int offset, int alen, uchar * data, | |
372 | int len) | |
373 | { | |
374 | uchar status = 0; | |
375 | unsigned int i2cFreq = CFG_I2C_SPEED; | |
376 | ||
377 | DP (puts ("i2c_read\n")); | |
378 | ||
379 | i2c_init (i2cFreq, 0); /* set the i2c frequency */ | |
380 | ||
381 | status = i2c_start (); | |
382 | ||
383 | if (status) { | |
384 | #ifdef DEBUG_I2C | |
385 | printf ("Transaction start failed: 0x%02x\n", status); | |
386 | #endif | |
387 | return status; | |
388 | } | |
389 | ||
390 | status = i2c_set_dev_offset (dev_addr, offset, 0, alen); /* send the slave address + offset */ | |
391 | if (status) { | |
392 | #ifdef DEBUG_I2C | |
393 | printf ("Failed to set slave address & offset: 0x%02x\n", | |
394 | status); | |
395 | #endif | |
396 | return status; | |
397 | } | |
398 | ||
399 | i2c_init (i2cFreq, 0); /* set the i2c frequency again */ | |
400 | ||
401 | status = i2c_start (); | |
402 | if (status) { | |
403 | #ifdef DEBUG_I2C | |
404 | printf ("Transaction restart failed: 0x%02x\n", status); | |
405 | #endif | |
406 | return status; | |
407 | } | |
408 | ||
409 | status = i2c_select_device (dev_addr, 1, 0); /* send the slave address */ | |
410 | if (status) { | |
411 | #ifdef DEBUG_I2C | |
412 | printf ("Address not acknowledged: 0x%02x\n", status); | |
413 | #endif | |
414 | return status; | |
415 | } | |
416 | ||
417 | status = i2c_get_data (data, len); | |
418 | if (status) { | |
419 | #ifdef DEBUG_I2C | |
420 | printf ("Data not recieved: 0x%02x\n", status); | |
421 | #endif | |
422 | return status; | |
423 | } | |
424 | ||
425 | return 0; | |
426 | } | |
427 | ||
428 | /* 11-14-2002 Paul Marchese */ | |
429 | /* Function to set the I2C stop bit */ | |
430 | void i2c_stop (void) | |
431 | { | |
432 | GT_REG_WRITE (I2C_CONTROL, (0x1 << 4)); | |
433 | } | |
434 | ||
435 | /* 11-14-2002 Paul Marchese */ | |
436 | /* I2C write function */ | |
437 | /* dev_addr = device address */ | |
438 | /* offset = address offset */ | |
439 | /* alen = length in bytes of the address offset */ | |
440 | /* data = pointer to buffer to read data into */ | |
441 | /* len = # of bytes to read */ | |
442 | /* */ | |
443 | /* returns 0 = succesful */ | |
444 | /* anything but zero is failure */ | |
445 | uchar | |
446 | i2c_write (uchar dev_addr, unsigned int offset, int alen, uchar * data, | |
447 | int len) | |
448 | { | |
449 | uchar status = 0; | |
450 | unsigned int i2cFreq = CFG_I2C_SPEED; | |
451 | ||
452 | DP (puts ("i2c_write\n")); | |
453 | ||
454 | i2c_init (i2cFreq, 0); /* set the i2c frequency */ | |
455 | ||
456 | status = i2c_start (); /* send a start bit */ | |
457 | ||
458 | if (status) { | |
459 | #ifdef DEBUG_I2C | |
460 | printf ("Transaction start failed: 0x%02x\n", status); | |
461 | #endif | |
462 | return status; | |
463 | } | |
464 | ||
465 | status = i2c_set_dev_offset (dev_addr, offset, 0, alen); /* send the slave address + offset */ | |
466 | if (status) { | |
467 | #ifdef DEBUG_I2C | |
468 | printf ("Failed to set slave address & offset: 0x%02x\n", | |
469 | status); | |
470 | #endif | |
471 | return status; | |
472 | } | |
473 | ||
474 | ||
475 | status = i2c_write_byte (data, len); /* write the data */ | |
476 | if (status) { | |
477 | #ifdef DEBUG_I2C | |
478 | printf ("Data not written: 0x%02x\n", status); | |
479 | #endif | |
480 | return status; | |
481 | } | |
482 | /* issue a stop bit */ | |
483 | i2c_stop (); | |
484 | return 0; | |
485 | } | |
486 | ||
487 | /* 11-14-2002 Paul Marchese */ | |
488 | /* function to determine if an I2C device is present */ | |
489 | /* chip = device address of chip to check for */ | |
490 | /* */ | |
491 | /* returns 0 = sucessful, the device exists */ | |
492 | /* anything other than zero is failure, no device */ | |
493 | int i2c_probe (uchar chip) | |
494 | { | |
495 | ||
496 | /* We are just looking for an <ACK> back. */ | |
497 | /* To see if the device/chip is there */ | |
498 | ||
499 | #ifdef DEBUG_I2C | |
500 | unsigned int i2c_status; | |
501 | #endif | |
502 | uchar status = 0; | |
503 | unsigned int i2cFreq = CFG_I2C_SPEED; | |
504 | ||
505 | DP (puts ("i2c_probe\n")); | |
506 | ||
507 | i2c_init (i2cFreq, 0); /* set the i2c frequency */ | |
508 | ||
509 | status = i2c_start (); /* send a start bit */ | |
510 | ||
511 | if (status) { | |
512 | #ifdef DEBUG_I2C | |
513 | printf ("Transaction start failed: 0x%02x\n", status); | |
514 | #endif | |
515 | return (int) status; | |
516 | } | |
517 | ||
518 | status = i2c_set_dev_offset (chip, 0, 0, 0); /* send the slave address + no offset */ | |
519 | if (status) { | |
520 | #ifdef DEBUG_I2C | |
521 | printf ("Failed to set slave address: 0x%02x\n", status); | |
522 | #endif | |
523 | return (int) status; | |
524 | } | |
525 | #ifdef DEBUG_I2C | |
526 | GT_REG_READ (I2C_STATUS_BAUDE_RATE, &i2c_status); | |
527 | printf ("address %#x returned %#x\n", chip, i2c_status); | |
528 | #endif | |
529 | /* issue a stop bit */ | |
530 | i2c_stop (); | |
531 | return 0; /* successful completion */ | |
532 | } |