diff mbox series

[U-Boot,v2,6/8] reset: socfpga: add reset handling for old kernels

Message ID 20190221214332.4246-7-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 code to take peripherals out of reset based on an environment
variable. This is in preparation for removing the code that does this from
SPL.

However, some drivers even in current Linux cannot handle peripheral reset,
so until this works, we need a compatibility workaround.

This workaround is implemented in the 'remove' callback of this reset
driver, which is called on OS_PREPARE: it checks if the environment
variable "socfpga_permodrst_ungate" - if it is set to 1, it deasserts all
peripheral resets, which is what the gen5 SPL did up to now.

This is in preparation to clean up the SPL and implementing proper reset
handling for U-Boot.

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

Changes in v2:
- moved from Kernel option "OLD_SOCFPGA_KERNEL_COMPAT" to environment
  variable "socfpga_permodrst_ungate"

 drivers/reset/reset-socfpga.c | 34 ++++++++++++++++++++++++++++++++++
 1 file changed, 34 insertions(+)

Comments

Marek Vasut Feb. 21, 2019, 9:51 p.m. UTC | #1
On 2/21/19 10:43 PM, Simon Goldschmidt wrote:
> This adds code to take peripherals out of reset based on an environment
> variable. This is in preparation for removing the code that does this from
> SPL.
> 
> However, some drivers even in current Linux cannot handle peripheral reset,
> so until this works, we need a compatibility workaround.
> 
> This workaround is implemented in the 'remove' callback of this reset
> driver, which is called on OS_PREPARE: it checks if the environment
> variable "socfpga_permodrst_ungate" - if it is set to 1, it deasserts all
> peripheral resets, which is what the gen5 SPL did up to now.
> 
> This is in preparation to clean up the SPL and implementing proper reset
> handling for U-Boot.
> 
> Signed-off-by: Simon Goldschmidt <simon.k.r.goldschmidt@gmail.com>
> ---
> 
> Changes in v2:
> - moved from Kernel option "OLD_SOCFPGA_KERNEL_COMPAT" to environment
>   variable "socfpga_permodrst_ungate"
> 
>  drivers/reset/reset-socfpga.c | 34 ++++++++++++++++++++++++++++++++++
>  1 file changed, 34 insertions(+)
> 
> diff --git a/drivers/reset/reset-socfpga.c b/drivers/reset/reset-socfpga.c
> index b2acfcd2ec..749f671e05 100644
> --- a/drivers/reset/reset-socfpga.c
> +++ b/drivers/reset/reset-socfpga.c
> @@ -89,6 +89,36 @@ static int socfpga_reset_probe(struct udevice *dev)
>  	return 0;
>  }
>  
> +#ifndef CONFIG_SPL_BUILD
> +/*
> + * This remove function is called before starting OS to deassert peripheral
> + * resets for Kernels that don't support this.
> + *
> + * The reset driver checks the environment variable "socfpga_permodrst_ungate"
> + * when it is removed. If this variable is '1', all peripherals in 'permodrst'
> + * are taken out of reset before booting into the OS.
> + * This should be required for gen5 systems only that are running Linux kernels
> + * without proper peripheral reset support for all drivers used.
> + */
> +static int socfpga_reset_remove(struct udevice *dev)
> +{
> +	struct socfpga_reset_data *data = dev_get_priv(dev);
> +	const char *env_str;
> +	long val;
> +
> +	env_str = env_get("socfpga_permodrst_ungate");
> +	if (env_str) {
> +		val = simple_strtol(env_str, NULL, 0);
> +		if (val == 1) {
> +			puts("Deasserting all peripheral resets\n");
> +			writel(0, data->membase + 4);
> +		}
> +	}
> +
> +	return 0;
> +}
> +#endif
> +
>  static const struct udevice_id socfpga_reset_match[] = {
>  	{ .compatible = "altr,rst-mgr" },
>  	{ /* sentinel */ },
> @@ -101,4 +131,8 @@ U_BOOT_DRIVER(socfpga_reset) = {
>  	.probe = socfpga_reset_probe,
>  	.priv_auto_alloc_size = sizeof(struct socfpga_reset_data),
>  	.ops = &socfpga_reset_ops,
> +#ifndef CONFIG_SPL_BUILD
> +	.remove = socfpga_reset_remove,
> +	.flags	= DM_FLAG_OS_PREPARE,
> +#endif
>  };

Does this work if you use Falcon mode ? :)
Simon Goldschmidt Feb. 21, 2019, 10:07 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 code to take peripherals out of reset based on an environment
> > variable. This is in preparation for removing the code that does this
> from
> > SPL.
> >
> > However, some drivers even in current Linux cannot handle peripheral
> reset,
> > so until this works, we need a compatibility workaround.
> >
> > This workaround is implemented in the 'remove' callback of this reset
> > driver, which is called on OS_PREPARE: it checks if the environment
> > variable "socfpga_permodrst_ungate" - if it is set to 1, it deasserts all
> > peripheral resets, which is what the gen5 SPL did up to now.
> >
> > This is in preparation to clean up the SPL and implementing proper reset
> > handling for U-Boot.
> >
> > Signed-off-by: Simon Goldschmidt <simon.k.r.goldschmidt@gmail.com>
> > ---
> >
> > Changes in v2:
> > - moved from Kernel option "OLD_SOCFPGA_KERNEL_COMPAT" to environment
> >   variable "socfpga_permodrst_ungate"
> >
> >  drivers/reset/reset-socfpga.c | 34 ++++++++++++++++++++++++++++++++++
> >  1 file changed, 34 insertions(+)
> >
> > diff --git a/drivers/reset/reset-socfpga.c
> b/drivers/reset/reset-socfpga.c
> > index b2acfcd2ec..749f671e05 100644
> > --- a/drivers/reset/reset-socfpga.c
> > +++ b/drivers/reset/reset-socfpga.c
> > @@ -89,6 +89,36 @@ static int socfpga_reset_probe(struct udevice *dev)
> >       return 0;
> >  }
> >
> > +#ifndef CONFIG_SPL_BUILD
> > +/*
> > + * This remove function is called before starting OS to deassert
> peripheral
> > + * resets for Kernels that don't support this.
> > + *
> > + * The reset driver checks the environment variable
> "socfpga_permodrst_ungate"
> > + * when it is removed. If this variable is '1', all peripherals in
> 'permodrst'
> > + * are taken out of reset before booting into the OS.
> > + * This should be required for gen5 systems only that are running Linux
> kernels
> > + * without proper peripheral reset support for all drivers used.
> > + */
> > +static int socfpga_reset_remove(struct udevice *dev)
> > +{
> > +     struct socfpga_reset_data *data = dev_get_priv(dev);
> > +     const char *env_str;
> > +     long val;
> > +
> > +     env_str = env_get("socfpga_permodrst_ungate");
> > +     if (env_str) {
> > +             val = simple_strtol(env_str, NULL, 0);
> > +             if (val == 1) {
> > +                     puts("Deasserting all peripheral resets\n");
> > +                     writel(0, data->membase + 4);
> > +             }
> > +     }
> > +
> > +     return 0;
> > +}
> > +#endif
> > +
> >  static const struct udevice_id socfpga_reset_match[] = {
> >       { .compatible = "altr,rst-mgr" },
> >       { /* sentinel */ },
> > @@ -101,4 +131,8 @@ U_BOOT_DRIVER(socfpga_reset) = {
> >       .probe = socfpga_reset_probe,
> >       .priv_auto_alloc_size = sizeof(struct socfpga_reset_data),
> >       .ops = &socfpga_reset_ops,
> > +#ifndef CONFIG_SPL_BUILD
> > +     .remove = socfpga_reset_remove,
> > +     .flags  = DM_FLAG_OS_PREPARE,
> > +#endif
> >  };
>
> Does this work if you use Falcon mode ? :)
>

