^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * drivers/clk/clkdev.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2008 Russell King.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Helper for the clk API to assist looking up a struct clk.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/list.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/mutex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/clk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/clkdev.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/clk-provider.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include "clk.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) static LIST_HEAD(clocks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) static DEFINE_MUTEX(clocks_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * Find the correct struct clk for the device and connection ID.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * We do slightly fuzzy matching here:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * An entry with a NULL ID is assumed to be a wildcard.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * If an entry has a device ID, it must match
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * If an entry has a connection ID, it must match
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * Then we take the most specific entry - with the following
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * order of precedence: dev+con > dev only > con only.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) static struct clk_lookup *clk_find(const char *dev_id, const char *con_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) struct clk_lookup *p, *cl = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) int match, best_found = 0, best_possible = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) if (dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) best_possible += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) if (con_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) best_possible += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) lockdep_assert_held(&clocks_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) list_for_each_entry(p, &clocks, node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) match = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) if (p->dev_id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) if (!dev_id || strcmp(p->dev_id, dev_id))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) match += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) if (p->con_id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) if (!con_id || strcmp(p->con_id, con_id))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) match += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) if (match > best_found) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) cl = p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) if (match != best_possible)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) best_found = match;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) return cl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) struct clk_hw *clk_find_hw(const char *dev_id, const char *con_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) struct clk_lookup *cl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) struct clk_hw *hw = ERR_PTR(-ENOENT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) mutex_lock(&clocks_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) cl = clk_find(dev_id, con_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) if (cl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) hw = cl->clk_hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) mutex_unlock(&clocks_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) return hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) static struct clk *__clk_get_sys(struct device *dev, const char *dev_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) const char *con_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) struct clk_hw *hw = clk_find_hw(dev_id, con_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) return clk_hw_create_clk(dev, hw, dev_id, con_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) struct clk *clk_get_sys(const char *dev_id, const char *con_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) return __clk_get_sys(NULL, dev_id, con_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) EXPORT_SYMBOL(clk_get_sys);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) struct clk *clk_get(struct device *dev, const char *con_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) const char *dev_id = dev ? dev_name(dev) : NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) struct clk_hw *hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) if (dev && dev->of_node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) hw = of_clk_get_hw(dev->of_node, 0, con_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) if (!IS_ERR(hw) || PTR_ERR(hw) == -EPROBE_DEFER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) return clk_hw_create_clk(dev, hw, dev_id, con_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) return __clk_get_sys(dev, dev_id, con_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) EXPORT_SYMBOL(clk_get);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) void clk_put(struct clk *clk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) __clk_put(clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) EXPORT_SYMBOL(clk_put);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) static void __clkdev_add(struct clk_lookup *cl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) mutex_lock(&clocks_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) list_add_tail(&cl->node, &clocks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) mutex_unlock(&clocks_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) void clkdev_add(struct clk_lookup *cl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) if (!cl->clk_hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) cl->clk_hw = __clk_get_hw(cl->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) __clkdev_add(cl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) EXPORT_SYMBOL(clkdev_add);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) void clkdev_add_table(struct clk_lookup *cl, size_t num)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) mutex_lock(&clocks_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) while (num--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) cl->clk_hw = __clk_get_hw(cl->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) list_add_tail(&cl->node, &clocks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) cl++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) mutex_unlock(&clocks_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) #define MAX_DEV_ID 20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) #define MAX_CON_ID 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) struct clk_lookup_alloc {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) struct clk_lookup cl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) char dev_id[MAX_DEV_ID];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) char con_id[MAX_CON_ID];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) static struct clk_lookup * __ref
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) vclkdev_alloc(struct clk_hw *hw, const char *con_id, const char *dev_fmt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) va_list ap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) struct clk_lookup_alloc *cla;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) cla = kzalloc(sizeof(*cla), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) if (!cla)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) cla->cl.clk_hw = hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) if (con_id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) strlcpy(cla->con_id, con_id, sizeof(cla->con_id));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) cla->cl.con_id = cla->con_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) if (dev_fmt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) vscnprintf(cla->dev_id, sizeof(cla->dev_id), dev_fmt, ap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) cla->cl.dev_id = cla->dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) return &cla->cl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) static struct clk_lookup *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) vclkdev_create(struct clk_hw *hw, const char *con_id, const char *dev_fmt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) va_list ap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) struct clk_lookup *cl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) cl = vclkdev_alloc(hw, con_id, dev_fmt, ap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) if (cl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) __clkdev_add(cl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) return cl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) struct clk_lookup * __ref
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) clkdev_alloc(struct clk *clk, const char *con_id, const char *dev_fmt, ...)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) struct clk_lookup *cl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) va_list ap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) va_start(ap, dev_fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) cl = vclkdev_alloc(__clk_get_hw(clk), con_id, dev_fmt, ap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) va_end(ap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) return cl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) EXPORT_SYMBOL(clkdev_alloc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) struct clk_lookup *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) clkdev_hw_alloc(struct clk_hw *hw, const char *con_id, const char *dev_fmt, ...)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) struct clk_lookup *cl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) va_list ap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) va_start(ap, dev_fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) cl = vclkdev_alloc(hw, con_id, dev_fmt, ap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) va_end(ap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) return cl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) EXPORT_SYMBOL(clkdev_hw_alloc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) * clkdev_create - allocate and add a clkdev lookup structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) * @clk: struct clk to associate with all clk_lookups
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) * @con_id: connection ID string on device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) * @dev_fmt: format string describing device name
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) * Returns a clk_lookup structure, which can be later unregistered and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) * freed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) struct clk_lookup *clkdev_create(struct clk *clk, const char *con_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) const char *dev_fmt, ...)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) struct clk_lookup *cl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) va_list ap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) va_start(ap, dev_fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) cl = vclkdev_create(__clk_get_hw(clk), con_id, dev_fmt, ap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) va_end(ap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) return cl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) EXPORT_SYMBOL_GPL(clkdev_create);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) * clkdev_hw_create - allocate and add a clkdev lookup structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) * @hw: struct clk_hw to associate with all clk_lookups
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) * @con_id: connection ID string on device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) * @dev_fmt: format string describing device name
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) * Returns a clk_lookup structure, which can be later unregistered and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) * freed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) struct clk_lookup *clkdev_hw_create(struct clk_hw *hw, const char *con_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) const char *dev_fmt, ...)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) struct clk_lookup *cl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) va_list ap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) va_start(ap, dev_fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) cl = vclkdev_create(hw, con_id, dev_fmt, ap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) va_end(ap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) return cl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) EXPORT_SYMBOL_GPL(clkdev_hw_create);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) int clk_add_alias(const char *alias, const char *alias_dev_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) const char *con_id, struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) struct clk *r = clk_get(dev, con_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) struct clk_lookup *l;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) if (IS_ERR(r))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) return PTR_ERR(r);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) l = clkdev_create(r, alias, alias_dev_name ? "%s" : NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) alias_dev_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) clk_put(r);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) return l ? 0 : -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) EXPORT_SYMBOL(clk_add_alias);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) * clkdev_drop - remove a clock dynamically allocated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) void clkdev_drop(struct clk_lookup *cl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) mutex_lock(&clocks_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) list_del(&cl->node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) mutex_unlock(&clocks_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) kfree(cl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) EXPORT_SYMBOL(clkdev_drop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) static struct clk_lookup *__clk_register_clkdev(struct clk_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) const char *con_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) const char *dev_id, ...)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) struct clk_lookup *cl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) va_list ap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) va_start(ap, dev_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) cl = vclkdev_create(hw, con_id, dev_id, ap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) va_end(ap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) return cl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) static int do_clk_register_clkdev(struct clk_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) struct clk_lookup **cl, const char *con_id, const char *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) if (IS_ERR(hw))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) return PTR_ERR(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) * Since dev_id can be NULL, and NULL is handled specially, we must
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) * pass it as either a NULL format string, or with "%s".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) if (dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) *cl = __clk_register_clkdev(hw, con_id, "%s", dev_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) *cl = __clk_register_clkdev(hw, con_id, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) return *cl ? 0 : -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) * clk_register_clkdev - register one clock lookup for a struct clk
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) * @clk: struct clk to associate with all clk_lookups
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) * @con_id: connection ID string on device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) * @dev_id: string describing device name
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) * con_id or dev_id may be NULL as a wildcard, just as in the rest of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) * clkdev.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) * To make things easier for mass registration, we detect error clks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) * from a previous clk_register() call, and return the error code for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) * those. This is to permit this function to be called immediately
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) * after clk_register().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) int clk_register_clkdev(struct clk *clk, const char *con_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) const char *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) struct clk_lookup *cl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) if (IS_ERR(clk))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) return PTR_ERR(clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) return do_clk_register_clkdev(__clk_get_hw(clk), &cl, con_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) dev_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) EXPORT_SYMBOL(clk_register_clkdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) * clk_hw_register_clkdev - register one clock lookup for a struct clk_hw
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) * @hw: struct clk_hw to associate with all clk_lookups
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) * @con_id: connection ID string on device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) * @dev_id: format string describing device name
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) * con_id or dev_id may be NULL as a wildcard, just as in the rest of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) * clkdev.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) * To make things easier for mass registration, we detect error clk_hws
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) * from a previous clk_hw_register_*() call, and return the error code for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) * those. This is to permit this function to be called immediately
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) * after clk_hw_register_*().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) int clk_hw_register_clkdev(struct clk_hw *hw, const char *con_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) const char *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) struct clk_lookup *cl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) return do_clk_register_clkdev(hw, &cl, con_id, dev_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) EXPORT_SYMBOL(clk_hw_register_clkdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) static void devm_clkdev_release(struct device *dev, void *res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) clkdev_drop(*(struct clk_lookup **)res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) static int devm_clk_match_clkdev(struct device *dev, void *res, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) struct clk_lookup **l = res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) return *l == data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) * devm_clk_release_clkdev - Resource managed clkdev lookup release
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) * @dev: device this lookup is bound
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) * @con_id: connection ID string on device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) * @dev_id: format string describing device name
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) * Drop the clkdev lookup created with devm_clk_hw_register_clkdev.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) * Normally this function will not need to be called and the resource
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) * management code will ensure that the resource is freed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) void devm_clk_release_clkdev(struct device *dev, const char *con_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) const char *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) struct clk_lookup *cl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) int rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) mutex_lock(&clocks_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) cl = clk_find(dev_id, con_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) mutex_unlock(&clocks_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) WARN_ON(!cl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) rval = devres_release(dev, devm_clkdev_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) devm_clk_match_clkdev, cl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) WARN_ON(rval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) EXPORT_SYMBOL(devm_clk_release_clkdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) * devm_clk_hw_register_clkdev - managed clk lookup registration for clk_hw
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) * @dev: device this lookup is bound
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) * @hw: struct clk_hw to associate with all clk_lookups
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) * @con_id: connection ID string on device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) * @dev_id: format string describing device name
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) * con_id or dev_id may be NULL as a wildcard, just as in the rest of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) * clkdev.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) * To make things easier for mass registration, we detect error clk_hws
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) * from a previous clk_hw_register_*() call, and return the error code for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) * those. This is to permit this function to be called immediately
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) * after clk_hw_register_*().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) int devm_clk_hw_register_clkdev(struct device *dev, struct clk_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) const char *con_id, const char *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) int rval = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) struct clk_lookup **cl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) cl = devres_alloc(devm_clkdev_release, sizeof(*cl), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) if (cl) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) rval = do_clk_register_clkdev(hw, cl, con_id, dev_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) if (!rval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) devres_add(dev, cl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) devres_free(cl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) return rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) EXPORT_SYMBOL(devm_clk_hw_register_clkdev);