1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Clock and PLL control for C64x+ devices
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright (C) 2010, 2011 Texas Instruments.
6*4882a593Smuzhiyun * Contributed by: Mark Salter <msalter@redhat.com>
7*4882a593Smuzhiyun *
8*4882a593Smuzhiyun * Copied heavily from arm/mach-davinci/clock.c, so:
9*4882a593Smuzhiyun *
10*4882a593Smuzhiyun * Copyright (C) 2006-2007 Texas Instruments.
11*4882a593Smuzhiyun * Copyright (C) 2008-2009 Deep Root Systems, LLC
12*4882a593Smuzhiyun */
13*4882a593Smuzhiyun
14*4882a593Smuzhiyun #include <linux/module.h>
15*4882a593Smuzhiyun #include <linux/clkdev.h>
16*4882a593Smuzhiyun #include <linux/clk.h>
17*4882a593Smuzhiyun #include <linux/io.h>
18*4882a593Smuzhiyun #include <linux/err.h>
19*4882a593Smuzhiyun
20*4882a593Smuzhiyun #include <asm/clock.h>
21*4882a593Smuzhiyun #include <asm/soc.h>
22*4882a593Smuzhiyun
23*4882a593Smuzhiyun static LIST_HEAD(clocks);
24*4882a593Smuzhiyun static DEFINE_MUTEX(clocks_mutex);
25*4882a593Smuzhiyun static DEFINE_SPINLOCK(clockfw_lock);
26*4882a593Smuzhiyun
__clk_enable(struct clk * clk)27*4882a593Smuzhiyun static void __clk_enable(struct clk *clk)
28*4882a593Smuzhiyun {
29*4882a593Smuzhiyun if (clk->parent)
30*4882a593Smuzhiyun __clk_enable(clk->parent);
31*4882a593Smuzhiyun clk->usecount++;
32*4882a593Smuzhiyun }
33*4882a593Smuzhiyun
__clk_disable(struct clk * clk)34*4882a593Smuzhiyun static void __clk_disable(struct clk *clk)
35*4882a593Smuzhiyun {
36*4882a593Smuzhiyun if (WARN_ON(clk->usecount == 0))
37*4882a593Smuzhiyun return;
38*4882a593Smuzhiyun --clk->usecount;
39*4882a593Smuzhiyun
40*4882a593Smuzhiyun if (clk->parent)
41*4882a593Smuzhiyun __clk_disable(clk->parent);
42*4882a593Smuzhiyun }
43*4882a593Smuzhiyun
clk_enable(struct clk * clk)44*4882a593Smuzhiyun int clk_enable(struct clk *clk)
45*4882a593Smuzhiyun {
46*4882a593Smuzhiyun unsigned long flags;
47*4882a593Smuzhiyun
48*4882a593Smuzhiyun if (clk == NULL || IS_ERR(clk))
49*4882a593Smuzhiyun return -EINVAL;
50*4882a593Smuzhiyun
51*4882a593Smuzhiyun spin_lock_irqsave(&clockfw_lock, flags);
52*4882a593Smuzhiyun __clk_enable(clk);
53*4882a593Smuzhiyun spin_unlock_irqrestore(&clockfw_lock, flags);
54*4882a593Smuzhiyun
55*4882a593Smuzhiyun return 0;
56*4882a593Smuzhiyun }
57*4882a593Smuzhiyun EXPORT_SYMBOL(clk_enable);
58*4882a593Smuzhiyun
clk_disable(struct clk * clk)59*4882a593Smuzhiyun void clk_disable(struct clk *clk)
60*4882a593Smuzhiyun {
61*4882a593Smuzhiyun unsigned long flags;
62*4882a593Smuzhiyun
63*4882a593Smuzhiyun if (clk == NULL || IS_ERR(clk))
64*4882a593Smuzhiyun return;
65*4882a593Smuzhiyun
66*4882a593Smuzhiyun spin_lock_irqsave(&clockfw_lock, flags);
67*4882a593Smuzhiyun __clk_disable(clk);
68*4882a593Smuzhiyun spin_unlock_irqrestore(&clockfw_lock, flags);
69*4882a593Smuzhiyun }
70*4882a593Smuzhiyun EXPORT_SYMBOL(clk_disable);
71*4882a593Smuzhiyun
clk_get_rate(struct clk * clk)72*4882a593Smuzhiyun unsigned long clk_get_rate(struct clk *clk)
73*4882a593Smuzhiyun {
74*4882a593Smuzhiyun if (clk == NULL || IS_ERR(clk))
75*4882a593Smuzhiyun return -EINVAL;
76*4882a593Smuzhiyun
77*4882a593Smuzhiyun return clk->rate;
78*4882a593Smuzhiyun }
79*4882a593Smuzhiyun EXPORT_SYMBOL(clk_get_rate);
80*4882a593Smuzhiyun
clk_round_rate(struct clk * clk,unsigned long rate)81*4882a593Smuzhiyun long clk_round_rate(struct clk *clk, unsigned long rate)
82*4882a593Smuzhiyun {
83*4882a593Smuzhiyun if (clk == NULL || IS_ERR(clk))
84*4882a593Smuzhiyun return -EINVAL;
85*4882a593Smuzhiyun
86*4882a593Smuzhiyun if (clk->round_rate)
87*4882a593Smuzhiyun return clk->round_rate(clk, rate);
88*4882a593Smuzhiyun
89*4882a593Smuzhiyun return clk->rate;
90*4882a593Smuzhiyun }
91*4882a593Smuzhiyun EXPORT_SYMBOL(clk_round_rate);
92*4882a593Smuzhiyun
93*4882a593Smuzhiyun /* Propagate rate to children */
propagate_rate(struct clk * root)94*4882a593Smuzhiyun static void propagate_rate(struct clk *root)
95*4882a593Smuzhiyun {
96*4882a593Smuzhiyun struct clk *clk;
97*4882a593Smuzhiyun
98*4882a593Smuzhiyun list_for_each_entry(clk, &root->children, childnode) {
99*4882a593Smuzhiyun if (clk->recalc)
100*4882a593Smuzhiyun clk->rate = clk->recalc(clk);
101*4882a593Smuzhiyun propagate_rate(clk);
102*4882a593Smuzhiyun }
103*4882a593Smuzhiyun }
104*4882a593Smuzhiyun
clk_set_rate(struct clk * clk,unsigned long rate)105*4882a593Smuzhiyun int clk_set_rate(struct clk *clk, unsigned long rate)
106*4882a593Smuzhiyun {
107*4882a593Smuzhiyun unsigned long flags;
108*4882a593Smuzhiyun int ret = -EINVAL;
109*4882a593Smuzhiyun
110*4882a593Smuzhiyun if (clk == NULL || IS_ERR(clk))
111*4882a593Smuzhiyun return ret;
112*4882a593Smuzhiyun
113*4882a593Smuzhiyun if (clk->set_rate)
114*4882a593Smuzhiyun ret = clk->set_rate(clk, rate);
115*4882a593Smuzhiyun
116*4882a593Smuzhiyun spin_lock_irqsave(&clockfw_lock, flags);
117*4882a593Smuzhiyun if (ret == 0) {
118*4882a593Smuzhiyun if (clk->recalc)
119*4882a593Smuzhiyun clk->rate = clk->recalc(clk);
120*4882a593Smuzhiyun propagate_rate(clk);
121*4882a593Smuzhiyun }
122*4882a593Smuzhiyun spin_unlock_irqrestore(&clockfw_lock, flags);
123*4882a593Smuzhiyun
124*4882a593Smuzhiyun return ret;
125*4882a593Smuzhiyun }
126*4882a593Smuzhiyun EXPORT_SYMBOL(clk_set_rate);
127*4882a593Smuzhiyun
clk_set_parent(struct clk * clk,struct clk * parent)128*4882a593Smuzhiyun int clk_set_parent(struct clk *clk, struct clk *parent)
129*4882a593Smuzhiyun {
130*4882a593Smuzhiyun unsigned long flags;
131*4882a593Smuzhiyun
132*4882a593Smuzhiyun if (clk == NULL || IS_ERR(clk))
133*4882a593Smuzhiyun return -EINVAL;
134*4882a593Smuzhiyun
135*4882a593Smuzhiyun /* Cannot change parent on enabled clock */
136*4882a593Smuzhiyun if (WARN_ON(clk->usecount))
137*4882a593Smuzhiyun return -EINVAL;
138*4882a593Smuzhiyun
139*4882a593Smuzhiyun mutex_lock(&clocks_mutex);
140*4882a593Smuzhiyun clk->parent = parent;
141*4882a593Smuzhiyun list_del_init(&clk->childnode);
142*4882a593Smuzhiyun list_add(&clk->childnode, &clk->parent->children);
143*4882a593Smuzhiyun mutex_unlock(&clocks_mutex);
144*4882a593Smuzhiyun
145*4882a593Smuzhiyun spin_lock_irqsave(&clockfw_lock, flags);
146*4882a593Smuzhiyun if (clk->recalc)
147*4882a593Smuzhiyun clk->rate = clk->recalc(clk);
148*4882a593Smuzhiyun propagate_rate(clk);
149*4882a593Smuzhiyun spin_unlock_irqrestore(&clockfw_lock, flags);
150*4882a593Smuzhiyun
151*4882a593Smuzhiyun return 0;
152*4882a593Smuzhiyun }
153*4882a593Smuzhiyun EXPORT_SYMBOL(clk_set_parent);
154*4882a593Smuzhiyun
clk_register(struct clk * clk)155*4882a593Smuzhiyun int clk_register(struct clk *clk)
156*4882a593Smuzhiyun {
157*4882a593Smuzhiyun if (clk == NULL || IS_ERR(clk))
158*4882a593Smuzhiyun return -EINVAL;
159*4882a593Smuzhiyun
160*4882a593Smuzhiyun if (WARN(clk->parent && !clk->parent->rate,
161*4882a593Smuzhiyun "CLK: %s parent %s has no rate!\n",
162*4882a593Smuzhiyun clk->name, clk->parent->name))
163*4882a593Smuzhiyun return -EINVAL;
164*4882a593Smuzhiyun
165*4882a593Smuzhiyun mutex_lock(&clocks_mutex);
166*4882a593Smuzhiyun list_add_tail(&clk->node, &clocks);
167*4882a593Smuzhiyun if (clk->parent)
168*4882a593Smuzhiyun list_add_tail(&clk->childnode, &clk->parent->children);
169*4882a593Smuzhiyun mutex_unlock(&clocks_mutex);
170*4882a593Smuzhiyun
171*4882a593Smuzhiyun /* If rate is already set, use it */
172*4882a593Smuzhiyun if (clk->rate)
173*4882a593Smuzhiyun return 0;
174*4882a593Smuzhiyun
175*4882a593Smuzhiyun /* Else, see if there is a way to calculate it */
176*4882a593Smuzhiyun if (clk->recalc)
177*4882a593Smuzhiyun clk->rate = clk->recalc(clk);
178*4882a593Smuzhiyun
179*4882a593Smuzhiyun /* Otherwise, default to parent rate */
180*4882a593Smuzhiyun else if (clk->parent)
181*4882a593Smuzhiyun clk->rate = clk->parent->rate;
182*4882a593Smuzhiyun
183*4882a593Smuzhiyun return 0;
184*4882a593Smuzhiyun }
185*4882a593Smuzhiyun EXPORT_SYMBOL(clk_register);
186*4882a593Smuzhiyun
clk_unregister(struct clk * clk)187*4882a593Smuzhiyun void clk_unregister(struct clk *clk)
188*4882a593Smuzhiyun {
189*4882a593Smuzhiyun if (clk == NULL || IS_ERR(clk))
190*4882a593Smuzhiyun return;
191*4882a593Smuzhiyun
192*4882a593Smuzhiyun mutex_lock(&clocks_mutex);
193*4882a593Smuzhiyun list_del(&clk->node);
194*4882a593Smuzhiyun list_del(&clk->childnode);
195*4882a593Smuzhiyun mutex_unlock(&clocks_mutex);
196*4882a593Smuzhiyun }
197*4882a593Smuzhiyun EXPORT_SYMBOL(clk_unregister);
198*4882a593Smuzhiyun
199*4882a593Smuzhiyun
pll_read(struct pll_data * pll,int reg)200*4882a593Smuzhiyun static u32 pll_read(struct pll_data *pll, int reg)
201*4882a593Smuzhiyun {
202*4882a593Smuzhiyun return soc_readl(pll->base + reg);
203*4882a593Smuzhiyun }
204*4882a593Smuzhiyun
clk_sysclk_recalc(struct clk * clk)205*4882a593Smuzhiyun static unsigned long clk_sysclk_recalc(struct clk *clk)
206*4882a593Smuzhiyun {
207*4882a593Smuzhiyun u32 v, plldiv = 0;
208*4882a593Smuzhiyun struct pll_data *pll;
209*4882a593Smuzhiyun unsigned long rate = clk->rate;
210*4882a593Smuzhiyun
211*4882a593Smuzhiyun if (WARN_ON(!clk->parent))
212*4882a593Smuzhiyun return rate;
213*4882a593Smuzhiyun
214*4882a593Smuzhiyun rate = clk->parent->rate;
215*4882a593Smuzhiyun
216*4882a593Smuzhiyun /* the parent must be a PLL */
217*4882a593Smuzhiyun if (WARN_ON(!clk->parent->pll_data))
218*4882a593Smuzhiyun return rate;
219*4882a593Smuzhiyun
220*4882a593Smuzhiyun pll = clk->parent->pll_data;
221*4882a593Smuzhiyun
222*4882a593Smuzhiyun /* If pre-PLL, source clock is before the multiplier and divider(s) */
223*4882a593Smuzhiyun if (clk->flags & PRE_PLL)
224*4882a593Smuzhiyun rate = pll->input_rate;
225*4882a593Smuzhiyun
226*4882a593Smuzhiyun if (!clk->div) {
227*4882a593Smuzhiyun pr_debug("%s: (no divider) rate = %lu KHz\n",
228*4882a593Smuzhiyun clk->name, rate / 1000);
229*4882a593Smuzhiyun return rate;
230*4882a593Smuzhiyun }
231*4882a593Smuzhiyun
232*4882a593Smuzhiyun if (clk->flags & FIXED_DIV_PLL) {
233*4882a593Smuzhiyun rate /= clk->div;
234*4882a593Smuzhiyun pr_debug("%s: (fixed divide by %d) rate = %lu KHz\n",
235*4882a593Smuzhiyun clk->name, clk->div, rate / 1000);
236*4882a593Smuzhiyun return rate;
237*4882a593Smuzhiyun }
238*4882a593Smuzhiyun
239*4882a593Smuzhiyun v = pll_read(pll, clk->div);
240*4882a593Smuzhiyun if (v & PLLDIV_EN)
241*4882a593Smuzhiyun plldiv = (v & PLLDIV_RATIO_MASK) + 1;
242*4882a593Smuzhiyun
243*4882a593Smuzhiyun if (plldiv == 0)
244*4882a593Smuzhiyun plldiv = 1;
245*4882a593Smuzhiyun
246*4882a593Smuzhiyun rate /= plldiv;
247*4882a593Smuzhiyun
248*4882a593Smuzhiyun pr_debug("%s: (divide by %d) rate = %lu KHz\n",
249*4882a593Smuzhiyun clk->name, plldiv, rate / 1000);
250*4882a593Smuzhiyun
251*4882a593Smuzhiyun return rate;
252*4882a593Smuzhiyun }
253*4882a593Smuzhiyun
clk_leafclk_recalc(struct clk * clk)254*4882a593Smuzhiyun static unsigned long clk_leafclk_recalc(struct clk *clk)
255*4882a593Smuzhiyun {
256*4882a593Smuzhiyun if (WARN_ON(!clk->parent))
257*4882a593Smuzhiyun return clk->rate;
258*4882a593Smuzhiyun
259*4882a593Smuzhiyun pr_debug("%s: (parent %s) rate = %lu KHz\n",
260*4882a593Smuzhiyun clk->name, clk->parent->name, clk->parent->rate / 1000);
261*4882a593Smuzhiyun
262*4882a593Smuzhiyun return clk->parent->rate;
263*4882a593Smuzhiyun }
264*4882a593Smuzhiyun
clk_pllclk_recalc(struct clk * clk)265*4882a593Smuzhiyun static unsigned long clk_pllclk_recalc(struct clk *clk)
266*4882a593Smuzhiyun {
267*4882a593Smuzhiyun u32 ctrl, mult = 0, prediv = 0, postdiv = 0;
268*4882a593Smuzhiyun u8 bypass;
269*4882a593Smuzhiyun struct pll_data *pll = clk->pll_data;
270*4882a593Smuzhiyun unsigned long rate = clk->rate;
271*4882a593Smuzhiyun
272*4882a593Smuzhiyun if (clk->flags & FIXED_RATE_PLL)
273*4882a593Smuzhiyun return rate;
274*4882a593Smuzhiyun
275*4882a593Smuzhiyun ctrl = pll_read(pll, PLLCTL);
276*4882a593Smuzhiyun rate = pll->input_rate = clk->parent->rate;
277*4882a593Smuzhiyun
278*4882a593Smuzhiyun if (ctrl & PLLCTL_PLLEN)
279*4882a593Smuzhiyun bypass = 0;
280*4882a593Smuzhiyun else
281*4882a593Smuzhiyun bypass = 1;
282*4882a593Smuzhiyun
283*4882a593Smuzhiyun if (pll->flags & PLL_HAS_MUL) {
284*4882a593Smuzhiyun mult = pll_read(pll, PLLM);
285*4882a593Smuzhiyun mult = (mult & PLLM_PLLM_MASK) + 1;
286*4882a593Smuzhiyun }
287*4882a593Smuzhiyun if (pll->flags & PLL_HAS_PRE) {
288*4882a593Smuzhiyun prediv = pll_read(pll, PLLPRE);
289*4882a593Smuzhiyun if (prediv & PLLDIV_EN)
290*4882a593Smuzhiyun prediv = (prediv & PLLDIV_RATIO_MASK) + 1;
291*4882a593Smuzhiyun else
292*4882a593Smuzhiyun prediv = 0;
293*4882a593Smuzhiyun }
294*4882a593Smuzhiyun if (pll->flags & PLL_HAS_POST) {
295*4882a593Smuzhiyun postdiv = pll_read(pll, PLLPOST);
296*4882a593Smuzhiyun if (postdiv & PLLDIV_EN)
297*4882a593Smuzhiyun postdiv = (postdiv & PLLDIV_RATIO_MASK) + 1;
298*4882a593Smuzhiyun else
299*4882a593Smuzhiyun postdiv = 1;
300*4882a593Smuzhiyun }
301*4882a593Smuzhiyun
302*4882a593Smuzhiyun if (!bypass) {
303*4882a593Smuzhiyun if (prediv)
304*4882a593Smuzhiyun rate /= prediv;
305*4882a593Smuzhiyun if (mult)
306*4882a593Smuzhiyun rate *= mult;
307*4882a593Smuzhiyun if (postdiv)
308*4882a593Smuzhiyun rate /= postdiv;
309*4882a593Smuzhiyun
310*4882a593Smuzhiyun pr_debug("PLL%d: input = %luMHz, pre[%d] mul[%d] post[%d] "
311*4882a593Smuzhiyun "--> %luMHz output.\n",
312*4882a593Smuzhiyun pll->num, clk->parent->rate / 1000000,
313*4882a593Smuzhiyun prediv, mult, postdiv, rate / 1000000);
314*4882a593Smuzhiyun } else
315*4882a593Smuzhiyun pr_debug("PLL%d: input = %luMHz, bypass mode.\n",
316*4882a593Smuzhiyun pll->num, clk->parent->rate / 1000000);
317*4882a593Smuzhiyun
318*4882a593Smuzhiyun return rate;
319*4882a593Smuzhiyun }
320*4882a593Smuzhiyun
321*4882a593Smuzhiyun
__init_clk(struct clk * clk)322*4882a593Smuzhiyun static void __init __init_clk(struct clk *clk)
323*4882a593Smuzhiyun {
324*4882a593Smuzhiyun INIT_LIST_HEAD(&clk->node);
325*4882a593Smuzhiyun INIT_LIST_HEAD(&clk->children);
326*4882a593Smuzhiyun INIT_LIST_HEAD(&clk->childnode);
327*4882a593Smuzhiyun
328*4882a593Smuzhiyun if (!clk->recalc) {
329*4882a593Smuzhiyun
330*4882a593Smuzhiyun /* Check if clock is a PLL */
331*4882a593Smuzhiyun if (clk->pll_data)
332*4882a593Smuzhiyun clk->recalc = clk_pllclk_recalc;
333*4882a593Smuzhiyun
334*4882a593Smuzhiyun /* Else, if it is a PLL-derived clock */
335*4882a593Smuzhiyun else if (clk->flags & CLK_PLL)
336*4882a593Smuzhiyun clk->recalc = clk_sysclk_recalc;
337*4882a593Smuzhiyun
338*4882a593Smuzhiyun /* Otherwise, it is a leaf clock (PSC clock) */
339*4882a593Smuzhiyun else if (clk->parent)
340*4882a593Smuzhiyun clk->recalc = clk_leafclk_recalc;
341*4882a593Smuzhiyun }
342*4882a593Smuzhiyun }
343*4882a593Smuzhiyun
c6x_clks_init(struct clk_lookup * clocks)344*4882a593Smuzhiyun void __init c6x_clks_init(struct clk_lookup *clocks)
345*4882a593Smuzhiyun {
346*4882a593Smuzhiyun struct clk_lookup *c;
347*4882a593Smuzhiyun struct clk *clk;
348*4882a593Smuzhiyun size_t num_clocks = 0;
349*4882a593Smuzhiyun
350*4882a593Smuzhiyun for (c = clocks; c->clk; c++) {
351*4882a593Smuzhiyun clk = c->clk;
352*4882a593Smuzhiyun
353*4882a593Smuzhiyun __init_clk(clk);
354*4882a593Smuzhiyun clk_register(clk);
355*4882a593Smuzhiyun num_clocks++;
356*4882a593Smuzhiyun
357*4882a593Smuzhiyun /* Turn on clocks that Linux doesn't otherwise manage */
358*4882a593Smuzhiyun if (clk->flags & ALWAYS_ENABLED)
359*4882a593Smuzhiyun clk_enable(clk);
360*4882a593Smuzhiyun }
361*4882a593Smuzhiyun
362*4882a593Smuzhiyun clkdev_add_table(clocks, num_clocks);
363*4882a593Smuzhiyun }
364*4882a593Smuzhiyun
365*4882a593Smuzhiyun #ifdef CONFIG_DEBUG_FS
366*4882a593Smuzhiyun
367*4882a593Smuzhiyun #include <linux/debugfs.h>
368*4882a593Smuzhiyun #include <linux/seq_file.h>
369*4882a593Smuzhiyun
370*4882a593Smuzhiyun #define CLKNAME_MAX 10 /* longest clock name */
371*4882a593Smuzhiyun #define NEST_DELTA 2
372*4882a593Smuzhiyun #define NEST_MAX 4
373*4882a593Smuzhiyun
374*4882a593Smuzhiyun static void
dump_clock(struct seq_file * s,unsigned nest,struct clk * parent)375*4882a593Smuzhiyun dump_clock(struct seq_file *s, unsigned nest, struct clk *parent)
376*4882a593Smuzhiyun {
377*4882a593Smuzhiyun char *state;
378*4882a593Smuzhiyun char buf[CLKNAME_MAX + NEST_DELTA * NEST_MAX];
379*4882a593Smuzhiyun struct clk *clk;
380*4882a593Smuzhiyun unsigned i;
381*4882a593Smuzhiyun
382*4882a593Smuzhiyun if (parent->flags & CLK_PLL)
383*4882a593Smuzhiyun state = "pll";
384*4882a593Smuzhiyun else
385*4882a593Smuzhiyun state = "";
386*4882a593Smuzhiyun
387*4882a593Smuzhiyun /* <nest spaces> name <pad to end> */
388*4882a593Smuzhiyun memset(buf, ' ', sizeof(buf) - 1);
389*4882a593Smuzhiyun buf[sizeof(buf) - 1] = 0;
390*4882a593Smuzhiyun i = strlen(parent->name);
391*4882a593Smuzhiyun memcpy(buf + nest, parent->name,
392*4882a593Smuzhiyun min(i, (unsigned)(sizeof(buf) - 1 - nest)));
393*4882a593Smuzhiyun
394*4882a593Smuzhiyun seq_printf(s, "%s users=%2d %-3s %9ld Hz\n",
395*4882a593Smuzhiyun buf, parent->usecount, state, clk_get_rate(parent));
396*4882a593Smuzhiyun /* REVISIT show device associations too */
397*4882a593Smuzhiyun
398*4882a593Smuzhiyun /* cost is now small, but not linear... */
399*4882a593Smuzhiyun list_for_each_entry(clk, &parent->children, childnode) {
400*4882a593Smuzhiyun dump_clock(s, nest + NEST_DELTA, clk);
401*4882a593Smuzhiyun }
402*4882a593Smuzhiyun }
403*4882a593Smuzhiyun
c6x_ck_show(struct seq_file * m,void * v)404*4882a593Smuzhiyun static int c6x_ck_show(struct seq_file *m, void *v)
405*4882a593Smuzhiyun {
406*4882a593Smuzhiyun struct clk *clk;
407*4882a593Smuzhiyun
408*4882a593Smuzhiyun /*
409*4882a593Smuzhiyun * Show clock tree; We trust nonzero usecounts equate to PSC enables...
410*4882a593Smuzhiyun */
411*4882a593Smuzhiyun mutex_lock(&clocks_mutex);
412*4882a593Smuzhiyun list_for_each_entry(clk, &clocks, node)
413*4882a593Smuzhiyun if (!clk->parent)
414*4882a593Smuzhiyun dump_clock(m, 0, clk);
415*4882a593Smuzhiyun mutex_unlock(&clocks_mutex);
416*4882a593Smuzhiyun
417*4882a593Smuzhiyun return 0;
418*4882a593Smuzhiyun }
419*4882a593Smuzhiyun
c6x_ck_open(struct inode * inode,struct file * file)420*4882a593Smuzhiyun static int c6x_ck_open(struct inode *inode, struct file *file)
421*4882a593Smuzhiyun {
422*4882a593Smuzhiyun return single_open(file, c6x_ck_show, NULL);
423*4882a593Smuzhiyun }
424*4882a593Smuzhiyun
425*4882a593Smuzhiyun static const struct file_operations c6x_ck_operations = {
426*4882a593Smuzhiyun .open = c6x_ck_open,
427*4882a593Smuzhiyun .read = seq_read,
428*4882a593Smuzhiyun .llseek = seq_lseek,
429*4882a593Smuzhiyun .release = single_release,
430*4882a593Smuzhiyun };
431*4882a593Smuzhiyun
c6x_clk_debugfs_init(void)432*4882a593Smuzhiyun static int __init c6x_clk_debugfs_init(void)
433*4882a593Smuzhiyun {
434*4882a593Smuzhiyun debugfs_create_file("c6x_clocks", S_IFREG | S_IRUGO, NULL, NULL,
435*4882a593Smuzhiyun &c6x_ck_operations);
436*4882a593Smuzhiyun
437*4882a593Smuzhiyun return 0;
438*4882a593Smuzhiyun }
439*4882a593Smuzhiyun device_initcall(c6x_clk_debugfs_init);
440*4882a593Smuzhiyun #endif /* CONFIG_DEBUG_FS */
441