]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/esd/cpci750/i2c.c
imported Freescale specific U-Boot additions for i.MX28,... release L2.6.31_10.08.01
[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  * 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>
30 #include <i2c.h>
31 #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
45 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 minMargin = 0xffffffff;
50         unsigned int tclk = CONFIG_SYS_TCLK;
51         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);
76         asm(" sync");
77         GT_REG_WRITE (I2C_CONTROL, 0);
78         asm(" sync");
79
80         DP (puts ("set baudrate\n"));
81
82         GT_REG_WRITE (I2C_STATUS_BAUDE_RATE, (actualM << 3) | actualN);
83         asm(" sync");
84
85         DP (puts ("udelay...\n"));
86
87         udelay (I2C_DELAY);
88
89         GT_REG_WRITE (I2C_CONTROL, (0x1 << 2) | (0x1 << 6));
90         asm(" sync");
91 }
92
93
94 static uchar i2c_select_device (uchar dev_addr, uchar read, int ten_bit)
95 {
96         unsigned int status, data, bits = 7;
97         unsigned int control;
98         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);
111         asm(" sync");
112
113         GT_REG_READ (I2C_CONTROL, &control);
114         control |= (0x1 << 5);  /* generate the I2C_START_BIT */
115         GT_REG_WRITE (I2C_CONTROL, control);
116         asm(" sync");
117         RESET_REG_BITS (I2C_CONTROL, (0x01 << 3));
118         asm(" sync");
119
120         GT_REG_READ (I2C_CONTROL, &status);
121         while ((status & 0x08) != 0x08) {
122                 GT_REG_READ (I2C_CONTROL, &status);
123                 }
124
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
132                         printf ("Failed to set startbit: 0x%02x\n", status);
133 #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);
150         asm(" sync");
151         RESET_REG_BITS (I2C_CONTROL, BIT3);
152         asm(" sync");
153
154         GT_REG_READ (I2C_CONTROL, &status);
155         while ((status & 0x08) != 0x08) {
156                 GT_REG_READ (I2C_CONTROL, &status);
157                 }
158
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
164                         printf ("Failed to write address: 0x%02x\n", status);
165 #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
182 static 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) {
199                         GT_REG_READ (I2C_CONTROL, &status);
200                         }
201
202                 GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status);
203                 count++;
204                 while ((status & 0xff) != 0x50) {
205                         if (count > 20) {
206 #ifdef DEBUG_I2C
207                                 printf ("Failed to get data len status: 0x%02x\n", status);
208 #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);
223         asm(" sync");
224         count = 0;
225
226         GT_REG_READ (I2C_CONTROL, &status);
227         while ((status & 0x08) != 0x08) {
228                 GT_REG_READ (I2C_CONTROL, &status);
229                 }
230
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 */
240         asm(" sync");
241         RESET_REG_BITS (I2C_CONTROL, (0x1 << 3));
242         asm(" sync");
243
244         return (0);
245 }
246
247
248 static 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) {
258                 count = 0;
259                 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);
268                         }
269
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
288 static 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) {
298                 count = 0;
299                 /* 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);
310                         }
311
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
329 static uchar
330 i2c_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
344 22              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
379 int
380 i2c_read (uchar dev_addr, unsigned int offset, int alen, uchar * data,
381           int len)
382 {
383         uchar status = 0;
384         unsigned int i2cFreq = CONFIG_SYS_I2C_SPEED;
385
386         DP (puts ("i2c_read\n"));
387
388         /* set the i2c frequency */
389         i2c_init (i2cFreq, CONFIG_SYS_I2C_SLAVE);
390
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
421 void i2c_stop (void)
422 {
423         GT_REG_WRITE (I2C_CONTROL, (0x1 << 4));
424         asm(" sync");
425 }
426
427
428 int
429 i2c_write (uchar dev_addr, unsigned int offset, int alen, uchar * data,
430            int len)
431 {
432         uchar status = 0;
433         unsigned int i2cFreq = CONFIG_SYS_I2C_SPEED;
434
435         DP (puts ("i2c_write\n"));
436
437         /* set the i2c frequency */
438         i2c_init (i2cFreq, CONFIG_SYS_I2C_SLAVE);
439
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;
447                 }
448
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;
456                 }
457         /* issue a stop bit */
458         i2c_stop ();
459         return 0;
460 }
461
462
463 int i2c_probe (uchar chip)
464 {
465
466 #ifdef DEBUG_I2C
467         unsigned int i2c_status;
468 #endif
469         uchar status = 0;
470         unsigned int i2cFreq = CONFIG_SYS_I2C_SPEED;
471
472         DP (puts ("i2c_probe\n"));
473
474         /* set the i2c frequency */
475         i2c_init (i2cFreq, CONFIG_SYS_I2C_SLAVE);
476
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 }