1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * Copyright 2020-2021 NXP |
4 | */ |
5 | |
6 | #include <linux/init.h> |
7 | #include <linux/interconnect.h> |
8 | #include <linux/ioctl.h> |
9 | #include <linux/list.h> |
10 | #include <linux/kernel.h> |
11 | #include <linux/module.h> |
12 | #include <linux/platform_device.h> |
13 | #include "vpu.h" |
14 | #include "vpu_mbox.h" |
15 | #include "vpu_msgs.h" |
16 | |
17 | static void vpu_mbox_rx_callback(struct mbox_client *cl, void *msg) |
18 | { |
19 | struct vpu_mbox *rx = container_of(cl, struct vpu_mbox, cl); |
20 | struct vpu_core *core = container_of(rx, struct vpu_core, rx); |
21 | |
22 | vpu_isr(core, irq: *(u32 *)msg); |
23 | } |
24 | |
25 | static int vpu_mbox_request_channel(struct device *dev, struct vpu_mbox *mbox) |
26 | { |
27 | struct mbox_chan *ch; |
28 | struct mbox_client *cl; |
29 | |
30 | if (!dev || !mbox) |
31 | return -EINVAL; |
32 | if (mbox->ch) |
33 | return 0; |
34 | |
35 | cl = &mbox->cl; |
36 | cl->dev = dev; |
37 | if (mbox->block) { |
38 | cl->tx_block = true; |
39 | cl->tx_tout = 1000; |
40 | } else { |
41 | cl->tx_block = false; |
42 | } |
43 | cl->knows_txdone = false; |
44 | cl->rx_callback = vpu_mbox_rx_callback; |
45 | |
46 | ch = mbox_request_channel_byname(cl, name: mbox->name); |
47 | if (IS_ERR(ptr: ch)) |
48 | return dev_err_probe(dev, err: PTR_ERR(ptr: ch), |
49 | fmt: "Failed to request mbox chan %s\n" , |
50 | mbox->name); |
51 | |
52 | mbox->ch = ch; |
53 | return 0; |
54 | } |
55 | |
56 | int vpu_mbox_init(struct vpu_core *core) |
57 | { |
58 | scnprintf(buf: core->tx_type.name, size: sizeof(core->tx_type.name) - 1, fmt: "tx0" ); |
59 | core->tx_type.block = true; |
60 | |
61 | scnprintf(buf: core->tx_data.name, size: sizeof(core->tx_data.name) - 1, fmt: "tx1" ); |
62 | core->tx_data.block = false; |
63 | |
64 | scnprintf(buf: core->rx.name, size: sizeof(core->rx.name) - 1, fmt: "rx" ); |
65 | core->rx.block = true; |
66 | |
67 | return 0; |
68 | } |
69 | |
70 | int vpu_mbox_request(struct vpu_core *core) |
71 | { |
72 | int ret; |
73 | |
74 | ret = vpu_mbox_request_channel(dev: core->dev, mbox: &core->tx_type); |
75 | if (ret) |
76 | goto error; |
77 | ret = vpu_mbox_request_channel(dev: core->dev, mbox: &core->tx_data); |
78 | if (ret) |
79 | goto error; |
80 | ret = vpu_mbox_request_channel(dev: core->dev, mbox: &core->rx); |
81 | if (ret) |
82 | goto error; |
83 | |
84 | dev_dbg(core->dev, "%s request mbox\n" , vpu_core_type_desc(core->type)); |
85 | return 0; |
86 | error: |
87 | vpu_mbox_free(core); |
88 | return ret; |
89 | } |
90 | |
91 | void vpu_mbox_free(struct vpu_core *core) |
92 | { |
93 | mbox_free_channel(chan: core->tx_type.ch); |
94 | mbox_free_channel(chan: core->tx_data.ch); |
95 | mbox_free_channel(chan: core->rx.ch); |
96 | core->tx_type.ch = NULL; |
97 | core->tx_data.ch = NULL; |
98 | core->rx.ch = NULL; |
99 | dev_dbg(core->dev, "%s free mbox\n" , vpu_core_type_desc(core->type)); |
100 | } |
101 | |
102 | void vpu_mbox_send_type(struct vpu_core *core, u32 type) |
103 | { |
104 | mbox_send_message(chan: core->tx_type.ch, mssg: &type); |
105 | } |
106 | |
107 | void vpu_mbox_send_msg(struct vpu_core *core, u32 type, u32 data) |
108 | { |
109 | mbox_send_message(chan: core->tx_data.ch, mssg: &data); |
110 | mbox_send_message(chan: core->tx_type.ch, mssg: &type); |
111 | } |
112 | |
113 | void vpu_mbox_enable_rx(struct vpu_dev *dev) |
114 | { |
115 | } |
116 | |