apr.c 17 KB
Newer Older
1 2 3 4 5 6 7 8 9 10
// SPDX-License-Identifier: GPL-2.0
// Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
// Copyright (c) 2018, Linaro Limited

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/spinlock.h>
#include <linux/idr.h>
#include <linux/slab.h>
11
#include <linux/workqueue.h>
12 13
#include <linux/of_device.h>
#include <linux/soc/qcom/apr.h>
14
#include <linux/soc/qcom/pdr.h>
15 16 17
#include <linux/rpmsg.h>
#include <linux/of.h>

18 19
enum {
	PR_TYPE_APR = 0,
20
	PR_TYPE_GPR,
21 22
};

23 24 25 26
/* Some random values tbh which does not collide with static modules */
#define GPR_DYNAMIC_PORT_START	0x10000000
#define GPR_DYNAMIC_PORT_END	0x20000000

27
struct packet_router {
28 29 30
	struct rpmsg_endpoint *ch;
	struct device *dev;
	spinlock_t svcs_lock;
31
	spinlock_t rx_lock;
32 33
	struct idr svcs_idr;
	int dest_domain_id;
34
	int type;
35
	struct pdr_handle *pdr;
36 37 38 39 40 41 42 43 44
	struct workqueue_struct *rxwq;
	struct work_struct rx_work;
	struct list_head rx_list;
};

struct apr_rx_buf {
	struct list_head node;
	int len;
	uint8_t buf[];
45 46 47 48 49 50 51 52 53 54 55 56
};

/**
 * apr_send_pkt() - Send a apr message from apr device
 *
 * @adev: Pointer to previously registered apr device.
 * @pkt: Pointer to apr packet to send
 *
 * Return: Will be an negative on packet size on success.
 */
int apr_send_pkt(struct apr_device *adev, struct apr_pkt *pkt)
{
57
	struct packet_router *apr = dev_get_drvdata(adev->dev.parent);
58 59 60 61
	struct apr_hdr *hdr;
	unsigned long flags;
	int ret;

62
	spin_lock_irqsave(&adev->svc.lock, flags);
63 64 65

	hdr = &pkt->hdr;
	hdr->src_domain = APR_DOMAIN_APPS;
66
	hdr->src_svc = adev->svc.id;
67
	hdr->dest_domain = adev->domain_id;
68
	hdr->dest_svc = adev->svc.id;
69 70

	ret = rpmsg_trysend(apr->ch, pkt, hdr->pkt_size);
71
	spin_unlock_irqrestore(&adev->svc.lock, flags);
72 73 74 75 76

	return ret ? ret : hdr->pkt_size;
}
EXPORT_SYMBOL_GPL(apr_send_pkt);

77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
void gpr_free_port(gpr_port_t *port)
{
	struct packet_router *gpr = port->pr;
	unsigned long flags;

	spin_lock_irqsave(&gpr->svcs_lock, flags);
	idr_remove(&gpr->svcs_idr, port->id);
	spin_unlock_irqrestore(&gpr->svcs_lock, flags);

	kfree(port);
}
EXPORT_SYMBOL_GPL(gpr_free_port);

gpr_port_t *gpr_alloc_port(struct apr_device *gdev, struct device *dev,
				gpr_port_cb cb,	void *priv)
{
	struct packet_router *pr = dev_get_drvdata(gdev->dev.parent);
	gpr_port_t *port;
	struct pkt_router_svc *svc;
	int id;

	port = kzalloc(sizeof(*port), GFP_KERNEL);
	if (!port)
		return ERR_PTR(-ENOMEM);

	svc = port;
	svc->callback = cb;
	svc->pr = pr;
	svc->priv = priv;
	svc->dev = dev;
	spin_lock_init(&svc->lock);

	spin_lock(&pr->svcs_lock);
	id = idr_alloc_cyclic(&pr->svcs_idr, svc, GPR_DYNAMIC_PORT_START,
			      GPR_DYNAMIC_PORT_END, GFP_ATOMIC);
	if (id < 0) {
		dev_err(dev, "Unable to allocate dynamic GPR src port\n");
		kfree(port);
		spin_unlock(&pr->svcs_lock);
		return ERR_PTR(id);
	}

	svc->id = id;
	spin_unlock(&pr->svcs_lock);

	return port;
}
EXPORT_SYMBOL_GPL(gpr_alloc_port);

