Commit 3efa0ea7 authored by Tzung-Bi Shih's avatar Tzung-Bi Shih Committed by Bjorn Andersson

remoteproc/mediatek: read IPI buffer offset from FW

Reads the IPI buffer offset from the FW binary.  The information resides
in addr of .ipi_buffer section.

Moves scp_ipi_init() to rproc_ops::parse_fw() 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.
Reviewed-by: default avatarMathieu Poirier <mathieu.poirier@linaro.org>
Signed-off-by: default avatarTzung-Bi Shih <tzungbi@google.com>
Link: https://lore.kernel.org/r/20201202044609.2501913-1-tzungbi@google.comSigned-off-by: default avatarBjorn Andersson <bjorn.andersson@linaro.org>
parent 22c3df6f
...@@ -78,6 +78,8 @@ struct mtk_scp_of_data { ...@@ -78,6 +78,8 @@ struct mtk_scp_of_data {
u32 host_to_scp_reg; u32 host_to_scp_reg;
u32 host_to_scp_int_bit; u32 host_to_scp_int_bit;
size_t ipi_buf_offset;
}; };
struct mtk_scp { struct mtk_scp {
......
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
#include "remoteproc_internal.h" #include "remoteproc_internal.h"
#define MAX_CODE_SIZE 0x500000 #define MAX_CODE_SIZE 0x500000
#define SCP_FW_END 0x7C000 #define SECTION_NAME_IPI_BUFFER ".ipi_buffer"
/** /**
* scp_get() - get a reference to SCP. * scp_get() - get a reference to SCP.
...@@ -119,16 +119,29 @@ static void scp_ipi_handler(struct mtk_scp *scp) ...@@ -119,16 +119,29 @@ static void scp_ipi_handler(struct mtk_scp *scp)
wake_up(&scp->ack_wq); 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); int ret;
size_t recv_offset = send_offset - sizeof(struct mtk_share_obj); 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->recv_buf = (scp->sram_base + offset);
(struct mtk_share_obj __iomem *)(scp->sram_base + recv_offset); scp->send_buf = (struct mtk_share_obj __iomem *)
scp->send_buf = (scp->sram_base + offset + sizeof(*scp->recv_buf));
(struct mtk_share_obj __iomem *)(scp->sram_base + send_offset);
memset_io(scp->recv_buf, 0, sizeof(*scp->recv_buf)); memset_io(scp->recv_buf, 0, sizeof(*scp->recv_buf));
memset_io(scp->send_buf, 0, sizeof(*scp->send_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) ...@@ -271,6 +284,32 @@ static int scp_elf_load_segments(struct rproc *rproc, const struct firmware *fw)
return ret; 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) static int mt8183_scp_before_load(struct mtk_scp *scp)
{ {
/* Clear SCP to host interrupt */ /* Clear SCP to host interrupt */
...@@ -359,6 +398,23 @@ static int scp_load(struct rproc *rproc, const struct firmware *fw) ...@@ -359,6 +398,23 @@ static int scp_load(struct rproc *rproc, const struct firmware *fw)
return ret; return ret;
} }
static int scp_parse_fw(struct rproc *rproc, const struct firmware *fw)
{
struct mtk_scp *scp = rproc->priv;
struct device *dev = scp->dev;
int ret;
ret = clk_prepare_enable(scp->clk);
if (ret) {
dev_err(dev, "failed to enable clocks\n");
return ret;
}
ret = scp_ipi_init(scp, fw);
clk_disable_unprepare(scp->clk);
return ret;
}
static int scp_start(struct rproc *rproc) static int scp_start(struct rproc *rproc)
{ {
struct mtk_scp *scp = (struct mtk_scp *)rproc->priv; struct mtk_scp *scp = (struct mtk_scp *)rproc->priv;
...@@ -462,6 +518,7 @@ static const struct rproc_ops scp_ops = { ...@@ -462,6 +518,7 @@ static const struct rproc_ops scp_ops = {
.stop = scp_stop, .stop = scp_stop,
.load = scp_load, .load = scp_load,
.da_to_va = scp_da_to_va, .da_to_va = scp_da_to_va,
.parse_fw = scp_parse_fw,
}; };
/** /**
...@@ -681,19 +738,6 @@ static int scp_probe(struct platform_device *pdev) ...@@ -681,19 +738,6 @@ static int scp_probe(struct platform_device *pdev)
goto release_dev_mem; 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 */ /* register SCP initialization IPI */
ret = scp_ipi_register(scp, SCP_IPI_INIT, scp_init_ipi_handler, scp); ret = scp_ipi_register(scp, SCP_IPI_INIT, scp_init_ipi_handler, scp);
if (ret) { if (ret) {
...@@ -761,6 +805,7 @@ static const struct mtk_scp_of_data mt8183_of_data = { ...@@ -761,6 +805,7 @@ static const struct mtk_scp_of_data mt8183_of_data = {
.scp_stop = mt8183_scp_stop, .scp_stop = mt8183_scp_stop,
.host_to_scp_reg = MT8183_HOST_TO_SCP, .host_to_scp_reg = MT8183_HOST_TO_SCP,
.host_to_scp_int_bit = MT8183_HOST_IPC_INT_BIT, .host_to_scp_int_bit = MT8183_HOST_IPC_INT_BIT,
.ipi_buf_offset = 0x7bdb0,
}; };
static const struct mtk_scp_of_data mt8192_of_data = { static const struct mtk_scp_of_data mt8192_of_data = {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment