• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6.36/arch/arm/mach-s5pv210/
1/* linux/arch/arm/mach-s5pv210/clock.c
2 *
3 * Copyright (c) 2010 Samsung Electronics Co., Ltd.
4 *		http://www.samsung.com/
5 *
6 * S5PV210 - Clock support
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11*/
12
13#include <linux/init.h>
14#include <linux/module.h>
15#include <linux/kernel.h>
16#include <linux/list.h>
17#include <linux/errno.h>
18#include <linux/err.h>
19#include <linux/clk.h>
20#include <linux/sysdev.h>
21#include <linux/io.h>
22
23#include <mach/map.h>
24
25#include <plat/cpu-freq.h>
26#include <mach/regs-clock.h>
27#include <plat/clock.h>
28#include <plat/cpu.h>
29#include <plat/pll.h>
30#include <plat/s5p-clock.h>
31#include <plat/clock-clksrc.h>
32#include <plat/s5pv210.h>
33
34static struct clksrc_clk clk_mout_apll = {
35	.clk	= {
36		.name		= "mout_apll",
37		.id		= -1,
38	},
39	.sources	= &clk_src_apll,
40	.reg_src	= { .reg = S5P_CLK_SRC0, .shift = 0, .size = 1 },
41};
42
43static struct clksrc_clk clk_mout_epll = {
44	.clk	= {
45		.name		= "mout_epll",
46		.id		= -1,
47	},
48	.sources	= &clk_src_epll,
49	.reg_src	= { .reg = S5P_CLK_SRC0, .shift = 8, .size = 1 },
50};
51
52static struct clksrc_clk clk_mout_mpll = {
53	.clk = {
54		.name		= "mout_mpll",
55		.id		= -1,
56	},
57	.sources	= &clk_src_mpll,
58	.reg_src	= { .reg = S5P_CLK_SRC0, .shift = 4, .size = 1 },
59};
60
61static struct clk *clkset_armclk_list[] = {
62	[0] = &clk_mout_apll.clk,
63	[1] = &clk_mout_mpll.clk,
64};
65
66static struct clksrc_sources clkset_armclk = {
67	.sources	= clkset_armclk_list,
68	.nr_sources	= ARRAY_SIZE(clkset_armclk_list),
69};
70
71static struct clksrc_clk clk_armclk = {
72	.clk	= {
73		.name		= "armclk",
74		.id		= -1,
75	},
76	.sources	= &clkset_armclk,
77	.reg_src	= { .reg = S5P_CLK_SRC0, .shift = 16, .size = 1 },
78	.reg_div	= { .reg = S5P_CLK_DIV0, .shift = 0, .size = 3 },
79};
80
81static struct clksrc_clk clk_hclk_msys = {
82	.clk	= {
83		.name		= "hclk_msys",
84		.id		= -1,
85		.parent		= &clk_armclk.clk,
86	},
87	.reg_div	= { .reg = S5P_CLK_DIV0, .shift = 8, .size = 3 },
88};
89
90static struct clksrc_clk clk_pclk_msys = {
91	.clk	= {
92		.name		= "pclk_msys",
93		.id		= -1,
94		.parent		= &clk_hclk_msys.clk,
95	},
96	.reg_div        = { .reg = S5P_CLK_DIV0, .shift = 12, .size = 3 },
97};
98
99static struct clksrc_clk clk_sclk_a2m = {
100	.clk	= {
101		.name		= "sclk_a2m",
102		.id		= -1,
103		.parent		= &clk_mout_apll.clk,
104	},
105	.reg_div	= { .reg = S5P_CLK_DIV0, .shift = 4, .size = 3 },
106};
107
108static struct clk *clkset_hclk_sys_list[] = {
109	[0] = &clk_mout_mpll.clk,
110	[1] = &clk_sclk_a2m.clk,
111};
112
113static struct clksrc_sources clkset_hclk_sys = {
114	.sources	= clkset_hclk_sys_list,
115	.nr_sources	= ARRAY_SIZE(clkset_hclk_sys_list),
116};
117
118static struct clksrc_clk clk_hclk_dsys = {
119	.clk	= {
120		.name	= "hclk_dsys",
121		.id	= -1,
122	},
123	.sources	= &clkset_hclk_sys,
124	.reg_src        = { .reg = S5P_CLK_SRC0, .shift = 20, .size = 1 },
125	.reg_div        = { .reg = S5P_CLK_DIV0, .shift = 16, .size = 4 },
126};
127
128static struct clksrc_clk clk_pclk_dsys = {
129	.clk	= {
130		.name	= "pclk_dsys",
131		.id	= -1,
132		.parent	= &clk_hclk_dsys.clk,
133	},
134	.reg_div = { .reg = S5P_CLK_DIV0, .shift = 20, .size = 3 },
135};
136
137static struct clksrc_clk clk_hclk_psys = {
138	.clk	= {
139		.name	= "hclk_psys",
140		.id	= -1,
141	},
142	.sources	= &clkset_hclk_sys,
143	.reg_src        = { .reg = S5P_CLK_SRC0, .shift = 24, .size = 1 },
144	.reg_div        = { .reg = S5P_CLK_DIV0, .shift = 24, .size = 4 },
145};
146
147static struct clksrc_clk clk_pclk_psys = {
148	.clk	= {
149		.name	= "pclk_psys",
150		.id	= -1,
151		.parent	= &clk_hclk_psys.clk,
152	},
153	.reg_div        = { .reg = S5P_CLK_DIV0, .shift = 28, .size = 3 },
154};
155
156static int s5pv210_clk_ip0_ctrl(struct clk *clk, int enable)
157{
158	return s5p_gatectrl(S5P_CLKGATE_IP0, clk, enable);
159}
160
161static int s5pv210_clk_ip1_ctrl(struct clk *clk, int enable)
162{
163	return s5p_gatectrl(S5P_CLKGATE_IP1, clk, enable);
164}
165
166static int s5pv210_clk_ip2_ctrl(struct clk *clk, int enable)
167{
168	return s5p_gatectrl(S5P_CLKGATE_IP2, clk, enable);
169}
170
171static int s5pv210_clk_ip3_ctrl(struct clk *clk, int enable)
172{
173	return s5p_gatectrl(S5P_CLKGATE_IP3, clk, enable);
174}
175
176static int s5pv210_clk_mask0_ctrl(struct clk *clk, int enable)
177{
178	return s5p_gatectrl(S5P_CLK_SRC_MASK0, clk, enable);
179}
180
181static int s5pv210_clk_mask1_ctrl(struct clk *clk, int enable)
182{
183	return s5p_gatectrl(S5P_CLK_SRC_MASK1, clk, enable);
184}
185
186static struct clk clk_sclk_hdmi27m = {
187	.name		= "sclk_hdmi27m",
188	.id		= -1,
189	.rate		= 27000000,
190};
191
192static struct clk clk_sclk_hdmiphy = {
193	.name		= "sclk_hdmiphy",
194	.id		= -1,
195};
196
197static struct clk clk_sclk_usbphy0 = {
198	.name		= "sclk_usbphy0",
199	.id		= -1,
200};
201
202static struct clk clk_sclk_usbphy1 = {
203	.name		= "sclk_usbphy1",
204	.id		= -1,
205};
206
207static struct clk clk_pcmcdclk0 = {
208	.name		= "pcmcdclk",
209	.id		= -1,
210};
211
212static struct clk clk_pcmcdclk1 = {
213	.name		= "pcmcdclk",
214	.id		= -1,
215};
216
217static struct clk clk_pcmcdclk2 = {
218	.name		= "pcmcdclk",
219	.id		= -1,
220};
221
222static struct clk *clkset_vpllsrc_list[] = {
223	[0] = &clk_fin_vpll,
224	[1] = &clk_sclk_hdmi27m,
225};
226
227static struct clksrc_sources clkset_vpllsrc = {
228	.sources	= clkset_vpllsrc_list,
229	.nr_sources	= ARRAY_SIZE(clkset_vpllsrc_list),
230};
231
232static struct clksrc_clk clk_vpllsrc = {
233	.clk	= {
234		.name		= "vpll_src",
235		.id		= -1,
236		.enable		= s5pv210_clk_mask0_ctrl,
237		.ctrlbit	= (1 << 7),
238	},
239	.sources	= &clkset_vpllsrc,
240	.reg_src	= { .reg = S5P_CLK_SRC1, .shift = 28, .size = 1 },
241};
242
243static struct clk *clkset_sclk_vpll_list[] = {
244	[0] = &clk_vpllsrc.clk,
245	[1] = &clk_fout_vpll,
246};
247
248static struct clksrc_sources clkset_sclk_vpll = {
249	.sources	= clkset_sclk_vpll_list,
250	.nr_sources	= ARRAY_SIZE(clkset_sclk_vpll_list),
251};
252
253static struct clksrc_clk clk_sclk_vpll = {
254	.clk	= {
255		.name		= "sclk_vpll",
256		.id		= -1,
257	},
258	.sources	= &clkset_sclk_vpll,
259	.reg_src	= { .reg = S5P_CLK_SRC0, .shift = 12, .size = 1 },
260};
261
262static unsigned long s5pv210_clk_imem_get_rate(struct clk *clk)
263{
264	return clk_get_rate(clk->parent) / 2;
265}
266
267static struct clk_ops clk_hclk_imem_ops = {
268	.get_rate	= s5pv210_clk_imem_get_rate,
269};
270
271static struct clk init_clocks_disable[] = {
272	{
273		.name		= "rot",
274		.id		= -1,
275		.parent		= &clk_hclk_dsys.clk,
276		.enable		= s5pv210_clk_ip0_ctrl,
277		.ctrlbit	= (1<<29),
278	}, {
279		.name		= "fimc",
280		.id		= 0,
281		.parent		= &clk_hclk_dsys.clk,
282		.enable		= s5pv210_clk_ip0_ctrl,
283		.ctrlbit	= (1 << 24),
284	}, {
285		.name		= "fimc",
286		.id		= 1,
287		.parent		= &clk_hclk_dsys.clk,
288		.enable		= s5pv210_clk_ip0_ctrl,
289		.ctrlbit	= (1 << 25),
290	}, {
291		.name		= "fimc",
292		.id		= 2,
293		.parent		= &clk_hclk_dsys.clk,
294		.enable		= s5pv210_clk_ip0_ctrl,
295		.ctrlbit	= (1 << 26),
296	}, {
297		.name		= "otg",
298		.id		= -1,
299		.parent		= &clk_hclk_psys.clk,
300		.enable		= s5pv210_clk_ip1_ctrl,
301		.ctrlbit	= (1<<16),
302	}, {
303		.name		= "usb-host",
304		.id		= -1,
305		.parent		= &clk_hclk_psys.clk,
306		.enable		= s5pv210_clk_ip1_ctrl,
307		.ctrlbit	= (1<<17),
308	}, {
309		.name		= "lcd",
310		.id		= -1,
311		.parent		= &clk_hclk_dsys.clk,
312		.enable		= s5pv210_clk_ip1_ctrl,
313		.ctrlbit	= (1<<0),
314	}, {
315		.name		= "cfcon",
316		.id		= 0,
317		.parent		= &clk_hclk_psys.clk,
318		.enable		= s5pv210_clk_ip1_ctrl,
319		.ctrlbit	= (1<<25),
320	}, {
321		.name		= "hsmmc",
322		.id		= 0,
323		.parent		= &clk_hclk_psys.clk,
324		.enable		= s5pv210_clk_ip2_ctrl,
325		.ctrlbit	= (1<<16),
326	}, {
327		.name		= "hsmmc",
328		.id		= 1,
329		.parent		= &clk_hclk_psys.clk,
330		.enable		= s5pv210_clk_ip2_ctrl,
331		.ctrlbit	= (1<<17),
332	}, {
333		.name		= "hsmmc",
334		.id		= 2,
335		.parent		= &clk_hclk_psys.clk,
336		.enable		= s5pv210_clk_ip2_ctrl,
337		.ctrlbit	= (1<<18),
338	}, {
339		.name		= "hsmmc",
340		.id		= 3,
341		.parent		= &clk_hclk_psys.clk,
342		.enable		= s5pv210_clk_ip2_ctrl,
343		.ctrlbit	= (1<<19),
344	}, {
345		.name		= "systimer",
346		.id		= -1,
347		.parent		= &clk_pclk_psys.clk,
348		.enable		= s5pv210_clk_ip3_ctrl,
349		.ctrlbit	= (1<<16),
350	}, {
351		.name		= "watchdog",
352		.id		= -1,
353		.parent		= &clk_pclk_psys.clk,
354		.enable		= s5pv210_clk_ip3_ctrl,
355		.ctrlbit	= (1<<22),
356	}, {
357		.name		= "rtc",
358		.id		= -1,
359		.parent		= &clk_pclk_psys.clk,
360		.enable		= s5pv210_clk_ip3_ctrl,
361		.ctrlbit	= (1<<15),
362	}, {
363		.name		= "i2c",
364		.id		= 0,
365		.parent		= &clk_pclk_psys.clk,
366		.enable		= s5pv210_clk_ip3_ctrl,
367		.ctrlbit	= (1<<7),
368	}, {
369		.name		= "i2c",
370		.id		= 1,
371		.parent		= &clk_pclk_psys.clk,
372		.enable		= s5pv210_clk_ip3_ctrl,
373		.ctrlbit	= (1 << 10),
374	}, {
375		.name		= "i2c",
376		.id		= 2,
377		.parent		= &clk_pclk_psys.clk,
378		.enable		= s5pv210_clk_ip3_ctrl,
379		.ctrlbit	= (1<<9),
380	}, {
381		.name		= "spi",
382		.id		= 0,
383		.parent		= &clk_pclk_psys.clk,
384		.enable		= s5pv210_clk_ip3_ctrl,
385		.ctrlbit	= (1<<12),
386	}, {
387		.name		= "spi",
388		.id		= 1,
389		.parent		= &clk_pclk_psys.clk,
390		.enable		= s5pv210_clk_ip3_ctrl,
391		.ctrlbit	= (1<<13),
392	}, {
393		.name		= "spi",
394		.id		= 2,
395		.parent		= &clk_pclk_psys.clk,
396		.enable		= s5pv210_clk_ip3_ctrl,
397		.ctrlbit	= (1<<14),
398	}, {
399		.name		= "timers",
400		.id		= -1,
401		.parent		= &clk_pclk_psys.clk,
402		.enable		= s5pv210_clk_ip3_ctrl,
403		.ctrlbit	= (1<<23),
404	}, {
405		.name		= "adc",
406		.id		= -1,
407		.parent		= &clk_pclk_psys.clk,
408		.enable		= s5pv210_clk_ip3_ctrl,
409		.ctrlbit	= (1<<24),
410	}, {
411		.name		= "keypad",
412		.id		= -1,
413		.parent		= &clk_pclk_psys.clk,
414		.enable		= s5pv210_clk_ip3_ctrl,
415		.ctrlbit	= (1<<21),
416	}, {
417		.name		= "i2s_v50",
418		.id		= 0,
419		.parent		= &clk_p,
420		.enable		= s5pv210_clk_ip3_ctrl,
421		.ctrlbit	= (1<<4),
422	}, {
423		.name		= "i2s_v32",
424		.id		= 0,
425		.parent		= &clk_p,
426		.enable		= s5pv210_clk_ip3_ctrl,
427		.ctrlbit	= (1 << 5),
428	}, {
429		.name		= "i2s_v32",
430		.id		= 1,
431		.parent		= &clk_p,
432		.enable		= s5pv210_clk_ip3_ctrl,
433		.ctrlbit	= (1 << 6),
434	},
435};
436
437static struct clk init_clocks[] = {
438	{
439		.name		= "hclk_imem",
440		.id		= -1,
441		.parent		= &clk_hclk_msys.clk,
442		.ctrlbit	= (1 << 5),
443		.enable		= s5pv210_clk_ip0_ctrl,
444		.ops		= &clk_hclk_imem_ops,
445	}, {
446		.name		= "uart",
447		.id		= 0,
448		.parent		= &clk_pclk_psys.clk,
449		.enable		= s5pv210_clk_ip3_ctrl,
450		.ctrlbit	= (1 << 17),
451	}, {
452		.name		= "uart",
453		.id		= 1,
454		.parent		= &clk_pclk_psys.clk,
455		.enable		= s5pv210_clk_ip3_ctrl,
456		.ctrlbit	= (1 << 18),
457	}, {
458		.name		= "uart",
459		.id		= 2,
460		.parent		= &clk_pclk_psys.clk,
461		.enable		= s5pv210_clk_ip3_ctrl,
462		.ctrlbit	= (1 << 19),
463	}, {
464		.name		= "uart",
465		.id		= 3,
466		.parent		= &clk_pclk_psys.clk,
467		.enable		= s5pv210_clk_ip3_ctrl,
468		.ctrlbit	= (1 << 20),
469	},
470};
471
472static struct clk *clkset_uart_list[] = {
473	[6] = &clk_mout_mpll.clk,
474	[7] = &clk_mout_epll.clk,
475};
476
477static struct clksrc_sources clkset_uart = {
478	.sources	= clkset_uart_list,
479	.nr_sources	= ARRAY_SIZE(clkset_uart_list),
480};
481
482static struct clk *clkset_group1_list[] = {
483	[0] = &clk_sclk_a2m.clk,
484	[1] = &clk_mout_mpll.clk,
485	[2] = &clk_mout_epll.clk,
486	[3] = &clk_sclk_vpll.clk,
487};
488
489static struct clksrc_sources clkset_group1 = {
490	.sources	= clkset_group1_list,
491	.nr_sources	= ARRAY_SIZE(clkset_group1_list),
492};
493
494static struct clk *clkset_sclk_onenand_list[] = {
495	[0] = &clk_hclk_psys.clk,
496	[1] = &clk_hclk_dsys.clk,
497};
498
499static struct clksrc_sources clkset_sclk_onenand = {
500	.sources	= clkset_sclk_onenand_list,
501	.nr_sources	= ARRAY_SIZE(clkset_sclk_onenand_list),
502};
503
504static struct clk *clkset_sclk_dac_list[] = {
505	[0] = &clk_sclk_vpll.clk,
506	[1] = &clk_sclk_hdmiphy,
507};
508
509static struct clksrc_sources clkset_sclk_dac = {
510	.sources	= clkset_sclk_dac_list,
511	.nr_sources	= ARRAY_SIZE(clkset_sclk_dac_list),
512};
513
514static struct clksrc_clk clk_sclk_dac = {
515	.clk		= {
516		.name		= "sclk_dac",
517		.id		= -1,
518		.enable		= s5pv210_clk_mask0_ctrl,
519		.ctrlbit	= (1 << 2),
520	},
521	.sources	= &clkset_sclk_dac,
522	.reg_src	= { .reg = S5P_CLK_SRC1, .shift = 8, .size = 1 },
523};
524
525static struct clksrc_clk clk_sclk_pixel = {
526	.clk		= {
527		.name		= "sclk_pixel",
528		.id		= -1,
529		.parent		= &clk_sclk_vpll.clk,
530	},
531	.reg_div	= { .reg = S5P_CLK_DIV1, .shift = 0, .size = 4},
532};
533
534static struct clk *clkset_sclk_hdmi_list[] = {
535	[0] = &clk_sclk_pixel.clk,
536	[1] = &clk_sclk_hdmiphy,
537};
538
539static struct clksrc_sources clkset_sclk_hdmi = {
540	.sources	= clkset_sclk_hdmi_list,
541	.nr_sources	= ARRAY_SIZE(clkset_sclk_hdmi_list),
542};
543
544static struct clksrc_clk clk_sclk_hdmi = {
545	.clk		= {
546		.name		= "sclk_hdmi",
547		.id		= -1,
548		.enable		= s5pv210_clk_mask0_ctrl,
549		.ctrlbit	= (1 << 0),
550	},
551	.sources	= &clkset_sclk_hdmi,
552	.reg_src	= { .reg = S5P_CLK_SRC1, .shift = 0, .size = 1 },
553};
554
555static struct clk *clkset_sclk_mixer_list[] = {
556	[0] = &clk_sclk_dac.clk,
557	[1] = &clk_sclk_hdmi.clk,
558};
559
560static struct clksrc_sources clkset_sclk_mixer = {
561	.sources	= clkset_sclk_mixer_list,
562	.nr_sources	= ARRAY_SIZE(clkset_sclk_mixer_list),
563};
564
565static struct clk *clkset_sclk_audio0_list[] = {
566	[0] = &clk_ext_xtal_mux,
567	[1] = &clk_pcmcdclk0,
568	[2] = &clk_sclk_hdmi27m,
569	[3] = &clk_sclk_usbphy0,
570	[4] = &clk_sclk_usbphy1,
571	[5] = &clk_sclk_hdmiphy,
572	[6] = &clk_mout_mpll.clk,
573	[7] = &clk_mout_epll.clk,
574	[8] = &clk_sclk_vpll.clk,
575};
576
577static struct clksrc_sources clkset_sclk_audio0 = {
578	.sources	= clkset_sclk_audio0_list,
579	.nr_sources	= ARRAY_SIZE(clkset_sclk_audio0_list),
580};
581
582static struct clksrc_clk clk_sclk_audio0 = {
583	.clk		= {
584		.name		= "sclk_audio",
585		.id		= 0,
586		.enable		= s5pv210_clk_mask0_ctrl,
587		.ctrlbit	= (1 << 24),
588	},
589	.sources = &clkset_sclk_audio0,
590	.reg_src = { .reg = S5P_CLK_SRC6, .shift = 0, .size = 4 },
591	.reg_div = { .reg = S5P_CLK_DIV6, .shift = 0, .size = 4 },
592};
593
594static struct clk *clkset_sclk_audio1_list[] = {
595	[0] = &clk_ext_xtal_mux,
596	[1] = &clk_pcmcdclk1,
597	[2] = &clk_sclk_hdmi27m,
598	[3] = &clk_sclk_usbphy0,
599	[4] = &clk_sclk_usbphy1,
600	[5] = &clk_sclk_hdmiphy,
601	[6] = &clk_mout_mpll.clk,
602	[7] = &clk_mout_epll.clk,
603	[8] = &clk_sclk_vpll.clk,
604};
605
606static struct clksrc_sources clkset_sclk_audio1 = {
607	.sources	= clkset_sclk_audio1_list,
608	.nr_sources	= ARRAY_SIZE(clkset_sclk_audio1_list),
609};
610
611static struct clksrc_clk clk_sclk_audio1 = {
612	.clk		= {
613		.name		= "sclk_audio",
614		.id		= 1,
615		.enable		= s5pv210_clk_mask0_ctrl,
616		.ctrlbit	= (1 << 25),
617	},
618	.sources = &clkset_sclk_audio1,
619	.reg_src = { .reg = S5P_CLK_SRC6, .shift = 4, .size = 4 },
620	.reg_div = { .reg = S5P_CLK_DIV6, .shift = 4, .size = 4 },
621};
622
623static struct clk *clkset_sclk_audio2_list[] = {
624	[0] = &clk_ext_xtal_mux,
625	[1] = &clk_pcmcdclk0,
626	[2] = &clk_sclk_hdmi27m,
627	[3] = &clk_sclk_usbphy0,
628	[4] = &clk_sclk_usbphy1,
629	[5] = &clk_sclk_hdmiphy,
630	[6] = &clk_mout_mpll.clk,
631	[7] = &clk_mout_epll.clk,
632	[8] = &clk_sclk_vpll.clk,
633};
634
635static struct clksrc_sources clkset_sclk_audio2 = {
636	.sources	= clkset_sclk_audio2_list,
637	.nr_sources	= ARRAY_SIZE(clkset_sclk_audio2_list),
638};
639
640static struct clksrc_clk clk_sclk_audio2 = {
641	.clk		= {
642		.name		= "sclk_audio",
643		.id		= 2,
644		.enable		= s5pv210_clk_mask0_ctrl,
645		.ctrlbit	= (1 << 26),
646	},
647	.sources = &clkset_sclk_audio2,
648	.reg_src = { .reg = S5P_CLK_SRC6, .shift = 8, .size = 4 },
649	.reg_div = { .reg = S5P_CLK_DIV6, .shift = 8, .size = 4 },
650};
651
652static struct clk *clkset_sclk_spdif_list[] = {
653	[0] = &clk_sclk_audio0.clk,
654	[1] = &clk_sclk_audio1.clk,
655	[2] = &clk_sclk_audio2.clk,
656};
657
658static struct clksrc_sources clkset_sclk_spdif = {
659	.sources	= clkset_sclk_spdif_list,
660	.nr_sources	= ARRAY_SIZE(clkset_sclk_spdif_list),
661};
662
663static struct clk *clkset_group2_list[] = {
664	[0] = &clk_ext_xtal_mux,
665	[1] = &clk_xusbxti,
666	[2] = &clk_sclk_hdmi27m,
667	[3] = &clk_sclk_usbphy0,
668	[4] = &clk_sclk_usbphy1,
669	[5] = &clk_sclk_hdmiphy,
670	[6] = &clk_mout_mpll.clk,
671	[7] = &clk_mout_epll.clk,
672	[8] = &clk_sclk_vpll.clk,
673};
674
675static struct clksrc_sources clkset_group2 = {
676	.sources	= clkset_group2_list,
677	.nr_sources	= ARRAY_SIZE(clkset_group2_list),
678};
679
680static struct clksrc_clk clksrcs[] = {
681	{
682		.clk	= {
683			.name		= "sclk_dmc",
684			.id		= -1,
685		},
686		.sources = &clkset_group1,
687		.reg_src = { .reg = S5P_CLK_SRC6, .shift = 24, .size = 2 },
688		.reg_div = { .reg = S5P_CLK_DIV6, .shift = 28, .size = 4 },
689	}, {
690		.clk	= {
691			.name		= "sclk_onenand",
692			.id		= -1,
693		},
694		.sources = &clkset_sclk_onenand,
695		.reg_src = { .reg = S5P_CLK_SRC0, .shift = 28, .size = 1 },
696		.reg_div = { .reg = S5P_CLK_DIV6, .shift = 12, .size = 3 },
697	}, {
698		.clk	= {
699			.name		= "uclk1",
700			.id		= 0,
701			.enable		= s5pv210_clk_mask0_ctrl,
702			.ctrlbit	= (1 << 12),
703		},
704		.sources = &clkset_uart,
705		.reg_src = { .reg = S5P_CLK_SRC4, .shift = 16, .size = 4 },
706		.reg_div = { .reg = S5P_CLK_DIV4, .shift = 16, .size = 4 },
707	}, {
708		.clk		= {
709			.name		= "uclk1",
710			.id		= 1,
711			.enable		= s5pv210_clk_mask0_ctrl,
712			.ctrlbit	= (1 << 13),
713		},
714		.sources = &clkset_uart,
715		.reg_src = { .reg = S5P_CLK_SRC4, .shift = 20, .size = 4 },
716		.reg_div = { .reg = S5P_CLK_DIV4, .shift = 20, .size = 4 },
717	}, {
718		.clk		= {
719			.name		= "uclk1",
720			.id		= 2,
721			.enable		= s5pv210_clk_mask0_ctrl,
722			.ctrlbit	= (1 << 14),
723		},
724		.sources = &clkset_uart,
725		.reg_src = { .reg = S5P_CLK_SRC4, .shift = 24, .size = 4 },
726		.reg_div = { .reg = S5P_CLK_DIV4, .shift = 24, .size = 4 },
727	}, {
728		.clk		= {
729			.name		= "uclk1",
730			.id		= 3,
731			.enable		= s5pv210_clk_mask0_ctrl,
732			.ctrlbit	= (1 << 15),
733		},
734		.sources = &clkset_uart,
735		.reg_src = { .reg = S5P_CLK_SRC4, .shift = 28, .size = 4 },
736		.reg_div = { .reg = S5P_CLK_DIV4, .shift = 28, .size = 4 },
737	}, {
738		.clk	= {
739			.name		= "sclk_mixer",
740			.id		= -1,
741			.enable		= s5pv210_clk_mask0_ctrl,
742			.ctrlbit	= (1 << 1),
743		},
744		.sources = &clkset_sclk_mixer,
745		.reg_src = { .reg = S5P_CLK_SRC1, .shift = 4, .size = 1 },
746	}, {
747		.clk		= {
748			.name		= "sclk_spdif",
749			.id		= -1,
750			.enable		= s5pv210_clk_mask0_ctrl,
751			.ctrlbit	= (1 << 27),
752		},
753		.sources = &clkset_sclk_spdif,
754		.reg_src = { .reg = S5P_CLK_SRC6, .shift = 12, .size = 2 },
755	}, {
756		.clk	= {
757			.name		= "sclk_fimc",
758			.id		= 0,
759			.enable		= s5pv210_clk_mask1_ctrl,
760			.ctrlbit	= (1 << 2),
761		},
762		.sources = &clkset_group2,
763		.reg_src = { .reg = S5P_CLK_SRC3, .shift = 12, .size = 4 },
764		.reg_div = { .reg = S5P_CLK_DIV3, .shift = 12, .size = 4 },
765	}, {
766		.clk	= {
767			.name		= "sclk_fimc",
768			.id		= 1,
769			.enable		= s5pv210_clk_mask1_ctrl,
770			.ctrlbit	= (1 << 3),
771		},
772		.sources = &clkset_group2,
773		.reg_src = { .reg = S5P_CLK_SRC3, .shift = 16, .size = 4 },
774		.reg_div = { .reg = S5P_CLK_DIV3, .shift = 16, .size = 4 },
775	}, {
776		.clk	= {
777			.name		= "sclk_fimc",
778			.id		= 2,
779			.enable		= s5pv210_clk_mask1_ctrl,
780			.ctrlbit	= (1 << 4),
781		},
782		.sources = &clkset_group2,
783		.reg_src = { .reg = S5P_CLK_SRC3, .shift = 20, .size = 4 },
784		.reg_div = { .reg = S5P_CLK_DIV3, .shift = 20, .size = 4 },
785	}, {
786		.clk		= {
787			.name		= "sclk_cam",
788			.id		= 0,
789			.enable		= s5pv210_clk_mask0_ctrl,
790			.ctrlbit	= (1 << 3),
791		},
792		.sources = &clkset_group2,
793		.reg_src = { .reg = S5P_CLK_SRC1, .shift = 12, .size = 4 },
794		.reg_div = { .reg = S5P_CLK_DIV1, .shift = 12, .size = 4 },
795	}, {
796		.clk		= {
797			.name		= "sclk_cam",
798			.id		= 1,
799			.enable		= s5pv210_clk_mask0_ctrl,
800			.ctrlbit	= (1 << 4),
801		},
802		.sources = &clkset_group2,
803		.reg_src = { .reg = S5P_CLK_SRC1, .shift = 16, .size = 4 },
804		.reg_div = { .reg = S5P_CLK_DIV1, .shift = 16, .size = 4 },
805	}, {
806		.clk		= {
807			.name		= "sclk_fimd",
808			.id		= -1,
809			.enable		= s5pv210_clk_mask0_ctrl,
810			.ctrlbit	= (1 << 5),
811		},
812		.sources = &clkset_group2,
813		.reg_src = { .reg = S5P_CLK_SRC1, .shift = 20, .size = 4 },
814		.reg_div = { .reg = S5P_CLK_DIV1, .shift = 20, .size = 4 },
815	}, {
816		.clk		= {
817			.name		= "sclk_mmc",
818			.id		= 0,
819			.enable		= s5pv210_clk_mask0_ctrl,
820			.ctrlbit	= (1 << 8),
821		},
822		.sources = &clkset_group2,
823		.reg_src = { .reg = S5P_CLK_SRC4, .shift = 0, .size = 4 },
824		.reg_div = { .reg = S5P_CLK_DIV4, .shift = 0, .size = 4 },
825	}, {
826		.clk		= {
827			.name		= "sclk_mmc",
828			.id		= 1,
829			.enable		= s5pv210_clk_mask0_ctrl,
830			.ctrlbit	= (1 << 9),
831		},
832		.sources = &clkset_group2,
833		.reg_src = { .reg = S5P_CLK_SRC4, .shift = 4, .size = 4 },
834		.reg_div = { .reg = S5P_CLK_DIV4, .shift = 4, .size = 4 },
835	}, {
836		.clk		= {
837			.name		= "sclk_mmc",
838			.id		= 2,
839			.enable		= s5pv210_clk_mask0_ctrl,
840			.ctrlbit	= (1 << 10),
841		},
842		.sources = &clkset_group2,
843		.reg_src = { .reg = S5P_CLK_SRC4, .shift = 8, .size = 4 },
844		.reg_div = { .reg = S5P_CLK_DIV4, .shift = 8, .size = 4 },
845	}, {
846		.clk		= {
847			.name		= "sclk_mmc",
848			.id		= 3,
849			.enable		= s5pv210_clk_mask0_ctrl,
850			.ctrlbit	= (1 << 11),
851		},
852		.sources = &clkset_group2,
853		.reg_src = { .reg = S5P_CLK_SRC4, .shift = 12, .size = 4 },
854		.reg_div = { .reg = S5P_CLK_DIV4, .shift = 12, .size = 4 },
855	}, {
856		.clk		= {
857			.name		= "sclk_mfc",
858			.id		= -1,
859			.enable		= s5pv210_clk_ip0_ctrl,
860			.ctrlbit	= (1 << 16),
861		},
862		.sources = &clkset_group1,
863		.reg_src = { .reg = S5P_CLK_SRC2, .shift = 4, .size = 2 },
864		.reg_div = { .reg = S5P_CLK_DIV2, .shift = 4, .size = 4 },
865	}, {
866		.clk		= {
867			.name		= "sclk_g2d",
868			.id		= -1,
869			.enable		= s5pv210_clk_ip0_ctrl,
870			.ctrlbit	= (1 << 12),
871		},
872		.sources = &clkset_group1,
873		.reg_src = { .reg = S5P_CLK_SRC2, .shift = 8, .size = 2 },
874		.reg_div = { .reg = S5P_CLK_DIV2, .shift = 8, .size = 4 },
875	}, {
876		.clk		= {
877			.name		= "sclk_g3d",
878			.id		= -1,
879			.enable		= s5pv210_clk_ip0_ctrl,
880			.ctrlbit	= (1 << 8),
881		},
882		.sources = &clkset_group1,
883		.reg_src = { .reg = S5P_CLK_SRC2, .shift = 0, .size = 2 },
884		.reg_div = { .reg = S5P_CLK_DIV2, .shift = 0, .size = 4 },
885	}, {
886		.clk		= {
887			.name		= "sclk_csis",
888			.id		= -1,
889			.enable		= s5pv210_clk_mask0_ctrl,
890			.ctrlbit	= (1 << 6),
891		},
892		.sources = &clkset_group2,
893		.reg_src = { .reg = S5P_CLK_SRC1, .shift = 24, .size = 4 },
894		.reg_div = { .reg = S5P_CLK_DIV1, .shift = 28, .size = 4 },
895	}, {
896		.clk		= {
897			.name		= "sclk_spi",
898			.id		= 0,
899			.enable		= s5pv210_clk_mask0_ctrl,
900			.ctrlbit	= (1 << 16),
901		},
902		.sources = &clkset_group2,
903		.reg_src = { .reg = S5P_CLK_SRC5, .shift = 0, .size = 4 },
904		.reg_div = { .reg = S5P_CLK_DIV5, .shift = 0, .size = 4 },
905	}, {
906		.clk		= {
907			.name		= "sclk_spi",
908			.id		= 1,
909			.enable		= s5pv210_clk_mask0_ctrl,
910			.ctrlbit	= (1 << 17),
911		},
912		.sources = &clkset_group2,
913		.reg_src = { .reg = S5P_CLK_SRC5, .shift = 4, .size = 4 },
914		.reg_div = { .reg = S5P_CLK_DIV5, .shift = 4, .size = 4 },
915	}, {
916		.clk		= {
917			.name		= "sclk_pwi",
918			.id		= -1,
919			.enable		= s5pv210_clk_mask0_ctrl,
920			.ctrlbit	= (1 << 29),
921		},
922		.sources = &clkset_group2,
923		.reg_src = { .reg = S5P_CLK_SRC6, .shift = 20, .size = 4 },
924		.reg_div = { .reg = S5P_CLK_DIV6, .shift = 24, .size = 4 },
925	}, {
926		.clk		= {
927			.name		= "sclk_pwm",
928			.id		= -1,
929			.enable		= s5pv210_clk_mask0_ctrl,
930			.ctrlbit	= (1 << 19),
931		},
932		.sources = &clkset_group2,
933		.reg_src = { .reg = S5P_CLK_SRC5, .shift = 12, .size = 4 },
934		.reg_div = { .reg = S5P_CLK_DIV5, .shift = 12, .size = 4 },
935	},
936};
937
938/* Clock initialisation code */
939static struct clksrc_clk *sysclks[] = {
940	&clk_mout_apll,
941	&clk_mout_epll,
942	&clk_mout_mpll,
943	&clk_armclk,
944	&clk_hclk_msys,
945	&clk_sclk_a2m,
946	&clk_hclk_dsys,
947	&clk_hclk_psys,
948	&clk_pclk_msys,
949	&clk_pclk_dsys,
950	&clk_pclk_psys,
951	&clk_vpllsrc,
952	&clk_sclk_vpll,
953	&clk_sclk_dac,
954	&clk_sclk_pixel,
955	&clk_sclk_hdmi,
956};
957
958void __init_or_cpufreq s5pv210_setup_clocks(void)
959{
960	struct clk *xtal_clk;
961	unsigned long xtal;
962	unsigned long vpllsrc;
963	unsigned long armclk;
964	unsigned long hclk_msys;
965	unsigned long hclk_dsys;
966	unsigned long hclk_psys;
967	unsigned long pclk_msys;
968	unsigned long pclk_dsys;
969	unsigned long pclk_psys;
970	unsigned long apll;
971	unsigned long mpll;
972	unsigned long epll;
973	unsigned long vpll;
974	unsigned int ptr;
975	u32 clkdiv0, clkdiv1;
976
977	printk(KERN_DEBUG "%s: registering clocks\n", __func__);
978
979	clkdiv0 = __raw_readl(S5P_CLK_DIV0);
980	clkdiv1 = __raw_readl(S5P_CLK_DIV1);
981
982	printk(KERN_DEBUG "%s: clkdiv0 = %08x, clkdiv1 = %08x\n",
983				__func__, clkdiv0, clkdiv1);
984
985	xtal_clk = clk_get(NULL, "xtal");
986	BUG_ON(IS_ERR(xtal_clk));
987
988	xtal = clk_get_rate(xtal_clk);
989	clk_put(xtal_clk);
990
991	printk(KERN_DEBUG "%s: xtal is %ld\n", __func__, xtal);
992
993	apll = s5p_get_pll45xx(xtal, __raw_readl(S5P_APLL_CON), pll_4508);
994	mpll = s5p_get_pll45xx(xtal, __raw_readl(S5P_MPLL_CON), pll_4502);
995	epll = s5p_get_pll45xx(xtal, __raw_readl(S5P_EPLL_CON), pll_4500);
996	vpllsrc = clk_get_rate(&clk_vpllsrc.clk);
997	vpll = s5p_get_pll45xx(vpllsrc, __raw_readl(S5P_VPLL_CON), pll_4502);
998
999	clk_fout_apll.rate = apll;
1000	clk_fout_mpll.rate = mpll;
1001	clk_fout_epll.rate = epll;
1002	clk_fout_vpll.rate = vpll;
1003
1004	printk(KERN_INFO "S5PV210: PLL settings, A=%ld, M=%ld, E=%ld V=%ld",
1005			apll, mpll, epll, vpll);
1006
1007	armclk = clk_get_rate(&clk_armclk.clk);
1008	hclk_msys = clk_get_rate(&clk_hclk_msys.clk);
1009	hclk_dsys = clk_get_rate(&clk_hclk_dsys.clk);
1010	hclk_psys = clk_get_rate(&clk_hclk_psys.clk);
1011	pclk_msys = clk_get_rate(&clk_pclk_msys.clk);
1012	pclk_dsys = clk_get_rate(&clk_pclk_dsys.clk);
1013	pclk_psys = clk_get_rate(&clk_pclk_psys.clk);
1014
1015	printk(KERN_INFO "S5PV210: ARMCLK=%ld, HCLKM=%ld, HCLKD=%ld\n"
1016			 "HCLKP=%ld, PCLKM=%ld, PCLKD=%ld, PCLKP=%ld\n",
1017			armclk, hclk_msys, hclk_dsys, hclk_psys,
1018			pclk_msys, pclk_dsys, pclk_psys);
1019
1020	clk_f.rate = armclk;
1021	clk_h.rate = hclk_psys;
1022	clk_p.rate = pclk_psys;
1023
1024	for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++)
1025		s3c_set_clksrc(&clksrcs[ptr], true);
1026}
1027
1028static struct clk *clks[] __initdata = {
1029	&clk_sclk_hdmi27m,
1030	&clk_sclk_hdmiphy,
1031	&clk_sclk_usbphy0,
1032	&clk_sclk_usbphy1,
1033	&clk_pcmcdclk0,
1034	&clk_pcmcdclk1,
1035	&clk_pcmcdclk2,
1036};
1037
1038void __init s5pv210_register_clocks(void)
1039{
1040	struct clk *clkp;
1041	int ret;
1042	int ptr;
1043
1044	ret = s3c24xx_register_clocks(clks, ARRAY_SIZE(clks));
1045	if (ret > 0)
1046		printk(KERN_ERR "Failed to register %u clocks\n", ret);
1047
1048	for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++)
1049		s3c_register_clksrc(sysclks[ptr], 1);
1050
1051	s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
1052	s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
1053
1054	clkp = init_clocks_disable;
1055	for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) {
1056		ret = s3c24xx_register_clock(clkp);
1057		if (ret < 0) {
1058			printk(KERN_ERR "Failed to register clock %s (%d)\n",
1059			       clkp->name, ret);
1060		}
1061		(clkp->enable)(clkp, 0);
1062	}
1063
1064	s3c_pwmclk_init();
1065}
1066