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