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

clk-devres.c (3451B)


      1// SPDX-License-Identifier: GPL-2.0
      2#include <linux/clk.h>
      3#include <linux/device.h>
      4#include <linux/export.h>
      5#include <linux/gfp.h>
      6
      7static void devm_clk_release(struct device *dev, void *res)
      8{
      9	clk_put(*(struct clk **)res);
     10}
     11
     12struct clk *devm_clk_get(struct device *dev, const char *id)
     13{
     14	struct clk **ptr, *clk;
     15
     16	ptr = devres_alloc(devm_clk_release, sizeof(*ptr), GFP_KERNEL);
     17	if (!ptr)
     18		return ERR_PTR(-ENOMEM);
     19
     20	clk = clk_get(dev, id);
     21	if (!IS_ERR(clk)) {
     22		*ptr = clk;
     23		devres_add(dev, ptr);
     24	} else {
     25		devres_free(ptr);
     26	}
     27
     28	return clk;
     29}
     30EXPORT_SYMBOL(devm_clk_get);
     31
     32struct clk *devm_clk_get_optional(struct device *dev, const char *id)
     33{
     34	struct clk *clk = devm_clk_get(dev, id);
     35
     36	if (clk == ERR_PTR(-ENOENT))
     37		return NULL;
     38
     39	return clk;
     40}
     41EXPORT_SYMBOL(devm_clk_get_optional);
     42
     43struct clk_bulk_devres {
     44	struct clk_bulk_data *clks;
     45	int num_clks;
     46};
     47
     48static void devm_clk_bulk_release(struct device *dev, void *res)
     49{
     50	struct clk_bulk_devres *devres = res;
     51
     52	clk_bulk_put(devres->num_clks, devres->clks);
     53}
     54
     55static int __devm_clk_bulk_get(struct device *dev, int num_clks,
     56			       struct clk_bulk_data *clks, bool optional)
     57{
     58	struct clk_bulk_devres *devres;
     59	int ret;
     60
     61	devres = devres_alloc(devm_clk_bulk_release,
     62			      sizeof(*devres), GFP_KERNEL);
     63	if (!devres)
     64		return -ENOMEM;
     65
     66	if (optional)
     67		ret = clk_bulk_get_optional(dev, num_clks, clks);
     68	else
     69		ret = clk_bulk_get(dev, num_clks, clks);
     70	if (!ret) {
     71		devres->clks = clks;
     72		devres->num_clks = num_clks;
     73		devres_add(dev, devres);
     74	} else {
     75		devres_free(devres);
     76	}
     77
     78	return ret;
     79}
     80
     81int __must_check devm_clk_bulk_get(struct device *dev, int num_clks,
     82		      struct clk_bulk_data *clks)
     83{
     84	return __devm_clk_bulk_get(dev, num_clks, clks, false);
     85}
     86EXPORT_SYMBOL_GPL(devm_clk_bulk_get);
     87
     88int __must_check devm_clk_bulk_get_optional(struct device *dev, int num_clks,
     89		      struct clk_bulk_data *clks)
     90{
     91	return __devm_clk_bulk_get(dev, num_clks, clks, true);
     92}
     93EXPORT_SYMBOL_GPL(devm_clk_bulk_get_optional);
     94
     95static void devm_clk_bulk_release_all(struct device *dev, void *res)
     96{
     97	struct clk_bulk_devres *devres = res;
     98
     99	clk_bulk_put_all(devres->num_clks, devres->clks);
    100}
    101
    102int __must_check devm_clk_bulk_get_all(struct device *dev,
    103				       struct clk_bulk_data **clks)
    104{
    105	struct clk_bulk_devres *devres;
    106	int ret;
    107
    108	devres = devres_alloc(devm_clk_bulk_release_all,
    109			      sizeof(*devres), GFP_KERNEL);
    110	if (!devres)
    111		return -ENOMEM;
    112
    113	ret = clk_bulk_get_all(dev, &devres->clks);
    114	if (ret > 0) {
    115		*clks = devres->clks;
    116		devres->num_clks = ret;
    117		devres_add(dev, devres);
    118	} else {
    119		devres_free(devres);
    120	}
    121
    122	return ret;
    123}
    124EXPORT_SYMBOL_GPL(devm_clk_bulk_get_all);
    125
    126static int devm_clk_match(struct device *dev, void *res, void *data)
    127{
    128	struct clk **c = res;
    129	if (!c || !*c) {
    130		WARN_ON(!c || !*c);
    131		return 0;
    132	}
    133	return *c == data;
    134}
    135
    136void devm_clk_put(struct device *dev, struct clk *clk)
    137{
    138	int ret;
    139
    140	ret = devres_release(dev, devm_clk_release, devm_clk_match, clk);
    141
    142	WARN_ON(ret);
    143}
    144EXPORT_SYMBOL(devm_clk_put);
    145
    146struct clk *devm_get_clk_from_child(struct device *dev,
    147				    struct device_node *np, const char *con_id)
    148{
    149	struct clk **ptr, *clk;
    150
    151	ptr = devres_alloc(devm_clk_release, sizeof(*ptr), GFP_KERNEL);
    152	if (!ptr)
    153		return ERR_PTR(-ENOMEM);
    154
    155	clk = of_clk_get_by_name(np, con_id);
    156	if (!IS_ERR(clk)) {
    157		*ptr = clk;
    158		devres_add(dev, ptr);
    159	} else {
    160		devres_free(ptr);
    161	}
    162
    163	return clk;
    164}
    165EXPORT_SYMBOL(devm_get_clk_from_child);