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

TOMOYO Linux Cross Reference
Linux/arch/unicore32/kernel/clock.c

Version: ~ [ linux-5.6 ] ~ [ linux-5.5.13 ] ~ [ linux-5.4.28 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.113 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.174 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.217 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.217 ] ~ [ 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.82 ] ~ [ 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.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  * linux/arch/unicore32/kernel/clock.c
  3  *
  4  * Code specific to PKUnity SoC and UniCore ISA
  5  *
  6  *      Maintained by GUAN Xue-tao <gxt@mprc.pku.edu.cn>
  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 = readl(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                 writel(pll_rate, PM_PLLSYSCFG);
205 
206                 writel(PM_PMCR_CFBSYS, PM_PMCR);
207                 while ((readl(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 

~ [ 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