xref: /openbmc/linux/drivers/base/power/clock_ops.c (revision 8fdff1dc)
1 /*
2  * drivers/base/power/clock_ops.c - Generic clock manipulation PM callbacks
3  *
4  * Copyright (c) 2011 Rafael J. Wysocki <rjw@sisk.pl>, Renesas Electronics Corp.
5  *
6  * This file is released under the GPLv2.
7  */
8 
9 #include <linux/init.h>
10 #include <linux/kernel.h>
11 #include <linux/device.h>
12 #include <linux/io.h>
13 #include <linux/pm.h>
14 #include <linux/pm_clock.h>
15 #include <linux/clk.h>
16 #include <linux/slab.h>
17 #include <linux/err.h>
18 
19 #ifdef CONFIG_PM
20 
21 enum pce_status {
22 	PCE_STATUS_NONE = 0,
23 	PCE_STATUS_ACQUIRED,
24 	PCE_STATUS_ENABLED,
25 	PCE_STATUS_ERROR,
26 };
27 
28 struct pm_clock_entry {
29 	struct list_head node;
30 	char *con_id;
31 	struct clk *clk;
32 	enum pce_status status;
33 };
34 
35 /**
36  * pm_clk_acquire - Acquire a device clock.
37  * @dev: Device whose clock is to be acquired.
38  * @ce: PM clock entry corresponding to the clock.
39  */
40 static void pm_clk_acquire(struct device *dev, struct pm_clock_entry *ce)
41 {
42 	ce->clk = clk_get(dev, ce->con_id);
43 	if (IS_ERR(ce->clk)) {
44 		ce->status = PCE_STATUS_ERROR;
45 	} else {
46 		ce->status = PCE_STATUS_ACQUIRED;
47 		dev_dbg(dev, "Clock %s managed by runtime PM.\n", ce->con_id);
48 	}
49 }
50 
51 /**
52  * pm_clk_add - Start using a device clock for power management.
53  * @dev: Device whose clock is going to be used for power management.
54  * @con_id: Connection ID of the clock.
55  *
56  * Add the clock represented by @con_id to the list of clocks used for
57  * the power management of @dev.
58  */
59 int pm_clk_add(struct device *dev, const char *con_id)
60 {
61 	struct pm_subsys_data *psd = dev_to_psd(dev);
62 	struct pm_clock_entry *ce;
63 
64 	if (!psd)
65 		return -EINVAL;
66 
67 	ce = kzalloc(sizeof(*ce), GFP_KERNEL);
68 	if (!ce) {
69 		dev_err(dev, "Not enough memory for clock entry.\n");
70 		return -ENOMEM;
71 	}
72 
73 	if (con_id) {
74 		ce->con_id = kstrdup(con_id, GFP_KERNEL);
75 		if (!ce->con_id) {
76 			dev_err(dev,
77 				"Not enough memory for clock connection ID.\n");
78 			kfree(ce);
79 			return -ENOMEM;
80 		}
81 	}
82 
83 	pm_clk_acquire(dev, ce);
84 
85 	spin_lock_irq(&psd->lock);
86 	list_add_tail(&ce->node, &psd->clock_list);
87 	spin_unlock_irq(&psd->lock);
88 	return 0;
89 }
90 
91 /**
92  * __pm_clk_remove - Destroy PM clock entry.
93  * @ce: PM clock entry to destroy.
94  */
95 static void __pm_clk_remove(struct pm_clock_entry *ce)
96 {
97 	if (!ce)
98 		return;
99 
100 	if (ce->status < PCE_STATUS_ERROR) {
101 		if (ce->status == PCE_STATUS_ENABLED)
102 			clk_disable_unprepare(ce->clk);
103 
104 		if (ce->status >= PCE_STATUS_ACQUIRED)
105 			clk_put(ce->clk);
106 	}
107 
108 	kfree(ce->con_id);
109 	kfree(ce);
110 }
111 
112 /**
113  * pm_clk_remove - Stop using a device clock for power management.
114  * @dev: Device whose clock should not be used for PM any more.
115  * @con_id: Connection ID of the clock.
116  *
117  * Remove the clock represented by @con_id from the list of clocks used for
118  * the power management of @dev.
119  */
120 void pm_clk_remove(struct device *dev, const char *con_id)
121 {
122 	struct pm_subsys_data *psd = dev_to_psd(dev);
123 	struct pm_clock_entry *ce;
124 
125 	if (!psd)
126 		return;
127 
128 	spin_lock_irq(&psd->lock);
129 
130 	list_for_each_entry(ce, &psd->clock_list, node) {
131 		if (!con_id && !ce->con_id)
132 			goto remove;
133 		else if (!con_id || !ce->con_id)
134 			continue;
135 		else if (!strcmp(con_id, ce->con_id))
136 			goto remove;
137 	}
138 
139 	spin_unlock_irq(&psd->lock);
140 	return;
141 
142  remove:
143 	list_del(&ce->node);
144 	spin_unlock_irq(&psd->lock);
145 
146 	__pm_clk_remove(ce);
147 }
148 
149 /**
150  * pm_clk_init - Initialize a device's list of power management clocks.
151  * @dev: Device to initialize the list of PM clocks for.
152  *
153  * Initialize the lock and clock_list members of the device's pm_subsys_data
154  * object.
155  */
156 void pm_clk_init(struct device *dev)
157 {
158 	struct pm_subsys_data *psd = dev_to_psd(dev);
159 	if (psd)
160 		INIT_LIST_HEAD(&psd->clock_list);
161 }
162 
163 /**
164  * pm_clk_create - Create and initialize a device's list of PM clocks.
165  * @dev: Device to create and initialize the list of PM clocks for.
166  *
167  * Allocate a struct pm_subsys_data object, initialize its lock and clock_list
168  * members and make the @dev's power.subsys_data field point to it.
169  */
170 int pm_clk_create(struct device *dev)
171 {
172 	return dev_pm_get_subsys_data(dev);
173 }
174 
175 /**
176  * pm_clk_destroy - Destroy a device's list of power management clocks.
177  * @dev: Device to destroy the list of PM clocks for.
178  *
179  * Clear the @dev's power.subsys_data field, remove the list of clock entries
180  * from the struct pm_subsys_data object pointed to by it before and free
181  * that object.
182  */
183 void pm_clk_destroy(struct device *dev)
184 {
185 	struct pm_subsys_data *psd = dev_to_psd(dev);
186 	struct pm_clock_entry *ce, *c;
187 	struct list_head list;
188 
189 	if (!psd)
190 		return;
191 
192 	INIT_LIST_HEAD(&list);
193 
194 	spin_lock_irq(&psd->lock);
195 
196 	list_for_each_entry_safe_reverse(ce, c, &psd->clock_list, node)
197 		list_move(&ce->node, &list);
198 
199 	spin_unlock_irq(&psd->lock);
200 
201 	dev_pm_put_subsys_data(dev);
202 
203 	list_for_each_entry_safe_reverse(ce, c, &list, node) {
204 		list_del(&ce->node);
205 		__pm_clk_remove(ce);
206 	}
207 }
208 
209 #endif /* CONFIG_PM */
210 
211 #ifdef CONFIG_PM_RUNTIME
212 
213 /**
214  * pm_clk_suspend - Disable clocks in a device's PM clock list.
215  * @dev: Device to disable the clocks for.
216  */
217 int pm_clk_suspend(struct device *dev)
218 {
219 	struct pm_subsys_data *psd = dev_to_psd(dev);
220 	struct pm_clock_entry *ce;
221 	unsigned long flags;
222 
223 	dev_dbg(dev, "%s()\n", __func__);
224 
225 	if (!psd)
226 		return 0;
227 
228 	spin_lock_irqsave(&psd->lock, flags);
229 
230 	list_for_each_entry_reverse(ce, &psd->clock_list, node) {
231 		if (ce->status < PCE_STATUS_ERROR) {
232 			if (ce->status == PCE_STATUS_ENABLED)
233 				clk_disable(ce->clk);
234 			ce->status = PCE_STATUS_ACQUIRED;
235 		}
236 	}
237 
238 	spin_unlock_irqrestore(&psd->lock, flags);
239 
240 	return 0;
241 }
242 
243 /**
244  * pm_clk_resume - Enable clocks in a device's PM clock list.
245  * @dev: Device to enable the clocks for.
246  */
247 int pm_clk_resume(struct device *dev)
248 {
249 	struct pm_subsys_data *psd = dev_to_psd(dev);
250 	struct pm_clock_entry *ce;
251 	unsigned long flags;
252 
253 	dev_dbg(dev, "%s()\n", __func__);
254 
255 	if (!psd)
256 		return 0;
257 
258 	spin_lock_irqsave(&psd->lock, flags);
259 
260 	list_for_each_entry(ce, &psd->clock_list, node) {
261 		if (ce->status < PCE_STATUS_ERROR) {
262 			clk_enable(ce->clk);
263 			ce->status = PCE_STATUS_ENABLED;
264 		}
265 	}
266 
267 	spin_unlock_irqrestore(&psd->lock, flags);
268 
269 	return 0;
270 }
271 
272 /**
273  * pm_clk_notify - Notify routine for device addition and removal.
274  * @nb: Notifier block object this function is a member of.
275  * @action: Operation being carried out by the caller.
276  * @data: Device the routine is being run for.
277  *
278  * For this function to work, @nb must be a member of an object of type
279  * struct pm_clk_notifier_block containing all of the requisite data.
280  * Specifically, the pm_domain member of that object is copied to the device's
281  * pm_domain field and its con_ids member is used to populate the device's list
282  * of PM clocks, depending on @action.
283  *
284  * If the device's pm_domain field is already populated with a value different
285  * from the one stored in the struct pm_clk_notifier_block object, the function
286  * does nothing.
287  */
288 static int pm_clk_notify(struct notifier_block *nb,
289 				 unsigned long action, void *data)
290 {
291 	struct pm_clk_notifier_block *clknb;
292 	struct device *dev = data;
293 	char **con_id;
294 	int error;
295 
296 	dev_dbg(dev, "%s() %ld\n", __func__, action);
297 
298 	clknb = container_of(nb, struct pm_clk_notifier_block, nb);
299 
300 	switch (action) {
301 	case BUS_NOTIFY_ADD_DEVICE:
302 		if (dev->pm_domain)
303 			break;
304 
305 		error = pm_clk_create(dev);
306 		if (error)
307 			break;
308 
309 		dev->pm_domain = clknb->pm_domain;
310 		if (clknb->con_ids[0]) {
311 			for (con_id = clknb->con_ids; *con_id; con_id++)
312 				pm_clk_add(dev, *con_id);
313 		} else {
314 			pm_clk_add(dev, NULL);
315 		}
316 
317 		break;
318 	case BUS_NOTIFY_DEL_DEVICE:
319 		if (dev->pm_domain != clknb->pm_domain)
320 			break;
321 
322 		dev->pm_domain = NULL;
323 		pm_clk_destroy(dev);
324 		break;
325 	}
326 
327 	return 0;
328 }
329 
330 #else /* !CONFIG_PM_RUNTIME */
331 
332 #ifdef CONFIG_PM
333 
334 /**
335  * pm_clk_suspend - Disable clocks in a device's PM clock list.
336  * @dev: Device to disable the clocks for.
337  */
338 int pm_clk_suspend(struct device *dev)
339 {
340 	struct pm_subsys_data *psd = dev_to_psd(dev);
341 	struct pm_clock_entry *ce;
342 	unsigned long flags;
343 
344 	dev_dbg(dev, "%s()\n", __func__);
345 
346 	/* If there is no driver, the clocks are already disabled. */
347 	if (!psd || !dev->driver)
348 		return 0;
349 
350 	spin_lock_irqsave(&psd->lock, flags);
351 
352 	list_for_each_entry_reverse(ce, &psd->clock_list, node)
353 		clk_disable(ce->clk);
354 
355 	spin_unlock_irqrestore(&psd->lock, flags);
356 
357 	return 0;
358 }
359 
360 /**
361  * pm_clk_resume - Enable clocks in a device's PM clock list.
362  * @dev: Device to enable the clocks for.
363  */
364 int pm_clk_resume(struct device *dev)
365 {
366 	struct pm_subsys_data *psd = dev_to_psd(dev);
367 	struct pm_clock_entry *ce;
368 	unsigned long flags;
369 
370 	dev_dbg(dev, "%s()\n", __func__);
371 
372 	/* If there is no driver, the clocks should remain disabled. */
373 	if (!psd || !dev->driver)
374 		return 0;
375 
376 	spin_lock_irqsave(&psd->lock, flags);
377 
378 	list_for_each_entry(ce, &psd->clock_list, node)
379 		clk_enable(ce->clk);
380 
381 	spin_unlock_irqrestore(&psd->lock, flags);
382 
383 	return 0;
384 }
385 
386 #endif /* CONFIG_PM */
387 
388 /**
389  * enable_clock - Enable a device clock.
390  * @dev: Device whose clock is to be enabled.
391  * @con_id: Connection ID of the clock.
392  */
393 static void enable_clock(struct device *dev, const char *con_id)
394 {
395 	struct clk *clk;
396 
397 	clk = clk_get(dev, con_id);
398 	if (!IS_ERR(clk)) {
399 		clk_prepare_enable(clk);
400 		clk_put(clk);
401 		dev_info(dev, "Runtime PM disabled, clock forced on.\n");
402 	}
403 }
404 
405 /**
406  * disable_clock - Disable a device clock.
407  * @dev: Device whose clock is to be disabled.
408  * @con_id: Connection ID of the clock.
409  */
410 static void disable_clock(struct device *dev, const char *con_id)
411 {
412 	struct clk *clk;
413 
414 	clk = clk_get(dev, con_id);
415 	if (!IS_ERR(clk)) {
416 		clk_disable_unprepare(clk);
417 		clk_put(clk);
418 		dev_info(dev, "Runtime PM disabled, clock forced off.\n");
419 	}
420 }
421 
422 /**
423  * pm_clk_notify - Notify routine for device addition and removal.
424  * @nb: Notifier block object this function is a member of.
425  * @action: Operation being carried out by the caller.
426  * @data: Device the routine is being run for.
427  *
428  * For this function to work, @nb must be a member of an object of type
429  * struct pm_clk_notifier_block containing all of the requisite data.
430  * Specifically, the con_ids member of that object is used to enable or disable
431  * the device's clocks, depending on @action.
432  */
433 static int pm_clk_notify(struct notifier_block *nb,
434 				 unsigned long action, void *data)
435 {
436 	struct pm_clk_notifier_block *clknb;
437 	struct device *dev = data;
438 	char **con_id;
439 
440 	dev_dbg(dev, "%s() %ld\n", __func__, action);
441 
442 	clknb = container_of(nb, struct pm_clk_notifier_block, nb);
443 
444 	switch (action) {
445 	case BUS_NOTIFY_BIND_DRIVER:
446 		if (clknb->con_ids[0]) {
447 			for (con_id = clknb->con_ids; *con_id; con_id++)
448 				enable_clock(dev, *con_id);
449 		} else {
450 			enable_clock(dev, NULL);
451 		}
452 		break;
453 	case BUS_NOTIFY_UNBOUND_DRIVER:
454 		if (clknb->con_ids[0]) {
455 			for (con_id = clknb->con_ids; *con_id; con_id++)
456 				disable_clock(dev, *con_id);
457 		} else {
458 			disable_clock(dev, NULL);
459 		}
460 		break;
461 	}
462 
463 	return 0;
464 }
465 
466 #endif /* !CONFIG_PM_RUNTIME */
467 
468 /**
469  * pm_clk_add_notifier - Add bus type notifier for power management clocks.
470  * @bus: Bus type to add the notifier to.
471  * @clknb: Notifier to be added to the given bus type.
472  *
473  * The nb member of @clknb is not expected to be initialized and its
474  * notifier_call member will be replaced with pm_clk_notify().  However,
475  * the remaining members of @clknb should be populated prior to calling this
476  * routine.
477  */
478 void pm_clk_add_notifier(struct bus_type *bus,
479 				 struct pm_clk_notifier_block *clknb)
480 {
481 	if (!bus || !clknb)
482 		return;
483 
484 	clknb->nb.notifier_call = pm_clk_notify;
485 	bus_register_notifier(bus, &clknb->nb);
486 }
487