cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

clock_ops.c (19792B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * drivers/base/power/clock_ops.c - Generic clock manipulation PM callbacks
      4 *
      5 * Copyright (c) 2011 Rafael J. Wysocki <rjw@sisk.pl>, Renesas Electronics Corp.
      6 */
      7
      8#include <linux/kernel.h>
      9#include <linux/device.h>
     10#include <linux/io.h>
     11#include <linux/pm.h>
     12#include <linux/pm_clock.h>
     13#include <linux/clk.h>
     14#include <linux/clkdev.h>
     15#include <linux/of_clk.h>
     16#include <linux/slab.h>
     17#include <linux/err.h>
     18#include <linux/pm_domain.h>
     19#include <linux/pm_runtime.h>
     20
     21#ifdef CONFIG_PM_CLK
     22
     23enum pce_status {
     24	PCE_STATUS_NONE = 0,
     25	PCE_STATUS_ACQUIRED,
     26	PCE_STATUS_PREPARED,
     27	PCE_STATUS_ENABLED,
     28	PCE_STATUS_ERROR,
     29};
     30
     31struct pm_clock_entry {
     32	struct list_head node;
     33	char *con_id;
     34	struct clk *clk;
     35	enum pce_status status;
     36	bool enabled_when_prepared;
     37};
     38
     39/**
     40 * pm_clk_list_lock - ensure exclusive access for modifying the PM clock
     41 *		      entry list.
     42 * @psd: pm_subsys_data instance corresponding to the PM clock entry list
     43 *	 and clk_op_might_sleep count to be modified.
     44 *
     45 * Get exclusive access before modifying the PM clock entry list and the
     46 * clock_op_might_sleep count to guard against concurrent modifications.
     47 * This also protects against a concurrent clock_op_might_sleep and PM clock
     48 * entry list usage in pm_clk_suspend()/pm_clk_resume() that may or may not
     49 * happen in atomic context, hence both the mutex and the spinlock must be
     50 * taken here.
     51 */
     52static void pm_clk_list_lock(struct pm_subsys_data *psd)
     53	__acquires(&psd->lock)
     54{
     55	mutex_lock(&psd->clock_mutex);
     56	spin_lock_irq(&psd->lock);
     57}
     58
     59/**
     60 * pm_clk_list_unlock - counterpart to pm_clk_list_lock().
     61 * @psd: the same pm_subsys_data instance previously passed to
     62 *	 pm_clk_list_lock().
     63 */
     64static void pm_clk_list_unlock(struct pm_subsys_data *psd)
     65	__releases(&psd->lock)
     66{
     67	spin_unlock_irq(&psd->lock);
     68	mutex_unlock(&psd->clock_mutex);
     69}
     70
     71/**
     72 * pm_clk_op_lock - ensure exclusive access for performing clock operations.
     73 * @psd: pm_subsys_data instance corresponding to the PM clock entry list
     74 *	 and clk_op_might_sleep count being used.
     75 * @flags: stored irq flags.
     76 * @fn: string for the caller function's name.
     77 *
     78 * This is used by pm_clk_suspend() and pm_clk_resume() to guard
     79 * against concurrent modifications to the clock entry list and the
     80 * clock_op_might_sleep count. If clock_op_might_sleep is != 0 then
     81 * only the mutex can be locked and those functions can only be used in
     82 * non atomic context. If clock_op_might_sleep == 0 then these functions
     83 * may be used in any context and only the spinlock can be locked.
     84 * Returns -EINVAL if called in atomic context when clock ops might sleep.
     85 */
     86static int pm_clk_op_lock(struct pm_subsys_data *psd, unsigned long *flags,
     87			  const char *fn)
     88	/* sparse annotations don't work here as exit state isn't static */
     89{
     90	bool atomic_context = in_atomic() || irqs_disabled();
     91
     92try_again:
     93	spin_lock_irqsave(&psd->lock, *flags);
     94	if (!psd->clock_op_might_sleep) {
     95		/* the __release is there to work around sparse limitations */
     96		__release(&psd->lock);
     97		return 0;
     98	}
     99
    100	/* bail out if in atomic context */
    101	if (atomic_context) {
    102		pr_err("%s: atomic context with clock_ops_might_sleep = %d",
    103		       fn, psd->clock_op_might_sleep);
    104		spin_unlock_irqrestore(&psd->lock, *flags);
    105		might_sleep();
    106		return -EPERM;
    107	}
    108
    109	/* we must switch to the mutex */
    110	spin_unlock_irqrestore(&psd->lock, *flags);
    111	mutex_lock(&psd->clock_mutex);
    112
    113	/*
    114	 * There was a possibility for psd->clock_op_might_sleep
    115	 * to become 0 above. Keep the mutex only if not the case.
    116	 */
    117	if (likely(psd->clock_op_might_sleep))
    118		return 0;
    119
    120	mutex_unlock(&psd->clock_mutex);
    121	goto try_again;
    122}
    123
    124/**
    125 * pm_clk_op_unlock - counterpart to pm_clk_op_lock().
    126 * @psd: the same pm_subsys_data instance previously passed to
    127 *	 pm_clk_op_lock().
    128 * @flags: irq flags provided by pm_clk_op_lock().
    129 */
    130static void pm_clk_op_unlock(struct pm_subsys_data *psd, unsigned long *flags)
    131	/* sparse annotations don't work here as entry state isn't static */
    132{
    133	if (psd->clock_op_might_sleep) {
    134		mutex_unlock(&psd->clock_mutex);
    135	} else {
    136		/* the __acquire is there to work around sparse limitations */
    137		__acquire(&psd->lock);
    138		spin_unlock_irqrestore(&psd->lock, *flags);
    139	}
    140}
    141
    142/**
    143 * __pm_clk_enable - Enable a clock, reporting any errors
    144 * @dev: The device for the given clock
    145 * @ce: PM clock entry corresponding to the clock.
    146 */
    147static inline void __pm_clk_enable(struct device *dev, struct pm_clock_entry *ce)
    148{
    149	int ret;
    150
    151	switch (ce->status) {
    152	case PCE_STATUS_ACQUIRED:
    153		ret = clk_prepare_enable(ce->clk);
    154		break;
    155	case PCE_STATUS_PREPARED:
    156		ret = clk_enable(ce->clk);
    157		break;
    158	default:
    159		return;
    160	}
    161	if (!ret)
    162		ce->status = PCE_STATUS_ENABLED;
    163	else
    164		dev_err(dev, "%s: failed to enable clk %p, error %d\n",
    165			__func__, ce->clk, ret);
    166}
    167
    168/**
    169 * pm_clk_acquire - Acquire a device clock.
    170 * @dev: Device whose clock is to be acquired.
    171 * @ce: PM clock entry corresponding to the clock.
    172 */
    173static void pm_clk_acquire(struct device *dev, struct pm_clock_entry *ce)
    174{
    175	if (!ce->clk)
    176		ce->clk = clk_get(dev, ce->con_id);
    177	if (IS_ERR(ce->clk)) {
    178		ce->status = PCE_STATUS_ERROR;
    179		return;
    180	} else if (clk_is_enabled_when_prepared(ce->clk)) {
    181		/* we defer preparing the clock in that case */
    182		ce->status = PCE_STATUS_ACQUIRED;
    183		ce->enabled_when_prepared = true;
    184	} else if (clk_prepare(ce->clk)) {
    185		ce->status = PCE_STATUS_ERROR;
    186		dev_err(dev, "clk_prepare() failed\n");
    187		return;
    188	} else {
    189		ce->status = PCE_STATUS_PREPARED;
    190	}
    191	dev_dbg(dev, "Clock %pC con_id %s managed by runtime PM.\n",
    192		ce->clk, ce->con_id);
    193}
    194
    195static int __pm_clk_add(struct device *dev, const char *con_id,
    196			struct clk *clk)
    197{
    198	struct pm_subsys_data *psd = dev_to_psd(dev);
    199	struct pm_clock_entry *ce;
    200
    201	if (!psd)
    202		return -EINVAL;
    203
    204	ce = kzalloc(sizeof(*ce), GFP_KERNEL);
    205	if (!ce)
    206		return -ENOMEM;
    207
    208	if (con_id) {
    209		ce->con_id = kstrdup(con_id, GFP_KERNEL);
    210		if (!ce->con_id) {
    211			kfree(ce);
    212			return -ENOMEM;
    213		}
    214	} else {
    215		if (IS_ERR(clk)) {
    216			kfree(ce);
    217			return -ENOENT;
    218		}
    219		ce->clk = clk;
    220	}
    221
    222	pm_clk_acquire(dev, ce);
    223
    224	pm_clk_list_lock(psd);
    225	list_add_tail(&ce->node, &psd->clock_list);
    226	if (ce->enabled_when_prepared)
    227		psd->clock_op_might_sleep++;
    228	pm_clk_list_unlock(psd);
    229	return 0;
    230}
    231
    232/**
    233 * pm_clk_add - Start using a device clock for power management.
    234 * @dev: Device whose clock is going to be used for power management.
    235 * @con_id: Connection ID of the clock.
    236 *
    237 * Add the clock represented by @con_id to the list of clocks used for
    238 * the power management of @dev.
    239 */
    240int pm_clk_add(struct device *dev, const char *con_id)
    241{
    242	return __pm_clk_add(dev, con_id, NULL);
    243}
    244EXPORT_SYMBOL_GPL(pm_clk_add);
    245
    246/**
    247 * pm_clk_add_clk - Start using a device clock for power management.
    248 * @dev: Device whose clock is going to be used for power management.
    249 * @clk: Clock pointer
    250 *
    251 * Add the clock to the list of clocks used for the power management of @dev.
    252 * The power-management code will take control of the clock reference, so
    253 * callers should not call clk_put() on @clk after this function sucessfully
    254 * returned.
    255 */
    256int pm_clk_add_clk(struct device *dev, struct clk *clk)
    257{
    258	return __pm_clk_add(dev, NULL, clk);
    259}
    260EXPORT_SYMBOL_GPL(pm_clk_add_clk);
    261
    262
    263/**
    264 * of_pm_clk_add_clk - Start using a device clock for power management.
    265 * @dev: Device whose clock is going to be used for power management.
    266 * @name: Name of clock that is going to be used for power management.
    267 *
    268 * Add the clock described in the 'clocks' device-tree node that matches
    269 * with the 'name' provided, to the list of clocks used for the power
    270 * management of @dev. On success, returns 0. Returns a negative error
    271 * code if the clock is not found or cannot be added.
    272 */
    273int of_pm_clk_add_clk(struct device *dev, const char *name)
    274{
    275	struct clk *clk;
    276	int ret;
    277
    278	if (!dev || !dev->of_node || !name)
    279		return -EINVAL;
    280
    281	clk = of_clk_get_by_name(dev->of_node, name);
    282	if (IS_ERR(clk))
    283		return PTR_ERR(clk);
    284
    285	ret = pm_clk_add_clk(dev, clk);
    286	if (ret) {
    287		clk_put(clk);
    288		return ret;
    289	}
    290
    291	return 0;
    292}
    293EXPORT_SYMBOL_GPL(of_pm_clk_add_clk);
    294
    295/**
    296 * of_pm_clk_add_clks - Start using device clock(s) for power management.
    297 * @dev: Device whose clock(s) is going to be used for power management.
    298 *
    299 * Add a series of clocks described in the 'clocks' device-tree node for
    300 * a device to the list of clocks used for the power management of @dev.
    301 * On success, returns the number of clocks added. Returns a negative
    302 * error code if there are no clocks in the device node for the device
    303 * or if adding a clock fails.
    304 */
    305int of_pm_clk_add_clks(struct device *dev)
    306{
    307	struct clk **clks;
    308	int i, count;
    309	int ret;
    310
    311	if (!dev || !dev->of_node)
    312		return -EINVAL;
    313
    314	count = of_clk_get_parent_count(dev->of_node);
    315	if (count <= 0)
    316		return -ENODEV;
    317
    318	clks = kcalloc(count, sizeof(*clks), GFP_KERNEL);
    319	if (!clks)
    320		return -ENOMEM;
    321
    322	for (i = 0; i < count; i++) {
    323		clks[i] = of_clk_get(dev->of_node, i);
    324		if (IS_ERR(clks[i])) {
    325			ret = PTR_ERR(clks[i]);
    326			goto error;
    327		}
    328
    329		ret = pm_clk_add_clk(dev, clks[i]);
    330		if (ret) {
    331			clk_put(clks[i]);
    332			goto error;
    333		}
    334	}
    335
    336	kfree(clks);
    337
    338	return i;
    339
    340error:
    341	while (i--)
    342		pm_clk_remove_clk(dev, clks[i]);
    343
    344	kfree(clks);
    345
    346	return ret;
    347}
    348EXPORT_SYMBOL_GPL(of_pm_clk_add_clks);
    349
    350/**
    351 * __pm_clk_remove - Destroy PM clock entry.
    352 * @ce: PM clock entry to destroy.
    353 */
    354static void __pm_clk_remove(struct pm_clock_entry *ce)
    355{
    356	if (!ce)
    357		return;
    358
    359	switch (ce->status) {
    360	case PCE_STATUS_ENABLED:
    361		clk_disable(ce->clk);
    362		fallthrough;
    363	case PCE_STATUS_PREPARED:
    364		clk_unprepare(ce->clk);
    365		fallthrough;
    366	case PCE_STATUS_ACQUIRED:
    367	case PCE_STATUS_ERROR:
    368		if (!IS_ERR(ce->clk))
    369			clk_put(ce->clk);
    370		break;
    371	default:
    372		break;
    373	}
    374
    375	kfree(ce->con_id);
    376	kfree(ce);
    377}
    378
    379/**
    380 * pm_clk_remove - Stop using a device clock for power management.
    381 * @dev: Device whose clock should not be used for PM any more.
    382 * @con_id: Connection ID of the clock.
    383 *
    384 * Remove the clock represented by @con_id from the list of clocks used for
    385 * the power management of @dev.
    386 */
    387void pm_clk_remove(struct device *dev, const char *con_id)
    388{
    389	struct pm_subsys_data *psd = dev_to_psd(dev);
    390	struct pm_clock_entry *ce;
    391
    392	if (!psd)
    393		return;
    394
    395	pm_clk_list_lock(psd);
    396
    397	list_for_each_entry(ce, &psd->clock_list, node) {
    398		if (!con_id && !ce->con_id)
    399			goto remove;
    400		else if (!con_id || !ce->con_id)
    401			continue;
    402		else if (!strcmp(con_id, ce->con_id))
    403			goto remove;
    404	}
    405
    406	pm_clk_list_unlock(psd);
    407	return;
    408
    409 remove:
    410	list_del(&ce->node);
    411	if (ce->enabled_when_prepared)
    412		psd->clock_op_might_sleep--;
    413	pm_clk_list_unlock(psd);
    414
    415	__pm_clk_remove(ce);
    416}
    417EXPORT_SYMBOL_GPL(pm_clk_remove);
    418
    419/**
    420 * pm_clk_remove_clk - Stop using a device clock for power management.
    421 * @dev: Device whose clock should not be used for PM any more.
    422 * @clk: Clock pointer
    423 *
    424 * Remove the clock pointed to by @clk from the list of clocks used for
    425 * the power management of @dev.
    426 */
    427void pm_clk_remove_clk(struct device *dev, struct clk *clk)
    428{
    429	struct pm_subsys_data *psd = dev_to_psd(dev);
    430	struct pm_clock_entry *ce;
    431
    432	if (!psd || !clk)
    433		return;
    434
    435	pm_clk_list_lock(psd);
    436
    437	list_for_each_entry(ce, &psd->clock_list, node) {
    438		if (clk == ce->clk)
    439			goto remove;
    440	}
    441
    442	pm_clk_list_unlock(psd);
    443	return;
    444
    445 remove:
    446	list_del(&ce->node);
    447	if (ce->enabled_when_prepared)
    448		psd->clock_op_might_sleep--;
    449	pm_clk_list_unlock(psd);
    450
    451	__pm_clk_remove(ce);
    452}
    453EXPORT_SYMBOL_GPL(pm_clk_remove_clk);
    454
    455/**
    456 * pm_clk_init - Initialize a device's list of power management clocks.
    457 * @dev: Device to initialize the list of PM clocks for.
    458 *
    459 * Initialize the lock and clock_list members of the device's pm_subsys_data
    460 * object, set the count of clocks that might sleep to 0.
    461 */
    462void pm_clk_init(struct device *dev)
    463{
    464	struct pm_subsys_data *psd = dev_to_psd(dev);
    465	if (psd) {
    466		INIT_LIST_HEAD(&psd->clock_list);
    467		mutex_init(&psd->clock_mutex);
    468		psd->clock_op_might_sleep = 0;
    469	}
    470}
    471EXPORT_SYMBOL_GPL(pm_clk_init);
    472
    473/**
    474 * pm_clk_create - Create and initialize a device's list of PM clocks.
    475 * @dev: Device to create and initialize the list of PM clocks for.
    476 *
    477 * Allocate a struct pm_subsys_data object, initialize its lock and clock_list
    478 * members and make the @dev's power.subsys_data field point to it.
    479 */
    480int pm_clk_create(struct device *dev)
    481{
    482	return dev_pm_get_subsys_data(dev);
    483}
    484EXPORT_SYMBOL_GPL(pm_clk_create);
    485
    486/**
    487 * pm_clk_destroy - Destroy a device's list of power management clocks.
    488 * @dev: Device to destroy the list of PM clocks for.
    489 *
    490 * Clear the @dev's power.subsys_data field, remove the list of clock entries
    491 * from the struct pm_subsys_data object pointed to by it before and free
    492 * that object.
    493 */
    494void pm_clk_destroy(struct device *dev)
    495{
    496	struct pm_subsys_data *psd = dev_to_psd(dev);
    497	struct pm_clock_entry *ce, *c;
    498	struct list_head list;
    499
    500	if (!psd)
    501		return;
    502
    503	INIT_LIST_HEAD(&list);
    504
    505	pm_clk_list_lock(psd);
    506
    507	list_for_each_entry_safe_reverse(ce, c, &psd->clock_list, node)
    508		list_move(&ce->node, &list);
    509	psd->clock_op_might_sleep = 0;
    510
    511	pm_clk_list_unlock(psd);
    512
    513	dev_pm_put_subsys_data(dev);
    514
    515	list_for_each_entry_safe_reverse(ce, c, &list, node) {
    516		list_del(&ce->node);
    517		__pm_clk_remove(ce);
    518	}
    519}
    520EXPORT_SYMBOL_GPL(pm_clk_destroy);
    521
    522static void pm_clk_destroy_action(void *data)
    523{
    524	pm_clk_destroy(data);
    525}
    526
    527int devm_pm_clk_create(struct device *dev)
    528{
    529	int ret;
    530
    531	ret = pm_clk_create(dev);
    532	if (ret)
    533		return ret;
    534
    535	return devm_add_action_or_reset(dev, pm_clk_destroy_action, dev);
    536}
    537EXPORT_SYMBOL_GPL(devm_pm_clk_create);
    538
    539/**
    540 * pm_clk_suspend - Disable clocks in a device's PM clock list.
    541 * @dev: Device to disable the clocks for.
    542 */
    543int pm_clk_suspend(struct device *dev)
    544{
    545	struct pm_subsys_data *psd = dev_to_psd(dev);
    546	struct pm_clock_entry *ce;
    547	unsigned long flags;
    548	int ret;
    549
    550	dev_dbg(dev, "%s()\n", __func__);
    551
    552	if (!psd)
    553		return 0;
    554
    555	ret = pm_clk_op_lock(psd, &flags, __func__);
    556	if (ret)
    557		return ret;
    558
    559	list_for_each_entry_reverse(ce, &psd->clock_list, node) {
    560		if (ce->status == PCE_STATUS_ENABLED) {
    561			if (ce->enabled_when_prepared) {
    562				clk_disable_unprepare(ce->clk);
    563				ce->status = PCE_STATUS_ACQUIRED;
    564			} else {
    565				clk_disable(ce->clk);
    566				ce->status = PCE_STATUS_PREPARED;
    567			}
    568		}
    569	}
    570
    571	pm_clk_op_unlock(psd, &flags);
    572
    573	return 0;
    574}
    575EXPORT_SYMBOL_GPL(pm_clk_suspend);
    576
    577/**
    578 * pm_clk_resume - Enable clocks in a device's PM clock list.
    579 * @dev: Device to enable the clocks for.
    580 */
    581int pm_clk_resume(struct device *dev)
    582{
    583	struct pm_subsys_data *psd = dev_to_psd(dev);
    584	struct pm_clock_entry *ce;
    585	unsigned long flags;
    586	int ret;
    587
    588	dev_dbg(dev, "%s()\n", __func__);
    589
    590	if (!psd)
    591		return 0;
    592
    593	ret = pm_clk_op_lock(psd, &flags, __func__);
    594	if (ret)
    595		return ret;
    596
    597	list_for_each_entry(ce, &psd->clock_list, node)
    598		__pm_clk_enable(dev, ce);
    599
    600	pm_clk_op_unlock(psd, &flags);
    601
    602	return 0;
    603}
    604EXPORT_SYMBOL_GPL(pm_clk_resume);
    605
    606/**
    607 * pm_clk_notify - Notify routine for device addition and removal.
    608 * @nb: Notifier block object this function is a member of.
    609 * @action: Operation being carried out by the caller.
    610 * @data: Device the routine is being run for.
    611 *
    612 * For this function to work, @nb must be a member of an object of type
    613 * struct pm_clk_notifier_block containing all of the requisite data.
    614 * Specifically, the pm_domain member of that object is copied to the device's
    615 * pm_domain field and its con_ids member is used to populate the device's list
    616 * of PM clocks, depending on @action.
    617 *
    618 * If the device's pm_domain field is already populated with a value different
    619 * from the one stored in the struct pm_clk_notifier_block object, the function
    620 * does nothing.
    621 */
    622static int pm_clk_notify(struct notifier_block *nb,
    623				 unsigned long action, void *data)
    624{
    625	struct pm_clk_notifier_block *clknb;
    626	struct device *dev = data;
    627	char **con_id;
    628	int error;
    629
    630	dev_dbg(dev, "%s() %ld\n", __func__, action);
    631
    632	clknb = container_of(nb, struct pm_clk_notifier_block, nb);
    633
    634	switch (action) {
    635	case BUS_NOTIFY_ADD_DEVICE:
    636		if (dev->pm_domain)
    637			break;
    638
    639		error = pm_clk_create(dev);
    640		if (error)
    641			break;
    642
    643		dev_pm_domain_set(dev, clknb->pm_domain);
    644		if (clknb->con_ids[0]) {
    645			for (con_id = clknb->con_ids; *con_id; con_id++)
    646				pm_clk_add(dev, *con_id);
    647		} else {
    648			pm_clk_add(dev, NULL);
    649		}
    650
    651		break;
    652	case BUS_NOTIFY_DEL_DEVICE:
    653		if (dev->pm_domain != clknb->pm_domain)
    654			break;
    655
    656		dev_pm_domain_set(dev, NULL);
    657		pm_clk_destroy(dev);
    658		break;
    659	}
    660
    661	return 0;
    662}
    663
    664int pm_clk_runtime_suspend(struct device *dev)
    665{
    666	int ret;
    667
    668	dev_dbg(dev, "%s\n", __func__);
    669
    670	ret = pm_generic_runtime_suspend(dev);
    671	if (ret) {
    672		dev_err(dev, "failed to suspend device\n");
    673		return ret;
    674	}
    675
    676	ret = pm_clk_suspend(dev);
    677	if (ret) {
    678		dev_err(dev, "failed to suspend clock\n");
    679		pm_generic_runtime_resume(dev);
    680		return ret;
    681	}
    682
    683	return 0;
    684}
    685EXPORT_SYMBOL_GPL(pm_clk_runtime_suspend);
    686
    687int pm_clk_runtime_resume(struct device *dev)
    688{
    689	int ret;
    690
    691	dev_dbg(dev, "%s\n", __func__);
    692
    693	ret = pm_clk_resume(dev);
    694	if (ret) {
    695		dev_err(dev, "failed to resume clock\n");
    696		return ret;
    697	}
    698
    699	return pm_generic_runtime_resume(dev);
    700}
    701EXPORT_SYMBOL_GPL(pm_clk_runtime_resume);
    702
    703#else /* !CONFIG_PM_CLK */
    704
    705/**
    706 * enable_clock - Enable a device clock.
    707 * @dev: Device whose clock is to be enabled.
    708 * @con_id: Connection ID of the clock.
    709 */
    710static void enable_clock(struct device *dev, const char *con_id)
    711{
    712	struct clk *clk;
    713
    714	clk = clk_get(dev, con_id);
    715	if (!IS_ERR(clk)) {
    716		clk_prepare_enable(clk);
    717		clk_put(clk);
    718		dev_info(dev, "Runtime PM disabled, clock forced on.\n");
    719	}
    720}
    721
    722/**
    723 * disable_clock - Disable a device clock.
    724 * @dev: Device whose clock is to be disabled.
    725 * @con_id: Connection ID of the clock.
    726 */
    727static void disable_clock(struct device *dev, const char *con_id)
    728{
    729	struct clk *clk;
    730
    731	clk = clk_get(dev, con_id);
    732	if (!IS_ERR(clk)) {
    733		clk_disable_unprepare(clk);
    734		clk_put(clk);
    735		dev_info(dev, "Runtime PM disabled, clock forced off.\n");
    736	}
    737}
    738
    739/**
    740 * pm_clk_notify - Notify routine for device addition and removal.
    741 * @nb: Notifier block object this function is a member of.
    742 * @action: Operation being carried out by the caller.
    743 * @data: Device the routine is being run for.
    744 *
    745 * For this function to work, @nb must be a member of an object of type
    746 * struct pm_clk_notifier_block containing all of the requisite data.
    747 * Specifically, the con_ids member of that object is used to enable or disable
    748 * the device's clocks, depending on @action.
    749 */
    750static int pm_clk_notify(struct notifier_block *nb,
    751				 unsigned long action, void *data)
    752{
    753	struct pm_clk_notifier_block *clknb;
    754	struct device *dev = data;
    755	char **con_id;
    756
    757	dev_dbg(dev, "%s() %ld\n", __func__, action);
    758
    759	clknb = container_of(nb, struct pm_clk_notifier_block, nb);
    760
    761	switch (action) {
    762	case BUS_NOTIFY_BIND_DRIVER:
    763		if (clknb->con_ids[0]) {
    764			for (con_id = clknb->con_ids; *con_id; con_id++)
    765				enable_clock(dev, *con_id);
    766		} else {
    767			enable_clock(dev, NULL);
    768		}
    769		break;
    770	case BUS_NOTIFY_DRIVER_NOT_BOUND:
    771	case BUS_NOTIFY_UNBOUND_DRIVER:
    772		if (clknb->con_ids[0]) {
    773			for (con_id = clknb->con_ids; *con_id; con_id++)
    774				disable_clock(dev, *con_id);
    775		} else {
    776			disable_clock(dev, NULL);
    777		}
    778		break;
    779	}
    780
    781	return 0;
    782}
    783
    784#endif /* !CONFIG_PM_CLK */
    785
    786/**
    787 * pm_clk_add_notifier - Add bus type notifier for power management clocks.
    788 * @bus: Bus type to add the notifier to.
    789 * @clknb: Notifier to be added to the given bus type.
    790 *
    791 * The nb member of @clknb is not expected to be initialized and its
    792 * notifier_call member will be replaced with pm_clk_notify().  However,
    793 * the remaining members of @clknb should be populated prior to calling this
    794 * routine.
    795 */
    796void pm_clk_add_notifier(struct bus_type *bus,
    797				 struct pm_clk_notifier_block *clknb)
    798{
    799	if (!bus || !clknb)
    800		return;
    801
    802	clknb->nb.notifier_call = pm_clk_notify;
    803	bus_register_notifier(bus, &clknb->nb);
    804}
    805EXPORT_SYMBOL_GPL(pm_clk_add_notifier);