clock_ops.c (19792B)
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * drivers/base/power/clock_ops.c - Generic clock manipulation PM callbacks 4 * 5 * Copyright (c) 2011 Rafael J. Wysocki <rjw@sisk.pl>, Renesas Electronics Corp. 6 */ 7 8#include <linux/kernel.h> 9#include <linux/device.h> 10#include <linux/io.h> 11#include <linux/pm.h> 12#include <linux/pm_clock.h> 13#include <linux/clk.h> 14#include <linux/clkdev.h> 15#include <linux/of_clk.h> 16#include <linux/slab.h> 17#include <linux/err.h> 18#include <linux/pm_domain.h> 19#include <linux/pm_runtime.h> 20 21#ifdef CONFIG_PM_CLK 22 23enum pce_status { 24 PCE_STATUS_NONE = 0, 25 PCE_STATUS_ACQUIRED, 26 PCE_STATUS_PREPARED, 27 PCE_STATUS_ENABLED, 28 PCE_STATUS_ERROR, 29}; 30 31struct pm_clock_entry { 32 struct list_head node; 33 char *con_id; 34 struct clk *clk; 35 enum pce_status status; 36 bool enabled_when_prepared; 37}; 38 39/** 40 * pm_clk_list_lock - ensure exclusive access for modifying the PM clock 41 * entry list. 42 * @psd: pm_subsys_data instance corresponding to the PM clock entry list 43 * and clk_op_might_sleep count to be modified. 44 * 45 * Get exclusive access before modifying the PM clock entry list and the 46 * clock_op_might_sleep count to guard against concurrent modifications. 47 * This also protects against a concurrent clock_op_might_sleep and PM clock 48 * entry list usage in pm_clk_suspend()/pm_clk_resume() that may or may not 49 * happen in atomic context, hence both the mutex and the spinlock must be 50 * taken here. 51 */ 52static void pm_clk_list_lock(struct pm_subsys_data *psd) 53 __acquires(&psd->lock) 54{ 55 mutex_lock(&psd->clock_mutex); 56 spin_lock_irq(&psd->lock); 57} 58 59/** 60 * pm_clk_list_unlock - counterpart to pm_clk_list_lock(). 61 * @psd: the same pm_subsys_data instance previously passed to 62 * pm_clk_list_lock(). 63 */ 64static void pm_clk_list_unlock(struct pm_subsys_data *psd) 65 __releases(&psd->lock) 66{ 67 spin_unlock_irq(&psd->lock); 68 mutex_unlock(&psd->clock_mutex); 69} 70 71/** 72 * pm_clk_op_lock - ensure exclusive access for performing clock operations. 73 * @psd: pm_subsys_data instance corresponding to the PM clock entry list 74 * and clk_op_might_sleep count being used. 75 * @flags: stored irq flags. 76 * @fn: string for the caller function's name. 77 * 78 * This is used by pm_clk_suspend() and pm_clk_resume() to guard 79 * against concurrent modifications to the clock entry list and the 80 * clock_op_might_sleep count. If clock_op_might_sleep is != 0 then 81 * only the mutex can be locked and those functions can only be used in 82 * non atomic context. If clock_op_might_sleep == 0 then these functions 83 * may be used in any context and only the spinlock can be locked. 84 * Returns -EINVAL if called in atomic context when clock ops might sleep. 85 */ 86static int pm_clk_op_lock(struct pm_subsys_data *psd, unsigned long *flags, 87 const char *fn) 88 /* sparse annotations don't work here as exit state isn't static */ 89{ 90 bool atomic_context = in_atomic() || irqs_disabled(); 91 92try_again: 93 spin_lock_irqsave(&psd->lock, *flags); 94 if (!psd->clock_op_might_sleep) { 95 /* the __release is there to work around sparse limitations */ 96 __release(&psd->lock); 97 return 0; 98 } 99 100 /* bail out if in atomic context */ 101 if (atomic_context) { 102 pr_err("%s: atomic context with clock_ops_might_sleep = %d", 103 fn, psd->clock_op_might_sleep); 104 spin_unlock_irqrestore(&psd->lock, *flags); 105 might_sleep(); 106 return -EPERM; 107 } 108 109 /* we must switch to the mutex */ 110 spin_unlock_irqrestore(&psd->lock, *flags); 111 mutex_lock(&psd->clock_mutex); 112 113 /* 114 * There was a possibility for psd->clock_op_might_sleep 115 * to become 0 above. Keep the mutex only if not the case. 116 */ 117 if (likely(psd->clock_op_might_sleep)) 118 return 0; 119 120 mutex_unlock(&psd->clock_mutex); 121 goto try_again; 122} 123 124/** 125 * pm_clk_op_unlock - counterpart to pm_clk_op_lock(). 126 * @psd: the same pm_subsys_data instance previously passed to 127 * pm_clk_op_lock(). 128 * @flags: irq flags provided by pm_clk_op_lock(). 129 */ 130static void pm_clk_op_unlock(struct pm_subsys_data *psd, unsigned long *flags) 131 /* sparse annotations don't work here as entry state isn't static */ 132{ 133 if (psd->clock_op_might_sleep) { 134 mutex_unlock(&psd->clock_mutex); 135 } else { 136 /* the __acquire is there to work around sparse limitations */ 137 __acquire(&psd->lock); 138 spin_unlock_irqrestore(&psd->lock, *flags); 139 } 140} 141 142/** 143 * __pm_clk_enable - Enable a clock, reporting any errors 144 * @dev: The device for the given clock 145 * @ce: PM clock entry corresponding to the clock. 146 */ 147static inline void __pm_clk_enable(struct device *dev, struct pm_clock_entry *ce) 148{ 149 int ret; 150 151 switch (ce->status) { 152 case PCE_STATUS_ACQUIRED: 153 ret = clk_prepare_enable(ce->clk); 154 break; 155 case PCE_STATUS_PREPARED: 156 ret = clk_enable(ce->clk); 157 break; 158 default: 159 return; 160 } 161 if (!ret) 162 ce->status = PCE_STATUS_ENABLED; 163 else 164 dev_err(dev, "%s: failed to enable clk %p, error %d\n", 165 __func__, ce->clk, ret); 166} 167 168/** 169 * pm_clk_acquire - Acquire a device clock. 170 * @dev: Device whose clock is to be acquired. 171 * @ce: PM clock entry corresponding to the clock. 172 */ 173static void pm_clk_acquire(struct device *dev, struct pm_clock_entry *ce) 174{ 175 if (!ce->clk) 176 ce->clk = clk_get(dev, ce->con_id); 177 if (IS_ERR(ce->clk)) { 178 ce->status = PCE_STATUS_ERROR; 179 return; 180 } else if (clk_is_enabled_when_prepared(ce->clk)) { 181 /* we defer preparing the clock in that case */ 182 ce->status = PCE_STATUS_ACQUIRED; 183 ce->enabled_when_prepared = true; 184 } else if (clk_prepare(ce->clk)) { 185 ce->status = PCE_STATUS_ERROR; 186 dev_err(dev, "clk_prepare() failed\n"); 187 return; 188 } else { 189 ce->status = PCE_STATUS_PREPARED; 190 } 191 dev_dbg(dev, "Clock %pC con_id %s managed by runtime PM.\n", 192 ce->clk, ce->con_id); 193} 194 195static int __pm_clk_add(struct device *dev, const char *con_id, 196 struct clk *clk) 197{ 198 struct pm_subsys_data *psd = dev_to_psd(dev); 199 struct pm_clock_entry *ce; 200 201 if (!psd) 202 return -EINVAL; 203 204 ce = kzalloc(sizeof(*ce), GFP_KERNEL); 205 if (!ce) 206 return -ENOMEM; 207 208 if (con_id) { 209 ce->con_id = kstrdup(con_id, GFP_KERNEL); 210 if (!ce->con_id) { 211 kfree(ce); 212 return -ENOMEM; 213 } 214 } else { 215 if (IS_ERR(clk)) { 216 kfree(ce); 217 return -ENOENT; 218 } 219 ce->clk = clk; 220 } 221 222 pm_clk_acquire(dev, ce); 223 224 pm_clk_list_lock(psd); 225 list_add_tail(&ce->node, &psd->clock_list); 226 if (ce->enabled_when_prepared) 227 psd->clock_op_might_sleep++; 228 pm_clk_list_unlock(psd); 229 return 0; 230} 231 232/** 233 * pm_clk_add - Start using a device clock for power management. 234 * @dev: Device whose clock is going to be used for power management. 235 * @con_id: Connection ID of the clock. 236 * 237 * Add the clock represented by @con_id to the list of clocks used for 238 * the power management of @dev. 239 */ 240int pm_clk_add(struct device *dev, const char *con_id) 241{ 242 return __pm_clk_add(dev, con_id, NULL); 243} 244EXPORT_SYMBOL_GPL(pm_clk_add); 245 246/** 247 * pm_clk_add_clk - Start using a device clock for power management. 248 * @dev: Device whose clock is going to be used for power management. 249 * @clk: Clock pointer 250 * 251 * Add the clock to the list of clocks used for the power management of @dev. 252 * The power-management code will take control of the clock reference, so 253 * callers should not call clk_put() on @clk after this function sucessfully 254 * returned. 255 */ 256int pm_clk_add_clk(struct device *dev, struct clk *clk) 257{ 258 return __pm_clk_add(dev, NULL, clk); 259} 260EXPORT_SYMBOL_GPL(pm_clk_add_clk); 261 262 263/** 264 * of_pm_clk_add_clk - Start using a device clock for power management. 265 * @dev: Device whose clock is going to be used for power management. 266 * @name: Name of clock that is going to be used for power management. 267 * 268 * Add the clock described in the 'clocks' device-tree node that matches 269 * with the 'name' provided, to the list of clocks used for the power 270 * management of @dev. On success, returns 0. Returns a negative error 271 * code if the clock is not found or cannot be added. 272 */ 273int of_pm_clk_add_clk(struct device *dev, const char *name) 274{ 275 struct clk *clk; 276 int ret; 277 278 if (!dev || !dev->of_node || !name) 279 return -EINVAL; 280 281 clk = of_clk_get_by_name(dev->of_node, name); 282 if (IS_ERR(clk)) 283 return PTR_ERR(clk); 284 285 ret = pm_clk_add_clk(dev, clk); 286 if (ret) { 287 clk_put(clk); 288 return ret; 289 } 290 291 return 0; 292} 293EXPORT_SYMBOL_GPL(of_pm_clk_add_clk); 294 295/** 296 * of_pm_clk_add_clks - Start using device clock(s) for power management. 297 * @dev: Device whose clock(s) is going to be used for power management. 298 * 299 * Add a series of clocks described in the 'clocks' device-tree node for 300 * a device to the list of clocks used for the power management of @dev. 301 * On success, returns the number of clocks added. Returns a negative 302 * error code if there are no clocks in the device node for the device 303 * or if adding a clock fails. 304 */ 305int of_pm_clk_add_clks(struct device *dev) 306{ 307 struct clk **clks; 308 int i, count; 309 int ret; 310 311 if (!dev || !dev->of_node) 312 return -EINVAL; 313 314 count = of_clk_get_parent_count(dev->of_node); 315 if (count <= 0) 316 return -ENODEV; 317 318 clks = kcalloc(count, sizeof(*clks), GFP_KERNEL); 319 if (!clks) 320 return -ENOMEM; 321 322 for (i = 0; i < count; i++) { 323 clks[i] = of_clk_get(dev->of_node, i); 324 if (IS_ERR(clks[i])) { 325 ret = PTR_ERR(clks[i]); 326 goto error; 327 } 328 329 ret = pm_clk_add_clk(dev, clks[i]); 330 if (ret) { 331 clk_put(clks[i]); 332 goto error; 333 } 334 } 335 336 kfree(clks); 337 338 return i; 339 340error: 341 while (i--) 342 pm_clk_remove_clk(dev, clks[i]); 343 344 kfree(clks); 345 346 return ret; 347} 348EXPORT_SYMBOL_GPL(of_pm_clk_add_clks); 349 350/** 351 * __pm_clk_remove - Destroy PM clock entry. 352 * @ce: PM clock entry to destroy. 353 */ 354static void __pm_clk_remove(struct pm_clock_entry *ce) 355{ 356 if (!ce) 357 return; 358 359 switch (ce->status) { 360 case PCE_STATUS_ENABLED: 361 clk_disable(ce->clk); 362 fallthrough; 363 case PCE_STATUS_PREPARED: 364 clk_unprepare(ce->clk); 365 fallthrough; 366 case PCE_STATUS_ACQUIRED: 367 case PCE_STATUS_ERROR: 368 if (!IS_ERR(ce->clk)) 369 clk_put(ce->clk); 370 break; 371 default: 372 break; 373 } 374 375 kfree(ce->con_id); 376 kfree(ce); 377} 378 379/** 380 * pm_clk_remove - Stop using a device clock for power management. 381 * @dev: Device whose clock should not be used for PM any more. 382 * @con_id: Connection ID of the clock. 383 * 384 * Remove the clock represented by @con_id from the list of clocks used for 385 * the power management of @dev. 386 */ 387void pm_clk_remove(struct device *dev, const char *con_id) 388{ 389 struct pm_subsys_data *psd = dev_to_psd(dev); 390 struct pm_clock_entry *ce; 391 392 if (!psd) 393 return; 394 395 pm_clk_list_lock(psd); 396 397 list_for_each_entry(ce, &psd->clock_list, node) { 398 if (!con_id && !ce->con_id) 399 goto remove; 400 else if (!con_id || !ce->con_id) 401 continue; 402 else if (!strcmp(con_id, ce->con_id)) 403 goto remove; 404 } 405 406 pm_clk_list_unlock(psd); 407 return; 408 409 remove: 410 list_del(&ce->node); 411 if (ce->enabled_when_prepared) 412 psd->clock_op_might_sleep--; 413 pm_clk_list_unlock(psd); 414 415 __pm_clk_remove(ce); 416} 417EXPORT_SYMBOL_GPL(pm_clk_remove); 418 419/** 420 * pm_clk_remove_clk - Stop using a device clock for power management. 421 * @dev: Device whose clock should not be used for PM any more. 422 * @clk: Clock pointer 423 * 424 * Remove the clock pointed to by @clk from the list of clocks used for 425 * the power management of @dev. 426 */ 427void pm_clk_remove_clk(struct device *dev, struct clk *clk) 428{ 429 struct pm_subsys_data *psd = dev_to_psd(dev); 430 struct pm_clock_entry *ce; 431 432 if (!psd || !clk) 433 return; 434 435 pm_clk_list_lock(psd); 436 437 list_for_each_entry(ce, &psd->clock_list, node) { 438 if (clk == ce->clk) 439 goto remove; 440 } 441 442 pm_clk_list_unlock(psd); 443 return; 444 445 remove: 446 list_del(&ce->node); 447 if (ce->enabled_when_prepared) 448 psd->clock_op_might_sleep--; 449 pm_clk_list_unlock(psd); 450 451 __pm_clk_remove(ce); 452} 453EXPORT_SYMBOL_GPL(pm_clk_remove_clk); 454 455/** 456 * pm_clk_init - Initialize a device's list of power management clocks. 457 * @dev: Device to initialize the list of PM clocks for. 458 * 459 * Initialize the lock and clock_list members of the device's pm_subsys_data 460 * object, set the count of clocks that might sleep to 0. 461 */ 462void pm_clk_init(struct device *dev) 463{ 464 struct pm_subsys_data *psd = dev_to_psd(dev); 465 if (psd) { 466 INIT_LIST_HEAD(&psd->clock_list); 467 mutex_init(&psd->clock_mutex); 468 psd->clock_op_might_sleep = 0; 469 } 470} 471EXPORT_SYMBOL_GPL(pm_clk_init); 472 473/** 474 * pm_clk_create - Create and initialize a device's list of PM clocks. 475 * @dev: Device to create and initialize the list of PM clocks for. 476 * 477 * Allocate a struct pm_subsys_data object, initialize its lock and clock_list 478 * members and make the @dev's power.subsys_data field point to it. 479 */ 480int pm_clk_create(struct device *dev) 481{ 482 return dev_pm_get_subsys_data(dev); 483} 484EXPORT_SYMBOL_GPL(pm_clk_create); 485 486/** 487 * pm_clk_destroy - Destroy a device's list of power management clocks. 488 * @dev: Device to destroy the list of PM clocks for. 489 * 490 * Clear the @dev's power.subsys_data field, remove the list of clock entries 491 * from the struct pm_subsys_data object pointed to by it before and free 492 * that object. 493 */ 494void pm_clk_destroy(struct device *dev) 495{ 496 struct pm_subsys_data *psd = dev_to_psd(dev); 497 struct pm_clock_entry *ce, *c; 498 struct list_head list; 499 500 if (!psd) 501 return; 502 503 INIT_LIST_HEAD(&list); 504 505 pm_clk_list_lock(psd); 506 507 list_for_each_entry_safe_reverse(ce, c, &psd->clock_list, node) 508 list_move(&ce->node, &list); 509 psd->clock_op_might_sleep = 0; 510 511 pm_clk_list_unlock(psd); 512 513 dev_pm_put_subsys_data(dev); 514 515 list_for_each_entry_safe_reverse(ce, c, &list, node) { 516 list_del(&ce->node); 517 __pm_clk_remove(ce); 518 } 519} 520EXPORT_SYMBOL_GPL(pm_clk_destroy); 521 522static void pm_clk_destroy_action(void *data) 523{ 524 pm_clk_destroy(data); 525} 526 527int devm_pm_clk_create(struct device *dev) 528{ 529 int ret; 530 531 ret = pm_clk_create(dev); 532 if (ret) 533 return ret; 534 535 return devm_add_action_or_reset(dev, pm_clk_destroy_action, dev); 536} 537EXPORT_SYMBOL_GPL(devm_pm_clk_create); 538 539/** 540 * pm_clk_suspend - Disable clocks in a device's PM clock list. 541 * @dev: Device to disable the clocks for. 542 */ 543int pm_clk_suspend(struct device *dev) 544{ 545 struct pm_subsys_data *psd = dev_to_psd(dev); 546 struct pm_clock_entry *ce; 547 unsigned long flags; 548 int ret; 549 550 dev_dbg(dev, "%s()\n", __func__); 551 552 if (!psd) 553 return 0; 554 555 ret = pm_clk_op_lock(psd, &flags, __func__); 556 if (ret) 557 return ret; 558 559 list_for_each_entry_reverse(ce, &psd->clock_list, node) { 560 if (ce->status == PCE_STATUS_ENABLED) { 561 if (ce->enabled_when_prepared) { 562 clk_disable_unprepare(ce->clk); 563 ce->status = PCE_STATUS_ACQUIRED; 564 } else { 565 clk_disable(ce->clk); 566 ce->status = PCE_STATUS_PREPARED; 567 } 568 } 569 } 570 571 pm_clk_op_unlock(psd, &flags); 572 573 return 0; 574} 575EXPORT_SYMBOL_GPL(pm_clk_suspend); 576 577/** 578 * pm_clk_resume - Enable clocks in a device's PM clock list. 579 * @dev: Device to enable the clocks for. 580 */ 581int pm_clk_resume(struct device *dev) 582{ 583 struct pm_subsys_data *psd = dev_to_psd(dev); 584 struct pm_clock_entry *ce; 585 unsigned long flags; 586 int ret; 587 588 dev_dbg(dev, "%s()\n", __func__); 589 590 if (!psd) 591 return 0; 592 593 ret = pm_clk_op_lock(psd, &flags, __func__); 594 if (ret) 595 return ret; 596 597 list_for_each_entry(ce, &psd->clock_list, node) 598 __pm_clk_enable(dev, ce); 599 600 pm_clk_op_unlock(psd, &flags); 601 602 return 0; 603} 604EXPORT_SYMBOL_GPL(pm_clk_resume); 605 606/** 607 * pm_clk_notify - Notify routine for device addition and removal. 608 * @nb: Notifier block object this function is a member of. 609 * @action: Operation being carried out by the caller. 610 * @data: Device the routine is being run for. 611 * 612 * For this function to work, @nb must be a member of an object of type 613 * struct pm_clk_notifier_block containing all of the requisite data. 614 * Specifically, the pm_domain member of that object is copied to the device's 615 * pm_domain field and its con_ids member is used to populate the device's list 616 * of PM clocks, depending on @action. 617 * 618 * If the device's pm_domain field is already populated with a value different 619 * from the one stored in the struct pm_clk_notifier_block object, the function 620 * does nothing. 621 */ 622static int pm_clk_notify(struct notifier_block *nb, 623 unsigned long action, void *data) 624{ 625 struct pm_clk_notifier_block *clknb; 626 struct device *dev = data; 627 char **con_id; 628 int error; 629 630 dev_dbg(dev, "%s() %ld\n", __func__, action); 631 632 clknb = container_of(nb, struct pm_clk_notifier_block, nb); 633 634 switch (action) { 635 case BUS_NOTIFY_ADD_DEVICE: 636 if (dev->pm_domain) 637 break; 638 639 error = pm_clk_create(dev); 640 if (error) 641 break; 642 643 dev_pm_domain_set(dev, clknb->pm_domain); 644 if (clknb->con_ids[0]) { 645 for (con_id = clknb->con_ids; *con_id; con_id++) 646 pm_clk_add(dev, *con_id); 647 } else { 648 pm_clk_add(dev, NULL); 649 } 650 651 break; 652 case BUS_NOTIFY_DEL_DEVICE: 653 if (dev->pm_domain != clknb->pm_domain) 654 break; 655 656 dev_pm_domain_set(dev, NULL); 657 pm_clk_destroy(dev); 658 break; 659 } 660 661 return 0; 662} 663 664int pm_clk_runtime_suspend(struct device *dev) 665{ 666 int ret; 667 668 dev_dbg(dev, "%s\n", __func__); 669 670 ret = pm_generic_runtime_suspend(dev); 671 if (ret) { 672 dev_err(dev, "failed to suspend device\n"); 673 return ret; 674 } 675 676 ret = pm_clk_suspend(dev); 677 if (ret) { 678 dev_err(dev, "failed to suspend clock\n"); 679 pm_generic_runtime_resume(dev); 680 return ret; 681 } 682 683 return 0; 684} 685EXPORT_SYMBOL_GPL(pm_clk_runtime_suspend); 686 687int pm_clk_runtime_resume(struct device *dev) 688{ 689 int ret; 690 691 dev_dbg(dev, "%s\n", __func__); 692 693 ret = pm_clk_resume(dev); 694 if (ret) { 695 dev_err(dev, "failed to resume clock\n"); 696 return ret; 697 } 698 699 return pm_generic_runtime_resume(dev); 700} 701EXPORT_SYMBOL_GPL(pm_clk_runtime_resume); 702 703#else /* !CONFIG_PM_CLK */ 704 705/** 706 * enable_clock - Enable a device clock. 707 * @dev: Device whose clock is to be enabled. 708 * @con_id: Connection ID of the clock. 709 */ 710static void enable_clock(struct device *dev, const char *con_id) 711{ 712 struct clk *clk; 713 714 clk = clk_get(dev, con_id); 715 if (!IS_ERR(clk)) { 716 clk_prepare_enable(clk); 717 clk_put(clk); 718 dev_info(dev, "Runtime PM disabled, clock forced on.\n"); 719 } 720} 721 722/** 723 * disable_clock - Disable a device clock. 724 * @dev: Device whose clock is to be disabled. 725 * @con_id: Connection ID of the clock. 726 */ 727static void disable_clock(struct device *dev, const char *con_id) 728{ 729 struct clk *clk; 730 731 clk = clk_get(dev, con_id); 732 if (!IS_ERR(clk)) { 733 clk_disable_unprepare(clk); 734 clk_put(clk); 735 dev_info(dev, "Runtime PM disabled, clock forced off.\n"); 736 } 737} 738 739/** 740 * pm_clk_notify - Notify routine for device addition and removal. 741 * @nb: Notifier block object this function is a member of. 742 * @action: Operation being carried out by the caller. 743 * @data: Device the routine is being run for. 744 * 745 * For this function to work, @nb must be a member of an object of type 746 * struct pm_clk_notifier_block containing all of the requisite data. 747 * Specifically, the con_ids member of that object is used to enable or disable 748 * the device's clocks, depending on @action. 749 */ 750static int pm_clk_notify(struct notifier_block *nb, 751 unsigned long action, void *data) 752{ 753 struct pm_clk_notifier_block *clknb; 754 struct device *dev = data; 755 char **con_id; 756 757 dev_dbg(dev, "%s() %ld\n", __func__, action); 758 759 clknb = container_of(nb, struct pm_clk_notifier_block, nb); 760 761 switch (action) { 762 case BUS_NOTIFY_BIND_DRIVER: 763 if (clknb->con_ids[0]) { 764 for (con_id = clknb->con_ids; *con_id; con_id++) 765 enable_clock(dev, *con_id); 766 } else { 767 enable_clock(dev, NULL); 768 } 769 break; 770 case BUS_NOTIFY_DRIVER_NOT_BOUND: 771 case BUS_NOTIFY_UNBOUND_DRIVER: 772 if (clknb->con_ids[0]) { 773 for (con_id = clknb->con_ids; *con_id; con_id++) 774 disable_clock(dev, *con_id); 775 } else { 776 disable_clock(dev, NULL); 777 } 778 break; 779 } 780 781 return 0; 782} 783 784#endif /* !CONFIG_PM_CLK */ 785 786/** 787 * pm_clk_add_notifier - Add bus type notifier for power management clocks. 788 * @bus: Bus type to add the notifier to. 789 * @clknb: Notifier to be added to the given bus type. 790 * 791 * The nb member of @clknb is not expected to be initialized and its 792 * notifier_call member will be replaced with pm_clk_notify(). However, 793 * the remaining members of @clknb should be populated prior to calling this 794 * routine. 795 */ 796void pm_clk_add_notifier(struct bus_type *bus, 797 struct pm_clk_notifier_block *clknb) 798{ 799 if (!bus || !clknb) 800 return; 801 802 clknb->nb.notifier_call = pm_clk_notify; 803 bus_register_notifier(bus, &clknb->nb); 804} 805EXPORT_SYMBOL_GPL(pm_clk_add_notifier);