Lines Matching +full:apr +full:- +full:v2
1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
13 #include <linux/soc/qcom/apr.h>
43 * apr_send_pkt() - Send a apr message from apr device
45 * @adev: Pointer to previously registered apr device.
46 * @pkt: Pointer to apr packet to send
52 struct packet_router *apr = dev_get_drvdata(adev->dev.parent); in apr_send_pkt() local
57 spin_lock_irqsave(&adev->svc.lock, flags); in apr_send_pkt()
59 hdr = &pkt->hdr; in apr_send_pkt()
60 hdr->src_domain = APR_DOMAIN_APPS; in apr_send_pkt()
61 hdr->src_svc = adev->svc.id; in apr_send_pkt()
62 hdr->dest_domain = adev->domain_id; in apr_send_pkt()
63 hdr->dest_svc = adev->svc.id; in apr_send_pkt()
65 ret = rpmsg_trysend(apr->ch, pkt, hdr->pkt_size); in apr_send_pkt()
66 spin_unlock_irqrestore(&adev->svc.lock, flags); in apr_send_pkt()
68 return ret ? ret : hdr->pkt_size; in apr_send_pkt()
82 struct packet_router *apr = dev_get_drvdata(&rpdev->dev); in apr_callback() local
87 dev_err(apr->dev, "APR: Improper apr pkt received:%p %d\n", in apr_callback()
89 return -EINVAL; in apr_callback()
94 return -ENOMEM; in apr_callback()
96 abuf->len = len; in apr_callback()
97 memcpy(abuf->buf, buf, len); in apr_callback()
99 spin_lock_irqsave(&apr->rx_lock, flags); in apr_callback()
100 list_add_tail(&abuf->node, &apr->rx_list); in apr_callback()
101 spin_unlock_irqrestore(&apr->rx_lock, flags); in apr_callback()
103 queue_work(apr->rxwq, &apr->rx_work); in apr_callback()
108 static int apr_do_rx_callback(struct packet_router *apr, struct apr_rx_buf *abuf) in apr_do_rx_callback() argument
117 void *buf = abuf->buf; in apr_do_rx_callback()
118 int len = abuf->len; in apr_do_rx_callback()
121 ver = APR_HDR_FIELD_VER(hdr->hdr_field); in apr_do_rx_callback()
123 return -EINVAL; in apr_do_rx_callback()
125 hdr_size = APR_HDR_FIELD_SIZE_BYTES(hdr->hdr_field); in apr_do_rx_callback()
127 dev_err(apr->dev, "APR: Wrong hdr size:%d\n", hdr_size); in apr_do_rx_callback()
128 return -EINVAL; in apr_do_rx_callback()
131 if (hdr->pkt_size < APR_HDR_SIZE || hdr->pkt_size != len) { in apr_do_rx_callback()
132 dev_err(apr->dev, "APR: Wrong packet size\n"); in apr_do_rx_callback()
133 return -EINVAL; in apr_do_rx_callback()
136 msg_type = APR_HDR_FIELD_MT(hdr->hdr_field); in apr_do_rx_callback()
138 dev_err(apr->dev, "APR: Wrong message type: %d\n", msg_type); in apr_do_rx_callback()
139 return -EINVAL; in apr_do_rx_callback()
142 if (hdr->src_domain >= APR_DOMAIN_MAX || in apr_do_rx_callback()
143 hdr->dest_domain >= APR_DOMAIN_MAX || in apr_do_rx_callback()
144 hdr->src_svc >= APR_SVC_MAX || in apr_do_rx_callback()
145 hdr->dest_svc >= APR_SVC_MAX) { in apr_do_rx_callback()
146 dev_err(apr->dev, "APR: Wrong APR header\n"); in apr_do_rx_callback()
147 return -EINVAL; in apr_do_rx_callback()
150 svc_id = hdr->dest_svc; in apr_do_rx_callback()
151 spin_lock_irqsave(&apr->svcs_lock, flags); in apr_do_rx_callback()
152 svc = idr_find(&apr->svcs_idr, svc_id); in apr_do_rx_callback()
153 if (svc && svc->dev->driver) { in apr_do_rx_callback()
155 adrv = to_apr_driver(adev->dev.driver); in apr_do_rx_callback()
157 spin_unlock_irqrestore(&apr->svcs_lock, flags); in apr_do_rx_callback()
160 dev_err(apr->dev, "APR: service is not registered (%d)\n", in apr_do_rx_callback()
162 return -EINVAL; in apr_do_rx_callback()
166 resp.payload_size = hdr->pkt_size - hdr_size; in apr_do_rx_callback()
175 adrv->callback(adev, &resp); in apr_do_rx_callback()
182 struct packet_router *apr = container_of(work, struct packet_router, rx_work); in apr_rxwq() local
186 if (!list_empty(&apr->rx_list)) { in apr_rxwq()
187 list_for_each_entry_safe(abuf, b, &apr->rx_list, node) { in apr_rxwq()
188 switch (apr->type) { in apr_rxwq()
190 apr_do_rx_callback(apr, abuf); in apr_rxwq()
195 spin_lock_irqsave(&apr->rx_lock, flags); in apr_rxwq()
196 list_del(&abuf->node); in apr_rxwq()
197 spin_unlock_irqrestore(&apr->rx_lock, flags); in apr_rxwq()
207 const struct apr_device_id *id = adrv->id_table; in apr_device_match()
216 while (id->domain_id != 0 || id->svc_id != 0) { in apr_device_match()
217 if (id->domain_id == adev->domain_id && in apr_device_match()
218 id->svc_id == adev->svc.id) in apr_device_match()
229 struct apr_driver *adrv = to_apr_driver(dev->driver); in apr_device_probe()
231 return adrv->probe(adev); in apr_device_probe()
238 struct packet_router *apr = dev_get_drvdata(adev->dev.parent); in apr_device_remove() local
240 if (dev->driver) { in apr_device_remove()
241 adrv = to_apr_driver(dev->driver); in apr_device_remove()
242 if (adrv->remove) in apr_device_remove()
243 adrv->remove(adev); in apr_device_remove()
244 spin_lock(&apr->svcs_lock); in apr_device_remove()
245 idr_remove(&apr->svcs_idr, adev->svc.id); in apr_device_remove()
246 spin_unlock(&apr->svcs_lock); in apr_device_remove()
258 if (ret != -ENODEV) in apr_uevent()
261 return add_uevent_var(env, "MODALIAS=apr:%s", adev->name); in apr_uevent()
276 struct packet_router *apr = dev_get_drvdata(dev); in apr_add_device() local
283 return -ENOMEM; in apr_add_device()
285 adev->svc_id = svc_id; in apr_add_device()
286 svc = &adev->svc; in apr_add_device()
288 svc->id = svc_id; in apr_add_device()
289 svc->pr = apr; in apr_add_device()
290 svc->priv = adev; in apr_add_device()
291 svc->dev = dev; in apr_add_device()
292 spin_lock_init(&svc->lock); in apr_add_device()
294 adev->domain_id = domain_id; in apr_add_device()
297 snprintf(adev->name, APR_NAME_SIZE, "%pOFn", np); in apr_add_device()
299 switch (apr->type) { in apr_add_device()
301 dev_set_name(&adev->dev, "aprsvc:%s:%x:%x", adev->name, in apr_add_device()
308 adev->dev.bus = &aprbus; in apr_add_device()
309 adev->dev.parent = dev; in apr_add_device()
310 adev->dev.of_node = np; in apr_add_device()
311 adev->dev.release = apr_dev_release; in apr_add_device()
312 adev->dev.driver = NULL; in apr_add_device()
314 spin_lock(&apr->svcs_lock); in apr_add_device()
315 ret = idr_alloc(&apr->svcs_idr, svc, svc_id, svc_id + 1, GFP_ATOMIC); in apr_add_device()
316 spin_unlock(&apr->svcs_lock); in apr_add_device()
323 ret = of_property_read_string_index(np, "qcom,protection-domain", in apr_add_device()
324 1, &adev->service_path); in apr_add_device()
325 if (ret < 0 && ret != -EINVAL) { in apr_add_device()
326 dev_err(dev, "Failed to read second value of qcom,protection-domain\n"); in apr_add_device()
330 dev_info(dev, "Adding APR dev: %s\n", dev_name(&adev->dev)); in apr_add_device()
332 ret = device_register(&adev->dev); in apr_add_device()
335 put_device(&adev->dev); in apr_add_device()
345 struct packet_router *apr = dev_get_drvdata(dev); in of_apr_add_pd_lookups() local
350 for_each_child_of_node(dev->of_node, node) { in of_apr_add_pd_lookups()
351 ret = of_property_read_string_index(node, "qcom,protection-domain", in of_apr_add_pd_lookups()
356 ret = of_property_read_string_index(node, "qcom,protection-domain", in of_apr_add_pd_lookups()
364 pds = pdr_add_lookup(apr->pdr, service_name, service_path); in of_apr_add_pd_lookups()
365 if (IS_ERR(pds) && PTR_ERR(pds) != -EALREADY) { in of_apr_add_pd_lookups()
377 struct packet_router *apr = dev_get_drvdata(dev); in of_register_apr_devices() local
382 for_each_child_of_node(dev->of_node, node) { in of_register_apr_devices()
388 * apr_probe(), in which case we register any apr devices in of_register_apr_devices()
389 * without a qcom,protection-domain specified. in of_register_apr_devices()
394 * this case we register any apr devices with a matching in of_register_apr_devices()
395 * qcom,protection-domain. in of_register_apr_devices()
398 ret = of_property_read_string_index(node, "qcom,protection-domain", in of_register_apr_devices()
401 /* skip APR services that are PD independent */ in of_register_apr_devices()
405 /* skip APR services whose PD paths don't match */ in of_register_apr_devices()
409 /* skip APR services whose PD lookups are registered */ in of_register_apr_devices()
417 domain_id = apr->dest_domain_id; in of_register_apr_devices()
420 dev_err(dev, "Failed to add apr %d svc\n", svc_id); in of_register_apr_devices()
428 if (svc_path && adev->service_path) { in apr_remove_device()
429 if (!strcmp(adev->service_path, (char *)svc_path)) in apr_remove_device()
430 device_unregister(&adev->dev); in apr_remove_device()
432 device_unregister(&adev->dev); in apr_remove_device()
440 struct packet_router *apr = (struct packet_router *)priv; in apr_pd_status() local
444 of_register_apr_devices(apr->dev, svc_path); in apr_pd_status()
447 device_for_each_child(apr->dev, svc_path, apr_remove_device); in apr_pd_status()
454 struct device *dev = &rpdev->dev; in apr_probe()
455 struct packet_router *apr; in apr_probe() local
458 apr = devm_kzalloc(dev, sizeof(*apr), GFP_KERNEL); in apr_probe()
459 if (!apr) in apr_probe()
460 return -ENOMEM; in apr_probe()
462 ret = of_property_read_u32(dev->of_node, "qcom,domain", &apr->dest_domain_id); in apr_probe()
463 if (ret) /* try deprecated apr-domain property */ in apr_probe()
464 ret = of_property_read_u32(dev->of_node, "qcom,apr-domain", in apr_probe()
465 &apr->dest_domain_id); in apr_probe()
466 apr->type = PR_TYPE_APR; in apr_probe()
472 dev_set_drvdata(dev, apr); in apr_probe()
473 apr->ch = rpdev->ept; in apr_probe()
474 apr->dev = dev; in apr_probe()
475 apr->rxwq = create_singlethread_workqueue("qcom_apr_rx"); in apr_probe()
476 if (!apr->rxwq) { in apr_probe()
477 dev_err(apr->dev, "Failed to start Rx WQ\n"); in apr_probe()
478 return -ENOMEM; in apr_probe()
480 INIT_WORK(&apr->rx_work, apr_rxwq); in apr_probe()
482 apr->pdr = pdr_handle_alloc(apr_pd_status, apr); in apr_probe()
483 if (IS_ERR(apr->pdr)) { in apr_probe()
485 ret = PTR_ERR(apr->pdr); in apr_probe()
489 INIT_LIST_HEAD(&apr->rx_list); in apr_probe()
490 spin_lock_init(&apr->rx_lock); in apr_probe()
491 spin_lock_init(&apr->svcs_lock); in apr_probe()
492 idr_init(&apr->svcs_idr); in apr_probe()
503 pdr_handle_release(apr->pdr); in apr_probe()
505 destroy_workqueue(apr->rxwq); in apr_probe()
511 struct packet_router *apr = dev_get_drvdata(&rpdev->dev); in apr_remove() local
513 pdr_handle_release(apr->pdr); in apr_remove()
514 device_for_each_child(&rpdev->dev, NULL, apr_remove_device); in apr_remove()
515 flush_workqueue(apr->rxwq); in apr_remove()
516 destroy_workqueue(apr->rxwq); in apr_remove()
520 * __apr_driver_register() - Client driver registration with aprbus
522 * @drv:Client driver to be associated with client-device.
526 * It is called from the driver's module-init function.
530 drv->driver.bus = &aprbus; in __apr_driver_register()
531 drv->driver.owner = owner; in __apr_driver_register()
533 return driver_register(&drv->driver); in __apr_driver_register()
538 * apr_driver_unregister() - Undo effect of apr_driver_register
544 driver_unregister(&drv->driver); in apr_driver_unregister()
549 { .compatible = "qcom,apr"},
550 { .compatible = "qcom,apr-v2"},
560 .name = "qcom,apr",
587 MODULE_LICENSE("GPL v2");
588 MODULE_DESCRIPTION("Qualcomm APR Bus");