Commit 9d282c17 authored by Patrice Chotard's avatar Patrice Chotard Committed by Mark Brown

spi: stm32-qspi: Add pm_runtime support

By default, STM32_AUTOSUSPEND_DELAY is set to -1 which has for
effect to prevent runtime suspends.
Runtime suspends can be activated by setting autosuspend_delay_ms using
sysfs entry :
echo {delay_in_ms} > /sys/devices/platform/soc/58003000.spi/power/autosusp
end_delay_ms)
Signed-off-by: default avatarChristophe Kerello <christophe.kerello@st.com>
Signed-off-by: default avatarPatrice Chotard <patrice.chotard@st.com>
Signed-off-by: default avatarBenjamin Gaignard <benjamin.gaignard@st.com>
Link: https://lore.kernel.org/r/20200417121241.6473-1-patrice.chotard@st.comSigned-off-by: default avatarMark Brown <broonie@kernel.org>
parent 5ba8e3e7
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_device.h> #include <linux/of_device.h>
#include <linux/pinctrl/consumer.h> #include <linux/pinctrl/consumer.h>
#include <linux/pm_runtime.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/reset.h> #include <linux/reset.h>
#include <linux/sizes.h> #include <linux/sizes.h>
...@@ -87,6 +88,7 @@ ...@@ -87,6 +88,7 @@
#define STM32_BUSY_TIMEOUT_US 100000 #define STM32_BUSY_TIMEOUT_US 100000
#define STM32_ABT_TIMEOUT_US 100000 #define STM32_ABT_TIMEOUT_US 100000
#define STM32_COMP_TIMEOUT_MS 1000 #define STM32_COMP_TIMEOUT_MS 1000
#define STM32_AUTOSUSPEND_DELAY -1
struct stm32_qspi_flash { struct stm32_qspi_flash {
struct stm32_qspi *qspi; struct stm32_qspi *qspi;
...@@ -431,10 +433,17 @@ static int stm32_qspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) ...@@ -431,10 +433,17 @@ static int stm32_qspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
struct stm32_qspi *qspi = spi_controller_get_devdata(mem->spi->master); struct stm32_qspi *qspi = spi_controller_get_devdata(mem->spi->master);
int ret; int ret;
ret = pm_runtime_get_sync(qspi->dev);
if (ret < 0)
return ret;
mutex_lock(&qspi->lock); mutex_lock(&qspi->lock);
ret = stm32_qspi_send(mem, op); ret = stm32_qspi_send(mem, op);
mutex_unlock(&qspi->lock); mutex_unlock(&qspi->lock);
pm_runtime_mark_last_busy(qspi->dev);
pm_runtime_put_autosuspend(qspi->dev);
return ret; return ret;
} }
...@@ -444,6 +453,7 @@ static int stm32_qspi_setup(struct spi_device *spi) ...@@ -444,6 +453,7 @@ static int stm32_qspi_setup(struct spi_device *spi)
struct stm32_qspi *qspi = spi_controller_get_devdata(ctrl); struct stm32_qspi *qspi = spi_controller_get_devdata(ctrl);
struct stm32_qspi_flash *flash; struct stm32_qspi_flash *flash;
u32 presc; u32 presc;
int ret;
if (ctrl->busy) if (ctrl->busy)
return -EBUSY; return -EBUSY;
...@@ -451,6 +461,10 @@ static int stm32_qspi_setup(struct spi_device *spi) ...@@ -451,6 +461,10 @@ static int stm32_qspi_setup(struct spi_device *spi)
if (!spi->max_speed_hz) if (!spi->max_speed_hz)
return -EINVAL; return -EINVAL;
ret = pm_runtime_get_sync(qspi->dev);
if (ret < 0)
return ret;
presc = DIV_ROUND_UP(qspi->clk_rate, spi->max_speed_hz) - 1; presc = DIV_ROUND_UP(qspi->clk_rate, spi->max_speed_hz) - 1;
flash = &qspi->flash[spi->chip_select]; flash = &qspi->flash[spi->chip_select];
...@@ -467,6 +481,9 @@ static int stm32_qspi_setup(struct spi_device *spi) ...@@ -467,6 +481,9 @@ static int stm32_qspi_setup(struct spi_device *spi)
writel_relaxed(qspi->dcr_reg, qspi->io_base + QSPI_DCR); writel_relaxed(qspi->dcr_reg, qspi->io_base + QSPI_DCR);
mutex_unlock(&qspi->lock); mutex_unlock(&qspi->lock);
pm_runtime_mark_last_busy(qspi->dev);
pm_runtime_put_autosuspend(qspi->dev);
return 0; return 0;
} }
...@@ -643,9 +660,20 @@ static int stm32_qspi_probe(struct platform_device *pdev) ...@@ -643,9 +660,20 @@ static int stm32_qspi_probe(struct platform_device *pdev)
ctrl->num_chipselect = STM32_QSPI_MAX_NORCHIP; ctrl->num_chipselect = STM32_QSPI_MAX_NORCHIP;
ctrl->dev.of_node = dev->of_node; ctrl->dev.of_node = dev->of_node;
pm_runtime_set_autosuspend_delay(dev, STM32_AUTOSUSPEND_DELAY);
pm_runtime_use_autosuspend(dev);
pm_runtime_set_active(dev);
pm_runtime_enable(dev);
pm_runtime_get_noresume(dev);
ret = devm_spi_register_master(dev, ctrl); ret = devm_spi_register_master(dev, ctrl);
if (!ret) if (ret)
return 0; goto err_qspi_release;
pm_runtime_mark_last_busy(dev);
pm_runtime_put_autosuspend(dev);
return 0;
err_qspi_release: err_qspi_release:
stm32_qspi_release(qspi); stm32_qspi_release(qspi);
...@@ -660,14 +688,28 @@ static int stm32_qspi_remove(struct platform_device *pdev) ...@@ -660,14 +688,28 @@ static int stm32_qspi_remove(struct platform_device *pdev)
struct stm32_qspi *qspi = platform_get_drvdata(pdev); struct stm32_qspi *qspi = platform_get_drvdata(pdev);
stm32_qspi_release(qspi); stm32_qspi_release(qspi);
return 0; return 0;
} }
static int __maybe_unused stm32_qspi_suspend(struct device *dev) static int __maybe_unused stm32_qspi_runtime_suspend(struct device *dev)
{ {
struct stm32_qspi *qspi = dev_get_drvdata(dev); struct stm32_qspi *qspi = dev_get_drvdata(dev);
clk_disable_unprepare(qspi->clk); clk_disable_unprepare(qspi->clk);
return 0;
}
static int __maybe_unused stm32_qspi_runtime_resume(struct device *dev)
{
struct stm32_qspi *qspi = dev_get_drvdata(dev);
return clk_prepare_enable(qspi->clk);
}
static int __maybe_unused stm32_qspi_suspend(struct device *dev)
{
pinctrl_pm_select_sleep_state(dev); pinctrl_pm_select_sleep_state(dev);
return 0; return 0;
...@@ -683,10 +725,17 @@ static int __maybe_unused stm32_qspi_resume(struct device *dev) ...@@ -683,10 +725,17 @@ static int __maybe_unused stm32_qspi_resume(struct device *dev)
writel_relaxed(qspi->cr_reg, qspi->io_base + QSPI_CR); writel_relaxed(qspi->cr_reg, qspi->io_base + QSPI_CR);
writel_relaxed(qspi->dcr_reg, qspi->io_base + QSPI_DCR); writel_relaxed(qspi->dcr_reg, qspi->io_base + QSPI_DCR);
pm_runtime_mark_last_busy(qspi->dev);
pm_runtime_put_autosuspend(qspi->dev);
return 0; return 0;
} }
static SIMPLE_DEV_PM_OPS(stm32_qspi_pm_ops, stm32_qspi_suspend, stm32_qspi_resume); static const struct dev_pm_ops stm32_qspi_pm_ops = {
SET_RUNTIME_PM_OPS(stm32_qspi_runtime_suspend,
stm32_qspi_runtime_resume, NULL)
SET_SYSTEM_SLEEP_PM_OPS(stm32_qspi_suspend, stm32_qspi_resume)
};
static const struct of_device_id stm32_qspi_match[] = { static const struct of_device_id stm32_qspi_match[] = {
{.compatible = "st,stm32f469-qspi"}, {.compatible = "st,stm32f469-qspi"},
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment