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