Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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");