Skip to content

Commit a1fd068

Browse files
MrVangregkh
authored andcommitted
firmware: imx-scu: Support one TX and one RX
[ Upstream commit f25a066 ] 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> Signed-off-by: Shawn Guo <shawnguo@kernel.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent da24a76 commit a1fd068

File tree

1 file changed

+43
-11
lines changed

1 file changed

+43
-11
lines changed

drivers/firmware/imx/imx-scu.c

Lines changed: 43 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ struct imx_sc_ipc {
3838
struct device *dev;
3939
struct mutex lock;
4040
struct completion done;
41+
bool fast_ipc;
4142

4243
/* temporarily store the SCU msg */
4344
u32 *msg;
@@ -115,13 +116,27 @@ static void imx_scu_rx_callback(struct mbox_client *c, void *msg)
115116
struct imx_sc_ipc *sc_ipc = sc_chan->sc_ipc;
116117
struct imx_sc_rpc_msg *hdr;
117118
u32 *data = msg;
119+
int i;
118120

119121
if (!sc_ipc->msg) {
120122
dev_warn(sc_ipc->dev, "unexpected rx idx %d 0x%08x, ignore!\n",
121123
sc_chan->idx, *data);
122124
return;
123125
}
124126

127+
if (sc_ipc->fast_ipc) {
128+
hdr = msg;
129+
sc_ipc->rx_size = hdr->size;
130+
sc_ipc->msg[0] = *data++;
131+
132+
for (i = 1; i < sc_ipc->rx_size; i++)
133+
sc_ipc->msg[i] = *data++;
134+
135+
complete(&sc_ipc->done);
136+
137+
return;
138+
}
139+
125140
if (sc_chan->idx == 0) {
126141
hdr = msg;
127142
sc_ipc->rx_size = hdr->size;
@@ -147,6 +162,7 @@ static int imx_scu_ipc_write(struct imx_sc_ipc *sc_ipc, void *msg)
147162
struct imx_sc_chan *sc_chan;
148163
u32 *data = msg;
149164
int ret;
165+
int size;
150166
int i;
151167

152168
/* Check size */
@@ -156,7 +172,8 @@ static int imx_scu_ipc_write(struct imx_sc_ipc *sc_ipc, void *msg)
156172
dev_dbg(sc_ipc->dev, "RPC SVC %u FUNC %u SIZE %u\n", hdr->svc,
157173
hdr->func, hdr->size);
158174

159-
for (i = 0; i < hdr->size; i++) {
175+
size = sc_ipc->fast_ipc ? 1 : hdr->size;
176+
for (i = 0; i < size; i++) {
160177
sc_chan = &sc_ipc->chans[i % 4];
161178

162179
/*
@@ -168,8 +185,10 @@ static int imx_scu_ipc_write(struct imx_sc_ipc *sc_ipc, void *msg)
168185
* Wait for tx_done before every send to ensure that no
169186
* queueing happens at the mailbox channel level.
170187
*/
171-
wait_for_completion(&sc_chan->tx_done);
172-
reinit_completion(&sc_chan->tx_done);
188+
if (!sc_ipc->fast_ipc) {
189+
wait_for_completion(&sc_chan->tx_done);
190+
reinit_completion(&sc_chan->tx_done);
191+
}
173192

174193
ret = mbox_send_message(sc_chan->ch, &data[i]);
175194
if (ret < 0)
@@ -232,18 +251,29 @@ static int imx_scu_probe(struct platform_device *pdev)
232251
struct imx_sc_chan *sc_chan;
233252
struct mbox_client *cl;
234253
char *chan_name;
254+
struct of_phandle_args args;
255+
int num_channel;
235256
int ret;
236257
int i;
237258

238259
sc_ipc = devm_kzalloc(dev, sizeof(*sc_ipc), GFP_KERNEL);
239260
if (!sc_ipc)
240261
return -ENOMEM;
241262

242-
for (i = 0; i < SCU_MU_CHAN_NUM; i++) {
243-
if (i < 4)
263+
ret = of_parse_phandle_with_args(pdev->dev.of_node, "mboxes",
264+
"#mbox-cells", 0, &args);
265+
if (ret)
266+
return ret;
267+
268+
sc_ipc->fast_ipc = of_device_is_compatible(args.np, "fsl,imx8-mu-scu");
269+
270+
num_channel = sc_ipc->fast_ipc ? 2 : SCU_MU_CHAN_NUM;
271+
for (i = 0; i < num_channel; i++) {
272+
if (i < num_channel / 2)
244273
chan_name = kasprintf(GFP_KERNEL, "tx%d", i);
245274
else
246-
chan_name = kasprintf(GFP_KERNEL, "rx%d", i - 4);
275+
chan_name = kasprintf(GFP_KERNEL, "rx%d",
276+
i - num_channel / 2);
247277

248278
if (!chan_name)
249279
return -ENOMEM;
@@ -255,13 +285,15 @@ static int imx_scu_probe(struct platform_device *pdev)
255285
cl->knows_txdone = true;
256286
cl->rx_callback = imx_scu_rx_callback;
257287

258-
/* Initial tx_done completion as "done" */
259-
cl->tx_done = imx_scu_tx_done;
260-
init_completion(&sc_chan->tx_done);
261-
complete(&sc_chan->tx_done);
288+
if (!sc_ipc->fast_ipc) {
289+
/* Initial tx_done completion as "done" */
290+
cl->tx_done = imx_scu_tx_done;
291+
init_completion(&sc_chan->tx_done);
292+
complete(&sc_chan->tx_done);
293+
}
262294

263295
sc_chan->sc_ipc = sc_ipc;
264-
sc_chan->idx = i % 4;
296+
sc_chan->idx = i % (num_channel / 2);
265297
sc_chan->ch = mbox_request_channel_byname(cl, chan_name);
266298
if (IS_ERR(sc_chan->ch)) {
267299
ret = PTR_ERR(sc_chan->ch);

0 commit comments

Comments
 (0)