1 /* 2 * Copyright (c) 2016 BayLibre, SAS 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6 7 #ifndef ZEPHYR_DRIVERS_SPI_SPI_LL_STM32_H_ 8 #define ZEPHYR_DRIVERS_SPI_SPI_LL_STM32_H_ 9 10 #include "spi_context.h" 11 12 typedef void (*irq_config_func_t)(const struct device *port); 13 14 /* This symbol takes the value 1 if one of the device instances */ 15 /* is configured in dts with a domain clock */ 16 #if STM32_DT_INST_DEV_DOMAIN_CLOCK_SUPPORT 17 #define STM32_SPI_DOMAIN_CLOCK_SUPPORT 1 18 #else 19 #define STM32_SPI_DOMAIN_CLOCK_SUPPORT 0 20 #endif 21 22 struct spi_stm32_config { 23 SPI_TypeDef *spi; 24 const struct pinctrl_dev_config *pcfg; 25 #ifdef CONFIG_SPI_STM32_INTERRUPT 26 irq_config_func_t irq_config; 27 #endif 28 #if DT_HAS_COMPAT_STATUS_OKAY(st_stm32_spi_subghz) 29 bool use_subghzspi_nss; 30 #endif 31 #if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_spi) 32 int midi_clocks; 33 int mssi_clocks; 34 #endif 35 size_t pclk_len; 36 const struct stm32_pclken *pclken; 37 bool fifo_enabled; 38 }; 39 40 #ifdef CONFIG_SPI_STM32_DMA 41 42 #define SPI_STM32_DMA_ERROR_FLAG 0x01 43 #define SPI_STM32_DMA_RX_DONE_FLAG 0x02 44 #define SPI_STM32_DMA_TX_DONE_FLAG 0x04 45 #define SPI_STM32_DMA_DONE_FLAG \ 46 (SPI_STM32_DMA_RX_DONE_FLAG | SPI_STM32_DMA_TX_DONE_FLAG) 47 48 #define SPI_STM32_DMA_TX 0x01 49 #define SPI_STM32_DMA_RX 0x02 50 51 struct stream { 52 const struct device *dma_dev; 53 uint32_t channel; /* stores the channel for dma or mux */ 54 struct dma_config dma_cfg; 55 struct dma_block_config dma_blk_cfg; 56 uint8_t priority; 57 bool src_addr_increment; 58 bool dst_addr_increment; 59 int fifo_threshold; 60 }; 61 #endif 62 63 struct spi_stm32_data { 64 struct spi_context ctx; 65 #ifdef CONFIG_SPI_STM32_DMA 66 struct k_sem status_sem; 67 volatile uint32_t status_flags; 68 struct stream dma_rx; 69 struct stream dma_tx; 70 #endif /* CONFIG_SPI_STM32_DMA */ 71 bool pm_policy_state_on; 72 }; 73 74 #ifdef CONFIG_SPI_STM32_DMA ll_func_dma_get_reg_addr(SPI_TypeDef * spi,uint32_t location)75static inline uint32_t ll_func_dma_get_reg_addr(SPI_TypeDef *spi, uint32_t location) 76 { 77 #if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_spi) 78 if (location == SPI_STM32_DMA_TX) { 79 /* use direct register location until the LL_SPI_DMA_GetTxRegAddr exists */ 80 return (uint32_t)&(spi->TXDR); 81 } 82 /* use direct register location until the LL_SPI_DMA_GetRxRegAddr exists */ 83 return (uint32_t)&(spi->RXDR); 84 #else 85 ARG_UNUSED(location); 86 return (uint32_t)LL_SPI_DMA_GetRegAddr(spi); 87 #endif /* st_stm32h7_spi */ 88 } 89 90 /* checks that DMA Tx packet is fully transmitted over the SPI */ ll_func_spi_dma_busy(SPI_TypeDef * spi)91static inline uint32_t ll_func_spi_dma_busy(SPI_TypeDef *spi) 92 { 93 #ifdef LL_SPI_SR_TXC 94 return LL_SPI_IsActiveFlag_TXC(spi); 95 #else 96 /* the SPI Tx empty and busy flags are needed */ 97 return (LL_SPI_IsActiveFlag_TXE(spi) && 98 !LL_SPI_IsActiveFlag_BSY(spi)); 99 #endif /* LL_SPI_SR_TXC */ 100 } 101 #endif /* CONFIG_SPI_STM32_DMA */ 102 ll_func_tx_is_not_full(SPI_TypeDef * spi)103static inline uint32_t ll_func_tx_is_not_full(SPI_TypeDef *spi) 104 { 105 #if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_spi) 106 return LL_SPI_IsActiveFlag_TXP(spi); 107 #else 108 return LL_SPI_IsActiveFlag_TXE(spi); 109 #endif /* st_stm32h7_spi */ 110 } 111 ll_func_rx_is_not_empty(SPI_TypeDef * spi)112static inline uint32_t ll_func_rx_is_not_empty(SPI_TypeDef *spi) 113 { 114 #if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_spi) 115 return LL_SPI_IsActiveFlag_RXP(spi); 116 #else 117 return LL_SPI_IsActiveFlag_RXNE(spi); 118 #endif /* st_stm32h7_spi */ 119 } 120 ll_func_enable_int_tx_empty(SPI_TypeDef * spi)121static inline void ll_func_enable_int_tx_empty(SPI_TypeDef *spi) 122 { 123 #if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_spi) 124 LL_SPI_EnableIT_TXP(spi); 125 #else 126 LL_SPI_EnableIT_TXE(spi); 127 #endif /* st_stm32h7_spi */ 128 } 129 ll_func_enable_int_rx_not_empty(SPI_TypeDef * spi)130static inline void ll_func_enable_int_rx_not_empty(SPI_TypeDef *spi) 131 { 132 #if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_spi) 133 LL_SPI_EnableIT_RXP(spi); 134 #else 135 LL_SPI_EnableIT_RXNE(spi); 136 #endif /* st_stm32h7_spi */ 137 } 138 ll_func_enable_int_errors(SPI_TypeDef * spi)139static inline void ll_func_enable_int_errors(SPI_TypeDef *spi) 140 { 141 #if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_spi) 142 LL_SPI_EnableIT_UDR(spi); 143 LL_SPI_EnableIT_OVR(spi); 144 LL_SPI_EnableIT_CRCERR(spi); 145 LL_SPI_EnableIT_FRE(spi); 146 LL_SPI_EnableIT_MODF(spi); 147 #else 148 LL_SPI_EnableIT_ERR(spi); 149 #endif /* st_stm32h7_spi */ 150 } 151 ll_func_disable_int_tx_empty(SPI_TypeDef * spi)152static inline void ll_func_disable_int_tx_empty(SPI_TypeDef *spi) 153 { 154 #if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_spi) 155 LL_SPI_DisableIT_TXP(spi); 156 #else 157 LL_SPI_DisableIT_TXE(spi); 158 #endif /* st_stm32h7_spi */ 159 } 160 ll_func_disable_int_rx_not_empty(SPI_TypeDef * spi)161static inline void ll_func_disable_int_rx_not_empty(SPI_TypeDef *spi) 162 { 163 #if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_spi) 164 LL_SPI_DisableIT_RXP(spi); 165 #else 166 LL_SPI_DisableIT_RXNE(spi); 167 #endif /* st_stm32h7_spi */ 168 } 169 ll_func_disable_int_errors(SPI_TypeDef * spi)170static inline void ll_func_disable_int_errors(SPI_TypeDef *spi) 171 { 172 #if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_spi) 173 LL_SPI_DisableIT_UDR(spi); 174 LL_SPI_DisableIT_OVR(spi); 175 LL_SPI_DisableIT_CRCERR(spi); 176 LL_SPI_DisableIT_FRE(spi); 177 LL_SPI_DisableIT_MODF(spi); 178 #else 179 LL_SPI_DisableIT_ERR(spi); 180 #endif /* st_stm32h7_spi */ 181 } 182 ll_func_spi_is_busy(SPI_TypeDef * spi)183static inline uint32_t ll_func_spi_is_busy(SPI_TypeDef *spi) 184 { 185 #if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_spi) 186 if (LL_SPI_GetTransferSize(spi) == 0) { 187 return LL_SPI_IsActiveFlag_TXC(spi) == 0; 188 } else { 189 return LL_SPI_IsActiveFlag_EOT(spi) == 0; 190 } 191 #else 192 return LL_SPI_IsActiveFlag_BSY(spi); 193 #endif /* st_stm32h7_spi */ 194 } 195 196 /* Header is compiled first, this switch avoid the compiler to lookup for 197 * non-existing LL FIFO functions for SoC without SPI FIFO 198 */ 199 #if DT_HAS_COMPAT_STATUS_OKAY(st_stm32_spi_fifo) ll_func_set_fifo_threshold_8bit(SPI_TypeDef * spi)200static inline void ll_func_set_fifo_threshold_8bit(SPI_TypeDef *spi) 201 { 202 #if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_spi) 203 LL_SPI_SetFIFOThreshold(spi, LL_SPI_FIFO_TH_01DATA); 204 #else 205 LL_SPI_SetRxFIFOThreshold(spi, LL_SPI_RX_FIFO_TH_QUARTER); 206 #endif /* st_stm32h7_spi */ 207 } 208 ll_func_set_fifo_threshold_16bit(SPI_TypeDef * spi)209static inline void ll_func_set_fifo_threshold_16bit(SPI_TypeDef *spi) 210 { 211 #if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_spi) 212 LL_SPI_SetFIFOThreshold(spi, LL_SPI_FIFO_TH_02DATA); 213 #else 214 LL_SPI_SetRxFIFOThreshold(spi, LL_SPI_RX_FIFO_TH_HALF); 215 #endif /* st_stm32h7_spi */ 216 } 217 #endif /* st_stm32_spi_fifo */ 218 ll_func_disable_spi(SPI_TypeDef * spi)219static inline void ll_func_disable_spi(SPI_TypeDef *spi) 220 { 221 #if DT_HAS_COMPAT_STATUS_OKAY(st_stm32_spi_fifo) 222 /* Flush RX buffer */ 223 while (ll_func_rx_is_not_empty(spi)) { 224 (void) LL_SPI_ReceiveData8(spi); 225 } 226 #endif /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32_spi_fifo) */ 227 228 LL_SPI_Disable(spi); 229 230 while (LL_SPI_IsEnabled(spi)) { 231 /* NOP */ 232 } 233 } 234 235 #endif /* ZEPHYR_DRIVERS_SPI_SPI_LL_STM32_H_ */ 236