1 /* 2 * Copyright 2018, 2024 NXP 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6 7 #include <zephyr/drivers/spi.h> 8 #include <zephyr/drivers/spi/rtio.h> 9 #include <zephyr/drivers/pinctrl.h> 10 #include <zephyr/drivers/clock_control.h> 11 #include <zephyr/irq.h> 12 13 #include "../spi_context.h" 14 15 #if CONFIG_NXP_LP_FLEXCOMM 16 #include <zephyr/drivers/mfd/nxp_lp_flexcomm.h> 17 #endif 18 19 #include <fsl_lpspi.h> 20 21 /* If any hardware revisions change this, make it into a DT property. 22 * DONT'T make #ifdefs here by platform. 23 */ 24 #define LPSPI_CHIP_SELECT_COUNT 4 25 #define LPSPI_MIN_FRAME_SIZE_BITS 8 26 27 /* Required by DEVICE_MMIO_NAMED_* macros */ 28 #define DEV_CFG(_dev) ((const struct spi_mcux_config *)(_dev)->config) 29 #define DEV_DATA(_dev) ((struct spi_mcux_data *)(_dev)->data) 30 31 /* flag for SDK API for master transfers */ 32 #define LPSPI_MASTER_XFER_CFG_FLAGS(slave) \ 33 kLPSPI_MasterPcsContinuous | (slave << LPSPI_MASTER_PCS_SHIFT) 34 35 struct spi_mcux_config { 36 DEVICE_MMIO_NAMED_ROM(reg_base); 37 const struct device *clock_dev; 38 clock_control_subsys_t clock_subsys; 39 void (*irq_config_func)(const struct device *dev); 40 uint32_t pcs_sck_delay; 41 uint32_t sck_pcs_delay; 42 uint32_t transfer_delay; 43 const struct pinctrl_dev_config *pincfg; 44 lpspi_pin_config_t data_pin_config; 45 bool output_config; 46 uint8_t tx_fifo_size; 47 uint8_t rx_fifo_size; 48 uint8_t irqn; 49 }; 50 51 struct spi_mcux_data { 52 DEVICE_MMIO_NAMED_RAM(reg_base); 53 const struct device *dev; 54 struct spi_context ctx; 55 void *driver_data; 56 size_t transfer_len; 57 }; 58 59 /* common configure function that verifies spi_cfg validity and set up configuration parameters */ 60 int spi_mcux_configure(const struct device *dev, const struct spi_config *spi_cfg); 61 62 /* Does these things: 63 * Set data.dev 64 * Check clocks device is ready 65 * Configure cs gpio pin if needed 66 * Mux pinctrl to lpspi 67 * Enable LPSPI IRQ at system level 68 */ 69 int spi_nxp_init_common(const struct device *dev); 70 71 /* common api function for now */ 72 int spi_mcux_release(const struct device *dev, const struct spi_config *spi_cfg); 73 74 void lpspi_wait_tx_fifo_empty(const struct device *dev); 75 76 /* Argument to MCUX SDK IRQ handler */ 77 #define LPSPI_IRQ_HANDLE_ARG COND_CODE_1(CONFIG_NXP_LP_FLEXCOMM, (LPSPI_GetInstance(base)), (base)) 78 79 #define SPI_MCUX_LPSPI_IRQ_FUNC_LP_FLEXCOMM(n) \ 80 nxp_lp_flexcomm_setirqhandler(DEVICE_DT_GET(DT_INST_PARENT(n)), DEVICE_DT_INST_GET(n), \ 81 LP_FLEXCOMM_PERIPH_LPSPI, lpspi_isr); 82 83 #define SPI_MCUX_LPSPI_IRQ_FUNC_DISTINCT(n) \ 84 IRQ_CONNECT(DT_INST_IRQN(n), DT_INST_IRQ(n, priority), lpspi_isr, DEVICE_DT_INST_GET(n), \ 85 0); \ 86 irq_enable(DT_INST_IRQN(n)); 87 88 #define SPI_MCUX_LPSPI_IRQ_FUNC(n) COND_CODE_1(DT_NODE_HAS_COMPAT(DT_INST_PARENT(n), \ 89 nxp_lp_flexcomm), \ 90 (SPI_MCUX_LPSPI_IRQ_FUNC_LP_FLEXCOMM(n)), \ 91 (SPI_MCUX_LPSPI_IRQ_FUNC_DISTINCT(n))) 92 93 #define LPSPI_IRQN(n) COND_CODE_1(DT_NODE_HAS_COMPAT(DT_INST_PARENT(n), nxp_lp_flexcomm), \ 94 (DT_IRQN(DT_INST_PARENT(n))), (DT_INST_IRQN(n))) 95 96 #define SPI_MCUX_LPSPI_CONFIG_INIT(n) \ 97 static const struct spi_mcux_config spi_mcux_config_##n = { \ 98 DEVICE_MMIO_NAMED_ROM_INIT(reg_base, DT_DRV_INST(n)), \ 99 .clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(n)), \ 100 .clock_subsys = (clock_control_subsys_t)DT_INST_CLOCKS_CELL(n, name), \ 101 .irq_config_func = spi_mcux_config_func_##n, \ 102 .pcs_sck_delay = UTIL_AND(DT_INST_NODE_HAS_PROP(n, pcs_sck_delay), \ 103 DT_INST_PROP(n, pcs_sck_delay)), \ 104 .sck_pcs_delay = UTIL_AND(DT_INST_NODE_HAS_PROP(n, sck_pcs_delay), \ 105 DT_INST_PROP(n, sck_pcs_delay)), \ 106 .transfer_delay = UTIL_AND(DT_INST_NODE_HAS_PROP(n, transfer_delay), \ 107 DT_INST_PROP(n, transfer_delay)), \ 108 .pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ 109 .data_pin_config = DT_INST_ENUM_IDX(n, data_pin_config), \ 110 .output_config = DT_INST_PROP(n, tristate_output), \ 111 .rx_fifo_size = (uint8_t)DT_INST_PROP(n, rx_fifo_size), \ 112 .tx_fifo_size = (uint8_t)DT_INST_PROP(n, tx_fifo_size), \ 113 .irqn = (uint8_t)LPSPI_IRQN(n), \ 114 }; 115 116 #define SPI_NXP_LPSPI_COMMON_INIT(n) \ 117 PINCTRL_DT_INST_DEFINE(n); \ 118 \ 119 static void spi_mcux_config_func_##n(const struct device *dev) \ 120 { \ 121 SPI_MCUX_LPSPI_IRQ_FUNC(n) \ 122 } 123 124 #define SPI_NXP_LPSPI_COMMON_DATA_INIT(n) \ 125 SPI_CONTEXT_INIT_LOCK(spi_mcux_data_##n, ctx), \ 126 SPI_CONTEXT_INIT_SYNC(spi_mcux_data_##n, ctx), \ 127 SPI_CONTEXT_CS_GPIOS_INITIALIZE(DT_DRV_INST(n), ctx) 128 129 #define SPI_NXP_LPSPI_HAS_DMAS(n) \ 130 UTIL_AND(DT_INST_DMAS_HAS_NAME(n, tx), DT_INST_DMAS_HAS_NAME(n, rx)) 131