diff mbox series

[v3] soc: renesas: rcar-rst: Add support to set rproc boot address

Message ID 20211012121117.61864-1-julien.massot@iot.bzh (mailing list archive)
State Superseded
Delegated to: Geert Uytterhoeven
Headers show
Series [v3] soc: renesas: rcar-rst: Add support to set rproc boot address | expand

Commit Message

Julien Massot Oct. 12, 2021, 12:11 p.m. UTC
R-Car Gen3 SoC series has a realtime processor, the boot
address of this processor can be set thanks to CR7BAR register
of the reset module.

Export this function so that it's possible to set the boot
address from a remoteproc driver.

Also drop the __initdata qualifier on rcar_rst_base,
since we will use this address later than init time.

Signed-off-by: Julien Massot <julien.massot@iot.bzh>
---

Change since v2:
- Reordered rcar_rst_set_gen3_rproc_boot_addr and variable to avoid forward declaration
- Turned const struct rst_config structs back to __initconst
- Check for 256KiB boundary and not 4KiB
- Rephrase comment about boot address on Gen 3

---
 drivers/soc/renesas/rcar-rst.c       | 42 ++++++++++++++++++++++++++--
 include/linux/soc/renesas/rcar-rst.h |  2 ++
 2 files changed, 41 insertions(+), 3 deletions(-)

Comments

Geert Uytterhoeven Oct. 21, 2021, 9:10 a.m. UTC | #1
Hi Julien,

On Tue, Oct 12, 2021 at 2:12 PM Julien Massot <julien.massot@iot.bzh> wrote:
> R-Car Gen3 SoC series has a realtime processor, the boot
> address of this processor can be set thanks to CR7BAR register
> of the reset module.
>
> Export this function so that it's possible to set the boot
> address from a remoteproc driver.
>
> Also drop the __initdata qualifier on rcar_rst_base,
> since we will use this address later than init time.
>
> Signed-off-by: Julien Massot <julien.massot@iot.bzh>
> ---
>
> Change since v2:
> - Reordered rcar_rst_set_gen3_rproc_boot_addr and variable to avoid forward declaration
> - Turned const struct rst_config structs back to __initconst
> - Check for 256KiB boundary and not 4KiB
> - Rephrase comment about boot address on Gen 3

Thanks for the update!

> --- a/drivers/soc/renesas/rcar-rst.c
> +++ b/drivers/soc/renesas/rcar-rst.c

> @@ -19,9 +25,30 @@ static int rcar_rst_enable_wdt_reset(void __iomem *base)
>         return 0;
>  }
>
> +/*
> + * Most of the R-Car Gen3 SoCs have an ARM Realtime Core.
> + * Firmware boot address has to be set in CR7BAR before
> + * starting the realtime core.
> + * Boot address must be aligned on a 256k boundary.
> + */
> +static int rcar_rst_set_gen3_rproc_boot_addr(u32 boot_addr)

phys_addr_t?

> +{
> +       if (boot_addr % SZ_256K) {
> +               pr_warn("Invalid boot address for CR7 processor,"
> +                      "should be aligned on 256KiB got %x\n", boot_addr);

Please don't split printed messages, for easier searching.

> +               return -EINVAL;
> +       }
> +
> +       iowrite32(boot_addr, rcar_rst_base + CR7BAR);
> +       iowrite32(boot_addr | CR7BAREN, rcar_rst_base + CR7BAR);
> +
> +       return 0;
> +}
> +
>  struct rst_config {
>         unsigned int modemr;            /* Mode Monitoring Register Offset */
>         int (*configure)(void __iomem *base);   /* Platform specific config */
> +       int (*set_rproc_boot_addr)(u32 boot_addr);

phys_addr_t

>  };
>
>  static const struct rst_config rcar_rst_gen1 __initconst = {

> @@ -130,3 +157,12 @@ int __init rcar_rst_read_mode_pins(u32 *mode)
>         *mode = saved_mode;
>         return 0;
>  }
> +
> +int rcar_rst_set_rproc_boot_addr(u32 boot_addr)

phys_addr_t

> +{
> +       if (!rcar_rst_set_rproc_boot_addr_func)
> +               return -EIO;
> +
> +       return rcar_rst_set_rproc_boot_addr_func(boot_addr);
> +}
> +EXPORT_SYMBOL(rcar_rst_set_rproc_boot_addr);

EXPORT_SYMBOL_GPL?

Do you have a public user of this code, too?

Thanks!

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds
Julien Massot Oct. 21, 2021, 12:52 p.m. UTC | #2
Hi Geert,

