Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions drivers/mspi/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,6 @@ zephyr_library_sources_ifdef(CONFIG_MSPI_AMBIQ_AP5 mspi_ambiq_ap5.c)
zephyr_library_sources_ifdef(CONFIG_MSPI_AMBIQ_TIMING_SCAN mspi_ambiq_timing_scan.c)
zephyr_library_sources_ifdef(CONFIG_MSPI_DW mspi_dw.c)
zephyr_library_sources_ifdef(CONFIG_MSPI_EMUL mspi_emul.c)
zephyr_library_sources_ifdef(CONFIG_MSPI_STM32_OSPI mspi_stm32_ospi.c)
zephyr_library_sources_ifdef(CONFIG_MSPI_STM32_QSPI mspi_stm32_qspi.c)
zephyr_library_sources_ifdef(CONFIG_MSPI_STM32_XSPI mspi_stm32_xspi.c)
1 change: 1 addition & 0 deletions drivers/mspi/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -62,5 +62,6 @@ source "subsys/logging/Kconfig.template.log_config"
source "drivers/mspi/Kconfig.ambiq"
source "drivers/mspi/Kconfig.dw"
source "drivers/mspi/Kconfig.mspi_emul"
source "drivers/mspi/Kconfig.stm32"

endif # MSPI
59 changes: 59 additions & 0 deletions drivers/mspi/Kconfig.stm32
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# STM32 MSPI flash driver configuration options

# Copyright (c) 2025 STMicroelectronics
# SPDX-License-Identifier: Apache-2.0

config MSPI_STM32_XSPI
bool "STM32 XSPI Controller driver"
depends on DT_HAS_ST_STM32_XSPI_CONTROLLER_ENABLED
select USE_STM32_HAL_XSPI
select USE_STM32_LL_DLYB
select DMA
select USE_STM32_HAL_DMA
select USE_STM32_HAL_DMA_EX
imply MSPI_XIP
default y
help
Enable driver for STM32 family of processors.

config MSPI_STM32_QSPI
bool "STM32 QSPI Controller driver"
default y
depends on DT_HAS_ST_STM32_QSPI_CONTROLLER_ENABLED
select USE_STM32_HAL_QSPI
select DMA
select USE_STM32_HAL_DMA
select USE_STM32_HAL_DMA_EX
select USE_STM32_HAL_MDMA
imply MSPI_XIP
help
Enable QSPI driver for STM32 family of processors.

#DT_STM32_OCTOSPI_HAS_DMA := $(dt_compat_any_has_prop,$(DT_COMPAT_ST_STM32_OSPI),dmas)

config MSPI_STM32_OSPI
bool "STM32 OSPI Controller driver"
default y
depends on DT_HAS_ST_STM32_OSPI_CONTROLLER_ENABLED
select USE_STM32_HAL_OSPI if !SOC_SERIES_STM32H5X
select USE_STM32_LL_DLYB if (SOC_SERIES_STM32H5X || SOC_SERIES_STM32U5X)
select USE_STM32_HAL_MDMA if SOC_SERIES_STM32H7X
select DMA
select USE_STM32_HAL_DMA
select USE_STM32_HAL_DMA_EX
help
Enable OSPI driver for STM32 family of processors.

config MSPI_BUFFER_ALIGNMENT
int
default 32
help
Some MSPI host controllers require alignment of their data buffers
in order for DMA to work correctly. This represents the alignment
of buffers required in bytes.

config MSPI_STM32_ALLOW_WRITE_IN_MEMMAP
bool "Allow write in MEMMAP mode"
default n
help
Some MSPI host controllers allow to write in memory map mode.
201 changes: 201 additions & 0 deletions drivers/mspi/mspi_stm32.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
/*
* Copyright (c) 2025 EXALT Technologies.
*
* SPDX-License-Identifier: Apache-2.0
*/

#ifndef ZEPHYR_DRIVERS_MSPI_STM32_H_
#define ZEPHYR_DRIVERS_MSPI_STM32_H_
/* Macro to check if any xspi device has a domain clock or more */
#define MSPI_STM32_DOMAIN_CLOCK_INST_SUPPORT(inst) DT_CLOCKS_HAS_IDX(DT_INST_PARENT(inst), 1) ||
#define MSPI_STM32_INST_DEV_DOMAIN_CLOCK_SUPPORT \
(DT_INST_FOREACH_STATUS_OKAY(MSPI_STM32_DOMAIN_CLOCK_INST_SUPPORT) 0)

