add kick method that does nothing, to avoid errors in rproc_virtio_notify.
Signed-off-by: Nikita Shubin <[email protected]>
---
drivers/remoteproc/imx_rproc.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c
index 3e72b6f38d4b..796b6b86550a 100644
--- a/drivers/remoteproc/imx_rproc.c
+++ b/drivers/remoteproc/imx_rproc.c
@@ -240,9 +240,15 @@ static void *imx_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
return va;
}
+static void imx_rproc_kick(struct rproc *rproc, int vqid)
+{
+
+}
+
static const struct rproc_ops imx_rproc_ops = {
.start = imx_rproc_start,
.stop = imx_rproc_stop,
+ .kick = imx_rproc_kick,
.da_to_va = imx_rproc_da_to_va,
};
--
2.24.1
In case elf file interrupt vector is not supposed to be at OCRAM_S,
it is needed to write elf entry point to OCRAM_S + 0x4, to boot M4
firmware.
Otherwise firmware located anywhere besides OCRAM_S won't boot.
The firmware must set stack poiner as first instruction:
Reset_Handler:
ldr sp, = __stack /* set stack pointer */
Signed-off-by: Nikita Shubin <[email protected]>
---
drivers/remoteproc/imx_rproc.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c
index 796b6b86550a..d02007f05ebd 100644
--- a/drivers/remoteproc/imx_rproc.c
+++ b/drivers/remoteproc/imx_rproc.c
@@ -45,6 +45,8 @@
#define IMX7D_RPROC_MEM_MAX 8
+#define IMX_BOOT_PC 0x4
+
/**
* struct imx_rproc_mem - slim internal memory structure
* @cpu_addr: MPU virtual address of the memory region
@@ -85,6 +87,7 @@ struct imx_rproc {
const struct imx_rproc_dcfg *dcfg;
struct imx_rproc_mem mem[IMX7D_RPROC_MEM_MAX];
struct clk *clk;
+ void __iomem *bootreg;
};
static const struct imx_rproc_att imx_rproc_att_imx7d[] = {
@@ -162,11 +165,16 @@ static int imx_rproc_start(struct rproc *rproc)
struct device *dev = priv->dev;
int ret;
+ /* write entry point to program counter */
+ writel(rproc->bootaddr, priv->bootreg);
+
ret = regmap_update_bits(priv->regmap, dcfg->src_reg,
dcfg->src_mask, dcfg->src_start);
if (ret)
dev_err(dev, "Failed to enable M4!\n");
+ dev_info(&rproc->dev, "Started from 0x%x\n", rproc->bootaddr);
+
return ret;
}
@@ -182,6 +190,9 @@ static int imx_rproc_stop(struct rproc *rproc)
if (ret)
dev_err(dev, "Failed to stop M4!\n");
+ /* clear entry points */
+ writel(0, priv->bootreg);
+
return ret;
}
@@ -366,6 +377,8 @@ static int imx_rproc_probe(struct platform_device *pdev)
goto err_put_rproc;
}
+ priv->bootreg = imx_rproc_da_to_va(rproc, IMX_BOOT_PC, sizeof(u32));
+
/*
* clk for M4 block including memory. Should be
* enabled before .start for FW transfer.
--
2.24.1
On Wed, 4 Mar 2020 at 07:25, Nikita Shubin <[email protected]> wrote:
>
> add kick method that does nothing, to avoid errors in rproc_virtio_notify.
>
> Signed-off-by: Nikita Shubin <[email protected]>
> ---
> drivers/remoteproc/imx_rproc.c | 6 ++++++
> 1 file changed, 6 insertions(+)
>
> diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c
> index 3e72b6f38d4b..796b6b86550a 100644
> --- a/drivers/remoteproc/imx_rproc.c
> +++ b/drivers/remoteproc/imx_rproc.c
> @@ -240,9 +240,15 @@ static void *imx_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
> return va;
> }
>
> +static void imx_rproc_kick(struct rproc *rproc, int vqid)
> +{
> +
> +}
> +
If rproc::kick() is empty, how does the MCU know there is packets to
fetch in the virtio queues?
> static const struct rproc_ops imx_rproc_ops = {
> .start = imx_rproc_start,
> .stop = imx_rproc_stop,
> + .kick = imx_rproc_kick,
> .da_to_va = imx_rproc_da_to_va,
> };
>
> --
> 2.24.1
>
05.03.2020, 19:17, "Mathieu Poirier" <[email protected]>:
> On Wed, 4 Mar 2020 at 07:25, Nikita Shubin <[email protected]> wrote:
>> add kick method that does nothing, to avoid errors in rproc_virtio_notify.
>>
>> Signed-off-by: Nikita Shubin <[email protected]>
>> ---
>> drivers/remoteproc/imx_rproc.c | 6 ++++++
>> 1 file changed, 6 insertions(+)
>>
>> diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c
>> index 3e72b6f38d4b..796b6b86550a 100644
>> --- a/drivers/remoteproc/imx_rproc.c
>> +++ b/drivers/remoteproc/imx_rproc.c
>> @@ -240,9 +240,15 @@ static void *imx_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
>> return va;
>> }
>>
>> +static void imx_rproc_kick(struct rproc *rproc, int vqid)
>> +{
>> +
>> +}
>> +
>
> If rproc::kick() is empty, how does the MCU know there is packets to
> fetch in the virtio queues?
Well, of course it doesn't i understand this perfectly - just following documentation citing:
| Every remoteproc implementation should at least provide the ->start and ->stop
| handlers. If rpmsg/virtio functionality is also desired, then the ->kick handler
| should be provided as well.
But i as i mentioned in "remoteproc: Fix NULL pointer dereference in rproc_virtio_notify" kick method will be called if
"resource_table exists in firmware and has "Virtio device entry" defined" anyway, the imx_rproc is not in control of what
exactly it is booting, so such situation can occur.
>
>> static const struct rproc_ops imx_rproc_ops = {
>> .start = imx_rproc_start,
>> .stop = imx_rproc_stop,
>> + .kick = imx_rproc_kick,
>> .da_to_va = imx_rproc_da_to_va,
>> };
>>
>> --
>> 2.24.1
On Thu, 5 Mar 2020 at 10:29, <[email protected]> wrote:
>
>
>
> 05.03.2020, 19:17, "Mathieu Poirier" <[email protected]>:
> > On Wed, 4 Mar 2020 at 07:25, Nikita Shubin <[email protected]> wrote:
> >> add kick method that does nothing, to avoid errors in rproc_virtio_notify.
> >>
> >> Signed-off-by: Nikita Shubin <[email protected]>
> >> ---
> >> drivers/remoteproc/imx_rproc.c | 6 ++++++
> >> 1 file changed, 6 insertions(+)
> >>
> >> diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c
> >> index 3e72b6f38d4b..796b6b86550a 100644
> >> --- a/drivers/remoteproc/imx_rproc.c
> >> +++ b/drivers/remoteproc/imx_rproc.c
> >> @@ -240,9 +240,15 @@ static void *imx_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
> >> return va;
> >> }
> >>
> >> +static void imx_rproc_kick(struct rproc *rproc, int vqid)
> >> +{
> >> +
> >> +}
> >> +
> >
> > If rproc::kick() is empty, how does the MCU know there is packets to
> > fetch in the virtio queues?
>
> Well, of course it doesn't i understand this perfectly - just following documentation citing:
>
> | Every remoteproc implementation should at least provide the ->start and ->stop
> | handlers. If rpmsg/virtio functionality is also desired, then the ->kick handler
> | should be provided as well.
>
> But i as i mentioned in "remoteproc: Fix NULL pointer dereference in rproc_virtio_notify" kick method will be called if
> "resource_table exists in firmware and has "Virtio device entry" defined" anyway, the imx_rproc is not in control of what
> exactly it is booting, so such situation can occur.
If I understand correctly, the MCU can boot images that have a virtio
device in its resource table and still do useful work even if the
virtio device/rpmsg bus can't be setup - is this correct?
Thanks,
Mathieu
>
> >
> >> static const struct rproc_ops imx_rproc_ops = {
> >> .start = imx_rproc_start,
> >> .stop = imx_rproc_stop,
> >> + .kick = imx_rproc_kick,
> >> .da_to_va = imx_rproc_da_to_va,
> >> };
> >>
> >> --
> >> 2.24.1
05.03.2020, 20:54, "Mathieu Poirier" <[email protected]>:
> On Thu, 5 Mar 2020 at 10:29, <[email protected]> wrote:
>> 05.03.2020, 19:17, "Mathieu Poirier" <[email protected]>:
>> > On Wed, 4 Mar 2020 at 07:25, Nikita Shubin <[email protected]> wrote:
>> >> add kick method that does nothing, to avoid errors in rproc_virtio_notify.
>> >>
>> >> Signed-off-by: Nikita Shubin <[email protected]>
>> >> ---
>> >> drivers/remoteproc/imx_rproc.c | 6 ++++++
>> >> 1 file changed, 6 insertions(+)
>> >>
>> >> diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c
>> >> index 3e72b6f38d4b..796b6b86550a 100644
>> >> --- a/drivers/remoteproc/imx_rproc.c
>> >> +++ b/drivers/remoteproc/imx_rproc.c
>> >> @@ -240,9 +240,15 @@ static void *imx_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
>> >> return va;
>> >> }
>> >>
>> >> +static void imx_rproc_kick(struct rproc *rproc, int vqid)
>> >> +{
>> >> +
>> >> +}
>> >> +
>> >
>> > If rproc::kick() is empty, how does the MCU know there is packets to
>> > fetch in the virtio queues?
>>
>> Well, of course it doesn't i understand this perfectly - just following documentation citing:
>>
>> | Every remoteproc implementation should at least provide the ->start and ->stop
>> | handlers. If rpmsg/virtio functionality is also desired, then the ->kick handler
>> | should be provided as well.
>>
>> But i as i mentioned in "remoteproc: Fix NULL pointer dereference in rproc_virtio_notify" kick method will be called if
>> "resource_table exists in firmware and has "Virtio device entry" defined" anyway, the imx_rproc is not in control of what
>> exactly it is booting, so such situation can occur.
>
> If I understand correctly, the MCU can boot images that have a virtio
> device in its resource table and still do useful work even if the
> virtio device/rpmsg bus can't be setup - is this correct?
Yes, this assumption is correct.
Despite this situation is not i desire at all - such thing can happen.
I am currently using co-proc as a realtime part of UGV control,
so it must immediately stop the engines, if not provided with navigational information.
The imx7d MCU have access to the most periphery that have the main processor.
Of course the kick method should do real work, but i decided to submit step by step if i am allowed to do so.
>
> Thanks,
> Mathieu
>
>> >
>> >> static const struct rproc_ops imx_rproc_ops = {
>> >> .start = imx_rproc_start,
>> >> .stop = imx_rproc_stop,
>> >> + .kick = imx_rproc_kick,
>> >> .da_to_va = imx_rproc_da_to_va,
>> >> };
>> >>
>> >> --
>> >> 2.24.1
On Thu, 5 Mar 2020 at 11:07, <[email protected]> wrote:
>
>
>
> 05.03.2020, 20:54, "Mathieu Poirier" <[email protected]>:
> > On Thu, 5 Mar 2020 at 10:29, <[email protected]> wrote:
> >> 05.03.2020, 19:17, "Mathieu Poirier" <[email protected]>:
> >> > On Wed, 4 Mar 2020 at 07:25, Nikita Shubin <[email protected]> wrote:
> >> >> add kick method that does nothing, to avoid errors in rproc_virtio_notify.
> >> >>
> >> >> Signed-off-by: Nikita Shubin <[email protected]>
> >> >> ---
> >> >> drivers/remoteproc/imx_rproc.c | 6 ++++++
> >> >> 1 file changed, 6 insertions(+)
> >> >>
> >> >> diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c
> >> >> index 3e72b6f38d4b..796b6b86550a 100644
> >> >> --- a/drivers/remoteproc/imx_rproc.c
> >> >> +++ b/drivers/remoteproc/imx_rproc.c
> >> >> @@ -240,9 +240,15 @@ static void *imx_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
> >> >> return va;
> >> >> }
> >> >>
> >> >> +static void imx_rproc_kick(struct rproc *rproc, int vqid)
> >> >> +{
> >> >> +
> >> >> +}
> >> >> +
> >> >
> >> > If rproc::kick() is empty, how does the MCU know there is packets to
> >> > fetch in the virtio queues?
> >>
> >> Well, of course it doesn't i understand this perfectly - just following documentation citing:
> >>
> >> | Every remoteproc implementation should at least provide the ->start and ->stop
> >> | handlers. If rpmsg/virtio functionality is also desired, then the ->kick handler
> >> | should be provided as well.
> >>
> >> But i as i mentioned in "remoteproc: Fix NULL pointer dereference in rproc_virtio_notify" kick method will be called if
> >> "resource_table exists in firmware and has "Virtio device entry" defined" anyway, the imx_rproc is not in control of what
> >> exactly it is booting, so such situation can occur.
> >
> > If I understand correctly, the MCU can boot images that have a virtio
> > device in its resource table and still do useful work even if the
> > virtio device/rpmsg bus can't be setup - is this correct?
>
> Yes, this assumption is correct.
>
> Despite this situation is not i desire at all - such thing can happen.
> I am currently using co-proc as a realtime part of UGV control,
> so it must immediately stop the engines, if not provided with navigational information.
>
> The imx7d MCU have access to the most periphery that have the main processor.
>
> Of course the kick method should do real work, but i decided to submit step by step if i am allowed to do so.
Ok, the situation is clearer now and I have put your patches back in
my queue. I am seriously back-logged at this time so it will take a
little while before I get to them.
>
> >
> > Thanks,
> > Mathieu
> >
> >> >
> >> >> static const struct rproc_ops imx_rproc_ops = {
> >> >> .start = imx_rproc_start,
> >> >> .stop = imx_rproc_stop,
> >> >> + .kick = imx_rproc_kick,
> >> >> .da_to_va = imx_rproc_da_to_va,
> >> >> };
> >> >>
> >> >> --
> >> >> 2.24.1
That's totally okay - thank you for review.
05.03.2020, 21:36, "Mathieu Poirier" <[email protected]>:
> On Thu, 5 Mar 2020 at 11:07, <[email protected]> wrote:
>> 05.03.2020, 20:54, "Mathieu Poirier" <[email protected]>:
>> > On Thu, 5 Mar 2020 at 10:29, <[email protected]> wrote:
>> >> 05.03.2020, 19:17, "Mathieu Poirier" <[email protected]>:
>> >> > On Wed, 4 Mar 2020 at 07:25, Nikita Shubin <[email protected]> wrote:
>> >> >> add kick method that does nothing, to avoid errors in rproc_virtio_notify.
>> >> >>
>> >> >> Signed-off-by: Nikita Shubin <[email protected]>
>> >> >> ---
>> >> >> drivers/remoteproc/imx_rproc.c | 6 ++++++
>> >> >> 1 file changed, 6 insertions(+)
>> >> >>
>> >> >> diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c
>> >> >> index 3e72b6f38d4b..796b6b86550a 100644
>> >> >> --- a/drivers/remoteproc/imx_rproc.c
>> >> >> +++ b/drivers/remoteproc/imx_rproc.c
>> >> >> @@ -240,9 +240,15 @@ static void *imx_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
>> >> >> return va;
>> >> >> }
>> >> >>
>> >> >> +static void imx_rproc_kick(struct rproc *rproc, int vqid)
>> >> >> +{
>> >> >> +
>> >> >> +}
>> >> >> +
>> >> >
>> >> > If rproc::kick() is empty, how does the MCU know there is packets to
>> >> > fetch in the virtio queues?
>> >>
>> >> Well, of course it doesn't i understand this perfectly - just following documentation citing:
>> >>
>> >> | Every remoteproc implementation should at least provide the ->start and ->stop
>> >> | handlers. If rpmsg/virtio functionality is also desired, then the ->kick handler
>> >> | should be provided as well.
>> >>
>> >> But i as i mentioned in "remoteproc: Fix NULL pointer dereference in rproc_virtio_notify" kick method will be called if
>> >> "resource_table exists in firmware and has "Virtio device entry" defined" anyway, the imx_rproc is not in control of what
>> >> exactly it is booting, so such situation can occur.
>> >
>> > If I understand correctly, the MCU can boot images that have a virtio
>> > device in its resource table and still do useful work even if the
>> > virtio device/rpmsg bus can't be setup - is this correct?
>>
>> Yes, this assumption is correct.
>>
>> Despite this situation is not i desire at all - such thing can happen.
>> I am currently using co-proc as a realtime part of UGV control,
>> so it must immediately stop the engines, if not provided with navigational information.
>>
>> The imx7d MCU have access to the most periphery that have the main processor.
>>
>> Of course the kick method should do real work, but i decided to submit step by step if i am allowed to do so.
>
> Ok, the situation is clearer now and I have put your patches back in
> my queue. I am seriously back-logged at this time so it will take a
> little while before I get to them.
>
>> >
>> > Thanks,
>> > Mathieu
>> >
>> >> >
>> >> >> static const struct rproc_ops imx_rproc_ops = {
>> >> >> .start = imx_rproc_start,
>> >> >> .stop = imx_rproc_stop,
>> >> >> + .kick = imx_rproc_kick,
>> >> >> .da_to_va = imx_rproc_da_to_va,
>> >> >> };
>> >> >>
>> >> >> --
>> >> >> 2.24.1
This patch set introduces virtio support for imx7d-m4 communication:
- support booting loaded vim imx-rproc firmware
- implement .kick method support using mailbox in imx-processor
- parse vdev0vring0, vdev0vring1, vdev0buffer memory regions required
for virtio_rpmsg_bus initialization
Regarding imx7d-m4 boot proccess
Citing ARM documentation:
At Reset, Cortex-M3 and Cortex-M4 processors always boot from a vector table at address zero.
"With uninitialized memory at address zero (for example, unprogrammed Flash or uninitialized RAM),
the processor will read a spurious initial Main Stack Pointer value from address zero and a spurious
code entry point (Reset vector) from address 0x4, possibly containing an illegal instruction
set state specifier (ESPR.T bit) in bit[0]."
So to successfully boot m4 coproc we need to write Stack Pointer and Program counter, i see no
obvious to get Stack Pointer value, so two ways exist ethier form a special elf section:
"
.loader :
{
LONG(__StackTop);
LONG(Reset_Handler + 1);
} > m_start
"
and put it at 0x0 address:
"
m_start (RX) : ORIGIN = 0x00000000, LENGTH = 0x00008000
"
Or (the way i've chosen) only put Entry Point at 0x04 and set stack as first instruction:
"
Reset_Handler:
ldr sp, =__stack /* set stack pointer */
"
Regarding mailboxes and memory regions :
This code is heavily derived from stm32-rproc (i.e. copy pasted) and this fact needs to
reflected in commits, please tell me how to emphasize this fact.
Attaching succesful trace booting m4 (with Add rpmsg tty driver applied) :
[ 143.240616] remoteproc remoteproc0: powering up imx-rproc
[ 143.251768] remoteproc remoteproc0: Booting fw image huginn.elf, size 466876
[ 143.251786] imx-rproc imx7d-cm4: iommu not present
[ 143.251825] remoteproc remoteproc0: rsc: type 3
[ 143.251837] remoteproc remoteproc0: vdev rsc: id 7, dfeatures 0x1, cfg len 0, 2 vrings
[ 143.251924] remoteproc remoteproc0: vdev rsc: vring0: da 0xffffffff, qsz 16, align 16
[ 143.251935] remoteproc remoteproc0: vdev rsc: vring1: da 0xffffffff, qsz 16, align 16
[ 143.251955] imx-rproc imx7d-cm4: map memory: 0x00900000+20000
[ 143.251987] imx-rproc imx7d-cm4: map memory: 0x00920000+2000
[ 143.252003] imx-rproc imx7d-cm4: map memory: 0x00922000+2000
[ 143.252020] remoteproc remoteproc0: phdr: type 1 da 0x20200000 memsz 0x240 filesz 0x240
[ 143.252032] remoteproc remoteproc0: da = 0x20200000 len = 0x240 va = 0x(ptrval)
[ 143.252043] remoteproc remoteproc0: phdr: type 1 da 0x20200240 memsz 0x5b38 filesz 0x5b38
[ 143.252053] remoteproc remoteproc0: da = 0x20200240 len = 0x5b38 va = 0x(ptrval)
[ 143.252105] remoteproc remoteproc0: phdr: type 1 da 0x20205d78 memsz 0x4b58 filesz 0x758
[ 143.252115] remoteproc remoteproc0: da = 0x20205d78 len = 0x4b58 va = 0x(ptrval)
[ 143.252159] remoteproc remoteproc0: da = 0x200006cc len = 0x8c va = 0x(ptrval)
[ 143.252176] remoteproc remoteproc0: Started from 0x202002f5
[ 143.252211] imx7d-cm4#vdev0buffer: assigned reserved memory node vdev0buffer@00924000
[ 143.252232] virtio virtio0: reset !
[ 143.252241] virtio virtio0: status: 1
[ 143.260567] virtio_rpmsg_bus virtio0: status: 3
[ 143.260598] remoteproc remoteproc0: vring0: va c083c000 qsz 16 notifyid 0
[ 143.260614] remoteproc remoteproc0: vring1: va c0872000 qsz 16 notifyid 1
[ 143.260651] virtio_rpmsg_bus virtio0: buffers: va c0894000, dma 0x00924000
[ 143.260666] Added buffer head 0 to (ptrval)
[ 143.260674] Added buffer head 1 to (ptrval)
[ 143.260680] Added buffer head 2 to (ptrval)
[ 143.260686] Added buffer head 3 to (ptrval)
[ 143.260692] Added buffer head 4 to (ptrval)
[ 143.260697] Added buffer head 5 to (ptrval)
[ 143.260703] Added buffer head 6 to (ptrval)
[ 143.260709] Added buffer head 7 to (ptrval)
[ 143.260715] Added buffer head 8 to (ptrval)
[ 143.260721] Added buffer head 9 to (ptrval)
[ 143.260727] Added buffer head 10 to (ptrval)
[ 143.260733] Added buffer head 11 to (ptrval)
[ 143.260738] Added buffer head 12 to (ptrval)
[ 143.260744] Added buffer head 13 to (ptrval)
[ 143.260750] Added buffer head 14 to (ptrval)
[ 143.260756] Added buffer head 15 to (ptrval)
[ 143.260771] virtio_rpmsg_bus virtio0: status: 7
[ 143.260779] remoteproc remoteproc0: kicking vq index: 0
[ 143.260788] remoteproc remoteproc0: sending message : vqid = 0
[ 143.260802] imx_mu 30aa0000.mailbox: Send data on wrong channel type: 1
[ 143.260810] virtio_rpmsg_bus virtio0: rpmsg host is online
[ 143.261680] imx7d-cm4#vdev0buffer: registered virtio0 (type 7)
[ 143.261694] remoteproc remoteproc0: remote processor imx-rproc is now up
[ 143.354880] remoteproc remoteproc0: vq index 0 is interrupted
[ 143.354895] virtqueue callback for (ptrval) ((ptrval))
[ 143.354912] virtio_rpmsg_bus virtio0: From: 0x0, To: 0x35, Len: 40, Flags: 0, Reserved: 0
[ 143.354924] rpmsg_virtio RX: 00 00 00 00 35 00 00 00 00 00 00 00 28 00 00 00 ....5.......(...
[ 143.354932] rpmsg_virtio RX: 72 70 6d 73 67 2d 74 74 79 2d 72 61 77 00 00 00 rpmsg-tty-raw...
[ 143.354939] rpmsg_virtio RX: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
[ 143.354945] rpmsg_virtio RX: 00 00 00 00 00 00 00 00 ........
[ 143.354956] NS announcement: 72 70 6d 73 67 2d 74 74 79 2d 72 61 77 00 00 00 rpmsg-tty-raw...
[ 143.354963] NS announcement: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
[ 143.354969] NS announcement: 00 00 00 00 00 00 00 00 ........
[ 143.354980] virtio_rpmsg_bus virtio0: creating channel rpmsg-tty-raw addr 0x0
[ 143.356584] rpmsg_tty virtio0.rpmsg-tty-raw.-1.0: new channel: 0x400 -> 0x0 : ttyRPMSG0
[ 143.356651] Added buffer head 0 to (ptrval)
[ 143.356658] No more buffers in queue
[ 143.356667] virtio_rpmsg_bus virtio0: Received 1 messages
[ 143.404302] remoteproc remoteproc0: vq index 0 is interrupted
[ 143.404319] virtqueue callback for (ptrval) ((ptrval))
[ 143.404337] virtio_rpmsg_bus virtio0: From: 0x1, To: 0x35, Len: 40, Flags: 0, Reserved: 0
[ 143.404350] rpmsg_virtio RX: 01 00 00 00 35 00 00 00 00 00 00 00 28 00 00 00 ....5.......(...
[ 143.404391] rpmsg_virtio RX: 72 70 6d 73 67 2d 74 74 79 2d 72 61 77 00 00 00 rpmsg-tty-raw...
[ 143.404399] rpmsg_virtio RX: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
[ 143.404405] rpmsg_virtio RX: 01 00 00 00 00 00 00 00 ........
[ 143.404417] NS announcement: 72 70 6d 73 67 2d 74 74 79 2d 72 61 77 00 00 00 rpmsg-tty-raw...
[ 143.404424] NS announcement: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
[ 143.404430] NS announcement: 01 00 00 00 00 00 00 00 ........
[ 143.404441] virtio_rpmsg_bus virtio0: creating channel rpmsg-tty-raw addr 0x1
[ 143.411114] rpmsg_tty virtio0.rpmsg-tty-raw.-1.1: new channel: 0x401 -> 0x1 : ttyRPMSG1
Add support for carveout memory regions required for vdev vring's and
buffer.
Search in device tree and allocate memory regions like for ocram:
vdev0vring0: vdev0vring0@00920000 {
compatible = "shared-dma-pool";
reg = <0x00920000 0x2000>;
no-map;
};
vdev0vring1: vdev0vring1@00922000 {
compatible = "shared-dma-pool";
reg = <0x00922000 0x2000>;
no-map;
};
vdev0buffer: vdev0buffer@00924000 {
compatible = "shared-dma-pool";
reg = <0x00924000 0x4000>;
no-map;
};
imx7d-cm4 {
compatible = "fsl,imx7d-cm4";
memory-region = <&ocram>, <&vdev0vring0>, <&vdev0vring1>, \
<&vdev0buffer>;
}
vdev0vring0, vdev0vring1, vdev0buffer are required for virtio
functioning.
Signed-off-by: Nikita Shubin <[email protected]>
---
drivers/remoteproc/imx_rproc.c | 119 ++++++++++++++++++++++++++++++++-
1 file changed, 118 insertions(+), 1 deletion(-)
diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c
index d2bede4ccb70..cdcff2bd2867 100644
--- a/drivers/remoteproc/imx_rproc.c
+++ b/drivers/remoteproc/imx_rproc.c
@@ -11,6 +11,7 @@
#include <linux/module.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
+#include <linux/of_reserved_mem.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/remoteproc.h>
@@ -238,6 +239,29 @@ static int imx_rproc_da_to_sys(struct imx_rproc *priv, u64 da,
return -ENOENT;
}
+static int imx_rproc_sys_to_da(struct imx_rproc *priv, u64 sys,
+ int len, u64 *da)
+{
+ const struct imx_rproc_dcfg *dcfg = priv->dcfg;
+ int i;
+
+ /* parse address translation table */
+ for (i = 0; i < dcfg->att_size; i++) {
+ const struct imx_rproc_att *att = &dcfg->att[i];
+
+ if (sys >= att->sa && sys + len <= att->sa + att->size) {
+ unsigned int offset = sys - att->sa;
+
+ *da = att->da + offset;
+ return 0;
+ }
+ }
+
+ dev_warn(priv->dev, "Translation failed: sys = 0x%llx len = 0x%x\n",
+ sys, len);
+ return -ENOENT;
+}
+
static void *imx_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
{
struct imx_rproc *priv = rproc->priv;
@@ -372,16 +396,109 @@ static void imx_rproc_kick(struct rproc *rproc, int vqid)
err = mbox_send_message(ddata->mb[i].chan, &vqid);
if (err < 0)
dev_err(&rproc->dev, "%s: failed (%s, err:%d)\n",
- __func__, ddata->mb[i].name, err);
+ __func__, ddata->mb[i].name, err);
return;
}
}
+static int imx_rproc_mem_alloc(struct rproc *rproc,
+ struct rproc_mem_entry *mem)
+{
+ struct device *dev = rproc->dev.parent;
+ void *va;
+
+ dev_dbg(dev, "map memory: %pa+%x\n", &mem->dma, mem->len);
+ va = ioremap_wc(mem->dma, mem->len);
+ if (IS_ERR_OR_NULL(va)) {
+ dev_err(dev, "Unable to map memory region: %pa+%x\n",
+ &mem->dma, mem->len);
+ return -ENOMEM;
+ }
+
+ /* Update memory entry va */
+ mem->va = va;
+
+ return 0;
+}
+
+static int imx_rproc_mem_release(struct rproc *rproc,
+ struct rproc_mem_entry *mem)
+{
+ dev_dbg(rproc->dev.parent, "unmap memory: %pa\n", &mem->dma);
+ iounmap(mem->va);
+
+ return 0;
+}
+
+static int imx_rproc_parse_fw(struct rproc *rproc, const struct firmware *fw)
+{
+ struct imx_rproc *priv = rproc->priv;
+ struct device *dev = rproc->dev.parent;
+ struct device_node *np = dev->of_node;
+ struct of_phandle_iterator it;
+ struct rproc_mem_entry *mem = 0;
+ struct reserved_mem *rmem;
+ u64 da;
+ int index = 0;
+
+ /* Register associated reserved memory regions */
+ of_phandle_iterator_init(&it, np, "memory-region", NULL, 0);
+ while (of_phandle_iterator_next(&it) == 0) {
+ rmem = of_reserved_mem_lookup(it.node);
+ if (!rmem) {
+ dev_err(dev, "unable to acquire memory-region\n");
+ return -EINVAL;
+ }
+
+ /*
+ * Let's assume all data in device tree is from
+ * CPU A7 point of view then we should translate
+ * rmem->base into M4 da
+ */
+ if (imx_rproc_sys_to_da(priv, rmem->base, rmem->size, &da)) {
+ dev_err(dev, "memory region not valid %pa\n",
+ &rmem->base);
+ return -EINVAL;
+ }
+
+ if (strcmp(it.node->name, "vdev0buffer")) {
+ /* Register memory region */
+ mem = rproc_mem_entry_init(dev, NULL,
+ (dma_addr_t)rmem->base,
+ rmem->size, da,
+ imx_rproc_mem_alloc,
+ imx_rproc_mem_release,
+ it.node->name);
+
+ if (mem)
+ rproc_coredump_add_segment(rproc, da,
+ rmem->size);
+ } else {
+ mem = rproc_of_resm_mem_entry_init(dev, index,
+ rmem->size,
+ rmem->base,
+ it.node->name);
+ }
+
+ if (!mem)
+ return -ENOMEM;
+
+ rproc_add_carveout(rproc, mem);
+ index++;
+ }
+
+ return rproc_elf_load_rsc_table(rproc, fw);
+}
+
static const struct rproc_ops imx_rproc_ops = {
.start = imx_rproc_start,
.stop = imx_rproc_stop,
.da_to_va = imx_rproc_da_to_va,
.kick = imx_rproc_kick,
+ .load = rproc_elf_load_segments,
+ .parse_fw = imx_rproc_parse_fw,
+ .find_loaded_rsc_table = rproc_elf_find_loaded_rsc_table,
+ .sanity_check = rproc_elf_sanity_check,
.get_boot_addr = rproc_elf_get_boot_addr,
};
--
2.25.1
Add support for mailboxes to imx_rproc
Signed-off-by: Nikita Shubin <[email protected]>
---
drivers/remoteproc/Kconfig | 2 +
drivers/remoteproc/imx_rproc.c | 142 ++++++++++++++++++++++++++++++++-
2 files changed, 143 insertions(+), 1 deletion(-)
diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig
index 94afdde4bc9f..02d23a54c9cf 100644
--- a/drivers/remoteproc/Kconfig
+++ b/drivers/remoteproc/Kconfig
@@ -17,6 +17,8 @@ if REMOTEPROC
config IMX_REMOTEPROC
tristate "IMX6/7 remoteproc support"
depends on ARCH_MXC
+ select MAILBOX
+ select IMX_MBOX
help
Say y here to support iMX's remote processors (Cortex M4
on iMX7D) via the remote processor framework.
diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c
index bebc58d0f711..d2bede4ccb70 100644
--- a/drivers/remoteproc/imx_rproc.c
+++ b/drivers/remoteproc/imx_rproc.c
@@ -14,6 +14,9 @@
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/remoteproc.h>
+#include <linux/mailbox_client.h>
+
+#include "remoteproc_internal.h"
#define IMX7D_SRC_SCR 0x0C
#define IMX7D_ENABLE_M4 BIT(3)
@@ -47,6 +50,12 @@
#define IMX_BOOT_PC 0x4
+#define IMX_MBOX_NB_VQ 2
+#define IMX_MBOX_NB_MBX 2
+
+#define IMX_MBX_VQ0 "vq0"
+#define IMX_MBX_VQ1 "vq1"
+
/**
* struct imx_rproc_mem - slim internal memory structure
* @cpu_addr: MPU virtual address of the memory region
@@ -80,6 +89,14 @@ struct imx_rproc_dcfg {
size_t att_size;
};
+struct imx_mbox {
+ const unsigned char name[10];
+ struct mbox_chan *chan;
+ struct mbox_client client;
+ struct work_struct vq_work;
+ int vq_id;
+};
+
struct imx_rproc {
struct device *dev;
struct regmap *regmap;
@@ -88,6 +105,8 @@ struct imx_rproc {
struct imx_rproc_mem mem[IMX7D_RPROC_MEM_MAX];
struct clk *clk;
void __iomem *bootreg;
+ struct imx_mbox mb[IMX_MBOX_NB_MBX];
+ struct workqueue_struct *workqueue;
};
static const struct imx_rproc_att imx_rproc_att_imx7d[] = {
@@ -251,10 +270,118 @@ static void *imx_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
return va;
}
+static void imx_rproc_mb_vq_work(struct work_struct *work)
+{
+ struct imx_mbox *mb = container_of(work, struct imx_mbox, vq_work);
+ struct rproc *rproc = dev_get_drvdata(mb->client.dev);
+
+ if (rproc_vq_interrupt(rproc, mb->vq_id) == IRQ_NONE)
+ dev_dbg(&rproc->dev, "no message found in vq%d\n", mb->vq_id);
+}
+
+static void imx_rproc_mb_callback(struct mbox_client *cl, void *data)
+{
+ struct rproc *rproc = dev_get_drvdata(cl->dev);
+ struct imx_mbox *mb = container_of(cl, struct imx_mbox, client);
+ struct imx_rproc *ddata = rproc->priv;
+
+ queue_work(ddata->workqueue, &mb->vq_work);
+}
+
+static const struct imx_mbox imx_rproc_mbox[IMX_MBOX_NB_MBX] = {
+ {
+ .name = IMX_MBX_VQ0,
+ .vq_id = 0,
+ .client = {
+ .rx_callback = imx_rproc_mb_callback,
+ .tx_block = false,
+ },
+ },
+ {
+ .name = IMX_MBX_VQ1,
+ .vq_id = 1,
+ .client = {
+ .rx_callback = imx_rproc_mb_callback,
+ .tx_block = false,
+ },
+ },
+};
+
+static void imx_rproc_request_mbox(struct rproc *rproc)
+{
+ struct imx_rproc *ddata = rproc->priv;
+ struct device *dev = &rproc->dev;
+ unsigned int i;
+ const unsigned char *name;
+ struct mbox_client *cl;
+
+ /* Initialise mailbox structure table */
+ memcpy(ddata->mb, imx_rproc_mbox, sizeof(imx_rproc_mbox));
+
+ for (i = 0; i < IMX_MBOX_NB_MBX; i++) {
+ name = ddata->mb[i].name;
+
+ cl = &ddata->mb[i].client;
+ cl->dev = dev->parent;
+
+ ddata->mb[i].chan = mbox_request_channel_byname(cl, name);
+
+ dev_dbg(dev, "%s: name=%s, idx=%u\n",
+ __func__, name, ddata->mb[i].vq_id);
+
+ if (IS_ERR(ddata->mb[i].chan)) {
+ dev_warn(dev, "cannot get %s mbox\n", name);
+ ddata->mb[i].chan = NULL;
+ }
+
+ if (ddata->mb[i].vq_id >= 0)
+ INIT_WORK(&ddata->mb[i].vq_work, imx_rproc_mb_vq_work);
+ }
+}
+
+static void imx_rproc_free_mbox(struct rproc *rproc)
+{
+ struct imx_rproc *ddata = rproc->priv;
+ unsigned int i;
+
+ dev_dbg(&rproc->dev, "%s: %d boxes\n",
+ __func__, ARRAY_SIZE(ddata->mb));
+
+ for (i = 0; i < ARRAY_SIZE(ddata->mb); i++) {
+ if (ddata->mb[i].chan)
+ mbox_free_channel(ddata->mb[i].chan);
+ ddata->mb[i].chan = NULL;
+ }
+}
+
+static void imx_rproc_kick(struct rproc *rproc, int vqid)
+{
+ struct imx_rproc *ddata = rproc->priv;
+ unsigned int i;
+ int err;
+
+ if (WARN_ON(vqid >= IMX_MBOX_NB_VQ))
+ return;
+
+ for (i = 0; i < IMX_MBOX_NB_MBX; i++) {
+ if (vqid != ddata->mb[i].vq_id)
+ continue;
+ if (!ddata->mb[i].chan)
+ return;
+ dev_dbg(&rproc->dev, "sending message : vqid = %d\n", vqid);
+ err = mbox_send_message(ddata->mb[i].chan, &vqid);
+ if (err < 0)
+ dev_err(&rproc->dev, "%s: failed (%s, err:%d)\n",
+ __func__, ddata->mb[i].name, err);
+ return;
+ }
+}
+
static const struct rproc_ops imx_rproc_ops = {
.start = imx_rproc_start,
.stop = imx_rproc_stop,
.da_to_va = imx_rproc_da_to_va,
+ .kick = imx_rproc_kick,
.get_boot_addr = rproc_elf_get_boot_addr,
};
@@ -384,14 +511,26 @@ static int imx_rproc_probe(struct platform_device *pdev)
goto err_put_rproc;
}
+ priv->workqueue = create_workqueue(dev_name(dev));
+ if (!priv->workqueue) {
+ dev_err(dev, "cannot create workqueue\n");
+ ret = -ENOMEM;
+ goto err_put_clk;
+ }
+
+ imx_rproc_request_mbox(rproc);
+
ret = rproc_add(rproc);
if (ret) {
dev_err(dev, "rproc_add failed\n");
- goto err_put_clk;
+ goto err_free_mb;
}
return 0;
+err_free_mb:
+ imx_rproc_free_mbox(rproc);
+ destroy_workqueue(priv->workqueue);
err_put_clk:
clk_disable_unprepare(priv->clk);
err_put_rproc:
@@ -407,6 +546,7 @@ static int imx_rproc_remove(struct platform_device *pdev)
clk_disable_unprepare(priv->clk);
rproc_del(rproc);
+ imx_rproc_free_mbox(rproc);
rproc_free(rproc);
return 0;
--
2.25.1
Hi,
Thank you for the patch! Perhaps something to improve:
[auto build test WARNING on linux/master]
[also build test WARNING on v5.6 next-20200406]
[cannot apply to linus/master remoteproc/for-next rpmsg/for-next]
[if your patch is applied to the wrong git tree, please drop us a note to help
improve the system. BTW, we also suggest to use '--base' option to specify the
base tree in git format-patch, please see https://stackoverflow.com/a/37406982]
url: https://github.com/0day-ci/linux/commits/nikita-shubin-maquefel-me/remoteproc-imx_rproc-add-virtio-support/20200406-201717
base: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git f5ae2ea6347a308cfe91f53b53682ce635497d0d
config: arm64-allmodconfig (attached as .config)
compiler: aarch64-linux-gcc (GCC) 9.3.0
reproduce:
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
GCC_VERSION=9.3.0 make.cross ARCH=arm64
If you fix the issue, kindly add following tag as appropriate
Reported-by: kbuild test robot <[email protected]>
All warnings (new ones prefixed by >>):
In file included from include/linux/printk.h:331,
from include/linux/kernel.h:15,
from include/linux/clk.h:13,
from drivers/remoteproc/imx_rproc.c:6:
drivers/remoteproc/imx_rproc.c: In function 'imx_rproc_free_mbox':
>> drivers/remoteproc/imx_rproc.c:347:23: warning: format '%d' expects argument of type 'int', but argument 5 has type 'long unsigned int' [-Wformat=]
347 | dev_dbg(&rproc->dev, "%s: %d boxes\n",
| ^~~~~~~~~~~~~~~~
include/linux/dynamic_debug.h:125:15: note: in definition of macro '__dynamic_func_call'
125 | func(&id, ##__VA_ARGS__); \
| ^~~~~~~~~~~
include/linux/dynamic_debug.h:157:2: note: in expansion of macro '_dynamic_func_call'
157 | _dynamic_func_call(fmt,__dynamic_dev_dbg, \
| ^~~~~~~~~~~~~~~~~~
include/linux/device.h:1784:2: note: in expansion of macro 'dynamic_dev_dbg'
1784 | dynamic_dev_dbg(dev, dev_fmt(fmt), ##__VA_ARGS__)
| ^~~~~~~~~~~~~~~
include/linux/device.h:1784:23: note: in expansion of macro 'dev_fmt'
1784 | dynamic_dev_dbg(dev, dev_fmt(fmt), ##__VA_ARGS__)
| ^~~~~~~
>> drivers/remoteproc/imx_rproc.c:347:2: note: in expansion of macro 'dev_dbg'
347 | dev_dbg(&rproc->dev, "%s: %d boxes\n",
| ^~~~~~~
drivers/remoteproc/imx_rproc.c:347:29: note: format string is defined here
347 | dev_dbg(&rproc->dev, "%s: %d boxes\n",
| ~^
| |
| int
| %ld
vim +347 drivers/remoteproc/imx_rproc.c
341
342 static void imx_rproc_free_mbox(struct rproc *rproc)
343 {
344 struct imx_rproc *ddata = rproc->priv;
345 unsigned int i;
346
> 347 dev_dbg(&rproc->dev, "%s: %d boxes\n",
348 __func__, ARRAY_SIZE(ddata->mb));
349
350 for (i = 0; i < ARRAY_SIZE(ddata->mb); i++) {
351 if (ddata->mb[i].chan)
352 mbox_free_channel(ddata->mb[i].chan);
353 ddata->mb[i].chan = NULL;
354 }
355 }
356
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/[email protected]
On Mon, Apr 06, 2020 at 02:33:09PM +0300, [email protected] wrote:
> Add support for mailboxes to imx_rproc
>
> Signed-off-by: Nikita Shubin <[email protected]>
> ---
> drivers/remoteproc/Kconfig | 2 +
> drivers/remoteproc/imx_rproc.c | 142 ++++++++++++++++++++++++++++++++-
> 2 files changed, 143 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig
> index 94afdde4bc9f..02d23a54c9cf 100644
> --- a/drivers/remoteproc/Kconfig
> +++ b/drivers/remoteproc/Kconfig
> @@ -17,6 +17,8 @@ if REMOTEPROC
> config IMX_REMOTEPROC
> tristate "IMX6/7 remoteproc support"
> depends on ARCH_MXC
> + select MAILBOX
> + select IMX_MBOX
> help
> Say y here to support iMX's remote processors (Cortex M4
> on iMX7D) via the remote processor framework.
> diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c
> index bebc58d0f711..d2bede4ccb70 100644
> --- a/drivers/remoteproc/imx_rproc.c
> +++ b/drivers/remoteproc/imx_rproc.c
> @@ -14,6 +14,9 @@
> #include <linux/platform_device.h>
> #include <linux/regmap.h>
> #include <linux/remoteproc.h>
> +#include <linux/mailbox_client.h>
> +
> +#include "remoteproc_internal.h"
>
> #define IMX7D_SRC_SCR 0x0C
> #define IMX7D_ENABLE_M4 BIT(3)
> @@ -47,6 +50,12 @@
>
> #define IMX_BOOT_PC 0x4
>
> +#define IMX_MBOX_NB_VQ 2
> +#define IMX_MBOX_NB_MBX 2
Please align this.
> +
> +#define IMX_MBX_VQ0 "vq0"
> +#define IMX_MBX_VQ1 "vq1"
> +
> /**
> * struct imx_rproc_mem - slim internal memory structure
> * @cpu_addr: MPU virtual address of the memory region
> @@ -80,6 +89,14 @@ struct imx_rproc_dcfg {
> size_t att_size;
> };
>
> +struct imx_mbox {
> + const unsigned char name[10];
> + struct mbox_chan *chan;
> + struct mbox_client client;
> + struct work_struct vq_work;
> + int vq_id;
> +};
> +
> struct imx_rproc {
> struct device *dev;
> struct regmap *regmap;
> @@ -88,6 +105,8 @@ struct imx_rproc {
> struct imx_rproc_mem mem[IMX7D_RPROC_MEM_MAX];
> struct clk *clk;
> void __iomem *bootreg;
> + struct imx_mbox mb[IMX_MBOX_NB_MBX];
> + struct workqueue_struct *workqueue;
> };
>
> static const struct imx_rproc_att imx_rproc_att_imx7d[] = {
> @@ -251,10 +270,118 @@ static void *imx_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
> return va;
> }
>
> +static void imx_rproc_mb_vq_work(struct work_struct *work)
> +{
> + struct imx_mbox *mb = container_of(work, struct imx_mbox, vq_work);
> + struct rproc *rproc = dev_get_drvdata(mb->client.dev);
> +
> + if (rproc_vq_interrupt(rproc, mb->vq_id) == IRQ_NONE)
> + dev_dbg(&rproc->dev, "no message found in vq%d\n", mb->vq_id);
> +}
> +
> +static void imx_rproc_mb_callback(struct mbox_client *cl, void *data)
> +{
> + struct rproc *rproc = dev_get_drvdata(cl->dev);
> + struct imx_mbox *mb = container_of(cl, struct imx_mbox, client);
> + struct imx_rproc *ddata = rproc->priv;
> +
> + queue_work(ddata->workqueue, &mb->vq_work);
> +}
> +
> +static const struct imx_mbox imx_rproc_mbox[IMX_MBOX_NB_MBX] = {
> + {
> + .name = IMX_MBX_VQ0,
> + .vq_id = 0,
> + .client = {
> + .rx_callback = imx_rproc_mb_callback,
> + .tx_block = false,
> + },
> + },
> + {
> + .name = IMX_MBX_VQ1,
> + .vq_id = 1,
> + .client = {
> + .rx_callback = imx_rproc_mb_callback,
> + .tx_block = false,
> + },
> + },
> +};
> +
> +static void imx_rproc_request_mbox(struct rproc *rproc)
> +{
> + struct imx_rproc *ddata = rproc->priv;
> + struct device *dev = &rproc->dev;
> + unsigned int i;
> + const unsigned char *name;
> + struct mbox_client *cl;
> +
> + /* Initialise mailbox structure table */
> + memcpy(ddata->mb, imx_rproc_mbox, sizeof(imx_rproc_mbox));
> +
> + for (i = 0; i < IMX_MBOX_NB_MBX; i++) {
> + name = ddata->mb[i].name;
> +
> + cl = &ddata->mb[i].client;
> + cl->dev = dev->parent;
> +
> + ddata->mb[i].chan = mbox_request_channel_byname(cl, name);
> +
> + dev_dbg(dev, "%s: name=%s, idx=%u\n",
> + __func__, name, ddata->mb[i].vq_id);
> +
> + if (IS_ERR(ddata->mb[i].chan)) {
> + dev_warn(dev, "cannot get %s mbox\n", name);
> + ddata->mb[i].chan = NULL;
If the mailbox isn't ready this driver will fail without a chance of recovery.
Since most of the code in this patch is a carbon copy of the implementation
found in stm32_proc.c, I suggest you do the same as they did in
stm32_rproc_request_mbox() and privision for cases where requesting a channel
returns -EPROBE_DEFER.
> + }
> +
> + if (ddata->mb[i].vq_id >= 0)
> + INIT_WORK(&ddata->mb[i].vq_work, imx_rproc_mb_vq_work);
> + }
> +}
> +
> +static void imx_rproc_free_mbox(struct rproc *rproc)
> +{
> + struct imx_rproc *ddata = rproc->priv;
> + unsigned int i;
> +
> + dev_dbg(&rproc->dev, "%s: %d boxes\n",
> + __func__, ARRAY_SIZE(ddata->mb));
> +
> + for (i = 0; i < ARRAY_SIZE(ddata->mb); i++) {
> + if (ddata->mb[i].chan)
> + mbox_free_channel(ddata->mb[i].chan);
> + ddata->mb[i].chan = NULL;
> + }
> +}
> +
> +static void imx_rproc_kick(struct rproc *rproc, int vqid)
> +{
> + struct imx_rproc *ddata = rproc->priv;
> + unsigned int i;
> + int err;
> +
> + if (WARN_ON(vqid >= IMX_MBOX_NB_VQ))
> + return;
> +
> + for (i = 0; i < IMX_MBOX_NB_MBX; i++) {
> + if (vqid != ddata->mb[i].vq_id)
> + continue;
> + if (!ddata->mb[i].chan)
> + return;
> + dev_dbg(&rproc->dev, "sending message : vqid = %d\n", vqid);
> + err = mbox_send_message(ddata->mb[i].chan, &vqid);
> + if (err < 0)
> + dev_err(&rproc->dev, "%s: failed (%s, err:%d)\n",
> + __func__, ddata->mb[i].name, err);
> + return;
> + }
> +}
> +
> static const struct rproc_ops imx_rproc_ops = {
> .start = imx_rproc_start,
> .stop = imx_rproc_stop,
> .da_to_va = imx_rproc_da_to_va,
> + .kick = imx_rproc_kick,
> .get_boot_addr = rproc_elf_get_boot_addr,
> };
>
> @@ -384,14 +511,26 @@ static int imx_rproc_probe(struct platform_device *pdev)
> goto err_put_rproc;
> }
>
> + priv->workqueue = create_workqueue(dev_name(dev));
> + if (!priv->workqueue) {
> + dev_err(dev, "cannot create workqueue\n");
> + ret = -ENOMEM;
> + goto err_put_clk;
> + }
> +
> + imx_rproc_request_mbox(rproc);
> +
> ret = rproc_add(rproc);
> if (ret) {
> dev_err(dev, "rproc_add failed\n");
> - goto err_put_clk;
> + goto err_free_mb;
> }
>
> return 0;
>
> +err_free_mb:
> + imx_rproc_free_mbox(rproc);
> + destroy_workqueue(priv->workqueue);
> err_put_clk:
> clk_disable_unprepare(priv->clk);
> err_put_rproc:
> @@ -407,6 +546,7 @@ static int imx_rproc_remove(struct platform_device *pdev)
>
> clk_disable_unprepare(priv->clk);
> rproc_del(rproc);
> + imx_rproc_free_mbox(rproc);
I have no issues with people reusing code already found in the kernel - in fact
I encourage it because it makes reviewing patches much easier. On the flip side
you have to give credit where it is due. Here adding a line in the changelog
that mentions where you took your inspiration from will be much appreciated.
Thanks,
Mathieu
> rproc_free(rproc);
>
> return 0;
> --
> 2.25.1
>
On Mon, Apr 06, 2020 at 02:33:10PM +0300, [email protected] wrote:
> Add support for carveout memory regions required for vdev vring's and
> buffer.
>
> Search in device tree and allocate memory regions like for ocram:
>
> vdev0vring0: vdev0vring0@00920000 {
> compatible = "shared-dma-pool";
> reg = <0x00920000 0x2000>;
> no-map;
> };
>
> vdev0vring1: vdev0vring1@00922000 {
> compatible = "shared-dma-pool";
> reg = <0x00922000 0x2000>;
> no-map;
> };
>
> vdev0buffer: vdev0buffer@00924000 {
> compatible = "shared-dma-pool";
> reg = <0x00924000 0x4000>;
> no-map;
> };
>
> imx7d-cm4 {
> compatible = "fsl,imx7d-cm4";
> memory-region = <&ocram>, <&vdev0vring0>, <&vdev0vring1>, \
> <&vdev0buffer>;
> }
>
> vdev0vring0, vdev0vring1, vdev0buffer are required for virtio
> functioning.
>
> Signed-off-by: Nikita Shubin <[email protected]>
> ---
> drivers/remoteproc/imx_rproc.c | 119 ++++++++++++++++++++++++++++++++-
> 1 file changed, 118 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c
> index d2bede4ccb70..cdcff2bd2867 100644
> --- a/drivers/remoteproc/imx_rproc.c
> +++ b/drivers/remoteproc/imx_rproc.c
> @@ -11,6 +11,7 @@
> #include <linux/module.h>
> #include <linux/of_address.h>
> #include <linux/of_device.h>
> +#include <linux/of_reserved_mem.h>
> #include <linux/platform_device.h>
> #include <linux/regmap.h>
> #include <linux/remoteproc.h>
> @@ -238,6 +239,29 @@ static int imx_rproc_da_to_sys(struct imx_rproc *priv, u64 da,
> return -ENOENT;
> }
>
> +static int imx_rproc_sys_to_da(struct imx_rproc *priv, u64 sys,
> + int len, u64 *da)
> +{
> + const struct imx_rproc_dcfg *dcfg = priv->dcfg;
> + int i;
> +
> + /* parse address translation table */
> + for (i = 0; i < dcfg->att_size; i++) {
> + const struct imx_rproc_att *att = &dcfg->att[i];
> +
> + if (sys >= att->sa && sys + len <= att->sa + att->size) {
> + unsigned int offset = sys - att->sa;
> +
> + *da = att->da + offset;
> + return 0;
> + }
> + }
> +
> + dev_warn(priv->dev, "Translation failed: sys = 0x%llx len = 0x%x\n",
> + sys, len);
> + return -ENOENT;
> +}
> +
> static void *imx_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
> {
> struct imx_rproc *priv = rproc->priv;
> @@ -372,16 +396,109 @@ static void imx_rproc_kick(struct rproc *rproc, int vqid)
> err = mbox_send_message(ddata->mb[i].chan, &vqid);
> if (err < 0)
> dev_err(&rproc->dev, "%s: failed (%s, err:%d)\n",
> - __func__, ddata->mb[i].name, err);
> + __func__, ddata->mb[i].name, err);
> return;
> }
> }
>
> +static int imx_rproc_mem_alloc(struct rproc *rproc,
> + struct rproc_mem_entry *mem)
> +{
> + struct device *dev = rproc->dev.parent;
> + void *va;
> +
> + dev_dbg(dev, "map memory: %pa+%x\n", &mem->dma, mem->len);
> + va = ioremap_wc(mem->dma, mem->len);
> + if (IS_ERR_OR_NULL(va)) {
> + dev_err(dev, "Unable to map memory region: %pa+%x\n",
> + &mem->dma, mem->len);
> + return -ENOMEM;
> + }
> +
> + /* Update memory entry va */
> + mem->va = va;
> +
> + return 0;
> +}
> +
> +static int imx_rproc_mem_release(struct rproc *rproc,
> + struct rproc_mem_entry *mem)
> +{
> + dev_dbg(rproc->dev.parent, "unmap memory: %pa\n", &mem->dma);
> + iounmap(mem->va);
> +
> + return 0;
> +}
> +
> +static int imx_rproc_parse_fw(struct rproc *rproc, const struct firmware *fw)
> +{
> + struct imx_rproc *priv = rproc->priv;
> + struct device *dev = rproc->dev.parent;
> + struct device_node *np = dev->of_node;
> + struct of_phandle_iterator it;
> + struct rproc_mem_entry *mem = 0;
> + struct reserved_mem *rmem;
> + u64 da;
> + int index = 0;
> +
> + /* Register associated reserved memory regions */
> + of_phandle_iterator_init(&it, np, "memory-region", NULL, 0);
This will likely clash with the parsing done in imx_rproc_addr_init(), and the
parsing in there will also clash with what is done below... I advise you to
register carvouts in imx_rproc_addr_init() as you parse the rest of the memory
regions.
Thanks,
Mathieu
> + while (of_phandle_iterator_next(&it) == 0) {
> + rmem = of_reserved_mem_lookup(it.node);
> + if (!rmem) {
> + dev_err(dev, "unable to acquire memory-region\n");
> + return -EINVAL;
> + }
> +
> + /*
> + * Let's assume all data in device tree is from
> + * CPU A7 point of view then we should translate
> + * rmem->base into M4 da
> + */
> + if (imx_rproc_sys_to_da(priv, rmem->base, rmem->size, &da)) {
> + dev_err(dev, "memory region not valid %pa\n",
> + &rmem->base);
> + return -EINVAL;
> + }
> +
> + if (strcmp(it.node->name, "vdev0buffer")) {
> + /* Register memory region */
> + mem = rproc_mem_entry_init(dev, NULL,
> + (dma_addr_t)rmem->base,
> + rmem->size, da,
> + imx_rproc_mem_alloc,
> + imx_rproc_mem_release,
> + it.node->name);
> +
> + if (mem)
> + rproc_coredump_add_segment(rproc, da,
> + rmem->size);
> + } else {
> + mem = rproc_of_resm_mem_entry_init(dev, index,
> + rmem->size,
> + rmem->base,
> + it.node->name);
> + }
> +
> + if (!mem)
> + return -ENOMEM;
> +
> + rproc_add_carveout(rproc, mem);
> + index++;
> + }
> +
> + return rproc_elf_load_rsc_table(rproc, fw);
> +}
> +
> static const struct rproc_ops imx_rproc_ops = {
> .start = imx_rproc_start,
> .stop = imx_rproc_stop,
> .da_to_va = imx_rproc_da_to_va,
> .kick = imx_rproc_kick,
> + .load = rproc_elf_load_segments,
> + .parse_fw = imx_rproc_parse_fw,
> + .find_loaded_rsc_table = rproc_elf_find_loaded_rsc_table,
> + .sanity_check = rproc_elf_sanity_check,
> .get_boot_addr = rproc_elf_get_boot_addr,
> };
>
> --
> 2.25.1
>
On Mon, Apr 06, 2020 at 02:33:09PM +0300, [email protected] wrote:
> Add support for mailboxes to imx_rproc
>
> Signed-off-by: Nikita Shubin <[email protected]>
> ---
> drivers/remoteproc/Kconfig | 2 +
> drivers/remoteproc/imx_rproc.c | 142 ++++++++++++++++++++++++++++++++-
> 2 files changed, 143 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig
> index 94afdde4bc9f..02d23a54c9cf 100644
> --- a/drivers/remoteproc/Kconfig
> +++ b/drivers/remoteproc/Kconfig
> @@ -17,6 +17,8 @@ if REMOTEPROC
> config IMX_REMOTEPROC
> tristate "IMX6/7 remoteproc support"
> depends on ARCH_MXC
> + select MAILBOX
> + select IMX_MBOX
> help
> Say y here to support iMX's remote processors (Cortex M4
> on iMX7D) via the remote processor framework.
> diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c
> index bebc58d0f711..d2bede4ccb70 100644
> --- a/drivers/remoteproc/imx_rproc.c
> +++ b/drivers/remoteproc/imx_rproc.c
> @@ -14,6 +14,9 @@
> #include <linux/platform_device.h>
> #include <linux/regmap.h>
> #include <linux/remoteproc.h>
> +#include <linux/mailbox_client.h>
> +
> +#include "remoteproc_internal.h"
>
> #define IMX7D_SRC_SCR 0x0C
> #define IMX7D_ENABLE_M4 BIT(3)
> @@ -47,6 +50,12 @@
>
> #define IMX_BOOT_PC 0x4
>
> +#define IMX_MBOX_NB_VQ 2
> +#define IMX_MBOX_NB_MBX 2
> +
> +#define IMX_MBX_VQ0 "vq0"
> +#define IMX_MBX_VQ1 "vq1"
> +
> /**
> * struct imx_rproc_mem - slim internal memory structure
> * @cpu_addr: MPU virtual address of the memory region
> @@ -80,6 +89,14 @@ struct imx_rproc_dcfg {
> size_t att_size;
> };
>
> +struct imx_mbox {
> + const unsigned char name[10];
> + struct mbox_chan *chan;
> + struct mbox_client client;
> + struct work_struct vq_work;
> + int vq_id;
> +};
> +
> struct imx_rproc {
> struct device *dev;
> struct regmap *regmap;
> @@ -88,6 +105,8 @@ struct imx_rproc {
> struct imx_rproc_mem mem[IMX7D_RPROC_MEM_MAX];
> struct clk *clk;
> void __iomem *bootreg;
> + struct imx_mbox mb[IMX_MBOX_NB_MBX];
> + struct workqueue_struct *workqueue;
> };
>
> static const struct imx_rproc_att imx_rproc_att_imx7d[] = {
> @@ -251,10 +270,118 @@ static void *imx_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
> return va;
> }
>
> +static void imx_rproc_mb_vq_work(struct work_struct *work)
> +{
> + struct imx_mbox *mb = container_of(work, struct imx_mbox, vq_work);
> + struct rproc *rproc = dev_get_drvdata(mb->client.dev);
> +
> + if (rproc_vq_interrupt(rproc, mb->vq_id) == IRQ_NONE)
> + dev_dbg(&rproc->dev, "no message found in vq%d\n", mb->vq_id);
> +}
> +
> +static void imx_rproc_mb_callback(struct mbox_client *cl, void *data)
> +{
> + struct rproc *rproc = dev_get_drvdata(cl->dev);
> + struct imx_mbox *mb = container_of(cl, struct imx_mbox, client);
> + struct imx_rproc *ddata = rproc->priv;
> +
> + queue_work(ddata->workqueue, &mb->vq_work);
> +}
> +
> +static const struct imx_mbox imx_rproc_mbox[IMX_MBOX_NB_MBX] = {
> + {
> + .name = IMX_MBX_VQ0,
> + .vq_id = 0,
> + .client = {
> + .rx_callback = imx_rproc_mb_callback,
> + .tx_block = false,
> + },
> + },
> + {
> + .name = IMX_MBX_VQ1,
> + .vq_id = 1,
> + .client = {
> + .rx_callback = imx_rproc_mb_callback,
> + .tx_block = false,
> + },
> + },
> +};
> +
> +static void imx_rproc_request_mbox(struct rproc *rproc)
> +{
> + struct imx_rproc *ddata = rproc->priv;
> + struct device *dev = &rproc->dev;
> + unsigned int i;
> + const unsigned char *name;
> + struct mbox_client *cl;
> +
> + /* Initialise mailbox structure table */
> + memcpy(ddata->mb, imx_rproc_mbox, sizeof(imx_rproc_mbox));
> +
> + for (i = 0; i < IMX_MBOX_NB_MBX; i++) {
> + name = ddata->mb[i].name;
> +
> + cl = &ddata->mb[i].client;
> + cl->dev = dev->parent;
> +
> + ddata->mb[i].chan = mbox_request_channel_byname(cl, name);
I forgot... You will also need to update the bindings document (imx-rproc.txt).
> +
> + dev_dbg(dev, "%s: name=%s, idx=%u\n",
> + __func__, name, ddata->mb[i].vq_id);
> +
> + if (IS_ERR(ddata->mb[i].chan)) {
> + dev_warn(dev, "cannot get %s mbox\n", name);
> + ddata->mb[i].chan = NULL;
> + }
> +
> + if (ddata->mb[i].vq_id >= 0)
> + INIT_WORK(&ddata->mb[i].vq_work, imx_rproc_mb_vq_work);
> + }
> +}
> +
> +static void imx_rproc_free_mbox(struct rproc *rproc)
> +{
> + struct imx_rproc *ddata = rproc->priv;
> + unsigned int i;
> +
> + dev_dbg(&rproc->dev, "%s: %d boxes\n",
> + __func__, ARRAY_SIZE(ddata->mb));
> +
> + for (i = 0; i < ARRAY_SIZE(ddata->mb); i++) {
> + if (ddata->mb[i].chan)
> + mbox_free_channel(ddata->mb[i].chan);
> + ddata->mb[i].chan = NULL;
> + }
> +}
> +
> +static void imx_rproc_kick(struct rproc *rproc, int vqid)
> +{
> + struct imx_rproc *ddata = rproc->priv;
> + unsigned int i;
> + int err;
> +
> + if (WARN_ON(vqid >= IMX_MBOX_NB_VQ))
> + return;
> +
> + for (i = 0; i < IMX_MBOX_NB_MBX; i++) {
> + if (vqid != ddata->mb[i].vq_id)
> + continue;
> + if (!ddata->mb[i].chan)
> + return;
> + dev_dbg(&rproc->dev, "sending message : vqid = %d\n", vqid);
> + err = mbox_send_message(ddata->mb[i].chan, &vqid);
> + if (err < 0)
> + dev_err(&rproc->dev, "%s: failed (%s, err:%d)\n",
> + __func__, ddata->mb[i].name, err);
> + return;
> + }
> +}
> +
> static const struct rproc_ops imx_rproc_ops = {
> .start = imx_rproc_start,
> .stop = imx_rproc_stop,
> .da_to_va = imx_rproc_da_to_va,
> + .kick = imx_rproc_kick,
> .get_boot_addr = rproc_elf_get_boot_addr,
> };
>
> @@ -384,14 +511,26 @@ static int imx_rproc_probe(struct platform_device *pdev)
> goto err_put_rproc;
> }
>
> + priv->workqueue = create_workqueue(dev_name(dev));
> + if (!priv->workqueue) {
> + dev_err(dev, "cannot create workqueue\n");
> + ret = -ENOMEM;
> + goto err_put_clk;
> + }
> +
> + imx_rproc_request_mbox(rproc);
> +
> ret = rproc_add(rproc);
> if (ret) {
> dev_err(dev, "rproc_add failed\n");
> - goto err_put_clk;
> + goto err_free_mb;
> }
>
> return 0;
>
> +err_free_mb:
> + imx_rproc_free_mbox(rproc);
> + destroy_workqueue(priv->workqueue);
> err_put_clk:
> clk_disable_unprepare(priv->clk);
> err_put_rproc:
> @@ -407,6 +546,7 @@ static int imx_rproc_remove(struct platform_device *pdev)
>
> clk_disable_unprepare(priv->clk);
> rproc_del(rproc);
> + imx_rproc_free_mbox(rproc);
> rproc_free(rproc);
>
> return 0;
> --
> 2.25.1
>
> Subject: [PATCH v2 0/3] remoteproc: imx_rproc: add virtio support
Have you ever see https://patchwork.kernel.org/cover/11390477/?
I have been waiting for Mathieu's rproc sync state patch, then
rebase.
Thanks,
Peng.
>
> This patch set introduces virtio support for imx7d-m4 communication:
>
> - support booting loaded vim imx-rproc firmware
> - implement .kick method support using mailbox in imx-processor
> - parse vdev0vring0, vdev0vring1, vdev0buffer memory regions required for
> virtio_rpmsg_bus initialization
>
> Regarding imx7d-m4 boot proccess
>
> Citing ARM documentation:
>
> At Reset, Cortex-M3 and Cortex-M4 processors always boot from a vector
> table at address zero.
>
> "With uninitialized memory at address zero (for example, unprogrammed
> Flash or uninitialized RAM), the processor will read a spurious initial Main
> Stack Pointer value from address zero and a spurious code entry point (Reset
> vector) from address 0x4, possibly containing an illegal instruction set state
> specifier (ESPR.T bit) in bit[0]."
>
> So to successfully boot m4 coproc we need to write Stack Pointer and
> Program counter, i see no obvious to get Stack Pointer value, so two ways
> exist ethier form a special elf section:
>
> "
> .loader :
> {
> LONG(__StackTop);
> LONG(Reset_Handler + 1);
> } > m_start
> "
>
> and put it at 0x0 address:
>
> "
> m_start (RX) : ORIGIN = 0x00000000, LENGTH =
> 0x00008000
> "
>
> Or (the way i've chosen) only put Entry Point at 0x04 and set stack as first
> instruction:
>
> "
> Reset_Handler:
> ldr sp, =__stack /* set stack pointer */
> "
>
> Regarding mailboxes and memory regions :
>
> This code is heavily derived from stm32-rproc (i.e. copy pasted) and this fact
> needs to reflected in commits, please tell me how to emphasize this fact.
>
> Attaching succesful trace booting m4 (with Add rpmsg tty driver applied) :
>
> [ 143.240616] remoteproc remoteproc0: powering up imx-rproc
> [ 143.251768] remoteproc remoteproc0: Booting fw image huginn.elf, size
> 466876 [ 143.251786] imx-rproc imx7d-cm4: iommu not present
> [ 143.251825] remoteproc remoteproc0: rsc: type 3 [ 143.251837]
> remoteproc remoteproc0: vdev rsc: id 7, dfeatures 0x1, cfg len 0, 2 vrings
> [ 143.251924] remoteproc remoteproc0: vdev rsc: vring0: da 0xffffffff, qsz
> 16, align 16 [ 143.251935] remoteproc remoteproc0: vdev rsc: vring1: da
> 0xffffffff, qsz 16, align 16 [ 143.251955] imx-rproc imx7d-cm4: map memory:
> 0x00900000+20000 [ 143.251987] imx-rproc imx7d-cm4: map memory:
> 0x00920000+2000 [ 143.252003] imx-rproc imx7d-cm4: map memory:
> 0x00922000+2000 [ 143.252020] remoteproc remoteproc0: phdr: type 1 da
> 0x20200000 memsz 0x240 filesz 0x240 [ 143.252032] remoteproc
> remoteproc0: da = 0x20200000 len = 0x240 va = 0x(ptrval) [ 143.252043]
> remoteproc remoteproc0: phdr: type 1 da 0x20200240 memsz 0x5b38 filesz
> 0x5b38 [ 143.252053] remoteproc remoteproc0: da = 0x20200240 len =
> 0x5b38 va = 0x(ptrval) [ 143.252105] remoteproc remoteproc0: phdr: type
> 1 da 0x20205d78 memsz 0x4b58 filesz 0x758 [ 143.252115] remoteproc
> remoteproc0: da = 0x20205d78 len = 0x4b58 va = 0x(ptrval) [ 143.252159]
> remoteproc remoteproc0: da = 0x200006cc len = 0x8c va = 0x(ptrval)
> [ 143.252176] remoteproc remoteproc0: Started from 0x202002f5
> [ 143.252211] imx7d-cm4#vdev0buffer: assigned reserved memory node
> vdev0buffer@00924000 [ 143.252232] virtio virtio0: reset !
> [ 143.252241] virtio virtio0: status: 1 [ 143.260567] virtio_rpmsg_bus
> virtio0: status: 3 [ 143.260598] remoteproc remoteproc0: vring0: va
> c083c000 qsz 16 notifyid 0 [ 143.260614] remoteproc remoteproc0: vring1:
> va c0872000 qsz 16 notifyid 1 [ 143.260651] virtio_rpmsg_bus virtio0:
> buffers: va c0894000, dma 0x00924000 [ 143.260666] Added buffer head 0
> to (ptrval) [ 143.260674] Added buffer head 1 to (ptrval) [ 143.260680]
> Added buffer head 2 to (ptrval) [ 143.260686] Added buffer head 3 to (ptrval)
> [ 143.260692] Added buffer head 4 to (ptrval) [ 143.260697] Added buffer
> head 5 to (ptrval) [ 143.260703] Added buffer head 6 to (ptrval)
> [ 143.260709] Added buffer head 7 to (ptrval) [ 143.260715] Added buffer
> head 8 to (ptrval) [ 143.260721] Added buffer head 9 to (ptrval)
> [ 143.260727] Added buffer head 10 to (ptrval) [ 143.260733] Added
> buffer head 11 to (ptrval) [ 143.260738] Added buffer head 12 to (ptrval)
> [ 143.260744] Added buffer head 13 to (ptrval) [ 143.260750] Added
> buffer head 14 to (ptrval) [ 143.260756] Added buffer head 15 to (ptrval)
> [ 143.260771] virtio_rpmsg_bus virtio0: status: 7 [ 143.260779]
> remoteproc remoteproc0: kicking vq index: 0 [ 143.260788] remoteproc
> remoteproc0: sending message : vqid = 0 [ 143.260802] imx_mu
> 30aa0000.mailbox: Send data on wrong channel type: 1 [ 143.260810]
> virtio_rpmsg_bus virtio0: rpmsg host is online [ 143.261680]
> imx7d-cm4#vdev0buffer: registered virtio0 (type 7) [ 143.261694]
> remoteproc remoteproc0: remote processor imx-rproc is now up
> [ 143.354880] remoteproc remoteproc0: vq index 0 is interrupted
> [ 143.354895] virtqueue callback for (ptrval) ((ptrval)) [ 143.354912]
> virtio_rpmsg_bus virtio0: From: 0x0, To: 0x35, Len: 40, Flags: 0, Reserved: 0
> [ 143.354924] rpmsg_virtio RX: 00 00 00 00 35 00 00 00 00 00 00 00 28 00
> 00 00 ....5.......(...
> [ 143.354932] rpmsg_virtio RX: 72 70 6d 73 67 2d 74 74 79 2d 72 61 77 00
> 00 00 rpmsg-tty-raw...
> [ 143.354939] rpmsg_virtio RX: 00 00 00 00 00 00 00 00 00 00 00 00 00 00
> 00 00 ................
> [ 143.354945] rpmsg_virtio RX: 00 00 00 00 00 00 00
> 00 ........
> [ 143.354956] NS announcement: 72 70 6d 73 67 2d 74 74 79 2d 72 61 77
> 00 00 00 rpmsg-tty-raw...
> [ 143.354963] NS announcement: 00 00 00 00 00 00 00 00 00 00 00 00 00
> 00 00 00 ................
> [ 143.354969] NS announcement: 00 00 00 00 00 00 00
> 00 ........
> [ 143.354980] virtio_rpmsg_bus virtio0: creating channel rpmsg-tty-raw
> addr 0x0 [ 143.356584] rpmsg_tty virtio0.rpmsg-tty-raw.-1.0: new channel:
> 0x400 -> 0x0 : ttyRPMSG0 [ 143.356651] Added buffer head 0 to (ptrval)
> [ 143.356658] No more buffers in queue [ 143.356667] virtio_rpmsg_bus
> virtio0: Received 1 messages [ 143.404302] remoteproc remoteproc0: vq
> index 0 is interrupted [ 143.404319] virtqueue callback for (ptrval) ((ptrval))
> [ 143.404337] virtio_rpmsg_bus virtio0: From: 0x1, To: 0x35, Len: 40, Flags:
> 0, Reserved: 0 [ 143.404350] rpmsg_virtio RX: 01 00 00 00 35 00 00 00 00
> 00 00 00 28 00 00 00 ....5.......(...
> [ 143.404391] rpmsg_virtio RX: 72 70 6d 73 67 2d 74 74 79 2d 72 61 77 00
> 00 00 rpmsg-tty-raw...
> [ 143.404399] rpmsg_virtio RX: 00 00 00 00 00 00 00 00 00 00 00 00 00 00
> 00 00 ................
> [ 143.404405] rpmsg_virtio RX: 01 00 00 00 00 00 00
> 00 ........
> [ 143.404417] NS announcement: 72 70 6d 73 67 2d 74 74 79 2d 72 61 77
> 00 00 00 rpmsg-tty-raw...
> [ 143.404424] NS announcement: 00 00 00 00 00 00 00 00 00 00 00 00 00
> 00 00 00 ................
> [ 143.404430] NS announcement: 01 00 00 00 00 00 00
> 00 ........
> [ 143.404441] virtio_rpmsg_bus virtio0: creating channel rpmsg-tty-raw
> addr 0x1 [ 143.411114] rpmsg_tty virtio0.rpmsg-tty-raw.-1.1: new channel:
> 0x401 -> 0x1 : ttyRPMSG1
On Tue, 14 Apr 2020 at 20:42, Peng Fan <[email protected]> wrote:
>
> > Subject: [PATCH v2 0/3] remoteproc: imx_rproc: add virtio support
>
> Have you ever see https://patchwork.kernel.org/cover/11390477/?
>
> I have been waiting for Mathieu's rproc sync state patch, then
> rebase.
I have already sent out 2 revisions of the MCU synchronisation
patchset, the latest here [1]. A new iteration should be out by the
end of the week or early next week. When that happens, I would really
appreciate it if you could take a look and provide comments.
Thanks,
Mathieu
[1].https://patchwork.kernel.org/project/linux-remoteproc/list/?series=261069
>
> Thanks,
> Peng.
>
> >
> > This patch set introduces virtio support for imx7d-m4 communication:
> >
> > - support booting loaded vim imx-rproc firmware
> > - implement .kick method support using mailbox in imx-processor
> > - parse vdev0vring0, vdev0vring1, vdev0buffer memory regions required for
> > virtio_rpmsg_bus initialization
> >
> > Regarding imx7d-m4 boot proccess
> >
> > Citing ARM documentation:
> >
> > At Reset, Cortex-M3 and Cortex-M4 processors always boot from a vector
> > table at address zero.
> >
> > "With uninitialized memory at address zero (for example, unprogrammed
> > Flash or uninitialized RAM), the processor will read a spurious initial Main
> > Stack Pointer value from address zero and a spurious code entry point (Reset
> > vector) from address 0x4, possibly containing an illegal instruction set state
> > specifier (ESPR.T bit) in bit[0]."
> >
> > So to successfully boot m4 coproc we need to write Stack Pointer and
> > Program counter, i see no obvious to get Stack Pointer value, so two ways
> > exist ethier form a special elf section:
> >
> > "
> > .loader :
> > {
> > LONG(__StackTop);
> > LONG(Reset_Handler + 1);
> > } > m_start
> > "
> >
> > and put it at 0x0 address:
> >
> > "
> > m_start (RX) : ORIGIN = 0x00000000, LENGTH =
> > 0x00008000
> > "
> >
> > Or (the way i've chosen) only put Entry Point at 0x04 and set stack as first
> > instruction:
> >
> > "
> > Reset_Handler:
> > ldr sp, =__stack /* set stack pointer */
> > "
> >
> > Regarding mailboxes and memory regions :
> >
> > This code is heavily derived from stm32-rproc (i.e. copy pasted) and this fact
> > needs to reflected in commits, please tell me how to emphasize this fact.
> >
> > Attaching succesful trace booting m4 (with Add rpmsg tty driver applied) :
> >
> > [ 143.240616] remoteproc remoteproc0: powering up imx-rproc
> > [ 143.251768] remoteproc remoteproc0: Booting fw image huginn.elf, size
> > 466876 [ 143.251786] imx-rproc imx7d-cm4: iommu not present
> > [ 143.251825] remoteproc remoteproc0: rsc: type 3 [ 143.251837]
> > remoteproc remoteproc0: vdev rsc: id 7, dfeatures 0x1, cfg len 0, 2 vrings
> > [ 143.251924] remoteproc remoteproc0: vdev rsc: vring0: da 0xffffffff, qsz
> > 16, align 16 [ 143.251935] remoteproc remoteproc0: vdev rsc: vring1: da
> > 0xffffffff, qsz 16, align 16 [ 143.251955] imx-rproc imx7d-cm4: map memory:
> > 0x00900000+20000 [ 143.251987] imx-rproc imx7d-cm4: map memory:
> > 0x00920000+2000 [ 143.252003] imx-rproc imx7d-cm4: map memory:
> > 0x00922000+2000 [ 143.252020] remoteproc remoteproc0: phdr: type 1 da
> > 0x20200000 memsz 0x240 filesz 0x240 [ 143.252032] remoteproc
> > remoteproc0: da = 0x20200000 len = 0x240 va = 0x(ptrval) [ 143.252043]
> > remoteproc remoteproc0: phdr: type 1 da 0x20200240 memsz 0x5b38 filesz
> > 0x5b38 [ 143.252053] remoteproc remoteproc0: da = 0x20200240 len =
> > 0x5b38 va = 0x(ptrval) [ 143.252105] remoteproc remoteproc0: phdr: type
> > 1 da 0x20205d78 memsz 0x4b58 filesz 0x758 [ 143.252115] remoteproc
> > remoteproc0: da = 0x20205d78 len = 0x4b58 va = 0x(ptrval) [ 143.252159]
> > remoteproc remoteproc0: da = 0x200006cc len = 0x8c va = 0x(ptrval)
> > [ 143.252176] remoteproc remoteproc0: Started from 0x202002f5
> > [ 143.252211] imx7d-cm4#vdev0buffer: assigned reserved memory node
> > vdev0buffer@00924000 [ 143.252232] virtio virtio0: reset !
> > [ 143.252241] virtio virtio0: status: 1 [ 143.260567] virtio_rpmsg_bus
> > virtio0: status: 3 [ 143.260598] remoteproc remoteproc0: vring0: va
> > c083c000 qsz 16 notifyid 0 [ 143.260614] remoteproc remoteproc0: vring1:
> > va c0872000 qsz 16 notifyid 1 [ 143.260651] virtio_rpmsg_bus virtio0:
> > buffers: va c0894000, dma 0x00924000 [ 143.260666] Added buffer head 0
> > to (ptrval) [ 143.260674] Added buffer head 1 to (ptrval) [ 143.260680]
> > Added buffer head 2 to (ptrval) [ 143.260686] Added buffer head 3 to (ptrval)
> > [ 143.260692] Added buffer head 4 to (ptrval) [ 143.260697] Added buffer
> > head 5 to (ptrval) [ 143.260703] Added buffer head 6 to (ptrval)
> > [ 143.260709] Added buffer head 7 to (ptrval) [ 143.260715] Added buffer
> > head 8 to (ptrval) [ 143.260721] Added buffer head 9 to (ptrval)
> > [ 143.260727] Added buffer head 10 to (ptrval) [ 143.260733] Added
> > buffer head 11 to (ptrval) [ 143.260738] Added buffer head 12 to (ptrval)
> > [ 143.260744] Added buffer head 13 to (ptrval) [ 143.260750] Added
> > buffer head 14 to (ptrval) [ 143.260756] Added buffer head 15 to (ptrval)
> > [ 143.260771] virtio_rpmsg_bus virtio0: status: 7 [ 143.260779]
> > remoteproc remoteproc0: kicking vq index: 0 [ 143.260788] remoteproc
> > remoteproc0: sending message : vqid = 0 [ 143.260802] imx_mu
> > 30aa0000.mailbox: Send data on wrong channel type: 1 [ 143.260810]
> > virtio_rpmsg_bus virtio0: rpmsg host is online [ 143.261680]
> > imx7d-cm4#vdev0buffer: registered virtio0 (type 7) [ 143.261694]
> > remoteproc remoteproc0: remote processor imx-rproc is now up
> > [ 143.354880] remoteproc remoteproc0: vq index 0 is interrupted
> > [ 143.354895] virtqueue callback for (ptrval) ((ptrval)) [ 143.354912]
> > virtio_rpmsg_bus virtio0: From: 0x0, To: 0x35, Len: 40, Flags: 0, Reserved: 0
> > [ 143.354924] rpmsg_virtio RX: 00 00 00 00 35 00 00 00 00 00 00 00 28 00
> > 00 00 ....5.......(...
> > [ 143.354932] rpmsg_virtio RX: 72 70 6d 73 67 2d 74 74 79 2d 72 61 77 00
> > 00 00 rpmsg-tty-raw...
> > [ 143.354939] rpmsg_virtio RX: 00 00 00 00 00 00 00 00 00 00 00 00 00 00
> > 00 00 ................
> > [ 143.354945] rpmsg_virtio RX: 00 00 00 00 00 00 00
> > 00 ........
> > [ 143.354956] NS announcement: 72 70 6d 73 67 2d 74 74 79 2d 72 61 77
> > 00 00 00 rpmsg-tty-raw...
> > [ 143.354963] NS announcement: 00 00 00 00 00 00 00 00 00 00 00 00 00
> > 00 00 00 ................
> > [ 143.354969] NS announcement: 00 00 00 00 00 00 00
> > 00 ........
> > [ 143.354980] virtio_rpmsg_bus virtio0: creating channel rpmsg-tty-raw
> > addr 0x0 [ 143.356584] rpmsg_tty virtio0.rpmsg-tty-raw.-1.0: new channel:
> > 0x400 -> 0x0 : ttyRPMSG0 [ 143.356651] Added buffer head 0 to (ptrval)
> > [ 143.356658] No more buffers in queue [ 143.356667] virtio_rpmsg_bus
> > virtio0: Received 1 messages [ 143.404302] remoteproc remoteproc0: vq
> > index 0 is interrupted [ 143.404319] virtqueue callback for (ptrval) ((ptrval))
> > [ 143.404337] virtio_rpmsg_bus virtio0: From: 0x1, To: 0x35, Len: 40, Flags:
> > 0, Reserved: 0 [ 143.404350] rpmsg_virtio RX: 01 00 00 00 35 00 00 00 00
> > 00 00 00 28 00 00 00 ....5.......(...
> > [ 143.404391] rpmsg_virtio RX: 72 70 6d 73 67 2d 74 74 79 2d 72 61 77 00
> > 00 00 rpmsg-tty-raw...
> > [ 143.404399] rpmsg_virtio RX: 00 00 00 00 00 00 00 00 00 00 00 00 00 00
> > 00 00 ................
> > [ 143.404405] rpmsg_virtio RX: 01 00 00 00 00 00 00
> > 00 ........
> > [ 143.404417] NS announcement: 72 70 6d 73 67 2d 74 74 79 2d 72 61 77
> > 00 00 00 rpmsg-tty-raw...
> > [ 143.404424] NS announcement: 00 00 00 00 00 00 00 00 00 00 00 00 00
> > 00 00 00 ................
> > [ 143.404430] NS announcement: 01 00 00 00 00 00 00
> > 00 ........
> > [ 143.404441] virtio_rpmsg_bus virtio0: creating channel rpmsg-tty-raw
> > addr 0x1 [ 143.411114] rpmsg_tty virtio0.rpmsg-tty-raw.-1.1: new channel:
> > 0x401 -> 0x1 : ttyRPMSG1
>
> _______________________________________________
> linux-arm-kernel mailing list
> [email protected]
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
On Tue, 14 Apr 2020 11:20:05 -0600
Mathieu Poirier <[email protected]> wrote:
> On Mon, Apr 06, 2020 at 02:33:09PM +0300, [email protected]
> wrote:
> > Add support for mailboxes to imx_rproc
> >
> > Signed-off-by: Nikita Shubin <[email protected]>
> > ---
> > drivers/remoteproc/Kconfig | 2 +
> > drivers/remoteproc/imx_rproc.c | 142
> > ++++++++++++++++++++++++++++++++- 2 files changed, 143
> > insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig
> > index 94afdde4bc9f..02d23a54c9cf 100644
> > --- a/drivers/remoteproc/Kconfig
> > +++ b/drivers/remoteproc/Kconfig
> > @@ -17,6 +17,8 @@ if REMOTEPROC
> > config IMX_REMOTEPROC
> > tristate "IMX6/7 remoteproc support"
> > depends on ARCH_MXC
> > + select MAILBOX
> > + select IMX_MBOX
> > help
> > Say y here to support iMX's remote processors (Cortex M4
> > on iMX7D) via the remote processor framework.
> > diff --git a/drivers/remoteproc/imx_rproc.c
> > b/drivers/remoteproc/imx_rproc.c index bebc58d0f711..d2bede4ccb70
> > 100644 --- a/drivers/remoteproc/imx_rproc.c
> > +++ b/drivers/remoteproc/imx_rproc.c
> > @@ -14,6 +14,9 @@
> > #include <linux/platform_device.h>
> > #include <linux/regmap.h>
> > #include <linux/remoteproc.h>
> > +#include <linux/mailbox_client.h>
> > +
> > +#include "remoteproc_internal.h"
> >
> > #define IMX7D_SRC_SCR 0x0C
> > #define IMX7D_ENABLE_M4 BIT(3)
> > @@ -47,6 +50,12 @@
> >
> > #define IMX_BOOT_PC 0x4
> >
> > +#define IMX_MBOX_NB_VQ 2
> > +#define IMX_MBOX_NB_MBX 2
>
> Please align this.
>
> > +
> > +#define IMX_MBX_VQ0 "vq0"
> > +#define IMX_MBX_VQ1 "vq1"
> > +
> > /**
> > * struct imx_rproc_mem - slim internal memory structure
> > * @cpu_addr: MPU virtual address of the memory region
> > @@ -80,6 +89,14 @@ struct imx_rproc_dcfg {
> > size_t att_size;
> > };
> >
> > +struct imx_mbox {
> > + const unsigned char name[10];
> > + struct mbox_chan *chan;
> > + struct mbox_client client;
> > + struct work_struct vq_work;
> > + int vq_id;
> > +};
> > +
> > struct imx_rproc {
> > struct device *dev;
> > struct regmap *regmap;
> > @@ -88,6 +105,8 @@ struct imx_rproc {
> > struct imx_rproc_mem
> > mem[IMX7D_RPROC_MEM_MAX]; struct clk *clk;
> > void __iomem *bootreg;
> > + struct imx_mbox mb[IMX_MBOX_NB_MBX];
> > + struct workqueue_struct *workqueue;
> > };
> >
> > static const struct imx_rproc_att imx_rproc_att_imx7d[] = {
> > @@ -251,10 +270,118 @@ static void *imx_rproc_da_to_va(struct rproc
> > *rproc, u64 da, int len) return va;
> > }
> >
> > +static void imx_rproc_mb_vq_work(struct work_struct *work)
> > +{
> > + struct imx_mbox *mb = container_of(work, struct imx_mbox,
> > vq_work);
> > + struct rproc *rproc = dev_get_drvdata(mb->client.dev);
> > +
> > + if (rproc_vq_interrupt(rproc, mb->vq_id) == IRQ_NONE)
> > + dev_dbg(&rproc->dev, "no message found in vq%d\n",
> > mb->vq_id); +}
> > +
> > +static void imx_rproc_mb_callback(struct mbox_client *cl, void
> > *data) +{
> > + struct rproc *rproc = dev_get_drvdata(cl->dev);
> > + struct imx_mbox *mb = container_of(cl, struct imx_mbox,
> > client);
> > + struct imx_rproc *ddata = rproc->priv;
> > +
> > + queue_work(ddata->workqueue, &mb->vq_work);
> > +}
> > +
> > +static const struct imx_mbox imx_rproc_mbox[IMX_MBOX_NB_MBX] = {
> > + {
> > + .name = IMX_MBX_VQ0,
> > + .vq_id = 0,
> > + .client = {
> > + .rx_callback = imx_rproc_mb_callback,
> > + .tx_block = false,
> > + },
> > + },
> > + {
> > + .name = IMX_MBX_VQ1,
> > + .vq_id = 1,
> > + .client = {
> > + .rx_callback = imx_rproc_mb_callback,
> > + .tx_block = false,
> > + },
> > + },
> > +};
> > +
> > +static void imx_rproc_request_mbox(struct rproc *rproc)
> > +{
> > + struct imx_rproc *ddata = rproc->priv;
> > + struct device *dev = &rproc->dev;
> > + unsigned int i;
> > + const unsigned char *name;
> > + struct mbox_client *cl;
> > +
> > + /* Initialise mailbox structure table */
> > + memcpy(ddata->mb, imx_rproc_mbox, sizeof(imx_rproc_mbox));
> > +
> > + for (i = 0; i < IMX_MBOX_NB_MBX; i++) {
> > + name = ddata->mb[i].name;
> > +
> > + cl = &ddata->mb[i].client;
> > + cl->dev = dev->parent;
> > +
> > + ddata->mb[i].chan =
> > mbox_request_channel_byname(cl, name); +
> > + dev_dbg(dev, "%s: name=%s, idx=%u\n",
> > + __func__, name, ddata->mb[i].vq_id);
> > +
> > + if (IS_ERR(ddata->mb[i].chan)) {
> > + dev_warn(dev, "cannot get %s mbox\n",
> > name);
> > + ddata->mb[i].chan = NULL;
>
> If the mailbox isn't ready this driver will fail without a chance of
> recovery. Since most of the code in this patch is a carbon copy of
> the implementation found in stm32_proc.c, I suggest you do the same
> as they did in stm32_rproc_request_mbox() and privision for cases
> where requesting a channel returns -EPROBE_DEFER.
>
Noted, will be fixed.
> > + }
> > +
> > + if (ddata->mb[i].vq_id >= 0)
> > + INIT_WORK(&ddata->mb[i].vq_work,
> > imx_rproc_mb_vq_work);
> > + }
> > +}
> > +
> > +static void imx_rproc_free_mbox(struct rproc *rproc)
> > +{
> > + struct imx_rproc *ddata = rproc->priv;
> > + unsigned int i;
> > +
> > + dev_dbg(&rproc->dev, "%s: %d boxes\n",
> > + __func__, ARRAY_SIZE(ddata->mb));
> > +
> > + for (i = 0; i < ARRAY_SIZE(ddata->mb); i++) {
> > + if (ddata->mb[i].chan)
> > + mbox_free_channel(ddata->mb[i].chan);
> > + ddata->mb[i].chan = NULL;
> > + }
> > +}
> > +
> > +static void imx_rproc_kick(struct rproc *rproc, int vqid)
> > +{
> > + struct imx_rproc *ddata = rproc->priv;
> > + unsigned int i;
> > + int err;
> > +
> > + if (WARN_ON(vqid >= IMX_MBOX_NB_VQ))
> > + return;
> > +
> > + for (i = 0; i < IMX_MBOX_NB_MBX; i++) {
> > + if (vqid != ddata->mb[i].vq_id)
> > + continue;
> > + if (!ddata->mb[i].chan)
> > + return;
> > + dev_dbg(&rproc->dev, "sending message : vqid =
> > %d\n", vqid);
> > + err = mbox_send_message(ddata->mb[i].chan, &vqid);
> > + if (err < 0)
> > + dev_err(&rproc->dev, "%s: failed (%s,
> > err:%d)\n",
> > + __func__,
> > ddata->mb[i].name, err);
> > + return;
> > + }
> > +}
> > +
> > static const struct rproc_ops imx_rproc_ops = {
> > .start = imx_rproc_start,
> > .stop = imx_rproc_stop,
> > .da_to_va = imx_rproc_da_to_va,
> > + .kick = imx_rproc_kick,
> > .get_boot_addr = rproc_elf_get_boot_addr,
> > };
> >
> > @@ -384,14 +511,26 @@ static int imx_rproc_probe(struct
> > platform_device *pdev) goto err_put_rproc;
> > }
> >
> > + priv->workqueue = create_workqueue(dev_name(dev));
> > + if (!priv->workqueue) {
> > + dev_err(dev, "cannot create workqueue\n");
> > + ret = -ENOMEM;
> > + goto err_put_clk;
> > + }
> > +
> > + imx_rproc_request_mbox(rproc);
> > +
> > ret = rproc_add(rproc);
> > if (ret) {
> > dev_err(dev, "rproc_add failed\n");
> > - goto err_put_clk;
> > + goto err_free_mb;
> > }
> >
> > return 0;
> >
> > +err_free_mb:
> > + imx_rproc_free_mbox(rproc);
> > + destroy_workqueue(priv->workqueue);
> > err_put_clk:
> > clk_disable_unprepare(priv->clk);
> > err_put_rproc:
> > @@ -407,6 +546,7 @@ static int imx_rproc_remove(struct
> > platform_device *pdev)
> > clk_disable_unprepare(priv->clk);
> > rproc_del(rproc);
> > + imx_rproc_free_mbox(rproc);
>
> I have no issues with people reusing code already found in the kernel
> - in fact I encourage it because it makes reviewing patches much
> easier. On the flip side you have to give credit where it is due.
> Here adding a line in the changelog that mentions where you took your
> inspiration from will be much appreciated.
Please don't blame on things i never did citing my own self from 0/0:
| Regarding mailboxes and memory regions :
| This code is heavily derived from stm32-rproc (i.e. copy pasted) and
| this fact needs to reflected in commits, please tell me how to
| emphasize this fact.
I am eager to give credits.
>
> Thanks,
> Mathieu
>
> > rproc_free(rproc);
> >
> > return 0;
> > --
> > 2.25.1
> >
On Wed, 15 Apr 2020 02:42:32 +0000
Peng Fan <[email protected]> wrote:
> > Subject: [PATCH v2 0/3] remoteproc: imx_rproc: add virtio support
>
> Have you ever see https://patchwork.kernel.org/cover/11390477/?
>
I don't see anything that allows booting imx7-m4 from A7 In case elf
file interrupt vector is not supposed to be at OCRAM_S, am i missing
something?
I not interested in booting A7 from M4, i interested in wise versa
scenario.
> I have been waiting for Mathieu's rproc sync state patch, then
> rebase.
>
> Thanks,
> Peng.
>
> >
> > This patch set introduces virtio support for imx7d-m4 communication:
> >
> > - support booting loaded vim imx-rproc firmware
> > - implement .kick method support using mailbox in imx-processor
> > - parse vdev0vring0, vdev0vring1, vdev0buffer memory regions
> > required for virtio_rpmsg_bus initialization
> >
> > Regarding imx7d-m4 boot proccess
> >
> > Citing ARM documentation:
> >
> > At Reset, Cortex-M3 and Cortex-M4 processors always boot from a
> > vector table at address zero.
> >
> > "With uninitialized memory at address zero (for example,
> > unprogrammed Flash or uninitialized RAM), the processor will read a
> > spurious initial Main Stack Pointer value from address zero and a
> > spurious code entry point (Reset vector) from address 0x4, possibly
> > containing an illegal instruction set state specifier (ESPR.T bit)
> > in bit[0]."
> >
> > So to successfully boot m4 coproc we need to write Stack Pointer and
> > Program counter, i see no obvious to get Stack Pointer value, so
> > two ways exist ethier form a special elf section:
> >
> > "
> > .loader :
> > {
> > LONG(__StackTop);
> > LONG(Reset_Handler + 1);
> > } > m_start
> > "
> >
> > and put it at 0x0 address:
> >
> > "
> > m_start (RX) : ORIGIN = 0x00000000, LENGTH =
> > 0x00008000
> > "
> >
> > Or (the way i've chosen) only put Entry Point at 0x04 and set stack
> > as first instruction:
> >
> > "
> > Reset_Handler:
> > ldr sp, =__stack /* set stack pointer */
> > "
> >
> > Regarding mailboxes and memory regions :
> >
> > This code is heavily derived from stm32-rproc (i.e. copy pasted)
> > and this fact needs to reflected in commits, please tell me how to
> > emphasize this fact.
> >
> > Attaching succesful trace booting m4 (with Add rpmsg tty driver
> > applied) :
> >
> > [ 143.240616] remoteproc remoteproc0: powering up imx-rproc
> > [ 143.251768] remoteproc remoteproc0: Booting fw image huginn.elf,
> > size 466876 [ 143.251786] imx-rproc imx7d-cm4: iommu not present
> > [ 143.251825] remoteproc remoteproc0: rsc: type 3 [ 143.251837]
> > remoteproc remoteproc0: vdev rsc: id 7, dfeatures 0x1, cfg len 0, 2
> > vrings [ 143.251924] remoteproc remoteproc0: vdev rsc: vring0: da
> > 0xffffffff, qsz 16, align 16 [ 143.251935] remoteproc remoteproc0:
> > vdev rsc: vring1: da 0xffffffff, qsz 16, align 16 [ 143.251955]
> > imx-rproc imx7d-cm4: map memory: 0x00900000+20000 [ 143.251987]
> > imx-rproc imx7d-cm4: map memory: 0x00920000+2000 [ 143.252003]
> > imx-rproc imx7d-cm4: map memory: 0x00922000+2000 [ 143.252020]
> > remoteproc remoteproc0: phdr: type 1 da 0x20200000 memsz 0x240
> > filesz 0x240 [ 143.252032] remoteproc remoteproc0: da = 0x20200000
> > len = 0x240 va = 0x(ptrval) [ 143.252043] remoteproc remoteproc0:
> > phdr: type 1 da 0x20200240 memsz 0x5b38 filesz 0x5b38 [
> > 143.252053] remoteproc remoteproc0: da = 0x20200240 len = 0x5b38 va
> > = 0x(ptrval) [ 143.252105] remoteproc remoteproc0: phdr: type 1 da
> > 0x20205d78 memsz 0x4b58 filesz 0x758 [ 143.252115] remoteproc
> > remoteproc0: da = 0x20205d78 len = 0x4b58 va = 0x(ptrval) [
> > 143.252159] remoteproc remoteproc0: da = 0x200006cc len = 0x8c va =
> > 0x(ptrval) [ 143.252176] remoteproc remoteproc0: Started from
> > 0x202002f5 [ 143.252211] imx7d-cm4#vdev0buffer: assigned reserved
> > memory node vdev0buffer@00924000 [ 143.252232] virtio virtio0:
> > reset ! [ 143.252241] virtio virtio0: status: 1 [ 143.260567]
> > virtio_rpmsg_bus virtio0: status: 3 [ 143.260598] remoteproc
> > remoteproc0: vring0: va c083c000 qsz 16 notifyid 0 [ 143.260614]
> > remoteproc remoteproc0: vring1: va c0872000 qsz 16 notifyid 1 [
> > 143.260651] virtio_rpmsg_bus virtio0: buffers: va c0894000, dma
> > 0x00924000 [ 143.260666] Added buffer head 0 to (ptrval) [
> > 143.260674] Added buffer head 1 to (ptrval) [ 143.260680] Added
> > buffer head 2 to (ptrval) [ 143.260686] Added buffer head 3 to
> > (ptrval) [ 143.260692] Added buffer head 4 to (ptrval) [
> > 143.260697] Added buffer head 5 to (ptrval) [ 143.260703] Added
> > buffer head 6 to (ptrval) [ 143.260709] Added buffer head 7 to
> > (ptrval) [ 143.260715] Added buffer head 8 to (ptrval) [
> > 143.260721] Added buffer head 9 to (ptrval) [ 143.260727] Added
> > buffer head 10 to (ptrval) [ 143.260733] Added buffer head 11 to
> > (ptrval) [ 143.260738] Added buffer head 12 to (ptrval) [
> > 143.260744] Added buffer head 13 to (ptrval) [ 143.260750] Added
> > buffer head 14 to (ptrval) [ 143.260756] Added buffer head 15 to
> > (ptrval) [ 143.260771] virtio_rpmsg_bus virtio0: status: 7 [
> > 143.260779] remoteproc remoteproc0: kicking vq index: 0 [
> > 143.260788] remoteproc remoteproc0: sending message : vqid = 0 [
> > 143.260802] imx_mu 30aa0000.mailbox: Send data on wrong channel
> > type: 1 [ 143.260810] virtio_rpmsg_bus virtio0: rpmsg host is
> > online [ 143.261680] imx7d-cm4#vdev0buffer: registered virtio0
> > (type 7) [ 143.261694] remoteproc remoteproc0: remote processor
> > imx-rproc is now up [ 143.354880] remoteproc remoteproc0: vq index
> > 0 is interrupted [ 143.354895] virtqueue callback for (ptrval)
> > ((ptrval)) [ 143.354912] virtio_rpmsg_bus virtio0: From: 0x0, To:
> > 0x35, Len: 40, Flags: 0, Reserved: 0 [ 143.354924] rpmsg_virtio
> > RX: 00 00 00 00 35 00 00 00 00 00 00 00 28 00 00 00
> > ....5.......(... [ 143.354932] rpmsg_virtio RX: 72 70 6d 73 67 2d
> > 74 74 79 2d 72 61 77 00 00 00 rpmsg-tty-raw... [ 143.354939]
> > rpmsg_virtio RX: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
> > ................ [ 143.354945] rpmsg_virtio RX: 00 00 00 00 00 00
> > 00 00 ........ [ 143.354956] NS
> > announcement: 72 70 6d 73 67 2d 74 74 79 2d 72 61 77 00 00 00
> > rpmsg-tty-raw... [ 143.354963] NS announcement: 00 00 00 00 00 00
> > 00 00 00 00 00 00 00 00 00 00 ................ [ 143.354969] NS
> > announcement: 00 00 00 00 00 00 00 00
> > ........ [ 143.354980] virtio_rpmsg_bus virtio0: creating channel
> > rpmsg-tty-raw addr 0x0 [ 143.356584] rpmsg_tty
> > virtio0.rpmsg-tty-raw.-1.0: new channel: 0x400 -> 0x0 : ttyRPMSG0 [
> > 143.356651] Added buffer head 0 to (ptrval) [ 143.356658] No more
> > buffers in queue [ 143.356667] virtio_rpmsg_bus virtio0: Received
> > 1 messages [ 143.404302] remoteproc remoteproc0: vq index 0 is
> > interrupted [ 143.404319] virtqueue callback for (ptrval)
> > ((ptrval)) [ 143.404337] virtio_rpmsg_bus virtio0: From: 0x1, To:
> > 0x35, Len: 40, Flags: 0, Reserved: 0 [ 143.404350] rpmsg_virtio
> > RX: 01 00 00 00 35 00 00 00 00 00 00 00 28 00 00 00
> > ....5.......(... [ 143.404391] rpmsg_virtio RX: 72 70 6d 73 67 2d
> > 74 74 79 2d 72 61 77 00 00 00 rpmsg-tty-raw... [ 143.404399]
> > rpmsg_virtio RX: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
> > ................ [ 143.404405] rpmsg_virtio RX: 01 00 00 00 00 00
> > 00 00 ........
> > [ 143.404417] NS announcement: 72 70 6d 73 67 2d 74 74 79 2d 72 61
> > 77 00 00 00 rpmsg-tty-raw...
> > [ 143.404424] NS announcement: 00 00 00 00 00 00 00 00 00 00 00 00
> > 00 00 00 00 ................
> > [ 143.404430] NS announcement: 01 00 00 00 00 00 00
> > 00 ........
> > [ 143.404441] virtio_rpmsg_bus virtio0: creating channel
> > rpmsg-tty-raw addr 0x1 [ 143.411114] rpmsg_tty
> > virtio0.rpmsg-tty-raw.-1.1: new channel: 0x401 -> 0x1 : ttyRPMSG1
On Fri, 17 Apr 2020 at 02:38, Nikita Shubin <[email protected]> wrote:
>
> On Tue, 14 Apr 2020 11:20:05 -0600
> Mathieu Poirier <[email protected]> wrote:
>
> > On Mon, Apr 06, 2020 at 02:33:09PM +0300, [email protected]
> > wrote:
> > > Add support for mailboxes to imx_rproc
> > >
> > > Signed-off-by: Nikita Shubin <[email protected]>
> > > ---
> > > drivers/remoteproc/Kconfig | 2 +
> > > drivers/remoteproc/imx_rproc.c | 142
> > > ++++++++++++++++++++++++++++++++- 2 files changed, 143
> > > insertions(+), 1 deletion(-)
> > >
> > > diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig
> > > index 94afdde4bc9f..02d23a54c9cf 100644
> > > --- a/drivers/remoteproc/Kconfig
> > > +++ b/drivers/remoteproc/Kconfig
> > > @@ -17,6 +17,8 @@ if REMOTEPROC
> > > config IMX_REMOTEPROC
> > > tristate "IMX6/7 remoteproc support"
> > > depends on ARCH_MXC
> > > + select MAILBOX
> > > + select IMX_MBOX
> > > help
> > > Say y here to support iMX's remote processors (Cortex M4
> > > on iMX7D) via the remote processor framework.
> > > diff --git a/drivers/remoteproc/imx_rproc.c
> > > b/drivers/remoteproc/imx_rproc.c index bebc58d0f711..d2bede4ccb70
> > > 100644 --- a/drivers/remoteproc/imx_rproc.c
> > > +++ b/drivers/remoteproc/imx_rproc.c
> > > @@ -14,6 +14,9 @@
> > > #include <linux/platform_device.h>
> > > #include <linux/regmap.h>
> > > #include <linux/remoteproc.h>
> > > +#include <linux/mailbox_client.h>
> > > +
> > > +#include "remoteproc_internal.h"
> > >
> > > #define IMX7D_SRC_SCR 0x0C
> > > #define IMX7D_ENABLE_M4 BIT(3)
> > > @@ -47,6 +50,12 @@
> > >
> > > #define IMX_BOOT_PC 0x4
> > >
> > > +#define IMX_MBOX_NB_VQ 2
> > > +#define IMX_MBOX_NB_MBX 2
> >
> > Please align this.
> >
> > > +
> > > +#define IMX_MBX_VQ0 "vq0"
> > > +#define IMX_MBX_VQ1 "vq1"
> > > +
> > > /**
> > > * struct imx_rproc_mem - slim internal memory structure
> > > * @cpu_addr: MPU virtual address of the memory region
> > > @@ -80,6 +89,14 @@ struct imx_rproc_dcfg {
> > > size_t att_size;
> > > };
> > >
> > > +struct imx_mbox {
> > > + const unsigned char name[10];
> > > + struct mbox_chan *chan;
> > > + struct mbox_client client;
> > > + struct work_struct vq_work;
> > > + int vq_id;
> > > +};
> > > +
> > > struct imx_rproc {
> > > struct device *dev;
> > > struct regmap *regmap;
> > > @@ -88,6 +105,8 @@ struct imx_rproc {
> > > struct imx_rproc_mem
> > > mem[IMX7D_RPROC_MEM_MAX]; struct clk *clk;
> > > void __iomem *bootreg;
> > > + struct imx_mbox mb[IMX_MBOX_NB_MBX];
> > > + struct workqueue_struct *workqueue;
> > > };
> > >
> > > static const struct imx_rproc_att imx_rproc_att_imx7d[] = {
> > > @@ -251,10 +270,118 @@ static void *imx_rproc_da_to_va(struct rproc
> > > *rproc, u64 da, int len) return va;
> > > }
> > >
> > > +static void imx_rproc_mb_vq_work(struct work_struct *work)
> > > +{
> > > + struct imx_mbox *mb = container_of(work, struct imx_mbox,
> > > vq_work);
> > > + struct rproc *rproc = dev_get_drvdata(mb->client.dev);
> > > +
> > > + if (rproc_vq_interrupt(rproc, mb->vq_id) == IRQ_NONE)
> > > + dev_dbg(&rproc->dev, "no message found in vq%d\n",
> > > mb->vq_id); +}
> > > +
> > > +static void imx_rproc_mb_callback(struct mbox_client *cl, void
> > > *data) +{
> > > + struct rproc *rproc = dev_get_drvdata(cl->dev);
> > > + struct imx_mbox *mb = container_of(cl, struct imx_mbox,
> > > client);
> > > + struct imx_rproc *ddata = rproc->priv;
> > > +
> > > + queue_work(ddata->workqueue, &mb->vq_work);
> > > +}
> > > +
> > > +static const struct imx_mbox imx_rproc_mbox[IMX_MBOX_NB_MBX] = {
> > > + {
> > > + .name = IMX_MBX_VQ0,
> > > + .vq_id = 0,
> > > + .client = {
> > > + .rx_callback = imx_rproc_mb_callback,
> > > + .tx_block = false,
> > > + },
> > > + },
> > > + {
> > > + .name = IMX_MBX_VQ1,
> > > + .vq_id = 1,
> > > + .client = {
> > > + .rx_callback = imx_rproc_mb_callback,
> > > + .tx_block = false,
> > > + },
> > > + },
> > > +};
> > > +
> > > +static void imx_rproc_request_mbox(struct rproc *rproc)
> > > +{
> > > + struct imx_rproc *ddata = rproc->priv;
> > > + struct device *dev = &rproc->dev;
> > > + unsigned int i;
> > > + const unsigned char *name;
> > > + struct mbox_client *cl;
> > > +
> > > + /* Initialise mailbox structure table */
> > > + memcpy(ddata->mb, imx_rproc_mbox, sizeof(imx_rproc_mbox));
> > > +
> > > + for (i = 0; i < IMX_MBOX_NB_MBX; i++) {
> > > + name = ddata->mb[i].name;
> > > +
> > > + cl = &ddata->mb[i].client;
> > > + cl->dev = dev->parent;
> > > +
> > > + ddata->mb[i].chan =
> > > mbox_request_channel_byname(cl, name); +
> > > + dev_dbg(dev, "%s: name=%s, idx=%u\n",
> > > + __func__, name, ddata->mb[i].vq_id);
> > > +
> > > + if (IS_ERR(ddata->mb[i].chan)) {
> > > + dev_warn(dev, "cannot get %s mbox\n",
> > > name);
> > > + ddata->mb[i].chan = NULL;
> >
> > If the mailbox isn't ready this driver will fail without a chance of
> > recovery. Since most of the code in this patch is a carbon copy of
> > the implementation found in stm32_proc.c, I suggest you do the same
> > as they did in stm32_rproc_request_mbox() and privision for cases
> > where requesting a channel returns -EPROBE_DEFER.
> >
>
> Noted, will be fixed.
>
> > > + }
> > > +
> > > + if (ddata->mb[i].vq_id >= 0)
> > > + INIT_WORK(&ddata->mb[i].vq_work,
> > > imx_rproc_mb_vq_work);
> > > + }
> > > +}
> > > +
> > > +static void imx_rproc_free_mbox(struct rproc *rproc)
> > > +{
> > > + struct imx_rproc *ddata = rproc->priv;
> > > + unsigned int i;
> > > +
> > > + dev_dbg(&rproc->dev, "%s: %d boxes\n",
> > > + __func__, ARRAY_SIZE(ddata->mb));
> > > +
> > > + for (i = 0; i < ARRAY_SIZE(ddata->mb); i++) {
> > > + if (ddata->mb[i].chan)
> > > + mbox_free_channel(ddata->mb[i].chan);
> > > + ddata->mb[i].chan = NULL;
> > > + }
> > > +}
> > > +
> > > +static void imx_rproc_kick(struct rproc *rproc, int vqid)
> > > +{
> > > + struct imx_rproc *ddata = rproc->priv;
> > > + unsigned int i;
> > > + int err;
> > > +
> > > + if (WARN_ON(vqid >= IMX_MBOX_NB_VQ))
> > > + return;
> > > +
> > > + for (i = 0; i < IMX_MBOX_NB_MBX; i++) {
> > > + if (vqid != ddata->mb[i].vq_id)
> > > + continue;
> > > + if (!ddata->mb[i].chan)
> > > + return;
> > > + dev_dbg(&rproc->dev, "sending message : vqid =
> > > %d\n", vqid);
> > > + err = mbox_send_message(ddata->mb[i].chan, &vqid);
> > > + if (err < 0)
> > > + dev_err(&rproc->dev, "%s: failed (%s,
> > > err:%d)\n",
> > > + __func__,
> > > ddata->mb[i].name, err);
> > > + return;
> > > + }
> > > +}
> > > +
> > > static const struct rproc_ops imx_rproc_ops = {
> > > .start = imx_rproc_start,
> > > .stop = imx_rproc_stop,
> > > .da_to_va = imx_rproc_da_to_va,
> > > + .kick = imx_rproc_kick,
> > > .get_boot_addr = rproc_elf_get_boot_addr,
> > > };
> > >
> > > @@ -384,14 +511,26 @@ static int imx_rproc_probe(struct
> > > platform_device *pdev) goto err_put_rproc;
> > > }
> > >
> > > + priv->workqueue = create_workqueue(dev_name(dev));
> > > + if (!priv->workqueue) {
> > > + dev_err(dev, "cannot create workqueue\n");
> > > + ret = -ENOMEM;
> > > + goto err_put_clk;
> > > + }
> > > +
> > > + imx_rproc_request_mbox(rproc);
> > > +
> > > ret = rproc_add(rproc);
> > > if (ret) {
> > > dev_err(dev, "rproc_add failed\n");
> > > - goto err_put_clk;
> > > + goto err_free_mb;
> > > }
> > >
> > > return 0;
> > >
> > > +err_free_mb:
> > > + imx_rproc_free_mbox(rproc);
> > > + destroy_workqueue(priv->workqueue);
> > > err_put_clk:
> > > clk_disable_unprepare(priv->clk);
> > > err_put_rproc:
> > > @@ -407,6 +546,7 @@ static int imx_rproc_remove(struct
> > > platform_device *pdev)
> > > clk_disable_unprepare(priv->clk);
> > > rproc_del(rproc);
> > > + imx_rproc_free_mbox(rproc);
> >
> > I have no issues with people reusing code already found in the kernel
> > - in fact I encourage it because it makes reviewing patches much
> > easier. On the flip side you have to give credit where it is due.
> > Here adding a line in the changelog that mentions where you took your
> > inspiration from will be much appreciated.
>
> Please don't blame on things i never did citing my own self from 0/0:
I am not blaming you at all.
>
> | Regarding mailboxes and memory regions :
>
> | This code is heavily derived from stm32-rproc (i.e. copy pasted) and
> | this fact needs to reflected in commits, please tell me how to
> | emphasize this fact.
>
> I am eager to give credits.
I didn't notice that in the original cover letter. In the changelog,
between the description of the work and the signed-off-by and on a
line on its own, simply write that "the work is inspired from the
STM32 platform driver (drivers/remoteproc/stm32_rproc.c)".
>
>
> >
> > Thanks,
> > Mathieu
> >
> > > rproc_free(rproc);
> > >
> > > return 0;
> > > --
> > > 2.25.1
> > >
>