diff --git a/drivers/flash/Kconfig.stm32_qspi b/drivers/flash/Kconfig.stm32_qspi index aa174bfd21e..38b6ab7213a 100644 --- a/drivers/flash/Kconfig.stm32_qspi +++ b/drivers/flash/Kconfig.stm32_qspi @@ -6,7 +6,7 @@ DT_STM32_QUADSPI_HAS_DMA := $(dt_compat_any_has_prop,$(DT_COMPAT_ST_STM32_QSPI),dmas) -config FLASH_STM32_QSPI +menuconfig FLASH_STM32_QSPI bool "STM32 Quad SPI Flash driver" default y depends on DT_HAS_ST_STM32_QSPI_NOR_ENABLED @@ -21,3 +21,22 @@ config FLASH_STM32_QSPI select USE_STM32_HAL_DMA if $(DT_STM32_QUADSPI_HAS_DMA) help Enable QSPI-NOR support on the STM32 family of processors. + +if FLASH_STM32_QSPI + +config FLASH_STM32_QSPI_GENERIC_READ + bool "Generic read command extended operation" + select FLASH_HAS_EX_OP + help + Enables flash extended operation that can be used to transmit + a custom command and read the result to a user-provided buffer. + +config FLASH_STM32_QSPI_GENERIC_WRITE + bool "Generic write command extended operation" + select FLASH_HAS_EX_OP + help + Enables flash extended operation that can be used to transmit + a custom command and write data taken from a user-provided + buffer. + +endif # FLASH_STM32_QSPI diff --git a/drivers/flash/flash_stm32_qspi.c b/drivers/flash/flash_stm32_qspi.c index aec6e99a578..b9ab1afebf1 100644 --- a/drivers/flash/flash_stm32_qspi.c +++ b/drivers/flash/flash_stm32_qspi.c @@ -20,10 +20,16 @@ #include #include #include +#include #include #include #include +#ifdef CONFIG_USERSPACE +#include +#include +#endif + #if DT_INST_NODE_HAS_PROP(0, spi_bus_width) && \ DT_INST_PROP(0, spi_bus_width) == 4 #define STM32_QSPI_USE_QUAD_IO 1 @@ -886,6 +892,81 @@ static void flash_stm32_qspi_pages_layout(const struct device *dev, } #endif +#if defined(CONFIG_FLASH_EX_OP_ENABLED) +#if defined(CONFIG_FLASH_STM32_QSPI_GENERIC_READ) +static int flash_stm32_qspi_generic_read(const struct device *dev, QSPI_CommandTypeDef *cmd, + void *out) +{ + int ret; + +#ifdef CONFIG_USERSPACE + QSPI_CommandTypeDef cmd_copy; + + bool syscall_trap = z_syscall_trap(); + + if (syscall_trap) { + K_OOPS(k_usermode_from_copy(&cmd_copy, cmd, sizeof(cmd_copy))); + cmd = &cmd_copy; + + K_OOPS(K_SYSCALL_MEMORY_WRITE(out, cmd->NbData)); + } +#endif + qspi_lock_thread(dev); + + ret = qspi_read_access(dev, cmd, out, cmd->NbData); + + qspi_unlock_thread(dev); + + return ret; +} +#endif /* CONFIG_FLASH_STM32_QSPI_GENERIC_READ */ + +#if defined(CONFIG_FLASH_STM32_QSPI_GENERIC_WRITE) +static int flash_stm32_qspi_generic_write(const struct device *dev, QSPI_CommandTypeDef *cmd, + void *in) +{ + int ret; + +#ifdef CONFIG_USERSPACE + QSPI_CommandTypeDef cmd_copy; + + bool syscall_trap = z_syscall_trap(); + + if (syscall_trap) { + K_OOPS(k_usermode_from_copy(&cmd_copy, cmd, sizeof(cmd_copy))); + cmd = &cmd_copy; + + K_OOPS(K_SYSCALL_MEMORY_READ(in, cmd->NbData)); + } +#endif + qspi_lock_thread(dev); + + ret = qspi_write_access(dev, cmd, in, cmd->NbData); + + qspi_unlock_thread(dev); + + return ret; +} +#endif /* CONFIG_FLASH_STM32_QSPI_GENERIC_WRITE */ + +static int flash_stm32_qspi_ex_op(const struct device *dev, uint16_t code, const uintptr_t cmd, + void *data) +{ + switch (code) { +#if defined(CONFIG_FLASH_STM32_QSPI_GENERIC_READ) + case FLASH_STM32_QSPI_EX_OP_GENERIC_READ: + return flash_stm32_qspi_generic_read(dev, (QSPI_CommandTypeDef *)cmd, data); +#endif +#if defined(CONFIG_FLASH_STM32_QSPI_GENERIC_WRITE) + case FLASH_STM32_QSPI_EX_OP_GENERIC_WRITE: + return flash_stm32_qspi_generic_write(dev, (QSPI_CommandTypeDef *)cmd, data); +#endif + default: + return -ENOTSUP; + } +} +#endif /* CONFIG_FLASH_EX_OP_ENABLED */ + static DEVICE_API(flash, flash_stm32_qspi_driver_api) = { .read = flash_stm32_qspi_read, .write = flash_stm32_qspi_write, @@ -899,6 +980,9 @@ static DEVICE_API(flash, flash_stm32_qspi_driver_api) = { .sfdp_read = qspi_read_sfdp, .read_jedec_id = qspi_read_jedec_id, #endif /* CONFIG_FLASH_JESD216_API */ +#if defined(CONFIG_FLASH_EX_OP_ENABLED) + .ex_op = flash_stm32_qspi_ex_op, +#endif }; #if defined(CONFIG_FLASH_PAGE_LAYOUT) diff --git a/include/zephyr/drivers/flash/stm32_flash_api_extensions.h b/include/zephyr/drivers/flash/stm32_flash_api_extensions.h index 01147350536..b58a3007352 100644 --- a/include/zephyr/drivers/flash/stm32_flash_api_extensions.h +++ b/include/zephyr/drivers/flash/stm32_flash_api_extensions.h @@ -64,6 +64,25 @@ enum stm32_ex_ops { FLASH_STM32_EX_OP_OPTB_WRITE, }; +#if defined(CONFIG_FLASH_EX_OP_ENABLED) +enum stm32_qspi_ex_ops { + /* + * QSPI generic read command. + * + * Transmit the custom command and read the result to the user-provided + * buffer. + */ + FLASH_STM32_QSPI_EX_OP_GENERIC_READ, + /* + * QSPI generic write command. + * + * Transmit the custom command and then write data taken from the + * user-provided buffer. + */ + FLASH_STM32_QSPI_EX_OP_GENERIC_WRITE, +}; +#endif /* CONFIG_FLASH_EX_OP_ENABLED */ + #if defined(CONFIG_FLASH_STM32_WRITE_PROTECT) struct flash_stm32_ex_op_sector_wp_in { uint64_t enable_mask;