/* This symbol takes the value 1 if device instance has a domain clock in its dts */
#if MSPI_STM32_INST_DEV_DOMAIN_CLOCK_SUPPORT
#define MSPI_STM32_DOMAIN_CLOCK_SUPPORT 1
#else
#define MSPI_STM32_DOMAIN_CLOCK_SUPPORT 0
#endif

#define MSPI_STM32_FIFO_THRESHOLD 4U
#define MSPI_MAX_FREQ 250000000
#define MSPI_MAX_DEVICE 2

#if defined(CONFIG_SOC_SERIES_STM32U5X)
/* Valid range is [1, 256] */
#define MSPI_STM32_CLOCK_PRESCALER_MIN 1U
#define MSPI_STM32_CLOCK_PRESCALER_MAX 256U
#define MSPI_STM32_CLOCK_COMPUTE(bus_freq, prescaler) ((bus_freq) / (prescaler))
#else
/* Valid range is [0, 255] */
#define MSPI_STM32_CLOCK_PRESCALER_MIN 0U
#define MSPI_STM32_CLOCK_PRESCALER_MAX 255U
#define MSPI_STM32_CLOCK_COMPUTE(bus_freq, prescaler) ((bus_freq) / ((prescaler) + 1U))
#endif

#define MSPI_STM32_WRITE_REG_MAX_TIME 40U
#define MSPI_STM32_MAX_FREQ 48000000

#define MSPI_STM32_CMD_WRSR 0x01 /* Write status register */
#define MSPI_STM32_CMD_RDSR 0x05 /* Read status register */
#define MSPI_STM32_CMD_READ 0x03 /* Read data */
#define MSPI_STM32_CMD_READ_FAST 0x0B /* Read data */
#define MSPI_STM32_CMD_PP 0x02 /* Page program */
#define MSPI_STM32_CMD_READ_4B 0x13 /* Read data 4 Byte Address */
#define MSPI_STM32_CMD_READ_FAST_4B 0x0C /* Fast Read 4 Byte Address */
#define MSPI_STM32_CMD_PP_4B 0x12 /* Page Program 4 Byte Address */
#define MSPI_STM32_CMD_WREN 0x06 /* Write enable */
#define MSPI_STM32_CMD_RDPD 0xAB /* Release from Deep Power Down */
#define MSPI_STM32_CMD_RD_CFGREG2 0x71 /* Read config register 2 */
#define MSPI_STM32_CMD_WR_CFGREG2 0x72 /* Write config register 2 */
#define MSPI_STM32_CMD_SE 0x20 /* Sector erase */
#define MSPI_STM32_CMD_SE_4B 0x21 /* Sector erase 4 byte address*/

#define MSPI_STM32_OCMD_RDSR 0x05FA /* Octal Read status register */
#define MSPI_STM32_OCMD_RD 0xEC13 /* Octal IO read command */
#define MSPI_STM32_OCMD_PAGE_PRG 0x12ED /* Octal Page Prog */
#define MSPI_STM32_OCMD_WREN 0x06F9 /* Octal Write enable */
#define MSPI_STM32_OCMD_DTR_RD 0xEE11 /* Octal IO DTR read command */
#define MSPI_STM32_OCMD_WR_CFGREG2 0x728D /* Octal Write configuration Register2 */
#define MSPI_STM32_OCMD_RD_CFGREG2 0x718E /* Octal Read configuration Register2 */
#define MSPI_STM32_OCMD_SE 0x21DE /* Octal Sector erase */

/* Flash Auto-polling values */
#define MSPI_STM32_WREN_MATCH 0x02
#define MSPI_STM32_WREN_MASK 0x02
#define MSPI_STM32_WEL_MATCH 0x00
#define MSPI_STM32_WEL_MASK 0x02
#define MSPI_STM32_MEM_RDY_MATCH 0x00
#define MSPI_STM32_MEM_RDY_MASK 0x01
#define MSPI_STM32_AUTO_POLLING_INTERVAL 0x10

/* Flash Dummy Cycles values */
#define MSPI_STM32_DUMMY_REG_OCTAL 4U
#define MSPI_STM32_DUMMY_REG_OCTAL_DTR 5U

