xref: /openbmc/linux/drivers/amba/bus.c (revision 29a36d4d)
1 /*
2  *  linux/arch/arm/common/amba.c
3  *
4  *  Copyright (C) 2003 Deep Blue Solutions Ltd, All Rights Reserved.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  */
10 #include <linux/module.h>
11 #include <linux/init.h>
12 #include <linux/device.h>
13 #include <linux/string.h>
14 #include <linux/slab.h>
15 #include <linux/io.h>
16 #include <linux/pm.h>
17 #include <linux/pm_runtime.h>
18 #include <linux/amba/bus.h>
19 
20 #include <asm/irq.h>
21 #include <asm/sizes.h>
22 
23 #define to_amba_driver(d)	container_of(d, struct amba_driver, drv)
24 
25 static const struct amba_id *
26 amba_lookup(const struct amba_id *table, struct amba_device *dev)
27 {
28 	int ret = 0;
29 
30 	while (table->mask) {
31 		ret = (dev->periphid & table->mask) == table->id;
32 		if (ret)
33 			break;
34 		table++;
35 	}
36 
37 	return ret ? table : NULL;
38 }
39 
40 static int amba_match(struct device *dev, struct device_driver *drv)
41 {
42 	struct amba_device *pcdev = to_amba_device(dev);
43 	struct amba_driver *pcdrv = to_amba_driver(drv);
44 
45 	return amba_lookup(pcdrv->id_table, pcdev) != NULL;
46 }
47 
48 #ifdef CONFIG_HOTPLUG
49 static int amba_uevent(struct device *dev, struct kobj_uevent_env *env)
50 {
51 	struct amba_device *pcdev = to_amba_device(dev);
52 	int retval = 0;
53 
54 	retval = add_uevent_var(env, "AMBA_ID=%08x", pcdev->periphid);
55 	return retval;
56 }
57 #else
58 #define amba_uevent NULL
59 #endif
60 
61 #define amba_attr_func(name,fmt,arg...)					\
62 static ssize_t name##_show(struct device *_dev,				\
63 			   struct device_attribute *attr, char *buf)	\
64 {									\
65 	struct amba_device *dev = to_amba_device(_dev);			\
66 	return sprintf(buf, fmt, arg);					\
67 }
68 
69 #define amba_attr(name,fmt,arg...)	\
70 amba_attr_func(name,fmt,arg)		\
71 static DEVICE_ATTR(name, S_IRUGO, name##_show, NULL)
72 
73 amba_attr_func(id, "%08x\n", dev->periphid);
74 amba_attr(irq0, "%u\n", dev->irq[0]);
75 amba_attr(irq1, "%u\n", dev->irq[1]);
76 amba_attr_func(resource, "\t%016llx\t%016llx\t%016lx\n",
77 	 (unsigned long long)dev->res.start, (unsigned long long)dev->res.end,
78 	 dev->res.flags);
79 
80 static struct device_attribute amba_dev_attrs[] = {
81 	__ATTR_RO(id),
82 	__ATTR_RO(resource),
83 	__ATTR_NULL,
84 };
85 
86 #ifdef CONFIG_PM_SLEEP
87 
88 static int amba_legacy_suspend(struct device *dev, pm_message_t mesg)
89 {
90 	struct amba_driver *adrv = to_amba_driver(dev->driver);
91 	struct amba_device *adev = to_amba_device(dev);
92 	int ret = 0;
93 
94 	if (dev->driver && adrv->suspend)
95 		ret = adrv->suspend(adev, mesg);
96 
97 	return ret;
98 }
99 
100 static int amba_legacy_resume(struct device *dev)
101 {
102 	struct amba_driver *adrv = to_amba_driver(dev->driver);
103 	struct amba_device *adev = to_amba_device(dev);
104 	int ret = 0;
105 
106 	if (dev->driver && adrv->resume)
107 		ret = adrv->resume(adev);
108 
109 	return ret;
110 }
111 
112 static int amba_pm_prepare(struct device *dev)
113 {
114 	struct device_driver *drv = dev->driver;
115 	int ret = 0;
116 
117 	if (drv && drv->pm && drv->pm->prepare)
118 		ret = drv->pm->prepare(dev);
119 
120 	return ret;
121 }
122 
123 static void amba_pm_complete(struct device *dev)
124 {
125 	struct device_driver *drv = dev->driver;
126 
127 	if (drv && drv->pm && drv->pm->complete)
128 		drv->pm->complete(dev);
129 }
130 
131 #else /* !CONFIG_PM_SLEEP */
132 
133 #define amba_pm_prepare		NULL
134 #define amba_pm_complete		NULL
135 
136 #endif /* !CONFIG_PM_SLEEP */
137 
138 #ifdef CONFIG_SUSPEND
139 
140 static int amba_pm_suspend(struct device *dev)
141 {
142 	struct device_driver *drv = dev->driver;
143 	int ret = 0;
144 
145 	if (!drv)
146 		return 0;
147 
148 	if (drv->pm) {
149 		if (drv->pm->suspend)
150 			ret = drv->pm->suspend(dev);
151 	} else {
152 		ret = amba_legacy_suspend(dev, PMSG_SUSPEND);
153 	}
154 
155 	return ret;
156 }
157 
158 static int amba_pm_suspend_noirq(struct device *dev)
159 {
160 	struct device_driver *drv = dev->driver;
161 	int ret = 0;
162 
163 	if (!drv)
164 		return 0;
165 
166 	if (drv->pm) {
167 		if (drv->pm->suspend_noirq)
168 			ret = drv->pm->suspend_noirq(dev);
169 	}
170 
171 	return ret;
172 }
173 
174 static int amba_pm_resume(struct device *dev)
175 {
176 	struct device_driver *drv = dev->driver;
177 	int ret = 0;
178 
179 	if (!drv)
180 		return 0;
181 
182 	if (drv->pm) {
183 		if (drv->pm->resume)
184 			ret = drv->pm->resume(dev);
185 	} else {
186 		ret = amba_legacy_resume(dev);
187 	}
188 
189 	return ret;
190 }
191 
192 static int amba_pm_resume_noirq(struct device *dev)
193 {
194 	struct device_driver *drv = dev->driver;
195 	int ret = 0;
196 
197 	if (!drv)
198 		return 0;
199 
200 	if (drv->pm) {
201 		if (drv->pm->resume_noirq)
202 			ret = drv->pm->resume_noirq(dev);
203 	}
204 
205 	return ret;
206 }
207 
208 #else /* !CONFIG_SUSPEND */
209 
210 #define amba_pm_suspend		NULL
211 #define amba_pm_resume		NULL
212 #define amba_pm_suspend_noirq	NULL
213 #define amba_pm_resume_noirq	NULL
214 
215 #endif /* !CONFIG_SUSPEND */
216 
217 #ifdef CONFIG_HIBERNATE_CALLBACKS
218 
219 static int amba_pm_freeze(struct device *dev)
220 {
221 	struct device_driver *drv = dev->driver;
222 	int ret = 0;
223 
224 	if (!drv)
225 		return 0;
226 
227 	if (drv->pm) {
228 		if (drv->pm->freeze)
229 			ret = drv->pm->freeze(dev);
230 	} else {
231 		ret = amba_legacy_suspend(dev, PMSG_FREEZE);
232 	}
233 
234 	return ret;
235 }
236 
237 static int amba_pm_freeze_noirq(struct device *dev)
238 {
239 	struct device_driver *drv = dev->driver;
240 	int ret = 0;
241 
242 	if (!drv)
243 		return 0;
244 
245 	if (drv->pm) {
246 		if (drv->pm->freeze_noirq)
247 			ret = drv->pm->freeze_noirq(dev);
248 	}
249 
250 	return ret;
251 }
252 
253 static int amba_pm_thaw(struct device *dev)
254 {
255 	struct device_driver *drv = dev->driver;
256 	int ret = 0;
257 
258 	if (!drv)
259 		return 0;
260 
261 	if (drv->pm) {
262 		if (drv->pm->thaw)
263 			ret = drv->pm->thaw(dev);
264 	} else {
265 		ret = amba_legacy_resume(dev);
266 	}
267 
268 	return ret;
269 }
270 
271 static int amba_pm_thaw_noirq(struct device *dev)
272 {
273 	struct device_driver *drv = dev->driver;
274 	int ret = 0;
275 
276 	if (!drv)
277 		return 0;
278 
279 	if (drv->pm) {
280 		if (drv->pm->thaw_noirq)
281 			ret = drv->pm->thaw_noirq(dev);
282 	}
283 
284 	return ret;
285 }
286 
287 static int amba_pm_poweroff(struct device *dev)
288 {
289 	struct device_driver *drv = dev->driver;
290 	int ret = 0;
291 
292 	if (!drv)
293 		return 0;
294 
295 	if (drv->pm) {
296 		if (drv->pm->poweroff)
297 			ret = drv->pm->poweroff(dev);
298 	} else {
299 		ret = amba_legacy_suspend(dev, PMSG_HIBERNATE);
300 	}
301 
302 	return ret;
303 }
304 
305 static int amba_pm_poweroff_noirq(struct device *dev)
306 {
307 	struct device_driver *drv = dev->driver;
308 	int ret = 0;
309 
310 	if (!drv)
311 		return 0;
312 
313 	if (drv->pm) {
314 		if (drv->pm->poweroff_noirq)
315 			ret = drv->pm->poweroff_noirq(dev);
316 	}
317 
318 	return ret;
319 }
320 
321 static int amba_pm_restore(struct device *dev)
322 {
323 	struct device_driver *drv = dev->driver;
324 	int ret = 0;
325 
326 	if (!drv)
327 		return 0;
328 
329 	if (drv->pm) {
330 		if (drv->pm->restore)
331 			ret = drv->pm->restore(dev);
332 	} else {
333 		ret = amba_legacy_resume(dev);
334 	}
335 
336 	return ret;
337 }
338 
339 static int amba_pm_restore_noirq(struct device *dev)
340 {
341 	struct device_driver *drv = dev->driver;
342 	int ret = 0;
343 
344 	if (!drv)
345 		return 0;
346 
347 	if (drv->pm) {
348 		if (drv->pm->restore_noirq)
349 			ret = drv->pm->restore_noirq(dev);
350 	}
351 
352 	return ret;
353 }
354 
355 #else /* !CONFIG_HIBERNATE_CALLBACKS */
356 
357 #define amba_pm_freeze		NULL
358 #define amba_pm_thaw		NULL
359 #define amba_pm_poweroff		NULL
360 #define amba_pm_restore		NULL
361 #define amba_pm_freeze_noirq	NULL
362 #define amba_pm_thaw_noirq		NULL
363 #define amba_pm_poweroff_noirq	NULL
364 #define amba_pm_restore_noirq	NULL
365 
366 #endif /* !CONFIG_HIBERNATE_CALLBACKS */
367 
368 #ifdef CONFIG_PM_RUNTIME
369 /*
370  * Hooks to provide runtime PM of the pclk (bus clock).  It is safe to
371  * enable/disable the bus clock at runtime PM suspend/resume as this
372  * does not result in loss of context.  However, disabling vcore power
373  * would do, so we leave that to the driver.
374  */
375 static int amba_pm_runtime_suspend(struct device *dev)
376 {
377 	struct amba_device *pcdev = to_amba_device(dev);
378 	int ret = pm_generic_runtime_suspend(dev);
379 
380 	if (ret == 0 && dev->driver)
381 		clk_disable(pcdev->pclk);
382 
383 	return ret;
384 }
385 
386 static int amba_pm_runtime_resume(struct device *dev)
387 {
388 	struct amba_device *pcdev = to_amba_device(dev);
389 	int ret;
390 
391 	if (dev->driver) {
392 		ret = clk_enable(pcdev->pclk);
393 		/* Failure is probably fatal to the system, but... */
394 		if (ret)
395 			return ret;
396 	}
397 
398 	return pm_generic_runtime_resume(dev);
399 }
400 #endif
401 
402 #ifdef CONFIG_PM
403 
404 static const struct dev_pm_ops amba_pm = {
405 	.prepare	= amba_pm_prepare,
406 	.complete	= amba_pm_complete,
407 	.suspend	= amba_pm_suspend,
408 	.resume		= amba_pm_resume,
409 	.freeze		= amba_pm_freeze,
410 	.thaw		= amba_pm_thaw,
411 	.poweroff	= amba_pm_poweroff,
412 	.restore	= amba_pm_restore,
413 	.suspend_noirq	= amba_pm_suspend_noirq,
414 	.resume_noirq	= amba_pm_resume_noirq,
415 	.freeze_noirq	= amba_pm_freeze_noirq,
416 	.thaw_noirq	= amba_pm_thaw_noirq,
417 	.poweroff_noirq	= amba_pm_poweroff_noirq,
418 	.restore_noirq	= amba_pm_restore_noirq,
419 	SET_RUNTIME_PM_OPS(
420 		amba_pm_runtime_suspend,
421 		amba_pm_runtime_resume,
422 		pm_generic_runtime_idle
423 	)
424 };
425 
426 #define AMBA_PM (&amba_pm)
427 
428 #else /* !CONFIG_PM */
429 
430 #define AMBA_PM	NULL
431 
432 #endif /* !CONFIG_PM */
433 
434 /*
435  * Primecells are part of the Advanced Microcontroller Bus Architecture,
436  * so we call the bus "amba".
437  */
438 struct bus_type amba_bustype = {
439 	.name		= "amba",
440 	.dev_attrs	= amba_dev_attrs,
441 	.match		= amba_match,
442 	.uevent		= amba_uevent,
443 	.pm		= AMBA_PM,
444 };
445 
446 static int __init amba_init(void)
447 {
448 	return bus_register(&amba_bustype);
449 }
450 
451 postcore_initcall(amba_init);
452 
453 static int amba_get_enable_pclk(struct amba_device *pcdev)
454 {
455 	struct clk *pclk = clk_get(&pcdev->dev, "apb_pclk");
456 	int ret;
457 
458 	pcdev->pclk = pclk;
459 
460 	if (IS_ERR(pclk))
461 		return PTR_ERR(pclk);
462 
463 	ret = clk_prepare(pclk);
464 	if (ret) {
465 		clk_put(pclk);
466 		return ret;
467 	}
468 
469 	ret = clk_enable(pclk);
470 	if (ret) {
471 		clk_unprepare(pclk);
472 		clk_put(pclk);
473 	}
474 
475 	return ret;
476 }
477 
478 static void amba_put_disable_pclk(struct amba_device *pcdev)
479 {
480 	struct clk *pclk = pcdev->pclk;
481 
482 	clk_disable(pclk);
483 	clk_unprepare(pclk);
484 	clk_put(pclk);
485 }
486 
487 static int amba_get_enable_vcore(struct amba_device *pcdev)
488 {
489 	struct regulator *vcore = regulator_get(&pcdev->dev, "vcore");
490 	int ret;
491 
492 	pcdev->vcore = vcore;
493 
494 	if (IS_ERR(vcore)) {
495 		/* It is OK not to supply a vcore regulator */
496 		if (PTR_ERR(vcore) == -ENODEV)
497 			return 0;
498 		return PTR_ERR(vcore);
499 	}
500 
501 	ret = regulator_enable(vcore);
502 	if (ret) {
503 		regulator_put(vcore);
504 		pcdev->vcore = ERR_PTR(-ENODEV);
505 	}
506 
507 	return ret;
508 }
509 
510 static void amba_put_disable_vcore(struct amba_device *pcdev)
511 {
512 	struct regulator *vcore = pcdev->vcore;
513 
514 	if (!IS_ERR(vcore)) {
515 		regulator_disable(vcore);
516 		regulator_put(vcore);
517 	}
518 }
519 
520 /*
521  * These are the device model conversion veneers; they convert the
522  * device model structures to our more specific structures.
523  */
524 static int amba_probe(struct device *dev)
525 {
526 	struct amba_device *pcdev = to_amba_device(dev);
527 	struct amba_driver *pcdrv = to_amba_driver(dev->driver);
528 	const struct amba_id *id = amba_lookup(pcdrv->id_table, pcdev);
529 	int ret;
530 
531 	do {
532 		ret = amba_get_enable_vcore(pcdev);
533 		if (ret)
534 			break;
535 
536 		ret = amba_get_enable_pclk(pcdev);
537 		if (ret)
538 			break;
539 
540 		pm_runtime_get_noresume(dev);
541 		pm_runtime_set_active(dev);
542 		pm_runtime_enable(dev);
543 
544 		ret = pcdrv->probe(pcdev, id);
545 		if (ret == 0)
546 			break;
547 
548 		pm_runtime_disable(dev);
549 		pm_runtime_set_suspended(dev);
550 		pm_runtime_put_noidle(dev);
551 
552 		amba_put_disable_pclk(pcdev);
553 		amba_put_disable_vcore(pcdev);
554 	} while (0);
555 
556 	return ret;
557 }
558 
559 static int amba_remove(struct device *dev)
560 {
561 	struct amba_device *pcdev = to_amba_device(dev);
562 	struct amba_driver *drv = to_amba_driver(dev->driver);
563 	int ret;
564 
565 	pm_runtime_get_sync(dev);
566 	ret = drv->remove(pcdev);
567 	pm_runtime_put_noidle(dev);
568 
569 	/* Undo the runtime PM settings in amba_probe() */
570 	pm_runtime_disable(dev);
571 	pm_runtime_set_suspended(dev);
572 	pm_runtime_put_noidle(dev);
573 
574 	amba_put_disable_pclk(pcdev);
575 	amba_put_disable_vcore(pcdev);
576 
577 	return ret;
578 }
579 
580 static void amba_shutdown(struct device *dev)
581 {
582 	struct amba_driver *drv = to_amba_driver(dev->driver);
583 	drv->shutdown(to_amba_device(dev));
584 }
585 
586 /**
587  *	amba_driver_register - register an AMBA device driver
588  *	@drv: amba device driver structure
589  *
590  *	Register an AMBA device driver with the Linux device model
591  *	core.  If devices pre-exist, the drivers probe function will
592  *	be called.
593  */
594 int amba_driver_register(struct amba_driver *drv)
595 {
596 	drv->drv.bus = &amba_bustype;
597 
598 #define SETFN(fn)	if (drv->fn) drv->drv.fn = amba_##fn
599 	SETFN(probe);
600 	SETFN(remove);
601 	SETFN(shutdown);
602 
603 	return driver_register(&drv->drv);
604 }
605 
606 /**
607  *	amba_driver_unregister - remove an AMBA device driver
608  *	@drv: AMBA device driver structure to remove
609  *
610  *	Unregister an AMBA device driver from the Linux device
611  *	model.  The device model will call the drivers remove function
612  *	for each device the device driver is currently handling.
613  */
614 void amba_driver_unregister(struct amba_driver *drv)
615 {
616 	driver_unregister(&drv->drv);
617 }
618 
619 
620 static void amba_device_release(struct device *dev)
621 {
622 	struct amba_device *d = to_amba_device(dev);
623 
624 	if (d->res.parent)
625 		release_resource(&d->res);
626 	kfree(d);
627 }
628 
629 /**
630  *	amba_device_register - register an AMBA device
631  *	@dev: AMBA device to register
632  *	@parent: parent memory resource
633  *
634  *	Setup the AMBA device, reading the cell ID if present.
635  *	Claim the resource, and register the AMBA device with
636  *	the Linux device manager.
637  */
638 int amba_device_register(struct amba_device *dev, struct resource *parent)
639 {
640 	u32 size;
641 	void __iomem *tmp;
642 	int i, ret;
643 
644 	device_initialize(&dev->dev);
645 
646 	/*
647 	 * Copy from device_add
648 	 */
649 	if (dev->dev.init_name) {
650 		dev_set_name(&dev->dev, "%s", dev->dev.init_name);
651 		dev->dev.init_name = NULL;
652 	}
653 
654 	dev->dev.release = amba_device_release;
655 	dev->dev.bus = &amba_bustype;
656 	dev->dev.dma_mask = &dev->dma_mask;
657 	dev->res.name = dev_name(&dev->dev);
658 
659 	if (!dev->dev.coherent_dma_mask && dev->dma_mask)
660 		dev_warn(&dev->dev, "coherent dma mask is unset\n");
661 
662 	ret = request_resource(parent, &dev->res);
663 	if (ret)
664 		goto err_out;
665 
666 	/* Hard-coded primecell ID instead of plug-n-play */
667 	if (dev->periphid != 0)
668 		goto skip_probe;
669 
670 	/*
671 	 * Dynamically calculate the size of the resource
672 	 * and use this for iomap
673 	 */
674 	size = resource_size(&dev->res);
675 	tmp = ioremap(dev->res.start, size);
676 	if (!tmp) {
677 		ret = -ENOMEM;
678 		goto err_release;
679 	}
680 
681 	ret = amba_get_enable_pclk(dev);
682 	if (ret == 0) {
683 		u32 pid, cid;
684 
685 		/*
686 		 * Read pid and cid based on size of resource
687 		 * they are located at end of region
688 		 */
689 		for (pid = 0, i = 0; i < 4; i++)
690 			pid |= (readl(tmp + size - 0x20 + 4 * i) & 255) <<
691 				(i * 8);
692 		for (cid = 0, i = 0; i < 4; i++)
693 			cid |= (readl(tmp + size - 0x10 + 4 * i) & 255) <<
694 				(i * 8);
695 
696 		amba_put_disable_pclk(dev);
697 
698 		if (cid == AMBA_CID)
699 			dev->periphid = pid;
700 
701 		if (!dev->periphid)
702 			ret = -ENODEV;
703 	}
704 
705 	iounmap(tmp);
706 
707 	if (ret)
708 		goto err_release;
709 
710  skip_probe:
711 	ret = device_add(&dev->dev);
712 	if (ret)
713 		goto err_release;
714 
715 	if (dev->irq[0] != NO_IRQ)
716 		ret = device_create_file(&dev->dev, &dev_attr_irq0);
717 	if (ret == 0 && dev->irq[1] != NO_IRQ)
718 		ret = device_create_file(&dev->dev, &dev_attr_irq1);
719 	if (ret == 0)
720 		return ret;
721 
722 	device_unregister(&dev->dev);
723 
724  err_release:
725 	release_resource(&dev->res);
726  err_out:
727 	return ret;
728 }
729 
730 /**
731  *	amba_device_unregister - unregister an AMBA device
732  *	@dev: AMBA device to remove
733  *
734  *	Remove the specified AMBA device from the Linux device
735  *	manager.  All files associated with this object will be
736  *	destroyed, and device drivers notified that the device has
737  *	been removed.  The AMBA device's resources including
738  *	the amba_device structure will be freed once all
739  *	references to it have been dropped.
740  */
741 void amba_device_unregister(struct amba_device *dev)
742 {
743 	device_unregister(&dev->dev);
744 }
745 
746 
747 struct find_data {
748 	struct amba_device *dev;
749 	struct device *parent;
750 	const char *busid;
751 	unsigned int id;
752 	unsigned int mask;
753 };
754 
755 static int amba_find_match(struct device *dev, void *data)
756 {
757 	struct find_data *d = data;
758 	struct amba_device *pcdev = to_amba_device(dev);
759 	int r;
760 
761 	r = (pcdev->periphid & d->mask) == d->id;
762 	if (d->parent)
763 		r &= d->parent == dev->parent;
764 	if (d->busid)
765 		r &= strcmp(dev_name(dev), d->busid) == 0;
766 
767 	if (r) {
768 		get_device(dev);
769 		d->dev = pcdev;
770 	}
771 
772 	return r;
773 }
774 
775 /**
776  *	amba_find_device - locate an AMBA device given a bus id
777  *	@busid: bus id for device (or NULL)
778  *	@parent: parent device (or NULL)
779  *	@id: peripheral ID (or 0)
780  *	@mask: peripheral ID mask (or 0)
781  *
782  *	Return the AMBA device corresponding to the supplied parameters.
783  *	If no device matches, returns NULL.
784  *
785  *	NOTE: When a valid device is found, its refcount is
786  *	incremented, and must be decremented before the returned
787  *	reference.
788  */
789 struct amba_device *
790 amba_find_device(const char *busid, struct device *parent, unsigned int id,
791 		 unsigned int mask)
792 {
793 	struct find_data data;
794 
795 	data.dev = NULL;
796 	data.parent = parent;
797 	data.busid = busid;
798 	data.id = id;
799 	data.mask = mask;
800 
801 	bus_for_each_dev(&amba_bustype, NULL, &data, amba_find_match);
802 
803 	return data.dev;
804 }
805 
806 /**
807  *	amba_request_regions - request all mem regions associated with device
808  *	@dev: amba_device structure for device
809  *	@name: name, or NULL to use driver name
810  */
811 int amba_request_regions(struct amba_device *dev, const char *name)
812 {
813 	int ret = 0;
814 	u32 size;
815 
816 	if (!name)
817 		name = dev->dev.driver->name;
818 
819 	size = resource_size(&dev->res);
820 
821 	if (!request_mem_region(dev->res.start, size, name))
822 		ret = -EBUSY;
823 
824 	return ret;
825 }
826 
827 /**
828  *	amba_release_regions - release mem regions associated with device
829  *	@dev: amba_device structure for device
830  *
831  *	Release regions claimed by a successful call to amba_request_regions.
832  */
833 void amba_release_regions(struct amba_device *dev)
834 {
835 	u32 size;
836 
837 	size = resource_size(&dev->res);
838 	release_mem_region(dev->res.start, size);
839 }
840 
841 EXPORT_SYMBOL(amba_driver_register);
842 EXPORT_SYMBOL(amba_driver_unregister);
843 EXPORT_SYMBOL(amba_device_register);
844 EXPORT_SYMBOL(amba_device_unregister);
845 EXPORT_SYMBOL(amba_find_device);
846 EXPORT_SYMBOL(amba_request_regions);
847 EXPORT_SYMBOL(amba_release_regions);
848