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