413bfecaa131dffe3b9a47626f1751e28093e149
[openwrt.git] / target / linux / mcs814x / files-3.14 / arch / arm / mach-mcs814x / clock.c
1 /*
2  * Moschip MCS814x clock routines
3  *
4  * Copyright (C) 2012, Florian Fainelli <florian@openwrt.org>
5  *
6  * Licensed under GPLv2
7  */
8 #include <linux/kernel.h>
9 #include <linux/init.h>
10 #include <linux/export.h>
11 #include <linux/spinlock.h>
12 #include <linux/err.h>
13 #include <linux/io.h>
14 #include <linux/clkdev.h>
15 #include <linux/clk.h>
16
17 #include <mach/mcs814x.h>
18
19 #include "common.h"
20
21 #define KHZ     1000
22 #define MHZ     (KHZ * KHZ)
23
24 struct clk_ops {
25         unsigned long (*get_rate)(struct clk *clk);
26         int (*set_rate)(struct clk *clk, unsigned long rate);
27         struct clk *(*get_parent)(struct clk *clk);
28         int (*enable)(struct clk *clk, int enable);
29 };
30
31 struct clk {
32         struct clk *parent;             /* parent clk */
33         unsigned long rate;             /* clock rate in Hz */
34         unsigned long divider;          /* clock divider */
35         u32 usecount;                   /* reference count */
36         struct clk_ops *ops;            /* clock operation */
37         u32 enable_reg;                 /* clock enable register */
38         u32 enable_mask;                /* clock enable mask */
39 };
40
41 static unsigned long clk_divide_parent(struct clk *clk)
42 {
43         if (clk->parent && clk->divider)
44                 return clk_get_rate(clk->parent) / clk->divider;
45         else
46                 return 0;
47 }
48
49 static int clk_local_onoff_enable(struct clk *clk, int enable)
50 {
51         u32 tmp;
52
53         /* no enable_reg means the clock is always enabled */
54         if (!clk->enable_reg)
55                 return 0;
56
57         tmp = readl_relaxed(mcs814x_sysdbg_base + clk->enable_reg);
58         if (!enable)
59                 tmp &= ~clk->enable_mask;
60         else
61                 tmp |= clk->enable_mask;
62
63         writel_relaxed(tmp, mcs814x_sysdbg_base + clk->enable_reg);
64
65         return 0;
66 }
67
68 static struct clk_ops default_clk_ops = {
69         .get_rate       = clk_divide_parent,
70         .enable         = clk_local_onoff_enable,
71 };
72
73 static DEFINE_SPINLOCK(clocks_lock);
74
75 static const unsigned long cpu_freq_table[] = {
76         175000,
77         300000,
78         125000,
79         137500,
80         212500,
81         250000,
82         162500,
83         187500,
84         162500,
85         150000,
86         225000,
87         237500,
88         200000,
89         262500,
90         275000,
91         287500
92 };
93
94 static struct clk clk_cpu;
95
96 /* System clock is fixed at 50Mhz */
97 static struct clk clk_sys = {
98         .rate   = 50 * MHZ,
99 };
100
101 static struct clk clk_sdram;
102
103 static struct clk clk_timer0 = {
104         .parent = &clk_sdram,
105         .divider = 2,
106         .ops    = &default_clk_ops,
107 };
108
109 static struct clk clk_timer1_2 = {
110         .parent = &clk_sys,
111 };
112
113 /* Watchdog clock is system clock / 128 */
114 static struct clk clk_wdt = {
115         .parent = &clk_sys,
116         .divider = 128,
117         .ops    = &default_clk_ops,
118 };
119
120 static struct clk clk_emac = {
121         .ops            = &default_clk_ops,
122         .enable_reg     = SYSDBG_SYSCTL,
123         .enable_mask    = SYSCTL_EMAC,
124 };
125
126 static struct clk clk_ephy = {
127         .ops            = &default_clk_ops,
128         .enable_reg     = SYSDBG_PLL_CTL,
129         .enable_mask    = ~SYSCTL_EPHY, /* active low */
130 };
131
132 static struct clk clk_cipher = {
133         .ops            = &default_clk_ops,
134         .enable_reg     = SYSDBG_SYSCTL,
135         .enable_mask    = SYSCTL_CIPHER,
136 };
137
138 #define CLK(_dev, _con, _clk)   \
139 { .dev_id = (_dev), .con_id = (_con), .clk = (_clk) },
140
141 static struct clk_lookup mcs814x_chip_clks[] = {
142         CLK("cpu", NULL, &clk_cpu)
143         CLK("sys", NULL, &clk_sys)
144         CLK("sdram", NULL, &clk_sdram)
145         /* 32-bits timer0 */
146         CLK("timer0", NULL, &clk_timer0)
147         /* 16-bits timer1 */
148         CLK("timer1", NULL, &clk_timer1_2)
149         /* 64-bits timer2, same as timer 1 */
150         CLK("timer2", NULL, &clk_timer1_2)
151         CLK(NULL, "wdt", &clk_wdt)
152         CLK(NULL, "emac", &clk_emac)
153         CLK(NULL, "ephy", &clk_ephy)
154         CLK(NULL, "cipher", &clk_cipher)
155 };
156
157 static void local_clk_disable(struct clk *clk)
158 {
159         WARN_ON(!clk->usecount);
160
161         if (clk->usecount > 0) {
162                 clk->usecount--;
163
164                 if ((clk->usecount == 0) && (clk->ops->enable))
165                         clk->ops->enable(clk, 0);
166
167                 if (clk->parent)
168                         local_clk_disable(clk->parent);
169         }
170 }
171
172 static int local_clk_enable(struct clk *clk)
173 {
174         int ret = 0;
175
176         if (clk->parent)
177                 ret = local_clk_enable(clk->parent);
178
179         if (ret)
180                 return ret;
181
182         if ((clk->usecount == 0) && (clk->ops->enable))
183                 ret = clk->ops->enable(clk, 1);
184
185         if (!ret)
186                 clk->usecount++;
187         else if (clk->parent && clk->parent->ops->enable)
188                 local_clk_disable(clk->parent);
189
190         return ret;
191 }
192
193 int clk_enable(struct clk *clk)
194 {
195         int ret;
196         unsigned long flags;
197
198         spin_lock_irqsave(&clocks_lock, flags);
199         ret = local_clk_enable(clk);
200         spin_unlock_irqrestore(&clocks_lock, flags);
201
202         return ret;
203 }
204 EXPORT_SYMBOL(clk_enable);
205
206 void clk_disable(struct clk *clk)
207 {
208         unsigned long flags;
209
210         spin_lock_irqsave(&clocks_lock, flags);
211         local_clk_disable(clk);
212         spin_unlock_irqrestore(&clocks_lock, flags);
213 }
214 EXPORT_SYMBOL(clk_disable);
215
216 unsigned long clk_get_rate(struct clk *clk)
217 {
218         if (unlikely(IS_ERR_OR_NULL(clk)))
219                 return 0;
220
221         if (clk->rate)
222                 return clk->rate;
223
224         if (clk->ops && clk->ops->get_rate)
225                 return clk->ops->get_rate(clk);
226
227         return clk_get_rate(clk->parent);
228 }
229 EXPORT_SYMBOL(clk_get_rate);
230
231 struct clk *clk_get_parent(struct clk *clk)
232 {
233         unsigned long flags;
234
235         if (unlikely(IS_ERR_OR_NULL(clk)))
236                 return NULL;
237
238         if (!clk->ops || !clk->ops->get_parent)
239                 return clk->parent;
240
241         spin_lock_irqsave(&clocks_lock, flags);
242         clk->parent = clk->ops->get_parent(clk);
243         spin_unlock_irqrestore(&clocks_lock, flags);
244
245         return clk->parent;
246 }
247 EXPORT_SYMBOL(clk_get_parent);
248
249 void __init mcs814x_clk_init(void)
250 {
251         u32 bs1;
252         u8 cpu_freq;
253
254         clkdev_add_table(mcs814x_chip_clks, ARRAY_SIZE(mcs814x_chip_clks));
255
256         /* read the bootstrap registers to know the exact clocking scheme */
257         bs1 = readl_relaxed(mcs814x_sysdbg_base + SYSDBG_BS1);
258         cpu_freq = (bs1 >> CPU_FREQ_SHIFT) & CPU_FREQ_MASK;
259
260         pr_info("CPU frequency: %lu (kHz)\n", cpu_freq_table[cpu_freq]);
261         clk_cpu.rate = cpu_freq * KHZ;
262
263         /* read SDRAM frequency */
264         if (bs1 & SDRAM_FREQ_BIT)
265                 clk_sdram.rate = 100 * MHZ;
266         else
267                 clk_sdram.rate = 133 * MHZ;
268
269         pr_info("SDRAM frequency: %lu (MHz)\n", clk_sdram.rate / MHZ);
270 }
271