Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
clock.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2006 - 2008 Lemote Inc. & Insititute of Computing Technology
3  * Author: Yanhua, [email protected]
4  *
5  * This file is subject to the terms and conditions of the GNU General Public
6  * License. See the file "COPYING" in the main directory of this archive
7  * for more details.
8  */
9 #include <linux/clk.h>
10 #include <linux/cpufreq.h>
11 #include <linux/errno.h>
12 #include <linux/export.h>
13 #include <linux/init.h>
14 #include <linux/list.h>
15 #include <linux/mutex.h>
16 #include <linux/spinlock.h>
17 
18 #include <asm/clock.h>
20 
21 static LIST_HEAD(clock_list);
22 static DEFINE_SPINLOCK(clock_lock);
23 static DEFINE_MUTEX(clock_list_sem);
24 
25 /* Minimum CLK support */
26 enum {
29 };
30 
34  {DC_25PT, 0},
35  {DC_37PT, 0},
36  {DC_50PT, 0},
37  {DC_62PT, 0},
38  {DC_75PT, 0},
39  {DC_87PT, 0},
40  {DC_DISABLE, 0},
42 };
43 EXPORT_SYMBOL_GPL(loongson2_clockmod_table);
44 
45 static struct clk cpu_clk = {
46  .name = "cpu_clk",
48  .rate = 800000000,
49 };
50 
51 struct clk *clk_get(struct device *dev, const char *id)
52 {
53  return &cpu_clk;
54 }
56 
57 static void propagate_rate(struct clk *clk)
58 {
59  struct clk *clkp;
60 
61  list_for_each_entry(clkp, &clock_list, node) {
62  if (likely(clkp->parent != clk))
63  continue;
64  if (likely(clkp->ops && clkp->ops->recalc))
65  clkp->ops->recalc(clkp);
66  if (unlikely(clkp->flags & CLK_RATE_PROPAGATES))
67  propagate_rate(clkp);
68  }
69 }
70 
71 int clk_enable(struct clk *clk)
72 {
73  return 0;
74 }
76 
77 void clk_disable(struct clk *clk)
78 {
79 }
81 
82 unsigned long clk_get_rate(struct clk *clk)
83 {
84  return (unsigned long)clk->rate;
85 }
87 
88 void clk_put(struct clk *clk)
89 {
90 }
92 
93 int clk_set_rate(struct clk *clk, unsigned long rate)
94 {
95  int ret = 0;
96  int regval;
97  int i;
98 
99  if (likely(clk->ops && clk->ops->set_rate)) {
100  unsigned long flags;
101 
102  spin_lock_irqsave(&clock_lock, flags);
103  ret = clk->ops->set_rate(clk, rate, 0);
104  spin_unlock_irqrestore(&clock_lock, flags);
105  }
106 
107  if (unlikely(clk->flags & CLK_RATE_PROPAGATES))
108  propagate_rate(clk);
109 
110  for (i = 0; loongson2_clockmod_table[i].frequency != CPUFREQ_TABLE_END;
111  i++) {
112  if (loongson2_clockmod_table[i].frequency ==
114  continue;
115  if (rate == loongson2_clockmod_table[i].frequency)
116  break;
117  }
118  if (rate != loongson2_clockmod_table[i].frequency)
119  return -ENOTSUPP;
120 
121  clk->rate = rate;
122 
123  regval = LOONGSON_CHIPCFG0;
124  regval = (regval & ~0x7) | (loongson2_clockmod_table[i].index - 1);
125  LOONGSON_CHIPCFG0 = regval;
126 
127  return ret;
128 }
130 
131 long clk_round_rate(struct clk *clk, unsigned long rate)
132 {
133  if (likely(clk->ops && clk->ops->round_rate)) {
134  unsigned long flags, rounded;
135 
136  spin_lock_irqsave(&clock_lock, flags);
137  rounded = clk->ops->round_rate(clk, rate);
138  spin_unlock_irqrestore(&clock_lock, flags);
139 
140  return rounded;
141  }
142 
143  return rate;
144 }