source: SVN/rincon/u-boot/board/Marvell/common/i2c.c @ 55

Last change on this file since 55 was 55, checked in by Tim Harvey, 22 months ago

rincon: added latest u-boot source

restored form server backup

Signed-off-by: Tim Harvey <tharvey@…>

File size: 12.5 KB
Line 
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
45static 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
95static 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
126static 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
168static uchar i2c_get_data (uchar * return_data, int len)
169{
170
171        unsigned int data, status = 0;
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
215static 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 */
271static 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
317static uchar
318i2c_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
370uchar
371i2c_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 */
430void 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 */
445uchar
446i2c_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 */
493int 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}
Note: See TracBrowser for help on using the repository browser.