Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/unicore32/kernel/clock.c
10817 views
1
/*
2
* linux/arch/unicore32/kernel/clock.c
3
*
4
* Code specific to PKUnity SoC and UniCore ISA
5
*
6
* Maintained by GUAN Xue-tao <[email protected]>
7
* Copyright (C) 2001-2010 Guan Xuetao
8
*
9
* This program is free software; you can redistribute it and/or modify
10
* it under the terms of the GNU General Public License version 2 as
11
* published by the Free Software Foundation.
12
*/
13
#include <linux/module.h>
14
#include <linux/kernel.h>
15
#include <linux/device.h>
16
#include <linux/list.h>
17
#include <linux/errno.h>
18
#include <linux/err.h>
19
#include <linux/string.h>
20
#include <linux/clk.h>
21
#include <linux/mutex.h>
22
#include <linux/delay.h>
23
#include <linux/io.h>
24
25
#include <mach/hardware.h>
26
27
/*
28
* Very simple clock implementation
29
*/
30
struct clk {
31
struct list_head node;
32
unsigned long rate;
33
const char *name;
34
};
35
36
static struct clk clk_ost_clk = {
37
.name = "OST_CLK",
38
.rate = CLOCK_TICK_RATE,
39
};
40
41
static struct clk clk_mclk_clk = {
42
.name = "MAIN_CLK",
43
};
44
45
static struct clk clk_bclk32_clk = {
46
.name = "BUS32_CLK",
47
};
48
49
static struct clk clk_ddr_clk = {
50
.name = "DDR_CLK",
51
};
52
53
static struct clk clk_vga_clk = {
54
.name = "VGA_CLK",
55
};
56
57
static LIST_HEAD(clocks);
58
static DEFINE_MUTEX(clocks_mutex);
59
60
struct clk *clk_get(struct device *dev, const char *id)
61
{
62
struct clk *p, *clk = ERR_PTR(-ENOENT);
63
64
mutex_lock(&clocks_mutex);
65
list_for_each_entry(p, &clocks, node) {
66
if (strcmp(id, p->name) == 0) {
67
clk = p;
68
break;
69
}
70
}
71
mutex_unlock(&clocks_mutex);
72
73
return clk;
74
}
75
EXPORT_SYMBOL(clk_get);
76
77
void clk_put(struct clk *clk)
78
{
79
}
80
EXPORT_SYMBOL(clk_put);
81
82
int clk_enable(struct clk *clk)
83
{
84
return 0;
85
}
86
EXPORT_SYMBOL(clk_enable);
87
88
void clk_disable(struct clk *clk)
89
{
90
}
91
EXPORT_SYMBOL(clk_disable);
92
93
unsigned long clk_get_rate(struct clk *clk)
94
{
95
return clk->rate;
96
}
97
EXPORT_SYMBOL(clk_get_rate);
98
99
struct {
100
unsigned long rate;
101
unsigned long cfg;
102
unsigned long div;
103
} vga_clk_table[] = {
104
{.rate = 25175000, .cfg = 0x00002001, .div = 0x9},
105
{.rate = 31500000, .cfg = 0x00002001, .div = 0x7},
106
{.rate = 40000000, .cfg = 0x00003801, .div = 0x9},
107
{.rate = 49500000, .cfg = 0x00003801, .div = 0x7},
108
{.rate = 65000000, .cfg = 0x00002c01, .div = 0x4},
109
{.rate = 78750000, .cfg = 0x00002400, .div = 0x7},
110
{.rate = 108000000, .cfg = 0x00002c01, .div = 0x2},
111
{.rate = 106500000, .cfg = 0x00003c01, .div = 0x3},
112
{.rate = 50650000, .cfg = 0x00106400, .div = 0x9},
113
{.rate = 61500000, .cfg = 0x00106400, .div = 0xa},
114
{.rate = 85500000, .cfg = 0x00002800, .div = 0x6},
115
};
116
117
struct {
118
unsigned long mrate;
119
unsigned long prate;
120
} mclk_clk_table[] = {
121
{.mrate = 500000000, .prate = 0x00109801},
122
{.mrate = 525000000, .prate = 0x00104C00},
123
{.mrate = 550000000, .prate = 0x00105000},
124
{.mrate = 575000000, .prate = 0x00105400},
125
{.mrate = 600000000, .prate = 0x00105800},
126
{.mrate = 625000000, .prate = 0x00105C00},
127
{.mrate = 650000000, .prate = 0x00106000},
128
{.mrate = 675000000, .prate = 0x00106400},
129
{.mrate = 700000000, .prate = 0x00106800},
130
{.mrate = 725000000, .prate = 0x00106C00},
131
{.mrate = 750000000, .prate = 0x00107000},
132
{.mrate = 775000000, .prate = 0x00107400},
133
{.mrate = 800000000, .prate = 0x00107800},
134
};
135
136
int clk_set_rate(struct clk *clk, unsigned long rate)
137
{
138
if (clk == &clk_vga_clk) {
139
unsigned long pll_vgacfg, pll_vgadiv;
140
int ret, i;
141
142
/* lookup vga_clk_table */
143
ret = -EINVAL;
144
for (i = 0; i < ARRAY_SIZE(vga_clk_table); i++) {
145
if (rate == vga_clk_table[i].rate) {
146
pll_vgacfg = vga_clk_table[i].cfg;
147
pll_vgadiv = vga_clk_table[i].div;
148
ret = 0;
149
break;
150
}
151
}
152
153
if (ret)
154
return ret;
155
156
if (readl(PM_PLLVGACFG) == pll_vgacfg)
157
return 0;
158
159
/* set pll vga cfg reg. */
160
writel(pll_vgacfg, PM_PLLVGACFG);
161
162
writel(PM_PMCR_CFBVGA, PM_PMCR);
163
while ((readl(PM_PLLDFCDONE) & PM_PLLDFCDONE_VGADFC)
164
!= PM_PLLDFCDONE_VGADFC)
165
udelay(100); /* about 1ms */
166
167
/* set div cfg reg. */
168
writel(readl(PM_PCGR) | PM_PCGR_VGACLK, PM_PCGR);
169
170
writel((readl(PM_DIVCFG) & ~PM_DIVCFG_VGACLK_MASK)
171
| PM_DIVCFG_VGACLK(pll_vgadiv), PM_DIVCFG);
172
173
writel(readl(PM_SWRESET) | PM_SWRESET_VGADIV, PM_SWRESET);
174
while ((readl(PM_SWRESET) & PM_SWRESET_VGADIV)
175
== PM_SWRESET_VGADIV)
176
udelay(100); /* 65536 bclk32, about 320us */
177
178
writel(readl(PM_PCGR) & ~PM_PCGR_VGACLK, PM_PCGR);
179
}
180
#ifdef CONFIG_CPU_FREQ
181
if (clk == &clk_mclk_clk) {
182
u32 pll_rate, divstatus = PM_DIVSTATUS;
183
int ret, i;
184
185
/* lookup mclk_clk_table */
186
ret = -EINVAL;
187
for (i = 0; i < ARRAY_SIZE(mclk_clk_table); i++) {
188
if (rate == mclk_clk_table[i].mrate) {
189
pll_rate = mclk_clk_table[i].prate;
190
clk_mclk_clk.rate = mclk_clk_table[i].mrate;
191
ret = 0;
192
break;
193
}
194
}
195
196
if (ret)
197
return ret;
198
199
if (clk_mclk_clk.rate)
200
clk_bclk32_clk.rate = clk_mclk_clk.rate
201
/ (((divstatus & 0x0000f000) >> 12) + 1);
202
203
/* set pll sys cfg reg. */
204
PM_PLLSYSCFG = pll_rate;
205
206
PM_PMCR = PM_PMCR_CFBSYS;
207
while ((PM_PLLDFCDONE & PM_PLLDFCDONE_SYSDFC)
208
!= PM_PLLDFCDONE_SYSDFC)
209
udelay(100);
210
/* about 1ms */
211
}
212
#endif
213
return 0;
214
}
215
EXPORT_SYMBOL(clk_set_rate);
216
217
int clk_register(struct clk *clk)
218
{
219
mutex_lock(&clocks_mutex);
220
list_add(&clk->node, &clocks);
221
mutex_unlock(&clocks_mutex);
222
printk(KERN_DEFAULT "PKUnity PM: %s %lu.%02luM\n", clk->name,
223
(clk->rate)/1000000, (clk->rate)/10000 % 100);
224
return 0;
225
}
226
EXPORT_SYMBOL(clk_register);
227
228
void clk_unregister(struct clk *clk)
229
{
230
mutex_lock(&clocks_mutex);
231
list_del(&clk->node);
232
mutex_unlock(&clocks_mutex);
233
}
234
EXPORT_SYMBOL(clk_unregister);
235
236
struct {
237
unsigned long prate;
238
unsigned long rate;
239
} pllrate_table[] = {
240
{.prate = 0x00002001, .rate = 250000000},
241
{.prate = 0x00104801, .rate = 250000000},
242
{.prate = 0x00104C01, .rate = 262500000},
243
{.prate = 0x00002401, .rate = 275000000},
244
{.prate = 0x00105001, .rate = 275000000},
245
{.prate = 0x00105401, .rate = 287500000},
246
{.prate = 0x00002801, .rate = 300000000},
247
{.prate = 0x00105801, .rate = 300000000},
248
{.prate = 0x00105C01, .rate = 312500000},
249
{.prate = 0x00002C01, .rate = 325000000},
250
{.prate = 0x00106001, .rate = 325000000},
251
{.prate = 0x00106401, .rate = 337500000},
252
{.prate = 0x00003001, .rate = 350000000},
253
{.prate = 0x00106801, .rate = 350000000},
254
{.prate = 0x00106C01, .rate = 362500000},
255
{.prate = 0x00003401, .rate = 375000000},
256
{.prate = 0x00107001, .rate = 375000000},
257
{.prate = 0x00107401, .rate = 387500000},
258
{.prate = 0x00003801, .rate = 400000000},
259
{.prate = 0x00107801, .rate = 400000000},
260
{.prate = 0x00107C01, .rate = 412500000},
261
{.prate = 0x00003C01, .rate = 425000000},
262
{.prate = 0x00108001, .rate = 425000000},
263
{.prate = 0x00108401, .rate = 437500000},
264
{.prate = 0x00004001, .rate = 450000000},
265
{.prate = 0x00108801, .rate = 450000000},
266
{.prate = 0x00108C01, .rate = 462500000},
267
{.prate = 0x00004401, .rate = 475000000},
268
{.prate = 0x00109001, .rate = 475000000},
269
{.prate = 0x00109401, .rate = 487500000},
270
{.prate = 0x00004801, .rate = 500000000},
271
{.prate = 0x00109801, .rate = 500000000},
272
{.prate = 0x00104C00, .rate = 525000000},
273
{.prate = 0x00002400, .rate = 550000000},
274
{.prate = 0x00105000, .rate = 550000000},
275
{.prate = 0x00105400, .rate = 575000000},
276
{.prate = 0x00002800, .rate = 600000000},
277
{.prate = 0x00105800, .rate = 600000000},
278
{.prate = 0x00105C00, .rate = 625000000},
279
{.prate = 0x00002C00, .rate = 650000000},
280
{.prate = 0x00106000, .rate = 650000000},
281
{.prate = 0x00106400, .rate = 675000000},
282
{.prate = 0x00003000, .rate = 700000000},
283
{.prate = 0x00106800, .rate = 700000000},
284
{.prate = 0x00106C00, .rate = 725000000},
285
{.prate = 0x00003400, .rate = 750000000},
286
{.prate = 0x00107000, .rate = 750000000},
287
{.prate = 0x00107400, .rate = 775000000},
288
{.prate = 0x00003800, .rate = 800000000},
289
{.prate = 0x00107800, .rate = 800000000},
290
{.prate = 0x00107C00, .rate = 825000000},
291
{.prate = 0x00003C00, .rate = 850000000},
292
{.prate = 0x00108000, .rate = 850000000},
293
{.prate = 0x00108400, .rate = 875000000},
294
{.prate = 0x00004000, .rate = 900000000},
295
{.prate = 0x00108800, .rate = 900000000},
296
{.prate = 0x00108C00, .rate = 925000000},
297
{.prate = 0x00004400, .rate = 950000000},
298
{.prate = 0x00109000, .rate = 950000000},
299
{.prate = 0x00109400, .rate = 975000000},
300
{.prate = 0x00004800, .rate = 1000000000},
301
{.prate = 0x00109800, .rate = 1000000000},
302
};
303
304
struct {
305
unsigned long prate;
306
unsigned long drate;
307
} pddr_table[] = {
308
{.prate = 0x00100800, .drate = 44236800},
309
{.prate = 0x00100C00, .drate = 66355200},
310
{.prate = 0x00101000, .drate = 88473600},
311
{.prate = 0x00101400, .drate = 110592000},
312
{.prate = 0x00101800, .drate = 132710400},
313
{.prate = 0x00101C01, .drate = 154828800},
314
{.prate = 0x00102001, .drate = 176947200},
315
{.prate = 0x00102401, .drate = 199065600},
316
{.prate = 0x00102801, .drate = 221184000},
317
{.prate = 0x00102C01, .drate = 243302400},
318
{.prate = 0x00103001, .drate = 265420800},
319
{.prate = 0x00103401, .drate = 287539200},
320
{.prate = 0x00103801, .drate = 309657600},
321
{.prate = 0x00103C01, .drate = 331776000},
322
{.prate = 0x00104001, .drate = 353894400},
323
};
324
325
static int __init clk_init(void)
326
{
327
#ifdef CONFIG_PUV3_PM
328
u32 pllrate, divstatus = readl(PM_DIVSTATUS);
329
u32 pcgr_val = readl(PM_PCGR);
330
int i;
331
332
pcgr_val |= PM_PCGR_BCLKMME | PM_PCGR_BCLKH264E | PM_PCGR_BCLKH264D
333
| PM_PCGR_HECLK | PM_PCGR_HDCLK;
334
writel(pcgr_val, PM_PCGR);
335
336
pllrate = readl(PM_PLLSYSSTATUS);
337
338
/* lookup pmclk_table */
339
clk_mclk_clk.rate = 0;
340
for (i = 0; i < ARRAY_SIZE(pllrate_table); i++) {
341
if (pllrate == pllrate_table[i].prate) {
342
clk_mclk_clk.rate = pllrate_table[i].rate;
343
break;
344
}
345
}
346
347
if (clk_mclk_clk.rate)
348
clk_bclk32_clk.rate = clk_mclk_clk.rate /
349
(((divstatus & 0x0000f000) >> 12) + 1);
350
351
pllrate = readl(PM_PLLDDRSTATUS);
352
353
/* lookup pddr_table */
354
clk_ddr_clk.rate = 0;
355
for (i = 0; i < ARRAY_SIZE(pddr_table); i++) {
356
if (pllrate == pddr_table[i].prate) {
357
clk_ddr_clk.rate = pddr_table[i].drate;
358
break;
359
}
360
}
361
362
pllrate = readl(PM_PLLVGASTATUS);
363
364
/* lookup pvga_table */
365
clk_vga_clk.rate = 0;
366
for (i = 0; i < ARRAY_SIZE(pllrate_table); i++) {
367
if (pllrate == pllrate_table[i].prate) {
368
clk_vga_clk.rate = pllrate_table[i].rate;
369
break;
370
}
371
}
372
373
if (clk_vga_clk.rate)
374
clk_vga_clk.rate = clk_vga_clk.rate /
375
(((divstatus & 0x00f00000) >> 20) + 1);
376
377
clk_register(&clk_vga_clk);
378
#endif
379
#ifdef CONFIG_ARCH_FPGA
380
clk_ddr_clk.rate = 33000000;
381
clk_mclk_clk.rate = 33000000;
382
clk_bclk32_clk.rate = 33000000;
383
#endif
384
clk_register(&clk_ddr_clk);
385
clk_register(&clk_mclk_clk);
386
clk_register(&clk_bclk32_clk);
387
clk_register(&clk_ost_clk);
388
return 0;
389
}
390
core_initcall(clk_init);
391
392