>> +/*
>> + * Most of the R-Car Gen3 SoCs have an ARM Realtime Core.
>> + * Firmware boot address has to be set in CR7BAR before
>> + * starting the realtime core.
>> + * Boot address must be aligned on a 256k boundary.
>> + */
>> +static int rcar_rst_set_gen3_rproc_boot_addr(u32 boot_addr)
> 
> phys_addr_t?
Not sure, in the remoteproc subsystem the boot address is in the
remote processor address space, which can be a different mapping than the host
processor. On Gen3 both the realtime and the application cores share the same address
map. (excepted for 64 bits address)
So a physical address from the CA5x processors is the same on the CR7
processor.
My feeling is that it's better to keep u32.

> 
>> +{
>> +       if (boot_addr % SZ_256K) {
>> +               pr_warn("Invalid boot address for CR7 processor,"
>> +                      "should be aligned on 256KiB got %x\n", boot_addr);
> 
> Please don't split printed messages, for easier searching.
Sure will fix.
> 
>> +               return -EINVAL;
>> +       }
>> +
>> +       iowrite32(boot_addr, rcar_rst_base + CR7BAR);
>> +       iowrite32(boot_addr | CR7BAREN, rcar_rst_base + CR7BAR);
>> +
>> +       return 0;
>> +}
>> +
>>   struct rst_config {
>>          unsigned int modemr;            /* Mode Monitoring Register Offset */
>>          int (*configure)(void __iomem *base);   /* Platform specific config */
>> +       int (*set_rproc_boot_addr)(u32 boot_addr);
> 
> phys_addr_t
> 
>>   };
>>
>>   static const struct rst_config rcar_rst_gen1 __initconst = {
> 
>> @@ -130,3 +157,12 @@ int __init rcar_rst_read_mode_pins(u32 *mode)
>>          *mode = saved_mode;
>>          return 0;
>>   }
>> +
>> +int rcar_rst_set_rproc_boot_addr(u32 boot_addr)
> 
> phys_addr_t
> 
>> +{
>> +       if (!rcar_rst_set_rproc_boot_addr_func)
>> +               return -EIO;
>> +
>> +       return rcar_rst_set_rproc_boot_addr_func(boot_addr);
>> +}
>> +EXPORT_SYMBOL(rcar_rst_set_rproc_boot_addr);
> 
> EXPORT_SYMBOL_GPL?
Ok

> 
> Do you have a public user of this code, too?
I have one that I plan to submit to the remoteproc subsystem once
it will be possible to set the CR7 boot address.

Please have a look there
https://github.com/iotbzh/linux/blob/iot/for-upstream/rproc/drivers/remoteproc/rcar_rproc.c#L114

In this function the remoteproc subsystem already fetched a firmware and parsed the elf file.
The firmware entry point is stored in a u64 variable
https://github.com/iotbzh/linux/blob/iot/for-upstream/rproc/include/linux/remoteproc.h#L550

Then we can start the processor by deasserting the reset.


Thanks,
Julien
Geert Uytterhoeven Oct. 21, 2021, 2:30 p.m. UTC | #3
Hi Julien,

On Thu, Oct 21, 2021 at 2:52 PM Julien Massot <julien.massot@iot.bzh> wrote:
> >> +/*
> >> + * Most of the R-Car Gen3 SoCs have an ARM Realtime Core.
> >> + * Firmware boot address has to be set in CR7BAR before
> >> + * starting the realtime core.
> >> + * Boot address must be aligned on a 256k boundary.
> >> + */
> >> +static int rcar_rst_set_gen3_rproc_boot_addr(u32 boot_addr)
> >
> > phys_addr_t?
> Not sure, in the remoteproc subsystem the boot address is in the
> remote processor address space, which can be a different mapping than the host
> processor. On Gen3 both the realtime and the application cores share the same address
> map. (excepted for 64 bits address)
> So a physical address from the CA5x processors is the same on the CR7
> processor.
> My feeling is that it's better to keep u32.

> > Do you have a public user of this code, too?
> I have one that I plan to submit to the remoteproc subsystem once
> it will be possible to set the CR7 boot address.

OK.

> Please have a look there
> https://github.com/iotbzh/linux/blob/iot/for-upstream/rproc/drivers/remoteproc/rcar_rproc.c#L114
>
> In this function the remoteproc subsystem already fetched a firmware and parsed the elf file.
> The firmware entry point is stored in a u64 variable
> https://github.com/iotbzh/linux/blob/iot/for-upstream/rproc/include/linux/remoteproc.h#L550
>
> Then we can start the processor by deasserting the reset.

Given rproc defines this as u64, I think using u64 would be even better
than phys_addr_t.  I'd like to keep this as generic as possible, as
someone may want to do the reverse too (boot the CA5x from the CR7).
And of course there's also the SH-4A core on R-Car Gen2 ;-)

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds
Julien Massot Oct. 21, 2021, 2:40 p.m. UTC | #4
> Given rproc defines this as u64, I think using u64 would be even better
> than phys_addr_t.  I'd like to keep this as generic as possible, as
> someone may want to do the reverse too (boot the CA5x from the CR7).
> And of course there's also the SH-4A core on R-Car Gen2 ;-)
Ok let's go for u64, will just move the sanity check for 32bits length inside the
rcar-rst function.
Thanks for your time!
diff mbox series

