clock_ops.c 10.9 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
/*
 * 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/init.h>
#include <linux/kernel.h>
#include <linux/io.h>
#include <linux/pm.h>
#include <linux/pm_runtime.h>
#include <linux/clk.h>
#include <linux/slab.h>
#include <linux/err.h>

18
#ifdef CONFIG_PM
19

20
struct pm_clk_data {
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
	struct list_head clock_list;
	struct mutex lock;
};

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;
};

39
static struct pm_clk_data *__to_pcd(struct device *dev)
40 41 42 43 44
{
	return dev ? dev->power.subsys_data : NULL;
}

/**
45 46
 * pm_clk_add - Start using a device clock for power management.
 * @dev: Device whose clock is going to be used for power management.
47 48 49
 * @con_id: Connection ID of the clock.
 *
 * Add the clock represented by @con_id to the list of clocks used for
50
 * the power management of @dev.
51
 */
52
int pm_clk_add(struct device *dev, const char *con_id)
53
{
54
	struct pm_clk_data *pcd = __to_pcd(dev);
55 56
	struct pm_clock_entry *ce;

57
	if (!pcd)
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
		return -EINVAL;

	ce = kzalloc(sizeof(*ce), GFP_KERNEL);
	if (!ce) {
		dev_err(dev, "Not enough memory for clock entry.\n");
		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;
		}
	}

76 77 78
	mutex_lock(&pcd->lock);
	list_add_tail(&ce->node, &pcd->clock_list);
	mutex_unlock(&pcd->lock);
79 80 81 82
	return 0;
}

/**
83 84
 * __pm_clk_remove - Destroy PM clock entry.
 * @ce: PM clock entry to destroy.
85
 *
86 87
 * This routine must be called under the mutex protecting the PM list of clocks
 * corresponding the the @ce's device.
88
 */
89
static void __pm_clk_remove(struct pm_clock_entry *ce)
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
{
	if (!ce)
		return;

	list_del(&ce->node);

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

		if (ce->status >= PCE_STATUS_ACQUIRED)
			clk_put(ce->clk);
	}

	if (ce->con_id)
		kfree(ce->con_id);

	kfree(ce);
}

/**
111 112
 * pm_clk_remove - Stop using a device clock for power management.
 * @dev: Device whose clock should not be used for PM any more.
113 114 115
 * @con_id: Connection ID of the clock.
 *
 * Remove the clock represented by @con_id from the list of clocks used for
116
 * the power management of @dev.
117
 */
118
void pm_clk_remove(struct device *dev, const char *con_id)
119
{
120
	struct pm_clk_data *pcd = __to_pcd(dev);
121 122
	struct pm_clock_entry *ce;

123
	if (!pcd)
124 125
		return;

126
	mutex_lock(&pcd->lock);
127

128
	list_for_each_entry(ce, &pcd->clock_list, node) {
129
		if (!con_id && !ce->con_id) {
130
			__pm_clk_remove(ce);
131 132 133 134
			break;
		} else if (!con_id || !ce->con_id) {
			continue;
		} else if (!strcmp(con_id, ce->con_id)) {
135
			__pm_clk_remove(ce);
136 137 138 139
			break;
		}
	}

140
	mutex_unlock(&pcd->lock);
141 142 143
}

/**
144 145
 * pm_clk_init - Initialize a device's list of power management clocks.
 * @dev: Device to initialize the list of PM clocks for.
146
 *
147
 * Allocate a struct pm_clk_data object, initialize its lock member and
148 149
 * make the @dev's power.subsys_data field point to it.
 */
150
int pm_clk_init(struct device *dev)
151
{
152
	struct pm_clk_data *pcd;
153

154 155 156
	pcd = kzalloc(sizeof(*pcd), GFP_KERNEL);
	if (!pcd) {
		dev_err(dev, "Not enough memory for PM clock data.\n");
157 158 159
		return -ENOMEM;
	}

160 161 162
	INIT_LIST_HEAD(&pcd->clock_list);
	mutex_init(&pcd->lock);
	dev->power.subsys_data = pcd;
163 164 165 166
	return 0;
}

/**
167 168
 * pm_clk_destroy - Destroy a device's list of power management clocks.
 * @dev: Device to destroy the list of PM clocks for.
169 170
 *
 * Clear the @dev's power.subsys_data field, remove the list of clock entries
171
 * from the struct pm_clk_data object pointed to by it before and free
172 173
 * that object.
 */
