~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/arm/mach-ns9xxx/clock.c

Version: ~ [ linux-5.3-rc1 ] ~ [ linux-5.2.2 ] ~ [ linux-5.1.19 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.60 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.134 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.186 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.186 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.70 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.39.4 ] ~ [ linux-2.6.38.8 ] ~ [ linux-2.6.37.6 ] ~ [ linux-2.6.36.4 ] ~ [ linux-2.6.35.14 ] ~ [ linux-2.6.34.15 ] ~ [ linux-2.6.33.20 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  * arch/arm/mach-ns9xxx/clock.c
  3  *
  4  * Copyright (C) 2007 by Digi International Inc.
  5  * All rights reserved.
  6  *
  7  * This program is free software; you can redistribute it and/or modify it
  8  * under the terms of the GNU General Public License version 2 as published by
  9  * the Free Software Foundation.
 10  */
 11 #include <linux/err.h>
 12 #include <linux/module.h>
 13 #include <linux/list.h>
 14 #include <linux/clk.h>
 15 #include <linux/string.h>
 16 #include <linux/platform_device.h>
 17 #include <linux/semaphore.h>
 18 
 19 #include "clock.h"
 20 
 21 static LIST_HEAD(clocks);
 22 static DEFINE_SPINLOCK(clk_lock);
 23 
 24 struct clk *clk_get(struct device *dev, const char *id)
 25 {
 26         struct clk *p, *ret = NULL, *retgen = NULL;
 27         unsigned long flags;
 28         int idno;
 29 
 30         if (dev == NULL || dev->bus != &platform_bus_type)
 31                 idno = -1;
 32         else
 33                 idno = to_platform_device(dev)->id;
 34 
 35         spin_lock_irqsave(&clk_lock, flags);
 36         list_for_each_entry(p, &clocks, node) {
 37                 if (strcmp(id, p->name) == 0) {
 38                         if (p->id == idno) {
 39                                 if (!try_module_get(p->owner))
 40                                         continue;
 41                                 ret = p;
 42                                 break;
 43                         } else if (p->id == -1)
 44                                 /* remember match with id == -1 in case there is
 45                                  * no clock for idno */
 46                                 retgen = p;
 47                 }
 48         }
 49 
 50         if (!ret && retgen && try_module_get(retgen->owner))
 51                 ret = retgen;
 52 
 53         if (ret)
 54                 ++ret->refcount;
 55 
 56         spin_unlock_irqrestore(&clk_lock, flags);
 57 
 58         return ret ? ret : ERR_PTR(-ENOENT);
 59 }
 60 EXPORT_SYMBOL(clk_get);
 61 
 62 void clk_put(struct clk *clk)
 63 {
 64         module_put(clk->owner);
 65         --clk->refcount;
 66 }
 67 EXPORT_SYMBOL(clk_put);
 68 
 69 static int clk_enable_unlocked(struct clk *clk)
 70 {
 71         int ret = 0;
 72         if (clk->parent) {
 73                 ret = clk_enable_unlocked(clk->parent);
 74                 if (ret)
 75                         return ret;
 76         }
 77 
 78         if (clk->usage++ == 0 && clk->endisable)
 79                 ret = clk->endisable(clk, 1);
 80 
 81         return ret;
 82 }
 83 
 84 int clk_enable(struct clk *clk)
 85 {
 86         int ret;
 87         unsigned long flags;
 88 
 89         spin_lock_irqsave(&clk_lock, flags);
 90 
 91         ret = clk_enable_unlocked(clk);
 92 
 93         spin_unlock_irqrestore(&clk_lock, flags);
 94 
 95         return ret;
 96 }
 97 EXPORT_SYMBOL(clk_enable);
 98 
 99 static void clk_disable_unlocked(struct clk *clk)
100 {
101         if (--clk->usage == 0 && clk->endisable)
102                 clk->endisable(clk, 0);
103 
104         if (clk->parent)
105                 clk_disable_unlocked(clk->parent);
106 }
107 
108 void clk_disable(struct clk *clk)
109 {
110         unsigned long flags;
111 
112         spin_lock_irqsave(&clk_lock, flags);
113 
114         clk_disable_unlocked(clk);
115 
116         spin_unlock_irqrestore(&clk_lock, flags);
117 }
118 EXPORT_SYMBOL(clk_disable);
119 
120 unsigned long clk_get_rate(struct clk *clk)
121 {
122         if (clk->get_rate)
123                 return clk->get_rate(clk);
124 
125         if (clk->rate)
126                 return clk->rate;
127 
128         if (clk->parent)
129                 return clk_get_rate(clk->parent);
130 
131         return 0;
132 }
133 EXPORT_SYMBOL(clk_get_rate);
134 
135 int clk_register(struct clk *clk)
136 {
137         unsigned long flags;
138 
139         spin_lock_irqsave(&clk_lock, flags);
140 
141         list_add(&clk->node, &clocks);
142 
143         if (clk->parent)
144                 ++clk->parent->refcount;
145 
146         spin_unlock_irqrestore(&clk_lock, flags);
147 
148         return 0;
149 }
150 
151 int clk_unregister(struct clk *clk)
152 {
153         int ret = 0;
154         unsigned long flags;
155 
156         spin_lock_irqsave(&clk_lock, flags);
157 
158         if (clk->usage || clk->refcount)
159                 ret = -EBUSY;
160         else
161                 list_del(&clk->node);
162 
163         if (clk->parent)
164                 --clk->parent->refcount;
165 
166         spin_unlock_irqrestore(&clk_lock, flags);
167 
168         return ret;
169 }
170 
171 #if defined CONFIG_DEBUG_FS
172 
173 #include <linux/debugfs.h>
174 #include <linux/seq_file.h>
175 
176 static int clk_debugfs_show(struct seq_file *s, void *null)
177 {
178         unsigned long flags;
179         struct clk *p;
180 
181         spin_lock_irqsave(&clk_lock, flags);
182 
183         list_for_each_entry(p, &clocks, node)
184                 seq_printf(s, "%s.%d: usage=%lu refcount=%lu rate=%lu\n",
185                                 p->name, p->id, p->usage, p->refcount,
186                                 p->usage ? clk_get_rate(p) : 0);
187 
188         spin_unlock_irqrestore(&clk_lock, flags);
189 
190         return 0;
191 }
192 
193 static int clk_debugfs_open(struct inode *inode, struct file *file)
194 {
195         return single_open(file, clk_debugfs_show, NULL);
196 }
197 
198 static const struct file_operations clk_debugfs_operations = {
199         .open = clk_debugfs_open,
200         .read = seq_read,
201         .llseek = seq_lseek,
202         .release = single_release,
203 };
204 
205 static int __init clk_debugfs_init(void)
206 {
207         struct dentry *dentry;
208 
209         dentry = debugfs_create_file("clk", S_IFREG | S_IRUGO, NULL, NULL,
210                         &clk_debugfs_operations);
211         return IS_ERR(dentry) ? PTR_ERR(dentry) : 0;
212 }
213 subsys_initcall(clk_debugfs_init);
214 
215 #endif /* if defined CONFIG_DEBUG_FS */
216 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp