1 /* 2 * drivers/clk/clkdev.c 3 * 4 * Copyright (C) 2008 Russell King. 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 2 as 8 * published by the Free Software Foundation. 9 * 10 * Helper for the clk API to assist looking up a struct clk. 11 */ 12 #include <linux/module.h> 13 #include <linux/kernel.h> 14 #include <linux/device.h> 15 #include <linux/list.h> 16 #include <linux/errno.h> 17 #include <linux/err.h> 18 #include <linux/string.h> 19 #include <linux/mutex.h> 20 #include <linux/clk.h> 21 #include <linux/clkdev.h> 22 23 static LIST_HEAD(clocks); 24 static DEFINE_MUTEX(clocks_mutex); 25 26 /* 27 * Find the correct struct clk for the device and connection ID. 28 * We do slightly fuzzy matching here: 29 * An entry with a NULL ID is assumed to be a wildcard. 30 * If an entry has a device ID, it must match 31 * If an entry has a connection ID, it must match 32 * Then we take the most specific entry - with the following 33 * order of precedence: dev+con > dev only > con only. 34 */ 35 static struct clk_lookup *clk_find(const char *dev_id, const char *con_id) 36 { 37 struct clk_lookup *p, *cl = NULL; 38 int match, best_found = 0, best_possible = 0; 39 40 if (dev_id) 41 best_possible += 2; 42 if (con_id) 43 best_possible += 1; 44 45 list_for_each_entry(p, &clocks, node) { 46 match = 0; 47 if (p->dev_id) { 48 if (!dev_id || strcmp(p->dev_id, dev_id)) 49 continue; 50 match += 2; 51 } 52 if (p->con_id) { 53 if (!con_id || strcmp(p->con_id, con_id)) 54 continue; 55 match += 1; 56 } 57 58 if (match > best_found) { 59 cl = p; 60 if (match != best_possible) 61 best_found = match; 62 else 63 break; 64 } 65 } 66 return cl; 67 } 68 69 struct clk *clk_get_sys(const char *dev_id, const char *con_id) 70 { 71 struct clk_lookup *cl; 72 73 mutex_lock(&clocks_mutex); 74 cl = clk_find(dev_id, con_id); 75 if (cl && !__clk_get(cl->clk)) 76 cl = NULL; 77 mutex_unlock(&clocks_mutex); 78 79 return cl ? cl->clk : ERR_PTR(-ENOENT); 80 } 81 EXPORT_SYMBOL(clk_get_sys); 82 83 struct clk *clk_get(struct device *dev, const char *con_id) 84 { 85 const char *dev_id = dev ? dev_name(dev) : NULL; 86 87 return clk_get_sys(dev_id, con_id); 88 } 89 EXPORT_SYMBOL(clk_get); 90 91 void clk_put(struct clk *clk) 92 { 93 __clk_put(clk); 94 } 95 EXPORT_SYMBOL(clk_put); 96 97 static void devm_clk_release(struct device *dev, void *res) 98 { 99 clk_put(*(struct clk **)res); 100 } 101 102 struct clk *devm_clk_get(struct device *dev, const char *id) 103 { 104 struct clk **ptr, *clk; 105 106 ptr = devres_alloc(devm_clk_release, sizeof(*ptr), GFP_KERNEL); 107 if (!ptr) 108 return ERR_PTR(-ENOMEM); 109 110 clk = clk_get(dev, id); 111 if (!IS_ERR(clk)) { 112 *ptr = clk; 113 devres_add(dev, ptr); 114 } else { 115 devres_free(ptr); 116 } 117 118 return clk; 119 } 120 EXPORT_SYMBOL(devm_clk_get); 121 122 static int devm_clk_match(struct device *dev, void *res, void *data) 123 { 124 struct clk **c = res; 125 if (!c || !*c) { 126 WARN_ON(!c || !*c); 127 return 0; 128 } 129 return *c == data; 130 } 131 132 void devm_clk_put(struct device *dev, struct clk *clk) 133 { 134 int ret; 135 136 ret = devres_destroy(dev, devm_clk_release, devm_clk_match, clk); 137 138 WARN_ON(ret); 139 } 140 EXPORT_SYMBOL(devm_clk_put); 141 142 void clkdev_add(struct clk_lookup *cl) 143 { 144 mutex_lock(&clocks_mutex); 145 list_add_tail(&cl->node, &clocks); 146 mutex_unlock(&clocks_mutex); 147 } 148 EXPORT_SYMBOL(clkdev_add); 149 150 void __init clkdev_add_table(struct clk_lookup *cl, size_t num) 151 { 152 mutex_lock(&clocks_mutex); 153 while (num--) { 154 list_add_tail(&cl->node, &clocks); 155 cl++; 156 } 157 mutex_unlock(&clocks_mutex); 158 } 159 160 #define MAX_DEV_ID 20 161 #define MAX_CON_ID 16 162 163 struct clk_lookup_alloc { 164 struct clk_lookup cl; 165 char dev_id[MAX_DEV_ID]; 166 char con_id[MAX_CON_ID]; 167 }; 168 169 static struct clk_lookup * __init_refok 170 vclkdev_alloc(struct clk *clk, const char *con_id, const char *dev_fmt, 171 va_list ap) 172 { 173 struct clk_lookup_alloc *cla; 174 175 cla = __clkdev_alloc(sizeof(*cla)); 176 if (!cla) 177 return NULL; 178 179 cla->cl.clk = clk; 180 if (con_id) { 181 strlcpy(cla->con_id, con_id, sizeof(cla->con_id)); 182 cla->cl.con_id = cla->con_id; 183 } 184 185 if (dev_fmt) { 186 vscnprintf(cla->dev_id, sizeof(cla->dev_id), dev_fmt, ap); 187 cla->cl.dev_id = cla->dev_id; 188 } 189 190 return &cla->cl; 191 } 192 193 struct clk_lookup * __init_refok 194 clkdev_alloc(struct clk *clk, const char *con_id, const char *dev_fmt, ...) 195 { 196 struct clk_lookup *cl; 197 va_list ap; 198 199 va_start(ap, dev_fmt); 200 cl = vclkdev_alloc(clk, con_id, dev_fmt, ap); 201 va_end(ap); 202 203 return cl; 204 } 205 EXPORT_SYMBOL(clkdev_alloc); 206 207 int clk_add_alias(const char *alias, const char *alias_dev_name, char *id, 208 struct device *dev) 209 { 210 struct clk *r = clk_get(dev, id); 211 struct clk_lookup *l; 212 213 if (IS_ERR(r)) 214 return PTR_ERR(r); 215 216 l = clkdev_alloc(r, alias, alias_dev_name); 217 clk_put(r); 218 if (!l) 219 return -ENODEV; 220 clkdev_add(l); 221 return 0; 222 } 223 EXPORT_SYMBOL(clk_add_alias); 224 225 /* 226 * clkdev_drop - remove a clock dynamically allocated 227 */ 228 void clkdev_drop(struct clk_lookup *cl) 229 { 230 mutex_lock(&clocks_mutex); 231 list_del(&cl->node); 232 mutex_unlock(&clocks_mutex); 233 kfree(cl); 234 } 235 EXPORT_SYMBOL(clkdev_drop); 236 237 /** 238 * clk_register_clkdev - register one clock lookup for a struct clk 239 * @clk: struct clk to associate with all clk_lookups 240 * @con_id: connection ID string on device 241 * @dev_id: format string describing device name 242 * 243 * con_id or dev_id may be NULL as a wildcard, just as in the rest of 244 * clkdev. 245 * 246 * To make things easier for mass registration, we detect error clks 247 * from a previous clk_register() call, and return the error code for 248 * those. This is to permit this function to be called immediately 249 * after clk_register(). 250 */ 251 int clk_register_clkdev(struct clk *clk, const char *con_id, 252 const char *dev_fmt, ...) 253 { 254 struct clk_lookup *cl; 255 va_list ap; 256 257 if (IS_ERR(clk)) 258 return PTR_ERR(clk); 259 260 va_start(ap, dev_fmt); 261 cl = vclkdev_alloc(clk, con_id, dev_fmt, ap); 262 va_end(ap); 263 264 if (!cl) 265 return -ENOMEM; 266 267 clkdev_add(cl); 268 269 return 0; 270 } 271 272 /** 273 * clk_register_clkdevs - register a set of clk_lookup for a struct clk 274 * @clk: struct clk to associate with all clk_lookups 275 * @cl: array of clk_lookup structures with con_id and dev_id pre-initialized 276 * @num: number of clk_lookup structures to register 277 * 278 * To make things easier for mass registration, we detect error clks 279 * from a previous clk_register() call, and return the error code for 280 * those. This is to permit this function to be called immediately 281 * after clk_register(). 282 */ 283 int clk_register_clkdevs(struct clk *clk, struct clk_lookup *cl, size_t num) 284 { 285 unsigned i; 286 287 if (IS_ERR(clk)) 288 return PTR_ERR(clk); 289 290 for (i = 0; i < num; i++, cl++) { 291 cl->clk = clk; 292 clkdev_add(cl); 293 } 294 295 return 0; 296 } 297 EXPORT_SYMBOL(clk_register_clkdevs); 298