/* Memory registers address */
#define MSPI_STM32_REG2_ADDR1 0x0000000
#define MSPI_STM32_CR2_STR_OPI_EN 0x01
#define MSPI_STM32_CR2_DTR_OPI_EN 0x02
#define MSPI_STM32_REG2_ADDR3 0x00000300
#define MSPI_STM32_CR2_DUMMY_CYCLES_66MHZ 0x07

typedef void (*irq_config_func_t)(void);

#ifndef DMA_LOW_PRIORITY_LOW_WEIGHT
#define DMA_LOW_PRIORITY_LOW_WEIGHT DMA_PRIORITY_LOW
#endif

#ifndef DMA_LOW_PRIORITY_MID_WEIGHT
#define DMA_LOW_PRIORITY_MID_WEIGHT DMA_PRIORITY_MEDIUM
#endif

#ifndef DMA_LOW_PRIORITY_HIGH_WEIGHT
#define DMA_LOW_PRIORITY_HIGH_WEIGHT DMA_PRIORITY_HIGH
#endif

#ifndef DMA_HIGH_PRIORITY
#define DMA_HIGH_PRIORITY DMA_PRIORITY_VERY_HIGH
#endif

enum mspi_access_mode {
MSPI_ACCESS_ASYNC = 1,
MSPI_ACCESS_SYNC = 2,
MSPI_ACCESS_DMA = 3
};

struct mspi_context {
struct mspi_xfer xfer;
int packets_left;
struct k_sem lock;
};

struct mspi_stm32_conf {
bool use_dma;
size_t pclk_len;
irq_config_func_t irq_config;
struct mspi_cfg mspicfg;
const struct stm32_pclken *pclken;
const struct pinctrl_dev_config *pcfg;
};

/* Lookup table to set dma priority from the DTS */
static const uint32_t table_priority[] = {
DMA_LOW_PRIORITY_LOW_WEIGHT,
DMA_LOW_PRIORITY_MID_WEIGHT,
DMA_LOW_PRIORITY_HIGH_WEIGHT,
DMA_HIGH_PRIORITY,
};

/* Lookup table to set dma channel direction from the DTS */
static const uint32_t table_direction[] = {
DMA_MEMORY_TO_MEMORY,
DMA_MEMORY_TO_PERIPH,
DMA_PERIPH_TO_MEMORY,
};

#if CONFIG_DMA_STM32U5
static const uint32_t table_src_size[] = {
LL_DMA_SRC_DATAWIDTH_BYTE,
LL_DMA_SRC_DATAWIDTH_HALFWORD,
LL_DMA_SRC_DATAWIDTH_WORD,
};

static const uint32_t table_dest_size[] = {
LL_DMA_DEST_DATAWIDTH_BYTE,
LL_DMA_DEST_DATAWIDTH_HALFWORD,
LL_DMA_DEST_DATAWIDTH_WORD,
};
#else
static const uint32_t table_m_size[] = {
LL_DMA_MDATAALIGN_BYTE,
LL_DMA_MDATAALIGN_HALFWORD,
LL_DMA_MDATAALIGN_WORD,
};

static const uint32_t table_p_size[] = {
LL_DMA_PDATAALIGN_BYTE,
LL_DMA_PDATAALIGN_HALFWORD,
LL_DMA_PDATAALIGN_WORD,
};
#endif /* CONFIG_DMA_STM32U5 */

struct stream {
DMA_TypeDef *reg;
const struct device *dev;
uint32_t channel;
struct dma_config cfg;
uint8_t priority;
bool src_addr_increment;
bool dst_addr_increment;
};

union hmspi_handle {
#ifdef CONFIG_MSPI_STM32_XSPI
XSPI_HandleTypeDef xspi;
#endif
#ifdef CONFIG_MSPI_STM32_OSPI
OSPI_HandleTypeDef ospi;
#endif
#ifdef CONFIG_MSPI_STM32_QSPI
QSPI_HandleTypeDef qspi;
#endif
};

/* mspi data includes the controller specific config variable */
struct mspi_stm32_data {
union hmspi_handle hmspi;
uint32_t memmap_base_addr;
struct mspi_context ctx;
struct mspi_dev_id *dev_id;
struct k_mutex lock;
struct k_sem sync;
struct mspi_dev_cfg dev_cfg;
struct mspi_xip_cfg xip_cfg;
struct stream dma_tx;
struct stream dma_rx;
struct stream dma;
};

#endif /* ZEPHYR_DRIVERS_MSPI_STM32_H_ */
Loading
Loading