mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	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: Christophe Kerello <christophe.kerello@st.com>
Signed-off-by: Patrice Chotard <patrice.chotard@st.com>
Signed-off-by: Benjamin Gaignard <benjamin.gaignard@st.com>
Link: https://lore.kernel.org/r/20200417121241.6473-1-patrice.chotard@st.com
Signed-off-by: Mark Brown <broonie@kernel.org>
			
			
This commit is contained in:
		
							parent
							
								
									5ba8e3e753
								
							
						
					
					
						commit
						9d282c17b0
					
				
					 1 changed files with 53 additions and 4 deletions
				
			
		| 
						 | 
				
			
			@ -16,6 +16,7 @@
 | 
			
		|||
#include <linux/of.h>
 | 
			
		||||
#include <linux/of_device.h>
 | 
			
		||||
#include <linux/pinctrl/consumer.h>
 | 
			
		||||
#include <linux/pm_runtime.h>
 | 
			
		||||
#include <linux/platform_device.h>
 | 
			
		||||
#include <linux/reset.h>
 | 
			
		||||
#include <linux/sizes.h>
 | 
			
		||||
| 
						 | 
				
			
			@ -87,6 +88,7 @@
 | 
			
		|||
#define STM32_BUSY_TIMEOUT_US 100000
 | 
			
		||||
#define STM32_ABT_TIMEOUT_US 100000
 | 
			
		||||
#define STM32_COMP_TIMEOUT_MS 1000
 | 
			
		||||
#define STM32_AUTOSUSPEND_DELAY -1
 | 
			
		||||
 | 
			
		||||
struct stm32_qspi_flash {
 | 
			
		||||
	struct stm32_qspi *qspi;
 | 
			
		||||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	ret = pm_runtime_get_sync(qspi->dev);
 | 
			
		||||
	if (ret < 0)
 | 
			
		||||
		return ret;
 | 
			
		||||
 | 
			
		||||
	mutex_lock(&qspi->lock);
 | 
			
		||||
	ret = stm32_qspi_send(mem, op);
 | 
			
		||||
	mutex_unlock(&qspi->lock);
 | 
			
		||||
 | 
			
		||||
	pm_runtime_mark_last_busy(qspi->dev);
 | 
			
		||||
	pm_runtime_put_autosuspend(qspi->dev);
 | 
			
		||||
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -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_flash *flash;
 | 
			
		||||
	u32 presc;
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	if (ctrl->busy)
 | 
			
		||||
		return -EBUSY;
 | 
			
		||||
| 
						 | 
				
			
			@ -451,6 +461,10 @@ static int stm32_qspi_setup(struct spi_device *spi)
 | 
			
		|||
	if (!spi->max_speed_hz)
 | 
			
		||||
		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;
 | 
			
		||||
 | 
			
		||||
	flash = &qspi->flash[spi->chip_select];
 | 
			
		||||
| 
						 | 
				
			
			@ -467,6 +481,9 @@ static int stm32_qspi_setup(struct spi_device *spi)
 | 
			
		|||
	writel_relaxed(qspi->dcr_reg, qspi->io_base + QSPI_DCR);
 | 
			
		||||
	mutex_unlock(&qspi->lock);
 | 
			
		||||
 | 
			
		||||
	pm_runtime_mark_last_busy(qspi->dev);
 | 
			
		||||
	pm_runtime_put_autosuspend(qspi->dev);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -643,8 +660,19 @@ static int stm32_qspi_probe(struct platform_device *pdev)
 | 
			
		|||
	ctrl->num_chipselect = STM32_QSPI_MAX_NORCHIP;
 | 
			
		||||
	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);
 | 
			
		||||
	if (!ret)
 | 
			
		||||
	if (ret)
 | 
			
		||||
		goto err_qspi_release;
 | 
			
		||||
 | 
			
		||||
	pm_runtime_mark_last_busy(dev);
 | 
			
		||||
	pm_runtime_put_autosuspend(dev);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
 | 
			
		||||
err_qspi_release:
 | 
			
		||||
| 
						 | 
				
			
			@ -660,14 +688,28 @@ static int stm32_qspi_remove(struct platform_device *pdev)
 | 
			
		|||
	struct stm32_qspi *qspi = platform_get_drvdata(pdev);
 | 
			
		||||
 | 
			
		||||
	stm32_qspi_release(qspi);
 | 
			
		||||
 | 
			
		||||
	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);
 | 
			
		||||
 | 
			
		||||
	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);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -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->dcr_reg, qspi->io_base + QSPI_DCR);
 | 
			
		||||
 | 
			
		||||
	pm_runtime_mark_last_busy(qspi->dev);
 | 
			
		||||
	pm_runtime_put_autosuspend(qspi->dev);
 | 
			
		||||
 | 
			
		||||
	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[] = {
 | 
			
		||||
	{.compatible = "st,stm32f469-qspi"},
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue