1 /* I2cCore.c - MPC8220 PPC I2C Library */
3 /* Copyright 2004 Freescale Semiconductor, Inc. */
8 01c,29jun04,tcl 1.3 removed CR. Added two bytes offset support.
9 01b,19jan04,tcl 1.2 removed i2cMsDelay and sysDecGet. renamed i2cMsDelay
11 01a,19jan04,tcl 1.1 created and seperated from i2c.c
16 This file contain I2C low level handling library functions
37 #define ABS(x) ((x < 0)? -x : x)
40 "Transfer in Progress\n", /* 0 */
41 "Transfer complete\n",
42 "Not Addressed\n", /* 2 */
43 "Addressed as a slave\n",
44 "Bus is Idle\n", /* 4 */
46 "Arbitration Lost\n", /* 6 */
47 "Arbitration on Track\n",
48 "Slave receive, master writing to slave\n", /* 8 */
49 "Slave transmit, master reading from slave\n",
50 "Interrupt is pending\n", /* 10 */
51 "Interrupt complete\n",
52 "Acknowledge received\n", /* 12 */
53 "No acknowledge received\n",
54 "Unknown status\n", /* 14 */
58 /******************************************************************************
60 * chk_status - Check I2C status bit
62 * RETURNS: OK, or ERROR if the bit encounter
66 STATUS
chk_status (PSI2C pi2c
, UINT8 sta_bit
, UINT8 truefalse
)
70 for (i
= 0; i
< I2C_POLL_COUNT
; i
++) {
71 if ((pi2c
->sr
& sta_bit
) == (truefalse
? sta_bit
: 0))
75 I2CCDBG (L2
, ("--- sr %x stabit %x truefalse %d\n",
76 pi2c
->sr
, sta_bit
, truefalse
, 0, 0, 0));
78 if (i
== I2C_POLL_COUNT
) {
109 I2CCDBG (NO
, ("--- status %d\n", status
, 0, 0, 0, 0, 0));
110 I2CCDBG (NO
, (I2CERR
[status
], 0, 0, 0, 0, 0, 0));
116 /******************************************************************************
118 * I2C Enable - Enable the I2C Controller
121 STATUS
i2c_enable (SI2C
* pi2c
, PI2CSET pi2cSet
)
123 int fdr
= pi2cSet
->bit_rate
;
124 UINT8 adr
= pi2cSet
->i2c_adr
;
126 I2CCDBG (L2
, ("i2c_enable fdr %d adr %x\n", fdr
, adr
, 0, 0, 0, 0));
128 i2c_clear (pi2c
); /* Clear FDR, ADR, SR and CR reg */
130 SetI2cFDR (pi2c
, fdr
); /* Frequency */
133 pi2c
->cr
= I2C_CTL_EN
; /* Set Enable */
136 The I2C bus should be in Idle state. If the bus is busy,
137 clear the STA bit in control register
139 if (chk_status (pi2c
, I2C_STA_BB
, 0) != OK
) {
140 if ((pi2c
->cr
& I2C_CTL_STA
) == I2C_CTL_STA
)
141 pi2c
->cr
&= ~I2C_CTL_STA
;
143 /* Check again if it is still busy, return error if found */
144 if (chk_status (pi2c
, I2C_STA_BB
, 1) == OK
)
151 /******************************************************************************
153 * I2C Disable - Disable the I2C Controller
156 STATUS
i2c_disable (PSI2C pi2c
)
160 pi2c
->cr
&= I2C_CTL_EN
; /* Disable I2c */
162 if ((pi2c
->cr
& I2C_CTL_STA
) == I2C_CTL_STA
)
163 pi2c
->cr
&= ~I2C_CTL_STA
;
165 if (chk_status (pi2c
, I2C_STA_BB
, 0) != OK
)
171 /******************************************************************************
173 * I2C Clear - Clear the I2C Controller
176 STATUS
i2c_clear (PSI2C pi2c
)
187 STATUS
i2c_start (PSI2C pi2c
, PI2CSET pi2cSet
)
190 UINT16 ByteOffset
= pi2cSet
->str_adr
;
192 UINT8 ByteOffset
= pi2cSet
->str_adr
;
197 UINT8 Addr
= pi2cSet
->slv_adr
;
199 pi2c
->cr
|= I2C_CTL_STA
; /* Generate start signal */
201 if (chk_status (pi2c
, I2C_STA_BB
, 1) != OK
)
204 /* Write slave address */
205 if (i2c_writebyte (pi2c
, &Addr
) != OK
) {
206 i2c_stop (pi2c
); /* Disable I2c */
211 /* Issue the offset to start */
212 if (i2c_write2byte (pi2c
, &ByteOffset
) != OK
) {
213 i2c_stop (pi2c
); /* Disable I2c */
217 tmp
= (ByteOffset
>> 8) & 0xff;
218 if (i2c_writebyte (pi2c
, &tmp
) != OK
) {
219 i2c_stop (pi2c
); /* Disable I2c */
222 tmp
= ByteOffset
& 0xff;
223 if (i2c_writebyte (pi2c
, &tmp
) != OK
) {
224 i2c_stop (pi2c
); /* Disable I2c */
228 if (i2c_writebyte (pi2c
, &ByteOffset
) != OK
) {
229 i2c_stop (pi2c
); /* Disable I2c */
237 STATUS
i2c_stop (PSI2C pi2c
)
239 pi2c
->cr
&= ~I2C_CTL_STA
; /* Generate stop signal */
240 if (chk_status (pi2c
, I2C_STA_BB
, 0) != OK
)
246 /******************************************************************************
248 * Read Len bytes to the location pointed to by *Data from the device
251 int i2c_readblock (SI2C
* pi2c
, PI2CSET pi2cSet
, UINT8
* Data
)
256 /* UINT8 ByteOffset = pi2cSet->str_adr; not used? */
257 UINT8 Addr
= pi2cSet
->slv_adr
;
258 int Length
= pi2cSet
->xfer_size
;
260 I2CCDBG (L1
, ("i2c_readblock addr %x data 0x%08x len %d offset %d\n",
261 Addr
, (int) Data
, Length
, ByteOffset
, 0, 0));
263 if (pi2c
->sr
& I2C_STA_AL
) { /* Check if Arbitration lost */
264 I2CCDBG (FN
, ("Arbitration lost\n", 0, 0, 0, 0, 0, 0));
265 pi2c
->sr
&= ~I2C_STA_AL
; /* Clear Arbitration status bit */
269 pi2c
->cr
|= I2C_CTL_TX
; /* Enable the I2c for TX, Ack */
271 if (i2c_start (pi2c
, pi2cSet
) == ERROR
)
274 pi2c
->cr
|= I2C_CTL_RSTA
; /* Repeat Start */
278 if (i2c_writebyte (pi2c
, &Tmp
) != OK
) {
279 i2c_stop (pi2c
); /* Disable I2c */
283 if (((pi2c
->sr
& 0x07) == 0x07) || (pi2c
->sr
& 0x01))
286 pi2c
->cr
&= ~I2C_CTL_TX
; /* Set receive mode */
288 if (((pi2c
->sr
& 0x07) == 0x07) || (pi2c
->sr
& 0x01))
292 if (i2c_readbyte (pi2c
, &Tmp
, &i
) != OK
) {
293 i2c_stop (pi2c
); /* Disable I2c */
300 pi2c
->cr
|= I2C_CTL_TXAK
;
303 pi2c
->cr
&= ~I2C_CTL_STA
;
305 if (i2c_readbyte (pi2c
, Data
, &Length
) != OK
) {
306 return i2c_stop (pi2c
);
313 if (i2c_stop (pi2c
) == ERROR
)
319 STATUS
i2c_writeblock (SI2C
* pi2c
, PI2CSET pi2cSet
, UINT8
* Data
)
321 int Length
= pi2cSet
->xfer_size
;
324 UINT16 ByteOffset
= pi2cSet
->str_adr
;
326 UINT8 ByteOffset
= pi2cSet
->str_adr
;
330 I2CCDBG (L2
, ("i2c_writeblock\n", 0, 0, 0, 0, 0, 0));
332 if (pi2c
->sr
& I2C_STA_AL
) {
333 /* Check if arbitration lost */
334 I2CCDBG (L2
, ("Arbitration lost\n", 0, 0, 0, 0, 0, 0));
335 pi2c
->sr
&= ~I2C_STA_AL
; /* Clear the condition */
339 pi2c
->cr
|= I2C_CTL_TX
; /* Enable the I2c for TX, Ack */
341 /* Do the not even offset first */
342 if ((ByteOffset
% 8) != 0) {
346 remain
= 8 - (ByteOffset
% 8);
349 pi2cSet
->str_adr
= ByteOffset
;
351 if (i2c_start (pi2c
, pi2cSet
) == ERROR
)
354 for (j
= ByteOffset
; j
< remain
; j
++) {
355 if (i2c_writebyte (pi2c
, Data
++) != OK
)
359 if (i2c_stop (pi2c
) == ERROR
)
364 /* Update the new ByteOffset */
365 ByteOffset
+= remain
;
369 for (j
= ByteOffset
, k
= 0; j
< (Length
+ ByteOffset
); j
++) {
371 pi2cSet
->str_adr
= j
;
372 if (i2c_start (pi2c
, pi2cSet
) == ERROR
)
378 if (i2c_writebyte (pi2c
, Data
++) != OK
)
381 if ((j
== (Length
- 1)) || ((k
% 8) == 0)) {
382 if (i2c_stop (pi2c
) == ERROR
)
393 STATUS
i2c_readbyte (SI2C
* pi2c
, UINT8
* readb
, int *index
)
395 pi2c
->sr
&= ~I2C_STA_IF
; /* Clear Interrupt Bit */
396 *readb
= pi2c
->dr
; /* Read a byte */
399 Set I2C_CTRL_TXAK will cause Transfer pending and
400 set I2C_CTRL_STA will cause Interrupt pending
403 if (chk_status (pi2c
, I2C_STA_CF
, 1) != OK
) /* Transfer not complete? */
408 if (chk_status (pi2c
, I2C_STA_IF
, 1) != OK
)
416 STATUS
i2c_writebyte (SI2C
* pi2c
, UINT8
* writeb
)
418 pi2c
->sr
&= ~I2C_STA_IF
; /* Clear Interrupt */
419 pi2c
->dr
= *writeb
; /* Write a byte */
421 if (chk_status (pi2c
, I2C_STA_CF
, 1) != OK
) /* Transfer not complete? */
424 if (chk_status (pi2c
, I2C_STA_IF
, 1) != OK
)
430 STATUS
i2c_write2byte (SI2C
* pi2c
, UINT16
* writeb
)
434 data
= (UINT8
) ((*writeb
>> 8) & 0xff);
435 if (i2c_writebyte (pi2c
, &data
) != OK
)
437 data
= (UINT8
) (*writeb
& 0xff);
438 if (i2c_writebyte (pi2c
, &data
) != OK
)
443 /* FDR table base on 33Mhz - more detail please refer to Odini2c_dividers.xls
444 FDR FDR scl sda scl2tap2
445 510 432 tap tap tap tap scl_per sda_hold I2C Freq 0 1 2 3 4 5
446 000 000 9 3 4 1 28 Clocks 9 Clocks 1190 KHz 0 0 0 0 0 0
447 000 001 9 3 4 2 44 Clocks 11 Clocks 758 KHz 0 0 1 0 0 0
448 000 010 9 3 6 4 80 Clocks 17 Clocks 417 KHz 0 0 0 1 0 0
449 000 011 9 3 6 8 144 Clocks 25 Clocks 231 KHz 0 0 1 1 0 0
450 000 100 9 3 14 16 288 Clocks 49 Clocks 116 KHz 0 0 0 0 1 0
451 000 101 9 3 30 32 576 Clocks 97 Clocks 58 KHz 0 0 1 0 1 0
452 000 110 9 3 62 64 1152 Clocks 193 Clocks 29 KHz 0 0 0 1 1 0
453 000 111 9 3 126 128 2304 Clocks 385 Clocks 14 KHz 0 0 1 1 1 0
454 001 000 10 3 4 1 30 Clocks 9 Clocks 1111 KHz1 0 0 0 0 0
455 001 001 10 3 4 2 48 Clocks 11 Clocks 694 KHz 1 0 1 0 0 0
456 001 010 10 3 6 4 88 Clocks 17 Clocks 379 KHz 1 0 0 1 0 0
457 001 011 10 3 6 8 160 Clocks 25 Clocks 208 KHz 1 0 1 1 0 0
458 001 100 10 3 14 16 320 Clocks 49 Clocks 104 KHz 1 0 0 0 1 0
459 001 101 10 3 30 32 640 Clocks 97 Clocks 52 KHz 1 0 1 0 1 0
460 001 110 10 3 62 64 1280 Clocks 193 Clocks 26 KHz 1 0 0 1 1 0
461 001 111 10 3 126 128 2560 Clocks 385 Clocks 13 KHz 1 0 1 1 1 0
462 010 000 12 4 4 1 34 Clocks 10 Clocks 980 KHz 0 1 0 0 0 0
463 010 001 12 4 4 2 56 Clocks 13 Clocks 595 KHz 0 1 1 0 0 0
464 010 010 12 4 6 4 104 Clocks 21 Clocks 321 KHz 0 1 0 1 0 0
465 010 011 12 4 6 8 192 Clocks 33 Clocks 174 KHz 0 1 1 1 0 0
466 010 100 12 4 14 16 384 Clocks 65 Clocks 87 KHz 0 1 0 0 1 0
467 010 101 12 4 30 32 768 Clocks 129 Clocks 43 KHz 0 1 1 0 1 0
468 010 110 12 4 62 64 1536 Clocks 257 Clocks 22 KHz 0 1 0 1 1 0
469 010 111 12 4 126 128 3072 Clocks 513 Clocks 11 KHz 0 1 1 1 1 0
470 011 000 15 4 4 1 40 Clocks 10 Clocks 833 KHz 1 1 0 0 0 0
471 011 001 15 4 4 2 68 Clocks 13 Clocks 490 KHz 1 1 1 0 0 0
472 011 010 15 4 6 4 128 Clocks 21 Clocks 260 KHz 1 1 0 1 0 0
473 011 011 15 4 6 8 240 Clocks 33 Clocks 139 KHz 1 1 1 1 0 0
474 011 100 15 4 14 16 480 Clocks 65 Clocks 69 KHz 1 1 0 0 1 0
475 011 101 15 4 30 32 960 Clocks 129 Clocks 35 KHz 1 1 1 0 1 0
476 011 110 15 4 62 64 1920 Clocks 257 Clocks 17 KHz 1 1 0 1 1 0
477 011 111 15 4 126 128 3840 Clocks 513 Clocks 9 KHz 1 1 1 1 1 0
478 100 000 5 1 4 1 20 Clocks 7 Clocks 1667 KHz 0 0 0 0 0 1
479 100 001 5 1 4 2 28 Clocks 7 Clocks 1190 KHz 0 0 1 0 0 1
480 100 010 5 1 6 4 48 Clocks 9 Clocks 694 KHz 0 0 0 1 0 1
481 100 011 5 1 6 8 80 Clocks 9 Clocks 417 KHz 0 0 1 1 0 1
482 100 100 5 1 14 16 160 Clocks 17 Clocks 208 KHz 0 0 0 0 1 1
483 100 101 5 1 30 32 320 Clocks 33 Clocks 104 KHz 0 0 1 0 1 1
484 100 110 5 1 62 64 640 Clocks 65 Clocks 52 KHz 0 0 0 1 1 1
485 100 111 5 1 126 128 1280 Clocks 129 Clocks 26 KHz 0 0 1 1 1 1
486 101 000 6 1 4 1 22 Clocks 7 Clocks 1515 KHz 1 0 0 0 0 1
487 101 001 6 1 4 2 32 Clocks 7 Clocks 1042 KHz 1 0 1 0 0 1
488 101 010 6 1 6 4 56 Clocks 9 Clocks 595 KHz 1 0 0 1 0 1
489 101 011 6 1 6 8 96 Clocks 9 Clocks 347 KHz 1 0 1 1 0 1
490 101 100 6 1 14 16 192 Clocks 17 Clocks 174 KHz 1 0 0 0 1 1
491 101 101 6 1 30 32 384 Clocks 33 Clocks 87 KHz 1 0 1 0 1 1
492 101 110 6 1 62 64 768 Clocks 65 Clocks 43 KHz 1 0 0 1 1 1
493 101 111 6 1 126 128 1536 Clocks 129 Clocks 22 KHz 1 0 1 1 1 1
494 110 000 7 2 4 1 24 Clocks 8 Clocks 1389 KHz 0 1 0 0 0 1
495 110 001 7 2 4 2 36 Clocks 9 Clocks 926 KHz 0 1 1 0 0 1
496 110 010 7 2 6 4 64 Clocks 13 Clocks 521 KHz 0 1 0 1 0 1
497 110 011 7 2 6 8 112 Clocks 17 Clocks 298 KHz 0 1 1 1 0 1
498 110 100 7 2 14 16 224 Clocks 33 Clocks 149 KHz 0 1 0 0 1 1
499 110 101 7 2 30 32 448 Clocks 65 Clocks 74 KHz 0 1 1 0 1 1
500 110 110 7 2 62 64 896 Clocks 129 Clocks 37 KHz 0 1 0 1 1 1
501 110 111 7 2 126 128 1792 Clocks 257 Clocks 19 KHz 0 1 1 1 1 1
502 111 000 8 2 4 1 26 Clocks 8 Clocks 1282 KHz 1 1 0 0 0 1
503 111 001 8 2 4 2 40 Clocks 9 Clocks 833 KHz 1 1 1 0 0 1
504 111 010 8 2 6 4 72 Clocks 13 Clocks 463 KHz 1 1 0 1 0 1
505 111 011 8 2 6 8 128 Clocks 17 Clocks 260 KHz 1 1 1 1 0 1
506 111 100 8 2 14 16 256 Clocks 33 Clocks 130 KHz 1 1 0 0 1 1
507 111 101 8 2 30 32 512 Clocks 65 Clocks 65 KHz 1 1 1 0 1 1
508 111 110 8 2 62 64 1024 Clocks 129 Clocks 33 KHz 1 1 0 1 1 1
509 111 111 8 2 126 128 2048 Clocks 257 Clocks 16 KHz 1 1 1 1 1 1
511 STATUS
SetI2cFDR (PSI2C pi2cRegs
, int bitrate
)
514 const UINT8 div_hold
[8][3] = { {9, 3}, {10, 3},
520 const UINT8 scl_tap
[8][2] = { {4, 1}, {4, 2},
532 int WhichFreq
, iRec
, jRec
;
537 I2CCDBG (L2
, ("Entering getBitRate: bitrate %d pi2cRegs 0x%08x\n",
538 bitrate
, (int) pi2cRegs
, 0, 0, 0, 0));
541 I2CCDBG (NO
, ("Invalid bitrate\n", 0, 0, 0, 0, 0, 0));
548 WhichFreq
= iRec
= jRec
= 0;
550 for (i
= 0; i
< 8; i
++) {
551 for (j
= 0; j
< 8; j
++) {
552 /* SCL Period = 2 * (scl2tap + [(SCL_Tap - 1) * tap2tap] + 2)
553 * SCL Hold = scl2tap + ((SDA_Tap - 1) * tap2tap) + 3
554 * Bit Rate (I2C Freq) = System Freq / SCL Period
558 ((div_hold
[j
][0] - 1) * scl_tap
[i
][1]) +
561 /* Now get the I2C Freq */
562 I2C_Freq
= DEV_CLOCK_FREQ
/ SCL_Period
;
564 /* Take equal or slower */
565 if (I2C_Freq
> bitrate
)
568 /* Take the differences */
569 Diff
= I2C_Freq
- bitrate
;
573 /* Find the closer value */
576 WhichFreq
= I2C_Freq
;
582 ("--- (%d,%d) I2C_Freq %d minDiff %d min %d\n",
583 i
, j
, I2C_Freq
, Diff
, min
, 0));
588 2 * (scl_tap
[iRec
][0] +
589 ((div_hold
[jRec
][0] - 1) * scl_tap
[iRec
][1]) + 2);
591 I2CCDBG (L2
, ("\nmin %d WhichFreq %d iRec %d jRec %d\n",
592 min
, WhichFreq
, iRec
, jRec
, 0, 0));
593 I2CCDBG (L2
, ("--- scl2tap %d SCL_Tap %d tap2tap %d\n",
594 scl_tap
[iRec
][0], div_hold
[jRec
][0], scl_tap
[iRec
][1],
597 /* This may no require */
600 ((div_hold
[jRec
][1] - 1) * scl_tap
[iRec
][1]) + 3;
602 ("--- SCL_Period %d SCL_Hold %d\n", SCL_Period
, SCL_Hold
, 0,
605 I2CCDBG (L2
, ("--- mfdr_bits %x\n", mfdr_bits
, 0, 0, 0, 0, 0));
609 mfdr_bits
|= 0x04; /* FDR 2 */
611 mfdr_bits
|= 0x08; /* FDR 3 */
613 mfdr_bits
|= 0x10; /* FDR 4 */
616 mfdr_bits
|= 0x01; /* FDR 0 */
618 mfdr_bits
|= 0x02; /* FDR 1 */
620 mfdr_bits
|= 0x20; /* FDR 5 */
622 I2CCDBG (L2
, ("--- mfdr_bits %x\n", mfdr_bits
, 0, 0, 0, 0, 0));
624 pi2cRegs
->fdr
= mfdr_bits
;