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