···1212#include <linux/pm.h>1313#include <linux/pm_clock.h>1414#include <linux/clk.h>1515+#include <linux/clkdev.h>1516#include <linux/slab.h>1617#include <linux/err.h>1718···3534/**3635 * pm_clk_enable - Enable a clock, reporting any errors3736 * @dev: The device for the given clock3838- * @clk: The clock being enabled.3737+ * @ce: PM clock entry corresponding to the clock.3938 */4040-static inline int __pm_clk_enable(struct device *dev, struct clk *clk)3939+static inline int __pm_clk_enable(struct device *dev, struct pm_clock_entry *ce)4140{4242- int ret = clk_enable(clk);4343- if (ret)4444- dev_err(dev, "%s: failed to enable clk %p, error %d\n",4545- __func__, clk, ret);4141+ int ret;4242+4343+ if (ce->status < PCE_STATUS_ERROR) {4444+ ret = clk_enable(ce->clk);4545+ if (!ret)4646+ ce->status = PCE_STATUS_ENABLED;4747+ else4848+ dev_err(dev, "%s: failed to enable clk %p, error %d\n",4949+ __func__, ce->clk, ret);5050+ }46514752 return ret;4853}···6053 */6154static void pm_clk_acquire(struct device *dev, struct pm_clock_entry *ce)6255{6363- ce->clk = clk_get(dev, ce->con_id);5656+ if (!ce->clk)5757+ ce->clk = clk_get(dev, ce->con_id);6458 if (IS_ERR(ce->clk)) {6559 ce->status = PCE_STATUS_ERROR;6660 } else {···7163 }7264}73657474-/**7575- * pm_clk_add - Start using a device clock for power management.7676- * @dev: Device whose clock is going to be used for power management.7777- * @con_id: Connection ID of the clock.7878- *7979- * Add the clock represented by @con_id to the list of clocks used for8080- * the power management of @dev.8181- */8282-int pm_clk_add(struct device *dev, const char *con_id)6666+static int __pm_clk_add(struct device *dev, const char *con_id,6767+ struct clk *clk)8368{8469 struct pm_subsys_data *psd = dev_to_psd(dev);8570 struct pm_clock_entry *ce;···9493 kfree(ce);9594 return -ENOMEM;9695 }9696+ } else {9797+ if (IS_ERR(ce->clk) || !__clk_get(clk)) {9898+ kfree(ce);9999+ return -ENOENT;100100+ }101101+ ce->clk = clk;97102 }9810399104 pm_clk_acquire(dev, ce);···108101 list_add_tail(&ce->node, &psd->clock_list);109102 spin_unlock_irq(&psd->lock);110103 return 0;104104+}105105+106106+/**107107+ * pm_clk_add - Start using a device clock for power management.108108+ * @dev: Device whose clock is going to be used for power management.109109+ * @con_id: Connection ID of the clock.110110+ *111111+ * Add the clock represented by @con_id to the list of clocks used for112112+ * the power management of @dev.113113+ */114114+int pm_clk_add(struct device *dev, const char *con_id)115115+{116116+ return __pm_clk_add(dev, con_id, NULL);117117+}118118+119119+/**120120+ * pm_clk_add_clk - Start using a device clock for power management.121121+ * @dev: Device whose clock is going to be used for power management.122122+ * @clk: Clock pointer123123+ *124124+ * Add the clock to the list of clocks used for the power management of @dev.125125+ * It will increment refcount on clock pointer, use clk_put() on it when done.126126+ */127127+int pm_clk_add_clk(struct device *dev, struct clk *clk)128128+{129129+ return __pm_clk_add(dev, NULL, clk);111130}112131113132/**···299266 struct pm_subsys_data *psd = dev_to_psd(dev);300267 struct pm_clock_entry *ce;301268 unsigned long flags;302302- int ret;303269304270 dev_dbg(dev, "%s()\n", __func__);305271···307275308276 spin_lock_irqsave(&psd->lock, flags);309277310310- list_for_each_entry(ce, &psd->clock_list, node) {311311- if (ce->status < PCE_STATUS_ERROR) {312312- ret = __pm_clk_enable(dev, ce->clk);313313- if (!ret)314314- ce->status = PCE_STATUS_ENABLED;315315- }316316- }278278+ list_for_each_entry(ce, &psd->clock_list, node)279279+ __pm_clk_enable(dev, ce);317280318281 spin_unlock_irqrestore(&psd->lock, flags);319282···417390 struct pm_subsys_data *psd = dev_to_psd(dev);418391 struct pm_clock_entry *ce;419392 unsigned long flags;420420- int ret;421393422394 dev_dbg(dev, "%s()\n", __func__);423395···426400427401 spin_lock_irqsave(&psd->lock, flags);428402429429- list_for_each_entry(ce, &psd->clock_list, node) {430430- if (ce->status < PCE_STATUS_ERROR) {431431- ret = __pm_clk_enable(dev, ce->clk);432432- if (!ret)433433- ce->status = PCE_STATUS_ENABLED;434434- }435435- }403403+ list_for_each_entry(ce, &psd->clock_list, node)404404+ __pm_clk_enable(dev, ce);436405437406 spin_unlock_irqrestore(&psd->lock, flags);438407
+8
include/linux/pm_clock.h
···1818 char *con_ids[];1919};20202121+struct clk;2222+2123#ifdef CONFIG_PM_CLK2224static inline bool pm_clk_no_clocks(struct device *dev)2325{···3129extern int pm_clk_create(struct device *dev);3230extern void pm_clk_destroy(struct device *dev);3331extern int pm_clk_add(struct device *dev, const char *con_id);3232+extern int pm_clk_add_clk(struct device *dev, struct clk *clk);3433extern void pm_clk_remove(struct device *dev, const char *con_id);3534extern int pm_clk_suspend(struct device *dev);3635extern int pm_clk_resume(struct device *dev);···5148{5249}5350static inline int pm_clk_add(struct device *dev, const char *con_id)5151+{5252+ return -EINVAL;5353+}5454+5555+static inline int pm_clk_add_clk(struct device *dev, struct clk *clk)5456{5557 return -EINVAL;5658}