/drivers/base/power/clock_ops.c
C | 431 lines | 255 code | 71 blank | 105 comment | 49 complexity | 0689e5094c78b913bf0041f34a291297 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, AGPL-1.0
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_RUNTIME 19 20struct pm_runtime_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_runtime_clk_data *__to_prd(struct device *dev) 40{ 41 return dev ? dev->power.subsys_data : NULL; 42} 43 44/** 45 * pm_runtime_clk_add - Start using a device clock for runtime PM. 46 * @dev: Device whose clock is going to be used for runtime PM. 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 runtime PM of @dev. 51 */ 52int pm_runtime_clk_add(struct device *dev, const char *con_id) 53{ 54 struct pm_runtime_clk_data *prd = __to_prd(dev); 55 struct pm_clock_entry *ce; 56 57 if (!prd) 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(&prd->lock); 77 list_add_tail(&ce->node, &prd->clock_list); 78 mutex_unlock(&prd->lock); 79 return 0; 80} 81 82/** 83 * __pm_runtime_clk_remove - Destroy runtime PM clock entry. 84 * @ce: Runtime PM clock entry to destroy. 85 * 86 * This routine must be called under the mutex protecting the runtime PM list 87 * of clocks corresponding the the @ce's device. 88 */ 89static void __pm_runtime_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_runtime_clk_remove - Stop using a device clock for runtime PM. 112 * @dev: Device whose clock should not be used for runtime 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 runtime PM of @dev. 117 */ 118void pm_runtime_clk_remove(struct device *dev, const char *con_id) 119{ 120 struct pm_runtime_clk_data *prd = __to_prd(dev); 121 struct pm_clock_entry *ce; 122 123 if (!prd) 124 return; 125 126 mutex_lock(&prd->lock); 127 128 list_for_each_entry(ce, &prd->clock_list, node) { 129 if (!con_id && !ce->con_id) { 130 __pm_runtime_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_runtime_clk_remove(ce); 136 break; 137 } 138 } 139 140 mutex_unlock(&prd->lock); 141} 142 143/** 144 * pm_runtime_clk_init - Initialize a device's list of runtime PM clocks. 145 * @dev: Device to initialize the list of runtime PM clocks for. 146 * 147 * Allocate a struct pm_runtime_clk_data object, initialize its lock member and 148 * make the @dev's power.subsys_data field point to it. 149 */ 150int pm_runtime_clk_init(struct device *dev) 151{ 152 struct pm_runtime_clk_data *prd; 153 154 prd = kzalloc(sizeof(*prd), GFP_KERNEL); 155 if (!prd) { 156 dev_err(dev, "Not enough memory fo runtime PM data.\n"); 157 return -ENOMEM; 158 } 159 160 INIT_LIST_HEAD(&prd->clock_list); 161 mutex_init(&prd->lock); 162 dev->power.subsys_data = prd; 163 return 0; 164} 165 166/** 167 * pm_runtime_clk_destroy - Destroy a device's list of runtime PM clocks. 168 * @dev: Device to destroy the list of runtime PM clocks for. 169 * 170 * Clear the @dev's power.subsys_data field, remove the list of clock entries 171 * from the struct pm_runtime_clk_data object pointed to by it before and free 172 * that object. 173 */ 174void pm_runtime_clk_destroy(struct device *dev) 175{ 176 struct pm_runtime_clk_data *prd = __to_prd(dev); 177 struct pm_clock_entry *ce, *c; 178 179 if (!prd) 180 return; 181 182 dev->power.subsys_data = NULL; 183 184 mutex_lock(&prd->lock); 185 186 list_for_each_entry_safe_reverse(ce, c, &prd->clock_list, node) 187 __pm_runtime_clk_remove(ce); 188 189 mutex_unlock(&prd->lock); 190 191 kfree(prd); 192} 193 194/** 195 * pm_runtime_clk_acquire - Acquire a device clock. 196 * @dev: Device whose clock is to be acquired. 197 * @con_id: Connection ID of the clock. 198 */ 199static void pm_runtime_clk_acquire(struct device *dev, 200 struct pm_clock_entry *ce) 201{ 202 ce->clk = clk_get(dev, ce->con_id); 203 if (IS_ERR(ce->clk)) { 204 ce->status = PCE_STATUS_ERROR; 205 } else { 206 ce->status = PCE_STATUS_ACQUIRED; 207 dev_dbg(dev, "Clock %s managed by runtime PM.\n", ce->con_id); 208 } 209} 210 211/** 212 * pm_runtime_clk_suspend - Disable clocks in a device's runtime PM clock list. 213 * @dev: Device to disable the clocks for. 214 */ 215int pm_runtime_clk_suspend(struct device *dev) 216{ 217 struct pm_runtime_clk_data *prd = __to_prd(dev); 218 struct pm_clock_entry *ce; 219 220 dev_dbg(dev, "%s()\n", __func__); 221 222 if (!prd) 223 return 0; 224 225 mutex_lock(&prd->lock); 226 227 list_for_each_entry_reverse(ce, &prd->clock_list, node) { 228 if (ce->status == PCE_STATUS_NONE) 229 pm_runtime_clk_acquire(dev, ce); 230 231 if (ce->status < PCE_STATUS_ERROR) { 232 clk_disable(ce->clk); 233 ce->status = PCE_STATUS_ACQUIRED; 234 } 235 } 236 237 mutex_unlock(&prd->lock); 238 239 return 0; 240} 241 242/** 243 * pm_runtime_clk_resume - Enable clocks in a device's runtime PM clock list. 244 * @dev: Device to enable the clocks for. 245 */ 246int pm_runtime_clk_resume(struct device *dev) 247{ 248 struct pm_runtime_clk_data *prd = __to_prd(dev); 249 struct pm_clock_entry *ce; 250 251 dev_dbg(dev, "%s()\n", __func__); 252 253 if (!prd) 254 return 0; 255 256 mutex_lock(&prd->lock); 257 258 list_for_each_entry(ce, &prd->clock_list, node) { 259 if (ce->status == PCE_STATUS_NONE) 260 pm_runtime_clk_acquire(dev, ce); 261 262 if (ce->status < PCE_STATUS_ERROR) { 263 clk_enable(ce->clk); 264 ce->status = PCE_STATUS_ENABLED; 265 } 266 } 267 268 mutex_unlock(&prd->lock); 269 270 return 0; 271} 272 273/** 274 * pm_runtime_clk_notify - Notify routine for device addition and removal. 275 * @nb: Notifier block object this function is a member of. 276 * @action: Operation being carried out by the caller. 277 * @data: Device the routine is being run for. 278 * 279 * For this function to work, @nb must be a member of an object of type 280 * struct pm_clk_notifier_block containing all of the requisite data. 281 * Specifically, the pwr_domain member of that object is copied to the device's 282 * pwr_domain field and its con_ids member is used to populate the device's list 283 * of runtime PM clocks, depending on @action. 284 * 285 * If the device's pwr_domain field is already populated with a value different 286 * from the one stored in the struct pm_clk_notifier_block object, the function 287 * does nothing. 288 */ 289static int pm_runtime_clk_notify(struct notifier_block *nb, 290 unsigned long action, void *data) 291{ 292 struct pm_clk_notifier_block *clknb; 293 struct device *dev = data; 294 char **con_id; 295 int error; 296 297 dev_dbg(dev, "%s() %ld\n", __func__, action); 298 299 clknb = container_of(nb, struct pm_clk_notifier_block, nb); 300 301 switch (action) { 302 case BUS_NOTIFY_ADD_DEVICE: 303 if (dev->pwr_domain) 304 break; 305 306 error = pm_runtime_clk_init(dev); 307 if (error) 308 break; 309 310 dev->pwr_domain = clknb->pwr_domain; 311 if (clknb->con_ids[0]) { 312 for (con_id = clknb->con_ids; *con_id; con_id++) 313 pm_runtime_clk_add(dev, *con_id); 314 } else { 315 pm_runtime_clk_add(dev, NULL); 316 } 317 318 break; 319 case BUS_NOTIFY_DEL_DEVICE: 320 if (dev->pwr_domain != clknb->pwr_domain) 321 break; 322 323 dev->pwr_domain = NULL; 324 pm_runtime_clk_destroy(dev); 325 break; 326 } 327 328 return 0; 329} 330 331#else /* !CONFIG_PM_RUNTIME */ 332 333/** 334 * enable_clock - Enable a device clock. 335 * @dev: Device whose clock is to be enabled. 336 * @con_id: Connection ID of the clock. 337 */ 338static void enable_clock(struct device *dev, const char *con_id) 339{ 340 struct clk *clk; 341 342 clk = clk_get(dev, con_id); 343 if (!IS_ERR(clk)) { 344 clk_enable(clk); 345 clk_put(clk); 346 dev_info(dev, "Runtime PM disabled, clock forced on.\n"); 347 } 348} 349 350/** 351 * disable_clock - Disable a device clock. 352 * @dev: Device whose clock is to be disabled. 353 * @con_id: Connection ID of the clock. 354 */ 355static void disable_clock(struct device *dev, const char *con_id) 356{ 357 struct clk *clk; 358 359 clk = clk_get(dev, con_id); 360 if (!IS_ERR(clk)) { 361 clk_disable(clk); 362 clk_put(clk); 363 dev_info(dev, "Runtime PM disabled, clock forced off.\n"); 364 } 365} 366 367/** 368 * pm_runtime_clk_notify - Notify routine for device addition and removal. 369 * @nb: Notifier block object this function is a member of. 370 * @action: Operation being carried out by the caller. 371 * @data: Device the routine is being run for. 372 * 373 * For this function to work, @nb must be a member of an object of type 374 * struct pm_clk_notifier_block containing all of the requisite data. 375 * Specifically, the con_ids member of that object is used to enable or disable 376 * the device's clocks, depending on @action. 377 */ 378static int pm_runtime_clk_notify(struct notifier_block *nb, 379 unsigned long action, void *data) 380{ 381 struct pm_clk_notifier_block *clknb; 382 struct device *dev = data; 383 char **con_id; 384 385 dev_dbg(dev, "%s() %ld\n", __func__, action); 386 387 clknb = container_of(nb, struct pm_clk_notifier_block, nb); 388 389 switch (action) { 390 case BUS_NOTIFY_BIND_DRIVER: 391 if (clknb->con_ids[0]) { 392 for (con_id = clknb->con_ids; *con_id; con_id++) 393 enable_clock(dev, *con_id); 394 } else { 395 enable_clock(dev, NULL); 396 } 397 break; 398 case BUS_NOTIFY_UNBOUND_DRIVER: 399 if (clknb->con_ids[0]) { 400 for (con_id = clknb->con_ids; *con_id; con_id++) 401 disable_clock(dev, *con_id); 402 } else { 403 disable_clock(dev, NULL); 404 } 405 break; 406 } 407 408 return 0; 409} 410 411#endif /* !CONFIG_PM_RUNTIME */ 412 413/** 414 * pm_runtime_clk_add_notifier - Add bus type notifier for runtime PM clocks. 415 * @bus: Bus type to add the notifier to. 416 * @clknb: Notifier to be added to the given bus type. 417 * 418 * The nb member of @clknb is not expected to be initialized and its 419 * notifier_call member will be replaced with pm_runtime_clk_notify(). However, 420 * the remaining members of @clknb should be populated prior to calling this 421 * routine. 422 */ 423void pm_runtime_clk_add_notifier(struct bus_type *bus, 424 struct pm_clk_notifier_block *clknb) 425{ 426 if (!bus || !clknb) 427 return; 428 429 clknb->nb.notifier_call = pm_runtime_clk_notify; 430 bus_register_notifier(bus, &clknb->nb); 431}