blob: b752903a146045b241b418b5403b60f1954652d5 [file] [log] [blame]
stroesec096c842004-12-16 18:21:17 +00001/*
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 * for cpci750 by reinhard.arlt@esd-electronics.com
26 */
27#include <common.h>
28#include <mpc8xx.h>
29#include <malloc.h>
Peter Tyserdc2da6c2009-04-24 15:34:06 -050030#include <i2c.h>
stroesec096c842004-12-16 18:21:17 +000031#include "../../Marvell/include/mv_gen_reg.h"
32#include "../../Marvell/include/core.h"
33
34#define I2C_DELAY 100
35#undef 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
Peter Tyserdc2da6c2009-04-24 15:34:06 -050045void i2c_init (int speed, int slaveaddr)
stroesec096c842004-12-16 18:21:17 +000046{
47 unsigned int n, m, freq, margin, power;
48 unsigned int actualN = 0, actualM = 0;
49 unsigned int minMargin = 0xffffffff;
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020050 unsigned int tclk = CONFIG_SYS_TCLK;
stroesec096c842004-12-16 18:21:17 +000051 unsigned int i2cFreq = speed; /* 100000 max. Fast mode not supported */
52
53 DP (puts ("i2c_init\n"));
54/* gtI2cMasterInit */
55 for (n = 0; n < 8; n++) {
56 for (m = 0; m < 16; m++) {
57 power = 2 << n; /* power = 2^(n+1) */
58 freq = tclk / (10 * (m + 1) * power);
59 if (i2cFreq > freq)
60 margin = i2cFreq - freq;
61 else
62 margin = freq - i2cFreq;
63 if (margin < minMargin) {
64 minMargin = margin;
65 actualN = n;
66 actualM = m;
67 }
68 }
69 }
70
71 DP (puts ("setup i2c bus\n"));
72
73 /* Setup bus */
74 /* gtI2cReset */
75 GT_REG_WRITE (I2C_SOFT_RESET, 0);
wdenk07d7e6b2004-12-16 21:44:03 +000076 asm(" sync");
stroesec096c842004-12-16 18:21:17 +000077 GT_REG_WRITE (I2C_CONTROL, 0);
wdenk07d7e6b2004-12-16 21:44:03 +000078 asm(" sync");
stroesec096c842004-12-16 18:21:17 +000079
80 DP (puts ("set baudrate\n"));
81
82 GT_REG_WRITE (I2C_STATUS_BAUDE_RATE, (actualM << 3) | actualN);
wdenk07d7e6b2004-12-16 21:44:03 +000083 asm(" sync");
stroesec096c842004-12-16 18:21:17 +000084
85 DP (puts ("udelay...\n"));
86
87 udelay (I2C_DELAY);
88
89 GT_REG_WRITE (I2C_CONTROL, (0x1 << 2) | (0x1 << 6));
wdenk07d7e6b2004-12-16 21:44:03 +000090 asm(" sync");
stroesec096c842004-12-16 18:21:17 +000091}
92
93
94static uchar i2c_select_device (uchar dev_addr, uchar read, int ten_bit)
95{
96 unsigned int status, data, bits = 7;
wdenk07d7e6b2004-12-16 21:44:03 +000097 unsigned int control;
stroesec096c842004-12-16 18:21:17 +000098 int count = 0;
99
100 DP (puts ("i2c_select_device\n"));
101
102 /* Output slave address */
103
104 if (ten_bit) {
105 bits = 10;
106 }
107
108 GT_REG_READ (I2C_CONTROL, &control);
109 control |= (0x1 << 2);
110 GT_REG_WRITE (I2C_CONTROL, control);
wdenk07d7e6b2004-12-16 21:44:03 +0000111 asm(" sync");
stroesec096c842004-12-16 18:21:17 +0000112
113 GT_REG_READ (I2C_CONTROL, &control);
114 control |= (0x1 << 5); /* generate the I2C_START_BIT */
115 GT_REG_WRITE (I2C_CONTROL, control);
wdenk07d7e6b2004-12-16 21:44:03 +0000116 asm(" sync");
stroesec096c842004-12-16 18:21:17 +0000117 RESET_REG_BITS (I2C_CONTROL, (0x01 << 3));
wdenk07d7e6b2004-12-16 21:44:03 +0000118 asm(" sync");
stroesec096c842004-12-16 18:21:17 +0000119
120 GT_REG_READ (I2C_CONTROL, &status);
121 while ((status & 0x08) != 0x08) {
wdenk07d7e6b2004-12-16 21:44:03 +0000122 GT_REG_READ (I2C_CONTROL, &status);
123 }
stroesec096c842004-12-16 18:21:17 +0000124
125
126 count = 0;
127
128 GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status);
129 while (((status & 0xff) != 0x08) && ((status & 0xff) != 0x10)){
130 if (count > 200) {
131#ifdef DEBUG_I2C
wdenk07d7e6b2004-12-16 21:44:03 +0000132 printf ("Failed to set startbit: 0x%02x\n", status);
stroesec096c842004-12-16 18:21:17 +0000133#endif
134 GT_REG_WRITE (I2C_CONTROL, (0x1 << 4)); /*stop */
135 asm(" sync");
136 return (status);
137 }
138 GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status);
139 count++;
140 }
141
142 DP (puts ("i2c_select_device:write addr byte\n"));
143
144 /* assert the address */
145
146 data = (dev_addr << 1);
147 /* set the read bit */
148 data |= read;
149 GT_REG_WRITE (I2C_DATA, data);
wdenk07d7e6b2004-12-16 21:44:03 +0000150 asm(" sync");
stroesec096c842004-12-16 18:21:17 +0000151 RESET_REG_BITS (I2C_CONTROL, BIT3);
wdenk07d7e6b2004-12-16 21:44:03 +0000152 asm(" sync");
stroesec096c842004-12-16 18:21:17 +0000153
154 GT_REG_READ (I2C_CONTROL, &status);
155 while ((status & 0x08) != 0x08) {
wdenk07d7e6b2004-12-16 21:44:03 +0000156 GT_REG_READ (I2C_CONTROL, &status);
157 }
stroesec096c842004-12-16 18:21:17 +0000158
159 GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status);
160 count = 0;
161 while (((status & 0xff) != 0x40) && ((status & 0xff) != 0x18)) {
162 if (count > 200) {
163#ifdef DEBUG_I2C
wdenk07d7e6b2004-12-16 21:44:03 +0000164 printf ("Failed to write address: 0x%02x\n", status);
stroesec096c842004-12-16 18:21:17 +0000165#endif
166 GT_REG_WRITE (I2C_CONTROL, (0x1 << 4)); /*stop */
167 return (status);
168 }
169 GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status);
170 asm(" sync");
171 count++;
172 }
173
174 if (bits == 10) {
175 printf ("10 bit I2C addressing not yet implemented\n");
176 return (0xff);
177 }
178
179 return (0);
180}
181
182static uchar i2c_get_data (uchar * return_data, int len)
183{
184
185 unsigned int data, status;
186 int count = 0;
187
188 DP (puts ("i2c_get_data\n"));
189
190 while (len) {
191
192 RESET_REG_BITS (I2C_CONTROL, BIT3);
193 asm(" sync");
194
195 /* Get and return the data */
196
197 GT_REG_READ (I2C_CONTROL, &status);
198 while ((status & 0x08) != 0x08) {
wdenk07d7e6b2004-12-16 21:44:03 +0000199 GT_REG_READ (I2C_CONTROL, &status);
200 }
stroesec096c842004-12-16 18:21:17 +0000201
202 GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status);
203 count++;
204 while ((status & 0xff) != 0x50) {
205 if (count > 20) {
206#ifdef DEBUG_I2C
wdenk07d7e6b2004-12-16 21:44:03 +0000207 printf ("Failed to get data len status: 0x%02x\n", status);
stroesec096c842004-12-16 18:21:17 +0000208#endif
209 GT_REG_WRITE (I2C_CONTROL, (0x1 << 4)); /*stop */
210 asm(" sync");
211 return 0;
212 }
213 GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status);
214 count++;
215 }
216 GT_REG_READ (I2C_DATA, &data);
217 len--;
218 *return_data = (uchar) data;
219 return_data++;
220
221 }
222 RESET_REG_BITS (I2C_CONTROL, BIT2 | BIT3);
wdenk07d7e6b2004-12-16 21:44:03 +0000223 asm(" sync");
stroesec096c842004-12-16 18:21:17 +0000224 count = 0;
225
226 GT_REG_READ (I2C_CONTROL, &status);
227 while ((status & 0x08) != 0x08) {
wdenk07d7e6b2004-12-16 21:44:03 +0000228 GT_REG_READ (I2C_CONTROL, &status);
229 }
stroesec096c842004-12-16 18:21:17 +0000230
231 while ((status & 0xff) != 0x58) {
232 if (count > 2000) {
233 GT_REG_WRITE (I2C_CONTROL, (0x1 << 4)); /*stop */
234 return (status);
235 }
236 GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status);
237 count++;
238 }
239 GT_REG_WRITE (I2C_CONTROL, (0x1 << 4)); /* stop */
wdenk07d7e6b2004-12-16 21:44:03 +0000240 asm(" sync");
stroesec096c842004-12-16 18:21:17 +0000241 RESET_REG_BITS (I2C_CONTROL, (0x1 << 3));
wdenk07d7e6b2004-12-16 21:44:03 +0000242 asm(" sync");
stroesec096c842004-12-16 18:21:17 +0000243
244 return (0);
245}
246
247
248static uchar i2c_write_data (unsigned int *data, int len)
249{
250 unsigned int status;
251 int count;
252 unsigned int temp;
253 unsigned int *temp_ptr = data;
254
255 DP (puts ("i2c_write_data\n"));
256
257 while (len) {
wdenk07d7e6b2004-12-16 21:44:03 +0000258 count = 0;
stroesec096c842004-12-16 18:21:17 +0000259 temp = (unsigned int) (*temp_ptr);
260 GT_REG_WRITE (I2C_DATA, temp);
261 asm(" sync");
262 RESET_REG_BITS (I2C_CONTROL, (0x1 << 3));
263 asm(" sync");
264
265 GT_REG_READ (I2C_CONTROL, &status);
266 while ((status & 0x08) != 0x08) {
267 GT_REG_READ (I2C_CONTROL, &status);
wdenk07d7e6b2004-12-16 21:44:03 +0000268 }
stroesec096c842004-12-16 18:21:17 +0000269
270 GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status);
271 count++;
272 while ((status & 0xff) != 0x28) {
273 if (count > 200) {
274 GT_REG_WRITE (I2C_CONTROL, (0x1 << 4)); /*stop */
275 asm(" sync");
276 return (status);
277 }
278 GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status);
279 count++;
280 }
281 len--;
282 temp_ptr++;
283 }
284 return (0);
285}
286
287
288static uchar i2c_write_byte (unsigned char *data, int len)
289{
290 unsigned int status;
291 int count;
292 unsigned int temp;
293 unsigned char *temp_ptr = data;
294
295 DP (puts ("i2c_write_byte\n"));
296
297 while (len) {
wdenk07d7e6b2004-12-16 21:44:03 +0000298 count = 0;
stroesec096c842004-12-16 18:21:17 +0000299 /* Set and assert the data */
300 temp = *temp_ptr;
301 GT_REG_WRITE (I2C_DATA, temp);
302 asm(" sync");
303 RESET_REG_BITS (I2C_CONTROL, (0x1 << 3));
304 asm(" sync");
305
306
307 GT_REG_READ (I2C_CONTROL, &status);
308 while ((status & 0x08) != 0x08) {
309 GT_REG_READ (I2C_CONTROL, &status);
wdenk07d7e6b2004-12-16 21:44:03 +0000310 }
stroesec096c842004-12-16 18:21:17 +0000311
312 GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status);
313 count++;
314 while ((status & 0xff) != 0x28) {
315 if (count > 200) {
316 GT_REG_WRITE (I2C_CONTROL, (0x1 << 4)); /*stop */
317 asm(" sync");
318 return (status);
319 }
320 GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status);
321 count++;
322 }
323 len--;
324 temp_ptr++;
325 }
326 return (0);
327}
328
329static uchar
330i2c_set_dev_offset (uchar dev_addr, unsigned int offset, int ten_bit,
331 int alen)
332{
333 uchar status;
334 unsigned int table[2];
335
336 table[1] = (offset ) & 0x0ff; /* low byte */
337 table[0] = (offset >> 8) & 0x0ff; /* high byte */
338
339 DP (puts ("i2c_set_dev_offset\n"));
340
341 status = i2c_select_device (dev_addr, 0, ten_bit);
342 if (status) {
343#ifdef DEBUG_I2C
34422 printf ("Failed to select device setting offset: 0x%02x\n",
345 status);
346#endif
347 return status;
348 }
349/* check the address offset length */
350 if (alen == 0)
351 /* no address offset */
352 return (0);
353 else if (alen == 1) {
354 /* 1 byte address offset */
355 status = i2c_write_data (&offset, 1);
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 if (alen == 2) {
363 /* 2 bytes address offset */
364 status = i2c_write_data (table, 2);
365 if (status) {
366#ifdef DEBUG_I2C
367 printf ("Failed to write data: 0x%02x\n", status);
368#endif
369 return status;
370 }
371 } else {
372 /* address offset unknown or not supported */
373 printf ("Address length offset %d is not supported\n", alen);
374 return 1;
375 }
376 return 0; /* sucessful completion */
377}
378
Peter Tyserdc2da6c2009-04-24 15:34:06 -0500379int
stroesec096c842004-12-16 18:21:17 +0000380i2c_read (uchar dev_addr, unsigned int offset, int alen, uchar * data,
381 int len)
382{
383 uchar status = 0;
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200384 unsigned int i2cFreq = CONFIG_SYS_I2C_SPEED;
stroesec096c842004-12-16 18:21:17 +0000385
386 DP (puts ("i2c_read\n"));
387
Peter Tyserdc2da6c2009-04-24 15:34:06 -0500388 /* set the i2c frequency */
389 i2c_init (i2cFreq, CONFIG_SYS_I2C_SLAVE);
stroesec096c842004-12-16 18:21:17 +0000390
391 status = i2c_set_dev_offset (dev_addr, offset, 0, alen); /* send the slave address + offset */
392 if (status) {
393#ifdef DEBUG_I2C
394 printf ("Failed to set slave address & offset: 0x%02x\n",
395 status);
396#endif
397 return status;
398 }
399
400 status = i2c_select_device (dev_addr, 1, 0);
401 if (status) {
402#ifdef DEBUG_I2C
403 printf ("Failed to select device for data read: 0x%02x\n",
404 status);
405#endif
406 return status;
407 }
408
409 status = i2c_get_data (data, len);
410 if (status) {
411#ifdef DEBUG_I2C
412 printf ("Data not read: 0x%02x\n", status);
413#endif
414 return status;
415 }
416
417 return 0;
418}
419
420
421void i2c_stop (void)
422{
423 GT_REG_WRITE (I2C_CONTROL, (0x1 << 4));
wdenk07d7e6b2004-12-16 21:44:03 +0000424 asm(" sync");
stroesec096c842004-12-16 18:21:17 +0000425}
426
427
Peter Tyserdc2da6c2009-04-24 15:34:06 -0500428int
stroesec096c842004-12-16 18:21:17 +0000429i2c_write (uchar dev_addr, unsigned int offset, int alen, uchar * data,
430 int len)
431{
432 uchar status = 0;
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200433 unsigned int i2cFreq = CONFIG_SYS_I2C_SPEED;
stroesec096c842004-12-16 18:21:17 +0000434
435 DP (puts ("i2c_write\n"));
436
Peter Tyserdc2da6c2009-04-24 15:34:06 -0500437 /* set the i2c frequency */
438 i2c_init (i2cFreq, CONFIG_SYS_I2C_SLAVE);
stroesec096c842004-12-16 18:21:17 +0000439
440 status = i2c_set_dev_offset (dev_addr, offset, 0, alen); /* send the slave address + offset */
441 if (status) {
442#ifdef DEBUG_I2C
443 printf ("Failed to set slave address & offset: 0x%02x\n",
444 status);
445#endif
446 return status;
wdenk07d7e6b2004-12-16 21:44:03 +0000447 }
stroesec096c842004-12-16 18:21:17 +0000448
449
450 status = i2c_write_byte (data, len); /* write the data */
451 if (status) {
452#ifdef DEBUG_I2C
453 printf ("Data not written: 0x%02x\n", status);
454#endif
455 return status;
wdenk07d7e6b2004-12-16 21:44:03 +0000456 }
stroesec096c842004-12-16 18:21:17 +0000457 /* issue a stop bit */
458 i2c_stop ();
459 return 0;
460}
461
462
463int i2c_probe (uchar chip)
464{
465
466#ifdef DEBUG_I2C
467 unsigned int i2c_status;
468#endif
469 uchar status = 0;
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200470 unsigned int i2cFreq = CONFIG_SYS_I2C_SPEED;
stroesec096c842004-12-16 18:21:17 +0000471
472 DP (puts ("i2c_probe\n"));
473
Peter Tyserdc2da6c2009-04-24 15:34:06 -0500474 /* set the i2c frequency */
475 i2c_init (i2cFreq, CONFIG_SYS_I2C_SLAVE);
stroesec096c842004-12-16 18:21:17 +0000476
477 status = i2c_set_dev_offset (chip, 0, 0, 0); /* send the slave address + no offset */
478 if (status) {
479#ifdef DEBUG_I2C
480 printf ("Failed to set slave address: 0x%02x\n", status);
481#endif
482 return (int) status;
483 }
484#ifdef DEBUG_I2C
485 GT_REG_READ (I2C_STATUS_BAUDE_RATE, &i2c_status);
486 printf ("address %#x returned %#x\n", chip, i2c_status);
487#endif
488 /* issue a stop bit */
489 i2c_stop ();
490 return 0; /* successful completion */
491}