Merge branch 'topic/x86-lds-nits' of git://git.kernel.org/pub/scm/linux/kernel/git...
[safe/jmp/linux-2.6] / arch / arm / plat-s5pc1xx / s5pc100-clock.c
1 /* linux/arch/arm/plat-s5pc1xx/s5pc100-clock.c
2  *
3  * Copyright 2009 Samsung Electronics, Co.
4  *      Byungho Min <bhmin@samsung.com>
5  *
6  * S5PC100 based common clock support
7  *
8  * Based on plat-s3c64xx/s3c6400-clock.c
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License version 2 as
12  * published by the Free Software Foundation.
13 */
14
15 #include <linux/init.h>
16 #include <linux/module.h>
17 #include <linux/kernel.h>
18 #include <linux/list.h>
19 #include <linux/errno.h>
20 #include <linux/err.h>
21 #include <linux/clk.h>
22 #include <linux/sysdev.h>
23 #include <linux/io.h>
24
25 #include <mach/hardware.h>
26 #include <mach/map.h>
27
28 #include <plat/cpu-freq.h>
29
30 #include <plat/regs-clock.h>
31 #include <plat/clock.h>
32 #include <plat/cpu.h>
33 #include <plat/pll.h>
34 #include <plat/devs.h>
35 #include <plat/s5pc100.h>
36
37 /* fin_apll, fin_mpll and fin_epll are all the same clock, which we call
38  * ext_xtal_mux for want of an actual name from the manual.
39 */
40
41 static struct clk clk_ext_xtal_mux = {
42         .name           = "ext_xtal",
43         .id             = -1,
44 };
45
46 #define clk_fin_apll clk_ext_xtal_mux
47 #define clk_fin_mpll clk_ext_xtal_mux
48 #define clk_fin_epll clk_ext_xtal_mux
49 #define clk_fin_hpll clk_ext_xtal_mux
50
51 #define clk_fout_mpll   clk_mpll
52
53 struct clk_sources {
54         unsigned int    nr_sources;
55         struct clk      **sources;
56 };
57
58 struct clksrc_clk {
59         struct clk              clk;
60         unsigned int            mask;
61         unsigned int            shift;
62
63         struct clk_sources      *sources;
64
65         unsigned int            divider_shift;
66         void __iomem            *reg_divider;
67         void __iomem            *reg_source;
68 };
69
70 static int clk_default_setrate(struct clk *clk, unsigned long rate)
71 {
72         clk->rate = rate;
73         return 1;
74 }
75
76 struct clk clk_27m = {
77         .name           = "clk_27m",
78         .id             = -1,
79         .rate           = 27000000,
80 };
81
82 static int clk_48m_ctrl(struct clk *clk, int enable)
83 {
84         unsigned long flags;
85         u32 val;
86
87         /* can't rely on clock lock, this register has other usages */
88         local_irq_save(flags);
89
90         val = __raw_readl(S5PC1XX_CLK_SRC1);
91         if (enable)
92                 val |= S5PC100_CLKSRC1_CLK48M_MASK;
93         else
94                 val &= ~S5PC100_CLKSRC1_CLK48M_MASK;
95
96         __raw_writel(val, S5PC1XX_CLK_SRC1);
97         local_irq_restore(flags);
98
99         return 0;
100 }
101
102 struct clk clk_48m = {
103         .name           = "clk_48m",
104         .id             = -1,
105         .rate           = 48000000,
106         .enable         = clk_48m_ctrl,
107 };
108
109 struct clk clk_54m = {
110         .name           = "clk_54m",
111         .id             = -1,
112         .rate           = 54000000,
113 };
114
115 struct clk clk_hpll = {
116         .name           = "hpll",
117         .id             = -1,
118 };
119
120 struct clk clk_hd0 = {
121         .name           = "hclkd0",
122         .id             = -1,
123         .rate           = 0,
124         .parent         = NULL,
125         .ctrlbit        = 0,
126         .set_rate       = clk_default_setrate,
127 };
128
129 struct clk clk_pd0 = {
130         .name           = "pclkd0",
131         .id             = -1,
132         .rate           = 0,
133         .parent         = NULL,
134         .ctrlbit        = 0,
135         .set_rate       = clk_default_setrate,
136 };
137
138 static int s5pc1xx_clk_gate(void __iomem *reg,
139                                 struct clk *clk,
140                                 int enable)
141 {
142         unsigned int ctrlbit = clk->ctrlbit;
143         u32 con;
144
145         con = __raw_readl(reg);
146
147         if (enable)
148                 con |= ctrlbit;
149         else
150                 con &= ~ctrlbit;
151
152         __raw_writel(con, reg);
153         return 0;
154 }
155
156 static int s5pc1xx_clk_d00_ctrl(struct clk *clk, int enable)
157 {
158         return s5pc1xx_clk_gate(S5PC100_CLKGATE_D00, clk, enable);
159 }
160
161 static int s5pc1xx_clk_d01_ctrl(struct clk *clk, int enable)
162 {
163         return s5pc1xx_clk_gate(S5PC100_CLKGATE_D01, clk, enable);
164 }
165
166 static int s5pc1xx_clk_d02_ctrl(struct clk *clk, int enable)
167 {
168         return s5pc1xx_clk_gate(S5PC100_CLKGATE_D02, clk, enable);
169 }
170
171 static int s5pc1xx_clk_d10_ctrl(struct clk *clk, int enable)
172 {
173         return s5pc1xx_clk_gate(S5PC100_CLKGATE_D10, clk, enable);
174 }
175
176 static int s5pc1xx_clk_d11_ctrl(struct clk *clk, int enable)
177 {
178         return s5pc1xx_clk_gate(S5PC100_CLKGATE_D11, clk, enable);
179 }
180
181 static int s5pc1xx_clk_d12_ctrl(struct clk *clk, int enable)
182 {
183         return s5pc1xx_clk_gate(S5PC100_CLKGATE_D12, clk, enable);
184 }
185
186 static int s5pc1xx_clk_d13_ctrl(struct clk *clk, int enable)
187 {
188         return s5pc1xx_clk_gate(S5PC100_CLKGATE_D13, clk, enable);
189 }
190
191 static int s5pc1xx_clk_d14_ctrl(struct clk *clk, int enable)
192 {
193         return s5pc1xx_clk_gate(S5PC100_CLKGATE_D14, clk, enable);
194 }
195
196 static int s5pc1xx_clk_d15_ctrl(struct clk *clk, int enable)
197 {
198         return s5pc1xx_clk_gate(S5PC100_CLKGATE_D15, clk, enable);
199 }
200
201 static int s5pc1xx_clk_d20_ctrl(struct clk *clk, int enable)
202 {
203         return s5pc1xx_clk_gate(S5PC100_CLKGATE_D20, clk, enable);
204 }
205
206 int s5pc1xx_sclk0_ctrl(struct clk *clk, int enable)
207 {
208         return s5pc1xx_clk_gate(S5PC100_SCLKGATE0, clk, enable);
209 }
210
211 int s5pc1xx_sclk1_ctrl(struct clk *clk, int enable)
212 {
213         return s5pc1xx_clk_gate(S5PC100_SCLKGATE1, clk, enable);
214 }
215
216 static struct clk init_clocks_disable[] = {
217         {
218                 .name           = "dsi",
219                 .id             = -1,
220                 .parent         = &clk_p,
221                 .enable         = s5pc1xx_clk_d11_ctrl,
222                 .ctrlbit        = S5PC100_CLKGATE_D11_DSI,
223         }, {
224                 .name           = "csi",
225                 .id             = -1,
226                 .parent         = &clk_h,
227                 .enable         = s5pc1xx_clk_d11_ctrl,
228                 .ctrlbit        = S5PC100_CLKGATE_D11_CSI,
229         }, {
230                 .name           = "ccan0",
231                 .id             = 0,
232                 .parent         = &clk_p,
233                 .enable         = s5pc1xx_clk_d14_ctrl,
234                 .ctrlbit        = S5PC100_CLKGATE_D14_CCAN0,
235         }, {
236                 .name           = "ccan1",
237                 .id             = 1,
238                 .parent         = &clk_p,
239                 .enable         = s5pc1xx_clk_d14_ctrl,
240                 .ctrlbit        = S5PC100_CLKGATE_D14_CCAN1,
241         }, {
242                 .name           = "keypad",
243                 .id             = -1,
244                 .parent         = &clk_p,
245                 .enable         = s5pc1xx_clk_d15_ctrl,
246                 .ctrlbit        = S5PC100_CLKGATE_D15_KEYIF,
247         }, {
248                 .name           = "hclkd2",
249                 .id             = -1,
250                 .parent         = NULL,
251                 .enable         = s5pc1xx_clk_d20_ctrl,
252                 .ctrlbit        = S5PC100_CLKGATE_D20_HCLKD2,
253         }, {
254                 .name           = "iis-d2",
255                 .id             = -1,
256                 .parent         = NULL,
257                 .enable         = s5pc1xx_clk_d20_ctrl,
258                 .ctrlbit        = S5PC100_CLKGATE_D20_I2SD2,
259         }, {
260                 .name           = "otg",
261                 .id             = -1,
262                 .parent         = &clk_h,
263                 .enable         = s5pc1xx_clk_d10_ctrl,
264                 .ctrlbit        = S5PC100_CLKGATE_D10_USBOTG,
265         },
266 };
267
268 static struct clk init_clocks[] = {
269         /* System1 (D0_0) devices */
270         {
271                 .name           = "intc",
272                 .id             = -1,
273                 .parent         = &clk_hd0,
274                 .enable         = s5pc1xx_clk_d00_ctrl,
275                 .ctrlbit        = S5PC100_CLKGATE_D00_INTC,
276         }, {
277                 .name           = "tzic",
278                 .id             = -1,
279                 .parent         = &clk_hd0,
280                 .enable         = s5pc1xx_clk_d00_ctrl,
281                 .ctrlbit        = S5PC100_CLKGATE_D00_TZIC,
282         }, {
283                 .name           = "cf-ata",
284                 .id             = -1,
285                 .parent         = &clk_hd0,
286                 .enable         = s5pc1xx_clk_d00_ctrl,
287                 .ctrlbit        = S5PC100_CLKGATE_D00_CFCON,
288         }, {
289                 .name           = "mdma",
290                 .id             = -1,
291                 .parent         = &clk_hd0,
292                 .enable         = s5pc1xx_clk_d00_ctrl,
293                 .ctrlbit        = S5PC100_CLKGATE_D00_MDMA,
294         }, {
295                 .name           = "g2d",
296                 .id             = -1,
297                 .parent         = &clk_hd0,
298                 .enable         = s5pc1xx_clk_d00_ctrl,
299                 .ctrlbit        = S5PC100_CLKGATE_D00_G2D,
300         }, {
301                 .name           = "secss",
302                 .id             = -1,
303                 .parent         = &clk_hd0,
304                 .enable         = s5pc1xx_clk_d00_ctrl,
305                 .ctrlbit        = S5PC100_CLKGATE_D00_SECSS,
306         }, {
307                 .name           = "cssys",
308                 .id             = -1,
309                 .parent         = &clk_hd0,
310                 .enable         = s5pc1xx_clk_d00_ctrl,
311                 .ctrlbit        = S5PC100_CLKGATE_D00_CSSYS,
312         },
313
314         /* Memory (D0_1) devices */
315         {
316                 .name           = "dmc",
317                 .id             = -1,
318                 .parent         = &clk_hd0,
319                 .enable         = s5pc1xx_clk_d01_ctrl,
320                 .ctrlbit        = S5PC100_CLKGATE_D01_DMC,
321         }, {
322                 .name           = "sromc",
323                 .id             = -1,
324                 .parent         = &clk_hd0,
325                 .enable         = s5pc1xx_clk_d01_ctrl,
326                 .ctrlbit        = S5PC100_CLKGATE_D01_SROMC,
327         }, {
328                 .name           = "onenand",
329                 .id             = -1,
330                 .parent         = &clk_hd0,
331                 .enable         = s5pc1xx_clk_d01_ctrl,
332                 .ctrlbit        = S5PC100_CLKGATE_D01_ONENAND,
333         }, {
334                 .name           = "nand",
335                 .id             = -1,
336                 .parent         = &clk_hd0,
337                 .enable         = s5pc1xx_clk_d01_ctrl,
338                 .ctrlbit        = S5PC100_CLKGATE_D01_NFCON,
339         }, {
340                 .name           = "intmem",
341                 .id             = -1,
342                 .parent         = &clk_hd0,
343                 .enable         = s5pc1xx_clk_d01_ctrl,
344                 .ctrlbit        = S5PC100_CLKGATE_D01_INTMEM,
345         }, {
346                 .name           = "ebi",
347                 .id             = -1,
348                 .parent         = &clk_hd0,
349                 .enable         = s5pc1xx_clk_d01_ctrl,
350                 .ctrlbit        = S5PC100_CLKGATE_D01_EBI,
351         },
352
353         /* System2 (D0_2) devices */
354         {
355                 .name           = "seckey",
356                 .id             = -1,
357                 .parent         = &clk_pd0,
358                 .enable         = s5pc1xx_clk_d02_ctrl,
359                 .ctrlbit        = S5PC100_CLKGATE_D02_SECKEY,
360         }, {
361                 .name           = "sdm",
362                 .id             = -1,
363                 .parent         = &clk_hd0,
364                 .enable         = s5pc1xx_clk_d02_ctrl,
365                 .ctrlbit        = S5PC100_CLKGATE_D02_SDM,
366         },
367
368         /* File (D1_0) devices */
369         {
370                 .name           = "pdma0",
371                 .id             = -1,
372                 .parent         = &clk_h,
373                 .enable         = s5pc1xx_clk_d10_ctrl,
374                 .ctrlbit        = S5PC100_CLKGATE_D10_PDMA0,
375         }, {
376                 .name           = "pdma1",
377                 .id             = -1,
378                 .parent         = &clk_h,
379                 .enable         = s5pc1xx_clk_d10_ctrl,
380                 .ctrlbit        = S5PC100_CLKGATE_D10_PDMA1,
381         }, {
382                 .name           = "usb-host",
383                 .id             = -1,
384                 .parent         = &clk_h,
385                 .enable         = s5pc1xx_clk_d10_ctrl,
386                 .ctrlbit        = S5PC100_CLKGATE_D10_USBHOST,
387         }, {
388                 .name           = "modem",
389                 .id             = -1,
390                 .parent         = &clk_h,
391                 .enable         = s5pc1xx_clk_d10_ctrl,
392                 .ctrlbit        = S5PC100_CLKGATE_D10_MODEMIF,
393         }, {
394                 .name           = "hsmmc",
395                 .id             = 0,
396                 .parent         = &clk_h,
397                 .enable         = s5pc1xx_clk_d10_ctrl,
398                 .ctrlbit        = S5PC100_CLKGATE_D10_HSMMC0,
399         }, {
400                 .name           = "hsmmc",
401                 .id             = 1,
402                 .parent         = &clk_h,
403                 .enable         = s5pc1xx_clk_d10_ctrl,
404                 .ctrlbit        = S5PC100_CLKGATE_D10_HSMMC1,
405         }, {
406                 .name           = "hsmmc",
407                 .id             = 2,
408                 .parent         = &clk_h,
409                 .enable         = s5pc1xx_clk_d10_ctrl,
410                 .ctrlbit        = S5PC100_CLKGATE_D10_HSMMC2,
411         },
412
413         /* Multimedia1 (D1_1) devices */
414         {
415                 .name           = "lcd",
416                 .id             = -1,
417                 .parent         = &clk_h,
418                 .enable         = s5pc1xx_clk_d11_ctrl,
419                 .ctrlbit        = S5PC100_CLKGATE_D11_LCD,
420         }, {
421                 .name           = "rotator",
422                 .id             = -1,
423                 .parent         = &clk_h,
424                 .enable         = s5pc1xx_clk_d11_ctrl,
425                 .ctrlbit        = S5PC100_CLKGATE_D11_ROTATOR,
426         }, {
427                 .name           = "fimc",
428                 .id             = 0,
429                 .parent         = &clk_h,
430                 .enable         = s5pc1xx_clk_d11_ctrl,
431                 .ctrlbit        = S5PC100_CLKGATE_D11_FIMC0,
432         }, {
433                 .name           = "fimc",
434                 .id             = 1,
435                 .parent         = &clk_h,
436                 .enable         = s5pc1xx_clk_d11_ctrl,
437                 .ctrlbit        = S5PC100_CLKGATE_D11_FIMC1,
438         }, {
439                 .name           = "fimc",
440                 .id             = 2,
441                 .parent         = &clk_h,
442                 .enable         = s5pc1xx_clk_d11_ctrl,
443                 .ctrlbit        = S5PC100_CLKGATE_D11_FIMC2,
444         }, {
445                 .name           = "jpeg",
446                 .id             = -1,
447                 .parent         = &clk_h,
448                 .enable         = s5pc1xx_clk_d11_ctrl,
449                 .ctrlbit        = S5PC100_CLKGATE_D11_JPEG,
450         }, {
451                 .name           = "g3d",
452                 .id             = -1,
453                 .parent         = &clk_h,
454                 .enable         = s5pc1xx_clk_d11_ctrl,
455                 .ctrlbit        = S5PC100_CLKGATE_D11_G3D,
456         },
457
458         /* Multimedia2 (D1_2) devices */
459         {
460                 .name           = "tv",
461                 .id             = -1,
462                 .parent         = &clk_h,
463                 .enable         = s5pc1xx_clk_d12_ctrl,
464                 .ctrlbit        = S5PC100_CLKGATE_D12_TV,
465         }, {
466                 .name           = "vp",
467                 .id             = -1,
468                 .parent         = &clk_h,
469                 .enable         = s5pc1xx_clk_d12_ctrl,
470                 .ctrlbit        = S5PC100_CLKGATE_D12_VP,
471         }, {
472                 .name           = "mixer",
473                 .id             = -1,
474                 .parent         = &clk_h,
475                 .enable         = s5pc1xx_clk_d12_ctrl,
476                 .ctrlbit        = S5PC100_CLKGATE_D12_MIXER,
477         }, {
478                 .name           = "hdmi",
479                 .id             = -1,
480                 .parent         = &clk_h,
481                 .enable         = s5pc1xx_clk_d12_ctrl,
482                 .ctrlbit        = S5PC100_CLKGATE_D12_HDMI,
483         }, {
484                 .name           = "mfc",
485                 .id             = -1,
486                 .parent         = &clk_h,
487                 .enable         = s5pc1xx_clk_d12_ctrl,
488                 .ctrlbit        = S5PC100_CLKGATE_D12_MFC,
489         },
490
491         /* System (D1_3) devices */
492         {
493                 .name           = "chipid",
494                 .id             = -1,
495                 .parent         = &clk_p,
496                 .enable         = s5pc1xx_clk_d13_ctrl,
497                 .ctrlbit        = S5PC100_CLKGATE_D13_CHIPID,
498         }, {
499                 .name           = "gpio",
500                 .id             = -1,
501                 .parent         = &clk_p,
502                 .enable         = s5pc1xx_clk_d13_ctrl,
503                 .ctrlbit        = S5PC100_CLKGATE_D13_GPIO,
504         }, {
505                 .name           = "apc",
506                 .id             = -1,
507                 .parent         = &clk_p,
508                 .enable         = s5pc1xx_clk_d13_ctrl,
509                 .ctrlbit        = S5PC100_CLKGATE_D13_APC,
510         }, {
511                 .name           = "iec",
512                 .id             = -1,
513                 .parent         = &clk_p,
514                 .enable         = s5pc1xx_clk_d13_ctrl,
515                 .ctrlbit        = S5PC100_CLKGATE_D13_IEC,
516         }, {
517                 .name           = "timers",
518                 .id             = -1,
519                 .parent         = &clk_p,
520                 .enable         = s5pc1xx_clk_d13_ctrl,
521                 .ctrlbit        = S5PC100_CLKGATE_D13_PWM,
522         }, {
523                 .name           = "systimer",
524                 .id             = -1,
525                 .parent         = &clk_p,
526                 .enable         = s5pc1xx_clk_d13_ctrl,
527                 .ctrlbit        = S5PC100_CLKGATE_D13_SYSTIMER,
528         }, {
529                 .name           = "watchdog",
530                 .id             = -1,
531                 .parent         = &clk_p,
532                 .enable         = s5pc1xx_clk_d13_ctrl,
533                 .ctrlbit        = S5PC100_CLKGATE_D13_WDT,
534         }, {
535                 .name           = "rtc",
536                 .id             = -1,
537                 .parent         = &clk_p,
538                 .enable         = s5pc1xx_clk_d13_ctrl,
539                 .ctrlbit        = S5PC100_CLKGATE_D13_RTC,
540         },
541
542         /* Connectivity (D1_4) devices */
543         {
544                 .name           = "uart",
545                 .id             = 0,
546                 .parent         = &clk_p,
547                 .enable         = s5pc1xx_clk_d14_ctrl,
548                 .ctrlbit        = S5PC100_CLKGATE_D14_UART0,
549         }, {
550                 .name           = "uart",
551                 .id             = 1,
552                 .parent         = &clk_p,
553                 .enable         = s5pc1xx_clk_d14_ctrl,
554                 .ctrlbit        = S5PC100_CLKGATE_D14_UART1,
555         }, {
556                 .name           = "uart",
557                 .id             = 2,
558                 .parent         = &clk_p,
559                 .enable         = s5pc1xx_clk_d14_ctrl,
560                 .ctrlbit        = S5PC100_CLKGATE_D14_UART2,
561         }, {
562                 .name           = "uart",
563                 .id             = 3,
564                 .parent         = &clk_p,
565                 .enable         = s5pc1xx_clk_d14_ctrl,
566                 .ctrlbit        = S5PC100_CLKGATE_D14_UART3,
567         }, {
568                 .name           = "i2c",
569                 .id             = -1,
570                 .parent         = &clk_p,
571                 .enable         = s5pc1xx_clk_d14_ctrl,
572                 .ctrlbit        = S5PC100_CLKGATE_D14_IIC,
573         }, {
574                 .name           = "hdmi-i2c",
575                 .id             = -1,
576                 .parent         = &clk_p,
577                 .enable         = s5pc1xx_clk_d14_ctrl,
578                 .ctrlbit        = S5PC100_CLKGATE_D14_HDMI_IIC,
579         }, {
580                 .name           = "spi",
581                 .id             = 0,
582                 .parent         = &clk_p,
583                 .enable         = s5pc1xx_clk_d14_ctrl,
584                 .ctrlbit        = S5PC100_CLKGATE_D14_SPI0,
585         }, {
586                 .name           = "spi",
587                 .id             = 1,
588                 .parent         = &clk_p,
589                 .enable         = s5pc1xx_clk_d14_ctrl,
590                 .ctrlbit        = S5PC100_CLKGATE_D14_SPI1,
591         }, {
592                 .name           = "spi",
593                 .id             = 2,
594                 .parent         = &clk_p,
595                 .enable         = s5pc1xx_clk_d14_ctrl,
596                 .ctrlbit        = S5PC100_CLKGATE_D14_SPI2,
597         }, {
598                 .name           = "irda",
599                 .id             = -1,
600                 .parent         = &clk_p,
601                 .enable         = s5pc1xx_clk_d14_ctrl,
602                 .ctrlbit        = S5PC100_CLKGATE_D14_IRDA,
603         }, {
604                 .name           = "hsitx",
605                 .id             = -1,
606                 .parent         = &clk_p,
607                 .enable         = s5pc1xx_clk_d14_ctrl,
608                 .ctrlbit        = S5PC100_CLKGATE_D14_HSITX,
609         }, {
610                 .name           = "hsirx",
611                 .id             = -1,
612                 .parent         = &clk_p,
613                 .enable         = s5pc1xx_clk_d14_ctrl,
614                 .ctrlbit        = S5PC100_CLKGATE_D14_HSIRX,
615         },
616
617         /* Audio (D1_5) devices */
618         {
619                 .name           = "iis",
620                 .id             = 0,
621                 .parent         = &clk_p,
622                 .enable         = s5pc1xx_clk_d15_ctrl,
623                 .ctrlbit        = S5PC100_CLKGATE_D15_IIS0,
624         }, {
625                 .name           = "iis",
626                 .id             = 1,
627                 .parent         = &clk_p,
628                 .enable         = s5pc1xx_clk_d15_ctrl,
629                 .ctrlbit        = S5PC100_CLKGATE_D15_IIS1,
630         }, {
631                 .name           = "iis",
632                 .id             = 2,
633                 .parent         = &clk_p,
634                 .enable         = s5pc1xx_clk_d15_ctrl,
635                 .ctrlbit        = S5PC100_CLKGATE_D15_IIS2,
636         }, {
637                 .name           = "ac97",
638                 .id             = -1,
639                 .parent         = &clk_p,
640                 .enable         = s5pc1xx_clk_d15_ctrl,
641                 .ctrlbit        = S5PC100_CLKGATE_D15_AC97,
642         }, {
643                 .name           = "pcm",
644                 .id             = 0,
645                 .parent         = &clk_p,
646                 .enable         = s5pc1xx_clk_d15_ctrl,
647                 .ctrlbit        = S5PC100_CLKGATE_D15_PCM0,
648         }, {
649                 .name           = "pcm",
650                 .id             = 1,
651                 .parent         = &clk_p,
652                 .enable         = s5pc1xx_clk_d15_ctrl,
653                 .ctrlbit        = S5PC100_CLKGATE_D15_PCM1,
654         }, {
655                 .name           = "spdif",
656                 .id             = -1,
657                 .parent         = &clk_p,
658                 .enable         = s5pc1xx_clk_d15_ctrl,
659                 .ctrlbit        = S5PC100_CLKGATE_D15_SPDIF,
660         }, {
661                 .name           = "adc",
662                 .id             = -1,
663                 .parent         = &clk_p,
664                 .enable         = s5pc1xx_clk_d15_ctrl,
665                 .ctrlbit        = S5PC100_CLKGATE_D15_TSADC,
666         }, {
667                 .name           = "keyif",
668                 .id             = -1,
669                 .parent         = &clk_p,
670                 .enable         = s5pc1xx_clk_d15_ctrl,
671                 .ctrlbit        = S5PC100_CLKGATE_D15_KEYIF,
672         }, {
673                 .name           = "cg",
674                 .id             = -1,
675                 .parent         = &clk_p,
676                 .enable         = s5pc1xx_clk_d15_ctrl,
677                 .ctrlbit        = S5PC100_CLKGATE_D15_CG,
678         },
679
680         /* Audio (D2_0) devices: all disabled */
681
682         /* Special Clocks 1 */
683         {
684                 .name           = "sclk_hpm",
685                 .id             = -1,
686                 .parent         = NULL,
687                 .enable         = s5pc1xx_sclk0_ctrl,
688                 .ctrlbit        = S5PC1XX_CLKGATE_SCLK0_HPM,
689         }, {
690                 .name           = "sclk_onenand",
691                 .id             = -1,
692                 .parent         = NULL,
693                 .enable         = s5pc1xx_sclk0_ctrl,
694                 .ctrlbit        = S5PC100_CLKGATE_SCLK0_ONENAND,
695         }, {
696                 .name           = "sclk_spi_48",
697                 .id             = 0,
698                 .parent         = &clk_48m,
699                 .enable         = s5pc1xx_sclk0_ctrl,
700                 .ctrlbit        = S5PC100_CLKGATE_SCLK0_SPI0_48,
701         }, {
702                 .name           = "sclk_spi_48",
703                 .id             = 1,
704                 .parent         = &clk_48m,
705                 .enable         = s5pc1xx_sclk0_ctrl,
706                 .ctrlbit        = S5PC100_CLKGATE_SCLK0_SPI1_48,
707         }, {
708                 .name           = "sclk_spi_48",
709                 .id             = 2,
710                 .parent         = &clk_48m,
711                 .enable         = s5pc1xx_sclk0_ctrl,
712                 .ctrlbit        = S5PC100_CLKGATE_SCLK0_SPI2_48,
713         }, {
714                 .name           = "sclk_mmc_48",
715                 .id             = 0,
716                 .parent         = &clk_48m,
717                 .enable         = s5pc1xx_sclk0_ctrl,
718                 .ctrlbit        = S5PC100_CLKGATE_SCLK0_MMC0_48,
719         }, {
720                 .name           = "sclk_mmc_48",
721                 .id             = 1,
722                 .parent         = &clk_48m,
723                 .enable         = s5pc1xx_sclk0_ctrl,
724                 .ctrlbit        = S5PC100_CLKGATE_SCLK0_MMC1_48,
725         }, {
726                 .name           = "sclk_mmc_48",
727                 .id             = 2,
728                 .parent         = &clk_48m,
729                 .enable         = s5pc1xx_sclk0_ctrl,
730                 .ctrlbit        = S5PC100_CLKGATE_SCLK0_MMC2_48,
731         },
732
733         /* Special Clocks 2 */
734         {
735                 .name           = "sclk_tv_54",
736                 .id             = -1,
737                 .parent         = &clk_54m,
738                 .enable         = s5pc1xx_sclk1_ctrl,
739                 .ctrlbit        = S5PC100_CLKGATE_SCLK1_TV54,
740         }, {
741                 .name           = "sclk_vdac_54",
742                 .id             = -1,
743                 .parent         = &clk_54m,
744                 .enable         = s5pc1xx_sclk1_ctrl,
745                 .ctrlbit        = S5PC100_CLKGATE_SCLK1_VDAC54,
746         }, {
747                 .name           = "sclk_spdif",
748                 .id             = -1,
749                 .parent         = NULL,
750                 .enable         = s5pc1xx_sclk1_ctrl,
751                 .ctrlbit        = S5PC100_CLKGATE_SCLK1_SPDIF,
752         },
753 };
754
755 void __init s5pc1xx_register_clocks(void)
756 {
757         struct clk *clkp;
758         int ret;
759         int ptr;
760
761         clkp = init_clocks;
762         for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++, clkp++) {
763                 ret = s3c24xx_register_clock(clkp);
764                 if (ret < 0) {
765                         printk(KERN_ERR "Failed to register clock %s (%d)\n",
766                                clkp->name, ret);
767                 }
768         }
769
770         clkp = init_clocks_disable;
771         for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) {
772
773                 ret = s3c24xx_register_clock(clkp);
774                 if (ret < 0) {
775                         printk(KERN_ERR "Failed to register clock %s (%d)\n",
776                                clkp->name, ret);
777                 }
778
779                 (clkp->enable)(clkp, 0);
780         }
781
782         s3c_pwmclk_init();
783 }
784 static struct clk clk_fout_apll = {
785         .name           = "fout_apll",
786         .id             = -1,
787 };
788
789 static struct clk *clk_src_apll_list[] = {
790         [0] = &clk_fin_apll,
791         [1] = &clk_fout_apll,
792 };
793
794 static struct clk_sources clk_src_apll = {
795         .sources        = clk_src_apll_list,
796         .nr_sources     = ARRAY_SIZE(clk_src_apll_list),
797 };
798
799 static struct clksrc_clk clk_mout_apll = {
800         .clk    = {
801                 .name           = "mout_apll",
802                 .id             = -1,
803         },
804         .shift          = S5PC1XX_CLKSRC0_APLL_SHIFT,
805         .mask           = S5PC1XX_CLKSRC0_APLL_MASK,
806         .sources        = &clk_src_apll,
807         .reg_source     = S5PC1XX_CLK_SRC0,
808 };
809
810 static struct clk clk_fout_epll = {
811         .name           = "fout_epll",
812         .id             = -1,
813 };
814
815 static struct clk *clk_src_epll_list[] = {
816         [0] = &clk_fin_epll,
817         [1] = &clk_fout_epll,
818 };
819
820 static struct clk_sources clk_src_epll = {
821         .sources        = clk_src_epll_list,
822         .nr_sources     = ARRAY_SIZE(clk_src_epll_list),
823 };
824
825 static struct clksrc_clk clk_mout_epll = {
826         .clk    = {
827                 .name           = "mout_epll",
828                 .id             = -1,
829         },
830         .shift          = S5PC1XX_CLKSRC0_EPLL_SHIFT,
831         .mask           = S5PC1XX_CLKSRC0_EPLL_MASK,
832         .sources        = &clk_src_epll,
833         .reg_source     = S5PC1XX_CLK_SRC0,
834 };
835
836 static struct clk *clk_src_mpll_list[] = {
837         [0] = &clk_fin_mpll,
838         [1] = &clk_fout_mpll,
839 };
840
841 static struct clk_sources clk_src_mpll = {
842         .sources        = clk_src_mpll_list,
843         .nr_sources     = ARRAY_SIZE(clk_src_mpll_list),
844 };
845
846 static struct clksrc_clk clk_mout_mpll = {
847         .clk = {
848                 .name           = "mout_mpll",
849                 .id             = -1,
850         },
851         .shift          = S5PC1XX_CLKSRC0_MPLL_SHIFT,
852         .mask           = S5PC1XX_CLKSRC0_MPLL_MASK,
853         .sources        = &clk_src_mpll,
854         .reg_source     = S5PC1XX_CLK_SRC0,
855 };
856
857 static unsigned long s5pc1xx_clk_doutmpll_get_rate(struct clk *clk)
858 {
859         unsigned long rate = clk_get_rate(clk->parent);
860         unsigned long clkdiv;
861
862         printk(KERN_DEBUG "%s: parent is %ld\n", __func__, rate);
863
864         clkdiv = __raw_readl(S5PC1XX_CLK_DIV1) & S5PC100_CLKDIV1_MPLL_MASK;
865         rate /= (clkdiv >> S5PC100_CLKDIV1_MPLL_SHIFT) + 1;
866
867         return rate;
868 }
869
870 static struct clk clk_dout_mpll = {
871         .name           = "dout_mpll",
872         .id             = -1,
873         .parent         = &clk_mout_mpll.clk,
874         .get_rate       = s5pc1xx_clk_doutmpll_get_rate,
875 };
876
877 static unsigned long s5pc1xx_clk_doutmpll2_get_rate(struct clk *clk)
878 {
879         unsigned long rate = clk_get_rate(clk->parent);
880         unsigned long clkdiv;
881
882         printk(KERN_DEBUG "%s: parent is %ld\n", __func__, rate);
883
884         clkdiv = __raw_readl(S5PC1XX_CLK_DIV1) & S5PC100_CLKDIV1_MPLL2_MASK;
885         rate /= (clkdiv >> S5PC100_CLKDIV1_MPLL2_SHIFT) + 1;
886
887         return rate;
888 }
889
890 struct clk clk_dout_mpll2 = {
891         .name           = "dout_mpll2",
892         .id             = -1,
893         .parent         = &clk_mout_mpll.clk,
894         .get_rate       = s5pc1xx_clk_doutmpll2_get_rate,
895 };
896
897 static struct clk *clkset_uart_list[] = {
898         &clk_mout_epll.clk,
899         &clk_dout_mpll,
900         NULL,
901         NULL
902 };
903
904 static struct clk_sources clkset_uart = {
905         .sources        = clkset_uart_list,
906         .nr_sources     = ARRAY_SIZE(clkset_uart_list),
907 };
908
909 static inline struct clksrc_clk *to_clksrc(struct clk *clk)
910 {
911         return container_of(clk, struct clksrc_clk, clk);
912 }
913
914 static unsigned long s5pc1xx_getrate_clksrc(struct clk *clk)
915 {
916         struct clksrc_clk *sclk = to_clksrc(clk);
917         unsigned long rate = clk_get_rate(clk->parent);
918         u32 clkdiv = __raw_readl(sclk->reg_divider);
919
920         clkdiv >>= sclk->divider_shift;
921         clkdiv &= 0xf;
922         clkdiv++;
923
924         rate /= clkdiv;
925         return rate;
926 }
927
928 static int s5pc1xx_setrate_clksrc(struct clk *clk, unsigned long rate)
929 {
930         struct clksrc_clk *sclk = to_clksrc(clk);
931         void __iomem *reg = sclk->reg_divider;
932         unsigned int div;
933         u32 val;
934
935         rate = clk_round_rate(clk, rate);
936         div = clk_get_rate(clk->parent) / rate;
937         if (div > 16)
938                 return -EINVAL;
939
940         val = __raw_readl(reg);
941         val &= ~(0xf << sclk->shift);
942         val |= (div - 1) << sclk->shift;
943         __raw_writel(val, reg);
944
945         return 0;
946 }
947
948 static int s5pc1xx_setparent_clksrc(struct clk *clk, struct clk *parent)
949 {
950         struct clksrc_clk *sclk = to_clksrc(clk);
951         struct clk_sources *srcs = sclk->sources;
952         u32 clksrc = __raw_readl(sclk->reg_source);
953         int src_nr = -1;
954         int ptr;
955
956         for (ptr = 0; ptr < srcs->nr_sources; ptr++)
957                 if (srcs->sources[ptr] == parent) {
958                         src_nr = ptr;
959                         break;
960                 }
961
962         if (src_nr >= 0) {
963                 clksrc &= ~sclk->mask;
964                 clksrc |= src_nr << sclk->shift;
965
966                 __raw_writel(clksrc, sclk->reg_source);
967                 return 0;
968         }
969
970         return -EINVAL;
971 }
972
973 static unsigned long s5pc1xx_roundrate_clksrc(struct clk *clk,
974                                               unsigned long rate)
975 {
976         unsigned long parent_rate = clk_get_rate(clk->parent);
977         int div;
978
979         if (rate > parent_rate)
980                 rate = parent_rate;
981         else {
982                 div = rate / parent_rate;
983
984                 if (div == 0)
985                         div = 1;
986                 if (div > 16)
987                         div = 16;
988
989                 rate = parent_rate / div;
990         }
991
992         return rate;
993 }
994
995 static struct clksrc_clk clk_uart_uclk1 = {
996         .clk    = {
997                 .name           = "uclk1",
998                 .id             = -1,
999                 .ctrlbit        = S5PC100_CLKGATE_SCLK0_UART,
1000                 .enable         = s5pc1xx_sclk0_ctrl,
1001                 .set_parent     = s5pc1xx_setparent_clksrc,
1002                 .get_rate       = s5pc1xx_getrate_clksrc,
1003                 .set_rate       = s5pc1xx_setrate_clksrc,
1004                 .round_rate     = s5pc1xx_roundrate_clksrc,
1005         },
1006         .shift          = S5PC100_CLKSRC1_UART_SHIFT,
1007         .mask           = S5PC100_CLKSRC1_UART_MASK,
1008         .sources        = &clkset_uart,
1009         .divider_shift  = S5PC100_CLKDIV2_UART_SHIFT,
1010         .reg_divider    = S5PC1XX_CLK_DIV2,
1011         .reg_source     = S5PC1XX_CLK_SRC1,
1012 };
1013
1014 /* Clock initialisation code */
1015
1016 static struct clksrc_clk *init_parents[] = {
1017         &clk_mout_apll,
1018         &clk_mout_epll,
1019         &clk_mout_mpll,
1020         &clk_uart_uclk1,
1021 };
1022
1023 static void __init_or_cpufreq s5pc1xx_set_clksrc(struct clksrc_clk *clk)
1024 {
1025         struct clk_sources *srcs = clk->sources;
1026         u32 clksrc = __raw_readl(clk->reg_source);
1027
1028         clksrc &= clk->mask;
1029         clksrc >>= clk->shift;
1030
1031         if (clksrc > srcs->nr_sources || !srcs->sources[clksrc]) {
1032                 printk(KERN_ERR "%s: bad source %d\n",
1033                        clk->clk.name, clksrc);
1034                 return;
1035         }
1036
1037         clk->clk.parent = srcs->sources[clksrc];
1038
1039         printk(KERN_INFO "%s: source is %s (%d), rate is %ld\n",
1040                clk->clk.name, clk->clk.parent->name, clksrc,
1041                clk_get_rate(&clk->clk));
1042 }
1043
1044 #define GET_DIV(clk, field) ((((clk) & field##_MASK) >> field##_SHIFT) + 1)
1045
1046 void __init_or_cpufreq s5pc100_setup_clocks(void)
1047 {
1048         struct clk *xtal_clk;
1049         unsigned long xtal;
1050         unsigned long armclk;
1051         unsigned long hclkd0;
1052         unsigned long hclk;
1053         unsigned long pclkd0;
1054         unsigned long pclk;
1055         unsigned long apll;
1056         unsigned long mpll;
1057         unsigned long hpll;
1058         unsigned long epll;
1059         unsigned int ptr;
1060         u32 clkdiv0, clkdiv1;
1061
1062         printk(KERN_DEBUG "%s: registering clocks\n", __func__);
1063
1064         clkdiv0 = __raw_readl(S5PC1XX_CLK_DIV0);
1065         clkdiv1 = __raw_readl(S5PC1XX_CLK_DIV1);
1066
1067         printk(KERN_DEBUG "%s: clkdiv0 = %08x, clkdiv1 = %08x\n",
1068                         __func__, clkdiv0, clkdiv1);
1069
1070         xtal_clk = clk_get(NULL, "xtal");
1071         BUG_ON(IS_ERR(xtal_clk));
1072
1073         xtal = clk_get_rate(xtal_clk);
1074         clk_put(xtal_clk);
1075
1076         printk(KERN_DEBUG "%s: xtal is %ld\n", __func__, xtal);
1077
1078         apll = s5pc1xx_get_pll(xtal, __raw_readl(S5PC1XX_APLL_CON));
1079         mpll = s5pc1xx_get_pll(xtal, __raw_readl(S5PC1XX_MPLL_CON));
1080         epll = s5pc1xx_get_pll(xtal, __raw_readl(S5PC1XX_EPLL_CON));
1081         hpll = s5pc1xx_get_pll(xtal, __raw_readl(S5PC100_HPLL_CON));
1082
1083         printk(KERN_INFO "S5PC100: PLL settings, A=%ld, M=%ld, E=%ld, H=%ld\n",
1084                apll, mpll, epll, hpll);
1085
1086         armclk = apll / GET_DIV(clkdiv0, S5PC1XX_CLKDIV0_APLL);
1087         armclk = armclk / GET_DIV(clkdiv0, S5PC100_CLKDIV0_ARM);
1088         hclkd0 = armclk / GET_DIV(clkdiv0, S5PC100_CLKDIV0_D0);
1089         pclkd0 = hclkd0 / GET_DIV(clkdiv0, S5PC100_CLKDIV0_PCLKD0);
1090         hclk = mpll / GET_DIV(clkdiv1, S5PC100_CLKDIV1_D1);
1091         pclk = hclk / GET_DIV(clkdiv1, S5PC100_CLKDIV1_PCLKD1);
1092
1093         printk(KERN_INFO "S5PC100: ARMCLK=%ld, HCLKD0=%ld, PCLKD0=%ld, HCLK=%ld, PCLK=%ld\n",
1094                armclk, hclkd0, pclkd0, hclk, pclk);
1095
1096         clk_fout_apll.rate = apll;
1097         clk_fout_mpll.rate = mpll;
1098         clk_fout_epll.rate = epll;
1099         clk_fout_apll.rate = apll;
1100
1101         clk_h.rate = hclk;
1102         clk_p.rate = pclk;
1103
1104         for (ptr = 0; ptr < ARRAY_SIZE(init_parents); ptr++)
1105                 s5pc1xx_set_clksrc(init_parents[ptr]);
1106 }
1107
1108 static struct clk *clks[] __initdata = {
1109         &clk_ext_xtal_mux,
1110         &clk_mout_epll.clk,
1111         &clk_fout_epll,
1112         &clk_mout_mpll.clk,
1113         &clk_dout_mpll,
1114         &clk_uart_uclk1.clk,
1115         &clk_ext,
1116         &clk_epll,
1117         &clk_27m,
1118         &clk_48m,
1119         &clk_54m,
1120 };
1121
1122 void __init s5pc100_register_clocks(void)
1123 {
1124         struct clk *clkp;
1125         int ret;
1126         int ptr;
1127
1128         for (ptr = 0; ptr < ARRAY_SIZE(clks); ptr++) {
1129                 clkp = clks[ptr];
1130                 ret = s3c24xx_register_clock(clkp);
1131                 if (ret < 0) {
1132                         printk(KERN_ERR "Failed to register clock %s (%d)\n",
1133                                clkp->name, ret);
1134                 }
1135         }
1136
1137         clk_mpll.parent = &clk_mout_mpll.clk;
1138         clk_epll.parent = &clk_mout_epll.clk;
1139 }