aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-s3c2443/clock.c
diff options
context:
space:
mode:
authorBen Dooks <ben-linux@fluff.org>2010-01-30 03:25:49 -0500
committerBen Dooks <ben-linux@fluff.org>2010-03-07 17:56:11 -0500
commit4bed36b2c5b3248ae6f9aaf5194fbe85153e4026 (patch)
tree1f99b1d559b83c16444bd55dc2743343512d7103 /arch/arm/mach-s3c2443/clock.c
parent9aa753c4422492547a190df8a3b6a56282669f9b (diff)
ARM: S3C2443: Further clksrc-clk conversions
Move more of the core clocks that where left over from the last commit as they are much more core to the system operation. This should allow for easier tracking of any problems. Signed-off-by: Ben Dooks <ben-linux@fluff.org>
Diffstat (limited to 'arch/arm/mach-s3c2443/clock.c')
-rw-r--r--arch/arm/mach-s3c2443/clock.c187
1 files changed, 62 insertions, 125 deletions
diff --git a/arch/arm/mach-s3c2443/clock.c b/arch/arm/mach-s3c2443/clock.c
index f89e71f50345..1307f69abf98 100644
--- a/arch/arm/mach-s3c2443/clock.c
+++ b/arch/arm/mach-s3c2443/clock.c
@@ -1,6 +1,6 @@
1/* linux/arch/arm/mach-s3c2443/clock.c 1/* linux/arch/arm/mach-s3c2443/clock.c
2 * 2 *
3 * Copyright (c) 2007,2010 Simtec Electronics 3 * Copyright (c) 2007, 2010 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk> 4 * Ben Dooks <ben@simtec.co.uk>
5 * 5 *
6 * S3C2443 Clock control support 6 * S3C2443 Clock control support
@@ -145,33 +145,24 @@ static struct clk clk_mdivclk = {
145 }, 145 },
146}; 146};
147 147
148static int s3c2443_setparent_msysclk(struct clk *clk, struct clk *parent) 148static struct clk *clk_msysclk_sources[] = {
149{ 149 [0] = &clk_mpllref,
150 unsigned long clksrc = __raw_readl(S3C2443_CLKSRC); 150 [1] = &clk_mpll,
151 151 [2] = &clk_mdivclk,
152 clksrc &= ~(S3C2443_CLKSRC_MSYSCLK_MPLL | 152 [3] = &clk_mpllref,
153 S3C2443_CLKSRC_EXTCLK_DIV); 153};
154
155 if (parent == &clk_mpll)
156 clksrc |= S3C2443_CLKSRC_MSYSCLK_MPLL;
157 else if (parent == &clk_mdivclk)
158 clksrc |= S3C2443_CLKSRC_EXTCLK_DIV;
159 else if (parent != &clk_mpllref)
160 return -EINVAL;
161
162 __raw_writel(clksrc, S3C2443_CLKSRC);
163 clk->parent = parent;
164
165 return 0;
166}
167 154
168static struct clk clk_msysclk = { 155static struct clksrc_clk clk_msysclk = {
169 .name = "msysclk", 156 .clk = {
170 .parent = &clk_xtal, 157 .name = "msysclk",
171 .id = -1, 158 .parent = &clk_xtal,
172 .ops = &(struct clk_ops) { 159 .id = -1,
173 .set_parent = s3c2443_setparent_msysclk, 160 },
161 .sources = &(struct clksrc_sources) {
162 .sources = clk_msysclk_sources,
163 .nr_sources = ARRAY_SIZE(clk_msysclk_sources),
174 }, 164 },
165 .reg_src = { .reg = S3C2443_CLKSRC, .size = 2, .shift = 3 },
175}; 166};
176 167
177/* armdiv 168/* armdiv
@@ -183,38 +174,29 @@ static struct clk clk_msysclk = {
183static struct clk clk_armdiv = { 174static struct clk clk_armdiv = {
184 .name = "armdiv", 175 .name = "armdiv",
185 .id = -1, 176 .id = -1,
186 .parent = &clk_msysclk, 177 .parent = &clk_msysclk.clk,
187}; 178};
188 179
189/* armclk 180/* armclk
190 * 181 *
191 * this is the clock fed into the ARM core itself, either from 182 * this is the clock fed into the ARM core itself, from armdiv or from hclk.
192 * armdiv or from hclk.
193 */ 183 */
194 184
195static int s3c2443_setparent_armclk(struct clk *clk, struct clk *parent) 185static struct clk *clk_arm_sources[] = {
196{ 186 [0] = &clk_armdiv,
197 unsigned long clkdiv0; 187 [1] = &clk_h,
198 188};
199 clkdiv0 = __raw_readl(S3C2443_CLKDIV0);
200
201 if (parent == &clk_armdiv)
202 clkdiv0 &= ~S3C2443_CLKDIV0_DVS;
203 else if (parent == &clk_h)
204 clkdiv0 |= S3C2443_CLKDIV0_DVS;
205 else
206 return -EINVAL;
207
208 __raw_writel(clkdiv0, S3C2443_CLKDIV0);
209 return 0;
210}
211 189
212static struct clk clk_arm = { 190static struct clksrc_clk clk_arm = {
213 .name = "armclk", 191 .clk = {
214 .id = -1, 192 .name = "armclk",
215 .ops = &(struct clk_ops) { 193 .id = -1,
216 .set_parent = s3c2443_setparent_armclk,
217 }, 194 },
195 .sources = &(struct clksrc_sources) {
196 .sources = clk_arm_sources,
197 .nr_sources = ARRAY_SIZE(clk_arm_sources),
198 },
199 .reg_src = { .reg = S3C2443_CLKDIV0, .size = 1, .shift = 13 },
218}; 200};
219 201
220/* esysclk 202/* esysclk
@@ -222,30 +204,22 @@ static struct clk clk_arm = {
222 * this is sourced from either the EPLL or the EPLLref clock 204 * this is sourced from either the EPLL or the EPLLref clock
223*/ 205*/
224 206
225static int s3c2443_setparent_esysclk(struct clk *clk, struct clk *parent) 207static struct clk *clk_sysclk_sources[] = {
226{ 208 [0] = &clk_epllref.clk,
227 unsigned long clksrc = __raw_readl(S3C2443_CLKSRC); 209 [1] = &clk_epll,
228 210};
229 if (parent == &clk_epll)
230 clksrc |= S3C2443_CLKSRC_ESYSCLK_EPLL;
231 else if (parent == &clk_epllref.clk)
232 clksrc &= ~S3C2443_CLKSRC_ESYSCLK_EPLL;
233 else
234 return -EINVAL;
235
236 __raw_writel(clksrc, S3C2443_CLKSRC);
237 clk->parent = parent;
238
239 return 0;
240}
241 211
242static struct clk clk_esysclk = { 212static struct clksrc_clk clk_esysclk = {
243 .name = "esysclk", 213 .clk = {
244 .parent = &clk_epll, 214 .name = "esysclk",
245 .id = -1, 215 .parent = &clk_epll,
246 .ops = &(struct clk_ops) { 216 .id = -1,
247 .set_parent = s3c2443_setparent_esysclk,
248 }, 217 },
218 .sources = &(struct clksrc_sources) {
219 .sources = clk_sysclk_sources,
220 .nr_sources = ARRAY_SIZE(clk_sysclk_sources),
221 },
222 .reg_src = { .reg = S3C2443_CLKSRC, .size = 1, .shift = 6 },
249}; 223};
250 224
251/* uartclk 225/* uartclk
@@ -257,7 +231,7 @@ static struct clksrc_clk clk_uart = {
257 .clk = { 231 .clk = {
258 .name = "uartclk", 232 .name = "uartclk",
259 .id = -1, 233 .id = -1,
260 .parent = &clk_esysclk, 234 .parent = &clk_esysclk.clk,
261 }, 235 },
262 .reg_div = { .reg = S3C2443_CLKDIV1, .size = 4, .shift = 8 }, 236 .reg_div = { .reg = S3C2443_CLKDIV1, .size = 4, .shift = 8 },
263}; 237};
@@ -272,7 +246,7 @@ static struct clksrc_clk clk_hsspi = {
272 .clk = { 246 .clk = {
273 .name = "hsspi", 247 .name = "hsspi",
274 .id = -1, 248 .id = -1,
275 .parent = &clk_esysclk, 249 .parent = &clk_esysclk.clk,
276 .ctrlbit = S3C2443_SCLKCON_HSSPICLK, 250 .ctrlbit = S3C2443_SCLKCON_HSSPICLK,
277 .enable = s3c2443_clkcon_enable_s, 251 .enable = s3c2443_clkcon_enable_s,
278 }, 252 },
@@ -288,7 +262,7 @@ static struct clksrc_clk clk_usb_bus_host = {
288 .clk = { 262 .clk = {
289 .name = "usb-bus-host-parent", 263 .name = "usb-bus-host-parent",
290 .id = -1, 264 .id = -1,
291 .parent = &clk_esysclk, 265 .parent = &clk_esysclk.clk,
292 .ctrlbit = S3C2443_SCLKCON_USBHOST, 266 .ctrlbit = S3C2443_SCLKCON_USBHOST,
293 .enable = s3c2443_clkcon_enable_s, 267 .enable = s3c2443_clkcon_enable_s,
294 }, 268 },
@@ -306,7 +280,7 @@ static struct clksrc_clk clk_hsmmc_div = {
306 .clk = { 280 .clk = {
307 .name = "hsmmc-div", 281 .name = "hsmmc-div",
308 .id = -1, 282 .id = -1,
309 .parent = &clk_esysclk, 283 .parent = &clk_esysclk.clk,
310 }, 284 },
311 .reg_div = { .reg = S3C2443_CLKDIV1, .size = 2, .shift = 6 }, 285 .reg_div = { .reg = S3C2443_CLKDIV1, .size = 2, .shift = 6 },
312}; 286};
@@ -358,7 +332,7 @@ static struct clksrc_clk clk_i2s_eplldiv = {
358 .clk = { 332 .clk = {
359 .name = "i2s-eplldiv", 333 .name = "i2s-eplldiv",
360 .id = -1, 334 .id = -1,
361 .parent = &clk_esysclk, 335 .parent = &clk_esysclk.clk,
362 }, 336 },
363 .reg_div = { .reg = S3C2443_CLKDIV1, .size = 4, .shift = 12, }, 337 .reg_div = { .reg = S3C2443_CLKDIV1, .size = 4, .shift = 12, },
364}; 338};
@@ -401,7 +375,7 @@ static struct clksrc_clk clk_cam = {
401 .clk = { 375 .clk = {
402 .name = "camif-upll", /* same as 2440 name */ 376 .name = "camif-upll", /* same as 2440 name */
403 .id = -1, 377 .id = -1,
404 .parent = &clk_esysclk, 378 .parent = &clk_esysclk.clk,
405 .ctrlbit = S3C2443_SCLKCON_CAMCLK, 379 .ctrlbit = S3C2443_SCLKCON_CAMCLK,
406 .enable = s3c2443_clkcon_enable_s, 380 .enable = s3c2443_clkcon_enable_s,
407 }, 381 },
@@ -417,7 +391,7 @@ static struct clksrc_clk clk_display = {
417 .clk = { 391 .clk = {
418 .name = "display-if", 392 .name = "display-if",
419 .id = -1, 393 .id = -1,
420 .parent = &clk_esysclk, 394 .parent = &clk_esysclk.clk,
421 .ctrlbit = S3C2443_SCLKCON_DISPCLK, 395 .ctrlbit = S3C2443_SCLKCON_DISPCLK,
422 .enable = s3c2443_clkcon_enable_s, 396 .enable = s3c2443_clkcon_enable_s,
423 }, 397 },
@@ -443,7 +417,7 @@ static unsigned long s3c2443_prediv_getrate(struct clk *clk)
443static struct clk clk_prediv = { 417static struct clk clk_prediv = {
444 .name = "prediv", 418 .name = "prediv",
445 .id = -1, 419 .id = -1,
446 .parent = &clk_msysclk, 420 .parent = &clk_msysclk.clk,
447 .ops = &(struct clk_ops) { 421 .ops = &(struct clk_ops) {
448 .get_rate = s3c2443_prediv_getrate, 422 .get_rate = s3c2443_prediv_getrate,
449 }, 423 },
@@ -629,19 +603,11 @@ static struct clk init_clocks[] = {
629 603
630/* clocks to add where we need to check their parentage */ 604/* clocks to add where we need to check their parentage */
631 605
632/* s3c2443_clk_initparents
633 *
634 * Initialise the parents for the clocks that we get at start-time
635*/
636
637static int __init clk_init_set_parent(struct clk *clk, struct clk *parent)
638{
639 printk(KERN_DEBUG "clock %s: parent %s\n", clk->name, parent->name);
640 return clk_set_parent(clk, parent);
641}
642
643static struct clksrc_clk __initdata *init_list[] = { 606static struct clksrc_clk __initdata *init_list[] = {
644 &clk_epllref, /* should be first */ 607 &clk_epllref, /* should be first */
608 &clk_esysclk,
609 &clk_msysclk,
610 &clk_arm,
645 &clk_i2s_eplldiv, 611 &clk_i2s_eplldiv,
646 &clk_i2s, 612 &clk_i2s,
647 &clk_cam, 613 &clk_cam,
@@ -653,39 +619,10 @@ static struct clksrc_clk __initdata *init_list[] = {
653 619
654static void __init s3c2443_clk_initparents(void) 620static void __init s3c2443_clk_initparents(void)
655{ 621{
656 unsigned long clksrc = __raw_readl(S3C2443_CLKSRC);
657 struct clk *parent;
658 int ptr; 622 int ptr;
659 623
660 /* esysclk source */
661
662 parent = (clksrc & S3C2443_CLKSRC_ESYSCLK_EPLL) ?
663 &clk_epll : &clk_epllref.clk;
664
665 clk_init_set_parent(&clk_esysclk, parent);
666
667 /* msysclk source */
668
669 if (clksrc & S3C2443_CLKSRC_MSYSCLK_MPLL) {
670 parent = &clk_mpll;
671 } else {
672 parent = (clksrc & S3C2443_CLKSRC_EXTCLK_DIV) ?
673 &clk_mdivclk : &clk_mpllref;
674 }
675
676 clk_init_set_parent(&clk_msysclk, parent);
677
678 /* arm */
679
680 if (__raw_readl(S3C2443_CLKDIV0) & S3C2443_CLKDIV0_DVS)
681 parent = &clk_h;
682 else
683 parent = &clk_armdiv;
684
685 clk_init_set_parent(&clk_arm, parent);
686
687 for (ptr = 0; ptr < ARRAY_SIZE(init_list); ptr++) 624 for (ptr = 0; ptr < ARRAY_SIZE(init_list); ptr++)
688 s3c_set_clksrc(init_list[ptr], false); 625 s3c_set_clksrc(init_list[ptr], true);
689} 626}
690 627
691/* armdiv divisor table */ 628/* armdiv divisor table */
@@ -720,6 +657,9 @@ static inline unsigned long s3c2443_get_hdiv(unsigned long clkcon0)
720static struct clksrc_clk *clksrcs[] __initdata = { 657static struct clksrc_clk *clksrcs[] __initdata = {
721 &clk_usb_bus_host, 658 &clk_usb_bus_host,
722 &clk_epllref, 659 &clk_epllref,
660 &clk_esysclk,
661 &clk_msysclk,
662 &clk_arm,
723 &clk_uart, 663 &clk_uart,
724 &clk_display, 664 &clk_display,
725 &clk_cam, 665 &clk_cam,
@@ -733,12 +673,9 @@ static struct clk *clks[] __initdata = {
733 &clk_ext, 673 &clk_ext,
734 &clk_epll, 674 &clk_epll,
735 &clk_usb_bus, 675 &clk_usb_bus,
736 &clk_esysclk,
737 &clk_mpllref, 676 &clk_mpllref,
738 &clk_msysclk,
739 &clk_hsmmc, 677 &clk_hsmmc,
740 &clk_armdiv, 678 &clk_armdiv,
741 &clk_arm,
742 &clk_prediv, 679 &clk_prediv,
743}; 680};
744 681
@@ -758,7 +695,7 @@ void __init_or_cpufreq s3c2443_setup_clocks(void)
758 clk_put(xtal_clk); 695 clk_put(xtal_clk);
759 696
760 pll = s3c2443_get_mpll(mpllcon, xtal); 697 pll = s3c2443_get_mpll(mpllcon, xtal);
761 clk_msysclk.rate = pll; 698 clk_msysclk.clk.rate = pll;
762 699
763 fclk = pll / s3c2443_fclk_div(clkdiv0); 700 fclk = pll / s3c2443_fclk_div(clkdiv0);
764 hclk = s3c2443_prediv_getrate(&clk_prediv); 701 hclk = s3c2443_prediv_getrate(&clk_prediv);