Mikhail Siomin | 8dbfdd6 | 2024-03-11 23:45:36 +0300 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) 2024, STRIM, ALC |
Anke Xiao | 04ae22e | 2024-08-12 16:11:44 +0800 | [diff] [blame] | 3 | * Copyright 2024 NXP |
Mikhail Siomin | 8dbfdd6 | 2024-03-11 23:45:36 +0300 | [diff] [blame] | 4 | * |
| 5 | * SPDX-License-Identifier: Apache-2.0 |
| 6 | */ |
| 7 | |
| 8 | #define DT_DRV_COMPAT nxp_flexio_spi |
| 9 | |
| 10 | #include <errno.h> |
| 11 | #include <zephyr/drivers/spi.h> |
Luis Ubieda | 64a038a | 2024-08-16 01:09:59 -0400 | [diff] [blame] | 12 | #include <zephyr/drivers/spi/rtio.h> |
Mikhail Siomin | 8dbfdd6 | 2024-03-11 23:45:36 +0300 | [diff] [blame] | 13 | #include <zephyr/drivers/clock_control.h> |
| 14 | #include <fsl_flexio_spi.h> |
| 15 | #include <zephyr/logging/log.h> |
| 16 | #include <zephyr/drivers/pinctrl.h> |
| 17 | #include <zephyr/drivers/misc/nxp_flexio/nxp_flexio.h> |
| 18 | |
| 19 | LOG_MODULE_REGISTER(spi_mcux_flexio_spi, CONFIG_SPI_LOG_LEVEL); |
| 20 | |
| 21 | #include "spi_context.h" |
| 22 | |
| 23 | |
| 24 | struct spi_mcux_flexio_config { |
| 25 | FLEXIO_SPI_Type *flexio_spi; |
| 26 | const struct device *flexio_dev; |
| 27 | const struct pinctrl_dev_config *pincfg; |
| 28 | const struct nxp_flexio_child *child; |
| 29 | }; |
| 30 | |
| 31 | struct spi_mcux_flexio_data { |
| 32 | const struct device *dev; |
| 33 | flexio_spi_master_handle_t handle; |
| 34 | struct spi_context ctx; |
| 35 | size_t transfer_len; |
| 36 | uint8_t transfer_flags; |
| 37 | }; |
| 38 | |
| 39 | |
| 40 | static void spi_mcux_transfer_next_packet(const struct device *dev) |
| 41 | { |
| 42 | const struct spi_mcux_flexio_config *config = dev->config; |
| 43 | struct spi_mcux_flexio_data *data = dev->data; |
| 44 | struct spi_context *ctx = &data->ctx; |
| 45 | flexio_spi_transfer_t transfer; |
| 46 | status_t status; |
| 47 | |
| 48 | if ((ctx->tx_len == 0) && (ctx->rx_len == 0)) { |
| 49 | /* nothing left to rx or tx, we're done! */ |
| 50 | spi_context_cs_control(&data->ctx, false); |
| 51 | spi_context_complete(&data->ctx, dev, 0); |
| 52 | return; |
| 53 | } |
| 54 | |
| 55 | transfer.flags = kFLEXIO_SPI_csContinuous | data->transfer_flags; |
| 56 | |
| 57 | if (ctx->tx_len == 0) { |
| 58 | /* rx only, nothing to tx */ |
| 59 | transfer.txData = NULL; |
| 60 | transfer.rxData = ctx->rx_buf; |
| 61 | transfer.dataSize = ctx->rx_len; |
| 62 | } else if (ctx->rx_len == 0) { |
| 63 | /* tx only, nothing to rx */ |
| 64 | transfer.txData = (uint8_t *) ctx->tx_buf; |
| 65 | transfer.rxData = NULL; |
| 66 | transfer.dataSize = ctx->tx_len; |
| 67 | } else if (ctx->tx_len == ctx->rx_len) { |
| 68 | /* rx and tx are the same length */ |
| 69 | transfer.txData = (uint8_t *) ctx->tx_buf; |
| 70 | transfer.rxData = ctx->rx_buf; |
| 71 | transfer.dataSize = ctx->tx_len; |
| 72 | } else if (ctx->tx_len > ctx->rx_len) { |
| 73 | /* Break up the tx into multiple transfers so we don't have to |
| 74 | * rx into a longer intermediate buffer. Leave chip select |
| 75 | * active between transfers. |
| 76 | */ |
| 77 | transfer.txData = (uint8_t *) ctx->tx_buf; |
| 78 | transfer.rxData = ctx->rx_buf; |
| 79 | transfer.dataSize = ctx->rx_len; |
| 80 | } else { |
| 81 | /* Break up the rx into multiple transfers so we don't have to |
| 82 | * tx from a longer intermediate buffer. Leave chip select |
| 83 | * active between transfers. |
| 84 | */ |
| 85 | transfer.txData = (uint8_t *) ctx->tx_buf; |
| 86 | transfer.rxData = ctx->rx_buf; |
| 87 | transfer.dataSize = ctx->tx_len; |
| 88 | } |
| 89 | |
| 90 | data->transfer_len = transfer.dataSize; |
| 91 | |
| 92 | status = FLEXIO_SPI_MasterTransferNonBlocking(config->flexio_spi, &data->handle, |
| 93 | &transfer); |
| 94 | if (status != kStatus_Success) { |
| 95 | LOG_ERR("Transfer could not start"); |
| 96 | } |
| 97 | } |
| 98 | |
| 99 | static int spi_mcux_flexio_isr(void *user_data) |
| 100 | { |
| 101 | const struct device *dev = (const struct device *)user_data; |
| 102 | const struct spi_mcux_flexio_config *config = dev->config; |
| 103 | struct spi_mcux_flexio_data *data = dev->data; |
| 104 | |
Anke Xiao | 04ae22e | 2024-08-12 16:11:44 +0800 | [diff] [blame] | 105 | #if defined(CONFIG_SOC_SERIES_KE1XZ) |
| 106 | /* Wait until data transfer complete. */ |
| 107 | WAIT_FOR((0U == (FLEXIO_SPI_GetStatusFlags(config->flexio_spi) |
| 108 | & (uint32_t)kFLEXIO_SPI_TxBufferEmptyFlag)), 100, NULL); |
| 109 | #endif |
Mikhail Siomin | 8dbfdd6 | 2024-03-11 23:45:36 +0300 | [diff] [blame] | 110 | FLEXIO_SPI_MasterTransferHandleIRQ(config->flexio_spi, &data->handle); |
| 111 | |
| 112 | return 0; |
| 113 | } |
| 114 | |
| 115 | static void spi_mcux_master_transfer_callback(FLEXIO_SPI_Type *flexio_spi, |
| 116 | flexio_spi_master_handle_t *handle, status_t status, void *userData) |
| 117 | { |
| 118 | struct spi_mcux_flexio_data *data = userData; |
| 119 | |
| 120 | spi_context_update_tx(&data->ctx, 1, data->transfer_len); |
| 121 | spi_context_update_rx(&data->ctx, 1, data->transfer_len); |
| 122 | |
| 123 | spi_mcux_transfer_next_packet(data->dev); |
| 124 | } |
| 125 | |
| 126 | static void spi_flexio_master_init(FLEXIO_SPI_Type *base, flexio_spi_master_config_t *masterConfig, |
| 127 | uint8_t pol, uint32_t srcClock_Hz) |
| 128 | { |
| 129 | assert(base != NULL); |
| 130 | assert(masterConfig != NULL); |
| 131 | |
| 132 | flexio_shifter_config_t shifterConfig; |
| 133 | flexio_timer_config_t timerConfig; |
| 134 | uint32_t ctrlReg = 0; |
| 135 | uint16_t timerDiv = 0; |
| 136 | uint16_t timerCmp = 0; |
| 137 | |
| 138 | /* Clear the shifterConfig & timerConfig struct. */ |
| 139 | (void)memset(&shifterConfig, 0, sizeof(shifterConfig)); |
| 140 | (void)memset(&timerConfig, 0, sizeof(timerConfig)); |
| 141 | |
| 142 | /* Configure FLEXIO SPI Master */ |
| 143 | ctrlReg = base->flexioBase->CTRL; |
| 144 | ctrlReg &= ~(FLEXIO_CTRL_DOZEN_MASK | FLEXIO_CTRL_DBGE_MASK | |
| 145 | FLEXIO_CTRL_FASTACC_MASK | FLEXIO_CTRL_FLEXEN_MASK); |
| 146 | ctrlReg |= (FLEXIO_CTRL_DBGE(masterConfig->enableInDebug) | |
| 147 | FLEXIO_CTRL_FASTACC(masterConfig->enableFastAccess) | |
| 148 | FLEXIO_CTRL_FLEXEN(masterConfig->enableMaster)); |
| 149 | if (!masterConfig->enableInDoze) { |
| 150 | ctrlReg |= FLEXIO_CTRL_DOZEN_MASK; |
| 151 | } |
| 152 | |
| 153 | base->flexioBase->CTRL = ctrlReg; |
| 154 | |
| 155 | /* Do hardware configuration. */ |
| 156 | /* 1. Configure the shifter 0 for tx. */ |
| 157 | shifterConfig.timerSelect = base->timerIndex[0]; |
| 158 | shifterConfig.pinConfig = kFLEXIO_PinConfigOutput; |
| 159 | shifterConfig.pinSelect = base->SDOPinIndex; |
| 160 | shifterConfig.pinPolarity = kFLEXIO_PinActiveHigh; |
| 161 | shifterConfig.shifterMode = kFLEXIO_ShifterModeTransmit; |
| 162 | shifterConfig.inputSource = kFLEXIO_ShifterInputFromPin; |
| 163 | if (masterConfig->phase == kFLEXIO_SPI_ClockPhaseFirstEdge) { |
| 164 | shifterConfig.timerPolarity = kFLEXIO_ShifterTimerPolarityOnNegitive; |
| 165 | shifterConfig.shifterStop = kFLEXIO_ShifterStopBitDisable; |
| 166 | shifterConfig.shifterStart = kFLEXIO_ShifterStartBitDisabledLoadDataOnEnable; |
| 167 | } else { |
| 168 | shifterConfig.timerPolarity = kFLEXIO_ShifterTimerPolarityOnPositive; |
| 169 | shifterConfig.shifterStop = kFLEXIO_ShifterStopBitLow; |
| 170 | shifterConfig.shifterStart = kFLEXIO_ShifterStartBitDisabledLoadDataOnShift; |
| 171 | } |
| 172 | |
| 173 | FLEXIO_SetShifterConfig(base->flexioBase, base->shifterIndex[0], &shifterConfig); |
| 174 | |
| 175 | /* 2. Configure the shifter 1 for rx. */ |
| 176 | shifterConfig.timerSelect = base->timerIndex[0]; |
| 177 | shifterConfig.pinConfig = kFLEXIO_PinConfigOutputDisabled; |
| 178 | shifterConfig.pinSelect = base->SDIPinIndex; |
| 179 | shifterConfig.pinPolarity = kFLEXIO_PinActiveHigh; |
| 180 | shifterConfig.shifterMode = kFLEXIO_ShifterModeReceive; |
| 181 | shifterConfig.inputSource = kFLEXIO_ShifterInputFromPin; |
| 182 | shifterConfig.shifterStop = kFLEXIO_ShifterStopBitDisable; |
| 183 | shifterConfig.shifterStart = kFLEXIO_ShifterStartBitDisabledLoadDataOnEnable; |
| 184 | if (masterConfig->phase == kFLEXIO_SPI_ClockPhaseFirstEdge) { |
| 185 | shifterConfig.timerPolarity = kFLEXIO_ShifterTimerPolarityOnPositive; |
| 186 | } else { |
| 187 | shifterConfig.timerPolarity = kFLEXIO_ShifterTimerPolarityOnNegitive; |
| 188 | } |
| 189 | |
| 190 | FLEXIO_SetShifterConfig(base->flexioBase, base->shifterIndex[1], &shifterConfig); |
| 191 | |
| 192 | /*3. Configure the timer 0 for SCK. */ |
| 193 | timerConfig.triggerSelect = FLEXIO_TIMER_TRIGGER_SEL_SHIFTnSTAT(base->shifterIndex[0]); |
| 194 | timerConfig.triggerPolarity = kFLEXIO_TimerTriggerPolarityActiveLow; |
| 195 | timerConfig.triggerSource = kFLEXIO_TimerTriggerSourceInternal; |
| 196 | timerConfig.pinConfig = kFLEXIO_PinConfigOutput; |
| 197 | timerConfig.pinSelect = base->SCKPinIndex; |
| 198 | timerConfig.pinPolarity = pol ? kFLEXIO_PinActiveLow : kFLEXIO_PinActiveHigh; |
| 199 | timerConfig.timerMode = kFLEXIO_TimerModeDual8BitBaudBit; |
| 200 | timerConfig.timerOutput = kFLEXIO_TimerOutputZeroNotAffectedByReset; |
| 201 | timerConfig.timerDecrement = kFLEXIO_TimerDecSrcOnFlexIOClockShiftTimerOutput; |
| 202 | timerConfig.timerReset = kFLEXIO_TimerResetNever; |
| 203 | timerConfig.timerDisable = kFLEXIO_TimerDisableOnTimerCompare; |
| 204 | timerConfig.timerEnable = kFLEXIO_TimerEnableOnTriggerHigh; |
| 205 | timerConfig.timerStop = kFLEXIO_TimerStopBitEnableOnTimerDisable; |
| 206 | timerConfig.timerStart = kFLEXIO_TimerStartBitEnabled; |
| 207 | /* Low 8-bits are used to configure baudrate. */ |
| 208 | timerDiv = (uint16_t)(srcClock_Hz / masterConfig->baudRate_Bps); |
| 209 | timerDiv = timerDiv / 2U - 1U; |
| 210 | /* High 8-bits are used to configure shift clock edges(transfer width). */ |
| 211 | timerCmp = ((uint16_t)masterConfig->dataMode * 2U - 1U) << 8U; |
| 212 | timerCmp |= timerDiv; |
| 213 | |
| 214 | timerConfig.timerCompare = timerCmp; |
| 215 | |
| 216 | FLEXIO_SetTimerConfig(base->flexioBase, base->timerIndex[0], &timerConfig); |
| 217 | } |
| 218 | |
| 219 | static int spi_mcux_flexio_configure(const struct device *dev, |
| 220 | const struct spi_config *spi_cfg) |
| 221 | { |
| 222 | const struct spi_mcux_flexio_config *config = dev->config; |
| 223 | struct spi_mcux_flexio_data *data = dev->data; |
| 224 | |
| 225 | flexio_spi_master_config_t master_config; |
| 226 | uint32_t clock_freq; |
| 227 | uint32_t word_size; |
| 228 | |
| 229 | if (spi_context_configured(&data->ctx, spi_cfg)) { |
| 230 | /* This configuration is already in use */ |
| 231 | return 0; |
| 232 | } |
| 233 | |
| 234 | if (spi_cfg->operation & SPI_HALF_DUPLEX) { |
| 235 | LOG_ERR("Half-duplex not supported"); |
| 236 | return -ENOTSUP; |
| 237 | } |
| 238 | |
| 239 | if (SPI_OP_MODE_GET(spi_cfg->operation) != SPI_OP_MODE_MASTER) { |
| 240 | LOG_ERR("Mode Slave not supported"); |
| 241 | return -ENOTSUP; |
| 242 | } |
| 243 | |
| 244 | FLEXIO_SPI_MasterGetDefaultConfig(&master_config); |
| 245 | |
| 246 | word_size = SPI_WORD_SIZE_GET(spi_cfg->operation); |
| 247 | if ((word_size != 8) && (word_size != 16) && (word_size != 32)) { |
| 248 | LOG_ERR("Word size %d must be 8, 16 or 32", word_size); |
| 249 | return -EINVAL; |
| 250 | } |
| 251 | master_config.dataMode = word_size; |
| 252 | |
| 253 | if (spi_cfg->operation & SPI_TRANSFER_LSB) { |
| 254 | if (word_size == 8) { |
| 255 | data->transfer_flags = kFLEXIO_SPI_8bitLsb; |
| 256 | } else if (word_size == 16) { |
| 257 | data->transfer_flags = kFLEXIO_SPI_16bitLsb; |
| 258 | } else { |
| 259 | data->transfer_flags = kFLEXIO_SPI_32bitLsb; |
| 260 | } |
| 261 | } else { |
| 262 | if (word_size == 8) { |
| 263 | data->transfer_flags = kFLEXIO_SPI_8bitMsb; |
| 264 | } else if (word_size == 16) { |
| 265 | data->transfer_flags = kFLEXIO_SPI_16bitMsb; |
| 266 | } else { |
| 267 | data->transfer_flags = kFLEXIO_SPI_32bitMsb; |
| 268 | } |
| 269 | } |
| 270 | |
| 271 | if (nxp_flexio_get_rate(config->flexio_dev, &clock_freq)) { |
| 272 | return -EINVAL; |
| 273 | } |
| 274 | |
| 275 | master_config.phase = |
| 276 | (SPI_MODE_GET(spi_cfg->operation) & SPI_MODE_CPHA) |
| 277 | ? kFLEXIO_SPI_ClockPhaseSecondEdge |
| 278 | : kFLEXIO_SPI_ClockPhaseFirstEdge; |
| 279 | |
| 280 | master_config.baudRate_Bps = spi_cfg->frequency; |
| 281 | spi_flexio_master_init(config->flexio_spi, &master_config, |
| 282 | (SPI_MODE_GET(spi_cfg->operation) & SPI_MODE_CPOL), clock_freq); |
| 283 | |
| 284 | FLEXIO_SPI_MasterTransferCreateHandle(config->flexio_spi, &data->handle, |
| 285 | spi_mcux_master_transfer_callback, |
| 286 | data); |
| 287 | /* No SetDummyData() for FlexIO_SPI */ |
| 288 | |
| 289 | data->ctx.config = spi_cfg; |
| 290 | |
| 291 | return 0; |
| 292 | } |
| 293 | |
| 294 | |
| 295 | static int transceive(const struct device *dev, |
| 296 | const struct spi_config *spi_cfg, |
| 297 | const struct spi_buf_set *tx_bufs, |
| 298 | const struct spi_buf_set *rx_bufs, |
| 299 | bool asynchronous, |
| 300 | spi_callback_t cb, |
| 301 | void *userdata) |
| 302 | { |
| 303 | const struct spi_mcux_flexio_config *config = dev->config; |
| 304 | struct spi_mcux_flexio_data *data = dev->data; |
| 305 | int ret; |
| 306 | |
| 307 | spi_context_lock(&data->ctx, asynchronous, cb, userdata, spi_cfg); |
| 308 | |
| 309 | nxp_flexio_lock(config->flexio_dev); |
| 310 | ret = spi_mcux_flexio_configure(dev, spi_cfg); |
| 311 | nxp_flexio_unlock(config->flexio_dev); |
| 312 | if (ret) { |
| 313 | goto out; |
| 314 | } |
| 315 | |
| 316 | spi_context_buffers_setup(&data->ctx, tx_bufs, rx_bufs, 1); |
| 317 | |
| 318 | spi_context_cs_control(&data->ctx, true); |
| 319 | |
| 320 | nxp_flexio_lock(config->flexio_dev); |
| 321 | nxp_flexio_irq_disable(config->flexio_dev); |
| 322 | |
| 323 | spi_mcux_transfer_next_packet(dev); |
| 324 | |
| 325 | nxp_flexio_irq_enable(config->flexio_dev); |
| 326 | nxp_flexio_unlock(config->flexio_dev); |
| 327 | |
| 328 | ret = spi_context_wait_for_completion(&data->ctx); |
| 329 | out: |
| 330 | spi_context_release(&data->ctx, ret); |
| 331 | |
| 332 | return ret; |
| 333 | } |
| 334 | |
| 335 | static int spi_mcux_transceive(const struct device *dev, |
| 336 | const struct spi_config *spi_cfg, |
| 337 | const struct spi_buf_set *tx_bufs, |
| 338 | const struct spi_buf_set *rx_bufs) |
| 339 | { |
| 340 | return transceive(dev, spi_cfg, tx_bufs, rx_bufs, false, NULL, NULL); |
| 341 | } |
| 342 | |
| 343 | #ifdef CONFIG_SPI_ASYNC |
| 344 | static int spi_mcux_transceive_async(const struct device *dev, |
| 345 | const struct spi_config *spi_cfg, |
| 346 | const struct spi_buf_set *tx_bufs, |
| 347 | const struct spi_buf_set *rx_bufs, |
| 348 | spi_callback_t cb, |
| 349 | void *userdata) |
| 350 | { |
| 351 | return transceive(dev, spi_cfg, tx_bufs, rx_bufs, true, cb, userdata); |
| 352 | } |
| 353 | #endif /* CONFIG_SPI_ASYNC */ |
| 354 | |
| 355 | static int spi_mcux_release(const struct device *dev, |
| 356 | const struct spi_config *spi_cfg) |
| 357 | { |
| 358 | struct spi_mcux_flexio_data *data = dev->data; |
| 359 | |
| 360 | spi_context_unlock_unconditionally(&data->ctx); |
| 361 | |
| 362 | return 0; |
| 363 | } |
| 364 | |
| 365 | static int spi_mcux_init(const struct device *dev) |
| 366 | { |
| 367 | const struct spi_mcux_flexio_config *config = dev->config; |
| 368 | struct spi_mcux_flexio_data *data = dev->data; |
| 369 | int err; |
| 370 | |
| 371 | err = nxp_flexio_child_attach(config->flexio_dev, config->child); |
| 372 | if (err < 0) { |
| 373 | return err; |
| 374 | } |
| 375 | |
| 376 | err = spi_context_cs_configure_all(&data->ctx); |
| 377 | if (err < 0) { |
| 378 | return err; |
| 379 | } |
| 380 | |
| 381 | spi_context_unlock_unconditionally(&data->ctx); |
| 382 | |
| 383 | data->dev = dev; |
| 384 | |
| 385 | /* TODO: DMA */ |
| 386 | |
| 387 | err = pinctrl_apply_state(config->pincfg, PINCTRL_STATE_DEFAULT); |
| 388 | if (err) { |
| 389 | return err; |
| 390 | } |
| 391 | |
| 392 | spi_context_unlock_unconditionally(&data->ctx); |
| 393 | |
| 394 | return 0; |
| 395 | } |
| 396 | |
| 397 | static const struct spi_driver_api spi_mcux_driver_api = { |
| 398 | .transceive = spi_mcux_transceive, |
| 399 | #ifdef CONFIG_SPI_ASYNC |
| 400 | .transceive_async = spi_mcux_transceive_async, |
| 401 | #endif |
Luis Ubieda | 64a038a | 2024-08-16 01:09:59 -0400 | [diff] [blame] | 402 | #ifdef CONFIG_SPI_RTIO |
| 403 | .iodev_submit = spi_rtio_iodev_default_submit, |
| 404 | #endif |
Mikhail Siomin | 8dbfdd6 | 2024-03-11 23:45:36 +0300 | [diff] [blame] | 405 | .release = spi_mcux_release, |
| 406 | }; |
| 407 | |
| 408 | #define SPI_MCUX_FLEXIO_SPI_INIT(n) \ |
| 409 | PINCTRL_DT_INST_DEFINE(n); \ |
| 410 | \ |
| 411 | static FLEXIO_SPI_Type flexio_spi_##n = { \ |
| 412 | .flexioBase = (FLEXIO_Type *)DT_REG_ADDR(DT_INST_PARENT(n)), \ |
| 413 | .SDOPinIndex = DT_INST_PROP(n, sdo_pin), \ |
| 414 | .SDIPinIndex = DT_INST_PROP(n, sdi_pin), \ |
| 415 | .SCKPinIndex = DT_INST_PROP(n, sck_pin), \ |
| 416 | }; \ |
| 417 | \ |
| 418 | static const struct nxp_flexio_child nxp_flexio_spi_child_##n = { \ |
| 419 | .isr = spi_mcux_flexio_isr, \ |
| 420 | .user_data = (void *)DEVICE_DT_INST_GET(n), \ |
| 421 | .res = { \ |
| 422 | .shifter_index = flexio_spi_##n.shifterIndex, \ |
| 423 | .shifter_count = ARRAY_SIZE(flexio_spi_##n.shifterIndex), \ |
| 424 | .timer_index = flexio_spi_##n.timerIndex, \ |
| 425 | .timer_count = ARRAY_SIZE(flexio_spi_##n.timerIndex) \ |
| 426 | } \ |
| 427 | }; \ |
| 428 | \ |
| 429 | static const struct spi_mcux_flexio_config spi_mcux_flexio_config_##n = { \ |
| 430 | .flexio_spi = &flexio_spi_##n, \ |
| 431 | .flexio_dev = DEVICE_DT_GET(DT_INST_PARENT(n)), \ |
| 432 | .pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ |
| 433 | .child = &nxp_flexio_spi_child_##n, \ |
| 434 | }; \ |
| 435 | \ |
| 436 | static struct spi_mcux_flexio_data spi_mcux_flexio_data_##n = { \ |
| 437 | SPI_CONTEXT_INIT_LOCK(spi_mcux_flexio_data_##n, ctx), \ |
| 438 | SPI_CONTEXT_INIT_SYNC(spi_mcux_flexio_data_##n, ctx), \ |
| 439 | SPI_CONTEXT_CS_GPIOS_INITIALIZE(DT_DRV_INST(n), ctx) \ |
| 440 | }; \ |
| 441 | \ |
Pisit Sawangvonganan | dcd0a27 | 2024-07-06 18:56:05 +0700 | [diff] [blame] | 442 | DEVICE_DT_INST_DEFINE(n, spi_mcux_init, NULL, \ |
Mikhail Siomin | 8dbfdd6 | 2024-03-11 23:45:36 +0300 | [diff] [blame] | 443 | &spi_mcux_flexio_data_##n, \ |
| 444 | &spi_mcux_flexio_config_##n, POST_KERNEL, \ |
| 445 | CONFIG_SPI_INIT_PRIORITY, \ |
| 446 | &spi_mcux_driver_api); \ |
| 447 | |
| 448 | DT_INST_FOREACH_STATUS_OKAY(SPI_MCUX_FLEXIO_SPI_INIT) |