File indexing completed on 2025-05-11 08:23:52
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020 #include "../i2c/mpc5200mbus.h"
0021 #include <bsp/mpc5200.h>
0022 #include <bsp/irq.h>
0023 #include <bsp/i2c.h>
0024
0025
0026 typedef enum i2c_event {
0027 EVENT_NONE,
0028 EVENT_TRANSFER,
0029 EVENT_NEXTMSG,
0030 EVENT_ACK,
0031 EVENT_NACK,
0032 EVENT_TIMEOUT,
0033 EVENT_DATA_RECV,
0034 EVENT_ARB_LOST,
0035 EVENT_SLAVE
0036 } i2c_event;
0037
0038
0039
0040
0041 #define next_state(bus,new_state) \
0042 do { \
0043 (bus)->state = (new_state); \
0044 } while (0)
0045
0046
0047 #define mpc5200mbus_start(bus) \
0048 do { \
0049 mpc5200.i2c_regs[bus->bus_idx].mcr |= MPC5200_I2C_MCR_MSTA; \
0050 } while (0)
0051
0052
0053 #define mpc5200mbus_stop(bus) \
0054 do { \
0055 mpc5200.i2c_regs[bus->bus_idx].mcr &= ~MPC5200_I2C_MCR_MSTA; \
0056 } while (0)
0057
0058
0059 #define mpc5200mbus_rstart(bus) \
0060 do { \
0061 mpc5200.i2c_regs[bus->bus_idx].mcr |= MPC5200_I2C_MCR_RSTA; \
0062 } while (0)
0063
0064
0065 #define mpc5200mbus_send(bus,byte) \
0066 do { \
0067 mpc5200.i2c_regs[bus->bus_idx].mdr = (byte); \
0068 } while (0)
0069
0070
0071 #define mpc5200mbus_tx_mode(bus) \
0072 do { \
0073 mpc5200.i2c_regs[bus->bus_idx].mcr |= MPC5200_I2C_MCR_MTX; \
0074 } while (0)
0075
0076
0077 #define mpc5200mbus_rx_mode(bus) \
0078 do { \
0079 mpc5200.i2c_regs[bus->bus_idx].mcr &= ~MPC5200_I2C_MCR_MTX; \
0080 (void)mpc5200.i2c_regs[bus->bus_idx].mdr; \
0081 } while (0)
0082
0083
0084
0085 #define mpc5200mbus_send_ack(bus) \
0086 do { \
0087 mpc5200.i2c_regs[bus->bus_idx].mcr &= ~MPC5200_I2C_MCR_TXAK; \
0088 } while (0)
0089
0090
0091 #define mpc5200mbus_send_nack(bus) \
0092 do { \
0093 mpc5200.i2c_regs[bus->bus_idx].mcr |= MPC5200_I2C_MCR_TXAK; \
0094 } while (0)
0095
0096 #define mpc5200mbus_error(bus,err_status) \
0097 do { \
0098 do { \
0099 (bus)->cmsg->status = (err_status); \
0100 (bus)->cmsg++; \
0101 } while (((bus)->cmsg - (bus)->msg < (bus)->nmsg) && \
0102 ((bus)->cmsg->flags & I2C_MSG_ERRSKIP)); \
0103 bus->cmsg--; \
0104 } while (0)
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116 static i2c_event
0117 mpc5200mbus_get_event(mpc5200mbus *bus)
0118 {
0119 i2c_event event;
0120 uint8_t status, control;
0121 rtems_interrupt_level level;
0122 rtems_interrupt_disable(level);
0123 status = mpc5200.i2c_regs[bus->bus_idx].msr;
0124 control = mpc5200.i2c_regs[bus->bus_idx].mcr;
0125 if (status & MPC5200_I2C_MSR_MIF)
0126 {
0127 if (status & MPC5200_I2C_MSR_MAAS)
0128 {
0129 event = EVENT_SLAVE;
0130 mpc5200.i2c_regs[bus->bus_idx].mcr = control;
0131
0132 }
0133 else if (status & MPC5200_I2C_MSR_MAL)
0134 {
0135 mpc5200.i2c_regs[bus->bus_idx].msr = status & ~MPC5200_I2C_MSR_MAL;
0136 event = EVENT_ARB_LOST;
0137 }
0138 else if (control & MPC5200_I2C_MCR_MTX)
0139 {
0140 if (status & MPC5200_I2C_MSR_RXAK)
0141 event = EVENT_NACK;
0142 else
0143 event = EVENT_ACK;
0144 }
0145 else
0146 {
0147 event = EVENT_DATA_RECV;
0148 }
0149
0150
0151 mpc5200.i2c_regs[bus->bus_idx].msr &= ~MPC5200_I2C_MSR_MIF;
0152 }
0153 else
0154 {
0155 event = EVENT_NONE;
0156 }
0157 rtems_interrupt_enable(level);
0158 return event;
0159 }
0160
0161 static void
0162 mpc5200mbus_machine_error(mpc5200mbus *bus, i2c_event event)
0163 {
0164 return;
0165 }
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175
0176
0177 static void
0178 mpc5200mbus_machine(mpc5200mbus *bus, i2c_event event)
0179 {
0180 uint8_t b;
0181 switch (bus->state)
0182 {
0183
0184 case STATE_UNINITIALIZED:
0185
0186 mpc5200mbus_machine_error(bus, event);
0187 break;
0188 case STATE_IDLE:
0189 switch (event)
0190 {
0191 case EVENT_NEXTMSG:
0192 bus->cmsg++;
0193
0194
0195 case EVENT_TRANSFER:
0196 if (bus->cmsg - bus->msg >= bus->nmsg)
0197 {
0198 mpc5200mbus_stop(bus);
0199 next_state(bus, STATE_IDLE);
0200 bus->msg = bus->cmsg = NULL;
0201 bus->nmsg = bus->byte = 0;
0202 bus->done(bus->done_arg_ptr);
0203 break;
0204 }
0205
0206
0207 if (event == EVENT_TRANSFER)
0208 {
0209 mpc5200mbus_start(bus);
0210 }
0211 else
0212 {
0213 mpc5200mbus_rstart(bus);
0214 }
0215
0216 bus->byte = 0;
0217 mpc5200mbus_tx_mode(bus);
0218
0219
0220 if (bus->cmsg->flags & I2C_MSG_ADDR_10)
0221 {
0222 i2c_address a = bus->cmsg->addr;
0223 b = 0xf0 | (((a >> 8) & 0x03) << 1);
0224 if (bus->cmsg->flags & I2C_MSG_WR)
0225 {
0226 mpc5200mbus_send(bus, b);
0227 next_state(bus, STATE_ADDR_1_W);
0228 }
0229 else
0230 {
0231 mpc5200mbus_send(bus, b | 1);
0232 next_state(bus, STATE_ADDR_1_R);
0233 }
0234 }
0235 else
0236 {
0237 b = (bus->cmsg->addr & ~0x01);
0238
0239 if (bus->cmsg->flags & I2C_MSG_WR)
0240 {
0241 next_state(bus, STATE_SENDING);
0242 }
0243 else
0244 {
0245 next_state(bus, STATE_ADDR_7);
0246 b |= 1;
0247 }
0248
0249 mpc5200mbus_send(bus, b);
0250 }
0251 break;
0252
0253 default:
0254 mpc5200mbus_machine_error(bus, event);
0255 break;
0256 }
0257 break;
0258
0259 case STATE_ADDR_7:
0260 switch (event)
0261 {
0262 case EVENT_ACK:
0263 mpc5200mbus_rx_mode(bus);
0264 if (bus->cmsg->len <= 1)
0265 mpc5200mbus_send_nack(bus);
0266 else
0267 mpc5200mbus_send_ack(bus);
0268 next_state(bus, STATE_RECEIVING);
0269 break;
0270
0271 case EVENT_NACK:
0272 mpc5200mbus_error(bus, I2C_NO_DEVICE);
0273 next_state(bus, STATE_IDLE);
0274 mpc5200mbus_machine(bus, EVENT_NEXTMSG);
0275 break;
0276
0277 case EVENT_ARB_LOST:
0278 mpc5200mbus_error(bus, I2C_ARBITRATION_LOST);
0279 next_state(bus, STATE_IDLE);
0280 mpc5200mbus_machine(bus, EVENT_NEXTMSG);
0281 break;
0282
0283 default:
0284 mpc5200mbus_machine_error(bus, event);
0285 break;
0286 }
0287 break;
0288
0289 case STATE_ADDR_1_R:
0290 case STATE_ADDR_1_W:
0291 switch (event)
0292 {
0293 case EVENT_ACK:
0294 {
0295 uint8_t b = (bus->cmsg->addr & 0xff);
0296 mpc5200mbus_send(bus, b);
0297 if (bus->state == STATE_ADDR_1_W)
0298 {
0299 next_state(bus, STATE_SENDING);
0300 }
0301 else
0302 {
0303 i2c_address a;
0304 mpc5200mbus_rstart(bus);
0305 mpc5200mbus_tx_mode(bus);
0306 a = bus->cmsg->addr;
0307 b = 0xf0 | (((a >> 8) & 0x03) << 1) | 1;
0308 mpc5200mbus_send(bus, b);
0309 next_state(bus, STATE_ADDR_7);
0310 }
0311 break;
0312 }
0313
0314 case EVENT_NACK:
0315 mpc5200mbus_error(bus, I2C_NO_DEVICE);
0316 next_state(bus, STATE_IDLE);
0317 mpc5200mbus_machine(bus, EVENT_NEXTMSG);
0318 break;
0319
0320 case EVENT_ARB_LOST:
0321 mpc5200mbus_error(bus, I2C_ARBITRATION_LOST);
0322 next_state(bus, STATE_IDLE);
0323 mpc5200mbus_machine(bus, EVENT_NEXTMSG);
0324 break;
0325
0326 default:
0327 mpc5200mbus_machine_error(bus, event);
0328 break;
0329 }
0330 break;
0331
0332 case STATE_SENDING:
0333 switch (event)
0334 {
0335 case EVENT_ACK:
0336 if (bus->byte == bus->cmsg->len)
0337 {
0338 next_state(bus, STATE_IDLE);
0339 mpc5200mbus_machine(bus, EVENT_NEXTMSG);
0340 }
0341 else
0342 {
0343 mpc5200mbus_send(bus, bus->cmsg->buf[bus->byte++]);
0344 next_state(bus, STATE_SENDING);
0345 }
0346 break;
0347
0348 case EVENT_NACK:
0349 if (bus->byte == 0)
0350 {
0351 mpc5200mbus_error(bus, I2C_NO_DEVICE);
0352 }
0353 else
0354 {
0355 mpc5200mbus_error(bus, I2C_NO_ACKNOWLEDGE);
0356 }
0357 next_state(bus, STATE_IDLE);
0358 mpc5200mbus_machine(bus, EVENT_NEXTMSG);
0359 break;
0360
0361 case EVENT_ARB_LOST:
0362 mpc5200mbus_error(bus, I2C_ARBITRATION_LOST);
0363 next_state(bus, STATE_IDLE);
0364 mpc5200mbus_machine(bus, EVENT_NEXTMSG);
0365 break;
0366
0367 default:
0368 mpc5200mbus_machine_error(bus, event);
0369 break;
0370
0371 }
0372 break;
0373
0374 case STATE_RECEIVING:
0375 switch (event)
0376 {
0377 case EVENT_DATA_RECV:
0378 if (bus->cmsg->len - bus->byte <= 2)
0379 {
0380 mpc5200mbus_send_nack(bus);
0381 if (bus->cmsg->len - bus->byte <= 1)
0382 {
0383 if (bus->cmsg - bus->msg + 1 == bus->nmsg)
0384 mpc5200mbus_stop(bus);
0385 else
0386 mpc5200mbus_rstart(bus);
0387 }
0388 }
0389 else
0390 {
0391 mpc5200mbus_send_ack(bus);
0392 }
0393 bus->cmsg->buf[bus->byte++] = mpc5200.i2c_regs[bus->bus_idx].mdr;
0394 if (bus->cmsg->len == bus->byte)
0395 {
0396 next_state(bus,STATE_IDLE);
0397 mpc5200mbus_machine(bus, EVENT_NEXTMSG);
0398 }
0399 else
0400 {
0401 next_state(bus,STATE_RECEIVING);
0402 }
0403 break;
0404
0405 case EVENT_ARB_LOST:
0406 mpc5200mbus_error(bus, I2C_ARBITRATION_LOST);
0407 next_state(bus, STATE_IDLE);
0408 mpc5200mbus_machine(bus, EVENT_NEXTMSG);
0409 break;
0410
0411 default:
0412 mpc5200mbus_machine_error(bus, event);
0413 break;
0414 }
0415 break;
0416 }
0417 }
0418
0419
0420
0421
0422
0423
0424
0425
0426
0427
0428 static void mpc5200mbus_interrupt_handler(rtems_irq_hdl_param handle)
0429 {
0430 i2c_event event;
0431 mpc5200mbus *bus = handle;
0432
0433 event = mpc5200mbus_get_event(bus);
0434
0435
0436
0437 mpc5200.i2c_regs[bus->bus_idx].msr &= ~MPC5200_I2C_MSR_MIF;
0438
0439 mpc5200mbus_machine(bus, event);
0440 }
0441
0442
0443
0444
0445
0446 static void mpc5200mbus_irq_enable(const rtems_irq_connect_data* ptr)
0447 {
0448 int minor = ((mpc5200mbus*)(ptr->handle))->bus_idx;
0449
0450 mpc5200.i2c_regs[minor].mcr |= MPC5200_I2C_MCR_MIEN;
0451 }
0452
0453
0454
0455
0456
0457 static void mpc5200mbus_irq_disable(const rtems_irq_connect_data* ptr)
0458 {
0459 int minor = ((mpc5200mbus*)(ptr->handle))->bus_idx;
0460
0461 mpc5200.i2c_regs[minor].mcr &= ~MPC5200_I2C_MCR_MIEN;
0462 }
0463
0464
0465
0466
0467
0468 static int mpc5200mbus_irq_isOn(const rtems_irq_connect_data* ptr)
0469 {
0470 int minor = ((mpc5200mbus*)(ptr->handle))->bus_idx;
0471
0472 return (0 != (mpc5200.i2c_regs[minor].mcr & MPC5200_I2C_MCR_MIEN));
0473 }
0474
0475
0476
0477
0478
0479
0480
0481
0482
0483
0484
0485 void
0486 mpc5200mbus_poll(mpc5200mbus *bus)
0487 {
0488 i2c_event event;
0489 event = mpc5200mbus_get_event(bus);
0490 if (event != EVENT_NONE)
0491 mpc5200mbus_machine(bus, event);
0492 }
0493
0494
0495
0496
0497
0498
0499
0500
0501
0502
0503
0504
0505
0506 rtems_status_code
0507 mpc5200mbus_select_clock_divider(mpc5200mbus *bus, int divider)
0508 {
0509 int i;
0510 int mbc;
0511 struct {
0512 int divider;
0513 int mbc;
0514 } dividers[] ={
0515 { 20, 0x20 }, { 22, 0x21 }, { 24, 0x22 }, { 26, 0x23 },
0516 { 28, 0x00 }, { 30, 0x01 }, { 32, 0x25 }, { 34, 0x02 },
0517 { 36, 0x26 }, { 40, 0x03 }, { 44, 0x04 }, { 48, 0x05 },
0518 { 56, 0x06 }, { 64, 0x2a }, { 68, 0x07 }, { 72, 0x2B },
0519 { 80, 0x08 }, { 88, 0x09 }, { 96, 0x2D }, { 104, 0x0A },
0520 { 112, 0x2E }, { 128, 0x0B }, { 144, 0x0C }, { 160, 0x0D },
0521 { 192, 0x0E }, { 224, 0x32 }, { 240, 0x0F }, { 256, 0x33 },
0522 { 288, 0x10 }, { 320, 0x11 }, { 384, 0x12 }, { 448, 0x36 },
0523 { 480, 0x13 }, { 512, 0x37 }, { 576, 0x14 }, { 640, 0x15 },
0524 { 768, 0x16 }, { 896, 0x3A }, { 960, 0x17 }, { 1024, 0x3B },
0525 { 1152, 0x18 }, { 1280, 0x19 }, { 1536, 0x1A }, { 1792, 0x3E },
0526 { 1920, 0x1B }, { 2048, 0x3F }, { 2304, 0x1C }, { 2560, 0x1D },
0527 { 3072, 0x1E }, { 3840, 0x1F }
0528 };
0529
0530 if (bus == NULL)
0531 return RTEMS_INVALID_ADDRESS;
0532
0533 for (i = 0, mbc = -1; i < sizeof(dividers)/sizeof(dividers[0]); i++)
0534 {
0535 mbc = dividers[i].mbc;
0536 if (dividers[i].divider >= divider)
0537 {
0538 break;
0539 }
0540 }
0541 mpc5200.i2c_regs[bus->bus_idx].mfdr = mbc;
0542 return RTEMS_SUCCESSFUL;
0543 }
0544
0545
0546
0547
0548
0549
0550
0551
0552
0553
0554 rtems_status_code
0555 mpc5200mbus_initialize(mpc5200mbus *i2c_bus)
0556 {
0557 rtems_interrupt_level level;
0558 rtems_status_code sc;
0559 rtems_irq_connect_data mbusIrqData;
0560
0561 if (i2c_bus == NULL)
0562 return RTEMS_INVALID_ADDRESS;
0563
0564 if (i2c_bus->state != STATE_UNINITIALIZED)
0565 return RTEMS_RESOURCE_IN_USE;
0566
0567 i2c_bus->state = STATE_IDLE;
0568 i2c_bus->msg = NULL;
0569 i2c_bus->cmsg = NULL;
0570 i2c_bus->nmsg = 0;
0571 i2c_bus->byte = 0;
0572
0573
0574
0575
0576 mbusIrqData.on = mpc5200mbus_irq_enable;
0577 mbusIrqData.off = mpc5200mbus_irq_disable;
0578 mbusIrqData.isOn = mpc5200mbus_irq_isOn;
0579 mbusIrqData.handle = (rtems_irq_hdl_param)i2c_bus;
0580 mbusIrqData.hdl = mpc5200mbus_interrupt_handler;
0581 switch(i2c_bus->bus_idx) {
0582 case 0:
0583 mbusIrqData.name = BSP_SIU_IRQ_I2C1;
0584 break;
0585 case 1:
0586 mbusIrqData.name = BSP_SIU_IRQ_I2C2;
0587 break;
0588 }
0589 if (!BSP_install_rtems_irq_handler (&mbusIrqData)) {
0590 sc = RTEMS_UNSATISFIED;
0591 return sc;
0592 }
0593
0594 rtems_interrupt_disable(level);
0595
0596 mpc5200.i2c_regs[i2c_bus->bus_idx].mcr &= ~MPC5200_I2C_MCR_MEN;
0597 mpc5200.i2c_regs[i2c_bus->bus_idx].msr = 0;
0598 mpc5200.i2c_regs[i2c_bus->bus_idx].mdr = 0x1F;
0599 mpc5200.i2c_regs[i2c_bus->bus_idx].mcr |= MPC5200_I2C_MCR_MEN;
0600
0601 rtems_interrupt_enable(level);
0602
0603 return RTEMS_SUCCESSFUL;
0604 }
0605
0606
0607
0608
0609
0610
0611
0612
0613
0614
0615
0616
0617
0618
0619
0620
0621 rtems_status_code
0622 mpc5200mbus_i2c_transfer(mpc5200mbus *bus, int nmsg, i2c_message *msg,
0623 i2c_transfer_done done, void *done_arg_ptr)
0624 {
0625 if (bus->state == STATE_UNINITIALIZED)
0626 return RTEMS_NOT_CONFIGURED;
0627
0628 bus->done = done;
0629 bus->done_arg_ptr = done_arg_ptr;
0630 bus->cmsg = bus->msg = msg;
0631 bus->nmsg = nmsg;
0632 bus->byte = 0;
0633 bus->state = STATE_IDLE;
0634 mpc5200mbus_machine(bus, EVENT_TRANSFER);
0635 return RTEMS_SUCCESSFUL;
0636 }
0637
0638
0639
0640
0641
0642
0643
0644
0645
0646
0647
0648
0649 rtems_status_code
0650 mpc5200mbus_i2c_done(mpc5200mbus *i2c_bus)
0651 {
0652 rtems_status_code sc = RTEMS_SUCCESSFUL;
0653
0654 if (i2c_bus->state == STATE_UNINITIALIZED)
0655 return RTEMS_NOT_CONFIGURED;
0656
0657 mpc5200.i2c_regs[i2c_bus->bus_idx].mcr = 0;
0658
0659 return sc;
0660 }