* [PATCH v3] remoteproc/mediatek: read IPI buffer offset from FW
@ 2020-11-30 3:40 ` Tzung-Bi Shih
0 siblings, 0 replies; 6+ messages in thread
From: Tzung-Bi Shih @ 2020-11-30 3:40 UTC (permalink / raw)
To: ohad, bjorn.andersson
Cc: linux-remoteproc, matthias.bgg, linux-mediatek, linux-arm-kernel,
pihsun, mathieu.poirier, tzungbi, erin.lo
Reads the IPI buffer offset from the FW binary. The information resides
in addr of .ipi_buffer section.
Moves scp_ipi_init() to scp_load() phase. The IPI buffer can be
initialized only if the offset is clear.
To backward compatible to MT8183 SCP, specify the offset in the board
specific mtk_scp_of_data. Reads the default offset if the firmware
doesn't have it.
Signed-off-by: Tzung-Bi Shih <tzungbi@google.com>
---
Previous discussion:
https://patchwork.kernel.org/project/linux-remoteproc/patch/20201127092941.1646260-1-tzungbi@google.com/
Changes from v2:
- to backward-compatible, reads the default offset if the firmware doesn't
have it
drivers/remoteproc/mtk_common.h | 2 +
drivers/remoteproc/mtk_scp.c | 79 +++++++++++++++++++++++----------
2 files changed, 57 insertions(+), 24 deletions(-)
diff --git a/drivers/remoteproc/mtk_common.h b/drivers/remoteproc/mtk_common.h
index b3397d327786..5169ddce2dc7 100644
--- a/drivers/remoteproc/mtk_common.h
+++ b/drivers/remoteproc/mtk_common.h
@@ -78,6 +78,8 @@ struct mtk_scp_of_data {
u32 host_to_scp_reg;
u32 host_to_scp_int_bit;
+
+ size_t ipi_buf_offset;
};
struct mtk_scp {
diff --git a/drivers/remoteproc/mtk_scp.c b/drivers/remoteproc/mtk_scp.c
index 5f42b9ce7185..5392c2fff682 100644
--- a/drivers/remoteproc/mtk_scp.c
+++ b/drivers/remoteproc/mtk_scp.c
@@ -21,7 +21,7 @@
#include "remoteproc_internal.h"
#define MAX_CODE_SIZE 0x500000
-#define SCP_FW_END 0x7C000
+#define SECTION_NAME_IPI_BUFFER ".ipi_buffer"
/**
* scp_get() - get a reference to SCP.
@@ -119,16 +119,29 @@ static void scp_ipi_handler(struct mtk_scp *scp)
wake_up(&scp->ack_wq);
}
-static int scp_ipi_init(struct mtk_scp *scp)
+static int scp_elf_read_ipi_buf_addr(struct mtk_scp *scp,
+ const struct firmware *fw,
+ size_t *offset);
+
+static int scp_ipi_init(struct mtk_scp *scp, const struct firmware *fw)
{
- size_t send_offset = SCP_FW_END - sizeof(struct mtk_share_obj);
- size_t recv_offset = send_offset - sizeof(struct mtk_share_obj);
+ int ret;
+ size_t offset;
+
+ /* read the ipi buf addr from FW itself first */
+ ret = scp_elf_read_ipi_buf_addr(scp, fw, &offset);
+ if (ret) {
+ /* use default ipi buf addr if the FW doesn't have it */
+ offset = scp->data->ipi_buf_offset;
+ if (!offset)
+ return ret;
+ }
+ dev_info(scp->dev, "IPI buf addr %#010zx\n", offset);
- /* shared buffer initialization */
- scp->recv_buf =
- (struct mtk_share_obj __iomem *)(scp->sram_base + recv_offset);
- scp->send_buf =
- (struct mtk_share_obj __iomem *)(scp->sram_base + send_offset);
+ scp->recv_buf = (struct mtk_share_obj __iomem *)
+ (scp->sram_base + offset);
+ scp->send_buf = (struct mtk_share_obj __iomem *)
+ (scp->sram_base + offset + sizeof(*scp->recv_buf));
memset_io(scp->recv_buf, 0, sizeof(*scp->recv_buf));
memset_io(scp->send_buf, 0, sizeof(*scp->send_buf));
@@ -271,6 +284,32 @@ static int scp_elf_load_segments(struct rproc *rproc, const struct firmware *fw)
return ret;
}
+static int scp_elf_read_ipi_buf_addr(struct mtk_scp *scp,
+ const struct firmware *fw,
+ size_t *offset)
+{
+ struct elf32_hdr *ehdr;
+ struct elf32_shdr *shdr, *shdr_strtab;
+ int i;
+ const u8 *elf_data = fw->data;
+ const char *strtab;
+
+ ehdr = (struct elf32_hdr *)elf_data;
+ shdr = (struct elf32_shdr *)(elf_data + ehdr->e_shoff);
+ shdr_strtab = shdr + ehdr->e_shstrndx;
+ strtab = (const char *)(elf_data + shdr_strtab->sh_offset);
+
+ for (i = 0; i < ehdr->e_shnum; i++, shdr++) {
+ if (strcmp(strtab + shdr->sh_name,
+ SECTION_NAME_IPI_BUFFER) == 0) {
+ *offset = shdr->sh_addr;
+ return 0;
+ }
+ }
+
+ return -ENOENT;
+}
+
static int mt8183_scp_before_load(struct mtk_scp *scp)
{
/* Clear SCP to host interrupt */
@@ -350,11 +389,15 @@ static int scp_load(struct rproc *rproc, const struct firmware *fw)
ret = scp->data->scp_before_load(scp);
if (ret < 0)
- return ret;
+ goto leave;
ret = scp_elf_load_segments(rproc, fw);
- clk_disable_unprepare(scp->clk);
+ if (ret)
+ goto leave;
+ ret = scp_ipi_init(scp, fw);
+leave:
+ clk_disable_unprepare(scp->clk);
return ret;
}
@@ -680,19 +723,6 @@ static int scp_probe(struct platform_device *pdev)
goto release_dev_mem;
}
- ret = clk_prepare_enable(scp->clk);
- if (ret) {
- dev_err(dev, "failed to enable clocks\n");
- goto release_dev_mem;
- }
-
- ret = scp_ipi_init(scp);
- clk_disable_unprepare(scp->clk);
- if (ret) {
- dev_err(dev, "Failed to init ipi\n");
- goto release_dev_mem;
- }
-
/* register SCP initialization IPI */
ret = scp_ipi_register(scp, SCP_IPI_INIT, scp_init_ipi_handler, scp);
if (ret) {
@@ -760,6 +790,7 @@ static const struct mtk_scp_of_data mt8183_of_data = {
.scp_stop = mt8183_scp_stop,
.host_to_scp_reg = MT8183_HOST_TO_SCP,
.host_to_scp_int_bit = MT8183_HOST_IPC_INT_BIT,
+ .ipi_buf_offset = 0x7bdb0,
};
static const struct mtk_scp_of_data mt8192_of_data = {
--
2.29.2.454.gaff20da3a2-goog
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH v3] remoteproc/mediatek: read IPI buffer offset from FW
@ 2020-11-30 3:40 ` Tzung-Bi Shih
0 siblings, 0 replies; 6+ messages in thread
From: Tzung-Bi Shih @ 2020-11-30 3:40 UTC (permalink / raw)
To: ohad, bjorn.andersson
Cc: mathieu.poirier, erin.lo, linux-remoteproc, tzungbi,
linux-mediatek, pihsun, matthias.bgg, linux-arm-kernel
Reads the IPI buffer offset from the FW binary. The information resides
in addr of .ipi_buffer section.
Moves scp_ipi_init() to scp_load() phase. The IPI buffer can be
initialized only if the offset is clear.
To backward compatible to MT8183 SCP, specify the offset in the board
specific mtk_scp_of_data. Reads the default offset if the firmware
doesn't have it.
Signed-off-by: Tzung-Bi Shih <tzungbi@google.com>
---
Previous discussion:
https://patchwork.kernel.org/project/linux-remoteproc/patch/20201127092941.1646260-1-tzungbi@google.com/
Changes from v2:
- to backward-compatible, reads the default offset if the firmware doesn't
have it
drivers/remoteproc/mtk_common.h | 2 +
drivers/remoteproc/mtk_scp.c | 79 +++++++++++++++++++++++----------
2 files changed, 57 insertions(+), 24 deletions(-)
diff --git a/drivers/remoteproc/mtk_common.h b/drivers/remoteproc/mtk_common.h
index b3397d327786..5169ddce2dc7 100644
--- a/drivers/remoteproc/mtk_common.h
+++ b/drivers/remoteproc/mtk_common.h
@@ -78,6 +78,8 @@ struct mtk_scp_of_data {
u32 host_to_scp_reg;
u32 host_to_scp_int_bit;
+
+ size_t ipi_buf_offset;
};
struct mtk_scp {
diff --git a/drivers/remoteproc/mtk_scp.c b/drivers/remoteproc/mtk_scp.c
index 5f42b9ce7185..5392c2fff682 100644
--- a/drivers/remoteproc/mtk_scp.c
+++ b/drivers/remoteproc/mtk_scp.c
@@ -21,7 +21,7 @@
#include "remoteproc_internal.h"
#define MAX_CODE_SIZE 0x500000
-#define SCP_FW_END 0x7C000
+#define SECTION_NAME_IPI_BUFFER ".ipi_buffer"
/**
* scp_get() - get a reference to SCP.
@@ -119,16 +119,29 @@ static void scp_ipi_handler(struct mtk_scp *scp)
wake_up(&scp->ack_wq);
}
-static int scp_ipi_init(struct mtk_scp *scp)
+static int scp_elf_read_ipi_buf_addr(struct mtk_scp *scp,
+ const struct firmware *fw,
+ size_t *offset);
+
+static int scp_ipi_init(struct mtk_scp *scp, const struct firmware *fw)
{
- size_t send_offset = SCP_FW_END - sizeof(struct mtk_share_obj);
- size_t recv_offset = send_offset - sizeof(struct mtk_share_obj);
+ int ret;
+ size_t offset;
+
+ /* read the ipi buf addr from FW itself first */
+ ret = scp_elf_read_ipi_buf_addr(scp, fw, &offset);
+ if (ret) {
+ /* use default ipi buf addr if the FW doesn't have it */
+ offset = scp->data->ipi_buf_offset;
+ if (!offset)
+ return ret;
+ }
+ dev_info(scp->dev, "IPI buf addr %#010zx\n", offset);
- /* shared buffer initialization */
- scp->recv_buf =
- (struct mtk_share_obj __iomem *)(scp->sram_base + recv_offset);
- scp->send_buf =
- (struct mtk_share_obj __iomem *)(scp->sram_base + send_offset);
+ scp->recv_buf = (struct mtk_share_obj __iomem *)
+ (scp->sram_base + offset);
+ scp->send_buf = (struct mtk_share_obj __iomem *)
+ (scp->sram_base + offset + sizeof(*scp->recv_buf));
memset_io(scp->recv_buf, 0, sizeof(*scp->recv_buf));
memset_io(scp->send_buf, 0, sizeof(*scp->send_buf));
@@ -271,6 +284,32 @@ static int scp_elf_load_segments(struct rproc *rproc, const struct firmware *fw)
return ret;
}
+static int scp_elf_read_ipi_buf_addr(struct mtk_scp *scp,
+ const struct firmware *fw,
+ size_t *offset)
+{
+ struct elf32_hdr *ehdr;
+ struct elf32_shdr *shdr, *shdr_strtab;
+ int i;
+ const u8 *elf_data = fw->data;
+ const char *strtab;
+
+ ehdr = (struct elf32_hdr *)elf_data;
+ shdr = (struct elf32_shdr *)(elf_data + ehdr->e_shoff);
+ shdr_strtab = shdr + ehdr->e_shstrndx;
+ strtab = (const char *)(elf_data + shdr_strtab->sh_offset);
+
+ for (i = 0; i < ehdr->e_shnum; i++, shdr++) {
+ if (strcmp(strtab + shdr->sh_name,
+ SECTION_NAME_IPI_BUFFER) == 0) {
+ *offset = shdr->sh_addr;
+ return 0;
+ }
+ }
+
+ return -ENOENT;
+}
+
static int mt8183_scp_before_load(struct mtk_scp *scp)
{
/* Clear SCP to host interrupt */
@@ -350,11 +389,15 @@ static int scp_load(struct rproc *rproc, const struct firmware *fw)
ret = scp->data->scp_before_load(scp);
if (ret < 0)
- return ret;
+ goto leave;
ret = scp_elf_load_segments(rproc, fw);
- clk_disable_unprepare(scp->clk);
+ if (ret)
+ goto leave;
+ ret = scp_ipi_init(scp, fw);
+leave:
+ clk_disable_unprepare(scp->clk);
return ret;
}
@@ -680,19 +723,6 @@ static int scp_probe(struct platform_device *pdev)
goto release_dev_mem;
}
- ret = clk_prepare_enable(scp->clk);
- if (ret) {
- dev_err(dev, "failed to enable clocks\n");
- goto release_dev_mem;
- }
-
- ret = scp_ipi_init(scp);
- clk_disable_unprepare(scp->clk);
- if (ret) {
- dev_err(dev, "Failed to init ipi\n");
- goto release_dev_mem;
- }
-
/* register SCP initialization IPI */
ret = scp_ipi_register(scp, SCP_IPI_INIT, scp_init_ipi_handler, scp);
if (ret) {
@@ -760,6 +790,7 @@ static const struct mtk_scp_of_data mt8183_of_data = {
.scp_stop = mt8183_scp_stop,
.host_to_scp_reg = MT8183_HOST_TO_SCP,
.host_to_scp_int_bit = MT8183_HOST_IPC_INT_BIT,
+ .ipi_buf_offset = 0x7bdb0,
};
static const struct mtk_scp_of_data mt8192_of_data = {
--
2.29.2.454.gaff20da3a2-goog
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH v3] remoteproc/mediatek: read IPI buffer offset from FW
@ 2020-11-30 3:40 ` Tzung-Bi Shih
0 siblings, 0 replies; 6+ messages in thread
From: Tzung-Bi Shih @ 2020-11-30 3:40 UTC (permalink / raw)
To: ohad, bjorn.andersson
Cc: mathieu.poirier, erin.lo, linux-remoteproc, tzungbi,
linux-mediatek, pihsun, matthias.bgg, linux-arm-kernel
Reads the IPI buffer offset from the FW binary. The information resides
in addr of .ipi_buffer section.
Moves scp_ipi_init() to scp_load() phase. The IPI buffer can be
initialized only if the offset is clear.
To backward compatible to MT8183 SCP, specify the offset in the board
specific mtk_scp_of_data. Reads the default offset if the firmware
doesn't have it.
Signed-off-by: Tzung-Bi Shih <tzungbi@google.com>
---
Previous discussion:
https://patchwork.kernel.org/project/linux-remoteproc/patch/20201127092941.1646260-1-tzungbi@google.com/
Changes from v2:
- to backward-compatible, reads the default offset if the firmware doesn't
have it
drivers/remoteproc/mtk_common.h | 2 +
drivers/remoteproc/mtk_scp.c | 79 +++++++++++++++++++++++----------
2 files changed, 57 insertions(+), 24 deletions(-)
diff --git a/drivers/remoteproc/mtk_common.h b/drivers/remoteproc/mtk_common.h
index b3397d327786..5169ddce2dc7 100644
--- a/drivers/remoteproc/mtk_common.h
+++ b/drivers/remoteproc/mtk_common.h
@@ -78,6 +78,8 @@ struct mtk_scp_of_data {
u32 host_to_scp_reg;
u32 host_to_scp_int_bit;
+
+ size_t ipi_buf_offset;
};
struct mtk_scp {
diff --git a/drivers/remoteproc/mtk_scp.c b/drivers/remoteproc/mtk_scp.c
index 5f42b9ce7185..5392c2fff682 100644
--- a/drivers/remoteproc/mtk_scp.c
+++ b/drivers/remoteproc/mtk_scp.c
@@ -21,7 +21,7 @@
#include "remoteproc_internal.h"
#define MAX_CODE_SIZE 0x500000
-#define SCP_FW_END 0x7C000
+#define SECTION_NAME_IPI_BUFFER ".ipi_buffer"
/**
* scp_get() - get a reference to SCP.
@@ -119,16 +119,29 @@ static void scp_ipi_handler(struct mtk_scp *scp)
wake_up(&scp->ack_wq);
}
-static int scp_ipi_init(struct mtk_scp *scp)
+static int scp_elf_read_ipi_buf_addr(struct mtk_scp *scp,
+ const struct firmware *fw,
+ size_t *offset);
+
+static int scp_ipi_init(struct mtk_scp *scp, const struct firmware *fw)
{
- size_t send_offset = SCP_FW_END - sizeof(struct mtk_share_obj);
- size_t recv_offset = send_offset - sizeof(struct mtk_share_obj);
+ int ret;
+ size_t offset;
+
+ /* read the ipi buf addr from FW itself first */
+ ret = scp_elf_read_ipi_buf_addr(scp, fw, &offset);
+ if (ret) {
+ /* use default ipi buf addr if the FW doesn't have it */
+ offset = scp->data->ipi_buf_offset;
+ if (!offset)
+ return ret;
+ }
+ dev_info(scp->dev, "IPI buf addr %#010zx\n", offset);
- /* shared buffer initialization */
- scp->recv_buf =
- (struct mtk_share_obj __iomem *)(scp->sram_base + recv_offset);
- scp->send_buf =
- (struct mtk_share_obj __iomem *)(scp->sram_base + send_offset);
+ scp->recv_buf = (struct mtk_share_obj __iomem *)
+ (scp->sram_base + offset);
+ scp->send_buf = (struct mtk_share_obj __iomem *)
+ (scp->sram_base + offset + sizeof(*scp->recv_buf));
memset_io(scp->recv_buf, 0, sizeof(*scp->recv_buf));
memset_io(scp->send_buf, 0, sizeof(*scp->send_buf));
@@ -271,6 +284,32 @@ static int scp_elf_load_segments(struct rproc *rproc, const struct firmware *fw)
return ret;
}
+static int scp_elf_read_ipi_buf_addr(struct mtk_scp *scp,
+ const struct firmware *fw,
+ size_t *offset)
+{
+ struct elf32_hdr *ehdr;
+ struct elf32_shdr *shdr, *shdr_strtab;
+ int i;
+ const u8 *elf_data = fw->data;
+ const char *strtab;
+
+ ehdr = (struct elf32_hdr *)elf_data;
+ shdr = (struct elf32_shdr *)(elf_data + ehdr->e_shoff);
+ shdr_strtab = shdr + ehdr->e_shstrndx;
+ strtab = (const char *)(elf_data + shdr_strtab->sh_offset);
+
+ for (i = 0; i < ehdr->e_shnum; i++, shdr++) {
+ if (strcmp(strtab + shdr->sh_name,
+ SECTION_NAME_IPI_BUFFER) == 0) {
+ *offset = shdr->sh_addr;
+ return 0;
+ }
+ }
+
+ return -ENOENT;
+}
+
static int mt8183_scp_before_load(struct mtk_scp *scp)
{
/* Clear SCP to host interrupt */
@@ -350,11 +389,15 @@ static int scp_load(struct rproc *rproc, const struct firmware *fw)
ret = scp->data->scp_before_load(scp);
if (ret < 0)
- return ret;
+ goto leave;
ret = scp_elf_load_segments(rproc, fw);
- clk_disable_unprepare(scp->clk);
+ if (ret)
+ goto leave;
+ ret = scp_ipi_init(scp, fw);
+leave:
+ clk_disable_unprepare(scp->clk);
return ret;
}
@@ -680,19 +723,6 @@ static int scp_probe(struct platform_device *pdev)
goto release_dev_mem;
}
- ret = clk_prepare_enable(scp->clk);
- if (ret) {
- dev_err(dev, "failed to enable clocks\n");
- goto release_dev_mem;
- }
-
- ret = scp_ipi_init(scp);
- clk_disable_unprepare(scp->clk);
- if (ret) {
- dev_err(dev, "Failed to init ipi\n");
- goto release_dev_mem;
- }
-
/* register SCP initialization IPI */
ret = scp_ipi_register(scp, SCP_IPI_INIT, scp_init_ipi_handler, scp);
if (ret) {
@@ -760,6 +790,7 @@ static const struct mtk_scp_of_data mt8183_of_data = {
.scp_stop = mt8183_scp_stop,
.host_to_scp_reg = MT8183_HOST_TO_SCP,
.host_to_scp_int_bit = MT8183_HOST_IPC_INT_BIT,
+ .ipi_buf_offset = 0x7bdb0,
};
static const struct mtk_scp_of_data mt8192_of_data = {
--
2.29.2.454.gaff20da3a2-goog
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH v3] remoteproc/mediatek: read IPI buffer offset from FW
2020-11-30 3:40 ` Tzung-Bi Shih
(?)
@ 2020-12-01 19:03 ` Mathieu Poirier
-1 siblings, 0 replies; 6+ messages in thread
From: Mathieu Poirier @ 2020-12-01 19:03 UTC (permalink / raw)
To: Tzung-Bi Shih
Cc: ohad, bjorn.andersson, linux-remoteproc, matthias.bgg,
linux-mediatek, linux-arm-kernel, pihsun, erin.lo
On Mon, Nov 30, 2020 at 11:40:25AM +0800, Tzung-Bi Shih wrote:
> Reads the IPI buffer offset from the FW binary. The information resides
> in addr of .ipi_buffer section.
>
> Moves scp_ipi_init() to scp_load() phase. The IPI buffer can be
> initialized only if the offset is clear.
>
> To backward compatible to MT8183 SCP, specify the offset in the board
> specific mtk_scp_of_data. Reads the default offset if the firmware
> doesn't have it.
>
> Signed-off-by: Tzung-Bi Shih <tzungbi@google.com>
> ---
> Previous discussion:
> https://patchwork.kernel.org/project/linux-remoteproc/patch/20201127092941.1646260-1-tzungbi@google.com/
>
> Changes from v2:
> - to backward-compatible, reads the default offset if the firmware doesn't
> have it
>
> drivers/remoteproc/mtk_common.h | 2 +
> drivers/remoteproc/mtk_scp.c | 79 +++++++++++++++++++++++----------
> 2 files changed, 57 insertions(+), 24 deletions(-)
>
> diff --git a/drivers/remoteproc/mtk_common.h b/drivers/remoteproc/mtk_common.h
> index b3397d327786..5169ddce2dc7 100644
> --- a/drivers/remoteproc/mtk_common.h
> +++ b/drivers/remoteproc/mtk_common.h
> @@ -78,6 +78,8 @@ struct mtk_scp_of_data {
>
> u32 host_to_scp_reg;
> u32 host_to_scp_int_bit;
> +
> + size_t ipi_buf_offset;
> };
>
> struct mtk_scp {
> diff --git a/drivers/remoteproc/mtk_scp.c b/drivers/remoteproc/mtk_scp.c
> index 5f42b9ce7185..5392c2fff682 100644
> --- a/drivers/remoteproc/mtk_scp.c
> +++ b/drivers/remoteproc/mtk_scp.c
> @@ -21,7 +21,7 @@
> #include "remoteproc_internal.h"
>
> #define MAX_CODE_SIZE 0x500000
> -#define SCP_FW_END 0x7C000
> +#define SECTION_NAME_IPI_BUFFER ".ipi_buffer"
>
> /**
> * scp_get() - get a reference to SCP.
> @@ -119,16 +119,29 @@ static void scp_ipi_handler(struct mtk_scp *scp)
> wake_up(&scp->ack_wq);
> }
>
> -static int scp_ipi_init(struct mtk_scp *scp)
> +static int scp_elf_read_ipi_buf_addr(struct mtk_scp *scp,
> + const struct firmware *fw,
> + size_t *offset);
> +
> +static int scp_ipi_init(struct mtk_scp *scp, const struct firmware *fw)
> {
> - size_t send_offset = SCP_FW_END - sizeof(struct mtk_share_obj);
> - size_t recv_offset = send_offset - sizeof(struct mtk_share_obj);
> + int ret;
> + size_t offset;
> +
> + /* read the ipi buf addr from FW itself first */
> + ret = scp_elf_read_ipi_buf_addr(scp, fw, &offset);
> + if (ret) {
> + /* use default ipi buf addr if the FW doesn't have it */
> + offset = scp->data->ipi_buf_offset;
> + if (!offset)
> + return ret;
> + }
> + dev_info(scp->dev, "IPI buf addr %#010zx\n", offset);
>
> - /* shared buffer initialization */
> - scp->recv_buf =
> - (struct mtk_share_obj __iomem *)(scp->sram_base + recv_offset);
> - scp->send_buf =
> - (struct mtk_share_obj __iomem *)(scp->sram_base + send_offset);
> + scp->recv_buf = (struct mtk_share_obj __iomem *)
> + (scp->sram_base + offset);
> + scp->send_buf = (struct mtk_share_obj __iomem *)
> + (scp->sram_base + offset + sizeof(*scp->recv_buf));
> memset_io(scp->recv_buf, 0, sizeof(*scp->recv_buf));
> memset_io(scp->send_buf, 0, sizeof(*scp->send_buf));
>
> @@ -271,6 +284,32 @@ static int scp_elf_load_segments(struct rproc *rproc, const struct firmware *fw)
> return ret;
> }
>
> +static int scp_elf_read_ipi_buf_addr(struct mtk_scp *scp,
> + const struct firmware *fw,
> + size_t *offset)
> +{
> + struct elf32_hdr *ehdr;
> + struct elf32_shdr *shdr, *shdr_strtab;
> + int i;
> + const u8 *elf_data = fw->data;
> + const char *strtab;
> +
> + ehdr = (struct elf32_hdr *)elf_data;
> + shdr = (struct elf32_shdr *)(elf_data + ehdr->e_shoff);
> + shdr_strtab = shdr + ehdr->e_shstrndx;
> + strtab = (const char *)(elf_data + shdr_strtab->sh_offset);
> +
> + for (i = 0; i < ehdr->e_shnum; i++, shdr++) {
> + if (strcmp(strtab + shdr->sh_name,
> + SECTION_NAME_IPI_BUFFER) == 0) {
> + *offset = shdr->sh_addr;
> + return 0;
> + }
> + }
> +
> + return -ENOENT;
> +}
> +
> static int mt8183_scp_before_load(struct mtk_scp *scp)
> {
> /* Clear SCP to host interrupt */
> @@ -350,11 +389,15 @@ static int scp_load(struct rproc *rproc, const struct firmware *fw)
>
> ret = scp->data->scp_before_load(scp);
> if (ret < 0)
> - return ret;
> + goto leave;
>
> ret = scp_elf_load_segments(rproc, fw);
> - clk_disable_unprepare(scp->clk);
> + if (ret)
> + goto leave;
>
> + ret = scp_ipi_init(scp, fw);
This version is much better. Since this is effectively what is going on,
please put this (along with clock related requirements) in rproc_ops::parse_fw.
Thanks,
Mathieu
> +leave:
> + clk_disable_unprepare(scp->clk);
> return ret;
> }
>
> @@ -680,19 +723,6 @@ static int scp_probe(struct platform_device *pdev)
> goto release_dev_mem;
> }
>
> - ret = clk_prepare_enable(scp->clk);
> - if (ret) {
> - dev_err(dev, "failed to enable clocks\n");
> - goto release_dev_mem;
> - }
> -
> - ret = scp_ipi_init(scp);
> - clk_disable_unprepare(scp->clk);
> - if (ret) {
> - dev_err(dev, "Failed to init ipi\n");
> - goto release_dev_mem;
> - }
> -
> /* register SCP initialization IPI */
> ret = scp_ipi_register(scp, SCP_IPI_INIT, scp_init_ipi_handler, scp);
> if (ret) {
> @@ -760,6 +790,7 @@ static const struct mtk_scp_of_data mt8183_of_data = {
> .scp_stop = mt8183_scp_stop,
> .host_to_scp_reg = MT8183_HOST_TO_SCP,
> .host_to_scp_int_bit = MT8183_HOST_IPC_INT_BIT,
> + .ipi_buf_offset = 0x7bdb0,
> };
>
> static const struct mtk_scp_of_data mt8192_of_data = {
> --
> 2.29.2.454.gaff20da3a2-goog
>
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v3] remoteproc/mediatek: read IPI buffer offset from FW
@ 2020-12-01 19:03 ` Mathieu Poirier
0 siblings, 0 replies; 6+ messages in thread
From: Mathieu Poirier @ 2020-12-01 19:03 UTC (permalink / raw)
To: Tzung-Bi Shih
Cc: ohad, erin.lo, linux-remoteproc, bjorn.andersson, linux-mediatek,
pihsun, matthias.bgg, linux-arm-kernel
On Mon, Nov 30, 2020 at 11:40:25AM +0800, Tzung-Bi Shih wrote:
> Reads the IPI buffer offset from the FW binary. The information resides
> in addr of .ipi_buffer section.
>
> Moves scp_ipi_init() to scp_load() phase. The IPI buffer can be
> initialized only if the offset is clear.
>
> To backward compatible to MT8183 SCP, specify the offset in the board
> specific mtk_scp_of_data. Reads the default offset if the firmware
> doesn't have it.
>
> Signed-off-by: Tzung-Bi Shih <tzungbi@google.com>
> ---
> Previous discussion:
> https://patchwork.kernel.org/project/linux-remoteproc/patch/20201127092941.1646260-1-tzungbi@google.com/
>
> Changes from v2:
> - to backward-compatible, reads the default offset if the firmware doesn't
> have it
>
> drivers/remoteproc/mtk_common.h | 2 +
> drivers/remoteproc/mtk_scp.c | 79 +++++++++++++++++++++++----------
> 2 files changed, 57 insertions(+), 24 deletions(-)
>
> diff --git a/drivers/remoteproc/mtk_common.h b/drivers/remoteproc/mtk_common.h
> index b3397d327786..5169ddce2dc7 100644
> --- a/drivers/remoteproc/mtk_common.h
> +++ b/drivers/remoteproc/mtk_common.h
> @@ -78,6 +78,8 @@ struct mtk_scp_of_data {
>
> u32 host_to_scp_reg;
> u32 host_to_scp_int_bit;
> +
> + size_t ipi_buf_offset;
> };
>
> struct mtk_scp {
> diff --git a/drivers/remoteproc/mtk_scp.c b/drivers/remoteproc/mtk_scp.c
> index 5f42b9ce7185..5392c2fff682 100644
> --- a/drivers/remoteproc/mtk_scp.c
> +++ b/drivers/remoteproc/mtk_scp.c
> @@ -21,7 +21,7 @@
> #include "remoteproc_internal.h"
>
> #define MAX_CODE_SIZE 0x500000
> -#define SCP_FW_END 0x7C000
> +#define SECTION_NAME_IPI_BUFFER ".ipi_buffer"
>
> /**
> * scp_get() - get a reference to SCP.
> @@ -119,16 +119,29 @@ static void scp_ipi_handler(struct mtk_scp *scp)
> wake_up(&scp->ack_wq);
> }
>
> -static int scp_ipi_init(struct mtk_scp *scp)
> +static int scp_elf_read_ipi_buf_addr(struct mtk_scp *scp,
> + const struct firmware *fw,
> + size_t *offset);
> +
> +static int scp_ipi_init(struct mtk_scp *scp, const struct firmware *fw)
> {
> - size_t send_offset = SCP_FW_END - sizeof(struct mtk_share_obj);
> - size_t recv_offset = send_offset - sizeof(struct mtk_share_obj);
> + int ret;
> + size_t offset;
> +
> + /* read the ipi buf addr from FW itself first */
> + ret = scp_elf_read_ipi_buf_addr(scp, fw, &offset);
> + if (ret) {
> + /* use default ipi buf addr if the FW doesn't have it */
> + offset = scp->data->ipi_buf_offset;
> + if (!offset)
> + return ret;
> + }
> + dev_info(scp->dev, "IPI buf addr %#010zx\n", offset);
>
> - /* shared buffer initialization */
> - scp->recv_buf =
> - (struct mtk_share_obj __iomem *)(scp->sram_base + recv_offset);
> - scp->send_buf =
> - (struct mtk_share_obj __iomem *)(scp->sram_base + send_offset);
> + scp->recv_buf = (struct mtk_share_obj __iomem *)
> + (scp->sram_base + offset);
> + scp->send_buf = (struct mtk_share_obj __iomem *)
> + (scp->sram_base + offset + sizeof(*scp->recv_buf));
> memset_io(scp->recv_buf, 0, sizeof(*scp->recv_buf));
> memset_io(scp->send_buf, 0, sizeof(*scp->send_buf));
>
> @@ -271,6 +284,32 @@ static int scp_elf_load_segments(struct rproc *rproc, const struct firmware *fw)
> return ret;
> }
>
> +static int scp_elf_read_ipi_buf_addr(struct mtk_scp *scp,
> + const struct firmware *fw,
> + size_t *offset)
> +{
> + struct elf32_hdr *ehdr;
> + struct elf32_shdr *shdr, *shdr_strtab;
> + int i;
> + const u8 *elf_data = fw->data;
> + const char *strtab;
> +
> + ehdr = (struct elf32_hdr *)elf_data;
> + shdr = (struct elf32_shdr *)(elf_data + ehdr->e_shoff);
> + shdr_strtab = shdr + ehdr->e_shstrndx;
> + strtab = (const char *)(elf_data + shdr_strtab->sh_offset);
> +
> + for (i = 0; i < ehdr->e_shnum; i++, shdr++) {
> + if (strcmp(strtab + shdr->sh_name,
> + SECTION_NAME_IPI_BUFFER) == 0) {
> + *offset = shdr->sh_addr;
> + return 0;
> + }
> + }
> +
> + return -ENOENT;
> +}
> +
> static int mt8183_scp_before_load(struct mtk_scp *scp)
> {
> /* Clear SCP to host interrupt */
> @@ -350,11 +389,15 @@ static int scp_load(struct rproc *rproc, const struct firmware *fw)
>
> ret = scp->data->scp_before_load(scp);
> if (ret < 0)
> - return ret;
> + goto leave;
>
> ret = scp_elf_load_segments(rproc, fw);
> - clk_disable_unprepare(scp->clk);
> + if (ret)
> + goto leave;
>
> + ret = scp_ipi_init(scp, fw);
This version is much better. Since this is effectively what is going on,
please put this (along with clock related requirements) in rproc_ops::parse_fw.
Thanks,
Mathieu
> +leave:
> + clk_disable_unprepare(scp->clk);
> return ret;
> }
>
> @@ -680,19 +723,6 @@ static int scp_probe(struct platform_device *pdev)
> goto release_dev_mem;
> }
>
> - ret = clk_prepare_enable(scp->clk);
> - if (ret) {
> - dev_err(dev, "failed to enable clocks\n");
> - goto release_dev_mem;
> - }
> -
> - ret = scp_ipi_init(scp);
> - clk_disable_unprepare(scp->clk);
> - if (ret) {
> - dev_err(dev, "Failed to init ipi\n");
> - goto release_dev_mem;
> - }
> -
> /* register SCP initialization IPI */
> ret = scp_ipi_register(scp, SCP_IPI_INIT, scp_init_ipi_handler, scp);
> if (ret) {
> @@ -760,6 +790,7 @@ static const struct mtk_scp_of_data mt8183_of_data = {
> .scp_stop = mt8183_scp_stop,
> .host_to_scp_reg = MT8183_HOST_TO_SCP,
> .host_to_scp_int_bit = MT8183_HOST_IPC_INT_BIT,
> + .ipi_buf_offset = 0x7bdb0,
> };
>
> static const struct mtk_scp_of_data mt8192_of_data = {
> --
> 2.29.2.454.gaff20da3a2-goog
>
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v3] remoteproc/mediatek: read IPI buffer offset from FW
@ 2020-12-01 19:03 ` Mathieu Poirier
0 siblings, 0 replies; 6+ messages in thread
From: Mathieu Poirier @ 2020-12-01 19:03 UTC (permalink / raw)
To: Tzung-Bi Shih
Cc: ohad, erin.lo, linux-remoteproc, bjorn.andersson, linux-mediatek,
pihsun, matthias.bgg, linux-arm-kernel
On Mon, Nov 30, 2020 at 11:40:25AM +0800, Tzung-Bi Shih wrote:
> Reads the IPI buffer offset from the FW binary. The information resides
> in addr of .ipi_buffer section.
>
> Moves scp_ipi_init() to scp_load() phase. The IPI buffer can be
> initialized only if the offset is clear.
>
> To backward compatible to MT8183 SCP, specify the offset in the board
> specific mtk_scp_of_data. Reads the default offset if the firmware
> doesn't have it.
>
> Signed-off-by: Tzung-Bi Shih <tzungbi@google.com>
> ---
> Previous discussion:
> https://patchwork.kernel.org/project/linux-remoteproc/patch/20201127092941.1646260-1-tzungbi@google.com/
>
> Changes from v2:
> - to backward-compatible, reads the default offset if the firmware doesn't
> have it
>
> drivers/remoteproc/mtk_common.h | 2 +
> drivers/remoteproc/mtk_scp.c | 79 +++++++++++++++++++++++----------
> 2 files changed, 57 insertions(+), 24 deletions(-)
>
> diff --git a/drivers/remoteproc/mtk_common.h b/drivers/remoteproc/mtk_common.h
> index b3397d327786..5169ddce2dc7 100644
> --- a/drivers/remoteproc/mtk_common.h
> +++ b/drivers/remoteproc/mtk_common.h
> @@ -78,6 +78,8 @@ struct mtk_scp_of_data {
>
> u32 host_to_scp_reg;
> u32 host_to_scp_int_bit;
> +
> + size_t ipi_buf_offset;
> };
>
> struct mtk_scp {
> diff --git a/drivers/remoteproc/mtk_scp.c b/drivers/remoteproc/mtk_scp.c
> index 5f42b9ce7185..5392c2fff682 100644
> --- a/drivers/remoteproc/mtk_scp.c
> +++ b/drivers/remoteproc/mtk_scp.c
> @@ -21,7 +21,7 @@
> #include "remoteproc_internal.h"
>
> #define MAX_CODE_SIZE 0x500000
> -#define SCP_FW_END 0x7C000
> +#define SECTION_NAME_IPI_BUFFER ".ipi_buffer"
>
> /**
> * scp_get() - get a reference to SCP.
> @@ -119,16 +119,29 @@ static void scp_ipi_handler(struct mtk_scp *scp)
> wake_up(&scp->ack_wq);
> }
>
> -static int scp_ipi_init(struct mtk_scp *scp)
> +static int scp_elf_read_ipi_buf_addr(struct mtk_scp *scp,
> + const struct firmware *fw,
> + size_t *offset);
> +
> +static int scp_ipi_init(struct mtk_scp *scp, const struct firmware *fw)
> {
> - size_t send_offset = SCP_FW_END - sizeof(struct mtk_share_obj);
> - size_t recv_offset = send_offset - sizeof(struct mtk_share_obj);
> + int ret;
> + size_t offset;
> +
> + /* read the ipi buf addr from FW itself first */
> + ret = scp_elf_read_ipi_buf_addr(scp, fw, &offset);
> + if (ret) {
> + /* use default ipi buf addr if the FW doesn't have it */
> + offset = scp->data->ipi_buf_offset;
> + if (!offset)
> + return ret;
> + }
> + dev_info(scp->dev, "IPI buf addr %#010zx\n", offset);
>
> - /* shared buffer initialization */
> - scp->recv_buf =
> - (struct mtk_share_obj __iomem *)(scp->sram_base + recv_offset);
> - scp->send_buf =
> - (struct mtk_share_obj __iomem *)(scp->sram_base + send_offset);
> + scp->recv_buf = (struct mtk_share_obj __iomem *)
> + (scp->sram_base + offset);
> + scp->send_buf = (struct mtk_share_obj __iomem *)
> + (scp->sram_base + offset + sizeof(*scp->recv_buf));
> memset_io(scp->recv_buf, 0, sizeof(*scp->recv_buf));
> memset_io(scp->send_buf, 0, sizeof(*scp->send_buf));
>
> @@ -271,6 +284,32 @@ static int scp_elf_load_segments(struct rproc *rproc, const struct firmware *fw)
> return ret;
> }
>
> +static int scp_elf_read_ipi_buf_addr(struct mtk_scp *scp,
> + const struct firmware *fw,
> + size_t *offset)
> +{
> + struct elf32_hdr *ehdr;
> + struct elf32_shdr *shdr, *shdr_strtab;
> + int i;
> + const u8 *elf_data = fw->data;
> + const char *strtab;
> +
> + ehdr = (struct elf32_hdr *)elf_data;
> + shdr = (struct elf32_shdr *)(elf_data + ehdr->e_shoff);
> + shdr_strtab = shdr + ehdr->e_shstrndx;
> + strtab = (const char *)(elf_data + shdr_strtab->sh_offset);
> +
> + for (i = 0; i < ehdr->e_shnum; i++, shdr++) {
> + if (strcmp(strtab + shdr->sh_name,
> + SECTION_NAME_IPI_BUFFER) == 0) {
> + *offset = shdr->sh_addr;
> + return 0;
> + }
> + }
> +
> + return -ENOENT;
> +}
> +
> static int mt8183_scp_before_load(struct mtk_scp *scp)
> {
> /* Clear SCP to host interrupt */
> @@ -350,11 +389,15 @@ static int scp_load(struct rproc *rproc, const struct firmware *fw)
>
> ret = scp->data->scp_before_load(scp);
> if (ret < 0)
> - return ret;
> + goto leave;
>
> ret = scp_elf_load_segments(rproc, fw);
> - clk_disable_unprepare(scp->clk);
> + if (ret)
> + goto leave;
>
> + ret = scp_ipi_init(scp, fw);
This version is much better. Since this is effectively what is going on,
please put this (along with clock related requirements) in rproc_ops::parse_fw.
Thanks,
Mathieu
> +leave:
> + clk_disable_unprepare(scp->clk);
> return ret;
> }
>
> @@ -680,19 +723,6 @@ static int scp_probe(struct platform_device *pdev)
> goto release_dev_mem;
> }
>
> - ret = clk_prepare_enable(scp->clk);
> - if (ret) {
> - dev_err(dev, "failed to enable clocks\n");
> - goto release_dev_mem;
> - }
> -
> - ret = scp_ipi_init(scp);
> - clk_disable_unprepare(scp->clk);
> - if (ret) {
> - dev_err(dev, "Failed to init ipi\n");
> - goto release_dev_mem;
> - }
> -
> /* register SCP initialization IPI */
> ret = scp_ipi_register(scp, SCP_IPI_INIT, scp_init_ipi_handler, scp);
> if (ret) {
> @@ -760,6 +790,7 @@ static const struct mtk_scp_of_data mt8183_of_data = {
> .scp_stop = mt8183_scp_stop,
> .host_to_scp_reg = MT8183_HOST_TO_SCP,
> .host_to_scp_int_bit = MT8183_HOST_IPC_INT_BIT,
> + .ipi_buf_offset = 0x7bdb0,
> };
>
> static const struct mtk_scp_of_data mt8192_of_data = {
> --
> 2.29.2.454.gaff20da3a2-goog
>
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2020-12-01 19:04 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-11-30 3:40 [PATCH v3] remoteproc/mediatek: read IPI buffer offset from FW Tzung-Bi Shih
2020-11-30 3:40 ` Tzung-Bi Shih
2020-11-30 3:40 ` Tzung-Bi Shih
2020-12-01 19:03 ` Mathieu Poirier
2020-12-01 19:03 ` Mathieu Poirier
2020-12-01 19:03 ` Mathieu Poirier
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.