lkml.org 
[lkml]   [2020]   [Mar]   [3]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
/
SubjectRe: [PATCH V5 4/4] firmware: imx-scu: Support one TX and one RX
From
Date


On 03.03.20 08:42, peng.fan@nxp.com wrote:
> From: Peng Fan <peng.fan@nxp.com>
>
> Current imx-scu requires four TX and four RX to communicate with
> SCU. This is low efficient and causes lots of mailbox interrupts.
>
> With imx-mailbox driver could support one TX to use all four transmit
> registers and one RX to use all four receive registers, imx-scu
> could use one TX and one RX.
>
> Signed-off-by: Peng Fan <peng.fan@nxp.com>

This driver should be review by some one else.

> ---
> V5:
> None
> V4:
> None
> V3:
> Check mbox fsl,imx8-mu-scu for fast_ipc
>
> drivers/firmware/imx/imx-scu.c | 54 +++++++++++++++++++++++++++++++++---------
> 1 file changed, 43 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/firmware/imx/imx-scu.c b/drivers/firmware/imx/imx-scu.c
> index f71eaa5bf52d..e94a5585b698 100644
> --- a/drivers/firmware/imx/imx-scu.c
> +++ b/drivers/firmware/imx/imx-scu.c
> @@ -38,6 +38,7 @@ struct imx_sc_ipc {
> struct device *dev;
> struct mutex lock;
> struct completion done;
> + bool fast_ipc;
>
> /* temporarily store the SCU msg */
> u32 *msg;
> @@ -115,6 +116,7 @@ static void imx_scu_rx_callback(struct mbox_client *c, void *msg)
> struct imx_sc_ipc *sc_ipc = sc_chan->sc_ipc;
> struct imx_sc_rpc_msg *hdr;
> u32 *data = msg;
> + int i;
>
> if (!sc_ipc->msg) {
> dev_warn(sc_ipc->dev, "unexpected rx idx %d 0x%08x, ignore!\n",
> @@ -122,6 +124,19 @@ static void imx_scu_rx_callback(struct mbox_client *c, void *msg)
> return;
> }
>
> + if (sc_ipc->fast_ipc) {
> + hdr = msg;
> + sc_ipc->rx_size = hdr->size;
> + sc_ipc->msg[0] = *data++;
> +
> + for (i = 1; i < sc_ipc->rx_size; i++)
> + sc_ipc->msg[i] = *data++;
> +
> + complete(&sc_ipc->done);
> +
> + return;
> + }
> +
> if (sc_chan->idx == 0) {
> hdr = msg;
> sc_ipc->rx_size = hdr->size;
> @@ -147,6 +162,7 @@ static int imx_scu_ipc_write(struct imx_sc_ipc *sc_ipc, void *msg)
> struct imx_sc_chan *sc_chan;
> u32 *data = msg;
> int ret;
> + int size;
> int i;
>
> /* Check size */
> @@ -156,7 +172,8 @@ static int imx_scu_ipc_write(struct imx_sc_ipc *sc_ipc, void *msg)
> dev_dbg(sc_ipc->dev, "RPC SVC %u FUNC %u SIZE %u\n", hdr->svc,
> hdr->func, hdr->size);
>
> - for (i = 0; i < hdr->size; i++) {
> + size = sc_ipc->fast_ipc ? 1 : hdr->size;
> + for (i = 0; i < size; i++) {
> sc_chan = &sc_ipc->chans[i % 4];
>
> /*
> @@ -168,8 +185,10 @@ static int imx_scu_ipc_write(struct imx_sc_ipc *sc_ipc, void *msg)
> * Wait for tx_done before every send to ensure that no
> * queueing happens at the mailbox channel level.
> */
> - wait_for_completion(&sc_chan->tx_done);
> - reinit_completion(&sc_chan->tx_done);
> + if (!sc_ipc->fast_ipc) {
> + wait_for_completion(&sc_chan->tx_done);
> + reinit_completion(&sc_chan->tx_done);
> + }
>
> ret = mbox_send_message(sc_chan->ch, &data[i]);
> if (ret < 0)
> @@ -246,6 +265,8 @@ static int imx_scu_probe(struct platform_device *pdev)
> struct imx_sc_chan *sc_chan;
> struct mbox_client *cl;
> char *chan_name;
> + struct of_phandle_args args;
> + int num_channel;
> int ret;
> int i;
>
> @@ -253,11 +274,20 @@ static int imx_scu_probe(struct platform_device *pdev)
> if (!sc_ipc)
> return -ENOMEM;
>
> - for (i = 0; i < SCU_MU_CHAN_NUM; i++) {
> - if (i < 4)
> + ret = of_parse_phandle_with_args(pdev->dev.of_node, "mboxes",
> + "#mbox-cells", 0, &args);
> + if (ret)
> + return ret;
> +
> + sc_ipc->fast_ipc = of_device_is_compatible(args.np, "fsl,imx8-mu-scu");
> +
> + num_channel = sc_ipc->fast_ipc ? 2 : SCU_MU_CHAN_NUM;
> + for (i = 0; i < num_channel; i++) {
> + if (i < num_channel / 2)
> chan_name = kasprintf(GFP_KERNEL, "tx%d", i);
> else
> - chan_name = kasprintf(GFP_KERNEL, "rx%d", i - 4);
> + chan_name = kasprintf(GFP_KERNEL, "rx%d",
> + i - num_channel / 2);
>
> if (!chan_name)
> return -ENOMEM;
> @@ -269,13 +299,15 @@ static int imx_scu_probe(struct platform_device *pdev)
> cl->knows_txdone = true;
> cl->rx_callback = imx_scu_rx_callback;
>
> - /* Initial tx_done completion as "done" */
> - cl->tx_done = imx_scu_tx_done;
> - init_completion(&sc_chan->tx_done);
> - complete(&sc_chan->tx_done);
> + if (!sc_ipc->fast_ipc) {
> + /* Initial tx_done completion as "done" */
> + cl->tx_done = imx_scu_tx_done;
> + init_completion(&sc_chan->tx_done);
> + complete(&sc_chan->tx_done);
> + }
>
> sc_chan->sc_ipc = sc_ipc;
> - sc_chan->idx = i % 4;
> + sc_chan->idx = i % (num_channel / 2);
> sc_chan->ch = mbox_request_channel_byname(cl, chan_name);
> if (IS_ERR(sc_chan->ch)) {
> ret = PTR_ERR(sc_chan->ch);
>

Kind regards,
Oleksij Rempel

--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |

\
 
 \ /
  Last update: 2020-03-03 09:00    [W:0.094 / U:0.488 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site