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