You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
238 lines
6.0 KiB
238 lines
6.0 KiB
/* |
|
* Copyright (c) 2016 BayLibre, SAS |
|
* |
|
* SPDX-License-Identifier: Apache-2.0 |
|
*/ |
|
|
|
#ifndef ZEPHYR_DRIVERS_SPI_SPI_LL_STM32_H_ |
|
#define ZEPHYR_DRIVERS_SPI_SPI_LL_STM32_H_ |
|
|
|
#include "spi_context.h" |
|
|
|
typedef void (*irq_config_func_t)(const struct device *port); |
|
|
|
/* This symbol takes the value 1 if one of the device instances */ |
|
/* is configured in dts with a domain clock */ |
|
#if STM32_DT_INST_DEV_DOMAIN_CLOCK_SUPPORT |
|
#define STM32_SPI_DOMAIN_CLOCK_SUPPORT 1 |
|
#else |
|
#define STM32_SPI_DOMAIN_CLOCK_SUPPORT 0 |
|
#endif |
|
|
|
struct spi_stm32_config { |
|
SPI_TypeDef *spi; |
|
const struct pinctrl_dev_config *pcfg; |
|
#ifdef CONFIG_SPI_STM32_INTERRUPT |
|
irq_config_func_t irq_config; |
|
#ifdef CONFIG_SOC_SERIES_STM32H7X |
|
uint32_t irq_line; |
|
#endif /* CONFIG_SOC_SERIES_STM32H7X */ |
|
#endif |
|
#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32_spi_subghz) |
|
bool use_subghzspi_nss; |
|
#endif |
|
#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_spi) |
|
int midi_clocks; |
|
int mssi_clocks; |
|
#endif |
|
size_t pclk_len; |
|
const struct stm32_pclken *pclken; |
|
bool fifo_enabled; |
|
}; |
|
|
|
#ifdef CONFIG_SPI_STM32_DMA |
|
|
|
#define SPI_STM32_DMA_ERROR_FLAG 0x01 |
|
#define SPI_STM32_DMA_RX_DONE_FLAG 0x02 |
|
#define SPI_STM32_DMA_TX_DONE_FLAG 0x04 |
|
#define SPI_STM32_DMA_DONE_FLAG \ |
|
(SPI_STM32_DMA_RX_DONE_FLAG | SPI_STM32_DMA_TX_DONE_FLAG) |
|
|
|
#define SPI_STM32_DMA_TX 0x01 |
|
#define SPI_STM32_DMA_RX 0x02 |
|
|
|
struct stream { |
|
const struct device *dma_dev; |
|
uint32_t channel; /* stores the channel for dma or mux */ |
|
struct dma_config dma_cfg; |
|
struct dma_block_config dma_blk_cfg; |
|
uint8_t priority; |
|
bool src_addr_increment; |
|
bool dst_addr_increment; |
|
int fifo_threshold; |
|
}; |
|
#endif |
|
|
|
struct spi_stm32_data { |
|
struct spi_context ctx; |
|
#ifdef CONFIG_SPI_STM32_DMA |
|
struct k_sem status_sem; |
|
volatile uint32_t status_flags; |
|
struct stream dma_rx; |
|
struct stream dma_tx; |
|
#endif /* CONFIG_SPI_STM32_DMA */ |
|
bool pm_policy_state_on; |
|
}; |
|
|
|
#ifdef CONFIG_SPI_STM32_DMA |
|
static inline uint32_t ll_func_dma_get_reg_addr(SPI_TypeDef *spi, uint32_t location) |
|
{ |
|
#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_spi) |
|
if (location == SPI_STM32_DMA_TX) { |
|
/* use direct register location until the LL_SPI_DMA_GetTxRegAddr exists */ |
|
return (uint32_t)&(spi->TXDR); |
|
} |
|
/* use direct register location until the LL_SPI_DMA_GetRxRegAddr exists */ |
|
return (uint32_t)&(spi->RXDR); |
|
#else |
|
ARG_UNUSED(location); |
|
return (uint32_t)LL_SPI_DMA_GetRegAddr(spi); |
|
#endif /* st_stm32h7_spi */ |
|
} |
|
|
|
/* checks that DMA Tx packet is fully transmitted over the SPI */ |
|
static inline uint32_t ll_func_spi_dma_busy(SPI_TypeDef *spi) |
|
{ |
|
#ifdef LL_SPI_SR_TXC |
|
return LL_SPI_IsActiveFlag_TXC(spi); |
|
#else |
|
/* the SPI Tx empty and busy flags are needed */ |
|
return (LL_SPI_IsActiveFlag_TXE(spi) && |
|
!LL_SPI_IsActiveFlag_BSY(spi)); |
|
#endif /* LL_SPI_SR_TXC */ |
|
} |
|
#endif /* CONFIG_SPI_STM32_DMA */ |
|
|
|
static inline uint32_t ll_func_tx_is_not_full(SPI_TypeDef *spi) |
|
{ |
|
#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_spi) |
|
return LL_SPI_IsActiveFlag_TXP(spi); |
|
#else |
|
return LL_SPI_IsActiveFlag_TXE(spi); |
|
#endif /* st_stm32h7_spi */ |
|
} |
|
|
|
static inline uint32_t ll_func_rx_is_not_empty(SPI_TypeDef *spi) |
|
{ |
|
#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_spi) |
|
return LL_SPI_IsActiveFlag_RXP(spi); |
|
#else |
|
return LL_SPI_IsActiveFlag_RXNE(spi); |
|
#endif /* st_stm32h7_spi */ |
|
} |
|
|
|
static inline void ll_func_enable_int_tx_empty(SPI_TypeDef *spi) |
|
{ |
|
#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_spi) |
|
LL_SPI_EnableIT_TXP(spi); |
|
#else |
|
LL_SPI_EnableIT_TXE(spi); |
|
#endif /* st_stm32h7_spi */ |
|
} |
|
|
|
static inline void ll_func_enable_int_rx_not_empty(SPI_TypeDef *spi) |
|
{ |
|
#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_spi) |
|
LL_SPI_EnableIT_RXP(spi); |
|
#else |
|
LL_SPI_EnableIT_RXNE(spi); |
|
#endif /* st_stm32h7_spi */ |
|
} |
|
|
|
static inline void ll_func_enable_int_errors(SPI_TypeDef *spi) |
|
{ |
|
#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_spi) |
|
LL_SPI_EnableIT_UDR(spi); |
|
LL_SPI_EnableIT_OVR(spi); |
|
LL_SPI_EnableIT_CRCERR(spi); |
|
LL_SPI_EnableIT_FRE(spi); |
|
LL_SPI_EnableIT_MODF(spi); |
|
#else |
|
LL_SPI_EnableIT_ERR(spi); |
|
#endif /* st_stm32h7_spi */ |
|
} |
|
|
|
static inline void ll_func_disable_int_tx_empty(SPI_TypeDef *spi) |
|
{ |
|
#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_spi) |
|
LL_SPI_DisableIT_TXP(spi); |
|
#else |
|
LL_SPI_DisableIT_TXE(spi); |
|
#endif /* st_stm32h7_spi */ |
|
} |
|
|
|
static inline void ll_func_disable_int_rx_not_empty(SPI_TypeDef *spi) |
|
{ |
|
#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_spi) |
|
LL_SPI_DisableIT_RXP(spi); |
|
#else |
|
LL_SPI_DisableIT_RXNE(spi); |
|
#endif /* st_stm32h7_spi */ |
|
} |
|
|
|
static inline void ll_func_disable_int_errors(SPI_TypeDef *spi) |
|
{ |
|
#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_spi) |
|
LL_SPI_DisableIT_UDR(spi); |
|
LL_SPI_DisableIT_OVR(spi); |
|
LL_SPI_DisableIT_CRCERR(spi); |
|
LL_SPI_DisableIT_FRE(spi); |
|
LL_SPI_DisableIT_MODF(spi); |
|
#else |
|
LL_SPI_DisableIT_ERR(spi); |
|
#endif /* st_stm32h7_spi */ |
|
} |
|
|
|
static inline uint32_t ll_func_spi_is_busy(SPI_TypeDef *spi) |
|
{ |
|
#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_spi) |
|
if (LL_SPI_GetTransferSize(spi) == 0) { |
|
return LL_SPI_IsActiveFlag_TXC(spi) == 0; |
|
} else { |
|
return LL_SPI_IsActiveFlag_EOT(spi) == 0; |
|
} |
|
#else |
|
return LL_SPI_IsActiveFlag_BSY(spi); |
|
#endif /* st_stm32h7_spi */ |
|
} |
|
|
|
/* Header is compiled first, this switch avoid the compiler to lookup for |
|
* non-existing LL FIFO functions for SoC without SPI FIFO |
|
*/ |
|
#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32_spi_fifo) |
|
static inline void ll_func_set_fifo_threshold_8bit(SPI_TypeDef *spi) |
|
{ |
|
#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_spi) |
|
LL_SPI_SetFIFOThreshold(spi, LL_SPI_FIFO_TH_01DATA); |
|
#else |
|
LL_SPI_SetRxFIFOThreshold(spi, LL_SPI_RX_FIFO_TH_QUARTER); |
|
#endif /* st_stm32h7_spi */ |
|
} |
|
|
|
static inline void ll_func_set_fifo_threshold_16bit(SPI_TypeDef *spi) |
|
{ |
|
#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_spi) |
|
LL_SPI_SetFIFOThreshold(spi, LL_SPI_FIFO_TH_02DATA); |
|
#else |
|
LL_SPI_SetRxFIFOThreshold(spi, LL_SPI_RX_FIFO_TH_HALF); |
|
#endif /* st_stm32h7_spi */ |
|
} |
|
#endif /* st_stm32_spi_fifo */ |
|
|
|
static inline void ll_func_disable_spi(SPI_TypeDef *spi) |
|
{ |
|
#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32_spi_fifo) |
|
/* Flush RX buffer */ |
|
while (ll_func_rx_is_not_empty(spi)) { |
|
(void) LL_SPI_ReceiveData8(spi); |
|
} |
|
#endif /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32_spi_fifo) */ |
|
|
|
LL_SPI_Disable(spi); |
|
|
|
while (LL_SPI_IsEnabled(spi)) { |
|
/* NOP */ |
|
} |
|
} |
|
|
|
#endif /* ZEPHYR_DRIVERS_SPI_SPI_LL_STM32_H_ */
|
|
|