static int pkt_router_send_svc_pkt(struct pkt_router_svc *svc, struct gpr_pkt *pkt)
{
	struct packet_router *pr = svc->pr;
	struct gpr_hdr *hdr;
	unsigned long flags;
	int ret;

	hdr = &pkt->hdr;

	spin_lock_irqsave(&svc->lock, flags);
	ret = rpmsg_trysend(pr->ch, pkt, hdr->pkt_size);
	spin_unlock_irqrestore(&svc->lock, flags);

	return ret ? ret : hdr->pkt_size;
}

int gpr_send_pkt(struct apr_device *gdev, struct gpr_pkt *pkt)
{
	return pkt_router_send_svc_pkt(&gdev->svc, pkt);
}
EXPORT_SYMBOL_GPL(gpr_send_pkt);

int gpr_send_port_pkt(gpr_port_t *port, struct gpr_pkt *pkt)
{
	return pkt_router_send_svc_pkt(port, pkt);
}
EXPORT_SYMBOL_GPL(gpr_send_port_pkt);

154 155 156 157 158 159 160 161 162 163
static void apr_dev_release(struct device *dev)
{
	struct apr_device *adev = to_apr_device(dev);

	kfree(adev);
}

static int apr_callback(struct rpmsg_device *rpdev, void *buf,
				  int len, void *priv, u32 addr)
{
164
	struct packet_router *apr = dev_get_drvdata(&rpdev->dev);
165
	struct apr_rx_buf *abuf;
166 167 168 169 170 171 172 173
	unsigned long flags;

	if (len <= APR_HDR_SIZE) {
		dev_err(apr->dev, "APR: Improper apr pkt received:%p %d\n",
			buf, len);
		return -EINVAL;
	}

174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
	abuf = kzalloc(sizeof(*abuf) + len, GFP_ATOMIC);
	if (!abuf)
		return -ENOMEM;

	abuf->len = len;
	memcpy(abuf->buf, buf, len);

	spin_lock_irqsave(&apr->rx_lock, flags);
	list_add_tail(&abuf->node, &apr->rx_list);
	spin_unlock_irqrestore(&apr->rx_lock, flags);

	queue_work(apr->rxwq, &apr->rx_work);

	return 0;
}

190
static int apr_do_rx_callback(struct packet_router *apr, struct apr_rx_buf *abuf)
191 192
{
	uint16_t hdr_size, msg_type, ver, svc_id;
193 194
	struct pkt_router_svc *svc;
	struct apr_device *adev;
195 196 197 198 199 200 201
	struct apr_driver *adrv = NULL;
	struct apr_resp_pkt resp;
	struct apr_hdr *hdr;
	unsigned long flags;
	void *buf = abuf->buf;
	int len = abuf->len;

202 203 204 205 206 207 208 209 210 211 212 213
	hdr = buf;
	ver = APR_HDR_FIELD_VER(hdr->hdr_field);
	if (ver > APR_PKT_VER + 1)
		return -EINVAL;

	hdr_size = APR_HDR_FIELD_SIZE_BYTES(hdr->hdr_field);
	if (hdr_size < APR_HDR_SIZE) {
		dev_err(apr->dev, "APR: Wrong hdr size:%d\n", hdr_size);
		return -EINVAL;
	}

	if (hdr->pkt_size < APR_HDR_SIZE || hdr->pkt_size != len) {
214
		dev_err(apr->dev, "APR: Wrong packet size\n");
215 216 217 218
		return -EINVAL;
	}

	msg_type = APR_HDR_FIELD_MT(hdr->hdr_field);
219
	if (msg_type >= APR_MSG_TYPE_MAX) {
220 221 222 223 224 225 226 227 228 229 230 231 232 233 234
		dev_err(apr->dev, "APR: Wrong message type: %d\n", msg_type);
		return -EINVAL;
	}

	if (hdr->src_domain >= APR_DOMAIN_MAX ||
			hdr->dest_domain >= APR_DOMAIN_MAX ||
			hdr->src_svc >= APR_SVC_MAX ||
			hdr->dest_svc >= APR_SVC_MAX) {
		dev_err(apr->dev, "APR: Wrong APR header\n");
		return -EINVAL;
	}

	svc_id = hdr->dest_svc;
	spin_lock_irqsave(&apr->svcs_lock, flags);
	svc = idr_find(&apr->svcs_idr, svc_id);
235 236 237 238
	if (svc && svc->dev->driver) {
		adev = svc_to_apr_device(svc);
		adrv = to_apr_driver(adev->dev.driver);
	}
239 240
	spin_unlock_irqrestore(&apr->svcs_lock, flags);

241 242 243
	if (!adrv || !adev) {
		dev_err(apr->dev, "APR: service is not registered (%d)\n",
			svc_id);
244 245 246 247 248 249 250 251 252 253 254 255 256
		return -EINVAL;
	}

	resp.hdr = *hdr;
	resp.payload_size = hdr->pkt_size - hdr_size;

	/*
	 * NOTE: hdr_size is not same as APR_HDR_SIZE as remote can include
	 * optional headers in to apr_hdr which should be ignored
	 */
	if (resp.payload_size > 0)
		resp.payload = buf + hdr_size;

257
	adrv->callback(adev, &resp);
258 259 260 261

	return 0;
}

