i2s: stm32h7: add i2s support for stm32h7 mcu family
This commit modifies the I2S driver to work for STM32H7 family of MCU's. Currently only TX is working. Tested on nucleo_stm32h743zi. Requires dma1 & dmamux1 to be enabled. Signed-off-by: Emil Lindqvist <emil@lindq.gr>
This commit is contained in:
parent
c3e8b731ef
commit
ed6da68f5b
7 changed files with 153 additions and 32 deletions
|
@ -10,7 +10,7 @@ menuconfig I2S_STM32
|
|||
select DMA
|
||||
help
|
||||
Enable I2S support on the STM32 family of processors.
|
||||
(Tested on the STM32F4 series)
|
||||
(Tested on the STM32F4 & STM32H7 series)
|
||||
|
||||
if I2S_STM32
|
||||
|
||||
|
|
|
@ -22,11 +22,7 @@
|
|||
#include <zephyr/irq.h>
|
||||
LOG_MODULE_REGISTER(i2s_ll_stm32);
|
||||
|
||||
/* FIXME change to
|
||||
* #if __DCACHE_PRESENT == 1
|
||||
* when cache support is added
|
||||
*/
|
||||
#if 0
|
||||
#if __DCACHE_PRESENT == 1
|
||||
#define DCACHE_INVALIDATE(addr, size) \
|
||||
SCB_InvalidateDCache_by_Addr((uint32_t *)addr, size)
|
||||
#define DCACHE_CLEAN(addr, size) \
|
||||
|
@ -187,6 +183,9 @@ static int i2s_stm32_configure(const struct device *dev, enum i2s_dir dir,
|
|||
int ret;
|
||||
|
||||
if (dir == I2S_DIR_RX) {
|
||||
#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_i2s)
|
||||
return -ENOSYS;
|
||||
#endif
|
||||
stream = &dev_data->rx;
|
||||
} else if (dir == I2S_DIR_TX) {
|
||||
stream = &dev_data->tx;
|
||||
|
@ -549,7 +548,11 @@ static void dma_rx_callback(const struct device *dma_dev, void *arg,
|
|||
|
||||
ret = reload_dma(stream->dev_dma, stream->dma_channel,
|
||||
&stream->dma_cfg,
|
||||
#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_i2s)
|
||||
(void *)LL_SPI_DMA_GetRxRegAddr(cfg->i2s),
|
||||
#else
|
||||
(void *)LL_SPI_DMA_GetRegAddr(cfg->i2s),
|
||||
#endif
|
||||
stream->mem_block,
|
||||
stream->cfg.block_size);
|
||||
if (ret < 0) {
|
||||
|
@ -634,7 +637,11 @@ static void dma_tx_callback(const struct device *dma_dev, void *arg,
|
|||
ret = reload_dma(stream->dev_dma, stream->dma_channel,
|
||||
&stream->dma_cfg,
|
||||
stream->mem_block,
|
||||
#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_i2s)
|
||||
(void *)LL_SPI_DMA_GetTxRegAddr(cfg->i2s),
|
||||
#else
|
||||
(void *)LL_SPI_DMA_GetRegAddr(cfg->i2s),
|
||||
#endif
|
||||
stream->cfg.block_size);
|
||||
if (ret < 0) {
|
||||
LOG_DBG("Failed to start TX DMA transfer: %d", ret);
|
||||
|
@ -649,6 +656,7 @@ tx_disable:
|
|||
|
||||
static uint32_t i2s_stm32_irq_count;
|
||||
static uint32_t i2s_stm32_irq_ovr_count;
|
||||
static uint32_t i2s_stm32_irq_udr_count;
|
||||
|
||||
static void i2s_stm32_isr(const struct device *dev)
|
||||
{
|
||||
|
@ -665,6 +673,12 @@ static void i2s_stm32_isr(const struct device *dev)
|
|||
LL_I2S_ClearFlag_OVR(cfg->i2s);
|
||||
}
|
||||
|
||||
/* NOTE: UDR error must be explicitly cleared on STM32H7 */
|
||||
if (LL_I2S_IsActiveFlag_UDR(cfg->i2s)) {
|
||||
i2s_stm32_irq_udr_count++;
|
||||
LL_I2S_ClearFlag_UDR(cfg->i2s);
|
||||
}
|
||||
|
||||
i2s_stm32_irq_count++;
|
||||
}
|
||||
|
||||
|
@ -736,7 +750,11 @@ static int rx_stream_start(struct stream *stream, const struct device *dev)
|
|||
|
||||
ret = start_dma(stream->dev_dma, stream->dma_channel,
|
||||
&stream->dma_cfg,
|
||||
#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_i2s)
|
||||
(void *)LL_SPI_DMA_GetRxRegAddr(cfg->i2s),
|
||||
#else
|
||||
(void *)LL_SPI_DMA_GetRegAddr(cfg->i2s),
|
||||
#endif
|
||||
stream->src_addr_increment, stream->mem_block,
|
||||
stream->dst_addr_increment, stream->fifo_threshold,
|
||||
stream->cfg.block_size);
|
||||
|
@ -747,8 +765,17 @@ static int rx_stream_start(struct stream *stream, const struct device *dev)
|
|||
|
||||
LL_I2S_EnableDMAReq_RX(cfg->i2s);
|
||||
|
||||
#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_i2s)
|
||||
LL_I2S_EnableIT_OVR(cfg->i2s);
|
||||
LL_I2S_EnableIT_UDR(cfg->i2s);
|
||||
LL_I2S_EnableIT_FRE(cfg->i2s);
|
||||
LL_I2S_Enable(cfg->i2s);
|
||||
LL_SPI_StartMasterTransfer(cfg->i2s);
|
||||
#else
|
||||
LL_I2S_EnableIT_ERR(cfg->i2s);
|
||||
LL_I2S_Enable(cfg->i2s);
|
||||
#endif
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -781,7 +808,11 @@ static int tx_stream_start(struct stream *stream, const struct device *dev)
|
|||
ret = start_dma(stream->dev_dma, stream->dma_channel,
|
||||
&stream->dma_cfg,
|
||||
stream->mem_block, stream->src_addr_increment,
|
||||
#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_i2s)
|
||||
(void *)LL_SPI_DMA_GetTxRegAddr(cfg->i2s),
|
||||
#else
|
||||
(void *)LL_SPI_DMA_GetRegAddr(cfg->i2s),
|
||||
#endif
|
||||
stream->dst_addr_increment, stream->fifo_threshold,
|
||||
stream->cfg.block_size);
|
||||
if (ret < 0) {
|
||||
|
@ -791,8 +822,17 @@ static int tx_stream_start(struct stream *stream, const struct device *dev)
|
|||
|
||||
LL_I2S_EnableDMAReq_TX(cfg->i2s);
|
||||
|
||||
#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_i2s)
|
||||
LL_I2S_EnableIT_OVR(cfg->i2s);
|
||||
LL_I2S_EnableIT_UDR(cfg->i2s);
|
||||
LL_I2S_EnableIT_FRE(cfg->i2s);
|
||||
|
||||
LL_I2S_Enable(cfg->i2s);
|
||||
LL_SPI_StartMasterTransfer(cfg->i2s);
|
||||
#else
|
||||
LL_I2S_EnableIT_ERR(cfg->i2s);
|
||||
LL_I2S_Enable(cfg->i2s);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -802,7 +842,13 @@ static void rx_stream_disable(struct stream *stream, const struct device *dev)
|
|||
const struct i2s_stm32_cfg *cfg = dev->config;
|
||||
|
||||
LL_I2S_DisableDMAReq_RX(cfg->i2s);
|
||||
#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_i2s)
|
||||
LL_I2S_DisableIT_OVR(cfg->i2s);
|
||||
LL_I2S_DisableIT_UDR(cfg->i2s);
|
||||
LL_I2S_DisableIT_FRE(cfg->i2s);
|
||||
#else
|
||||
LL_I2S_DisableIT_ERR(cfg->i2s);
|
||||
#endif
|
||||
|
||||
dma_stop(stream->dev_dma, stream->dma_channel);
|
||||
if (stream->mem_block != NULL) {
|
||||
|
@ -820,7 +866,13 @@ static void tx_stream_disable(struct stream *stream, const struct device *dev)
|
|||
const struct i2s_stm32_cfg *cfg = dev->config;
|
||||
|
||||
LL_I2S_DisableDMAReq_TX(cfg->i2s);
|
||||
#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_i2s)
|
||||
LL_I2S_DisableIT_OVR(cfg->i2s);
|
||||
LL_I2S_DisableIT_UDR(cfg->i2s);
|
||||
LL_I2S_DisableIT_FRE(cfg->i2s);
|
||||
#else
|
||||
LL_I2S_DisableIT_ERR(cfg->i2s);
|
||||
#endif
|
||||
|
||||
dma_stop(stream->dev_dma, stream->dma_channel);
|
||||
if (stream->mem_block != NULL) {
|
||||
|
|
|
@ -466,6 +466,48 @@
|
|||
status = "disabled";
|
||||
};
|
||||
|
||||
i2s1: i2s@40013000 {
|
||||
compatible = "st,stm32h7-i2s", "st,stm32-i2s";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reg = <0x40013000 0x400>;
|
||||
clocks = <&rcc STM32_CLOCK_BUS_APB2 0x00001000>,
|
||||
<&rcc STM32_SRC_PLL1_Q SPI123_SEL(0)>;
|
||||
dmas = <&dmamux1 0 38 (STM32_DMA_PERIPH_TX | STM32_DMA_PRIORITY_HIGH)
|
||||
&dmamux1 1 37 (STM32_DMA_PERIPH_RX | STM32_DMA_PRIORITY_HIGH)>;
|
||||
dma-names = "tx", "rx";
|
||||
interrupts = <35 3>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
i2s2: i2s@40003800 {
|
||||
compatible = "st,stm32h7-i2s", "st,stm32-i2s";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reg = <0x40003800 0x400>;
|
||||
clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00004000>,
|
||||
<&rcc STM32_SRC_PLL1_Q SPI123_SEL(0)>;
|
||||
dmas = <&dmamux1 0 40 (STM32_DMA_PERIPH_TX | STM32_DMA_PRIORITY_HIGH)
|
||||
&dmamux1 1 39 (STM32_DMA_PERIPH_RX | STM32_DMA_PRIORITY_HIGH)>;
|
||||
dma-names = "tx", "rx";
|
||||
interrupts = <36 0>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
i2s3: i2s@40003c00 {
|
||||
compatible = "st,stm32h7-i2s", "st,stm32-i2s";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reg = <0x40003c00 0x400>;
|
||||
clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00008000>,
|
||||
<&rcc STM32_SRC_PLL1_Q SPI123_SEL(0)>;
|
||||
dmas = <&dmamux1 0 62 (STM32_DMA_PERIPH_TX | STM32_DMA_PRIORITY_HIGH)
|
||||
&dmamux1 1 61 (STM32_DMA_PERIPH_RX | STM32_DMA_PRIORITY_HIGH)>;
|
||||
dma-names = "tx", "rx";
|
||||
interrupts = <51 0>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
fdcan1: can@4000a000 {
|
||||
compatible = "st,stm32h7-fdcan";
|
||||
reg = <0x4000a000 0x400>, <0x4000ac00 0x350>;
|
||||
|
|
|
@ -79,6 +79,19 @@
|
|||
status = "disabled";
|
||||
};
|
||||
|
||||
i2s6: i2s@58001400 {
|
||||
compatible = "st,stm32h7-i2s", "st,stm32-i2s";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reg = <0x58001400 0x400>;
|
||||
clocks = <&rcc STM32_CLOCK_BUS_APB4 0x00000020>,
|
||||
<&rcc STM32_SRC_PLL1_Q SPI6_SEL(0)>;
|
||||
dmas = <&dmamux2 0 12 0x20440 &dmamux2 1 11 0x20480>;
|
||||
dma-names = "tx", "rx";
|
||||
interrupts = <86 0>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
rng: rng@48021800 {
|
||||
nist-config = <0xf00d00>;
|
||||
health-test-magic = <0x17590abc>;
|
||||
|
|
31
dts/bindings/i2s/st,stm32-i2s-common.yaml
Normal file
31
dts/bindings/i2s/st,stm32-i2s-common.yaml
Normal file
|
@ -0,0 +1,31 @@
|
|||
# Copyright (c) 2018, STMicroelectronics
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
# Common fields for STM32 I2S peripherals.
|
||||
|
||||
include: [i2s-controller.yaml, pinctrl-device.yaml]
|
||||
|
||||
properties:
|
||||
reg:
|
||||
required: true
|
||||
|
||||
interrupts:
|
||||
required: true
|
||||
|
||||
dmas:
|
||||
required: true
|
||||
|
||||
dma-names:
|
||||
required: true
|
||||
|
||||
pinctrl-0:
|
||||
required: true
|
||||
|
||||
pinctrl-names:
|
||||
required: true
|
||||
|
||||
mck-enabled:
|
||||
type: boolean
|
||||
description: |
|
||||
Master Clock Output function.
|
||||
An mck pin must be listed within pinctrl-0 when enabling this property.
|
|
@ -5,29 +5,4 @@ description: STM32 I2S controller
|
|||
|
||||
compatible: "st,stm32-i2s"
|
||||
|
||||
include: [i2s-controller.yaml, pinctrl-device.yaml]
|
||||
|
||||
properties:
|
||||
reg:
|
||||
required: true
|
||||
|
||||
interrupts:
|
||||
required: true
|
||||
|
||||
dmas:
|
||||
required: true
|
||||
|
||||
dma-names:
|
||||
required: true
|
||||
|
||||
pinctrl-0:
|
||||
required: true
|
||||
|
||||
pinctrl-names:
|
||||
required: true
|
||||
|
||||
mck-enabled:
|
||||
type: boolean
|
||||
description: |
|
||||
Master Clock Output function.
|
||||
An mck pin must be listed within pinctrl-0 when enabling this property.
|
||||
include: st,stm32-i2s-common.yaml
|
||||
|
|
8
dts/bindings/i2s/st,stm32h7-i2s.yaml
Normal file
8
dts/bindings/i2s/st,stm32h7-i2s.yaml
Normal file
|
@ -0,0 +1,8 @@
|
|||
# Copyright (c) 2018, STMicroelectronics
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
description: STM32H7 I2S controller
|
||||
|
||||
compatible: "st,stm32h7-i2s"
|
||||
|
||||
include: st,stm32-i2s-common.yaml
|
Loading…
Add table
Add a link
Reference in a new issue