aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/mach-s3c2410/include/mach/regs-s3c2443-clock.h29
-rw-r--r--arch/arm/mach-s3c2443/Kconfig1
-rw-r--r--arch/arm/mach-s3c2443/clock.c513
3 files changed, 128 insertions, 415 deletions
diff --git a/arch/arm/mach-s3c2410/include/mach/regs-s3c2443-clock.h b/arch/arm/mach-s3c2410/include/mach/regs-s3c2443-clock.h
index 6026d091a2fe..64217ca796b0 100644
--- a/arch/arm/mach-s3c2410/include/mach/regs-s3c2443-clock.h
+++ b/arch/arm/mach-s3c2410/include/mach/regs-s3c2443-clock.h
@@ -42,12 +42,6 @@
42 42
43#define S3C2443_PLLCON_OFF (1<<24) 43#define S3C2443_PLLCON_OFF (1<<24)
44 44
45#define S3C2443_CLKSRC_I2S_EXT (1<<14)
46#define S3C2443_CLKSRC_I2S_EPLLDIV (0<<14)
47#define S3C2443_CLKSRC_I2S_EPLLREF (2<<14)
48#define S3C2443_CLKSRC_I2S_EPLLREF3 (3<<14)
49#define S3C2443_CLKSRC_I2S_MASK (3<<14)
50
51#define S3C2443_CLKSRC_EPLLREF_XTAL (2<<7) 45#define S3C2443_CLKSRC_EPLLREF_XTAL (2<<7)
52#define S3C2443_CLKSRC_EPLLREF_EXTCLK (3<<7) 46#define S3C2443_CLKSRC_EPLLREF_EXTCLK (3<<7)
53#define S3C2443_CLKSRC_EPLLREF_MPLLREF (0<<7) 47#define S3C2443_CLKSRC_EPLLREF_MPLLREF (0<<7)
@@ -81,28 +75,7 @@
81#define S3C2443_CLKDIV0_ARMDIV_12 (13<<9) 75#define S3C2443_CLKDIV0_ARMDIV_12 (13<<9)
82#define S3C2443_CLKDIV0_ARMDIV_16 (15<<9) 76#define S3C2443_CLKDIV0_ARMDIV_16 (15<<9)
83 77
84/* S3C2443_CLKDIV1 */ 78/* S3C2443_CLKDIV1 removed, only used in clock.c code */
85
86#define S3C2443_CLKDIV1_CAMDIV_MASK (15<<26)
87#define S3C2443_CLKDIV1_CAMDIV_SHIFT (26)
88
89#define S3C2443_CLKDIV1_HSSPIDIV_MASK (3<<24)
90#define S3C2443_CLKDIV1_HSSPIDIV_SHIFT (24)
91
92#define S3C2443_CLKDIV1_DISPDIV_MASK (0xff<<16)
93#define S3C2443_CLKDIV1_DISPDIV_SHIFT (16)
94
95#define S3C2443_CLKDIV1_I2SDIV_MASK (15<<12)
96#define S3C2443_CLKDIV1_I2SDIV_SHIFT (12)
97
98#define S3C2443_CLKDIV1_UARTDIV_MASK (15<<8)
99#define S3C2443_CLKDIV1_UARTDIV_SHIFT (8)
100
101#define S3C2443_CLKDIV1_HSMMCDIV_MASK (3<<6)
102#define S3C2443_CLKDIV1_HSMMCDIV_SHIFT (6)
103
104#define S3C2443_CLKDIV1_USBHOSTDIV_MASK (3<<4)
105#define S3C2443_CLKDIV1_USBHOSTDIV_SHIFT (4)
106 79
107#define S3C2443_CLKCON_NAND 80#define S3C2443_CLKCON_NAND
108 81
diff --git a/arch/arm/mach-s3c2443/Kconfig b/arch/arm/mach-s3c2443/Kconfig
index 4314c4424909..698140af247c 100644
--- a/arch/arm/mach-s3c2443/Kconfig
+++ b/arch/arm/mach-s3c2443/Kconfig
@@ -7,6 +7,7 @@ config CPU_S3C2443
7 depends on ARCH_S3C2410 7 depends on ARCH_S3C2410
8 select S3C2443_DMA if S3C2410_DMA 8 select S3C2443_DMA if S3C2410_DMA
9 select CPU_LLSERIAL_S3C2440 9 select CPU_LLSERIAL_S3C2440
10 select SAMSUNG_CLKSRC
10 help 11 help
11 Support for the S3C2443 SoC from the S3C24XX line 12 Support for the S3C2443 SoC from the S3C24XX line
12 13
diff --git a/arch/arm/mach-s3c2443/clock.c b/arch/arm/mach-s3c2443/clock.c
index 5d061ea0c513..f89e71f50345 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 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
@@ -42,6 +42,7 @@
42 42
43#include <plat/s3c2443.h> 43#include <plat/s3c2443.h>
44#include <plat/clock.h> 44#include <plat/clock.h>
45#include <plat/clock-clksrc.h>
45#include <plat/cpu.h> 46#include <plat/cpu.h>
46 47
47/* We currently have to assume that the system is running 48/* We currently have to assume that the system is running
@@ -82,45 +83,7 @@ static int s3c2443_clkcon_enable_s(struct clk *clk, int enable)
82 return s3c2443_gate(S3C2443_SCLKCON, clk, enable); 83 return s3c2443_gate(S3C2443_SCLKCON, clk, enable);
83} 84}
84 85
85static unsigned long s3c2443_roundrate_clksrc(struct clk *clk, 86/* s3c2443_roundate_clksrc is close enough to s3c_roundate_clksrc */
86 unsigned long rate,
87 unsigned int max)
88{
89 unsigned long parent_rate = clk_get_rate(clk->parent);
90 int div;
91
92 if (rate > parent_rate)
93 return parent_rate;
94
95 /* note, we remove the +/- 1 calculations as they cancel out */
96
97 div = (rate / parent_rate);
98
99 if (div < 1)
100 div = 1;
101 else if (div > max)
102 div = max;
103
104 return parent_rate / div;
105}
106
107static unsigned long s3c2443_roundrate_clksrc4(struct clk *clk,
108 unsigned long rate)
109{
110 return s3c2443_roundrate_clksrc(clk, rate, 4);
111}
112
113static unsigned long s3c2443_roundrate_clksrc16(struct clk *clk,
114 unsigned long rate)
115{
116 return s3c2443_roundrate_clksrc(clk, rate, 16);
117}
118
119static unsigned long s3c2443_roundrate_clksrc256(struct clk *clk,
120 unsigned long rate)
121{
122 return s3c2443_roundrate_clksrc(clk, rate, 256);
123}
124 87
125/* clock selections */ 88/* clock selections */
126 89
@@ -143,31 +106,23 @@ static struct clk clk_i2s_ext = {
143 .id = -1, 106 .id = -1,
144}; 107};
145 108
146static int s3c2443_setparent_epllref(struct clk *clk, struct clk *parent) 109static struct clk *clk_epllref_sources[] = {
147{ 110 [0] = &clk_mpllref,
148 unsigned long clksrc = __raw_readl(S3C2443_CLKSRC); 111 [1] = &clk_mpllref,
149 112 [2] = &clk_xtal,
150 clksrc &= ~S3C2443_CLKSRC_EPLLREF_MASK; 113 [3] = &clk_ext,
151 114};
152 if (parent == &clk_xtal)
153 clksrc |= S3C2443_CLKSRC_EPLLREF_XTAL;
154 else if (parent == &clk_ext)
155 clksrc |= S3C2443_CLKSRC_EPLLREF_EXTCLK;
156 else if (parent != &clk_mpllref)
157 return -EINVAL;
158
159 __raw_writel(clksrc, S3C2443_CLKSRC);
160 clk->parent = parent;
161
162 return 0;
163}
164 115
165static struct clk clk_epllref = { 116static struct clksrc_clk clk_epllref = {
166 .name = "epllref", 117 .clk = {
167 .id = -1, 118 .name = "epllref",
168 .ops = &(struct clk_ops) { 119 .id = -1,
169 .set_parent = s3c2443_setparent_epllref, 120 },
121 .sources = &(struct clksrc_sources) {
122 .sources = clk_epllref_sources,
123 .nr_sources = ARRAY_SIZE(clk_epllref_sources),
170 }, 124 },
125 .reg_src = { .reg = S3C2443_CLKSRC, .size = 2, .shift = 7 },
171}; 126};
172 127
173static unsigned long s3c2443_getrate_mdivclk(struct clk *clk) 128static unsigned long s3c2443_getrate_mdivclk(struct clk *clk)
@@ -273,7 +228,7 @@ static int s3c2443_setparent_esysclk(struct clk *clk, struct clk *parent)
273 228
274 if (parent == &clk_epll) 229 if (parent == &clk_epll)
275 clksrc |= S3C2443_CLKSRC_ESYSCLK_EPLL; 230 clksrc |= S3C2443_CLKSRC_ESYSCLK_EPLL;
276 else if (parent == &clk_epllref) 231 else if (parent == &clk_epllref.clk)
277 clksrc &= ~S3C2443_CLKSRC_ESYSCLK_EPLL; 232 clksrc &= ~S3C2443_CLKSRC_ESYSCLK_EPLL;
278 else 233 else
279 return -EINVAL; 234 return -EINVAL;
@@ -298,87 +253,30 @@ static struct clk clk_esysclk = {
298 * UART baud-rate clock sourced from esysclk via a divisor 253 * UART baud-rate clock sourced from esysclk via a divisor
299*/ 254*/
300 255
301static unsigned long s3c2443_getrate_uart(struct clk *clk) 256static struct clksrc_clk clk_uart = {
302{ 257 .clk = {
303 unsigned long parent_rate = clk_get_rate(clk->parent); 258 .name = "uartclk",
304 unsigned long div = __raw_readl(S3C2443_CLKDIV1); 259 .id = -1,
305 260 .parent = &clk_esysclk,
306 div &= S3C2443_CLKDIV1_UARTDIV_MASK;
307 div >>= S3C2443_CLKDIV1_UARTDIV_SHIFT;
308
309 return parent_rate / (div + 1);
310}
311
312
313static int s3c2443_setrate_uart(struct clk *clk, unsigned long rate)
314{
315 unsigned long parent_rate = clk_get_rate(clk->parent);
316 unsigned long clkdivn = __raw_readl(S3C2443_CLKDIV1);
317
318 rate = s3c2443_roundrate_clksrc16(clk, rate);
319 rate = parent_rate / rate;
320
321 clkdivn &= ~S3C2443_CLKDIV1_UARTDIV_MASK;
322 clkdivn |= (rate - 1) << S3C2443_CLKDIV1_UARTDIV_SHIFT;
323
324 __raw_writel(clkdivn, S3C2443_CLKDIV1);
325 return 0;
326}
327
328static struct clk clk_uart = {
329 .name = "uartclk",
330 .id = -1,
331 .parent = &clk_esysclk,
332 .ops = &(struct clk_ops) {
333 .get_rate = s3c2443_getrate_uart,
334 .set_rate = s3c2443_setrate_uart,
335 .round_rate = s3c2443_roundrate_clksrc16,
336 }, 261 },
262 .reg_div = { .reg = S3C2443_CLKDIV1, .size = 4, .shift = 8 },
337}; 263};
338 264
265
339/* hsspi 266/* hsspi
340 * 267 *
341 * high-speed spi clock, sourced from esysclk 268 * high-speed spi clock, sourced from esysclk
342*/ 269*/
343 270
344static unsigned long s3c2443_getrate_hsspi(struct clk *clk) 271static struct clksrc_clk clk_hsspi = {
345{ 272 .clk = {
346 unsigned long parent_rate = clk_get_rate(clk->parent); 273 .name = "hsspi",
347 unsigned long div = __raw_readl(S3C2443_CLKDIV1); 274 .id = -1,
348 275 .parent = &clk_esysclk,
349 div &= S3C2443_CLKDIV1_HSSPIDIV_MASK; 276 .ctrlbit = S3C2443_SCLKCON_HSSPICLK,
350 div >>= S3C2443_CLKDIV1_HSSPIDIV_SHIFT; 277 .enable = s3c2443_clkcon_enable_s,
351
352 return parent_rate / (div + 1);
353}
354
355
356static int s3c2443_setrate_hsspi(struct clk *clk, unsigned long rate)
357{
358 unsigned long parent_rate = clk_get_rate(clk->parent);
359 unsigned long clkdivn = __raw_readl(S3C2443_CLKDIV1);
360
361 rate = s3c2443_roundrate_clksrc4(clk, rate);
362 rate = parent_rate / rate;
363
364 clkdivn &= ~S3C2443_CLKDIV1_HSSPIDIV_MASK;
365 clkdivn |= (rate - 1) << S3C2443_CLKDIV1_HSSPIDIV_SHIFT;
366
367 __raw_writel(clkdivn, S3C2443_CLKDIV1);
368 return 0;
369}
370
371static struct clk clk_hsspi = {
372 .name = "hsspi",
373 .id = -1,
374 .parent = &clk_esysclk,
375 .ctrlbit = S3C2443_SCLKCON_HSSPICLK,
376 .enable = s3c2443_clkcon_enable_s,
377 .ops = &(struct clk_ops) {
378 .get_rate = s3c2443_getrate_hsspi,
379 .set_rate = s3c2443_setrate_hsspi,
380 .round_rate = s3c2443_roundrate_clksrc4,
381 }, 278 },
279 .reg_div = { .reg = S3C2443_CLKDIV1, .size = 2, .shift = 4 },
382}; 280};
383 281
384/* usbhost 282/* usbhost
@@ -386,43 +284,15 @@ static struct clk clk_hsspi = {
386 * usb host bus-clock, usually 48MHz to provide USB bus clock timing 284 * usb host bus-clock, usually 48MHz to provide USB bus clock timing
387*/ 285*/
388 286
389static unsigned long s3c2443_getrate_usbhost(struct clk *clk) 287static struct clksrc_clk clk_usb_bus_host = {
390{ 288 .clk = {
391 unsigned long parent_rate = clk_get_rate(clk->parent); 289 .name = "usb-bus-host-parent",
392 unsigned long div = __raw_readl(S3C2443_CLKDIV1); 290 .id = -1,
393 291 .parent = &clk_esysclk,
394 div &= S3C2443_CLKDIV1_USBHOSTDIV_MASK; 292 .ctrlbit = S3C2443_SCLKCON_USBHOST,
395 div >>= S3C2443_CLKDIV1_USBHOSTDIV_SHIFT; 293 .enable = s3c2443_clkcon_enable_s,
396
397 return parent_rate / (div + 1);
398}
399
400static int s3c2443_setrate_usbhost(struct clk *clk, unsigned long rate)
401{
402 unsigned long parent_rate = clk_get_rate(clk->parent);
403 unsigned long clkdivn = __raw_readl(S3C2443_CLKDIV1);
404
405 rate = s3c2443_roundrate_clksrc4(clk, rate);
406 rate = parent_rate / rate;
407
408 clkdivn &= ~S3C2443_CLKDIV1_USBHOSTDIV_MASK;
409 clkdivn |= (rate - 1) << S3C2443_CLKDIV1_USBHOSTDIV_SHIFT;
410
411 __raw_writel(clkdivn, S3C2443_CLKDIV1);
412 return 0;
413}
414
415static struct clk clk_usb_bus_host = {
416 .name = "usb-bus-host-parent",
417 .id = -1,
418 .parent = &clk_esysclk,
419 .ctrlbit = S3C2443_SCLKCON_USBHOST,
420 .enable = s3c2443_clkcon_enable_s,
421 .ops = &(struct clk_ops) {
422 .get_rate = s3c2443_getrate_usbhost,
423 .set_rate = s3c2443_setrate_usbhost,
424 .round_rate = s3c2443_roundrate_clksrc4,
425 }, 294 },
295 .reg_div = { .reg = S3C2443_CLKDIV1, .size = 2, .shift = 4 },
426}; 296};
427 297
428/* clk_hsmcc_div 298/* clk_hsmcc_div
@@ -432,41 +302,13 @@ static struct clk clk_usb_bus_host = {
432 * be fed to the hsmmc block 302 * be fed to the hsmmc block
433*/ 303*/
434 304
435static unsigned long s3c2443_getrate_hsmmc_div(struct clk *clk) 305static struct clksrc_clk clk_hsmmc_div = {
436{ 306 .clk = {
437 unsigned long parent_rate = clk_get_rate(clk->parent); 307 .name = "hsmmc-div",
438 unsigned long div = __raw_readl(S3C2443_CLKDIV1); 308 .id = -1,
439 309 .parent = &clk_esysclk,
440 div &= S3C2443_CLKDIV1_HSMMCDIV_MASK;
441 div >>= S3C2443_CLKDIV1_HSMMCDIV_SHIFT;
442
443 return parent_rate / (div + 1);
444}
445
446static int s3c2443_setrate_hsmmc_div(struct clk *clk, unsigned long rate)
447{
448 unsigned long parent_rate = clk_get_rate(clk->parent);
449 unsigned long clkdivn = __raw_readl(S3C2443_CLKDIV1);
450
451 rate = s3c2443_roundrate_clksrc4(clk, rate);
452 rate = parent_rate / rate;
453
454 clkdivn &= ~S3C2443_CLKDIV1_HSMMCDIV_MASK;
455 clkdivn |= (rate - 1) << S3C2443_CLKDIV1_HSMMCDIV_SHIFT;
456
457 __raw_writel(clkdivn, S3C2443_CLKDIV1);
458 return 0;
459}
460
461static struct clk clk_hsmmc_div = {
462 .name = "hsmmc-div",
463 .id = -1,
464 .parent = &clk_esysclk,
465 .ops = &(struct clk_ops) {
466 .get_rate = s3c2443_getrate_hsmmc_div,
467 .set_rate = s3c2443_setrate_hsmmc_div,
468 .round_rate = s3c2443_roundrate_clksrc4,
469 }, 310 },
311 .reg_div = { .reg = S3C2443_CLKDIV1, .size = 2, .shift = 6 },
470}; 312};
471 313
472static int s3c2443_setparent_hsmmc(struct clk *clk, struct clk *parent) 314static int s3c2443_setparent_hsmmc(struct clk *clk, struct clk *parent)
@@ -499,7 +341,7 @@ static int s3c2443_enable_hsmmc(struct clk *clk, int enable)
499static struct clk clk_hsmmc = { 341static struct clk clk_hsmmc = {
500 .name = "hsmmc-if", 342 .name = "hsmmc-if",
501 .id = -1, 343 .id = -1,
502 .parent = &clk_hsmmc_div, 344 .parent = &clk_hsmmc_div.clk,
503 .enable = s3c2443_enable_hsmmc, 345 .enable = s3c2443_enable_hsmmc,
504 .ops = &(struct clk_ops) { 346 .ops = &(struct clk_ops) {
505 .set_parent = s3c2443_setparent_hsmmc, 347 .set_parent = s3c2443_setparent_hsmmc,
@@ -508,79 +350,46 @@ static struct clk clk_hsmmc = {
508 350
509/* i2s_eplldiv 351/* i2s_eplldiv
510 * 352 *
511 * this clock is the output from the i2s divisor of esysclk 353 * This clock is the output from the I2S divisor of ESYSCLK, and is seperate
354 * from the mux that comes after it (cannot merge into one single clock)
512*/ 355*/
513 356
514static unsigned long s3c2443_getrate_i2s_eplldiv(struct clk *clk) 357static struct clksrc_clk clk_i2s_eplldiv = {
515{ 358 .clk = {
516 unsigned long parent_rate = clk_get_rate(clk->parent); 359 .name = "i2s-eplldiv",
517 unsigned long div = __raw_readl(S3C2443_CLKDIV1); 360 .id = -1,
518 361 .parent = &clk_esysclk,
519 div &= S3C2443_CLKDIV1_I2SDIV_MASK;
520 div >>= S3C2443_CLKDIV1_I2SDIV_SHIFT;
521
522 return parent_rate / (div + 1);
523}
524
525static int s3c2443_setrate_i2s_eplldiv(struct clk *clk, unsigned long rate)
526{
527 unsigned long parent_rate = clk_get_rate(clk->parent);
528 unsigned long clkdivn = __raw_readl(S3C2443_CLKDIV1);
529
530 rate = s3c2443_roundrate_clksrc16(clk, rate);
531 rate = parent_rate / rate;
532
533 clkdivn &= ~S3C2443_CLKDIV1_I2SDIV_MASK;
534 clkdivn |= (rate - 1) << S3C2443_CLKDIV1_I2SDIV_SHIFT;
535
536 __raw_writel(clkdivn, S3C2443_CLKDIV1);
537 return 0;
538}
539
540static struct clk clk_i2s_eplldiv = {
541 .name = "i2s-eplldiv",
542 .id = -1,
543 .parent = &clk_esysclk,
544 .ops = &(struct clk_ops) {
545 .get_rate = s3c2443_getrate_i2s_eplldiv,
546 .set_rate = s3c2443_setrate_i2s_eplldiv,
547 .round_rate = s3c2443_roundrate_clksrc16,
548 }, 362 },
363 .reg_div = { .reg = S3C2443_CLKDIV1, .size = 4, .shift = 12, },
549}; 364};
550 365
551/* i2s-ref 366/* i2s-ref
552 * 367 *
553 * i2s bus reference clock, selectable from external, esysclk or epllref 368 * i2s bus reference clock, selectable from external, esysclk or epllref
369 *
370 * Note, this used to be two clocks, but was compressed into one.
554*/ 371*/
555 372
556static int s3c2443_setparent_i2s(struct clk *clk, struct clk *parent) 373struct clk *clk_i2s_srclist[] = {
557{ 374 [0] = &clk_i2s_eplldiv.clk,
558 unsigned long clksrc = __raw_readl(S3C2443_CLKSRC); 375 [1] = &clk_i2s_ext,
559 376 [2] = &clk_epllref.clk,
560 clksrc &= ~S3C2443_CLKSRC_I2S_MASK; 377 [3] = &clk_epllref.clk,
561 378};
562 if (parent == &clk_epllref)
563 clksrc |= S3C2443_CLKSRC_I2S_EPLLREF;
564 else if (parent == &clk_i2s_ext)
565 clksrc |= S3C2443_CLKSRC_I2S_EXT;
566 else if (parent != &clk_i2s_eplldiv)
567 return -EINVAL;
568
569 clk->parent = parent;
570 __raw_writel(clksrc, S3C2443_CLKSRC);
571 379
572 return 0; 380static struct clksrc_clk clk_i2s = {
573} 381 .clk = {
382 .name = "i2s-if",
383 .id = -1,
384 .ctrlbit = S3C2443_SCLKCON_I2SCLK,
385 .enable = s3c2443_clkcon_enable_s,
574 386
575static struct clk clk_i2s = {
576 .name = "i2s-if",
577 .id = -1,
578 .parent = &clk_i2s_eplldiv,
579 .ctrlbit = S3C2443_SCLKCON_I2SCLK,
580 .enable = s3c2443_clkcon_enable_s,
581 .ops = &(struct clk_ops) {
582 .set_parent = s3c2443_setparent_i2s,
583 }, 387 },
388 .sources = &(struct clksrc_sources) {
389 .sources = clk_i2s_srclist,
390 .nr_sources = ARRAY_SIZE(clk_i2s_srclist),
391 },
392 .reg_src = { .reg = S3C2443_CLKSRC, .size = 2, .shift = 14 },
584}; 393};
585 394
586/* cam-if 395/* cam-if
@@ -588,43 +397,15 @@ static struct clk clk_i2s = {
588 * camera interface bus-clock, divided down from esysclk 397 * camera interface bus-clock, divided down from esysclk
589*/ 398*/
590 399
591static unsigned long s3c2443_getrate_cam(struct clk *clk) 400static struct clksrc_clk clk_cam = {
592{ 401 .clk = {
593 unsigned long parent_rate = clk_get_rate(clk->parent); 402 .name = "camif-upll", /* same as 2440 name */
594 unsigned long div = __raw_readl(S3C2443_CLKDIV1); 403 .id = -1,
595 404 .parent = &clk_esysclk,
596 div &= S3C2443_CLKDIV1_CAMDIV_MASK; 405 .ctrlbit = S3C2443_SCLKCON_CAMCLK,
597 div >>= S3C2443_CLKDIV1_CAMDIV_SHIFT; 406 .enable = s3c2443_clkcon_enable_s,
598
599 return parent_rate / (div + 1);
600}
601
602static int s3c2443_setrate_cam(struct clk *clk, unsigned long rate)
603{
604 unsigned long parent_rate = clk_get_rate(clk->parent);
605 unsigned long clkdiv1 = __raw_readl(S3C2443_CLKDIV1);
606
607 rate = s3c2443_roundrate_clksrc16(clk, rate);
608 rate = parent_rate / rate;
609
610 clkdiv1 &= ~S3C2443_CLKDIV1_CAMDIV_MASK;
611 clkdiv1 |= (rate - 1) << S3C2443_CLKDIV1_CAMDIV_SHIFT;
612
613 __raw_writel(clkdiv1, S3C2443_CLKDIV1);
614 return 0;
615}
616
617static struct clk clk_cam = {
618 .name = "camif-upll", /* same as 2440 name */
619 .id = -1,
620 .parent = &clk_esysclk,
621 .ctrlbit = S3C2443_SCLKCON_CAMCLK,
622 .enable = s3c2443_clkcon_enable_s,
623 .ops = &(struct clk_ops) {
624 .get_rate = s3c2443_getrate_cam,
625 .set_rate = s3c2443_setrate_cam,
626 .round_rate = s3c2443_roundrate_clksrc16,
627 }, 407 },
408 .reg_div = { .reg = S3C2443_CLKDIV1, .size = 4, .shift = 26 },
628}; 409};
629 410
630/* display-if 411/* display-if
@@ -632,43 +413,15 @@ static struct clk clk_cam = {
632 * display interface clock, divided from esysclk 413 * display interface clock, divided from esysclk
633*/ 414*/
634 415
635static unsigned long s3c2443_getrate_display(struct clk *clk) 416static struct clksrc_clk clk_display = {
636{ 417 .clk = {
637 unsigned long parent_rate = clk_get_rate(clk->parent); 418 .name = "display-if",
638 unsigned long div = __raw_readl(S3C2443_CLKDIV1); 419 .id = -1,
639 420 .parent = &clk_esysclk,
640 div &= S3C2443_CLKDIV1_DISPDIV_MASK; 421 .ctrlbit = S3C2443_SCLKCON_DISPCLK,
641 div >>= S3C2443_CLKDIV1_DISPDIV_SHIFT; 422 .enable = s3c2443_clkcon_enable_s,
642
643 return parent_rate / (div + 1);
644}
645
646static int s3c2443_setrate_display(struct clk *clk, unsigned long rate)
647{
648 unsigned long parent_rate = clk_get_rate(clk->parent);
649 unsigned long clkdivn = __raw_readl(S3C2443_CLKDIV1);
650
651 rate = s3c2443_roundrate_clksrc256(clk, rate);
652 rate = parent_rate / rate;
653
654 clkdivn &= ~S3C2443_CLKDIV1_UARTDIV_MASK;
655 clkdivn |= (rate - 1) << S3C2443_CLKDIV1_UARTDIV_SHIFT;
656
657 __raw_writel(clkdivn, S3C2443_CLKDIV1);
658 return 0;
659}
660
661static struct clk clk_display = {
662 .name = "display-if",
663 .id = -1,
664 .parent = &clk_esysclk,
665 .ctrlbit = S3C2443_SCLKCON_DISPCLK,
666 .enable = s3c2443_clkcon_enable_s,
667 .ops = &(struct clk_ops) {
668 .get_rate = s3c2443_getrate_display,
669 .set_rate = s3c2443_setrate_display,
670 .round_rate = s3c2443_roundrate_clksrc256,
671 }, 423 },
424 .reg_div = { .reg = S3C2443_CLKDIV1, .size = 8, .shift = 16 },
672}; 425};
673 426
674/* prediv 427/* prediv
@@ -865,7 +618,7 @@ static struct clk init_clocks[] = {
865 }, { 618 }, {
866 .name = "usb-bus-host", 619 .name = "usb-bus-host",
867 .id = -1, 620 .id = -1,
868 .parent = &clk_usb_bus_host, 621 .parent = &clk_usb_bus_host.clk,
869 }, { 622 }, {
870 .name = "ac97", 623 .name = "ac97",
871 .id = -1, 624 .id = -1,
@@ -887,50 +640,27 @@ static int __init clk_init_set_parent(struct clk *clk, struct clk *parent)
887 return clk_set_parent(clk, parent); 640 return clk_set_parent(clk, parent);
888} 641}
889 642
643static struct clksrc_clk __initdata *init_list[] = {
644 &clk_epllref, /* should be first */
645 &clk_i2s_eplldiv,
646 &clk_i2s,
647 &clk_cam,
648 &clk_uart,
649 &clk_display,
650 &clk_hsmmc_div,
651 &clk_usb_bus_host,
652};
653
890static void __init s3c2443_clk_initparents(void) 654static void __init s3c2443_clk_initparents(void)
891{ 655{
892 unsigned long clksrc = __raw_readl(S3C2443_CLKSRC); 656 unsigned long clksrc = __raw_readl(S3C2443_CLKSRC);
893 struct clk *parent; 657 struct clk *parent;
894 658 int ptr;
895 switch (clksrc & S3C2443_CLKSRC_EPLLREF_MASK) {
896 case S3C2443_CLKSRC_EPLLREF_EXTCLK:
897 parent = &clk_ext;
898 break;
899
900 case S3C2443_CLKSRC_EPLLREF_XTAL:
901 default:
902 parent = &clk_xtal;
903 break;
904
905 case S3C2443_CLKSRC_EPLLREF_MPLLREF:
906 case S3C2443_CLKSRC_EPLLREF_MPLLREF2:
907 parent = &clk_mpllref;
908 break;
909 }
910
911 clk_init_set_parent(&clk_epllref, parent);
912
913 switch (clksrc & S3C2443_CLKSRC_I2S_MASK) {
914 case S3C2443_CLKSRC_I2S_EXT:
915 parent = &clk_i2s_ext;
916 break;
917
918 case S3C2443_CLKSRC_I2S_EPLLDIV:
919 default:
920 parent = &clk_i2s_eplldiv;
921 break;
922
923 case S3C2443_CLKSRC_I2S_EPLLREF:
924 case S3C2443_CLKSRC_I2S_EPLLREF3:
925 parent = &clk_epllref;
926 }
927
928 clk_init_set_parent(&clk_i2s, &clk_epllref);
929 659
930 /* esysclk source */ 660 /* esysclk source */
931 661
932 parent = (clksrc & S3C2443_CLKSRC_ESYSCLK_EPLL) ? 662 parent = (clksrc & S3C2443_CLKSRC_ESYSCLK_EPLL) ?
933 &clk_epll : &clk_epllref; 663 &clk_epll : &clk_epllref.clk;
934 664
935 clk_init_set_parent(&clk_esysclk, parent); 665 clk_init_set_parent(&clk_esysclk, parent);
936 666
@@ -953,6 +683,9 @@ static void __init s3c2443_clk_initparents(void)
953 parent = &clk_armdiv; 683 parent = &clk_armdiv;
954 684
955 clk_init_set_parent(&clk_arm, parent); 685 clk_init_set_parent(&clk_arm, parent);
686
687 for (ptr = 0; ptr < ARRAY_SIZE(init_list); ptr++)
688 s3c_set_clksrc(init_list[ptr], false);
956} 689}
957 690
958/* armdiv divisor table */ 691/* armdiv divisor table */
@@ -984,15 +717,9 @@ static inline unsigned long s3c2443_get_hdiv(unsigned long clkcon0)
984 717
985/* clocks to add straight away */ 718/* clocks to add straight away */
986 719
987static struct clk *clks[] __initdata = { 720static struct clksrc_clk *clksrcs[] __initdata = {
988 &clk_ext,
989 &clk_epll,
990 &clk_usb_bus_host, 721 &clk_usb_bus_host,
991 &clk_usb_bus,
992 &clk_esysclk,
993 &clk_epllref, 722 &clk_epllref,
994 &clk_mpllref,
995 &clk_msysclk,
996 &clk_uart, 723 &clk_uart,
997 &clk_display, 724 &clk_display,
998 &clk_cam, 725 &clk_cam,
@@ -1000,6 +727,15 @@ static struct clk *clks[] __initdata = {
1000 &clk_i2s, 727 &clk_i2s,
1001 &clk_hsspi, 728 &clk_hsspi,
1002 &clk_hsmmc_div, 729 &clk_hsmmc_div,
730};
731
732static struct clk *clks[] __initdata = {
733 &clk_ext,
734 &clk_epll,
735 &clk_usb_bus,
736 &clk_esysclk,
737 &clk_mpllref,
738 &clk_msysclk,
1003 &clk_hsmmc, 739 &clk_hsmmc,
1004 &clk_armdiv, 740 &clk_armdiv,
1005 &clk_arm, 741 &clk_arm,
@@ -1064,15 +800,18 @@ void __init s3c2443_init_clocks(int xtal)
1064 } 800 }
1065 } 801 }
1066 802
803 for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++)
804 s3c_register_clksrc(clksrcs[ptr], 1);
805
1067 clk_epll.rate = s3c2443_get_epll(epllcon, xtal); 806 clk_epll.rate = s3c2443_get_epll(epllcon, xtal);
1068 clk_epll.parent = &clk_epllref; 807 clk_epll.parent = &clk_epllref.clk;
1069 clk_usb_bus.parent = &clk_usb_bus_host; 808 clk_usb_bus.parent = &clk_usb_bus_host.clk;
1070 809
1071 /* ensure usb bus clock is within correct rate of 48MHz */ 810 /* ensure usb bus clock is within correct rate of 48MHz */
1072 811
1073 if (clk_get_rate(&clk_usb_bus_host) != (48 * 1000 * 1000)) { 812 if (clk_get_rate(&clk_usb_bus_host.clk) != (48 * 1000 * 1000)) {
1074 printk(KERN_INFO "Warning: USB host bus not at 48MHz\n"); 813 printk(KERN_INFO "Warning: USB host bus not at 48MHz\n");
1075 clk_set_rate(&clk_usb_bus_host, 48*1000*1000); 814 clk_set_rate(&clk_usb_bus_host.clk, 48*1000*1000);
1076 } 815 }
1077 816
1078 printk("S3C2443: epll %s %ld.%03ld MHz, usb-bus %ld.%03ld MHz\n", 817 printk("S3C2443: epll %s %ld.%03ld MHz, usb-bus %ld.%03ld MHz\n",