0001
0002
0003
0004
0005
0006 #include <linux/idr.h>
0007 #include <linux/interrupt.h>
0008 #include <linux/io.h>
0009 #include <linux/list.h>
0010 #include <linux/mfd/syscon.h>
0011 #include <linux/module.h>
0012 #include <linux/of.h>
0013 #include <linux/of_address.h>
0014 #include <linux/platform_device.h>
0015 #include <linux/regmap.h>
0016 #include <linux/rpmsg.h>
0017 #include <linux/slab.h>
0018 #include <linux/workqueue.h>
0019 #include <linux/mailbox_client.h>
0020
0021 #include "rpmsg_internal.h"
0022 #include "qcom_glink_native.h"
0023
0024 #define RPM_TOC_SIZE 256
0025 #define RPM_TOC_MAGIC 0x67727430
0026 #define RPM_TOC_MAX_ENTRIES ((RPM_TOC_SIZE - sizeof(struct rpm_toc)) / \
0027 sizeof(struct rpm_toc_entry))
0028
0029 #define RPM_TX_FIFO_ID 0x61703272
0030 #define RPM_RX_FIFO_ID 0x72326170
0031
0032 #define to_rpm_pipe(p) container_of(p, struct glink_rpm_pipe, native)
0033
0034 struct rpm_toc_entry {
0035 __le32 id;
0036 __le32 offset;
0037 __le32 size;
0038 } __packed;
0039
0040 struct rpm_toc {
0041 __le32 magic;
0042 __le32 count;
0043
0044 struct rpm_toc_entry entries[];
0045 } __packed;
0046
0047 struct glink_rpm_pipe {
0048 struct qcom_glink_pipe native;
0049
0050 void __iomem *tail;
0051 void __iomem *head;
0052
0053 void __iomem *fifo;
0054 };
0055
0056 static size_t glink_rpm_rx_avail(struct qcom_glink_pipe *glink_pipe)
0057 {
0058 struct glink_rpm_pipe *pipe = to_rpm_pipe(glink_pipe);
0059 unsigned int head;
0060 unsigned int tail;
0061
0062 head = readl(pipe->head);
0063 tail = readl(pipe->tail);
0064
0065 if (head < tail)
0066 return pipe->native.length - tail + head;
0067 else
0068 return head - tail;
0069 }
0070
0071 static void glink_rpm_rx_peak(struct qcom_glink_pipe *glink_pipe,
0072 void *data, unsigned int offset, size_t count)
0073 {
0074 struct glink_rpm_pipe *pipe = to_rpm_pipe(glink_pipe);
0075 unsigned int tail;
0076 size_t len;
0077
0078 tail = readl(pipe->tail);
0079 tail += offset;
0080 if (tail >= pipe->native.length)
0081 tail -= pipe->native.length;
0082
0083 len = min_t(size_t, count, pipe->native.length - tail);
0084 if (len) {
0085 __ioread32_copy(data, pipe->fifo + tail,
0086 len / sizeof(u32));
0087 }
0088
0089 if (len != count) {
0090 __ioread32_copy(data + len, pipe->fifo,
0091 (count - len) / sizeof(u32));
0092 }
0093 }
0094
0095 static void glink_rpm_rx_advance(struct qcom_glink_pipe *glink_pipe,
0096 size_t count)
0097 {
0098 struct glink_rpm_pipe *pipe = to_rpm_pipe(glink_pipe);
0099 unsigned int tail;
0100
0101 tail = readl(pipe->tail);
0102
0103 tail += count;
0104 if (tail >= pipe->native.length)
0105 tail -= pipe->native.length;
0106
0107 writel(tail, pipe->tail);
0108 }
0109
0110 static size_t glink_rpm_tx_avail(struct qcom_glink_pipe *glink_pipe)
0111 {
0112 struct glink_rpm_pipe *pipe = to_rpm_pipe(glink_pipe);
0113 unsigned int head;
0114 unsigned int tail;
0115
0116 head = readl(pipe->head);
0117 tail = readl(pipe->tail);
0118
0119 if (tail <= head)
0120 return pipe->native.length - head + tail;
0121 else
0122 return tail - head;
0123 }
0124
0125 static unsigned int glink_rpm_tx_write_one(struct glink_rpm_pipe *pipe,
0126 unsigned int head,
0127 const void *data, size_t count)
0128 {
0129 size_t len;
0130
0131 len = min_t(size_t, count, pipe->native.length - head);
0132 if (len) {
0133 __iowrite32_copy(pipe->fifo + head, data,
0134 len / sizeof(u32));
0135 }
0136
0137 if (len != count) {
0138 __iowrite32_copy(pipe->fifo, data + len,
0139 (count - len) / sizeof(u32));
0140 }
0141
0142 head += count;
0143 if (head >= pipe->native.length)
0144 head -= pipe->native.length;
0145
0146 return head;
0147 }
0148
0149 static void glink_rpm_tx_write(struct qcom_glink_pipe *glink_pipe,
0150 const void *hdr, size_t hlen,
0151 const void *data, size_t dlen)
0152 {
0153 struct glink_rpm_pipe *pipe = to_rpm_pipe(glink_pipe);
0154 size_t tlen = hlen + dlen;
0155 size_t aligned_dlen;
0156 unsigned int head;
0157 char padding[8] = {0};
0158 size_t pad;
0159
0160
0161 if (WARN(hlen % 4, "Glink Header length must be 4 bytes aligned\n"))
0162 return;
0163
0164
0165
0166
0167
0168 aligned_dlen = ALIGN_DOWN(dlen, 4);
0169 if (aligned_dlen != dlen)
0170 memcpy(padding, data + aligned_dlen, dlen - aligned_dlen);
0171
0172 head = readl(pipe->head);
0173 head = glink_rpm_tx_write_one(pipe, head, hdr, hlen);
0174 head = glink_rpm_tx_write_one(pipe, head, data, aligned_dlen);
0175
0176 pad = ALIGN(tlen, 8) - ALIGN_DOWN(tlen, 4);
0177 if (pad)
0178 head = glink_rpm_tx_write_one(pipe, head, padding, pad);
0179 writel(head, pipe->head);
0180 }
0181
0182 static int glink_rpm_parse_toc(struct device *dev,
0183 void __iomem *msg_ram,
0184 size_t msg_ram_size,
0185 struct glink_rpm_pipe *rx,
0186 struct glink_rpm_pipe *tx)
0187 {
0188 struct rpm_toc *toc;
0189 int num_entries;
0190 unsigned int id;
0191 size_t offset;
0192 size_t size;
0193 void *buf;
0194 int i;
0195
0196 buf = kzalloc(RPM_TOC_SIZE, GFP_KERNEL);
0197 if (!buf)
0198 return -ENOMEM;
0199
0200 __ioread32_copy(buf, msg_ram + msg_ram_size - RPM_TOC_SIZE,
0201 RPM_TOC_SIZE / sizeof(u32));
0202
0203 toc = buf;
0204
0205 if (le32_to_cpu(toc->magic) != RPM_TOC_MAGIC) {
0206 dev_err(dev, "RPM TOC has invalid magic\n");
0207 goto err_inval;
0208 }
0209
0210 num_entries = le32_to_cpu(toc->count);
0211 if (num_entries > RPM_TOC_MAX_ENTRIES) {
0212 dev_err(dev, "Invalid number of toc entries\n");
0213 goto err_inval;
0214 }
0215
0216 for (i = 0; i < num_entries; i++) {
0217 id = le32_to_cpu(toc->entries[i].id);
0218 offset = le32_to_cpu(toc->entries[i].offset);
0219 size = le32_to_cpu(toc->entries[i].size);
0220
0221 if (offset > msg_ram_size || offset + size > msg_ram_size) {
0222 dev_err(dev, "TOC entry with invalid size\n");
0223 continue;
0224 }
0225
0226 switch (id) {
0227 case RPM_RX_FIFO_ID:
0228 rx->native.length = size;
0229
0230 rx->tail = msg_ram + offset;
0231 rx->head = msg_ram + offset + sizeof(u32);
0232 rx->fifo = msg_ram + offset + 2 * sizeof(u32);
0233 break;
0234 case RPM_TX_FIFO_ID:
0235 tx->native.length = size;
0236
0237 tx->tail = msg_ram + offset;
0238 tx->head = msg_ram + offset + sizeof(u32);
0239 tx->fifo = msg_ram + offset + 2 * sizeof(u32);
0240 break;
0241 }
0242 }
0243
0244 if (!rx->fifo || !tx->fifo) {
0245 dev_err(dev, "Unable to find rx and tx descriptors\n");
0246 goto err_inval;
0247 }
0248
0249 kfree(buf);
0250 return 0;
0251
0252 err_inval:
0253 kfree(buf);
0254 return -EINVAL;
0255 }
0256
0257 static int glink_rpm_probe(struct platform_device *pdev)
0258 {
0259 struct qcom_glink *glink;
0260 struct glink_rpm_pipe *rx_pipe;
0261 struct glink_rpm_pipe *tx_pipe;
0262 struct device_node *np;
0263 void __iomem *msg_ram;
0264 size_t msg_ram_size;
0265 struct device *dev = &pdev->dev;
0266 struct resource r;
0267 int ret;
0268
0269 rx_pipe = devm_kzalloc(&pdev->dev, sizeof(*rx_pipe), GFP_KERNEL);
0270 tx_pipe = devm_kzalloc(&pdev->dev, sizeof(*tx_pipe), GFP_KERNEL);
0271 if (!rx_pipe || !tx_pipe)
0272 return -ENOMEM;
0273
0274 np = of_parse_phandle(dev->of_node, "qcom,rpm-msg-ram", 0);
0275 ret = of_address_to_resource(np, 0, &r);
0276 of_node_put(np);
0277 if (ret)
0278 return ret;
0279
0280 msg_ram = devm_ioremap(dev, r.start, resource_size(&r));
0281 msg_ram_size = resource_size(&r);
0282 if (!msg_ram)
0283 return -ENOMEM;
0284
0285 ret = glink_rpm_parse_toc(dev, msg_ram, msg_ram_size,
0286 rx_pipe, tx_pipe);
0287 if (ret)
0288 return ret;
0289
0290
0291 rx_pipe->native.avail = glink_rpm_rx_avail;
0292 rx_pipe->native.peak = glink_rpm_rx_peak;
0293 rx_pipe->native.advance = glink_rpm_rx_advance;
0294 tx_pipe->native.avail = glink_rpm_tx_avail;
0295 tx_pipe->native.write = glink_rpm_tx_write;
0296
0297 writel(0, tx_pipe->head);
0298 writel(0, rx_pipe->tail);
0299
0300 glink = qcom_glink_native_probe(&pdev->dev,
0301 0,
0302 &rx_pipe->native,
0303 &tx_pipe->native,
0304 true);
0305 if (IS_ERR(glink))
0306 return PTR_ERR(glink);
0307
0308 platform_set_drvdata(pdev, glink);
0309
0310 return 0;
0311 }
0312
0313 static int glink_rpm_remove(struct platform_device *pdev)
0314 {
0315 struct qcom_glink *glink = platform_get_drvdata(pdev);
0316
0317 qcom_glink_native_remove(glink);
0318
0319 return 0;
0320 }
0321
0322 static const struct of_device_id glink_rpm_of_match[] = {
0323 { .compatible = "qcom,glink-rpm" },
0324 {}
0325 };
0326 MODULE_DEVICE_TABLE(of, glink_rpm_of_match);
0327
0328 static struct platform_driver glink_rpm_driver = {
0329 .probe = glink_rpm_probe,
0330 .remove = glink_rpm_remove,
0331 .driver = {
0332 .name = "qcom_glink_rpm",
0333 .of_match_table = glink_rpm_of_match,
0334 },
0335 };
0336
0337 static int __init glink_rpm_init(void)
0338 {
0339 return platform_driver_register(&glink_rpm_driver);
0340 }
0341 subsys_initcall(glink_rpm_init);
0342
0343 static void __exit glink_rpm_exit(void)
0344 {
0345 platform_driver_unregister(&glink_rpm_driver);
0346 }
0347 module_exit(glink_rpm_exit);
0348
0349 MODULE_AUTHOR("Bjorn Andersson <bjorn.andersson@linaro.org>");
0350 MODULE_DESCRIPTION("Qualcomm GLINK RPM driver");
0351 MODULE_LICENSE("GPL v2");