262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314
static int gpr_do_rx_callback(struct packet_router *gpr, struct apr_rx_buf *abuf)
{
	uint16_t hdr_size, ver;
	struct pkt_router_svc *svc = NULL;
	struct gpr_resp_pkt resp;
	struct gpr_hdr *hdr;
	unsigned long flags;
	void *buf = abuf->buf;
	int len = abuf->len;

	hdr = buf;
	ver = hdr->version;
	if (ver > GPR_PKT_VER + 1)
		return -EINVAL;

	hdr_size = hdr->hdr_size;
	if (hdr_size < GPR_PKT_HEADER_WORD_SIZE) {
		dev_err(gpr->dev, "GPR: Wrong hdr size:%d\n", hdr_size);
		return -EINVAL;
	}

	if (hdr->pkt_size < GPR_PKT_HEADER_BYTE_SIZE || hdr->pkt_size != len) {
		dev_err(gpr->dev, "GPR: Wrong packet size\n");
		return -EINVAL;
	}

	resp.hdr = *hdr;
	resp.payload_size = hdr->pkt_size - (hdr_size * 4);

	/*
	 * NOTE: hdr_size is not same as GPR_HDR_SIZE as remote can include
	 * optional headers in to gpr_hdr which should be ignored
	 */
	if (resp.payload_size > 0)
		resp.payload = buf + (hdr_size *  4);


	spin_lock_irqsave(&gpr->svcs_lock, flags);
	svc = idr_find(&gpr->svcs_idr, hdr->dest_port);
	spin_unlock_irqrestore(&gpr->svcs_lock, flags);

	if (!svc) {
		dev_err(gpr->dev, "GPR: Port(%x) is not registered\n",
			hdr->dest_port);
		return -EINVAL;
	}

	if (svc->callback)
		svc->callback(&resp, svc->priv, 0);

	return 0;
}

315 316
static void apr_rxwq(struct work_struct *work)
{
317
	struct packet_router *apr = container_of(work, struct packet_router, rx_work);
318 319 320 321 322
	struct apr_rx_buf *abuf, *b;
	unsigned long flags;

	if (!list_empty(&apr->rx_list)) {
		list_for_each_entry_safe(abuf, b, &apr->rx_list, node) {
323 324 325 326
			switch (apr->type) {
			case PR_TYPE_APR:
				apr_do_rx_callback(apr, abuf);
				break;
327 328 329
			case PR_TYPE_GPR:
				gpr_do_rx_callback(apr, abuf);
				break;
330 331 332
			default:
				break;
			}
333 334 335 336 337 338 339 340
			spin_lock_irqsave(&apr->rx_lock, flags);
			list_del(&abuf->node);
			spin_unlock_irqrestore(&apr->rx_lock, flags);
			kfree(abuf);
		}
	}
}

341 342 343 344 345 346 347 348 349 350 351 352 353 354 355
static int apr_device_match(struct device *dev, struct device_driver *drv)
{
	struct apr_device *adev = to_apr_device(dev);
	struct apr_driver *adrv = to_apr_driver(drv);
	const struct apr_device_id *id = adrv->id_table;

	/* Attempt an OF style match first */
	if (of_driver_match_device(dev, drv))
		return 1;

	if (!id)
		return 0;

	while (id->domain_id != 0 || id->svc_id != 0) {
		if (id->domain_id == adev->domain_id &&
356
		    id->svc_id == adev->svc.id)
357 358 359 360 361 362 363 364 365 366 367
			return 1;
		id++;
	}

	return 0;
}

