Skip to content

Commit 223af8c

Browse files
committed
drivers: spi: stm32: Add reinitialization feature
The added reinitialization feature helps PM logic restore bus functionality when clock context is lost in certain low-power modes. Signed-off-by: Kenneth J. Miller <[email protected]>
1 parent 71547b1 commit 223af8c

File tree

2 files changed

+56
-0
lines changed

2 files changed

+56
-0
lines changed

drivers/spi/spi_ll_stm32.c

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1011,6 +1011,27 @@ static int spi_stm32_clock_configure(const struct spi_stm32_config *cfg)
10111011
return 0;
10121012
}
10131013

1014+
#ifdef CONFIG_PM
1015+
/**
1016+
* @brief Reinitialization of SPI context
1017+
*
1018+
* This function reenables clocks, which is required upon exiting certain
1019+
* low-power modes on select SoCs.
1020+
*
1021+
* @param dev SPI device struct
1022+
*
1023+
* @return 0
1024+
*/
1025+
static void spi_stm32_reinit(uint8_t direction, void *ctx)
1026+
{
1027+
ARG_UNUSED(direction);
1028+
const struct device *dev = ctx;
1029+
const struct spi_stm32_config *cfg = dev->config;
1030+
1031+
spi_stm32_clock_configure(cfg);
1032+
}
1033+
#endif /* CONFIG_PM */
1034+
10141035
static int spi_stm32_init(const struct device *dev)
10151036
{
10161037
struct spi_stm32_data *data __attribute__((unused)) = dev->data;
@@ -1059,6 +1080,15 @@ static int spi_stm32_init(const struct device *dev)
10591080

10601081
spi_context_unlock_unconditionally(&data->ctx);
10611082

1083+
#ifdef CONFIG_PM
1084+
if (cfg->reinit_states_size > 0) {
1085+
for (size_t i = 0; i < cfg->reinit_states_size; i++) {
1086+
pm_notifier_register(cfg->notifier, cfg->reinit_states[i].state,
1087+
cfg->reinit_states[i].substate_id);
1088+
}
1089+
}
1090+
#endif /* CONFIG_PM */
1091+
10621092
return 0;
10631093
}
10641094

@@ -1130,11 +1160,30 @@ static void spi_stm32_irq_config_func_##id(const struct device *dev) \
11301160
#define STM32_SPI_USE_SUBGHZSPI_NSS_CONFIG(id)
11311161
#endif
11321162

1163+
#ifdef CONFIG_PM
1164+
#define STM32_SPI_REINIT_STATE_INIT(id) \
1165+
static const struct pm_state_info reinit_states_##id[] \
1166+
= PM_STATE_INFO_LIST_FROM_DT_REINIT(DT_DRV_INST(id))
1167+
1168+
#define STM32_SPI_REINIT_CFG_INIT(id) \
1169+
.notifier = &PM_NOTIFIER(DT_INST_DEP_ORD(id)), \
1170+
.reinit_states = reinit_states_##id, \
1171+
.reinit_states_size = ARRAY_SIZE(reinit_states_##id),
1172+
#else
1173+
#define STM32_SPI_REINIT_STATE_INIT(id)
1174+
#define STM32_SPI_REINIT_CFG_INIT(id)
1175+
#endif /* CONFIG_PM */
1176+
11331177
#define STM32_SPI_INIT(id) \
11341178
STM32_SPI_IRQ_HANDLER_DECL(id); \
11351179
\
11361180
PINCTRL_DT_INST_DEFINE(id); \
11371181
\
1182+
STM32_SPI_REINIT_STATE_INIT(id); \
1183+
\
1184+
PM_NOTIFIER_DEFINE(DT_INST_DEP_ORD(id), PM_STATE_EXIT, \
1185+
spi_stm32_reinit, DEVICE_DT_INST_GET(id)); \
1186+
\
11381187
static const struct stm32_pclken pclken_##id[] = \
11391188
STM32_DT_INST_CLOCKS(id);\
11401189
\
@@ -1145,6 +1194,7 @@ static const struct spi_stm32_config spi_stm32_cfg_##id = { \
11451194
.pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(id), \
11461195
STM32_SPI_IRQ_HANDLER_FUNC(id) \
11471196
STM32_SPI_USE_SUBGHZSPI_NSS_CONFIG(id) \
1197+
STM32_SPI_REINIT_CFG_INIT(id) \
11481198
}; \
11491199
\
11501200
static struct spi_stm32_data spi_stm32_dev_data_##id = { \

drivers/spi/spi_ll_stm32.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#ifndef ZEPHYR_DRIVERS_SPI_SPI_LL_STM32_H_
88
#define ZEPHYR_DRIVERS_SPI_SPI_LL_STM32_H_
99

10+
#include <zephyr/pm/pm.h>
1011
#include <stm32_ll_spi.h>
1112

1213
#include "spi_context.h"
@@ -32,6 +33,11 @@ struct spi_stm32_config {
3233
#endif
3334
size_t pclk_len;
3435
const struct stm32_pclken *pclken;
36+
#ifdef CONFIG_PM
37+
struct pm_notifier *notifier;
38+
const struct pm_state_info *reinit_states;
39+
size_t reinit_states_size;
40+
#endif
3541
};
3642

3743
#ifdef CONFIG_SPI_STM32_DMA

0 commit comments

Comments
 (0)