Patch

diff --git a/drivers/soc/renesas/rcar-rst.c b/drivers/soc/renesas/rcar-rst.c
index 8a1e402ea799..3bd0595f1535 100644
--- a/drivers/soc/renesas/rcar-rst.c
+++ b/drivers/soc/renesas/rcar-rst.c
@@ -12,6 +12,12 @@ 
 
 #define WDTRSTCR_RESET		0xA55A0002
 #define WDTRSTCR		0x0054
+#define CR7BAR			0x0070
+#define CR7BAREN		BIT(4)
+
+static void __iomem *rcar_rst_base;
+static u32 saved_mode __initdata;
+static int (*rcar_rst_set_rproc_boot_addr_func)(u32 boot_addr);
 
 static int rcar_rst_enable_wdt_reset(void __iomem *base)
 {
@@ -19,9 +25,30 @@  static int rcar_rst_enable_wdt_reset(void __iomem *base)
 	return 0;
 }
 
+/*
+ * Most of the R-Car Gen3 SoCs have an ARM Realtime Core.
+ * Firmware boot address has to be set in CR7BAR before
+ * starting the realtime core.
+ * Boot address must be aligned on a 256k boundary.
+ */
+static int rcar_rst_set_gen3_rproc_boot_addr(u32 boot_addr)
+{
+	if (boot_addr % SZ_256K) {
+		pr_warn("Invalid boot address for CR7 processor,"
+		       "should be aligned on 256KiB got %x\n", boot_addr);
+		return -EINVAL;
+	}
+
+	iowrite32(boot_addr, rcar_rst_base + CR7BAR);
+	iowrite32(boot_addr | CR7BAREN, rcar_rst_base + CR7BAR);
+
+	return 0;
+}
+
 struct rst_config {
 	unsigned int modemr;		/* Mode Monitoring Register Offset */
 	int (*configure)(void __iomem *base);	/* Platform specific config */
+	int (*set_rproc_boot_addr)(u32 boot_addr);
 };
 
 static const struct rst_config rcar_rst_gen1 __initconst = {
@@ -35,6 +62,7 @@  static const struct rst_config rcar_rst_gen2 __initconst = {
 
 static const struct rst_config rcar_rst_gen3 __initconst = {
 	.modemr = 0x60,
+	.set_rproc_boot_addr = rcar_rst_set_gen3_rproc_boot_addr,
 };
 
 static const struct rst_config rcar_rst_r8a779a0 __initconst = {
@@ -76,9 +104,6 @@  static const struct of_device_id rcar_rst_matches[] __initconst = {
 	{ /* sentinel */ }
 };
 
-static void __iomem *rcar_rst_base __initdata;
-static u32 saved_mode __initdata;
-
 static int __init rcar_rst_init(void)
 {
 	const struct of_device_id *match;
@@ -100,6 +125,8 @@  static int __init rcar_rst_init(void)
 
 	rcar_rst_base = base;
 	cfg = match->data;
+	rcar_rst_set_rproc_boot_addr_func = cfg->set_rproc_boot_addr;
+
 	saved_mode = ioread32(base + cfg->modemr);
 	if (cfg->configure) {
 		error = cfg->configure(base);
@@ -130,3 +157,12 @@  int __init rcar_rst_read_mode_pins(u32 *mode)
 	*mode = saved_mode;
 	return 0;
 }
+
+int rcar_rst_set_rproc_boot_addr(u32 boot_addr)
+{
+	if (!rcar_rst_set_rproc_boot_addr_func)
+		return -EIO;
+
+	return rcar_rst_set_rproc_boot_addr_func(boot_addr);
+}
+EXPORT_SYMBOL(rcar_rst_set_rproc_boot_addr);
diff --git a/include/linux/soc/renesas/rcar-rst.h b/include/linux/soc/renesas/rcar-rst.h
index 7899a5b8c247..7c97c2c4bba6 100644
--- a/include/linux/soc/renesas/rcar-rst.h
+++ b/include/linux/soc/renesas/rcar-rst.h
@@ -4,8 +4,10 @@ 
 
 #ifdef CONFIG_RST_RCAR
 int rcar_rst_read_mode_pins(u32 *mode);
+int rcar_rst_set_rproc_boot_addr(u32 boot_addr);
 #else
 static inline int rcar_rst_read_mode_pins(u32 *mode) { return -ENODEV; }
+static inline int rcar_rst_set_rproc_boot_addr(u32 boot_addr) { return -ENODEV; }
 #endif
 
 #endif /* __LINUX_SOC_RENESAS_RCAR_RST_H__ */