2 * Copyright (c) 2016-2017, Linaro Ltd
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 and
6 * only version 2 as published by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
14 #include <linux/idr.h>
15 #include <linux/interrupt.h>
17 #include <linux/list.h>
18 #include <linux/mfd/syscon.h>
19 #include <linux/module.h>
21 #include <linux/of_address.h>
22 #include <linux/platform_device.h>
23 #include <linux/regmap.h>
24 #include <linux/rpmsg.h>
25 #include <linux/slab.h>
26 #include <linux/workqueue.h>
27 #include <linux/mailbox_client.h>
29 #include "rpmsg_internal.h"
30 #include "qcom_glink_native.h"
32 #define RPM_TOC_SIZE 256
33 #define RPM_TOC_MAGIC 0x67727430 /* grt0 */
34 #define RPM_TOC_MAX_ENTRIES ((RPM_TOC_SIZE - sizeof(struct rpm_toc)) / \
35 sizeof(struct rpm_toc_entry))
37 #define RPM_TX_FIFO_ID 0x61703272 /* ap2r */
38 #define RPM_RX_FIFO_ID 0x72326170 /* r2ap */
40 #define to_rpm_pipe(p) container_of(p, struct glink_rpm_pipe, native)
42 struct rpm_toc_entry
{
52 struct rpm_toc_entry entries
[];
55 struct glink_rpm_pipe
{
56 struct qcom_glink_pipe native
;
64 static size_t glink_rpm_rx_avail(struct qcom_glink_pipe
*glink_pipe
)
66 struct glink_rpm_pipe
*pipe
= to_rpm_pipe(glink_pipe
);
70 head
= readl(pipe
->head
);
71 tail
= readl(pipe
->tail
);
74 return pipe
->native
.length
- tail
+ head
;
79 static void glink_rpm_rx_peak(struct qcom_glink_pipe
*glink_pipe
,
80 void *data
, unsigned int offset
, size_t count
)
82 struct glink_rpm_pipe
*pipe
= to_rpm_pipe(glink_pipe
);
86 tail
= readl(pipe
->tail
);
88 if (tail
>= pipe
->native
.length
)
89 tail
-= pipe
->native
.length
;
91 len
= min_t(size_t, count
, pipe
->native
.length
- tail
);
93 __ioread32_copy(data
, pipe
->fifo
+ tail
,
98 __ioread32_copy(data
+ len
, pipe
->fifo
,
99 (count
- len
) / sizeof(u32
));
103 static void glink_rpm_rx_advance(struct qcom_glink_pipe
*glink_pipe
,
106 struct glink_rpm_pipe
*pipe
= to_rpm_pipe(glink_pipe
);
109 tail
= readl(pipe
->tail
);
112 if (tail
>= pipe
->native
.length
)
113 tail
-= pipe
->native
.length
;
115 writel(tail
, pipe
->tail
);
118 static size_t glink_rpm_tx_avail(struct qcom_glink_pipe
*glink_pipe
)
120 struct glink_rpm_pipe
*pipe
= to_rpm_pipe(glink_pipe
);
124 head
= readl(pipe
->head
);
125 tail
= readl(pipe
->tail
);
128 return pipe
->native
.length
- head
+ tail
;
133 static unsigned int glink_rpm_tx_write_one(struct glink_rpm_pipe
*pipe
,
135 const void *data
, size_t count
)
139 len
= min_t(size_t, count
, pipe
->native
.length
- head
);
141 __iowrite32_copy(pipe
->fifo
+ head
, data
,
146 __iowrite32_copy(pipe
->fifo
, data
+ len
,
147 (count
- len
) / sizeof(u32
));
151 if (head
>= pipe
->native
.length
)
152 head
-= pipe
->native
.length
;
157 static void glink_rpm_tx_write(struct qcom_glink_pipe
*glink_pipe
,
158 const void *hdr
, size_t hlen
,
159 const void *data
, size_t dlen
)
161 struct glink_rpm_pipe
*pipe
= to_rpm_pipe(glink_pipe
);
162 size_t tlen
= hlen
+ dlen
;
165 char padding
[8] = {0};
168 /* Header length comes from glink native and is always 4 byte aligned */
169 if (WARN(hlen
% 4, "Glink Header length must be 4 bytes aligned\n"))
173 * Move the unaligned tail of the message to the padding chunk, to
174 * ensure word aligned accesses
176 aligned_dlen
= ALIGN_DOWN(dlen
, 4);
177 if (aligned_dlen
!= dlen
)
178 memcpy(padding
, data
+ aligned_dlen
, dlen
- aligned_dlen
);
180 head
= readl(pipe
->head
);
181 head
= glink_rpm_tx_write_one(pipe
, head
, hdr
, hlen
);
182 head
= glink_rpm_tx_write_one(pipe
, head
, data
, aligned_dlen
);
184 pad
= ALIGN(tlen
, 8) - ALIGN_DOWN(tlen
, 4);
186 head
= glink_rpm_tx_write_one(pipe
, head
, padding
, pad
);
187 writel(head
, pipe
->head
);
190 static int glink_rpm_parse_toc(struct device
*dev
,
191 void __iomem
*msg_ram
,
193 struct glink_rpm_pipe
*rx
,
194 struct glink_rpm_pipe
*tx
)
204 buf
= kzalloc(RPM_TOC_SIZE
, GFP_KERNEL
);
208 __ioread32_copy(buf
, msg_ram
+ msg_ram_size
- RPM_TOC_SIZE
,
209 RPM_TOC_SIZE
/ sizeof(u32
));
213 if (le32_to_cpu(toc
->magic
) != RPM_TOC_MAGIC
) {
214 dev_err(dev
, "RPM TOC has invalid magic\n");
218 num_entries
= le32_to_cpu(toc
->count
);
219 if (num_entries
> RPM_TOC_MAX_ENTRIES
) {
220 dev_err(dev
, "Invalid number of toc entries\n");
224 for (i
= 0; i
< num_entries
; i
++) {
225 id
= le32_to_cpu(toc
->entries
[i
].id
);
226 offset
= le32_to_cpu(toc
->entries
[i
].offset
);
227 size
= le32_to_cpu(toc
->entries
[i
].size
);
229 if (offset
> msg_ram_size
|| offset
+ size
> msg_ram_size
) {
230 dev_err(dev
, "TOC entry with invalid size\n");
236 rx
->native
.length
= size
;
238 rx
->tail
= msg_ram
+ offset
;
239 rx
->head
= msg_ram
+ offset
+ sizeof(u32
);
240 rx
->fifo
= msg_ram
+ offset
+ 2 * sizeof(u32
);
243 tx
->native
.length
= size
;
245 tx
->tail
= msg_ram
+ offset
;
246 tx
->head
= msg_ram
+ offset
+ sizeof(u32
);
247 tx
->fifo
= msg_ram
+ offset
+ 2 * sizeof(u32
);
252 if (!rx
->fifo
|| !tx
->fifo
) {
253 dev_err(dev
, "Unable to find rx and tx descriptors\n");
265 static int glink_rpm_probe(struct platform_device
*pdev
)
267 struct qcom_glink
*glink
;
268 struct glink_rpm_pipe
*rx_pipe
;
269 struct glink_rpm_pipe
*tx_pipe
;
270 struct device_node
*np
;
271 void __iomem
*msg_ram
;
273 struct device
*dev
= &pdev
->dev
;
277 rx_pipe
= devm_kzalloc(&pdev
->dev
, sizeof(*rx_pipe
), GFP_KERNEL
);
278 tx_pipe
= devm_kzalloc(&pdev
->dev
, sizeof(*tx_pipe
), GFP_KERNEL
);
279 if (!rx_pipe
|| !tx_pipe
)
282 np
= of_parse_phandle(dev
->of_node
, "qcom,rpm-msg-ram", 0);
283 ret
= of_address_to_resource(np
, 0, &r
);
288 msg_ram
= devm_ioremap(dev
, r
.start
, resource_size(&r
));
289 msg_ram_size
= resource_size(&r
);
293 ret
= glink_rpm_parse_toc(dev
, msg_ram
, msg_ram_size
,
298 /* Pipe specific accessors */
299 rx_pipe
->native
.avail
= glink_rpm_rx_avail
;
300 rx_pipe
->native
.peak
= glink_rpm_rx_peak
;
301 rx_pipe
->native
.advance
= glink_rpm_rx_advance
;
302 tx_pipe
->native
.avail
= glink_rpm_tx_avail
;
303 tx_pipe
->native
.write
= glink_rpm_tx_write
;
305 writel(0, tx_pipe
->head
);
306 writel(0, rx_pipe
->tail
);
308 glink
= qcom_glink_native_probe(&pdev
->dev
,
314 return PTR_ERR(glink
);
316 platform_set_drvdata(pdev
, glink
);
321 static int glink_rpm_remove(struct platform_device
*pdev
)
323 struct qcom_glink
*glink
= platform_get_drvdata(pdev
);
325 qcom_glink_native_remove(glink
);
330 static const struct of_device_id glink_rpm_of_match
[] = {
331 { .compatible
= "qcom,glink-rpm" },
334 MODULE_DEVICE_TABLE(of
, glink_rpm_of_match
);
336 static struct platform_driver glink_rpm_driver
= {
337 .probe
= glink_rpm_probe
,
338 .remove
= glink_rpm_remove
,
340 .name
= "qcom_glink_rpm",
341 .of_match_table
= glink_rpm_of_match
,
345 static int __init
glink_rpm_init(void)
347 return platform_driver_register(&glink_rpm_driver
);
349 subsys_initcall(glink_rpm_init
);
351 static void __exit
glink_rpm_exit(void)
353 platform_driver_unregister(&glink_rpm_driver
);
355 module_exit(glink_rpm_exit
);
357 MODULE_AUTHOR("Bjorn Andersson <bjorn.andersson@linaro.org>");
358 MODULE_DESCRIPTION("Qualcomm GLINK RPM driver");
359 MODULE_LICENSE("GPL v2");