File indexing completed on 2025-05-11 08:22:50
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 #include <bsp.h>
0029 #include <bsp/fatal.h>
0030 #include <bsp/fdt.h>
0031 #include <bsp/irq.h>
0032
0033 #include <chip.h>
0034 #include <dev/i2c/i2c.h>
0035 #include <fsl_clock.h>
0036 #include <fsl_lpi2c.h>
0037 #include <libfdt.h>
0038
0039 #define LPI2C_MTDR_CMD_transmit LPI2C_MTDR_CMD(0)
0040 #define LPI2C_MTDR_CMD_receive LPI2C_MTDR_CMD(1)
0041 #define LPI2C_MTDR_CMD_stop LPI2C_MTDR_CMD(2)
0042 #define LPI2C_MTDR_CMD_receive_and_discard LPI2C_MTDR_CMD(3)
0043 #define LPI2C_MTDR_CMD_start_and_transmit LPI2C_MTDR_CMD(4)
0044 #define LPI2C_MTDR_CMD_start_and_transmit_NACK LPI2C_MTDR_CMD(5)
0045 #define LPI2C_MTDR_CMD_start_and_transmit_highspeed LPI2C_MTDR_CMD(6)
0046 #define LPI2C_MTDR_CMD_start_and_transmit_highspeed_NACK LPI2C_MTDR_CMD(7)
0047
0048 #define LPI2C_INT_ERRORS_SERIOUS ( \
0049 LPI2C_MSR_FEF_MASK | LPI2C_MSR_ALF_MASK | LPI2C_MSR_PLTF_MASK )
0050
0051 #define LPI2C_INT_ERROR_NO_ACK (LPI2C_MSR_NDF_MASK)
0052
0053 #define LPI2C_INT_ERRORS (LPI2C_INT_ERRORS_SERIOUS | LPI2C_INT_ERROR_NO_ACK)
0054
0055 #define LPI2C_INT_ADDRESSED (LPI2C_INT_ERRORS | LPI2C_MSR_TDF_MASK)
0056
0057 #define LPI2C_INT_STOP_SENT (LPI2C_INT_ERRORS | LPI2C_MSR_SDF_MASK)
0058
0059 #define LPI2C_INT_RECEIVED (LPI2C_INT_ERRORS | LPI2C_MSR_RDF_MASK)
0060
0061 #define LPI2C_INT_TRANSMITTED (LPI2C_INT_ERRORS | LPI2C_MSR_TDF_MASK)
0062
0063 struct imxrt_lpi2c_bus {
0064 i2c_bus base;
0065 volatile LPI2C_Type *regs;
0066 rtems_vector_number irq;
0067 uint32_t src_clock_hz;
0068 clock_ip_name_t clock_ip;
0069 unsigned long clock;
0070
0071 rtems_binary_semaphore sem;
0072 int eno;
0073
0074 uint32_t msg_todo;
0075 const i2c_msg *msg;
0076
0077
0078 uint32_t chunk_todo;
0079 uint16_t buf_todo;
0080 uint8_t *buf;
0081 bool stop;
0082 bool read;
0083 };
0084
0085 static void imxrt_lpi2c_sw_reset(volatile LPI2C_Type *regs)
0086 {
0087 regs->MCR = LPI2C_MCR_RST_MASK | LPI2C_MCR_RRF_MASK | LPI2C_MCR_RTF_MASK;
0088 regs->SCR = LPI2C_SCR_RST_MASK | LPI2C_SCR_RRF_MASK | LPI2C_SCR_RTF_MASK;
0089 regs->MCR = 0;
0090 regs->SCR = 0;
0091 }
0092
0093 static int imxrt_lpi2c_set_clock(i2c_bus *base, unsigned long clock)
0094 {
0095 struct imxrt_lpi2c_bus *bus;
0096 volatile LPI2C_Type *regs;
0097
0098 bus = (struct imxrt_lpi2c_bus *) base;
0099 regs = bus->regs;
0100
0101 bus->clock = clock;
0102
0103
0104
0105
0106
0107 LPI2C_MasterSetBaudRate((LPI2C_Type *)regs, bus->src_clock_hz, clock);
0108
0109 return 0;
0110 }
0111
0112 static void imxrt_lpi2c_do_reinit(
0113 struct imxrt_lpi2c_bus *bus,
0114 volatile LPI2C_Type *regs
0115 )
0116 {
0117 regs->MIER = 0;
0118 imxrt_lpi2c_sw_reset(regs);
0119
0120 regs->MCFGR2 = LPI2C_MCFGR2_FILTSDA(0) | LPI2C_MCFGR2_FILTSCL(0) |
0121 LPI2C_MCFGR2_BUSIDLE(0);
0122 regs->MCFGR3 = LPI2C_MCFGR3_PINLOW(0);
0123
0124 regs->MFCR = LPI2C_MFCR_RXWATER(0) | LPI2C_MFCR_TXWATER(1);
0125
0126 imxrt_lpi2c_set_clock(&bus->base, bus->clock);
0127 }
0128
0129 static void imxrt_lpi2c_done(
0130 struct imxrt_lpi2c_bus *bus,
0131 volatile LPI2C_Type *regs
0132 )
0133 {
0134 regs->MIER = 0;
0135 regs->MCR &= ~LPI2C_MCR_MEN_MASK;
0136 rtems_binary_semaphore_post(&bus->sem);
0137 }
0138
0139 static void imxrt_lpi2c_next_msg(
0140 struct imxrt_lpi2c_bus *bus,
0141 volatile LPI2C_Type *regs
0142 );
0143
0144 static void imxrt_lpi2c_transmit_next(
0145 struct imxrt_lpi2c_bus *bus,
0146 volatile LPI2C_Type *regs
0147 )
0148 {
0149 if (bus->chunk_todo == 0) {
0150
0151 if (bus->stop) {
0152 regs->MTDR = LPI2C_MTDR_CMD_stop;
0153 bus->stop = false;
0154 regs->MIER = LPI2C_INT_STOP_SENT;
0155 } else {
0156 imxrt_lpi2c_next_msg(bus, regs);
0157 }
0158 } else {
0159 if (bus->read) {
0160 uint16_t to_read;
0161 to_read = MIN(bus->chunk_todo, 256);
0162 bus->chunk_todo -= to_read;
0163
0164 regs->MTDR = LPI2C_MTDR_CMD_receive | (to_read - 1);
0165 regs->MIER = LPI2C_INT_RECEIVED;
0166 } else {
0167 regs->MTDR = LPI2C_MTDR_CMD_transmit | *bus->buf;
0168 ++bus->buf;
0169 --bus->buf_todo;
0170 --bus->chunk_todo;
0171 regs->MIER = LPI2C_INT_TRANSMITTED;
0172 }
0173 }
0174 }
0175
0176 static void imxrt_lpi2c_next_msg(
0177 struct imxrt_lpi2c_bus *bus,
0178 volatile LPI2C_Type *regs
0179 )
0180 {
0181 if (bus->msg_todo == 0) {
0182 imxrt_lpi2c_done(bus, regs);
0183 } else {
0184 const i2c_msg *msg;
0185 int flags;
0186 bool start;
0187 uint16_t addr;
0188
0189 msg = bus->msg;
0190 flags = msg->flags;
0191
0192 addr = msg->addr;
0193 start = (flags & I2C_M_NOSTART) == 0;
0194 bus->read = (flags & I2C_M_RD) != 0;
0195 bus->chunk_todo = msg->len;
0196 bus->buf_todo = msg->len;
0197 bus->buf = msg->buf;
0198 bus->stop = (flags & I2C_M_STOP) != 0 || bus->msg_todo <= 1;
0199
0200 ++bus->msg;
0201 --bus->msg_todo;
0202
0203 if (start) {
0204 uint32_t mtdr;
0205 mtdr = LPI2C_MTDR_CMD_start_and_transmit;
0206 mtdr |= addr << 1;
0207 if (bus->read) {
0208 mtdr |= 1;
0209 }
0210 regs->MTDR = mtdr;
0211 regs->MIER = LPI2C_INT_ADDRESSED;
0212 } else {
0213 imxrt_lpi2c_transmit_next(bus, regs);
0214 }
0215 }
0216 }
0217
0218 static void imxrt_lpi2c_interrupt(void *arg)
0219 {
0220 struct imxrt_lpi2c_bus *bus;
0221 volatile LPI2C_Type *regs;
0222 uint32_t msr;
0223
0224 bus = arg;
0225 regs = bus->regs;
0226
0227 msr = regs->MSR;
0228 regs->MSR = msr;
0229
0230 if ((msr & LPI2C_INT_ERROR_NO_ACK) != 0) {
0231
0232 bus->eno = EIO;
0233 imxrt_lpi2c_done(bus, regs);
0234 } else if ((msr & LPI2C_INT_ERRORS_SERIOUS) != 0) {
0235
0236 bus->eno = EIO;
0237 imxrt_lpi2c_do_reinit(bus, regs);
0238 imxrt_lpi2c_done(bus, regs);
0239 } else {
0240 uint32_t mrdr;
0241 while (((mrdr = regs->MRDR) & LPI2C_MRDR_RXEMPTY_MASK) == 0) {
0242 if (bus->read && bus->buf_todo > 0) {
0243 *bus->buf = (mrdr & LPI2C_MRDR_DATA_MASK) >> LPI2C_MRDR_DATA_SHIFT;
0244 ++bus->buf;
0245 --bus->buf_todo;
0246 }
0247 }
0248
0249 if (
0250 ((msr & LPI2C_MSR_TDF_MASK) != 0) &&
0251 (!bus->read || bus->chunk_todo > 0 || bus->buf_todo == 0)
0252 ) {
0253 imxrt_lpi2c_transmit_next(bus, regs);
0254 }
0255 }
0256 }
0257
0258 static int imxrt_lpi2c_wait_for_not_busy(volatile LPI2C_Type *regs)
0259 {
0260 rtems_interval timeout;
0261 bool before;
0262
0263 if ((regs->MSR & LPI2C_MSR_BBF_MASK) == 0) {
0264 return 0;
0265 }
0266
0267 timeout = rtems_clock_tick_later_usec(5000);
0268
0269 do {
0270 before = rtems_clock_tick_before(timeout);
0271
0272 if ((regs->MSR & LPI2C_MSR_BBF_MASK) == 0) {
0273 return 0;
0274 }
0275 } while (before);
0276
0277 return ETIMEDOUT;
0278 }
0279
0280 static void imxrt_lpi2c_first_msg(
0281 struct imxrt_lpi2c_bus *bus,
0282 volatile LPI2C_Type *regs
0283 )
0284 {
0285 if ((regs->MCR & LPI2C_MCR_MEN_MASK) == 0) {
0286 regs->MCR |= LPI2C_MCR_MEN_MASK;
0287 }
0288
0289 imxrt_lpi2c_next_msg(bus, regs);
0290 }
0291
0292 static int imxrt_lpi2c_transfer(i2c_bus *base, i2c_msg *msgs, uint32_t n)
0293 {
0294 struct imxrt_lpi2c_bus *bus;
0295 volatile LPI2C_Type *regs;
0296 int supported_flags;
0297 int eno;
0298 uint16_t i;
0299
0300 bus = (struct imxrt_lpi2c_bus *) base;
0301 regs = bus->regs;
0302
0303 supported_flags = I2C_M_RD | I2C_M_STOP;
0304
0305 for (i = 0; i < n; ++i) {
0306 if ((msgs[i].flags & ~supported_flags) != 0) {
0307 return -EINVAL;
0308 }
0309
0310 supported_flags |= I2C_M_NOSTART;
0311 }
0312
0313 eno = imxrt_lpi2c_wait_for_not_busy(regs);
0314 if (eno != 0) {
0315 imxrt_lpi2c_do_reinit(bus, regs);
0316 return -eno;
0317 }
0318
0319 bus->msg_todo = n;
0320 bus->msg = &msgs[0];
0321 bus->eno = 0;
0322
0323 imxrt_lpi2c_first_msg(bus, regs);
0324
0325 eno = rtems_binary_semaphore_wait_timed_ticks(&bus->sem, bus->base.timeout);
0326 if (eno != 0) {
0327
0328 imxrt_lpi2c_do_reinit(bus, regs);
0329 rtems_binary_semaphore_try_wait(&bus->sem);
0330 return -eno;
0331 }
0332
0333 return -bus->eno;
0334 }
0335
0336 static void imxrt_lpi2c_destroy(i2c_bus *base)
0337 {
0338 struct imxrt_lpi2c_bus *bus;
0339 volatile LPI2C_Type *regs;
0340
0341 bus = (struct imxrt_lpi2c_bus *) base;
0342 regs = bus->regs;
0343 imxrt_lpi2c_sw_reset(regs);
0344 CLOCK_DisableClock(bus->clock_ip);
0345
0346 rtems_interrupt_handler_remove(bus->irq, imxrt_lpi2c_interrupt, bus);
0347 i2c_bus_destroy_and_free(&bus->base);
0348 }
0349
0350 static int imxrt_lpi2c_hw_init(struct imxrt_lpi2c_bus *bus)
0351 {
0352 rtems_status_code sc;
0353 volatile LPI2C_Type *regs;
0354
0355 regs = bus->regs;
0356
0357 CLOCK_EnableClock(bus->clock_ip);
0358
0359 bus->clock = I2C_BUS_CLOCK_DEFAULT;
0360 imxrt_lpi2c_do_reinit(bus, regs);
0361
0362 sc = rtems_interrupt_handler_install(
0363 bus->irq,
0364 "LPI2C",
0365 RTEMS_INTERRUPT_UNIQUE,
0366 imxrt_lpi2c_interrupt,
0367 bus
0368 );
0369 if (sc != RTEMS_SUCCESSFUL) {
0370 return EAGAIN;
0371 }
0372
0373 return 0;
0374 }
0375
0376 static uint32_t imxrt_lpi2c_get_src_freq(clock_ip_name_t clock_ip)
0377 {
0378 uint32_t freq;
0379 #if IMXRT_IS_MIMXRT10xx
0380 uint32_t mux;
0381 uint32_t divider;
0382
0383 (void) clock_ip;
0384
0385 mux = CLOCK_GetMux(kCLOCK_Lpi2cMux);
0386 divider = 1;
0387
0388 switch (mux) {
0389 case 0:
0390 freq = CLOCK_GetFreq(kCLOCK_Usb1PllClk);
0391 divider = 8;
0392 break;
0393 case 1:
0394 freq = CLOCK_GetFreq(kCLOCK_OscClk);
0395 break;
0396 default:
0397 freq = 0;
0398 }
0399
0400 divider *= CLOCK_GetDiv(kCLOCK_Lpi2cDiv) + 1;
0401 freq /= divider;
0402 #elif IMXRT_IS_MIMXRT11xx
0403
0404
0405
0406
0407 clock_root_t clock_root = clock_ip + kCLOCK_Root_Lpi2c1 - kCLOCK_Lpi2c1;
0408
0409 freq = CLOCK_GetRootClockFreq(clock_root);
0410 #else
0411 #error Getting I2C frequency is not implemented for this chip.
0412 #endif
0413
0414 return freq;
0415 }
0416
0417 static clock_ip_name_t imxrt_lpi2c_clock_ip(volatile LPI2C_Type *regs)
0418 {
0419 LPI2C_Type *const base_addresses[] = LPI2C_BASE_PTRS;
0420 static const clock_ip_name_t lpi2c_clocks[] = LPI2C_CLOCKS;
0421 size_t i;
0422
0423 for (i = 0; i < RTEMS_ARRAY_SIZE(base_addresses); ++i) {
0424 if (base_addresses[i] == regs) {
0425 return lpi2c_clocks[i];
0426 }
0427 }
0428
0429 return kCLOCK_IpInvalid;
0430 }
0431
0432 void imxrt_lpi2c_init(void)
0433 {
0434 const void *fdt;
0435 int node;
0436
0437 fdt = bsp_fdt_get();
0438 node = -1;
0439
0440 do {
0441 node = fdt_node_offset_by_compatible(fdt, node, "nxp,imxrt-lpi2c");
0442
0443 if (node >= 0 && imxrt_fdt_node_is_enabled(fdt, node)) {
0444 struct imxrt_lpi2c_bus *bus;
0445 int eno;
0446 const char *bus_path;
0447
0448 bus = (struct imxrt_lpi2c_bus*) i2c_bus_alloc_and_init(sizeof(*bus));
0449 if (bus == NULL) {
0450 bsp_fatal(IMXRT_FATAL_LPI2C_ALLOC_FAILED);
0451 }
0452
0453 rtems_binary_semaphore_init(&bus->sem, "LPI2C");
0454
0455 bus->regs = imx_get_reg_of_node(fdt, node);
0456 if (bus->regs == NULL) {
0457 (*bus->base.destroy)(&bus->base);
0458 bsp_fatal(IMXRT_FATAL_LPI2C_INVALID_FDT);
0459 }
0460
0461 bus->irq = imx_get_irq_of_node(fdt, node, 0);
0462 if (bus->irq == BSP_INTERRUPT_VECTOR_INVALID) {
0463 (*bus->base.destroy)(&bus->base);
0464 bsp_fatal(IMXRT_FATAL_LPI2C_INVALID_FDT);
0465 }
0466
0467 bus_path = fdt_getprop(fdt, node, "rtems,path", NULL);
0468 if (bus_path == NULL) {
0469 (*bus->base.destroy)(&bus->base);
0470 bsp_fatal(IMXRT_FATAL_LPI2C_INVALID_FDT);
0471 }
0472
0473 bus->clock_ip = imxrt_lpi2c_clock_ip(bus->regs);
0474 bus->src_clock_hz = imxrt_lpi2c_get_src_freq(bus->clock_ip);
0475
0476 eno = imxrt_lpi2c_hw_init(bus);
0477 if (eno != 0) {
0478 (*bus->base.destroy)(&bus->base);
0479 bsp_fatal(IMXRT_FATAL_LPI2C_HW_INIT_FAILED);
0480 }
0481
0482 bus->base.transfer = imxrt_lpi2c_transfer;
0483 bus->base.set_clock = imxrt_lpi2c_set_clock;
0484 bus->base.destroy = imxrt_lpi2c_destroy;
0485
0486
0487
0488
0489
0490
0491
0492 if ((1 << ((bus->regs->PARAM & LPI2C_PARAM_MTXFIFO_MASK) >>
0493 LPI2C_PARAM_MTXFIFO_SHIFT)) < 3) {
0494 bsp_fatal(IMXRT_FATAL_LPI2C_UNSUPPORTED_HARDWARE);
0495 }
0496
0497 eno = i2c_bus_register(&bus->base, bus_path);
0498 if (eno != 0) {
0499 bsp_fatal(IMXRT_FATAL_LPI2C_REGISTER_FAILED);
0500 }
0501 }
0502 } while (node >= 0);
0503 }