Probably not, but would anyone be able to use falcon mode in socfpga gen5
given the current SPL size? I think it didn't fit for,a last time I checked.

And if it fits in the future, we probably don't need this workaraound any
more...

I did it like that since env_get() broke compilation of SPL. But if you
insist of making this work even for SPL, I'll check again.

Regards,
Simon

>
Marek Vasut Feb. 21, 2019, 10:15 p.m. UTC | #3
On 2/21/19 11:07 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 code to take peripherals out of reset based on an
>     environment
>     > variable. This is in preparation for removing the code that does
>     this from
>     > SPL.
>     >
>     > However, some drivers even in current Linux cannot handle
>     peripheral reset,
>     > so until this works, we need a compatibility workaround.
>     >
>     > This workaround is implemented in the 'remove' callback of this reset
>     > driver, which is called on OS_PREPARE: it checks if the environment
>     > variable "socfpga_permodrst_ungate" - if it is set to 1, it
>     deasserts all
>     > peripheral resets, which is what the gen5 SPL did up to now.
>     >
>     > This is in preparation to clean up the SPL and implementing proper
>     reset
>     > handling for U-Boot.
>     >
>     > Signed-off-by: Simon Goldschmidt <simon.k.r.goldschmidt@gmail.com
>     <mailto:simon.k.r.goldschmidt@gmail.com>>
>     > ---
>     >
>     > Changes in v2:
>     > - moved from Kernel option "OLD_SOCFPGA_KERNEL_COMPAT" to environment
>     >   variable "socfpga_permodrst_ungate"
>     >
>     >  drivers/reset/reset-socfpga.c | 34 ++++++++++++++++++++++++++++++++++
>     >  1 file changed, 34 insertions(+)
>     >
>     > diff --git a/drivers/reset/reset-socfpga.c
>     b/drivers/reset/reset-socfpga.c
>     > index b2acfcd2ec..749f671e05 100644
>     > --- a/drivers/reset/reset-socfpga.c
>     > +++ b/drivers/reset/reset-socfpga.c
>     > @@ -89,6 +89,36 @@ static int socfpga_reset_probe(struct udevice *dev)
>     >       return 0;
>     >  }
>     > 
>     > +#ifndef CONFIG_SPL_BUILD
>     > +/*
>     > + * This remove function is called before starting OS to deassert
>     peripheral
>     > + * resets for Kernels that don't support this.
>     > + *
>     > + * The reset driver checks the environment variable
>     "socfpga_permodrst_ungate"
>     > + * when it is removed. If this variable is '1', all peripherals
>     in 'permodrst'
>     > + * are taken out of reset before booting into the OS.
>     > + * This should be required for gen5 systems only that are running
>     Linux kernels
>     > + * without proper peripheral reset support for all drivers used.
>     > + */
>     > +static int socfpga_reset_remove(struct udevice *dev)
>     > +{
>     > +     struct socfpga_reset_data *data = dev_get_priv(dev);
>     > +     const char *env_str;
>     > +     long val;
>     > +
>     > +     env_str = env_get("socfpga_permodrst_ungate");
>     > +     if (env_str) {
>     > +             val = simple_strtol(env_str, NULL, 0);
>     > +             if (val == 1) {
>     > +                     puts("Deasserting all peripheral resets\n");
>     > +                     writel(0, data->membase + 4);
>     > +             }
>     > +     }
>     > +
>     > +     return 0;
>     > +}
>     > +#endif
>     > +
>     >  static const struct udevice_id socfpga_reset_match[] = {
>     >       { .compatible = "altr,rst-mgr" },
>     >       { /* sentinel */ },
>     > @@ -101,4 +131,8 @@ U_BOOT_DRIVER(socfpga_reset) = {
>     >       .probe = socfpga_reset_probe,
>     >       .priv_auto_alloc_size = sizeof(struct socfpga_reset_data),
>     >       .ops = &socfpga_reset_ops,
>     > +#ifndef CONFIG_SPL_BUILD
>     > +     .remove = socfpga_reset_remove,
>     > +     .flags  = DM_FLAG_OS_PREPARE,
>     > +#endif
>     >  };
> 
>     Does this work if you use Falcon mode ? :)
> 
> 
> Probably not, but would anyone be able to use falcon mode in socfpga
> gen5 given the current SPL size? I think it didn't fit for,a last time I
> checked.

