blob: 727981be3a2edc52088294931cbe75360f32cdd7 [file] [log] [blame]
xjb04a4022021-11-25 15:01:52 +08001/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * Copyright (c) 2019 MediaTek Inc.
4 */
5#include <linux/of.h>
6#include <linux/slab.h>
7
8#include "rpmsg_internal.h"
9#include <linux/soc/mediatek/mtk-mbox.h>
10#include <linux/rpmsg/mtk_rpmsg.h>
11
12#define to_mtk_rpmsg_device(r) container_of(r, struct mtk_rpmsg_device, rpdev)
13#define to_mtk_rpmsg_endpoint(r) container_of(r, struct mtk_rpmsg_endpoint, ept)
14
15int mtk_mbox_send(struct mtk_rpmsg_endpoint *mept,
16 struct mtk_rpmsg_channel_info *mchan, void *buf,
17 unsigned int len, unsigned int wait)
18{
19
20 struct mtk_rpmsg_device *mdev;
21 struct mtk_mbox_device *mbdev;
22 unsigned int status;
23 unsigned long flags;
24 int ret;
25
26 if (WARN_ON(len > mchan->send_slot_size || WARN_ON(!buf))) {
27 pr_err("mbox:%u warning\n", mchan->mbox);
28 return -EINVAL;
29 }
30
31 mdev = mept->mdev;
32 mbdev = mept->mdev->mbdev;
33
34 spin_lock_irqsave(&mchan->channel_lock, flags);
35 status = mtk_mbox_check_send_irq(mbdev, mchan->mbox,
36 mchan->send_pin_index);
37 if (status != 0) {
38 spin_unlock_irqrestore(&mchan->channel_lock, flags);
39 return MBOX_PIN_BUSY;
40 }
41 spin_unlock_irqrestore(&mchan->channel_lock, flags);
42
43 ret = mtk_mbox_write(mbdev, mchan->mbox, mchan->send_slot, buf,
44 len * MBOX_SLOT_SIZE);
45 if (ret != MBOX_DONE)
46 return ret;
47
48 /*
49 * Ensure that all writes to SRAM are committed before sending the
50 * interrupt to mbox.
51 */
52 mb();
53
54 ret = mtk_mbox_trigger_irq(mbdev, mchan->mbox,
55 0x1 << mchan->send_pin_index);
56 if (ret != MBOX_DONE)
57 return ret;
58
59 return ret;
60}
61EXPORT_SYMBOL_GPL(mtk_mbox_send);
62
63static struct mtk_rpmsg_operations mtk_rpmsg_ops = {
64 .mbox_send = mtk_mbox_send,
65 // .send_ipi = mtk_mbox_send,
66 // .register_ipi = scp_ipi_register,
67 // .unregister_ipi = scp_ipi_unregister,
68};
69
70static void __ept_release(struct kref *kref)
71{
72 struct rpmsg_endpoint *ept;
73
74 ept = container_of(kref, struct rpmsg_endpoint, refcount);
75 kfree(to_mtk_rpmsg_endpoint(ept));
76}
77
78static void mtk_rpmsg_destroy_ept(struct rpmsg_endpoint *ept)
79{
80 kref_put(&ept->refcount, __ept_release);
81}
82
83static int mtk_rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len)
84{
85 struct mtk_rpmsg_device *mdev;
86 struct mtk_rpmsg_channel_info *mchan;
87
88 mdev = to_mtk_rpmsg_endpoint(ept)->mdev;
89 mchan = to_mtk_rpmsg_endpoint(ept)->mchan;
90
91 return mdev->ops->mbox_send(to_mtk_rpmsg_endpoint(ept),
92 mchan, data, len, 1);
93}
94
95static int mtk_rpmsg_trysend(struct rpmsg_endpoint *ept, void *data, int len)
96{
97 struct mtk_rpmsg_device *mdev;
98 struct mtk_rpmsg_channel_info *mchan;
99
100 mdev = to_mtk_rpmsg_endpoint(ept)->mdev;
101 mchan = to_mtk_rpmsg_endpoint(ept)->mchan;
102
103 return mdev->ops->mbox_send(to_mtk_rpmsg_endpoint(ept),
104 mchan, data, len, 0);
105}
106
107static const struct rpmsg_endpoint_ops mtk_rpmsg_endpoint_ops = {
108 .destroy_ept = mtk_rpmsg_destroy_ept,
109 .send = mtk_rpmsg_send,
110 .trysend = mtk_rpmsg_trysend,
111};
112
113
114/*
115 * create mtk rpmsg channel
116 */
117struct mtk_rpmsg_channel_info *
118mtk_rpmsg_create_channel(struct mtk_rpmsg_device *mdev, u32 chan_id, char *name)
119{
120 struct mtk_rpmsg_channel_info *mchan;
121 struct mtk_mbox_device *mbdev;
122 struct mtk_mbox_pin_send *msend;
123 struct mtk_mbox_pin_recv *mrecv;
124 unsigned int i, count, found;
125
126 //malloc mtk_rpmsg_channel_info mchan
127 mchan = kzalloc(sizeof(*mchan), GFP_KERNEL);
128 if (!mchan)
129 return NULL;
130
131 mbdev = mdev->mbdev;
132 spin_lock_init(&mchan->channel_lock);
133 mchan->info.src = chan_id;
134 //mchan->info.dst = dst;
135 //copy name to rpdev, only dev no need now
136 //strncpy(rpdev->id.name, name, RPMSG_NAME_SIZE);
137 //copy name to channel info
138 strlcpy(mchan->info.name, name, RPMSG_NAME_SIZE);
139
140 count = mbdev->recv_count;
141 found = 0;
142 for (i = 0; i < count; ++i) {
143 mrecv = &(mbdev->pin_recv_table[i]);
144 if (chan_id == mrecv->chan_id) {
145 mchan->mbox = mrecv->mbox;
146 mchan->recv_slot = mrecv->offset;
147 mchan->recv_slot_size = mrecv->msg_size;
148 mchan->recv_pin_index = mrecv->pin_index;
149 mchan->recv_pin_offset = i;
150 //TODO if not found
151 found = 1;
152 }
153 }
154
155 count = mbdev->send_count;
156 found = 0;
157 for (i = 0; i < count; ++i) {
158 msend = &(mbdev->pin_send_table[i]);
159 if (chan_id == msend->chan_id) {
160 mchan->mbox = msend->mbox;
161 mchan->send_slot = msend->offset;
162 mchan->send_slot_size = msend->msg_size;
163 mchan->send_pin_index = msend->pin_index;
164 mchan->send_pin_offset = i;
165 //TODO if not found
166 found = 1;
167 }
168 }
169 return mchan;
170}
171EXPORT_SYMBOL_GPL(mtk_rpmsg_create_channel);
172
173/*
174 * create endpoint
175 */
176static struct rpmsg_endpoint *
177__rpmsg_create_ept(struct rpmsg_device *rpdev, rpmsg_rx_cb_t cb, void *priv,
178 struct rpmsg_channel_info chinfo)
179{
180 struct mtk_rpmsg_endpoint *mept;
181 struct rpmsg_endpoint *ept;
182
183 mept = kzalloc(sizeof(*mept), GFP_KERNEL);
184 if (!mept)
185 return NULL;
186
187 mept->mdev = to_mtk_rpmsg_device(rpdev);
188 mept->mchan = (struct mtk_rpmsg_channel_info *)priv;
189
190 ept = &mept->ept;
191 kref_init(&ept->refcount);
192
193 ept->rpdev = rpdev;
194 ept->cb = cb;
195 //ept->priv = priv;
196 ept->ops = &mtk_rpmsg_endpoint_ops;
197 ept->addr = chinfo.src;
198
199 return ept;
200}
201
202static struct rpmsg_endpoint *
203mtk_rpmsg_create_ept(struct rpmsg_device *rpdev, rpmsg_rx_cb_t cb, void *priv,
204 struct rpmsg_channel_info chinfo)
205{
206 return __rpmsg_create_ept(rpdev, cb, priv, chinfo);
207}
208
209static const struct rpmsg_device_ops mtk_rpmsg_device_ops = {
210 .create_ept = mtk_rpmsg_create_ept,
211};
212
213static void mtk_rpmsg_release_device(struct device *dev)
214{
215 struct rpmsg_device *rpdev = to_rpmsg_device(dev);
216 struct mtk_rpmsg_device *mdev = to_mtk_rpmsg_device(rpdev);
217
218 kfree(mdev);
219}
220
221/*
222 * create mtk rpmsg device
223 */
224struct mtk_rpmsg_device *
225mtk_rpmsg_create_device(struct platform_device *pdev,
226 struct mtk_mbox_device *mbdev, unsigned int ipc_chan_id)
227{
228
229 struct rpmsg_device *rpdev;
230 struct mtk_rpmsg_device *mdev;
231 int ret;
232
233 mdev = kzalloc(sizeof(*mdev), GFP_KERNEL);
234 if (!mdev)
235 return NULL;
236
237 mdev->pdev = pdev;
238 mdev->mbdev = mbdev;
239 mdev->ops = &mtk_rpmsg_ops;
240 rpdev = &mdev->rpdev;
241 rpdev->ops = &mtk_rpmsg_device_ops;
242 rpdev->src = ipc_chan_id;
243 //rpdev->dst = info->dst;
244
245//register RPMSG device
246
247#if 0
248 rpdev->dev.of_node =
249 mtk_rpmsg_match_device_subnode
250 (pdev->dev.of_node, info->name);
251#endif
252 rpdev->dev.parent = &pdev->dev;
253 rpdev->dev.release = mtk_rpmsg_release_device;
254
255 ret = rpmsg_register_device(rpdev);
256 if (ret) {
257 kfree(mdev);
258 return NULL;
259 }
260
261 return mdev;
262}
263EXPORT_SYMBOL_GPL(mtk_rpmsg_create_device);
264
265
266//MODULE_LICENSE("GPL v2");
267//MODULE_DESCRIPTION("MediaTek rpmsg driver");