1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (c) 2016-2017, Linaro Ltd 4 */ 5 6 #include <linux/idr.h> 7 #include <linux/interrupt.h> 8 #include <linux/io.h> 9 #include <linux/list.h> 10 #include <linux/mfd/syscon.h> 11 #include <linux/module.h> 12 #include <linux/of.h> 13 #include <linux/of_address.h> 14 #include <linux/platform_device.h> 15 #include <linux/regmap.h> 16 #include <linux/rpmsg.h> 17 #include <linux/slab.h> 18 #include <linux/workqueue.h> 19 #include <linux/mailbox_client.h> 20 21 #include "rpmsg_internal.h" 22 #include "qcom_glink_native.h" 23 24 #define RPM_TOC_SIZE 256 25 #define RPM_TOC_MAGIC 0x67727430 /* grt0 */ 26 #define RPM_TOC_MAX_ENTRIES ((RPM_TOC_SIZE - sizeof(struct rpm_toc)) / \ 27 sizeof(struct rpm_toc_entry)) 28 29 #define RPM_TX_FIFO_ID 0x61703272 /* ap2r */ 30 #define RPM_RX_FIFO_ID 0x72326170 /* r2ap */ 31 32 #define to_rpm_pipe(p) container_of(p, struct glink_rpm_pipe, native) 33 34 struct rpm_toc_entry { 35 __le32 id; 36 __le32 offset; 37 __le32 size; 38 } __packed; 39 40 struct rpm_toc { 41 __le32 magic; 42 __le32 count; 43 44 struct rpm_toc_entry entries[]; 45 } __packed; 46 47 struct glink_rpm_pipe { 48 struct qcom_glink_pipe native; 49 50 void __iomem *tail; 51 void __iomem *head; 52 53 void __iomem *fifo; 54 }; 55 56 struct glink_rpm { 57 struct qcom_glink *glink; 58 59 struct glink_rpm_pipe rx_pipe; 60 struct glink_rpm_pipe tx_pipe; 61 }; 62 63 static size_t glink_rpm_rx_avail(struct qcom_glink_pipe *glink_pipe) 64 { 65 struct glink_rpm_pipe *pipe = to_rpm_pipe(glink_pipe); 66 unsigned int head; 67 unsigned int tail; 68 69 head = readl(pipe->head); 70 tail = readl(pipe->tail); 71 72 if (head < tail) 73 return pipe->native.length - tail + head; 74 else 75 return head - tail; 76 } 77 78 static void glink_rpm_rx_peak(struct qcom_glink_pipe *glink_pipe, 79 void *data, unsigned int offset, size_t count) 80 { 81 struct glink_rpm_pipe *pipe = to_rpm_pipe(glink_pipe); 82 unsigned int tail; 83 size_t len; 84 85 tail = readl(pipe->tail); 86 tail += offset; 87 if (tail >= pipe->native.length) 88 tail -= pipe->native.length; 89 90 len = min_t(size_t, count, pipe->native.length - tail); 91 if (len) { 92 __ioread32_copy(data, pipe->fifo + tail, 93 len / sizeof(u32)); 94 } 95 96 if (len != count) { 97 __ioread32_copy(data + len, pipe->fifo, 98 (count - len) / sizeof(u32)); 99 } 100 } 101 102 static void glink_rpm_rx_advance(struct qcom_glink_pipe *glink_pipe, 103 size_t count) 104 { 105 struct glink_rpm_pipe *pipe = to_rpm_pipe(glink_pipe); 106 unsigned int tail; 107 108 tail = readl(pipe->tail); 109 110 tail += count; 111 if (tail >= pipe->native.length) 112 tail -= pipe->native.length; 113 114 writel(tail, pipe->tail); 115 } 116 117 static size_t glink_rpm_tx_avail(struct qcom_glink_pipe *glink_pipe) 118 { 119 struct glink_rpm_pipe *pipe = to_rpm_pipe(glink_pipe); 120 unsigned int head; 121 unsigned int tail; 122 123 head = readl(pipe->head); 124 tail = readl(pipe->tail); 125 126 if (tail <= head) 127 return pipe->native.length - head + tail; 128 else 129 return tail - head; 130 } 131 132 static unsigned int glink_rpm_tx_write_one(struct glink_rpm_pipe *pipe, 133 unsigned int head, 134 const void *data, size_t count) 135 { 136 size_t len; 137 138 len = min_t(size_t, count, pipe->native.length - head); 139 if (len) { 140 __iowrite32_copy(pipe->fifo + head, data, 141 len / sizeof(u32)); 142 } 143 144 if (len != count) { 145 __iowrite32_copy(pipe->fifo, data + len, 146 (count - len) / sizeof(u32)); 147 } 148 149 head += count; 150 if (head >= pipe->native.length) 151 head -= pipe->native.length; 152 153 return head; 154 } 155 156 static void glink_rpm_tx_write(struct qcom_glink_pipe *glink_pipe, 157 const void *hdr, size_t hlen, 158 const void *data, size_t dlen) 159 { 160 struct glink_rpm_pipe *pipe = to_rpm_pipe(glink_pipe); 161 size_t tlen = hlen + dlen; 162 size_t aligned_dlen; 163 unsigned int head; 164 char padding[8] = {0}; 165 size_t pad; 166 167 /* Header length comes from glink native and is always 4 byte aligned */ 168 if (WARN(hlen % 4, "Glink Header length must be 4 bytes aligned\n")) 169 return; 170 171 /* 172 * Move the unaligned tail of the message to the padding chunk, to 173 * ensure word aligned accesses 174 */ 175 aligned_dlen = ALIGN_DOWN(dlen, 4); 176 if (aligned_dlen != dlen) 177 memcpy(padding, data + aligned_dlen, dlen - aligned_dlen); 178 179 head = readl(pipe->head); 180 head = glink_rpm_tx_write_one(pipe, head, hdr, hlen); 181 head = glink_rpm_tx_write_one(pipe, head, data, aligned_dlen); 182 183 pad = ALIGN(tlen, 8) - ALIGN_DOWN(tlen, 4); 184 if (pad) 185 head = glink_rpm_tx_write_one(pipe, head, padding, pad); 186 writel(head, pipe->head); 187 } 188 189 static int glink_rpm_parse_toc(struct device *dev, 190 void __iomem *msg_ram, 191 size_t msg_ram_size, 192 struct glink_rpm_pipe *rx, 193 struct glink_rpm_pipe *tx) 194 { 195 struct rpm_toc *toc; 196 int num_entries; 197 unsigned int id; 198 size_t offset; 199 size_t size; 200 void *buf; 201 int i; 202 203 buf = kzalloc(RPM_TOC_SIZE, GFP_KERNEL); 204 if (!buf) 205 return -ENOMEM; 206 207 __ioread32_copy(buf, msg_ram + msg_ram_size - RPM_TOC_SIZE, 208 RPM_TOC_SIZE / sizeof(u32)); 209 210 toc = buf; 211 212 if (le32_to_cpu(toc->magic) != RPM_TOC_MAGIC) { 213 dev_err(dev, "RPM TOC has invalid magic\n"); 214 goto err_inval; 215 } 216 217 num_entries = le32_to_cpu(toc->count); 218 if (num_entries > RPM_TOC_MAX_ENTRIES) { 219 dev_err(dev, "Invalid number of toc entries\n"); 220 goto err_inval; 221 } 222 223 for (i = 0; i < num_entries; i++) { 224 id = le32_to_cpu(toc->entries[i].id); 225 offset = le32_to_cpu(toc->entries[i].offset); 226 size = le32_to_cpu(toc->entries[i].size); 227 228 if (offset > msg_ram_size || offset + size > msg_ram_size) { 229 dev_err(dev, "TOC entry with invalid size\n"); 230 continue; 231 } 232 233 switch (id) { 234 case RPM_RX_FIFO_ID: 235 rx->native.length = size; 236 237 rx->tail = msg_ram + offset; 238 rx->head = msg_ram + offset + sizeof(u32); 239 rx->fifo = msg_ram + offset + 2 * sizeof(u32); 240 break; 241 case RPM_TX_FIFO_ID: 242 tx->native.length = size; 243 244 tx->tail = msg_ram + offset; 245 tx->head = msg_ram + offset + sizeof(u32); 246 tx->fifo = msg_ram + offset + 2 * sizeof(u32); 247 break; 248 } 249 } 250 251 if (!rx->fifo || !tx->fifo) { 252 dev_err(dev, "Unable to find rx and tx descriptors\n"); 253 goto err_inval; 254 } 255 256 kfree(buf); 257 return 0; 258 259 err_inval: 260 kfree(buf); 261 return -EINVAL; 262 } 263 264 static int glink_rpm_probe(struct platform_device *pdev) 265 { 266 struct qcom_glink *glink; 267 struct glink_rpm *rpm; 268 struct device_node *np; 269 void __iomem *msg_ram; 270 size_t msg_ram_size; 271 struct device *dev = &pdev->dev; 272 struct resource r; 273 int ret; 274 275 rpm = devm_kzalloc(&pdev->dev, sizeof(*rpm), GFP_KERNEL); 276 if (!rpm) 277 return -ENOMEM; 278 279 np = of_parse_phandle(dev->of_node, "qcom,rpm-msg-ram", 0); 280 ret = of_address_to_resource(np, 0, &r); 281 of_node_put(np); 282 if (ret) 283 return ret; 284 285 msg_ram = devm_ioremap(dev, r.start, resource_size(&r)); 286 msg_ram_size = resource_size(&r); 287 if (!msg_ram) 288 return -ENOMEM; 289 290 ret = glink_rpm_parse_toc(dev, msg_ram, msg_ram_size, 291 &rpm->rx_pipe, &rpm->tx_pipe); 292 if (ret) 293 return ret; 294 295 /* Pipe specific accessors */ 296 rpm->rx_pipe.native.avail = glink_rpm_rx_avail; 297 rpm->rx_pipe.native.peak = glink_rpm_rx_peak; 298 rpm->rx_pipe.native.advance = glink_rpm_rx_advance; 299 rpm->tx_pipe.native.avail = glink_rpm_tx_avail; 300 rpm->tx_pipe.native.write = glink_rpm_tx_write; 301 302 writel(0, rpm->tx_pipe.head); 303 writel(0, rpm->rx_pipe.tail); 304 305 glink = qcom_glink_native_probe(dev, 306 0, 307 &rpm->rx_pipe.native, 308 &rpm->tx_pipe.native, 309 true); 310 if (IS_ERR(glink)) 311 return PTR_ERR(glink); 312 313 rpm->glink = glink; 314 315 platform_set_drvdata(pdev, rpm); 316 317 return 0; 318 } 319 320 static int glink_rpm_remove(struct platform_device *pdev) 321 { 322 struct glink_rpm *rpm = platform_get_drvdata(pdev); 323 struct qcom_glink *glink = rpm->glink; 324 325 qcom_glink_native_remove(glink); 326 327 return 0; 328 } 329 330 static const struct of_device_id glink_rpm_of_match[] = { 331 { .compatible = "qcom,glink-rpm" }, 332 {} 333 }; 334 MODULE_DEVICE_TABLE(of, glink_rpm_of_match); 335 336 static struct platform_driver glink_rpm_driver = { 337 .probe = glink_rpm_probe, 338 .remove = glink_rpm_remove, 339 .driver = { 340 .name = "qcom_glink_rpm", 341 .of_match_table = glink_rpm_of_match, 342 }, 343 }; 344 345 static int __init glink_rpm_init(void) 346 { 347 return platform_driver_register(&glink_rpm_driver); 348 } 349 subsys_initcall(glink_rpm_init); 350 351 static void __exit glink_rpm_exit(void) 352 { 353 platform_driver_unregister(&glink_rpm_driver); 354 } 355 module_exit(glink_rpm_exit); 356 357 MODULE_AUTHOR("Bjorn Andersson <bjorn.andersson@linaro.org>"); 358 MODULE_DESCRIPTION("Qualcomm GLINK RPM driver"); 359 MODULE_LICENSE("GPL v2"); 360