Skip to content

Conversation

@Praneethsvch
Copy link

Added PM device runtime actions so driver now honors device runtime actions when PM_DEVICE and/or PM_DEVICE_RUNTIME is used. This allows dynamic suspend and resume actions.

  • stm32_sdmmc_pm_action() handling for PM_DEVICE_ACTION_RESUME/SUSPEND
  • Runtime power management via pm_device_runtime_enable()
  • Automatic clock gating and power GPIO control during suspend/resume
  • Safe synchronization with DMA and IRQ state transitions
  • Optional system PM policy locks around active transfers

This ensures the SDMMC peripheral enters low-power states when idle and
restores correctly when accessed again via disk or FS layers.

Tested on: STM32U575 (nucleo_u575zi_q)

Added PM device runtime actions so driver now honors device runtime actions
when PM_DEVICE and/or PM_DEVICE_RUNTIME is used.

Signed-off-by: Praneeth <[email protected]>
@github-actions
Copy link

Hello @Praneethsvch, and thank you very much for your first pull request to the Zephyr project!
Our Continuous Integration pipeline will execute a series of checks on your Pull Request commit messages and code, and you are expected to address any failures by updating the PR. Please take a look at our commit message guidelines to find out how to format your commit messages, and at our contribution workflow to understand how to update your Pull Request. If you haven't already, please make sure to review the project's Contributor Expectations and update (by amending and force-pushing the commits) your pull request if necessary.
If you are stuck or need help please join us on Discord and ask your question there. Additionally, you can escalate the review when applicable. 😊

@sonarqubecloud
Copy link

Copy link
Contributor

@bearsh bearsh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pm_device_runtime_get() / pm_device_runtime_put() is not called in stm32_sdmmc_access_read() stm32_sdmmc_access_write()


#ifdef CONFIG_PM_DEVICE_RUNTIME
pm_device_runtime_get(dev);
#endif
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if CONFIG_PM_DEVICE_RUNTIME is defined, the following code is being called twice, once in stm32_sdmmc_activate() and then here


#ifdef CONFIG_PM_DEVICE_RUNTIME
pm_device_runtime_put(dev);
#endif
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

here the same, stm32_sdmmc_suspend() repeats code already executed in stm32_sdmmc_access_deinit()

Comment on lines +377 to +379
#ifdef CONFIG_PM_DEVICE_RUNTIME
pm_device_runtime_get(dev);
#endif
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pm_device_runtime_*() are already stubbed when CONFIG_PM_DEVICE_RUNTIME is disabled.

Suggested change
#ifdef CONFIG_PM_DEVICE_RUNTIME
pm_device_runtime_get(dev);
#endif
pm_device_runtime_get(dev);

Ditto below.

That said, device the device for runtime PM would make stm32_sdmmc_activate() to be called, so all the clock/pinctrl/SD/MMC initialization already proceeded, no?

return 0;
}

#ifdef CONFIG_PM_DEVICE
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Condition can be remove.


switch (action) {
case PM_DEVICE_ACTION_RESUME:
err = stm32_sdmmc_activate(dev);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpicking: can remove err and use return stm32_sdmmc_xxx(dev); straight.

/* Apply sleep/low-leakage pin state before removing power */
int ret = pinctrl_apply_state(priv->pcfg, PINCTRL_STATE_SLEEP);
if (ret && ret != -ENOTSUP) {
LOG_WRN("sleep pinctrl failed: %d", ret);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LOG_WARN_ONCE() should be enough.
That said stm32_sdmmc_pwr_off(), called right above, already does the job.

/* Gate SDMMC clocks and reset peripheral to kill any latent state */
(void)stm32_sdmmc_clock_disable(priv);
__HAL_RCC_SDMMC1_FORCE_RESET();
__HAL_RCC_SDMMC1_RELEASE_RESET();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prefer reset_line_toggle_dt(&priv->reset); over use of HAL functions.
I wonder if reset should be done at deinit, rather at init, which is already done.

Note: reset operation needs clock to be enabled.


static int stm32_sdmmc_activate(const struct device *dev)
{
pm_policy_state_lock_get(PM_STATE_SUSPEND_TO_IDLE, PM_ALL_SUBSTATES);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this needed?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think so, SDMMC, at least on a U5 is only working in run and sleep but not stop. I don't thinks this is different in other families...

stm32_sdmmc_pwr_off(priv);

/* If HSI48 was used only for SDMMC, system PM may turn it off later.
If you want to force it off right here (safe if USB not used): */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As you said, this may be unsafe. I would leave it running for now until there are some refcount on clock gating requests.

memcpy(csd, &priv->hsd.CSD, sizeof(priv->hsd.CSD));
}

static int stm32_sdmmc_activate(const struct device *dev)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Most of the sequence is already done in in stm32_sdmmc_access_init(). Could you factorize their common code?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants