diff mbox series

[U-Boot,v2,5/8] spi: cadence_qspi: add reset handling

Message ID 20190221214332.4246-6-simon.k.r.goldschmidt@gmail.com
State Superseded
Delegated to: Marek Vasut
Headers show
Series arm: socfpga: implement proper peripheral reset handling | expand

Commit Message

Simon Goldschmidt Feb. 21, 2019, 9:43 p.m. UTC
This adds reset handling to the cadence qspi driver.

For backwards compatibility, only a warning is printed when failing to
get reset handles.

Signed-off-by: Simon Goldschmidt <simon.k.r.goldschmidt@gmail.com>
---

Changes in v2:
- add .remove callback to release the resets

 drivers/spi/cadence_qspi.c | 16 ++++++++++++++++
 drivers/spi/cadence_qspi.h |  4 ++++
 2 files changed, 20 insertions(+)

Comments

Marek Vasut Feb. 21, 2019, 9:50 p.m. UTC | #1
On 2/21/19 10:43 PM, Simon Goldschmidt wrote:
> This adds reset handling to the cadence qspi driver.
> 
> For backwards compatibility, only a warning is printed when failing to
> get reset handles.
> 
> Signed-off-by: Simon Goldschmidt <simon.k.r.goldschmidt@gmail.com>
> ---
> 
> Changes in v2:
> - add .remove callback to release the resets
> 
>  drivers/spi/cadence_qspi.c | 16 ++++++++++++++++
>  drivers/spi/cadence_qspi.h |  4 ++++
>  2 files changed, 20 insertions(+)
> 
> diff --git a/drivers/spi/cadence_qspi.c b/drivers/spi/cadence_qspi.c
> index 11fce9c4fe..3bfa0201c4 100644
> --- a/drivers/spi/cadence_qspi.c
> +++ b/drivers/spi/cadence_qspi.c
> @@ -8,6 +8,7 @@
>  #include <dm.h>
>  #include <fdtdec.h>
>  #include <malloc.h>
> +#include <reset.h>
>  #include <spi.h>
>  #include <linux/errno.h>
>  #include "cadence_qspi.h"
> @@ -154,10 +155,17 @@ static int cadence_spi_probe(struct udevice *bus)
>  {
>  	struct cadence_spi_platdata *plat = bus->platdata;
>  	struct cadence_spi_priv *priv = dev_get_priv(bus);
> +	int ret;
>  
>  	priv->regbase = plat->regbase;
>  	priv->ahbbase = plat->ahbbase;
>  
> +	ret = reset_get_bulk(bus, &priv->resets);
> +	if (ret)
> +		dev_warn(bus, "Can't get reset: %d\n", ret);
> +	else
> +		reset_deassert_bulk(&priv->resets);
> +
>  	if (!priv->qspi_is_init) {
>  		cadence_qspi_apb_controller_init(plat);
>  		priv->qspi_is_init = 1;
> @@ -166,6 +174,13 @@ static int cadence_spi_probe(struct udevice *bus)
>  	return 0;
>  }
>  
> +static int cadence_spi_remove(struct udevice *dev)
> +{
> +	struct cadence_spi_priv *priv = dev_get_priv(dev);
> +
> +	return reset_release_bulk(&priv->resets);
> +}
> +
>  static int cadence_spi_set_mode(struct udevice *bus, uint mode)
>  {
>  	struct cadence_spi_priv *priv = dev_get_priv(bus);
> @@ -342,4 +357,5 @@ U_BOOT_DRIVER(cadence_spi) = {
>  	.platdata_auto_alloc_size = sizeof(struct cadence_spi_platdata),
>  	.priv_auto_alloc_size = sizeof(struct cadence_spi_priv),
>  	.probe = cadence_spi_probe,
> +	.remove = cadence_spi_remove,

.remove() only ever gets executed for drivers setting DM_FLAG_OS_PREPARE
flag. Fix this in the other drivers too.
Simon Goldschmidt Feb. 21, 2019, 10:04 p.m. UTC | #2
Am Do., 21. Feb. 2019, 22:56 hat Marek Vasut <marex@denx.de> geschrieben:

> On 2/21/19 10:43 PM, Simon Goldschmidt wrote:
> > This adds reset handling to the cadence qspi driver.
> >
> > For backwards compatibility, only a warning is printed when failing to
> > get reset handles.
> >
> > Signed-off-by: Simon Goldschmidt <simon.k.r.goldschmidt@gmail.com>
> > ---
> >
> > Changes in v2:
> > - add .remove callback to release the resets
> >
> >  drivers/spi/cadence_qspi.c | 16 ++++++++++++++++
> >  drivers/spi/cadence_qspi.h |  4 ++++
> >  2 files changed, 20 insertions(+)
> >
> > diff --git a/drivers/spi/cadence_qspi.c b/drivers/spi/cadence_qspi.c
> > index 11fce9c4fe..3bfa0201c4 100644
> > --- a/drivers/spi/cadence_qspi.c
> > +++ b/drivers/spi/cadence_qspi.c
> > @@ -8,6 +8,7 @@
> >  #include <dm.h>
> >  #include <fdtdec.h>
> >  #include <malloc.h>
> > +#include <reset.h>
> >  #include <spi.h>
> >  #include <linux/errno.h>
> >  #include "cadence_qspi.h"
> > @@ -154,10 +155,17 @@ static int cadence_spi_probe(struct udevice *bus)
> >  {
> >       struct cadence_spi_platdata *plat = bus->platdata;
> >       struct cadence_spi_priv *priv = dev_get_priv(bus);
> > +     int ret;
> >
> >       priv->regbase = plat->regbase;
> >       priv->ahbbase = plat->ahbbase;
> >
> > +     ret = reset_get_bulk(bus, &priv->resets);
> > +     if (ret)
> > +             dev_warn(bus, "Can't get reset: %d\n", ret);
> > +     else
> > +             reset_deassert_bulk(&priv->resets);
> > +
> >       if (!priv->qspi_is_init) {
> >               cadence_qspi_apb_controller_init(plat);
> >               priv->qspi_is_init = 1;
> > @@ -166,6 +174,13 @@ static int cadence_spi_probe(struct udevice *bus)
> >       return 0;
> >  }
> >
> > +static int cadence_spi_remove(struct udevice *dev)
> > +{
> > +     struct cadence_spi_priv *priv = dev_get_priv(dev);
> > +
> > +     return reset_release_bulk(&priv->resets);
> > +}
> > +
> >  static int cadence_spi_set_mode(struct udevice *bus, uint mode)
> >  {
> >       struct cadence_spi_priv *priv = dev_get_priv(bus);
> > @@ -342,4 +357,5 @@ U_BOOT_DRIVER(cadence_spi) = {
> >       .platdata_auto_alloc_size = sizeof(struct cadence_spi_platdata),
> >       .priv_auto_alloc_size = sizeof(struct cadence_spi_priv),
> >       .probe = cadence_spi_probe,
> > +     .remove = cadence_spi_remove,
>
> .remove() only ever gets executed for drivers setting DM_FLAG_OS_PREPARE
> flag. Fix this in the other drivers too.
>

Ehrm, I haven't checked, but is this common practice? Why doesn't it always
get called?

Regards,
Simon

>
Marek Vasut Feb. 21, 2019, 10:14 p.m. UTC | #3
On 2/21/19 11:04 PM, Simon Goldschmidt wrote:
> 
> 
> Am Do., 21. Feb. 2019, 22:56 hat Marek Vasut <marex@denx.de
> <mailto:marex@denx.de>> geschrieben:
> 
>     On 2/21/19 10:43 PM, Simon Goldschmidt wrote:
>     > This adds reset handling to the cadence qspi driver.
>     >
>     > For backwards compatibility, only a warning is printed when failing to
>     > get reset handles.
>     >
>     > Signed-off-by: Simon Goldschmidt <simon.k.r.goldschmidt@gmail.com
>     <mailto:simon.k.r.goldschmidt@gmail.com>>
>     > ---
>     >
>     > Changes in v2:
>     > - add .remove callback to release the resets
>     >
>     >  drivers/spi/cadence_qspi.c | 16 ++++++++++++++++
>     >  drivers/spi/cadence_qspi.h |  4 ++++
>     >  2 files changed, 20 insertions(+)
>     >
>     > diff --git a/drivers/spi/cadence_qspi.c b/drivers/spi/cadence_qspi.c
>     > index 11fce9c4fe..3bfa0201c4 100644
>     > --- a/drivers/spi/cadence_qspi.c
>     > +++ b/drivers/spi/cadence_qspi.c
>     > @@ -8,6 +8,7 @@
>     >  #include <dm.h>
>     >  #include <fdtdec.h>
>     >  #include <malloc.h>
>     > +#include <reset.h>
>     >  #include <spi.h>
>     >  #include <linux/errno.h>
>     >  #include "cadence_qspi.h"
>     > @@ -154,10 +155,17 @@ static int cadence_spi_probe(struct udevice
>     *bus)
>     >  {
>     >       struct cadence_spi_platdata *plat = bus->platdata;
>     >       struct cadence_spi_priv *priv = dev_get_priv(bus);
>     > +     int ret;
>     > 
>     >       priv->regbase = plat->regbase;
>     >       priv->ahbbase = plat->ahbbase;
>     > 
>     > +     ret = reset_get_bulk(bus, &priv->resets);
>     > +     if (ret)
>     > +             dev_warn(bus, "Can't get reset: %d\n", ret);
>     > +     else
>     > +             reset_deassert_bulk(&priv->resets);
>     > +
>     >       if (!priv->qspi_is_init) {
>     >               cadence_qspi_apb_controller_init(plat);
>     >               priv->qspi_is_init = 1;
>     > @@ -166,6 +174,13 @@ static int cadence_spi_probe(struct udevice *bus)
>     >       return 0;
>     >  }
>     > 
>     > +static int cadence_spi_remove(struct udevice *dev)
>     > +{
>     > +     struct cadence_spi_priv *priv = dev_get_priv(dev);
>     > +
>     > +     return reset_release_bulk(&priv->resets);
>     > +}
>     > +
>     >  static int cadence_spi_set_mode(struct udevice *bus, uint mode)
>     >  {
>     >       struct cadence_spi_priv *priv = dev_get_priv(bus);
>     > @@ -342,4 +357,5 @@ U_BOOT_DRIVER(cadence_spi) = {
>     >       .platdata_auto_alloc_size = sizeof(struct cadence_spi_platdata),
>     >       .priv_auto_alloc_size = sizeof(struct cadence_spi_priv),
>     >       .probe = cadence_spi_probe,
>     > +     .remove = cadence_spi_remove,
> 
>     .remove() only ever gets executed for drivers setting DM_FLAG_OS_PREPARE
>     flag. Fix this in the other drivers too.
> 
> 
> Ehrm, I haven't checked, but is this common practice? Why doesn't it
> always get called?

That's how the code behaves. Probably to speed up booting the kernel on
devices which don't need to be torn down.
Simon Goldschmidt Feb. 22, 2019, 6:06 a.m. UTC | #4
On Thu, Feb 21, 2019 at 11:14 PM Marek Vasut <marex@denx.de> wrote:
>
> On 2/21/19 11:04 PM, Simon Goldschmidt wrote:
> >
> >
> > Am Do., 21. Feb. 2019, 22:56 hat Marek Vasut <marex@denx.de
> > <mailto:marex@denx.de>> geschrieben:
> >
> >     On 2/21/19 10:43 PM, Simon Goldschmidt wrote:
> >     > This adds reset handling to the cadence qspi driver.
> >     >
> >     > For backwards compatibility, only a warning is printed when failing to
> >     > get reset handles.
> >     >
> >     > Signed-off-by: Simon Goldschmidt <simon.k.r.goldschmidt@gmail.com
> >     <mailto:simon.k.r.goldschmidt@gmail.com>>
> >     > ---
> >     >
> >     > Changes in v2:
> >     > - add .remove callback to release the resets
> >     >
> >     >  drivers/spi/cadence_qspi.c | 16 ++++++++++++++++
> >     >  drivers/spi/cadence_qspi.h |  4 ++++
> >     >  2 files changed, 20 insertions(+)
> >     >
> >     > diff --git a/drivers/spi/cadence_qspi.c b/drivers/spi/cadence_qspi.c
> >     > index 11fce9c4fe..3bfa0201c4 100644
> >     > --- a/drivers/spi/cadence_qspi.c
> >     > +++ b/drivers/spi/cadence_qspi.c
> >     > @@ -8,6 +8,7 @@
> >     >  #include <dm.h>
> >     >  #include <fdtdec.h>
> >     >  #include <malloc.h>
> >     > +#include <reset.h>
> >     >  #include <spi.h>
> >     >  #include <linux/errno.h>
> >     >  #include "cadence_qspi.h"
> >     > @@ -154,10 +155,17 @@ static int cadence_spi_probe(struct udevice
> >     *bus)
> >     >  {
> >     >       struct cadence_spi_platdata *plat = bus->platdata;
> >     >       struct cadence_spi_priv *priv = dev_get_priv(bus);
> >     > +     int ret;
> >     >
> >     >       priv->regbase = plat->regbase;
> >     >       priv->ahbbase = plat->ahbbase;
> >     >
> >     > +     ret = reset_get_bulk(bus, &priv->resets);
> >     > +     if (ret)
> >     > +             dev_warn(bus, "Can't get reset: %d\n", ret);
> >     > +     else
> >     > +             reset_deassert_bulk(&priv->resets);
> >     > +
> >     >       if (!priv->qspi_is_init) {
> >     >               cadence_qspi_apb_controller_init(plat);
> >     >               priv->qspi_is_init = 1;
> >     > @@ -166,6 +174,13 @@ static int cadence_spi_probe(struct udevice *bus)
> >     >       return 0;
> >     >  }
> >     >
> >     > +static int cadence_spi_remove(struct udevice *dev)
> >     > +{
> >     > +     struct cadence_spi_priv *priv = dev_get_priv(dev);
> >     > +
> >     > +     return reset_release_bulk(&priv->resets);
> >     > +}
> >     > +
> >     >  static int cadence_spi_set_mode(struct udevice *bus, uint mode)
> >     >  {
> >     >       struct cadence_spi_priv *priv = dev_get_priv(bus);
> >     > @@ -342,4 +357,5 @@ U_BOOT_DRIVER(cadence_spi) = {
> >     >       .platdata_auto_alloc_size = sizeof(struct cadence_spi_platdata),
> >     >       .priv_auto_alloc_size = sizeof(struct cadence_spi_priv),
> >     >       .probe = cadence_spi_probe,
> >     > +     .remove = cadence_spi_remove,
> >
> >     .remove() only ever gets executed for drivers setting DM_FLAG_OS_PREPARE
> >     flag. Fix this in the other drivers too.
> >
> >
> > Ehrm, I haven't checked, but is this common practice? Why doesn't it
> > always get called?
>
> That's how the code behaves. Probably to speed up booting the kernel on
> devices which don't need to be torn down.

What surprises me is that the OS_PREPARE flag is used only for one spi driver
and for 'mmc_blk' (but this is really new). Is it still the right
thing to do? How could
this be one of the first drivers releasing its reset before boot? :-)

Regards,
Simon
Marek Vasut Feb. 22, 2019, 4:07 p.m. UTC | #5
On 2/22/19 7:06 AM, Simon Goldschmidt wrote:
> On Thu, Feb 21, 2019 at 11:14 PM Marek Vasut <marex@denx.de> wrote:
>>
>> On 2/21/19 11:04 PM, Simon Goldschmidt wrote:
>>>
>>>
>>> Am Do., 21. Feb. 2019, 22:56 hat Marek Vasut <marex@denx.de
>>> <mailto:marex@denx.de>> geschrieben:
>>>
>>>     On 2/21/19 10:43 PM, Simon Goldschmidt wrote:
>>>     > This adds reset handling to the cadence qspi driver.
>>>     >
>>>     > For backwards compatibility, only a warning is printed when failing to
>>>     > get reset handles.
>>>     >
>>>     > Signed-off-by: Simon Goldschmidt <simon.k.r.goldschmidt@gmail.com
>>>     <mailto:simon.k.r.goldschmidt@gmail.com>>
>>>     > ---
>>>     >
>>>     > Changes in v2:
>>>     > - add .remove callback to release the resets
>>>     >
>>>     >  drivers/spi/cadence_qspi.c | 16 ++++++++++++++++
>>>     >  drivers/spi/cadence_qspi.h |  4 ++++
>>>     >  2 files changed, 20 insertions(+)
>>>     >
>>>     > diff --git a/drivers/spi/cadence_qspi.c b/drivers/spi/cadence_qspi.c
>>>     > index 11fce9c4fe..3bfa0201c4 100644
>>>     > --- a/drivers/spi/cadence_qspi.c
>>>     > +++ b/drivers/spi/cadence_qspi.c
>>>     > @@ -8,6 +8,7 @@
>>>     >  #include <dm.h>
>>>     >  #include <fdtdec.h>
>>>     >  #include <malloc.h>
>>>     > +#include <reset.h>
>>>     >  #include <spi.h>
>>>     >  #include <linux/errno.h>
>>>     >  #include "cadence_qspi.h"
>>>     > @@ -154,10 +155,17 @@ static int cadence_spi_probe(struct udevice
>>>     *bus)
>>>     >  {
>>>     >       struct cadence_spi_platdata *plat = bus->platdata;
>>>     >       struct cadence_spi_priv *priv = dev_get_priv(bus);
>>>     > +     int ret;
>>>     >
>>>     >       priv->regbase = plat->regbase;
>>>     >       priv->ahbbase = plat->ahbbase;
>>>     >
>>>     > +     ret = reset_get_bulk(bus, &priv->resets);
>>>     > +     if (ret)
>>>     > +             dev_warn(bus, "Can't get reset: %d\n", ret);
>>>     > +     else
>>>     > +             reset_deassert_bulk(&priv->resets);
>>>     > +
>>>     >       if (!priv->qspi_is_init) {
>>>     >               cadence_qspi_apb_controller_init(plat);
>>>     >               priv->qspi_is_init = 1;
>>>     > @@ -166,6 +174,13 @@ static int cadence_spi_probe(struct udevice *bus)
>>>     >       return 0;
>>>     >  }
>>>     >
>>>     > +static int cadence_spi_remove(struct udevice *dev)
>>>     > +{
>>>     > +     struct cadence_spi_priv *priv = dev_get_priv(dev);
>>>     > +
>>>     > +     return reset_release_bulk(&priv->resets);
>>>     > +}
>>>     > +
>>>     >  static int cadence_spi_set_mode(struct udevice *bus, uint mode)
>>>     >  {
>>>     >       struct cadence_spi_priv *priv = dev_get_priv(bus);
>>>     > @@ -342,4 +357,5 @@ U_BOOT_DRIVER(cadence_spi) = {
>>>     >       .platdata_auto_alloc_size = sizeof(struct cadence_spi_platdata),
>>>     >       .priv_auto_alloc_size = sizeof(struct cadence_spi_priv),
>>>     >       .probe = cadence_spi_probe,
>>>     > +     .remove = cadence_spi_remove,
>>>
>>>     .remove() only ever gets executed for drivers setting DM_FLAG_OS_PREPARE
>>>     flag. Fix this in the other drivers too.
>>>
>>>
>>> Ehrm, I haven't checked, but is this common practice? Why doesn't it
>>> always get called?
>>
>> That's how the code behaves. Probably to speed up booting the kernel on
>> devices which don't need to be torn down.
> 
> What surprises me is that the OS_PREPARE flag is used only for one spi driver
> and for 'mmc_blk' (but this is really new). Is it still the right
> thing to do? How could
> this be one of the first drivers releasing its reset before boot? :-)

I suspect this might be an area for improvement :)
diff mbox series

Patch

diff --git a/drivers/spi/cadence_qspi.c b/drivers/spi/cadence_qspi.c
index 11fce9c4fe..3bfa0201c4 100644
--- a/drivers/spi/cadence_qspi.c
+++ b/drivers/spi/cadence_qspi.c
@@ -8,6 +8,7 @@ 
 #include <dm.h>
 #include <fdtdec.h>
 #include <malloc.h>
+#include <reset.h>
 #include <spi.h>
 #include <linux/errno.h>
 #include "cadence_qspi.h"
@@ -154,10 +155,17 @@  static int cadence_spi_probe(struct udevice *bus)
 {
 	struct cadence_spi_platdata *plat = bus->platdata;
 	struct cadence_spi_priv *priv = dev_get_priv(bus);
+	int ret;
 
 	priv->regbase = plat->regbase;
 	priv->ahbbase = plat->ahbbase;
 
+	ret = reset_get_bulk(bus, &priv->resets);
+	if (ret)
+		dev_warn(bus, "Can't get reset: %d\n", ret);
+	else
+		reset_deassert_bulk(&priv->resets);
+
 	if (!priv->qspi_is_init) {
 		cadence_qspi_apb_controller_init(plat);
 		priv->qspi_is_init = 1;
@@ -166,6 +174,13 @@  static int cadence_spi_probe(struct udevice *bus)
 	return 0;
 }
 
+static int cadence_spi_remove(struct udevice *dev)
+{
+	struct cadence_spi_priv *priv = dev_get_priv(dev);
+
+	return reset_release_bulk(&priv->resets);
+}
+
 static int cadence_spi_set_mode(struct udevice *bus, uint mode)
 {
 	struct cadence_spi_priv *priv = dev_get_priv(bus);
@@ -342,4 +357,5 @@  U_BOOT_DRIVER(cadence_spi) = {
 	.platdata_auto_alloc_size = sizeof(struct cadence_spi_platdata),
 	.priv_auto_alloc_size = sizeof(struct cadence_spi_priv),
 	.probe = cadence_spi_probe,
+	.remove = cadence_spi_remove,
 };
diff --git a/drivers/spi/cadence_qspi.h b/drivers/spi/cadence_qspi.h
index 055900def0..d4ede6e15e 100644
--- a/drivers/spi/cadence_qspi.h
+++ b/drivers/spi/cadence_qspi.h
@@ -7,6 +7,8 @@ 
 #ifndef __CADENCE_QSPI_H__
 #define __CADENCE_QSPI_H__
 
+#include <reset.h>
+
 #define CQSPI_IS_ADDR(cmd_len)		(cmd_len > 1 ? 1 : 0)
 
 #define CQSPI_NO_DECODER_MAX_CS		4
@@ -42,6 +44,8 @@  struct cadence_spi_priv {
 	unsigned int	qspi_calibrated_hz;
 	unsigned int	qspi_calibrated_cs;
 	unsigned int	previous_hz;
+
+	struct reset_ctl_bulk resets;
 };
 
 /* Functions call declaration */