1 /*
2 * Copyright (c) 2016 Freescale Semiconductor, Inc.
3 * Copyright (c) 2019, 2022 NXP
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8 #define DT_DRV_COMPAT nxp_lpc_i2c
9
10 #include <errno.h>
11 #include <zephyr/drivers/i2c.h>
12 #include <zephyr/drivers/clock_control.h>
13 #include <fsl_i2c.h>
14 #include <zephyr/drivers/pinctrl.h>
15 #include <zephyr/drivers/reset.h>
16
17 #ifdef CONFIG_I2C_MCUX_FLEXCOMM_BUS_RECOVERY
18 #include "i2c_bitbang.h"
19 #include <zephyr/drivers/gpio.h>
20 #endif /* CONFIG_I2C_MCUX_FLEXCOMM_BUS_RECOVERY */
21
22 #include <zephyr/logging/log.h>
23 #include <zephyr/irq.h>
24 LOG_MODULE_REGISTER(mcux_flexcomm);
25
26 #include "i2c-priv.h"
27
28 #define I2C_TRANSFER_TIMEOUT_MSEC \
29 COND_CODE_0(CONFIG_I2C_NXP_TRANSFER_TIMEOUT, (K_FOREVER), \
30 (K_MSEC(CONFIG_I2C_NXP_TRANSFER_TIMEOUT)))
31
32 #define MCUX_FLEXCOMM_MAX_TARGETS 4
33
34 struct mcux_flexcomm_config {
35 I2C_Type *base;
36 const struct device *clock_dev;
37 clock_control_subsys_t clock_subsys;
38 void (*irq_config_func)(const struct device *dev);
39 uint32_t bitrate;
40 const struct pinctrl_dev_config *pincfg;
41 const struct reset_dt_spec reset;
42 #ifdef CONFIG_I2C_MCUX_FLEXCOMM_BUS_RECOVERY
43 struct gpio_dt_spec scl;
44 struct gpio_dt_spec sda;
45 #endif /* CONFIG_I2C_MCUX_FLEXCOMM_BUS_RECOVERY */
46 };
47
48 #ifdef CONFIG_I2C_TARGET
49 struct mcux_flexcomm_target_data {
50 struct i2c_target_config *target_cfg;
51 bool target_attached;
52 bool first_read;
53 bool first_write;
54 bool is_write;
55 };
56 #endif
57
58 struct mcux_flexcomm_data {
59 i2c_master_handle_t handle;
60 struct k_sem device_sync_sem;
61 struct k_sem lock;
62 status_t callback_status;
63 #ifdef CONFIG_I2C_TARGET
64 uint8_t nr_targets_attached;
65 i2c_slave_config_t i2c_cfg;
66 i2c_slave_handle_t target_handle;
67 struct mcux_flexcomm_target_data target_data[MCUX_FLEXCOMM_MAX_TARGETS];
68 #endif
69 };
70
mcux_flexcomm_configure(const struct device * dev,uint32_t dev_config_raw)71 static int mcux_flexcomm_configure(const struct device *dev,
72 uint32_t dev_config_raw)
73 {
74 const struct mcux_flexcomm_config *config = dev->config;
75 struct mcux_flexcomm_data *data = dev->data;
76 I2C_Type *base = config->base;
77 uint32_t clock_freq;
78 uint32_t baudrate;
79
80 if (!(I2C_MODE_CONTROLLER & dev_config_raw)) {
81 return -EINVAL;
82 }
83
84 if (I2C_ADDR_10_BITS & dev_config_raw) {
85 return -EINVAL;
86 }
87
88 switch (I2C_SPEED_GET(dev_config_raw)) {
89 case I2C_SPEED_STANDARD:
90 baudrate = KHZ(100);
91 break;
92 case I2C_SPEED_FAST:
93 baudrate = KHZ(400);
94 break;
95 case I2C_SPEED_FAST_PLUS:
96 baudrate = MHZ(1);
97 break;
98 default:
99 return -EINVAL;
100 }
101
102 /* Get the clock frequency */
103 if (clock_control_get_rate(config->clock_dev, config->clock_subsys,
104 &clock_freq)) {
105 return -EINVAL;
106 }
107
108 k_sem_take(&data->lock, K_FOREVER);
109 I2C_MasterSetBaudRate(base, baudrate, clock_freq);
110 k_sem_give(&data->lock);
111
112 return 0;
113 }
114
mcux_flexcomm_master_transfer_callback(I2C_Type * base,i2c_master_handle_t * handle,status_t status,void * userData)115 static void mcux_flexcomm_master_transfer_callback(I2C_Type *base,
116 i2c_master_handle_t *handle,
117 status_t status,
118 void *userData)
119 {
120 struct mcux_flexcomm_data *data = userData;
121
122 ARG_UNUSED(handle);
123 ARG_UNUSED(base);
124
125 data->callback_status = status;
126 k_sem_give(&data->device_sync_sem);
127 }
128
mcux_flexcomm_convert_flags(int msg_flags)129 static uint32_t mcux_flexcomm_convert_flags(int msg_flags)
130 {
131 uint32_t flags = 0U;
132
133 if (!(msg_flags & I2C_MSG_STOP)) {
134 flags |= kI2C_TransferNoStopFlag;
135 }
136
137 if (msg_flags & I2C_MSG_RESTART) {
138 flags |= kI2C_TransferRepeatedStartFlag;
139 }
140
141 return flags;
142 }
143
mcux_flexcomm_transfer(const struct device * dev,struct i2c_msg * msgs,uint8_t num_msgs,uint16_t addr)144 static int mcux_flexcomm_transfer(const struct device *dev,
145 struct i2c_msg *msgs,
146 uint8_t num_msgs, uint16_t addr)
147 {
148 const struct mcux_flexcomm_config *config = dev->config;
149 struct mcux_flexcomm_data *data = dev->data;
150 I2C_Type *base = config->base;
151 i2c_master_transfer_t transfer;
152 status_t status;
153 int ret = 0;
154
155 k_sem_take(&data->lock, K_FOREVER);
156
157 /* Iterate over all the messages */
158 for (int i = 0; i < num_msgs; i++) {
159 if (I2C_MSG_ADDR_10_BITS & msgs->flags) {
160 ret = -ENOTSUP;
161 break;
162 }
163
164 /* Initialize the transfer descriptor */
165 transfer.flags = mcux_flexcomm_convert_flags(msgs->flags);
166
167 /* Prevent the controller to send a start condition between
168 * messages, except if explicitly requested.
169 */
170 if (i != 0 && !(msgs->flags & I2C_MSG_RESTART)) {
171 transfer.flags |= kI2C_TransferNoStartFlag;
172 }
173
174 transfer.slaveAddress = addr;
175 transfer.direction = (msgs->flags & I2C_MSG_READ)
176 ? kI2C_Read : kI2C_Write;
177 transfer.subaddress = 0;
178 transfer.subaddressSize = 0;
179 transfer.data = msgs->buf;
180 transfer.dataSize = msgs->len;
181
182 /* Start the transfer */
183 status = I2C_MasterTransferNonBlocking(base,
184 &data->handle, &transfer);
185
186 /* Return an error if the transfer didn't start successfully
187 * e.g., if the bus was busy
188 */
189 if (status != kStatus_Success) {
190 I2C_MasterTransferAbort(base, &data->handle);
191 ret = -EIO;
192 break;
193 }
194
195 /* Wait for the transfer to complete */
196 k_sem_take(&data->device_sync_sem, I2C_TRANSFER_TIMEOUT_MSEC);
197
198 /* Return an error if the transfer didn't complete
199 * successfully. e.g., nak, timeout, lost arbitration
200 */
201 if (data->callback_status != kStatus_Success) {
202 I2C_MasterTransferAbort(base, &data->handle);
203 ret = -EIO;
204 break;
205 }
206
207 /* Move to the next message */
208 msgs++;
209 }
210
211 k_sem_give(&data->lock);
212
213 return ret;
214 }
215
216 #if CONFIG_I2C_MCUX_FLEXCOMM_BUS_RECOVERY
mcux_flexcomm_bitbang_set_scl(void * io_context,int state)217 static void mcux_flexcomm_bitbang_set_scl(void *io_context, int state)
218 {
219 const struct mcux_flexcomm_config *config = io_context;
220
221 gpio_pin_set_dt(&config->scl, state);
222 }
223
mcux_flexcomm_bitbang_set_sda(void * io_context,int state)224 static void mcux_flexcomm_bitbang_set_sda(void *io_context, int state)
225 {
226 const struct mcux_flexcomm_config *config = io_context;
227
228 gpio_pin_set_dt(&config->sda, state);
229 }
230
mcux_flexcomm_bitbang_get_sda(void * io_context)231 static int mcux_flexcomm_bitbang_get_sda(void *io_context)
232 {
233 const struct mcux_flexcomm_config *config = io_context;
234
235 return gpio_pin_get_dt(&config->sda) == 0 ? 0 : 1;
236 }
237
mcux_flexcomm_recover_bus(const struct device * dev)238 static int mcux_flexcomm_recover_bus(const struct device *dev)
239 {
240 const struct mcux_flexcomm_config *config = dev->config;
241 struct mcux_flexcomm_data *data = dev->data;
242 struct i2c_bitbang bitbang_ctx;
243 struct i2c_bitbang_io bitbang_io = {
244 .set_scl = mcux_flexcomm_bitbang_set_scl,
245 .set_sda = mcux_flexcomm_bitbang_set_sda,
246 .get_sda = mcux_flexcomm_bitbang_get_sda,
247 };
248 uint32_t bitrate_cfg;
249 int error = 0;
250
251 if (!gpio_is_ready_dt(&config->scl)) {
252 LOG_ERR("SCL GPIO device not ready");
253 return -EIO;
254 }
255
256 if (!gpio_is_ready_dt(&config->sda)) {
257 LOG_ERR("SDA GPIO device not ready");
258 return -EIO;
259 }
260
261 k_sem_take(&data->lock, K_FOREVER);
262
263 error = gpio_pin_configure_dt(&config->scl, GPIO_OUTPUT_HIGH);
264 if (error != 0) {
265 LOG_ERR("failed to configure SCL GPIO (err %d)", error);
266 goto restore;
267 }
268
269 error = gpio_pin_configure_dt(&config->sda, GPIO_OUTPUT_HIGH);
270 if (error != 0) {
271 LOG_ERR("failed to configure SDA GPIO (err %d)", error);
272 goto restore;
273 }
274
275 i2c_bitbang_init(&bitbang_ctx, &bitbang_io, (void *)config);
276
277 bitrate_cfg = i2c_map_dt_bitrate(config->bitrate) | I2C_MODE_CONTROLLER;
278 error = i2c_bitbang_configure(&bitbang_ctx, bitrate_cfg);
279 if (error != 0) {
280 LOG_ERR("failed to configure I2C bitbang (err %d)", error);
281 goto restore;
282 }
283
284 error = i2c_bitbang_recover_bus(&bitbang_ctx);
285 if (error != 0) {
286 LOG_ERR("failed to recover bus (err %d)", error);
287 goto restore;
288 }
289
290 restore:
291 (void)pinctrl_apply_state(config->pincfg, PINCTRL_STATE_DEFAULT);
292
293 k_sem_give(&data->lock);
294
295 return error;
296 }
297 #endif /* CONFIG_I2C_MCUX_FLEXCOMM_BUS_RECOVERY */
298
299 #if defined(CONFIG_I2C_TARGET)
300
mcux_flexcomm_find_free_target(struct mcux_flexcomm_data * data)301 static struct mcux_flexcomm_target_data *mcux_flexcomm_find_free_target(
302 struct mcux_flexcomm_data *data)
303 {
304 struct mcux_flexcomm_target_data *target;
305 int i;
306
307 for (i = 0; i < ARRAY_SIZE(data->target_data); i++) {
308 target = &data->target_data[i];
309 if (!target->target_attached) {
310 return target;
311 }
312 }
313 return NULL;
314 }
315
mcux_flexcomm_find_target_by_address(struct mcux_flexcomm_data * data,uint16_t address)316 static struct mcux_flexcomm_target_data *mcux_flexcomm_find_target_by_address(
317 struct mcux_flexcomm_data *data, uint16_t address)
318 {
319 struct mcux_flexcomm_target_data *target;
320 int i;
321
322 for (i = 0; i < ARRAY_SIZE(data->target_data); i++) {
323 target = &data->target_data[i];
324 if (target->target_attached && target->target_cfg->address == address) {
325 return target;
326 }
327 }
328 return NULL;
329 }
330
mcux_flexcomm_setup_i2c_config_address(struct mcux_flexcomm_data * data,struct mcux_flexcomm_target_data * target,bool disabled)331 static int mcux_flexcomm_setup_i2c_config_address(struct mcux_flexcomm_data *data,
332 struct mcux_flexcomm_target_data *target, bool disabled)
333 {
334 i2c_slave_address_t *addr;
335 int idx = -1;
336 int i;
337
338 for (i = 0; i < ARRAY_SIZE(data->target_data); i++) {
339 if (data->target_data[i].target_attached && &data->target_data[i] == target) {
340 idx = i;
341 break;
342 }
343 }
344
345 if (idx < 0) {
346 return -ENODEV;
347 }
348
349 /* This could be just shifting a pointer in the i2c_cfg struct */
350 /* However would be less readable and error prone if the struct changes */
351 switch (idx) {
352 case 0:
353 addr = &data->i2c_cfg.address0;
354 break;
355 case 1:
356 addr = &data->i2c_cfg.address1;
357 break;
358 case 2:
359 addr = &data->i2c_cfg.address2;
360 break;
361 case 3:
362 addr = &data->i2c_cfg.address3;
363 break;
364 default:
365 return -1;
366 }
367
368 addr->address = target->target_cfg->address;
369 addr->addressDisable = disabled;
370
371 return 0;
372 }
373
i2c_target_transfer_callback(I2C_Type * base,volatile i2c_slave_transfer_t * transfer,void * userData)374 static void i2c_target_transfer_callback(I2C_Type *base,
375 volatile i2c_slave_transfer_t *transfer, void *userData)
376 {
377 /* Convert 8-bit received address to 7-bit address */
378 uint8_t address = transfer->receivedAddress >> 1;
379 struct mcux_flexcomm_data *data = userData;
380 struct mcux_flexcomm_target_data *target;
381 const struct i2c_target_callbacks *target_cb;
382 static uint8_t rxVal, txVal;
383
384 ARG_UNUSED(base);
385
386 target = mcux_flexcomm_find_target_by_address(data, address);
387 if (!target) {
388 LOG_ERR("No target found for address: 0x%x", address);
389 return;
390 }
391
392 target_cb = target->target_cfg->callbacks;
393
394 switch (transfer->event) {
395 case kI2C_SlaveTransmitEvent:
396 /* request to provide data to transmit */
397 if (target->first_read && target_cb->read_requested) {
398 target->first_read = false;
399 target_cb->read_requested(target->target_cfg, &txVal);
400 } else if (target_cb->read_processed) {
401 target_cb->read_processed(target->target_cfg, &txVal);
402 }
403
404 transfer->txData = &txVal;
405 transfer->txSize = 1;
406 break;
407
408 case kI2C_SlaveReceiveEvent:
409 /* request to provide a buffer in which to place received data */
410 if (target->first_write && target_cb->write_requested) {
411 target_cb->write_requested(target->target_cfg);
412 target->first_write = false;
413 }
414
415 transfer->rxData = &rxVal;
416 transfer->rxSize = 1;
417 target->is_write = true;
418 break;
419
420 case kI2C_SlaveCompletionEvent:
421 /* called after every transferred byte */
422 if (target->is_write && target_cb->write_received) {
423 target_cb->write_received(target->target_cfg, rxVal);
424 target->is_write = false;
425 }
426 break;
427
428 case kI2C_SlaveDeselectedEvent:
429 if (target_cb->stop) {
430 target_cb->stop(target->target_cfg);
431 }
432
433 target->first_read = true;
434 target->first_write = true;
435 break;
436
437 default:
438 LOG_INF("Unhandled event: %d", transfer->event);
439 break;
440 }
441 }
442
mcux_flexcomm_setup_slave_config(const struct device * dev)443 static int mcux_flexcomm_setup_slave_config(const struct device *dev)
444 {
445 const struct mcux_flexcomm_config *config = dev->config;
446 struct mcux_flexcomm_data *data = dev->data;
447 I2C_Type *base = config->base;
448 uint32_t clock_freq;
449
450 /* Get the clock frequency */
451 if (clock_control_get_rate(config->clock_dev, config->clock_subsys,
452 &clock_freq)) {
453 return -EINVAL;
454 }
455
456 I2C_SlaveInit(base, &data->i2c_cfg, clock_freq);
457 I2C_SlaveTransferCreateHandle(base, &data->target_handle,
458 i2c_target_transfer_callback, data);
459 I2C_SlaveTransferNonBlocking(base, &data->target_handle,
460 kI2C_SlaveCompletionEvent | kI2C_SlaveTransmitEvent |
461 kI2C_SlaveReceiveEvent | kI2C_SlaveDeselectedEvent);
462
463 return 0;
464 }
465
mcux_flexcomm_target_register(const struct device * dev,struct i2c_target_config * target_config)466 int mcux_flexcomm_target_register(const struct device *dev,
467 struct i2c_target_config *target_config)
468 {
469 const struct mcux_flexcomm_config *config = dev->config;
470 struct mcux_flexcomm_data *data = dev->data;
471 struct mcux_flexcomm_target_data *target;
472 I2C_Type *base = config->base;
473
474 I2C_MasterDeinit(base);
475
476 if (!target_config) {
477 return -EINVAL;
478 }
479
480 target = mcux_flexcomm_find_free_target(data);
481 if (!target) {
482 return -EBUSY;
483 }
484
485 target->target_cfg = target_config;
486 target->target_attached = true;
487 target->first_read = true;
488 target->first_write = true;
489
490 if (data->nr_targets_attached == 0) {
491 I2C_SlaveGetDefaultConfig(&data->i2c_cfg);
492 }
493
494 if (mcux_flexcomm_setup_i2c_config_address(data, target, false) < 0) {
495 return -EINVAL;
496 }
497
498 if (mcux_flexcomm_setup_slave_config(dev) < 0) {
499 return -EINVAL;
500 }
501
502 data->nr_targets_attached++;
503 return 0;
504 }
505
mcux_flexcomm_target_unregister(const struct device * dev,struct i2c_target_config * target_config)506 int mcux_flexcomm_target_unregister(const struct device *dev,
507 struct i2c_target_config *target_config)
508 {
509 const struct mcux_flexcomm_config *config = dev->config;
510 struct mcux_flexcomm_data *data = dev->data;
511 struct mcux_flexcomm_target_data *target;
512 I2C_Type *base = config->base;
513
514 target = mcux_flexcomm_find_target_by_address(data, target_config->address);
515 if (!target || !target->target_attached) {
516 return -EINVAL;
517 }
518
519 if (mcux_flexcomm_setup_i2c_config_address(data, target, true) < 0) {
520 return -EINVAL;
521 }
522
523 target->target_cfg = NULL;
524 target->target_attached = false;
525
526 data->nr_targets_attached--;
527
528 if (data->nr_targets_attached > 0) {
529 /* still slaves attached, reconfigure the I2C peripheral after address removal */
530 if (mcux_flexcomm_setup_slave_config(dev) < 0) {
531 return -EINVAL;
532 }
533
534 } else {
535 I2C_SlaveDeinit(base);
536 }
537
538 return 0;
539 }
540 #endif
541
mcux_flexcomm_isr(const struct device * dev)542 static void mcux_flexcomm_isr(const struct device *dev)
543 {
544 const struct mcux_flexcomm_config *config = dev->config;
545 struct mcux_flexcomm_data *data = dev->data;
546 I2C_Type *base = config->base;
547
548 #if defined(CONFIG_I2C_TARGET)
549 if (data->nr_targets_attached > 0) {
550 I2C_SlaveTransferHandleIRQ(base, &data->target_handle);
551 return;
552 }
553 #endif
554
555 I2C_MasterTransferHandleIRQ(base, &data->handle);
556 }
557
mcux_flexcomm_init(const struct device * dev)558 static int mcux_flexcomm_init(const struct device *dev)
559 {
560 const struct mcux_flexcomm_config *config = dev->config;
561 struct mcux_flexcomm_data *data = dev->data;
562 I2C_Type *base = config->base;
563 uint32_t clock_freq, bitrate_cfg;
564 i2c_master_config_t master_config;
565 int error;
566
567 if (!device_is_ready(config->reset.dev)) {
568 LOG_ERR("Reset device not ready");
569 return -ENODEV;
570 }
571
572 error = reset_line_toggle(config->reset.dev, config->reset.id);
573 if (error) {
574 return error;
575 }
576
577 error = pinctrl_apply_state(config->pincfg, PINCTRL_STATE_DEFAULT);
578 if (error) {
579 return error;
580 }
581
582 k_sem_init(&data->lock, 1, 1);
583 k_sem_init(&data->device_sync_sem, 0, K_SEM_MAX_LIMIT);
584
585 if (!device_is_ready(config->clock_dev)) {
586 LOG_ERR("clock control device not ready");
587 return -ENODEV;
588 }
589
590 /* Get the clock frequency */
591 if (clock_control_get_rate(config->clock_dev, config->clock_subsys,
592 &clock_freq)) {
593 return -EINVAL;
594 }
595
596 I2C_MasterGetDefaultConfig(&master_config);
597 I2C_MasterInit(base, &master_config, clock_freq);
598 I2C_MasterTransferCreateHandle(base, &data->handle,
599 mcux_flexcomm_master_transfer_callback,
600 data);
601
602 bitrate_cfg = i2c_map_dt_bitrate(config->bitrate);
603
604 error = mcux_flexcomm_configure(dev, I2C_MODE_CONTROLLER | bitrate_cfg);
605 if (error) {
606 return error;
607 }
608
609 config->irq_config_func(dev);
610
611 return 0;
612 }
613
614 static DEVICE_API(i2c, mcux_flexcomm_driver_api) = {
615 .configure = mcux_flexcomm_configure,
616 .transfer = mcux_flexcomm_transfer,
617 #if CONFIG_I2C_MCUX_FLEXCOMM_BUS_RECOVERY
618 .recover_bus = mcux_flexcomm_recover_bus,
619 #endif /* CONFIG_I2C_MCUX_FLEXCOMM_BUS_RECOVERY */
620 #if defined(CONFIG_I2C_TARGET)
621 .target_register = mcux_flexcomm_target_register,
622 .target_unregister = mcux_flexcomm_target_unregister,
623 #endif
624 #ifdef CONFIG_I2C_RTIO
625 .iodev_submit = i2c_iodev_submit_fallback,
626 #endif
627 };
628
629 #if CONFIG_I2C_MCUX_FLEXCOMM_BUS_RECOVERY
630 #define I2C_MCUX_FLEXCOMM_SCL_INIT(n) .scl = GPIO_DT_SPEC_INST_GET_OR(n, scl_gpios, {0}),
631 #define I2C_MCUX_FLEXCOMM_SDA_INIT(n) .sda = GPIO_DT_SPEC_INST_GET_OR(n, sda_gpios, {0}),
632 #else
633 #define I2C_MCUX_FLEXCOMM_SCL_INIT(n)
634 #define I2C_MCUX_FLEXCOMM_SDA_INIT(n)
635 #endif /* CONFIG_I2C_MCUX_FLEXCOMM_BUS_RECOVERY */
636
637 #define I2C_MCUX_FLEXCOMM_DEVICE(id) \
638 PINCTRL_DT_INST_DEFINE(id); \
639 static void mcux_flexcomm_config_func_##id(const struct device *dev); \
640 static const struct mcux_flexcomm_config mcux_flexcomm_config_##id = { \
641 .base = (I2C_Type *) DT_INST_REG_ADDR(id), \
642 .clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(id)), \
643 .clock_subsys = \
644 (clock_control_subsys_t)DT_INST_CLOCKS_CELL(id, name),\
645 .irq_config_func = mcux_flexcomm_config_func_##id, \
646 .bitrate = DT_INST_PROP(id, clock_frequency), \
647 .pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(id), \
648 I2C_MCUX_FLEXCOMM_SCL_INIT(id) \
649 I2C_MCUX_FLEXCOMM_SDA_INIT(id) \
650 .reset = RESET_DT_SPEC_INST_GET(id), \
651 }; \
652 static struct mcux_flexcomm_data mcux_flexcomm_data_##id; \
653 I2C_DEVICE_DT_INST_DEFINE(id, \
654 mcux_flexcomm_init, \
655 NULL, \
656 &mcux_flexcomm_data_##id, \
657 &mcux_flexcomm_config_##id, \
658 POST_KERNEL, \
659 CONFIG_I2C_INIT_PRIORITY, \
660 &mcux_flexcomm_driver_api); \
661 static void mcux_flexcomm_config_func_##id(const struct device *dev) \
662 { \
663 IRQ_CONNECT(DT_INST_IRQN(id), \
664 DT_INST_IRQ(id, priority), \
665 mcux_flexcomm_isr, \
666 DEVICE_DT_INST_GET(id), \
667 0); \
668 irq_enable(DT_INST_IRQN(id)); \
669 } \
670
671 DT_INST_FOREACH_STATUS_OKAY(I2C_MCUX_FLEXCOMM_DEVICE)
672