static int apr_device_probe(struct device *dev)
{
	struct apr_device *adev = to_apr_device(dev);
	struct apr_driver *adrv = to_apr_driver(dev->driver);
368
	int ret;
369

370 371 372 373 374
	ret = adrv->probe(adev);
	if (!ret)
		adev->svc.callback = adrv->gpr_callback;

	return ret;
375 376
}

377
static void apr_device_remove(struct device *dev)
378 379
{
	struct apr_device *adev = to_apr_device(dev);
380
	struct apr_driver *adrv = to_apr_driver(dev->driver);
381
	struct packet_router *apr = dev_get_drvdata(adev->dev.parent);
382

383 384 385 386 387
	if (adrv->remove)
		adrv->remove(adev);
	spin_lock(&apr->svcs_lock);
	idr_remove(&apr->svcs_idr, adev->svc.id);
	spin_unlock(&apr->svcs_lock);
388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411
}

static int apr_uevent(struct device *dev, struct kobj_uevent_env *env)
{
	struct apr_device *adev = to_apr_device(dev);
	int ret;

	ret = of_device_uevent_modalias(dev, env);
	if (ret != -ENODEV)
		return ret;

	return add_uevent_var(env, "MODALIAS=apr:%s", adev->name);
}

struct bus_type aprbus = {
	.name		= "aprbus",
	.match		= apr_device_match,
	.probe		= apr_device_probe,
	.uevent		= apr_uevent,
	.remove		= apr_device_remove,
};
EXPORT_SYMBOL_GPL(aprbus);

static int apr_add_device(struct device *dev, struct device_node *np,
412
			  u32 svc_id, u32 domain_id)
413
{
414
	struct packet_router *apr = dev_get_drvdata(dev);
415
	struct apr_device *adev = NULL;
416
	struct pkt_router_svc *svc;
417 418 419 420 421 422
	int ret;

	adev = kzalloc(sizeof(*adev), GFP_KERNEL);
	if (!adev)
		return -ENOMEM;

423 424 425 426 427 428 429 430 431 432
	adev->svc_id = svc_id;
	svc = &adev->svc;

	svc->id = svc_id;
	svc->pr = apr;
	svc->priv = adev;
	svc->dev = dev;
	spin_lock_init(&svc->lock);

	adev->domain_id = domain_id;
433 434

	if (np)
435
		snprintf(adev->name, APR_NAME_SIZE, "%pOFn", np);
436

437 438 439 440 441
	switch (apr->type) {
	case PR_TYPE_APR:
		dev_set_name(&adev->dev, "aprsvc:%s:%x:%x", adev->name,
			     domain_id, svc_id);
		break;
442 443 444 445
	case PR_TYPE_GPR:
		dev_set_name(&adev->dev, "gprsvc:%s:%x:%x", adev->name,
			     domain_id, svc_id);
		break;
446 447 448
	default:
		break;
	}
449 450 451 452 453 454 455 456

	adev->dev.bus = &aprbus;
	adev->dev.parent = dev;
	adev->dev.of_node = np;
	adev->dev.release = apr_dev_release;
	adev->dev.driver = NULL;

	spin_lock(&apr->svcs_lock);
457
	ret = idr_alloc(&apr->svcs_idr, svc, svc_id, svc_id + 1, GFP_ATOMIC);
458
	spin_unlock(&apr->svcs_lock);
459 460 461 462
	if (ret < 0) {
		dev_err(dev, "idr_alloc failed: %d\n", ret);
		goto out;
	}
463

464
	/* Protection domain is optional, it does not exist on older platforms */
465 466
	ret = of_property_read_string_index(np, "qcom,protection-domain",
					    1, &adev->service_path);
467
	if (ret < 0 && ret != -EINVAL) {
468 469 470
		dev_err(dev, "Failed to read second value of qcom,protection-domain\n");
		goto out;
	}
471

472
	dev_info(dev, "Adding APR/GPR dev: %s\n", dev_name(&adev->dev));
473 474 475 476 477 478 479

	ret = device_register(&adev->dev);
	if (ret) {
		dev_err(dev, "device_register failed: %d\n", ret);
		put_device(&adev->dev);
	}

480
out:
481 482 483
	return ret;
}

