wdenk | 983fda8 | 2004-10-28 00:09:35 +0000 | [diff] [blame] | 1 | /* I2cCore.c - MPC8220 PPC I2C Library */ |
| 2 | |
| 3 | /* Copyright 2004 Freescale Semiconductor, Inc. */ |
| 4 | |
| 5 | /* |
| 6 | modification history |
| 7 | -------------------- |
| 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 |
| 10 | back to sysMsDelay |
| 11 | 01a,19jan04,tcl 1.1 created and seperated from i2c.c |
| 12 | */ |
| 13 | |
| 14 | /* |
| 15 | DESCRIPTION |
| 16 | This file contain I2C low level handling library functions |
| 17 | */ |
| 18 | |
| 19 | #include <stdio.h> |
| 20 | #include <stdlib.h> |
| 21 | #include <string.h> |
| 22 | #include <vxWorks.h> |
| 23 | #include <sysLib.h> |
| 24 | #include <iosLib.h> |
| 25 | #include <logLib.h> |
| 26 | #include <tickLib.h> |
| 27 | |
| 28 | /* BSP Includes */ |
| 29 | #include "config.h" |
| 30 | #include "mpc8220.h" |
| 31 | #include "i2cCore.h" |
| 32 | |
| 33 | #ifdef DEBUG_I2CCORE |
| 34 | int I2CCDbg = 0; |
| 35 | #endif |
| 36 | |
| 37 | #define ABS(x) ((x < 0)? -x : x) |
| 38 | |
| 39 | char *I2CERR[16] = { |
| 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 */ |
| 45 | "Bus is busy\n", |
| 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 */ |
| 55 | "\n" |
| 56 | }; |
| 57 | |
| 58 | /****************************************************************************** |
| 59 | * |
| 60 | * chk_status - Check I2C status bit |
| 61 | * |
| 62 | * RETURNS: OK, or ERROR if the bit encounter |
| 63 | * |
| 64 | */ |
| 65 | |
| 66 | STATUS chk_status (PSI2C pi2c, UINT8 sta_bit, UINT8 truefalse) |
| 67 | { |
| 68 | int i, status = 0; |
| 69 | |
| 70 | for (i = 0; i < I2C_POLL_COUNT; i++) { |
| 71 | if ((pi2c->sr & sta_bit) == (truefalse ? sta_bit : 0)) |
| 72 | return (OK); |
| 73 | } |
| 74 | |
| 75 | I2CCDBG (L2, ("--- sr %x stabit %x truefalse %d\n", |
| 76 | pi2c->sr, sta_bit, truefalse, 0, 0, 0)); |
| 77 | |
| 78 | if (i == I2C_POLL_COUNT) { |
| 79 | switch (sta_bit) { |
| 80 | case I2C_STA_CF: |
| 81 | status = 0; |
| 82 | break; |
| 83 | case I2C_STA_AAS: |
| 84 | status = 2; |
| 85 | break; |
| 86 | case I2C_STA_BB: |
| 87 | status = 4; |
| 88 | break; |
| 89 | case I2C_STA_AL: |
| 90 | status = 6; |
| 91 | break; |
| 92 | case I2C_STA_SRW: |
| 93 | status = 8; |
| 94 | break; |
| 95 | case I2C_STA_IF: |
| 96 | status = 10; |
| 97 | break; |
| 98 | case I2C_STA_RXAK: |
| 99 | status = 12; |
| 100 | break; |
| 101 | default: |
| 102 | status = 14; |
| 103 | break; |
| 104 | } |
| 105 | |
| 106 | if (!truefalse) |
| 107 | status++; |
| 108 | |
| 109 | I2CCDBG (NO, ("--- status %d\n", status, 0, 0, 0, 0, 0)); |
| 110 | I2CCDBG (NO, (I2CERR[status], 0, 0, 0, 0, 0, 0)); |
| 111 | } |
| 112 | |
| 113 | return (ERROR); |
| 114 | } |
| 115 | |
| 116 | /****************************************************************************** |
| 117 | * |
| 118 | * I2C Enable - Enable the I2C Controller |
| 119 | * |
| 120 | */ |
| 121 | STATUS i2c_enable (SI2C * pi2c, PI2CSET pi2cSet) |
| 122 | { |
| 123 | int fdr = pi2cSet->bit_rate; |
| 124 | UINT8 adr = pi2cSet->i2c_adr; |
| 125 | |
| 126 | I2CCDBG (L2, ("i2c_enable fdr %d adr %x\n", fdr, adr, 0, 0, 0, 0)); |
| 127 | |
| 128 | i2c_clear (pi2c); /* Clear FDR, ADR, SR and CR reg */ |
| 129 | |
| 130 | SetI2cFDR (pi2c, fdr); /* Frequency */ |
| 131 | pi2c->adr = adr; |
| 132 | |
| 133 | pi2c->cr = I2C_CTL_EN; /* Set Enable */ |
| 134 | |
| 135 | /* |
| 136 | The I2C bus should be in Idle state. If the bus is busy, |
| 137 | clear the STA bit in control register |
| 138 | */ |
| 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; |
| 142 | |
| 143 | /* Check again if it is still busy, return error if found */ |
| 144 | if (chk_status (pi2c, I2C_STA_BB, 1) == OK) |
| 145 | return ERROR; |
| 146 | } |
| 147 | |
| 148 | return (OK); |
| 149 | } |
| 150 | |
| 151 | /****************************************************************************** |
| 152 | * |
| 153 | * I2C Disable - Disable the I2C Controller |
| 154 | * |
| 155 | */ |
| 156 | STATUS i2c_disable (PSI2C pi2c) |
| 157 | { |
| 158 | i2c_clear (pi2c); |
| 159 | |
| 160 | pi2c->cr &= I2C_CTL_EN; /* Disable I2c */ |
| 161 | |
| 162 | if ((pi2c->cr & I2C_CTL_STA) == I2C_CTL_STA) |
| 163 | pi2c->cr &= ~I2C_CTL_STA; |
| 164 | |
| 165 | if (chk_status (pi2c, I2C_STA_BB, 0) != OK) |
| 166 | return ERROR; |
| 167 | |
| 168 | return (OK); |
| 169 | } |
| 170 | |
| 171 | /****************************************************************************** |
| 172 | * |
| 173 | * I2C Clear - Clear the I2C Controller |
| 174 | * |
| 175 | */ |
| 176 | STATUS i2c_clear (PSI2C pi2c) |
| 177 | { |
| 178 | pi2c->adr = 0; |
| 179 | pi2c->fdr = 0; |
| 180 | pi2c->cr = 0; |
| 181 | pi2c->sr = 0; |
| 182 | |
| 183 | return (OK); |
| 184 | } |
| 185 | |
| 186 | |
| 187 | STATUS i2c_start (PSI2C pi2c, PI2CSET pi2cSet) |
| 188 | { |
| 189 | #ifdef TWOBYTES |
| 190 | UINT16 ByteOffset = pi2cSet->str_adr; |
| 191 | #else |
| 192 | UINT8 ByteOffset = pi2cSet->str_adr; |
| 193 | #endif |
| 194 | #if 1 |
| 195 | UINT8 tmp = 0; |
| 196 | #endif |
| 197 | UINT8 Addr = pi2cSet->slv_adr; |
| 198 | |
| 199 | pi2c->cr |= I2C_CTL_STA; /* Generate start signal */ |
| 200 | |
| 201 | if (chk_status (pi2c, I2C_STA_BB, 1) != OK) |
| 202 | return ERROR; |
| 203 | |
| 204 | /* Write slave address */ |
| 205 | if (i2c_writebyte (pi2c, &Addr) != OK) { |
| 206 | i2c_stop (pi2c); /* Disable I2c */ |
| 207 | return ERROR; |
| 208 | } |
| 209 | #ifdef TWOBYTES |
| 210 | # if 0 |
| 211 | /* Issue the offset to start */ |
| 212 | if (i2c_write2byte (pi2c, &ByteOffset) != OK) { |
| 213 | i2c_stop (pi2c); /* Disable I2c */ |
| 214 | return ERROR; |
| 215 | } |
| 216 | #endif |
| 217 | tmp = (ByteOffset >> 8) & 0xff; |
| 218 | if (i2c_writebyte (pi2c, &tmp) != OK) { |
| 219 | i2c_stop (pi2c); /* Disable I2c */ |
| 220 | return ERROR; |
| 221 | } |
| 222 | tmp = ByteOffset & 0xff; |
| 223 | if (i2c_writebyte (pi2c, &tmp) != OK) { |
| 224 | i2c_stop (pi2c); /* Disable I2c */ |
| 225 | return ERROR; |
| 226 | } |
| 227 | #else |
| 228 | if (i2c_writebyte (pi2c, &ByteOffset) != OK) { |
| 229 | i2c_stop (pi2c); /* Disable I2c */ |
| 230 | return ERROR; |
| 231 | } |
| 232 | #endif |
| 233 | |
| 234 | return (OK); |
| 235 | } |
| 236 | |
| 237 | STATUS i2c_stop (PSI2C pi2c) |
| 238 | { |
| 239 | pi2c->cr &= ~I2C_CTL_STA; /* Generate stop signal */ |
| 240 | if (chk_status (pi2c, I2C_STA_BB, 0) != OK) |
| 241 | return ERROR; |
| 242 | |
| 243 | return (OK); |
| 244 | } |
| 245 | |
| 246 | /****************************************************************************** |
| 247 | * |
| 248 | * Read Len bytes to the location pointed to by *Data from the device |
| 249 | * with address Addr. |
| 250 | */ |
| 251 | int i2c_readblock (SI2C * pi2c, PI2CSET pi2cSet, UINT8 * Data) |
| 252 | { |
| 253 | int i = 0; |
| 254 | UINT8 Tmp; |
| 255 | |
| 256 | /* UINT8 ByteOffset = pi2cSet->str_adr; not used? */ |
| 257 | UINT8 Addr = pi2cSet->slv_adr; |
| 258 | int Length = pi2cSet->xfer_size; |
| 259 | |
| 260 | I2CCDBG (L1, ("i2c_readblock addr %x data 0x%08x len %d offset %d\n", |
| 261 | Addr, (int) Data, Length, ByteOffset, 0, 0)); |
| 262 | |
| 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 */ |
| 266 | return ERROR; |
| 267 | } |
| 268 | |
| 269 | pi2c->cr |= I2C_CTL_TX; /* Enable the I2c for TX, Ack */ |
| 270 | |
| 271 | if (i2c_start (pi2c, pi2cSet) == ERROR) |
| 272 | return ERROR; |
| 273 | |
| 274 | pi2c->cr |= I2C_CTL_RSTA; /* Repeat Start */ |
| 275 | |
| 276 | Tmp = Addr | 1; |
| 277 | |
| 278 | if (i2c_writebyte (pi2c, &Tmp) != OK) { |
| 279 | i2c_stop (pi2c); /* Disable I2c */ |
| 280 | return ERROR; |
| 281 | } |
| 282 | |
| 283 | if (((pi2c->sr & 0x07) == 0x07) || (pi2c->sr & 0x01)) |
| 284 | return ERROR; |
| 285 | |
| 286 | pi2c->cr &= ~I2C_CTL_TX; /* Set receive mode */ |
| 287 | |
| 288 | if (((pi2c->sr & 0x07) == 0x07) || (pi2c->sr & 0x01)) |
| 289 | return ERROR; |
| 290 | |
| 291 | /* Dummy Read */ |
| 292 | if (i2c_readbyte (pi2c, &Tmp, &i) != OK) { |
| 293 | i2c_stop (pi2c); /* Disable I2c */ |
| 294 | return ERROR; |
| 295 | } |
| 296 | |
| 297 | i = 0; |
| 298 | while (Length) { |
| 299 | if (Length == 2) |
| 300 | pi2c->cr |= I2C_CTL_TXAK; |
| 301 | |
| 302 | if (Length == 1) |
| 303 | pi2c->cr &= ~I2C_CTL_STA; |
| 304 | |
| 305 | if (i2c_readbyte (pi2c, Data, &Length) != OK) { |
| 306 | return i2c_stop (pi2c); |
| 307 | } |
| 308 | i++; |
| 309 | Length--; |
| 310 | Data++; |
| 311 | } |
| 312 | |
| 313 | if (i2c_stop (pi2c) == ERROR) |
| 314 | return ERROR; |
| 315 | |
| 316 | return i; |
| 317 | } |
| 318 | |
| 319 | STATUS i2c_writeblock (SI2C * pi2c, PI2CSET pi2cSet, UINT8 * Data) |
| 320 | { |
| 321 | int Length = pi2cSet->xfer_size; |
| 322 | |
| 323 | #ifdef TWOBYTES |
| 324 | UINT16 ByteOffset = pi2cSet->str_adr; |
| 325 | #else |
| 326 | UINT8 ByteOffset = pi2cSet->str_adr; |
| 327 | #endif |
| 328 | int j, k; |
| 329 | |
| 330 | I2CCDBG (L2, ("i2c_writeblock\n", 0, 0, 0, 0, 0, 0)); |
| 331 | |
| 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 */ |
| 336 | return ERROR; |
| 337 | } |
| 338 | |
| 339 | pi2c->cr |= I2C_CTL_TX; /* Enable the I2c for TX, Ack */ |
| 340 | |
| 341 | /* Do the not even offset first */ |
| 342 | if ((ByteOffset % 8) != 0) { |
| 343 | int remain; |
| 344 | |
| 345 | if (Length > 8) { |
| 346 | remain = 8 - (ByteOffset % 8); |
| 347 | Length -= remain; |
| 348 | |
| 349 | pi2cSet->str_adr = ByteOffset; |
| 350 | |
| 351 | if (i2c_start (pi2c, pi2cSet) == ERROR) |
| 352 | return ERROR; |
| 353 | |
| 354 | for (j = ByteOffset; j < remain; j++) { |
| 355 | if (i2c_writebyte (pi2c, Data++) != OK) |
| 356 | return ERROR; |
| 357 | } |
| 358 | |
| 359 | if (i2c_stop (pi2c) == ERROR) |
| 360 | return ERROR; |
| 361 | |
| 362 | sysMsDelay (32); |
| 363 | |
| 364 | /* Update the new ByteOffset */ |
| 365 | ByteOffset += remain; |
| 366 | } |
| 367 | } |
| 368 | |
| 369 | for (j = ByteOffset, k = 0; j < (Length + ByteOffset); j++) { |
| 370 | if ((j % 8) == 0) { |
| 371 | pi2cSet->str_adr = j; |
| 372 | if (i2c_start (pi2c, pi2cSet) == ERROR) |
| 373 | return ERROR; |
| 374 | } |
| 375 | |
| 376 | k++; |
| 377 | |
| 378 | if (i2c_writebyte (pi2c, Data++) != OK) |
| 379 | return ERROR; |
| 380 | |
| 381 | if ((j == (Length - 1)) || ((k % 8) == 0)) { |
| 382 | if (i2c_stop (pi2c) == ERROR) |
| 383 | return ERROR; |
| 384 | |
| 385 | sysMsDelay (50); |
| 386 | } |
| 387 | |
| 388 | } |
| 389 | |
| 390 | return k; |
| 391 | } |
| 392 | |
| 393 | STATUS i2c_readbyte (SI2C * pi2c, UINT8 * readb, int *index) |
| 394 | { |
| 395 | pi2c->sr &= ~I2C_STA_IF; /* Clear Interrupt Bit */ |
| 396 | *readb = pi2c->dr; /* Read a byte */ |
| 397 | |
| 398 | /* |
| 399 | Set I2C_CTRL_TXAK will cause Transfer pending and |
| 400 | set I2C_CTRL_STA will cause Interrupt pending |
| 401 | */ |
| 402 | if (*index != 2) { |
| 403 | if (chk_status (pi2c, I2C_STA_CF, 1) != OK) /* Transfer not complete? */ |
| 404 | return ERROR; |
| 405 | } |
| 406 | |
| 407 | if (*index != 1) { |
| 408 | if (chk_status (pi2c, I2C_STA_IF, 1) != OK) |
| 409 | return ERROR; |
| 410 | } |
| 411 | |
| 412 | return (OK); |
| 413 | } |
| 414 | |
| 415 | |
| 416 | STATUS i2c_writebyte (SI2C * pi2c, UINT8 * writeb) |
| 417 | { |
| 418 | pi2c->sr &= ~I2C_STA_IF; /* Clear Interrupt */ |
| 419 | pi2c->dr = *writeb; /* Write a byte */ |
| 420 | |
| 421 | if (chk_status (pi2c, I2C_STA_CF, 1) != OK) /* Transfer not complete? */ |
| 422 | return ERROR; |
| 423 | |
| 424 | if (chk_status (pi2c, I2C_STA_IF, 1) != OK) |
| 425 | return ERROR; |
| 426 | |
| 427 | return OK; |
| 428 | } |
| 429 | |
| 430 | STATUS i2c_write2byte (SI2C * pi2c, UINT16 * writeb) |
| 431 | { |
| 432 | UINT8 data; |
| 433 | |
| 434 | data = (UINT8) ((*writeb >> 8) & 0xff); |
| 435 | if (i2c_writebyte (pi2c, &data) != OK) |
| 436 | return ERROR; |
| 437 | data = (UINT8) (*writeb & 0xff); |
| 438 | if (i2c_writebyte (pi2c, &data) != OK) |
| 439 | return ERROR; |
| 440 | return OK; |
| 441 | } |
| 442 | |
| 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 |
| 510 | */ |
| 511 | STATUS SetI2cFDR (PSI2C pi2cRegs, int bitrate) |
| 512 | { |
| 513 | /* Constants */ |
| 514 | const UINT8 div_hold[8][3] = { {9, 3}, {10, 3}, |
| 515 | {12, 4}, {15, 4}, |
| 516 | {5, 1}, {6, 1}, |
| 517 | {7, 2}, {8, 2} |
| 518 | }; |
| 519 | |
| 520 | const UINT8 scl_tap[8][2] = { {4, 1}, {4, 2}, |
| 521 | {6, 4}, {6, 8}, |
| 522 | {14, 16}, {30, 32}, |
| 523 | {62, 64}, {126, 128} |
| 524 | }; |
| 525 | |
| 526 | UINT8 mfdr_bits; |
| 527 | |
| 528 | int i = 0; |
| 529 | int j = 0; |
| 530 | |
| 531 | int Diff, min; |
| 532 | int WhichFreq, iRec, jRec; |
| 533 | int SCL_Period; |
| 534 | int SCL_Hold; |
| 535 | int I2C_Freq; |
| 536 | |
| 537 | I2CCDBG (L2, ("Entering getBitRate: bitrate %d pi2cRegs 0x%08x\n", |
| 538 | bitrate, (int) pi2cRegs, 0, 0, 0, 0)); |
| 539 | |
| 540 | if (bitrate < 0) { |
| 541 | I2CCDBG (NO, ("Invalid bitrate\n", 0, 0, 0, 0, 0, 0)); |
| 542 | return ERROR; |
| 543 | } |
| 544 | |
| 545 | /* Initialize */ |
| 546 | mfdr_bits = 0; |
| 547 | min = 0x7fffffff; |
| 548 | WhichFreq = iRec = jRec = 0; |
| 549 | |
| 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 |
| 555 | */ |
| 556 | SCL_Period = |
| 557 | 2 * (scl_tap[i][0] + |
| 558 | ((div_hold[j][0] - 1) * scl_tap[i][1]) + |
| 559 | 2); |
| 560 | |
| 561 | /* Now get the I2C Freq */ |
| 562 | I2C_Freq = DEV_CLOCK_FREQ / SCL_Period; |
| 563 | |
| 564 | /* Take equal or slower */ |
| 565 | if (I2C_Freq > bitrate) |
| 566 | continue; |
| 567 | |
| 568 | /* Take the differences */ |
| 569 | Diff = I2C_Freq - bitrate; |
| 570 | |
| 571 | Diff = ABS (Diff); |
| 572 | |
| 573 | /* Find the closer value */ |
| 574 | if (Diff < min) { |
| 575 | min = Diff; |
| 576 | WhichFreq = I2C_Freq; |
| 577 | iRec = i; |
| 578 | jRec = j; |
| 579 | } |
| 580 | |
| 581 | I2CCDBG (L2, |
| 582 | ("--- (%d,%d) I2C_Freq %d minDiff %d min %d\n", |
| 583 | i, j, I2C_Freq, Diff, min, 0)); |
| 584 | } |
| 585 | } |
| 586 | |
| 587 | SCL_Period = |
| 588 | 2 * (scl_tap[iRec][0] + |
| 589 | ((div_hold[jRec][0] - 1) * scl_tap[iRec][1]) + 2); |
| 590 | |
| 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], |
| 595 | 0, 0, 0)); |
| 596 | |
| 597 | /* This may no require */ |
| 598 | SCL_Hold = |
| 599 | scl_tap[iRec][0] + |
| 600 | ((div_hold[jRec][1] - 1) * scl_tap[iRec][1]) + 3; |
| 601 | I2CCDBG (L2, |
| 602 | ("--- SCL_Period %d SCL_Hold %d\n", SCL_Period, SCL_Hold, 0, |
| 603 | 0, 0, 0)); |
| 604 | |
| 605 | I2CCDBG (L2, ("--- mfdr_bits %x\n", mfdr_bits, 0, 0, 0, 0, 0)); |
| 606 | |
| 607 | /* FDR 4,3,2 */ |
| 608 | if ((iRec & 1) == 1) |
| 609 | mfdr_bits |= 0x04; /* FDR 2 */ |
| 610 | if ((iRec & 2) == 2) |
| 611 | mfdr_bits |= 0x08; /* FDR 3 */ |
| 612 | if ((iRec & 4) == 4) |
| 613 | mfdr_bits |= 0x10; /* FDR 4 */ |
| 614 | /* FDR 5,1,0 */ |
| 615 | if ((jRec & 1) == 1) |
| 616 | mfdr_bits |= 0x01; /* FDR 0 */ |
| 617 | if ((jRec & 2) == 2) |
| 618 | mfdr_bits |= 0x02; /* FDR 1 */ |
| 619 | if ((jRec & 4) == 4) |
| 620 | mfdr_bits |= 0x20; /* FDR 5 */ |
| 621 | |
| 622 | I2CCDBG (L2, ("--- mfdr_bits %x\n", mfdr_bits, 0, 0, 0, 0, 0)); |
| 623 | |
| 624 | pi2cRegs->fdr = mfdr_bits; |
| 625 | |
| 626 | return OK; |
| 627 | } |