1/* 2 * arch/arm/mach-spear6xx/clock.c 3 * 4 * SPEAr6xx machines clock framework source file 5 * 6 * Copyright (C) 2009 ST Microelectronics 7 * Viresh Kumar<viresh.kumar@st.com> 8 * 9 * This file is licensed under the terms of the GNU General Public 10 * License version 2. This program is licensed "as is" without any 11 * warranty of any kind, whether express or implied. 12 */ 13 14#include <linux/init.h> 15#include <linux/kernel.h> 16#include <mach/misc_regs.h> 17#include <plat/clock.h> 18 19/* root clks */ 20/* 32 KHz oscillator clock */ 21static struct clk osc_32k_clk = { 22 .flags = ALWAYS_ENABLED, 23 .rate = 32000, 24}; 25 26/* 30 MHz oscillator clock */ 27static struct clk osc_30m_clk = { 28 .flags = ALWAYS_ENABLED, 29 .rate = 30000000, 30}; 31 32/* clock derived from 32 KHz osc clk */ 33/* rtc clock */ 34static struct clk rtc_clk = { 35 .pclk = &osc_32k_clk, 36 .en_reg = PERIP1_CLK_ENB, 37 .en_reg_bit = RTC_CLK_ENB, 38 .recalc = &follow_parent, 39}; 40 41/* clock derived from 30 MHz osc clk */ 42/* pll1 configuration structure */ 43static struct pll_clk_config pll1_config = { 44 .mode_reg = PLL1_CTR, 45 .cfg_reg = PLL1_FRQ, 46}; 47 48/* PLL1 clock */ 49static struct clk pll1_clk = { 50 .pclk = &osc_30m_clk, 51 .en_reg = PLL1_CTR, 52 .en_reg_bit = PLL_ENABLE, 53 .recalc = &pll1_clk_recalc, 54 .private_data = &pll1_config, 55}; 56 57/* PLL3 48 MHz clock */ 58static struct clk pll3_48m_clk = { 59 .flags = ALWAYS_ENABLED, 60 .pclk = &osc_30m_clk, 61 .rate = 48000000, 62}; 63 64/* watch dog timer clock */ 65static struct clk wdt_clk = { 66 .flags = ALWAYS_ENABLED, 67 .pclk = &osc_30m_clk, 68 .recalc = &follow_parent, 69}; 70 71/* clock derived from pll1 clk */ 72/* cpu clock */ 73static struct clk cpu_clk = { 74 .flags = ALWAYS_ENABLED, 75 .pclk = &pll1_clk, 76 .recalc = &follow_parent, 77}; 78 79/* ahb configuration structure */ 80static struct bus_clk_config ahb_config = { 81 .reg = CORE_CLK_CFG, 82 .mask = PLL_HCLK_RATIO_MASK, 83 .shift = PLL_HCLK_RATIO_SHIFT, 84}; 85 86/* ahb clock */ 87static struct clk ahb_clk = { 88 .flags = ALWAYS_ENABLED, 89 .pclk = &pll1_clk, 90 .recalc = &bus_clk_recalc, 91 .private_data = &ahb_config, 92}; 93 94/* uart parents */ 95static struct pclk_info uart_pclk_info[] = { 96 { 97 .pclk = &pll1_clk, 98 .pclk_mask = AUX_CLK_PLL1_MASK, 99 .scalable = 1, 100 }, { 101 .pclk = &pll3_48m_clk, 102 .pclk_mask = AUX_CLK_PLL3_MASK, 103 .scalable = 0, 104 }, 105}; 106 107/* uart parent select structure */ 108static struct pclk_sel uart_pclk_sel = { 109 .pclk_info = uart_pclk_info, 110 .pclk_count = ARRAY_SIZE(uart_pclk_info), 111 .pclk_sel_reg = PERIP_CLK_CFG, 112 .pclk_sel_mask = UART_CLK_MASK, 113}; 114 115/* uart configurations */ 116static struct aux_clk_config uart_config = { 117 .synth_reg = UART_CLK_SYNT, 118}; 119 120/* uart0 clock */ 121static struct clk uart0_clk = { 122 .en_reg = PERIP1_CLK_ENB, 123 .en_reg_bit = UART0_CLK_ENB, 124 .pclk_sel = &uart_pclk_sel, 125 .pclk_sel_shift = UART_CLK_SHIFT, 126 .recalc = &aux_clk_recalc, 127 .private_data = &uart_config, 128}; 129 130/* uart1 clock */ 131static struct clk uart1_clk = { 132 .en_reg = PERIP1_CLK_ENB, 133 .en_reg_bit = UART1_CLK_ENB, 134 .pclk_sel = &uart_pclk_sel, 135 .pclk_sel_shift = UART_CLK_SHIFT, 136 .recalc = &aux_clk_recalc, 137 .private_data = &uart_config, 138}; 139 140/* firda configurations */ 141static struct aux_clk_config firda_config = { 142 .synth_reg = FIRDA_CLK_SYNT, 143}; 144 145/* firda parents */ 146static struct pclk_info firda_pclk_info[] = { 147 { 148 .pclk = &pll1_clk, 149 .pclk_mask = AUX_CLK_PLL1_MASK, 150 .scalable = 1, 151 }, { 152 .pclk = &pll3_48m_clk, 153 .pclk_mask = AUX_CLK_PLL3_MASK, 154 .scalable = 0, 155 }, 156}; 157 158/* firda parent select structure */ 159static struct pclk_sel firda_pclk_sel = { 160 .pclk_info = firda_pclk_info, 161 .pclk_count = ARRAY_SIZE(firda_pclk_info), 162 .pclk_sel_reg = PERIP_CLK_CFG, 163 .pclk_sel_mask = FIRDA_CLK_MASK, 164}; 165 166/* firda clock */ 167static struct clk firda_clk = { 168 .en_reg = PERIP1_CLK_ENB, 169 .en_reg_bit = FIRDA_CLK_ENB, 170 .pclk_sel = &firda_pclk_sel, 171 .pclk_sel_shift = FIRDA_CLK_SHIFT, 172 .recalc = &aux_clk_recalc, 173 .private_data = &firda_config, 174}; 175 176/* clcd configurations */ 177static struct aux_clk_config clcd_config = { 178 .synth_reg = CLCD_CLK_SYNT, 179}; 180 181/* clcd parents */ 182static struct pclk_info clcd_pclk_info[] = { 183 { 184 .pclk = &pll1_clk, 185 .pclk_mask = AUX_CLK_PLL1_MASK, 186 .scalable = 1, 187 }, { 188 .pclk = &pll3_48m_clk, 189 .pclk_mask = AUX_CLK_PLL3_MASK, 190 .scalable = 0, 191 }, 192}; 193 194/* clcd parent select structure */ 195static struct pclk_sel clcd_pclk_sel = { 196 .pclk_info = clcd_pclk_info, 197 .pclk_count = ARRAY_SIZE(clcd_pclk_info), 198 .pclk_sel_reg = PERIP_CLK_CFG, 199 .pclk_sel_mask = CLCD_CLK_MASK, 200}; 201 202/* clcd clock */ 203static struct clk clcd_clk = { 204 .en_reg = PERIP1_CLK_ENB, 205 .en_reg_bit = CLCD_CLK_ENB, 206 .pclk_sel = &clcd_pclk_sel, 207 .pclk_sel_shift = CLCD_CLK_SHIFT, 208 .recalc = &aux_clk_recalc, 209 .private_data = &clcd_config, 210}; 211 212/* gpt parents */ 213static struct pclk_info gpt_pclk_info[] = { 214 { 215 .pclk = &pll1_clk, 216 .pclk_mask = AUX_CLK_PLL1_MASK, 217 .scalable = 1, 218 }, { 219 .pclk = &pll3_48m_clk, 220 .pclk_mask = AUX_CLK_PLL3_MASK, 221 .scalable = 0, 222 }, 223}; 224 225/* gpt parent select structure */ 226static struct pclk_sel gpt_pclk_sel = { 227 .pclk_info = gpt_pclk_info, 228 .pclk_count = ARRAY_SIZE(gpt_pclk_info), 229 .pclk_sel_reg = PERIP_CLK_CFG, 230 .pclk_sel_mask = GPT_CLK_MASK, 231}; 232 233/* gpt0_1 configurations */ 234static struct aux_clk_config gpt0_1_config = { 235 .synth_reg = PRSC1_CLK_CFG, 236}; 237 238/* gpt0 ARM1 subsystem timer clock */ 239static struct clk gpt0_clk = { 240 .flags = ALWAYS_ENABLED, 241 .pclk_sel = &gpt_pclk_sel, 242 .pclk_sel_shift = GPT0_CLK_SHIFT, 243 .recalc = &gpt_clk_recalc, 244 .private_data = &gpt0_1_config, 245}; 246 247/* gpt1 timer clock */ 248static struct clk gpt1_clk = { 249 .flags = ALWAYS_ENABLED, 250 .pclk_sel = &gpt_pclk_sel, 251 .pclk_sel_shift = GPT1_CLK_SHIFT, 252 .recalc = &gpt_clk_recalc, 253 .private_data = &gpt0_1_config, 254}; 255 256/* gpt2 configurations */ 257static struct aux_clk_config gpt2_config = { 258 .synth_reg = PRSC2_CLK_CFG, 259}; 260 261/* gpt2 timer clock */ 262static struct clk gpt2_clk = { 263 .en_reg = PERIP1_CLK_ENB, 264 .en_reg_bit = GPT2_CLK_ENB, 265 .pclk_sel = &gpt_pclk_sel, 266 .pclk_sel_shift = GPT2_CLK_SHIFT, 267 .recalc = &gpt_clk_recalc, 268 .private_data = &gpt2_config, 269}; 270 271/* gpt3 configurations */ 272static struct aux_clk_config gpt3_config = { 273 .synth_reg = PRSC3_CLK_CFG, 274}; 275 276/* gpt3 timer clock */ 277static struct clk gpt3_clk = { 278 .en_reg = PERIP1_CLK_ENB, 279 .en_reg_bit = GPT3_CLK_ENB, 280 .pclk_sel = &gpt_pclk_sel, 281 .pclk_sel_shift = GPT3_CLK_SHIFT, 282 .recalc = &gpt_clk_recalc, 283 .private_data = &gpt3_config, 284}; 285 286/* clock derived from pll3 clk */ 287/* usbh0 clock */ 288static struct clk usbh0_clk = { 289 .pclk = &pll3_48m_clk, 290 .en_reg = PERIP1_CLK_ENB, 291 .en_reg_bit = USBH0_CLK_ENB, 292 .recalc = &follow_parent, 293}; 294 295/* usbh1 clock */ 296static struct clk usbh1_clk = { 297 .pclk = &pll3_48m_clk, 298 .en_reg = PERIP1_CLK_ENB, 299 .en_reg_bit = USBH1_CLK_ENB, 300 .recalc = &follow_parent, 301}; 302 303/* usbd clock */ 304static struct clk usbd_clk = { 305 .pclk = &pll3_48m_clk, 306 .en_reg = PERIP1_CLK_ENB, 307 .en_reg_bit = USBD_CLK_ENB, 308 .recalc = &follow_parent, 309}; 310 311/* clock derived from ahb clk */ 312/* apb configuration structure */ 313static struct bus_clk_config apb_config = { 314 .reg = CORE_CLK_CFG, 315 .mask = HCLK_PCLK_RATIO_MASK, 316 .shift = HCLK_PCLK_RATIO_SHIFT, 317}; 318 319/* apb clock */ 320static struct clk apb_clk = { 321 .flags = ALWAYS_ENABLED, 322 .pclk = &ahb_clk, 323 .recalc = &bus_clk_recalc, 324 .private_data = &apb_config, 325}; 326 327/* i2c clock */ 328static struct clk i2c_clk = { 329 .pclk = &ahb_clk, 330 .en_reg = PERIP1_CLK_ENB, 331 .en_reg_bit = I2C_CLK_ENB, 332 .recalc = &follow_parent, 333}; 334 335/* dma clock */ 336static struct clk dma_clk = { 337 .pclk = &ahb_clk, 338 .en_reg = PERIP1_CLK_ENB, 339 .en_reg_bit = DMA_CLK_ENB, 340 .recalc = &follow_parent, 341}; 342 343/* jpeg clock */ 344static struct clk jpeg_clk = { 345 .pclk = &ahb_clk, 346 .en_reg = PERIP1_CLK_ENB, 347 .en_reg_bit = JPEG_CLK_ENB, 348 .recalc = &follow_parent, 349}; 350 351/* gmac clock */ 352static struct clk gmac_clk = { 353 .pclk = &ahb_clk, 354 .en_reg = PERIP1_CLK_ENB, 355 .en_reg_bit = GMAC_CLK_ENB, 356 .recalc = &follow_parent, 357}; 358 359/* smi clock */ 360static struct clk smi_clk = { 361 .pclk = &ahb_clk, 362 .en_reg = PERIP1_CLK_ENB, 363 .en_reg_bit = SMI_CLK_ENB, 364 .recalc = &follow_parent, 365}; 366 367/* fsmc clock */ 368static struct clk fsmc_clk = { 369 .pclk = &ahb_clk, 370 .en_reg = PERIP1_CLK_ENB, 371 .en_reg_bit = FSMC_CLK_ENB, 372 .recalc = &follow_parent, 373}; 374 375/* clock derived from apb clk */ 376/* adc clock */ 377static struct clk adc_clk = { 378 .pclk = &apb_clk, 379 .en_reg = PERIP1_CLK_ENB, 380 .en_reg_bit = ADC_CLK_ENB, 381 .recalc = &follow_parent, 382}; 383 384/* ssp0 clock */ 385static struct clk ssp0_clk = { 386 .pclk = &apb_clk, 387 .en_reg = PERIP1_CLK_ENB, 388 .en_reg_bit = SSP0_CLK_ENB, 389 .recalc = &follow_parent, 390}; 391 392/* ssp1 clock */ 393static struct clk ssp1_clk = { 394 .pclk = &apb_clk, 395 .en_reg = PERIP1_CLK_ENB, 396 .en_reg_bit = SSP1_CLK_ENB, 397 .recalc = &follow_parent, 398}; 399 400/* ssp2 clock */ 401static struct clk ssp2_clk = { 402 .pclk = &apb_clk, 403 .en_reg = PERIP1_CLK_ENB, 404 .en_reg_bit = SSP2_CLK_ENB, 405 .recalc = &follow_parent, 406}; 407 408/* gpio0 ARM subsystem clock */ 409static struct clk gpio0_clk = { 410 .flags = ALWAYS_ENABLED, 411 .pclk = &apb_clk, 412 .recalc = &follow_parent, 413}; 414 415/* gpio1 clock */ 416static struct clk gpio1_clk = { 417 .pclk = &apb_clk, 418 .en_reg = PERIP1_CLK_ENB, 419 .en_reg_bit = GPIO1_CLK_ENB, 420 .recalc = &follow_parent, 421}; 422 423/* gpio2 clock */ 424static struct clk gpio2_clk = { 425 .pclk = &apb_clk, 426 .en_reg = PERIP1_CLK_ENB, 427 .en_reg_bit = GPIO2_CLK_ENB, 428 .recalc = &follow_parent, 429}; 430 431static struct clk dummy_apb_pclk; 432 433/* array of all spear 6xx clock lookups */ 434static struct clk_lookup spear_clk_lookups[] = { 435 { .con_id = "apb_pclk", .clk = &dummy_apb_pclk}, 436 /* root clks */ 437 { .con_id = "osc_32k_clk", .clk = &osc_32k_clk}, 438 { .con_id = "osc_30m_clk", .clk = &osc_30m_clk}, 439 /* clock derived from 32 KHz os clk */ 440 { .dev_id = "rtc", .clk = &rtc_clk}, 441 /* clock derived from 30 MHz os clk */ 442 { .con_id = "pll1_clk", .clk = &pll1_clk}, 443 { .con_id = "pll3_48m_clk", .clk = &pll3_48m_clk}, 444 { .dev_id = "wdt", .clk = &wdt_clk}, 445 /* clock derived from pll1 clk */ 446 { .con_id = "cpu_clk", .clk = &cpu_clk}, 447 { .con_id = "ahb_clk", .clk = &ahb_clk}, 448 { .dev_id = "uart0", .clk = &uart0_clk}, 449 { .dev_id = "uart1", .clk = &uart1_clk}, 450 { .dev_id = "firda", .clk = &firda_clk}, 451 { .dev_id = "clcd", .clk = &clcd_clk}, 452 { .dev_id = "gpt0", .clk = &gpt0_clk}, 453 { .dev_id = "gpt1", .clk = &gpt1_clk}, 454 { .dev_id = "gpt2", .clk = &gpt2_clk}, 455 { .dev_id = "gpt3", .clk = &gpt3_clk}, 456 /* clock derived from pll3 clk */ 457 { .dev_id = "usbh0", .clk = &usbh0_clk}, 458 { .dev_id = "usbh1", .clk = &usbh1_clk}, 459 { .dev_id = "usbd", .clk = &usbd_clk}, 460 /* clock derived from ahb clk */ 461 { .con_id = "apb_clk", .clk = &apb_clk}, 462 { .dev_id = "i2c", .clk = &i2c_clk}, 463 { .dev_id = "dma", .clk = &dma_clk}, 464 { .dev_id = "jpeg", .clk = &jpeg_clk}, 465 { .dev_id = "gmac", .clk = &gmac_clk}, 466 { .dev_id = "smi", .clk = &smi_clk}, 467 { .dev_id = "fsmc", .clk = &fsmc_clk}, 468 /* clock derived from apb clk */ 469 { .dev_id = "adc", .clk = &adc_clk}, 470 { .dev_id = "ssp0", .clk = &ssp0_clk}, 471 { .dev_id = "ssp1", .clk = &ssp1_clk}, 472 { .dev_id = "ssp2", .clk = &ssp2_clk}, 473 { .dev_id = "gpio0", .clk = &gpio0_clk}, 474 { .dev_id = "gpio1", .clk = &gpio1_clk}, 475 { .dev_id = "gpio2", .clk = &gpio2_clk}, 476}; 477 478void __init clk_init(void) 479{ 480 int i; 481 482 for (i = 0; i < ARRAY_SIZE(spear_clk_lookups); i++) 483 clk_register(&spear_clk_lookups[i]); 484 485 recalc_root_clocks(); 486} 487