Lines Matching +full:cpu +full:- +full:centric

1 // SPDX-License-Identifier: GPL-2.0
3 * drivers/base/power/domain.c - Common code related to device power domains.
24 #include <linux/cpu.h>
37 __routine = genpd->dev_ops.callback; \
56 mutex_lock(&genpd->mlock); in genpd_lock_mtx()
62 mutex_lock_nested(&genpd->mlock, depth); in genpd_lock_nested_mtx()
67 return mutex_lock_interruptible(&genpd->mlock); in genpd_lock_interruptible_mtx()
72 return mutex_unlock(&genpd->mlock); in genpd_unlock_mtx()
83 __acquires(&genpd->slock) in genpd_lock_spin()
87 spin_lock_irqsave(&genpd->slock, flags); in genpd_lock_spin()
88 genpd->lock_flags = flags; in genpd_lock_spin()
93 __acquires(&genpd->slock) in genpd_lock_nested_spin()
97 spin_lock_irqsave_nested(&genpd->slock, flags, depth); in genpd_lock_nested_spin()
98 genpd->lock_flags = flags; in genpd_lock_nested_spin()
102 __acquires(&genpd->slock) in genpd_lock_interruptible_spin()
106 spin_lock_irqsave(&genpd->slock, flags); in genpd_lock_interruptible_spin()
107 genpd->lock_flags = flags; in genpd_lock_interruptible_spin()
112 __releases(&genpd->slock) in genpd_unlock_spin()
114 spin_unlock_irqrestore(&genpd->slock, genpd->lock_flags); in genpd_unlock_spin()
125 __acquires(&genpd->raw_slock) in genpd_lock_raw_spin()
129 raw_spin_lock_irqsave(&genpd->raw_slock, flags); in genpd_lock_raw_spin()
130 genpd->raw_lock_flags = flags; in genpd_lock_raw_spin()
135 __acquires(&genpd->raw_slock) in genpd_lock_nested_raw_spin()
139 raw_spin_lock_irqsave_nested(&genpd->raw_slock, flags, depth); in genpd_lock_nested_raw_spin()
140 genpd->raw_lock_flags = flags; in genpd_lock_nested_raw_spin()
144 __acquires(&genpd->raw_slock) in genpd_lock_interruptible_raw_spin()
148 raw_spin_lock_irqsave(&genpd->raw_slock, flags); in genpd_lock_interruptible_raw_spin()
149 genpd->raw_lock_flags = flags; in genpd_lock_interruptible_raw_spin()
154 __releases(&genpd->raw_slock) in genpd_unlock_raw_spin()
156 raw_spin_unlock_irqrestore(&genpd->raw_slock, genpd->raw_lock_flags); in genpd_unlock_raw_spin()
166 #define genpd_lock(p) p->lock_ops->lock(p)
167 #define genpd_lock_nested(p, d) p->lock_ops->lock_nested(p, d)
168 #define genpd_lock_interruptible(p) p->lock_ops->lock_interruptible(p)
169 #define genpd_unlock(p) p->lock_ops->unlock(p)
171 #define genpd_status_on(genpd) (genpd->status == GENPD_STATE_ON)
172 #define genpd_is_irq_safe(genpd) (genpd->flags & GENPD_FLAG_IRQ_SAFE)
173 #define genpd_is_always_on(genpd) (genpd->flags & GENPD_FLAG_ALWAYS_ON)
174 #define genpd_is_active_wakeup(genpd) (genpd->flags & GENPD_FLAG_ACTIVE_WAKEUP)
175 #define genpd_is_cpu_domain(genpd) (genpd->flags & GENPD_FLAG_CPU_DOMAIN)
176 #define genpd_is_rpm_always_on(genpd) (genpd->flags & GENPD_FLAG_RPM_ALWAYS_ON)
177 #define genpd_is_opp_table_fw(genpd) (genpd->flags & GENPD_FLAG_OPP_TABLE_FW)
178 #define genpd_is_dev_name_fw(genpd) (genpd->flags & GENPD_FLAG_DEV_NAME_FW)
197 dev_name(&genpd->dev)); in irq_safe_dev_in_sleep_domain()
212 if (IS_ERR_OR_NULL(dev) || IS_ERR_OR_NULL(dev->pm_domain)) in dev_to_genpd_safe()
215 /* A genpd's always have its ->runtime_suspend() callback assigned. */ in dev_to_genpd_safe()
216 if (dev->pm_domain->ops.runtime_suspend == genpd_runtime_suspend) in dev_to_genpd_safe()
217 return pd_to_genpd(dev->pm_domain); in dev_to_genpd_safe()
228 if (IS_ERR_OR_NULL(dev->pm_domain)) in dev_to_genpd()
229 return ERR_PTR(-EINVAL); in dev_to_genpd()
231 return pd_to_genpd(dev->pm_domain); in dev_to_genpd()
241 return &genpd->dev; in dev_to_genpd_dev()
260 if (!WARN_ON(atomic_read(&genpd->sd_count) == 0)) in genpd_sd_counter_dec()
261 ret = !!atomic_dec_and_test(&genpd->sd_count); in genpd_sd_counter_dec()
268 atomic_inc(&genpd->sd_count); in genpd_sd_counter_inc()
282 debugfs_lookup_and_remove(dev_name(&genpd->dev), genpd_debugfs_dir); in genpd_debug_remove()
290 if (now <= genpd->accounting_time) in genpd_update_accounting()
293 delta = now - genpd->accounting_time; in genpd_update_accounting()
296 * If genpd->status is active, it means we are just in genpd_update_accounting()
300 if (genpd->status == GENPD_STATE_ON) in genpd_update_accounting()
301 genpd->states[genpd->state_idx].idle_time += delta; in genpd_update_accounting()
303 genpd->on_time += delta; in genpd_update_accounting()
305 genpd->accounting_time = now; in genpd_update_accounting()
321 if (state == genpd->performance_state) in _genpd_reeval_performance_state()
325 if (state > genpd->performance_state) in _genpd_reeval_performance_state()
329 list_for_each_entry(pdd, &genpd->dev_list, list_node) { in _genpd_reeval_performance_state()
332 if (pd_data->performance_state > state) in _genpd_reeval_performance_state()
333 state = pd_data->performance_state; in _genpd_reeval_performance_state()
337 * Traverse all sub-domains within the domain. This can be in _genpd_reeval_performance_state()
338 * done without any additional locking as the link->performance_state in _genpd_reeval_performance_state()
339 * field is protected by the parent genpd->lock, which is already taken. in _genpd_reeval_performance_state()
341 * Also note that link->performance_state (subdomain's performance state in _genpd_reeval_performance_state()
343 * link->child->performance_state (current performance state requirement in _genpd_reeval_performance_state()
344 * of the devices/sub-domains of the subdomain) and so can have a in _genpd_reeval_performance_state()
347 * Note that we also take vote from powered-off sub-domains into account in _genpd_reeval_performance_state()
350 list_for_each_entry(link, &genpd->parent_links, parent_node) { in _genpd_reeval_performance_state()
351 if (link->performance_state > state) in _genpd_reeval_performance_state()
352 state = link->performance_state; in _genpd_reeval_performance_state()
362 if (!parent->set_performance_state) in genpd_xlate_performance_state()
365 return dev_pm_opp_xlate_performance_state(genpd->opp_table, in genpd_xlate_performance_state()
366 parent->opp_table, in genpd_xlate_performance_state()
375 struct generic_pm_domain *parent = link->parent; in _genpd_rollback_parent_state()
380 parent_state = link->prev_performance_state; in _genpd_rollback_parent_state()
381 link->performance_state = parent_state; in _genpd_rollback_parent_state()
386 parent->name, parent_state); in _genpd_rollback_parent_state()
396 struct generic_pm_domain *parent = link->parent; in _genpd_set_parent_state()
408 link->prev_performance_state = link->performance_state; in _genpd_set_parent_state()
409 link->performance_state = parent_state; in _genpd_set_parent_state()
414 link->performance_state = link->prev_performance_state; in _genpd_set_parent_state()
427 if (state == genpd->performance_state) in _genpd_set_performance_state()
431 if (state > genpd->performance_state) { in _genpd_set_performance_state()
432 list_for_each_entry(link, &genpd->child_links, child_node) { in _genpd_set_performance_state()
439 if (genpd->set_performance_state) { in _genpd_set_performance_state()
440 ret = genpd->set_performance_state(genpd, state); in _genpd_set_performance_state()
449 if (state < genpd->performance_state) { in _genpd_set_performance_state()
450 list_for_each_entry_reverse(link, &genpd->child_links, child_node) { in _genpd_set_performance_state()
457 genpd->performance_state = state; in _genpd_set_performance_state()
461 list_for_each_entry_continue_reverse(link, &genpd->child_links, child_node) in _genpd_set_performance_state()
465 list_for_each_entry_continue(link, &genpd->child_links, child_node) in _genpd_set_performance_state()
477 prev_state = gpd_data->performance_state; in genpd_set_performance_state()
481 gpd_data->performance_state = state; in genpd_set_performance_state()
486 gpd_data->performance_state = prev_state; in genpd_set_performance_state()
493 unsigned int prev_state = dev_gpd_data(dev)->performance_state; in genpd_drop_performance_state()
516 dev_gpd_data(dev)->rpm_pstate = state; in genpd_dev_pm_set_performance_state()
520 dev_gpd_data(dev)->rpm_pstate = 0; in genpd_dev_pm_set_performance_state()
528 * dev_pm_genpd_set_performance_state- Set performance state of device's power
531 * @dev: Device for which the performance-state needs to be set.
548 return -ENODEV; in dev_pm_genpd_set_performance_state()
550 if (WARN_ON(!dev->power.subsys_data || in dev_pm_genpd_set_performance_state()
551 !dev->power.subsys_data->domain_data)) in dev_pm_genpd_set_performance_state()
552 return -EINVAL; in dev_pm_genpd_set_performance_state()
559 * dev_pm_genpd_set_next_wakeup - Notify PM framework of an impending wakeup.
582 td = to_gpd_data(dev->power.subsys_data->domain_data)->td; in dev_pm_genpd_set_next_wakeup()
584 td->next_wakeup = next; in dev_pm_genpd_set_next_wakeup()
589 * dev_pm_genpd_get_next_hrtimer - Return the next_hrtimer for the genpd
606 if (genpd->gd) in dev_pm_genpd_get_next_hrtimer()
607 return genpd->gd->next_hrtimer; in dev_pm_genpd_get_next_hrtimer()
614 * dev_pm_genpd_synced_poweroff - Next power off should be synchronous
633 genpd->synced_poweroff = true; in dev_pm_genpd_synced_poweroff()
639 * dev_pm_genpd_set_hwmode() - Set the HW mode for the device and its PM domain.
641 * @dev: Device for which the HW-mode should be changed.
642 * @enable: Value to set or unset the HW-mode.
661 return -ENODEV; in dev_pm_genpd_set_hwmode()
663 if (!genpd->set_hwmode_dev) in dev_pm_genpd_set_hwmode()
664 return -EOPNOTSUPP; in dev_pm_genpd_set_hwmode()
668 if (dev_gpd_data(dev)->hw_mode == enable) in dev_pm_genpd_set_hwmode()
671 ret = genpd->set_hwmode_dev(genpd, dev, enable); in dev_pm_genpd_set_hwmode()
673 dev_gpd_data(dev)->hw_mode = enable; in dev_pm_genpd_set_hwmode()
682 * dev_pm_genpd_get_hwmode() - Get the HW mode setting for the device.
684 * @dev: Device for which the current HW-mode setting should be fetched.
696 return dev_gpd_data(dev)->hw_mode; in dev_pm_genpd_get_hwmode()
701 * dev_pm_genpd_rpm_always_on() - Control if the PM domain can be powered off.
706 * For some usecases a consumer driver requires its device to remain power-on
721 return -ENODEV; in dev_pm_genpd_rpm_always_on()
724 dev_gpd_data(dev)->rpm_always_on = on; in dev_pm_genpd_rpm_always_on()
733 unsigned int state_idx = genpd->state_idx; in _genpd_power_on()
739 ret = raw_notifier_call_chain_robust(&genpd->power_notifiers, in _genpd_power_on()
746 if (!genpd->power_on) in _genpd_power_on()
749 timed = timed && genpd->gd && !genpd->states[state_idx].fwnode; in _genpd_power_on()
751 ret = genpd->power_on(genpd); in _genpd_power_on()
759 ret = genpd->power_on(genpd); in _genpd_power_on()
764 if (elapsed_ns <= genpd->states[state_idx].power_on_latency_ns) in _genpd_power_on()
767 genpd->states[state_idx].power_on_latency_ns = elapsed_ns; in _genpd_power_on()
768 genpd->gd->max_off_time_changed = true; in _genpd_power_on()
769 pr_debug("%s: Power-%s latency exceeded, new value %lld ns\n", in _genpd_power_on()
770 dev_name(&genpd->dev), "on", elapsed_ns); in _genpd_power_on()
773 raw_notifier_call_chain(&genpd->power_notifiers, GENPD_NOTIFY_ON, NULL); in _genpd_power_on()
774 genpd->synced_poweroff = false; in _genpd_power_on()
777 raw_notifier_call_chain(&genpd->power_notifiers, GENPD_NOTIFY_OFF, in _genpd_power_on()
784 unsigned int state_idx = genpd->state_idx; in _genpd_power_off()
790 ret = raw_notifier_call_chain_robust(&genpd->power_notifiers, in _genpd_power_off()
797 if (!genpd->power_off) in _genpd_power_off()
800 timed = timed && genpd->gd && !genpd->states[state_idx].fwnode; in _genpd_power_off()
802 ret = genpd->power_off(genpd); in _genpd_power_off()
810 ret = genpd->power_off(genpd); in _genpd_power_off()
815 if (elapsed_ns <= genpd->states[state_idx].power_off_latency_ns) in _genpd_power_off()
818 genpd->states[state_idx].power_off_latency_ns = elapsed_ns; in _genpd_power_off()
819 genpd->gd->max_off_time_changed = true; in _genpd_power_off()
820 pr_debug("%s: Power-%s latency exceeded, new value %lld ns\n", in _genpd_power_off()
821 dev_name(&genpd->dev), "off", elapsed_ns); in _genpd_power_off()
824 raw_notifier_call_chain(&genpd->power_notifiers, GENPD_NOTIFY_OFF, in _genpd_power_off()
828 raw_notifier_call_chain(&genpd->power_notifiers, GENPD_NOTIFY_ON, NULL); in _genpd_power_off()
833 * genpd_queue_power_off_work - Queue up the execution of genpd_power_off().
841 queue_work(pm_wq, &genpd->power_off_work); in genpd_queue_power_off_work()
845 * genpd_power_off - Remove power from a given PM domain.
847 * @one_dev_on: If invoked from genpd's ->runtime_suspend|resume() callback, the
869 if (!genpd_status_on(genpd) || genpd->prepared_count > 0) in genpd_power_off()
879 atomic_read(&genpd->sd_count) > 0) in genpd_power_off()
880 return -EBUSY; in genpd_power_off()
883 * The children must be in their deepest (powered-off) states to allow in genpd_power_off()
888 list_for_each_entry(link, &genpd->parent_links, parent_node) { in genpd_power_off()
889 struct generic_pm_domain *child = link->child; in genpd_power_off()
890 if (child->state_idx < child->state_count - 1) in genpd_power_off()
891 return -EBUSY; in genpd_power_off()
894 list_for_each_entry(pdd, &genpd->dev_list, list_node) { in genpd_power_off()
897 * device is part of a non-IRQ safe domain. in genpd_power_off()
899 if (!pm_runtime_suspended(pdd->dev) || in genpd_power_off()
900 irq_safe_dev_in_sleep_domain(pdd->dev, genpd)) in genpd_power_off()
904 if (to_gpd_data(pdd)->rpm_always_on) in genpd_power_off()
905 return -EBUSY; in genpd_power_off()
909 return -EBUSY; in genpd_power_off()
911 if (genpd->gov && genpd->gov->power_down_ok) { in genpd_power_off()
912 if (!genpd->gov->power_down_ok(&genpd->domain)) in genpd_power_off()
913 return -EAGAIN; in genpd_power_off()
917 if (!genpd->gov) in genpd_power_off()
918 genpd->state_idx = 0; in genpd_power_off()
921 if (atomic_read(&genpd->sd_count) > 0) in genpd_power_off()
922 return -EBUSY; in genpd_power_off()
926 genpd->states[genpd->state_idx].rejected++; in genpd_power_off()
930 genpd->status = GENPD_STATE_OFF; in genpd_power_off()
932 genpd->states[genpd->state_idx].usage++; in genpd_power_off()
934 list_for_each_entry(link, &genpd->child_links, child_node) { in genpd_power_off()
935 genpd_sd_counter_dec(link->parent); in genpd_power_off()
936 genpd_lock_nested(link->parent, depth + 1); in genpd_power_off()
937 genpd_power_off(link->parent, false, depth + 1); in genpd_power_off()
938 genpd_unlock(link->parent); in genpd_power_off()
945 * genpd_power_on - Restore power to a given PM domain and its parents.
965 list_for_each_entry(link, &genpd->child_links, child_node) { in genpd_power_on()
966 struct generic_pm_domain *parent = link->parent; in genpd_power_on()
984 genpd->status = GENPD_STATE_ON; in genpd_power_on()
991 &genpd->child_links, in genpd_power_on()
993 genpd_sd_counter_dec(link->parent); in genpd_power_on()
994 genpd_lock_nested(link->parent, depth + 1); in genpd_power_on()
995 genpd_power_off(link->parent, false, depth + 1); in genpd_power_on()
996 genpd_unlock(link->parent); in genpd_power_on()
1016 dev = gpd_data->base.dev; in genpd_dev_pm_qos_notifier()
1019 struct generic_pm_domain *genpd = ERR_PTR(-ENODATA); in genpd_dev_pm_qos_notifier()
1023 spin_lock_irq(&dev->power.lock); in genpd_dev_pm_qos_notifier()
1025 pdd = dev->power.subsys_data ? in genpd_dev_pm_qos_notifier()
1026 dev->power.subsys_data->domain_data : NULL; in genpd_dev_pm_qos_notifier()
1028 td = to_gpd_data(pdd)->td; in genpd_dev_pm_qos_notifier()
1030 td->constraint_changed = true; in genpd_dev_pm_qos_notifier()
1035 spin_unlock_irq(&dev->power.lock); in genpd_dev_pm_qos_notifier()
1039 genpd->gd->max_off_time_changed = true; in genpd_dev_pm_qos_notifier()
1043 dev = dev->parent; in genpd_dev_pm_qos_notifier()
1044 if (!dev || dev->power.ignore_children) in genpd_dev_pm_qos_notifier()
1052 * genpd_power_off_work_fn - Power off PM domain whose subdomain count is 0.
1067 * __genpd_runtime_suspend - walk the hierarchy of ->runtime_suspend() callbacks
1074 if (dev->type && dev->type->pm) in __genpd_runtime_suspend()
1075 cb = dev->type->pm->runtime_suspend; in __genpd_runtime_suspend()
1076 else if (dev->class && dev->class->pm) in __genpd_runtime_suspend()
1077 cb = dev->class->pm->runtime_suspend; in __genpd_runtime_suspend()
1078 else if (dev->bus && dev->bus->pm) in __genpd_runtime_suspend()
1079 cb = dev->bus->pm->runtime_suspend; in __genpd_runtime_suspend()
1083 if (!cb && dev->driver && dev->driver->pm) in __genpd_runtime_suspend()
1084 cb = dev->driver->pm->runtime_suspend; in __genpd_runtime_suspend()
1090 * __genpd_runtime_resume - walk the hierarchy of ->runtime_resume() callbacks
1097 if (dev->type && dev->type->pm) in __genpd_runtime_resume()
1098 cb = dev->type->pm->runtime_resume; in __genpd_runtime_resume()
1099 else if (dev->class && dev->class->pm) in __genpd_runtime_resume()
1100 cb = dev->class->pm->runtime_resume; in __genpd_runtime_resume()
1101 else if (dev->bus && dev->bus->pm) in __genpd_runtime_resume()
1102 cb = dev->bus->pm->runtime_resume; in __genpd_runtime_resume()
1106 if (!cb && dev->driver && dev->driver->pm) in __genpd_runtime_resume()
1107 cb = dev->driver->pm->runtime_resume; in __genpd_runtime_resume()
1113 * genpd_runtime_suspend - Suspend a device belonging to I/O PM domain.
1125 struct gpd_timing_data *td = gpd_data->td; in genpd_runtime_suspend()
1135 return -EINVAL; in genpd_runtime_suspend()
1138 * A runtime PM centric subsystem/driver may re-use the runtime PM in genpd_runtime_suspend()
1143 suspend_ok = genpd->gov ? genpd->gov->suspend_ok : NULL; in genpd_runtime_suspend()
1145 return -EBUSY; in genpd_runtime_suspend()
1164 if (elapsed_ns > td->suspend_latency_ns) { in genpd_runtime_suspend()
1165 td->suspend_latency_ns = elapsed_ns; in genpd_runtime_suspend()
1168 genpd->gd->max_off_time_changed = true; in genpd_runtime_suspend()
1169 td->constraint_changed = true; in genpd_runtime_suspend()
1182 gpd_data->rpm_pstate = genpd_drop_performance_state(dev); in genpd_runtime_suspend()
1189 * genpd_runtime_resume - Resume a device belonging to I/O PM domain.
1200 struct gpd_timing_data *td = gpd_data->td; in genpd_runtime_resume()
1210 return -EINVAL; in genpd_runtime_resume()
1220 genpd_restore_performance_state(dev, gpd_data->rpm_pstate); in genpd_runtime_resume()
1243 if (elapsed_ns > td->resume_latency_ns) { in genpd_runtime_resume()
1244 td->resume_latency_ns = elapsed_ns; in genpd_runtime_resume()
1247 genpd->gd->max_off_time_changed = true; in genpd_runtime_resume()
1248 td->constraint_changed = true; in genpd_runtime_resume()
1260 gpd_data->rpm_pstate = genpd_drop_performance_state(dev); in genpd_runtime_resume()
1276 * genpd_power_off_unused - Power off all PM domains with no devices in use.
1302 * genpd_sync_power_off - Synchronously power off a PM domain and its parents.
1322 if (genpd->suspended_count != genpd->device_count in genpd_sync_power_off()
1323 || atomic_read(&genpd->sd_count) > 0) in genpd_sync_power_off()
1326 /* Check that the children are in their deepest (powered-off) state. */ in genpd_sync_power_off()
1327 list_for_each_entry(link, &genpd->parent_links, parent_node) { in genpd_sync_power_off()
1328 struct generic_pm_domain *child = link->child; in genpd_sync_power_off()
1329 if (child->state_idx < child->state_count - 1) in genpd_sync_power_off()
1334 genpd->state_idx = genpd->state_count - 1; in genpd_sync_power_off()
1336 genpd->states[genpd->state_idx].rejected++; in genpd_sync_power_off()
1339 genpd->states[genpd->state_idx].usage++; in genpd_sync_power_off()
1342 genpd->status = GENPD_STATE_OFF; in genpd_sync_power_off()
1344 list_for_each_entry(link, &genpd->child_links, child_node) { in genpd_sync_power_off()
1345 genpd_sd_counter_dec(link->parent); in genpd_sync_power_off()
1348 genpd_lock_nested(link->parent, depth + 1); in genpd_sync_power_off()
1350 genpd_sync_power_off(link->parent, use_lock, depth + 1); in genpd_sync_power_off()
1353 genpd_unlock(link->parent); in genpd_sync_power_off()
1358 * genpd_sync_power_on - Synchronously power on a PM domain and its parents.
1375 list_for_each_entry(link, &genpd->child_links, child_node) { in genpd_sync_power_on()
1376 genpd_sd_counter_inc(link->parent); in genpd_sync_power_on()
1379 genpd_lock_nested(link->parent, depth + 1); in genpd_sync_power_on()
1381 genpd_sync_power_on(link->parent, use_lock, depth + 1); in genpd_sync_power_on()
1384 genpd_unlock(link->parent); in genpd_sync_power_on()
1388 genpd->status = GENPD_STATE_ON; in genpd_sync_power_on()
1392 * genpd_prepare - Start power transition of a device in a PM domain.
1395 * Start a power transition of a device (during a system-wide power transition)
1409 return -EINVAL; in genpd_prepare()
1412 genpd->prepared_count++; in genpd_prepare()
1419 genpd->prepared_count--; in genpd_prepare()
1429 * genpd_finish_suspend - Completion of suspend or hibernation of device in an
1447 return -EINVAL; in genpd_finish_suspend()
1456 if (genpd->dev_ops.stop && genpd->dev_ops.start && in genpd_finish_suspend()
1466 genpd->suspended_count++; in genpd_finish_suspend()
1474 * genpd_suspend_noirq - Completion of suspend of device in an I/O PM domain.
1490 * genpd_finish_resume - Completion of resume of device in an I/O PM domain.
1506 return -EINVAL; in genpd_finish_resume()
1513 genpd->suspended_count--; in genpd_finish_resume()
1516 if (genpd->dev_ops.stop && genpd->dev_ops.start && in genpd_finish_resume()
1527 * genpd_resume_noirq - Start of resume of device in an I/O PM domain.
1540 * genpd_freeze_noirq - Completion of freezing a device in an I/O PM domain.
1558 * genpd_thaw_noirq - Early thaw of device in an I/O PM domain.
1572 * genpd_poweroff_noirq - Completion of hibernation of device in an
1589 * genpd_restore_noirq - Start of restore of device in an I/O PM domain.
1603 * genpd_complete - Complete power transition of a device in a power domain.
1606 * Complete a power transition of a device (during a system-wide power
1625 genpd->prepared_count--; in genpd_complete()
1626 if (!genpd->prepared_count) in genpd_complete()
1647 genpd->suspended_count++; in genpd_switch_state()
1651 genpd->suspended_count--; in genpd_switch_state()
1659 * dev_pm_genpd_suspend - Synchronously try to suspend the genpd for @dev
1664 * suspend-to-idle to suspend a corresponding CPU device that is attached to a
1674 * dev_pm_genpd_resume - Synchronously try to resume the genpd for @dev
1678 * during the syscore resume phase. It may also be called during suspend-to-idle
1679 * to resume a corresponding CPU device that is attached to a genpd.
1713 ret = -ENOMEM; in genpd_alloc_dev_data()
1717 gpd_data->base.dev = dev; in genpd_alloc_dev_data()
1718 gpd_data->nb.notifier_call = genpd_dev_pm_qos_notifier; in genpd_alloc_dev_data()
1724 ret = -ENOMEM; in genpd_alloc_dev_data()
1728 td->constraint_changed = true; in genpd_alloc_dev_data()
1729 td->effective_constraint_ns = PM_QOS_RESUME_LATENCY_NO_CONSTRAINT_NS; in genpd_alloc_dev_data()
1730 td->next_wakeup = KTIME_MAX; in genpd_alloc_dev_data()
1731 gpd_data->td = td; in genpd_alloc_dev_data()
1734 spin_lock_irq(&dev->power.lock); in genpd_alloc_dev_data()
1736 if (dev->power.subsys_data->domain_data) in genpd_alloc_dev_data()
1737 ret = -EINVAL; in genpd_alloc_dev_data()
1739 dev->power.subsys_data->domain_data = &gpd_data->base; in genpd_alloc_dev_data()
1741 spin_unlock_irq(&dev->power.lock); in genpd_alloc_dev_data()
1749 kfree(gpd_data->td); in genpd_alloc_dev_data()
1759 spin_lock_irq(&dev->power.lock); in genpd_free_dev_data()
1761 dev->power.subsys_data->domain_data = NULL; in genpd_free_dev_data()
1763 spin_unlock_irq(&dev->power.lock); in genpd_free_dev_data()
1765 dev_pm_opp_clear_config(gpd_data->opp_token); in genpd_free_dev_data()
1766 kfree(gpd_data->td); in genpd_free_dev_data()
1772 int cpu, bool set, unsigned int depth) in genpd_update_cpumask() argument
1779 list_for_each_entry(link, &genpd->child_links, child_node) { in genpd_update_cpumask()
1780 struct generic_pm_domain *parent = link->parent; in genpd_update_cpumask()
1783 genpd_update_cpumask(parent, cpu, set, depth + 1); in genpd_update_cpumask()
1788 cpumask_set_cpu(cpu, genpd->cpus); in genpd_update_cpumask()
1790 cpumask_clear_cpu(cpu, genpd->cpus); in genpd_update_cpumask()
1793 static void genpd_set_cpumask(struct generic_pm_domain *genpd, int cpu) in genpd_set_cpumask() argument
1795 if (cpu >= 0) in genpd_set_cpumask()
1796 genpd_update_cpumask(genpd, cpu, true, 0); in genpd_set_cpumask()
1799 static void genpd_clear_cpumask(struct generic_pm_domain *genpd, int cpu) in genpd_clear_cpumask() argument
1801 if (cpu >= 0) in genpd_clear_cpumask()
1802 genpd_update_cpumask(genpd, cpu, false, 0); in genpd_clear_cpumask()
1807 int cpu; in genpd_get_cpu() local
1810 return -1; in genpd_get_cpu()
1812 for_each_possible_cpu(cpu) { in genpd_get_cpu()
1813 if (get_cpu_device(cpu) == dev) in genpd_get_cpu()
1814 return cpu; in genpd_get_cpu()
1817 return -1; in genpd_get_cpu()
1823 struct genpd_governor_data *gd = genpd->gd; in genpd_add_device()
1833 gpd_data->cpu = genpd_get_cpu(genpd, base_dev); in genpd_add_device()
1835 gpd_data->hw_mode = genpd->get_hwmode_dev ? genpd->get_hwmode_dev(genpd, dev) : false; in genpd_add_device()
1837 ret = genpd->attach_dev ? genpd->attach_dev(genpd, dev) : 0; in genpd_add_device()
1843 genpd_set_cpumask(genpd, gpd_data->cpu); in genpd_add_device()
1845 genpd->device_count++; in genpd_add_device()
1847 gd->max_off_time_changed = true; in genpd_add_device()
1849 list_add_tail(&gpd_data->base.list_node, &genpd->dev_list); in genpd_add_device()
1852 dev_pm_domain_set(dev, &genpd->domain); in genpd_add_device()
1857 dev_pm_qos_add_notifier(dev, &gpd_data->nb, in genpd_add_device()
1864 * pm_genpd_add_device - Add a device to an I/O PM domain.
1873 return -EINVAL; in pm_genpd_add_device()
1892 pdd = dev->power.subsys_data->domain_data; in genpd_remove_device()
1894 dev_pm_qos_remove_notifier(dev, &gpd_data->nb, in genpd_remove_device()
1899 if (genpd->prepared_count > 0) { in genpd_remove_device()
1900 ret = -EAGAIN; in genpd_remove_device()
1904 genpd->device_count--; in genpd_remove_device()
1905 if (genpd->gd) in genpd_remove_device()
1906 genpd->gd->max_off_time_changed = true; in genpd_remove_device()
1908 genpd_clear_cpumask(genpd, gpd_data->cpu); in genpd_remove_device()
1910 list_del_init(&pdd->list_node); in genpd_remove_device()
1916 if (genpd->detach_dev) in genpd_remove_device()
1917 genpd->detach_dev(genpd, dev); in genpd_remove_device()
1925 dev_pm_qos_add_notifier(dev, &gpd_data->nb, DEV_PM_QOS_RESUME_LATENCY); in genpd_remove_device()
1931 * pm_genpd_remove_device - Remove a device from an I/O PM domain.
1939 return -EINVAL; in pm_genpd_remove_device()
1946 * dev_pm_genpd_add_notifier - Add a genpd power on/off notifier for @dev
1968 return -ENODEV; in dev_pm_genpd_add_notifier()
1970 if (WARN_ON(!dev->power.subsys_data || in dev_pm_genpd_add_notifier()
1971 !dev->power.subsys_data->domain_data)) in dev_pm_genpd_add_notifier()
1972 return -EINVAL; in dev_pm_genpd_add_notifier()
1974 gpd_data = to_gpd_data(dev->power.subsys_data->domain_data); in dev_pm_genpd_add_notifier()
1975 if (gpd_data->power_nb) in dev_pm_genpd_add_notifier()
1976 return -EEXIST; in dev_pm_genpd_add_notifier()
1979 ret = raw_notifier_chain_register(&genpd->power_notifiers, nb); in dev_pm_genpd_add_notifier()
1984 dev_name(&genpd->dev)); in dev_pm_genpd_add_notifier()
1988 gpd_data->power_nb = nb; in dev_pm_genpd_add_notifier()
1994 * dev_pm_genpd_remove_notifier - Remove a genpd power on/off notifier for @dev
2014 return -ENODEV; in dev_pm_genpd_remove_notifier()
2016 if (WARN_ON(!dev->power.subsys_data || in dev_pm_genpd_remove_notifier()
2017 !dev->power.subsys_data->domain_data)) in dev_pm_genpd_remove_notifier()
2018 return -EINVAL; in dev_pm_genpd_remove_notifier()
2020 gpd_data = to_gpd_data(dev->power.subsys_data->domain_data); in dev_pm_genpd_remove_notifier()
2021 if (!gpd_data->power_nb) in dev_pm_genpd_remove_notifier()
2022 return -ENODEV; in dev_pm_genpd_remove_notifier()
2025 ret = raw_notifier_chain_unregister(&genpd->power_notifiers, in dev_pm_genpd_remove_notifier()
2026 gpd_data->power_nb); in dev_pm_genpd_remove_notifier()
2031 dev_name(&genpd->dev)); in dev_pm_genpd_remove_notifier()
2035 gpd_data->power_nb = NULL; in dev_pm_genpd_remove_notifier()
2048 return -EINVAL; in genpd_add_subdomain()
2057 dev_name(&genpd->dev), subdomain->name); in genpd_add_subdomain()
2058 return -EINVAL; in genpd_add_subdomain()
2063 return -ENOMEM; in genpd_add_subdomain()
2069 ret = -EINVAL; in genpd_add_subdomain()
2073 list_for_each_entry(itr, &genpd->parent_links, parent_node) { in genpd_add_subdomain()
2074 if (itr->child == subdomain && itr->parent == genpd) { in genpd_add_subdomain()
2075 ret = -EINVAL; in genpd_add_subdomain()
2080 link->parent = genpd; in genpd_add_subdomain()
2081 list_add_tail(&link->parent_node, &genpd->parent_links); in genpd_add_subdomain()
2082 link->child = subdomain; in genpd_add_subdomain()
2083 list_add_tail(&link->child_node, &subdomain->child_links); in genpd_add_subdomain()
2096 * pm_genpd_add_subdomain - Add a subdomain to an I/O PM domain.
2114 * pm_genpd_remove_subdomain - Remove a subdomain from an I/O PM domain.
2122 int ret = -EINVAL; in pm_genpd_remove_subdomain()
2125 return -EINVAL; in pm_genpd_remove_subdomain()
2130 if (!list_empty(&subdomain->parent_links) || subdomain->device_count) { in pm_genpd_remove_subdomain()
2132 dev_name(&genpd->dev), subdomain->name); in pm_genpd_remove_subdomain()
2133 ret = -EBUSY; in pm_genpd_remove_subdomain()
2137 list_for_each_entry_safe(link, l, &genpd->parent_links, parent_node) { in pm_genpd_remove_subdomain()
2138 if (link->child != subdomain) in pm_genpd_remove_subdomain()
2141 list_del(&link->parent_node); in pm_genpd_remove_subdomain()
2142 list_del(&link->child_node); in pm_genpd_remove_subdomain()
2171 return -ENOMEM; in genpd_set_default_power_state()
2173 genpd->states = state; in genpd_set_default_power_state()
2174 genpd->state_count = 1; in genpd_set_default_power_state()
2175 genpd->free_states = genpd_free_default_power_state; in genpd_set_default_power_state()
2191 !zalloc_cpumask_var(&genpd->cpus, GFP_KERNEL)) in genpd_alloc_data()
2192 return -ENOMEM; in genpd_alloc_data()
2194 if (genpd->gov) { in genpd_alloc_data()
2197 ret = -ENOMEM; in genpd_alloc_data()
2201 gd->max_off_time_ns = -1; in genpd_alloc_data()
2202 gd->max_off_time_changed = true; in genpd_alloc_data()
2203 gd->next_wakeup = KTIME_MAX; in genpd_alloc_data()
2204 gd->next_hrtimer = KTIME_MAX; in genpd_alloc_data()
2208 if (genpd->state_count == 0) { in genpd_alloc_data()
2214 genpd->gd = gd; in genpd_alloc_data()
2215 device_initialize(&genpd->dev); in genpd_alloc_data()
2216 genpd->dev.release = genpd_provider_release; in genpd_alloc_data()
2219 dev_set_name(&genpd->dev, "%s", genpd->name); in genpd_alloc_data()
2225 genpd->device_id = ret; in genpd_alloc_data()
2226 dev_set_name(&genpd->dev, "%s_%u", genpd->name, genpd->device_id); in genpd_alloc_data()
2231 put_device(&genpd->dev); in genpd_alloc_data()
2232 if (genpd->free_states == genpd_free_default_power_state) in genpd_alloc_data()
2233 kfree(genpd->states); in genpd_alloc_data()
2236 free_cpumask_var(genpd->cpus); in genpd_alloc_data()
2243 put_device(&genpd->dev); in genpd_free_data()
2244 if (genpd->device_id != -ENXIO) in genpd_free_data()
2245 ida_free(&genpd_ida, genpd->device_id); in genpd_free_data()
2247 free_cpumask_var(genpd->cpus); in genpd_free_data()
2248 if (genpd->free_states) in genpd_free_data()
2249 genpd->free_states(genpd->states, genpd->state_count); in genpd_free_data()
2250 kfree(genpd->gd); in genpd_free_data()
2256 raw_spin_lock_init(&genpd->raw_slock); in genpd_lock_init()
2257 genpd->lock_ops = &genpd_raw_spin_ops; in genpd_lock_init()
2259 spin_lock_init(&genpd->slock); in genpd_lock_init()
2260 genpd->lock_ops = &genpd_spin_ops; in genpd_lock_init()
2262 mutex_init(&genpd->mlock); in genpd_lock_init()
2263 genpd->lock_ops = &genpd_mtx_ops; in genpd_lock_init()
2268 * pm_genpd_init - Initialize a generic I/O PM domain object.
2281 return -EINVAL; in pm_genpd_init()
2283 INIT_LIST_HEAD(&genpd->parent_links); in pm_genpd_init()
2284 INIT_LIST_HEAD(&genpd->child_links); in pm_genpd_init()
2285 INIT_LIST_HEAD(&genpd->dev_list); in pm_genpd_init()
2286 RAW_INIT_NOTIFIER_HEAD(&genpd->power_notifiers); in pm_genpd_init()
2288 genpd->gov = gov; in pm_genpd_init()
2289 INIT_WORK(&genpd->power_off_work, genpd_power_off_work_fn); in pm_genpd_init()
2290 atomic_set(&genpd->sd_count, 0); in pm_genpd_init()
2291 genpd->status = is_off ? GENPD_STATE_OFF : GENPD_STATE_ON; in pm_genpd_init()
2292 genpd->device_count = 0; in pm_genpd_init()
2293 genpd->provider = NULL; in pm_genpd_init()
2294 genpd->device_id = -ENXIO; in pm_genpd_init()
2295 genpd->has_provider = false; in pm_genpd_init()
2296 genpd->accounting_time = ktime_get_mono_fast_ns(); in pm_genpd_init()
2297 genpd->domain.ops.runtime_suspend = genpd_runtime_suspend; in pm_genpd_init()
2298 genpd->domain.ops.runtime_resume = genpd_runtime_resume; in pm_genpd_init()
2299 genpd->domain.ops.prepare = genpd_prepare; in pm_genpd_init()
2300 genpd->domain.ops.suspend_noirq = genpd_suspend_noirq; in pm_genpd_init()
2301 genpd->domain.ops.resume_noirq = genpd_resume_noirq; in pm_genpd_init()
2302 genpd->domain.ops.freeze_noirq = genpd_freeze_noirq; in pm_genpd_init()
2303 genpd->domain.ops.thaw_noirq = genpd_thaw_noirq; in pm_genpd_init()
2304 genpd->domain.ops.poweroff_noirq = genpd_poweroff_noirq; in pm_genpd_init()
2305 genpd->domain.ops.restore_noirq = genpd_restore_noirq; in pm_genpd_init()
2306 genpd->domain.ops.complete = genpd_complete; in pm_genpd_init()
2307 genpd->domain.start = genpd_dev_pm_start; in pm_genpd_init()
2308 genpd->domain.set_performance_state = genpd_dev_pm_set_performance_state; in pm_genpd_init()
2310 if (genpd->flags & GENPD_FLAG_PM_CLK) { in pm_genpd_init()
2311 genpd->dev_ops.stop = pm_clk_suspend; in pm_genpd_init()
2312 genpd->dev_ops.start = pm_clk_resume; in pm_genpd_init()
2315 /* The always-on governor works better with the corresponding flag. */ in pm_genpd_init()
2317 genpd->flags |= GENPD_FLAG_RPM_ALWAYS_ON; in pm_genpd_init()
2319 /* Always-on domains must be powered on at initialization. */ in pm_genpd_init()
2322 pr_err("always-on PM domain %s is not on\n", genpd->name); in pm_genpd_init()
2323 return -EINVAL; in pm_genpd_init()
2327 if (!gov && genpd->state_count > 1) in pm_genpd_init()
2328 pr_warn("%s: no governor for states\n", genpd->name); in pm_genpd_init()
2335 list_add(&genpd->gpd_list_node, &gpd_list); in pm_genpd_init()
2348 return -EINVAL; in genpd_remove()
2352 if (genpd->has_provider) { in genpd_remove()
2354 pr_err("Provider present, unable to remove %s\n", dev_name(&genpd->dev)); in genpd_remove()
2355 return -EBUSY; in genpd_remove()
2358 if (!list_empty(&genpd->parent_links) || genpd->device_count) { in genpd_remove()
2360 pr_err("%s: unable to remove %s\n", __func__, dev_name(&genpd->dev)); in genpd_remove()
2361 return -EBUSY; in genpd_remove()
2364 list_for_each_entry_safe(link, l, &genpd->child_links, child_node) { in genpd_remove()
2365 list_del(&link->parent_node); in genpd_remove()
2366 list_del(&link->child_node); in genpd_remove()
2370 list_del(&genpd->gpd_list_node); in genpd_remove()
2373 cancel_work_sync(&genpd->power_off_work); in genpd_remove()
2376 pr_debug("%s: removed %s\n", __func__, dev_name(&genpd->dev)); in genpd_remove()
2382 * pm_genpd_remove - Remove a generic I/O PM domain
2386 * - Removes the PM domain as a subdomain to any parent domains,
2388 * - Removes the PM domain from the list of registered PM domains.
2419 * - genpd_xlate_simple() for 1:1 device tree node to PM domain mapping.
2420 * - genpd_xlate_onecell() for mapping of multiple PM domains per node by
2425 * struct of_genpd_provider - PM domain provider registration structure
2428 * @xlate: Provider-specific xlate callback mapping a set of specifier cells
2445 * genpd_xlate_simple() - Xlate function for direct node-domain mapping
2447 * @data: xlate function private data - pointer to struct generic_pm_domain
2461 * genpd_xlate_onecell() - Xlate function using a single index.
2463 * @data: xlate function private data - pointer to struct genpd_onecell_data
2475 unsigned int idx = genpdspec->args[0]; in genpd_xlate_onecell()
2477 if (genpdspec->args_count != 1) in genpd_xlate_onecell()
2478 return ERR_PTR(-EINVAL); in genpd_xlate_onecell()
2480 if (idx >= genpd_data->num_domains) { in genpd_xlate_onecell()
2482 return ERR_PTR(-EINVAL); in genpd_xlate_onecell()
2485 if (!genpd_data->domains[idx]) in genpd_xlate_onecell()
2486 return ERR_PTR(-ENOENT); in genpd_xlate_onecell()
2488 return genpd_data->domains[idx]; in genpd_xlate_onecell()
2492 * genpd_add_provider() - Register a PM domain provider for a node
2504 return -ENOMEM; in genpd_add_provider()
2506 cp->node = of_node_get(np); in genpd_add_provider()
2507 cp->data = data; in genpd_add_provider()
2508 cp->xlate = xlate; in genpd_add_provider()
2509 fwnode_dev_initialized(&np->fwnode, true); in genpd_add_provider()
2512 list_add(&cp->link, &of_genpd_providers); in genpd_add_provider()
2537 * of_genpd_add_provider_simple() - Register a simple PM domain provider
2547 return -EINVAL; in of_genpd_add_provider_simple()
2550 return -EINVAL; in of_genpd_add_provider_simple()
2552 genpd->dev.of_node = np; in of_genpd_add_provider_simple()
2555 if (!genpd_is_opp_table_fw(genpd) && genpd->set_performance_state) { in of_genpd_add_provider_simple()
2556 ret = dev_pm_opp_of_add_table(&genpd->dev); in of_genpd_add_provider_simple()
2558 return dev_err_probe(&genpd->dev, ret, "Failed to add OPP table\n"); in of_genpd_add_provider_simple()
2564 genpd->opp_table = dev_pm_opp_get_opp_table(&genpd->dev); in of_genpd_add_provider_simple()
2565 WARN_ON(IS_ERR(genpd->opp_table)); in of_genpd_add_provider_simple()
2570 if (!genpd_is_opp_table_fw(genpd) && genpd->set_performance_state) { in of_genpd_add_provider_simple()
2571 dev_pm_opp_put_opp_table(genpd->opp_table); in of_genpd_add_provider_simple()
2572 dev_pm_opp_of_remove_table(&genpd->dev); in of_genpd_add_provider_simple()
2578 genpd->provider = &np->fwnode; in of_genpd_add_provider_simple()
2579 genpd->has_provider = true; in of_genpd_add_provider_simple()
2586 * of_genpd_add_provider_onecell() - Register a onecell PM domain provider
2595 int ret = -EINVAL; in of_genpd_add_provider_onecell()
2598 return -EINVAL; in of_genpd_add_provider_onecell()
2600 if (!data->xlate) in of_genpd_add_provider_onecell()
2601 data->xlate = genpd_xlate_onecell; in of_genpd_add_provider_onecell()
2603 for (i = 0; i < data->num_domains; i++) { in of_genpd_add_provider_onecell()
2604 genpd = data->domains[i]; in of_genpd_add_provider_onecell()
2611 genpd->dev.of_node = np; in of_genpd_add_provider_onecell()
2614 if (!genpd_is_opp_table_fw(genpd) && genpd->set_performance_state) { in of_genpd_add_provider_onecell()
2615 ret = dev_pm_opp_of_add_table_indexed(&genpd->dev, i); in of_genpd_add_provider_onecell()
2617 dev_err_probe(&genpd->dev, ret, in of_genpd_add_provider_onecell()
2626 genpd->opp_table = dev_pm_opp_get_opp_table(&genpd->dev); in of_genpd_add_provider_onecell()
2627 WARN_ON(IS_ERR(genpd->opp_table)); in of_genpd_add_provider_onecell()
2630 genpd->provider = &np->fwnode; in of_genpd_add_provider_onecell()
2631 genpd->has_provider = true; in of_genpd_add_provider_onecell()
2634 ret = genpd_add_provider(np, data->xlate, data); in of_genpd_add_provider_onecell()
2641 while (i--) { in of_genpd_add_provider_onecell()
2642 genpd = data->domains[i]; in of_genpd_add_provider_onecell()
2647 genpd->provider = NULL; in of_genpd_add_provider_onecell()
2648 genpd->has_provider = false; in of_genpd_add_provider_onecell()
2650 if (!genpd_is_opp_table_fw(genpd) && genpd->set_performance_state) { in of_genpd_add_provider_onecell()
2651 dev_pm_opp_put_opp_table(genpd->opp_table); in of_genpd_add_provider_onecell()
2652 dev_pm_opp_of_remove_table(&genpd->dev); in of_genpd_add_provider_onecell()
2661 * of_genpd_del_provider() - Remove a previously registered PM domain provider
2672 if (cp->node == np) { in of_genpd_del_provider()
2679 if (gpd->provider == &np->fwnode) { in of_genpd_del_provider()
2680 gpd->has_provider = false; in of_genpd_del_provider()
2682 if (genpd_is_opp_table_fw(gpd) || !gpd->set_performance_state) in of_genpd_del_provider()
2685 dev_pm_opp_put_opp_table(gpd->opp_table); in of_genpd_del_provider()
2686 dev_pm_opp_of_remove_table(&gpd->dev); in of_genpd_del_provider()
2690 fwnode_dev_initialized(&cp->node->fwnode, false); in of_genpd_del_provider()
2691 list_del(&cp->link); in of_genpd_del_provider()
2692 of_node_put(cp->node); in of_genpd_del_provider()
2703 * genpd_get_from_provider() - Look-up PM domain
2704 * @genpdspec: OF phandle args to use for look-up
2716 struct generic_pm_domain *genpd = ERR_PTR(-ENOENT); in genpd_get_from_provider()
2720 return ERR_PTR(-EINVAL); in genpd_get_from_provider()
2726 if (provider->node == genpdspec->np) in genpd_get_from_provider()
2727 genpd = provider->xlate(genpdspec, provider->data); in genpd_get_from_provider()
2738 * of_genpd_add_device() - Add a device to an I/O PM domain
2739 * @genpdspec: OF phandle args to use for look-up PM domain
2742 * Looks-up an I/O PM domain based upon phandle args provided and adds
2751 return -EINVAL; in of_genpd_add_device()
2771 * of_genpd_add_subdomain - Add a subdomain to an I/O PM domain.
2772 * @parent_spec: OF phandle args to use for parent PM domain look-up
2773 * @subdomain_spec: OF phandle args to use for subdomain look-up
2775 * Looks-up a parent PM domain and subdomain based upon phandle args
2804 return ret == -ENOENT ? -EPROBE_DEFER : ret; in of_genpd_add_subdomain()
2809 * of_genpd_remove_subdomain - Remove a subdomain from an I/O PM domain.
2810 * @parent_spec: OF phandle args to use for parent PM domain look-up
2811 * @subdomain_spec: OF phandle args to use for subdomain look-up
2813 * Looks-up a parent PM domain and subdomain based upon phandle args
2847 * of_genpd_remove_last - Remove the last PM domain registered for a provider
2861 struct generic_pm_domain *gpd, *tmp, *genpd = ERR_PTR(-ENOENT); in of_genpd_remove_last()
2865 return ERR_PTR(-EINVAL); in of_genpd_remove_last()
2869 if (gpd->provider == &np->fwnode) { in of_genpd_remove_last()
2883 of_node_put(dev->of_node); in genpd_release_dev()
2892 * genpd_dev_pm_detach - Detach a device from its PM domain.
2909 dev_dbg(dev, "removing from PM domain %s\n", pd->name); in genpd_dev_pm_detach()
2912 if (dev_gpd_data(dev)->default_pstate) { in genpd_dev_pm_detach()
2914 dev_gpd_data(dev)->default_pstate = 0; in genpd_dev_pm_detach()
2919 if (ret != -EAGAIN) in genpd_dev_pm_detach()
2928 pd->name, ret); in genpd_dev_pm_detach()
2936 if (dev->bus == &genpd_bus_type) in genpd_dev_pm_detach()
2959 /* Limit support to non-providers for now. */ in genpd_set_required_opp_dev()
2960 if (of_property_present(base_dev->of_node, "#power-domain-cells")) in genpd_set_required_opp_dev()
2970 dev_gpd_data(dev)->opp_token = ret; in genpd_set_required_opp_dev()
2979 pstate = of_get_required_opp_performance_state(dev->of_node, index); in genpd_set_required_opp()
2980 if (pstate < 0 && pstate != -ENODEV && pstate != -EOPNOTSUPP) { in genpd_set_required_opp()
2987 dev_gpd_data(dev)->default_pstate = pstate; in genpd_set_required_opp()
2992 dev_err(dev, "failed to set required performance state for power-domain %s: %d\n", in genpd_set_required_opp()
2993 dev_to_genpd(dev)->name, ret); in genpd_set_required_opp()
3005 ret = of_parse_phandle_with_args(dev->of_node, "power-domains", in __genpd_dev_pm_attach()
3006 "#power-domain-cells", index, &pd_args); in __genpd_dev_pm_attach()
3020 dev_dbg(dev, "adding to PM domain %s\n", pd->name); in __genpd_dev_pm_attach()
3026 return dev_err_probe(dev, ret, "failed to add to PM domain %s\n", pd->name); in __genpd_dev_pm_attach()
3028 dev->pm_domain->detach = genpd_dev_pm_detach; in __genpd_dev_pm_attach()
3029 dev->pm_domain->sync = genpd_dev_pm_sync; in __genpd_dev_pm_attach()
3054 if (dev_gpd_data(dev)->default_pstate) { in __genpd_dev_pm_attach()
3056 dev_gpd_data(dev)->default_pstate = 0; in __genpd_dev_pm_attach()
3060 return -EPROBE_DEFER; in __genpd_dev_pm_attach()
3071 * genpd_dev_pm_attach - Attach a device to its PM domain using DT.
3078 * PM domain or when multiple power-domains exists for it, else a negative error
3079 * code. Note that if a power-domain exists for the device, but it cannot be
3080 * found or turned on, then return -EPROBE_DEFER to ensure that the device is
3081 * not probed and to re-try again later.
3085 if (!dev->of_node) in genpd_dev_pm_attach()
3092 if (of_count_phandle_with_args(dev->of_node, "power-domains", in genpd_dev_pm_attach()
3093 "#power-domain-cells") != 1) in genpd_dev_pm_attach()
3101 * genpd_dev_pm_attach_by_id - Associate a device with one of its PM domains.
3107 * pm_domain ops. To deal with detaching of the virtual device, the ->detach()
3112 * failures. If a power-domain exists for the device, but cannot be found or
3113 * turned on, then ERR_PTR(-EPROBE_DEFER) is returned to ensure that the device
3114 * is not probed and to re-try again later.
3123 if (!dev->of_node) in genpd_dev_pm_attach_by_id()
3127 num_domains = of_count_phandle_with_args(dev->of_node, "power-domains", in genpd_dev_pm_attach_by_id()
3128 "#power-domain-cells"); in genpd_dev_pm_attach_by_id()
3135 return ERR_PTR(-ENOMEM); in genpd_dev_pm_attach_by_id()
3138 virt_dev->bus = &genpd_bus_type; in genpd_dev_pm_attach_by_id()
3139 virt_dev->release = genpd_release_dev; in genpd_dev_pm_attach_by_id()
3140 virt_dev->of_node = of_node_get(dev->of_node); in genpd_dev_pm_attach_by_id()
3163 * genpd_dev_pm_attach_by_name - Associate a device with one of its PM domains.
3168 * power-domain-names DT property. For further description see
3175 if (!dev->of_node) in genpd_dev_pm_attach_by_name()
3178 index = of_property_match_string(dev->of_node, "power-domain-names", in genpd_dev_pm_attach_by_name()
3187 { .compatible = "domain-idle-state", },
3198 err = of_property_read_u32(state_node, "entry-latency-us", in genpd_parse_state()
3201 pr_debug(" * %pOF missing entry-latency-us property\n", in genpd_parse_state()
3203 return -EINVAL; in genpd_parse_state()
3206 err = of_property_read_u32(state_node, "exit-latency-us", in genpd_parse_state()
3209 pr_debug(" * %pOF missing exit-latency-us property\n", in genpd_parse_state()
3211 return -EINVAL; in genpd_parse_state()
3214 err = of_property_read_u32(state_node, "min-residency-us", &residency); in genpd_parse_state()
3216 genpd_state->residency_ns = 1000LL * residency; in genpd_parse_state()
3218 of_property_read_string(state_node, "idle-state-name", &genpd_state->name); in genpd_parse_state()
3220 genpd_state->power_on_latency_ns = 1000LL * exit_latency; in genpd_parse_state()
3221 genpd_state->power_off_latency_ns = 1000LL * entry_latency; in genpd_parse_state()
3222 genpd_state->fwnode = &state_node->fwnode; in genpd_parse_state()
3235 ret = of_count_phandle_with_args(dn, "domain-idle-states", NULL); in genpd_iterate_idle_states()
3237 return ret == -ENOENT ? 0 : ret; in genpd_iterate_idle_states()
3240 of_for_each_phandle(&it, ret, dn, "domain-idle-states", NULL, 0) { in genpd_iterate_idle_states()
3293 return -ENOMEM; in of_genpd_parse_idle_states()
3298 return ret < 0 ? ret : -EINVAL; in of_genpd_parse_idle_states()
3334 if (dev->power.runtime_error) in rtpm_status_str()
3336 else if (dev->power.disable_depth) in rtpm_status_str()
3338 else if (dev->power.runtime_status < ARRAY_SIZE(status_lookup)) in rtpm_status_str()
3339 p = status_lookup[dev->power.runtime_status]; in rtpm_status_str()
3343 seq_printf(s, "%-26s ", p); in rtpm_status_str()
3350 gpd_data = to_gpd_data(dev->power.subsys_data->domain_data); in perf_status_str()
3352 seq_printf(s, "%-10u ", gpd_data->performance_state); in perf_status_str()
3359 gpd_data = to_gpd_data(dev->power.subsys_data->domain_data); in mode_status_str()
3361 seq_printf(s, "%2s", gpd_data->hw_mode ? "HW" : "SW"); in mode_status_str()
3378 return -ERESTARTSYS; in genpd_summary_one()
3380 if (WARN_ON(genpd->status >= ARRAY_SIZE(status_lookup))) in genpd_summary_one()
3383 snprintf(state, sizeof(state), "%s-%u", in genpd_summary_one()
3384 status_lookup[genpd->status], genpd->state_idx); in genpd_summary_one()
3387 status_lookup[genpd->status]); in genpd_summary_one()
3388 seq_printf(s, "%-30s %-30s %u", dev_name(&genpd->dev), state, genpd->performance_state); in genpd_summary_one()
3395 list_for_each_entry(link, &genpd->parent_links, parent_node) { in genpd_summary_one()
3396 if (list_is_first(&link->parent_node, &genpd->parent_links)) in genpd_summary_one()
3398 seq_printf(s, "%s", link->child->name); in genpd_summary_one()
3399 if (!list_is_last(&link->parent_node, &genpd->parent_links)) in genpd_summary_one()
3403 list_for_each_entry(pm_data, &genpd->dev_list, list_node) { in genpd_summary_one()
3404 seq_printf(s, "\n %-30s ", dev_name(pm_data->dev)); in genpd_summary_one()
3405 rtpm_status_str(s, pm_data->dev); in genpd_summary_one()
3406 perf_status_str(s, pm_data->dev); in genpd_summary_one()
3407 mode_status_str(s, pm_data->dev); in genpd_summary_one()
3424 seq_puts(s, "------------------------------------------------------------------------------\n"); in summary_show()
3428 return -ERESTARTSYS; in summary_show()
3447 struct generic_pm_domain *genpd = s->private; in status_show()
3452 return -ERESTARTSYS; in status_show()
3454 if (WARN_ON_ONCE(genpd->status >= ARRAY_SIZE(status_lookup))) in status_show()
3457 if (genpd->status == GENPD_STATE_OFF) in status_show()
3458 seq_printf(s, "%s-%u\n", status_lookup[genpd->status], in status_show()
3459 genpd->state_idx); in status_show()
3461 seq_printf(s, "%s\n", status_lookup[genpd->status]); in status_show()
3469 struct generic_pm_domain *genpd = s->private; in sub_domains_show()
3475 return -ERESTARTSYS; in sub_domains_show()
3477 list_for_each_entry(link, &genpd->parent_links, parent_node) in sub_domains_show()
3478 seq_printf(s, "%s\n", link->child->name); in sub_domains_show()
3486 struct generic_pm_domain *genpd = s->private; in idle_states_show()
3493 return -ERESTARTSYS; in idle_states_show()
3497 for (i = 0; i < genpd->state_count; i++) { in idle_states_show()
3498 struct genpd_power_state *state = &genpd->states[i]; in idle_states_show()
3501 idle_time += state->idle_time; in idle_states_show()
3503 if (genpd->status == GENPD_STATE_OFF && genpd->state_idx == i) { in idle_states_show()
3505 if (now > genpd->accounting_time) { in idle_states_show()
3506 delta = now - genpd->accounting_time; in idle_states_show()
3511 if (!state->name) in idle_states_show()
3512 snprintf(state_name, ARRAY_SIZE(state_name), "S%-13d", i); in idle_states_show()
3515 seq_printf(s, "%-14s %-14llu %-14llu %llu\n", in idle_states_show()
3516 state->name ?: state_name, idle_time, in idle_states_show()
3517 state->usage, state->rejected); in idle_states_show()
3526 struct generic_pm_domain *genpd = s->private; in active_time_show()
3532 return -ERESTARTSYS; in active_time_show()
3534 if (genpd->status == GENPD_STATE_ON) { in active_time_show()
3536 if (now > genpd->accounting_time) in active_time_show()
3537 delta = now - genpd->accounting_time; in active_time_show()
3540 on_time = genpd->on_time + delta; in active_time_show()
3550 struct generic_pm_domain *genpd = s->private; in total_idle_time_show()
3557 return -ERESTARTSYS; in total_idle_time_show()
3559 for (i = 0; i < genpd->state_count; i++) { in total_idle_time_show()
3560 total += genpd->states[i].idle_time; in total_idle_time_show()
3562 if (genpd->status == GENPD_STATE_OFF && genpd->state_idx == i) { in total_idle_time_show()
3564 if (now > genpd->accounting_time) { in total_idle_time_show()
3565 delta = now - genpd->accounting_time; in total_idle_time_show()
3581 struct generic_pm_domain *genpd = s->private; in devices_show()
3587 return -ERESTARTSYS; in devices_show()
3589 list_for_each_entry(pm_data, &genpd->dev_list, list_node) in devices_show()
3590 seq_printf(s, "%s\n", dev_name(pm_data->dev)); in devices_show()
3598 struct generic_pm_domain *genpd = s->private; in perf_state_show()
3601 return -ERESTARTSYS; in perf_state_show()
3603 seq_printf(s, "%u\n", genpd->performance_state); in perf_state_show()
3625 d = debugfs_create_dir(dev_name(&genpd->dev), genpd_debugfs_dir); in genpd_debug_add()
3639 if (genpd->set_performance_state) in genpd_debug_add()