clock_ops.c 11.7 KB
Newer Older
1 2 3 4 5 6 7 8 9
/*
 * drivers/base/power/clock_ops.c - Generic clock manipulation PM callbacks
 *
 * Copyright (c) 2011 Rafael J. Wysocki <rjw@sisk.pl>, Renesas Electronics Corp.
 *
 * This file is released under the GPLv2.
 */

#include <linux/kernel.h>
10
#include <linux/device.h>
11 12
#include <linux/io.h>
#include <linux/pm.h>
13
#include <linux/pm_clock.h>
14
#include <linux/clk.h>
15
#include <linux/clkdev.h>
16 17
#include <linux/slab.h>
#include <linux/err.h>
18
#include <linux/pm_domain.h>
19
#include <linux/pm_runtime.h>
20

21
#ifdef CONFIG_PM_CLK
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36

enum pce_status {
	PCE_STATUS_NONE = 0,
	PCE_STATUS_ACQUIRED,
	PCE_STATUS_ENABLED,
	PCE_STATUS_ERROR,
};

struct pm_clock_entry {
	struct list_head node;
	char *con_id;
	struct clk *clk;
	enum pce_status status;
};

37 38 39
/**
 * pm_clk_enable - Enable a clock, reporting any errors
 * @dev: The device for the given clock
40
 * @ce: PM clock entry corresponding to the clock.
41
 */
42
static inline void __pm_clk_enable(struct device *dev, struct pm_clock_entry *ce)
43
{
44 45 46 47 48 49 50 51 52 53
	int ret;

	if (ce->status < PCE_STATUS_ERROR) {
		ret = clk_enable(ce->clk);
		if (!ret)
			ce->status = PCE_STATUS_ENABLED;
		else
			dev_err(dev, "%s: failed to enable clk %p, error %d\n",
				__func__, ce->clk, ret);
	}
54 55
}

56 57 58 59 60 61 62
/**
 * pm_clk_acquire - Acquire a device clock.
 * @dev: Device whose clock is to be acquired.
 * @ce: PM clock entry corresponding to the clock.
 */
static void pm_clk_acquire(struct device *dev, struct pm_clock_entry *ce)
{
63 64
	if (!ce->clk)
		ce->clk = clk_get(dev, ce->con_id);
65 66 67
	if (IS_ERR(ce->clk)) {
		ce->status = PCE_STATUS_ERROR;
	} else {
68
		clk_prepare(ce->clk);
69
		ce->status = PCE_STATUS_ACQUIRED;
70 71
		dev_dbg(dev, "Clock %pC con_id %s managed by runtime PM.\n",
			ce->clk, ce->con_id);
72 73 74
	}
}

75 76
static int __pm_clk_add(struct device *dev, const char *con_id,
			struct clk *clk)
77
{
78
	struct pm_subsys_data *psd = dev_to_psd(dev);
79 80
	struct pm_clock_entry *ce;

81
	if (!psd)
82 83 84
		return -EINVAL;

	ce = kzalloc(sizeof(*ce), GFP_KERNEL);
85
	if (!ce)
86 87 88 89 90 91 92 93 94 95
		return -ENOMEM;

	if (con_id) {
		ce->con_id = kstrdup(con_id, GFP_KERNEL);
		if (!ce->con_id) {
			dev_err(dev,
				"Not enough memory for clock connection ID.\n");
			kfree(ce);
			return -ENOMEM;
		}
96
	} else {
97
		if (IS_ERR(clk)) {
98 99 100 101
			kfree(ce);
			return -ENOENT;
		}
		ce->clk = clk;
102 103
	}

104 105
	pm_clk_acquire(dev, ce);

106 107 108
	spin_lock_irq(&psd->lock);
	list_add_tail(&ce->node, &psd->clock_list);
	spin_unlock_irq(&psd->lock);
109 110 111
	return 0;
}

112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
/**
 * pm_clk_add - Start using a device clock for power management.
 * @dev: Device whose clock is going to be used for power management.
 * @con_id: Connection ID of the clock.
 *
 * Add the clock represented by @con_id to the list of clocks used for
 * the power management of @dev.
 */
int pm_clk_add(struct device *dev, const char *con_id)
{
	return __pm_clk_add(dev, con_id, NULL);
}

