1 /* 2 * Copyright 2004, 2007-2011 Freescale Semiconductor, Inc. 3 * 4 * (C) Copyright 2003 Motorola Inc. 5 * Xianghua Xiao, (X.Xiao@motorola.com) 6 * 7 * (C) Copyright 2000 8 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. 9 * 10 * See file CREDITS for list of people who contributed to this 11 * project. 12 * 13 * This program is free software; you can redistribute it and/or 14 * modify it under the terms of the GNU General Public License as 15 * published by the Free Software Foundation; either version 2 of 16 * the License, or (at your option) any later version. 17 * 18 * This program is distributed in the hope that it will be useful, 19 * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 * GNU General Public License for more details. 22 * 23 * You should have received a copy of the GNU General Public License 24 * along with this program; if not, write to the Free Software 25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 26 * MA 02111-1307 USA 27 */ 28 29 #include <common.h> 30 #include <ppc_asm.tmpl> 31 #include <linux/compiler.h> 32 #include <asm/processor.h> 33 #include <asm/io.h> 34 35 DECLARE_GLOBAL_DATA_PTR; 36 37 /* --------------------------------------------------------------- */ 38 39 void get_sys_info (sys_info_t * sysInfo) 40 { 41 volatile ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); 42 #ifdef CONFIG_FSL_IFC 43 struct fsl_ifc *ifc_regs = (void *)CONFIG_SYS_IFC_ADDR; 44 u32 ccr; 45 #endif 46 #ifdef CONFIG_FSL_CORENET 47 volatile ccsr_clk_t *clk = (void *)(CONFIG_SYS_FSL_CORENET_CLK_ADDR); 48 unsigned int cpu; 49 50 const u8 core_cplx_PLL[16] = { 51 [ 0] = 0, /* CC1 PPL / 1 */ 52 [ 1] = 0, /* CC1 PPL / 2 */ 53 [ 2] = 0, /* CC1 PPL / 4 */ 54 [ 4] = 1, /* CC2 PPL / 1 */ 55 [ 5] = 1, /* CC2 PPL / 2 */ 56 [ 6] = 1, /* CC2 PPL / 4 */ 57 [ 8] = 2, /* CC3 PPL / 1 */ 58 [ 9] = 2, /* CC3 PPL / 2 */ 59 [10] = 2, /* CC3 PPL / 4 */ 60 [12] = 3, /* CC4 PPL / 1 */ 61 [13] = 3, /* CC4 PPL / 2 */ 62 [14] = 3, /* CC4 PPL / 4 */ 63 }; 64 65 const u8 core_cplx_PLL_div[16] = { 66 [ 0] = 1, /* CC1 PPL / 1 */ 67 [ 1] = 2, /* CC1 PPL / 2 */ 68 [ 2] = 4, /* CC1 PPL / 4 */ 69 [ 4] = 1, /* CC2 PPL / 1 */ 70 [ 5] = 2, /* CC2 PPL / 2 */ 71 [ 6] = 4, /* CC2 PPL / 4 */ 72 [ 8] = 1, /* CC3 PPL / 1 */ 73 [ 9] = 2, /* CC3 PPL / 2 */ 74 [10] = 4, /* CC3 PPL / 4 */ 75 [12] = 1, /* CC4 PPL / 1 */ 76 [13] = 2, /* CC4 PPL / 2 */ 77 [14] = 4, /* CC4 PPL / 4 */ 78 }; 79 uint i, freqCC_PLL[6], rcw_tmp; 80 uint ratio[6]; 81 unsigned long sysclk = CONFIG_SYS_CLK_FREQ; 82 uint mem_pll_rat; 83 84 sysInfo->freqSystemBus = sysclk; 85 #ifdef CONFIG_DDR_CLK_FREQ 86 sysInfo->freqDDRBus = CONFIG_DDR_CLK_FREQ; 87 #else 88 sysInfo->freqDDRBus = sysclk; 89 #endif 90 91 sysInfo->freqSystemBus *= (in_be32(&gur->rcwsr[0]) >> 25) & 0x1f; 92 mem_pll_rat = (in_be32(&gur->rcwsr[0]) >> 93 FSL_CORENET_RCWSR0_MEM_PLL_RAT_SHIFT) 94 & FSL_CORENET_RCWSR0_MEM_PLL_RAT_MASK; 95 if (mem_pll_rat > 2) 96 sysInfo->freqDDRBus *= mem_pll_rat; 97 else 98 sysInfo->freqDDRBus = sysInfo->freqSystemBus * mem_pll_rat; 99 100 ratio[0] = (in_be32(&clk->pllc1gsr) >> 1) & 0x3f; 101 ratio[1] = (in_be32(&clk->pllc2gsr) >> 1) & 0x3f; 102 ratio[2] = (in_be32(&clk->pllc3gsr) >> 1) & 0x3f; 103 ratio[3] = (in_be32(&clk->pllc4gsr) >> 1) & 0x3f; 104 ratio[4] = (in_be32(&clk->pllc5gsr) >> 1) & 0x3f; 105 ratio[5] = (in_be32(&clk->pllc6gsr) >> 1) & 0x3f; 106 for (i = 0; i < 6; i++) { 107 if (ratio[i] > 4) 108 freqCC_PLL[i] = sysclk * ratio[i]; 109 else 110 freqCC_PLL[i] = sysInfo->freqSystemBus * ratio[i]; 111 } 112 #ifdef CONFIG_SYS_FSL_QORIQ_CHASSIS2 113 /* 114 * Each cluster has up to 4 cores, sharing the same PLL selection. 115 * The cluster assignment is fixed per SoC. PLL1, PLL2, PLL3 are 116 * cluster group A, feeding cores on cluster 1 and cluster 2. 117 * PLL4, PLL5, PLL6 are cluster group B, feeding cores on cluster 3 118 * and cluster 4 if existing. 119 */ 120 for_each_cpu(i, cpu, cpu_numcores(), cpu_mask()) { 121 int cluster = fsl_qoriq_core_to_cluster(cpu); 122 u32 c_pll_sel = (in_be32(&clk->clkcsr[cluster].clkcncsr) >> 27) 123 & 0xf; 124 u32 cplx_pll = core_cplx_PLL[c_pll_sel]; 125 if (cplx_pll > 3) 126 printf("Unsupported architecture configuration" 127 " in function %s\n", __func__); 128 cplx_pll += (cluster / 2) * 3; 129 sysInfo->freqProcessor[cpu] = 130 freqCC_PLL[cplx_pll] / core_cplx_PLL_div[c_pll_sel]; 131 } 132 #ifdef CONFIG_PPC_B4860 133 #define FM1_CLK_SEL 0xe0000000 134 #define FM1_CLK_SHIFT 29 135 #else 136 #define PME_CLK_SEL 0xe0000000 137 #define PME_CLK_SHIFT 29 138 #define FM1_CLK_SEL 0x1c000000 139 #define FM1_CLK_SHIFT 26 140 #endif 141 rcw_tmp = in_be32(&gur->rcwsr[7]); 142 143 #ifdef CONFIG_SYS_DPAA_PME 144 switch ((rcw_tmp & PME_CLK_SEL) >> PME_CLK_SHIFT) { 145 case 1: 146 sysInfo->freqPME = freqCC_PLL[0]; 147 break; 148 case 2: 149 sysInfo->freqPME = freqCC_PLL[0] / 2; 150 break; 151 case 3: 152 sysInfo->freqPME = freqCC_PLL[0] / 3; 153 break; 154 case 4: 155 sysInfo->freqPME = freqCC_PLL[0] / 4; 156 break; 157 case 6: 158 sysInfo->freqPME = freqCC_PLL[1] / 2; 159 break; 160 case 7: 161 sysInfo->freqPME = freqCC_PLL[1] / 3; 162 break; 163 default: 164 printf("Error: Unknown PME clock select!\n"); 165 case 0: 166 sysInfo->freqPME = sysInfo->freqSystemBus / 2; 167 break; 168 169 } 170 #endif 171 172 #ifdef CONFIG_SYS_DPAA_QBMAN 173 sysInfo->freqQMAN = sysInfo->freqSystemBus / 2; 174 #endif 175 176 #ifdef CONFIG_SYS_DPAA_FMAN 177 switch ((rcw_tmp & FM1_CLK_SEL) >> FM1_CLK_SHIFT) { 178 case 1: 179 sysInfo->freqFMan[0] = freqCC_PLL[3]; 180 break; 181 case 2: 182 sysInfo->freqFMan[0] = freqCC_PLL[3] / 2; 183 break; 184 case 3: 185 sysInfo->freqFMan[0] = freqCC_PLL[3] / 3; 186 break; 187 case 4: 188 sysInfo->freqFMan[0] = freqCC_PLL[3] / 4; 189 break; 190 case 5: 191 sysInfo->freqFMan[0] = sysInfo->freqSystemBus; 192 break; 193 case 6: 194 sysInfo->freqFMan[0] = freqCC_PLL[4] / 2; 195 break; 196 case 7: 197 sysInfo->freqFMan[0] = freqCC_PLL[4] / 3; 198 break; 199 default: 200 printf("Error: Unknown FMan1 clock select!\n"); 201 case 0: 202 sysInfo->freqFMan[0] = sysInfo->freqSystemBus / 2; 203 break; 204 } 205 #if (CONFIG_SYS_NUM_FMAN) == 2 206 #define FM2_CLK_SEL 0x00000038 207 #define FM2_CLK_SHIFT 3 208 rcw_tmp = in_be32(&gur->rcwsr[15]); 209 switch ((rcw_tmp & FM2_CLK_SEL) >> FM2_CLK_SHIFT) { 210 case 1: 211 sysInfo->freqFMan[1] = freqCC_PLL[4]; 212 break; 213 case 2: 214 sysInfo->freqFMan[1] = freqCC_PLL[4] / 2; 215 break; 216 case 3: 217 sysInfo->freqFMan[1] = freqCC_PLL[4] / 3; 218 break; 219 case 4: 220 sysInfo->freqFMan[1] = freqCC_PLL[4] / 4; 221 break; 222 case 6: 223 sysInfo->freqFMan[1] = freqCC_PLL[3] / 2; 224 break; 225 case 7: 226 sysInfo->freqFMan[1] = freqCC_PLL[3] / 3; 227 break; 228 default: 229 printf("Error: Unknown FMan2 clock select!\n"); 230 case 0: 231 sysInfo->freqFMan[1] = sysInfo->freqSystemBus / 2; 232 break; 233 } 234 #endif /* CONFIG_SYS_NUM_FMAN == 2 */ 235 #endif /* CONFIG_SYS_DPAA_FMAN */ 236 237 #else /* CONFIG_SYS_FSL_QORIQ_CHASSIS2 */ 238 239 for_each_cpu(i, cpu, cpu_numcores(), cpu_mask()) { 240 u32 c_pll_sel = (in_be32(&clk->clkcsr[cpu].clkcncsr) >> 27) 241 & 0xf; 242 u32 cplx_pll = core_cplx_PLL[c_pll_sel]; 243 244 sysInfo->freqProcessor[cpu] = 245 freqCC_PLL[cplx_pll] / core_cplx_PLL_div[c_pll_sel]; 246 } 247 #define PME_CLK_SEL 0x80000000 248 #define FM1_CLK_SEL 0x40000000 249 #define FM2_CLK_SEL 0x20000000 250 #define HWA_ASYNC_DIV 0x04000000 251 #if (CONFIG_SYS_FSL_NUM_CC_PLLS == 2) 252 #define HWA_CC_PLL 1 253 #elif (CONFIG_SYS_FSL_NUM_CC_PLLS == 3) 254 #define HWA_CC_PLL 2 255 #elif (CONFIG_SYS_FSL_NUM_CC_PLLS == 4) 256 #define HWA_CC_PLL 2 257 #else 258 #error CONFIG_SYS_FSL_NUM_CC_PLLS not set or unknown case 259 #endif 260 rcw_tmp = in_be32(&gur->rcwsr[7]); 261 262 #ifdef CONFIG_SYS_DPAA_PME 263 if (rcw_tmp & PME_CLK_SEL) { 264 if (rcw_tmp & HWA_ASYNC_DIV) 265 sysInfo->freqPME = freqCC_PLL[HWA_CC_PLL] / 4; 266 else 267 sysInfo->freqPME = freqCC_PLL[HWA_CC_PLL] / 2; 268 } else { 269 sysInfo->freqPME = sysInfo->freqSystemBus / 2; 270 } 271 #endif 272 273 #ifdef CONFIG_SYS_DPAA_FMAN 274 if (rcw_tmp & FM1_CLK_SEL) { 275 if (rcw_tmp & HWA_ASYNC_DIV) 276 sysInfo->freqFMan[0] = freqCC_PLL[HWA_CC_PLL] / 4; 277 else 278 sysInfo->freqFMan[0] = freqCC_PLL[HWA_CC_PLL] / 2; 279 } else { 280 sysInfo->freqFMan[0] = sysInfo->freqSystemBus / 2; 281 } 282 #if (CONFIG_SYS_NUM_FMAN) == 2 283 if (rcw_tmp & FM2_CLK_SEL) { 284 if (rcw_tmp & HWA_ASYNC_DIV) 285 sysInfo->freqFMan[1] = freqCC_PLL[HWA_CC_PLL] / 4; 286 else 287 sysInfo->freqFMan[1] = freqCC_PLL[HWA_CC_PLL] / 2; 288 } else { 289 sysInfo->freqFMan[1] = sysInfo->freqSystemBus / 2; 290 } 291 #endif 292 #endif 293 294 #ifdef CONFIG_SYS_DPAA_QBMAN 295 sysInfo->freqQMAN = sysInfo->freqSystemBus / 2; 296 #endif 297 298 #endif /* CONFIG_SYS_FSL_QORIQ_CHASSIS2 */ 299 300 #else /* CONFIG_FSL_CORENET */ 301 uint plat_ratio, e500_ratio, half_freqSystemBus; 302 int i; 303 #ifdef CONFIG_QE 304 __maybe_unused u32 qe_ratio; 305 #endif 306 307 plat_ratio = (gur->porpllsr) & 0x0000003e; 308 plat_ratio >>= 1; 309 sysInfo->freqSystemBus = plat_ratio * CONFIG_SYS_CLK_FREQ; 310 311 /* Divide before multiply to avoid integer 312 * overflow for processor speeds above 2GHz */ 313 half_freqSystemBus = sysInfo->freqSystemBus/2; 314 for (i = 0; i < cpu_numcores(); i++) { 315 e500_ratio = ((gur->porpllsr) >> (i * 8 + 16)) & 0x3f; 316 sysInfo->freqProcessor[i] = e500_ratio * half_freqSystemBus; 317 } 318 319 /* Note: freqDDRBus is the MCLK frequency, not the data rate. */ 320 sysInfo->freqDDRBus = sysInfo->freqSystemBus; 321 322 #ifdef CONFIG_DDR_CLK_FREQ 323 { 324 u32 ddr_ratio = ((gur->porpllsr) & MPC85xx_PORPLLSR_DDR_RATIO) 325 >> MPC85xx_PORPLLSR_DDR_RATIO_SHIFT; 326 if (ddr_ratio != 0x7) 327 sysInfo->freqDDRBus = ddr_ratio * CONFIG_DDR_CLK_FREQ; 328 } 329 #endif 330 331 #ifdef CONFIG_QE 332 #if defined(CONFIG_P1012) || defined(CONFIG_P1021) || defined(CONFIG_P1025) 333 sysInfo->freqQE = sysInfo->freqSystemBus; 334 #else 335 qe_ratio = ((gur->porpllsr) & MPC85xx_PORPLLSR_QE_RATIO) 336 >> MPC85xx_PORPLLSR_QE_RATIO_SHIFT; 337 sysInfo->freqQE = qe_ratio * CONFIG_SYS_CLK_FREQ; 338 #endif 339 #endif 340 341 #ifdef CONFIG_SYS_DPAA_FMAN 342 sysInfo->freqFMan[0] = sysInfo->freqSystemBus; 343 #endif 344 345 #endif /* CONFIG_FSL_CORENET */ 346 347 #if defined(CONFIG_FSL_LBC) 348 uint lcrr_div; 349 #if defined(CONFIG_SYS_LBC_LCRR) 350 /* We will program LCRR to this value later */ 351 lcrr_div = CONFIG_SYS_LBC_LCRR & LCRR_CLKDIV; 352 #else 353 lcrr_div = in_be32(&(LBC_BASE_ADDR)->lcrr) & LCRR_CLKDIV; 354 #endif 355 if (lcrr_div == 2 || lcrr_div == 4 || lcrr_div == 8) { 356 #if defined(CONFIG_FSL_CORENET) 357 /* If this is corenet based SoC, bit-representation 358 * for four times the clock divider values. 359 */ 360 lcrr_div *= 4; 361 #elif !defined(CONFIG_MPC8540) && !defined(CONFIG_MPC8541) && \ 362 !defined(CONFIG_MPC8555) && !defined(CONFIG_MPC8560) 363 /* 364 * Yes, the entire PQ38 family use the same 365 * bit-representation for twice the clock divider values. 366 */ 367 lcrr_div *= 2; 368 #endif 369 sysInfo->freqLocalBus = sysInfo->freqSystemBus / lcrr_div; 370 } else { 371 /* In case anyone cares what the unknown value is */ 372 sysInfo->freqLocalBus = lcrr_div; 373 } 374 #endif 375 376 #if defined(CONFIG_FSL_IFC) 377 ccr = in_be32(&ifc_regs->ifc_ccr); 378 ccr = ((ccr & IFC_CCR_CLK_DIV_MASK) >> IFC_CCR_CLK_DIV_SHIFT) + 1; 379 380 sysInfo->freqLocalBus = sysInfo->freqSystemBus / ccr; 381 #endif 382 } 383 384 385 int get_clocks (void) 386 { 387 sys_info_t sys_info; 388 #ifdef CONFIG_MPC8544 389 volatile ccsr_gur_t *gur = (void *) CONFIG_SYS_MPC85xx_GUTS_ADDR; 390 #endif 391 #if defined(CONFIG_CPM2) 392 volatile ccsr_cpm_t *cpm = (ccsr_cpm_t *)CONFIG_SYS_MPC85xx_CPM_ADDR; 393 uint sccr, dfbrg; 394 395 /* set VCO = 4 * BRG */ 396 cpm->im_cpm_intctl.sccr &= 0xfffffffc; 397 sccr = cpm->im_cpm_intctl.sccr; 398 dfbrg = (sccr & SCCR_DFBRG_MSK) >> SCCR_DFBRG_SHIFT; 399 #endif 400 get_sys_info (&sys_info); 401 gd->cpu_clk = sys_info.freqProcessor[0]; 402 gd->bus_clk = sys_info.freqSystemBus; 403 gd->mem_clk = sys_info.freqDDRBus; 404 gd->arch.lbc_clk = sys_info.freqLocalBus; 405 406 #ifdef CONFIG_QE 407 gd->arch.qe_clk = sys_info.freqQE; 408 gd->arch.brg_clk = gd->arch.qe_clk / 2; 409 #endif 410 /* 411 * The base clock for I2C depends on the actual SOC. Unfortunately, 412 * there is no pattern that can be used to determine the frequency, so 413 * the only choice is to look up the actual SOC number and use the value 414 * for that SOC. This information is taken from application note 415 * AN2919. 416 */ 417 #if defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || \ 418 defined(CONFIG_MPC8560) || defined(CONFIG_MPC8555) 419 gd->arch.i2c1_clk = sys_info.freqSystemBus; 420 #elif defined(CONFIG_MPC8544) 421 /* 422 * On the 8544, the I2C clock is the same as the SEC clock. This can be 423 * either CCB/2 or CCB/3, depending on the value of cfg_sec_freq. See 424 * 4.4.3.3 of the 8544 RM. Note that this might actually work for all 425 * 85xx, but only the 8544 has cfg_sec_freq, so it's unknown if the 426 * PORDEVSR2_SEC_CFG bit is 0 on all 85xx boards that are not an 8544. 427 */ 428 if (gur->pordevsr2 & MPC85xx_PORDEVSR2_SEC_CFG) 429 gd->arch.i2c1_clk = sys_info.freqSystemBus / 3; 430 else 431 gd->arch.i2c1_clk = sys_info.freqSystemBus / 2; 432 #else 433 /* Most 85xx SOCs use CCB/2, so this is the default behavior. */ 434 gd->arch.i2c1_clk = sys_info.freqSystemBus / 2; 435 #endif 436 gd->arch.i2c2_clk = gd->arch.i2c1_clk; 437 438 #if defined(CONFIG_FSL_ESDHC) 439 #if defined(CONFIG_MPC8569) || defined(CONFIG_P1010) ||\ 440 defined(CONFIG_P1014) 441 gd->arch.sdhc_clk = gd->bus_clk; 442 #else 443 gd->arch.sdhc_clk = gd->bus_clk / 2; 444 #endif 445 #endif /* defined(CONFIG_FSL_ESDHC) */ 446 447 #if defined(CONFIG_CPM2) 448 gd->arch.vco_out = 2*sys_info.freqSystemBus; 449 gd->arch.cpm_clk = gd->arch.vco_out / 2; 450 gd->arch.scc_clk = gd->arch.vco_out / 4; 451 gd->arch.brg_clk = gd->arch.vco_out / (1 << (2 * (dfbrg + 1))); 452 #endif 453 454 if(gd->cpu_clk != 0) return (0); 455 else return (1); 456 } 457 458 459 /******************************************** 460 * get_bus_freq 461 * return system bus freq in Hz 462 *********************************************/ 463 ulong get_bus_freq (ulong dummy) 464 { 465 return gd->bus_clk; 466 } 467 468 /******************************************** 469 * get_ddr_freq 470 * return ddr bus freq in Hz 471 *********************************************/ 472 ulong get_ddr_freq (ulong dummy) 473 { 474 return gd->mem_clk; 475 } 476