2 * Copyright 2009 Samsung Electronics Co., Ltd.
3 * http://www.samsung.com/
5 * S5P - Common clock support
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
12 #include <linux/init.h>
13 #include <linux/module.h>
14 #include <linux/kernel.h>
15 #include <linux/list.h>
16 #include <linux/errno.h>
17 #include <linux/err.h>
18 #include <linux/clk.h>
19 #include <linux/device.h>
21 #include <asm/div64.h>
23 #include <mach/regs-clock.h>
25 #include <plat/clock.h>
26 #include <plat/clock-clksrc.h>
27 #include <plat/s5p-clock.h>
29 /* fin_apll, fin_mpll and fin_epll are all the same clock, which we call
32 struct clk clk_ext_xtal_mux
= {
37 struct clk clk_xusbxti
= {
43 struct clk s5p_clk_27m
= {
49 /* 48MHz USB Phy clock output */
50 struct clk clk_48m
= {
57 * No need .ctrlbit, this is always on
59 struct clk clk_fout_apll
= {
64 /* BPLL clock output */
66 struct clk clk_fout_bpll
= {
71 struct clk clk_fout_bpll_div2
= {
72 .name
= "fout_bpll_div2",
76 /* CPLL clock output */
78 struct clk clk_fout_cpll
= {
84 * No need .ctrlbit, this is always on
86 struct clk clk_fout_mpll
= {
91 struct clk clk_fout_mpll_div2
= {
92 .name
= "fout_mpll_div2",
96 /* EPLL clock output */
97 struct clk clk_fout_epll
= {
100 .ctrlbit
= (1 << 31),
103 /* DPLL clock output */
104 struct clk clk_fout_dpll
= {
107 .ctrlbit
= (1 << 31),
110 /* VPLL clock output */
111 struct clk clk_fout_vpll
= {
114 .ctrlbit
= (1 << 31),
117 /* Possible clock sources for APLL Mux */
118 static struct clk
*clk_src_apll_list
[] = {
120 [1] = &clk_fout_apll
,
123 struct clksrc_sources clk_src_apll
= {
124 .sources
= clk_src_apll_list
,
125 .nr_sources
= ARRAY_SIZE(clk_src_apll_list
),
128 /* Possible clock sources for BPLL Mux */
129 static struct clk
*clk_src_bpll_list
[] = {
131 [1] = &clk_fout_bpll
,
134 struct clksrc_sources clk_src_bpll
= {
135 .sources
= clk_src_bpll_list
,
136 .nr_sources
= ARRAY_SIZE(clk_src_bpll_list
),
139 static struct clk
*clk_src_bpll_fout_list
[] = {
140 [0] = &clk_fout_bpll_div2
,
141 [1] = &clk_fout_bpll
,
144 struct clksrc_sources clk_src_bpll_fout
= {
145 .sources
= clk_src_bpll_fout_list
,
146 .nr_sources
= ARRAY_SIZE(clk_src_bpll_fout_list
),
149 /* Possible clock sources for CPLL Mux */
150 static struct clk
*clk_src_cpll_list
[] = {
152 [1] = &clk_fout_cpll
,
155 struct clksrc_sources clk_src_cpll
= {
156 .sources
= clk_src_cpll_list
,
157 .nr_sources
= ARRAY_SIZE(clk_src_cpll_list
),
160 /* Possible clock sources for MPLL Mux */
161 static struct clk
*clk_src_mpll_list
[] = {
163 [1] = &clk_fout_mpll
,
166 struct clksrc_sources clk_src_mpll
= {
167 .sources
= clk_src_mpll_list
,
168 .nr_sources
= ARRAY_SIZE(clk_src_mpll_list
),
171 static struct clk
*clk_src_mpll_fout_list
[] = {
172 [0] = &clk_fout_mpll_div2
,
173 [1] = &clk_fout_mpll
,
176 struct clksrc_sources clk_src_mpll_fout
= {
177 .sources
= clk_src_mpll_fout_list
,
178 .nr_sources
= ARRAY_SIZE(clk_src_mpll_fout_list
),
181 /* Possible clock sources for EPLL Mux */
182 static struct clk
*clk_src_epll_list
[] = {
184 [1] = &clk_fout_epll
,
187 struct clksrc_sources clk_src_epll
= {
188 .sources
= clk_src_epll_list
,
189 .nr_sources
= ARRAY_SIZE(clk_src_epll_list
),
192 /* Possible clock sources for DPLL Mux */
193 static struct clk
*clk_src_dpll_list
[] = {
195 [1] = &clk_fout_dpll
,
198 struct clksrc_sources clk_src_dpll
= {
199 .sources
= clk_src_dpll_list
,
200 .nr_sources
= ARRAY_SIZE(clk_src_dpll_list
),
203 struct clk clk_vpll
= {
208 int s5p_gatectrl(void __iomem
*reg
, struct clk
*clk
, int enable
)
210 unsigned int ctrlbit
= clk
->ctrlbit
;
213 con
= __raw_readl(reg
);
214 con
= enable
? (con
| ctrlbit
) : (con
& ~ctrlbit
);
215 __raw_writel(con
, reg
);
219 int s5p_epll_enable(struct clk
*clk
, int enable
)
221 unsigned int ctrlbit
= clk
->ctrlbit
;
222 unsigned int epll_con
= __raw_readl(S5P_EPLL_CON
) & ~ctrlbit
;
225 __raw_writel(epll_con
| ctrlbit
, S5P_EPLL_CON
);
227 __raw_writel(epll_con
, S5P_EPLL_CON
);
232 unsigned long s5p_epll_get_rate(struct clk
*clk
)
237 int s5p_spdif_set_rate(struct clk
*clk
, unsigned long rate
)
242 pclk
= clk_get_parent(clk
);
246 ret
= pclk
->ops
->set_rate(pclk
, rate
);
252 unsigned long s5p_spdif_get_rate(struct clk
*clk
)
257 pclk
= clk_get_parent(clk
);
261 rate
= pclk
->ops
->get_rate(pclk
);
267 struct clk_ops s5p_sclk_spdif_ops
= {
268 .set_rate
= s5p_spdif_set_rate
,
269 .get_rate
= s5p_spdif_get_rate
,
272 static struct clk
*s5p_clks
[] __initdata
= {
285 void __init
s5p_register_clocks(unsigned long xtal_freq
)
289 clk_ext_xtal_mux
.rate
= xtal_freq
;
291 ret
= s3c24xx_register_clocks(s5p_clks
, ARRAY_SIZE(s5p_clks
));
293 printk(KERN_ERR
"Failed to register s5p clocks\n");