174
void pm_clk_destroy(struct device *dev)
175
{
176
	struct pm_clk_data *pcd = __to_pcd(dev);
177 178
	struct pm_clock_entry *ce, *c;

179
	if (!pcd)
180 181 182 183
		return;

	dev->power.subsys_data = NULL;

184
	mutex_lock(&pcd->lock);
185

186 187
	list_for_each_entry_safe_reverse(ce, c, &pcd->clock_list, node)
		__pm_clk_remove(ce);
188

189
	mutex_unlock(&pcd->lock);
190

191
	kfree(pcd);
192 193
}

194 195 196 197
#endif /* CONFIG_PM */

#ifdef CONFIG_PM_RUNTIME

198
/**
199
 * pm_clk_acquire - Acquire a device clock.
200 201 202
 * @dev: Device whose clock is to be acquired.
 * @con_id: Connection ID of the clock.
 */
203
static void pm_clk_acquire(struct device *dev,
204 205 206 207 208 209 210 211 212 213 214 215
				    struct pm_clock_entry *ce)
{
	ce->clk = clk_get(dev, ce->con_id);
	if (IS_ERR(ce->clk)) {
		ce->status = PCE_STATUS_ERROR;
	} else {
		ce->status = PCE_STATUS_ACQUIRED;
		dev_dbg(dev, "Clock %s managed by runtime PM.\n", ce->con_id);
	}
}

/**
216
 * pm_clk_suspend - Disable clocks in a device's PM clock list.
217 218
 * @dev: Device to disable the clocks for.
 */
219
int pm_clk_suspend(struct device *dev)
220
{
221
	struct pm_clk_data *pcd = __to_pcd(dev);
222 223 224 225
	struct pm_clock_entry *ce;

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

226
	if (!pcd)
227 228
		return 0;

229
	mutex_lock(&pcd->lock);
230

231
	list_for_each_entry_reverse(ce, &pcd->clock_list, node) {
232
		if (ce->status == PCE_STATUS_NONE)
233
			pm_clk_acquire(dev, ce);
234 235 236 237 238 239 240

		if (ce->status < PCE_STATUS_ERROR) {
			clk_disable(ce->clk);
			ce->status = PCE_STATUS_ACQUIRED;
		}
	}

241
	mutex_unlock(&pcd->lock);
242 243 244 245 246

	return 0;
}

/**
247
 * pm_clk_resume - Enable clocks in a device's PM clock list.
248 249
 * @dev: Device to enable the clocks for.
 */
250
int pm_clk_resume(struct device *dev)
251
{
252
	struct pm_clk_data *pcd = __to_pcd(dev);
253 254 255 256
	struct pm_clock_entry *ce;

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

257
	if (!pcd)
258 259
		return 0;

260
	mutex_lock(&pcd->lock);
261

262
	list_for_each_entry(ce, &pcd->clock_list, node) {
263
		if (ce->status == PCE_STATUS_NONE)
264
			pm_clk_acquire(dev, ce);
265 266 267 268 269 270 271

		if (ce->status < PCE_STATUS_ERROR) {
			clk_enable(ce->clk);
			ce->status = PCE_STATUS_ENABLED;
		}
	}

272
	mutex_unlock(&pcd->lock);
273 274 275 276 277

	return 0;
}

/**
278
 * pm_clk_notify - Notify routine for device addition and removal.
279 280 281 282 283 284
 * @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.
285 286
 * 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
287
 * of PM clocks, depending on @action.
288
 *
289
 * If the device's pm_domain field is already populated with a value different
290 291 292
 * from the one stored in the struct pm_clk_notifier_block object, the function
 * does nothing.
 */
