]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/esd/cpci750/i2c.c
bad0dac05d479f000aff9484a7f5ee61c26a5136
[karo-tx-uboot.git] / board / esd / cpci750 / i2c.c
1 /*
2  * (C) Copyright 2000
3  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4  *
5  * SPDX-License-Identifier:     GPL-2.0+
6  *
7  * Hacked for the DB64360 board by Ingo.Assmus@keymile.com
8  * extra improvments by Brain Waite
9  * for cpci750 by reinhard.arlt@esd-electronics.com
10  */
11 #include <common.h>
12 #include <mpc8xx.h>
13 #include <malloc.h>
14 #include <i2c.h>
15 #include "../../Marvell/include/mv_gen_reg.h"
16 #include "../../Marvell/include/core.h"
17
18 #define I2C_DELAY           100
19 #undef  DEBUG_I2C
20
21 #ifdef DEBUG_I2C
22 #define DP(x) x
23 #else
24 #define DP(x)
25 #endif
26
27 /* Assuming that there is only one master on the bus (us) */
28
29 void i2c_init (int speed, int slaveaddr)
30 {
31         unsigned int n, m, freq, margin, power;
32         unsigned int actualN = 0, actualM = 0;
33         unsigned int minMargin = 0xffffffff;
34         unsigned int tclk = CONFIG_SYS_TCLK;
35         unsigned int i2cFreq = speed;   /* 100000 max. Fast mode not supported */
36
37         DP (puts ("i2c_init\n"));
38 /* gtI2cMasterInit */
39         for (n = 0; n < 8; n++) {
40                 for (m = 0; m < 16; m++) {
41                         power = 2 << n; /* power = 2^(n+1) */
42                         freq = tclk / (10 * (m + 1) * power);
43                         if (i2cFreq > freq)
44                                 margin = i2cFreq - freq;
45                         else
46                                 margin = freq - i2cFreq;
47                         if (margin < minMargin) {
48                                 minMargin = margin;
49                                 actualN = n;
50                                 actualM = m;
51                         }
52                 }
53         }
54
55         DP (puts ("setup i2c bus\n"));
56
57         /* Setup bus */
58         /* gtI2cReset */
59         GT_REG_WRITE (I2C_SOFT_RESET, 0);
60         asm(" sync");
61         GT_REG_WRITE (I2C_CONTROL, 0);
62         asm(" sync");
63
64         DP (puts ("set baudrate\n"));
65
66         GT_REG_WRITE (I2C_STATUS_BAUDE_RATE, (actualM << 3) | actualN);
67         asm(" sync");
68
69         DP (puts ("udelay...\n"));
70
71         udelay (I2C_DELAY);
72
73         GT_REG_WRITE (I2C_CONTROL, (0x1 << 2) | (0x1 << 6));
74         asm(" sync");
75 }
76
77
78 static uchar i2c_select_device (uchar dev_addr, uchar read, int ten_bit)
79 {
80         unsigned int status, data, bits = 7;
81         unsigned int control;
82         int count = 0;
83
84         DP (puts ("i2c_select_device\n"));
85
86         /* Output slave address */
87
88         if (ten_bit) {
89                 bits = 10;
90         }
91
92         GT_REG_READ (I2C_CONTROL, &control);
93         control |=  (0x1 << 2);
94         GT_REG_WRITE (I2C_CONTROL, control);
95         asm(" sync");
96
97         GT_REG_READ (I2C_CONTROL, &control);
98         control |= (0x1 << 5);  /* generate the I2C_START_BIT */
99         GT_REG_WRITE (I2C_CONTROL, control);
100         asm(" sync");
101         RESET_REG_BITS (I2C_CONTROL, (0x01 << 3));
102         asm(" sync");
103
104         GT_REG_READ (I2C_CONTROL, &status);
105         while ((status & 0x08) != 0x08) {
106                 GT_REG_READ (I2C_CONTROL, &status);
107                 }
108
109
110         count = 0;
111
112         GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status);
113         while (((status & 0xff) != 0x08) && ((status & 0xff) != 0x10)){
114                 if (count > 200) {
115 #ifdef DEBUG_I2C
116                         printf ("Failed to set startbit: 0x%02x\n", status);
117 #endif
118                         GT_REG_WRITE (I2C_CONTROL, (0x1 << 4)); /*stop */
119                         asm(" sync");
120                         return (status);
121                 }
122                 GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status);
123                 count++;
124         }
125
126         DP (puts ("i2c_select_device:write addr byte\n"));
127
128         /* assert the address */
129
130         data = (dev_addr << 1);
131         /* set the read bit */
132         data |= read;
133         GT_REG_WRITE (I2C_DATA, data);
134         asm(" sync");
135         RESET_REG_BITS (I2C_CONTROL, BIT3);
136         asm(" sync");
137
138         GT_REG_READ (I2C_CONTROL, &status);
139         while ((status & 0x08) != 0x08) {
140                 GT_REG_READ (I2C_CONTROL, &status);
141                 }
142
143         GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status);
144         count = 0;
145         while (((status & 0xff) != 0x40) && ((status & 0xff) != 0x18)) {
146                 if (count > 200) {
147 #ifdef DEBUG_I2C
148                         printf ("Failed to write address: 0x%02x\n", status);
149 #endif
150                         GT_REG_WRITE (I2C_CONTROL, (0x1 << 4)); /*stop */
151                         return (status);
152                 }
153                 GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status);
154                 asm(" sync");
155                 count++;
156         }
157
158         if (bits == 10) {
159                 printf ("10 bit I2C addressing not yet implemented\n");
160                 return (0xff);
161         }
162
163         return (0);
164 }
165
166 static uchar i2c_get_data (uchar * return_data, int len)
167 {
168
169         unsigned int data, status;
170         int count = 0;
171
172         DP (puts ("i2c_get_data\n"));
173
174         while (len) {
175
176                 RESET_REG_BITS (I2C_CONTROL, BIT3);
177                 asm(" sync");
178
179                 /* Get and return the data */
180
181                 GT_REG_READ (I2C_CONTROL, &status);
182                 while ((status & 0x08) != 0x08) {
183                         GT_REG_READ (I2C_CONTROL, &status);
184                         }
185
186                 GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status);
187                 count++;
188                 while ((status & 0xff) != 0x50) {
189                         if (count > 20) {
190 #ifdef DEBUG_I2C
191                                 printf ("Failed to get data len status: 0x%02x\n", status);
192 #endif
193                                 GT_REG_WRITE (I2C_CONTROL, (0x1 << 4)); /*stop */
194                                 asm(" sync");
195                                 return 0;
196                         }
197                         GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status);
198                         count++;
199                 }
200                 GT_REG_READ (I2C_DATA, &data);
201                 len--;
202                 *return_data = (uchar) data;
203                 return_data++;
204
205         }
206         RESET_REG_BITS (I2C_CONTROL, BIT2 | BIT3);
207         asm(" sync");
208         count = 0;
209
210         GT_REG_READ (I2C_CONTROL, &status);
211         while ((status & 0x08) != 0x08) {
212                 GT_REG_READ (I2C_CONTROL, &status);
213                 }
214
215         while ((status & 0xff) != 0x58) {
216                 if (count > 2000) {
217                         GT_REG_WRITE (I2C_CONTROL, (0x1 << 4)); /*stop */
218                         return (status);
219                 }
220                 GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status);
221                 count++;
222         }
223         GT_REG_WRITE (I2C_CONTROL, (0x1 << 4)); /* stop */
224         asm(" sync");
225         RESET_REG_BITS (I2C_CONTROL, (0x1 << 3));
226         asm(" sync");
227
228         return (0);
229 }
230
231
232 static uchar i2c_write_data (unsigned int *data, int len)
233 {
234         unsigned int status;
235         int count;
236         unsigned int temp;
237         unsigned int *temp_ptr = data;
238
239         DP (puts ("i2c_write_data\n"));
240
241         while (len) {
242                 count = 0;
243                 temp = (unsigned int) (*temp_ptr);
244                 GT_REG_WRITE (I2C_DATA, temp);
245                 asm(" sync");
246                 RESET_REG_BITS (I2C_CONTROL, (0x1 << 3));
247                 asm(" sync");
248
249                 GT_REG_READ (I2C_CONTROL, &status);
250                 while ((status & 0x08) != 0x08) {
251                         GT_REG_READ (I2C_CONTROL, &status);
252                         }
253
254                 GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status);
255                 count++;
256                 while ((status & 0xff) != 0x28) {
257                         if (count > 200) {
258                                 GT_REG_WRITE (I2C_CONTROL, (0x1 << 4)); /*stop */
259                                 asm(" sync");
260                                 return (status);
261                         }
262                         GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status);
263                         count++;
264                 }
265                 len--;
266                 temp_ptr++;
267         }
268         return (0);
269 }
270
271
272 static uchar i2c_write_byte (unsigned char *data, int len)
273 {
274         unsigned int status;
275         int count;
276         unsigned int temp;
277         unsigned char *temp_ptr = data;
278
279         DP (puts ("i2c_write_byte\n"));
280
281         while (len) {
282                 count = 0;
283                 /* Set and assert the data */
284                 temp = *temp_ptr;
285                 GT_REG_WRITE (I2C_DATA, temp);
286                 asm(" sync");
287                 RESET_REG_BITS (I2C_CONTROL, (0x1 << 3));
288                 asm(" sync");
289
290
291                 GT_REG_READ (I2C_CONTROL, &status);
292                 while ((status & 0x08) != 0x08) {
293                         GT_REG_READ (I2C_CONTROL, &status);
294                         }
295
296                 GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status);
297                 count++;
298                 while ((status & 0xff) != 0x28) {
299                         if (count > 200) {
300                                 GT_REG_WRITE (I2C_CONTROL, (0x1 << 4)); /*stop */
301                                 asm(" sync");
302                                 return (status);
303                         }
304                         GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status);
305                         count++;
306                 }
307                 len--;
308                 temp_ptr++;
309         }
310         return (0);
311 }
312
313 static uchar
314 i2c_set_dev_offset (uchar dev_addr, unsigned int offset, int ten_bit,
315                     int alen)
316 {
317         uchar status;
318         unsigned int table[2];
319
320         table[1] = (offset     ) & 0x0ff;       /* low byte */
321         table[0] = (offset >> 8) & 0x0ff;       /* high byte */
322
323         DP (puts ("i2c_set_dev_offset\n"));
324
325         status = i2c_select_device (dev_addr, 0, ten_bit);
326         if (status) {
327 #ifdef DEBUG_I2C
328 22              printf ("Failed to select device setting offset: 0x%02x\n",
329                         status);
330 #endif
331                 return status;
332         }
333 /* check the address offset length */
334         if (alen == 0)
335                 /* no address offset */
336                 return (0);
337         else if (alen == 1) {
338                 /* 1 byte address offset */
339                 status = i2c_write_data (&offset, 1);
340                 if (status) {
341 #ifdef DEBUG_I2C
342                         printf ("Failed to write data: 0x%02x\n", status);
343 #endif
344                         return status;
345                 }
346         } else if (alen == 2) {
347                 /* 2 bytes address offset */
348                 status = i2c_write_data (table, 2);
349                 if (status) {
350 #ifdef DEBUG_I2C
351                         printf ("Failed to write data: 0x%02x\n", status);
352 #endif
353                         return status;
354                 }
355         } else {
356                 /* address offset unknown or not supported */
357                 printf ("Address length offset %d is not supported\n", alen);
358                 return 1;
359         }
360         return 0;               /* sucessful completion */
361 }
362
363 int
364 i2c_read (uchar dev_addr, unsigned int offset, int alen, uchar * data,
365           int len)
366 {
367         uchar status = 0;
368         unsigned int i2cFreq = CONFIG_SYS_I2C_SPEED;
369
370         DP (puts ("i2c_read\n"));
371
372         /* set the i2c frequency */
373         i2c_init (i2cFreq, CONFIG_SYS_I2C_SLAVE);
374
375         status = i2c_set_dev_offset (dev_addr, offset, 0, alen);        /* send the slave address + offset */
376         if (status) {
377 #ifdef DEBUG_I2C
378                 printf ("Failed to set slave address & offset: 0x%02x\n",
379                         status);
380 #endif
381                 return status;
382         }
383
384         status = i2c_select_device (dev_addr, 1, 0);
385         if (status) {
386 #ifdef DEBUG_I2C
387                 printf ("Failed to select device for data read: 0x%02x\n",
388                         status);
389 #endif
390                 return status;
391         }
392
393         status = i2c_get_data (data, len);
394         if (status) {
395 #ifdef DEBUG_I2C
396                 printf ("Data not read: 0x%02x\n", status);
397 #endif
398                 return status;
399         }
400
401         return 0;
402 }
403
404
405 void i2c_stop (void)
406 {
407         GT_REG_WRITE (I2C_CONTROL, (0x1 << 4));
408         asm(" sync");
409 }
410
411
412 int
413 i2c_write (uchar dev_addr, unsigned int offset, int alen, uchar * data,
414            int len)
415 {
416         uchar status = 0;
417         unsigned int i2cFreq = CONFIG_SYS_I2C_SPEED;
418
419         DP (puts ("i2c_write\n"));
420
421         /* set the i2c frequency */
422         i2c_init (i2cFreq, CONFIG_SYS_I2C_SLAVE);
423
424         status = i2c_set_dev_offset (dev_addr, offset, 0, alen);        /* send the slave address + offset */
425         if (status) {
426 #ifdef DEBUG_I2C
427                 printf ("Failed to set slave address & offset: 0x%02x\n",
428                         status);
429 #endif
430                 return status;
431                 }
432
433
434         status = i2c_write_byte (data, len);    /* write the data */
435         if (status) {
436 #ifdef DEBUG_I2C
437                 printf ("Data not written: 0x%02x\n", status);
438 #endif
439                 return status;
440                 }
441         /* issue a stop bit */
442         i2c_stop ();
443         return 0;
444 }
445
446
447 int i2c_probe (uchar chip)
448 {
449
450 #ifdef DEBUG_I2C
451         unsigned int i2c_status;
452 #endif
453         uchar status = 0;
454         unsigned int i2cFreq = CONFIG_SYS_I2C_SPEED;
455
456         DP (puts ("i2c_probe\n"));
457
458         /* set the i2c frequency */
459         i2c_init (i2cFreq, CONFIG_SYS_I2C_SLAVE);
460
461         status = i2c_set_dev_offset (chip, 0, 0, 0);    /* send the slave address + no offset */
462         if (status) {
463 #ifdef DEBUG_I2C
464                 printf ("Failed to set slave address: 0x%02x\n", status);
465 #endif
466                 return (int) status;
467         }
468 #ifdef DEBUG_I2C
469         GT_REG_READ (I2C_STATUS_BAUDE_RATE, &i2c_status);
470         printf ("address %#x returned %#x\n", chip, i2c_status);
471 #endif
472         /* issue a stop bit */
473         i2c_stop ();
474         return 0;               /* successful completion */
475 }