Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'pm-clk' into pm-runtime

+61 -32
+53 -32
drivers/base/power/clock_ops.c
··· 12 12 #include <linux/pm.h> 13 13 #include <linux/pm_clock.h> 14 14 #include <linux/clk.h> 15 + #include <linux/clkdev.h> 15 16 #include <linux/slab.h> 16 17 #include <linux/err.h> 17 18 ··· 35 34 /** 36 35 * pm_clk_enable - Enable a clock, reporting any errors 37 36 * @dev: The device for the given clock 38 - * @clk: The clock being enabled. 37 + * @ce: PM clock entry corresponding to the clock. 39 38 */ 40 - static inline int __pm_clk_enable(struct device *dev, struct clk *clk) 39 + static inline int __pm_clk_enable(struct device *dev, struct pm_clock_entry *ce) 41 40 { 42 - int ret = clk_enable(clk); 43 - if (ret) 44 - dev_err(dev, "%s: failed to enable clk %p, error %d\n", 45 - __func__, clk, ret); 41 + int ret; 42 + 43 + if (ce->status < PCE_STATUS_ERROR) { 44 + ret = clk_enable(ce->clk); 45 + if (!ret) 46 + ce->status = PCE_STATUS_ENABLED; 47 + else 48 + dev_err(dev, "%s: failed to enable clk %p, error %d\n", 49 + __func__, ce->clk, ret); 50 + } 46 51 47 52 return ret; 48 53 } ··· 60 53 */ 61 54 static void pm_clk_acquire(struct device *dev, struct pm_clock_entry *ce) 62 55 { 63 - ce->clk = clk_get(dev, ce->con_id); 56 + if (!ce->clk) 57 + ce->clk = clk_get(dev, ce->con_id); 64 58 if (IS_ERR(ce->clk)) { 65 59 ce->status = PCE_STATUS_ERROR; 66 60 } else { ··· 71 63 } 72 64 } 73 65 74 - /** 75 - * pm_clk_add - Start using a device clock for power management. 76 - * @dev: Device whose clock is going to be used for power management. 77 - * @con_id: Connection ID of the clock. 78 - * 79 - * Add the clock represented by @con_id to the list of clocks used for 80 - * the power management of @dev. 81 - */ 82 - int pm_clk_add(struct device *dev, const char *con_id) 66 + static int __pm_clk_add(struct device *dev, const char *con_id, 67 + struct clk *clk) 83 68 { 84 69 struct pm_subsys_data *psd = dev_to_psd(dev); 85 70 struct pm_clock_entry *ce; ··· 94 93 kfree(ce); 95 94 return -ENOMEM; 96 95 } 96 + } else { 97 + if (IS_ERR(ce->clk) || !__clk_get(clk)) { 98 + kfree(ce); 99 + return -ENOENT; 100 + } 101 + ce->clk = clk; 97 102 } 98 103 99 104 pm_clk_acquire(dev, ce); ··· 108 101 list_add_tail(&ce->node, &psd->clock_list); 109 102 spin_unlock_irq(&psd->lock); 110 103 return 0; 104 + } 105 + 106 + /** 107 + * pm_clk_add - Start using a device clock for power management. 108 + * @dev: Device whose clock is going to be used for power management. 109 + * @con_id: Connection ID of the clock. 110 + * 111 + * Add the clock represented by @con_id to the list of clocks used for 112 + * the power management of @dev. 113 + */ 114 + int pm_clk_add(struct device *dev, const char *con_id) 115 + { 116 + return __pm_clk_add(dev, con_id, NULL); 117 + } 118 + 119 + /** 120 + * pm_clk_add_clk - Start using a device clock for power management. 121 + * @dev: Device whose clock is going to be used for power management. 122 + * @clk: Clock pointer 123 + * 124 + * Add the clock to the list of clocks used for the power management of @dev. 125 + * It will increment refcount on clock pointer, use clk_put() on it when done. 126 + */ 127 + int pm_clk_add_clk(struct device *dev, struct clk *clk) 128 + { 129 + return __pm_clk_add(dev, NULL, clk); 111 130 } 112 131 113 132 /** ··· 299 266 struct pm_subsys_data *psd = dev_to_psd(dev); 300 267 struct pm_clock_entry *ce; 301 268 unsigned long flags; 302 - int ret; 303 269 304 270 dev_dbg(dev, "%s()\n", __func__); 305 271 ··· 307 275 308 276 spin_lock_irqsave(&psd->lock, flags); 309 277 310 - list_for_each_entry(ce, &psd->clock_list, node) { 311 - if (ce->status < PCE_STATUS_ERROR) { 312 - ret = __pm_clk_enable(dev, ce->clk); 313 - if (!ret) 314 - ce->status = PCE_STATUS_ENABLED; 315 - } 316 - } 278 + list_for_each_entry(ce, &psd->clock_list, node) 279 + __pm_clk_enable(dev, ce); 317 280 318 281 spin_unlock_irqrestore(&psd->lock, flags); 319 282 ··· 417 390 struct pm_subsys_data *psd = dev_to_psd(dev); 418 391 struct pm_clock_entry *ce; 419 392 unsigned long flags; 420 - int ret; 421 393 422 394 dev_dbg(dev, "%s()\n", __func__); 423 395 ··· 426 400 427 401 spin_lock_irqsave(&psd->lock, flags); 428 402 429 - list_for_each_entry(ce, &psd->clock_list, node) { 430 - if (ce->status < PCE_STATUS_ERROR) { 431 - ret = __pm_clk_enable(dev, ce->clk); 432 - if (!ret) 433 - ce->status = PCE_STATUS_ENABLED; 434 - } 435 - } 403 + list_for_each_entry(ce, &psd->clock_list, node) 404 + __pm_clk_enable(dev, ce); 436 405 437 406 spin_unlock_irqrestore(&psd->lock, flags); 438 407
+8
include/linux/pm_clock.h
··· 18 18 char *con_ids[]; 19 19 }; 20 20 21 + struct clk; 22 + 21 23 #ifdef CONFIG_PM_CLK 22 24 static inline bool pm_clk_no_clocks(struct device *dev) 23 25 { ··· 31 29 extern int pm_clk_create(struct device *dev); 32 30 extern void pm_clk_destroy(struct device *dev); 33 31 extern int pm_clk_add(struct device *dev, const char *con_id); 32 + extern int pm_clk_add_clk(struct device *dev, struct clk *clk); 34 33 extern void pm_clk_remove(struct device *dev, const char *con_id); 35 34 extern int pm_clk_suspend(struct device *dev); 36 35 extern int pm_clk_resume(struct device *dev); ··· 51 48 { 52 49 } 53 50 static inline int pm_clk_add(struct device *dev, const char *con_id) 51 + { 52 + return -EINVAL; 53 + } 54 + 55 + static inline int pm_clk_add_clk(struct device *dev, struct clk *clk) 54 56 { 55 57 return -EINVAL; 56 58 }