linux/arch/arm/plat-s5pc1xx/s5pc100-clock.c
<<
>>
Prefs
   1/* linux/arch/arm/plat-s5pc1xx/s5pc100-clock.c
   2 *
   3 * Copyright 2009 Samsung Electronics, Co.
   4 *      Byungho Min <bhmin@samsung.com>
   5 *
   6 * S5PC100 based common clock support
   7 *
   8 * Based on plat-s3c64xx/s3c6400-clock.c
   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/kernel.h>
  18#include <linux/list.h>
  19#include <linux/errno.h>
  20#include <linux/err.h>
  21#include <linux/clk.h>
  22#include <linux/sysdev.h>
  23#include <linux/io.h>
  24
  25#include <mach/hardware.h>
  26#include <mach/map.h>
  27
  28#include <plat/cpu-freq.h>
  29
  30#include <plat/regs-clock.h>
  31#include <plat/clock.h>
  32#include <plat/cpu.h>
  33#include <plat/pll.h>
  34#include <plat/devs.h>
  35#include <plat/s5pc100.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        .id             = -1,
  44};
  45
  46#define clk_fin_apll clk_ext_xtal_mux
  47#define clk_fin_mpll clk_ext_xtal_mux
  48#define clk_fin_epll clk_ext_xtal_mux
  49#define clk_fin_hpll clk_ext_xtal_mux
  50
  51#define clk_fout_mpll   clk_mpll
  52
  53struct clk_sources {
  54        unsigned int    nr_sources;
  55        struct clk      **sources;
  56};
  57
  58struct clksrc_clk {
  59        struct clk              clk;
  60        unsigned int            mask;
  61        unsigned int            shift;
  62
  63        struct clk_sources      *sources;
  64
  65        unsigned int            divider_shift;
  66        void __iomem            *reg_divider;
  67        void __iomem            *reg_source;
  68};
  69
  70static int clk_default_setrate(struct clk *clk, unsigned long rate)
  71{
  72        clk->rate = rate;
  73        return 1;
  74}
  75
  76struct clk clk_27m = {
  77        .name           = "clk_27m",
  78        .id             = -1,
  79        .rate           = 27000000,
  80};
  81
  82static int clk_48m_ctrl(struct clk *clk, int enable)
  83{
  84        unsigned long flags;
  85        u32 val;
  86
  87        /* can't rely on clock lock, this register has other usages */
  88        local_irq_save(flags);
  89
  90        val = __raw_readl(S5PC1XX_CLK_SRC1);
  91        if (enable)
  92                val |= S5PC100_CLKSRC1_CLK48M_MASK;
  93        else
  94                val &= ~S5PC100_CLKSRC1_CLK48M_MASK;
  95
  96        __raw_writel(val, S5PC1XX_CLK_SRC1);
  97        local_irq_restore(flags);
  98
  99        return 0;
 100}
 101
 102struct clk clk_48m = {
 103        .name           = "clk_48m",
 104        .id             = -1,
 105        .rate           = 48000000,
 106        .enable         = clk_48m_ctrl,
 107};
 108
 109struct clk clk_54m = {
 110        .name           = "clk_54m",
 111        .id             = -1,
 112        .rate           = 54000000,
 113};
 114
 115struct clk clk_hpll = {
 116        .name           = "hpll",
 117        .id             = -1,
 118};
 119
 120struct clk clk_hd0 = {
 121        .name           = "hclkd0",
 122        .id             = -1,
 123        .rate           = 0,
 124        .parent         = NULL,
 125        .ctrlbit        = 0,
 126        .set_rate       = clk_default_setrate,
 127};
 128
 129struct clk clk_pd0 = {
 130        .name           = "pclkd0",
 131        .id             = -1,
 132        .rate           = 0,
 133        .parent         = NULL,
 134        .ctrlbit        = 0,
 135        .set_rate       = clk_default_setrate,
 136};
 137
 138static int s5pc1xx_clk_gate(void __iomem *reg,
 139                                struct clk *clk,
 140                                int enable)
 141{
 142        unsigned int ctrlbit = clk->ctrlbit;
 143        u32 con;
 144
 145        con = __raw_readl(reg);
 146
 147        if (enable)
 148                con |= ctrlbit;
 149        else
 150                con &= ~ctrlbit;
 151
 152        __raw_writel(con, reg);
 153        return 0;
 154}
 155
 156static int s5pc1xx_clk_d00_ctrl(struct clk *clk, int enable)
 157{
 158        return s5pc1xx_clk_gate(S5PC100_CLKGATE_D00, clk, enable);
 159}
 160
 161static int s5pc1xx_clk_d01_ctrl(struct clk *clk, int enable)
 162{
 163        return s5pc1xx_clk_gate(S5PC100_CLKGATE_D01, clk, enable);
 164}
 165
 166static int s5pc1xx_clk_d02_ctrl(struct clk *clk, int enable)
 167{
 168        return s5pc1xx_clk_gate(S5PC100_CLKGATE_D02, clk, enable);
 169}
 170
 171static int s5pc1xx_clk_d10_ctrl(struct clk *clk, int enable)
 172{
 173        return s5pc1xx_clk_gate(S5PC100_CLKGATE_D10, clk, enable);
 174}
 175
 176static int s5pc1xx_clk_d11_ctrl(struct clk *clk, int enable)
 177{
 178        return s5pc1xx_clk_gate(S5PC100_CLKGATE_D11, clk, enable);
 179}
 180
 181static int s5pc1xx_clk_d12_ctrl(struct clk *clk, int enable)
 182{
 183        return s5pc1xx_clk_gate(S5PC100_CLKGATE_D12, clk, enable);
 184}
 185
 186static int s5pc1xx_clk_d13_ctrl(struct clk *clk, int enable)
 187{
 188        return s5pc1xx_clk_gate(S5PC100_CLKGATE_D13, clk, enable);
 189}
 190
 191static int s5pc1xx_clk_d14_ctrl(struct clk *clk, int enable)
 192{
 193        return s5pc1xx_clk_gate(S5PC100_CLKGATE_D14, clk, enable);
 194}
 195
 196static int s5pc1xx_clk_d15_ctrl(struct clk *clk, int enable)
 197{
 198        return s5pc1xx_clk_gate(S5PC100_CLKGATE_D15, clk, enable);
 199}
 200
 201static int s5pc1xx_clk_d20_ctrl(struct clk *clk, int enable)
 202{
 203        return s5pc1xx_clk_gate(S5PC100_CLKGATE_D20, clk, enable);
 204}
 205
 206int s5pc1xx_sclk0_ctrl(struct clk *clk, int enable)
 207{
 208        return s5pc1xx_clk_gate(S5PC100_SCLKGATE0, clk, enable);
 209}
 210
 211int s5pc1xx_sclk1_ctrl(struct clk *clk, int enable)
 212{
 213        return s5pc1xx_clk_gate(S5PC100_SCLKGATE1, clk, enable);
 214}
 215
 216static struct clk init_clocks_disable[] = {
 217        {
 218                .name           = "dsi",
 219                .id             = -1,
 220                .parent         = &clk_p,
 221                .enable         = s5pc1xx_clk_d11_ctrl,
 222                .ctrlbit        = S5PC100_CLKGATE_D11_DSI,
 223        }, {
 224                .name           = "csi",
 225                .id             = -1,
 226                .parent         = &clk_h,
 227                .enable         = s5pc1xx_clk_d11_ctrl,
 228                .ctrlbit        = S5PC100_CLKGATE_D11_CSI,
 229        }, {
 230                .name           = "ccan0",
 231                .id             = 0,
 232                .parent         = &clk_p,
 233                .enable         = s5pc1xx_clk_d14_ctrl,
 234                .ctrlbit        = S5PC100_CLKGATE_D14_CCAN0,
 235        }, {
 236                .name           = "ccan1",
 237                .id             = 1,
 238                .parent         = &clk_p,
 239                .enable         = s5pc1xx_clk_d14_ctrl,
 240                .ctrlbit        = S5PC100_CLKGATE_D14_CCAN1,
 241        }, {
 242                .name           = "keypad",
 243                .id             = -1,
 244                .parent         = &clk_p,
 245                .enable         = s5pc1xx_clk_d15_ctrl,
 246                .ctrlbit        = S5PC100_CLKGATE_D15_KEYIF,
 247        }, {
 248                .name           = "hclkd2",
 249                .id             = -1,
 250                .parent         = NULL,
 251                .enable         = s5pc1xx_clk_d20_ctrl,
 252                .ctrlbit        = S5PC100_CLKGATE_D20_HCLKD2,
 253        }, {
 254                .name           = "iis-d2",
 255                .id             = -1,
 256                .parent         = NULL,
 257                .enable         = s5pc1xx_clk_d20_ctrl,
 258                .ctrlbit        = S5PC100_CLKGATE_D20_I2SD2,
 259        }, {
 260                .name           = "otg",
 261                .id             = -1,
 262                .parent         = &clk_h,
 263                .enable         = s5pc1xx_clk_d10_ctrl,
 264                .ctrlbit        = S5PC100_CLKGATE_D10_USBOTG,
 265        },
 266};
 267
 268static struct clk init_clocks[] = {
 269        /* System1 (D0_0) devices */
 270        {
 271                .name           = "intc",
 272                .id             = -1,
 273                .parent         = &clk_hd0,
 274                .enable         = s5pc1xx_clk_d00_ctrl,
 275                .ctrlbit        = S5PC100_CLKGATE_D00_INTC,
 276        }, {
 277                .name           = "tzic",
 278                .id             = -1,
 279                .parent         = &clk_hd0,
 280                .enable         = s5pc1xx_clk_d00_ctrl,
 281                .ctrlbit        = S5PC100_CLKGATE_D00_TZIC,
 282        }, {
 283                .name           = "cf-ata",
 284                .id             = -1,
 285                .parent         = &clk_hd0,
 286                .enable         = s5pc1xx_clk_d00_ctrl,
 287                .ctrlbit        = S5PC100_CLKGATE_D00_CFCON,
 288        }, {
 289                .name           = "mdma",
 290                .id             = -1,
 291                .parent         = &clk_hd0,
 292                .enable         = s5pc1xx_clk_d00_ctrl,
 293                .ctrlbit        = S5PC100_CLKGATE_D00_MDMA,
 294        }, {
 295                .name           = "g2d",
 296                .id             = -1,
 297                .parent         = &clk_hd0,
 298                .enable         = s5pc1xx_clk_d00_ctrl,
 299                .ctrlbit        = S5PC100_CLKGATE_D00_G2D,
 300        }, {
 301                .name           = "secss",
 302                .id             = -1,
 303                .parent         = &clk_hd0,
 304                .enable         = s5pc1xx_clk_d00_ctrl,
 305                .ctrlbit        = S5PC100_CLKGATE_D00_SECSS,
 306        }, {
 307                .name           = "cssys",
 308                .id             = -1,
 309                .parent         = &clk_hd0,
 310                .enable         = s5pc1xx_clk_d00_ctrl,
 311                .ctrlbit        = S5PC100_CLKGATE_D00_CSSYS,
 312        },
 313
 314        /* Memory (D0_1) devices */
 315        {
 316                .name           = "dmc",
 317                .id             = -1,
 318                .parent         = &clk_hd0,
 319                .enable         = s5pc1xx_clk_d01_ctrl,
 320                .ctrlbit        = S5PC100_CLKGATE_D01_DMC,
 321        }, {
 322                .name           = "sromc",
 323                .id             = -1,
 324                .parent         = &clk_hd0,
 325                .enable         = s5pc1xx_clk_d01_ctrl,
 326                .ctrlbit        = S5PC100_CLKGATE_D01_SROMC,
 327        }, {
 328                .name           = "onenand",
 329                .id             = -1,
 330                .parent         = &clk_hd0,
 331                .enable         = s5pc1xx_clk_d01_ctrl,
 332                .ctrlbit        = S5PC100_CLKGATE_D01_ONENAND,
 333        }, {
 334                .name           = "nand",
 335                .id             = -1,
 336                .parent         = &clk_hd0,
 337                .enable         = s5pc1xx_clk_d01_ctrl,
 338                .ctrlbit        = S5PC100_CLKGATE_D01_NFCON,
 339        }, {
 340                .name           = "intmem",
 341                .id             = -1,
 342                .parent         = &clk_hd0,
 343                .enable         = s5pc1xx_clk_d01_ctrl,
 344                .ctrlbit        = S5PC100_CLKGATE_D01_INTMEM,
 345        }, {
 346                .name           = "ebi",
 347                .id             = -1,
 348                .parent         = &clk_hd0,
 349                .enable         = s5pc1xx_clk_d01_ctrl,
 350                .ctrlbit        = S5PC100_CLKGATE_D01_EBI,
 351        },
 352
 353        /* System2 (D0_2) devices */
 354        {
 355                .name           = "seckey",
 356                .id             = -1,
 357                .parent         = &clk_pd0,
 358                .enable         = s5pc1xx_clk_d02_ctrl,
 359                .ctrlbit        = S5PC100_CLKGATE_D02_SECKEY,
 360        }, {
 361                .name           = "sdm",
 362                .id             = -1,
 363                .parent         = &clk_hd0,
 364                .enable         = s5pc1xx_clk_d02_ctrl,
 365                .ctrlbit        = S5PC100_CLKGATE_D02_SDM,
 366        },
 367
 368        /* File (D1_0) devices */
 369        {
 370                .name           = "pdma0",
 371                .id             = -1,
 372                .parent         = &clk_h,
 373                .enable         = s5pc1xx_clk_d10_ctrl,
 374                .ctrlbit        = S5PC100_CLKGATE_D10_PDMA0,
 375        }, {
 376                .name           = "pdma1",
 377                .id             = -1,
 378                .parent         = &clk_h,
 379                .enable         = s5pc1xx_clk_d10_ctrl,
 380                .ctrlbit        = S5PC100_CLKGATE_D10_PDMA1,
 381        }, {
 382                .name           = "usb-host",
 383                .id             = -1,
 384                .parent         = &clk_h,
 385                .enable         = s5pc1xx_clk_d10_ctrl,
 386                .ctrlbit        = S5PC100_CLKGATE_D10_USBHOST,
 387        }, {
 388                .name           = "modem",
 389                .id             = -1,
 390                .parent         = &clk_h,
 391                .enable         = s5pc1xx_clk_d10_ctrl,
 392                .ctrlbit        = S5PC100_CLKGATE_D10_MODEMIF,
 393        }, {
 394                .name           = "hsmmc",
 395                .id             = 0,
 396                .parent         = &clk_h,
 397                .enable         = s5pc1xx_clk_d10_ctrl,
 398                .ctrlbit        = S5PC100_CLKGATE_D10_HSMMC0,
 399        }, {
 400                .name           = "hsmmc",
 401                .id             = 1,
 402                .parent         = &clk_h,
 403                .enable         = s5pc1xx_clk_d10_ctrl,
 404                .ctrlbit        = S5PC100_CLKGATE_D10_HSMMC1,
 405        }, {
 406                .name           = "hsmmc",
 407                .id             = 2,
 408                .parent         = &clk_h,
 409                .enable         = s5pc1xx_clk_d10_ctrl,
 410                .ctrlbit        = S5PC100_CLKGATE_D10_HSMMC2,
 411        },
 412
 413        /* Multimedia1 (D1_1) devices */
 414        {
 415                .name           = "lcd",
 416                .id             = -1,
 417                .parent         = &clk_h,
 418                .enable         = s5pc1xx_clk_d11_ctrl,
 419                .ctrlbit        = S5PC100_CLKGATE_D11_LCD,
 420        }, {
 421                .name           = "rotator",
 422                .id             = -1,
 423                .parent         = &clk_h,
 424                .enable         = s5pc1xx_clk_d11_ctrl,
 425                .ctrlbit        = S5PC100_CLKGATE_D11_ROTATOR,
 426        }, {
 427                .name           = "fimc",
 428                .id             = 0,
 429                .parent         = &clk_h,
 430                .enable         = s5pc1xx_clk_d11_ctrl,
 431                .ctrlbit        = S5PC100_CLKGATE_D11_FIMC0,
 432        }, {
 433                .name           = "fimc",
 434                .id             = 1,
 435                .parent         = &clk_h,
 436                .enable         = s5pc1xx_clk_d11_ctrl,
 437                .ctrlbit        = S5PC100_CLKGATE_D11_FIMC1,
 438        }, {
 439                .name           = "fimc",
 440                .id             = 2,
 441                .parent         = &clk_h,
 442                .enable         = s5pc1xx_clk_d11_ctrl,
 443                .ctrlbit        = S5PC100_CLKGATE_D11_FIMC2,
 444        }, {
 445                .name           = "jpeg",
 446                .id             = -1,
 447                .parent         = &clk_h,
 448                .enable         = s5pc1xx_clk_d11_ctrl,
 449                .ctrlbit        = S5PC100_CLKGATE_D11_JPEG,
 450        }, {
 451                .name           = "g3d",
 452                .id             = -1,
 453                .parent         = &clk_h,
 454                .enable         = s5pc1xx_clk_d11_ctrl,
 455                .ctrlbit        = S5PC100_CLKGATE_D11_G3D,
 456        },
 457
 458        /* Multimedia2 (D1_2) devices */
 459        {
 460                .name           = "tv",
 461                .id             = -1,
 462                .parent         = &clk_h,
 463                .enable         = s5pc1xx_clk_d12_ctrl,
 464                .ctrlbit        = S5PC100_CLKGATE_D12_TV,
 465        }, {
 466                .name           = "vp",
 467                .id             = -1,
 468                .parent         = &clk_h,
 469                .enable         = s5pc1xx_clk_d12_ctrl,
 470                .ctrlbit        = S5PC100_CLKGATE_D12_VP,
 471        }, {
 472                .name           = "mixer",
 473                .id             = -1,
 474                .parent         = &clk_h,
 475                .enable         = s5pc1xx_clk_d12_ctrl,
 476                .ctrlbit        = S5PC100_CLKGATE_D12_MIXER,
 477        }, {
 478                .name           = "hdmi",
 479                .id             = -1,
 480                .parent         = &clk_h,
 481                .enable         = s5pc1xx_clk_d12_ctrl,
 482                .ctrlbit        = S5PC100_CLKGATE_D12_HDMI,
 483        }, {
 484                .name           = "mfc",
 485                .id             = -1,
 486                .parent         = &clk_h,
 487                .enable         = s5pc1xx_clk_d12_ctrl,
 488                .ctrlbit        = S5PC100_CLKGATE_D12_MFC,
 489        },
 490
 491        /* System (D1_3) devices */
 492        {
 493                .name           = "chipid",
 494                .id             = -1,
 495                .parent         = &clk_p,
 496                .enable         = s5pc1xx_clk_d13_ctrl,
 497                .ctrlbit        = S5PC100_CLKGATE_D13_CHIPID,
 498        }, {
 499                .name           = "gpio",
 500                .id             = -1,
 501                .parent         = &clk_p,
 502                .enable         = s5pc1xx_clk_d13_ctrl,
 503                .ctrlbit        = S5PC100_CLKGATE_D13_GPIO,
 504        }, {
 505                .name           = "apc",
 506                .id             = -1,
 507                .parent         = &clk_p,
 508                .enable         = s5pc1xx_clk_d13_ctrl,
 509                .ctrlbit        = S5PC100_CLKGATE_D13_APC,
 510        }, {
 511                .name           = "iec",
 512                .id             = -1,
 513                .parent         = &clk_p,
 514                .enable         = s5pc1xx_clk_d13_ctrl,
 515                .ctrlbit        = S5PC100_CLKGATE_D13_IEC,
 516        }, {
 517                .name           = "timers",
 518                .id             = -1,
 519                .parent         = &clk_p,
 520                .enable         = s5pc1xx_clk_d13_ctrl,
 521                .ctrlbit        = S5PC100_CLKGATE_D13_PWM,
 522        }, {
 523                .name           = "systimer",
 524                .id             = -1,
 525                .parent         = &clk_p,
 526                .enable         = s5pc1xx_clk_d13_ctrl,
 527                .ctrlbit        = S5PC100_CLKGATE_D13_SYSTIMER,
 528        }, {
 529                .name           = "watchdog",
 530                .id             = -1,
 531                .parent         = &clk_p,
 532                .enable         = s5pc1xx_clk_d13_ctrl,
 533                .ctrlbit        = S5PC100_CLKGATE_D13_WDT,
 534        }, {
 535                .name           = "rtc",
 536                .id             = -1,
 537                .parent         = &clk_p,
 538                .enable         = s5pc1xx_clk_d13_ctrl,
 539                .ctrlbit        = S5PC100_CLKGATE_D13_RTC,
 540        },
 541
 542        /* Connectivity (D1_4) devices */
 543        {
 544                .name           = "uart",
 545                .id             = 0,
 546                .parent         = &clk_p,
 547                .enable         = s5pc1xx_clk_d14_ctrl,
 548                .ctrlbit        = S5PC100_CLKGATE_D14_UART0,
 549        }, {
 550                .name           = "uart",
 551                .id             = 1,
 552                .parent         = &clk_p,
 553                .enable         = s5pc1xx_clk_d14_ctrl,
 554                .ctrlbit        = S5PC100_CLKGATE_D14_UART1,
 555        }, {
 556                .name           = "uart",
 557                .id             = 2,
 558                .parent         = &clk_p,
 559                .enable         = s5pc1xx_clk_d14_ctrl,
 560                .ctrlbit        = S5PC100_CLKGATE_D14_UART2,
 561        }, {
 562                .name           = "uart",
 563                .id             = 3,
 564                .parent         = &clk_p,
 565                .enable         = s5pc1xx_clk_d14_ctrl,
 566                .ctrlbit        = S5PC100_CLKGATE_D14_UART3,
 567        }, {
 568                .name           = "i2c",
 569                .id             = -1,
 570                .parent         = &clk_p,
 571                .enable         = s5pc1xx_clk_d14_ctrl,
 572                .ctrlbit        = S5PC100_CLKGATE_D14_IIC,
 573        }, {
 574                .name           = "hdmi-i2c",
 575                .id             = -1,
 576                .parent         = &clk_p,
 577                .enable         = s5pc1xx_clk_d14_ctrl,
 578                .ctrlbit        = S5PC100_CLKGATE_D14_HDMI_IIC,
 579        }, {
 580                .name           = "spi",
 581                .id             = 0,
 582                .parent         = &clk_p,
 583                .enable         = s5pc1xx_clk_d14_ctrl,
 584                .ctrlbit        = S5PC100_CLKGATE_D14_SPI0,
 585        }, {
 586                .name           = "spi",
 587                .id             = 1,
 588                .parent         = &clk_p,
 589                .enable         = s5pc1xx_clk_d14_ctrl,
 590                .ctrlbit        = S5PC100_CLKGATE_D14_SPI1,
 591        }, {
 592                .name           = "spi",
 593                .id             = 2,
 594                .parent         = &clk_p,
 595                .enable         = s5pc1xx_clk_d14_ctrl,
 596                .ctrlbit        = S5PC100_CLKGATE_D14_SPI2,
 597        }, {
 598                .name           = "irda",
 599                .id             = -1,
 600                .parent         = &clk_p,
 601                .enable         = s5pc1xx_clk_d14_ctrl,
 602                .ctrlbit        = S5PC100_CLKGATE_D14_IRDA,
 603        }, {
 604                .name           = "hsitx",
 605                .id             = -1,
 606                .parent         = &clk_p,
 607                .enable         = s5pc1xx_clk_d14_ctrl,
 608                .ctrlbit        = S5PC100_CLKGATE_D14_HSITX,
 609        }, {
 610                .name           = "hsirx",
 611                .id             = -1,
 612                .parent         = &clk_p,
 613                .enable         = s5pc1xx_clk_d14_ctrl,
 614                .ctrlbit        = S5PC100_CLKGATE_D14_HSIRX,
 615        },
 616
 617        /* Audio (D1_5) devices */
 618        {
 619                .name           = "iis",
 620                .id             = 0,
 621                .parent         = &clk_p,
 622                .enable         = s5pc1xx_clk_d15_ctrl,
 623                .ctrlbit        = S5PC100_CLKGATE_D15_IIS0,
 624        }, {
 625                .name           = "iis",
 626                .id             = 1,
 627                .parent         = &clk_p,
 628                .enable         = s5pc1xx_clk_d15_ctrl,
 629                .ctrlbit        = S5PC100_CLKGATE_D15_IIS1,
 630        }, {
 631                .name           = "iis",
 632                .id             = 2,
 633                .parent         = &clk_p,
 634                .enable         = s5pc1xx_clk_d15_ctrl,
 635                .ctrlbit        = S5PC100_CLKGATE_D15_IIS2,
 636        }, {
 637                .name           = "ac97",
 638                .id             = -1,
 639                .parent         = &clk_p,
 640                .enable         = s5pc1xx_clk_d15_ctrl,
 641                .ctrlbit        = S5PC100_CLKGATE_D15_AC97,
 642        }, {
 643                .name           = "pcm",
 644                .id             = 0,
 645                .parent         = &clk_p,
 646                .enable         = s5pc1xx_clk_d15_ctrl,
 647                .ctrlbit        = S5PC100_CLKGATE_D15_PCM0,
 648        }, {
 649                .name           = "pcm",
 650                .id             = 1,
 651                .parent         = &clk_p,
 652                .enable         = s5pc1xx_clk_d15_ctrl,
 653                .ctrlbit        = S5PC100_CLKGATE_D15_PCM1,
 654        }, {
 655                .name           = "spdif",
 656                .id             = -1,
 657                .parent         = &clk_p,
 658                .enable         = s5pc1xx_clk_d15_ctrl,
 659                .ctrlbit        = S5PC100_CLKGATE_D15_SPDIF,
 660        }, {
 661                .name           = "adc",
 662                .id             = -1,
 663                .parent         = &clk_p,
 664                .enable         = s5pc1xx_clk_d15_ctrl,
 665                .ctrlbit        = S5PC100_CLKGATE_D15_TSADC,
 666        }, {
 667                .name           = "keyif",
 668                .id             = -1,
 669                .parent         = &clk_p,
 670                .enable         = s5pc1xx_clk_d15_ctrl,
 671                .ctrlbit        = S5PC100_CLKGATE_D15_KEYIF,
 672        }, {
 673                .name           = "cg",
 674                .id             = -1,
 675                .parent         = &clk_p,
 676                .enable         = s5pc1xx_clk_d15_ctrl,
 677                .ctrlbit        = S5PC100_CLKGATE_D15_CG,
 678        },
 679
 680        /* Audio (D2_0) devices: all disabled */
 681
 682        /* Special Clocks 1 */
 683        {
 684                .name           = "sclk_hpm",
 685                .id             = -1,
 686                .parent         = NULL,
 687                .enable         = s5pc1xx_sclk0_ctrl,
 688                .ctrlbit        = S5PC1XX_CLKGATE_SCLK0_HPM,
 689        }, {
 690                .name           = "sclk_onenand",
 691                .id             = -1,
 692                .parent         = NULL,
 693                .enable         = s5pc1xx_sclk0_ctrl,
 694                .ctrlbit        = S5PC100_CLKGATE_SCLK0_ONENAND,
 695        }, {
 696                .name           = "sclk_spi_48",
 697                .id             = 0,
 698                .parent         = &clk_48m,
 699                .enable         = s5pc1xx_sclk0_ctrl,
 700                .ctrlbit        = S5PC100_CLKGATE_SCLK0_SPI0_48,
 701        }, {
 702                .name           = "sclk_spi_48",
 703                .id             = 1,
 704                .parent         = &clk_48m,
 705                .enable         = s5pc1xx_sclk0_ctrl,
 706                .ctrlbit        = S5PC100_CLKGATE_SCLK0_SPI1_48,
 707        }, {
 708                .name           = "sclk_spi_48",
 709                .id             = 2,
 710                .parent         = &clk_48m,
 711                .enable         = s5pc1xx_sclk0_ctrl,
 712                .ctrlbit        = S5PC100_CLKGATE_SCLK0_SPI2_48,
 713        }, {
 714                .name           = "sclk_mmc_48",
 715                .id             = 0,
 716                .parent         = &clk_48m,
 717                .enable         = s5pc1xx_sclk0_ctrl,
 718                .ctrlbit        = S5PC100_CLKGATE_SCLK0_MMC0_48,
 719        }, {
 720                .name           = "sclk_mmc_48",
 721                .id             = 1,
 722                .parent         = &clk_48m,
 723                .enable         = s5pc1xx_sclk0_ctrl,
 724                .ctrlbit        = S5PC100_CLKGATE_SCLK0_MMC1_48,
 725        }, {
 726                .name           = "sclk_mmc_48",
 727                .id             = 2,
 728                .parent         = &clk_48m,
 729                .enable         = s5pc1xx_sclk0_ctrl,
 730                .ctrlbit        = S5PC100_CLKGATE_SCLK0_MMC2_48,
 731        },
 732
 733        /* Special Clocks 2 */
 734        {
 735                .name           = "sclk_tv_54",
 736                .id             = -1,
 737                .parent         = &clk_54m,
 738                .enable         = s5pc1xx_sclk1_ctrl,
 739                .ctrlbit        = S5PC100_CLKGATE_SCLK1_TV54,
 740        }, {
 741                .name           = "sclk_vdac_54",
 742                .id             = -1,
 743                .parent         = &clk_54m,
 744                .enable         = s5pc1xx_sclk1_ctrl,
 745                .ctrlbit        = S5PC100_CLKGATE_SCLK1_VDAC54,
 746        }, {
 747                .name           = "sclk_spdif",
 748                .id             = -1,
 749                .parent         = NULL,
 750                .enable         = s5pc1xx_sclk1_ctrl,
 751                .ctrlbit        = S5PC100_CLKGATE_SCLK1_SPDIF,
 752        },
 753};
 754
 755void __init s5pc1xx_register_clocks(void)
 756{
 757        struct clk *clkp;
 758        int ret;
 759        int ptr;
 760
 761        clkp = init_clocks;
 762        for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++, clkp++) {
 763                ret = s3c24xx_register_clock(clkp);
 764                if (ret < 0) {
 765                        printk(KERN_ERR "Failed to register clock %s (%d)\n",
 766                               clkp->name, ret);
 767                }
 768        }
 769
 770        clkp = init_clocks_disable;
 771        for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) {
 772
 773                ret = s3c24xx_register_clock(clkp);
 774                if (ret < 0) {
 775                        printk(KERN_ERR "Failed to register clock %s (%d)\n",
 776                               clkp->name, ret);
 777                }
 778
 779                (clkp->enable)(clkp, 0);
 780        }
 781
 782        s3c_pwmclk_init();
 783}
 784static struct clk clk_fout_apll = {
 785        .name           = "fout_apll",
 786        .id             = -1,
 787};
 788
 789static struct clk *clk_src_apll_list[] = {
 790        [0] = &clk_fin_apll,
 791        [1] = &clk_fout_apll,
 792};
 793
 794static struct clk_sources clk_src_apll = {
 795        .sources        = clk_src_apll_list,
 796        .nr_sources     = ARRAY_SIZE(clk_src_apll_list),
 797};
 798
 799static struct clksrc_clk clk_mout_apll = {
 800        .clk    = {
 801                .name           = "mout_apll",
 802                .id             = -1,
 803        },
 804        .shift          = S5PC1XX_CLKSRC0_APLL_SHIFT,
 805        .mask           = S5PC1XX_CLKSRC0_APLL_MASK,
 806        .sources        = &clk_src_apll,
 807        .reg_source     = S5PC1XX_CLK_SRC0,
 808};
 809
 810static struct clk clk_fout_epll = {
 811        .name           = "fout_epll",
 812        .id             = -1,
 813};
 814
 815static struct clk *clk_src_epll_list[] = {
 816        [0] = &clk_fin_epll,
 817        [1] = &clk_fout_epll,
 818};
 819
 820static struct clk_sources clk_src_epll = {
 821        .sources        = clk_src_epll_list,
 822        .nr_sources     = ARRAY_SIZE(clk_src_epll_list),
 823};
 824
 825static struct clksrc_clk clk_mout_epll = {
 826        .clk    = {
 827                .name           = "mout_epll",
 828                .id             = -1,
 829        },
 830        .shift          = S5PC1XX_CLKSRC0_EPLL_SHIFT,
 831        .mask           = S5PC1XX_CLKSRC0_EPLL_MASK,
 832        .sources        = &clk_src_epll,
 833        .reg_source     = S5PC1XX_CLK_SRC0,
 834};
 835
 836static struct clk *clk_src_mpll_list[] = {
 837        [0] = &clk_fin_mpll,
 838        [1] = &clk_fout_mpll,
 839};
 840
 841static struct clk_sources clk_src_mpll = {
 842        .sources        = clk_src_mpll_list,
 843        .nr_sources     = ARRAY_SIZE(clk_src_mpll_list),
 844};
 845
 846static struct clksrc_clk clk_mout_mpll = {
 847        .clk = {
 848                .name           = "mout_mpll",
 849                .id             = -1,
 850        },
 851        .shift          = S5PC1XX_CLKSRC0_MPLL_SHIFT,
 852        .mask           = S5PC1XX_CLKSRC0_MPLL_MASK,
 853        .sources        = &clk_src_mpll,
 854        .reg_source     = S5PC1XX_CLK_SRC0,
 855};
 856
 857static unsigned long s5pc1xx_clk_doutmpll_get_rate(struct clk *clk)
 858{
 859        unsigned long rate = clk_get_rate(clk->parent);
 860        unsigned long clkdiv;
 861
 862        printk(KERN_DEBUG "%s: parent is %ld\n", __func__, rate);
 863
 864        clkdiv = __raw_readl(S5PC1XX_CLK_DIV1) & S5PC100_CLKDIV1_MPLL_MASK;
 865        rate /= (clkdiv >> S5PC100_CLKDIV1_MPLL_SHIFT) + 1;
 866
 867        return rate;
 868}
 869
 870static struct clk clk_dout_mpll = {
 871        .name           = "dout_mpll",
 872        .id             = -1,
 873        .parent         = &clk_mout_mpll.clk,
 874        .get_rate       = s5pc1xx_clk_doutmpll_get_rate,
 875};
 876
 877static unsigned long s5pc1xx_clk_doutmpll2_get_rate(struct clk *clk)
 878{
 879        unsigned long rate = clk_get_rate(clk->parent);
 880        unsigned long clkdiv;
 881
 882        printk(KERN_DEBUG "%s: parent is %ld\n", __func__, rate);
 883
 884        clkdiv = __raw_readl(S5PC1XX_CLK_DIV1) & S5PC100_CLKDIV1_MPLL2_MASK;
 885        rate /= (clkdiv >> S5PC100_CLKDIV1_MPLL2_SHIFT) + 1;
 886
 887        return rate;
 888}
 889
 890struct clk clk_dout_mpll2 = {
 891        .name           = "dout_mpll2",
 892        .id             = -1,
 893        .parent         = &clk_mout_mpll.clk,
 894        .get_rate       = s5pc1xx_clk_doutmpll2_get_rate,
 895};
 896
 897static struct clk *clkset_uart_list[] = {
 898        &clk_mout_epll.clk,
 899        &clk_dout_mpll,
 900        NULL,
 901        NULL
 902};
 903
 904static struct clk_sources clkset_uart = {
 905        .sources        = clkset_uart_list,
 906        .nr_sources     = ARRAY_SIZE(clkset_uart_list),
 907};
 908
 909static inline struct clksrc_clk *to_clksrc(struct clk *clk)
 910{
 911        return container_of(clk, struct clksrc_clk, clk);
 912}
 913
 914static unsigned long s5pc1xx_getrate_clksrc(struct clk *clk)
 915{
 916        struct clksrc_clk *sclk = to_clksrc(clk);
 917        unsigned long rate = clk_get_rate(clk->parent);
 918        u32 clkdiv = __raw_readl(sclk->reg_divider);
 919
 920        clkdiv >>= sclk->divider_shift;
 921        clkdiv &= 0xf;
 922        clkdiv++;
 923
 924        rate /= clkdiv;
 925        return rate;
 926}
 927
 928static int s5pc1xx_setrate_clksrc(struct clk *clk, unsigned long rate)
 929{
 930        struct clksrc_clk *sclk = to_clksrc(clk);
 931        void __iomem *reg = sclk->reg_divider;
 932        unsigned int div;
 933        u32 val;
 934
 935        rate = clk_round_rate(clk, rate);
 936        div = clk_get_rate(clk->parent) / rate;
 937        if (div > 16)
 938                return -EINVAL;
 939
 940        val = __raw_readl(reg);
 941        val &= ~(0xf << sclk->shift);
 942        val |= (div - 1) << sclk->shift;
 943        __raw_writel(val, reg);
 944
 945        return 0;
 946}
 947
 948static int s5pc1xx_setparent_clksrc(struct clk *clk, struct clk *parent)
 949{
 950        struct clksrc_clk *sclk = to_clksrc(clk);
 951        struct clk_sources *srcs = sclk->sources;
 952        u32 clksrc = __raw_readl(sclk->reg_source);
 953        int src_nr = -1;
 954        int ptr;
 955
 956        for (ptr = 0; ptr < srcs->nr_sources; ptr++)
 957                if (srcs->sources[ptr] == parent) {
 958                        src_nr = ptr;
 959                        break;
 960                }
 961
 962        if (src_nr >= 0) {
 963                clksrc &= ~sclk->mask;
 964                clksrc |= src_nr << sclk->shift;
 965
 966                __raw_writel(clksrc, sclk->reg_source);
 967                return 0;
 968        }
 969
 970        return -EINVAL;
 971}
 972
 973static unsigned long s5pc1xx_roundrate_clksrc(struct clk *clk,
 974                                              unsigned long rate)
 975{
 976        unsigned long parent_rate = clk_get_rate(clk->parent);
 977        int div;
 978
 979        if (rate > parent_rate)
 980                rate = parent_rate;
 981        else {
 982                div = rate / parent_rate;
 983
 984                if (div == 0)
 985                        div = 1;
 986                if (div > 16)
 987                        div = 16;
 988
 989                rate = parent_rate / div;
 990        }
 991
 992        return rate;
 993}
 994
 995static struct clksrc_clk clk_uart_uclk1 = {
 996        .clk    = {
 997                .name           = "uclk1",
 998                .id             = -1,
 999                .ctrlbit        = S5PC100_CLKGATE_SCLK0_UART,
1000                .enable         = s5pc1xx_sclk0_ctrl,
1001                .set_parent     = s5pc1xx_setparent_clksrc,
1002                .get_rate       = s5pc1xx_getrate_clksrc,
1003                .set_rate       = s5pc1xx_setrate_clksrc,
1004                .round_rate     = s5pc1xx_roundrate_clksrc,
1005        },
1006        .shift          = S5PC100_CLKSRC1_UART_SHIFT,
1007        .mask           = S5PC100_CLKSRC1_UART_MASK,
1008        .sources        = &clkset_uart,
1009        .divider_shift  = S5PC100_CLKDIV2_UART_SHIFT,
1010        .reg_divider    = S5PC1XX_CLK_DIV2,
1011        .reg_source     = S5PC1XX_CLK_SRC1,
1012};
1013
1014/* Clock initialisation code */
1015
1016static struct clksrc_clk *init_parents[] = {
1017        &clk_mout_apll,
1018        &clk_mout_epll,
1019        &clk_mout_mpll,
1020        &clk_uart_uclk1,
1021};
1022
1023static void __init_or_cpufreq s5pc1xx_set_clksrc(struct clksrc_clk *clk)
1024{
1025        struct clk_sources *srcs = clk->sources;
1026        u32 clksrc = __raw_readl(clk->reg_source);
1027
1028        clksrc &= clk->mask;
1029        clksrc >>= clk->shift;
1030
1031        if (clksrc > srcs->nr_sources || !srcs->sources[clksrc]) {
1032                printk(KERN_ERR "%s: bad source %d\n",
1033                       clk->clk.name, clksrc);
1034                return;
1035        }
1036
1037        clk->clk.parent = srcs->sources[clksrc];
1038
1039        printk(KERN_INFO "%s: source is %s (%d), rate is %ld\n",
1040               clk->clk.name, clk->clk.parent->name, clksrc,
1041               clk_get_rate(&clk->clk));
1042}
1043
1044#define GET_DIV(clk, field) ((((clk) & field##_MASK) >> field##_SHIFT) + 1)
1045
1046void __init_or_cpufreq s5pc100_setup_clocks(void)
1047{
1048        struct clk *xtal_clk;
1049        unsigned long xtal;
1050        unsigned long armclk;
1051        unsigned long hclkd0;
1052        unsigned long hclk;
1053        unsigned long pclkd0;
1054        unsigned long pclk;
1055        unsigned long apll;
1056        unsigned long mpll;
1057        unsigned long hpll;
1058        unsigned long epll;
1059        unsigned int ptr;
1060        u32 clkdiv0, clkdiv1;
1061
1062        printk(KERN_DEBUG "%s: registering clocks\n", __func__);
1063
1064        clkdiv0 = __raw_readl(S5PC1XX_CLK_DIV0);
1065        clkdiv1 = __raw_readl(S5PC1XX_CLK_DIV1);
1066
1067        printk(KERN_DEBUG "%s: clkdiv0 = %08x, clkdiv1 = %08x\n",
1068                        __func__, clkdiv0, clkdiv1);
1069
1070        xtal_clk = clk_get(NULL, "xtal");
1071        BUG_ON(IS_ERR(xtal_clk));
1072
1073        xtal = clk_get_rate(xtal_clk);
1074        clk_put(xtal_clk);
1075
1076        printk(KERN_DEBUG "%s: xtal is %ld\n", __func__, xtal);
1077
1078        apll = s5pc1xx_get_pll(xtal, __raw_readl(S5PC1XX_APLL_CON));
1079        mpll = s5pc1xx_get_pll(xtal, __raw_readl(S5PC1XX_MPLL_CON));
1080        epll = s5pc1xx_get_pll(xtal, __raw_readl(S5PC1XX_EPLL_CON));
1081        hpll = s5pc1xx_get_pll(xtal, __raw_readl(S5PC100_HPLL_CON));
1082
1083        printk(KERN_INFO "S5PC100: PLL settings, A=%ld, M=%ld, E=%ld, H=%ld\n",
1084               apll, mpll, epll, hpll);
1085
1086        armclk = apll / GET_DIV(clkdiv0, S5PC1XX_CLKDIV0_APLL);
1087        armclk = armclk / GET_DIV(clkdiv0, S5PC100_CLKDIV0_ARM);
1088        hclkd0 = armclk / GET_DIV(clkdiv0, S5PC100_CLKDIV0_D0);
1089        pclkd0 = hclkd0 / GET_DIV(clkdiv0, S5PC100_CLKDIV0_PCLKD0);
1090        hclk = mpll / GET_DIV(clkdiv1, S5PC100_CLKDIV1_D1);
1091        pclk = hclk / GET_DIV(clkdiv1, S5PC100_CLKDIV1_PCLKD1);
1092
1093        printk(KERN_INFO "S5PC100: ARMCLK=%ld, HCLKD0=%ld, PCLKD0=%ld, HCLK=%ld, PCLK=%ld\n",
1094               armclk, hclkd0, pclkd0, hclk, pclk);
1095
1096        clk_fout_apll.rate = apll;
1097        clk_fout_mpll.rate = mpll;
1098        clk_fout_epll.rate = epll;
1099        clk_fout_apll.rate = apll;
1100
1101        clk_h.rate = hclk;
1102        clk_p.rate = pclk;
1103
1104        for (ptr = 0; ptr < ARRAY_SIZE(init_parents); ptr++)
1105                s5pc1xx_set_clksrc(init_parents[ptr]);
1106}
1107
1108static struct clk *clks[] __initdata = {
1109        &clk_ext_xtal_mux,
1110        &clk_mout_epll.clk,
1111        &clk_fout_epll,
1112        &clk_mout_mpll.clk,
1113        &clk_dout_mpll,
1114        &clk_uart_uclk1.clk,
1115        &clk_ext,
1116        &clk_epll,
1117        &clk_27m,
1118        &clk_48m,
1119        &clk_54m,
1120};
1121
1122void __init s5pc100_register_clocks(void)
1123{
1124        struct clk *clkp;
1125        int ret;
1126        int ptr;
1127
1128        for (ptr = 0; ptr < ARRAY_SIZE(clks); ptr++) {
1129                clkp = clks[ptr];
1130                ret = s3c24xx_register_clock(clkp);
1131                if (ret < 0) {
1132                        printk(KERN_ERR "Failed to register clock %s (%d)\n",
1133                               clkp->name, ret);
1134                }
1135        }
1136
1137        clk_mpll.parent = &clk_mout_mpll.clk;
1138        clk_epll.parent = &clk_mout_epll.clk;
1139}
1140
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.