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