drivers: i2s: Add support for I2S stm32
STM32 I2S driver implementation. It has been designed in the most generic way possible, with the possibility of using it in master/slave and rx/tx mode. Currenty it has been tested for master rx mode only using the microphone on ArgonKey board. The configuration file permits to compile it for STM32F4xx product family only, but it should be easy to extend it also for other families. It supports all 5 STM32F4xx I2S controllers (I2S 1/4/5 on APB2 and I2S 2/3 on APB1). It makes uses of the available DMA channels for rx/tx streams. The clock source can be selected among one of the following two choices: - PLLI2S pll, with possibility to configure PLLM/PLLN/PLLR - HSE/HSI clock Interrupt is triggered only in case of errors (FRM/OVR/UDR). Signed-off-by: Armando Visconti <armando.visconti@st.com>
This commit is contained in:
parent
31f2e81e10
commit
7b82e9f2d0
4 changed files with 1375 additions and 0 deletions
|
@ -4,3 +4,4 @@ zephyr_library_sources(i2s_common.c)
|
||||||
zephyr_library_sources_ifdef(CONFIG_I2S_SAM_SSC i2s_sam_ssc.c)
|
zephyr_library_sources_ifdef(CONFIG_I2S_SAM_SSC i2s_sam_ssc.c)
|
||||||
zephyr_library_sources_ifdef(CONFIG_I2S_CAVS i2s_cavs.c)
|
zephyr_library_sources_ifdef(CONFIG_I2S_CAVS i2s_cavs.c)
|
||||||
zephyr_library_sources_ifdef(CONFIG_USERSPACE i2s_handlers.c)
|
zephyr_library_sources_ifdef(CONFIG_USERSPACE i2s_handlers.c)
|
||||||
|
zephyr_library_sources_ifdef(CONFIG_I2S_STM32 i2s_ll_stm32.c)
|
||||||
|
|
98
drivers/i2s/Kconfig.stm32
Normal file
98
drivers/i2s/Kconfig.stm32
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
# Kconfig - STM32 I2S driver configuration options
|
||||||
|
#
|
||||||
|
# Copyright (c) 2018 STMicroelectronics
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
#
|
||||||
|
|
||||||
|
menuconfig I2S_STM32
|
||||||
|
bool "STM32 MCU I2S controller driver"
|
||||||
|
depends on I2S && SOC_SERIES_STM32F4X
|
||||||
|
select DMA
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
Enable I2S support on the STM32 family of processors.
|
||||||
|
(Tested on the STM32F4 series)
|
||||||
|
|
||||||
|
if I2S_STM32
|
||||||
|
|
||||||
|
config I2S_STM32_RX_BLOCK_COUNT
|
||||||
|
int "RX queue length"
|
||||||
|
default 4
|
||||||
|
|
||||||
|
config I2S_STM32_TX_BLOCK_COUNT
|
||||||
|
int "TX queue length"
|
||||||
|
default 4
|
||||||
|
|
||||||
|
config I2S_STM32_USE_PLLI2S_ENABLE
|
||||||
|
bool "Enable usage of PLL"
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
Enable it if I2S clock should be provided by the PLLI2S.
|
||||||
|
If not enabled the clock will be provided by HSI/HSE.
|
||||||
|
|
||||||
|
config I2S_STM32_PLLI2S_PLLM
|
||||||
|
int "Division factor for PLLI2S VCO input clock"
|
||||||
|
depends on I2S_STM32_USE_PLLI2S_ENABLE
|
||||||
|
default 8
|
||||||
|
range 2 63
|
||||||
|
help
|
||||||
|
Division factor for the audio PLL (PLLI2S) VCO input clock.
|
||||||
|
PLLM factor should be selected to ensure that the VCO
|
||||||
|
input frequency ranges from 1 to 2 MHz. It is recommended
|
||||||
|
to select a frequency of 2 MHz to limit PLL jitter.
|
||||||
|
Allowed values: 2-63
|
||||||
|
|
||||||
|
config I2S_STM32_PLLI2S_PLLN
|
||||||
|
int "Multiplier factor for PLLI2S VCO output clock"
|
||||||
|
depends on I2S_STM32_USE_PLLI2S_ENABLE
|
||||||
|
default 56
|
||||||
|
range 50 432
|
||||||
|
help
|
||||||
|
Multiply factor for the audio PLL (PLLI2S) VCO output clock.
|
||||||
|
PLLN factor should be selected to ensure that the VCO
|
||||||
|
output frequency ranges from 100 to 432 MHz.
|
||||||
|
Allowed values: 50-432
|
||||||
|
|
||||||
|
config I2S_STM32_PLLI2S_PLLR
|
||||||
|
int "Division factor for I2S clock"
|
||||||
|
depends on I2S_STM32_USE_PLLI2S_ENABLE
|
||||||
|
default 7
|
||||||
|
range 2 7
|
||||||
|
help
|
||||||
|
Division factor for the I2S clock.
|
||||||
|
PLLR factor should be selected to ensure that the I2S clock
|
||||||
|
frequency is less than or equal to 192MHz.
|
||||||
|
Allowed values: 2-7
|
||||||
|
|
||||||
|
config I2S_1
|
||||||
|
bool "I2S port 1"
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
Enable I2S controller port 1.
|
||||||
|
|
||||||
|
config I2S_2
|
||||||
|
bool "I2S port 2"
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
Enable I2S controller port 2.
|
||||||
|
|
||||||
|
config I2S_3
|
||||||
|
bool "I2S port 3"
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
Enable I2S controller port 3.
|
||||||
|
|
||||||
|
config I2S_4
|
||||||
|
bool "I2S port 4"
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
Enable I2S controller port 4.
|
||||||
|
|
||||||
|
config I2S_5
|
||||||
|
bool "I2S port 5"
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
Enable I2S controller port 5.
|
||||||
|
|
||||||
|
endif # I2S_STM32
|
1147
drivers/i2s/i2s_ll_stm32.c
Normal file
1147
drivers/i2s/i2s_ll_stm32.c
Normal file
File diff suppressed because it is too large
Load diff
129
drivers/i2s/i2s_ll_stm32.h
Normal file
129
drivers/i2s/i2s_ll_stm32.h
Normal file
|
@ -0,0 +1,129 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018 STMicroelectronics
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _STM32_I2S_H_
|
||||||
|
#define _STM32_I2S_H_
|
||||||
|
|
||||||
|
#ifdef CONFIG_I2S_STM32_USE_PLLI2S_ENABLE
|
||||||
|
|
||||||
|
#if defined(RCC_CFGR_I2SSRC)
|
||||||
|
/* single selector for the I2S clock source (SEL_1 == SEL_2) */
|
||||||
|
#define CLK_SEL_1 LL_RCC_I2S1_CLKSOURCE_PLLI2S
|
||||||
|
#define CLK_SEL_2 LL_RCC_I2S1_CLKSOURCE_PLLI2S
|
||||||
|
#else
|
||||||
|
#if defined(RCC_DCKCFGR_I2SSRC)
|
||||||
|
/* single selector for the I2S clock source (SEL_1 == SEL_2) */
|
||||||
|
#define CLK_SEL_1 LL_RCC_I2S1_CLKSOURCE_PLL
|
||||||
|
#define CLK_SEL_2 LL_RCC_I2S1_CLKSOURCE_PLL
|
||||||
|
#else
|
||||||
|
#if defined(RCC_DCKCFGR_I2S1SRC) && defined(RCC_DCKCFGR_I2S2SRC)
|
||||||
|
/* double selector for the I2S clock source (SEL_1 != SEL_2) */
|
||||||
|
#define CLK_SEL_1 LL_RCC_I2S1_CLKSOURCE_PLLI2S
|
||||||
|
#define CLK_SEL_2 LL_RCC_I2S2_CLKSOURCE_PLLI2S
|
||||||
|
#endif /* RCC_DCKCFGR_I2S1SRC && RCC_DCKCFGR_I2S2SRC */
|
||||||
|
#endif /* RCC_DCKCFGR_I2SSRC */
|
||||||
|
#endif /* RCC_CFGR_I2SSRC */
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#if defined(RCC_CFGR_I2SSRC)
|
||||||
|
/* single selector for the I2S clock source (SEL_1 == SEL_2) */
|
||||||
|
#define CLK_SEL_1 LL_RCC_I2S1_CLKSOURCE_PIN
|
||||||
|
#define CLK_SEL_2 LL_RCC_I2S1_CLKSOURCE_PIN
|
||||||
|
#else
|
||||||
|
#if defined(RCC_DCKCFGR_I2SSRC)
|
||||||
|
/* single selector for the I2S clock source (SEL_1 == SEL_2) */
|
||||||
|
#define CLK_SEL_1 LL_RCC_I2S1_CLKSOURCE_PLLSRC
|
||||||
|
#define CLK_SEL_2 LL_RCC_I2S1_CLKSOURCE_PLLSRC
|
||||||
|
#else
|
||||||
|
#if defined(RCC_DCKCFGR_I2S1SRC) && defined(RCC_DCKCFGR_I2S2SRC)
|
||||||
|
/* double selector for the I2S clock source (SEL_1 != SEL_2) */
|
||||||
|
#define CLK_SEL_1 LL_RCC_I2S1_CLKSOURCE_PLLSRC
|
||||||
|
#define CLK_SEL_2 LL_RCC_I2S2_CLKSOURCE_PLLSRC
|
||||||
|
#endif /* RCC_DCKCFGR_I2S1SRC && RCC_DCKCFGR_I2S2SRC */
|
||||||
|
#endif /* RCC_DCKCFGR_I2SSRC */
|
||||||
|
#endif /* RCC_CFGR_I2SSRC */
|
||||||
|
|
||||||
|
#endif /* CONFIG_I2S_STM32_USE_PLLI2S_ENABLE */
|
||||||
|
|
||||||
|
#ifdef CONFIG_SOC_SERIES_STM32F4X
|
||||||
|
#define I2S1_DMA_NAME CONFIG_DMA_2_NAME
|
||||||
|
#define I2S1_DMA_CHAN_RX 2
|
||||||
|
#define I2S1_DMA_SLOT_RX 3
|
||||||
|
#define I2S1_DMA_CHAN_TX 3
|
||||||
|
#define I2S1_DMA_SLOT_TX 3
|
||||||
|
#define I2S2_DMA_NAME CONFIG_DMA_1_NAME
|
||||||
|
#define I2S2_DMA_CHAN_RX 3
|
||||||
|
#define I2S2_DMA_SLOT_RX 0
|
||||||
|
#define I2S2_DMA_CHAN_TX 4
|
||||||
|
#define I2S2_DMA_SLOT_TX 0
|
||||||
|
#define I2S3_DMA_NAME CONFIG_DMA_1_NAME
|
||||||
|
#define I2S3_DMA_CHAN_RX 0
|
||||||
|
#define I2S3_DMA_SLOT_RX 0
|
||||||
|
#define I2S3_DMA_CHAN_TX 5
|
||||||
|
#define I2S3_DMA_SLOT_TX 0
|
||||||
|
#define I2S4_DMA_NAME CONFIG_DMA_2_NAME
|
||||||
|
#define I2S4_DMA_CHAN_RX 0
|
||||||
|
#define I2S4_DMA_SLOT_RX 4
|
||||||
|
#define I2S4_DMA_CHAN_TX 1
|
||||||
|
#define I2S4_DMA_SLOT_TX 4
|
||||||
|
#define I2S5_DMA_NAME CONFIG_DMA_2_NAME
|
||||||
|
#define I2S5_DMA_CHAN_RX 5
|
||||||
|
#define I2S5_DMA_SLOT_RX 7
|
||||||
|
#define I2S5_DMA_CHAN_TX 6
|
||||||
|
#define I2S5_DMA_SLOT_TX 7
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define DEV_CFG(dev) \
|
||||||
|
(const struct i2s_stm32_cfg * const)((dev)->config->config_info)
|
||||||
|
#define DEV_DATA(dev) \
|
||||||
|
((struct i2s_stm32_data *const)(dev)->driver_data)
|
||||||
|
|
||||||
|
struct queue_item {
|
||||||
|
void *mem_block;
|
||||||
|
size_t size;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Minimal ring buffer implementation */
|
||||||
|
struct ring_buf {
|
||||||
|
struct queue_item *buf;
|
||||||
|
u16_t len;
|
||||||
|
u16_t head;
|
||||||
|
u16_t tail;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Device constant configuration parameters */
|
||||||
|
struct i2s_stm32_cfg {
|
||||||
|
SPI_TypeDef *i2s;
|
||||||
|
struct stm32_pclken pclken;
|
||||||
|
u32_t i2s_clk_sel;
|
||||||
|
void (*irq_config)(struct device *dev);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct stream {
|
||||||
|
s32_t state;
|
||||||
|
struct k_sem sem;
|
||||||
|
u32_t dma_channel;
|
||||||
|
struct dma_config dma_cfg;
|
||||||
|
struct i2s_config cfg;
|
||||||
|
struct ring_buf mem_block_queue;
|
||||||
|
void *mem_block;
|
||||||
|
bool last_block;
|
||||||
|
bool master;
|
||||||
|
int (*stream_start)(struct stream *, struct device *dev);
|
||||||
|
void (*stream_disable)(struct stream *, struct device *dev);
|
||||||
|
void (*queue_drop)(struct stream *);
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Device run time data */
|
||||||
|
struct i2s_stm32_data {
|
||||||
|
struct device *dev_dma;
|
||||||
|
const char *dma_name;
|
||||||
|
struct stream rx;
|
||||||
|
struct stream tx;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* _STM32_I2S_H_ */
|
Loading…
Add table
Add a link
Reference in a new issue