diff mbox series

[v2,1/2] spi: orion: enable clocks before spi_setup

Message ID 20201217170933.10717-2-kostap@marvell.com
State Superseded
Headers show
Series spi: new feature and fix for Marvell Orion driver | expand

Commit Message

Kostya Porotchkin Dec. 17, 2020, 5:09 p.m. UTC
From: Marcin Wojtas <mw@semihalf.com>

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>
---
 drivers/spi/spi-orion.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

Comments

Mark Brown Dec. 17, 2020, 5:25 p.m. UTC | #1
On Thu, Dec 17, 2020 at 07:09:31PM +0200, kostap@marvell.com wrote:

> +	/*
> +	 * Make sure the clocks are enabled before
> +	 * configuring the SPI controller.
> +	 */
> +	clk_prepare_enable(orion_spi->clk);
> +	if (!IS_ERR(orion_spi->axi_clk))
> +		clk_prepare_enable(orion_spi->axi_clk);
> +
>  	return orion_spi_setup_transfer(spi, NULL);
>  }

There's no matching disable here so we'll leak the enables every time
setup() is called - we should unwind the enables after calling
_setup_transfer().  It may be more sensible to just take a runtime PM
reference rather than do the raw clock API stuff, one less call and
means if anything else gets added to runtime PM it'll be handled.
Kostya Porotchkin Dec. 22, 2020, 12:46 p.m. UTC | #2
Hi, Mark,

> -----Original Message-----

> From: Mark Brown <broonie@kernel.org>


> > +	/*

> > +	 * Make sure the clocks are enabled before

> > +	 * configuring the SPI controller.

> > +	 */

> > +	clk_prepare_enable(orion_spi->clk);

> > +	if (!IS_ERR(orion_spi->axi_clk))

> > +		clk_prepare_enable(orion_spi->axi_clk);

> > +

> >  	return orion_spi_setup_transfer(spi, NULL);  }

> 

> There's no matching disable here so we'll leak the enables every time

> setup() is called - we should unwind the enables after calling

> _setup_transfer().  It may be more sensible to just take a runtime PM

> reference rather than do the raw clock API stuff, one less call and means if

> anything else gets added to runtime PM it'll be handled.


[KP] You mean we should call here to orion_spi_runtime_resume() instead of clk_prepare_enable() and make this PM function available regardless the CONFIG_PM option?

Thanks
Kosta
Mark Brown Dec. 22, 2020, 4:56 p.m. UTC | #3
On Tue, Dec 22, 2020 at 12:46:01PM +0000, Kostya Porotchkin wrote:

Please fix your mail client to word wrap within paragraphs at something
substantially less than 80 columns.  Doing this makes your messages much
easier to read and reply to.

> > There's no matching disable here so we'll leak the enables every time

> > setup() is called - we should unwind the enables after calling

> > _setup_transfer().  It may be more sensible to just take a runtime PM

> > reference rather than do the raw clock API stuff, one less call and means if

> > anything else gets added to runtime PM it'll be handled.


> [KP] You mean we should call here to orion_spi_runtime_resume()

> instead of clk_prepare_enable() and make this PM function available

> regardless the CONFIG_PM option?


That's one part of the suggestion, yes - the other part is that you need
to have a disable matching the enable here.
diff mbox series

Patch

diff --git a/drivers/spi/spi-orion.c b/drivers/spi/spi-orion.c
index b57b8b3cc26e..3bfda4225d45 100644
--- a/drivers/spi/spi-orion.c
+++ b/drivers/spi/spi-orion.c
@@ -507,6 +507,16 @@  static int orion_spi_transfer_one(struct spi_master *master,
 
 static int orion_spi_setup(struct spi_device *spi)
 {
+	struct orion_spi *orion_spi = spi_master_get_devdata(spi->master);
+
+	/*
+	 * Make sure the clocks are enabled before
+	 * configuring the SPI controller.
+	 */
+	clk_prepare_enable(orion_spi->clk);
+	if (!IS_ERR(orion_spi->axi_clk))
+		clk_prepare_enable(orion_spi->axi_clk);
+
 	return orion_spi_setup_transfer(spi, NULL);
 }