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.
23 #include <linux/cpu.h>
34 __routine = genpd->dev_ops.callback; \
53 mutex_lock(&genpd->mlock); in genpd_lock_mtx()
59 mutex_lock_nested(&genpd->mlock, depth); in genpd_lock_nested_mtx()
64 return mutex_lock_interruptible(&genpd->mlock); in genpd_lock_interruptible_mtx()
69 return mutex_unlock(&genpd->mlock); in genpd_unlock_mtx()
80 __acquires(&genpd->slock) in genpd_lock_spin()
84 spin_lock_irqsave(&genpd->slock, flags); in genpd_lock_spin()
85 genpd->lock_flags = flags; in genpd_lock_spin()
90 __acquires(&genpd->slock) in genpd_lock_nested_spin()
94 spin_lock_irqsave_nested(&genpd->slock, flags, depth); in genpd_lock_nested_spin()
95 genpd->lock_flags = flags; in genpd_lock_nested_spin()
99 __acquires(&genpd->slock) in genpd_lock_interruptible_spin()
103 spin_lock_irqsave(&genpd->slock, flags); in genpd_lock_interruptible_spin()
104 genpd->lock_flags = flags; in genpd_lock_interruptible_spin()
109 __releases(&genpd->slock) in genpd_unlock_spin()
111 spin_unlock_irqrestore(&genpd->slock, genpd->lock_flags); in genpd_unlock_spin()
121 #define genpd_lock(p) p->lock_ops->lock(p)
122 #define genpd_lock_nested(p, d) p->lock_ops->lock_nested(p, d)
123 #define genpd_lock_interruptible(p) p->lock_ops->lock_interruptible(p)
124 #define genpd_unlock(p) p->lock_ops->unlock(p)
126 #define genpd_status_on(genpd) (genpd->status == GPD_STATE_ACTIVE)
127 #define genpd_is_irq_safe(genpd) (genpd->flags & GENPD_FLAG_IRQ_SAFE)
128 #define genpd_is_always_on(genpd) (genpd->flags & GENPD_FLAG_ALWAYS_ON)
129 #define genpd_is_active_wakeup(genpd) (genpd->flags & GENPD_FLAG_ACTIVE_WAKEUP)
130 #define genpd_is_cpu_domain(genpd) (genpd->flags & GENPD_FLAG_CPU_DOMAIN)
131 #define genpd_is_rpm_always_on(genpd) (genpd->flags & GENPD_FLAG_RPM_ALWAYS_ON)
147 genpd->name); in irq_safe_dev_in_no_sleep_domain()
162 if (IS_ERR_OR_NULL(dev) || IS_ERR_OR_NULL(dev->pm_domain)) in dev_to_genpd_safe()
165 /* A genpd's always have its ->runtime_suspend() callback assigned. */ in dev_to_genpd_safe()
166 if (dev->pm_domain->ops.runtime_suspend == genpd_runtime_suspend) in dev_to_genpd_safe()
167 return pd_to_genpd(dev->pm_domain); in dev_to_genpd_safe()
178 if (IS_ERR_OR_NULL(dev->pm_domain)) in dev_to_genpd()
179 return ERR_PTR(-EINVAL); in dev_to_genpd()
181 return pd_to_genpd(dev->pm_domain); in dev_to_genpd()
200 if (!WARN_ON(atomic_read(&genpd->sd_count) == 0)) in genpd_sd_counter_dec()
201 ret = !!atomic_dec_and_test(&genpd->sd_count); in genpd_sd_counter_dec()
208 atomic_inc(&genpd->sd_count); in genpd_sd_counter_inc()
218 delta = ktime_sub(now, genpd->accounting_time); in genpd_update_accounting()
221 * If genpd->status is active, it means we are just in genpd_update_accounting()
225 if (genpd->status == GPD_STATE_ACTIVE) { in genpd_update_accounting()
226 int state_idx = genpd->state_idx; in genpd_update_accounting()
228 genpd->states[state_idx].idle_time = in genpd_update_accounting()
229 ktime_add(genpd->states[state_idx].idle_time, delta); in genpd_update_accounting()
231 genpd->on_time = ktime_add(genpd->on_time, delta); in genpd_update_accounting()
234 genpd->accounting_time = now; in genpd_update_accounting()
248 if (state == genpd->performance_state) in _genpd_reeval_performance_state()
252 if (state > genpd->performance_state) in _genpd_reeval_performance_state()
256 list_for_each_entry(pdd, &genpd->dev_list, list_node) { in _genpd_reeval_performance_state()
259 if (pd_data->performance_state > state) in _genpd_reeval_performance_state()
260 state = pd_data->performance_state; in _genpd_reeval_performance_state()
264 * Traverse all sub-domains within the domain. This can be in _genpd_reeval_performance_state()
265 * done without any additional locking as the link->performance_state in _genpd_reeval_performance_state()
266 * field is protected by the master genpd->lock, which is already taken. in _genpd_reeval_performance_state()
268 * Also note that link->performance_state (subdomain's performance state in _genpd_reeval_performance_state()
270 * link->slave->performance_state (current performance state requirement in _genpd_reeval_performance_state()
271 * of the devices/sub-domains of the subdomain) and so can have a in _genpd_reeval_performance_state()
274 * Note that we also take vote from powered-off sub-domains into account in _genpd_reeval_performance_state()
277 list_for_each_entry(link, &genpd->master_links, master_node) { in _genpd_reeval_performance_state()
278 if (link->performance_state > state) in _genpd_reeval_performance_state()
279 state = link->performance_state; in _genpd_reeval_performance_state()
292 if (state == genpd->performance_state) in _genpd_set_performance_state()
296 list_for_each_entry(link, &genpd->slave_links, slave_node) { in _genpd_set_performance_state()
297 master = link->master; in _genpd_set_performance_state()
299 if (!master->set_performance_state) in _genpd_set_performance_state()
303 ret = dev_pm_opp_xlate_performance_state(genpd->opp_table, in _genpd_set_performance_state()
304 master->opp_table, in _genpd_set_performance_state()
313 link->prev_performance_state = link->performance_state; in _genpd_set_performance_state()
314 link->performance_state = master_state; in _genpd_set_performance_state()
319 link->performance_state = link->prev_performance_state; in _genpd_set_performance_state()
327 ret = genpd->set_performance_state(genpd, state); in _genpd_set_performance_state()
331 genpd->performance_state = state; in _genpd_set_performance_state()
336 list_for_each_entry_continue_reverse(link, &genpd->slave_links, in _genpd_set_performance_state()
338 master = link->master; in _genpd_set_performance_state()
340 if (!master->set_performance_state) in _genpd_set_performance_state()
345 master_state = link->prev_performance_state; in _genpd_set_performance_state()
346 link->performance_state = master_state; in _genpd_set_performance_state()
352 master->name, master_state); in _genpd_set_performance_state()
362 * dev_pm_genpd_set_performance_state- Set performance state of device's power
365 * @dev: Device for which the performance-state needs to be set.
385 return -ENODEV; in dev_pm_genpd_set_performance_state()
387 if (unlikely(!genpd->set_performance_state)) in dev_pm_genpd_set_performance_state()
388 return -EINVAL; in dev_pm_genpd_set_performance_state()
390 if (WARN_ON(!dev->power.subsys_data || in dev_pm_genpd_set_performance_state()
391 !dev->power.subsys_data->domain_data)) in dev_pm_genpd_set_performance_state()
392 return -EINVAL; in dev_pm_genpd_set_performance_state()
396 gpd_data = to_gpd_data(dev->power.subsys_data->domain_data); in dev_pm_genpd_set_performance_state()
397 prev = gpd_data->performance_state; in dev_pm_genpd_set_performance_state()
398 gpd_data->performance_state = state; in dev_pm_genpd_set_performance_state()
403 gpd_data->performance_state = prev; in dev_pm_genpd_set_performance_state()
413 unsigned int state_idx = genpd->state_idx; in _genpd_power_on()
418 if (!genpd->power_on) in _genpd_power_on()
422 return genpd->power_on(genpd); in _genpd_power_on()
425 ret = genpd->power_on(genpd); in _genpd_power_on()
430 if (elapsed_ns <= genpd->states[state_idx].power_on_latency_ns) in _genpd_power_on()
433 genpd->states[state_idx].power_on_latency_ns = elapsed_ns; in _genpd_power_on()
434 genpd->max_off_time_changed = true; in _genpd_power_on()
435 pr_debug("%s: Power-%s latency exceeded, new value %lld ns\n", in _genpd_power_on()
436 genpd->name, "on", elapsed_ns); in _genpd_power_on()
443 unsigned int state_idx = genpd->state_idx; in _genpd_power_off()
448 if (!genpd->power_off) in _genpd_power_off()
452 return genpd->power_off(genpd); in _genpd_power_off()
455 ret = genpd->power_off(genpd); in _genpd_power_off()
460 if (elapsed_ns <= genpd->states[state_idx].power_off_latency_ns) in _genpd_power_off()
463 genpd->states[state_idx].power_off_latency_ns = elapsed_ns; in _genpd_power_off()
464 genpd->max_off_time_changed = true; in _genpd_power_off()
465 pr_debug("%s: Power-%s latency exceeded, new value %lld ns\n", in _genpd_power_off()
466 genpd->name, "off", elapsed_ns); in _genpd_power_off()
472 * genpd_queue_power_off_work - Queue up the execution of genpd_power_off().
480 queue_work(pm_wq, &genpd->power_off_work); in genpd_queue_power_off_work()
484 * genpd_power_off - Remove power from a given PM domain.
486 * @one_dev_on: If invoked from genpd's ->runtime_suspend|resume() callback, the
506 if (!genpd_status_on(genpd) || genpd->prepared_count > 0) in genpd_power_off()
516 atomic_read(&genpd->sd_count) > 0) in genpd_power_off()
517 return -EBUSY; in genpd_power_off()
519 list_for_each_entry(pdd, &genpd->dev_list, list_node) { in genpd_power_off()
522 stat = dev_pm_qos_flags(pdd->dev, PM_QOS_FLAG_NO_POWER_OFF); in genpd_power_off()
524 return -EBUSY; in genpd_power_off()
528 * device is part of a non-IRQ safe domain. in genpd_power_off()
530 if (!pm_runtime_suspended(pdd->dev) || in genpd_power_off()
531 irq_safe_dev_in_no_sleep_domain(pdd->dev, genpd)) in genpd_power_off()
536 return -EBUSY; in genpd_power_off()
538 if (genpd->gov && genpd->gov->power_down_ok) { in genpd_power_off()
539 if (!genpd->gov->power_down_ok(&genpd->domain)) in genpd_power_off()
540 return -EAGAIN; in genpd_power_off()
544 if (!genpd->gov) in genpd_power_off()
545 genpd->state_idx = 0; in genpd_power_off()
547 if (genpd->power_off) { in genpd_power_off()
550 if (atomic_read(&genpd->sd_count) > 0) in genpd_power_off()
551 return -EBUSY; in genpd_power_off()
566 genpd->status = GPD_STATE_POWER_OFF; in genpd_power_off()
569 list_for_each_entry(link, &genpd->slave_links, slave_node) { in genpd_power_off()
570 genpd_sd_counter_dec(link->master); in genpd_power_off()
571 genpd_lock_nested(link->master, depth + 1); in genpd_power_off()
572 genpd_power_off(link->master, false, depth + 1); in genpd_power_off()
573 genpd_unlock(link->master); in genpd_power_off()
580 * genpd_power_on - Restore power to a given PM domain and its masters.
600 list_for_each_entry(link, &genpd->slave_links, slave_node) { in genpd_power_on()
601 struct generic_pm_domain *master = link->master; in genpd_power_on()
619 genpd->status = GPD_STATE_ACTIVE; in genpd_power_on()
626 &genpd->slave_links, in genpd_power_on()
628 genpd_sd_counter_dec(link->master); in genpd_power_on()
629 genpd_lock_nested(link->master, depth + 1); in genpd_power_on()
630 genpd_power_off(link->master, false, depth + 1); in genpd_power_on()
631 genpd_unlock(link->master); in genpd_power_on()
644 dev = gpd_data->base.dev; in genpd_dev_pm_qos_notifier()
650 spin_lock_irq(&dev->power.lock); in genpd_dev_pm_qos_notifier()
652 pdd = dev->power.subsys_data ? in genpd_dev_pm_qos_notifier()
653 dev->power.subsys_data->domain_data : NULL; in genpd_dev_pm_qos_notifier()
655 to_gpd_data(pdd)->td.constraint_changed = true; in genpd_dev_pm_qos_notifier()
658 genpd = ERR_PTR(-ENODATA); in genpd_dev_pm_qos_notifier()
661 spin_unlock_irq(&dev->power.lock); in genpd_dev_pm_qos_notifier()
665 genpd->max_off_time_changed = true; in genpd_dev_pm_qos_notifier()
669 dev = dev->parent; in genpd_dev_pm_qos_notifier()
670 if (!dev || dev->power.ignore_children) in genpd_dev_pm_qos_notifier()
678 * genpd_power_off_work_fn - Power off PM domain whose subdomain count is 0.
693 * __genpd_runtime_suspend - walk the hierarchy of ->runtime_suspend() callbacks
700 if (dev->type && dev->type->pm) in __genpd_runtime_suspend()
701 cb = dev->type->pm->runtime_suspend; in __genpd_runtime_suspend()
702 else if (dev->class && dev->class->pm) in __genpd_runtime_suspend()
703 cb = dev->class->pm->runtime_suspend; in __genpd_runtime_suspend()
704 else if (dev->bus && dev->bus->pm) in __genpd_runtime_suspend()
705 cb = dev->bus->pm->runtime_suspend; in __genpd_runtime_suspend()
709 if (!cb && dev->driver && dev->driver->pm) in __genpd_runtime_suspend()
710 cb = dev->driver->pm->runtime_suspend; in __genpd_runtime_suspend()
716 * __genpd_runtime_resume - walk the hierarchy of ->runtime_resume() callbacks
723 if (dev->type && dev->type->pm) in __genpd_runtime_resume()
724 cb = dev->type->pm->runtime_resume; in __genpd_runtime_resume()
725 else if (dev->class && dev->class->pm) in __genpd_runtime_resume()
726 cb = dev->class->pm->runtime_resume; in __genpd_runtime_resume()
727 else if (dev->bus && dev->bus->pm) in __genpd_runtime_resume()
728 cb = dev->bus->pm->runtime_resume; in __genpd_runtime_resume()
732 if (!cb && dev->driver && dev->driver->pm) in __genpd_runtime_resume()
733 cb = dev->driver->pm->runtime_resume; in __genpd_runtime_resume()
739 * genpd_runtime_suspend - Suspend a device belonging to I/O PM domain.
750 struct gpd_timing_data *td = &dev_gpd_data(dev)->td; in genpd_runtime_suspend()
760 return -EINVAL; in genpd_runtime_suspend()
763 * A runtime PM centric subsystem/driver may re-use the runtime PM in genpd_runtime_suspend()
768 suspend_ok = genpd->gov ? genpd->gov->suspend_ok : NULL; in genpd_runtime_suspend()
770 return -EBUSY; in genpd_runtime_suspend()
790 if (elapsed_ns > td->suspend_latency_ns) { in genpd_runtime_suspend()
791 td->suspend_latency_ns = elapsed_ns; in genpd_runtime_suspend()
794 genpd->max_off_time_changed = true; in genpd_runtime_suspend()
795 td->constraint_changed = true; in genpd_runtime_suspend()
814 * genpd_runtime_resume - Resume a device belonging to I/O PM domain.
824 struct gpd_timing_data *td = &dev_gpd_data(dev)->td; in genpd_runtime_resume()
835 return -EINVAL; in genpd_runtime_resume()
870 if (elapsed_ns > td->resume_latency_ns) { in genpd_runtime_resume()
871 td->resume_latency_ns = elapsed_ns; in genpd_runtime_resume()
874 genpd->max_off_time_changed = true; in genpd_runtime_resume()
875 td->constraint_changed = true; in genpd_runtime_resume()
903 * genpd_power_off_unused - Power off all PM domains with no devices in use.
946 * genpd_sync_power_off - Synchronously power off a PM domain and its masters.
966 if (genpd->suspended_count != genpd->device_count in genpd_sync_power_off()
967 || atomic_read(&genpd->sd_count) > 0) in genpd_sync_power_off()
971 genpd->state_idx = genpd->state_count - 1; in genpd_sync_power_off()
975 genpd->status = GPD_STATE_POWER_OFF; in genpd_sync_power_off()
977 list_for_each_entry(link, &genpd->slave_links, slave_node) { in genpd_sync_power_off()
978 genpd_sd_counter_dec(link->master); in genpd_sync_power_off()
981 genpd_lock_nested(link->master, depth + 1); in genpd_sync_power_off()
983 genpd_sync_power_off(link->master, use_lock, depth + 1); in genpd_sync_power_off()
986 genpd_unlock(link->master); in genpd_sync_power_off()
991 * genpd_sync_power_on - Synchronously power on a PM domain and its masters.
1008 list_for_each_entry(link, &genpd->slave_links, slave_node) { in genpd_sync_power_on()
1009 genpd_sd_counter_inc(link->master); in genpd_sync_power_on()
1012 genpd_lock_nested(link->master, depth + 1); in genpd_sync_power_on()
1014 genpd_sync_power_on(link->master, use_lock, depth + 1); in genpd_sync_power_on()
1017 genpd_unlock(link->master); in genpd_sync_power_on()
1022 genpd->status = GPD_STATE_ACTIVE; in genpd_sync_power_on()
1026 * resume_needed - Check whether to resume a device before system suspend.
1054 * genpd_prepare - Start power transition of a device in a PM domain.
1057 * Start a power transition of a device (during a system-wide power transition)
1071 return -EINVAL; in genpd_prepare()
1083 if (genpd->prepared_count++ == 0) in genpd_prepare()
1084 genpd->suspended_count = 0; in genpd_prepare()
1092 genpd->prepared_count--; in genpd_prepare()
1102 * genpd_finish_suspend - Completion of suspend or hibernation of device in an
1117 return -EINVAL; in genpd_finish_suspend()
1126 if (dev->power.wakeup_path && genpd_is_active_wakeup(genpd)) in genpd_finish_suspend()
1129 if (genpd->dev_ops.stop && genpd->dev_ops.start && in genpd_finish_suspend()
1142 genpd->suspended_count++; in genpd_finish_suspend()
1150 * genpd_suspend_noirq - Completion of suspend of device in an I/O PM domain.
1164 * genpd_resume_noirq - Start of resume of device in an I/O PM domain.
1178 return -EINVAL; in genpd_resume_noirq()
1180 if (dev->power.wakeup_path && genpd_is_active_wakeup(genpd)) in genpd_resume_noirq()
1185 genpd->suspended_count--; in genpd_resume_noirq()
1188 if (genpd->dev_ops.stop && genpd->dev_ops.start && in genpd_resume_noirq()
1199 * genpd_freeze_noirq - Completion of freezing a device in an I/O PM domain.
1216 return -EINVAL; in genpd_freeze_noirq()
1222 if (genpd->dev_ops.stop && genpd->dev_ops.start && in genpd_freeze_noirq()
1230 * genpd_thaw_noirq - Early thaw of device in an I/O PM domain.
1245 return -EINVAL; in genpd_thaw_noirq()
1247 if (genpd->dev_ops.stop && genpd->dev_ops.start && in genpd_thaw_noirq()
1258 * genpd_poweroff_noirq - Completion of hibernation of device in an
1273 * genpd_restore_noirq - Start of restore of device in an I/O PM domain.
1288 return -EINVAL; in genpd_restore_noirq()
1295 if (genpd->suspended_count++ == 0) in genpd_restore_noirq()
1301 genpd->status = GPD_STATE_POWER_OFF; in genpd_restore_noirq()
1306 if (genpd->dev_ops.stop && genpd->dev_ops.start && in genpd_restore_noirq()
1317 * genpd_complete - Complete power transition of a device in a power domain.
1320 * Complete a power transition of a device (during a system-wide power
1339 genpd->prepared_count--; in genpd_complete()
1340 if (!genpd->prepared_count) in genpd_complete()
1347 * genpd_syscore_switch - Switch power during system core suspend or resume.
1362 genpd->suspended_count++; in genpd_syscore_switch()
1366 genpd->suspended_count--; in genpd_syscore_switch()
1406 ret = -ENOMEM; in genpd_alloc_dev_data()
1410 gpd_data->base.dev = dev; in genpd_alloc_dev_data()
1411 gpd_data->td.constraint_changed = true; in genpd_alloc_dev_data()
1412 gpd_data->td.effective_constraint_ns = PM_QOS_RESUME_LATENCY_NO_CONSTRAINT_NS; in genpd_alloc_dev_data()
1413 gpd_data->nb.notifier_call = genpd_dev_pm_qos_notifier; in genpd_alloc_dev_data()
1415 spin_lock_irq(&dev->power.lock); in genpd_alloc_dev_data()
1417 if (dev->power.subsys_data->domain_data) { in genpd_alloc_dev_data()
1418 ret = -EINVAL; in genpd_alloc_dev_data()
1422 dev->power.subsys_data->domain_data = &gpd_data->base; in genpd_alloc_dev_data()
1424 spin_unlock_irq(&dev->power.lock); in genpd_alloc_dev_data()
1429 spin_unlock_irq(&dev->power.lock); in genpd_alloc_dev_data()
1439 spin_lock_irq(&dev->power.lock); in genpd_free_dev_data()
1441 dev->power.subsys_data->domain_data = NULL; in genpd_free_dev_data()
1443 spin_unlock_irq(&dev->power.lock); in genpd_free_dev_data()
1450 int cpu, bool set, unsigned int depth) in genpd_update_cpumask() argument
1457 list_for_each_entry(link, &genpd->slave_links, slave_node) { in genpd_update_cpumask()
1458 struct generic_pm_domain *master = link->master; in genpd_update_cpumask()
1461 genpd_update_cpumask(master, cpu, set, depth + 1); in genpd_update_cpumask()
1466 cpumask_set_cpu(cpu, genpd->cpus); in genpd_update_cpumask()
1468 cpumask_clear_cpu(cpu, genpd->cpus); in genpd_update_cpumask()
1471 static void genpd_set_cpumask(struct generic_pm_domain *genpd, int cpu) in genpd_set_cpumask() argument
1473 if (cpu >= 0) in genpd_set_cpumask()
1474 genpd_update_cpumask(genpd, cpu, true, 0); in genpd_set_cpumask()
1477 static void genpd_clear_cpumask(struct generic_pm_domain *genpd, int cpu) in genpd_clear_cpumask() argument
1479 if (cpu >= 0) in genpd_clear_cpumask()
1480 genpd_update_cpumask(genpd, cpu, false, 0); in genpd_clear_cpumask()
1485 int cpu; in genpd_get_cpu() local
1488 return -1; in genpd_get_cpu()
1490 for_each_possible_cpu(cpu) { in genpd_get_cpu()
1491 if (get_cpu_device(cpu) == dev) in genpd_get_cpu()
1492 return cpu; in genpd_get_cpu()
1495 return -1; in genpd_get_cpu()
1507 return -EINVAL; in genpd_add_device()
1513 gpd_data->cpu = genpd_get_cpu(genpd, base_dev); in genpd_add_device()
1515 ret = genpd->attach_dev ? genpd->attach_dev(genpd, dev) : 0; in genpd_add_device()
1521 genpd_set_cpumask(genpd, gpd_data->cpu); in genpd_add_device()
1522 dev_pm_domain_set(dev, &genpd->domain); in genpd_add_device()
1524 genpd->device_count++; in genpd_add_device()
1525 genpd->max_off_time_changed = true; in genpd_add_device()
1527 list_add_tail(&gpd_data->base.list_node, &genpd->dev_list); in genpd_add_device()
1534 dev_pm_qos_add_notifier(dev, &gpd_data->nb, in genpd_add_device()
1541 * pm_genpd_add_device - Add a device to an I/O PM domain.
1566 pdd = dev->power.subsys_data->domain_data; in genpd_remove_device()
1568 dev_pm_qos_remove_notifier(dev, &gpd_data->nb, in genpd_remove_device()
1573 if (genpd->prepared_count > 0) { in genpd_remove_device()
1574 ret = -EAGAIN; in genpd_remove_device()
1578 genpd->device_count--; in genpd_remove_device()
1579 genpd->max_off_time_changed = true; in genpd_remove_device()
1581 genpd_clear_cpumask(genpd, gpd_data->cpu); in genpd_remove_device()
1584 list_del_init(&pdd->list_node); in genpd_remove_device()
1588 if (genpd->detach_dev) in genpd_remove_device()
1589 genpd->detach_dev(genpd, dev); in genpd_remove_device()
1597 dev_pm_qos_add_notifier(dev, &gpd_data->nb, DEV_PM_QOS_RESUME_LATENCY); in genpd_remove_device()
1603 * pm_genpd_remove_device - Remove a device from an I/O PM domain.
1611 return -EINVAL; in pm_genpd_remove_device()
1625 return -EINVAL; in genpd_add_subdomain()
1634 genpd->name, subdomain->name); in genpd_add_subdomain()
1635 return -EINVAL; in genpd_add_subdomain()
1640 return -ENOMEM; in genpd_add_subdomain()
1646 ret = -EINVAL; in genpd_add_subdomain()
1650 list_for_each_entry(itr, &genpd->master_links, master_node) { in genpd_add_subdomain()
1651 if (itr->slave == subdomain && itr->master == genpd) { in genpd_add_subdomain()
1652 ret = -EINVAL; in genpd_add_subdomain()
1657 link->master = genpd; in genpd_add_subdomain()
1658 list_add_tail(&link->master_node, &genpd->master_links); in genpd_add_subdomain()
1659 link->slave = subdomain; in genpd_add_subdomain()
1660 list_add_tail(&link->slave_node, &subdomain->slave_links); in genpd_add_subdomain()
1673 * pm_genpd_add_subdomain - Add a subdomain to an I/O PM domain.
1691 * pm_genpd_remove_subdomain - Remove a subdomain from an I/O PM domain.
1699 int ret = -EINVAL; in pm_genpd_remove_subdomain()
1702 return -EINVAL; in pm_genpd_remove_subdomain()
1707 if (!list_empty(&subdomain->master_links) || subdomain->device_count) { in pm_genpd_remove_subdomain()
1709 genpd->name, subdomain->name); in pm_genpd_remove_subdomain()
1710 ret = -EBUSY; in pm_genpd_remove_subdomain()
1714 list_for_each_entry_safe(link, l, &genpd->master_links, master_node) { in pm_genpd_remove_subdomain()
1715 if (link->slave != subdomain) in pm_genpd_remove_subdomain()
1718 list_del(&link->master_node); in pm_genpd_remove_subdomain()
1719 list_del(&link->slave_node); in pm_genpd_remove_subdomain()
1748 return -ENOMEM; in genpd_set_default_power_state()
1750 genpd->states = state; in genpd_set_default_power_state()
1751 genpd->state_count = 1; in genpd_set_default_power_state()
1752 genpd->free_states = genpd_free_default_power_state; in genpd_set_default_power_state()
1759 if (genpd->flags & GENPD_FLAG_IRQ_SAFE) { in genpd_lock_init()
1760 spin_lock_init(&genpd->slock); in genpd_lock_init()
1761 genpd->lock_ops = &genpd_spin_ops; in genpd_lock_init()
1763 mutex_init(&genpd->mlock); in genpd_lock_init()
1764 genpd->lock_ops = &genpd_mtx_ops; in genpd_lock_init()
1769 * pm_genpd_init - Initialize a generic I/O PM domain object.
1782 return -EINVAL; in pm_genpd_init()
1784 INIT_LIST_HEAD(&genpd->master_links); in pm_genpd_init()
1785 INIT_LIST_HEAD(&genpd->slave_links); in pm_genpd_init()
1786 INIT_LIST_HEAD(&genpd->dev_list); in pm_genpd_init()
1788 genpd->gov = gov; in pm_genpd_init()
1789 INIT_WORK(&genpd->power_off_work, genpd_power_off_work_fn); in pm_genpd_init()
1790 atomic_set(&genpd->sd_count, 0); in pm_genpd_init()
1791 genpd->status = is_off ? GPD_STATE_POWER_OFF : GPD_STATE_ACTIVE; in pm_genpd_init()
1792 genpd->device_count = 0; in pm_genpd_init()
1793 genpd->max_off_time_ns = -1; in pm_genpd_init()
1794 genpd->max_off_time_changed = true; in pm_genpd_init()
1795 genpd->provider = NULL; in pm_genpd_init()
1796 genpd->has_provider = false; in pm_genpd_init()
1797 genpd->accounting_time = ktime_get(); in pm_genpd_init()
1798 genpd->domain.ops.runtime_suspend = genpd_runtime_suspend; in pm_genpd_init()
1799 genpd->domain.ops.runtime_resume = genpd_runtime_resume; in pm_genpd_init()
1800 genpd->domain.ops.prepare = genpd_prepare; in pm_genpd_init()
1801 genpd->domain.ops.suspend_noirq = genpd_suspend_noirq; in pm_genpd_init()
1802 genpd->domain.ops.resume_noirq = genpd_resume_noirq; in pm_genpd_init()
1803 genpd->domain.ops.freeze_noirq = genpd_freeze_noirq; in pm_genpd_init()
1804 genpd->domain.ops.thaw_noirq = genpd_thaw_noirq; in pm_genpd_init()
1805 genpd->domain.ops.poweroff_noirq = genpd_poweroff_noirq; in pm_genpd_init()
1806 genpd->domain.ops.restore_noirq = genpd_restore_noirq; in pm_genpd_init()
1807 genpd->domain.ops.complete = genpd_complete; in pm_genpd_init()
1809 if (genpd->flags & GENPD_FLAG_PM_CLK) { in pm_genpd_init()
1810 genpd->dev_ops.stop = pm_clk_suspend; in pm_genpd_init()
1811 genpd->dev_ops.start = pm_clk_resume; in pm_genpd_init()
1814 /* Always-on domains must be powered on at initialization. */ in pm_genpd_init()
1817 return -EINVAL; in pm_genpd_init()
1820 !zalloc_cpumask_var(&genpd->cpus, GFP_KERNEL)) in pm_genpd_init()
1821 return -ENOMEM; in pm_genpd_init()
1824 if (genpd->state_count == 0) { in pm_genpd_init()
1828 free_cpumask_var(genpd->cpus); in pm_genpd_init()
1831 } else if (!gov && genpd->state_count > 1) { in pm_genpd_init()
1832 pr_warn("%s: no governor for states\n", genpd->name); in pm_genpd_init()
1835 device_initialize(&genpd->dev); in pm_genpd_init()
1836 dev_set_name(&genpd->dev, "%s", genpd->name); in pm_genpd_init()
1839 list_add(&genpd->gpd_list_node, &gpd_list); in pm_genpd_init()
1851 return -EINVAL; in genpd_remove()
1855 if (genpd->has_provider) { in genpd_remove()
1857 pr_err("Provider present, unable to remove %s\n", genpd->name); in genpd_remove()
1858 return -EBUSY; in genpd_remove()
1861 if (!list_empty(&genpd->master_links) || genpd->device_count) { in genpd_remove()
1863 pr_err("%s: unable to remove %s\n", __func__, genpd->name); in genpd_remove()
1864 return -EBUSY; in genpd_remove()
1867 list_for_each_entry_safe(link, l, &genpd->slave_links, slave_node) { in genpd_remove()
1868 list_del(&link->master_node); in genpd_remove()
1869 list_del(&link->slave_node); in genpd_remove()
1873 list_del(&genpd->gpd_list_node); in genpd_remove()
1875 cancel_work_sync(&genpd->power_off_work); in genpd_remove()
1877 free_cpumask_var(genpd->cpus); in genpd_remove()
1878 if (genpd->free_states) in genpd_remove()
1879 genpd->free_states(genpd->states, genpd->state_count); in genpd_remove()
1881 pr_debug("%s: removed %s\n", __func__, genpd->name); in genpd_remove()
1887 * pm_genpd_remove - Remove a generic I/O PM domain
1891 * - Removes the PM domain as a subdomain to any parent domains,
1893 * - Removes the PM domain from the list of registered PM domains.
1924 * - genpd_xlate_simple() for 1:1 device tree node to PM domain mapping.
1925 * - genpd_xlate_onecell() for mapping of multiple PM domains per node by
1930 * struct of_genpd_provider - PM domain provider registration structure
1933 * @xlate: Provider-specific xlate callback mapping a set of specifier cells
1950 * genpd_xlate_simple() - Xlate function for direct node-domain mapping
1952 * @data: xlate function private data - pointer to struct generic_pm_domain
1966 * genpd_xlate_onecell() - Xlate function using a single index.
1968 * @data: xlate function private data - pointer to struct genpd_onecell_data
1980 unsigned int idx = genpdspec->args[0]; in genpd_xlate_onecell()
1982 if (genpdspec->args_count != 1) in genpd_xlate_onecell()
1983 return ERR_PTR(-EINVAL); in genpd_xlate_onecell()
1985 if (idx >= genpd_data->num_domains) { in genpd_xlate_onecell()
1987 return ERR_PTR(-EINVAL); in genpd_xlate_onecell()
1990 if (!genpd_data->domains[idx]) in genpd_xlate_onecell()
1991 return ERR_PTR(-ENOENT); in genpd_xlate_onecell()
1993 return genpd_data->domains[idx]; in genpd_xlate_onecell()
1997 * genpd_add_provider() - Register a PM domain provider for a node
2009 return -ENOMEM; in genpd_add_provider()
2011 cp->node = of_node_get(np); in genpd_add_provider()
2012 cp->data = data; in genpd_add_provider()
2013 cp->xlate = xlate; in genpd_add_provider()
2016 list_add(&cp->link, &of_genpd_providers); in genpd_add_provider()
2024 * of_genpd_add_provider_simple() - Register a simple PM domain provider
2031 int ret = -EINVAL; in of_genpd_add_provider_simple()
2034 return -EINVAL; in of_genpd_add_provider_simple()
2041 genpd->dev.of_node = np; in of_genpd_add_provider_simple()
2044 if (genpd->set_performance_state) { in of_genpd_add_provider_simple()
2045 ret = dev_pm_opp_of_add_table(&genpd->dev); in of_genpd_add_provider_simple()
2047 dev_err(&genpd->dev, "Failed to add OPP table: %d\n", in of_genpd_add_provider_simple()
2056 genpd->opp_table = dev_pm_opp_get_opp_table(&genpd->dev); in of_genpd_add_provider_simple()
2057 WARN_ON(!genpd->opp_table); in of_genpd_add_provider_simple()
2062 if (genpd->set_performance_state) { in of_genpd_add_provider_simple()
2063 dev_pm_opp_put_opp_table(genpd->opp_table); in of_genpd_add_provider_simple()
2064 dev_pm_opp_of_remove_table(&genpd->dev); in of_genpd_add_provider_simple()
2070 genpd->provider = &np->fwnode; in of_genpd_add_provider_simple()
2071 genpd->has_provider = true; in of_genpd_add_provider_simple()
2081 * of_genpd_add_provider_onecell() - Register a onecell PM domain provider
2090 int ret = -EINVAL; in of_genpd_add_provider_onecell()
2093 return -EINVAL; in of_genpd_add_provider_onecell()
2097 if (!data->xlate) in of_genpd_add_provider_onecell()
2098 data->xlate = genpd_xlate_onecell; in of_genpd_add_provider_onecell()
2100 for (i = 0; i < data->num_domains; i++) { in of_genpd_add_provider_onecell()
2101 genpd = data->domains[i]; in of_genpd_add_provider_onecell()
2108 genpd->dev.of_node = np; in of_genpd_add_provider_onecell()
2111 if (genpd->set_performance_state) { in of_genpd_add_provider_onecell()
2112 ret = dev_pm_opp_of_add_table_indexed(&genpd->dev, i); in of_genpd_add_provider_onecell()
2114 dev_err(&genpd->dev, "Failed to add OPP table for index %d: %d\n", in of_genpd_add_provider_onecell()
2123 genpd->opp_table = dev_pm_opp_get_opp_table_indexed(&genpd->dev, i); in of_genpd_add_provider_onecell()
2124 WARN_ON(!genpd->opp_table); in of_genpd_add_provider_onecell()
2127 genpd->provider = &np->fwnode; in of_genpd_add_provider_onecell()
2128 genpd->has_provider = true; in of_genpd_add_provider_onecell()
2131 ret = genpd_add_provider(np, data->xlate, data); in of_genpd_add_provider_onecell()
2140 while (i--) { in of_genpd_add_provider_onecell()
2141 genpd = data->domains[i]; in of_genpd_add_provider_onecell()
2146 genpd->provider = NULL; in of_genpd_add_provider_onecell()
2147 genpd->has_provider = false; in of_genpd_add_provider_onecell()
2149 if (genpd->set_performance_state) { in of_genpd_add_provider_onecell()
2150 dev_pm_opp_put_opp_table(genpd->opp_table); in of_genpd_add_provider_onecell()
2151 dev_pm_opp_of_remove_table(&genpd->dev); in of_genpd_add_provider_onecell()
2162 * of_genpd_del_provider() - Remove a previously registered PM domain provider
2173 if (cp->node == np) { in of_genpd_del_provider()
2180 if (gpd->provider == &np->fwnode) { in of_genpd_del_provider()
2181 gpd->has_provider = false; in of_genpd_del_provider()
2183 if (!gpd->set_performance_state) in of_genpd_del_provider()
2186 dev_pm_opp_put_opp_table(gpd->opp_table); in of_genpd_del_provider()
2187 dev_pm_opp_of_remove_table(&gpd->dev); in of_genpd_del_provider()
2191 list_del(&cp->link); in of_genpd_del_provider()
2192 of_node_put(cp->node); in of_genpd_del_provider()
2203 * genpd_get_from_provider() - Look-up PM domain
2204 * @genpdspec: OF phandle args to use for look-up
2216 struct generic_pm_domain *genpd = ERR_PTR(-ENOENT); in genpd_get_from_provider()
2220 return ERR_PTR(-EINVAL); in genpd_get_from_provider()
2226 if (provider->node == genpdspec->np) in genpd_get_from_provider()
2227 genpd = provider->xlate(genpdspec, provider->data); in genpd_get_from_provider()
2238 * of_genpd_add_device() - Add a device to an I/O PM domain
2239 * @genpdspec: OF phandle args to use for look-up PM domain
2242 * Looks-up an I/O PM domain based upon phandle args provided and adds
2268 * of_genpd_add_subdomain - Add a subdomain to an I/O PM domain.
2269 * @parent_spec: OF phandle args to use for parent PM domain look-up
2270 * @subdomain_spec: OF phandle args to use for subdomain look-up
2272 * Looks-up a parent PM domain and subdomain based upon phandle args
2306 * of_genpd_remove_last - Remove the last PM domain registered for a provider
2320 struct generic_pm_domain *gpd, *tmp, *genpd = ERR_PTR(-ENOENT); in of_genpd_remove_last()
2324 return ERR_PTR(-EINVAL); in of_genpd_remove_last()
2328 if (gpd->provider == &np->fwnode) { in of_genpd_remove_last()
2342 of_node_put(dev->of_node); in genpd_release_dev()
2351 * genpd_dev_pm_detach - Detach a device from its PM domain.
2368 dev_dbg(dev, "removing from PM domain %s\n", pd->name); in genpd_dev_pm_detach()
2372 if (ret != -EAGAIN) in genpd_dev_pm_detach()
2381 pd->name, ret); in genpd_dev_pm_detach()
2389 if (dev->bus == &genpd_bus_type) in genpd_dev_pm_detach()
2411 ret = of_parse_phandle_with_args(dev->of_node, "power-domains", in __genpd_dev_pm_attach()
2412 "#power-domain-cells", index, &pd_args); in __genpd_dev_pm_attach()
2426 dev_dbg(dev, "adding to PM domain %s\n", pd->name); in __genpd_dev_pm_attach()
2432 if (ret != -EPROBE_DEFER) in __genpd_dev_pm_attach()
2434 pd->name, ret); in __genpd_dev_pm_attach()
2438 dev->pm_domain->detach = genpd_dev_pm_detach; in __genpd_dev_pm_attach()
2439 dev->pm_domain->sync = genpd_dev_pm_sync; in __genpd_dev_pm_attach()
2450 return ret ? -EPROBE_DEFER : 1; in __genpd_dev_pm_attach()
2454 * genpd_dev_pm_attach - Attach a device to its PM domain using DT.
2461 * PM domain or when multiple power-domains exists for it, else a negative error
2462 * code. Note that if a power-domain exists for the device, but it cannot be
2463 * found or turned on, then return -EPROBE_DEFER to ensure that the device is
2464 * not probed and to re-try again later.
2468 if (!dev->of_node) in genpd_dev_pm_attach()
2475 if (of_count_phandle_with_args(dev->of_node, "power-domains", in genpd_dev_pm_attach()
2476 "#power-domain-cells") != 1) in genpd_dev_pm_attach()
2484 * genpd_dev_pm_attach_by_id - Associate a device with one of its PM domains.
2490 * pm_domain ops. To deal with detaching of the virtual device, the ->detach()
2495 * failures. If a power-domain exists for the device, but cannot be found or
2496 * turned on, then ERR_PTR(-EPROBE_DEFER) is returned to ensure that the device
2497 * is not probed and to re-try again later.
2506 if (!dev->of_node) in genpd_dev_pm_attach_by_id()
2510 num_domains = of_count_phandle_with_args(dev->of_node, "power-domains", in genpd_dev_pm_attach_by_id()
2511 "#power-domain-cells"); in genpd_dev_pm_attach_by_id()
2518 return ERR_PTR(-ENOMEM); in genpd_dev_pm_attach_by_id()
2521 virt_dev->bus = &genpd_bus_type; in genpd_dev_pm_attach_by_id()
2522 virt_dev->release = genpd_release_dev; in genpd_dev_pm_attach_by_id()
2523 virt_dev->of_node = of_node_get(dev->of_node); in genpd_dev_pm_attach_by_id()
2546 * genpd_dev_pm_attach_by_name - Associate a device with one of its PM domains.
2551 * power-domain-names DT property. For further description see
2558 if (!dev->of_node) in genpd_dev_pm_attach_by_name()
2561 index = of_property_match_string(dev->of_node, "power-domain-names", in genpd_dev_pm_attach_by_name()
2570 { .compatible = "domain-idle-state", },
2581 err = of_property_read_u32(state_node, "entry-latency-us", in genpd_parse_state()
2584 pr_debug(" * %pOF missing entry-latency-us property\n", in genpd_parse_state()
2586 return -EINVAL; in genpd_parse_state()
2589 err = of_property_read_u32(state_node, "exit-latency-us", in genpd_parse_state()
2592 pr_debug(" * %pOF missing exit-latency-us property\n", in genpd_parse_state()
2594 return -EINVAL; in genpd_parse_state()
2597 err = of_property_read_u32(state_node, "min-residency-us", &residency); in genpd_parse_state()
2599 genpd_state->residency_ns = 1000 * residency; in genpd_parse_state()
2601 genpd_state->power_on_latency_ns = 1000 * exit_latency; in genpd_parse_state()
2602 genpd_state->power_off_latency_ns = 1000 * entry_latency; in genpd_parse_state()
2603 genpd_state->fwnode = &state_node->fwnode; in genpd_parse_state()
2616 ret = of_count_phandle_with_args(dn, "domain-idle-states", NULL); in genpd_iterate_idle_states()
2621 of_for_each_phandle(&it, ret, dn, "domain-idle-states", NULL, 0) { in genpd_iterate_idle_states()
2670 return -ENOMEM; in of_genpd_parse_idle_states()
2675 return ret < 0 ? ret : -EINVAL; in of_genpd_parse_idle_states()
2686 * pm_genpd_opp_to_performance_state - Gets performance state of the genpd from its OPP node.
2688 * @genpd_dev: Genpd's device for which the performance-state needs to be found.
2693 * platform specific genpd->opp_to_performance_state() callback to translate
2706 if (unlikely(!genpd->opp_to_performance_state)) in pm_genpd_opp_to_performance_state()
2710 state = genpd->opp_to_performance_state(genpd, opp); in pm_genpd_opp_to_performance_state()
2751 if (dev->power.runtime_error) in rtpm_status_str()
2753 else if (dev->power.disable_depth) in rtpm_status_str()
2755 else if (dev->power.runtime_status < ARRAY_SIZE(status_lookup)) in rtpm_status_str()
2756 p = status_lookup[dev->power.runtime_status]; in rtpm_status_str()
2778 return -ERESTARTSYS; in genpd_summary_one()
2780 if (WARN_ON(genpd->status >= ARRAY_SIZE(status_lookup))) in genpd_summary_one()
2783 snprintf(state, sizeof(state), "%s-%u", in genpd_summary_one()
2784 status_lookup[genpd->status], genpd->state_idx); in genpd_summary_one()
2787 status_lookup[genpd->status]); in genpd_summary_one()
2788 seq_printf(s, "%-30s %-15s ", genpd->name, state); in genpd_summary_one()
2793 * Also genpd->name is immutable. in genpd_summary_one()
2795 list_for_each_entry(link, &genpd->master_links, master_node) { in genpd_summary_one()
2796 seq_printf(s, "%s", link->slave->name); in genpd_summary_one()
2797 if (!list_is_last(&link->master_node, &genpd->master_links)) in genpd_summary_one()
2801 list_for_each_entry(pm_data, &genpd->dev_list, list_node) { in genpd_summary_one()
2802 kobj_path = kobject_get_path(&pm_data->dev->kobj, in genpd_summary_one()
2808 seq_printf(s, "\n %-50s ", kobj_path); in genpd_summary_one()
2809 rtpm_status_str(s, pm_data->dev); in genpd_summary_one()
2827 seq_puts(s, "----------------------------------------------------------------------\n"); in summary_show()
2831 return -ERESTARTSYS; in summary_show()
2850 struct generic_pm_domain *genpd = s->private; in status_show()
2855 return -ERESTARTSYS; in status_show()
2857 if (WARN_ON_ONCE(genpd->status >= ARRAY_SIZE(status_lookup))) in status_show()
2860 if (genpd->status == GPD_STATE_POWER_OFF) in status_show()
2861 seq_printf(s, "%s-%u\n", status_lookup[genpd->status], in status_show()
2862 genpd->state_idx); in status_show()
2864 seq_printf(s, "%s\n", status_lookup[genpd->status]); in status_show()
2872 struct generic_pm_domain *genpd = s->private; in sub_domains_show()
2878 return -ERESTARTSYS; in sub_domains_show()
2880 list_for_each_entry(link, &genpd->master_links, master_node) in sub_domains_show()
2881 seq_printf(s, "%s\n", link->slave->name); in sub_domains_show()
2889 struct generic_pm_domain *genpd = s->private; in idle_states_show()
2895 return -ERESTARTSYS; in idle_states_show()
2899 for (i = 0; i < genpd->state_count; i++) { in idle_states_show()
2903 if ((genpd->status == GPD_STATE_POWER_OFF) && in idle_states_show()
2904 (genpd->state_idx == i)) in idle_states_show()
2905 delta = ktime_sub(ktime_get(), genpd->accounting_time); in idle_states_show()
2908 ktime_add(genpd->states[i].idle_time, delta)); in idle_states_show()
2909 seq_printf(s, "S%-13i %lld\n", i, msecs); in idle_states_show()
2918 struct generic_pm_domain *genpd = s->private; in active_time_show()
2924 return -ERESTARTSYS; in active_time_show()
2926 if (genpd->status == GPD_STATE_ACTIVE) in active_time_show()
2927 delta = ktime_sub(ktime_get(), genpd->accounting_time); in active_time_show()
2930 ktime_add(genpd->on_time, delta))); in active_time_show()
2938 struct generic_pm_domain *genpd = s->private; in total_idle_time_show()
2945 return -ERESTARTSYS; in total_idle_time_show()
2947 for (i = 0; i < genpd->state_count; i++) { in total_idle_time_show()
2949 if ((genpd->status == GPD_STATE_POWER_OFF) && in total_idle_time_show()
2950 (genpd->state_idx == i)) in total_idle_time_show()
2951 delta = ktime_sub(ktime_get(), genpd->accounting_time); in total_idle_time_show()
2953 total = ktime_add(total, genpd->states[i].idle_time); in total_idle_time_show()
2966 struct generic_pm_domain *genpd = s->private; in devices_show()
2973 return -ERESTARTSYS; in devices_show()
2975 list_for_each_entry(pm_data, &genpd->dev_list, list_node) { in devices_show()
2976 kobj_path = kobject_get_path(&pm_data->dev->kobj, in devices_show()
2992 struct generic_pm_domain *genpd = s->private; in perf_state_show()
2995 return -ERESTARTSYS; in perf_state_show()
2997 seq_printf(s, "%u\n", genpd->performance_state); in perf_state_show()
3023 d = debugfs_create_dir(genpd->name, genpd_debugfs_dir); in genpd_debug_init()
3037 if (genpd->set_performance_state) in genpd_debug_init()