Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * drivers/clk/clkdev.c
0004  *
0005  *  Copyright (C) 2008 Russell King.
0006  *
0007  * Helper for the clk API to assist looking up a struct clk.
0008  */
0009 #include <linux/module.h>
0010 #include <linux/kernel.h>
0011 #include <linux/device.h>
0012 #include <linux/list.h>
0013 #include <linux/errno.h>
0014 #include <linux/err.h>
0015 #include <linux/string.h>
0016 #include <linux/mutex.h>
0017 #include <linux/clk.h>
0018 #include <linux/clkdev.h>
0019 #include <linux/clk-provider.h>
0020 #include <linux/of.h>
0021 
0022 #include "clk.h"
0023 
0024 static LIST_HEAD(clocks);
0025 static DEFINE_MUTEX(clocks_mutex);
0026 
0027 /*
0028  * Find the correct struct clk for the device and connection ID.
0029  * We do slightly fuzzy matching here:
0030  *  An entry with a NULL ID is assumed to be a wildcard.
0031  *  If an entry has a device ID, it must match
0032  *  If an entry has a connection ID, it must match
0033  * Then we take the most specific entry - with the following
0034  * order of precedence: dev+con > dev only > con only.
0035  */
0036 static struct clk_lookup *clk_find(const char *dev_id, const char *con_id)
0037 {
0038     struct clk_lookup *p, *cl = NULL;
0039     int match, best_found = 0, best_possible = 0;
0040 
0041     if (dev_id)
0042         best_possible += 2;
0043     if (con_id)
0044         best_possible += 1;
0045 
0046     lockdep_assert_held(&clocks_mutex);
0047 
0048     list_for_each_entry(p, &clocks, node) {
0049         match = 0;
0050         if (p->dev_id) {
0051             if (!dev_id || strcmp(p->dev_id, dev_id))
0052                 continue;
0053             match += 2;
0054         }
0055         if (p->con_id) {
0056             if (!con_id || strcmp(p->con_id, con_id))
0057                 continue;
0058             match += 1;
0059         }
0060 
0061         if (match > best_found) {
0062             cl = p;
0063             if (match != best_possible)
0064                 best_found = match;
0065             else
0066                 break;
0067         }
0068     }
0069     return cl;
0070 }
0071 
0072 struct clk_hw *clk_find_hw(const char *dev_id, const char *con_id)
0073 {
0074     struct clk_lookup *cl;
0075     struct clk_hw *hw = ERR_PTR(-ENOENT);
0076 
0077     mutex_lock(&clocks_mutex);
0078     cl = clk_find(dev_id, con_id);
0079     if (cl)
0080         hw = cl->clk_hw;
0081     mutex_unlock(&clocks_mutex);
0082 
0083     return hw;
0084 }
0085 
0086 static struct clk *__clk_get_sys(struct device *dev, const char *dev_id,
0087                  const char *con_id)
0088 {
0089     struct clk_hw *hw = clk_find_hw(dev_id, con_id);
0090 
0091     return clk_hw_create_clk(dev, hw, dev_id, con_id);
0092 }
0093 
0094 struct clk *clk_get_sys(const char *dev_id, const char *con_id)
0095 {
0096     return __clk_get_sys(NULL, dev_id, con_id);
0097 }
0098 EXPORT_SYMBOL(clk_get_sys);
0099 
0100 struct clk *clk_get(struct device *dev, const char *con_id)
0101 {
0102     const char *dev_id = dev ? dev_name(dev) : NULL;
0103     struct clk_hw *hw;
0104 
0105     if (dev && dev->of_node) {
0106         hw = of_clk_get_hw(dev->of_node, 0, con_id);
0107         if (!IS_ERR(hw) || PTR_ERR(hw) == -EPROBE_DEFER)
0108             return clk_hw_create_clk(dev, hw, dev_id, con_id);
0109     }
0110 
0111     return __clk_get_sys(dev, dev_id, con_id);
0112 }
0113 EXPORT_SYMBOL(clk_get);
0114 
0115 void clk_put(struct clk *clk)
0116 {
0117     __clk_put(clk);
0118 }
0119 EXPORT_SYMBOL(clk_put);
0120 
0121 static void __clkdev_add(struct clk_lookup *cl)
0122 {
0123     mutex_lock(&clocks_mutex);
0124     list_add_tail(&cl->node, &clocks);
0125     mutex_unlock(&clocks_mutex);
0126 }
0127 
0128 void clkdev_add(struct clk_lookup *cl)
0129 {
0130     if (!cl->clk_hw)
0131         cl->clk_hw = __clk_get_hw(cl->clk);
0132     __clkdev_add(cl);
0133 }
0134 EXPORT_SYMBOL(clkdev_add);
0135 
0136 void clkdev_add_table(struct clk_lookup *cl, size_t num)
0137 {
0138     mutex_lock(&clocks_mutex);
0139     while (num--) {
0140         cl->clk_hw = __clk_get_hw(cl->clk);
0141         list_add_tail(&cl->node, &clocks);
0142         cl++;
0143     }
0144     mutex_unlock(&clocks_mutex);
0145 }
0146 
0147 #define MAX_DEV_ID  20
0148 #define MAX_CON_ID  16
0149 
0150 struct clk_lookup_alloc {
0151     struct clk_lookup cl;
0152     char    dev_id[MAX_DEV_ID];
0153     char    con_id[MAX_CON_ID];
0154 };
0155 
0156 static struct clk_lookup * __ref
0157 vclkdev_alloc(struct clk_hw *hw, const char *con_id, const char *dev_fmt,
0158     va_list ap)
0159 {
0160     struct clk_lookup_alloc *cla;
0161 
0162     cla = kzalloc(sizeof(*cla), GFP_KERNEL);
0163     if (!cla)
0164         return NULL;
0165 
0166     cla->cl.clk_hw = hw;
0167     if (con_id) {
0168         strlcpy(cla->con_id, con_id, sizeof(cla->con_id));
0169         cla->cl.con_id = cla->con_id;
0170     }
0171 
0172     if (dev_fmt) {
0173         vscnprintf(cla->dev_id, sizeof(cla->dev_id), dev_fmt, ap);
0174         cla->cl.dev_id = cla->dev_id;
0175     }
0176 
0177     return &cla->cl;
0178 }
0179 
0180 static struct clk_lookup *
0181 vclkdev_create(struct clk_hw *hw, const char *con_id, const char *dev_fmt,
0182     va_list ap)
0183 {
0184     struct clk_lookup *cl;
0185 
0186     cl = vclkdev_alloc(hw, con_id, dev_fmt, ap);
0187     if (cl)
0188         __clkdev_add(cl);
0189 
0190     return cl;
0191 }
0192 
0193 /**
0194  * clkdev_create - allocate and add a clkdev lookup structure
0195  * @clk: struct clk to associate with all clk_lookups
0196  * @con_id: connection ID string on device
0197  * @dev_fmt: format string describing device name
0198  *
0199  * Returns a clk_lookup structure, which can be later unregistered and
0200  * freed.
0201  */
0202 struct clk_lookup *clkdev_create(struct clk *clk, const char *con_id,
0203     const char *dev_fmt, ...)
0204 {
0205     struct clk_lookup *cl;
0206     va_list ap;
0207 
0208     va_start(ap, dev_fmt);
0209     cl = vclkdev_create(__clk_get_hw(clk), con_id, dev_fmt, ap);
0210     va_end(ap);
0211 
0212     return cl;
0213 }
0214 EXPORT_SYMBOL_GPL(clkdev_create);
0215 
0216 /**
0217  * clkdev_hw_create - allocate and add a clkdev lookup structure
0218  * @hw: struct clk_hw to associate with all clk_lookups
0219  * @con_id: connection ID string on device
0220  * @dev_fmt: format string describing device name
0221  *
0222  * Returns a clk_lookup structure, which can be later unregistered and
0223  * freed.
0224  */
0225 struct clk_lookup *clkdev_hw_create(struct clk_hw *hw, const char *con_id,
0226     const char *dev_fmt, ...)
0227 {
0228     struct clk_lookup *cl;
0229     va_list ap;
0230 
0231     va_start(ap, dev_fmt);
0232     cl = vclkdev_create(hw, con_id, dev_fmt, ap);
0233     va_end(ap);
0234 
0235     return cl;
0236 }
0237 EXPORT_SYMBOL_GPL(clkdev_hw_create);
0238 
0239 int clk_add_alias(const char *alias, const char *alias_dev_name,
0240     const char *con_id, struct device *dev)
0241 {
0242     struct clk *r = clk_get(dev, con_id);
0243     struct clk_lookup *l;
0244 
0245     if (IS_ERR(r))
0246         return PTR_ERR(r);
0247 
0248     l = clkdev_create(r, alias, alias_dev_name ? "%s" : NULL,
0249               alias_dev_name);
0250     clk_put(r);
0251 
0252     return l ? 0 : -ENODEV;
0253 }
0254 EXPORT_SYMBOL(clk_add_alias);
0255 
0256 /*
0257  * clkdev_drop - remove a clock dynamically allocated
0258  */
0259 void clkdev_drop(struct clk_lookup *cl)
0260 {
0261     mutex_lock(&clocks_mutex);
0262     list_del(&cl->node);
0263     mutex_unlock(&clocks_mutex);
0264     kfree(cl);
0265 }
0266 EXPORT_SYMBOL(clkdev_drop);
0267 
0268 static struct clk_lookup *__clk_register_clkdev(struct clk_hw *hw,
0269                         const char *con_id,
0270                         const char *dev_id, ...)
0271 {
0272     struct clk_lookup *cl;
0273     va_list ap;
0274 
0275     va_start(ap, dev_id);
0276     cl = vclkdev_create(hw, con_id, dev_id, ap);
0277     va_end(ap);
0278 
0279     return cl;
0280 }
0281 
0282 static int do_clk_register_clkdev(struct clk_hw *hw,
0283     struct clk_lookup **cl, const char *con_id, const char *dev_id)
0284 {
0285     if (IS_ERR(hw))
0286         return PTR_ERR(hw);
0287     /*
0288      * Since dev_id can be NULL, and NULL is handled specially, we must
0289      * pass it as either a NULL format string, or with "%s".
0290      */
0291     if (dev_id)
0292         *cl = __clk_register_clkdev(hw, con_id, "%s", dev_id);
0293     else
0294         *cl = __clk_register_clkdev(hw, con_id, NULL);
0295 
0296     return *cl ? 0 : -ENOMEM;
0297 }
0298 
0299 /**
0300  * clk_register_clkdev - register one clock lookup for a struct clk
0301  * @clk: struct clk to associate with all clk_lookups
0302  * @con_id: connection ID string on device
0303  * @dev_id: string describing device name
0304  *
0305  * con_id or dev_id may be NULL as a wildcard, just as in the rest of
0306  * clkdev.
0307  *
0308  * To make things easier for mass registration, we detect error clks
0309  * from a previous clk_register() call, and return the error code for
0310  * those.  This is to permit this function to be called immediately
0311  * after clk_register().
0312  */
0313 int clk_register_clkdev(struct clk *clk, const char *con_id,
0314     const char *dev_id)
0315 {
0316     struct clk_lookup *cl;
0317 
0318     if (IS_ERR(clk))
0319         return PTR_ERR(clk);
0320 
0321     return do_clk_register_clkdev(__clk_get_hw(clk), &cl, con_id,
0322                           dev_id);
0323 }
0324 EXPORT_SYMBOL(clk_register_clkdev);
0325 
0326 /**
0327  * clk_hw_register_clkdev - register one clock lookup for a struct clk_hw
0328  * @hw: struct clk_hw to associate with all clk_lookups
0329  * @con_id: connection ID string on device
0330  * @dev_id: format string describing device name
0331  *
0332  * con_id or dev_id may be NULL as a wildcard, just as in the rest of
0333  * clkdev.
0334  *
0335  * To make things easier for mass registration, we detect error clk_hws
0336  * from a previous clk_hw_register_*() call, and return the error code for
0337  * those.  This is to permit this function to be called immediately
0338  * after clk_hw_register_*().
0339  */
0340 int clk_hw_register_clkdev(struct clk_hw *hw, const char *con_id,
0341     const char *dev_id)
0342 {
0343     struct clk_lookup *cl;
0344 
0345     return do_clk_register_clkdev(hw, &cl, con_id, dev_id);
0346 }
0347 EXPORT_SYMBOL(clk_hw_register_clkdev);
0348 
0349 static void devm_clkdev_release(struct device *dev, void *res)
0350 {
0351     clkdev_drop(*(struct clk_lookup **)res);
0352 }
0353 
0354 static int devm_clk_match_clkdev(struct device *dev, void *res, void *data)
0355 {
0356     struct clk_lookup **l = res;
0357 
0358     return *l == data;
0359 }
0360 
0361 /**
0362  * devm_clk_release_clkdev - Resource managed clkdev lookup release
0363  * @dev: device this lookup is bound
0364  * @con_id: connection ID string on device
0365  * @dev_id: format string describing device name
0366  *
0367  * Drop the clkdev lookup created with devm_clk_hw_register_clkdev.
0368  * Normally this function will not need to be called and the resource
0369  * management code will ensure that the resource is freed.
0370  */
0371 void devm_clk_release_clkdev(struct device *dev, const char *con_id,
0372                  const char *dev_id)
0373 {
0374     struct clk_lookup *cl;
0375     int rval;
0376 
0377     mutex_lock(&clocks_mutex);
0378     cl = clk_find(dev_id, con_id);
0379     mutex_unlock(&clocks_mutex);
0380 
0381     WARN_ON(!cl);
0382     rval = devres_release(dev, devm_clkdev_release,
0383                   devm_clk_match_clkdev, cl);
0384     WARN_ON(rval);
0385 }
0386 EXPORT_SYMBOL(devm_clk_release_clkdev);
0387 
0388 /**
0389  * devm_clk_hw_register_clkdev - managed clk lookup registration for clk_hw
0390  * @dev: device this lookup is bound
0391  * @hw: struct clk_hw to associate with all clk_lookups
0392  * @con_id: connection ID string on device
0393  * @dev_id: format string describing device name
0394  *
0395  * con_id or dev_id may be NULL as a wildcard, just as in the rest of
0396  * clkdev.
0397  *
0398  * To make things easier for mass registration, we detect error clk_hws
0399  * from a previous clk_hw_register_*() call, and return the error code for
0400  * those.  This is to permit this function to be called immediately
0401  * after clk_hw_register_*().
0402  */
0403 int devm_clk_hw_register_clkdev(struct device *dev, struct clk_hw *hw,
0404                 const char *con_id, const char *dev_id)
0405 {
0406     int rval = -ENOMEM;
0407     struct clk_lookup **cl;
0408 
0409     cl = devres_alloc(devm_clkdev_release, sizeof(*cl), GFP_KERNEL);
0410     if (cl) {
0411         rval = do_clk_register_clkdev(hw, cl, con_id, dev_id);
0412         if (!rval)
0413             devres_add(dev, cl);
0414         else
0415             devres_free(cl);
0416     }
0417     return rval;
0418 }
0419 EXPORT_SYMBOL(devm_clk_hw_register_clkdev);