File indexing completed on 2025-05-11 08:23:46
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #include "mcf5206/mcfmbus.h"
0015 #include "mcf5206/mcf5206e.h"
0016 #include "i2c.h"
0017
0018
0019 typedef enum i2c_event {
0020 EVENT_NONE,
0021 EVENT_TRANSFER,
0022 EVENT_NEXTMSG,
0023 EVENT_ACK,
0024 EVENT_NACK,
0025 EVENT_TIMEOUT,
0026 EVENT_DATA_RECV,
0027 EVENT_ARB_LOST,
0028 EVENT_SLAVE
0029 } i2c_event;
0030
0031 static mcfmbus *mbus;
0032
0033
0034
0035
0036 #define next_state(bus,new_state) \
0037 do { \
0038 (bus)->state = (new_state); \
0039 } while (0)
0040
0041
0042 #define mcfmbus_start(bus) \
0043 do { \
0044 *MCF5206E_MBCR((bus)->base) |= MCF5206E_MBCR_MSTA; \
0045 } while (0)
0046
0047
0048 #define mcfmbus_stop(bus) \
0049 do { \
0050 *MCF5206E_MBCR((bus)->base) &= ~MCF5206E_MBCR_MSTA; \
0051 } while (0)
0052
0053
0054 #define mcfmbus_rstart(bus) \
0055 do { \
0056 *MCF5206E_MBCR((bus)->base) |= MCF5206E_MBCR_RSTA; \
0057 } while (0)
0058
0059
0060 #define mcfmbus_send(bus,byte) \
0061 do { \
0062 *MCF5206E_MBDR((bus)->base) = (byte); \
0063 } while (0)
0064
0065
0066 #define mcfmbus_tx_mode(bus) \
0067 do { \
0068 *MCF5206E_MBCR((bus)->base) |= MCF5206E_MBCR_MTX; \
0069 } while (0)
0070
0071
0072 #define mcfmbus_rx_mode(bus) \
0073 do { \
0074 *MCF5206E_MBCR((bus)->base) &= ~MCF5206E_MBCR_MTX; \
0075 (void)*MCF5206E_MBDR((bus)->base); \
0076 } while (0)
0077
0078
0079
0080 #define mcfmbus_send_ack(bus) \
0081 do { \
0082 *MCF5206E_MBCR((bus)->base) &= ~MCF5206E_MBCR_TXAK; \
0083 } while (0)
0084
0085
0086 #define mcfmbus_send_nack(bus) \
0087 do { \
0088 *MCF5206E_MBCR((bus)->base) |= MCF5206E_MBCR_TXAK; \
0089 } while (0)
0090
0091 #define mcfmbus_error(bus,err_status) \
0092 do { \
0093 do { \
0094 (bus)->cmsg->status = (err_status); \
0095 (bus)->cmsg++; \
0096 } while (((bus)->cmsg - (bus)->msg < (bus)->nmsg) && \
0097 ((bus)->cmsg->flags & I2C_MSG_ERRSKIP)); \
0098 bus->cmsg--; \
0099 } while (0)
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111 static i2c_event
0112 mcfmbus_get_event(mcfmbus *bus)
0113 {
0114 i2c_event event;
0115 uint8_t status, control;
0116 rtems_interrupt_level level;
0117 rtems_interrupt_disable(level);
0118 status = *MCF5206E_MBSR(bus->base);
0119 control = *MCF5206E_MBCR(bus->base);
0120
0121 if (status & MCF5206E_MBSR_MIF) {
0122 if (status & MCF5206E_MBSR_MAAS) {
0123 event = EVENT_SLAVE;
0124 *MCF5206E_MBCR(bus->base) = control;
0125
0126 } else if (status & MCF5206E_MBSR_MAL) {
0127 *MCF5206E_MBSR(bus->base) = status & ~MCF5206E_MBSR_MAL;
0128 event = EVENT_ARB_LOST;
0129 }
0130 else if (control & MCF5206E_MBCR_MTX) {
0131 if (status & MCF5206E_MBSR_RXAK)
0132 event = EVENT_NACK;
0133 else
0134 event = EVENT_ACK;
0135 } else {
0136 event = EVENT_DATA_RECV;
0137 }
0138
0139
0140 *MCF5206E_MBSR(bus->base) &= ~MCF5206E_MBSR_MIF;
0141 } else {
0142 event = EVENT_NONE;
0143 }
0144 rtems_interrupt_enable(level);
0145 return event;
0146 }
0147
0148 static void mcfmbus_machine_error(mcfmbus *bus, i2c_event event)
0149 {
0150 }
0151
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161
0162 static void mcfmbus_machine(mcfmbus *bus, i2c_event event)
0163 {
0164 uint8_t b;
0165
0166 switch (bus->state) {
0167 case STATE_IDLE:
0168 switch (event) {
0169 case EVENT_NEXTMSG:
0170 bus->cmsg++;
0171
0172
0173 case EVENT_TRANSFER:
0174 if (bus->cmsg - bus->msg >= bus->nmsg) {
0175 mcfmbus_stop(bus);
0176 next_state(bus, STATE_IDLE);
0177 bus->msg = bus->cmsg = NULL;
0178 bus->nmsg = bus->byte = 0;
0179 bus->done((void *)bus->done_arg_ptr);
0180 break;
0181 }
0182
0183
0184 if (event == EVENT_TRANSFER) {
0185 mcfmbus_start(bus);
0186 } else {
0187 mcfmbus_rstart(bus);
0188 }
0189
0190 bus->byte = 0;
0191 mcfmbus_tx_mode(bus);
0192
0193
0194 if (bus->cmsg->flags & I2C_MSG_ADDR_10) {
0195 i2c_address a = bus->cmsg->addr;
0196 b = 0xf0 | (((a >> 8) & 0x03) << 1);
0197 if (bus->cmsg->flags & I2C_MSG_WR) {
0198 mcfmbus_send(bus, b);
0199 next_state(bus, STATE_ADDR_1_W);
0200 } else {
0201 mcfmbus_send(bus, b | 1);
0202 next_state(bus, STATE_ADDR_1_R);
0203 }
0204 } else {
0205 b = (bus->cmsg->addr & ~0x01);
0206
0207 if (bus->cmsg->flags & I2C_MSG_WR) {
0208 next_state(bus, STATE_SENDING);
0209 } else {
0210 next_state(bus, STATE_ADDR_7);
0211 b |= 1;
0212 }
0213
0214 mcfmbus_send(bus, b);
0215 }
0216 break;
0217
0218 default:
0219 mcfmbus_machine_error(bus, event);
0220 break;
0221 }
0222 break;
0223
0224 case STATE_ADDR_7:
0225 switch (event) {
0226 case EVENT_ACK:
0227 mcfmbus_rx_mode(bus);
0228 if (bus->cmsg->len <= 1)
0229 mcfmbus_send_nack(bus);
0230 else
0231 mcfmbus_send_ack(bus);
0232 next_state(bus, STATE_RECEIVING);
0233 break;
0234
0235 case EVENT_NACK:
0236 mcfmbus_error(bus, I2C_NO_DEVICE);
0237 next_state(bus, STATE_IDLE);
0238 mcfmbus_machine(bus, EVENT_NEXTMSG);
0239 break;
0240
0241 case EVENT_ARB_LOST:
0242 mcfmbus_error(bus, I2C_ARBITRATION_LOST);
0243 next_state(bus, STATE_IDLE);
0244 mcfmbus_machine(bus, EVENT_NEXTMSG);
0245 break;
0246
0247 default:
0248 mcfmbus_machine_error(bus, event);
0249 break;
0250 }
0251 break;
0252
0253 case STATE_ADDR_1_R:
0254 case STATE_ADDR_1_W:
0255 switch (event) {
0256 case EVENT_ACK: {
0257 uint8_t b = (bus->cmsg->addr & 0xff);
0258 mcfmbus_send(bus, b);
0259 if (bus->state == STATE_ADDR_1_W) {
0260 next_state(bus, STATE_SENDING);
0261 } else {
0262 i2c_address a;
0263 mcfmbus_rstart(bus);
0264 mcfmbus_tx_mode(bus);
0265 a = bus->cmsg->addr;
0266 b = 0xf0 | (((a >> 8) & 0x03) << 1) | 1;
0267 mcfmbus_send(bus, b);
0268 next_state(bus, STATE_ADDR_7);
0269 }
0270 break;
0271 }
0272
0273 case EVENT_NACK:
0274 mcfmbus_error(bus, I2C_NO_DEVICE);
0275 next_state(bus, STATE_IDLE);
0276 mcfmbus_machine(bus, EVENT_NEXTMSG);
0277 break;
0278
0279 case EVENT_ARB_LOST:
0280 mcfmbus_error(bus, I2C_ARBITRATION_LOST);
0281 next_state(bus, STATE_IDLE);
0282 mcfmbus_machine(bus, EVENT_NEXTMSG);
0283 break;
0284
0285 default:
0286 mcfmbus_machine_error(bus, event);
0287 break;
0288 }
0289 break;
0290
0291 case STATE_SENDING:
0292 switch (event) {
0293 case EVENT_ACK:
0294 if (bus->byte == bus->cmsg->len) {
0295 next_state(bus, STATE_IDLE);
0296 mcfmbus_machine(bus, EVENT_NEXTMSG);
0297 } else {
0298 mcfmbus_send(bus, bus->cmsg->buf[bus->byte++]);
0299 next_state(bus, STATE_SENDING);
0300 }
0301 break;
0302
0303 case EVENT_NACK:
0304 if (bus->byte == 0) {
0305 mcfmbus_error(bus, I2C_NO_DEVICE);
0306 } else {
0307 mcfmbus_error(bus, I2C_NO_ACKNOWLEDGE);
0308 }
0309 next_state(bus, STATE_IDLE);
0310 mcfmbus_machine(bus, EVENT_NEXTMSG);
0311 break;
0312
0313 case EVENT_ARB_LOST:
0314 mcfmbus_error(bus, I2C_ARBITRATION_LOST);
0315 next_state(bus, STATE_IDLE);
0316 mcfmbus_machine(bus, EVENT_NEXTMSG);
0317 break;
0318
0319 default:
0320 mcfmbus_machine_error(bus, event);
0321 break;
0322 }
0323 break;
0324
0325 case STATE_RECEIVING:
0326 switch (event) {
0327 case EVENT_DATA_RECV:
0328 if (bus->cmsg->len - bus->byte <= 2) {
0329 mcfmbus_send_nack(bus);
0330 if (bus->cmsg->len - bus->byte <= 1) {
0331 if (bus->cmsg - bus->msg + 1 == bus->nmsg)
0332 mcfmbus_stop(bus);
0333 else
0334 mcfmbus_rstart(bus);
0335 }
0336 } else {
0337 mcfmbus_send_ack(bus);
0338 }
0339 bus->cmsg->buf[bus->byte++] = *MCF5206E_MBDR(bus->base);
0340 if (bus->cmsg->len == bus->byte) {
0341 next_state(bus,STATE_IDLE);
0342 mcfmbus_machine(bus, EVENT_NEXTMSG);
0343 } else {
0344 next_state(bus,STATE_RECEIVING);
0345 }
0346 break;
0347
0348 case EVENT_ARB_LOST:
0349 mcfmbus_error(bus, I2C_ARBITRATION_LOST);
0350 next_state(bus, STATE_IDLE);
0351 mcfmbus_machine(bus, EVENT_NEXTMSG);
0352 break;
0353
0354 default:
0355 mcfmbus_machine_error(bus, event);
0356 break;
0357 }
0358 break;
0359 }
0360 }
0361
0362
0363
0364
0365
0366
0367
0368
0369
0370
0371 static rtems_isr mcfmbus_interrupt_handler(rtems_vector_number vector)
0372 {
0373 i2c_event event;
0374 event = mcfmbus_get_event(mbus);
0375 mcfmbus_machine(mbus, event);
0376 }
0377
0378
0379
0380
0381
0382
0383
0384
0385
0386
0387
0388 void
0389 mcfmbus_poll(mcfmbus *bus)
0390 {
0391 i2c_event event;
0392 event = mcfmbus_get_event(bus);
0393 if (event != EVENT_NONE)
0394 mcfmbus_machine(bus, event);
0395 }
0396
0397
0398
0399
0400
0401
0402
0403
0404
0405
0406
0407
0408
0409 rtems_status_code
0410 mcfmbus_select_clock_divider(mcfmbus *i2c_bus, int divider)
0411 {
0412 int i;
0413 int mbc;
0414 struct {
0415 int divider;
0416 int mbc;
0417 } dividers[] ={
0418 { 20, 0x20 }, { 22, 0x21 }, { 24, 0x22 }, { 26, 0x23 },
0419 { 28, 0x00 }, { 30, 0x01 }, { 32, 0x25 }, { 34, 0x02 },
0420 { 36, 0x26 }, { 40, 0x03 }, { 44, 0x04 }, { 48, 0x05 },
0421 { 56, 0x06 }, { 64, 0x2a }, { 68, 0x07 }, { 72, 0x2B },
0422 { 80, 0x08 }, { 88, 0x09 }, { 96, 0x2D }, { 104, 0x0A },
0423 { 112, 0x2E }, { 128, 0x0B }, { 144, 0x0C }, { 160, 0x0D },
0424 { 192, 0x0E }, { 224, 0x32 }, { 240, 0x0F }, { 256, 0x33 },
0425 { 288, 0x10 }, { 320, 0x11 }, { 384, 0x12 }, { 448, 0x36 },
0426 { 480, 0x13 }, { 512, 0x37 }, { 576, 0x14 }, { 640, 0x15 },
0427 { 768, 0x16 }, { 896, 0x3A }, { 960, 0x17 }, { 1024, 0x3B },
0428 { 1152, 0x18 }, { 1280, 0x19 }, { 1536, 0x1A }, { 1792, 0x3E },
0429 { 1920, 0x1B }, { 2048, 0x3F }, { 2304, 0x1C }, { 2560, 0x1D },
0430 { 3072, 0x1E }, { 3840, 0x1F }
0431 };
0432
0433 if (i2c_bus == NULL)
0434 return RTEMS_INVALID_ADDRESS;
0435
0436 for (i = 0, mbc = -1; i < sizeof(dividers)/sizeof(dividers[0]); i++) {
0437 mbc = dividers[i].mbc;
0438 if (dividers[i].divider >= divider) {
0439 break;
0440 }
0441 }
0442 *MCF5206E_MFDR(i2c_bus->base) = mbc;
0443 return RTEMS_SUCCESSFUL;
0444 }
0445
0446
0447
0448
0449
0450
0451
0452
0453
0454
0455
0456 rtems_status_code mcfmbus_initialize(mcfmbus *i2c_bus, uint32_t base)
0457 {
0458 rtems_interrupt_level level;
0459 rtems_status_code sc;
0460
0461 if (mbus != NULL)
0462 return RTEMS_RESOURCE_IN_USE;
0463
0464 if (i2c_bus == NULL)
0465 return RTEMS_INVALID_ADDRESS;
0466
0467
0468 i2c_bus->base = base;
0469 i2c_bus->state = STATE_IDLE;
0470 i2c_bus->msg = NULL;
0471 i2c_bus->cmsg = NULL;
0472 i2c_bus->nmsg = 0;
0473 i2c_bus->byte = 0;
0474
0475 sc = rtems_interrupt_catch(
0476 mcfmbus_interrupt_handler,
0477 24 + ((*MCF5206E_ICR(base, MCF5206E_INTR_MBUS) & MCF5206E_ICR_IL) >>
0478 MCF5206E_ICR_IL_S),
0479 &i2c_bus->oldisr
0480 );
0481 if (sc != RTEMS_SUCCESSFUL)
0482 return sc;
0483
0484 mbus = i2c_bus;
0485 rtems_interrupt_disable(level);
0486 *MCF5206E_IMR(base) &= ~MCF5206E_INTR_BIT(MCF5206E_INTR_MBUS);
0487 *MCF5206E_MBCR(base) = 0;
0488 *MCF5206E_MBSR(base) = 0;
0489 *MCF5206E_MBDR(base) = 0x1F;
0490 *MCF5206E_MBCR(base) = MCF5206E_MBCR_MEN | MCF5206E_MBCR_MIEN;
0491 rtems_interrupt_enable(level);
0492
0493 return RTEMS_SUCCESSFUL;
0494 }
0495
0496
0497
0498
0499
0500
0501
0502
0503
0504
0505
0506
0507
0508
0509
0510
0511 rtems_status_code mcfmbus_i2c_transfer(
0512 mcfmbus *bus,
0513 int nmsg,
0514 i2c_message *msg,
0515 i2c_transfer_done done,
0516 void *done_arg_ptr
0517 )
0518 {
0519 if (bus != mbus)
0520 return RTEMS_NOT_CONFIGURED;
0521
0522 bus->done = done;
0523 bus->done_arg_ptr = (uintptr_t) done_arg_ptr;
0524 bus->cmsg = bus->msg = msg;
0525 bus->nmsg = nmsg;
0526 bus->byte = 0;
0527 bus->state = STATE_IDLE;
0528 mcfmbus_machine(bus, EVENT_TRANSFER);
0529 return RTEMS_SUCCESSFUL;
0530 }
0531
0532
0533
0534
0535
0536
0537
0538
0539
0540
0541
0542
0543 rtems_status_code mcfmbus_i2c_done(mcfmbus *i2c_bus)
0544 {
0545 rtems_status_code sc;
0546 uint32_t base;
0547 if (mbus == NULL)
0548 return RTEMS_NOT_CONFIGURED;
0549
0550 if (mbus != i2c_bus)
0551 return RTEMS_INVALID_ADDRESS;
0552
0553 base = i2c_bus->base;
0554
0555 *MCF5206E_IMR(base) |= MCF5206E_INTR_BIT(MCF5206E_INTR_MBUS);
0556 *MCF5206E_MBCR(base) = 0;
0557
0558 sc = rtems_interrupt_catch(
0559 i2c_bus->oldisr,
0560 24 + ((*MCF5206E_ICR(base, MCF5206E_INTR_MBUS) & MCF5206E_ICR_IL) >>
0561 MCF5206E_ICR_IL_S),
0562 NULL
0563 );
0564 return sc;
0565 }