484 485 486
static int of_apr_add_pd_lookups(struct device *dev)
{
	const char *service_name, *service_path;
487
	struct packet_router *apr = dev_get_drvdata(dev);
488 489 490 491 492 493 494 495 496 497 498 499 500 501
	struct device_node *node;
	struct pdr_service *pds;
	int ret;

	for_each_child_of_node(dev->of_node, node) {
		ret = of_property_read_string_index(node, "qcom,protection-domain",
						    0, &service_name);
		if (ret < 0)
			continue;

		ret = of_property_read_string_index(node, "qcom,protection-domain",
						    1, &service_path);
		if (ret < 0) {
			dev_err(dev, "pdr service path missing: %d\n", ret);
502
			of_node_put(node);
503 504 505 506 507
			return ret;
		}

		pds = pdr_add_lookup(apr->pdr, service_name, service_path);
		if (IS_ERR(pds) && PTR_ERR(pds) != -EALREADY) {
508
			dev_err(dev, "pdr add lookup failed: %ld\n", PTR_ERR(pds));
509
			of_node_put(node);
510 511 512 513 514 515 516 517
			return PTR_ERR(pds);
		}
	}

	return 0;
}

static void of_register_apr_devices(struct device *dev, const char *svc_path)
518
{
519
	struct packet_router *apr = dev_get_drvdata(dev);
520
	struct device_node *node;
521 522
	const char *service_path;
	int ret;
523 524

	for_each_child_of_node(dev->of_node, node) {
525 526
		u32 svc_id;
		u32 domain_id;
527

528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555
		/*
		 * This function is called with svc_path NULL during
		 * apr_probe(), in which case we register any apr devices
		 * without a qcom,protection-domain specified.
		 *
		 * Then as the protection domains becomes available
		 * (if applicable) this function is again called, but with
		 * svc_path representing the service becoming available. In
		 * this case we register any apr devices with a matching
		 * qcom,protection-domain.
		 */

		ret = of_property_read_string_index(node, "qcom,protection-domain",
						    1, &service_path);
		if (svc_path) {
			/* skip APR services that are PD independent */
			if (ret)
				continue;

			/* skip APR services whose PD paths don't match */
			if (strcmp(service_path, svc_path))
				continue;
		} else {
			/* skip APR services whose PD lookups are registered */
			if (ret == 0)
				continue;
		}

556
		if (of_property_read_u32(node, "reg", &svc_id))
557 558
			continue;

559
		domain_id = apr->dest_domain_id;
560

561 562
		if (apr_add_device(dev, node, svc_id, domain_id))
			dev_err(dev, "Failed to add apr %d svc\n", svc_id);
563 564 565
	}
}

566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581
static int apr_remove_device(struct device *dev, void *svc_path)
{
	struct apr_device *adev = to_apr_device(dev);

	if (svc_path && adev->service_path) {
		if (!strcmp(adev->service_path, (char *)svc_path))
			device_unregister(&adev->dev);
	} else {
		device_unregister(&adev->dev);
	}

	return 0;
}

static void apr_pd_status(int state, char *svc_path, void *priv)
{
582
	struct packet_router *apr = (struct packet_router *)priv;
583 584 585 586 587 588 589 590 591 592 593

	switch (state) {
	case SERVREG_SERVICE_STATE_UP:
		of_register_apr_devices(apr->dev, svc_path);
		break;
	case SERVREG_SERVICE_STATE_DOWN:
		device_for_each_child(apr->dev, svc_path, apr_remove_device);
		break;
	}
}

