From e2be70318d7b0ad9446d8a64ed1bc73e3316ee39 Mon Sep 17 00:00:00 2001 From: Marcin Wojtas Date: Wed, 23 Dec 2020 12:38:26 +0200 Subject: spi: orion: enable clocks before spi_setup The spi-orion driver disables its clocks whenever it is not used. In usual case during boot (i.e. using SPI flash) it is not a problem, as the child device driver is present and probed along with spi_register_master() execution. However in case the child device driver is not ready (e.g. when its type is module_spi_driver) the spi_setup() callback can be called after the spi-orion probe. It may happen, that as a result there will be an attempt to access controller's registers with the clocks disabled. Prevent such situations and make sure the clocks are on, each time the spi_setup() is called. Signed-off-by: Marcin Wojtas Signed-off-by: Konstantin Porotchkin Link: https://lore.kernel.org/r/20201223103827.29721-2-kostap@marvell.com Signed-off-by: Mark Brown --- drivers/spi/spi-orion.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) (limited to 'drivers/spi/spi-orion.c') diff --git a/drivers/spi/spi-orion.c b/drivers/spi/spi-orion.c index b57b8b3cc26e..133727552e99 100644 --- a/drivers/spi/spi-orion.c +++ b/drivers/spi/spi-orion.c @@ -96,10 +96,16 @@ struct orion_spi { struct clk *clk; struct clk *axi_clk; const struct orion_spi_dev *devdata; + struct device *dev; struct orion_child_options child[ORION_NUM_CHIPSELECTS]; }; +#ifdef CONFIG_PM +static int orion_spi_runtime_suspend(struct device *dev); +static int orion_spi_runtime_resume(struct device *dev); +#endif + static inline void __iomem *spi_reg(struct orion_spi *orion_spi, u32 reg) { return orion_spi->base + reg; @@ -507,7 +513,21 @@ static int orion_spi_transfer_one(struct spi_master *master, static int orion_spi_setup(struct spi_device *spi) { - return orion_spi_setup_transfer(spi, NULL); + int ret; +#ifdef CONFIG_PM + struct orion_spi *orion_spi = spi_master_get_devdata(spi->master); + struct device *dev = orion_spi->dev; + + orion_spi_runtime_resume(dev); +#endif + + ret = orion_spi_setup_transfer(spi, NULL); + +#ifdef CONFIG_PM + orion_spi_runtime_suspend(dev); +#endif + + return ret; } static int orion_spi_reset(struct orion_spi *orion_spi) @@ -630,6 +650,7 @@ static int orion_spi_probe(struct platform_device *pdev) spi = spi_master_get_devdata(master); spi->master = master; + spi->dev = &pdev->dev; of_id = of_match_device(orion_spi_of_match_table, &pdev->dev); devdata = (of_id) ? of_id->data : &orion_spi_dev_data; -- cgit