linux/arch/arm/mach-s5p64x0/clock-s5p6450.c
<<
>>
Prefs
   1/* linux/arch/arm/mach-s5p64x0/clock-s5p6450.c
   2 *
   3 * Copyright (c) 2010 Samsung Electronics Co., Ltd.
   4 *              http://www.samsung.com
   5 *
   6 * S5P6450 - 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/device.h>
  21#include <linux/io.h>
  22
  23#include <mach/hardware.h>
  24#include <mach/map.h>
  25#include <mach/regs-clock.h>
  26
  27#include <plat/cpu-freq.h>
  28#include <plat/clock.h>
  29#include <plat/cpu.h>
  30#include <plat/pll.h>
  31#include <plat/s5p-clock.h>
  32#include <plat/clock-clksrc.h>
  33
  34#include "clock.h"
  35#include "common.h"
  36
  37static struct clksrc_clk clk_mout_dpll = {
  38        .clk    = {
  39                .name           = "mout_dpll",
  40        },
  41        .sources        = &clk_src_dpll,
  42        .reg_src        = { .reg = S5P64X0_CLK_SRC0, .shift = 5, .size = 1 },
  43};
  44
  45static u32 epll_div[][5] = {
  46        { 133000000,    27307,  55, 2, 2 },
  47        { 100000000,    43691,  41, 2, 2 },
  48        { 480000000,    0,      80, 2, 0 },
  49};
  50
  51static int s5p6450_epll_set_rate(struct clk *clk, unsigned long rate)
  52{
  53        unsigned int epll_con, epll_con_k;
  54        unsigned int i;
  55
  56        if (clk->rate == rate)  /* Return if nothing changed */
  57                return 0;
  58
  59        epll_con = __raw_readl(S5P64X0_EPLL_CON);
  60        epll_con_k = __raw_readl(S5P64X0_EPLL_CON_K);
  61
  62        epll_con_k &= ~(PLL90XX_KDIV_MASK);
  63        epll_con &= ~(PLL90XX_MDIV_MASK | PLL90XX_PDIV_MASK | PLL90XX_SDIV_MASK);
  64
  65        for (i = 0; i < ARRAY_SIZE(epll_div); i++) {
  66                 if (epll_div[i][0] == rate) {
  67                        epll_con_k |= (epll_div[i][1] << PLL90XX_KDIV_SHIFT);
  68                        epll_con |= (epll_div[i][2] << PLL90XX_MDIV_SHIFT) |
  69                                    (epll_div[i][3] << PLL90XX_PDIV_SHIFT) |
  70                                    (epll_div[i][4] << PLL90XX_SDIV_SHIFT);
  71                        break;
  72                }
  73        }
  74
  75        if (i == ARRAY_SIZE(epll_div)) {
  76                printk(KERN_ERR "%s: Invalid Clock EPLL Frequency\n", __func__);
  77                return -EINVAL;
  78        }
  79
  80        __raw_writel(epll_con, S5P64X0_EPLL_CON);
  81        __raw_writel(epll_con_k, S5P64X0_EPLL_CON_K);
  82
  83        printk(KERN_WARNING "EPLL Rate changes from %lu to %lu\n",
  84                        clk->rate, rate);
  85
  86        clk->rate = rate;
  87
  88        return 0;
  89}
  90
  91static struct clk_ops s5p6450_epll_ops = {
  92        .get_rate = s5p_epll_get_rate,
  93        .set_rate = s5p6450_epll_set_rate,
  94};
  95
  96static struct clksrc_clk clk_dout_epll = {
  97        .clk    = {
  98                .name           = "dout_epll",
  99                .parent         = &clk_mout_epll.clk,
 100        },
 101        .reg_div        = { .reg = S5P64X0_CLK_DIV1, .shift = 24, .size = 4 },
 102};
 103
 104static struct clksrc_clk clk_mout_hclk_sel = {
 105        .clk    = {
 106                .name           = "mout_hclk_sel",
 107        },
 108        .sources        = &clkset_hclk_low,
 109        .reg_src        = { .reg = S5P64X0_OTHERS, .shift = 15, .size = 1 },
 110};
 111
 112static struct clk *clkset_hclk_list[] = {
 113        &clk_mout_hclk_sel.clk,
 114        &clk_armclk.clk,
 115};
 116
 117static struct clksrc_sources clkset_hclk = {
 118        .sources        = clkset_hclk_list,
 119        .nr_sources     = ARRAY_SIZE(clkset_hclk_list),
 120};
 121
 122static struct clksrc_clk clk_hclk = {
 123        .clk    = {
 124                .name           = "clk_hclk",
 125        },
 126        .sources        = &clkset_hclk,
 127        .reg_src        = { .reg = S5P64X0_OTHERS, .shift = 14, .size = 1 },
 128        .reg_div        = { .reg = S5P64X0_CLK_DIV0, .shift = 8, .size = 4 },
 129};
 130
 131static struct clksrc_clk clk_pclk = {
 132        .clk    = {
 133                .name           = "clk_pclk",
 134                .parent         = &clk_hclk.clk,
 135        },
 136        .reg_div = { .reg = S5P64X0_CLK_DIV0, .shift = 12, .size = 4 },
 137};
 138static struct clksrc_clk clk_dout_pwm_ratio0 = {
 139        .clk    = {
 140                .name           = "clk_dout_pwm_ratio0",
 141                .parent         = &clk_mout_hclk_sel.clk,
 142        },
 143        .reg_div        = { .reg = S5P64X0_CLK_DIV3, .shift = 16, .size = 4 },
 144};
 145
 146static struct clksrc_clk clk_pclk_to_wdt_pwm = {
 147        .clk    = {
 148                .name           = "clk_pclk_to_wdt_pwm",
 149                .parent         = &clk_dout_pwm_ratio0.clk,
 150        },
 151        .reg_div        = { .reg = S5P64X0_CLK_DIV3, .shift = 20, .size = 4 },
 152};
 153
 154static struct clksrc_clk clk_hclk_low = {
 155        .clk    = {
 156                .name           = "clk_hclk_low",
 157        },
 158        .sources        = &clkset_hclk_low,
 159        .reg_src        = { .reg = S5P64X0_OTHERS, .shift = 6, .size = 1 },
 160        .reg_div        = { .reg = S5P64X0_CLK_DIV3, .shift = 8, .size = 4 },
 161};
 162
 163static struct clksrc_clk clk_pclk_low = {
 164        .clk    = {
 165                .name           = "clk_pclk_low",
 166                .parent         = &clk_hclk_low.clk,
 167        },
 168        .reg_div        = { .reg = S5P64X0_CLK_DIV3, .shift = 12, .size = 4 },
 169};
 170
 171/*
 172 * The following clocks will be disabled during clock initialization. It is
 173 * recommended to keep the following clocks disabled until the driver requests
 174 * for enabling the clock.
 175 */
 176static struct clk init_clocks_off[] = {
 177        {
 178                .name           = "usbhost",
 179                .parent         = &clk_hclk_low.clk,
 180                .enable         = s5p64x0_hclk0_ctrl,
 181                .ctrlbit        = (1 << 3),
 182        }, {
 183                .name           = "dma",
 184                .devname        = "dma-pl330",
 185                .parent         = &clk_hclk_low.clk,
 186                .enable         = s5p64x0_hclk0_ctrl,
 187                .ctrlbit        = (1 << 12),
 188        }, {
 189                .name           = "hsmmc",
 190                .devname        = "s3c-sdhci.0",
 191                .parent         = &clk_hclk_low.clk,
 192                .enable         = s5p64x0_hclk0_ctrl,
 193                .ctrlbit        = (1 << 17),
 194        }, {
 195                .name           = "hsmmc",
 196                .devname        = "s3c-sdhci.1",
 197                .parent         = &clk_hclk_low.clk,
 198                .enable         = s5p64x0_hclk0_ctrl,
 199                .ctrlbit        = (1 << 18),
 200        }, {
 201                .name           = "hsmmc",
 202                .devname        = "s3c-sdhci.2",
 203                .parent         = &clk_hclk_low.clk,
 204                .enable         = s5p64x0_hclk0_ctrl,
 205                .ctrlbit        = (1 << 19),
 206        }, {
 207                .name           = "usbotg",
 208                .parent         = &clk_hclk_low.clk,
 209                .enable         = s5p64x0_hclk0_ctrl,
 210                .ctrlbit        = (1 << 20),
 211        }, {
 212                .name           = "lcd",
 213                .parent         = &clk_h,
 214                .enable         = s5p64x0_hclk1_ctrl,
 215                .ctrlbit        = (1 << 1),
 216        }, {
 217                .name           = "watchdog",
 218                .parent         = &clk_pclk_low.clk,
 219                .enable         = s5p64x0_pclk_ctrl,
 220                .ctrlbit        = (1 << 5),
 221        }, {
 222                .name           = "rtc",
 223                .parent         = &clk_pclk_low.clk,
 224                .enable         = s5p64x0_pclk_ctrl,
 225                .ctrlbit        = (1 << 6),
 226        }, {
 227                .name           = "adc",
 228                .parent         = &clk_pclk_low.clk,
 229                .enable         = s5p64x0_pclk_ctrl,
 230                .ctrlbit        = (1 << 12),
 231        }, {
 232                .name           = "i2c",
 233                .devname        = "s3c2440-i2c.0",
 234                .parent         = &clk_pclk_low.clk,
 235                .enable         = s5p64x0_pclk_ctrl,
 236                .ctrlbit        = (1 << 17),
 237        }, {
 238                .name           = "spi",
 239                .devname        = "s5p64x0-spi.0",
 240                .parent         = &clk_pclk_low.clk,
 241                .enable         = s5p64x0_pclk_ctrl,
 242                .ctrlbit        = (1 << 21),
 243        }, {
 244                .name           = "spi",
 245                .devname        = "s5p64x0-spi.1",
 246                .parent         = &clk_pclk_low.clk,
 247                .enable         = s5p64x0_pclk_ctrl,
 248                .ctrlbit        = (1 << 22),
 249        }, {
 250                .name           = "i2c",
 251                .devname        = "s3c2440-i2c.1",
 252                .parent         = &clk_pclk_low.clk,
 253                .enable         = s5p64x0_pclk_ctrl,
 254                .ctrlbit        = (1 << 27),
 255        }, {
 256                .name           = "dmc0",
 257                .parent         = &clk_pclk.clk,
 258                .enable         = s5p64x0_pclk_ctrl,
 259                .ctrlbit        = (1 << 30),
 260        }
 261};
 262
 263/*
 264 * The following clocks will be enabled during clock initialization.
 265 */
 266static struct clk init_clocks[] = {
 267        {
 268                .name           = "intc",
 269                .parent         = &clk_hclk.clk,
 270                .enable         = s5p64x0_hclk0_ctrl,
 271                .ctrlbit        = (1 << 1),
 272        }, {
 273                .name           = "mem",
 274                .parent         = &clk_hclk.clk,
 275                .enable         = s5p64x0_hclk0_ctrl,
 276                .ctrlbit        = (1 << 21),
 277        }, {
 278                .name           = "uart",
 279                .devname        = "s3c6400-uart.0",
 280                .parent         = &clk_pclk_low.clk,
 281                .enable         = s5p64x0_pclk_ctrl,
 282                .ctrlbit        = (1 << 1),
 283        }, {
 284                .name           = "uart",
 285                .devname        = "s3c6400-uart.1",
 286                .parent         = &clk_pclk_low.clk,
 287                .enable         = s5p64x0_pclk_ctrl,
 288                .ctrlbit        = (1 << 2),
 289        }, {
 290                .name           = "uart",
 291                .devname        = "s3c6400-uart.2",
 292                .parent         = &clk_pclk_low.clk,
 293                .enable         = s5p64x0_pclk_ctrl,
 294                .ctrlbit        = (1 << 3),
 295        }, {
 296                .name           = "uart",
 297                .devname        = "s3c6400-uart.3",
 298                .parent         = &clk_pclk_low.clk,
 299                .enable         = s5p64x0_pclk_ctrl,
 300                .ctrlbit        = (1 << 4),
 301        }, {
 302                .name           = "timers",
 303                .parent         = &clk_pclk_to_wdt_pwm.clk,
 304                .enable         = s5p64x0_pclk_ctrl,
 305                .ctrlbit        = (1 << 7),
 306        }, {
 307                .name           = "gpio",
 308                .parent         = &clk_pclk_low.clk,
 309                .enable         = s5p64x0_pclk_ctrl,
 310                .ctrlbit        = (1 << 18),
 311        },
 312};
 313
 314static struct clk *clkset_uart_list[] = {
 315        &clk_dout_epll.clk,
 316        &clk_dout_mpll.clk,
 317};
 318
 319static struct clksrc_sources clkset_uart = {
 320        .sources        = clkset_uart_list,
 321        .nr_sources     = ARRAY_SIZE(clkset_uart_list),
 322};
 323
 324static struct clk *clkset_mali_list[] = {
 325        &clk_mout_epll.clk,
 326        &clk_mout_apll.clk,
 327        &clk_mout_mpll.clk,
 328};
 329
 330static struct clksrc_sources clkset_mali = {
 331        .sources        = clkset_mali_list,
 332        .nr_sources     = ARRAY_SIZE(clkset_mali_list),
 333};
 334
 335static struct clk *clkset_group2_list[] = {
 336        &clk_dout_epll.clk,
 337        &clk_dout_mpll.clk,
 338        &clk_ext_xtal_mux,
 339};
 340
 341static struct clksrc_sources clkset_group2 = {
 342        .sources        = clkset_group2_list,
 343        .nr_sources     = ARRAY_SIZE(clkset_group2_list),
 344};
 345
 346static struct clk *clkset_dispcon_list[] = {
 347        &clk_dout_epll.clk,
 348        &clk_dout_mpll.clk,
 349        &clk_ext_xtal_mux,
 350        &clk_mout_dpll.clk,
 351};
 352
 353static struct clksrc_sources clkset_dispcon = {
 354        .sources        = clkset_dispcon_list,
 355        .nr_sources     = ARRAY_SIZE(clkset_dispcon_list),
 356};
 357
 358static struct clk *clkset_hsmmc44_list[] = {
 359        &clk_dout_epll.clk,
 360        &clk_dout_mpll.clk,
 361        &clk_ext_xtal_mux,
 362        &s5p_clk_27m,
 363        &clk_48m,
 364};
 365
 366static struct clksrc_sources clkset_hsmmc44 = {
 367        .sources        = clkset_hsmmc44_list,
 368        .nr_sources     = ARRAY_SIZE(clkset_hsmmc44_list),
 369};
 370
 371static struct clk *clkset_sclk_audio0_list[] = {
 372        [0] = &clk_dout_epll.clk,
 373        [1] = &clk_dout_mpll.clk,
 374        [2] = &clk_ext_xtal_mux,
 375        [3] = NULL,
 376        [4] = NULL,
 377};
 378
 379static struct clksrc_sources clkset_sclk_audio0 = {
 380        .sources        = clkset_sclk_audio0_list,
 381        .nr_sources     = ARRAY_SIZE(clkset_sclk_audio0_list),
 382};
 383
 384static struct clksrc_clk clk_sclk_audio0 = {
 385        .clk            = {
 386                .name           = "audio-bus",
 387                .devname        = "samsung-i2s.0",
 388                .enable         = s5p64x0_sclk_ctrl,
 389                .ctrlbit        = (1 << 8),
 390                .parent         = &clk_dout_epll.clk,
 391        },
 392        .sources        = &clkset_sclk_audio0,
 393        .reg_src        = { .reg = S5P64X0_CLK_SRC1, .shift = 10, .size = 3 },
 394        .reg_div        = { .reg = S5P64X0_CLK_DIV2, .shift = 8, .size = 4 },
 395};
 396
 397static struct clksrc_clk clksrcs[] = {
 398        {
 399                .clk    = {
 400                        .name           = "sclk_fimc",
 401                        .ctrlbit        = (1 << 10),
 402                        .enable         = s5p64x0_sclk_ctrl,
 403                },
 404                .sources = &clkset_group2,
 405                .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 26, .size = 2 },
 406                .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 12, .size = 4 },
 407        }, {
 408                .clk    = {
 409                        .name           = "aclk_mali",
 410                        .ctrlbit        = (1 << 2),
 411                        .enable         = s5p64x0_sclk1_ctrl,
 412                },
 413                .sources = &clkset_mali,
 414                .reg_src = { .reg = S5P64X0_CLK_SRC1, .shift = 8, .size = 2 },
 415                .reg_div = { .reg = S5P64X0_CLK_DIV3, .shift = 4, .size = 4 },
 416        }, {
 417                .clk    = {
 418                        .name           = "sclk_2d",
 419                        .ctrlbit        = (1 << 12),
 420                        .enable         = s5p64x0_sclk_ctrl,
 421                },
 422                .sources = &clkset_mali,
 423                .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 30, .size = 2 },
 424                .reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 20, .size = 4 },
 425        }, {
 426                .clk    = {
 427                        .name           = "sclk_usi",
 428                        .ctrlbit        = (1 << 7),
 429                        .enable         = s5p64x0_sclk_ctrl,
 430                },
 431                .sources = &clkset_group2,
 432                .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 10, .size = 2 },
 433                .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 16, .size = 4 },
 434        }, {
 435                .clk    = {
 436                        .name           = "sclk_camif",
 437                        .ctrlbit        = (1 << 6),
 438                        .enable         = s5p64x0_sclk_ctrl,
 439                },
 440                .sources = &clkset_group2,
 441                .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 28, .size = 2 },
 442                .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 20, .size = 4 },
 443        }, {
 444                .clk    = {
 445                        .name           = "sclk_dispcon",
 446                        .ctrlbit        = (1 << 1),
 447                        .enable         = s5p64x0_sclk1_ctrl,
 448                },
 449                .sources = &clkset_dispcon,
 450                .reg_src = { .reg = S5P64X0_CLK_SRC1, .shift = 4, .size = 2 },
 451                .reg_div = { .reg = S5P64X0_CLK_DIV3, .shift = 0, .size = 4 },
 452        }, {
 453                .clk    = {
 454                        .name           = "sclk_hsmmc44",
 455                        .ctrlbit        = (1 << 30),
 456                        .enable         = s5p64x0_sclk_ctrl,
 457                },
 458                .sources = &clkset_hsmmc44,
 459                .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 6, .size = 3 },
 460                .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 28, .size = 4 },
 461        },
 462};
 463
 464static struct clksrc_clk clk_sclk_mmc0 = {
 465        .clk    = {
 466                .name           = "sclk_mmc",
 467                .devname        = "s3c-sdhci.0",
 468                .ctrlbit        = (1 << 24),
 469                .enable         = s5p64x0_sclk_ctrl,
 470        },
 471        .sources = &clkset_group2,
 472        .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 18, .size = 2 },
 473        .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 0, .size = 4 },
 474};
 475
 476static struct clksrc_clk clk_sclk_mmc1 = {
 477        .clk    = {
 478                .name           = "sclk_mmc",
 479                .devname        = "s3c-sdhci.1",
 480                .ctrlbit        = (1 << 25),
 481                .enable         = s5p64x0_sclk_ctrl,
 482        },
 483        .sources = &clkset_group2,
 484        .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 20, .size = 2 },
 485        .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 4, .size = 4 },
 486};
 487
 488static struct clksrc_clk clk_sclk_mmc2 = {
 489        .clk    = {
 490                .name           = "sclk_mmc",
 491                .devname        = "s3c-sdhci.2",
 492                .ctrlbit        = (1 << 26),
 493                .enable         = s5p64x0_sclk_ctrl,
 494        },
 495        .sources = &clkset_group2,
 496        .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 22, .size = 2 },
 497        .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 8, .size = 4 },
 498};
 499
 500static struct clksrc_clk clk_sclk_uclk = {
 501        .clk    = {
 502                .name           = "uclk1",
 503                .ctrlbit        = (1 << 5),
 504                .enable         = s5p64x0_sclk_ctrl,
 505        },
 506        .sources = &clkset_uart,
 507        .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 13, .size = 1 },
 508        .reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 16, .size = 4 },
 509};
 510
 511static struct clksrc_clk clk_sclk_spi0 = {
 512        .clk    = {
 513                .name           = "sclk_spi",
 514                .devname        = "s5p64x0-spi.0",
 515                .ctrlbit        = (1 << 20),
 516                .enable         = s5p64x0_sclk_ctrl,
 517        },
 518        .sources = &clkset_group2,
 519        .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 14, .size = 2 },
 520        .reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 0, .size = 4 },
 521};
 522
 523static struct clksrc_clk clk_sclk_spi1 = {
 524        .clk    = {
 525                .name           = "sclk_spi",
 526                .devname        = "s5p64x0-spi.1",
 527                .ctrlbit        = (1 << 21),
 528                .enable         = s5p64x0_sclk_ctrl,
 529        },
 530        .sources = &clkset_group2,
 531        .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 16, .size = 2 },
 532        .reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 4, .size = 4 },
 533};
 534
 535static struct clk clk_i2s0 = {
 536        .name           = "iis",
 537        .devname        = "samsung-i2s.0",
 538        .parent         = &clk_pclk_low.clk,
 539        .enable         = s5p64x0_pclk_ctrl,
 540        .ctrlbit        = (1 << 26),
 541};
 542
 543static struct clk clk_i2s1 = {
 544        .name           = "iis",
 545        .devname        = "samsung-i2s.1",
 546        .parent         = &clk_pclk_low.clk,
 547        .enable         = s5p64x0_pclk_ctrl,
 548        .ctrlbit        = (1 << 15),
 549};
 550
 551static struct clk clk_i2s2 = {
 552        .name           = "iis",
 553        .devname        = "samsung-i2s.2",
 554        .parent         = &clk_pclk_low.clk,
 555        .enable         = s5p64x0_pclk_ctrl,
 556        .ctrlbit        = (1 << 16),
 557};
 558
 559static struct clk *clk_cdev[] = {
 560        &clk_i2s0,
 561        &clk_i2s1,
 562        &clk_i2s2,
 563};
 564
 565static struct clksrc_clk *clksrc_cdev[] = {
 566        &clk_sclk_uclk,
 567        &clk_sclk_spi0,
 568        &clk_sclk_spi1,
 569        &clk_sclk_mmc0,
 570        &clk_sclk_mmc1,
 571        &clk_sclk_mmc2,
 572        &clk_sclk_audio0,
 573};
 574
 575static struct clk_lookup s5p6450_clk_lookup[] = {
 576        CLKDEV_INIT(NULL, "clk_uart_baud2", &clk_pclk_low.clk),
 577        CLKDEV_INIT(NULL, "clk_uart_baud3", &clk_sclk_uclk.clk),
 578        CLKDEV_INIT(NULL, "spi_busclk0", &clk_p),
 579        CLKDEV_INIT("s5p64x0-spi.0", "spi_busclk1", &clk_sclk_spi0.clk),
 580        CLKDEV_INIT("s5p64x0-spi.1", "spi_busclk1", &clk_sclk_spi1.clk),
 581        CLKDEV_INIT("s3c-sdhci.0", "mmc_busclk.2", &clk_sclk_mmc0.clk),
 582        CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.2", &clk_sclk_mmc1.clk),
 583        CLKDEV_INIT("s3c-sdhci.2", "mmc_busclk.2", &clk_sclk_mmc2.clk),
 584        CLKDEV_INIT("samsung-i2s.0", "i2s_opclk0", &clk_i2s0),
 585        CLKDEV_INIT("samsung-i2s.0", "i2s_opclk1", &clk_sclk_audio0.clk),
 586        CLKDEV_INIT("samsung-i2s.1", "i2s_opclk0", &clk_i2s1),
 587        CLKDEV_INIT("samsung-i2s.2", "i2s_opclk0", &clk_i2s2),
 588};
 589
 590/* Clock initialization code */
 591static struct clksrc_clk *sysclks[] = {
 592        &clk_mout_apll,
 593        &clk_mout_epll,
 594        &clk_dout_epll,
 595        &clk_mout_mpll,
 596        &clk_dout_mpll,
 597        &clk_armclk,
 598        &clk_mout_hclk_sel,
 599        &clk_dout_pwm_ratio0,
 600        &clk_pclk_to_wdt_pwm,
 601        &clk_hclk,
 602        &clk_pclk,
 603        &clk_hclk_low,
 604        &clk_pclk_low,
 605};
 606
 607static struct clk dummy_apb_pclk = {
 608        .name           = "apb_pclk",
 609        .id             = -1,
 610};
 611
 612void __init_or_cpufreq s5p6450_setup_clocks(void)
 613{
 614        struct clk *xtal_clk;
 615
 616        unsigned long xtal;
 617        unsigned long fclk;
 618        unsigned long hclk;
 619        unsigned long hclk_low;
 620        unsigned long pclk;
 621        unsigned long pclk_low;
 622
 623        unsigned long apll;
 624        unsigned long mpll;
 625        unsigned long epll;
 626        unsigned long dpll;
 627        unsigned int ptr;
 628
 629        /* Set S5P6450 functions for clk_fout_epll */
 630
 631        clk_fout_epll.enable = s5p_epll_enable;
 632        clk_fout_epll.ops = &s5p6450_epll_ops;
 633
 634        clk_48m.enable = s5p64x0_clk48m_ctrl;
 635
 636        xtal_clk = clk_get(NULL, "ext_xtal");
 637        BUG_ON(IS_ERR(xtal_clk));
 638
 639        xtal = clk_get_rate(xtal_clk);
 640        clk_put(xtal_clk);
 641
 642        apll = s5p_get_pll45xx(xtal, __raw_readl(S5P64X0_APLL_CON), pll_4502);
 643        mpll = s5p_get_pll45xx(xtal, __raw_readl(S5P64X0_MPLL_CON), pll_4502);
 644        epll = s5p_get_pll90xx(xtal, __raw_readl(S5P64X0_EPLL_CON),
 645                                __raw_readl(S5P64X0_EPLL_CON_K));
 646        dpll = s5p_get_pll46xx(xtal, __raw_readl(S5P6450_DPLL_CON),
 647                                __raw_readl(S5P6450_DPLL_CON_K), pll_4650c);
 648
 649        clk_fout_apll.rate = apll;
 650        clk_fout_mpll.rate = mpll;
 651        clk_fout_epll.rate = epll;
 652        clk_fout_dpll.rate = dpll;
 653
 654        printk(KERN_INFO "S5P6450: PLL settings, A=%ld.%ldMHz, M=%ld.%ldMHz," \
 655                        " E=%ld.%ldMHz, D=%ld.%ldMHz\n",
 656                        print_mhz(apll), print_mhz(mpll), print_mhz(epll),
 657                        print_mhz(dpll));
 658
 659        fclk = clk_get_rate(&clk_armclk.clk);
 660        hclk = clk_get_rate(&clk_hclk.clk);
 661        pclk = clk_get_rate(&clk_pclk.clk);
 662        hclk_low = clk_get_rate(&clk_hclk_low.clk);
 663        pclk_low = clk_get_rate(&clk_pclk_low.clk);
 664
 665        printk(KERN_INFO "S5P6450: HCLK=%ld.%ldMHz, HCLK_LOW=%ld.%ldMHz," \
 666                        " PCLK=%ld.%ldMHz, PCLK_LOW=%ld.%ldMHz\n",
 667                        print_mhz(hclk), print_mhz(hclk_low),
 668                        print_mhz(pclk), print_mhz(pclk_low));
 669
 670        clk_f.rate = fclk;
 671        clk_h.rate = hclk;
 672        clk_p.rate = pclk;
 673
 674        for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++)
 675                s3c_set_clksrc(&clksrcs[ptr], true);
 676}
 677
 678void __init s5p6450_register_clocks(void)
 679{
 680        int ptr;
 681        unsigned int cnt;
 682
 683        for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++)
 684                s3c_register_clksrc(sysclks[ptr], 1);
 685
 686
 687        s3c24xx_register_clocks(clk_cdev, ARRAY_SIZE(clk_cdev));
 688        for (cnt = 0; cnt < ARRAY_SIZE(clk_cdev); cnt++)
 689                s3c_disable_clocks(clk_cdev[cnt], 1);
 690
 691        s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
 692        s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
 693        for (ptr = 0; ptr < ARRAY_SIZE(clksrc_cdev); ptr++)
 694                s3c_register_clksrc(clksrc_cdev[ptr], 1);
 695
 696        s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
 697        s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
 698        clkdev_add_table(s5p6450_clk_lookup, ARRAY_SIZE(s5p6450_clk_lookup));
 699
 700        s3c24xx_register_clock(&dummy_apb_pclk);
 701
 702        s3c_pwmclk_init();
 703}
 704