594 595 596
static int apr_probe(struct rpmsg_device *rpdev)
{
	struct device *dev = &rpdev->dev;
597
	struct packet_router *apr;
598 599 600 601 602 603
	int ret;

	apr = devm_kzalloc(dev, sizeof(*apr), GFP_KERNEL);
	if (!apr)
		return -ENOMEM;

604
	ret = of_property_read_u32(dev->of_node, "qcom,domain", &apr->dest_domain_id);
605 606 607 608 609 610 611 612 613 614

	if (of_device_is_compatible(dev->of_node, "qcom,gpr")) {
		apr->type = PR_TYPE_GPR;
	} else {
		if (ret) /* try deprecated apr-domain property */
			ret = of_property_read_u32(dev->of_node, "qcom,apr-domain",
						   &apr->dest_domain_id);
		apr->type = PR_TYPE_APR;
	}

615
	if (ret) {
616
		dev_err(dev, "Domain ID not specified in DT\n");
617 618 619 620 621 622
		return ret;
	}

	dev_set_drvdata(dev, apr);
	apr->ch = rpdev->ept;
	apr->dev = dev;
623 624 625 626 627 628
	apr->rxwq = create_singlethread_workqueue("qcom_apr_rx");
	if (!apr->rxwq) {
		dev_err(apr->dev, "Failed to start Rx WQ\n");
		return -ENOMEM;
	}
	INIT_WORK(&apr->rx_work, apr_rxwq);
629 630 631 632 633 634 635 636

	apr->pdr = pdr_handle_alloc(apr_pd_status, apr);
	if (IS_ERR(apr->pdr)) {
		dev_err(dev, "Failed to init PDR handle\n");
		ret = PTR_ERR(apr->pdr);
		goto destroy_wq;
	}

637 638
	INIT_LIST_HEAD(&apr->rx_list);
	spin_lock_init(&apr->rx_lock);
639 640 641
	spin_lock_init(&apr->svcs_lock);
	idr_init(&apr->svcs_idr);

642 643 644
	ret = of_apr_add_pd_lookups(dev);
	if (ret)
		goto handle_release;
645

646
	of_register_apr_devices(dev, NULL);
647 648

	return 0;
649 650 651 652 653 654

handle_release:
	pdr_handle_release(apr->pdr);
destroy_wq:
	destroy_workqueue(apr->rxwq);
	return ret;
655 656 657 658
}

static void apr_remove(struct rpmsg_device *rpdev)
{
659
	struct packet_router *apr = dev_get_drvdata(&rpdev->dev);
660

661
	pdr_handle_release(apr->pdr);
662
	device_for_each_child(&rpdev->dev, NULL, apr_remove_device);
663
	destroy_workqueue(apr->rxwq);
664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694
}

/*
 * __apr_driver_register() - Client driver registration with aprbus
 *
 * @drv:Client driver to be associated with client-device.
 * @owner: owning module/driver
 *
 * This API will register the client driver with the aprbus
 * It is called from the driver's module-init function.
 */
int __apr_driver_register(struct apr_driver *drv, struct module *owner)
{
	drv->driver.bus = &aprbus;
	drv->driver.owner = owner;

	return driver_register(&drv->driver);
}
EXPORT_SYMBOL_GPL(__apr_driver_register);

/*
 * apr_driver_unregister() - Undo effect of apr_driver_register
 *
 * @drv: Client driver to be unregistered
 */
void apr_driver_unregister(struct apr_driver *drv)
{
	driver_unregister(&drv->driver);
}
EXPORT_SYMBOL_GPL(apr_driver_unregister);

695
static const struct of_device_id pkt_router_of_match[] = {
696 697
	{ .compatible = "qcom,apr"},
	{ .compatible = "qcom,apr-v2"},
698
	{ .compatible = "qcom,gpr"},
699 700
	{}
};
701
MODULE_DEVICE_TABLE(of, pkt_router_of_match);
702

703
static struct rpmsg_driver packet_router_driver = {
704 705 706 707 708
	.probe = apr_probe,
	.remove = apr_remove,
	.callback = apr_callback,
	.drv = {
		.name = "qcom,apr",
709
		.of_match_table = pkt_router_of_match,
710 711 712 713 714 715 716 717 718
	},
};

static int __init apr_init(void)
{
	int ret;

	ret = bus_register(&aprbus);
	if (!ret)
719
		ret = register_rpmsg_driver(&packet_router_driver);
720 721 722 723 724 725 726 727 728
	else
		bus_unregister(&aprbus);

	return ret;
}

static void __exit apr_exit(void)
{
	bus_unregister(&aprbus);
729
	unregister_rpmsg_driver(&packet_router_driver);
730 731 732 733 734 735 736
}

subsys_initcall(apr_init);
module_exit(apr_exit);

MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("Qualcomm APR Bus");