/**
 * pm_clk_add_clk - Start using a device clock for power management.
 * @dev: Device whose clock is going to be used for power management.
 * @clk: Clock pointer
 *
 * Add the clock to the list of clocks used for the power management of @dev.
131 132 133
 * The power-management code will take control of the clock reference, so
 * callers should not call clk_put() on @clk after this function sucessfully
 * returned.
134 135 136 137 138 139
 */
int pm_clk_add_clk(struct device *dev, struct clk *clk)
{
	return __pm_clk_add(dev, NULL, clk);
}

140
/**
141 142
 * __pm_clk_remove - Destroy PM clock entry.
 * @ce: PM clock entry to destroy.
143
 */
144
static void __pm_clk_remove(struct pm_clock_entry *ce)
145 146 147 148 149 150
{
	if (!ce)
		return;

	if (ce->status < PCE_STATUS_ERROR) {
		if (ce->status == PCE_STATUS_ENABLED)
151
			clk_disable(ce->clk);
152

153 154
		if (ce->status >= PCE_STATUS_ACQUIRED) {
			clk_unprepare(ce->clk);
155
			clk_put(ce->clk);
156
		}
157 158
	}

159
	kfree(ce->con_id);
160 161 162 163
	kfree(ce);
}

/**
164 165
 * pm_clk_remove - Stop using a device clock for power management.
 * @dev: Device whose clock should not be used for PM any more.
166 167 168
 * @con_id: Connection ID of the clock.
 *
 * Remove the clock represented by @con_id from the list of clocks used for
169
 * the power management of @dev.
170
 */
171
void pm_clk_remove(struct device *dev, const char *con_id)
172
{
173
	struct pm_subsys_data *psd = dev_to_psd(dev);
174 175
	struct pm_clock_entry *ce;

176
	if (!psd)
177 178
		return;

179
	spin_lock_irq(&psd->lock);
180

181
	list_for_each_entry(ce, &psd->clock_list, node) {
182 183 184
		if (!con_id && !ce->con_id)
			goto remove;
		else if (!con_id || !ce->con_id)
185
			continue;
186 187
		else if (!strcmp(con_id, ce->con_id))
			goto remove;
188 189
	}

190
	spin_unlock_irq(&psd->lock);
191 192 193 194
	return;

 remove:
	list_del(&ce->node);
195
	spin_unlock_irq(&psd->lock);
196 197

	__pm_clk_remove(ce);
198 199 200
}

/**
201 202
 * pm_clk_init - Initialize a device's list of power management clocks.
 * @dev: Device to initialize the list of PM clocks for.
203
 *
204 205
 * Initialize the lock and clock_list members of the device's pm_subsys_data
 * object.
206
 */
207
void pm_clk_init(struct device *dev)
208
{
209
	struct pm_subsys_data *psd = dev_to_psd(dev);
210 211
	if (psd)
		INIT_LIST_HEAD(&psd->clock_list);
212 213 214 215 216 217 218 219 220 221 222
}

/**
 * pm_clk_create - Create and initialize a device's list of PM clocks.
 * @dev: Device to create and initialize the list of PM clocks for.
 *
 * Allocate a struct pm_subsys_data object, initialize its lock and clock_list
 * members and make the @dev's power.subsys_data field point to it.
 */
int pm_clk_create(struct device *dev)
{
223
	return dev_pm_get_subsys_data(dev);
224 225 226
}

/**
227 228
 * pm_clk_destroy - Destroy a device's list of power management clocks.
 * @dev: Device to destroy the list of PM clocks for.
229 230
 *
 * Clear the @dev's power.subsys_data field, remove the list of clock entries
231
 * from the struct pm_subsys_data object pointed to by it before and free
232 233
 * that object.
 */
234
void pm_clk_destroy(struct device *dev)
235
{
236
	struct pm_subsys_data *psd = dev_to_psd(dev);
237
	struct pm_clock_entry *ce, *c;
238
	struct list_head list;
239

240
	if (!psd)
241 242
		return;

243
	INIT_LIST_HEAD(&list);
244

245
	spin_lock_irq(&psd->lock);
246

247
	list_for_each_entry_safe_reverse(ce, c, &psd->clock_list, node)
248
		list_move(&ce->node, &list);
249

250
	spin_unlock_irq(&psd->lock);
251

252
	dev_pm_put_subsys_data(dev);
253 254 255 256 257

	list_for_each_entry_safe_reverse(ce, c, &list, node) {
		list_del(&ce->node);
		__pm_clk_remove(ce);
	}
258 259 260
}

