root/drivers/clk/clk-devres.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. devm_clk_release
  2. devm_clk_get
  3. devm_clk_get_optional
  4. devm_clk_bulk_release
  5. __devm_clk_bulk_get
  6. devm_clk_bulk_get
  7. devm_clk_bulk_get_optional
  8. devm_clk_bulk_get_all
  9. devm_clk_match
  10. devm_clk_put
  11. devm_get_clk_from_child

   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 
   7 static void devm_clk_release(struct device *dev, void *res)
   8 {
   9         clk_put(*(struct clk **)res);
  10 }
  11 
  12 struct 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 }
  30 EXPORT_SYMBOL(devm_clk_get);
  31 
  32 struct 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 }
  41 EXPORT_SYMBOL(devm_clk_get_optional);
  42 
  43 struct clk_bulk_devres {
  44         struct clk_bulk_data *clks;
  45         int num_clks;
  46 };
  47 
  48 static 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 
  55 static 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 
  81 int __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 }
  86 EXPORT_SYMBOL_GPL(devm_clk_bulk_get);
  87 
  88 int __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 }
  93 EXPORT_SYMBOL_GPL(devm_clk_bulk_get_optional);
  94 
  95 int __must_check devm_clk_bulk_get_all(struct device *dev,
  96                                        struct clk_bulk_data **clks)
  97 {
  98         struct clk_bulk_devres *devres;
  99         int ret;
 100 
 101         devres = devres_alloc(devm_clk_bulk_release,
 102                               sizeof(*devres), GFP_KERNEL);
 103         if (!devres)
 104                 return -ENOMEM;
 105 
 106         ret = clk_bulk_get_all(dev, &devres->clks);
 107         if (ret > 0) {
 108                 *clks = devres->clks;
 109                 devres->num_clks = ret;
 110                 devres_add(dev, devres);
 111         } else {
 112                 devres_free(devres);
 113         }
 114 
 115         return ret;
 116 }
 117 EXPORT_SYMBOL_GPL(devm_clk_bulk_get_all);
 118 
 119 static int devm_clk_match(struct device *dev, void *res, void *data)
 120 {
 121         struct clk **c = res;
 122         if (!c || !*c) {
 123                 WARN_ON(!c || !*c);
 124                 return 0;
 125         }
 126         return *c == data;
 127 }
 128 
 129 void devm_clk_put(struct device *dev, struct clk *clk)
 130 {
 131         int ret;
 132 
 133         ret = devres_release(dev, devm_clk_release, devm_clk_match, clk);
 134 
 135         WARN_ON(ret);
 136 }
 137 EXPORT_SYMBOL(devm_clk_put);
 138 
 139 struct clk *devm_get_clk_from_child(struct device *dev,
 140                                     struct device_node *np, const char *con_id)
 141 {
 142         struct clk **ptr, *clk;
 143 
 144         ptr = devres_alloc(devm_clk_release, sizeof(*ptr), GFP_KERNEL);
 145         if (!ptr)
 146                 return ERR_PTR(-ENOMEM);
 147 
 148         clk = of_clk_get_by_name(np, con_id);
 149         if (!IS_ERR(clk)) {
 150                 *ptr = clk;
 151                 devres_add(dev, ptr);
 152         } else {
 153                 devres_free(ptr);
 154         }
 155 
 156         return clk;
 157 }
 158 EXPORT_SYMBOL(devm_get_clk_from_child);

/* [<][>][^][v][top][bottom][index][help] */