1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) STMicroelectronics SA 2015
4 * Author: Hugues Fruchet <hugues.fruchet@st.com> for STMicroelectronics.
7 #include <linux/rpmsg.h>
10 #include "delta-ipc.h"
11 #include "delta-mem.h"
13 #define IPC_TIMEOUT 100
14 #define IPC_SANITY_TAG 0xDEADBEEF
16 enum delta_ipc_fw_command
{
23 #define to_rpmsg_driver(__drv) container_of(__drv, struct rpmsg_driver, drv)
24 #define to_delta(__d) container_of(__d, struct delta_dev, rpmsg_driver)
26 #define to_ctx(hdl) ((struct delta_ipc_ctx *)hdl)
27 #define to_pctx(ctx) container_of(ctx, struct delta_ctx, ipc_ctx)
29 struct delta_ipc_header_msg
{
36 #define to_host_hdl(ctx) ((void *)ctx)
38 #define msg_to_ctx(msg) ((struct delta_ipc_ctx *)(msg)->header.host_hdl)
39 #define msg_to_copro_hdl(msg) ((msg)->header.copro_hdl)
41 static inline dma_addr_t
to_paddr(struct delta_ipc_ctx
*ctx
, void *vaddr
)
43 return (ctx
->ipc_buf
->paddr
+ (vaddr
- ctx
->ipc_buf
->vaddr
));
46 static inline bool is_valid_data(struct delta_ipc_ctx
*ctx
,
49 return ((data
>= ctx
->ipc_buf
->vaddr
) &&
50 ((data
+ size
) <= (ctx
->ipc_buf
->vaddr
+ ctx
->ipc_buf
->size
)));
54 * IPC shared memory (@ipc_buf_size, @ipc_buf_paddr) is sent to copro
55 * at each instance opening. This memory is allocated by IPC client
56 * and given through delta_ipc_open(). All messages parameters
57 * (open, set_stream, decode) will have their phy address within
58 * this IPC shared memory, avoiding de-facto recopies inside delta-ipc.
59 * All the below messages structures are used on both host and firmware
60 * side and are packed (use only of 32 bits size fields in messages
61 * structures to ensure packing):
62 * - struct delta_ipc_open_msg
63 * - struct delta_ipc_set_stream_msg
64 * - struct delta_ipc_decode_msg
65 * - struct delta_ipc_close_msg
66 * - struct delta_ipc_cb_msg
68 struct delta_ipc_open_msg
{
69 struct delta_ipc_header_msg header
;
71 dma_addr_t ipc_buf_paddr
;
74 dma_addr_t param_paddr
;
77 struct delta_ipc_set_stream_msg
{
78 struct delta_ipc_header_msg header
;
80 dma_addr_t param_paddr
;
83 struct delta_ipc_decode_msg
{
84 struct delta_ipc_header_msg header
;
86 dma_addr_t param_paddr
;
88 dma_addr_t status_paddr
;
91 struct delta_ipc_close_msg
{
92 struct delta_ipc_header_msg header
;
95 struct delta_ipc_cb_msg
{
96 struct delta_ipc_header_msg header
;
100 static void build_msg_header(struct delta_ipc_ctx
*ctx
,
101 enum delta_ipc_fw_command command
,
102 struct delta_ipc_header_msg
*header
)
104 header
->tag
= IPC_SANITY_TAG
;
105 header
->host_hdl
= to_host_hdl(ctx
);
106 header
->copro_hdl
= ctx
->copro_hdl
;
107 header
->command
= command
;
110 int delta_ipc_open(struct delta_ctx
*pctx
, const char *name
,
111 struct delta_ipc_param
*param
, u32 ipc_buf_size
,
112 struct delta_buf
**ipc_buf
, void **hdl
)
114 struct delta_dev
*delta
= pctx
->dev
;
115 struct rpmsg_device
*rpmsg_device
= delta
->rpmsg_device
;
116 struct delta_ipc_ctx
*ctx
= &pctx
->ipc_ctx
;
117 struct delta_ipc_open_msg msg
;
118 struct delta_buf
*buf
= &ctx
->ipc_buf_struct
;
123 "%s ipc: failed to open, rpmsg is not initialized\n",
131 "%s ipc: failed to open, no name given\n",
136 if (!param
|| !param
->data
|| !param
->size
) {
138 "%s ipc: failed to open, empty parameter\n",
145 "%s ipc: failed to open, no size given for ipc buffer\n",
150 if (param
->size
> ipc_buf_size
) {
152 "%s ipc: failed to open, too large ipc parameter (%d bytes while max %d expected)\n",
154 param
->size
, ctx
->ipc_buf
->size
);
159 init_completion(&ctx
->done
);
162 * allocation of contiguous buffer for
163 * data of commands exchanged between
164 * host and firmware coprocessor
166 ret
= hw_alloc(pctx
, ipc_buf_size
,
167 "ipc data buffer", buf
);
172 /* build rpmsg message */
173 build_msg_header(ctx
, DELTA_IPC_OPEN
, &msg
.header
);
175 msg
.ipc_buf_size
= ipc_buf_size
;
176 msg
.ipc_buf_paddr
= ctx
->ipc_buf
->paddr
;
178 memcpy(msg
.name
, name
, sizeof(msg
.name
));
179 msg
.name
[sizeof(msg
.name
) - 1] = 0;
181 msg
.param_size
= param
->size
;
182 memcpy(ctx
->ipc_buf
->vaddr
, param
->data
, msg
.param_size
);
183 msg
.param_paddr
= ctx
->ipc_buf
->paddr
;
186 ret
= rpmsg_send(rpmsg_device
->ept
, &msg
, sizeof(msg
));
189 "%s ipc: failed to open, rpmsg_send failed (%d) for DELTA_IPC_OPEN (name=%s, size=%d, data=%p)\n",
191 ret
, name
, param
->size
, param
->data
);
195 /* wait for acknowledge */
196 if (!wait_for_completion_timeout
197 (&ctx
->done
, msecs_to_jiffies(IPC_TIMEOUT
))) {
199 "%s ipc: failed to open, timeout waiting for DELTA_IPC_OPEN callback (name=%s, size=%d, data=%p)\n",
201 name
, param
->size
, param
->data
);
206 /* command completed, check error */
209 "%s ipc: failed to open, DELTA_IPC_OPEN completed but with error (%d) (name=%s, size=%d, data=%p)\n",
211 ctx
->cb_err
, name
, param
->size
, param
->data
);
216 *ipc_buf
= ctx
->ipc_buf
;
224 hw_free(pctx
, ctx
->ipc_buf
);
231 int delta_ipc_set_stream(void *hdl
, struct delta_ipc_param
*param
)
233 struct delta_ipc_ctx
*ctx
= to_ctx(hdl
);
234 struct delta_ctx
*pctx
= to_pctx(ctx
);
235 struct delta_dev
*delta
= pctx
->dev
;
236 struct rpmsg_device
*rpmsg_device
= delta
->rpmsg_device
;
237 struct delta_ipc_set_stream_msg msg
;
242 "%s ipc: failed to set stream, invalid ipc handle\n",
249 "%s ipc: failed to set stream, rpmsg is not initialized\n",
254 if (!param
|| !param
->data
|| !param
->size
) {
256 "%s ipc: failed to set stream, empty parameter\n",
261 if (param
->size
> ctx
->ipc_buf
->size
) {
263 "%s ipc: failed to set stream, too large ipc parameter(%d bytes while max %d expected)\n",
265 param
->size
, ctx
->ipc_buf
->size
);
269 if (!is_valid_data(ctx
, param
->data
, param
->size
)) {
271 "%s ipc: failed to set stream, parameter is not in expected address range (size=%d, data=%p not in %p..%p)\n",
276 ctx
->ipc_buf
->vaddr
+ ctx
->ipc_buf
->size
- 1);
280 /* build rpmsg message */
281 build_msg_header(ctx
, DELTA_IPC_SET_STREAM
, &msg
.header
);
283 msg
.param_size
= param
->size
;
284 msg
.param_paddr
= to_paddr(ctx
, param
->data
);
287 ret
= rpmsg_send(rpmsg_device
->ept
, &msg
, sizeof(msg
));
290 "%s ipc: failed to set stream, rpmsg_send failed (%d) for DELTA_IPC_SET_STREAM (size=%d, data=%p)\n",
292 ret
, param
->size
, param
->data
);
297 /* wait for acknowledge */
298 if (!wait_for_completion_timeout
299 (&ctx
->done
, msecs_to_jiffies(IPC_TIMEOUT
))) {
301 "%s ipc: failed to set stream, timeout waiting for DELTA_IPC_SET_STREAM callback (size=%d, data=%p)\n",
303 param
->size
, param
->data
);
308 /* command completed, check status */
311 "%s ipc: failed to set stream, DELTA_IPC_SET_STREAM completed but with error (%d) (size=%d, data=%p)\n",
313 ctx
->cb_err
, param
->size
, param
->data
);
321 int delta_ipc_decode(void *hdl
, struct delta_ipc_param
*param
,
322 struct delta_ipc_param
*status
)
324 struct delta_ipc_ctx
*ctx
= to_ctx(hdl
);
325 struct delta_ctx
*pctx
= to_pctx(ctx
);
326 struct delta_dev
*delta
= pctx
->dev
;
327 struct rpmsg_device
*rpmsg_device
= delta
->rpmsg_device
;
328 struct delta_ipc_decode_msg msg
;
333 "%s ipc: failed to decode, invalid ipc handle\n",
340 "%s ipc: failed to decode, rpmsg is not initialized\n",
345 if (!param
|| !param
->data
|| !param
->size
) {
347 "%s ipc: failed to decode, empty parameter\n",
352 if (!status
|| !status
->data
|| !status
->size
) {
354 "%s ipc: failed to decode, empty status\n",
359 if (param
->size
+ status
->size
> ctx
->ipc_buf
->size
) {
361 "%s ipc: failed to decode, too large ipc parameter (%d bytes (param) + %d bytes (status) while max %d expected)\n",
369 if (!is_valid_data(ctx
, param
->data
, param
->size
)) {
371 "%s ipc: failed to decode, parameter is not in expected address range (size=%d, data=%p not in %p..%p)\n",
376 ctx
->ipc_buf
->vaddr
+ ctx
->ipc_buf
->size
- 1);
380 if (!is_valid_data(ctx
, status
->data
, status
->size
)) {
382 "%s ipc: failed to decode, status is not in expected address range (size=%d, data=%p not in %p..%p)\n",
387 ctx
->ipc_buf
->vaddr
+ ctx
->ipc_buf
->size
- 1);
391 /* build rpmsg message */
392 build_msg_header(ctx
, DELTA_IPC_DECODE
, &msg
.header
);
394 msg
.param_size
= param
->size
;
395 msg
.param_paddr
= to_paddr(ctx
, param
->data
);
397 msg
.status_size
= status
->size
;
398 msg
.status_paddr
= to_paddr(ctx
, status
->data
);
401 ret
= rpmsg_send(rpmsg_device
->ept
, &msg
, sizeof(msg
));
404 "%s ipc: failed to decode, rpmsg_send failed (%d) for DELTA_IPC_DECODE (size=%d, data=%p)\n",
406 ret
, param
->size
, param
->data
);
411 /* wait for acknowledge */
412 if (!wait_for_completion_timeout
413 (&ctx
->done
, msecs_to_jiffies(IPC_TIMEOUT
))) {
415 "%s ipc: failed to decode, timeout waiting for DELTA_IPC_DECODE callback (size=%d, data=%p)\n",
417 param
->size
, param
->data
);
422 /* command completed, check status */
425 "%s ipc: failed to decode, DELTA_IPC_DECODE completed but with error (%d) (size=%d, data=%p)\n",
427 ctx
->cb_err
, param
->size
, param
->data
);
435 void delta_ipc_close(void *hdl
)
437 struct delta_ipc_ctx
*ctx
= to_ctx(hdl
);
438 struct delta_ctx
*pctx
= to_pctx(ctx
);
439 struct delta_dev
*delta
= pctx
->dev
;
440 struct rpmsg_device
*rpmsg_device
= delta
->rpmsg_device
;
441 struct delta_ipc_close_msg msg
;
446 "%s ipc: failed to close, invalid ipc handle\n",
452 hw_free(pctx
, ctx
->ipc_buf
);
458 "%s ipc: failed to close, rpmsg is not initialized\n",
463 /* build rpmsg message */
464 build_msg_header(ctx
, DELTA_IPC_CLOSE
, &msg
.header
);
467 ret
= rpmsg_send(rpmsg_device
->ept
, &msg
, sizeof(msg
));
470 "%s ipc: failed to close, rpmsg_send failed (%d) for DELTA_IPC_CLOSE\n",
476 /* wait for acknowledge */
477 if (!wait_for_completion_timeout
478 (&ctx
->done
, msecs_to_jiffies(IPC_TIMEOUT
))) {
480 "%s ipc: failed to close, timeout waiting for DELTA_IPC_CLOSE callback\n",
486 /* command completed, check status */
489 "%s ipc: failed to close, DELTA_IPC_CLOSE completed but with error (%d)\n",
490 pctx
->name
, ctx
->cb_err
);
495 static int delta_ipc_cb(struct rpmsg_device
*rpdev
, void *data
,
496 int len
, void *priv
, u32 src
)
498 struct delta_ipc_ctx
*ctx
;
499 struct delta_ipc_cb_msg
*msg
;
503 dev_err(NULL
, "rpdev is NULL\n");
509 "unexpected empty message received from src=%d\n", src
);
513 if (len
!= sizeof(*msg
)) {
515 "unexpected message length received from src=%d (received %d bytes while %zu bytes expected)\n",
516 len
, src
, sizeof(*msg
));
520 msg
= (struct delta_ipc_cb_msg
*)data
;
521 if (msg
->header
.tag
!= IPC_SANITY_TAG
) {
523 "unexpected message tag received from src=%d (received %x tag while %x expected)\n",
524 src
, msg
->header
.tag
, IPC_SANITY_TAG
);
528 ctx
= msg_to_ctx(msg
);
531 "unexpected message with NULL host_hdl received from src=%d\n",
537 * if not already known, save copro instance context
538 * to ensure re-entrance on copro side
541 ctx
->copro_hdl
= msg_to_copro_hdl(msg
);
545 * update status & complete command
547 ctx
->cb_err
= msg
->err
;
548 complete(&ctx
->done
);
553 static int delta_ipc_probe(struct rpmsg_device
*rpmsg_device
)
555 struct rpmsg_driver
*rpdrv
= to_rpmsg_driver(rpmsg_device
->dev
.driver
);
556 struct delta_dev
*delta
= to_delta(rpdrv
);
558 delta
->rpmsg_device
= rpmsg_device
;
563 static void delta_ipc_remove(struct rpmsg_device
*rpmsg_device
)
565 struct rpmsg_driver
*rpdrv
= to_rpmsg_driver(rpmsg_device
->dev
.driver
);
566 struct delta_dev
*delta
= to_delta(rpdrv
);
568 delta
->rpmsg_device
= NULL
;
571 static struct rpmsg_device_id delta_ipc_device_id_table
[] = {
572 {.name
= "rpmsg-delta"},
576 static struct rpmsg_driver delta_rpmsg_driver
= {
577 .drv
= {.name
= KBUILD_MODNAME
},
578 .id_table
= delta_ipc_device_id_table
,
579 .probe
= delta_ipc_probe
,
580 .callback
= delta_ipc_cb
,
581 .remove
= delta_ipc_remove
,
584 int delta_ipc_init(struct delta_dev
*delta
)
586 delta
->rpmsg_driver
= delta_rpmsg_driver
;
588 return register_rpmsg_driver(&delta
->rpmsg_driver
);
591 void delta_ipc_exit(struct delta_dev
*delta
)
593 unregister_rpmsg_driver(&delta
->rpmsg_driver
);