Blame view
drivers/clk/clkdev.c
3.6 KB
0318e693d [ARM] clkdev: add... |
1 |
/* |
6d803ba73 ARM: 6483/1: arm ... |
2 |
* drivers/clk/clkdev.c |
0318e693d [ARM] clkdev: add... |
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
* * Copyright (C) 2008 Russell King. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Helper for the clk API to assist looking up a struct clk. */ #include <linux/module.h> #include <linux/kernel.h> #include <linux/device.h> #include <linux/list.h> #include <linux/errno.h> #include <linux/err.h> #include <linux/string.h> #include <linux/mutex.h> |
c0c60c4b9 ARM: 5639/1: arm:... |
20 |
#include <linux/clk.h> |
6d803ba73 ARM: 6483/1: arm ... |
21 |
#include <linux/clkdev.h> |
0318e693d [ARM] clkdev: add... |
22 23 24 |
static LIST_HEAD(clocks); static DEFINE_MUTEX(clocks_mutex); |
409dc360b [ARM] clkdev: fix... |
25 26 27 28 29 30 31 |
/* * Find the correct struct clk for the device and connection ID. * We do slightly fuzzy matching here: * An entry with a NULL ID is assumed to be a wildcard. * If an entry has a device ID, it must match * If an entry has a connection ID, it must match * Then we take the most specific entry - with the following |
659431fca fix typos "precid... |
32 |
* order of precedence: dev+con > dev only > con only. |
409dc360b [ARM] clkdev: fix... |
33 |
*/ |
0318e693d [ARM] clkdev: add... |
34 35 36 37 38 39 40 |
static struct clk *clk_find(const char *dev_id, const char *con_id) { struct clk_lookup *p; struct clk *clk = NULL; int match, best = 0; list_for_each_entry(p, &clocks, node) { |
0318e693d [ARM] clkdev: add... |
41 |
match = 0; |
409dc360b [ARM] clkdev: fix... |
42 43 44 45 46 47 48 49 50 51 |
if (p->dev_id) { if (!dev_id || strcmp(p->dev_id, dev_id)) continue; match += 2; } if (p->con_id) { if (!con_id || strcmp(p->con_id, con_id)) continue; match += 1; } |
0318e693d [ARM] clkdev: add... |
52 53 54 |
if (match > best) { clk = p->clk; |
e4bf5becc ARM: 5979/1: CLKD... |
55 56 57 58 |
if (match != 3) best = match; else break; |
0318e693d [ARM] clkdev: add... |
59 60 61 62 |
} } return clk; } |
05fd8e73e clkdev: add possi... |
63 |
struct clk *clk_get_sys(const char *dev_id, const char *con_id) |
0318e693d [ARM] clkdev: add... |
64 |
{ |
0318e693d [ARM] clkdev: add... |
65 66 67 68 69 70 71 72 73 74 |
struct clk *clk; mutex_lock(&clocks_mutex); clk = clk_find(dev_id, con_id); if (clk && !__clk_get(clk)) clk = NULL; mutex_unlock(&clocks_mutex); return clk ? clk : ERR_PTR(-ENOENT); } |
05fd8e73e clkdev: add possi... |
75 76 77 78 79 80 81 82 |
EXPORT_SYMBOL(clk_get_sys); struct clk *clk_get(struct device *dev, const char *con_id) { const char *dev_id = dev ? dev_name(dev) : NULL; return clk_get_sys(dev_id, con_id); } |
0318e693d [ARM] clkdev: add... |
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 |
EXPORT_SYMBOL(clk_get); void clk_put(struct clk *clk) { __clk_put(clk); } EXPORT_SYMBOL(clk_put); void clkdev_add(struct clk_lookup *cl) { mutex_lock(&clocks_mutex); list_add_tail(&cl->node, &clocks); mutex_unlock(&clocks_mutex); } EXPORT_SYMBOL(clkdev_add); |
0a0300dc8 ARM: Consolidate ... |
98 99 100 101 102 103 104 105 106 |
void __init clkdev_add_table(struct clk_lookup *cl, size_t num) { mutex_lock(&clocks_mutex); while (num--) { list_add_tail(&cl->node, &clocks); cl++; } mutex_unlock(&clocks_mutex); } |
0318e693d [ARM] clkdev: add... |
107 108 109 110 111 112 113 114 |
#define MAX_DEV_ID 20 #define MAX_CON_ID 16 struct clk_lookup_alloc { struct clk_lookup cl; char dev_id[MAX_DEV_ID]; char con_id[MAX_CON_ID]; }; |
6d803ba73 ARM: 6483/1: arm ... |
115 116 |
struct clk_lookup * __init_refok clkdev_alloc(struct clk *clk, const char *con_id, const char *dev_fmt, ...) |
0318e693d [ARM] clkdev: add... |
117 118 |
{ struct clk_lookup_alloc *cla; |
6d803ba73 ARM: 6483/1: arm ... |
119 |
cla = __clkdev_alloc(sizeof(*cla)); |
0318e693d [ARM] clkdev: add... |
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
if (!cla) return NULL; cla->cl.clk = clk; if (con_id) { strlcpy(cla->con_id, con_id, sizeof(cla->con_id)); cla->cl.con_id = cla->con_id; } if (dev_fmt) { va_list ap; va_start(ap, dev_fmt); vscnprintf(cla->dev_id, sizeof(cla->dev_id), dev_fmt, ap); cla->cl.dev_id = cla->dev_id; va_end(ap); } return &cla->cl; } EXPORT_SYMBOL(clkdev_alloc); |
c06830392 [ARM] 5536/1: Mov... |
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 |
int clk_add_alias(const char *alias, const char *alias_dev_name, char *id, struct device *dev) { struct clk *r = clk_get(dev, id); struct clk_lookup *l; if (IS_ERR(r)) return PTR_ERR(r); l = clkdev_alloc(r, alias, alias_dev_name); clk_put(r); if (!l) return -ENODEV; clkdev_add(l); return 0; } EXPORT_SYMBOL(clk_add_alias); |
0318e693d [ARM] clkdev: add... |
158 159 160 161 162 163 164 165 166 167 168 |
/* * clkdev_drop - remove a clock dynamically allocated */ void clkdev_drop(struct clk_lookup *cl) { mutex_lock(&clocks_mutex); list_del(&cl->node); mutex_unlock(&clocks_mutex); kfree(cl); } EXPORT_SYMBOL(clkdev_drop); |