Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * drivers/base/power/clock_ops.c - Generic clock manipulation PM callbacks
4 *
5 * Copyright (c) 2011 Rafael J. Wysocki <rjw@sisk.pl>, Renesas Electronics Corp.
6 */
7
8#include <linux/kernel.h>
9#include <linux/device.h>
10#include <linux/io.h>
11#include <linux/pm.h>
12#include <linux/pm_clock.h>
13#include <linux/clk.h>
14#include <linux/clkdev.h>
15#include <linux/slab.h>
16#include <linux/err.h>
17#include <linux/pm_domain.h>
18#include <linux/pm_runtime.h>
19
20#ifdef CONFIG_PM_CLK
21
22enum pce_status {
23 PCE_STATUS_NONE = 0,
24 PCE_STATUS_ACQUIRED,
25 PCE_STATUS_ENABLED,
26 PCE_STATUS_ERROR,
27};
28
29struct pm_clock_entry {
30 struct list_head node;
31 char *con_id;
32 struct clk *clk;
33 enum pce_status status;
34};
35
36/**
37 * pm_clk_enable - Enable a clock, reporting any errors
38 * @dev: The device for the given clock
39 * @ce: PM clock entry corresponding to the clock.
40 */
41static inline void __pm_clk_enable(struct device *dev, struct pm_clock_entry *ce)
42{
43 int ret;
44
45 if (ce->status < PCE_STATUS_ERROR) {
46 ret = clk_enable(ce->clk);
47 if (!ret)
48 ce->status = PCE_STATUS_ENABLED;
49 else
50 dev_err(dev, "%s: failed to enable clk %p, error %d\n",
51 __func__, ce->clk, ret);
52 }
53}
54
55/**
56 * pm_clk_acquire - Acquire a device clock.
57 * @dev: Device whose clock is to be acquired.
58 * @ce: PM clock entry corresponding to the clock.
59 */
60static void pm_clk_acquire(struct device *dev, struct pm_clock_entry *ce)
61{
62 if (!ce->clk)
63 ce->clk = clk_get(dev, ce->con_id);
64 if (IS_ERR(ce->clk)) {
65 ce->status = PCE_STATUS_ERROR;
66 } else {
67 if (clk_prepare(ce->clk)) {
68 ce->status = PCE_STATUS_ERROR;
69 dev_err(dev, "clk_prepare() failed\n");
70 } else {
71 ce->status = PCE_STATUS_ACQUIRED;
72 dev_dbg(dev,
73 "Clock %pC con_id %s managed by runtime PM.\n",
74 ce->clk, ce->con_id);
75 }
76 }
77}
78
79static int __pm_clk_add(struct device *dev, const char *con_id,
80 struct clk *clk)
81{
82 struct pm_subsys_data *psd = dev_to_psd(dev);
83 struct pm_clock_entry *ce;
84
85 if (!psd)
86 return -EINVAL;
87
88 ce = kzalloc(sizeof(*ce), GFP_KERNEL);
89 if (!ce)
90 return -ENOMEM;
91
92 if (con_id) {
93 ce->con_id = kstrdup(con_id, GFP_KERNEL);
94 if (!ce->con_id) {
95 dev_err(dev,
96 "Not enough memory for clock connection ID.\n");
97 kfree(ce);
98 return -ENOMEM;
99 }
100 } else {
101 if (IS_ERR(clk)) {
102 kfree(ce);
103 return -ENOENT;
104 }
105 ce->clk = clk;
106 }
107
108 pm_clk_acquire(dev, ce);
109
110 spin_lock_irq(&psd->lock);
111 list_add_tail(&ce->node, &psd->clock_list);
112 spin_unlock_irq(&psd->lock);
113 return 0;
114}
115
116/**
117 * pm_clk_add - Start using a device clock for power management.
118 * @dev: Device whose clock is going to be used for power management.
119 * @con_id: Connection ID of the clock.
120 *
121 * Add the clock represented by @con_id to the list of clocks used for
122 * the power management of @dev.
123 */
124int pm_clk_add(struct device *dev, const char *con_id)
125{
126 return __pm_clk_add(dev, con_id, NULL);
127}
128EXPORT_SYMBOL_GPL(pm_clk_add);
129
130/**
131 * pm_clk_add_clk - Start using a device clock for power management.
132 * @dev: Device whose clock is going to be used for power management.
133 * @clk: Clock pointer
134 *
135 * Add the clock to the list of clocks used for the power management of @dev.
136 * The power-management code will take control of the clock reference, so
137 * callers should not call clk_put() on @clk after this function sucessfully
138 * returned.
139 */
140int pm_clk_add_clk(struct device *dev, struct clk *clk)
141{
142 return __pm_clk_add(dev, NULL, clk);
143}
144EXPORT_SYMBOL_GPL(pm_clk_add_clk);
145
146
147/**
148 * of_pm_clk_add_clk - Start using a device clock for power management.
149 * @dev: Device whose clock is going to be used for power management.
150 * @name: Name of clock that is going to be used for power management.
151 *
152 * Add the clock described in the 'clocks' device-tree node that matches
153 * with the 'name' provided, to the list of clocks used for the power
154 * management of @dev. On success, returns 0. Returns a negative error
155 * code if the clock is not found or cannot be added.
156 */
157int of_pm_clk_add_clk(struct device *dev, const char *name)
158{
159 struct clk *clk;
160 int ret;
161
162 if (!dev || !dev->of_node || !name)
163 return -EINVAL;
164
165 clk = of_clk_get_by_name(dev->of_node, name);
166 if (IS_ERR(clk))
167 return PTR_ERR(clk);
168
169 ret = pm_clk_add_clk(dev, clk);
170 if (ret) {
171 clk_put(clk);
172 return ret;
173 }
174
175 return 0;
176}
177EXPORT_SYMBOL_GPL(of_pm_clk_add_clk);
178
179/**
180 * of_pm_clk_add_clks - Start using device clock(s) for power management.
181 * @dev: Device whose clock(s) is going to be used for power management.
182 *
183 * Add a series of clocks described in the 'clocks' device-tree node for
184 * a device to the list of clocks used for the power management of @dev.
185 * On success, returns the number of clocks added. Returns a negative
186 * error code if there are no clocks in the device node for the device
187 * or if adding a clock fails.
188 */
189int of_pm_clk_add_clks(struct device *dev)
190{
191 struct clk **clks;
192 int i, count;
193 int ret;
194
195 if (!dev || !dev->of_node)
196 return -EINVAL;
197
198 count = of_count_phandle_with_args(dev->of_node, "clocks",
199 "#clock-cells");
200 if (count <= 0)
201 return -ENODEV;
202
203 clks = kcalloc(count, sizeof(*clks), GFP_KERNEL);
204 if (!clks)
205 return -ENOMEM;
206
207 for (i = 0; i < count; i++) {
208 clks[i] = of_clk_get(dev->of_node, i);
209 if (IS_ERR(clks[i])) {
210 ret = PTR_ERR(clks[i]);
211 goto error;
212 }
213
214 ret = pm_clk_add_clk(dev, clks[i]);
215 if (ret) {
216 clk_put(clks[i]);
217 goto error;
218 }
219 }
220
221 kfree(clks);
222
223 return i;
224
225error:
226 while (i--)
227 pm_clk_remove_clk(dev, clks[i]);
228
229 kfree(clks);
230
231 return ret;
232}
233EXPORT_SYMBOL_GPL(of_pm_clk_add_clks);
234
235/**
236 * __pm_clk_remove - Destroy PM clock entry.
237 * @ce: PM clock entry to destroy.
238 */
239static void __pm_clk_remove(struct pm_clock_entry *ce)
240{
241 if (!ce)
242 return;
243
244 if (ce->status < PCE_STATUS_ERROR) {
245 if (ce->status == PCE_STATUS_ENABLED)
246 clk_disable(ce->clk);
247
248 if (ce->status >= PCE_STATUS_ACQUIRED) {
249 clk_unprepare(ce->clk);
250 clk_put(ce->clk);
251 }
252 }
253
254 kfree(ce->con_id);
255 kfree(ce);
256}
257
258/**
259 * pm_clk_remove - Stop using a device clock for power management.
260 * @dev: Device whose clock should not be used for PM any more.
261 * @con_id: Connection ID of the clock.
262 *
263 * Remove the clock represented by @con_id from the list of clocks used for
264 * the power management of @dev.
265 */
266void pm_clk_remove(struct device *dev, const char *con_id)
267{
268 struct pm_subsys_data *psd = dev_to_psd(dev);
269 struct pm_clock_entry *ce;
270
271 if (!psd)
272 return;
273
274 spin_lock_irq(&psd->lock);
275
276 list_for_each_entry(ce, &psd->clock_list, node) {
277 if (!con_id && !ce->con_id)
278 goto remove;
279 else if (!con_id || !ce->con_id)
280 continue;
281 else if (!strcmp(con_id, ce->con_id))
282 goto remove;
283 }
284
285 spin_unlock_irq(&psd->lock);
286 return;
287
288 remove:
289 list_del(&ce->node);
290 spin_unlock_irq(&psd->lock);
291
292 __pm_clk_remove(ce);
293}
294EXPORT_SYMBOL_GPL(pm_clk_remove);
295
296/**
297 * pm_clk_remove_clk - Stop using a device clock for power management.
298 * @dev: Device whose clock should not be used for PM any more.
299 * @clk: Clock pointer
300 *
301 * Remove the clock pointed to by @clk from the list of clocks used for
302 * the power management of @dev.
303 */
304void pm_clk_remove_clk(struct device *dev, struct clk *clk)
305{
306 struct pm_subsys_data *psd = dev_to_psd(dev);
307 struct pm_clock_entry *ce;
308
309 if (!psd || !clk)
310 return;
311
312 spin_lock_irq(&psd->lock);
313
314 list_for_each_entry(ce, &psd->clock_list, node) {
315 if (clk == ce->clk)
316 goto remove;
317 }
318
319 spin_unlock_irq(&psd->lock);
320 return;
321
322 remove:
323 list_del(&ce->node);
324 spin_unlock_irq(&psd->lock);
325
326 __pm_clk_remove(ce);
327}
328EXPORT_SYMBOL_GPL(pm_clk_remove_clk);
329
330/**
331 * pm_clk_init - Initialize a device's list of power management clocks.
332 * @dev: Device to initialize the list of PM clocks for.
333 *
334 * Initialize the lock and clock_list members of the device's pm_subsys_data
335 * object.
336 */
337void pm_clk_init(struct device *dev)
338{
339 struct pm_subsys_data *psd = dev_to_psd(dev);
340 if (psd)
341 INIT_LIST_HEAD(&psd->clock_list);
342}
343EXPORT_SYMBOL_GPL(pm_clk_init);
344
345/**
346 * pm_clk_create - Create and initialize a device's list of PM clocks.
347 * @dev: Device to create and initialize the list of PM clocks for.
348 *
349 * Allocate a struct pm_subsys_data object, initialize its lock and clock_list
350 * members and make the @dev's power.subsys_data field point to it.
351 */
352int pm_clk_create(struct device *dev)
353{
354 return dev_pm_get_subsys_data(dev);
355}
356EXPORT_SYMBOL_GPL(pm_clk_create);
357
358/**
359 * pm_clk_destroy - Destroy a device's list of power management clocks.
360 * @dev: Device to destroy the list of PM clocks for.
361 *
362 * Clear the @dev's power.subsys_data field, remove the list of clock entries
363 * from the struct pm_subsys_data object pointed to by it before and free
364 * that object.
365 */
366void pm_clk_destroy(struct device *dev)
367{
368 struct pm_subsys_data *psd = dev_to_psd(dev);
369 struct pm_clock_entry *ce, *c;
370 struct list_head list;
371
372 if (!psd)
373 return;
374
375 INIT_LIST_HEAD(&list);
376
377 spin_lock_irq(&psd->lock);
378
379 list_for_each_entry_safe_reverse(ce, c, &psd->clock_list, node)
380 list_move(&ce->node, &list);
381
382 spin_unlock_irq(&psd->lock);
383
384 dev_pm_put_subsys_data(dev);
385
386 list_for_each_entry_safe_reverse(ce, c, &list, node) {
387 list_del(&ce->node);
388 __pm_clk_remove(ce);
389 }
390}
391EXPORT_SYMBOL_GPL(pm_clk_destroy);
392
393/**
394 * pm_clk_suspend - Disable clocks in a device's PM clock list.
395 * @dev: Device to disable the clocks for.
396 */
397int pm_clk_suspend(struct device *dev)
398{
399 struct pm_subsys_data *psd = dev_to_psd(dev);
400 struct pm_clock_entry *ce;
401 unsigned long flags;
402
403 dev_dbg(dev, "%s()\n", __func__);
404
405 if (!psd)
406 return 0;
407
408 spin_lock_irqsave(&psd->lock, flags);
409
410 list_for_each_entry_reverse(ce, &psd->clock_list, node) {
411 if (ce->status < PCE_STATUS_ERROR) {
412 if (ce->status == PCE_STATUS_ENABLED)
413 clk_disable(ce->clk);
414 ce->status = PCE_STATUS_ACQUIRED;
415 }
416 }
417
418 spin_unlock_irqrestore(&psd->lock, flags);
419
420 return 0;
421}
422EXPORT_SYMBOL_GPL(pm_clk_suspend);
423
424/**
425 * pm_clk_resume - Enable clocks in a device's PM clock list.
426 * @dev: Device to enable the clocks for.
427 */
428int pm_clk_resume(struct device *dev)
429{
430 struct pm_subsys_data *psd = dev_to_psd(dev);
431 struct pm_clock_entry *ce;
432 unsigned long flags;
433
434 dev_dbg(dev, "%s()\n", __func__);
435
436 if (!psd)
437 return 0;
438
439 spin_lock_irqsave(&psd->lock, flags);
440
441 list_for_each_entry(ce, &psd->clock_list, node)
442 __pm_clk_enable(dev, ce);
443
444 spin_unlock_irqrestore(&psd->lock, flags);
445
446 return 0;
447}
448EXPORT_SYMBOL_GPL(pm_clk_resume);
449
450/**
451 * pm_clk_notify - Notify routine for device addition and removal.
452 * @nb: Notifier block object this function is a member of.
453 * @action: Operation being carried out by the caller.
454 * @data: Device the routine is being run for.
455 *
456 * For this function to work, @nb must be a member of an object of type
457 * struct pm_clk_notifier_block containing all of the requisite data.
458 * Specifically, the pm_domain member of that object is copied to the device's
459 * pm_domain field and its con_ids member is used to populate the device's list
460 * of PM clocks, depending on @action.
461 *
462 * If the device's pm_domain field is already populated with a value different
463 * from the one stored in the struct pm_clk_notifier_block object, the function
464 * does nothing.
465 */
466static int pm_clk_notify(struct notifier_block *nb,
467 unsigned long action, void *data)
468{
469 struct pm_clk_notifier_block *clknb;
470 struct device *dev = data;
471 char **con_id;
472 int error;
473
474 dev_dbg(dev, "%s() %ld\n", __func__, action);
475
476 clknb = container_of(nb, struct pm_clk_notifier_block, nb);
477
478 switch (action) {
479 case BUS_NOTIFY_ADD_DEVICE:
480 if (dev->pm_domain)
481 break;
482
483 error = pm_clk_create(dev);
484 if (error)
485 break;
486
487 dev_pm_domain_set(dev, clknb->pm_domain);
488 if (clknb->con_ids[0]) {
489 for (con_id = clknb->con_ids; *con_id; con_id++)
490 pm_clk_add(dev, *con_id);
491 } else {
492 pm_clk_add(dev, NULL);
493 }
494
495 break;
496 case BUS_NOTIFY_DEL_DEVICE:
497 if (dev->pm_domain != clknb->pm_domain)
498 break;
499
500 dev_pm_domain_set(dev, NULL);
501 pm_clk_destroy(dev);
502 break;
503 }
504
505 return 0;
506}
507
508int pm_clk_runtime_suspend(struct device *dev)
509{
510 int ret;
511
512 dev_dbg(dev, "%s\n", __func__);
513
514 ret = pm_generic_runtime_suspend(dev);
515 if (ret) {
516 dev_err(dev, "failed to suspend device\n");
517 return ret;
518 }
519
520 ret = pm_clk_suspend(dev);
521 if (ret) {
522 dev_err(dev, "failed to suspend clock\n");
523 pm_generic_runtime_resume(dev);
524 return ret;
525 }
526
527 return 0;
528}
529EXPORT_SYMBOL_GPL(pm_clk_runtime_suspend);
530
531int pm_clk_runtime_resume(struct device *dev)
532{
533 int ret;
534
535 dev_dbg(dev, "%s\n", __func__);
536
537 ret = pm_clk_resume(dev);
538 if (ret) {
539 dev_err(dev, "failed to resume clock\n");
540 return ret;
541 }
542
543 return pm_generic_runtime_resume(dev);
544}
545EXPORT_SYMBOL_GPL(pm_clk_runtime_resume);
546
547#else /* !CONFIG_PM_CLK */
548
549/**
550 * enable_clock - Enable a device clock.
551 * @dev: Device whose clock is to be enabled.
552 * @con_id: Connection ID of the clock.
553 */
554static void enable_clock(struct device *dev, const char *con_id)
555{
556 struct clk *clk;
557
558 clk = clk_get(dev, con_id);
559 if (!IS_ERR(clk)) {
560 clk_prepare_enable(clk);
561 clk_put(clk);
562 dev_info(dev, "Runtime PM disabled, clock forced on.\n");
563 }
564}
565
566/**
567 * disable_clock - Disable a device clock.
568 * @dev: Device whose clock is to be disabled.
569 * @con_id: Connection ID of the clock.
570 */
571static void disable_clock(struct device *dev, const char *con_id)
572{
573 struct clk *clk;
574
575 clk = clk_get(dev, con_id);
576 if (!IS_ERR(clk)) {
577 clk_disable_unprepare(clk);
578 clk_put(clk);
579 dev_info(dev, "Runtime PM disabled, clock forced off.\n");
580 }
581}
582
583/**
584 * pm_clk_notify - Notify routine for device addition and removal.
585 * @nb: Notifier block object this function is a member of.
586 * @action: Operation being carried out by the caller.
587 * @data: Device the routine is being run for.
588 *
589 * For this function to work, @nb must be a member of an object of type
590 * struct pm_clk_notifier_block containing all of the requisite data.
591 * Specifically, the con_ids member of that object is used to enable or disable
592 * the device's clocks, depending on @action.
593 */
594static int pm_clk_notify(struct notifier_block *nb,
595 unsigned long action, void *data)
596{
597 struct pm_clk_notifier_block *clknb;
598 struct device *dev = data;
599 char **con_id;
600
601 dev_dbg(dev, "%s() %ld\n", __func__, action);
602
603 clknb = container_of(nb, struct pm_clk_notifier_block, nb);
604
605 switch (action) {
606 case BUS_NOTIFY_BIND_DRIVER:
607 if (clknb->con_ids[0]) {
608 for (con_id = clknb->con_ids; *con_id; con_id++)
609 enable_clock(dev, *con_id);
610 } else {
611 enable_clock(dev, NULL);
612 }
613 break;
614 case BUS_NOTIFY_DRIVER_NOT_BOUND:
615 case BUS_NOTIFY_UNBOUND_DRIVER:
616 if (clknb->con_ids[0]) {
617 for (con_id = clknb->con_ids; *con_id; con_id++)
618 disable_clock(dev, *con_id);
619 } else {
620 disable_clock(dev, NULL);
621 }
622 break;
623 }
624
625 return 0;
626}
627
628#endif /* !CONFIG_PM_CLK */
629
630/**
631 * pm_clk_add_notifier - Add bus type notifier for power management clocks.
632 * @bus: Bus type to add the notifier to.
633 * @clknb: Notifier to be added to the given bus type.
634 *
635 * The nb member of @clknb is not expected to be initialized and its
636 * notifier_call member will be replaced with pm_clk_notify(). However,
637 * the remaining members of @clknb should be populated prior to calling this
638 * routine.
639 */
640void pm_clk_add_notifier(struct bus_type *bus,
641 struct pm_clk_notifier_block *clknb)
642{
643 if (!bus || !clknb)
644 return;
645
646 clknb->nb.notifier_call = pm_clk_notify;
647 bus_register_notifier(bus, &clknb->nb);
648}
649EXPORT_SYMBOL_GPL(pm_clk_add_notifier);