Skip to content

Commit 26d0fba

Browse files
cdleonardShawn Guo
authored andcommitted
firmware: imx: scu: Ensure sequential TX
SCU requires that all messages words are written sequentially but linux MU driver implements multiple independent channels for each register so ordering between different channels must be ensured by SCU API interface. Wait for tx_done before every send to ensure that no queueing happens at the mailbox channel level. Fixes: edbee09 ("firmware: imx: add SCU firmware driver support") Signed-off-by: Leonard Crestez <[email protected]> Cc: <[email protected]> Reviewed-by: Peng Fan <[email protected]> Reviewed-by:: Oleksij Rempel <[email protected]> Signed-off-by: Shawn Guo <[email protected]>
1 parent 2773fe1 commit 26d0fba

File tree

1 file changed

+27
-0
lines changed

1 file changed

+27
-0
lines changed

drivers/firmware/imx/imx-scu.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ struct imx_sc_chan {
2929
struct mbox_client cl;
3030
struct mbox_chan *ch;
3131
int idx;
32+
struct completion tx_done;
3233
};
3334

3435
struct imx_sc_ipc {
@@ -100,6 +101,14 @@ int imx_scu_get_handle(struct imx_sc_ipc **ipc)
100101
}
101102
EXPORT_SYMBOL(imx_scu_get_handle);
102103

104+
/* Callback called when the word of a message is ack-ed, eg read by SCU */
105+
static void imx_scu_tx_done(struct mbox_client *cl, void *mssg, int r)
106+
{
107+
struct imx_sc_chan *sc_chan = container_of(cl, struct imx_sc_chan, cl);
108+
109+
complete(&sc_chan->tx_done);
110+
}
111+
103112
static void imx_scu_rx_callback(struct mbox_client *c, void *msg)
104113
{
105114
struct imx_sc_chan *sc_chan = container_of(c, struct imx_sc_chan, cl);
@@ -149,6 +158,19 @@ static int imx_scu_ipc_write(struct imx_sc_ipc *sc_ipc, void *msg)
149158

150159
for (i = 0; i < hdr->size; i++) {
151160
sc_chan = &sc_ipc->chans[i % 4];
161+
162+
/*
163+
* SCU requires that all messages words are written
164+
* sequentially but linux MU driver implements multiple
165+
* independent channels for each register so ordering between
166+
* different channels must be ensured by SCU API interface.
167+
*
168+
* Wait for tx_done before every send to ensure that no
169+
* queueing happens at the mailbox channel level.
170+
*/
171+
wait_for_completion(&sc_chan->tx_done);
172+
reinit_completion(&sc_chan->tx_done);
173+
152174
ret = mbox_send_message(sc_chan->ch, &data[i]);
153175
if (ret < 0)
154176
return ret;
@@ -247,6 +269,11 @@ static int imx_scu_probe(struct platform_device *pdev)
247269
cl->knows_txdone = true;
248270
cl->rx_callback = imx_scu_rx_callback;
249271

272+
/* Initial tx_done completion as "done" */
273+
cl->tx_done = imx_scu_tx_done;
274+
init_completion(&sc_chan->tx_done);
275+
complete(&sc_chan->tx_done);
276+
250277
sc_chan->sc_ipc = sc_ipc;
251278
sc_chan->idx = i % 4;
252279
sc_chan->ch = mbox_request_channel_byname(cl, chan_name);

0 commit comments

Comments
 (0)