[V2,5/6] remoteproc: imx_rproc: set Cortex-M stack/pc to TCML

Message ID 20230127092246.1470865-6-peng.fan@oss.nxp.com
State New
Headers
Series remoteproc: imx_rproc: support firmware in DDR |

Commit Message

Peng Fan (OSS) Jan. 27, 2023, 9:22 a.m. UTC
  From: Peng Fan <peng.fan@nxp.com>

The i.MX8M Cortex-M core not has ROM. It has a requirement is
the stack, pc value should be set in address 0 and 4 from the view of
itself. From Cortex-A core view, the region is at TCML start address.

The stack and pc value are the first two words stored in section
".interrupts" of the firmware, and the section is the first section in
the firmware.

When the firmware is built to run in TCML, there is no issue, because
when copying elf segments, the first two words are copied to TCML also.

However when the firmware is built ro run in DDR, the first two words
are not copied to TCML start address.

This patch is to find the ".interrupts" section, read out the first
two words and write to TCML start address at offset 0 and 4.

Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
 drivers/remoteproc/imx_rproc.c | 37 +++++++++++++++++++++++++++++++++-
 1 file changed, 36 insertions(+), 1 deletion(-)
  

Comments

Mathieu Poirier Feb. 2, 2023, 9:56 p.m. UTC | #1
On Fri, Jan 27, 2023 at 05:22:45PM +0800, Peng Fan (OSS) wrote:
> From: Peng Fan <peng.fan@nxp.com>
> 
> The i.MX8M Cortex-M core not has ROM. It has a requirement is
> the stack, pc value should be set in address 0 and 4 from the view of
> itself. From Cortex-A core view, the region is at TCML start address.
> 
> The stack and pc value are the first two words stored in section
> ".interrupts" of the firmware, and the section is the first section in
> the firmware.
> 
> When the firmware is built to run in TCML, there is no issue, because
> when copying elf segments, the first two words are copied to TCML also.
> 
> However when the firmware is built ro run in DDR, the first two words
> are not copied to TCML start address.
> 
> This patch is to find the ".interrupts" section, read out the first
> two words and write to TCML start address at offset 0 and 4.
> 
> Signed-off-by: Peng Fan <peng.fan@nxp.com>
> ---
>  drivers/remoteproc/imx_rproc.c | 37 +++++++++++++++++++++++++++++++++-
>  1 file changed, 36 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c
> index 295e0e0e869a..f5ee0c9bb09d 100644
> --- a/drivers/remoteproc/imx_rproc.c
> +++ b/drivers/remoteproc/imx_rproc.c
> @@ -7,6 +7,7 @@
>  #include <linux/arm-smccc.h>
>  #include <linux/clk.h>
>  #include <linux/err.h>
> +#include <linux/firmware.h>
>  #include <linux/firmware/imx/sci.h>
>  #include <linux/interrupt.h>
>  #include <linux/kernel.h>
> @@ -23,6 +24,7 @@
>  #include <linux/workqueue.h>
>  
>  #include "imx_rproc.h"
> +#include "remoteproc_elf_helpers.h"
>  #include "remoteproc_internal.h"
>  
>  #define IMX7D_SRC_SCR			0x0C
> @@ -634,6 +636,39 @@ static struct resource_table *imx_rproc_get_loaded_rsc_table(struct rproc *rproc
>  	return (struct resource_table __force *)priv->rsc_table;
>  }
>  
> +static u64 imx_rproc_get_boot_addr(struct rproc *rproc, const struct firmware *fw)
> +{
> +	struct imx_rproc *priv = rproc->priv;
> +	const u8 *elf_data = (void *)fw->data;
> +	u8 class = fw_elf_get_class(fw);
> +	u64 bootaddr = rproc_elf_get_boot_addr(rproc, fw);
> +	const void *shdr;
> +	void __iomem *va;
> +	u64 sh_addr, offset;
> +
> +	if (priv->dcfg->devtype == IMX_RPROC_IMX8M) {
> +		/*
> +		 * i.MX8M Cortex-M requires [stack, pc] be put in address
> +		 * [0, 4], so the da address is 0, size is 8 words.
> +		 */
> +		va = (__force void __iomem *)rproc_da_to_va(rproc, 0, 8, NULL);
> +		shdr = rproc_elf_find_shdr(rproc, fw, ".interrupts");
> +		if (!shdr || !va)
> +			return bootaddr;
> +		sh_addr = elf_shdr_get_sh_addr(class, shdr);

This isn't used - why is it still there? 

> +		offset = elf_shdr_get_sh_offset(class, shdr);
> +
> +		/*
> +		 * Write stack, pc to TCML start address. The TCML region
> +		 * is marked with ATT_IOMEM, so use writel.
> +		 */
> +		writel(*(u32 *)(elf_data + offset), va);
> +		writel(*(u32 *)(elf_data + offset + 4), va + 4);

Here you are writing 2 words at address 0x0 and 2 words at address 0x4. Why are
you saying the size is 8 words in the comment above?

> +	}
> +
> +	return bootaddr;
> +}
> +
>  static const struct rproc_ops imx_rproc_ops = {
>  	.prepare	= imx_rproc_prepare,
>  	.attach		= imx_rproc_attach,
> @@ -647,7 +682,7 @@ static const struct rproc_ops imx_rproc_ops = {
>  	.find_loaded_rsc_table = rproc_elf_find_loaded_rsc_table,
>  	.get_loaded_rsc_table = imx_rproc_get_loaded_rsc_table,
>  	.sanity_check	= rproc_elf_sanity_check,
> -	.get_boot_addr	= rproc_elf_get_boot_addr,
> +	.get_boot_addr	= imx_rproc_get_boot_addr,
>  };
>  
>  static int imx_rproc_addr_init(struct imx_rproc *priv,
> -- 
> 2.37.1
>
  
Peng Fan Feb. 3, 2023, 12:04 a.m. UTC | #2
> Subject: Re: [PATCH V2 5/6] remoteproc: imx_rproc: set Cortex-M stack/pc
> to TCML
> 
> On Fri, Jan 27, 2023 at 05:22:45PM +0800, Peng Fan (OSS) wrote:
> > From: Peng Fan <peng.fan@nxp.com>
> >
> > The i.MX8M Cortex-M core not has ROM. It has a requirement is the
> > stack, pc value should be set in address 0 and 4 from the view of
> > itself. From Cortex-A core view, the region is at TCML start address.
> >
> > The stack and pc value are the first two words stored in section
> > ".interrupts" of the firmware, and the section is the first section in
> > the firmware.
> >
> > When the firmware is built to run in TCML, there is no issue, because
> > when copying elf segments, the first two words are copied to TCML also.
> >
> > However when the firmware is built ro run in DDR, the first two words
> > are not copied to TCML start address.
> >
> > This patch is to find the ".interrupts" section, read out the first
> > two words and write to TCML start address at offset 0 and 4.
> >
> > Signed-off-by: Peng Fan <peng.fan@nxp.com>
> > ---
> >  drivers/remoteproc/imx_rproc.c | 37
> > +++++++++++++++++++++++++++++++++-
> >  1 file changed, 36 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/remoteproc/imx_rproc.c
> > b/drivers/remoteproc/imx_rproc.c index 295e0e0e869a..f5ee0c9bb09d
> > 100644
> > --- a/drivers/remoteproc/imx_rproc.c
> > +++ b/drivers/remoteproc/imx_rproc.c
> > @@ -7,6 +7,7 @@
> >  #include <linux/arm-smccc.h>
> >  #include <linux/clk.h>
> >  #include <linux/err.h>
> > +#include <linux/firmware.h>
> >  #include <linux/firmware/imx/sci.h>
> >  #include <linux/interrupt.h>
> >  #include <linux/kernel.h>
> > @@ -23,6 +24,7 @@
> >  #include <linux/workqueue.h>
> >
> >  #include "imx_rproc.h"
> > +#include "remoteproc_elf_helpers.h"
> >  #include "remoteproc_internal.h"
> >
> >  #define IMX7D_SRC_SCR			0x0C
> > @@ -634,6 +636,39 @@ static struct resource_table
> *imx_rproc_get_loaded_rsc_table(struct rproc *rproc
> >  	return (struct resource_table __force *)priv->rsc_table;  }
> >
> > +static u64 imx_rproc_get_boot_addr(struct rproc *rproc, const struct
> > +firmware *fw) {
> > +	struct imx_rproc *priv = rproc->priv;
> > +	const u8 *elf_data = (void *)fw->data;
> > +	u8 class = fw_elf_get_class(fw);
> > +	u64 bootaddr = rproc_elf_get_boot_addr(rproc, fw);
> > +	const void *shdr;
> > +	void __iomem *va;
> > +	u64 sh_addr, offset;
> > +
> > +	if (priv->dcfg->devtype == IMX_RPROC_IMX8M) {
> > +		/*
> > +		 * i.MX8M Cortex-M requires [stack, pc] be put in address
> > +		 * [0, 4], so the da address is 0, size is 8 words.
> > +		 */
> > +		va = (__force void __iomem *)rproc_da_to_va(rproc, 0, 8,
> NULL);
> > +		shdr = rproc_elf_find_shdr(rproc, fw, ".interrupts");
> > +		if (!shdr || !va)
> > +			return bootaddr;
> > +		sh_addr = elf_shdr_get_sh_addr(class, shdr);
> 
> This isn't used - why is it still there?

will drop it.

> 
> > +		offset = elf_shdr_get_sh_offset(class, shdr);
> > +
> > +		/*
> > +		 * Write stack, pc to TCML start address. The TCML region
> > +		 * is marked with ATT_IOMEM, so use writel.
> > +		 */
> > +		writel(*(u32 *)(elf_data + offset), va);
> > +		writel(*(u32 *)(elf_data + offset + 4), va + 4);
> 
> Here you are writing 2 words at address 0x0 and 2 words at address 0x4.
> Why are you saying the size is 8 words in the comment above?

Typo. I should mean 8 bytes.

Thanks,
Peng.

> 
> > +	}
> > +
> > +	return bootaddr;
> > +}
> > +
> >  static const struct rproc_ops imx_rproc_ops = {
> >  	.prepare	= imx_rproc_prepare,
> >  	.attach		= imx_rproc_attach,
> > @@ -647,7 +682,7 @@ static const struct rproc_ops imx_rproc_ops = {
> >  	.find_loaded_rsc_table = rproc_elf_find_loaded_rsc_table,
> >  	.get_loaded_rsc_table = imx_rproc_get_loaded_rsc_table,
> >  	.sanity_check	= rproc_elf_sanity_check,
> > -	.get_boot_addr	= rproc_elf_get_boot_addr,
> > +	.get_boot_addr	= imx_rproc_get_boot_addr,
> >  };
> >
> >  static int imx_rproc_addr_init(struct imx_rproc *priv,
> > --
> > 2.37.1
> >
  
Daniel Baluta Feb. 3, 2023, 12:47 p.m. UTC | #3
On Fri, Jan 27, 2023 at 11:33 AM Peng Fan (OSS) <peng.fan@oss.nxp.com> wrote:
>
> From: Peng Fan <peng.fan@nxp.com>
>
> The i.MX8M Cortex-M core not has ROM. It has a requirement is
> the stack, pc value should be set in address 0 and 4 from the view of
> itself. From Cortex-A core view, the region is at TCML start address.
>
> The stack and pc value are the first two words stored in section
> ".interrupts" of the firmware, and the section is the first section in
> the firmware.
>
> When the firmware is built to run in TCML, there is no issue, because
> when copying elf segments, the first two words are copied to TCML also.
>
> However when the firmware is built ro run in DDR, the first two words
> are not copied to TCML start address.
>
> This patch is to find the ".interrupts" section, read out the first
> two words and write to TCML start address at offset 0 and 4.
>
> Signed-off-by: Peng Fan <peng.fan@nxp.com>
> ---
>  drivers/remoteproc/imx_rproc.c | 37 +++++++++++++++++++++++++++++++++-
>  1 file changed, 36 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c
> index 295e0e0e869a..f5ee0c9bb09d 100644
> --- a/drivers/remoteproc/imx_rproc.c
> +++ b/drivers/remoteproc/imx_rproc.c
> @@ -7,6 +7,7 @@
>  #include <linux/arm-smccc.h>
>  #include <linux/clk.h>
>  #include <linux/err.h>
> +#include <linux/firmware.h>

I wonder why do you need to include this? Nothing in this patch looks like
it is using it.
  
Peng Fan Feb. 3, 2023, 12:50 p.m. UTC | #4
Hi Daniel,

> Subject: Re: [PATCH V2 5/6] remoteproc: imx_rproc: set Cortex-M stack/pc
> to TCML
> 
> On Fri, Jan 27, 2023 at 11:33 AM Peng Fan (OSS) <peng.fan@oss.nxp.com>
> wrote:
> >
> > From: Peng Fan <peng.fan@nxp.com>
> >
> > The i.MX8M Cortex-M core not has ROM. It has a requirement is the
> > stack, pc value should be set in address 0 and 4 from the view of
> > itself. From Cortex-A core view, the region is at TCML start address.
> >
> > The stack and pc value are the first two words stored in section
> > ".interrupts" of the firmware, and the section is the first section in
> > the firmware.
> >
> > When the firmware is built to run in TCML, there is no issue, because
> > when copying elf segments, the first two words are copied to TCML also.
> >
> > However when the firmware is built ro run in DDR, the first two words
> > are not copied to TCML start address.
> >
> > This patch is to find the ".interrupts" section, read out the first
> > two words and write to TCML start address at offset 0 and 4.
> >
> > Signed-off-by: Peng Fan <peng.fan@nxp.com>
> > ---
> >  drivers/remoteproc/imx_rproc.c | 37
> > +++++++++++++++++++++++++++++++++-
> >  1 file changed, 36 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/remoteproc/imx_rproc.c
> > b/drivers/remoteproc/imx_rproc.c index 295e0e0e869a..f5ee0c9bb09d
> > 100644
> > --- a/drivers/remoteproc/imx_rproc.c
> > +++ b/drivers/remoteproc/imx_rproc.c
> > @@ -7,6 +7,7 @@
> >  #include <linux/arm-smccc.h>
> >  #include <linux/clk.h>
> >  #include <linux/err.h>
> > +#include <linux/firmware.h>
> 
> I wonder why do you need to include this? Nothing in this patch looks like it
> is using it.

It is the 2nd parameter of function imx_rproc_get_boot_addr use 
'const struct firmware *'

Thanks,
Peng.
  
Mathieu Poirier Feb. 13, 2023, 6:04 p.m. UTC | #5
On Fri, Feb 03, 2023 at 12:04:27AM +0000, Peng Fan wrote:
> > Subject: Re: [PATCH V2 5/6] remoteproc: imx_rproc: set Cortex-M stack/pc
> > to TCML
> > 
> > On Fri, Jan 27, 2023 at 05:22:45PM +0800, Peng Fan (OSS) wrote:
> > > From: Peng Fan <peng.fan@nxp.com>
> > >
> > > The i.MX8M Cortex-M core not has ROM. It has a requirement is the
> > > stack, pc value should be set in address 0 and 4 from the view of
> > > itself. From Cortex-A core view, the region is at TCML start address.
> > >
> > > The stack and pc value are the first two words stored in section
> > > ".interrupts" of the firmware, and the section is the first section in
> > > the firmware.
> > >
> > > When the firmware is built to run in TCML, there is no issue, because
> > > when copying elf segments, the first two words are copied to TCML also.
> > >
> > > However when the firmware is built ro run in DDR, the first two words
> > > are not copied to TCML start address.
> > >
> > > This patch is to find the ".interrupts" section, read out the first
> > > two words and write to TCML start address at offset 0 and 4.
> > >
> > > Signed-off-by: Peng Fan <peng.fan@nxp.com>
> > > ---
> > >  drivers/remoteproc/imx_rproc.c | 37
> > > +++++++++++++++++++++++++++++++++-
> > >  1 file changed, 36 insertions(+), 1 deletion(-)
> > >
> > > diff --git a/drivers/remoteproc/imx_rproc.c
> > > b/drivers/remoteproc/imx_rproc.c index 295e0e0e869a..f5ee0c9bb09d
> > > 100644
> > > --- a/drivers/remoteproc/imx_rproc.c
> > > +++ b/drivers/remoteproc/imx_rproc.c
> > > @@ -7,6 +7,7 @@
> > >  #include <linux/arm-smccc.h>
> > >  #include <linux/clk.h>
> > >  #include <linux/err.h>
> > > +#include <linux/firmware.h>
> > >  #include <linux/firmware/imx/sci.h>
> > >  #include <linux/interrupt.h>
> > >  #include <linux/kernel.h>
> > > @@ -23,6 +24,7 @@
> > >  #include <linux/workqueue.h>
> > >
> > >  #include "imx_rproc.h"
> > > +#include "remoteproc_elf_helpers.h"
> > >  #include "remoteproc_internal.h"
> > >
> > >  #define IMX7D_SRC_SCR			0x0C
> > > @@ -634,6 +636,39 @@ static struct resource_table
> > *imx_rproc_get_loaded_rsc_table(struct rproc *rproc
> > >  	return (struct resource_table __force *)priv->rsc_table;  }
> > >
> > > +static u64 imx_rproc_get_boot_addr(struct rproc *rproc, const struct
> > > +firmware *fw) {
> > > +	struct imx_rproc *priv = rproc->priv;
> > > +	const u8 *elf_data = (void *)fw->data;
> > > +	u8 class = fw_elf_get_class(fw);
> > > +	u64 bootaddr = rproc_elf_get_boot_addr(rproc, fw);
> > > +	const void *shdr;
> > > +	void __iomem *va;
> > > +	u64 sh_addr, offset;
> > > +
> > > +	if (priv->dcfg->devtype == IMX_RPROC_IMX8M) {
> > > +		/*
> > > +		 * i.MX8M Cortex-M requires [stack, pc] be put in address
> > > +		 * [0, 4], so the da address is 0, size is 8 words.
> > > +		 */
> > > +		va = (__force void __iomem *)rproc_da_to_va(rproc, 0, 8,
> > NULL);
> > > +		shdr = rproc_elf_find_shdr(rproc, fw, ".interrupts");
> > > +		if (!shdr || !va)
> > > +			return bootaddr;
> > > +		sh_addr = elf_shdr_get_sh_addr(class, shdr);
> > 
> > This isn't used - why is it still there?
> 
> will drop it.
> 
> > 
> > > +		offset = elf_shdr_get_sh_offset(class, shdr);
> > > +
> > > +		/*
> > > +		 * Write stack, pc to TCML start address. The TCML region
> > > +		 * is marked with ATT_IOMEM, so use writel.
> > > +		 */
> > > +		writel(*(u32 *)(elf_data + offset), va);
> > > +		writel(*(u32 *)(elf_data + offset + 4), va + 4);
> > 
> > Here you are writing 2 words at address 0x0 and 2 words at address 0x4.
> > Why are you saying the size is 8 words in the comment above?
> 
> Typo. I should mean 8 bytes.
>

How can I trust the code in this patchset when the "typo" is so obvious and
found in the comment above and 4 times in the changelog? 

> Thanks,
> Peng.
> 
> > 
> > > +	}
> > > +
> > > +	return bootaddr;
> > > +}
> > > +
> > >  static const struct rproc_ops imx_rproc_ops = {
> > >  	.prepare	= imx_rproc_prepare,
> > >  	.attach		= imx_rproc_attach,
> > > @@ -647,7 +682,7 @@ static const struct rproc_ops imx_rproc_ops = {
> > >  	.find_loaded_rsc_table = rproc_elf_find_loaded_rsc_table,
> > >  	.get_loaded_rsc_table = imx_rproc_get_loaded_rsc_table,
> > >  	.sanity_check	= rproc_elf_sanity_check,
> > > -	.get_boot_addr	= rproc_elf_get_boot_addr,
> > > +	.get_boot_addr	= imx_rproc_get_boot_addr,
> > >  };
> > >
> > >  static int imx_rproc_addr_init(struct imx_rproc *priv,
> > > --
> > > 2.37.1
> > >
  

Patch

diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c
index 295e0e0e869a..f5ee0c9bb09d 100644
--- a/drivers/remoteproc/imx_rproc.c
+++ b/drivers/remoteproc/imx_rproc.c
@@ -7,6 +7,7 @@ 
 #include <linux/arm-smccc.h>
 #include <linux/clk.h>
 #include <linux/err.h>
+#include <linux/firmware.h>
 #include <linux/firmware/imx/sci.h>
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
@@ -23,6 +24,7 @@ 
 #include <linux/workqueue.h>
 
 #include "imx_rproc.h"
+#include "remoteproc_elf_helpers.h"
 #include "remoteproc_internal.h"
 
 #define IMX7D_SRC_SCR			0x0C
@@ -634,6 +636,39 @@  static struct resource_table *imx_rproc_get_loaded_rsc_table(struct rproc *rproc
 	return (struct resource_table __force *)priv->rsc_table;
 }
 
+static u64 imx_rproc_get_boot_addr(struct rproc *rproc, const struct firmware *fw)
+{
+	struct imx_rproc *priv = rproc->priv;
+	const u8 *elf_data = (void *)fw->data;
+	u8 class = fw_elf_get_class(fw);
+	u64 bootaddr = rproc_elf_get_boot_addr(rproc, fw);
+	const void *shdr;
+	void __iomem *va;
+	u64 sh_addr, offset;
+
+	if (priv->dcfg->devtype == IMX_RPROC_IMX8M) {
+		/*
+		 * i.MX8M Cortex-M requires [stack, pc] be put in address
+		 * [0, 4], so the da address is 0, size is 8 words.
+		 */
+		va = (__force void __iomem *)rproc_da_to_va(rproc, 0, 8, NULL);
+		shdr = rproc_elf_find_shdr(rproc, fw, ".interrupts");
+		if (!shdr || !va)
+			return bootaddr;
+		sh_addr = elf_shdr_get_sh_addr(class, shdr);
+		offset = elf_shdr_get_sh_offset(class, shdr);
+
+		/*
+		 * Write stack, pc to TCML start address. The TCML region
+		 * is marked with ATT_IOMEM, so use writel.
+		 */
+		writel(*(u32 *)(elf_data + offset), va);
+		writel(*(u32 *)(elf_data + offset + 4), va + 4);
+	}
+
+	return bootaddr;
+}
+
 static const struct rproc_ops imx_rproc_ops = {
 	.prepare	= imx_rproc_prepare,
 	.attach		= imx_rproc_attach,
@@ -647,7 +682,7 @@  static const struct rproc_ops imx_rproc_ops = {
 	.find_loaded_rsc_table = rproc_elf_find_loaded_rsc_table,
 	.get_loaded_rsc_table = imx_rproc_get_loaded_rsc_table,
 	.sanity_check	= rproc_elf_sanity_check,
-	.get_boot_addr	= rproc_elf_get_boot_addr,
+	.get_boot_addr	= imx_rproc_get_boot_addr,
 };
 
 static int imx_rproc_addr_init(struct imx_rproc *priv,