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