root/drivers/amba/bus.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. amba_cs_uci_id_match
  2. amba_lookup
  3. amba_match
  4. amba_uevent
  5. driver_override_show
  6. driver_override_store
  7. amba_pm_runtime_suspend
  8. amba_pm_runtime_resume
  9. amba_init
  10. amba_get_enable_pclk
  11. amba_put_disable_pclk
  12. amba_probe
  13. amba_remove
  14. amba_shutdown
  15. amba_driver_register
  16. amba_driver_unregister
  17. amba_device_release
  18. amba_device_try_add
  19. amba_deferred_retry_func
  20. amba_device_add
  21. amba_aphb_device_add
  22. amba_apb_device_add
  23. amba_ahb_device_add
  24. amba_apb_device_add_res
  25. amba_ahb_device_add_res
  26. amba_device_initialize
  27. amba_device_alloc
  28. amba_device_register
  29. amba_device_put
  30. amba_device_unregister
  31. amba_find_match
  32. amba_find_device
  33. amba_request_regions
  34. amba_release_regions

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

/* [<][>][^][v][top][bottom][index][help] */