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