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/of_address.h> 39 #include <linux/of_irq.h> 40 #include <linux/notifier.h> 41 42 #include "common.h" 43 #include "soc.h" 44 #include "omap_device.h" 45 #include "omap_hwmod.h" 46 47 /* Private functions */ 48 49 static void _add_clkdev(struct omap_device *od, const char *clk_alias, 50 const char *clk_name) 51 { 52 struct clk *r; 53 int rc; 54 55 if (!clk_alias || !clk_name) 56 return; 57 58 dev_dbg(&od->pdev->dev, "Creating %s -> %s\n", clk_alias, clk_name); 59 60 r = clk_get_sys(dev_name(&od->pdev->dev), clk_alias); 61 if (!IS_ERR(r)) { 62 dev_dbg(&od->pdev->dev, 63 "alias %s already exists\n", clk_alias); 64 clk_put(r); 65 return; 66 } 67 68 r = clk_get_sys(NULL, clk_name); 69 70 if (IS_ERR(r)) { 71 struct of_phandle_args clkspec; 72 73 clkspec.np = of_find_node_by_name(NULL, clk_name); 74 75 r = of_clk_get_from_provider(&clkspec); 76 77 rc = clk_register_clkdev(r, clk_alias, 78 dev_name(&od->pdev->dev)); 79 } else { 80 rc = clk_add_alias(clk_alias, dev_name(&od->pdev->dev), 81 clk_name, NULL); 82 } 83 84 if (rc) { 85 if (rc == -ENODEV || rc == -ENOMEM) 86 dev_err(&od->pdev->dev, 87 "clkdev_alloc for %s failed\n", clk_alias); 88 else 89 dev_err(&od->pdev->dev, 90 "clk_get for %s failed\n", clk_name); 91 } 92 } 93 94 /** 95 * _add_hwmod_clocks_clkdev - Add clkdev entry for hwmod optional clocks 96 * and main clock 97 * @od: struct omap_device *od 98 * @oh: struct omap_hwmod *oh 99 * 100 * For the main clock and every optional clock present per hwmod per 101 * omap_device, this function adds an entry in the clkdev table of the 102 * form <dev-id=dev_name, con-id=role> if it does not exist already. 103 * 104 * The function is called from inside omap_device_build_ss(), after 105 * omap_device_register. 106 * 107 * This allows drivers to get a pointer to its optional clocks based on its role 108 * by calling clk_get(<dev*>, <role>). 109 * In the case of the main clock, a "fck" alias is used. 110 * 111 * No return value. 112 */ 113 static void _add_hwmod_clocks_clkdev(struct omap_device *od, 114 struct omap_hwmod *oh) 115 { 116 int i; 117 118 _add_clkdev(od, "fck", oh->main_clk); 119 120 for (i = 0; i < oh->opt_clks_cnt; i++) 121 _add_clkdev(od, oh->opt_clks[i].role, oh->opt_clks[i].clk); 122 } 123 124 125 /** 126 * omap_device_build_from_dt - build an omap_device with multiple hwmods 127 * @pdev_name: name of the platform_device driver to use 128 * @pdev_id: this platform_device's connection ID 129 * @oh: ptr to the single omap_hwmod that backs this omap_device 130 * @pdata: platform_data ptr to associate with the platform_device 131 * @pdata_len: amount of memory pointed to by @pdata 132 * 133 * Function for building an omap_device already registered from device-tree 134 * 135 * Returns 0 or PTR_ERR() on error. 136 */ 137 static int omap_device_build_from_dt(struct platform_device *pdev) 138 { 139 struct omap_hwmod **hwmods; 140 struct omap_device *od; 141 struct omap_hwmod *oh; 142 struct device_node *node = pdev->dev.of_node; 143 struct resource res; 144 const char *oh_name; 145 int oh_cnt, i, ret = 0; 146 bool device_active = false, skip_pm_domain = false; 147 148 oh_cnt = of_property_count_strings(node, "ti,hwmods"); 149 if (oh_cnt <= 0) { 150 dev_dbg(&pdev->dev, "No 'hwmods' to build omap_device\n"); 151 return -ENODEV; 152 } 153 154 /* SDMA still needs special handling for omap_device_build() */ 155 ret = of_property_read_string_index(node, "ti,hwmods", 0, &oh_name); 156 if (!ret && (!strncmp("dma_system", oh_name, 10) || 157 !strncmp("dma", oh_name, 3))) 158 skip_pm_domain = true; 159 160 /* Use ti-sysc driver instead of omap_device? */ 161 if (!skip_pm_domain && 162 !omap_hwmod_parse_module_range(NULL, node, &res)) 163 return -ENODEV; 164 165 hwmods = kcalloc(oh_cnt, sizeof(struct omap_hwmod *), GFP_KERNEL); 166 if (!hwmods) { 167 ret = -ENOMEM; 168 goto odbfd_exit; 169 } 170 171 for (i = 0; i < oh_cnt; i++) { 172 of_property_read_string_index(node, "ti,hwmods", i, &oh_name); 173 oh = omap_hwmod_lookup(oh_name); 174 if (!oh) { 175 dev_err(&pdev->dev, "Cannot lookup hwmod '%s'\n", 176 oh_name); 177 ret = -EINVAL; 178 goto odbfd_exit1; 179 } 180 hwmods[i] = oh; 181 if (oh->flags & HWMOD_INIT_NO_IDLE) 182 device_active = true; 183 } 184 185 od = omap_device_alloc(pdev, hwmods, oh_cnt); 186 if (IS_ERR(od)) { 187 dev_err(&pdev->dev, "Cannot allocate omap_device for :%s\n", 188 oh_name); 189 ret = PTR_ERR(od); 190 goto odbfd_exit1; 191 } 192 193 /* Fix up missing resource names */ 194 for (i = 0; i < pdev->num_resources; i++) { 195 struct resource *r = &pdev->resource[i]; 196 197 if (r->name == NULL) 198 r->name = dev_name(&pdev->dev); 199 } 200 201 if (!skip_pm_domain) { 202 dev_pm_domain_set(&pdev->dev, &omap_device_pm_domain); 203 if (device_active) { 204 omap_device_enable(pdev); 205 pm_runtime_set_active(&pdev->dev); 206 } 207 } 208 209 odbfd_exit1: 210 kfree(hwmods); 211 odbfd_exit: 212 /* if data/we are at fault.. load up a fail handler */ 213 if (ret) 214 dev_pm_domain_set(&pdev->dev, &omap_device_fail_pm_domain); 215 216 return ret; 217 } 218 219 static int _omap_device_notifier_call(struct notifier_block *nb, 220 unsigned long event, void *dev) 221 { 222 struct platform_device *pdev = to_platform_device(dev); 223 struct omap_device *od; 224 int err; 225 226 switch (event) { 227 case BUS_NOTIFY_REMOVED_DEVICE: 228 if (pdev->archdata.od) 229 omap_device_delete(pdev->archdata.od); 230 break; 231 case BUS_NOTIFY_UNBOUND_DRIVER: 232 od = to_omap_device(pdev); 233 if (od && (od->_state == OMAP_DEVICE_STATE_ENABLED)) { 234 dev_info(dev, "enabled after unload, idling\n"); 235 err = omap_device_idle(pdev); 236 if (err) 237 dev_err(dev, "failed to idle\n"); 238 } 239 break; 240 case BUS_NOTIFY_BIND_DRIVER: 241 od = to_omap_device(pdev); 242 if (od && (od->_state == OMAP_DEVICE_STATE_ENABLED) && 243 pm_runtime_status_suspended(dev)) { 244 od->_driver_status = BUS_NOTIFY_BIND_DRIVER; 245 pm_runtime_set_active(dev); 246 } 247 break; 248 case BUS_NOTIFY_ADD_DEVICE: 249 if (pdev->dev.of_node) 250 omap_device_build_from_dt(pdev); 251 omap_auxdata_legacy_init(dev); 252 /* fall through */ 253 default: 254 od = to_omap_device(pdev); 255 if (od) 256 od->_driver_status = event; 257 } 258 259 return NOTIFY_DONE; 260 } 261 262 /** 263 * _omap_device_enable_hwmods - call omap_hwmod_enable() on all hwmods 264 * @od: struct omap_device *od 265 * 266 * Enable all underlying hwmods. Returns 0. 267 */ 268 static int _omap_device_enable_hwmods(struct omap_device *od) 269 { 270 int ret = 0; 271 int i; 272 273 for (i = 0; i < od->hwmods_cnt; i++) 274 ret |= omap_hwmod_enable(od->hwmods[i]); 275 276 return ret; 277 } 278 279 /** 280 * _omap_device_idle_hwmods - call omap_hwmod_idle() on all hwmods 281 * @od: struct omap_device *od 282 * 283 * Idle all underlying hwmods. Returns 0. 284 */ 285 static int _omap_device_idle_hwmods(struct omap_device *od) 286 { 287 int ret = 0; 288 int i; 289 290 for (i = 0; i < od->hwmods_cnt; i++) 291 ret |= omap_hwmod_idle(od->hwmods[i]); 292 293 return ret; 294 } 295 296 /* Public functions for use by core code */ 297 298 /** 299 * omap_device_get_context_loss_count - get lost context count 300 * @od: struct omap_device * 301 * 302 * Using the primary hwmod, query the context loss count for this 303 * device. 304 * 305 * Callers should consider context for this device lost any time this 306 * function returns a value different than the value the caller got 307 * the last time it called this function. 308 * 309 * If any hwmods exist for the omap_device associated with @pdev, 310 * return the context loss counter for that hwmod, otherwise return 311 * zero. 312 */ 313 int omap_device_get_context_loss_count(struct platform_device *pdev) 314 { 315 struct omap_device *od; 316 u32 ret = 0; 317 318 od = to_omap_device(pdev); 319 320 if (od->hwmods_cnt) 321 ret = omap_hwmod_get_context_loss_count(od->hwmods[0]); 322 323 return ret; 324 } 325 326 /** 327 * omap_device_alloc - allocate an omap_device 328 * @pdev: platform_device that will be included in this omap_device 329 * @oh: ptr to the single omap_hwmod that backs this omap_device 330 * @pdata: platform_data ptr to associate with the platform_device 331 * @pdata_len: amount of memory pointed to by @pdata 332 * 333 * Convenience function for allocating an omap_device structure and filling 334 * hwmods, and resources. 335 * 336 * Returns an struct omap_device pointer or ERR_PTR() on error; 337 */ 338 struct omap_device *omap_device_alloc(struct platform_device *pdev, 339 struct omap_hwmod **ohs, int oh_cnt) 340 { 341 int ret = -ENOMEM; 342 struct omap_device *od; 343 int i; 344 struct omap_hwmod **hwmods; 345 346 od = kzalloc(sizeof(struct omap_device), GFP_KERNEL); 347 if (!od) { 348 ret = -ENOMEM; 349 goto oda_exit1; 350 } 351 od->hwmods_cnt = oh_cnt; 352 353 hwmods = kmemdup(ohs, sizeof(struct omap_hwmod *) * oh_cnt, GFP_KERNEL); 354 if (!hwmods) 355 goto oda_exit2; 356 357 od->hwmods = hwmods; 358 od->pdev = pdev; 359 pdev->archdata.od = od; 360 361 for (i = 0; i < oh_cnt; i++) { 362 hwmods[i]->od = od; 363 _add_hwmod_clocks_clkdev(od, hwmods[i]); 364 } 365 366 return od; 367 368 oda_exit2: 369 kfree(od); 370 oda_exit1: 371 dev_err(&pdev->dev, "omap_device: build failed (%d)\n", ret); 372 373 return ERR_PTR(ret); 374 } 375 376 void omap_device_delete(struct omap_device *od) 377 { 378 if (!od) 379 return; 380 381 od->pdev->archdata.od = NULL; 382 kfree(od->hwmods); 383 kfree(od); 384 } 385 386 /** 387 * omap_device_copy_resources - Add legacy IO and IRQ resources 388 * @oh: interconnect target module 389 * @pdev: platform device to copy resources to 390 * 391 * We still have legacy DMA and smartreflex needing resources. 392 * Let's populate what they need until we can eventually just 393 * remove this function. Note that there should be no need to 394 * call this from omap_device_build_from_dt(), nor should there 395 * be any need to call it for other devices. 396 */ 397 static int 398 omap_device_copy_resources(struct omap_hwmod *oh, 399 struct platform_device *pdev) 400 { 401 struct device_node *np, *child; 402 struct property *prop; 403 struct resource *res; 404 const char *name; 405 int error, irq = 0; 406 407 if (!oh || !oh->od || !oh->od->pdev) 408 return -EINVAL; 409 410 np = oh->od->pdev->dev.of_node; 411 if (!np) { 412 error = -ENODEV; 413 goto error; 414 } 415 416 res = kcalloc(2, sizeof(*res), GFP_KERNEL); 417 if (!res) 418 return -ENOMEM; 419 420 /* Do we have a dts range for the interconnect target module? */ 421 error = omap_hwmod_parse_module_range(oh, np, res); 422 423 /* No ranges, rely on device reg entry */ 424 if (error) 425 error = of_address_to_resource(np, 0, res); 426 if (error) 427 goto free; 428 429 /* SmartReflex needs first IO resource name to be "mpu" */ 430 res[0].name = "mpu"; 431 432 /* 433 * We may have a configured "ti,sysc" interconnect target with a 434 * dts child with the interrupt. If so use the first child's 435 * first interrupt for "ti-hwmods" legacy support. 436 */ 437 of_property_for_each_string(np, "compatible", prop, name) 438 if (!strncmp("ti,sysc-", name, 8)) 439 break; 440 441 child = of_get_next_available_child(np, NULL); 442 443 if (name) 444 irq = irq_of_parse_and_map(child, 0); 445 if (!irq) 446 irq = irq_of_parse_and_map(np, 0); 447 if (!irq) { 448 error = -EINVAL; 449 goto free; 450 } 451 452 /* Legacy DMA code needs interrupt name to be "0" */ 453 res[1].start = irq; 454 res[1].end = irq; 455 res[1].flags = IORESOURCE_IRQ; 456 res[1].name = "0"; 457 458 error = platform_device_add_resources(pdev, res, 2); 459 460 free: 461 kfree(res); 462 463 error: 464 WARN(error, "%s: %s device %s failed: %i\n", 465 __func__, oh->name, dev_name(&pdev->dev), 466 error); 467 468 return error; 469 } 470 471 /** 472 * omap_device_build - build and register an omap_device with one omap_hwmod 473 * @pdev_name: name of the platform_device driver to use 474 * @pdev_id: this platform_device's connection ID 475 * @oh: ptr to the single omap_hwmod that backs this omap_device 476 * @pdata: platform_data ptr to associate with the platform_device 477 * @pdata_len: amount of memory pointed to by @pdata 478 * 479 * Convenience function for building and registering a single 480 * omap_device record, which in turn builds and registers a 481 * platform_device record. See omap_device_build_ss() for more 482 * information. Returns ERR_PTR(-EINVAL) if @oh is NULL; otherwise, 483 * passes along the return value of omap_device_build_ss(). 484 */ 485 struct platform_device __init *omap_device_build(const char *pdev_name, 486 int pdev_id, 487 struct omap_hwmod *oh, 488 void *pdata, int pdata_len) 489 { 490 int ret = -ENOMEM; 491 struct platform_device *pdev; 492 struct omap_device *od; 493 494 if (!oh || !pdev_name) 495 return ERR_PTR(-EINVAL); 496 497 if (!pdata && pdata_len > 0) 498 return ERR_PTR(-EINVAL); 499 500 if (strncmp(oh->name, "smartreflex", 11) && 501 strncmp(oh->name, "dma", 3)) { 502 pr_warn("%s need to update %s to probe with dt\na", 503 __func__, pdev_name); 504 ret = -ENODEV; 505 goto odbs_exit; 506 } 507 508 pdev = platform_device_alloc(pdev_name, pdev_id); 509 if (!pdev) { 510 ret = -ENOMEM; 511 goto odbs_exit; 512 } 513 514 /* Set the dev_name early to allow dev_xxx in omap_device_alloc */ 515 if (pdev->id != -1) 516 dev_set_name(&pdev->dev, "%s.%d", pdev->name, pdev->id); 517 else 518 dev_set_name(&pdev->dev, "%s", pdev->name); 519 520 /* 521 * Must be called before omap_device_alloc() as oh->od 522 * only contains the currently registered omap_device 523 * and will get overwritten by omap_device_alloc(). 524 */ 525 ret = omap_device_copy_resources(oh, pdev); 526 if (ret) 527 goto odbs_exit1; 528 529 od = omap_device_alloc(pdev, &oh, 1); 530 if (IS_ERR(od)) { 531 ret = PTR_ERR(od); 532 goto odbs_exit1; 533 } 534 535 ret = platform_device_add_data(pdev, pdata, pdata_len); 536 if (ret) 537 goto odbs_exit2; 538 539 ret = omap_device_register(pdev); 540 if (ret) 541 goto odbs_exit2; 542 543 return pdev; 544 545 odbs_exit2: 546 omap_device_delete(od); 547 odbs_exit1: 548 platform_device_put(pdev); 549 odbs_exit: 550 551 pr_err("omap_device: %s: build failed (%d)\n", pdev_name, ret); 552 553 return ERR_PTR(ret); 554 } 555 556 #ifdef CONFIG_PM 557 static int _od_runtime_suspend(struct device *dev) 558 { 559 struct platform_device *pdev = to_platform_device(dev); 560 int ret; 561 562 ret = pm_generic_runtime_suspend(dev); 563 if (ret) 564 return ret; 565 566 return omap_device_idle(pdev); 567 } 568 569 static int _od_runtime_resume(struct device *dev) 570 { 571 struct platform_device *pdev = to_platform_device(dev); 572 int ret; 573 574 ret = omap_device_enable(pdev); 575 if (ret) { 576 dev_err(dev, "use pm_runtime_put_sync_suspend() in driver?\n"); 577 return ret; 578 } 579 580 return pm_generic_runtime_resume(dev); 581 } 582 583 static int _od_fail_runtime_suspend(struct device *dev) 584 { 585 dev_warn(dev, "%s: FIXME: missing hwmod/omap_dev info\n", __func__); 586 return -ENODEV; 587 } 588 589 static int _od_fail_runtime_resume(struct device *dev) 590 { 591 dev_warn(dev, "%s: FIXME: missing hwmod/omap_dev info\n", __func__); 592 return -ENODEV; 593 } 594 595 #endif 596 597 #ifdef CONFIG_SUSPEND 598 static int _od_suspend_noirq(struct device *dev) 599 { 600 struct platform_device *pdev = to_platform_device(dev); 601 struct omap_device *od = to_omap_device(pdev); 602 int ret; 603 604 /* Don't attempt late suspend on a driver that is not bound */ 605 if (od->_driver_status != BUS_NOTIFY_BOUND_DRIVER) 606 return 0; 607 608 ret = pm_generic_suspend_noirq(dev); 609 610 if (!ret && !pm_runtime_status_suspended(dev)) { 611 if (pm_generic_runtime_suspend(dev) == 0) { 612 omap_device_idle(pdev); 613 od->flags |= OMAP_DEVICE_SUSPENDED; 614 } 615 } 616 617 return ret; 618 } 619 620 static int _od_resume_noirq(struct device *dev) 621 { 622 struct platform_device *pdev = to_platform_device(dev); 623 struct omap_device *od = to_omap_device(pdev); 624 625 if (od->flags & OMAP_DEVICE_SUSPENDED) { 626 od->flags &= ~OMAP_DEVICE_SUSPENDED; 627 omap_device_enable(pdev); 628 pm_generic_runtime_resume(dev); 629 } 630 631 return pm_generic_resume_noirq(dev); 632 } 633 #else 634 #define _od_suspend_noirq NULL 635 #define _od_resume_noirq NULL 636 #endif 637 638 struct dev_pm_domain omap_device_fail_pm_domain = { 639 .ops = { 640 SET_RUNTIME_PM_OPS(_od_fail_runtime_suspend, 641 _od_fail_runtime_resume, NULL) 642 } 643 }; 644 645 struct dev_pm_domain omap_device_pm_domain = { 646 .ops = { 647 SET_RUNTIME_PM_OPS(_od_runtime_suspend, _od_runtime_resume, 648 NULL) 649 USE_PLATFORM_PM_SLEEP_OPS 650 SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(_od_suspend_noirq, 651 _od_resume_noirq) 652 } 653 }; 654 655 /** 656 * omap_device_register - register an omap_device with one omap_hwmod 657 * @od: struct omap_device * to register 658 * 659 * Register the omap_device structure. This currently just calls 660 * platform_device_register() on the underlying platform_device. 661 * Returns the return value of platform_device_register(). 662 */ 663 int omap_device_register(struct platform_device *pdev) 664 { 665 pr_debug("omap_device: %s: registering\n", pdev->name); 666 667 dev_pm_domain_set(&pdev->dev, &omap_device_pm_domain); 668 return platform_device_add(pdev); 669 } 670 671 672 /* Public functions for use by device drivers through struct platform_data */ 673 674 /** 675 * omap_device_enable - fully activate an omap_device 676 * @od: struct omap_device * to activate 677 * 678 * Do whatever is necessary for the hwmods underlying omap_device @od 679 * to be accessible and ready to operate. This generally involves 680 * enabling clocks, setting SYSCONFIG registers; and in the future may 681 * involve remuxing pins. Device drivers should call this function 682 * indirectly via pm_runtime_get*(). Returns -EINVAL if called when 683 * the omap_device is already enabled, or passes along the return 684 * value of _omap_device_enable_hwmods(). 685 */ 686 int omap_device_enable(struct platform_device *pdev) 687 { 688 int ret; 689 struct omap_device *od; 690 691 od = to_omap_device(pdev); 692 693 if (od->_state == OMAP_DEVICE_STATE_ENABLED) { 694 dev_warn(&pdev->dev, 695 "omap_device: %s() called from invalid state %d\n", 696 __func__, od->_state); 697 return -EINVAL; 698 } 699 700 ret = _omap_device_enable_hwmods(od); 701 702 if (ret == 0) 703 od->_state = OMAP_DEVICE_STATE_ENABLED; 704 705 return ret; 706 } 707 708 /** 709 * omap_device_idle - idle an omap_device 710 * @od: struct omap_device * to idle 711 * 712 * Idle omap_device @od. Device drivers call this function indirectly 713 * via pm_runtime_put*(). Returns -EINVAL if the omap_device is not 714 * currently enabled, or passes along the return value of 715 * _omap_device_idle_hwmods(). 716 */ 717 int omap_device_idle(struct platform_device *pdev) 718 { 719 int ret; 720 struct omap_device *od; 721 722 od = to_omap_device(pdev); 723 724 if (od->_state != OMAP_DEVICE_STATE_ENABLED) { 725 dev_warn(&pdev->dev, 726 "omap_device: %s() called from invalid state %d\n", 727 __func__, od->_state); 728 return -EINVAL; 729 } 730 731 ret = _omap_device_idle_hwmods(od); 732 733 if (ret == 0) 734 od->_state = OMAP_DEVICE_STATE_IDLE; 735 736 return ret; 737 } 738 739 /** 740 * omap_device_assert_hardreset - set a device's hardreset line 741 * @pdev: struct platform_device * to reset 742 * @name: const char * name of the reset line 743 * 744 * Set the hardreset line identified by @name on the IP blocks 745 * associated with the hwmods backing the platform_device @pdev. All 746 * of the hwmods associated with @pdev must have the same hardreset 747 * line linked to them for this to work. Passes along the return value 748 * of omap_hwmod_assert_hardreset() in the event of any failure, or 749 * returns 0 upon success. 750 */ 751 int omap_device_assert_hardreset(struct platform_device *pdev, const char *name) 752 { 753 struct omap_device *od = to_omap_device(pdev); 754 int ret = 0; 755 int i; 756 757 for (i = 0; i < od->hwmods_cnt; i++) { 758 ret = omap_hwmod_assert_hardreset(od->hwmods[i], name); 759 if (ret) 760 break; 761 } 762 763 return ret; 764 } 765 766 /** 767 * omap_device_deassert_hardreset - release a device's hardreset line 768 * @pdev: struct platform_device * to reset 769 * @name: const char * name of the reset line 770 * 771 * Release the hardreset line identified by @name on the IP blocks 772 * associated with the hwmods backing the platform_device @pdev. All 773 * of the hwmods associated with @pdev must have the same hardreset 774 * line linked to them for this to work. Passes along the return 775 * value of omap_hwmod_deassert_hardreset() in the event of any 776 * failure, or returns 0 upon success. 777 */ 778 int omap_device_deassert_hardreset(struct platform_device *pdev, 779 const char *name) 780 { 781 struct omap_device *od = to_omap_device(pdev); 782 int ret = 0; 783 int i; 784 785 for (i = 0; i < od->hwmods_cnt; i++) { 786 ret = omap_hwmod_deassert_hardreset(od->hwmods[i], name); 787 if (ret) 788 break; 789 } 790 791 return ret; 792 } 793 794 /** 795 * omap_device_get_by_hwmod_name() - convert a hwmod name to 796 * device pointer. 797 * @oh_name: name of the hwmod device 798 * 799 * Returns back a struct device * pointer associated with a hwmod 800 * device represented by a hwmod_name 801 */ 802 struct device *omap_device_get_by_hwmod_name(const char *oh_name) 803 { 804 struct omap_hwmod *oh; 805 806 if (!oh_name) { 807 WARN(1, "%s: no hwmod name!\n", __func__); 808 return ERR_PTR(-EINVAL); 809 } 810 811 oh = omap_hwmod_lookup(oh_name); 812 if (!oh) { 813 WARN(1, "%s: no hwmod for %s\n", __func__, 814 oh_name); 815 return ERR_PTR(-ENODEV); 816 } 817 if (!oh->od) { 818 WARN(1, "%s: no omap_device for %s\n", __func__, 819 oh_name); 820 return ERR_PTR(-ENODEV); 821 } 822 823 return &oh->od->pdev->dev; 824 } 825 826 static struct notifier_block platform_nb = { 827 .notifier_call = _omap_device_notifier_call, 828 }; 829 830 static int __init omap_device_init(void) 831 { 832 bus_register_notifier(&platform_bus_type, &platform_nb); 833 return 0; 834 } 835 omap_postcore_initcall(omap_device_init); 836 837 /** 838 * omap_device_late_idle - idle devices without drivers 839 * @dev: struct device * associated with omap_device 840 * @data: unused 841 * 842 * Check the driver bound status of this device, and idle it 843 * if there is no driver attached. 844 */ 845 static int __init omap_device_late_idle(struct device *dev, void *data) 846 { 847 struct platform_device *pdev = to_platform_device(dev); 848 struct omap_device *od = to_omap_device(pdev); 849 int i; 850 851 if (!od) 852 return 0; 853 854 /* 855 * If omap_device state is enabled, but has no driver bound, 856 * idle it. 857 */ 858 859 /* 860 * Some devices (like memory controllers) are always kept 861 * enabled, and should not be idled even with no drivers. 862 */ 863 for (i = 0; i < od->hwmods_cnt; i++) 864 if (od->hwmods[i]->flags & HWMOD_INIT_NO_IDLE) 865 return 0; 866 867 if (od->_driver_status != BUS_NOTIFY_BOUND_DRIVER && 868 od->_driver_status != BUS_NOTIFY_BIND_DRIVER) { 869 if (od->_state == OMAP_DEVICE_STATE_ENABLED) { 870 dev_warn(dev, "%s: enabled but no driver. Idling\n", 871 __func__); 872 omap_device_idle(pdev); 873 } 874 } 875 876 return 0; 877 } 878 879 static int __init omap_device_late_init(void) 880 { 881 bus_for_each_dev(&platform_bus_type, NULL, NULL, omap_device_late_idle); 882 883 return 0; 884 } 885 omap_late_initcall_sync(omap_device_late_init); 886