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