If you cut it down, why not ?

> And if it fits in the future, we probably don't need this workaraound
> any more...
> 
> I did it like that since env_get() broke compilation of SPL. But if you
> insist of making this work even for SPL, I'll check again.

SPL can also check env, so some more conditionals need to be added.
Should be a matter of some CONFIG_IS_ENABLED()
Simon Goldschmidt Feb. 22, 2019, 5:55 a.m. UTC | #4
On Thu, Feb 21, 2019 at 11:15 PM Marek Vasut <marex@denx.de> wrote:
>
> On 2/21/19 11:07 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 code to take peripherals out of reset based on an
> >     environment
> >     > variable. This is in preparation for removing the code that does
> >     this from
> >     > SPL.
> >     >
> >     > However, some drivers even in current Linux cannot handle
> >     peripheral reset,
> >     > so until this works, we need a compatibility workaround.
> >     >
> >     > This workaround is implemented in the 'remove' callback of this reset
> >     > driver, which is called on OS_PREPARE: it checks if the environment
> >     > variable "socfpga_permodrst_ungate" - if it is set to 1, it
> >     deasserts all
> >     > peripheral resets, which is what the gen5 SPL did up to now.
> >     >
> >     > This is in preparation to clean up the SPL and implementing proper
> >     reset
> >     > handling for U-Boot.
> >     >
> >     > Signed-off-by: Simon Goldschmidt <simon.k.r.goldschmidt@gmail.com
> >     <mailto:simon.k.r.goldschmidt@gmail.com>>
> >     > ---
> >     >
> >     > Changes in v2:
> >     > - moved from Kernel option "OLD_SOCFPGA_KERNEL_COMPAT" to environment
> >     >   variable "socfpga_permodrst_ungate"
> >     >
> >     >  drivers/reset/reset-socfpga.c | 34 ++++++++++++++++++++++++++++++++++
> >     >  1 file changed, 34 insertions(+)
> >     >
> >     > diff --git a/drivers/reset/reset-socfpga.c
> >     b/drivers/reset/reset-socfpga.c
> >     > index b2acfcd2ec..749f671e05 100644
> >     > --- a/drivers/reset/reset-socfpga.c
> >     > +++ b/drivers/reset/reset-socfpga.c
> >     > @@ -89,6 +89,36 @@ static int socfpga_reset_probe(struct udevice *dev)
> >     >       return 0;
> >     >  }
> >     >
> >     > +#ifndef CONFIG_SPL_BUILD
> >     > +/*
> >     > + * This remove function is called before starting OS to deassert
> >     peripheral
> >     > + * resets for Kernels that don't support this.
> >     > + *
> >     > + * The reset driver checks the environment variable
> >     "socfpga_permodrst_ungate"
> >     > + * when it is removed. If this variable is '1', all peripherals
> >     in 'permodrst'
> >     > + * are taken out of reset before booting into the OS.
> >     > + * This should be required for gen5 systems only that are running
> >     Linux kernels
> >     > + * without proper peripheral reset support for all drivers used.
> >     > + */
> >     > +static int socfpga_reset_remove(struct udevice *dev)
> >     > +{
> >     > +     struct socfpga_reset_data *data = dev_get_priv(dev);
> >     > +     const char *env_str;
> >     > +     long val;
> >     > +
> >     > +     env_str = env_get("socfpga_permodrst_ungate");
> >     > +     if (env_str) {
> >     > +             val = simple_strtol(env_str, NULL, 0);
> >     > +             if (val == 1) {
> >     > +                     puts("Deasserting all peripheral resets\n");
> >     > +                     writel(0, data->membase + 4);
> >     > +             }
> >     > +     }
> >     > +
> >     > +     return 0;
> >     > +}
> >     > +#endif
> >     > +
> >     >  static const struct udevice_id socfpga_reset_match[] = {
> >     >       { .compatible = "altr,rst-mgr" },
> >     >       { /* sentinel */ },
> >     > @@ -101,4 +131,8 @@ U_BOOT_DRIVER(socfpga_reset) = {
> >     >       .probe = socfpga_reset_probe,
> >     >       .priv_auto_alloc_size = sizeof(struct socfpga_reset_data),
> >     >       .ops = &socfpga_reset_ops,
> >     > +#ifndef CONFIG_SPL_BUILD
> >     > +     .remove = socfpga_reset_remove,
> >     > +     .flags  = DM_FLAG_OS_PREPARE,
> >     > +#endif
> >     >  };
> >
> >     Does this work if you use Falcon mode ? :)
> >
> >
> > Probably not, but would anyone be able to use falcon mode in socfpga
> > gen5 given the current SPL size? I think it didn't fit for,a last time I
> > checked.
>
> If you cut it down, why not ?
>
> > And if it fits in the future, we probably don't need this workaraound
> > any more...
> >
> > I did it like that since env_get() broke compilation of SPL. But if you
> > insist of making this work even for SPL, I'll check again.
>
> SPL can also check env, so some more conditionals need to be added.
> Should be a matter of some CONFIG_IS_ENABLED()

