1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * linux/arch/arm/common/amba.c 4 * 5 * Copyright (C) 2003 Deep Blue Solutions Ltd, All Rights Reserved. 6 */ 7 #include <linux/module.h> 8 #include <linux/init.h> 9 #include <linux/device.h> 10 #include <linux/string.h> 11 #include <linux/slab.h> 12 #include <linux/io.h> 13 #include <linux/pm.h> 14 #include <linux/pm_runtime.h> 15 #include <linux/pm_domain.h> 16 #include <linux/amba/bus.h> 17 #include <linux/sizes.h> 18 #include <linux/limits.h> 19 #include <linux/clk/clk-conf.h> 20 #include <linux/platform_device.h> 21 22 #include <asm/irq.h> 23 24 #define to_amba_driver(d) container_of(d, struct amba_driver, drv) 25 26 /* called on periphid match and class 0x9 coresight device. */ 27 static int 28 amba_cs_uci_id_match(const struct amba_id *table, struct amba_device *dev) 29 { 30 int ret = 0; 31 struct amba_cs_uci_id *uci; 32 33 uci = table->data; 34 35 /* no table data or zero mask - return match on periphid */ 36 if (!uci || (uci->devarch_mask == 0)) 37 return 1; 38 39 /* test against read devtype and masked devarch value */ 40 ret = (dev->uci.devtype == uci->devtype) && 41 ((dev->uci.devarch & uci->devarch_mask) == uci->devarch); 42 return ret; 43 } 44 45 static const struct amba_id * 46 amba_lookup(const struct amba_id *table, struct amba_device *dev) 47 { 48 while (table->mask) { 49 if (((dev->periphid & table->mask) == table->id) && 50 ((dev->cid != CORESIGHT_CID) || 51 (amba_cs_uci_id_match(table, dev)))) 52 return table; 53 table++; 54 } 55 return NULL; 56 } 57 58 static int amba_match(struct device *dev, struct device_driver *drv) 59 { 60 struct amba_device *pcdev = to_amba_device(dev); 61 struct amba_driver *pcdrv = to_amba_driver(drv); 62 63 /* When driver_override is set, only bind to the matching driver */ 64 if (pcdev->driver_override) 65 return !strcmp(pcdev->driver_override, drv->name); 66 67 return amba_lookup(pcdrv->id_table, pcdev) != NULL; 68 } 69 70 static int amba_uevent(struct device *dev, struct kobj_uevent_env *env) 71 { 72 struct amba_device *pcdev = to_amba_device(dev); 73 int retval = 0; 74 75 retval = add_uevent_var(env, "AMBA_ID=%08x", pcdev->periphid); 76 if (retval) 77 return retval; 78 79 retval = add_uevent_var(env, "MODALIAS=amba:d%08X", pcdev->periphid); 80 return retval; 81 } 82 83 static ssize_t driver_override_show(struct device *_dev, 84 struct device_attribute *attr, char *buf) 85 { 86 struct amba_device *dev = to_amba_device(_dev); 87 ssize_t len; 88 89 device_lock(_dev); 90 len = sprintf(buf, "%s\n", dev->driver_override); 91 device_unlock(_dev); 92 return len; 93 } 94 95 static ssize_t driver_override_store(struct device *_dev, 96 struct device_attribute *attr, 97 const char *buf, size_t count) 98 { 99 struct amba_device *dev = to_amba_device(_dev); 100 char *driver_override, *old, *cp; 101 102 /* We need to keep extra room for a newline */ 103 if (count >= (PAGE_SIZE - 1)) 104 return -EINVAL; 105 106 driver_override = kstrndup(buf, count, GFP_KERNEL); 107 if (!driver_override) 108 return -ENOMEM; 109 110 cp = strchr(driver_override, '\n'); 111 if (cp) 112 *cp = '\0'; 113 114 device_lock(_dev); 115 old = dev->driver_override; 116 if (strlen(driver_override)) { 117 dev->driver_override = driver_override; 118 } else { 119 kfree(driver_override); 120 dev->driver_override = NULL; 121 } 122 device_unlock(_dev); 123 124 kfree(old); 125 126 return count; 127 } 128 static DEVICE_ATTR_RW(driver_override); 129 130 #define amba_attr_func(name,fmt,arg...) \ 131 static ssize_t name##_show(struct device *_dev, \ 132 struct device_attribute *attr, char *buf) \ 133 { \ 134 struct amba_device *dev = to_amba_device(_dev); \ 135 return sprintf(buf, fmt, arg); \ 136 } \ 137 static DEVICE_ATTR_RO(name) 138 139 amba_attr_func(id, "%08x\n", dev->periphid); 140 amba_attr_func(irq0, "%u\n", dev->irq[0]); 141 amba_attr_func(irq1, "%u\n", dev->irq[1]); 142 amba_attr_func(resource, "\t%016llx\t%016llx\t%016lx\n", 143 (unsigned long long)dev->res.start, (unsigned long long)dev->res.end, 144 dev->res.flags); 145 146 static struct attribute *amba_dev_attrs[] = { 147 &dev_attr_id.attr, 148 &dev_attr_resource.attr, 149 &dev_attr_driver_override.attr, 150 NULL, 151 }; 152 ATTRIBUTE_GROUPS(amba_dev); 153 154 #ifdef CONFIG_PM 155 /* 156 * Hooks to provide runtime PM of the pclk (bus clock). It is safe to 157 * enable/disable the bus clock at runtime PM suspend/resume as this 158 * does not result in loss of context. 159 */ 160 static int amba_pm_runtime_suspend(struct device *dev) 161 { 162 struct amba_device *pcdev = to_amba_device(dev); 163 int ret = pm_generic_runtime_suspend(dev); 164 165 if (ret == 0 && dev->driver) { 166 if (pm_runtime_is_irq_safe(dev)) 167 clk_disable(pcdev->pclk); 168 else 169 clk_disable_unprepare(pcdev->pclk); 170 } 171 172 return ret; 173 } 174 175 static int amba_pm_runtime_resume(struct device *dev) 176 { 177 struct amba_device *pcdev = to_amba_device(dev); 178 int ret; 179 180 if (dev->driver) { 181 if (pm_runtime_is_irq_safe(dev)) 182 ret = clk_enable(pcdev->pclk); 183 else 184 ret = clk_prepare_enable(pcdev->pclk); 185 /* Failure is probably fatal to the system, but... */ 186 if (ret) 187 return ret; 188 } 189 190 return pm_generic_runtime_resume(dev); 191 } 192 #endif /* CONFIG_PM */ 193 194 static const struct dev_pm_ops amba_pm = { 195 .suspend = pm_generic_suspend, 196 .resume = pm_generic_resume, 197 .freeze = pm_generic_freeze, 198 .thaw = pm_generic_thaw, 199 .poweroff = pm_generic_poweroff, 200 .restore = pm_generic_restore, 201 SET_RUNTIME_PM_OPS( 202 amba_pm_runtime_suspend, 203 amba_pm_runtime_resume, 204 NULL 205 ) 206 }; 207 208 /* 209 * Primecells are part of the Advanced Microcontroller Bus Architecture, 210 * so we call the bus "amba". 211 * DMA configuration for platform and AMBA bus is same. So here we reuse 212 * platform's DMA config routine. 213 */ 214 struct bus_type amba_bustype = { 215 .name = "amba", 216 .dev_groups = amba_dev_groups, 217 .match = amba_match, 218 .uevent = amba_uevent, 219 .dma_configure = platform_dma_configure, 220 .pm = &amba_pm, 221 }; 222 EXPORT_SYMBOL_GPL(amba_bustype); 223 224 static int __init amba_init(void) 225 { 226 return bus_register(&amba_bustype); 227 } 228 229 postcore_initcall(amba_init); 230 231 static int amba_get_enable_pclk(struct amba_device *pcdev) 232 { 233 int ret; 234 235 pcdev->pclk = clk_get(&pcdev->dev, "apb_pclk"); 236 if (IS_ERR(pcdev->pclk)) 237 return PTR_ERR(pcdev->pclk); 238 239 ret = clk_prepare_enable(pcdev->pclk); 240 if (ret) 241 clk_put(pcdev->pclk); 242 243 return ret; 244 } 245 246 static void amba_put_disable_pclk(struct amba_device *pcdev) 247 { 248 clk_disable_unprepare(pcdev->pclk); 249 clk_put(pcdev->pclk); 250 } 251 252 /* 253 * These are the device model conversion veneers; they convert the 254 * device model structures to our more specific structures. 255 */ 256 static int amba_probe(struct device *dev) 257 { 258 struct amba_device *pcdev = to_amba_device(dev); 259 struct amba_driver *pcdrv = to_amba_driver(dev->driver); 260 const struct amba_id *id = amba_lookup(pcdrv->id_table, pcdev); 261 int ret; 262 263 do { 264 ret = of_clk_set_defaults(dev->of_node, false); 265 if (ret < 0) 266 break; 267 268 ret = dev_pm_domain_attach(dev, true); 269 if (ret) 270 break; 271 272 ret = amba_get_enable_pclk(pcdev); 273 if (ret) { 274 dev_pm_domain_detach(dev, true); 275 break; 276 } 277 278 pm_runtime_get_noresume(dev); 279 pm_runtime_set_active(dev); 280 pm_runtime_enable(dev); 281 282 ret = pcdrv->probe(pcdev, id); 283 if (ret == 0) 284 break; 285 286 pm_runtime_disable(dev); 287 pm_runtime_set_suspended(dev); 288 pm_runtime_put_noidle(dev); 289 290 amba_put_disable_pclk(pcdev); 291 dev_pm_domain_detach(dev, true); 292 } while (0); 293 294 return ret; 295 } 296 297 static int amba_remove(struct device *dev) 298 { 299 struct amba_device *pcdev = to_amba_device(dev); 300 struct amba_driver *drv = to_amba_driver(dev->driver); 301 int ret; 302 303 pm_runtime_get_sync(dev); 304 ret = drv->remove(pcdev); 305 pm_runtime_put_noidle(dev); 306 307 /* Undo the runtime PM settings in amba_probe() */ 308 pm_runtime_disable(dev); 309 pm_runtime_set_suspended(dev); 310 pm_runtime_put_noidle(dev); 311 312 amba_put_disable_pclk(pcdev); 313 dev_pm_domain_detach(dev, true); 314 315 return ret; 316 } 317 318 static void amba_shutdown(struct device *dev) 319 { 320 struct amba_driver *drv = to_amba_driver(dev->driver); 321 drv->shutdown(to_amba_device(dev)); 322 } 323 324 /** 325 * amba_driver_register - register an AMBA device driver 326 * @drv: amba device driver structure 327 * 328 * Register an AMBA device driver with the Linux device model 329 * core. If devices pre-exist, the drivers probe function will 330 * be called. 331 */ 332 int amba_driver_register(struct amba_driver *drv) 333 { 334 drv->drv.bus = &amba_bustype; 335 336 #define SETFN(fn) if (drv->fn) drv->drv.fn = amba_##fn 337 SETFN(probe); 338 SETFN(remove); 339 SETFN(shutdown); 340 341 return driver_register(&drv->drv); 342 } 343 344 /** 345 * amba_driver_unregister - remove an AMBA device driver 346 * @drv: AMBA device driver structure to remove 347 * 348 * Unregister an AMBA device driver from the Linux device 349 * model. The device model will call the drivers remove function 350 * for each device the device driver is currently handling. 351 */ 352 void amba_driver_unregister(struct amba_driver *drv) 353 { 354 driver_unregister(&drv->drv); 355 } 356 357 358 static void amba_device_release(struct device *dev) 359 { 360 struct amba_device *d = to_amba_device(dev); 361 362 if (d->res.parent) 363 release_resource(&d->res); 364 kfree(d); 365 } 366 367 static int amba_device_try_add(struct amba_device *dev, struct resource *parent) 368 { 369 u32 size; 370 void __iomem *tmp; 371 int i, ret; 372 373 WARN_ON(dev->irq[0] == (unsigned int)-1); 374 WARN_ON(dev->irq[1] == (unsigned int)-1); 375 376 ret = request_resource(parent, &dev->res); 377 if (ret) 378 goto err_out; 379 380 /* Hard-coded primecell ID instead of plug-n-play */ 381 if (dev->periphid != 0) 382 goto skip_probe; 383 384 /* 385 * Dynamically calculate the size of the resource 386 * and use this for iomap 387 */ 388 size = resource_size(&dev->res); 389 tmp = ioremap(dev->res.start, size); 390 if (!tmp) { 391 ret = -ENOMEM; 392 goto err_release; 393 } 394 395 ret = dev_pm_domain_attach(&dev->dev, true); 396 if (ret) { 397 iounmap(tmp); 398 goto err_release; 399 } 400 401 ret = amba_get_enable_pclk(dev); 402 if (ret == 0) { 403 u32 pid, cid; 404 405 /* 406 * Read pid and cid based on size of resource 407 * they are located at end of region 408 */ 409 for (pid = 0, i = 0; i < 4; i++) 410 pid |= (readl(tmp + size - 0x20 + 4 * i) & 255) << 411 (i * 8); 412 for (cid = 0, i = 0; i < 4; i++) 413 cid |= (readl(tmp + size - 0x10 + 4 * i) & 255) << 414 (i * 8); 415 416 if (cid == CORESIGHT_CID) { 417 /* set the base to the start of the last 4k block */ 418 void __iomem *csbase = tmp + size - 4096; 419 420 dev->uci.devarch = 421 readl(csbase + UCI_REG_DEVARCH_OFFSET); 422 dev->uci.devtype = 423 readl(csbase + UCI_REG_DEVTYPE_OFFSET) & 0xff; 424 } 425 426 amba_put_disable_pclk(dev); 427 428 if (cid == AMBA_CID || cid == CORESIGHT_CID) { 429 dev->periphid = pid; 430 dev->cid = cid; 431 } 432 433 if (!dev->periphid) 434 ret = -ENODEV; 435 } 436 437 iounmap(tmp); 438 dev_pm_domain_detach(&dev->dev, true); 439 440 if (ret) 441 goto err_release; 442 443 skip_probe: 444 ret = device_add(&dev->dev); 445 if (ret) 446 goto err_release; 447 448 if (dev->irq[0]) 449 ret = device_create_file(&dev->dev, &dev_attr_irq0); 450 if (ret == 0 && dev->irq[1]) 451 ret = device_create_file(&dev->dev, &dev_attr_irq1); 452 if (ret == 0) 453 return ret; 454 455 device_unregister(&dev->dev); 456 457 err_release: 458 release_resource(&dev->res); 459 err_out: 460 return ret; 461 } 462 463 /* 464 * Registration of AMBA device require reading its pid and cid registers. 465 * To do this, the device must be turned on (if it is a part of power domain) 466 * and have clocks enabled. However in some cases those resources might not be 467 * yet available. Returning EPROBE_DEFER is not a solution in such case, 468 * because callers don't handle this special error code. Instead such devices 469 * are added to the special list and their registration is retried from 470 * periodic worker, until all resources are available and registration succeeds. 471 */ 472 struct deferred_device { 473 struct amba_device *dev; 474 struct resource *parent; 475 struct list_head node; 476 }; 477 478 static LIST_HEAD(deferred_devices); 479 static DEFINE_MUTEX(deferred_devices_lock); 480 481 static void amba_deferred_retry_func(struct work_struct *dummy); 482 static DECLARE_DELAYED_WORK(deferred_retry_work, amba_deferred_retry_func); 483 484 #define DEFERRED_DEVICE_TIMEOUT (msecs_to_jiffies(5 * 1000)) 485 486 static void amba_deferred_retry_func(struct work_struct *dummy) 487 { 488 struct deferred_device *ddev, *tmp; 489 490 mutex_lock(&deferred_devices_lock); 491 492 list_for_each_entry_safe(ddev, tmp, &deferred_devices, node) { 493 int ret = amba_device_try_add(ddev->dev, ddev->parent); 494 495 if (ret == -EPROBE_DEFER) 496 continue; 497 498 list_del_init(&ddev->node); 499 kfree(ddev); 500 } 501 502 if (!list_empty(&deferred_devices)) 503 schedule_delayed_work(&deferred_retry_work, 504 DEFERRED_DEVICE_TIMEOUT); 505 506 mutex_unlock(&deferred_devices_lock); 507 } 508 509 /** 510 * amba_device_add - add a previously allocated AMBA device structure 511 * @dev: AMBA device allocated by amba_device_alloc 512 * @parent: resource parent for this devices resources 513 * 514 * Claim the resource, and read the device cell ID if not already 515 * initialized. Register the AMBA device with the Linux device 516 * manager. 517 */ 518 int amba_device_add(struct amba_device *dev, struct resource *parent) 519 { 520 int ret = amba_device_try_add(dev, parent); 521 522 if (ret == -EPROBE_DEFER) { 523 struct deferred_device *ddev; 524 525 ddev = kmalloc(sizeof(*ddev), GFP_KERNEL); 526 if (!ddev) 527 return -ENOMEM; 528 529 ddev->dev = dev; 530 ddev->parent = parent; 531 ret = 0; 532 533 mutex_lock(&deferred_devices_lock); 534 535 if (list_empty(&deferred_devices)) 536 schedule_delayed_work(&deferred_retry_work, 537 DEFERRED_DEVICE_TIMEOUT); 538 list_add_tail(&ddev->node, &deferred_devices); 539 540 mutex_unlock(&deferred_devices_lock); 541 } 542 return ret; 543 } 544 EXPORT_SYMBOL_GPL(amba_device_add); 545 546 static struct amba_device * 547 amba_aphb_device_add(struct device *parent, const char *name, 548 resource_size_t base, size_t size, int irq1, int irq2, 549 void *pdata, unsigned int periphid, u64 dma_mask, 550 struct resource *resbase) 551 { 552 struct amba_device *dev; 553 int ret; 554 555 dev = amba_device_alloc(name, base, size); 556 if (!dev) 557 return ERR_PTR(-ENOMEM); 558 559 dev->dev.coherent_dma_mask = dma_mask; 560 dev->irq[0] = irq1; 561 dev->irq[1] = irq2; 562 dev->periphid = periphid; 563 dev->dev.platform_data = pdata; 564 dev->dev.parent = parent; 565 566 ret = amba_device_add(dev, resbase); 567 if (ret) { 568 amba_device_put(dev); 569 return ERR_PTR(ret); 570 } 571 572 return dev; 573 } 574 575 struct amba_device * 576 amba_apb_device_add(struct device *parent, const char *name, 577 resource_size_t base, size_t size, int irq1, int irq2, 578 void *pdata, unsigned int periphid) 579 { 580 return amba_aphb_device_add(parent, name, base, size, irq1, irq2, pdata, 581 periphid, 0, &iomem_resource); 582 } 583 EXPORT_SYMBOL_GPL(amba_apb_device_add); 584 585 struct amba_device * 586 amba_ahb_device_add(struct device *parent, const char *name, 587 resource_size_t base, size_t size, int irq1, int irq2, 588 void *pdata, unsigned int periphid) 589 { 590 return amba_aphb_device_add(parent, name, base, size, irq1, irq2, pdata, 591 periphid, ~0ULL, &iomem_resource); 592 } 593 EXPORT_SYMBOL_GPL(amba_ahb_device_add); 594 595 struct amba_device * 596 amba_apb_device_add_res(struct device *parent, const char *name, 597 resource_size_t base, size_t size, int irq1, 598 int irq2, void *pdata, unsigned int periphid, 599 struct resource *resbase) 600 { 601 return amba_aphb_device_add(parent, name, base, size, irq1, irq2, pdata, 602 periphid, 0, resbase); 603 } 604 EXPORT_SYMBOL_GPL(amba_apb_device_add_res); 605 606 struct amba_device * 607 amba_ahb_device_add_res(struct device *parent, const char *name, 608 resource_size_t base, size_t size, int irq1, 609 int irq2, void *pdata, unsigned int periphid, 610 struct resource *resbase) 611 { 612 return amba_aphb_device_add(parent, name, base, size, irq1, irq2, pdata, 613 periphid, ~0ULL, resbase); 614 } 615 EXPORT_SYMBOL_GPL(amba_ahb_device_add_res); 616 617 618 static void amba_device_initialize(struct amba_device *dev, const char *name) 619 { 620 device_initialize(&dev->dev); 621 if (name) 622 dev_set_name(&dev->dev, "%s", name); 623 dev->dev.release = amba_device_release; 624 dev->dev.bus = &amba_bustype; 625 dev->dev.dma_mask = &dev->dev.coherent_dma_mask; 626 dev->res.name = dev_name(&dev->dev); 627 } 628 629 /** 630 * amba_device_alloc - allocate an AMBA device 631 * @name: sysfs name of the AMBA device 632 * @base: base of AMBA device 633 * @size: size of AMBA device 634 * 635 * Allocate and initialize an AMBA device structure. Returns %NULL 636 * on failure. 637 */ 638 struct amba_device *amba_device_alloc(const char *name, resource_size_t base, 639 size_t size) 640 { 641 struct amba_device *dev; 642 643 dev = kzalloc(sizeof(*dev), GFP_KERNEL); 644 if (dev) { 645 amba_device_initialize(dev, name); 646 dev->res.start = base; 647 dev->res.end = base + size - 1; 648 dev->res.flags = IORESOURCE_MEM; 649 } 650 651 return dev; 652 } 653 EXPORT_SYMBOL_GPL(amba_device_alloc); 654 655 /** 656 * amba_device_register - register an AMBA device 657 * @dev: AMBA device to register 658 * @parent: parent memory resource 659 * 660 * Setup the AMBA device, reading the cell ID if present. 661 * Claim the resource, and register the AMBA device with 662 * the Linux device manager. 663 */ 664 int amba_device_register(struct amba_device *dev, struct resource *parent) 665 { 666 amba_device_initialize(dev, dev->dev.init_name); 667 dev->dev.init_name = NULL; 668 669 return amba_device_add(dev, parent); 670 } 671 672 /** 673 * amba_device_put - put an AMBA device 674 * @dev: AMBA device to put 675 */ 676 void amba_device_put(struct amba_device *dev) 677 { 678 put_device(&dev->dev); 679 } 680 EXPORT_SYMBOL_GPL(amba_device_put); 681 682 /** 683 * amba_device_unregister - unregister an AMBA device 684 * @dev: AMBA device to remove 685 * 686 * Remove the specified AMBA device from the Linux device 687 * manager. All files associated with this object will be 688 * destroyed, and device drivers notified that the device has 689 * been removed. The AMBA device's resources including 690 * the amba_device structure will be freed once all 691 * references to it have been dropped. 692 */ 693 void amba_device_unregister(struct amba_device *dev) 694 { 695 device_unregister(&dev->dev); 696 } 697 698 699 struct find_data { 700 struct amba_device *dev; 701 struct device *parent; 702 const char *busid; 703 unsigned int id; 704 unsigned int mask; 705 }; 706 707 static int amba_find_match(struct device *dev, void *data) 708 { 709 struct find_data *d = data; 710 struct amba_device *pcdev = to_amba_device(dev); 711 int r; 712 713 r = (pcdev->periphid & d->mask) == d->id; 714 if (d->parent) 715 r &= d->parent == dev->parent; 716 if (d->busid) 717 r &= strcmp(dev_name(dev), d->busid) == 0; 718 719 if (r) { 720 get_device(dev); 721 d->dev = pcdev; 722 } 723 724 return r; 725 } 726 727 /** 728 * amba_find_device - locate an AMBA device given a bus id 729 * @busid: bus id for device (or NULL) 730 * @parent: parent device (or NULL) 731 * @id: peripheral ID (or 0) 732 * @mask: peripheral ID mask (or 0) 733 * 734 * Return the AMBA device corresponding to the supplied parameters. 735 * If no device matches, returns NULL. 736 * 737 * NOTE: When a valid device is found, its refcount is 738 * incremented, and must be decremented before the returned 739 * reference. 740 */ 741 struct amba_device * 742 amba_find_device(const char *busid, struct device *parent, unsigned int id, 743 unsigned int mask) 744 { 745 struct find_data data; 746 747 data.dev = NULL; 748 data.parent = parent; 749 data.busid = busid; 750 data.id = id; 751 data.mask = mask; 752 753 bus_for_each_dev(&amba_bustype, NULL, &data, amba_find_match); 754 755 return data.dev; 756 } 757 758 /** 759 * amba_request_regions - request all mem regions associated with device 760 * @dev: amba_device structure for device 761 * @name: name, or NULL to use driver name 762 */ 763 int amba_request_regions(struct amba_device *dev, const char *name) 764 { 765 int ret = 0; 766 u32 size; 767 768 if (!name) 769 name = dev->dev.driver->name; 770 771 size = resource_size(&dev->res); 772 773 if (!request_mem_region(dev->res.start, size, name)) 774 ret = -EBUSY; 775 776 return ret; 777 } 778 779 /** 780 * amba_release_regions - release mem regions associated with device 781 * @dev: amba_device structure for device 782 * 783 * Release regions claimed by a successful call to amba_request_regions. 784 */ 785 void amba_release_regions(struct amba_device *dev) 786 { 787 u32 size; 788 789 size = resource_size(&dev->res); 790 release_mem_region(dev->res.start, size); 791 } 792 793 EXPORT_SYMBOL(amba_driver_register); 794 EXPORT_SYMBOL(amba_driver_unregister); 795 EXPORT_SYMBOL(amba_device_register); 796 EXPORT_SYMBOL(amba_device_unregister); 797 EXPORT_SYMBOL(amba_find_device); 798 EXPORT_SYMBOL(amba_request_regions); 799 EXPORT_SYMBOL(amba_release_regions); 800