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 25#include <mach/clock.h> 26#include <mach/hardware.h> 27#include <mach/common.h> 28#include <asm/clkdev.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(NULL, "cspi1", cspi_clk[0]) 1176 _REGISTER_CLOCK(NULL, "cspi2", cspi_clk[1]) 1177 _REGISTER_CLOCK(NULL, "cspi3", 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("imx-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