Lines Matching +full:power +full:- +full:power +full:- +full:management

1 // SPDX-License-Identifier: GPL-2.0
3 * drivers/base/power/clock_ops.c - Generic clock manipulation PM callbacks
40 * pm_clk_list_lock - ensure exclusive access for modifying the PM clock
53 __acquires(&psd->lock) in pm_clk_list_lock()
55 mutex_lock(&psd->clock_mutex); in pm_clk_list_lock()
56 spin_lock_irq(&psd->lock); in pm_clk_list_lock()
60 * pm_clk_list_unlock - counterpart to pm_clk_list_lock().
65 __releases(&psd->lock) in pm_clk_list_unlock()
67 spin_unlock_irq(&psd->lock); in pm_clk_list_unlock()
68 mutex_unlock(&psd->clock_mutex); in pm_clk_list_unlock()
72 * pm_clk_op_lock - ensure exclusive access for performing clock operations.
84 * Returns -EINVAL if called in atomic context when clock ops might sleep.
93 spin_lock_irqsave(&psd->lock, *flags); in pm_clk_op_lock()
94 if (!psd->clock_op_might_sleep) { in pm_clk_op_lock()
96 __release(&psd->lock); in pm_clk_op_lock()
103 fn, psd->clock_op_might_sleep); in pm_clk_op_lock()
104 spin_unlock_irqrestore(&psd->lock, *flags); in pm_clk_op_lock()
106 return -EPERM; in pm_clk_op_lock()
110 spin_unlock_irqrestore(&psd->lock, *flags); in pm_clk_op_lock()
111 mutex_lock(&psd->clock_mutex); in pm_clk_op_lock()
114 * There was a possibility for psd->clock_op_might_sleep in pm_clk_op_lock()
117 if (likely(psd->clock_op_might_sleep)) in pm_clk_op_lock()
120 mutex_unlock(&psd->clock_mutex); in pm_clk_op_lock()
125 * pm_clk_op_unlock - counterpart to pm_clk_op_lock().
133 if (psd->clock_op_might_sleep) { in pm_clk_op_unlock()
134 mutex_unlock(&psd->clock_mutex); in pm_clk_op_unlock()
137 __acquire(&psd->lock); in pm_clk_op_unlock()
138 spin_unlock_irqrestore(&psd->lock, *flags); in pm_clk_op_unlock()
143 * __pm_clk_enable - Enable a clock, reporting any errors
151 switch (ce->status) { in __pm_clk_enable()
153 ret = clk_prepare_enable(ce->clk); in __pm_clk_enable()
156 ret = clk_enable(ce->clk); in __pm_clk_enable()
162 ce->status = PCE_STATUS_ENABLED; in __pm_clk_enable()
165 __func__, ce->clk, ret); in __pm_clk_enable()
169 * pm_clk_acquire - Acquire a device clock.
175 if (!ce->clk) in pm_clk_acquire()
176 ce->clk = clk_get(dev, ce->con_id); in pm_clk_acquire()
177 if (IS_ERR(ce->clk)) { in pm_clk_acquire()
178 ce->status = PCE_STATUS_ERROR; in pm_clk_acquire()
180 } else if (clk_is_enabled_when_prepared(ce->clk)) { in pm_clk_acquire()
182 ce->status = PCE_STATUS_ACQUIRED; in pm_clk_acquire()
183 ce->enabled_when_prepared = true; in pm_clk_acquire()
184 } else if (clk_prepare(ce->clk)) { in pm_clk_acquire()
185 ce->status = PCE_STATUS_ERROR; in pm_clk_acquire()
189 ce->status = PCE_STATUS_PREPARED; in pm_clk_acquire()
192 ce->clk, ce->con_id); in pm_clk_acquire()
202 return -EINVAL; in __pm_clk_add()
206 return -ENOMEM; in __pm_clk_add()
209 ce->con_id = kstrdup(con_id, GFP_KERNEL); in __pm_clk_add()
210 if (!ce->con_id) { in __pm_clk_add()
212 return -ENOMEM; in __pm_clk_add()
217 return -ENOENT; in __pm_clk_add()
219 ce->clk = clk; in __pm_clk_add()
225 list_add_tail(&ce->node, &psd->clock_list); in __pm_clk_add()
226 if (ce->enabled_when_prepared) in __pm_clk_add()
227 psd->clock_op_might_sleep++; in __pm_clk_add()
233 * pm_clk_add - Start using a device clock for power management.
234 * @dev: Device whose clock is going to be used for power management.
238 * the power management of @dev.
247 * pm_clk_add_clk - Start using a device clock for power management.
248 * @dev: Device whose clock is going to be used for power management.
251 * Add the clock to the list of clocks used for the power management of @dev.
252 * The power-management code will take control of the clock reference, so
264 * of_pm_clk_add_clk - Start using a device clock for power management.
265 * @dev: Device whose clock is going to be used for power management.
266 * @name: Name of clock that is going to be used for power management.
268 * Add the clock described in the 'clocks' device-tree node that matches
269 * with the 'name' provided, to the list of clocks used for the power
270 * management of @dev. On success, returns 0. Returns a negative error
278 if (!dev || !dev->of_node || !name) in of_pm_clk_add_clk()
279 return -EINVAL; in of_pm_clk_add_clk()
281 clk = of_clk_get_by_name(dev->of_node, name); in of_pm_clk_add_clk()
296 * of_pm_clk_add_clks - Start using device clock(s) for power management.
297 * @dev: Device whose clock(s) is going to be used for power management.
299 * Add a series of clocks described in the 'clocks' device-tree node for
300 * a device to the list of clocks used for the power management of @dev.
311 if (!dev || !dev->of_node) in of_pm_clk_add_clks()
312 return -EINVAL; in of_pm_clk_add_clks()
314 count = of_clk_get_parent_count(dev->of_node); in of_pm_clk_add_clks()
316 return -ENODEV; in of_pm_clk_add_clks()
320 return -ENOMEM; in of_pm_clk_add_clks()
323 clks[i] = of_clk_get(dev->of_node, i); in of_pm_clk_add_clks()
341 while (i--) in of_pm_clk_add_clks()
351 * __pm_clk_remove - Destroy PM clock entry.
359 switch (ce->status) { in __pm_clk_remove()
361 clk_disable(ce->clk); in __pm_clk_remove()
364 clk_unprepare(ce->clk); in __pm_clk_remove()
368 if (!IS_ERR(ce->clk)) in __pm_clk_remove()
369 clk_put(ce->clk); in __pm_clk_remove()
375 kfree(ce->con_id); in __pm_clk_remove()
380 * pm_clk_remove - Stop using a device clock for power management.
385 * the power management of @dev.
397 list_for_each_entry(ce, &psd->clock_list, node) { in pm_clk_remove()
398 if (!con_id && !ce->con_id) in pm_clk_remove()
400 else if (!con_id || !ce->con_id) in pm_clk_remove()
402 else if (!strcmp(con_id, ce->con_id)) in pm_clk_remove()
410 list_del(&ce->node); in pm_clk_remove()
411 if (ce->enabled_when_prepared) in pm_clk_remove()
412 psd->clock_op_might_sleep--; in pm_clk_remove()
420 * pm_clk_remove_clk - Stop using a device clock for power management.
425 * the power management of @dev.
437 list_for_each_entry(ce, &psd->clock_list, node) { in pm_clk_remove_clk()
438 if (clk == ce->clk) in pm_clk_remove_clk()
446 list_del(&ce->node); in pm_clk_remove_clk()
447 if (ce->enabled_when_prepared) in pm_clk_remove_clk()
448 psd->clock_op_might_sleep--; in pm_clk_remove_clk()
456 * pm_clk_init - Initialize a device's list of power management clocks.
466 INIT_LIST_HEAD(&psd->clock_list); in pm_clk_init()
467 mutex_init(&psd->clock_mutex); in pm_clk_init()
468 psd->clock_op_might_sleep = 0; in pm_clk_init()
474 * pm_clk_create - Create and initialize a device's list of PM clocks.
478 * members and make the @dev's power.subsys_data field point to it.
487 * pm_clk_destroy - Destroy a device's list of power management clocks.
490 * Clear the @dev's power.subsys_data field, remove the list of clock entries
507 list_for_each_entry_safe_reverse(ce, c, &psd->clock_list, node) in pm_clk_destroy()
508 list_move(&ce->node, &list); in pm_clk_destroy()
509 psd->clock_op_might_sleep = 0; in pm_clk_destroy()
516 list_del(&ce->node); in pm_clk_destroy()
540 * pm_clk_suspend - Disable clocks in a device's PM clock list.
559 list_for_each_entry_reverse(ce, &psd->clock_list, node) { in pm_clk_suspend()
560 if (ce->status == PCE_STATUS_ENABLED) { in pm_clk_suspend()
561 if (ce->enabled_when_prepared) { in pm_clk_suspend()
562 clk_disable_unprepare(ce->clk); in pm_clk_suspend()
563 ce->status = PCE_STATUS_ACQUIRED; in pm_clk_suspend()
565 clk_disable(ce->clk); in pm_clk_suspend()
566 ce->status = PCE_STATUS_PREPARED; in pm_clk_suspend()
578 * pm_clk_resume - Enable clocks in a device's PM clock list.
597 list_for_each_entry(ce, &psd->clock_list, node) in pm_clk_resume()
607 * pm_clk_notify - Notify routine for device addition and removal.
636 if (dev->pm_domain) in pm_clk_notify()
643 dev_pm_domain_set(dev, clknb->pm_domain); in pm_clk_notify()
644 if (clknb->con_ids[0]) { in pm_clk_notify()
645 for (con_id = clknb->con_ids; *con_id; con_id++) in pm_clk_notify()
653 if (dev->pm_domain != clknb->pm_domain) in pm_clk_notify()
706 * enable_clock - Enable a device clock.
723 * disable_clock - Disable a device clock.
740 * pm_clk_notify - Notify routine for device addition and removal.
763 if (clknb->con_ids[0]) { in pm_clk_notify()
764 for (con_id = clknb->con_ids; *con_id; con_id++) in pm_clk_notify()
772 if (clknb->con_ids[0]) { in pm_clk_notify()
773 for (con_id = clknb->con_ids; *con_id; con_id++) in pm_clk_notify()
787 * pm_clk_add_notifier - Add bus type notifier for power management clocks.
802 clknb->nb.notifier_call = pm_clk_notify; in pm_clk_add_notifier()
803 bus_register_notifier(bus, &clknb->nb); in pm_clk_add_notifier()