Skip to content

Commit f25a066

Browse files
MrVanShawn Guo
authored andcommitted
firmware: imx-scu: Support one TX and one RX
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 <[email protected]> Signed-off-by: Shawn Guo <[email protected]>
1 parent 04df45f commit f25a066

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)
@@ -246,18 +265,29 @@ static int imx_scu_probe(struct platform_device *pdev)
246265
struct imx_sc_chan *sc_chan;
247266
struct mbox_client *cl;
248267
char *chan_name;
268+
struct of_phandle_args args;
269+
int num_channel;
249270
int ret;
250271
int i;
251272

252273
sc_ipc = devm_kzalloc(dev, sizeof(*sc_ipc), GFP_KERNEL);
253274
if (!sc_ipc)
254275
return -ENOMEM;
255276

256-
for (i = 0; i < SCU_MU_CHAN_NUM; i++) {
257-
if (i < 4)
277+
ret = of_parse_phandle_with_args(pdev->dev.of_node, "mboxes",
278+
"#mbox-cells", 0, &args);
279+
if (ret)
280+
return ret;
281+
282+
sc_ipc->fast_ipc = of_device_is_compatible(args.np, "fsl,imx8-mu-scu");
283+
284+
num_channel = sc_ipc->fast_ipc ? 2 : SCU_MU_CHAN_NUM;
285+
for (i = 0; i < num_channel; i++) {
286+
if (i < num_channel / 2)
258287
chan_name = kasprintf(GFP_KERNEL, "tx%d", i);
259288
else
260-
chan_name = kasprintf(GFP_KERNEL, "rx%d", i - 4);
289+
chan_name = kasprintf(GFP_KERNEL, "rx%d",
290+
i - num_channel / 2);
261291

262292
if (!chan_name)
263293
return -ENOMEM;
@@ -269,13 +299,15 @@ static int imx_scu_probe(struct platform_device *pdev)
269299
cl->knows_txdone = true;
270300
cl->rx_callback = imx_scu_rx_callback;
271301

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);
302+
if (!sc_ipc->fast_ipc) {
303+
/* Initial tx_done completion as "done" */
304+
cl->tx_done = imx_scu_tx_done;
305+
init_completion(&sc_chan->tx_done);
306+
complete(&sc_chan->tx_done);
307+
}
276308

277309
sc_chan->sc_ipc = sc_ipc;
278-
sc_chan->idx = i % 4;
310+
sc_chan->idx = i % (num_channel / 2);
279311
sc_chan->ch = mbox_request_channel_byname(cl, chan_name);
280312
if (IS_ERR(sc_chan->ch)) {
281313
ret = PTR_ERR(sc_chan->ch);

0 commit comments

Comments
 (0)