summaryrefslogtreecommitdiff
path: root/drivers/spi/spi-orion.c
diff options
context:
space:
mode:
authorMarcin Wojtas <mw@semihalf.com>2020-12-23 13:38:26 +0300
committerMark Brown <broonie@kernel.org>2020-12-28 15:25:30 +0300
commite2be70318d7b0ad9446d8a64ed1bc73e3316ee39 (patch)
tree6a124300d4ad82083daa35a6f5379743da130508 /drivers/spi/spi-orion.c
parenta34d4197a144d83d508163404ad7d214082e909a (diff)
downloadlinux-e2be70318d7b0ad9446d8a64ed1bc73e3316ee39.tar.xz
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 <mw@semihalf.com> Signed-off-by: Konstantin Porotchkin <kostap@marvell.com> Link: https://lore.kernel.org/r/20201223103827.29721-2-kostap@marvell.com Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'drivers/spi/spi-orion.c')
-rw-r--r--drivers/spi/spi-orion.c23
1 files changed, 22 insertions, 1 deletions
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;