OK, I'll try that for V3.

Regards,
Simon
diff mbox series

Patch

diff --git a/drivers/reset/reset-socfpga.c b/drivers/reset/reset-socfpga.c
index b2acfcd2ec..749f671e05 100644
--- a/drivers/reset/reset-socfpga.c
+++ b/drivers/reset/reset-socfpga.c
@@ -89,6 +89,36 @@  static int socfpga_reset_probe(struct udevice *dev)
 	return 0;
 }
 
+#ifndef CONFIG_SPL_BUILD
+/*
+ * This remove function is called before starting OS to deassert peripheral
+ * resets for Kernels that don't support this.
+ *
+ * The reset driver checks the environment variable "socfpga_permodrst_ungate"
+ * when it is removed. If this variable is '1', all peripherals in 'permodrst'
+ * are taken out of reset before booting into the OS.
+ * This should be required for gen5 systems only that are running Linux kernels
+ * without proper peripheral reset support for all drivers used.
+ */
+static int socfpga_reset_remove(struct udevice *dev)
+{
+	struct socfpga_reset_data *data = dev_get_priv(dev);
+	const char *env_str;
+	long val;
+
+	env_str = env_get("socfpga_permodrst_ungate");
+	if (env_str) {
+		val = simple_strtol(env_str, NULL, 0);
+		if (val == 1) {
+			puts("Deasserting all peripheral resets\n");
+			writel(0, data->membase + 4);
+		}
+	}
+
+	return 0;
+}
+#endif
+
 static const struct udevice_id socfpga_reset_match[] = {
 	{ .compatible = "altr,rst-mgr" },
 	{ /* sentinel */ },
@@ -101,4 +131,8 @@  U_BOOT_DRIVER(socfpga_reset) = {
 	.probe = socfpga_reset_probe,
 	.priv_auto_alloc_size = sizeof(struct socfpga_reset_data),
 	.ops = &socfpga_reset_ops,
+#ifndef CONFIG_SPL_BUILD
+	.remove = socfpga_reset_remove,
+	.flags	= DM_FLAG_OS_PREPARE,
+#endif
 };