File indexing completed on 2025-05-11 08:23:53
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034 #include <stdlib.h>
0035 #include <bsp.h>
0036 #include <bsp/irq.h>
0037 #include <mpc83xx/mpc83xx_i2cdrv.h>
0038 #include <rtems/error.h>
0039 #include <rtems/bspIo.h>
0040 #include <errno.h>
0041 #include <rtems/libi2c.h>
0042
0043 #undef DEBUG
0044
0045 #if defined(LIBBSP_POWERPC_GEN83XX_BSP_H)
0046 #define I2CCR_MEN (1 << 7)
0047 #elif defined(LIBBSP_POWERPC_MPC55XXEVB_BSP_H)
0048 #define I2CCR_MDIS (1 << 7)
0049 #endif
0050 #define I2CCR_MIEN (1 << 6)
0051 #define I2CCR_MSTA (1 << 5)
0052 #define I2CCR_MTX (1 << 4)
0053 #define I2CCR_TXAK (1 << 3)
0054 #define I2CCR_RSTA (1 << 2)
0055 #define I2CCR_BCST (1 << 0)
0056
0057 #define I2CSR_MCF (1 << 7)
0058 #define I2CSR_MAAS (1 << 6)
0059 #define I2CSR_MBB (1 << 5)
0060 #define I2CSR_MAL (1 << 4)
0061 #define I2CSR_BCSTM (1 << 3)
0062 #define I2CSR_SRW (1 << 2)
0063 #define I2CSR_MIF (1 << 1)
0064 #define I2CSR_RXAK (1 << 0)
0065
0066
0067
0068
0069 static rtems_status_code mpc83xx_i2c_find_clock_divider
0070 (
0071
0072
0073
0074
0075
0076
0077 uint8_t *result,
0078 int divider
0079 )
0080
0081
0082
0083
0084 {
0085 int i;
0086 int fdr_val;
0087 rtems_status_code sc = RTEMS_SUCCESSFUL;
0088 struct {
0089 int divider;
0090 int fdr_val;
0091 } dividers[] ={
0092 #if defined(LIBBSP_POWERPC_GEN83XX_BSP_H)
0093 { 256,0x20 }, { 288,0x21 }, { 320,0x22 }, { 352,0x23 },
0094 { 384,0x00 }, { 416,0x01 }, { 448,0x25 }, { 480,0x02 },
0095 { 512,0x26 }, { 576,0x03 }, { 640,0x04 }, { 704,0x05 },
0096 { 768,0x29 }, { 832,0x06 }, { 896,0x2a }, { 1024,0x07 },
0097 { 1152,0x08 }, { 1280,0x09 }, { 1536,0x0A }, { 1792,0x2E },
0098 { 1920,0x0B }, { 2048,0x2F }, { 2304,0x0C }, { 2560,0x0D },
0099 { 3072,0x0E }, { 3584,0x32 }, { 3840,0x0F }, { 4096,0x33 },
0100 { 4608,0x10 }, { 5120,0x11 }, { 6144,0x12 }, { 7168,0x36 },
0101 { 7680,0x13 }, { 8192,0x37 }, { 9216,0x14 }, {10240,0x15 },
0102 {12288,0x16 }, {14336,0x3A }, {15360,0x17 }, {16384,0x3B },
0103 {18432,0x18 }, {20480,0x19 }, {24576,0x1A }, {28672,0x3E },
0104 {30720,0x1B }, {32768,0x3F }, {36864,0x1C }, {40960,0x1D },
0105 {49152,0x1E }, {61440,0x1F }
0106 #elif defined(LIBBSP_POWERPC_MPC55XXEVB_BSP_H)
0107 { 768, 0x31 }
0108 #endif
0109 };
0110
0111 if (divider <= 0) {
0112 sc = RTEMS_INVALID_NUMBER;
0113 }
0114
0115 if (sc == RTEMS_SUCCESSFUL) {
0116 sc = RTEMS_INVALID_NUMBER;
0117 for (i = 0, fdr_val = -1; i < sizeof(dividers)/sizeof(dividers[0]); i++) {
0118 fdr_val = dividers[i].fdr_val;
0119 if (dividers[i].divider >= divider)
0120 {
0121 sc = RTEMS_SUCCESSFUL;
0122 *result = fdr_val;
0123 break;
0124 }
0125 }
0126 }
0127 return sc;
0128 }
0129
0130
0131
0132
0133 static int mpc83xx_i2c_wait
0134 (
0135
0136
0137
0138
0139
0140
0141 mpc83xx_i2c_softc_t *softc_ptr,
0142 uint8_t desired_status,
0143 uint8_t status_mask
0144 )
0145
0146
0147
0148
0149 {
0150 uint8_t act_status;
0151 rtems_status_code rc;
0152 uint32_t tout;
0153
0154 #if defined(DEBUG)
0155 printk("mpc83xx_i2c_wait called... ");
0156 #endif
0157
0158 if (softc_ptr->initialized) {
0159
0160
0161
0162 softc_ptr->reg_ptr->i2ccr |= I2CCR_MIEN;
0163 rc = rtems_semaphore_obtain(softc_ptr->irq_sema_id,RTEMS_WAIT,100);
0164 if (rc != RTEMS_SUCCESSFUL) {
0165 return rc;
0166 }
0167 }
0168 else {
0169 tout = 0;
0170 do {
0171 if (tout++ > 1000000) {
0172 #if defined(DEBUG)
0173 printk("... exit with RTEMS_TIMEOUT\r\n");
0174 #endif
0175 return RTEMS_TIMEOUT;
0176 }
0177 } while (!(softc_ptr->reg_ptr->i2csr & I2CSR_MIF));
0178 }
0179 softc_ptr->reg_ptr->i2ccr &= ~I2CCR_MIEN;
0180
0181 act_status = softc_ptr->reg_ptr->i2csr;
0182 if ((act_status & status_mask) != desired_status) {
0183 #if defined(DEBUG)
0184 printk("... exit with RTEMS_IO_ERROR\r\n");
0185 #endif
0186 return RTEMS_IO_ERROR;
0187 }
0188 #if defined(DEBUG)
0189 printk("... exit OK\r\n");
0190 #endif
0191 return RTEMS_SUCCESSFUL;
0192 }
0193
0194
0195
0196
0197 static void mpc83xx_i2c_irq_handler
0198 (
0199
0200
0201
0202
0203
0204
0205 rtems_irq_hdl_param handle
0206 )
0207
0208
0209
0210
0211 {
0212 mpc83xx_i2c_softc_t *softc_ptr = (mpc83xx_i2c_softc_t *)handle;
0213
0214
0215
0216
0217 #if defined(LIBBSP_POWERPC_GEN83XX_BSP_H)
0218 softc_ptr->reg_ptr->i2csr &= ~I2CSR_MIF;
0219 #elif defined(LIBBSP_POWERPC_MPC55XXEVB_BSP_H)
0220 softc_ptr->reg_ptr->i2csr = I2CSR_MIF;
0221 #endif
0222
0223
0224
0225
0226 softc_ptr->reg_ptr->i2ccr &= ~I2CCR_MIEN;
0227 if (softc_ptr->initialized) {
0228 rtems_semaphore_release(softc_ptr->irq_sema_id);
0229 }
0230 }
0231
0232
0233
0234
0235 static void mpc83xx_i2c_irq_on_off
0236 (
0237
0238
0239
0240
0241
0242
0243 const
0244 rtems_irq_connect_data *irq_conn_data
0245 )
0246
0247
0248
0249
0250 {
0251 }
0252
0253
0254
0255
0256
0257 static int mpc83xx_i2c_irq_isOn
0258 (
0259
0260
0261
0262
0263
0264
0265 const
0266 rtems_irq_connect_data *irq_conn_data
0267 )
0268
0269
0270
0271
0272 {
0273 return (TRUE);
0274 }
0275
0276
0277
0278
0279 static void mpc83xx_i2c_install_irq_handler
0280 (
0281
0282
0283
0284
0285
0286
0287 mpc83xx_i2c_softc_t *softc_ptr,
0288 int install
0289 )
0290
0291
0292
0293
0294 {
0295 rtems_status_code rc = RTEMS_SUCCESSFUL;
0296
0297 rtems_irq_connect_data irq_conn_data = {
0298 softc_ptr->irq_number,
0299 mpc83xx_i2c_irq_handler,
0300 (rtems_irq_hdl_param)softc_ptr,
0301 mpc83xx_i2c_irq_on_off,
0302 mpc83xx_i2c_irq_on_off,
0303 mpc83xx_i2c_irq_isOn
0304 };
0305
0306
0307
0308
0309 if (install) {
0310
0311
0312
0313 rc = rtems_semaphore_create(rtems_build_name('i','2','c','s'),
0314 0,
0315 RTEMS_FIFO
0316 | RTEMS_SIMPLE_BINARY_SEMAPHORE,
0317 0,
0318 &softc_ptr->irq_sema_id);
0319 if (rc != RTEMS_SUCCESSFUL) {
0320 rtems_panic("I2C: cannot create semaphore");
0321 }
0322 if (!BSP_install_rtems_irq_handler (&irq_conn_data)) {
0323 rtems_panic("I2C: cannot install IRQ handler");
0324 }
0325 }
0326 else {
0327 if (!BSP_remove_rtems_irq_handler (&irq_conn_data)) {
0328 rtems_panic("I2C: cannot uninstall IRQ handler");
0329 }
0330
0331
0332
0333 if (softc_ptr->irq_sema_id != 0) {
0334 rc = rtems_semaphore_delete(softc_ptr->irq_sema_id);
0335 if (rc != RTEMS_SUCCESSFUL) {
0336 rtems_panic("I2C: cannot delete semaphore");
0337 }
0338 }
0339 }
0340 }
0341
0342
0343
0344
0345 static rtems_status_code mpc83xx_i2c_init
0346 (
0347
0348
0349
0350
0351
0352
0353 rtems_libi2c_bus_t *bh
0354 )
0355
0356
0357
0358
0359 {
0360 mpc83xx_i2c_softc_t *softc_ptr = &(((mpc83xx_i2c_desc_t *)(bh))->softc);
0361 uint8_t fdr_val;
0362 int errval;
0363 #if defined(DEBUG)
0364 printk("mpc83xx_i2c_init called... ");
0365 #endif
0366
0367
0368
0369
0370
0371
0372 errval = mpc83xx_i2c_find_clock_divider(&fdr_val,
0373 softc_ptr->base_frq/100000);
0374 if (errval != 0) {
0375 return errval;
0376 }
0377 softc_ptr->reg_ptr->i2cfdr = fdr_val;
0378
0379
0380
0381 softc_ptr->reg_ptr->i2cdfsrr = 0x10 ;
0382
0383
0384
0385 softc_ptr->reg_ptr->i2cadr = 0x00 ;
0386
0387
0388
0389
0390 #if defined(LIBBSP_POWERPC_GEN83XX_BSP_H)
0391 softc_ptr->reg_ptr->i2ccr = I2CCR_MEN;
0392 #elif defined(LIBBSP_POWERPC_MPC55XXEVB_BSP_H)
0393 softc_ptr->reg_ptr->i2ccr = 0;
0394 #endif
0395
0396
0397
0398
0399 mpc83xx_i2c_install_irq_handler(softc_ptr,TRUE);
0400
0401
0402
0403
0404 softc_ptr->initialized = TRUE;
0405 #if defined(DEBUG)
0406 printk("... exit OK\r\n");
0407 #endif
0408 return RTEMS_SUCCESSFUL;
0409 }
0410
0411
0412
0413
0414 static rtems_status_code mpc83xx_i2c_send_start
0415 (
0416
0417
0418
0419
0420
0421
0422 rtems_libi2c_bus_t *bh
0423 )
0424
0425
0426
0427
0428 {
0429 mpc83xx_i2c_softc_t *softc_ptr = &(((mpc83xx_i2c_desc_t *)(bh))->softc);
0430
0431 #if defined(DEBUG)
0432 printk("mpc83xx_i2c_send_start called... ");
0433 #endif
0434 if (0 != (softc_ptr->reg_ptr->i2ccr & I2CCR_MSTA)) {
0435
0436
0437
0438 softc_ptr->reg_ptr->i2ccr |= I2CCR_RSTA;
0439 }
0440 else {
0441 softc_ptr->reg_ptr->i2ccr |= I2CCR_MSTA;
0442 }
0443
0444 #if defined(DEBUG)
0445 printk("... exit OK\r\n");
0446 #endif
0447 return 0;
0448 }
0449
0450
0451
0452
0453 static rtems_status_code mpc83xx_i2c_send_stop
0454 (
0455
0456
0457
0458
0459
0460
0461 rtems_libi2c_bus_t *bh
0462 )
0463
0464
0465
0466
0467 {
0468 mpc83xx_i2c_softc_t *softc_ptr = &(((mpc83xx_i2c_desc_t *)(bh))->softc);
0469
0470 #if defined(DEBUG)
0471 printk("mpc83xx_i2c_send_stop called... ");
0472 #endif
0473 softc_ptr->reg_ptr->i2ccr &= ~I2CCR_MSTA;
0474
0475
0476
0477 while (0 != (softc_ptr->reg_ptr->i2csr & I2CSR_MBB)) {
0478 rtems_task_wake_after(RTEMS_YIELD_PROCESSOR);
0479 }
0480 #if defined(DEBUG)
0481 printk("... exit OK\r\n");
0482 #endif
0483 return 0;
0484 }
0485
0486
0487
0488
0489 static rtems_status_code mpc83xx_i2c_send_addr
0490 (
0491
0492
0493
0494
0495
0496
0497 rtems_libi2c_bus_t *bh,
0498 uint32_t addr,
0499 int rw
0500 )
0501
0502
0503
0504
0505 {
0506 mpc83xx_i2c_softc_t *softc_ptr = &(((mpc83xx_i2c_desc_t *)(bh))->softc);
0507 uint8_t addr_byte;
0508 rtems_status_code rc;
0509
0510 #if defined(DEBUG)
0511 printk("mpc83xx_i2c_send_addr called... ");
0512 #endif
0513 softc_ptr->reg_ptr->i2ccr |= I2CCR_MTX;
0514
0515
0516
0517 if (addr > 0x7f) {
0518 addr_byte = (0xf0
0519 | ((addr >> 7) & 0x06)
0520 | ((rw) ? 1 : 0));
0521
0522
0523
0524 softc_ptr->reg_ptr->i2cdr = addr_byte;
0525
0526
0527
0528 rc = mpc83xx_i2c_wait(softc_ptr, I2CSR_MCF, I2CSR_MCF | I2CSR_RXAK);
0529 if (rc != RTEMS_SUCCESSFUL) {
0530 #if defined(DEBUG)
0531 printk("... exit rc=%d\r\n",rc);
0532 #endif
0533 return rc;
0534 }
0535 }
0536
0537
0538
0539 addr_byte = ((addr << 1)
0540 | ((rw) ? 1 : 0));
0541
0542 softc_ptr->reg_ptr->i2cdr = addr_byte;
0543
0544
0545
0546 rc = mpc83xx_i2c_wait(softc_ptr, I2CSR_MCF, I2CSR_MCF | I2CSR_RXAK);
0547
0548 #if defined(DEBUG)
0549 printk("... exit rc=%d\r\n",rc);
0550 #endif
0551 return rc;
0552 }
0553
0554
0555
0556
0557 static int mpc83xx_i2c_read_bytes
0558 (
0559
0560
0561
0562
0563
0564
0565 rtems_libi2c_bus_t *bh,
0566 unsigned char *buf,
0567 int len
0568 )
0569
0570
0571
0572
0573 {
0574 mpc83xx_i2c_softc_t *softc_ptr = &(((mpc83xx_i2c_desc_t *)(bh))->softc);
0575 rtems_status_code rc;
0576 unsigned char *p = buf;
0577
0578 #if defined(DEBUG)
0579 printk("mpc83xx_i2c_read_bytes called... ");
0580 #endif
0581 softc_ptr->reg_ptr->i2ccr &= ~I2CCR_MTX;
0582 softc_ptr->reg_ptr->i2ccr &= ~I2CCR_TXAK;
0583
0584
0585
0586
0587
0588
0589
0590 softc_ptr->reg_ptr->i2cdr;
0591
0592 while (len-- > 0) {
0593 if (len == 0) {
0594
0595
0596
0597 softc_ptr->reg_ptr->i2ccr |= I2CCR_TXAK;
0598 }
0599
0600
0601
0602 rc = mpc83xx_i2c_wait(softc_ptr, I2CSR_MCF, I2CSR_MCF);
0603 if (rc != RTEMS_SUCCESSFUL) {
0604 #if defined(DEBUG)
0605 printk("... exit rc=%d\r\n",-rc);
0606 #endif
0607 return -rc;
0608 }
0609 *p++ = softc_ptr->reg_ptr->i2cdr;
0610
0611 }
0612
0613
0614
0615
0616 rc = mpc83xx_i2c_wait(softc_ptr, I2CSR_MCF, I2CSR_MCF);
0617
0618 #if defined(DEBUG)
0619 printk("... exit OK, rc=%d\r\n",p-buf);
0620 #endif
0621 return p - buf;
0622 }
0623
0624
0625
0626
0627 static int mpc83xx_i2c_write_bytes
0628 (
0629
0630
0631
0632
0633
0634
0635 rtems_libi2c_bus_t *bh,
0636 unsigned char *buf,
0637 int len
0638
0639 )
0640
0641
0642
0643
0644 {
0645 mpc83xx_i2c_softc_t *softc_ptr = &(((mpc83xx_i2c_desc_t *)(bh))->softc);
0646 rtems_status_code rc;
0647 unsigned char *p = buf;
0648
0649 #if defined(DEBUG)
0650 printk("mpc83xx_i2c_write_bytes called... ");
0651 #endif
0652 softc_ptr->reg_ptr->i2ccr =
0653 (softc_ptr->reg_ptr->i2ccr & ~I2CCR_TXAK) | I2CCR_MTX;
0654 while (len-- > 0) {
0655 int rxack = len != 0 ? I2CSR_RXAK : 0;
0656
0657 softc_ptr->reg_ptr->i2cdr = *p++;
0658
0659
0660
0661 rc = mpc83xx_i2c_wait(softc_ptr, I2CSR_MCF, I2CSR_MCF | rxack);
0662 if (rc != RTEMS_SUCCESSFUL) {
0663 #if defined(DEBUG)
0664 printk("... exit rc=%d\r\n",-rc);
0665 #endif
0666 return -rc;
0667 }
0668 }
0669 #if defined(DEBUG)
0670 printk("... exit OK, rc=%d\r\n",p-buf);
0671 #endif
0672 return p - buf;
0673 }
0674
0675 rtems_libi2c_bus_ops_t mpc83xx_i2c_ops = {
0676 .init = mpc83xx_i2c_init,
0677 .send_start = mpc83xx_i2c_send_start,
0678 .send_stop = mpc83xx_i2c_send_stop,
0679 .send_addr = mpc83xx_i2c_send_addr,
0680 .read_bytes = mpc83xx_i2c_read_bytes,
0681 .write_bytes = mpc83xx_i2c_write_bytes,
0682 };
0683