linux/arch/arm/mach-imx/clock-imx21.c
<<
>>
Prefs
   1/*
   2 * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
   3 * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
   4 * Copyright 2008 Martin Fuzzey, mfuzzey@gmail.com
   5 *
   6 * This program is free software; you can redistribute it and/or
   7 * modify it under the terms of the GNU General Public License
   8 * as published by the Free Software Foundation; either version 2
   9 * of the License, or (at your option) any later version.
  10 * This program is distributed in the hope that it will be useful,
  11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13 * GNU General Public License for more details.
  14 *
  15 * You should have received a copy of the GNU General Public License
  16 * along with this program; if not, write to the Free Software
  17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  18 * MA 02110-1301, USA.
  19 */
  20
  21#include <linux/clk.h>
  22#include <linux/io.h>
  23#include <linux/module.h>
  24#include <linux/clkdev.h>
  25
  26#include <mach/clock.h>
  27#include <mach/hardware.h>
  28#include <mach/common.h>
  29#include <asm/div64.h>
  30
  31#define IO_ADDR_CCM(off)        (MX21_IO_ADDRESS(MX21_CCM_BASE_ADDR + (off)))
  32
  33/* Register offsets */
  34#define CCM_CSCR                IO_ADDR_CCM(0x0)
  35#define CCM_MPCTL0              IO_ADDR_CCM(0x4)
  36#define CCM_MPCTL1              IO_ADDR_CCM(0x8)
  37#define CCM_SPCTL0              IO_ADDR_CCM(0xc)
  38#define CCM_SPCTL1              IO_ADDR_CCM(0x10)
  39#define CCM_OSC26MCTL           IO_ADDR_CCM(0x14)
  40#define CCM_PCDR0               IO_ADDR_CCM(0x18)
  41#define CCM_PCDR1               IO_ADDR_CCM(0x1c)
  42#define CCM_PCCR0               IO_ADDR_CCM(0x20)
  43#define CCM_PCCR1               IO_ADDR_CCM(0x24)
  44#define CCM_CCSR                IO_ADDR_CCM(0x28)
  45#define CCM_PMCTL               IO_ADDR_CCM(0x2c)
  46#define CCM_PMCOUNT             IO_ADDR_CCM(0x30)
  47#define CCM_WKGDCTL             IO_ADDR_CCM(0x34)
  48
  49#define CCM_CSCR_PRESC_OFFSET   29
  50#define CCM_CSCR_PRESC_MASK     (0x7 << CCM_CSCR_PRESC_OFFSET)
  51
  52#define CCM_CSCR_USB_OFFSET     26
  53#define CCM_CSCR_USB_MASK       (0x7 << CCM_CSCR_USB_OFFSET)
  54#define CCM_CSCR_SD_OFFSET      24
  55#define CCM_CSCR_SD_MASK        (0x3 << CCM_CSCR_SD_OFFSET)
  56#define CCM_CSCR_SPLLRES        (1 << 22)
  57#define CCM_CSCR_MPLLRES        (1 << 21)
  58#define CCM_CSCR_SSI2_OFFSET    20
  59#define CCM_CSCR_SSI2           (1 << CCM_CSCR_SSI2_OFFSET)
  60#define CCM_CSCR_SSI1_OFFSET    19
  61#define CCM_CSCR_SSI1           (1 << CCM_CSCR_SSI1_OFFSET)
  62#define CCM_CSCR_FIR_OFFSET     18
  63#define CCM_CSCR_FIR            (1 << CCM_CSCR_FIR_OFFSET)
  64#define CCM_CSCR_SP             (1 << 17)
  65#define CCM_CSCR_MCU            (1 << 16)
  66#define CCM_CSCR_BCLK_OFFSET    10
  67#define CCM_CSCR_BCLK_MASK      (0xf << CCM_CSCR_BCLK_OFFSET)
  68#define CCM_CSCR_IPDIV_OFFSET   9
  69#define CCM_CSCR_IPDIV          (1 << CCM_CSCR_IPDIV_OFFSET)
  70
  71#define CCM_CSCR_OSC26MDIV      (1 << 4)
  72#define CCM_CSCR_OSC26M         (1 << 3)
  73#define CCM_CSCR_FPM            (1 << 2)
  74#define CCM_CSCR_SPEN           (1 << 1)
  75#define CCM_CSCR_MPEN           1
  76
  77#define CCM_MPCTL0_CPLM         (1 << 31)
  78#define CCM_MPCTL0_PD_OFFSET    26
  79#define CCM_MPCTL0_PD_MASK      (0xf << 26)
  80#define CCM_MPCTL0_MFD_OFFSET   16
  81#define CCM_MPCTL0_MFD_MASK     (0x3ff << 16)
  82#define CCM_MPCTL0_MFI_OFFSET   10
  83#define CCM_MPCTL0_MFI_MASK     (0xf << 10)
  84#define CCM_MPCTL0_MFN_OFFSET   0
  85#define CCM_MPCTL0_MFN_MASK     0x3ff
  86
  87#define CCM_MPCTL1_LF           (1 << 15)
  88#define CCM_MPCTL1_BRMO         (1 << 6)
  89
  90#define CCM_SPCTL0_CPLM         (1 << 31)
  91#define CCM_SPCTL0_PD_OFFSET    26
  92#define CCM_SPCTL0_PD_MASK      (0xf << 26)
  93#define CCM_SPCTL0_MFD_OFFSET   16
  94#define CCM_SPCTL0_MFD_MASK     (0x3ff << 16)
  95#define CCM_SPCTL0_MFI_OFFSET   10
  96#define CCM_SPCTL0_MFI_MASK     (0xf << 10)
  97#define CCM_SPCTL0_MFN_OFFSET   0
  98#define CCM_SPCTL0_MFN_MASK     0x3ff
  99
 100#define CCM_SPCTL1_LF           (1 << 15)
 101#define CCM_SPCTL1_BRMO         (1 << 6)
 102
 103#define CCM_OSC26MCTL_PEAK_OFFSET       16
 104#define CCM_OSC26MCTL_PEAK_MASK         (0x3 << 16)
 105#define CCM_OSC26MCTL_AGC_OFFSET        8
 106#define CCM_OSC26MCTL_AGC_MASK          (0x3f << 8)
 107#define CCM_OSC26MCTL_ANATEST_OFFSET    0
 108#define CCM_OSC26MCTL_ANATEST_MASK      0x3f
 109
 110#define CCM_PCDR0_SSI2BAUDDIV_OFFSET    26
 111#define CCM_PCDR0_SSI2BAUDDIV_MASK      (0x3f << 26)
 112#define CCM_PCDR0_SSI1BAUDDIV_OFFSET    16
 113#define CCM_PCDR0_SSI1BAUDDIV_MASK      (0x3f << 16)
 114#define CCM_PCDR0_NFCDIV_OFFSET         12
 115#define CCM_PCDR0_NFCDIV_MASK           (0xf << 12)
 116#define CCM_PCDR0_48MDIV_OFFSET         5
 117#define CCM_PCDR0_48MDIV_MASK           (0x7 << CCM_PCDR0_48MDIV_OFFSET)
 118#define CCM_PCDR0_FIRIDIV_OFFSET        0
 119#define CCM_PCDR0_FIRIDIV_MASK          0x1f
 120#define CCM_PCDR1_PERDIV4_OFFSET        24
 121#define CCM_PCDR1_PERDIV4_MASK          (0x3f << 24)
 122#define CCM_PCDR1_PERDIV3_OFFSET        16
 123#define CCM_PCDR1_PERDIV3_MASK          (0x3f << 16)
 124#define CCM_PCDR1_PERDIV2_OFFSET        8
 125#define CCM_PCDR1_PERDIV2_MASK          (0x3f << 8)
 126#define CCM_PCDR1_PERDIV1_OFFSET        0
 127#define CCM_PCDR1_PERDIV1_MASK          0x3f
 128
 129#define CCM_PCCR_HCLK_CSI_OFFSET        31
 130#define CCM_PCCR_HCLK_CSI_REG           CCM_PCCR0
 131#define CCM_PCCR_HCLK_DMA_OFFSET        30
 132#define CCM_PCCR_HCLK_DMA_REG           CCM_PCCR0
 133#define CCM_PCCR_HCLK_BROM_OFFSET       28
 134#define CCM_PCCR_HCLK_BROM_REG          CCM_PCCR0
 135#define CCM_PCCR_HCLK_EMMA_OFFSET       27
 136#define CCM_PCCR_HCLK_EMMA_REG          CCM_PCCR0
 137#define CCM_PCCR_HCLK_LCDC_OFFSET       26
 138#define CCM_PCCR_HCLK_LCDC_REG          CCM_PCCR0
 139#define CCM_PCCR_HCLK_SLCDC_OFFSET      25
 140#define CCM_PCCR_HCLK_SLCDC_REG         CCM_PCCR0
 141#define CCM_PCCR_HCLK_USBOTG_OFFSET     24
 142#define CCM_PCCR_HCLK_USBOTG_REG        CCM_PCCR0
 143#define CCM_PCCR_HCLK_BMI_OFFSET        23
 144#define CCM_PCCR_BMI_MASK               (1 << CCM_PCCR_BMI_MASK)
 145#define CCM_PCCR_HCLK_BMI_REG           CCM_PCCR0
 146#define CCM_PCCR_PERCLK4_OFFSET         22
 147#define CCM_PCCR_PERCLK4_REG            CCM_PCCR0
 148#define CCM_PCCR_SLCDC_OFFSET           21
 149#define CCM_PCCR_SLCDC_REG              CCM_PCCR0
 150#define CCM_PCCR_FIRI_BAUD_OFFSET       20
 151#define CCM_PCCR_FIRI_BAUD_MASK         (1 << CCM_PCCR_FIRI_BAUD_MASK)
 152#define CCM_PCCR_FIRI_BAUD_REG          CCM_PCCR0
 153#define CCM_PCCR_NFC_OFFSET             19
 154#define CCM_PCCR_NFC_REG                CCM_PCCR0
 155#define CCM_PCCR_LCDC_OFFSET            18
 156#define CCM_PCCR_LCDC_REG               CCM_PCCR0
 157#define CCM_PCCR_SSI1_BAUD_OFFSET       17
 158#define CCM_PCCR_SSI1_BAUD_REG          CCM_PCCR0
 159#define CCM_PCCR_SSI2_BAUD_OFFSET       16
 160#define CCM_PCCR_SSI2_BAUD_REG          CCM_PCCR0
 161#define CCM_PCCR_EMMA_OFFSET            15
 162#define CCM_PCCR_EMMA_REG               CCM_PCCR0
 163#define CCM_PCCR_USBOTG_OFFSET          14
 164#define CCM_PCCR_USBOTG_REG             CCM_PCCR0
 165#define CCM_PCCR_DMA_OFFSET             13
 166#define CCM_PCCR_DMA_REG                CCM_PCCR0
 167#define CCM_PCCR_I2C1_OFFSET            12
 168#define CCM_PCCR_I2C1_REG               CCM_PCCR0
 169#define CCM_PCCR_GPIO_OFFSET            11
 170#define CCM_PCCR_GPIO_REG               CCM_PCCR0
 171#define CCM_PCCR_SDHC2_OFFSET           10
 172#define CCM_PCCR_SDHC2_REG              CCM_PCCR0
 173#define CCM_PCCR_SDHC1_OFFSET           9
 174#define CCM_PCCR_SDHC1_REG              CCM_PCCR0
 175#define CCM_PCCR_FIRI_OFFSET            8
 176#define CCM_PCCR_FIRI_MASK              (1 << CCM_PCCR_BAUD_MASK)
 177#define CCM_PCCR_FIRI_REG               CCM_PCCR0
 178#define CCM_PCCR_SSI2_IPG_OFFSET        7
 179#define CCM_PCCR_SSI2_REG               CCM_PCCR0
 180#define CCM_PCCR_SSI1_IPG_OFFSET        6
 181#define CCM_PCCR_SSI1_REG               CCM_PCCR0
 182#define CCM_PCCR_CSPI2_OFFSET           5
 183#define CCM_PCCR_CSPI2_REG              CCM_PCCR0
 184#define CCM_PCCR_CSPI1_OFFSET           4
 185#define CCM_PCCR_CSPI1_REG              CCM_PCCR0
 186#define CCM_PCCR_UART4_OFFSET           3
 187#define CCM_PCCR_UART4_REG              CCM_PCCR0
 188#define CCM_PCCR_UART3_OFFSET           2
 189#define CCM_PCCR_UART3_REG              CCM_PCCR0
 190#define CCM_PCCR_UART2_OFFSET           1
 191#define CCM_PCCR_UART2_REG              CCM_PCCR0
 192#define CCM_PCCR_UART1_OFFSET           0
 193#define CCM_PCCR_UART1_REG              CCM_PCCR0
 194
 195#define CCM_PCCR_OWIRE_OFFSET           31
 196#define CCM_PCCR_OWIRE_REG              CCM_PCCR1
 197#define CCM_PCCR_KPP_OFFSET             30
 198#define CCM_PCCR_KPP_REG                CCM_PCCR1
 199#define CCM_PCCR_RTC_OFFSET             29
 200#define CCM_PCCR_RTC_REG                CCM_PCCR1
 201#define CCM_PCCR_PWM_OFFSET             28
 202#define CCM_PCCR_PWM_REG                CCM_PCCR1
 203#define CCM_PCCR_GPT3_OFFSET            27
 204#define CCM_PCCR_GPT3_REG               CCM_PCCR1
 205#define CCM_PCCR_GPT2_OFFSET            26
 206#define CCM_PCCR_GPT2_REG               CCM_PCCR1
 207#define CCM_PCCR_GPT1_OFFSET            25
 208#define CCM_PCCR_GPT1_REG               CCM_PCCR1
 209#define CCM_PCCR_WDT_OFFSET             24
 210#define CCM_PCCR_WDT_REG                CCM_PCCR1
 211#define CCM_PCCR_CSPI3_OFFSET           23
 212#define CCM_PCCR_CSPI3_REG              CCM_PCCR1
 213
 214#define CCM_PCCR_CSPI1_MASK             (1 << CCM_PCCR_CSPI1_OFFSET)
 215#define CCM_PCCR_CSPI2_MASK             (1 << CCM_PCCR_CSPI2_OFFSET)
 216#define CCM_PCCR_CSPI3_MASK             (1 << CCM_PCCR_CSPI3_OFFSET)
 217#define CCM_PCCR_DMA_MASK               (1 << CCM_PCCR_DMA_OFFSET)
 218#define CCM_PCCR_EMMA_MASK              (1 << CCM_PCCR_EMMA_OFFSET)
 219#define CCM_PCCR_GPIO_MASK              (1 << CCM_PCCR_GPIO_OFFSET)
 220#define CCM_PCCR_GPT1_MASK              (1 << CCM_PCCR_GPT1_OFFSET)
 221#define CCM_PCCR_GPT2_MASK              (1 << CCM_PCCR_GPT2_OFFSET)
 222#define CCM_PCCR_GPT3_MASK              (1 << CCM_PCCR_GPT3_OFFSET)
 223#define CCM_PCCR_HCLK_BROM_MASK         (1 << CCM_PCCR_HCLK_BROM_OFFSET)
 224#define CCM_PCCR_HCLK_CSI_MASK          (1 << CCM_PCCR_HCLK_CSI_OFFSET)
 225#define CCM_PCCR_HCLK_DMA_MASK          (1 << CCM_PCCR_HCLK_DMA_OFFSET)
 226#define CCM_PCCR_HCLK_EMMA_MASK         (1 << CCM_PCCR_HCLK_EMMA_OFFSET)
 227#define CCM_PCCR_HCLK_LCDC_MASK         (1 << CCM_PCCR_HCLK_LCDC_OFFSET)
 228#define CCM_PCCR_HCLK_SLCDC_MASK        (1 << CCM_PCCR_HCLK_SLCDC_OFFSET)
 229#define CCM_PCCR_HCLK_USBOTG_MASK       (1 << CCM_PCCR_HCLK_USBOTG_OFFSET)
 230#define CCM_PCCR_I2C1_MASK              (1 << CCM_PCCR_I2C1_OFFSET)
 231#define CCM_PCCR_KPP_MASK               (1 << CCM_PCCR_KPP_OFFSET)
 232#define CCM_PCCR_LCDC_MASK              (1 << CCM_PCCR_LCDC_OFFSET)
 233#define CCM_PCCR_NFC_MASK               (1 << CCM_PCCR_NFC_OFFSET)
 234#define CCM_PCCR_OWIRE_MASK             (1 << CCM_PCCR_OWIRE_OFFSET)
 235#define CCM_PCCR_PERCLK4_MASK           (1 << CCM_PCCR_PERCLK4_OFFSET)
 236#define CCM_PCCR_PWM_MASK               (1 << CCM_PCCR_PWM_OFFSET)
 237#define CCM_PCCR_RTC_MASK               (1 << CCM_PCCR_RTC_OFFSET)
 238#define CCM_PCCR_SDHC1_MASK             (1 << CCM_PCCR_SDHC1_OFFSET)
 239#define CCM_PCCR_SDHC2_MASK             (1 << CCM_PCCR_SDHC2_OFFSET)
 240#define CCM_PCCR_SLCDC_MASK             (1 << CCM_PCCR_SLCDC_OFFSET)
 241#define CCM_PCCR_SSI1_BAUD_MASK         (1 << CCM_PCCR_SSI1_BAUD_OFFSET)
 242#define CCM_PCCR_SSI1_IPG_MASK          (1 << CCM_PCCR_SSI1_IPG_OFFSET)
 243#define CCM_PCCR_SSI2_BAUD_MASK         (1 << CCM_PCCR_SSI2_BAUD_OFFSET)
 244#define CCM_PCCR_SSI2_IPG_MASK          (1 << CCM_PCCR_SSI2_IPG_OFFSET)
 245#define CCM_PCCR_UART1_MASK             (1 << CCM_PCCR_UART1_OFFSET)
 246#define CCM_PCCR_UART2_MASK             (1 << CCM_PCCR_UART2_OFFSET)
 247#define CCM_PCCR_UART3_MASK             (1 << CCM_PCCR_UART3_OFFSET)
 248#define CCM_PCCR_UART4_MASK             (1 << CCM_PCCR_UART4_OFFSET)
 249#define CCM_PCCR_USBOTG_MASK            (1 << CCM_PCCR_USBOTG_OFFSET)
 250#define CCM_PCCR_WDT_MASK               (1 << CCM_PCCR_WDT_OFFSET)
 251
 252#define CCM_CCSR_32KSR          (1 << 15)
 253
 254#define CCM_CCSR_CLKMODE1       (1 << 9)
 255#define CCM_CCSR_CLKMODE0       (1 << 8)
 256
 257#define CCM_CCSR_CLKOSEL_OFFSET 0
 258#define CCM_CCSR_CLKOSEL_MASK   0x1f
 259
 260#define SYS_FMCR                0x14    /* Functional Muxing Control Reg */
 261#define SYS_CHIP_ID             0x00    /* The offset of CHIP ID register */
 262
 263static int _clk_enable(struct clk *clk)
 264{
 265        u32 reg;
 266
 267        reg = __raw_readl(clk->enable_reg);
 268        reg |= 1 << clk->enable_shift;
 269        __raw_writel(reg, clk->enable_reg);
 270        return 0;
 271}
 272
 273static void _clk_disable(struct clk *clk)
 274{
 275        u32 reg;
 276
 277        reg = __raw_readl(clk->enable_reg);
 278        reg &= ~(1 << clk->enable_shift);
 279        __raw_writel(reg, clk->enable_reg);
 280}
 281
 282static unsigned long _clk_generic_round_rate(struct clk *clk,
 283                        unsigned long rate,
 284                        u32 max_divisor)
 285{
 286        u32 div;
 287        unsigned long parent_rate;
 288
 289        parent_rate = clk_get_rate(clk->parent);
 290
 291        div = parent_rate / rate;
 292        if (parent_rate % rate)
 293                div++;
 294
 295        if (div > max_divisor)
 296                div = max_divisor;
 297
 298        return parent_rate / div;
 299}
 300
 301static int _clk_spll_enable(struct clk *clk)
 302{
 303        u32 reg;
 304
 305        reg = __raw_readl(CCM_CSCR);
 306        reg |= CCM_CSCR_SPEN;
 307        __raw_writel(reg, CCM_CSCR);
 308
 309        while ((__raw_readl(CCM_SPCTL1) & CCM_SPCTL1_LF) == 0)
 310                ;
 311        return 0;
 312}
 313
 314static void _clk_spll_disable(struct clk *clk)
 315{
 316        u32 reg;
 317
 318        reg = __raw_readl(CCM_CSCR);
 319        reg &= ~CCM_CSCR_SPEN;
 320        __raw_writel(reg, CCM_CSCR);
 321}
 322
 323
 324#define CSCR() (__raw_readl(CCM_CSCR))
 325#define PCDR0() (__raw_readl(CCM_PCDR0))
 326#define PCDR1() (__raw_readl(CCM_PCDR1))
 327
 328static unsigned long _clk_perclkx_round_rate(struct clk *clk,
 329                                             unsigned long rate)
 330{
 331        return _clk_generic_round_rate(clk, rate, 64);
 332}
 333
 334static int _clk_perclkx_set_rate(struct clk *clk, unsigned long rate)
 335{
 336        u32 reg;
 337        u32 div;
 338        unsigned long parent_rate;
 339
 340        parent_rate = clk_get_rate(clk->parent);
 341
 342        if (clk->id < 0 || clk->id > 3)
 343                return -EINVAL;
 344
 345        div = parent_rate / rate;
 346        if (div > 64 || div < 1 || ((parent_rate / div) != rate))
 347                return -EINVAL;
 348        div--;
 349
 350        reg =
 351            __raw_readl(CCM_PCDR1) & ~(CCM_PCDR1_PERDIV1_MASK <<
 352                                       (clk->id << 3));
 353        reg |= div << (clk->id << 3);
 354        __raw_writel(reg, CCM_PCDR1);
 355
 356        return 0;
 357}
 358
 359static unsigned long _clk_usb_recalc(struct clk *clk)
 360{
 361        unsigned long usb_pdf;
 362        unsigned long parent_rate;
 363
 364        parent_rate = clk_get_rate(clk->parent);
 365
 366        usb_pdf = (CSCR() & CCM_CSCR_USB_MASK) >> CCM_CSCR_USB_OFFSET;
 367
 368        return parent_rate / (usb_pdf + 1U);
 369}
 370
 371static unsigned long _clk_usb_round_rate(struct clk *clk,
 372                                             unsigned long rate)
 373{
 374        return _clk_generic_round_rate(clk, rate, 8);
 375}
 376
 377static int _clk_usb_set_rate(struct clk *clk, unsigned long rate)
 378{
 379        u32 reg;
 380        u32 div;
 381        unsigned long parent_rate;
 382
 383        parent_rate = clk_get_rate(clk->parent);
 384
 385        div = parent_rate / rate;
 386        if (div > 8 || div < 1 || ((parent_rate / div) != rate))
 387                return -EINVAL;
 388        div--;
 389
 390        reg = CSCR() & ~CCM_CSCR_USB_MASK;
 391        reg |= div << CCM_CSCR_USB_OFFSET;
 392        __raw_writel(reg, CCM_CSCR);
 393
 394        return 0;
 395}
 396
 397static unsigned long _clk_ssix_recalc(struct clk *clk, unsigned long pdf)
 398{
 399        unsigned long parent_rate;
 400
 401        parent_rate = clk_get_rate(clk->parent);
 402
 403        pdf = (pdf < 2) ? 124UL : pdf;  /* MX21 & MX27 TO1 */
 404
 405        return 2UL * parent_rate / pdf;
 406}
 407
 408static unsigned long _clk_ssi1_recalc(struct clk *clk)
 409{
 410        return _clk_ssix_recalc(clk,
 411                (PCDR0() & CCM_PCDR0_SSI1BAUDDIV_MASK)
 412                >> CCM_PCDR0_SSI1BAUDDIV_OFFSET);
 413}
 414
 415static unsigned long _clk_ssi2_recalc(struct clk *clk)
 416{
 417        return _clk_ssix_recalc(clk,
 418                (PCDR0() & CCM_PCDR0_SSI2BAUDDIV_MASK) >>
 419                CCM_PCDR0_SSI2BAUDDIV_OFFSET);
 420}
 421
 422static unsigned long _clk_nfc_recalc(struct clk *clk)
 423{
 424        unsigned long nfc_pdf;
 425        unsigned long parent_rate;
 426
 427        parent_rate = clk_get_rate(clk->parent);
 428
 429        nfc_pdf = (PCDR0() & CCM_PCDR0_NFCDIV_MASK)
 430                >> CCM_PCDR0_NFCDIV_OFFSET;
 431
 432        return parent_rate / (nfc_pdf + 1);
 433}
 434
 435static unsigned long _clk_parent_round_rate(struct clk *clk, unsigned long rate)
 436{
 437        return clk->parent->round_rate(clk->parent, rate);
 438}
 439
 440static int _clk_parent_set_rate(struct clk *clk, unsigned long rate)
 441{
 442        return clk->parent->set_rate(clk->parent, rate);
 443}
 444
 445static unsigned long external_high_reference; /* in Hz */
 446
 447static unsigned long get_high_reference_clock_rate(struct clk *clk)
 448{
 449        return external_high_reference;
 450}
 451
 452/*
 453 * the high frequency external clock reference
 454 * Default case is 26MHz.
 455 */
 456static struct clk ckih_clk = {
 457        .get_rate = get_high_reference_clock_rate,
 458};
 459
 460static unsigned long external_low_reference; /* in Hz */
 461
 462static unsigned long get_low_reference_clock_rate(struct clk *clk)
 463{
 464        return external_low_reference;
 465}
 466
 467/*
 468 * the low frequency external clock reference
 469 * Default case is 32.768kHz.
 470 */
 471static struct clk ckil_clk = {
 472        .get_rate = get_low_reference_clock_rate,
 473};
 474
 475
 476static unsigned long _clk_fpm_recalc(struct clk *clk)
 477{
 478        return clk_get_rate(clk->parent) * 512;
 479}
 480
 481/* Output of frequency pre multiplier */
 482static struct clk fpm_clk = {
 483        .parent = &ckil_clk,
 484        .get_rate = _clk_fpm_recalc,
 485};
 486
 487static unsigned long get_mpll_clk(struct clk *clk)
 488{
 489        uint32_t reg;
 490        unsigned long ref_clk;
 491        unsigned long mfi = 0, mfn = 0, mfd = 0, pdf = 0;
 492        unsigned long long temp;
 493
 494        ref_clk = clk_get_rate(clk->parent);
 495
 496        reg = __raw_readl(CCM_MPCTL0);
 497        pdf = (reg & CCM_MPCTL0_PD_MASK)  >> CCM_MPCTL0_PD_OFFSET;
 498        mfd = (reg & CCM_MPCTL0_MFD_MASK) >> CCM_MPCTL0_MFD_OFFSET;
 499        mfi = (reg & CCM_MPCTL0_MFI_MASK) >> CCM_MPCTL0_MFI_OFFSET;
 500        mfn = (reg & CCM_MPCTL0_MFN_MASK) >> CCM_MPCTL0_MFN_OFFSET;
 501
 502        mfi = (mfi <= 5) ? 5 : mfi;
 503        temp = 2LL * ref_clk * mfn;
 504        do_div(temp, mfd + 1);
 505        temp = 2LL * ref_clk * mfi + temp;
 506        do_div(temp, pdf + 1);
 507
 508        return (unsigned long)temp;
 509}
 510
 511static struct clk mpll_clk = {
 512        .parent = &ckih_clk,
 513        .get_rate = get_mpll_clk,
 514};
 515
 516static unsigned long _clk_fclk_get_rate(struct clk *clk)
 517{
 518        unsigned long parent_rate;
 519        u32 div;
 520
 521        div = (CSCR() & CCM_CSCR_PRESC_MASK) >> CCM_CSCR_PRESC_OFFSET;
 522        parent_rate = clk_get_rate(clk->parent);
 523
 524        return parent_rate / (div+1);
 525}
 526
 527static struct clk fclk_clk = {
 528        .parent = &mpll_clk,
 529        .get_rate = _clk_fclk_get_rate
 530};
 531
 532static unsigned long get_spll_clk(struct clk *clk)
 533{
 534        uint32_t reg;
 535        unsigned long ref_clk;
 536        unsigned long mfi = 0, mfn = 0, mfd = 0, pdf = 0;
 537        unsigned long long temp;
 538
 539        ref_clk = clk_get_rate(clk->parent);
 540
 541        reg = __raw_readl(CCM_SPCTL0);
 542        pdf = (reg & CCM_SPCTL0_PD_MASK) >> CCM_SPCTL0_PD_OFFSET;
 543        mfd = (reg & CCM_SPCTL0_MFD_MASK) >> CCM_SPCTL0_MFD_OFFSET;
 544        mfi = (reg & CCM_SPCTL0_MFI_MASK) >> CCM_SPCTL0_MFI_OFFSET;
 545        mfn = (reg & CCM_SPCTL0_MFN_MASK) >> CCM_SPCTL0_MFN_OFFSET;
 546
 547        mfi = (mfi <= 5) ? 5 : mfi;
 548        temp = 2LL * ref_clk * mfn;
 549        do_div(temp, mfd + 1);
 550        temp = 2LL * ref_clk * mfi + temp;
 551        do_div(temp, pdf + 1);
 552
 553        return (unsigned long)temp;
 554}
 555
 556static struct clk spll_clk = {
 557        .parent = &ckih_clk,
 558        .get_rate = get_spll_clk,
 559        .enable = _clk_spll_enable,
 560        .disable = _clk_spll_disable,
 561};
 562
 563static unsigned long get_hclk_clk(struct clk *clk)
 564{
 565        unsigned long rate;
 566        unsigned long bclk_pdf;
 567
 568        bclk_pdf = (CSCR() & CCM_CSCR_BCLK_MASK)
 569                >> CCM_CSCR_BCLK_OFFSET;
 570
 571        rate = clk_get_rate(clk->parent);
 572        return rate / (bclk_pdf + 1);
 573}
 574
 575static struct clk hclk_clk = {
 576        .parent = &fclk_clk,
 577        .get_rate = get_hclk_clk,
 578};
 579
 580static unsigned long get_ipg_clk(struct clk *clk)
 581{
 582        unsigned long rate;
 583        unsigned long ipg_pdf;
 584
 585        ipg_pdf = (CSCR() & CCM_CSCR_IPDIV) >> CCM_CSCR_IPDIV_OFFSET;
 586
 587        rate = clk_get_rate(clk->parent);
 588        return rate / (ipg_pdf + 1);
 589}
 590
 591static struct clk ipg_clk = {
 592        .parent = &hclk_clk,
 593        .get_rate = get_ipg_clk,
 594};
 595
 596static unsigned long _clk_perclkx_recalc(struct clk *clk)
 597{
 598        unsigned long perclk_pdf;
 599        unsigned long parent_rate;
 600
 601        parent_rate = clk_get_rate(clk->parent);
 602
 603        if (clk->id < 0 || clk->id > 3)
 604                return 0;
 605
 606        perclk_pdf = (PCDR1() >> (clk->id << 3)) & CCM_PCDR1_PERDIV1_MASK;
 607
 608        return parent_rate / (perclk_pdf + 1);
 609}
 610
 611static struct clk per_clk[] = {
 612        {
 613                .id = 0,
 614                .parent = &mpll_clk,
 615                .get_rate = _clk_perclkx_recalc,
 616        }, {
 617                .id = 1,
 618                .parent = &mpll_clk,
 619                .get_rate = _clk_perclkx_recalc,
 620        }, {
 621                .id = 2,
 622                .parent = &mpll_clk,
 623                .round_rate = _clk_perclkx_round_rate,
 624                .set_rate = _clk_perclkx_set_rate,
 625                .get_rate = _clk_perclkx_recalc,
 626                /* Enable/Disable done via lcd_clkc[1] */
 627        }, {
 628                .id = 3,
 629                .parent = &mpll_clk,
 630                .round_rate = _clk_perclkx_round_rate,
 631                .set_rate = _clk_perclkx_set_rate,
 632                .get_rate = _clk_perclkx_recalc,
 633                /* Enable/Disable done via csi_clk[1] */
 634        },
 635};
 636
 637static struct clk uart_ipg_clk[];
 638
 639static struct clk uart_clk[] = {
 640        {
 641                .id = 0,
 642                .parent = &per_clk[0],
 643                .secondary = &uart_ipg_clk[0],
 644        }, {
 645                .id = 1,
 646                .parent = &per_clk[0],
 647                .secondary = &uart_ipg_clk[1],
 648        }, {
 649                .id = 2,
 650                .parent = &per_clk[0],
 651                .secondary = &uart_ipg_clk[2],
 652        }, {
 653                .id = 3,
 654                .parent = &per_clk[0],
 655                .secondary = &uart_ipg_clk[3],
 656        },
 657};
 658
 659static struct clk uart_ipg_clk[] = {
 660        {
 661                .id = 0,
 662                .parent = &ipg_clk,
 663                .enable = _clk_enable,
 664                .enable_reg = CCM_PCCR_UART1_REG,
 665                .enable_shift = CCM_PCCR_UART1_OFFSET,
 666                .disable = _clk_disable,
 667        }, {
 668                .id = 1,
 669                .parent = &ipg_clk,
 670                .enable = _clk_enable,
 671                .enable_reg = CCM_PCCR_UART2_REG,
 672                .enable_shift = CCM_PCCR_UART2_OFFSET,
 673                .disable = _clk_disable,
 674        }, {
 675                .id = 2,
 676                .parent = &ipg_clk,
 677                .enable = _clk_enable,
 678                .enable_reg = CCM_PCCR_UART3_REG,
 679                .enable_shift = CCM_PCCR_UART3_OFFSET,
 680                .disable = _clk_disable,
 681        }, {
 682                .id = 3,
 683                .parent = &ipg_clk,
 684                .enable = _clk_enable,
 685                .enable_reg = CCM_PCCR_UART4_REG,
 686                .enable_shift = CCM_PCCR_UART4_OFFSET,
 687                .disable = _clk_disable,
 688        },
 689};
 690
 691static struct clk gpt_ipg_clk[];
 692
 693static struct clk gpt_clk[] = {
 694        {
 695                .id = 0,
 696                .parent = &per_clk[0],
 697                .secondary = &gpt_ipg_clk[0],
 698        }, {
 699                .id = 1,
 700                .parent = &per_clk[0],
 701                .secondary = &gpt_ipg_clk[1],
 702        }, {
 703                .id = 2,
 704                .parent = &per_clk[0],
 705                .secondary = &gpt_ipg_clk[2],
 706        },
 707};
 708
 709static struct clk gpt_ipg_clk[] = {
 710        {
 711                .id = 0,
 712                .parent = &ipg_clk,
 713                .enable = _clk_enable,
 714                .enable_reg = CCM_PCCR_GPT1_REG,
 715                .enable_shift = CCM_PCCR_GPT1_OFFSET,
 716                .disable = _clk_disable,
 717        }, {
 718                .id = 1,
 719                .parent = &ipg_clk,
 720                .enable = _clk_enable,
 721                .enable_reg = CCM_PCCR_GPT2_REG,
 722                .enable_shift = CCM_PCCR_GPT2_OFFSET,
 723                .disable = _clk_disable,
 724        }, {
 725                .id = 2,
 726                .parent = &ipg_clk,
 727                .enable = _clk_enable,
 728                .enable_reg = CCM_PCCR_GPT3_REG,
 729                .enable_shift = CCM_PCCR_GPT3_OFFSET,
 730                .disable = _clk_disable,
 731        },
 732};
 733
 734static struct clk pwm_clk[] = {
 735        {
 736                .parent = &per_clk[0],
 737                .secondary = &pwm_clk[1],
 738        }, {
 739                .parent = &ipg_clk,
 740                .enable = _clk_enable,
 741                .enable_reg = CCM_PCCR_PWM_REG,
 742                .enable_shift = CCM_PCCR_PWM_OFFSET,
 743                .disable = _clk_disable,
 744        },
 745};
 746
 747static struct clk sdhc_ipg_clk[];
 748
 749static struct clk sdhc_clk[] = {
 750        {
 751                .id = 0,
 752                .parent = &per_clk[1],
 753                .secondary = &sdhc_ipg_clk[0],
 754        }, {
 755                .id = 1,
 756                .parent = &per_clk[1],
 757                .secondary = &sdhc_ipg_clk[1],
 758        },
 759};
 760
 761static struct clk sdhc_ipg_clk[] = {
 762        {
 763                .id = 0,
 764                .parent = &ipg_clk,
 765                .enable = _clk_enable,
 766                .enable_reg = CCM_PCCR_SDHC1_REG,
 767                .enable_shift = CCM_PCCR_SDHC1_OFFSET,
 768                .disable = _clk_disable,
 769        }, {
 770                .id = 1,
 771                .parent = &ipg_clk,
 772                .enable = _clk_enable,
 773                .enable_reg = CCM_PCCR_SDHC2_REG,
 774                .enable_shift = CCM_PCCR_SDHC2_OFFSET,
 775                .disable = _clk_disable,
 776        },
 777};
 778
 779static struct clk cspi_ipg_clk[];
 780
 781static struct clk cspi_clk[] = {
 782        {
 783                .id = 0,
 784                .parent = &per_clk[1],
 785                .secondary = &cspi_ipg_clk[0],
 786        }, {
 787                .id = 1,
 788                .parent = &per_clk[1],
 789                .secondary = &cspi_ipg_clk[1],
 790        }, {
 791                .id = 2,
 792                .parent = &per_clk[1],
 793                .secondary = &cspi_ipg_clk[2],
 794        },
 795};
 796
 797static struct clk cspi_ipg_clk[] = {
 798        {
 799                .id = 0,
 800                .parent = &ipg_clk,
 801                .enable = _clk_enable,
 802                .enable_reg = CCM_PCCR_CSPI1_REG,
 803                .enable_shift = CCM_PCCR_CSPI1_OFFSET,
 804                .disable = _clk_disable,
 805        }, {
 806                .id = 1,
 807                .parent = &ipg_clk,
 808                .enable = _clk_enable,
 809                .enable_reg = CCM_PCCR_CSPI2_REG,
 810                .enable_shift = CCM_PCCR_CSPI2_OFFSET,
 811                .disable = _clk_disable,
 812        }, {
 813                .id = 3,
 814                .parent = &ipg_clk,
 815                .enable = _clk_enable,
 816                .enable_reg = CCM_PCCR_CSPI3_REG,
 817                .enable_shift = CCM_PCCR_CSPI3_OFFSET,
 818                .disable = _clk_disable,
 819        },
 820};
 821
 822static struct clk lcdc_clk[] = {
 823        {
 824                .parent = &per_clk[2],
 825                .secondary = &lcdc_clk[1],
 826                .round_rate = _clk_parent_round_rate,
 827                .set_rate = _clk_parent_set_rate,
 828        }, {
 829                .parent = &ipg_clk,
 830                .secondary = &lcdc_clk[2],
 831                .enable = _clk_enable,
 832                .enable_reg = CCM_PCCR_LCDC_REG,
 833                .enable_shift = CCM_PCCR_LCDC_OFFSET,
 834                .disable = _clk_disable,
 835        }, {
 836                .parent = &hclk_clk,
 837                .enable = _clk_enable,
 838                .enable_reg = CCM_PCCR_HCLK_LCDC_REG,
 839                .enable_shift = CCM_PCCR_HCLK_LCDC_OFFSET,
 840                .disable = _clk_disable,
 841        },
 842};
 843
 844static struct clk csi_clk[] = {
 845        {
 846                .parent = &per_clk[3],
 847                .secondary = &csi_clk[1],
 848                .round_rate = _clk_parent_round_rate,
 849                .set_rate = _clk_parent_set_rate,
 850        }, {
 851                .parent = &hclk_clk,
 852                .enable = _clk_enable,
 853                .enable_reg = CCM_PCCR_HCLK_CSI_REG,
 854                .enable_shift = CCM_PCCR_HCLK_CSI_OFFSET,
 855                .disable = _clk_disable,
 856        },
 857};
 858
 859static struct clk usb_clk[] = {
 860        {
 861                .parent = &spll_clk,
 862                .secondary = &usb_clk[1],
 863                .get_rate = _clk_usb_recalc,
 864                .enable = _clk_enable,
 865                .enable_reg = CCM_PCCR_USBOTG_REG,
 866                .enable_shift = CCM_PCCR_USBOTG_OFFSET,
 867                .disable = _clk_disable,
 868                .round_rate = _clk_usb_round_rate,
 869                .set_rate = _clk_usb_set_rate,
 870        }, {
 871                .parent = &hclk_clk,
 872                .enable = _clk_enable,
 873                .enable_reg = CCM_PCCR_HCLK_USBOTG_REG,
 874                .enable_shift = CCM_PCCR_HCLK_USBOTG_OFFSET,
 875                .disable = _clk_disable,
 876        }
 877};
 878
 879static struct clk ssi_ipg_clk[];
 880
 881static struct clk ssi_clk[] = {
 882        {
 883                .id = 0,
 884                .parent = &mpll_clk,
 885                .secondary = &ssi_ipg_clk[0],
 886                .get_rate = _clk_ssi1_recalc,
 887                .enable = _clk_enable,
 888                .enable_reg = CCM_PCCR_SSI1_BAUD_REG,
 889                .enable_shift = CCM_PCCR_SSI1_BAUD_OFFSET,
 890                .disable = _clk_disable,
 891        }, {
 892                .id = 1,
 893                .parent = &mpll_clk,
 894                .secondary = &ssi_ipg_clk[1],
 895                .get_rate = _clk_ssi2_recalc,
 896                .enable = _clk_enable,
 897                .enable_reg = CCM_PCCR_SSI2_BAUD_REG,
 898                .enable_shift = CCM_PCCR_SSI2_BAUD_OFFSET,
 899                .disable = _clk_disable,
 900        },
 901};
 902
 903static struct clk ssi_ipg_clk[] = {
 904        {
 905                .id = 0,
 906                .parent = &ipg_clk,
 907                .enable = _clk_enable,
 908                .enable_reg = CCM_PCCR_SSI1_REG,
 909                .enable_shift = CCM_PCCR_SSI1_IPG_OFFSET,
 910                .disable = _clk_disable,
 911        }, {
 912                .id = 1,
 913                .parent = &ipg_clk,
 914                .enable = _clk_enable,
 915                .enable_reg = CCM_PCCR_SSI2_REG,
 916                .enable_shift = CCM_PCCR_SSI2_IPG_OFFSET,
 917                .disable = _clk_disable,
 918        },
 919};
 920
 921
 922static struct clk nfc_clk = {
 923        .parent = &fclk_clk,
 924        .get_rate = _clk_nfc_recalc,
 925        .enable = _clk_enable,
 926        .enable_reg = CCM_PCCR_NFC_REG,
 927        .enable_shift = CCM_PCCR_NFC_OFFSET,
 928        .disable = _clk_disable,
 929};
 930
 931static struct clk dma_clk[] = {
 932        {
 933                .parent = &hclk_clk,
 934                .enable = _clk_enable,
 935                .enable_reg = CCM_PCCR_DMA_REG,
 936                .enable_shift = CCM_PCCR_DMA_OFFSET,
 937                .disable = _clk_disable,
 938                .secondary = &dma_clk[1],
 939        },  {
 940                .enable = _clk_enable,
 941                .enable_reg = CCM_PCCR_HCLK_DMA_REG,
 942                .enable_shift = CCM_PCCR_HCLK_DMA_OFFSET,
 943                .disable = _clk_disable,
 944        },
 945};
 946
 947static struct clk brom_clk = {
 948        .parent = &hclk_clk,
 949        .enable = _clk_enable,
 950        .enable_reg = CCM_PCCR_HCLK_BROM_REG,
 951        .enable_shift = CCM_PCCR_HCLK_BROM_OFFSET,
 952        .disable = _clk_disable,
 953};
 954
 955static struct clk emma_clk[] = {
 956        {
 957                .parent = &hclk_clk,
 958                .enable = _clk_enable,
 959                .enable_reg = CCM_PCCR_EMMA_REG,
 960                .enable_shift = CCM_PCCR_EMMA_OFFSET,
 961                .disable = _clk_disable,
 962                .secondary = &emma_clk[1],
 963        }, {
 964                .enable = _clk_enable,
 965                .enable_reg = CCM_PCCR_HCLK_EMMA_REG,
 966                .enable_shift = CCM_PCCR_HCLK_EMMA_OFFSET,
 967                .disable = _clk_disable,
 968        }
 969};
 970
 971static struct clk slcdc_clk[] = {
 972        {
 973                .parent = &hclk_clk,
 974                .enable = _clk_enable,
 975                .enable_reg = CCM_PCCR_SLCDC_REG,
 976                .enable_shift = CCM_PCCR_SLCDC_OFFSET,
 977                .disable = _clk_disable,
 978                .secondary = &slcdc_clk[1],
 979        }, {
 980                .enable = _clk_enable,
 981                .enable_reg = CCM_PCCR_HCLK_SLCDC_REG,
 982                .enable_shift = CCM_PCCR_HCLK_SLCDC_OFFSET,
 983                .disable = _clk_disable,
 984        }
 985};
 986
 987static struct clk wdog_clk = {
 988        .parent = &ipg_clk,
 989        .enable = _clk_enable,
 990        .enable_reg = CCM_PCCR_WDT_REG,
 991        .enable_shift = CCM_PCCR_WDT_OFFSET,
 992        .disable = _clk_disable,
 993};
 994
 995static struct clk gpio_clk = {
 996        .parent = &ipg_clk,
 997        .enable = _clk_enable,
 998        .enable_reg = CCM_PCCR_GPIO_REG,
 999        .enable_shift = CCM_PCCR_GPIO_OFFSET,
1000        .disable = _clk_disable,
1001};
1002
1003static struct clk i2c_clk = {
1004        .id = 0,
1005        .parent = &ipg_clk,
1006        .enable = _clk_enable,
1007        .enable_reg = CCM_PCCR_I2C1_REG,
1008        .enable_shift = CCM_PCCR_I2C1_OFFSET,
1009        .disable = _clk_disable,
1010};
1011
1012static struct clk kpp_clk = {
1013        .parent = &ipg_clk,
1014        .enable = _clk_enable,
1015        .enable_reg = CCM_PCCR_KPP_REG,
1016        .enable_shift = CCM_PCCR_KPP_OFFSET,
1017        .disable = _clk_disable,
1018};
1019
1020static struct clk owire_clk = {
1021        .parent = &ipg_clk,
1022        .enable = _clk_enable,
1023        .enable_reg = CCM_PCCR_OWIRE_REG,
1024        .enable_shift = CCM_PCCR_OWIRE_OFFSET,
1025        .disable = _clk_disable,
1026};
1027
1028static struct clk rtc_clk = {
1029        .parent = &ipg_clk,
1030        .enable = _clk_enable,
1031        .enable_reg = CCM_PCCR_RTC_REG,
1032        .enable_shift = CCM_PCCR_RTC_OFFSET,
1033        .disable = _clk_disable,
1034};
1035
1036static unsigned long _clk_clko_round_rate(struct clk *clk, unsigned long rate)
1037{
1038        return _clk_generic_round_rate(clk, rate, 8);
1039}
1040
1041static int _clk_clko_set_rate(struct clk *clk, unsigned long rate)
1042{
1043        u32 reg;
1044        u32 div;
1045        unsigned long parent_rate;
1046
1047        parent_rate = clk_get_rate(clk->parent);
1048
1049        div = parent_rate / rate;
1050
1051        if (div > 8 || div < 1 || ((parent_rate / div) != rate))
1052                return -EINVAL;
1053        div--;
1054
1055        reg = __raw_readl(CCM_PCDR0);
1056
1057        if (clk->parent == &usb_clk[0]) {
1058                reg &= ~CCM_PCDR0_48MDIV_MASK;
1059                reg |= div << CCM_PCDR0_48MDIV_OFFSET;
1060        }
1061        __raw_writel(reg, CCM_PCDR0);
1062
1063        return 0;
1064}
1065
1066static unsigned long _clk_clko_recalc(struct clk *clk)
1067{
1068        u32 div = 0;
1069        unsigned long parent_rate;
1070
1071        parent_rate = clk_get_rate(clk->parent);
1072
1073        if (clk->parent == &usb_clk[0]) /* 48M */
1074                div = __raw_readl(CCM_PCDR0) & CCM_PCDR0_48MDIV_MASK
1075                         >> CCM_PCDR0_48MDIV_OFFSET;
1076        div++;
1077
1078        return parent_rate / div;
1079}
1080
1081static struct clk clko_clk;
1082
1083static int _clk_clko_set_parent(struct clk *clk, struct clk *parent)
1084{
1085        u32 reg;
1086
1087        reg = __raw_readl(CCM_CCSR) & ~CCM_CCSR_CLKOSEL_MASK;
1088
1089        if (parent == &ckil_clk)
1090                reg |= 0 << CCM_CCSR_CLKOSEL_OFFSET;
1091        else if (parent == &fpm_clk)
1092                reg |= 1 << CCM_CCSR_CLKOSEL_OFFSET;
1093        else if (parent == &ckih_clk)
1094                reg |= 2 << CCM_CCSR_CLKOSEL_OFFSET;
1095        else if (parent == mpll_clk.parent)
1096                reg |= 3 << CCM_CCSR_CLKOSEL_OFFSET;
1097        else if (parent == spll_clk.parent)
1098                reg |= 4 << CCM_CCSR_CLKOSEL_OFFSET;
1099        else if (parent == &mpll_clk)
1100                reg |= 5 << CCM_CCSR_CLKOSEL_OFFSET;
1101        else if (parent == &spll_clk)
1102                reg |= 6 << CCM_CCSR_CLKOSEL_OFFSET;
1103        else if (parent == &fclk_clk)
1104                reg |= 7 << CCM_CCSR_CLKOSEL_OFFSET;
1105        else if (parent == &hclk_clk)
1106                reg |= 8 << CCM_CCSR_CLKOSEL_OFFSET;
1107        else if (parent == &ipg_clk)
1108                reg |= 9 << CCM_CCSR_CLKOSEL_OFFSET;
1109        else if (parent == &per_clk[0])
1110                reg |= 0xA << CCM_CCSR_CLKOSEL_OFFSET;
1111        else if (parent == &per_clk[1])
1112                reg |= 0xB << CCM_CCSR_CLKOSEL_OFFSET;
1113        else if (parent == &per_clk[2])
1114                reg |= 0xC << CCM_CCSR_CLKOSEL_OFFSET;
1115        else if (parent == &per_clk[3])
1116                reg |= 0xD << CCM_CCSR_CLKOSEL_OFFSET;
1117        else if (parent == &ssi_clk[0])
1118                reg |= 0xE << CCM_CCSR_CLKOSEL_OFFSET;
1119        else if (parent == &ssi_clk[1])
1120                reg |= 0xF << CCM_CCSR_CLKOSEL_OFFSET;
1121        else if (parent == &nfc_clk)
1122                reg |= 0x10 << CCM_CCSR_CLKOSEL_OFFSET;
1123        else if (parent == &usb_clk[0])
1124                reg |= 0x14 << CCM_CCSR_CLKOSEL_OFFSET;
1125        else if (parent == &clko_clk)
1126                reg |= 0x15 << CCM_CCSR_CLKOSEL_OFFSET;
1127        else
1128                return -EINVAL;
1129
1130        __raw_writel(reg, CCM_CCSR);
1131
1132        return 0;
1133}
1134
1135static struct clk clko_clk = {
1136        .get_rate = _clk_clko_recalc,
1137        .set_rate = _clk_clko_set_rate,
1138        .round_rate = _clk_clko_round_rate,
1139        .set_parent = _clk_clko_set_parent,
1140};
1141
1142
1143#define _REGISTER_CLOCK(d, n, c) \
1144        { \
1145                .dev_id = d, \
1146                .con_id = n, \
1147                .clk = &c, \
1148        },
1149static struct clk_lookup lookups[] = {
1150/* It's unlikely that any driver wants one of them directly:
1151        _REGISTER_CLOCK(NULL, "ckih", ckih_clk)
1152        _REGISTER_CLOCK(NULL, "ckil", ckil_clk)
1153        _REGISTER_CLOCK(NULL, "fpm", fpm_clk)
1154        _REGISTER_CLOCK(NULL, "mpll", mpll_clk)
1155        _REGISTER_CLOCK(NULL, "spll", spll_clk)
1156        _REGISTER_CLOCK(NULL, "fclk", fclk_clk)
1157        _REGISTER_CLOCK(NULL, "hclk", hclk_clk)
1158        _REGISTER_CLOCK(NULL, "ipg", ipg_clk)
1159*/
1160        _REGISTER_CLOCK(NULL, "perclk1", per_clk[0])
1161        _REGISTER_CLOCK(NULL, "perclk2", per_clk[1])
1162        _REGISTER_CLOCK(NULL, "perclk3", per_clk[2])
1163        _REGISTER_CLOCK(NULL, "perclk4", per_clk[3])
1164        _REGISTER_CLOCK(NULL, "clko", clko_clk)
1165        _REGISTER_CLOCK("imx-uart.0", NULL, uart_clk[0])
1166        _REGISTER_CLOCK("imx-uart.1", NULL, uart_clk[1])
1167        _REGISTER_CLOCK("imx-uart.2", NULL, uart_clk[2])
1168        _REGISTER_CLOCK("imx-uart.3", NULL, uart_clk[3])
1169        _REGISTER_CLOCK(NULL, "gpt1", gpt_clk[0])
1170        _REGISTER_CLOCK(NULL, "gpt1", gpt_clk[1])
1171        _REGISTER_CLOCK(NULL, "gpt1", gpt_clk[2])
1172        _REGISTER_CLOCK(NULL, "pwm", pwm_clk[0])
1173        _REGISTER_CLOCK(NULL, "sdhc1", sdhc_clk[0])
1174        _REGISTER_CLOCK(NULL, "sdhc2", sdhc_clk[1])
1175        _REGISTER_CLOCK("imx21-cspi.0", NULL, cspi_clk[0])
1176        _REGISTER_CLOCK("imx21-cspi.1", NULL, cspi_clk[1])
1177        _REGISTER_CLOCK("imx21-cspi.2", NULL, cspi_clk[2])
1178        _REGISTER_CLOCK("imx-fb.0", NULL, lcdc_clk[0])
1179        _REGISTER_CLOCK(NULL, "csi", csi_clk[0])
1180        _REGISTER_CLOCK("imx21-hcd.0", NULL, usb_clk[0])
1181        _REGISTER_CLOCK(NULL, "ssi1", ssi_clk[0])
1182        _REGISTER_CLOCK(NULL, "ssi2", ssi_clk[1])
1183        _REGISTER_CLOCK("mxc_nand.0", NULL, nfc_clk)
1184        _REGISTER_CLOCK(NULL, "dma", dma_clk[0])
1185        _REGISTER_CLOCK(NULL, "brom", brom_clk)
1186        _REGISTER_CLOCK(NULL, "emma", emma_clk[0])
1187        _REGISTER_CLOCK(NULL, "slcdc", slcdc_clk[0])
1188        _REGISTER_CLOCK("imx2-wdt.0", NULL, wdog_clk)
1189        _REGISTER_CLOCK(NULL, "gpio", gpio_clk)
1190        _REGISTER_CLOCK("imx-i2c.0", NULL, i2c_clk)
1191        _REGISTER_CLOCK("mxc-keypad", NULL, kpp_clk)
1192        _REGISTER_CLOCK(NULL, "owire", owire_clk)
1193        _REGISTER_CLOCK(NULL, "rtc", rtc_clk)
1194};
1195
1196/*
1197 * must be called very early to get information about the
1198 * available clock rate when the timer framework starts
1199 */
1200int __init mx21_clocks_init(unsigned long lref, unsigned long href)
1201{
1202        u32 cscr;
1203
1204        external_low_reference = lref;
1205        external_high_reference = href;
1206
1207        /* detect clock reference for both system PLL */
1208        cscr = CSCR();
1209        if (cscr & CCM_CSCR_MCU)
1210                mpll_clk.parent = &ckih_clk;
1211        else
1212                mpll_clk.parent = &fpm_clk;
1213
1214        if (cscr & CCM_CSCR_SP)
1215                spll_clk.parent = &ckih_clk;
1216        else
1217                spll_clk.parent = &fpm_clk;
1218
1219        clkdev_add_table(lookups, ARRAY_SIZE(lookups));
1220
1221        /* Turn off all clock gates */
1222        __raw_writel(0, CCM_PCCR0);
1223        __raw_writel(CCM_PCCR_GPT1_MASK, CCM_PCCR1);
1224
1225        /* This turns of the serial PLL as well */
1226        spll_clk.disable(&spll_clk);
1227
1228        /* This will propagate to all children and init all the clock rates. */
1229        clk_enable(&per_clk[0]);
1230        clk_enable(&gpio_clk);
1231
1232#if defined(CONFIG_DEBUG_LL) && !defined(CONFIG_DEBUG_ICEDCC)
1233        clk_enable(&uart_clk[0]);
1234#endif
1235
1236        mxc_timer_init(&gpt_clk[0], MX21_IO_ADDRESS(MX21_GPT1_BASE_ADDR),
1237                        MX21_INT_GPT1);
1238        return 0;
1239}
1240