1 /* linux/arch/arm/mach-s3c2443/clock.c
2  *
3  * Copyright (c) 2007, 2010 Simtec Electronics
4  *	Ben Dooks <ben@simtec.co.uk>
5  *
6  * S3C2443 Clock control 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 as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21 */
22 
23 #include <linux/init.h>
24 
25 #include <linux/module.h>
26 #include <linux/kernel.h>
27 #include <linux/list.h>
28 #include <linux/errno.h>
29 #include <linux/err.h>
30 #include <linux/sysdev.h>
31 #include <linux/clk.h>
32 #include <linux/mutex.h>
33 #include <linux/serial_core.h>
34 #include <linux/io.h>
35 
36 #include <asm/mach/map.h>
37 
38 #include <mach/hardware.h>
39 
40 #include <mach/regs-s3c2443-clock.h>
41 
42 #include <plat/cpu-freq.h>
43 
44 #include <plat/s3c2443.h>
45 #include <plat/clock.h>
46 #include <plat/clock-clksrc.h>
47 #include <plat/cpu.h>
48 
49 /* We currently have to assume that the system is running
50  * from the XTPll input, and that all ***REFCLKs are being
51  * fed from it, as we cannot read the state of OM[4] from
52  * software.
53  *
54  * It would be possible for each board initialisation to
55  * set the correct muxing at initialisation
56 */
57 
58 /* clock selections */
59 
60 static struct clk clk_i2s_ext = {
61 	.name		= "i2s-ext",
62 	.id		= -1,
63 };
64 
65 /* armdiv
66  *
67  * this clock is sourced from msysclk and can have a number of
68  * divider values applied to it to then be fed into armclk.
69 */
70 
71 /* armdiv divisor table */
72 
73 static unsigned int armdiv[16] = {
74 	[S3C2443_CLKDIV0_ARMDIV_1 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]	= 1,
75 	[S3C2443_CLKDIV0_ARMDIV_2 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]	= 2,
76 	[S3C2443_CLKDIV0_ARMDIV_3 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]	= 3,
77 	[S3C2443_CLKDIV0_ARMDIV_4 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]	= 4,
78 	[S3C2443_CLKDIV0_ARMDIV_6 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]	= 6,
79 	[S3C2443_CLKDIV0_ARMDIV_8 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]	= 8,
80 	[S3C2443_CLKDIV0_ARMDIV_12 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]	= 12,
81 	[S3C2443_CLKDIV0_ARMDIV_16 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]	= 16,
82 };
83 
s3c2443_fclk_div(unsigned long clkcon0)84 static inline unsigned int s3c2443_fclk_div(unsigned long clkcon0)
85 {
86 	clkcon0 &= S3C2443_CLKDIV0_ARMDIV_MASK;
87 
88 	return armdiv[clkcon0 >> S3C2443_CLKDIV0_ARMDIV_SHIFT];
89 }
90 
s3c2443_armclk_roundrate(struct clk * clk,unsigned long rate)91 static unsigned long s3c2443_armclk_roundrate(struct clk *clk,
92 					      unsigned long rate)
93 {
94 	unsigned long parent = clk_get_rate(clk->parent);
95 	unsigned long calc;
96 	unsigned best = 256; /* bigger than any value */
97 	unsigned div;
98 	int ptr;
99 
100 	for (ptr = 0; ptr < ARRAY_SIZE(armdiv); ptr++) {
101 		div = armdiv[ptr];
102 		calc = parent / div;
103 		if (calc <= rate && div < best)
104 			best = div;
105 	}
106 
107 	return parent / best;
108 }
109 
s3c2443_armclk_setrate(struct clk * clk,unsigned long rate)110 static int s3c2443_armclk_setrate(struct clk *clk, unsigned long rate)
111 {
112 	unsigned long parent = clk_get_rate(clk->parent);
113 	unsigned long calc;
114 	unsigned div;
115 	unsigned best = 256; /* bigger than any value */
116 	int ptr;
117 	int val = -1;
118 
119 	for (ptr = 0; ptr < ARRAY_SIZE(armdiv); ptr++) {
120 		div = armdiv[ptr];
121 		calc = parent / div;
122 		if (calc <= rate && div < best) {
123 			best = div;
124 			val = ptr;
125 		}
126 	}
127 
128 	if (val >= 0) {
129 		unsigned long clkcon0;
130 
131 		clkcon0 = __raw_readl(S3C2443_CLKDIV0);
132 		clkcon0 &= S3C2443_CLKDIV0_ARMDIV_MASK;
133 		clkcon0 |= val << S3C2443_CLKDIV0_ARMDIV_SHIFT;
134 		__raw_writel(clkcon0, S3C2443_CLKDIV0);
135 	}
136 
137 	return (val == -1) ? -EINVAL : 0;
138 }
139 
140 static struct clk clk_armdiv = {
141 	.name		= "armdiv",
142 	.id		= -1,
143 	.parent		= &clk_msysclk.clk,
144 	.ops		= &(struct clk_ops) {
145 		.round_rate = s3c2443_armclk_roundrate,
146 		.set_rate = s3c2443_armclk_setrate,
147 	},
148 };
149 
150 /* armclk
151  *
152  * this is the clock fed into the ARM core itself, from armdiv or from hclk.
153  */
154 
155 static struct clk *clk_arm_sources[] = {
156 	[0] = &clk_armdiv,
157 	[1] = &clk_h,
158 };
159 
160 static struct clksrc_clk clk_arm = {
161 	.clk	= {
162 		.name		= "armclk",
163 		.id		= -1,
164 	},
165 	.sources = &(struct clksrc_sources) {
166 		.sources = clk_arm_sources,
167 		.nr_sources = ARRAY_SIZE(clk_arm_sources),
168 	},
169 	.reg_src = { .reg = S3C2443_CLKDIV0, .size = 1, .shift = 13 },
170 };
171 
172 /* hsspi
173  *
174  * high-speed spi clock, sourced from esysclk
175 */
176 
177 static struct clksrc_clk clk_hsspi = {
178 	.clk	= {
179 		.name		= "hsspi",
180 		.id		= -1,
181 		.parent		= &clk_esysclk.clk,
182 		.ctrlbit	= S3C2443_SCLKCON_HSSPICLK,
183 		.enable		= s3c2443_clkcon_enable_s,
184 	},
185 	.reg_div = { .reg = S3C2443_CLKDIV1, .size = 2, .shift = 4 },
186 };
187 
188 
189 /* clk_hsmcc_div
190  *
191  * this clock is sourced from epll, and is fed through a divider,
192  * to a mux controlled by sclkcon where either it or a extclk can
193  * be fed to the hsmmc block
194 */
195 
196 static struct clksrc_clk clk_hsmmc_div = {
197 	.clk	= {
198 		.name		= "hsmmc-div",
199 		.id		= 1,
200 		.parent		= &clk_esysclk.clk,
201 	},
202 	.reg_div = { .reg = S3C2443_CLKDIV1, .size = 2, .shift = 6 },
203 };
204 
s3c2443_setparent_hsmmc(struct clk * clk,struct clk * parent)205 static int s3c2443_setparent_hsmmc(struct clk *clk, struct clk *parent)
206 {
207 	unsigned long clksrc = __raw_readl(S3C2443_SCLKCON);
208 
209 	clksrc &= ~(S3C2443_SCLKCON_HSMMCCLK_EXT |
210 		    S3C2443_SCLKCON_HSMMCCLK_EPLL);
211 
212 	if (parent == &clk_epll)
213 		clksrc |= S3C2443_SCLKCON_HSMMCCLK_EPLL;
214 	else if (parent == &clk_ext)
215 		clksrc |= S3C2443_SCLKCON_HSMMCCLK_EXT;
216 	else
217 		return -EINVAL;
218 
219 	if (clk->usage > 0) {
220 		__raw_writel(clksrc, S3C2443_SCLKCON);
221 	}
222 
223 	clk->parent = parent;
224 	return 0;
225 }
226 
s3c2443_enable_hsmmc(struct clk * clk,int enable)227 static int s3c2443_enable_hsmmc(struct clk *clk, int enable)
228 {
229 	return s3c2443_setparent_hsmmc(clk, clk->parent);
230 }
231 
232 static struct clk clk_hsmmc = {
233 	.name		= "hsmmc-if",
234 	.id		= 1,
235 	.parent		= &clk_hsmmc_div.clk,
236 	.enable		= s3c2443_enable_hsmmc,
237 	.ops		= &(struct clk_ops) {
238 		.set_parent	= s3c2443_setparent_hsmmc,
239 	},
240 };
241 
242 /* i2s_eplldiv
243  *
244  * This clock is the output from the I2S divisor of ESYSCLK, and is separate
245  * from the mux that comes after it (cannot merge into one single clock)
246 */
247 
248 static struct clksrc_clk clk_i2s_eplldiv = {
249 	.clk	= {
250 		.name		= "i2s-eplldiv",
251 		.id		= -1,
252 		.parent		= &clk_esysclk.clk,
253 	},
254 	.reg_div = { .reg = S3C2443_CLKDIV1, .size = 4, .shift = 12, },
255 };
256 
257 /* i2s-ref
258  *
259  * i2s bus reference clock, selectable from external, esysclk or epllref
260  *
261  * Note, this used to be two clocks, but was compressed into one.
262 */
263 
264 struct clk *clk_i2s_srclist[] = {
265 	[0] = &clk_i2s_eplldiv.clk,
266 	[1] = &clk_i2s_ext,
267 	[2] = &clk_epllref.clk,
268 	[3] = &clk_epllref.clk,
269 };
270 
271 static struct clksrc_clk clk_i2s = {
272 	.clk	= {
273 		.name		= "i2s-if",
274 		.id		= -1,
275 		.ctrlbit	= S3C2443_SCLKCON_I2SCLK,
276 		.enable		= s3c2443_clkcon_enable_s,
277 
278 	},
279 	.sources = &(struct clksrc_sources) {
280 		.sources = clk_i2s_srclist,
281 		.nr_sources = ARRAY_SIZE(clk_i2s_srclist),
282 	},
283 	.reg_src = { .reg = S3C2443_CLKSRC, .size = 2, .shift = 14 },
284 };
285 
286 /* standard clock definitions */
287 
288 static struct clk init_clocks_off[] = {
289 	{
290 		.name		= "sdi",
291 		.id		= -1,
292 		.parent		= &clk_p,
293 		.enable		= s3c2443_clkcon_enable_p,
294 		.ctrlbit	= S3C2443_PCLKCON_SDI,
295 	}, {
296 		.name		= "iis",
297 		.id		= -1,
298 		.parent		= &clk_p,
299 		.enable		= s3c2443_clkcon_enable_p,
300 		.ctrlbit	= S3C2443_PCLKCON_IIS,
301 	}, {
302 		.name		= "spi",
303 		.id		= 0,
304 		.parent		= &clk_p,
305 		.enable		= s3c2443_clkcon_enable_p,
306 		.ctrlbit	= S3C2443_PCLKCON_SPI0,
307 	}, {
308 		.name		= "spi",
309 		.id		= 1,
310 		.parent		= &clk_p,
311 		.enable		= s3c2443_clkcon_enable_p,
312 		.ctrlbit	= S3C2443_PCLKCON_SPI1,
313 	}
314 };
315 
316 static struct clk init_clocks[] = {
317 };
318 
319 /* clocks to add straight away */
320 
321 static struct clksrc_clk *clksrcs[] __initdata = {
322 	&clk_arm,
323 	&clk_i2s_eplldiv,
324 	&clk_i2s,
325 	&clk_hsspi,
326 	&clk_hsmmc_div,
327 };
328 
329 static struct clk *clks[] __initdata = {
330 	&clk_hsmmc,
331 	&clk_armdiv,
332 };
333 
s3c2443_setup_clocks(void)334 void __init_or_cpufreq s3c2443_setup_clocks(void)
335 {
336 	s3c2443_common_setup_clocks(s3c2443_get_mpll, s3c2443_fclk_div);
337 }
338 
s3c2443_init_clocks(int xtal)339 void __init s3c2443_init_clocks(int xtal)
340 {
341 	unsigned long epllcon = __raw_readl(S3C2443_EPLLCON);
342 	int ptr;
343 
344 	clk_epll.rate = s3c2443_get_epll(epllcon, xtal);
345 	clk_epll.parent = &clk_epllref.clk;
346 
347 	s3c2443_common_init_clocks(xtal, s3c2443_get_mpll, s3c2443_fclk_div);
348 
349 	s3c2443_setup_clocks();
350 
351 	s3c24xx_register_clocks(clks, ARRAY_SIZE(clks));
352 
353 	for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++)
354 		s3c_register_clksrc(clksrcs[ptr], 1);
355 
356 	/* register clocks from clock array */
357 
358 	s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
359 
360 	/* We must be careful disabling the clocks we are not intending to
361 	 * be using at boot time, as subsystems such as the LCD which do
362 	 * their own DMA requests to the bus can cause the system to lockup
363 	 * if they where in the middle of requesting bus access.
364 	 *
365 	 * Disabling the LCD clock if the LCD is active is very dangerous,
366 	 * and therefore the bootloader should be careful to not enable
367 	 * the LCD clock if it is not needed.
368 	*/
369 
370 	/* install (and disable) the clocks we do not need immediately */
371 
372 	s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
373 	s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
374 
375 	s3c_pwmclk_init();
376 }
377