/**
261
 * pm_clk_suspend - Disable clocks in a device's PM clock list.
262 263
 * @dev: Device to disable the clocks for.
 */
264
int pm_clk_suspend(struct device *dev)
265
{
266
	struct pm_subsys_data *psd = dev_to_psd(dev);
267
	struct pm_clock_entry *ce;
268
	unsigned long flags;
269 270 271

	dev_dbg(dev, "%s()\n", __func__);

272
	if (!psd)
273 274
		return 0;

275
	spin_lock_irqsave(&psd->lock, flags);
276

277
	list_for_each_entry_reverse(ce, &psd->clock_list, node) {
278
		if (ce->status < PCE_STATUS_ERROR) {
279 280
			if (ce->status == PCE_STATUS_ENABLED)
				clk_disable(ce->clk);
281 282 283 284
			ce->status = PCE_STATUS_ACQUIRED;
		}
	}

285
	spin_unlock_irqrestore(&psd->lock, flags);
286 287 288 289 290

	return 0;
}

/**
291
 * pm_clk_resume - Enable clocks in a device's PM clock list.
292 293
 * @dev: Device to enable the clocks for.
 */
294
int pm_clk_resume(struct device *dev)
295
{
296
	struct pm_subsys_data *psd = dev_to_psd(dev);
297
	struct pm_clock_entry *ce;
298
	unsigned long flags;
299 300 301

	dev_dbg(dev, "%s()\n", __func__);

302
	if (!psd)
303 304
		return 0;

305
	spin_lock_irqsave(&psd->lock, flags);
306

307 308
	list_for_each_entry(ce, &psd->clock_list, node)
		__pm_clk_enable(dev, ce);
309

310
	spin_unlock_irqrestore(&psd->lock, flags);
311 312 313 314 315

	return 0;
}

/**
316
 * pm_clk_notify - Notify routine for device addition and removal.
317 318 319 320 321 322
 * @nb: Notifier block object this function is a member of.
 * @action: Operation being carried out by the caller.
 * @data: Device the routine is being run for.
 *
 * For this function to work, @nb must be a member of an object of type
 * struct pm_clk_notifier_block containing all of the requisite data.
323 324
 * Specifically, the pm_domain member of that object is copied to the device's
 * pm_domain field and its con_ids member is used to populate the device's list
325
 * of PM clocks, depending on @action.
326
 *
327
 * If the device's pm_domain field is already populated with a value different
328 329 330
 * from the one stored in the struct pm_clk_notifier_block object, the function
 * does nothing.
 */
331
static int pm_clk_notify(struct notifier_block *nb,
332 333 334 335
				 unsigned long action, void *data)
{
	struct pm_clk_notifier_block *clknb;
	struct device *dev = data;
336
	char **con_id;
337 338 339 340 341 342 343 344
	int error;

	dev_dbg(dev, "%s() %ld\n", __func__, action);

	clknb = container_of(nb, struct pm_clk_notifier_block, nb);

	switch (action) {
	case BUS_NOTIFY_ADD_DEVICE:
345
		if (dev->pm_domain)
346 347
			break;

348
		error = pm_clk_create(dev);
349 350 351
		if (error)
			break;

352
		dev_pm_domain_set(dev, clknb->pm_domain);
353
		if (clknb->con_ids[0]) {
354
			for (con_id = clknb->con_ids; *con_id; con_id++)
355
				pm_clk_add(dev, *con_id);
356
		} else {
357
			pm_clk_add(dev, NULL);
358 359 360 361
		}

		break;
	case BUS_NOTIFY_DEL_DEVICE:
362
		if (dev->pm_domain != clknb->pm_domain)
363 364
			break;

365
		dev_pm_domain_set(dev, NULL);
366
		pm_clk_destroy(dev);
367 368 369 370 371 372
		break;
	}

	return 0;
}

