]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - cpu/mpc8260/i2c.c
Initial revision
[karo-tx-uboot.git] / cpu / mpc8260 / i2c.c
1 /*
2  * (C) Copyright 2000
3  * Paolo Scaffardi, AIRVENT SAM s.p.a - RIMINI(ITALY), arsenio@tin.it
4  *
5  * (C) Copyright 2000 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
6  * Marius Groeger <mgroeger@sysgo.de>
7  *
8  * See file CREDITS for list of people who contributed to this
9  * project.
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License as
13  * published by the Free Software Foundation; either version 2 of
14  * the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
24  * MA 02111-1307 USA
25  */
26
27 #include <common.h>
28
29 #if defined(CONFIG_HARD_I2C)
30
31 #include <asm/cpm_8260.h>
32 #include <i2c.h>
33
34 /* define to enable debug messages */
35 #undef  DEBUG_I2C
36
37 /* uSec to wait between polls of the i2c */
38 #define DELAY_US        100
39 /* uSec to wait for the CPM to start processing the buffer */
40 #define START_DELAY_US  1000
41
42 /*
43  * tx/rx per-byte timeout: we delay DELAY_US uSec between polls so the
44  * timeout will be (tx_length + rx_length) * DELAY_US * TOUT_LOOP
45  */
46 #define TOUT_LOOP 5
47
48 /*-----------------------------------------------------------------------
49  * Set default values
50  */
51 #ifndef CFG_I2C_SPEED
52 #define CFG_I2C_SPEED   50000
53 #endif
54
55 #ifndef CFG_I2C_SLAVE
56 #define CFG_I2C_SLAVE   0xFE
57 #endif
58 /*-----------------------------------------------------------------------
59  */
60
61 typedef void (*i2c_ecb_t)(int, int);    /* error callback function */
62
63 /* This structure keeps track of the bd and buffer space usage. */
64 typedef struct i2c_state {
65         int             rx_idx;         /* index   to next free Rx BD */
66         int             tx_idx;         /* index   to next free Tx BD */
67         void            *rxbd;          /* pointer to next free Rx BD */
68         void            *txbd;          /* pointer to next free Tx BD */
69         int             tx_space;       /* number  of Tx bytes left   */
70         unsigned char   *tx_buf;        /* pointer to free Tx area    */
71         i2c_ecb_t       err_cb;         /* error callback function    */
72 } i2c_state_t;
73
74 /* flags for i2c_send() and i2c_receive() */
75 #define I2CF_ENABLE_SECONDARY   0x01    /* secondary_address is valid   */
76 #define I2CF_START_COND         0x02    /* tx: generate start condition */
77 #define I2CF_STOP_COND          0x04    /* tx: generate stop  condition */
78
79 /* return codes */
80 #define I2CERR_NO_BUFFERS       0x01    /* no more BDs or buffer space  */
81 #define I2CERR_MSG_TOO_LONG     0x02    /* tried to send/receive to much data   */
82 #define I2CERR_TIMEOUT          0x03    /* timeout in i2c_doio()        */
83 #define I2CERR_QUEUE_EMPTY      0x04    /* i2c_doio called without send/receive */
84
85 /* error callback flags */
86 #define I2CECB_RX_ERR           0x10    /* this is a receive error      */
87 #define     I2CECB_RX_ERR_OV    0x02    /* receive overrun error        */
88 #define     I2CECB_RX_MASK      0x0f    /* mask for error bits          */
89 #define I2CECB_TX_ERR           0x20    /* this is a transmit error     */
90 #define     I2CECB_TX_CL        0x01    /* transmit collision error     */
91 #define     I2CECB_TX_UN        0x02    /* transmit underflow error     */
92 #define     I2CECB_TX_NAK       0x04    /* transmit no ack error        */
93 #define     I2CECB_TX_MASK      0x0f    /* mask for error bits          */
94 #define I2CECB_TIMEOUT          0x40    /* this is a timeout error      */
95
96 #define ERROR_I2C_NONE          0
97 #define ERROR_I2C_LENGTH        1
98
99 #define I2C_WRITE_BIT           0x00
100 #define I2C_READ_BIT            0x01
101
102 #define I2C_RXTX_LEN    128     /* maximum tx/rx buffer length */
103
104
105 #define NUM_RX_BDS 4
106 #define NUM_TX_BDS 4
107 #define MAX_TX_SPACE 256
108
109 typedef struct I2C_BD
110 {
111   unsigned short status;
112   unsigned short length;
113   unsigned char *addr;
114 } I2C_BD;
115 #define BD_I2C_TX_START 0x0400  /* special status for i2c: Start condition */
116
117 #define BD_I2C_TX_CL    0x0001  /* collision error */
118 #define BD_I2C_TX_UN    0x0002  /* underflow error */
119 #define BD_I2C_TX_NAK   0x0004  /* no acknowledge error */
120 #define BD_I2C_TX_ERR   (BD_I2C_TX_NAK|BD_I2C_TX_UN|BD_I2C_TX_CL)
121
122 #define BD_I2C_RX_ERR   BD_SC_OV
123
124 #ifdef DEBUG_I2C
125 #define PRINTD(x) printf x
126 #else
127 #define PRINTD(x)
128 #endif
129
130 /*
131  * Returns the best value of I2BRG to meet desired clock speed of I2C with
132  * input parameters (clock speed, filter, and predivider value).
133  * It returns computer speed value and the difference between it and desired
134  * speed.
135  */
136 static inline int
137 i2c_roundrate(int hz, int speed, int filter, int modval,
138                 int *brgval, int *totspeed)
139 {
140     int moddiv = 1 << (5-(modval & 3)), brgdiv, div;
141
142     PRINTD(("\t[I2C] trying hz=%d, speed=%d, filter=%d, modval=%d\n",
143         hz, speed, filter, modval));
144
145     div = moddiv * speed;
146     brgdiv = (hz + div - 1) / div;
147
148     PRINTD(("\t\tmoddiv=%d, brgdiv=%d\n", moddiv, brgdiv));
149
150     *brgval = (brgdiv / 2) - 3 - (2*filter);
151
152     if ((*brgval < 0) || (*brgval > 255)) {
153           PRINTD(("\t\trejected brgval=%d\n", *brgval));
154           return -1;
155     }
156
157     brgdiv = 2 * (*brgval + 3 + (2 * filter));
158     div = moddiv * brgdiv ;
159     *totspeed = (hz + div - 1) / div;
160
161     PRINTD(("\t\taccepted brgval=%d, totspeed=%d\n", *brgval, *totspeed));
162
163     return  0;
164 }
165
166 /*
167  * Sets the I2C clock predivider and divider to meet required clock speed.
168  */
169 static int i2c_setrate(int hz, int speed)
170 {
171     immap_t     *immap = (immap_t *)CFG_IMMR ;
172     volatile i2c8260_t *i2c = (i2c8260_t *)&immap->im_i2c;
173     int brgval,
174           modval,       /* 0-3 */
175           bestspeed_diff = speed,
176           bestspeed_brgval=0,
177           bestspeed_modval=0,
178           bestspeed_filter=0,
179           totspeed,
180           filter = 0; /* Use this fixed value */
181
182         for (modval = 0; modval < 4; modval++)
183         {
184                 if (i2c_roundrate (hz, speed, filter, modval, &brgval, &totspeed) == 0)
185                 {
186                         int diff = speed - totspeed ;
187
188                         if ((diff >= 0) && (diff < bestspeed_diff))
189                         {
190                                 bestspeed_diff  = diff ;
191                                 bestspeed_modval        = modval;
192                                 bestspeed_brgval        = brgval;
193                                 bestspeed_filter        = filter;
194                         }
195                 }
196         }
197
198     PRINTD(("[I2C] Best is:\n"));
199     PRINTD(("[I2C] CPU=%dhz RATE=%d F=%d I2MOD=%08x I2BRG=%08x DIFF=%dhz\n",
200                    hz, speed,
201                    bestspeed_filter, bestspeed_modval, bestspeed_brgval,
202                    bestspeed_diff));
203
204     i2c->i2c_i2mod |= ((bestspeed_modval & 3) << 1) | (bestspeed_filter << 3);
205     i2c->i2c_i2brg = bestspeed_brgval & 0xff;
206
207     PRINTD(("[I2C] i2mod=%08x i2brg=%08x\n", i2c->i2c_i2mod, i2c->i2c_i2brg));
208
209     return 1 ;
210 }
211
212 void i2c_init(int speed, int slaveadd)
213 {
214         DECLARE_GLOBAL_DATA_PTR;
215
216         volatile immap_t *immap = (immap_t *)CFG_IMMR ;
217         volatile cpm8260_t *cp = (cpm8260_t *)&immap->im_cpm;
218         volatile i2c8260_t *i2c = (i2c8260_t *)&immap->im_i2c;
219         volatile iic_t *iip;
220         ulong rbase, tbase;
221         volatile I2C_BD *rxbd, *txbd;
222         uint dpaddr;
223
224         dpaddr = *((unsigned short*)(&immap->im_dprambase[PROFF_I2C_BASE]));
225         if (dpaddr == 0) {
226             /* need to allocate dual port ram */
227             dpaddr = m8260_cpm_dpalloc(64 +
228                 (NUM_RX_BDS * sizeof(I2C_BD)) + (NUM_TX_BDS * sizeof(I2C_BD)) +
229                 MAX_TX_SPACE, 64);
230             *((unsigned short*)(&immap->im_dprambase[PROFF_I2C_BASE])) = dpaddr;
231         }
232
233         /*
234          * initialise data in dual port ram:
235          *
236          *        dpaddr -> parameter ram (64 bytes)
237          *         rbase -> rx BD         (NUM_RX_BDS * sizeof(I2C_BD) bytes)
238          *         tbase -> tx BD         (NUM_TX_BDS * sizeof(I2C_BD) bytes)
239          *                  tx buffer     (MAX_TX_SPACE bytes)
240          */
241
242         iip = (iic_t *)&immap->im_dprambase[dpaddr];
243         memset((void*)iip, 0, sizeof(iic_t));
244
245         rbase = dpaddr + 64;
246         tbase = rbase + NUM_RX_BDS * sizeof(I2C_BD);
247
248         /* Disable interrupts */
249         i2c->i2c_i2mod = 0x00;
250         i2c->i2c_i2cmr = 0x00;
251         i2c->i2c_i2cer = 0xff;
252         i2c->i2c_i2add = slaveadd;
253
254         /*
255          * Set the I2C BRG Clock division factor from desired i2c rate
256          * and current CPU rate (we assume sccr dfbgr field is 0;
257          * divide BRGCLK by 1)
258          */
259         PRINTD(("[I2C] Setting rate...\n"));
260         i2c_setrate (gd->brg_clk, CFG_I2C_SPEED) ;
261
262         /* Set I2C controller in master mode */
263         i2c->i2c_i2com = 0x01;
264
265         /* Initialize Tx/Rx parameters */
266         iip->iic_rbase = rbase;
267         iip->iic_tbase = tbase;
268         rxbd = (I2C_BD *)((unsigned char *)&immap->im_dprambase[iip->iic_rbase]);
269         txbd = (I2C_BD *)((unsigned char *)&immap->im_dprambase[iip->iic_tbase]);
270
271         PRINTD(("[I2C] rbase = %04x\n", iip->iic_rbase));
272         PRINTD(("[I2C] tbase = %04x\n", iip->iic_tbase));
273         PRINTD(("[I2C] rxbd = %08x\n", (int)rxbd));
274         PRINTD(("[I2C] txbd = %08x\n", (int)txbd));
275
276         /* Set big endian byte order */
277         iip->iic_tfcr = 0x10;
278         iip->iic_rfcr = 0x10;
279
280         /* Set maximum receive size. */
281         iip->iic_mrblr = I2C_RXTX_LEN;
282
283     cp->cp_cpcr = mk_cr_cmd(CPM_CR_I2C_PAGE,
284                                                         CPM_CR_I2C_SBLOCK,
285                                                         0x00,
286                                                         CPM_CR_INIT_TRX) | CPM_CR_FLG;
287     do {
288                 __asm__ __volatile__ ("eieio");
289     } while (cp->cp_cpcr & CPM_CR_FLG);
290
291         /* Clear events and interrupts */
292         i2c->i2c_i2cer = 0xff;
293         i2c->i2c_i2cmr = 0x00;
294 }
295
296 static
297 void i2c_newio(i2c_state_t *state)
298 {
299         volatile immap_t *immap = (immap_t *)CFG_IMMR ;
300         volatile iic_t *iip;
301         uint dpaddr;
302
303         PRINTD(("[I2C] i2c_newio\n"));
304
305         dpaddr = *((unsigned short*)(&immap->im_dprambase[PROFF_I2C_BASE]));
306         iip = (iic_t *)&immap->im_dprambase[dpaddr];
307         state->rx_idx = 0;
308         state->tx_idx = 0;
309         state->rxbd = (void*)&immap->im_dprambase[iip->iic_rbase];
310         state->txbd = (void*)&immap->im_dprambase[iip->iic_tbase];
311         state->tx_space = MAX_TX_SPACE;
312         state->tx_buf = (uchar*)state->txbd + NUM_TX_BDS * sizeof(I2C_BD);
313         state->err_cb = NULL;
314
315         PRINTD(("[I2C] rxbd = %08x\n", (int)state->rxbd));
316         PRINTD(("[I2C] txbd = %08x\n", (int)state->txbd));
317         PRINTD(("[I2C] tx_buf = %08x\n", (int)state->tx_buf));
318
319         /* clear the buffer memory */
320         memset((char *)state->tx_buf, 0, MAX_TX_SPACE);
321 }
322
323 static
324 int i2c_send(i2c_state_t *state,
325                          unsigned char address,
326                          unsigned char secondary_address,
327                          unsigned int flags,
328                          unsigned short size,
329                          unsigned char *dataout)
330 {
331         volatile I2C_BD *txbd;
332         int i,j;
333
334         PRINTD(("[I2C] i2c_send add=%02d sec=%02d flag=%02d size=%d\n",
335                         address, secondary_address, flags, size));
336
337         /* trying to send message larger than BD */
338         if (size > I2C_RXTX_LEN)
339           return I2CERR_MSG_TOO_LONG;
340
341         /* no more free bds */
342         if (state->tx_idx >= NUM_TX_BDS || state->tx_space < (2 + size))
343           return I2CERR_NO_BUFFERS;
344
345         txbd = (I2C_BD *)state->txbd;
346         txbd->addr = state->tx_buf;
347
348         PRINTD(("[I2C] txbd = %08x\n", (int)txbd));
349
350     if (flags & I2CF_START_COND)
351     {
352         PRINTD(("[I2C] Formatting addresses...\n"));
353         if (flags & I2CF_ENABLE_SECONDARY)
354         {
355                 txbd->length = size + 2;  /* Length of message plus dest addresses */
356                 txbd->addr[0] = address << 1;
357                 txbd->addr[1] = secondary_address;
358                 i = 2;
359         }
360         else
361         {
362                 txbd->length = size + 1;  /* Length of message plus dest address */
363                 txbd->addr[0] = address << 1;  /* Write destination address to BD */
364                 i = 1;
365         }
366     }
367     else
368     {
369         txbd->length = size;  /* Length of message */
370         i = 0;
371     }
372
373         /* set up txbd */
374         txbd->status = BD_SC_READY;
375         if (flags & I2CF_START_COND)
376           txbd->status |= BD_I2C_TX_START;
377         if (flags & I2CF_STOP_COND)
378           txbd->status |= BD_SC_LAST | BD_SC_WRAP;
379
380         /* Copy data to send into buffer */
381         PRINTD(("[I2C] copy data...\n"));
382         for(j = 0; j < size; i++, j++)
383           txbd->addr[i] = dataout[j];
384
385         PRINTD(("[I2C] txbd: length=0x%04x status=0x%04x addr[0]=0x%02x addr[1]=0x%02x\n",
386                    txbd->length,
387                    txbd->status,
388                    txbd->addr[0],
389                    txbd->addr[1]));
390
391         /* advance state */
392         state->tx_buf += txbd->length;
393         state->tx_space -= txbd->length;
394         state->tx_idx++;
395         state->txbd = (void*)(txbd + 1);
396
397         return 0;
398 }
399
400 static
401 int i2c_receive(i2c_state_t *state,
402                                 unsigned char address,
403                                 unsigned char secondary_address,
404                                 unsigned int flags,
405                                 unsigned short size_to_expect,
406                                 unsigned char *datain)
407 {
408         volatile I2C_BD *rxbd, *txbd;
409
410         PRINTD(("[I2C] i2c_receive %02d %02d %02d\n", address, secondary_address, flags));
411
412         /* Expected to receive too much */
413         if (size_to_expect > I2C_RXTX_LEN)
414           return I2CERR_MSG_TOO_LONG;
415
416         /* no more free bds */
417         if (state->tx_idx >= NUM_TX_BDS || state->rx_idx >= NUM_RX_BDS
418                  || state->tx_space < 2)
419           return I2CERR_NO_BUFFERS;
420
421         rxbd = (I2C_BD *)state->rxbd;
422         txbd = (I2C_BD *)state->txbd;
423
424         PRINTD(("[I2C] rxbd = %08x\n", (int)rxbd));
425         PRINTD(("[I2C] txbd = %08x\n", (int)txbd));
426
427         txbd->addr = state->tx_buf;
428
429         /* set up TXBD for destination address */
430         if (flags & I2CF_ENABLE_SECONDARY)
431         {
432                 txbd->length = 2;
433                 txbd->addr[0] = address << 1;   /* Write data */
434                 txbd->addr[1] = secondary_address;  /* Internal address */
435                 txbd->status = BD_SC_READY;
436         }
437         else
438         {
439                 txbd->length = 1 + size_to_expect;
440                 txbd->addr[0] = (address << 1) | 0x01;
441                 txbd->status = BD_SC_READY;
442                 memset(&txbd->addr[1], 0, txbd->length);
443         }
444
445         /* set up rxbd for reception */
446         rxbd->status = BD_SC_EMPTY;
447         rxbd->length = size_to_expect;
448         rxbd->addr = datain;
449
450         txbd->status |= BD_I2C_TX_START;
451         if (flags & I2CF_STOP_COND)
452         {
453                 txbd->status |= BD_SC_LAST | BD_SC_WRAP;
454                 rxbd->status |= BD_SC_WRAP;
455         }
456
457         PRINTD(("[I2C] txbd: length=0x%04x status=0x%04x addr[0]=0x%02x addr[1]=0x%02x\n",
458                    txbd->length,
459                    txbd->status,
460                    txbd->addr[0],
461                    txbd->addr[1]));
462         PRINTD(("[I2C] rxbd: length=0x%04x status=0x%04x addr[0]=0x%02x addr[1]=0x%02x\n",
463                    rxbd->length,
464                    rxbd->status,
465                    rxbd->addr[0],
466                    rxbd->addr[1]));
467
468         /* advance state */
469         state->tx_buf += txbd->length;
470         state->tx_space -= txbd->length;
471         state->tx_idx++;
472         state->txbd = (void*)(txbd + 1);
473         state->rx_idx++;
474         state->rxbd = (void*)(rxbd + 1);
475
476         return 0;
477 }
478
479
480 static
481 int i2c_doio(i2c_state_t *state)
482 {
483         volatile immap_t *immap = (immap_t *)CFG_IMMR ;
484         volatile iic_t *iip;
485         volatile i2c8260_t *i2c = (i2c8260_t *)&immap->im_i2c;
486         volatile I2C_BD *txbd, *rxbd;
487         int  j;
488         int  timeout;
489         uint dpaddr;
490
491         PRINTD(("[I2C] i2c_doio\n"));
492
493         timeout = TOUT_LOOP * 256;      /* arbitrarily long */
494
495         if (state->tx_idx <= 0 && state->rx_idx <= 0) {
496                 PRINTD(("[I2C] No I/O is queued\n"));
497                 return I2CERR_QUEUE_EMPTY;
498         }
499
500         dpaddr = *((unsigned short*)(&immap->im_dprambase[PROFF_I2C_BASE]));
501         iip = (iic_t *)&immap->im_dprambase[dpaddr];
502         iip->iic_rbptr = iip->iic_rbase;
503         iip->iic_tbptr = iip->iic_tbase;
504
505         /* Enable I2C */
506         PRINTD(("[I2C] Enabling I2C...\n"));
507         i2c->i2c_i2mod |= 0x01;
508
509         /* Begin transmission */
510         i2c->i2c_i2com |= 0x80;
511
512         /* Loop until transmit & receive completed */
513
514         txbd = ((I2C_BD*)state->txbd) - 1;
515         j = 0;
516         if (state->tx_idx > 0) {
517                 timeout = TOUT_LOOP * txbd->length;
518
519                 PRINTD(("[I2C] Transmitting...(txbd=0x%08lx)\n", (ulong)txbd));
520                 udelay(START_DELAY_US); /* give it time to start */
521                 while((txbd->status & BD_SC_READY) && (j++ < timeout)) {
522                         udelay(DELAY_US);
523                         if (ctrlc())
524                                 return (-1);
525                         __asm__ __volatile__ ("eieio");
526                 }
527         }
528
529         rxbd = ((I2C_BD*)state->rxbd) - 1;
530         j = 0;
531         if ((state->rx_idx > 0) && (j < timeout)) {
532                 timeout = TOUT_LOOP * rxbd->length;
533                 PRINTD(("[I2C] Receiving...(rxbd=0x%08lx)\n", (ulong)rxbd));
534                 udelay(START_DELAY_US); /* give it time to start */
535                 while((rxbd->status & BD_SC_EMPTY) && (j++ < timeout)) {
536                         udelay(DELAY_US);
537                         if (ctrlc())
538                                 return (-1);
539                         __asm__ __volatile__ ("eieio");
540                 }
541         }
542
543         /* Turn off I2C */
544         i2c->i2c_i2mod &= ~0x01;
545
546         if (state->err_cb != NULL) {
547                 int n, i, b;
548
549                 /*
550                  * if we have an error callback function, look at the
551                  * error bits in the bd status and pass them back
552                  */
553
554                 if ((n = state->tx_idx) > 0) {
555                         for (i = 0; i < n; i++) {
556                                 txbd = ((I2C_BD*)state->txbd) - (n - i);
557                                 if ((b = txbd->status & BD_I2C_TX_ERR) != 0)
558                                         (*state->err_cb)(I2CECB_TX_ERR|b, i);
559                         }
560                 }
561
562                 if ((n = state->rx_idx) > 0) {
563                         for (i = 0; i < n; i++) {
564                                 rxbd = ((I2C_BD*)state->rxbd) - (n - i);
565                                 if ((b = rxbd->status & BD_I2C_RX_ERR) != 0)
566                                         (*state->err_cb)(I2CECB_RX_ERR|b, i);
567                         }
568                 }
569
570                 if (j >= timeout)
571                         (*state->err_cb)(I2CECB_TIMEOUT, 0);
572         }
573
574         /* sort out errors and return appropriate good/error status */
575         if(j >= timeout)
576                 return(I2CERR_TIMEOUT);
577         if((txbd->status & BD_I2C_TX_ERR) != 0)
578                 return(I2CECB_TX_ERR | (txbd->status & I2CECB_TX_MASK));
579         if((rxbd->status & BD_I2C_RX_ERR) != 0)
580                 return(I2CECB_RX_ERR | (rxbd->status & I2CECB_RX_MASK));
581
582         return(0);
583 }
584
585 static int had_tx_nak;
586
587 static void
588 i2c_test_callback(int flags, int xnum)
589 {
590         if ((flags & I2CECB_TX_ERR) && (flags & I2CECB_TX_NAK))
591                 had_tx_nak = 1;
592 }
593
594 int i2c_probe(uchar chip)
595 {
596         i2c_state_t state;
597         int rc;
598         uchar buf[1];
599
600         i2c_newio(&state);
601
602         state.err_cb = i2c_test_callback;
603         had_tx_nak = 0;
604
605         rc = i2c_receive(&state, chip, 0, I2CF_START_COND|I2CF_STOP_COND, 1, buf);
606
607         if (rc != 0)
608                 return (rc);
609
610         rc = i2c_doio(&state);
611
612         if ((rc != 0) && (rc != I2CERR_TIMEOUT))
613                 return (rc);
614
615         return (had_tx_nak);
616 }
617
618
619 int
620 i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len)
621 {
622         i2c_state_t state;
623         uchar xaddr[4];
624         int rc;
625
626         xaddr[0] = (addr >> 24) & 0xFF;
627         xaddr[1] = (addr >> 16) & 0xFF;
628         xaddr[2] = (addr >>  8) & 0xFF;
629         xaddr[3] =  addr        & 0xFF;
630
631 #ifdef CFG_I2C_EEPROM_ADDR_OVERFLOW
632          /*
633           * EEPROM chips that implement "address overflow" are ones
634           * like Catalyst 24WC04/08/16 which has 9/10/11 bits of address
635           * and the extra bits end up in the "chip address" bit slots.
636           * This makes a 24WC08 (1Kbyte) chip look like four 256 byte
637           * chips.
638           *
639           * Note that we consider the length of the address field to still
640           * be one byte because the extra address bits are hidden in the
641           * chip address.
642           */
643         chip |= ((addr >> (alen * 8)) & CFG_I2C_EEPROM_ADDR_OVERFLOW);
644 #endif
645
646         i2c_newio(&state);
647
648         rc = i2c_send(&state, chip, 0, I2CF_START_COND, alen, &xaddr[4-alen]);
649         if (rc != 0) {
650                 printf("i2c_read: i2c_send failed (%d)\n", rc);
651                 return 1;
652         }
653
654         rc = i2c_receive(&state, chip, 0, I2CF_STOP_COND, len, buffer);
655         if (rc != 0) {
656                 printf("i2c_read: i2c_receive failed (%d)\n", rc);
657                 return 1;
658         }
659
660         rc = i2c_doio(&state);
661         if (rc != 0) {
662                 printf("i2c_read: i2c_doio failed (%d)\n", rc);
663                 return 1;
664         }
665         return 0;
666 }
667
668 int
669 i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len)
670 {
671         i2c_state_t state;
672         uchar xaddr[4];
673         int rc;
674
675         xaddr[0] = (addr >> 24) & 0xFF;
676         xaddr[1] = (addr >> 16) & 0xFF;
677         xaddr[2] = (addr >>  8) & 0xFF;
678         xaddr[3] =  addr        & 0xFF;
679
680 #ifdef CFG_I2C_EEPROM_ADDR_OVERFLOW
681          /*
682           * EEPROM chips that implement "address overflow" are ones
683           * like Catalyst 24WC04/08/16 which has 9/10/11 bits of address
684           * and the extra bits end up in the "chip address" bit slots.
685           * This makes a 24WC08 (1Kbyte) chip look like four 256 byte
686           * chips.
687           *
688           * Note that we consider the length of the address field to still
689           * be one byte because the extra address bits are hidden in the
690           * chip address.
691           */
692         chip |= ((addr >> (alen * 8)) & CFG_I2C_EEPROM_ADDR_OVERFLOW);
693 #endif
694
695         i2c_newio(&state);
696
697         rc = i2c_send(&state, chip, 0, I2CF_START_COND, alen, &xaddr[4-alen]);
698         if (rc != 0) {
699                 printf("i2c_write: first i2c_send failed (%d)\n", rc);
700                 return 1;
701         }
702
703         rc = i2c_send(&state, 0, 0, I2CF_STOP_COND, len, buffer);
704         if (rc != 0) {
705                 printf("i2c_write: second i2c_send failed (%d)\n", rc);
706                 return 1;
707         }
708
709         rc = i2c_doio(&state);
710         if (rc != 0) {
711                 printf("i2c_write: i2c_doio failed (%d)\n", rc);
712                 return 1;
713         }
714         return 0;
715 }
716
717 uchar
718 i2c_reg_read(uchar chip, uchar reg)
719 {
720         char buf;
721
722         i2c_read(chip, reg, 1, &buf, 1);
723
724         return (buf);
725 }
726
727 void
728 i2c_reg_write(uchar chip, uchar reg, uchar val)
729 {
730         i2c_write(chip, reg, 1, &val, 1);
731 }
732
733 #endif  /* CONFIG_HARD_I2C */