linux/arch/arm/mach-s3c64xx/clock.c
<<
>>
Prefs
   1/* linux/arch/arm/plat-s3c64xx/clock.c
   2 *
   3 * Copyright 2008 Openmoko, Inc.
   4 * Copyright 2008 Simtec Electronics
   5 *      Ben Dooks <ben@simtec.co.uk>
   6 *      http://armlinux.simtec.co.uk/
   7 *
   8 * S3C64XX Base clock support
   9 *
  10 * This program is free software; you can redistribute it and/or modify
  11 * it under the terms of the GNU General Public License version 2 as
  12 * published by the Free Software Foundation.
  13*/
  14
  15#include <linux/init.h>
  16#include <linux/module.h>
  17#include <linux/interrupt.h>
  18#include <linux/ioport.h>
  19#include <linux/clk.h>
  20#include <linux/err.h>
  21#include <linux/io.h>
  22
  23#include <mach/hardware.h>
  24#include <mach/map.h>
  25
  26#include <mach/regs-clock.h>
  27
  28#include <plat/cpu.h>
  29#include <plat/devs.h>
  30#include <plat/cpu-freq.h>
  31#include <plat/clock.h>
  32#include <plat/clock-clksrc.h>
  33#include <plat/pll.h>
  34
  35#include "regs-sys.h"
  36
  37/* fin_apll, fin_mpll and fin_epll are all the same clock, which we call
  38 * ext_xtal_mux for want of an actual name from the manual.
  39*/
  40
  41static struct clk clk_ext_xtal_mux = {
  42        .name           = "ext_xtal",
  43};
  44
  45#define clk_fin_apll clk_ext_xtal_mux
  46#define clk_fin_mpll clk_ext_xtal_mux
  47#define clk_fin_epll clk_ext_xtal_mux
  48
  49#define clk_fout_mpll   clk_mpll
  50#define clk_fout_epll   clk_epll
  51
  52struct clk clk_h2 = {
  53        .name           = "hclk2",
  54        .rate           = 0,
  55};
  56
  57struct clk clk_27m = {
  58        .name           = "clk_27m",
  59        .rate           = 27000000,
  60};
  61
  62static int clk_48m_ctrl(struct clk *clk, int enable)
  63{
  64        unsigned long flags;
  65        u32 val;
  66
  67        /* can't rely on clock lock, this register has other usages */
  68        local_irq_save(flags);
  69
  70        val = __raw_readl(S3C64XX_OTHERS);
  71        if (enable)
  72                val |= S3C64XX_OTHERS_USBMASK;
  73        else
  74                val &= ~S3C64XX_OTHERS_USBMASK;
  75
  76        __raw_writel(val, S3C64XX_OTHERS);
  77        local_irq_restore(flags);
  78
  79        return 0;
  80}
  81
  82struct clk clk_48m = {
  83        .name           = "clk_48m",
  84        .rate           = 48000000,
  85        .enable         = clk_48m_ctrl,
  86};
  87
  88struct clk clk_xusbxti = {
  89        .name           = "xusbxti",
  90        .rate           = 48000000,
  91};
  92
  93static int inline s3c64xx_gate(void __iomem *reg,
  94                                struct clk *clk,
  95                                int enable)
  96{
  97        unsigned int ctrlbit = clk->ctrlbit;
  98        u32 con;
  99
 100        con = __raw_readl(reg);
 101
 102        if (enable)
 103                con |= ctrlbit;
 104        else
 105                con &= ~ctrlbit;
 106
 107        __raw_writel(con, reg);
 108        return 0;
 109}
 110
 111static int s3c64xx_pclk_ctrl(struct clk *clk, int enable)
 112{
 113        return s3c64xx_gate(S3C_PCLK_GATE, clk, enable);
 114}
 115
 116static int s3c64xx_hclk_ctrl(struct clk *clk, int enable)
 117{
 118        return s3c64xx_gate(S3C_HCLK_GATE, clk, enable);
 119}
 120
 121int s3c64xx_sclk_ctrl(struct clk *clk, int enable)
 122{
 123        return s3c64xx_gate(S3C_SCLK_GATE, clk, enable);
 124}
 125
 126static struct clk init_clocks_off[] = {
 127        {
 128                .name           = "nand",
 129                .parent         = &clk_h,
 130        }, {
 131                .name           = "rtc",
 132                .parent         = &clk_p,
 133                .enable         = s3c64xx_pclk_ctrl,
 134                .ctrlbit        = S3C_CLKCON_PCLK_RTC,
 135        }, {
 136                .name           = "adc",
 137                .parent         = &clk_p,
 138                .enable         = s3c64xx_pclk_ctrl,
 139                .ctrlbit        = S3C_CLKCON_PCLK_TSADC,
 140        }, {
 141                .name           = "i2c",
 142                .devname        = "s3c2440-i2c.0",
 143                .parent         = &clk_p,
 144                .enable         = s3c64xx_pclk_ctrl,
 145                .ctrlbit        = S3C_CLKCON_PCLK_IIC,
 146        }, {
 147                .name           = "i2c",
 148                .devname        = "s3c2440-i2c.1",
 149                .parent         = &clk_p,
 150                .enable         = s3c64xx_pclk_ctrl,
 151                .ctrlbit        = S3C6410_CLKCON_PCLK_I2C1,
 152        }, {
 153                .name           = "keypad",
 154                .parent         = &clk_p,
 155                .enable         = s3c64xx_pclk_ctrl,
 156                .ctrlbit        = S3C_CLKCON_PCLK_KEYPAD,
 157        }, {
 158                .name           = "spi",
 159                .devname        = "s3c6410-spi.0",
 160                .parent         = &clk_p,
 161                .enable         = s3c64xx_pclk_ctrl,
 162                .ctrlbit        = S3C_CLKCON_PCLK_SPI0,
 163        }, {
 164                .name           = "spi",
 165                .devname        = "s3c6410-spi.1",
 166                .parent         = &clk_p,
 167                .enable         = s3c64xx_pclk_ctrl,
 168                .ctrlbit        = S3C_CLKCON_PCLK_SPI1,
 169        }, {
 170                .name           = "48m",
 171                .devname        = "s3c-sdhci.0",
 172                .parent         = &clk_48m,
 173                .enable         = s3c64xx_sclk_ctrl,
 174                .ctrlbit        = S3C_CLKCON_SCLK_MMC0_48,
 175        }, {
 176                .name           = "48m",
 177                .devname        = "s3c-sdhci.1",
 178                .parent         = &clk_48m,
 179                .enable         = s3c64xx_sclk_ctrl,
 180                .ctrlbit        = S3C_CLKCON_SCLK_MMC1_48,
 181        }, {
 182                .name           = "48m",
 183                .devname        = "s3c-sdhci.2",
 184                .parent         = &clk_48m,
 185                .enable         = s3c64xx_sclk_ctrl,
 186                .ctrlbit        = S3C_CLKCON_SCLK_MMC2_48,
 187        }, {
 188                .name           = "ac97",
 189                .parent         = &clk_p,
 190                .ctrlbit        = S3C_CLKCON_PCLK_AC97,
 191        }, {
 192                .name           = "cfcon",
 193                .parent         = &clk_h,
 194                .enable         = s3c64xx_hclk_ctrl,
 195                .ctrlbit        = S3C_CLKCON_HCLK_IHOST,
 196        }, {
 197                .name           = "dma0",
 198                .parent         = &clk_h,
 199                .enable         = s3c64xx_hclk_ctrl,
 200                .ctrlbit        = S3C_CLKCON_HCLK_DMA0,
 201        }, {
 202                .name           = "dma1",
 203                .parent         = &clk_h,
 204                .enable         = s3c64xx_hclk_ctrl,
 205                .ctrlbit        = S3C_CLKCON_HCLK_DMA1,
 206        }, {
 207                .name           = "3dse",
 208                .parent         = &clk_h,
 209                .enable         = s3c64xx_hclk_ctrl,
 210                .ctrlbit        = S3C_CLKCON_HCLK_3DSE,
 211        }, {
 212                .name           = "hclk_secur",
 213                .parent         = &clk_h,
 214                .enable         = s3c64xx_hclk_ctrl,
 215                .ctrlbit        = S3C_CLKCON_HCLK_SECUR,
 216        }, {
 217                .name           = "sdma1",
 218                .parent         = &clk_h,
 219                .enable         = s3c64xx_hclk_ctrl,
 220                .ctrlbit        = S3C_CLKCON_HCLK_SDMA1,
 221        }, {
 222                .name           = "sdma0",
 223                .parent         = &clk_h,
 224                .enable         = s3c64xx_hclk_ctrl,
 225                .ctrlbit        = S3C_CLKCON_HCLK_SDMA0,
 226        }, {
 227                .name           = "hclk_jpeg",
 228                .parent         = &clk_h,
 229                .enable         = s3c64xx_hclk_ctrl,
 230                .ctrlbit        = S3C_CLKCON_HCLK_JPEG,
 231        }, {
 232                .name           = "camif",
 233                .parent         = &clk_h,
 234                .enable         = s3c64xx_hclk_ctrl,
 235                .ctrlbit        = S3C_CLKCON_HCLK_CAMIF,
 236        }, {
 237                .name           = "hclk_scaler",
 238                .parent         = &clk_h,
 239                .enable         = s3c64xx_hclk_ctrl,
 240                .ctrlbit        = S3C_CLKCON_HCLK_SCALER,
 241        }, {
 242                .name           = "2d",
 243                .parent         = &clk_h,
 244                .enable         = s3c64xx_hclk_ctrl,
 245                .ctrlbit        = S3C_CLKCON_HCLK_2D,
 246        }, {
 247                .name           = "tv",
 248                .parent         = &clk_h,
 249                .enable         = s3c64xx_hclk_ctrl,
 250                .ctrlbit        = S3C_CLKCON_HCLK_TV,
 251        }, {
 252                .name           = "post0",
 253                .parent         = &clk_h,
 254                .enable         = s3c64xx_hclk_ctrl,
 255                .ctrlbit        = S3C_CLKCON_HCLK_POST0,
 256        }, {
 257                .name           = "rot",
 258                .parent         = &clk_h,
 259                .enable         = s3c64xx_hclk_ctrl,
 260                .ctrlbit        = S3C_CLKCON_HCLK_ROT,
 261        }, {
 262                .name           = "hclk_mfc",
 263                .parent         = &clk_h,
 264                .enable         = s3c64xx_hclk_ctrl,
 265                .ctrlbit        = S3C_CLKCON_HCLK_MFC,
 266        }, {
 267                .name           = "pclk_mfc",
 268                .parent         = &clk_p,
 269                .enable         = s3c64xx_pclk_ctrl,
 270                .ctrlbit        = S3C_CLKCON_PCLK_MFC,
 271        }, {
 272                .name           = "dac27",
 273                .enable         = s3c64xx_sclk_ctrl,
 274                .ctrlbit        = S3C_CLKCON_SCLK_DAC27,
 275        }, {
 276                .name           = "tv27",
 277                .enable         = s3c64xx_sclk_ctrl,
 278                .ctrlbit        = S3C_CLKCON_SCLK_TV27,
 279        }, {
 280                .name           = "scaler27",
 281                .enable         = s3c64xx_sclk_ctrl,
 282                .ctrlbit        = S3C_CLKCON_SCLK_SCALER27,
 283        }, {
 284                .name           = "sclk_scaler",
 285                .enable         = s3c64xx_sclk_ctrl,
 286                .ctrlbit        = S3C_CLKCON_SCLK_SCALER,
 287        }, {
 288                .name           = "post0_27",
 289                .enable         = s3c64xx_sclk_ctrl,
 290                .ctrlbit        = S3C_CLKCON_SCLK_POST0_27,
 291        }, {
 292                .name           = "secur",
 293                .enable         = s3c64xx_sclk_ctrl,
 294                .ctrlbit        = S3C_CLKCON_SCLK_SECUR,
 295        }, {
 296                .name           = "sclk_mfc",
 297                .enable         = s3c64xx_sclk_ctrl,
 298                .ctrlbit        = S3C_CLKCON_SCLK_MFC,
 299        }, {
 300                .name           = "sclk_jpeg",
 301                .enable         = s3c64xx_sclk_ctrl,
 302                .ctrlbit        = S3C_CLKCON_SCLK_JPEG,
 303        },
 304};
 305
 306static struct clk clk_48m_spi0 = {
 307        .name           = "spi_48m",
 308        .devname        = "s3c6410-spi.0",
 309        .parent         = &clk_48m,
 310        .enable         = s3c64xx_sclk_ctrl,
 311        .ctrlbit        = S3C_CLKCON_SCLK_SPI0_48,
 312};
 313
 314static struct clk clk_48m_spi1 = {
 315        .name           = "spi_48m",
 316        .devname        = "s3c6410-spi.1",
 317        .parent         = &clk_48m,
 318        .enable         = s3c64xx_sclk_ctrl,
 319        .ctrlbit        = S3C_CLKCON_SCLK_SPI1_48,
 320};
 321
 322static struct clk clk_i2s0 = {
 323        .name           = "iis",
 324        .devname        = "samsung-i2s.0",
 325        .parent         = &clk_p,
 326        .enable         = s3c64xx_pclk_ctrl,
 327        .ctrlbit        = S3C_CLKCON_PCLK_IIS0,
 328};
 329
 330static struct clk clk_i2s1 = {
 331        .name           = "iis",
 332        .devname        = "samsung-i2s.1",
 333        .parent         = &clk_p,
 334        .enable         = s3c64xx_pclk_ctrl,
 335        .ctrlbit        = S3C_CLKCON_PCLK_IIS1,
 336};
 337
 338#ifdef CONFIG_CPU_S3C6410
 339static struct clk clk_i2s2 = {
 340        .name           = "iis",
 341        .devname        = "samsung-i2s.2",
 342        .parent         = &clk_p,
 343        .enable         = s3c64xx_pclk_ctrl,
 344        .ctrlbit        = S3C6410_CLKCON_PCLK_IIS2,
 345};
 346#endif
 347
 348static struct clk init_clocks[] = {
 349        {
 350                .name           = "lcd",
 351                .parent         = &clk_h,
 352                .enable         = s3c64xx_hclk_ctrl,
 353                .ctrlbit        = S3C_CLKCON_HCLK_LCD,
 354        }, {
 355                .name           = "gpio",
 356                .parent         = &clk_p,
 357                .enable         = s3c64xx_pclk_ctrl,
 358                .ctrlbit        = S3C_CLKCON_PCLK_GPIO,
 359        }, {
 360                .name           = "usb-host",
 361                .parent         = &clk_h,
 362                .enable         = s3c64xx_hclk_ctrl,
 363                .ctrlbit        = S3C_CLKCON_HCLK_UHOST,
 364        }, {
 365                .name           = "otg",
 366                .parent         = &clk_h,
 367                .enable         = s3c64xx_hclk_ctrl,
 368                .ctrlbit        = S3C_CLKCON_HCLK_USB,
 369        }, {
 370                .name           = "timers",
 371                .parent         = &clk_p,
 372                .enable         = s3c64xx_pclk_ctrl,
 373                .ctrlbit        = S3C_CLKCON_PCLK_PWM,
 374        }, {
 375                .name           = "uart",
 376                .devname        = "s3c6400-uart.0",
 377                .parent         = &clk_p,
 378                .enable         = s3c64xx_pclk_ctrl,
 379                .ctrlbit        = S3C_CLKCON_PCLK_UART0,
 380        }, {
 381                .name           = "uart",
 382                .devname        = "s3c6400-uart.1",
 383                .parent         = &clk_p,
 384                .enable         = s3c64xx_pclk_ctrl,
 385                .ctrlbit        = S3C_CLKCON_PCLK_UART1,
 386        }, {
 387                .name           = "uart",
 388                .devname        = "s3c6400-uart.2",
 389                .parent         = &clk_p,
 390                .enable         = s3c64xx_pclk_ctrl,
 391                .ctrlbit        = S3C_CLKCON_PCLK_UART2,
 392        }, {
 393                .name           = "uart",
 394                .devname        = "s3c6400-uart.3",
 395                .parent         = &clk_p,
 396                .enable         = s3c64xx_pclk_ctrl,
 397                .ctrlbit        = S3C_CLKCON_PCLK_UART3,
 398        }, {
 399                .name           = "watchdog",
 400                .parent         = &clk_p,
 401                .ctrlbit        = S3C_CLKCON_PCLK_WDT,
 402        },
 403};
 404
 405static struct clk clk_hsmmc0 = {
 406        .name           = "hsmmc",
 407        .devname        = "s3c-sdhci.0",
 408        .parent         = &clk_h,
 409        .enable         = s3c64xx_hclk_ctrl,
 410        .ctrlbit        = S3C_CLKCON_HCLK_HSMMC0,
 411};
 412
 413static struct clk clk_hsmmc1 = {
 414        .name           = "hsmmc",
 415        .devname        = "s3c-sdhci.1",
 416        .parent         = &clk_h,
 417        .enable         = s3c64xx_hclk_ctrl,
 418        .ctrlbit        = S3C_CLKCON_HCLK_HSMMC1,
 419};
 420
 421static struct clk clk_hsmmc2 = {
 422        .name           = "hsmmc",
 423        .devname        = "s3c-sdhci.2",
 424        .parent         = &clk_h,
 425        .enable         = s3c64xx_hclk_ctrl,
 426        .ctrlbit        = S3C_CLKCON_HCLK_HSMMC2,
 427};
 428
 429static struct clk clk_fout_apll = {
 430        .name           = "fout_apll",
 431};
 432
 433static struct clk *clk_src_apll_list[] = {
 434        [0] = &clk_fin_apll,
 435        [1] = &clk_fout_apll,
 436};
 437
 438static struct clksrc_sources clk_src_apll = {
 439        .sources        = clk_src_apll_list,
 440        .nr_sources     = ARRAY_SIZE(clk_src_apll_list),
 441};
 442
 443static struct clksrc_clk clk_mout_apll = {
 444        .clk    = {
 445                .name           = "mout_apll",
 446        },
 447        .reg_src        = { .reg = S3C_CLK_SRC, .shift = 0, .size = 1  },
 448        .sources        = &clk_src_apll,
 449};
 450
 451static struct clk *clk_src_epll_list[] = {
 452        [0] = &clk_fin_epll,
 453        [1] = &clk_fout_epll,
 454};
 455
 456static struct clksrc_sources clk_src_epll = {
 457        .sources        = clk_src_epll_list,
 458        .nr_sources     = ARRAY_SIZE(clk_src_epll_list),
 459};
 460
 461static struct clksrc_clk clk_mout_epll = {
 462        .clk    = {
 463                .name           = "mout_epll",
 464        },
 465        .reg_src        = { .reg = S3C_CLK_SRC, .shift = 2, .size = 1  },
 466        .sources        = &clk_src_epll,
 467};
 468
 469static struct clk *clk_src_mpll_list[] = {
 470        [0] = &clk_fin_mpll,
 471        [1] = &clk_fout_mpll,
 472};
 473
 474static struct clksrc_sources clk_src_mpll = {
 475        .sources        = clk_src_mpll_list,
 476        .nr_sources     = ARRAY_SIZE(clk_src_mpll_list),
 477};
 478
 479static struct clksrc_clk clk_mout_mpll = {
 480        .clk = {
 481                .name           = "mout_mpll",
 482        },
 483        .reg_src        = { .reg = S3C_CLK_SRC, .shift = 1, .size = 1  },
 484        .sources        = &clk_src_mpll,
 485};
 486
 487static unsigned int armclk_mask;
 488
 489static unsigned long s3c64xx_clk_arm_get_rate(struct clk *clk)
 490{
 491        unsigned long rate = clk_get_rate(clk->parent);
 492        u32 clkdiv;
 493
 494        /* divisor mask starts at bit0, so no need to shift */
 495        clkdiv = __raw_readl(S3C_CLK_DIV0) & armclk_mask;
 496
 497        return rate / (clkdiv + 1);
 498}
 499
 500static unsigned long s3c64xx_clk_arm_round_rate(struct clk *clk,
 501                                                unsigned long rate)
 502{
 503        unsigned long parent = clk_get_rate(clk->parent);
 504        u32 div;
 505
 506        if (parent < rate)
 507                return parent;
 508
 509        div = (parent / rate) - 1;
 510        if (div > armclk_mask)
 511                div = armclk_mask;
 512
 513        return parent / (div + 1);
 514}
 515
 516static int s3c64xx_clk_arm_set_rate(struct clk *clk, unsigned long rate)
 517{
 518        unsigned long parent = clk_get_rate(clk->parent);
 519        u32 div;
 520        u32 val;
 521
 522        if (rate < parent / (armclk_mask + 1))
 523                return -EINVAL;
 524
 525        rate = clk_round_rate(clk, rate);
 526        div = clk_get_rate(clk->parent) / rate;
 527
 528        val = __raw_readl(S3C_CLK_DIV0);
 529        val &= ~armclk_mask;
 530        val |= (div - 1);
 531        __raw_writel(val, S3C_CLK_DIV0);
 532
 533        return 0;
 534
 535}
 536
 537static struct clk clk_arm = {
 538        .name           = "armclk",
 539        .parent         = &clk_mout_apll.clk,
 540        .ops            = &(struct clk_ops) {
 541                .get_rate       = s3c64xx_clk_arm_get_rate,
 542                .set_rate       = s3c64xx_clk_arm_set_rate,
 543                .round_rate     = s3c64xx_clk_arm_round_rate,
 544        },
 545};
 546
 547static unsigned long s3c64xx_clk_doutmpll_get_rate(struct clk *clk)
 548{
 549        unsigned long rate = clk_get_rate(clk->parent);
 550
 551        printk(KERN_DEBUG "%s: parent is %ld\n", __func__, rate);
 552
 553        if (__raw_readl(S3C_CLK_DIV0) & S3C6400_CLKDIV0_MPLL_MASK)
 554                rate /= 2;
 555
 556        return rate;
 557}
 558
 559static struct clk_ops clk_dout_ops = {
 560        .get_rate       = s3c64xx_clk_doutmpll_get_rate,
 561};
 562
 563static struct clk clk_dout_mpll = {
 564        .name           = "dout_mpll",
 565        .parent         = &clk_mout_mpll.clk,
 566        .ops            = &clk_dout_ops,
 567};
 568
 569static struct clk *clkset_spi_mmc_list[] = {
 570        &clk_mout_epll.clk,
 571        &clk_dout_mpll,
 572        &clk_fin_epll,
 573        &clk_27m,
 574};
 575
 576static struct clksrc_sources clkset_spi_mmc = {
 577        .sources        = clkset_spi_mmc_list,
 578        .nr_sources     = ARRAY_SIZE(clkset_spi_mmc_list),
 579};
 580
 581static struct clk *clkset_irda_list[] = {
 582        &clk_mout_epll.clk,
 583        &clk_dout_mpll,
 584        NULL,
 585        &clk_27m,
 586};
 587
 588static struct clksrc_sources clkset_irda = {
 589        .sources        = clkset_irda_list,
 590        .nr_sources     = ARRAY_SIZE(clkset_irda_list),
 591};
 592
 593static struct clk *clkset_uart_list[] = {
 594        &clk_mout_epll.clk,
 595        &clk_dout_mpll,
 596        NULL,
 597        NULL
 598};
 599
 600static struct clksrc_sources clkset_uart = {
 601        .sources        = clkset_uart_list,
 602        .nr_sources     = ARRAY_SIZE(clkset_uart_list),
 603};
 604
 605static struct clk *clkset_uhost_list[] = {
 606        &clk_48m,
 607        &clk_mout_epll.clk,
 608        &clk_dout_mpll,
 609        &clk_fin_epll,
 610};
 611
 612static struct clksrc_sources clkset_uhost = {
 613        .sources        = clkset_uhost_list,
 614        .nr_sources     = ARRAY_SIZE(clkset_uhost_list),
 615};
 616
 617/* The peripheral clocks are all controlled via clocksource followed
 618 * by an optional divider and gate stage. We currently roll this into
 619 * one clock which hides the intermediate clock from the mux.
 620 *
 621 * Note, the JPEG clock can only be an even divider...
 622 *
 623 * The scaler and LCD clocks depend on the S3C64XX version, and also
 624 * have a common parent divisor so are not included here.
 625 */
 626
 627/* clocks that feed other parts of the clock source tree */
 628
 629static struct clk clk_iis_cd0 = {
 630        .name           = "iis_cdclk0",
 631};
 632
 633static struct clk clk_iis_cd1 = {
 634        .name           = "iis_cdclk1",
 635};
 636
 637static struct clk clk_iisv4_cd = {
 638        .name           = "iis_cdclk_v4",
 639};
 640
 641static struct clk clk_pcm_cd = {
 642        .name           = "pcm_cdclk",
 643};
 644
 645static struct clk *clkset_audio0_list[] = {
 646        [0] = &clk_mout_epll.clk,
 647        [1] = &clk_dout_mpll,
 648        [2] = &clk_fin_epll,
 649        [3] = &clk_iis_cd0,
 650        [4] = &clk_pcm_cd,
 651};
 652
 653static struct clksrc_sources clkset_audio0 = {
 654        .sources        = clkset_audio0_list,
 655        .nr_sources     = ARRAY_SIZE(clkset_audio0_list),
 656};
 657
 658static struct clk *clkset_audio1_list[] = {
 659        [0] = &clk_mout_epll.clk,
 660        [1] = &clk_dout_mpll,
 661        [2] = &clk_fin_epll,
 662        [3] = &clk_iis_cd1,
 663        [4] = &clk_pcm_cd,
 664};
 665
 666static struct clksrc_sources clkset_audio1 = {
 667        .sources        = clkset_audio1_list,
 668        .nr_sources     = ARRAY_SIZE(clkset_audio1_list),
 669};
 670
 671#ifdef CONFIG_CPU_S3C6410
 672static struct clk *clkset_audio2_list[] = {
 673        [0] = &clk_mout_epll.clk,
 674        [1] = &clk_dout_mpll,
 675        [2] = &clk_fin_epll,
 676        [3] = &clk_iisv4_cd,
 677        [4] = &clk_pcm_cd,
 678};
 679
 680static struct clksrc_sources clkset_audio2 = {
 681        .sources        = clkset_audio2_list,
 682        .nr_sources     = ARRAY_SIZE(clkset_audio2_list),
 683};
 684#endif
 685
 686static struct clksrc_clk clksrcs[] = {
 687        {
 688                .clk    = {
 689                        .name           = "usb-bus-host",
 690                        .ctrlbit        = S3C_CLKCON_SCLK_UHOST,
 691                        .enable         = s3c64xx_sclk_ctrl,
 692                },
 693                .reg_src        = { .reg = S3C_CLK_SRC, .shift = 5, .size = 2  },
 694                .reg_div        = { .reg = S3C_CLK_DIV1, .shift = 20, .size = 4  },
 695                .sources        = &clkset_uhost,
 696        }, {
 697                .clk    = {
 698                        .name           = "irda-bus",
 699                        .ctrlbit        = S3C_CLKCON_SCLK_IRDA,
 700                        .enable         = s3c64xx_sclk_ctrl,
 701                },
 702                .reg_src        = { .reg = S3C_CLK_SRC, .shift = 24, .size = 2  },
 703                .reg_div        = { .reg = S3C_CLK_DIV2, .shift = 20, .size = 4  },
 704                .sources        = &clkset_irda,
 705        }, {
 706                .clk    = {
 707                        .name           = "camera",
 708                        .ctrlbit        = S3C_CLKCON_SCLK_CAM,
 709                        .enable         = s3c64xx_sclk_ctrl,
 710                        .parent         = &clk_h2,
 711                },
 712                .reg_div        = { .reg = S3C_CLK_DIV0, .shift = 20, .size = 4  },
 713        },
 714};
 715
 716/* Where does UCLK0 come from? */
 717static struct clksrc_clk clk_sclk_uclk = {
 718        .clk    = {
 719                .name           = "uclk1",
 720                .ctrlbit        = S3C_CLKCON_SCLK_UART,
 721                .enable         = s3c64xx_sclk_ctrl,
 722        },
 723        .reg_src        = { .reg = S3C_CLK_SRC, .shift = 13, .size = 1  },
 724        .reg_div        = { .reg = S3C_CLK_DIV2, .shift = 16, .size = 4  },
 725        .sources        = &clkset_uart,
 726};
 727
 728static struct clksrc_clk clk_sclk_mmc0 = {
 729        .clk    = {
 730                .name           = "mmc_bus",
 731                .devname        = "s3c-sdhci.0",
 732                .ctrlbit        = S3C_CLKCON_SCLK_MMC0,
 733                .enable         = s3c64xx_sclk_ctrl,
 734        },
 735        .reg_src        = { .reg = S3C_CLK_SRC, .shift = 18, .size = 2  },
 736        .reg_div        = { .reg = S3C_CLK_DIV1, .shift = 0, .size = 4  },
 737        .sources        = &clkset_spi_mmc,
 738};
 739
 740static struct clksrc_clk clk_sclk_mmc1 = {
 741        .clk    = {
 742                .name           = "mmc_bus",
 743                .devname        = "s3c-sdhci.1",
 744                .ctrlbit        = S3C_CLKCON_SCLK_MMC1,
 745                .enable         = s3c64xx_sclk_ctrl,
 746        },
 747        .reg_src        = { .reg = S3C_CLK_SRC, .shift = 20, .size = 2  },
 748        .reg_div        = { .reg = S3C_CLK_DIV1, .shift = 4, .size = 4  },
 749        .sources        = &clkset_spi_mmc,
 750};
 751
 752static struct clksrc_clk clk_sclk_mmc2 = {
 753        .clk    = {
 754                .name           = "mmc_bus",
 755                .devname        = "s3c-sdhci.2",
 756                .ctrlbit        = S3C_CLKCON_SCLK_MMC2,
 757                .enable         = s3c64xx_sclk_ctrl,
 758        },
 759        .reg_src        = { .reg = S3C_CLK_SRC, .shift = 22, .size = 2  },
 760        .reg_div        = { .reg = S3C_CLK_DIV1, .shift = 8, .size = 4  },
 761        .sources        = &clkset_spi_mmc,
 762};
 763
 764static struct clksrc_clk clk_sclk_spi0 = {
 765        .clk    = {
 766                .name           = "spi-bus",
 767                .devname        = "s3c6410-spi.0",
 768                .ctrlbit        = S3C_CLKCON_SCLK_SPI0,
 769                .enable         = s3c64xx_sclk_ctrl,
 770        },
 771        .reg_src = { .reg = S3C_CLK_SRC, .shift = 14, .size = 2 },
 772        .reg_div = { .reg = S3C_CLK_DIV2, .shift = 0, .size = 4 },
 773        .sources = &clkset_spi_mmc,
 774};
 775
 776static struct clksrc_clk clk_sclk_spi1 = {
 777        .clk    = {
 778                .name           = "spi-bus",
 779                .devname        = "s3c6410-spi.1",
 780                .ctrlbit        = S3C_CLKCON_SCLK_SPI1,
 781                .enable         = s3c64xx_sclk_ctrl,
 782        },
 783        .reg_src = { .reg = S3C_CLK_SRC, .shift = 16, .size = 2 },
 784        .reg_div = { .reg = S3C_CLK_DIV2, .shift = 4, .size = 4 },
 785        .sources = &clkset_spi_mmc,
 786};
 787
 788static struct clksrc_clk clk_audio_bus0 = {
 789        .clk    = {
 790                .name           = "audio-bus",
 791                .devname        = "samsung-i2s.0",
 792                .ctrlbit        = S3C_CLKCON_SCLK_AUDIO0,
 793                .enable         = s3c64xx_sclk_ctrl,
 794        },
 795        .reg_src        = { .reg = S3C_CLK_SRC, .shift = 7, .size = 3  },
 796        .reg_div        = { .reg = S3C_CLK_DIV2, .shift = 8, .size = 4  },
 797        .sources        = &clkset_audio0,
 798};
 799
 800static struct clksrc_clk clk_audio_bus1 = {
 801        .clk    = {
 802                .name           = "audio-bus",
 803                .devname        = "samsung-i2s.1",
 804                .ctrlbit        = S3C_CLKCON_SCLK_AUDIO1,
 805                .enable         = s3c64xx_sclk_ctrl,
 806        },
 807        .reg_src        = { .reg = S3C_CLK_SRC, .shift = 10, .size = 3  },
 808        .reg_div        = { .reg = S3C_CLK_DIV2, .shift = 12, .size = 4  },
 809        .sources        = &clkset_audio1,
 810};
 811
 812#ifdef CONFIG_CPU_S3C6410
 813static struct clksrc_clk clk_audio_bus2 = {
 814        .clk    = {
 815                .name           = "audio-bus",
 816                .devname        = "samsung-i2s.2",
 817                .ctrlbit        = S3C6410_CLKCON_SCLK_AUDIO2,
 818                .enable         = s3c64xx_sclk_ctrl,
 819        },
 820        .reg_src        = { .reg = S3C6410_CLK_SRC2, .shift = 0, .size = 3  },
 821        .reg_div        = { .reg = S3C_CLK_DIV2, .shift = 24, .size = 4  },
 822        .sources        = &clkset_audio2,
 823};
 824#endif
 825/* Clock initialisation code */
 826
 827static struct clksrc_clk *init_parents[] = {
 828        &clk_mout_apll,
 829        &clk_mout_epll,
 830        &clk_mout_mpll,
 831};
 832
 833static struct clksrc_clk *clksrc_cdev[] = {
 834        &clk_sclk_uclk,
 835        &clk_sclk_mmc0,
 836        &clk_sclk_mmc1,
 837        &clk_sclk_mmc2,
 838        &clk_sclk_spi0,
 839        &clk_sclk_spi1,
 840        &clk_audio_bus0,
 841        &clk_audio_bus1,
 842};
 843
 844static struct clk *clk_cdev[] = {
 845        &clk_hsmmc0,
 846        &clk_hsmmc1,
 847        &clk_hsmmc2,
 848        &clk_48m_spi0,
 849        &clk_48m_spi1,
 850        &clk_i2s0,
 851        &clk_i2s1,
 852};
 853
 854static struct clk_lookup s3c64xx_clk_lookup[] = {
 855        CLKDEV_INIT(NULL, "clk_uart_baud2", &clk_p),
 856        CLKDEV_INIT(NULL, "clk_uart_baud3", &clk_sclk_uclk.clk),
 857        CLKDEV_INIT("s3c-sdhci.0", "mmc_busclk.0", &clk_hsmmc0),
 858        CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.0", &clk_hsmmc1),
 859        CLKDEV_INIT("s3c-sdhci.2", "mmc_busclk.0", &clk_hsmmc2),
 860        CLKDEV_INIT("s3c-sdhci.0", "mmc_busclk.2", &clk_sclk_mmc0.clk),
 861        CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.2", &clk_sclk_mmc1.clk),
 862        CLKDEV_INIT("s3c-sdhci.2", "mmc_busclk.2", &clk_sclk_mmc2.clk),
 863        CLKDEV_INIT(NULL, "spi_busclk0", &clk_p),
 864        CLKDEV_INIT("s3c6410-spi.0", "spi_busclk1", &clk_sclk_spi0.clk),
 865        CLKDEV_INIT("s3c6410-spi.0", "spi_busclk2", &clk_48m_spi0),
 866        CLKDEV_INIT("s3c6410-spi.1", "spi_busclk1", &clk_sclk_spi1.clk),
 867        CLKDEV_INIT("s3c6410-spi.1", "spi_busclk2", &clk_48m_spi1),
 868        CLKDEV_INIT("samsung-i2s.0", "i2s_opclk0", &clk_i2s0),
 869        CLKDEV_INIT("samsung-i2s.0", "i2s_opclk1", &clk_audio_bus0.clk),
 870        CLKDEV_INIT("samsung-i2s.1", "i2s_opclk0", &clk_i2s1),
 871        CLKDEV_INIT("samsung-i2s.1", "i2s_opclk1", &clk_audio_bus1.clk),
 872#ifdef CONFIG_CPU_S3C6410
 873        CLKDEV_INIT("samsung-i2s.2", "i2s_opclk0", &clk_i2s2),
 874        CLKDEV_INIT("samsung-i2s.2", "i2s_opclk1", &clk_audio_bus2.clk),
 875#endif
 876};
 877
 878#define GET_DIV(clk, field) ((((clk) & field##_MASK) >> field##_SHIFT) + 1)
 879
 880void __init_or_cpufreq s3c64xx_setup_clocks(void)
 881{
 882        struct clk *xtal_clk;
 883        unsigned long xtal;
 884        unsigned long fclk;
 885        unsigned long hclk;
 886        unsigned long hclk2;
 887        unsigned long pclk;
 888        unsigned long epll;
 889        unsigned long apll;
 890        unsigned long mpll;
 891        unsigned int ptr;
 892        u32 clkdiv0;
 893
 894        printk(KERN_DEBUG "%s: registering clocks\n", __func__);
 895
 896        clkdiv0 = __raw_readl(S3C_CLK_DIV0);
 897        printk(KERN_DEBUG "%s: clkdiv0 = %08x\n", __func__, clkdiv0);
 898
 899        xtal_clk = clk_get(NULL, "xtal");
 900        BUG_ON(IS_ERR(xtal_clk));
 901
 902        xtal = clk_get_rate(xtal_clk);
 903        clk_put(xtal_clk);
 904
 905        printk(KERN_DEBUG "%s: xtal is %ld\n", __func__, xtal);
 906
 907        /* For now assume the mux always selects the crystal */
 908        clk_ext_xtal_mux.parent = xtal_clk;
 909
 910        epll = s3c_get_pll6553x(xtal, __raw_readl(S3C_EPLL_CON0),
 911                                __raw_readl(S3C_EPLL_CON1));
 912        mpll = s3c6400_get_pll(xtal, __raw_readl(S3C_MPLL_CON));
 913        apll = s3c6400_get_pll(xtal, __raw_readl(S3C_APLL_CON));
 914
 915        fclk = mpll;
 916
 917        printk(KERN_INFO "S3C64XX: PLL settings, A=%ld, M=%ld, E=%ld\n",
 918               apll, mpll, epll);
 919
 920        if(__raw_readl(S3C64XX_OTHERS) & S3C64XX_OTHERS_SYNCMUXSEL)
 921                /* Synchronous mode */
 922                hclk2 = apll / GET_DIV(clkdiv0, S3C6400_CLKDIV0_HCLK2);
 923        else
 924                /* Asynchronous mode */
 925                hclk2 = mpll / GET_DIV(clkdiv0, S3C6400_CLKDIV0_HCLK2);
 926
 927        hclk = hclk2 / GET_DIV(clkdiv0, S3C6400_CLKDIV0_HCLK);
 928        pclk = hclk2 / GET_DIV(clkdiv0, S3C6400_CLKDIV0_PCLK);
 929
 930        printk(KERN_INFO "S3C64XX: HCLK2=%ld, HCLK=%ld, PCLK=%ld\n",
 931               hclk2, hclk, pclk);
 932
 933        clk_fout_mpll.rate = mpll;
 934        clk_fout_epll.rate = epll;
 935        clk_fout_apll.rate = apll;
 936
 937        clk_h2.rate = hclk2;
 938        clk_h.rate = hclk;
 939        clk_p.rate = pclk;
 940        clk_f.rate = fclk;
 941
 942        for (ptr = 0; ptr < ARRAY_SIZE(init_parents); ptr++)
 943                s3c_set_clksrc(init_parents[ptr], true);
 944
 945        for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++)
 946                s3c_set_clksrc(&clksrcs[ptr], true);
 947}
 948
 949static struct clk *clks1[] __initdata = {
 950        &clk_ext_xtal_mux,
 951        &clk_iis_cd0,
 952        &clk_iis_cd1,
 953        &clk_iisv4_cd,
 954        &clk_pcm_cd,
 955        &clk_mout_epll.clk,
 956        &clk_mout_mpll.clk,
 957        &clk_dout_mpll,
 958        &clk_arm,
 959};
 960
 961static struct clk *clks[] __initdata = {
 962        &clk_ext,
 963        &clk_epll,
 964        &clk_27m,
 965        &clk_48m,
 966        &clk_h2,
 967        &clk_xusbxti,
 968};
 969
 970/**
 971 * s3c64xx_register_clocks - register clocks for s3c6400 and s3c6410
 972 * @xtal: The rate for the clock crystal feeding the PLLs.
 973 * @armclk_divlimit: Divisor mask for ARMCLK.
 974 *
 975 * Register the clocks for the S3C6400 and S3C6410 SoC range, such
 976 * as ARMCLK as well as the necessary parent clocks.
 977 *
 978 * This call does not setup the clocks, which is left to the
 979 * s3c64xx_setup_clocks() call which may be needed by the cpufreq
 980 * or resume code to re-set the clocks if the bootloader has changed
 981 * them.
 982 */
 983void __init s3c64xx_register_clocks(unsigned long xtal, 
 984                                    unsigned armclk_divlimit)
 985{
 986        unsigned int cnt;
 987
 988        armclk_mask = armclk_divlimit;
 989
 990        s3c24xx_register_baseclocks(xtal);
 991        s3c24xx_register_clocks(clks, ARRAY_SIZE(clks));
 992
 993        s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
 994
 995        s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
 996        s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
 997
 998        s3c24xx_register_clocks(clk_cdev, ARRAY_SIZE(clk_cdev));
 999        for (cnt = 0; cnt < ARRAY_SIZE(clk_cdev); cnt++)
1000                s3c_disable_clocks(clk_cdev[cnt], 1);
1001
1002        s3c24xx_register_clocks(clks1, ARRAY_SIZE(clks1));
1003        s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
1004        for (cnt = 0; cnt < ARRAY_SIZE(clksrc_cdev); cnt++)
1005                s3c_register_clksrc(clksrc_cdev[cnt], 1);
1006        clkdev_add_table(s3c64xx_clk_lookup, ARRAY_SIZE(s3c64xx_clk_lookup));
1007
1008        s3c_pwmclk_init();
1009}
1010