^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) // Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) // Copyright (c) 2018, Linaro Limited
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/idr.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/workqueue.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/of_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/soc/qcom/apr.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/soc/qcom/pdr.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/rpmsg.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) struct apr {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) struct rpmsg_endpoint *ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) struct device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) spinlock_t svcs_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) spinlock_t rx_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) struct idr svcs_idr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) int dest_domain_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) struct pdr_handle *pdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) struct workqueue_struct *rxwq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) struct work_struct rx_work;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) struct list_head rx_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) struct apr_rx_buf {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) struct list_head node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) uint8_t buf[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * apr_send_pkt() - Send a apr message from apr device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) * @adev: Pointer to previously registered apr device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) * @pkt: Pointer to apr packet to send
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * Return: Will be an negative on packet size on success.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) int apr_send_pkt(struct apr_device *adev, struct apr_pkt *pkt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) struct apr *apr = dev_get_drvdata(adev->dev.parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) struct apr_hdr *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) spin_lock_irqsave(&adev->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) hdr = &pkt->hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) hdr->src_domain = APR_DOMAIN_APPS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) hdr->src_svc = adev->svc_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) hdr->dest_domain = adev->domain_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) hdr->dest_svc = adev->svc_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) ret = rpmsg_trysend(apr->ch, pkt, hdr->pkt_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) spin_unlock_irqrestore(&adev->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) return ret ? ret : hdr->pkt_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) EXPORT_SYMBOL_GPL(apr_send_pkt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) static void apr_dev_release(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) struct apr_device *adev = to_apr_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) kfree(adev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) static int apr_callback(struct rpmsg_device *rpdev, void *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) int len, void *priv, u32 addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) struct apr *apr = dev_get_drvdata(&rpdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) struct apr_rx_buf *abuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) if (len <= APR_HDR_SIZE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) dev_err(apr->dev, "APR: Improper apr pkt received:%p %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) buf, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) abuf = kzalloc(sizeof(*abuf) + len, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) if (!abuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) abuf->len = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) memcpy(abuf->buf, buf, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) spin_lock_irqsave(&apr->rx_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) list_add_tail(&abuf->node, &apr->rx_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) spin_unlock_irqrestore(&apr->rx_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) queue_work(apr->rxwq, &apr->rx_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) static int apr_do_rx_callback(struct apr *apr, struct apr_rx_buf *abuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) uint16_t hdr_size, msg_type, ver, svc_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) struct apr_device *svc = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) struct apr_driver *adrv = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) struct apr_resp_pkt resp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) struct apr_hdr *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) void *buf = abuf->buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) int len = abuf->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) hdr = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) ver = APR_HDR_FIELD_VER(hdr->hdr_field);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) if (ver > APR_PKT_VER + 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) hdr_size = APR_HDR_FIELD_SIZE_BYTES(hdr->hdr_field);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) if (hdr_size < APR_HDR_SIZE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) dev_err(apr->dev, "APR: Wrong hdr size:%d\n", hdr_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) if (hdr->pkt_size < APR_HDR_SIZE || hdr->pkt_size != len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) dev_err(apr->dev, "APR: Wrong packet size\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) msg_type = APR_HDR_FIELD_MT(hdr->hdr_field);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) if (msg_type >= APR_MSG_TYPE_MAX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) dev_err(apr->dev, "APR: Wrong message type: %d\n", msg_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) return -EINVAL;
^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 (hdr->src_domain >= APR_DOMAIN_MAX ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) hdr->dest_domain >= APR_DOMAIN_MAX ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) hdr->src_svc >= APR_SVC_MAX ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) hdr->dest_svc >= APR_SVC_MAX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) dev_err(apr->dev, "APR: Wrong APR header\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) svc_id = hdr->dest_svc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) spin_lock_irqsave(&apr->svcs_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) svc = idr_find(&apr->svcs_idr, svc_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) if (svc && svc->dev.driver)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) adrv = to_apr_driver(svc->dev.driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) spin_unlock_irqrestore(&apr->svcs_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) if (!adrv) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) dev_err(apr->dev, "APR: service is not registered\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) resp.hdr = *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) resp.payload_size = hdr->pkt_size - hdr_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) * NOTE: hdr_size is not same as APR_HDR_SIZE as remote can include
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) * optional headers in to apr_hdr which should be ignored
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) if (resp.payload_size > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) resp.payload = buf + hdr_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) adrv->callback(svc, &resp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) static void apr_rxwq(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) struct apr *apr = container_of(work, struct apr, rx_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) struct apr_rx_buf *abuf, *b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) if (!list_empty(&apr->rx_list)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) list_for_each_entry_safe(abuf, b, &apr->rx_list, node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) apr_do_rx_callback(apr, abuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) spin_lock_irqsave(&apr->rx_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) list_del(&abuf->node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) spin_unlock_irqrestore(&apr->rx_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) kfree(abuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) static int apr_device_match(struct device *dev, struct device_driver *drv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) struct apr_device *adev = to_apr_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) struct apr_driver *adrv = to_apr_driver(drv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) const struct apr_device_id *id = adrv->id_table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) /* Attempt an OF style match first */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) if (of_driver_match_device(dev, drv))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) if (!id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) while (id->domain_id != 0 || id->svc_id != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) if (id->domain_id == adev->domain_id &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) id->svc_id == adev->svc_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) id++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) static int apr_device_probe(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) struct apr_device *adev = to_apr_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) struct apr_driver *adrv = to_apr_driver(dev->driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) return adrv->probe(adev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) static int apr_device_remove(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) struct apr_device *adev = to_apr_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) struct apr_driver *adrv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) struct apr *apr = dev_get_drvdata(adev->dev.parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) if (dev->driver) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) adrv = to_apr_driver(dev->driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) if (adrv->remove)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) adrv->remove(adev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) spin_lock(&apr->svcs_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) idr_remove(&apr->svcs_idr, adev->svc_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) spin_unlock(&apr->svcs_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) static int apr_uevent(struct device *dev, struct kobj_uevent_env *env)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) struct apr_device *adev = to_apr_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) ret = of_device_uevent_modalias(dev, env);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) if (ret != -ENODEV)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) return add_uevent_var(env, "MODALIAS=apr:%s", adev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) struct bus_type aprbus = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) .name = "aprbus",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) .match = apr_device_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) .probe = apr_device_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) .uevent = apr_uevent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) .remove = apr_device_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) EXPORT_SYMBOL_GPL(aprbus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) static int apr_add_device(struct device *dev, struct device_node *np,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) const struct apr_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) struct apr *apr = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) struct apr_device *adev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) adev = kzalloc(sizeof(*adev), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) if (!adev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) spin_lock_init(&adev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) adev->svc_id = id->svc_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) adev->domain_id = id->domain_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) adev->version = id->svc_version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) if (np)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) snprintf(adev->name, APR_NAME_SIZE, "%pOFn", np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) strscpy(adev->name, id->name, APR_NAME_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) dev_set_name(&adev->dev, "aprsvc:%s:%x:%x", adev->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) id->domain_id, id->svc_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) adev->dev.bus = &aprbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) adev->dev.parent = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) adev->dev.of_node = np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) adev->dev.release = apr_dev_release;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) adev->dev.driver = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) spin_lock(&apr->svcs_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) idr_alloc(&apr->svcs_idr, adev, id->svc_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) id->svc_id + 1, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) spin_unlock(&apr->svcs_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) of_property_read_string_index(np, "qcom,protection-domain",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 1, &adev->service_path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) dev_info(dev, "Adding APR dev: %s\n", dev_name(&adev->dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) ret = device_register(&adev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) dev_err(dev, "device_register failed: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) put_device(&adev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) static int of_apr_add_pd_lookups(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) const char *service_name, *service_path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) struct apr *apr = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) struct device_node *node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) struct pdr_service *pds;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) for_each_child_of_node(dev->of_node, node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) ret = of_property_read_string_index(node, "qcom,protection-domain",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 0, &service_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) ret = of_property_read_string_index(node, "qcom,protection-domain",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 1, &service_path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) dev_err(dev, "pdr service path missing: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) of_node_put(node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) pds = pdr_add_lookup(apr->pdr, service_name, service_path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) if (IS_ERR(pds) && PTR_ERR(pds) != -EALREADY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) dev_err(dev, "pdr add lookup failed: %ld\n", PTR_ERR(pds));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) of_node_put(node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) return PTR_ERR(pds);
^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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) static void of_register_apr_devices(struct device *dev, const char *svc_path)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) struct apr *apr = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) struct device_node *node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) const char *service_path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) for_each_child_of_node(dev->of_node, node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) struct apr_device_id id = { {0} };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) * This function is called with svc_path NULL during
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) * apr_probe(), in which case we register any apr devices
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) * without a qcom,protection-domain specified.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) * Then as the protection domains becomes available
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) * (if applicable) this function is again called, but with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) * svc_path representing the service becoming available. In
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) * this case we register any apr devices with a matching
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) * qcom,protection-domain.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) ret = of_property_read_string_index(node, "qcom,protection-domain",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 1, &service_path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) if (svc_path) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) /* skip APR services that are PD independent */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) /* skip APR services whose PD paths don't match */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) if (strcmp(service_path, svc_path))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) /* skip APR services whose PD lookups are registered */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) if (ret == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) if (of_property_read_u32(node, "reg", &id.svc_id))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) id.domain_id = apr->dest_domain_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) if (apr_add_device(dev, node, &id))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) dev_err(dev, "Failed to add apr %d svc\n", id.svc_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) static int apr_remove_device(struct device *dev, void *svc_path)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) struct apr_device *adev = to_apr_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) if (svc_path && adev->service_path) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) if (!strcmp(adev->service_path, (char *)svc_path))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) device_unregister(&adev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) device_unregister(&adev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) static void apr_pd_status(int state, char *svc_path, void *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) struct apr *apr = (struct apr *)priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) switch (state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) case SERVREG_SERVICE_STATE_UP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) of_register_apr_devices(apr->dev, svc_path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) case SERVREG_SERVICE_STATE_DOWN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) device_for_each_child(apr->dev, svc_path, apr_remove_device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) static int apr_probe(struct rpmsg_device *rpdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) struct device *dev = &rpdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) struct apr *apr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) apr = devm_kzalloc(dev, sizeof(*apr), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) if (!apr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) ret = of_property_read_u32(dev->of_node, "qcom,apr-domain", &apr->dest_domain_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) dev_err(dev, "APR Domain ID not specified in DT\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) dev_set_drvdata(dev, apr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) apr->ch = rpdev->ept;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) apr->dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) apr->rxwq = create_singlethread_workqueue("qcom_apr_rx");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) if (!apr->rxwq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) dev_err(apr->dev, "Failed to start Rx WQ\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) INIT_WORK(&apr->rx_work, apr_rxwq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) apr->pdr = pdr_handle_alloc(apr_pd_status, apr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) if (IS_ERR(apr->pdr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) dev_err(dev, "Failed to init PDR handle\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) ret = PTR_ERR(apr->pdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) goto destroy_wq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) INIT_LIST_HEAD(&apr->rx_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) spin_lock_init(&apr->rx_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) spin_lock_init(&apr->svcs_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) idr_init(&apr->svcs_idr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) ret = of_apr_add_pd_lookups(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) goto handle_release;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) of_register_apr_devices(dev, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) handle_release:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) pdr_handle_release(apr->pdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) destroy_wq:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) destroy_workqueue(apr->rxwq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) static void apr_remove(struct rpmsg_device *rpdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) struct apr *apr = dev_get_drvdata(&rpdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) pdr_handle_release(apr->pdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) device_for_each_child(&rpdev->dev, NULL, apr_remove_device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) flush_workqueue(apr->rxwq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) destroy_workqueue(apr->rxwq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) * __apr_driver_register() - Client driver registration with aprbus
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) * @drv:Client driver to be associated with client-device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) * @owner: owning module/driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) * This API will register the client driver with the aprbus
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) * It is called from the driver's module-init function.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) int __apr_driver_register(struct apr_driver *drv, struct module *owner)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) drv->driver.bus = &aprbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) drv->driver.owner = owner;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) return driver_register(&drv->driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) EXPORT_SYMBOL_GPL(__apr_driver_register);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) * apr_driver_unregister() - Undo effect of apr_driver_register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) * @drv: Client driver to be unregistered
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) void apr_driver_unregister(struct apr_driver *drv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) driver_unregister(&drv->driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) EXPORT_SYMBOL_GPL(apr_driver_unregister);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) static const struct of_device_id apr_of_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) { .compatible = "qcom,apr"},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) { .compatible = "qcom,apr-v2"},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) MODULE_DEVICE_TABLE(of, apr_of_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) static struct rpmsg_driver apr_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) .probe = apr_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) .remove = apr_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) .callback = apr_callback,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) .drv = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) .name = "qcom,apr",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) .of_match_table = apr_of_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) static int __init apr_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) ret = bus_register(&aprbus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) ret = register_rpmsg_driver(&apr_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) bus_unregister(&aprbus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) static void __exit apr_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) bus_unregister(&aprbus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) unregister_rpmsg_driver(&apr_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) subsys_initcall(apr_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) module_exit(apr_exit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) MODULE_LICENSE("GPL v2");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) MODULE_DESCRIPTION("Qualcomm APR Bus");