373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409
int pm_clk_runtime_suspend(struct device *dev)
{
	int ret;

	dev_dbg(dev, "%s\n", __func__);

	ret = pm_generic_runtime_suspend(dev);
	if (ret) {
		dev_err(dev, "failed to suspend device\n");
		return ret;
	}

	ret = pm_clk_suspend(dev);
	if (ret) {
		dev_err(dev, "failed to suspend clock\n");
		pm_generic_runtime_resume(dev);
		return ret;
	}

	return 0;
}

int pm_clk_runtime_resume(struct device *dev)
{
	int ret;

	dev_dbg(dev, "%s\n", __func__);

	ret = pm_clk_resume(dev);
	if (ret) {
		dev_err(dev, "failed to resume clock\n");
		return ret;
	}

	return pm_generic_runtime_resume(dev);
}

410
#else /* !CONFIG_PM_CLK */
411

412 413 414 415 416 417 418 419 420 421 422
/**
 * enable_clock - Enable a device clock.
 * @dev: Device whose clock is to be enabled.
 * @con_id: Connection ID of the clock.
 */
static void enable_clock(struct device *dev, const char *con_id)
{
	struct clk *clk;

	clk = clk_get(dev, con_id);
	if (!IS_ERR(clk)) {
423
		clk_prepare_enable(clk);
424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439
		clk_put(clk);
		dev_info(dev, "Runtime PM disabled, clock forced on.\n");
	}
}

/**
 * disable_clock - Disable a device clock.
 * @dev: Device whose clock is to be disabled.
 * @con_id: Connection ID of the clock.
 */
static void disable_clock(struct device *dev, const char *con_id)
{
	struct clk *clk;

	clk = clk_get(dev, con_id);
	if (!IS_ERR(clk)) {
440
		clk_disable_unprepare(clk);
441 442 443 444 445 446
		clk_put(clk);
		dev_info(dev, "Runtime PM disabled, clock forced off.\n");
	}
}

/**
447
 * pm_clk_notify - Notify routine for device addition and removal.
448 449 450 451 452 453 454 455 456
 * @nb: Notifier block object this function is a member of.
 * @action: Operation being carried out by the caller.
 * @data: Device the routine is being run for.
 *
 * For this function to work, @nb must be a member of an object of type
 * struct pm_clk_notifier_block containing all of the requisite data.
 * Specifically, the con_ids member of that object is used to enable or disable
 * the device's clocks, depending on @action.
 */
457
static int pm_clk_notify(struct notifier_block *nb,
458 459 460 461
				 unsigned long action, void *data)
{
	struct pm_clk_notifier_block *clknb;
	struct device *dev = data;
462
	char **con_id;
463 464 465 466 467 468

	dev_dbg(dev, "%s() %ld\n", __func__, action);

	clknb = container_of(nb, struct pm_clk_notifier_block, nb);

	switch (action) {
469
	case BUS_NOTIFY_BIND_DRIVER:
470
		if (clknb->con_ids[0]) {
471 472
			for (con_id = clknb->con_ids; *con_id; con_id++)
				enable_clock(dev, *con_id);
473 474 475 476
		} else {
			enable_clock(dev, NULL);
		}
		break;
477
	case BUS_NOTIFY_DRIVER_NOT_BOUND:
478
	case BUS_NOTIFY_UNBOUND_DRIVER:
479
		if (clknb->con_ids[0]) {
480 481
			for (con_id = clknb->con_ids; *con_id; con_id++)
				disable_clock(dev, *con_id);
482 483 484 485 486 487 488 489 490
		} else {
			disable_clock(dev, NULL);
		}
		break;
	}

	return 0;
}

491
#endif /* !CONFIG_PM_CLK */
492 493

/**
494
 * pm_clk_add_notifier - Add bus type notifier for power management clocks.
495 496 497 498
 * @bus: Bus type to add the notifier to.
 * @clknb: Notifier to be added to the given bus type.
 *
 * The nb member of @clknb is not expected to be initialized and its
499
 * notifier_call member will be replaced with pm_clk_notify().  However,
500 501 502
 * the remaining members of @clknb should be populated prior to calling this
 * routine.
 */
503
void pm_clk_add_notifier(struct bus_type *bus,
504 505 506 507 508
				 struct pm_clk_notifier_block *clknb)
{
	if (!bus || !clknb)
		return;

509
	clknb->nb.notifier_call = pm_clk_notify;
510 511
	bus_register_notifier(bus, &clknb->nb);
}