linux/arch/arm/mach-omap2/omap_device.c
<<
>>
Prefs
   1/*
   2 * omap_device implementation
   3 *
   4 * Copyright (C) 2009-2010 Nokia Corporation
   5 * Paul Walmsley, Kevin Hilman
   6 *
   7 * Developed in collaboration with (alphabetical order): Benoit
   8 * Cousson, Thara Gopinath, Tony Lindgren, Rajendra Nayak, Vikram
   9 * Pandita, Sakari Poussa, Anand Sawant, Santosh Shilimkar, Richard
  10 * Woodruff
  11 *
  12 * This program is free software; you can redistribute it and/or modify
  13 * it under the terms of the GNU General Public License version 2 as
  14 * published by the Free Software Foundation.
  15 *
  16 * This code provides a consistent interface for OMAP device drivers
  17 * to control power management and interconnect properties of their
  18 * devices.
  19 *
  20 * In the medium- to long-term, this code should be implemented as a
  21 * proper omap_bus/omap_device in Linux, no more platform_data func
  22 * pointers
  23 *
  24 *
  25 */
  26#undef DEBUG
  27
  28#include <linux/kernel.h>
  29#include <linux/platform_device.h>
  30#include <linux/slab.h>
  31#include <linux/err.h>
  32#include <linux/io.h>
  33#include <linux/clk.h>
  34#include <linux/clkdev.h>
  35#include <linux/pm_domain.h>
  36#include <linux/pm_runtime.h>
  37#include <linux/of.h>
  38#include <linux/notifier.h>
  39
  40#include "common.h"
  41#include "soc.h"
  42#include "omap_device.h"
  43#include "omap_hwmod.h"
  44
  45/* Private functions */
  46
  47static void _add_clkdev(struct omap_device *od, const char *clk_alias,
  48                       const char *clk_name)
  49{
  50        struct clk *r;
  51        int rc;
  52
  53        if (!clk_alias || !clk_name)
  54                return;
  55
  56        dev_dbg(&od->pdev->dev, "Creating %s -> %s\n", clk_alias, clk_name);
  57
  58        r = clk_get_sys(dev_name(&od->pdev->dev), clk_alias);
  59        if (!IS_ERR(r)) {
  60                dev_dbg(&od->pdev->dev,
  61                         "alias %s already exists\n", clk_alias);
  62                clk_put(r);
  63                return;
  64        }
  65
  66        rc = clk_add_alias(clk_alias, dev_name(&od->pdev->dev), clk_name, NULL);
  67        if (rc) {
  68                if (rc == -ENODEV || rc == -ENOMEM)
  69                        dev_err(&od->pdev->dev,
  70                                "clkdev_alloc for %s failed\n", clk_alias);
  71                else
  72                        dev_err(&od->pdev->dev,
  73                                "clk_get for %s failed\n", clk_name);
  74        }
  75}
  76
  77/**
  78 * _add_hwmod_clocks_clkdev - Add clkdev entry for hwmod optional clocks
  79 * and main clock
  80 * @od: struct omap_device *od
  81 * @oh: struct omap_hwmod *oh
  82 *
  83 * For the main clock and every optional clock present per hwmod per
  84 * omap_device, this function adds an entry in the clkdev table of the
  85 * form <dev-id=dev_name, con-id=role> if it does not exist already.
  86 *
  87 * The function is called from inside omap_device_build_ss(), after
  88 * omap_device_register.
  89 *
  90 * This allows drivers to get a pointer to its optional clocks based on its role
  91 * by calling clk_get(<dev*>, <role>).
  92 * In the case of the main clock, a "fck" alias is used.
  93 *
  94 * No return value.
  95 */
  96static void _add_hwmod_clocks_clkdev(struct omap_device *od,
  97                                     struct omap_hwmod *oh)
  98{
  99        int i;
 100
 101        _add_clkdev(od, "fck", oh->main_clk);
 102
 103        for (i = 0; i < oh->opt_clks_cnt; i++)
 104                _add_clkdev(od, oh->opt_clks[i].role, oh->opt_clks[i].clk);
 105}
 106
 107
 108/**
 109 * omap_device_build_from_dt - build an omap_device with multiple hwmods
 110 * @pdev_name: name of the platform_device driver to use
 111 * @pdev_id: this platform_device's connection ID
 112 * @oh: ptr to the single omap_hwmod that backs this omap_device
 113 * @pdata: platform_data ptr to associate with the platform_device
 114 * @pdata_len: amount of memory pointed to by @pdata
 115 *
 116 * Function for building an omap_device already registered from device-tree
 117 *
 118 * Returns 0 or PTR_ERR() on error.
 119 */
 120static int omap_device_build_from_dt(struct platform_device *pdev)
 121{
 122        struct omap_hwmod **hwmods;
 123        struct omap_device *od;
 124        struct omap_hwmod *oh;
 125        struct device_node *node = pdev->dev.of_node;
 126        const char *oh_name;
 127        int oh_cnt, i, ret = 0;
 128        bool device_active = false;
 129
 130        oh_cnt = of_property_count_strings(node, "ti,hwmods");
 131        if (oh_cnt <= 0) {
 132                dev_dbg(&pdev->dev, "No 'hwmods' to build omap_device\n");
 133                return -ENODEV;
 134        }
 135
 136        hwmods = kzalloc(sizeof(struct omap_hwmod *) * oh_cnt, GFP_KERNEL);
 137        if (!hwmods) {
 138                ret = -ENOMEM;
 139                goto odbfd_exit;
 140        }
 141
 142        for (i = 0; i < oh_cnt; i++) {
 143                of_property_read_string_index(node, "ti,hwmods", i, &oh_name);
 144                oh = omap_hwmod_lookup(oh_name);
 145                if (!oh) {
 146                        dev_err(&pdev->dev, "Cannot lookup hwmod '%s'\n",
 147                                oh_name);
 148                        ret = -EINVAL;
 149                        goto odbfd_exit1;
 150                }
 151                hwmods[i] = oh;
 152                if (oh->flags & HWMOD_INIT_NO_IDLE)
 153                        device_active = true;
 154        }
 155
 156        od = omap_device_alloc(pdev, hwmods, oh_cnt);
 157        if (IS_ERR(od)) {
 158                dev_err(&pdev->dev, "Cannot allocate omap_device for :%s\n",
 159                        oh_name);
 160                ret = PTR_ERR(od);
 161                goto odbfd_exit1;
 162        }
 163
 164        /* Fix up missing resource names */
 165        for (i = 0; i < pdev->num_resources; i++) {
 166                struct resource *r = &pdev->resource[i];
 167
 168                if (r->name == NULL)
 169                        r->name = dev_name(&pdev->dev);
 170        }
 171
 172        dev_pm_domain_set(&pdev->dev, &omap_device_pm_domain);
 173
 174        if (device_active) {
 175                omap_device_enable(pdev);
 176                pm_runtime_set_active(&pdev->dev);
 177        }
 178
 179odbfd_exit1:
 180        kfree(hwmods);
 181odbfd_exit:
 182        /* if data/we are at fault.. load up a fail handler */
 183        if (ret)
 184                dev_pm_domain_set(&pdev->dev, &omap_device_fail_pm_domain);
 185
 186        return ret;
 187}
 188
 189static int _omap_device_notifier_call(struct notifier_block *nb,
 190                                      unsigned long event, void *dev)
 191{
 192        struct platform_device *pdev = to_platform_device(dev);
 193        struct omap_device *od;
 194        int err;
 195
 196        switch (event) {
 197        case BUS_NOTIFY_DEL_DEVICE:
 198                if (pdev->archdata.od)
 199                        omap_device_delete(pdev->archdata.od);
 200                break;
 201        case BUS_NOTIFY_UNBOUND_DRIVER:
 202                od = to_omap_device(pdev);
 203                if (od && (od->_state == OMAP_DEVICE_STATE_ENABLED)) {
 204                        dev_info(dev, "enabled after unload, idling\n");
 205                        err = omap_device_idle(pdev);
 206                        if (err)
 207                                dev_err(dev, "failed to idle\n");
 208                }
 209                break;
 210        case BUS_NOTIFY_ADD_DEVICE:
 211                if (pdev->dev.of_node)
 212                        omap_device_build_from_dt(pdev);
 213                omap_auxdata_legacy_init(dev);
 214                /* fall through */
 215        default:
 216                od = to_omap_device(pdev);
 217                if (od)
 218                        od->_driver_status = event;
 219        }
 220
 221        return NOTIFY_DONE;
 222}
 223
 224/**
 225 * _omap_device_enable_hwmods - call omap_hwmod_enable() on all hwmods
 226 * @od: struct omap_device *od
 227 *
 228 * Enable all underlying hwmods.  Returns 0.
 229 */
 230static int _omap_device_enable_hwmods(struct omap_device *od)
 231{
 232        int ret = 0;
 233        int i;
 234
 235        for (i = 0; i < od->hwmods_cnt; i++)
 236                ret |= omap_hwmod_enable(od->hwmods[i]);
 237
 238        return ret;
 239}
 240
 241/**
 242 * _omap_device_idle_hwmods - call omap_hwmod_idle() on all hwmods
 243 * @od: struct omap_device *od
 244 *
 245 * Idle all underlying hwmods.  Returns 0.
 246 */
 247static int _omap_device_idle_hwmods(struct omap_device *od)
 248{
 249        int ret = 0;
 250        int i;
 251
 252        for (i = 0; i < od->hwmods_cnt; i++)
 253                ret |= omap_hwmod_idle(od->hwmods[i]);
 254
 255        return ret;
 256}
 257
 258/* Public functions for use by core code */
 259
 260/**
 261 * omap_device_get_context_loss_count - get lost context count
 262 * @od: struct omap_device *
 263 *
 264 * Using the primary hwmod, query the context loss count for this
 265 * device.
 266 *
 267 * Callers should consider context for this device lost any time this
 268 * function returns a value different than the value the caller got
 269 * the last time it called this function.
 270 *
 271 * If any hwmods exist for the omap_device assoiated with @pdev,
 272 * return the context loss counter for that hwmod, otherwise return
 273 * zero.
 274 */
 275int omap_device_get_context_loss_count(struct platform_device *pdev)
 276{
 277        struct omap_device *od;
 278        u32 ret = 0;
 279
 280        od = to_omap_device(pdev);
 281
 282        if (od->hwmods_cnt)
 283                ret = omap_hwmod_get_context_loss_count(od->hwmods[0]);
 284
 285        return ret;
 286}
 287
 288/**
 289 * omap_device_count_resources - count number of struct resource entries needed
 290 * @od: struct omap_device *
 291 * @flags: Type of resources to include when counting (IRQ/DMA/MEM)
 292 *
 293 * Count the number of struct resource entries needed for this
 294 * omap_device @od.  Used by omap_device_build_ss() to determine how
 295 * much memory to allocate before calling
 296 * omap_device_fill_resources().  Returns the count.
 297 */
 298static int omap_device_count_resources(struct omap_device *od,
 299                                       unsigned long flags)
 300{
 301        int c = 0;
 302        int i;
 303
 304        for (i = 0; i < od->hwmods_cnt; i++)
 305                c += omap_hwmod_count_resources(od->hwmods[i], flags);
 306
 307        pr_debug("omap_device: %s: counted %d total resources across %d hwmods\n",
 308                 od->pdev->name, c, od->hwmods_cnt);
 309
 310        return c;
 311}
 312
 313/**
 314 * omap_device_fill_resources - fill in array of struct resource
 315 * @od: struct omap_device *
 316 * @res: pointer to an array of struct resource to be filled in
 317 *
 318 * Populate one or more empty struct resource pointed to by @res with
 319 * the resource data for this omap_device @od.  Used by
 320 * omap_device_build_ss() after calling omap_device_count_resources().
 321 * Ideally this function would not be needed at all.  If omap_device
 322 * replaces platform_device, then we can specify our own
 323 * get_resource()/ get_irq()/etc functions that use the underlying
 324 * omap_hwmod information.  Or if platform_device is extended to use
 325 * subarchitecture-specific function pointers, the various
 326 * platform_device functions can simply call omap_device internal
 327 * functions to get device resources.  Hacking around the existing
 328 * platform_device code wastes memory.  Returns 0.
 329 */
 330static int omap_device_fill_resources(struct omap_device *od,
 331                                      struct resource *res)
 332{
 333        int i, r;
 334
 335        for (i = 0; i < od->hwmods_cnt; i++) {
 336                r = omap_hwmod_fill_resources(od->hwmods[i], res);
 337                res += r;
 338        }
 339
 340        return 0;
 341}
 342
 343/**
 344 * _od_fill_dma_resources - fill in array of struct resource with dma resources
 345 * @od: struct omap_device *
 346 * @res: pointer to an array of struct resource to be filled in
 347 *
 348 * Populate one or more empty struct resource pointed to by @res with
 349 * the dma resource data for this omap_device @od.  Used by
 350 * omap_device_alloc() after calling omap_device_count_resources().
 351 *
 352 * Ideally this function would not be needed at all.  If we have
 353 * mechanism to get dma resources from DT.
 354 *
 355 * Returns 0.
 356 */
 357static int _od_fill_dma_resources(struct omap_device *od,
 358                                      struct resource *res)
 359{
 360        int i, r;
 361
 362        for (i = 0; i < od->hwmods_cnt; i++) {
 363                r = omap_hwmod_fill_dma_resources(od->hwmods[i], res);
 364                res += r;
 365        }
 366
 367        return 0;
 368}
 369
 370/**
 371 * omap_device_alloc - allocate an omap_device
 372 * @pdev: platform_device that will be included in this omap_device
 373 * @oh: ptr to the single omap_hwmod that backs this omap_device
 374 * @pdata: platform_data ptr to associate with the platform_device
 375 * @pdata_len: amount of memory pointed to by @pdata
 376 *
 377 * Convenience function for allocating an omap_device structure and filling
 378 * hwmods, and resources.
 379 *
 380 * Returns an struct omap_device pointer or ERR_PTR() on error;
 381 */
 382struct omap_device *omap_device_alloc(struct platform_device *pdev,
 383                                        struct omap_hwmod **ohs, int oh_cnt)
 384{
 385        int ret = -ENOMEM;
 386        struct omap_device *od;
 387        struct resource *res = NULL;
 388        int i, res_count;
 389        struct omap_hwmod **hwmods;
 390
 391        od = kzalloc(sizeof(struct omap_device), GFP_KERNEL);
 392        if (!od) {
 393                ret = -ENOMEM;
 394                goto oda_exit1;
 395        }
 396        od->hwmods_cnt = oh_cnt;
 397
 398        hwmods = kmemdup(ohs, sizeof(struct omap_hwmod *) * oh_cnt, GFP_KERNEL);
 399        if (!hwmods)
 400                goto oda_exit2;
 401
 402        od->hwmods = hwmods;
 403        od->pdev = pdev;
 404
 405        /*
 406         * Non-DT Boot:
 407         *   Here, pdev->num_resources = 0, and we should get all the
 408         *   resources from hwmod.
 409         *
 410         * DT Boot:
 411         *   OF framework will construct the resource structure (currently
 412         *   does for MEM & IRQ resource) and we should respect/use these
 413         *   resources, killing hwmod dependency.
 414         *   If pdev->num_resources > 0, we assume that MEM & IRQ resources
 415         *   have been allocated by OF layer already (through DTB).
 416         *   As preparation for the future we examine the OF provided resources
 417         *   to see if we have DMA resources provided already. In this case
 418         *   there is no need to update the resources for the device, we use the
 419         *   OF provided ones.
 420         *
 421         * TODO: Once DMA resource is available from OF layer, we should
 422         *   kill filling any resources from hwmod.
 423         */
 424        if (!pdev->num_resources) {
 425                /* Count all resources for the device */
 426                res_count = omap_device_count_resources(od, IORESOURCE_IRQ |
 427                                                            IORESOURCE_DMA |
 428                                                            IORESOURCE_MEM);
 429        } else {
 430                /* Take a look if we already have DMA resource via DT */
 431                for (i = 0; i < pdev->num_resources; i++) {
 432                        struct resource *r = &pdev->resource[i];
 433
 434                        /* We have it, no need to touch the resources */
 435                        if (r->flags == IORESOURCE_DMA)
 436                                goto have_everything;
 437                }
 438                /* Count only DMA resources for the device */
 439                res_count = omap_device_count_resources(od, IORESOURCE_DMA);
 440                /* The device has no DMA resource, no need for update */
 441                if (!res_count)
 442                        goto have_everything;
 443
 444                res_count += pdev->num_resources;
 445        }
 446
 447        /* Allocate resources memory to account for new resources */
 448        res = kzalloc(sizeof(struct resource) * res_count, GFP_KERNEL);
 449        if (!res)
 450                goto oda_exit3;
 451
 452        if (!pdev->num_resources) {
 453                dev_dbg(&pdev->dev, "%s: using %d resources from hwmod\n",
 454                        __func__, res_count);
 455                omap_device_fill_resources(od, res);
 456        } else {
 457                dev_dbg(&pdev->dev,
 458                        "%s: appending %d DMA resources from hwmod\n",
 459                        __func__, res_count - pdev->num_resources);
 460                memcpy(res, pdev->resource,
 461                       sizeof(struct resource) * pdev->num_resources);
 462                _od_fill_dma_resources(od, &res[pdev->num_resources]);
 463        }
 464
 465        ret = platform_device_add_resources(pdev, res, res_count);
 466        kfree(res);
 467
 468        if (ret)
 469                goto oda_exit3;
 470
 471have_everything:
 472        pdev->archdata.od = od;
 473
 474        for (i = 0; i < oh_cnt; i++) {
 475                hwmods[i]->od = od;
 476                _add_hwmod_clocks_clkdev(od, hwmods[i]);
 477        }
 478
 479        return od;
 480
 481oda_exit3:
 482        kfree(hwmods);
 483oda_exit2:
 484        kfree(od);
 485oda_exit1:
 486        dev_err(&pdev->dev, "omap_device: build failed (%d)\n", ret);
 487
 488        return ERR_PTR(ret);
 489}
 490
 491void omap_device_delete(struct omap_device *od)
 492{
 493        if (!od)
 494                return;
 495
 496        od->pdev->archdata.od = NULL;
 497        kfree(od->hwmods);
 498        kfree(od);
 499}
 500
 501/**
 502 * omap_device_build - build and register an omap_device with one omap_hwmod
 503 * @pdev_name: name of the platform_device driver to use
 504 * @pdev_id: this platform_device's connection ID
 505 * @oh: ptr to the single omap_hwmod that backs this omap_device
 506 * @pdata: platform_data ptr to associate with the platform_device
 507 * @pdata_len: amount of memory pointed to by @pdata
 508 *
 509 * Convenience function for building and registering a single
 510 * omap_device record, which in turn builds and registers a
 511 * platform_device record.  See omap_device_build_ss() for more
 512 * information.  Returns ERR_PTR(-EINVAL) if @oh is NULL; otherwise,
 513 * passes along the return value of omap_device_build_ss().
 514 */
 515struct platform_device __init *omap_device_build(const char *pdev_name,
 516                                                 int pdev_id,
 517                                                 struct omap_hwmod *oh,
 518                                                 void *pdata, int pdata_len)
 519{
 520        struct omap_hwmod *ohs[] = { oh };
 521
 522        if (!oh)
 523                return ERR_PTR(-EINVAL);
 524
 525        return omap_device_build_ss(pdev_name, pdev_id, ohs, 1, pdata,
 526                                    pdata_len);
 527}
 528
 529/**
 530 * omap_device_build_ss - build and register an omap_device with multiple hwmods
 531 * @pdev_name: name of the platform_device driver to use
 532 * @pdev_id: this platform_device's connection ID
 533 * @oh: ptr to the single omap_hwmod that backs this omap_device
 534 * @pdata: platform_data ptr to associate with the platform_device
 535 * @pdata_len: amount of memory pointed to by @pdata
 536 *
 537 * Convenience function for building and registering an omap_device
 538 * subsystem record.  Subsystem records consist of multiple
 539 * omap_hwmods.  This function in turn builds and registers a
 540 * platform_device record.  Returns an ERR_PTR() on error, or passes
 541 * along the return value of omap_device_register().
 542 */
 543struct platform_device __init *omap_device_build_ss(const char *pdev_name,
 544                                                    int pdev_id,
 545                                                    struct omap_hwmod **ohs,
 546                                                    int oh_cnt, void *pdata,
 547                                                    int pdata_len)
 548{
 549        int ret = -ENOMEM;
 550        struct platform_device *pdev;
 551        struct omap_device *od;
 552
 553        if (!ohs || oh_cnt == 0 || !pdev_name)
 554                return ERR_PTR(-EINVAL);
 555
 556        if (!pdata && pdata_len > 0)
 557                return ERR_PTR(-EINVAL);
 558
 559        pdev = platform_device_alloc(pdev_name, pdev_id);
 560        if (!pdev) {
 561                ret = -ENOMEM;
 562                goto odbs_exit;
 563        }
 564
 565        /* Set the dev_name early to allow dev_xxx in omap_device_alloc */
 566        if (pdev->id != -1)
 567                dev_set_name(&pdev->dev, "%s.%d", pdev->name,  pdev->id);
 568        else
 569                dev_set_name(&pdev->dev, "%s", pdev->name);
 570
 571        od = omap_device_alloc(pdev, ohs, oh_cnt);
 572        if (IS_ERR(od))
 573                goto odbs_exit1;
 574
 575        ret = platform_device_add_data(pdev, pdata, pdata_len);
 576        if (ret)
 577                goto odbs_exit2;
 578
 579        ret = omap_device_register(pdev);
 580        if (ret)
 581                goto odbs_exit2;
 582
 583        return pdev;
 584
 585odbs_exit2:
 586        omap_device_delete(od);
 587odbs_exit1:
 588        platform_device_put(pdev);
 589odbs_exit:
 590
 591        pr_err("omap_device: %s: build failed (%d)\n", pdev_name, ret);
 592
 593        return ERR_PTR(ret);
 594}
 595
 596#ifdef CONFIG_PM
 597static int _od_runtime_suspend(struct device *dev)
 598{
 599        struct platform_device *pdev = to_platform_device(dev);
 600        int ret;
 601
 602        ret = pm_generic_runtime_suspend(dev);
 603        if (ret)
 604                return ret;
 605
 606        return omap_device_idle(pdev);
 607}
 608
 609static int _od_runtime_resume(struct device *dev)
 610{
 611        struct platform_device *pdev = to_platform_device(dev);
 612        int ret;
 613
 614        ret = omap_device_enable(pdev);
 615        if (ret) {
 616                dev_err(dev, "use pm_runtime_put_sync_suspend() in driver?\n");
 617                return ret;
 618        }
 619
 620        return pm_generic_runtime_resume(dev);
 621}
 622
 623static int _od_fail_runtime_suspend(struct device *dev)
 624{
 625        dev_warn(dev, "%s: FIXME: missing hwmod/omap_dev info\n", __func__);
 626        return -ENODEV;
 627}
 628
 629static int _od_fail_runtime_resume(struct device *dev)
 630{
 631        dev_warn(dev, "%s: FIXME: missing hwmod/omap_dev info\n", __func__);
 632        return -ENODEV;
 633}
 634
 635#endif
 636
 637#ifdef CONFIG_SUSPEND
 638static int _od_suspend_noirq(struct device *dev)
 639{
 640        struct platform_device *pdev = to_platform_device(dev);
 641        struct omap_device *od = to_omap_device(pdev);
 642        int ret;
 643
 644        /* Don't attempt late suspend on a driver that is not bound */
 645        if (od->_driver_status != BUS_NOTIFY_BOUND_DRIVER)
 646                return 0;
 647
 648        ret = pm_generic_suspend_noirq(dev);
 649
 650        if (!ret && !pm_runtime_status_suspended(dev)) {
 651                if (pm_generic_runtime_suspend(dev) == 0) {
 652                        pm_runtime_set_suspended(dev);
 653                        omap_device_idle(pdev);
 654                        od->flags |= OMAP_DEVICE_SUSPENDED;
 655                }
 656        }
 657
 658        return ret;
 659}
 660
 661static int _od_resume_noirq(struct device *dev)
 662{
 663        struct platform_device *pdev = to_platform_device(dev);
 664        struct omap_device *od = to_omap_device(pdev);
 665
 666        if (od->flags & OMAP_DEVICE_SUSPENDED) {
 667                od->flags &= ~OMAP_DEVICE_SUSPENDED;
 668                omap_device_enable(pdev);
 669                /*
 670                 * XXX: we run before core runtime pm has resumed itself. At
 671                 * this point in time, we just restore the runtime pm state and
 672                 * considering symmetric operations in resume, we donot expect
 673                 * to fail. If we failed, something changed in core runtime_pm
 674                 * framework OR some device driver messed things up, hence, WARN
 675                 */
 676                WARN(pm_runtime_set_active(dev),
 677                     "Could not set %s runtime state active\n", dev_name(dev));
 678                pm_generic_runtime_resume(dev);
 679        }
 680
 681        return pm_generic_resume_noirq(dev);
 682}
 683#else
 684#define _od_suspend_noirq NULL
 685#define _od_resume_noirq NULL
 686#endif
 687
 688struct dev_pm_domain omap_device_fail_pm_domain = {
 689        .ops = {
 690                SET_RUNTIME_PM_OPS(_od_fail_runtime_suspend,
 691                                   _od_fail_runtime_resume, NULL)
 692        }
 693};
 694
 695struct dev_pm_domain omap_device_pm_domain = {
 696        .ops = {
 697                SET_RUNTIME_PM_OPS(_od_runtime_suspend, _od_runtime_resume,
 698                                   NULL)
 699                USE_PLATFORM_PM_SLEEP_OPS
 700                SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(_od_suspend_noirq,
 701                                              _od_resume_noirq)
 702        }
 703};
 704
 705/**
 706 * omap_device_register - register an omap_device with one omap_hwmod
 707 * @od: struct omap_device * to register
 708 *
 709 * Register the omap_device structure.  This currently just calls
 710 * platform_device_register() on the underlying platform_device.
 711 * Returns the return value of platform_device_register().
 712 */
 713int omap_device_register(struct platform_device *pdev)
 714{
 715        pr_debug("omap_device: %s: registering\n", pdev->name);
 716
 717        dev_pm_domain_set(&pdev->dev, &omap_device_pm_domain);
 718        return platform_device_add(pdev);
 719}
 720
 721
 722/* Public functions for use by device drivers through struct platform_data */
 723
 724/**
 725 * omap_device_enable - fully activate an omap_device
 726 * @od: struct omap_device * to activate
 727 *
 728 * Do whatever is necessary for the hwmods underlying omap_device @od
 729 * to be accessible and ready to operate.  This generally involves
 730 * enabling clocks, setting SYSCONFIG registers; and in the future may
 731 * involve remuxing pins.  Device drivers should call this function
 732 * indirectly via pm_runtime_get*().  Returns -EINVAL if called when
 733 * the omap_device is already enabled, or passes along the return
 734 * value of _omap_device_enable_hwmods().
 735 */
 736int omap_device_enable(struct platform_device *pdev)
 737{
 738        int ret;
 739        struct omap_device *od;
 740
 741        od = to_omap_device(pdev);
 742
 743        if (od->_state == OMAP_DEVICE_STATE_ENABLED) {
 744                dev_warn(&pdev->dev,
 745                         "omap_device: %s() called from invalid state %d\n",
 746                         __func__, od->_state);
 747                return -EINVAL;
 748        }
 749
 750        ret = _omap_device_enable_hwmods(od);
 751
 752        if (ret == 0)
 753                od->_state = OMAP_DEVICE_STATE_ENABLED;
 754
 755        return ret;
 756}
 757
 758/**
 759 * omap_device_idle - idle an omap_device
 760 * @od: struct omap_device * to idle
 761 *
 762 * Idle omap_device @od.  Device drivers call this function indirectly
 763 * via pm_runtime_put*().  Returns -EINVAL if the omap_device is not
 764 * currently enabled, or passes along the return value of
 765 * _omap_device_idle_hwmods().
 766 */
 767int omap_device_idle(struct platform_device *pdev)
 768{
 769        int ret;
 770        struct omap_device *od;
 771
 772        od = to_omap_device(pdev);
 773
 774        if (od->_state != OMAP_DEVICE_STATE_ENABLED) {
 775                dev_warn(&pdev->dev,
 776                         "omap_device: %s() called from invalid state %d\n",
 777                         __func__, od->_state);
 778                return -EINVAL;
 779        }
 780
 781        ret = _omap_device_idle_hwmods(od);
 782
 783        if (ret == 0)
 784                od->_state = OMAP_DEVICE_STATE_IDLE;
 785
 786        return ret;
 787}
 788
 789/**
 790 * omap_device_assert_hardreset - set a device's hardreset line
 791 * @pdev: struct platform_device * to reset
 792 * @name: const char * name of the reset line
 793 *
 794 * Set the hardreset line identified by @name on the IP blocks
 795 * associated with the hwmods backing the platform_device @pdev.  All
 796 * of the hwmods associated with @pdev must have the same hardreset
 797 * line linked to them for this to work.  Passes along the return value
 798 * of omap_hwmod_assert_hardreset() in the event of any failure, or
 799 * returns 0 upon success.
 800 */
 801int omap_device_assert_hardreset(struct platform_device *pdev, const char *name)
 802{
 803        struct omap_device *od = to_omap_device(pdev);
 804        int ret = 0;
 805        int i;
 806
 807        for (i = 0; i < od->hwmods_cnt; i++) {
 808                ret = omap_hwmod_assert_hardreset(od->hwmods[i], name);
 809                if (ret)
 810                        break;
 811        }
 812
 813        return ret;
 814}
 815
 816/**
 817 * omap_device_deassert_hardreset - release a device's hardreset line
 818 * @pdev: struct platform_device * to reset
 819 * @name: const char * name of the reset line
 820 *
 821 * Release the hardreset line identified by @name on the IP blocks
 822 * associated with the hwmods backing the platform_device @pdev.  All
 823 * of the hwmods associated with @pdev must have the same hardreset
 824 * line linked to them for this to work.  Passes along the return
 825 * value of omap_hwmod_deassert_hardreset() in the event of any
 826 * failure, or returns 0 upon success.
 827 */
 828int omap_device_deassert_hardreset(struct platform_device *pdev,
 829                                   const char *name)
 830{
 831        struct omap_device *od = to_omap_device(pdev);
 832        int ret = 0;
 833        int i;
 834
 835        for (i = 0; i < od->hwmods_cnt; i++) {
 836                ret = omap_hwmod_deassert_hardreset(od->hwmods[i], name);
 837                if (ret)
 838                        break;
 839        }
 840
 841        return ret;
 842}
 843
 844/**
 845 * omap_device_get_by_hwmod_name() - convert a hwmod name to
 846 * device pointer.
 847 * @oh_name: name of the hwmod device
 848 *
 849 * Returns back a struct device * pointer associated with a hwmod
 850 * device represented by a hwmod_name
 851 */
 852struct device *omap_device_get_by_hwmod_name(const char *oh_name)
 853{
 854        struct omap_hwmod *oh;
 855
 856        if (!oh_name) {
 857                WARN(1, "%s: no hwmod name!\n", __func__);
 858                return ERR_PTR(-EINVAL);
 859        }
 860
 861        oh = omap_hwmod_lookup(oh_name);
 862        if (!oh) {
 863                WARN(1, "%s: no hwmod for %s\n", __func__,
 864                        oh_name);
 865                return ERR_PTR(-ENODEV);
 866        }
 867        if (!oh->od) {
 868                WARN(1, "%s: no omap_device for %s\n", __func__,
 869                        oh_name);
 870                return ERR_PTR(-ENODEV);
 871        }
 872
 873        return &oh->od->pdev->dev;
 874}
 875
 876static struct notifier_block platform_nb = {
 877        .notifier_call = _omap_device_notifier_call,
 878};
 879
 880static int __init omap_device_init(void)
 881{
 882        bus_register_notifier(&platform_bus_type, &platform_nb);
 883        return 0;
 884}
 885omap_postcore_initcall(omap_device_init);
 886
 887/**
 888 * omap_device_late_idle - idle devices without drivers
 889 * @dev: struct device * associated with omap_device
 890 * @data: unused
 891 *
 892 * Check the driver bound status of this device, and idle it
 893 * if there is no driver attached.
 894 */
 895static int __init omap_device_late_idle(struct device *dev, void *data)
 896{
 897        struct platform_device *pdev = to_platform_device(dev);
 898        struct omap_device *od = to_omap_device(pdev);
 899        int i;
 900
 901        if (!od)
 902                return 0;
 903
 904        /*
 905         * If omap_device state is enabled, but has no driver bound,
 906         * idle it.
 907         */
 908
 909        /*
 910         * Some devices (like memory controllers) are always kept
 911         * enabled, and should not be idled even with no drivers.
 912         */
 913        for (i = 0; i < od->hwmods_cnt; i++)
 914                if (od->hwmods[i]->flags & HWMOD_INIT_NO_IDLE)
 915                        return 0;
 916
 917        if (od->_driver_status != BUS_NOTIFY_BOUND_DRIVER &&
 918            od->_driver_status != BUS_NOTIFY_BIND_DRIVER) {
 919                if (od->_state == OMAP_DEVICE_STATE_ENABLED) {
 920                        dev_warn(dev, "%s: enabled but no driver.  Idling\n",
 921                                 __func__);
 922                        omap_device_idle(pdev);
 923                }
 924        }
 925
 926        return 0;
 927}
 928
 929static int __init omap_device_late_init(void)
 930{
 931        bus_for_each_dev(&platform_bus_type, NULL, NULL, omap_device_late_idle);
 932
 933        WARN(!of_have_populated_dt(),
 934                "legacy booting deprecated, please update to boot with .dts\n");
 935
 936        return 0;
 937}
 938omap_late_initcall_sync(omap_device_late_init);
 939