Skip to content

Commit

Permalink
spi: orion: enable clocks before spi_setup
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Marcin Wojtas authored and Mark Brown committed Dec 28, 2020
1 parent a34d419 commit e2be703
Showing 1 changed file with 22 additions and 1 deletion.
23 changes: 22 additions & 1 deletion drivers/spi/spi-orion.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit e2be703

Please sign in to comment.