293
static int pm_clk_notify(struct notifier_block *nb,
294 295 296 297
				 unsigned long action, void *data)
{
	struct pm_clk_notifier_block *clknb;
	struct device *dev = data;
298
	char **con_id;
299 300 301 302 303 304 305 306
	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:
307
		if (dev->pm_domain)
308 309
			break;

310
		error = pm_clk_init(dev);
311 312 313
		if (error)
			break;

314
		dev->pm_domain = clknb->pm_domain;
315
		if (clknb->con_ids[0]) {
316
			for (con_id = clknb->con_ids; *con_id; con_id++)
317
				pm_clk_add(dev, *con_id);
318
		} else {
319
			pm_clk_add(dev, NULL);
320 321 322 323
		}

		break;
	case BUS_NOTIFY_DEL_DEVICE:
324
		if (dev->pm_domain != clknb->pm_domain)
325 326
			break;

327
		dev->pm_domain = NULL;
328
		pm_clk_destroy(dev);
329 330 331 332 333 334 335 336
		break;
	}

	return 0;
}

#else /* !CONFIG_PM_RUNTIME */

337 338 339
#ifdef CONFIG_PM

/**
340
 * pm_clk_suspend - Disable clocks in a device's PM clock list.
341 342
 * @dev: Device to disable the clocks for.
 */
343
int pm_clk_suspend(struct device *dev)
344
{
345
	struct pm_clk_data *pcd = __to_pcd(dev);
346 347 348 349 350
	struct pm_clock_entry *ce;

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

	/* If there is no driver, the clocks are already disabled. */
351
	if (!pcd || !dev->driver)
352 353
		return 0;

354
	mutex_lock(&pcd->lock);
355

356
	list_for_each_entry_reverse(ce, &pcd->clock_list, node)
357 358
		clk_disable(ce->clk);

359
	mutex_unlock(&pcd->lock);
360 361 362 363 364

	return 0;
}

/**
365
 * pm_clk_resume - Enable clocks in a device's PM clock list.
366 367
 * @dev: Device to enable the clocks for.
 */
368
int pm_clk_resume(struct device *dev)
369
{
370
	struct pm_clk_data *pcd = __to_pcd(dev);
371 372 373 374 375
	struct pm_clock_entry *ce;

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

	/* If there is no driver, the clocks should remain disabled. */
376
	if (!pcd || !dev->driver)
377 378
		return 0;

379
	mutex_lock(&pcd->lock);
380

381
	list_for_each_entry(ce, &pcd->clock_list, node)
382 383
		clk_enable(ce->clk);

384
	mutex_unlock(&pcd->lock);
385 386 387 388 389 390

	return 0;
}

#endif /* CONFIG_PM */

391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425
/**
 * 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)) {
		clk_enable(clk);
		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)) {
		clk_disable(clk);
		clk_put(clk);
		dev_info(dev, "Runtime PM disabled, clock forced off.\n");
	}
}

/**
426
 * pm_clk_notify - Notify routine for device addition and removal.
427 428 429 430 431 432 433 434 435
 * @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.
 */
436
static int pm_clk_notify(struct notifier_block *nb,
437 438 439 440
				 unsigned long action, void *data)
{
	struct pm_clk_notifier_block *clknb;
	struct device *dev = data;
441
	char **con_id;
442 443 444 445 446 447

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

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

	switch (action) {
448
	case BUS_NOTIFY_BIND_DRIVER:
449
		if (clknb->con_ids[0]) {
450 451
			for (con_id = clknb->con_ids; *con_id; con_id++)
				enable_clock(dev, *con_id);
452 453 454 455
		} else {
			enable_clock(dev, NULL);
		}
		break;
456
	case BUS_NOTIFY_UNBOUND_DRIVER:
457
		if (clknb->con_ids[0]) {
458 459
			for (con_id = clknb->con_ids; *con_id; con_id++)
				disable_clock(dev, *con_id);
460 461 462 463 464 465 466 467 468 469 470 471
		} else {
			disable_clock(dev, NULL);
		}
		break;
	}

	return 0;
}

#endif /* !CONFIG_PM_RUNTIME */

/**
472
 * pm_clk_add_notifier - Add bus type notifier for power management clocks.
473 474 475 476
 * @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
477
 * notifier_call member will be replaced with pm_clk_notify().  However,
478 479 480
 * the remaining members of @clknb should be populated prior to calling this
 * routine.
 */
481
void pm_clk_add_notifier(struct bus_type *bus,
482 483 484 485 486
				 struct pm_clk_notifier_block *clknb)
{
	if (!bus || !clknb)
		return;

487
	clknb->nb.notifier_call = pm_clk_notify;
488 489
	bus_register_notifier(bus, &clknb->nb);
}