2 * (C) Copyright 2000-2007
3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
5 * See file CREDITS for list of people who contributed to this
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
25 #include <ppc_asm.tmpl>
27 #include <asm/processor.h>
29 DECLARE_GLOBAL_DATA_PTR;
31 #define ONE_BILLION 1000000000
33 #define DEBUGF(fmt,args...) printf(fmt ,##args)
35 #define DEBUGF(fmt,args...)
38 #if defined(CONFIG_405GP) || defined(CONFIG_405CR)
40 void get_sys_info (PPC4xx_SYS_INFO * sysInfo)
43 unsigned long sysClkPeriodPs = ONE_BILLION / (CONFIG_SYS_CLK_FREQ / 1000);
49 * Read PLL Mode register
51 pllmr = mfdcr (pllmd);
54 * Read Pin Strapping register
61 sysInfo->pllFwdDiv = 8 - ((pllmr & PLLMR_FWD_DIV_MASK) >> 29);
66 sysInfo->pllFbkDiv = ((pllmr & PLLMR_FB_DIV_MASK) >> 25);
67 if (sysInfo->pllFbkDiv == 0) {
68 sysInfo->pllFbkDiv = 16;
74 sysInfo->pllPlbDiv = ((pllmr & PLLMR_CPU_TO_PLB_MASK) >> 17) + 1;
79 sysInfo->pllPciDiv = ((pllmr & PLLMR_PCI_TO_PLB_MASK) >> 13) + 1;
82 * Determine EXTBUS_DIV.
84 sysInfo->pllExtBusDiv = ((pllmr & PLLMR_EXB_TO_PLB_MASK) >> 11) + 2;
89 sysInfo->pllOpbDiv = ((pllmr & PLLMR_OPB_TO_PLB_MASK) >> 15) + 1;
92 * Check if PPC405GPr used (mask minor revision field)
94 if ((pvr & 0xfffffff0) == (PVR_405GPR_RB & 0xfffffff0)) {
96 * Determine FWD_DIV B (only PPC405GPr with new mode strapping).
98 sysInfo->pllFwdDivB = 8 - (pllmr & PLLMR_FWDB_DIV_MASK);
101 * Determine factor m depending on PLL feedback clock source
103 if (!(psr & PSR_PCI_ASYNC_EN)) {
104 if (psr & PSR_NEW_MODE_EN) {
106 * sync pci clock used as feedback (new mode)
108 m = 1 * sysInfo->pllFwdDivB * 2 * sysInfo->pllPciDiv;
111 * sync pci clock used as feedback (legacy mode)
113 m = 1 * sysInfo->pllFwdDivB * sysInfo->pllPlbDiv * sysInfo->pllPciDiv;
115 } else if (psr & PSR_NEW_MODE_EN) {
116 if (psr & PSR_PERCLK_SYNC_MODE_EN) {
118 * PerClk used as feedback (new mode)
120 m = 1 * sysInfo->pllFwdDivB * 2 * sysInfo->pllExtBusDiv;
123 * CPU clock used as feedback (new mode)
125 m = sysInfo->pllFbkDiv * sysInfo->pllFwdDiv;
127 } else if (sysInfo->pllExtBusDiv == sysInfo->pllFbkDiv) {
129 * PerClk used as feedback (legacy mode)
131 m = 1 * sysInfo->pllFwdDivB * sysInfo->pllPlbDiv * sysInfo->pllExtBusDiv;
134 * PLB clock used as feedback (legacy mode)
136 m = sysInfo->pllFbkDiv * sysInfo->pllFwdDivB * sysInfo->pllPlbDiv;
139 sysInfo->freqVCOHz = (1000000000000LL * (unsigned long long)m) /
140 (unsigned long long)sysClkPeriodPs;
141 sysInfo->freqProcessor = sysInfo->freqVCOHz / sysInfo->pllFwdDiv;
142 sysInfo->freqPLB = sysInfo->freqVCOHz / (sysInfo->pllFwdDivB * sysInfo->pllPlbDiv);
145 * Check pllFwdDiv to see if running in bypass mode where the CPU speed
146 * is equal to the 405GP SYS_CLK_FREQ. If not in bypass mode, check VCO
147 * to make sure it is within the proper range.
148 * spec: VCO = SYS_CLOCK x FBKDIV x PLBDIV x FWDDIV
149 * Note freqVCO is calculated in Mhz to avoid errors introduced by rounding.
151 if (sysInfo->pllFwdDiv == 1) {
152 sysInfo->freqProcessor = CONFIG_SYS_CLK_FREQ;
153 sysInfo->freqPLB = CONFIG_SYS_CLK_FREQ / sysInfo->pllPlbDiv;
155 sysInfo->freqVCOHz = ( 1000000000000LL *
156 (unsigned long long)sysInfo->pllFwdDiv *
157 (unsigned long long)sysInfo->pllFbkDiv *
158 (unsigned long long)sysInfo->pllPlbDiv
159 ) / (unsigned long long)sysClkPeriodPs;
160 sysInfo->freqPLB = (ONE_BILLION / ((sysClkPeriodPs * 10) /
161 sysInfo->pllFbkDiv)) * 10000;
162 sysInfo->freqProcessor = sysInfo->freqPLB * sysInfo->pllPlbDiv;
166 sysInfo->freqUART = sysInfo->freqProcessor;
170 /********************************************
172 * return OPB bus freq in Hz
173 *********************************************/
174 ulong get_OPB_freq (void)
178 PPC4xx_SYS_INFO sys_info;
180 get_sys_info (&sys_info);
181 val = sys_info.freqPLB / sys_info.pllOpbDiv;
187 /********************************************
189 * return PCI bus freq in Hz
190 *********************************************/
191 ulong get_PCI_freq (void)
194 PPC4xx_SYS_INFO sys_info;
196 get_sys_info (&sys_info);
197 val = sys_info.freqPLB / sys_info.pllPciDiv;
202 #elif defined(CONFIG_440)
204 #if defined(CONFIG_440EP) || defined(CONFIG_440GR) || \
205 defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
206 void get_sys_info (sys_info_t *sysInfo)
212 unsigned long prbdv0;
214 WARNING: ASSUMES the following:
220 /* Decode CPR0_PLLD0 for divisors */
221 mfcpr(clk_plld, reg);
222 temp = (reg & PLLD_FWDVA_MASK) >> 16;
223 sysInfo->pllFwdDivA = temp ? temp : 16;
224 temp = (reg & PLLD_FWDVB_MASK) >> 8;
225 sysInfo->pllFwdDivB = temp ? temp: 8 ;
226 temp = (reg & PLLD_FBDV_MASK) >> 24;
227 sysInfo->pllFbkDiv = temp ? temp : 32;
228 lfdiv = reg & PLLD_LFBDV_MASK;
230 mfcpr(clk_opbd, reg);
231 temp = (reg & OPBDDV_MASK) >> 24;
232 sysInfo->pllOpbDiv = temp ? temp : 4;
234 mfcpr(clk_perd, reg);
235 temp = (reg & PERDV_MASK) >> 24;
236 sysInfo->pllExtBusDiv = temp ? temp : 8;
238 mfcpr(clk_primbd, reg);
239 temp = (reg & PRBDV_MASK) >> 24;
240 prbdv0 = temp ? temp : 8;
242 mfcpr(clk_spcid, reg);
243 temp = (reg & SPCID_MASK) >> 24;
244 sysInfo->pllPciDiv = temp ? temp : 4;
246 /* Calculate 'M' based on feedback source */
247 mfsdr(sdr_sdstp0, reg);
248 temp = (reg & PLLSYS0_SEL_MASK) >> 27;
249 if (temp == 0) { /* PLL output */
250 /* Figure which pll to use */
251 mfcpr(clk_pllc, reg);
252 temp = (reg & PLLC_SRC_MASK) >> 29;
253 if (!temp) /* PLLOUTA */
254 m = sysInfo->pllFbkDiv * lfdiv * sysInfo->pllFwdDivA;
256 m = sysInfo->pllFbkDiv * lfdiv * sysInfo->pllFwdDivB;
258 else if (temp == 1) /* CPU output */
259 m = sysInfo->pllFbkDiv * sysInfo->pllFwdDivA;
261 m = sysInfo->pllExtBusDiv * sysInfo->pllOpbDiv * sysInfo->pllFwdDivB;
263 /* Now calculate the individual clocks */
264 sysInfo->freqVCOMhz = (m * CONFIG_SYS_CLK_FREQ) + (m>>1);
265 sysInfo->freqProcessor = sysInfo->freqVCOMhz/sysInfo->pllFwdDivA;
266 sysInfo->freqPLB = sysInfo->freqVCOMhz/sysInfo->pllFwdDivB/prbdv0;
267 sysInfo->freqOPB = sysInfo->freqPLB/sysInfo->pllOpbDiv;
268 sysInfo->freqEBC = sysInfo->freqPLB/sysInfo->pllExtBusDiv;
269 sysInfo->freqPCI = sysInfo->freqPLB/sysInfo->pllPciDiv;
270 sysInfo->freqUART = sysInfo->freqPLB;
272 /* Figure which timer source to use */
273 if (mfspr(ccr1) & 0x0080) { /* External Clock, assume same as SYS_CLK */
274 temp = sysInfo->freqProcessor / 2; /* Max extern clock speed */
275 if (CONFIG_SYS_CLK_FREQ > temp)
276 sysInfo->freqTmrClk = temp;
278 sysInfo->freqTmrClk = CONFIG_SYS_CLK_FREQ;
280 else /* Internal clock */
281 sysInfo->freqTmrClk = sysInfo->freqProcessor;
284 /********************************************
286 * return PCI bus freq in Hz
287 *********************************************/
288 ulong get_PCI_freq (void)
291 get_sys_info (&sys_info);
292 return sys_info.freqPCI;
295 #elif !defined(CONFIG_440GX) && !defined(CONFIG_440SP) && !defined(CONFIG_440SPE)
296 void get_sys_info (sys_info_t * sysInfo)
302 /* Extract configured divisors */
303 strp0 = mfdcr( cpc0_strp0 );
304 sysInfo->pllFwdDivA = 8 - ((strp0 & PLLSYS0_FWD_DIV_A_MASK) >> 15);
305 sysInfo->pllFwdDivB = 8 - ((strp0 & PLLSYS0_FWD_DIV_B_MASK) >> 12);
306 temp = (strp0 & PLLSYS0_FB_DIV_MASK) >> 18;
307 sysInfo->pllFbkDiv = temp ? temp : 16;
308 sysInfo->pllOpbDiv = 1 + ((strp0 & PLLSYS0_OPB_DIV_MASK) >> 10);
309 sysInfo->pllExtBusDiv = 1 + ((strp0 & PLLSYS0_EPB_DIV_MASK) >> 8);
311 /* Calculate 'M' based on feedback source */
312 if( strp0 & PLLSYS0_EXTSL_MASK )
313 m = sysInfo->pllExtBusDiv * sysInfo->pllOpbDiv * sysInfo->pllFwdDivB;
315 m = sysInfo->pllFbkDiv * sysInfo->pllFwdDivA;
317 /* Now calculate the individual clocks */
318 sysInfo->freqVCOMhz = (m * CONFIG_SYS_CLK_FREQ) + (m>>1);
319 sysInfo->freqProcessor = sysInfo->freqVCOMhz/sysInfo->pllFwdDivA;
320 sysInfo->freqPLB = sysInfo->freqVCOMhz/sysInfo->pllFwdDivB;
321 if( get_pvr() == PVR_440GP_RB ) /* Rev B divs an extra 2 -- geez! */
322 sysInfo->freqPLB >>= 1;
323 sysInfo->freqOPB = sysInfo->freqPLB/sysInfo->pllOpbDiv;
324 sysInfo->freqEBC = sysInfo->freqOPB/sysInfo->pllExtBusDiv;
325 sysInfo->freqUART = sysInfo->freqPLB;
328 void get_sys_info (sys_info_t * sysInfo)
336 unsigned long prbdv0;
338 #if defined(CONFIG_YUCCA)
339 unsigned long sys_freq;
340 unsigned long sys_per=0;
342 unsigned long pci_clock_per;
343 unsigned long sdr_ddrpll;
345 /*-------------------------------------------------------------------------+
346 | Get the system clock period.
347 +-------------------------------------------------------------------------*/
348 sys_per = determine_sysper();
350 msr = (mfmsr () & ~(MSR_EE)); /* disable interrupts */
352 /*-------------------------------------------------------------------------+
353 | Calculate the system clock speed from the period.
354 +-------------------------------------------------------------------------*/
355 sys_freq = (ONE_BILLION / sys_per) * 1000;
358 /* Extract configured divisors */
359 mfsdr( sdr_sdstp0,strp0 );
360 mfsdr( sdr_sdstp1,strp1 );
362 temp = ((strp0 & PLLSYS0_FWD_DIV_A_MASK) >> 8);
363 sysInfo->pllFwdDivA = temp ? temp : 16 ;
364 temp = ((strp0 & PLLSYS0_FWD_DIV_B_MASK) >> 5);
365 sysInfo->pllFwdDivB = temp ? temp: 8 ;
366 temp = (strp0 & PLLSYS0_FB_DIV_MASK) >> 12;
367 sysInfo->pllFbkDiv = temp ? temp : 32;
368 temp = (strp0 & PLLSYS0_OPB_DIV_MASK);
369 sysInfo->pllOpbDiv = temp ? temp : 4;
370 temp = (strp1 & PLLSYS1_PERCLK_DIV_MASK) >> 24;
371 sysInfo->pllExtBusDiv = temp ? temp : 4;
372 prbdv0 = (strp0 >> 2) & 0x7;
374 /* Calculate 'M' based on feedback source */
375 temp = (strp0 & PLLSYS0_SEL_MASK) >> 27;
376 temp1 = (strp1 & PLLSYS1_LF_DIV_MASK) >> 26;
377 lfdiv = temp1 ? temp1 : 64;
378 if (temp == 0) { /* PLL output */
379 /* Figure which pll to use */
380 temp = (strp0 & PLLSYS0_SRC_MASK) >> 30;
382 m = sysInfo->pllFbkDiv * lfdiv * sysInfo->pllFwdDivA;
384 m = sysInfo->pllFbkDiv * lfdiv * sysInfo->pllFwdDivB;
386 else if (temp == 1) /* CPU output */
387 m = sysInfo->pllFbkDiv * sysInfo->pllFwdDivA;
389 m = sysInfo->pllExtBusDiv * sysInfo->pllOpbDiv * sysInfo->pllFwdDivB;
391 /* Now calculate the individual clocks */
392 #if defined(CONFIG_YUCCA)
393 sysInfo->freqVCOMhz = (m * sys_freq) ;
395 sysInfo->freqVCOMhz = (m * CONFIG_SYS_CLK_FREQ) + (m >> 1);
397 sysInfo->freqProcessor = sysInfo->freqVCOMhz/sysInfo->pllFwdDivA;
398 sysInfo->freqPLB = sysInfo->freqVCOMhz/sysInfo->pllFwdDivB/prbdv0;
399 sysInfo->freqOPB = sysInfo->freqPLB/sysInfo->pllOpbDiv;
400 sysInfo->freqEBC = sysInfo->freqOPB/sysInfo->pllExtBusDiv;
402 #if defined(CONFIG_YUCCA)
403 /* Determine PCI Clock Period */
404 pci_clock_per = determine_pci_clock_per();
405 sysInfo->freqPCI = (ONE_BILLION/pci_clock_per) * 1000;
406 mfsdr(sdr_ddr0, sdr_ddrpll);
407 sysInfo->freqDDR = ((sysInfo->freqPLB) * SDR0_DDR0_DDRM_DECODE(sdr_ddrpll));
410 sysInfo->freqUART = sysInfo->freqPLB;
415 #if defined(CONFIG_YUCCA)
416 unsigned long determine_sysper(void)
418 unsigned int fpga_clocking_reg;
419 unsigned int master_clock_selection;
420 unsigned long master_clock_per = 0;
421 unsigned long fb_div_selection;
422 unsigned int vco_div_reg_value;
423 unsigned long vco_div_selection;
424 unsigned long sys_per = 0;
427 /*-------------------------------------------------------------------------+
428 | Read FPGA reg 0 and reg 1 to get FPGA reg information
429 +-------------------------------------------------------------------------*/
430 fpga_clocking_reg = in16(FPGA_REG16);
433 /* Determine Master Clock Source Selection */
434 master_clock_selection = fpga_clocking_reg & FPGA_REG16_MASTER_CLK_MASK;
436 switch(master_clock_selection) {
437 case FPGA_REG16_MASTER_CLK_66_66:
438 master_clock_per = PERIOD_66_66MHZ;
440 case FPGA_REG16_MASTER_CLK_50:
441 master_clock_per = PERIOD_50_00MHZ;
443 case FPGA_REG16_MASTER_CLK_33_33:
444 master_clock_per = PERIOD_33_33MHZ;
446 case FPGA_REG16_MASTER_CLK_25:
447 master_clock_per = PERIOD_25_00MHZ;
449 case FPGA_REG16_MASTER_CLK_EXT:
450 if ((extClkVal==EXTCLK_33_33)
451 && (extClkVal==EXTCLK_50)
452 && (extClkVal==EXTCLK_66_66)
453 && (extClkVal==EXTCLK_83)) {
454 /* calculate master clock period from external clock value */
455 master_clock_per=(ONE_BILLION/extClkVal) * 1000;
458 DEBUGF ("%s[%d] *** master clock selection failed ***\n", __FUNCTION__,__LINE__);
464 DEBUGF ("%s[%d] *** master clock selection failed ***\n", __FUNCTION__,__LINE__);
469 /* Determine FB divisors values */
470 if ((fpga_clocking_reg & FPGA_REG16_FB1_DIV_MASK) == FPGA_REG16_FB1_DIV_LOW) {
471 if ((fpga_clocking_reg & FPGA_REG16_FB2_DIV_MASK) == FPGA_REG16_FB2_DIV_LOW)
472 fb_div_selection = FPGA_FB_DIV_6;
474 fb_div_selection = FPGA_FB_DIV_12;
476 if ((fpga_clocking_reg & FPGA_REG16_FB2_DIV_MASK) == FPGA_REG16_FB2_DIV_LOW)
477 fb_div_selection = FPGA_FB_DIV_10;
479 fb_div_selection = FPGA_FB_DIV_20;
482 /* Determine VCO divisors values */
483 vco_div_reg_value = fpga_clocking_reg & FPGA_REG16_VCO_DIV_MASK;
485 switch(vco_div_reg_value) {
486 case FPGA_REG16_VCO_DIV_4:
487 vco_div_selection = FPGA_VCO_DIV_4;
489 case FPGA_REG16_VCO_DIV_6:
490 vco_div_selection = FPGA_VCO_DIV_6;
492 case FPGA_REG16_VCO_DIV_8:
493 vco_div_selection = FPGA_VCO_DIV_8;
495 case FPGA_REG16_VCO_DIV_10:
497 vco_div_selection = FPGA_VCO_DIV_10;
501 if (master_clock_selection == FPGA_REG16_MASTER_CLK_EXT) {
502 switch(master_clock_per) {
503 case PERIOD_25_00MHZ:
504 if (fb_div_selection == FPGA_FB_DIV_12) {
505 if (vco_div_selection == FPGA_VCO_DIV_4)
506 sys_per = PERIOD_75_00MHZ;
507 if (vco_div_selection == FPGA_VCO_DIV_6)
508 sys_per = PERIOD_50_00MHZ;
511 case PERIOD_33_33MHZ:
512 if (fb_div_selection == FPGA_FB_DIV_6) {
513 if (vco_div_selection == FPGA_VCO_DIV_4)
514 sys_per = PERIOD_50_00MHZ;
515 if (vco_div_selection == FPGA_VCO_DIV_6)
516 sys_per = PERIOD_33_33MHZ;
518 if (fb_div_selection == FPGA_FB_DIV_10) {
519 if (vco_div_selection == FPGA_VCO_DIV_4)
520 sys_per = PERIOD_83_33MHZ;
521 if (vco_div_selection == FPGA_VCO_DIV_10)
522 sys_per = PERIOD_33_33MHZ;
524 if (fb_div_selection == FPGA_FB_DIV_12) {
525 if (vco_div_selection == FPGA_VCO_DIV_4)
526 sys_per = PERIOD_100_00MHZ;
527 if (vco_div_selection == FPGA_VCO_DIV_6)
528 sys_per = PERIOD_66_66MHZ;
529 if (vco_div_selection == FPGA_VCO_DIV_8)
530 sys_per = PERIOD_50_00MHZ;
533 case PERIOD_50_00MHZ:
534 if (fb_div_selection == FPGA_FB_DIV_6) {
535 if (vco_div_selection == FPGA_VCO_DIV_4)
536 sys_per = PERIOD_75_00MHZ;
537 if (vco_div_selection == FPGA_VCO_DIV_6)
538 sys_per = PERIOD_50_00MHZ;
540 if (fb_div_selection == FPGA_FB_DIV_10) {
541 if (vco_div_selection == FPGA_VCO_DIV_6)
542 sys_per = PERIOD_83_33MHZ;
543 if (vco_div_selection == FPGA_VCO_DIV_10)
544 sys_per = PERIOD_50_00MHZ;
546 if (fb_div_selection == FPGA_FB_DIV_12) {
547 if (vco_div_selection == FPGA_VCO_DIV_6)
548 sys_per = PERIOD_100_00MHZ;
549 if (vco_div_selection == FPGA_VCO_DIV_8)
550 sys_per = PERIOD_75_00MHZ;
553 case PERIOD_66_66MHZ:
554 if (fb_div_selection == FPGA_FB_DIV_6) {
555 if (vco_div_selection == FPGA_VCO_DIV_4)
556 sys_per = PERIOD_100_00MHZ;
557 if (vco_div_selection == FPGA_VCO_DIV_6)
558 sys_per = PERIOD_66_66MHZ;
559 if (vco_div_selection == FPGA_VCO_DIV_8)
560 sys_per = PERIOD_50_00MHZ;
562 if (fb_div_selection == FPGA_FB_DIV_10) {
563 if (vco_div_selection == FPGA_VCO_DIV_8)
564 sys_per = PERIOD_83_33MHZ;
565 if (vco_div_selection == FPGA_VCO_DIV_10)
566 sys_per = PERIOD_66_66MHZ;
568 if (fb_div_selection == FPGA_FB_DIV_12) {
569 if (vco_div_selection == FPGA_VCO_DIV_8)
570 sys_per = PERIOD_100_00MHZ;
578 /* Other combinations are not supported */
579 DEBUGF ("%s[%d] *** sys period compute failed ***\n", __FUNCTION__,__LINE__);
583 /* calcul system clock without cheking */
584 /* if engineering option clock no check is selected */
585 /* sys_per = master_clock_per * vco_div_selection / fb_div_selection */
586 sys_per = (master_clock_per/fb_div_selection) * vco_div_selection;
592 /*-------------------------------------------------------------------------+
593 | determine_pci_clock_per.
594 +-------------------------------------------------------------------------*/
595 unsigned long determine_pci_clock_per(void)
597 unsigned long pci_clock_selection, pci_period;
599 /*-------------------------------------------------------------------------+
600 | Read FPGA reg 6 to get PCI 0 FPGA reg information
601 +-------------------------------------------------------------------------*/
602 pci_clock_selection = in16(FPGA_REG16); /* was reg6 averifier */
605 pci_clock_selection = pci_clock_selection & FPGA_REG16_PCI0_CLK_MASK;
607 switch (pci_clock_selection) {
608 case FPGA_REG16_PCI0_CLK_133_33:
609 pci_period = PERIOD_133_33MHZ;
611 case FPGA_REG16_PCI0_CLK_100:
612 pci_period = PERIOD_100_00MHZ;
614 case FPGA_REG16_PCI0_CLK_66_66:
615 pci_period = PERIOD_66_66MHZ;
618 pci_period = PERIOD_33_33MHZ;;
626 ulong get_OPB_freq (void)
630 get_sys_info (&sys_info);
631 return sys_info.freqOPB;
634 #elif defined(CONFIG_XILINX_ML300)
635 extern void get_sys_info (sys_info_t * sysInfo);
636 extern ulong get_PCI_freq (void);
638 #elif defined(CONFIG_AP1000)
639 void get_sys_info (sys_info_t * sysInfo)
641 sysInfo->freqProcessor = 240 * 1000 * 1000;
642 sysInfo->freqPLB = 80 * 1000 * 1000;
643 sysInfo->freqPCI = 33 * 1000 * 1000;
646 #elif defined(CONFIG_405)
648 void get_sys_info (sys_info_t * sysInfo)
650 sysInfo->freqVCOMhz=3125000;
651 sysInfo->freqProcessor=12*1000*1000;
652 sysInfo->freqPLB=50*1000*1000;
653 sysInfo->freqPCI=66*1000*1000;
656 #elif defined(CONFIG_405EP)
657 void get_sys_info (PPC4xx_SYS_INFO * sysInfo)
659 unsigned long pllmr0;
660 unsigned long pllmr1;
661 unsigned long sysClkPeriodPs = ONE_BILLION / (CONFIG_SYS_CLK_FREQ / 1000);
663 unsigned long pllmr0_ccdv;
666 * Read PLL Mode registers
668 pllmr0 = mfdcr (cpc0_pllmr0);
669 pllmr1 = mfdcr (cpc0_pllmr1);
672 * Determine forward divider A
674 sysInfo->pllFwdDiv = 8 - ((pllmr1 & PLLMR1_FWDVA_MASK) >> 16);
677 * Determine forward divider B (should be equal to A)
679 sysInfo->pllFwdDivB = 8 - ((pllmr1 & PLLMR1_FWDVB_MASK) >> 12);
684 sysInfo->pllFbkDiv = ((pllmr1 & PLLMR1_FBMUL_MASK) >> 20);
685 if (sysInfo->pllFbkDiv == 0)
686 sysInfo->pllFbkDiv = 16;
691 sysInfo->pllPlbDiv = ((pllmr0 & PLLMR0_CPU_TO_PLB_MASK) >> 16) + 1;
696 sysInfo->pllPciDiv = (pllmr0 & PLLMR0_PCI_TO_PLB_MASK) + 1;
699 * Determine EXTBUS_DIV.
701 sysInfo->pllExtBusDiv = ((pllmr0 & PLLMR0_EXB_TO_PLB_MASK) >> 8) + 2;
706 sysInfo->pllOpbDiv = ((pllmr0 & PLLMR0_OPB_TO_PLB_MASK) >> 12) + 1;
709 * Determine the M factor
711 m = sysInfo->pllFbkDiv * sysInfo->pllFwdDivB;
714 * Determine VCO clock frequency
716 sysInfo->freqVCOHz = (1000000000000LL * (unsigned long long)m) /
717 (unsigned long long)sysClkPeriodPs;
720 * Determine CPU clock frequency
722 pllmr0_ccdv = ((pllmr0 & PLLMR0_CPU_DIV_MASK) >> 20) + 1;
723 if (pllmr1 & PLLMR1_SSCS_MASK) {
725 * This is true if FWDVA == FWDVB:
726 * sysInfo->freqProcessor = (CONFIG_SYS_CLK_FREQ * sysInfo->pllFbkDiv)
729 sysInfo->freqProcessor = (CONFIG_SYS_CLK_FREQ * sysInfo->pllFbkDiv * sysInfo->pllFwdDivB)
730 / sysInfo->pllFwdDiv / pllmr0_ccdv;
732 sysInfo->freqProcessor = CONFIG_SYS_CLK_FREQ / pllmr0_ccdv;
736 * Determine PLB clock frequency
738 sysInfo->freqPLB = sysInfo->freqProcessor / sysInfo->pllPlbDiv;
740 sysInfo->freqEBC = sysInfo->freqPLB / sysInfo->pllExtBusDiv;
742 sysInfo->freqUART = sysInfo->freqProcessor * pllmr0_ccdv;
746 /********************************************
748 * return OPB bus freq in Hz
749 *********************************************/
750 ulong get_OPB_freq (void)
754 PPC4xx_SYS_INFO sys_info;
756 get_sys_info (&sys_info);
757 val = sys_info.freqPLB / sys_info.pllOpbDiv;
763 /********************************************
765 * return PCI bus freq in Hz
766 *********************************************/
767 ulong get_PCI_freq (void)
770 PPC4xx_SYS_INFO sys_info;
772 get_sys_info (&sys_info);
773 val = sys_info.freqPLB / sys_info.pllPciDiv;
777 #elif defined(CONFIG_405EZ)
778 void get_sys_info (PPC4xx_SYS_INFO * sysInfo)
780 unsigned long cpr_plld;
781 unsigned long cpr_pllc;
782 unsigned long cpr_primad;
783 unsigned long sysClkPeriodPs = ONE_BILLION / (CONFIG_SYS_CLK_FREQ/1000);
784 unsigned long primad_cpudv;
788 * Read PLL Mode registers
790 mfcpr(cprplld, cpr_plld);
791 mfcpr(cprpllc, cpr_pllc);
794 * Determine forward divider A
796 sysInfo->pllFwdDiv = ((cpr_plld & PLLD_FWDVA_MASK) >> 16);
799 * Determine forward divider B
801 sysInfo->pllFwdDivB = ((cpr_plld & PLLD_FWDVB_MASK) >> 8);
802 if (sysInfo->pllFwdDivB == 0)
803 sysInfo->pllFwdDivB = 8;
808 sysInfo->pllFbkDiv = ((cpr_plld & PLLD_FBDV_MASK) >> 24);
809 if (sysInfo->pllFbkDiv == 0)
810 sysInfo->pllFbkDiv = 256;
813 * Read CPR_PRIMAD register
815 mfcpr(cprprimad, cpr_primad);
820 sysInfo->pllPlbDiv = ((cpr_primad & PRIMAD_PLBDV_MASK) >> 16);
821 if (sysInfo->pllPlbDiv == 0)
822 sysInfo->pllPlbDiv = 16;
825 * Determine EXTBUS_DIV.
827 sysInfo->pllExtBusDiv = (cpr_primad & PRIMAD_EBCDV_MASK);
828 if (sysInfo->pllExtBusDiv == 0)
829 sysInfo->pllExtBusDiv = 16;
834 sysInfo->pllOpbDiv = ((cpr_primad & PRIMAD_OPBDV_MASK) >> 8);
835 if (sysInfo->pllOpbDiv == 0)
836 sysInfo->pllOpbDiv = 16;
839 * Determine the M factor
841 if (cpr_pllc & PLLC_SRC_MASK)
842 m = sysInfo->pllFbkDiv * sysInfo->pllFwdDivB;
844 m = sysInfo->pllFbkDiv * sysInfo->pllFwdDiv;
847 * Determine VCO clock frequency
849 sysInfo->freqVCOHz = (1000000000000LL * (unsigned long long)m) /
850 (unsigned long long)sysClkPeriodPs;
853 * Determine CPU clock frequency
855 primad_cpudv = ((cpr_primad & PRIMAD_CPUDV_MASK) >> 24);
856 if (primad_cpudv == 0)
859 sysInfo->freqProcessor = (CONFIG_SYS_CLK_FREQ * m) /
860 sysInfo->pllFwdDiv / primad_cpudv;
863 * Determine PLB clock frequency
865 sysInfo->freqPLB = (CONFIG_SYS_CLK_FREQ * m) /
866 sysInfo->pllFwdDiv / sysInfo->pllPlbDiv;
868 sysInfo->freqEBC = (CONFIG_SYS_CLK_FREQ * sysInfo->pllFbkDiv) /
869 sysInfo->pllExtBusDiv;
871 sysInfo->freqUART = sysInfo->freqVCOHz;
874 /********************************************
876 * return OPB bus freq in Hz
877 *********************************************/
878 ulong get_OPB_freq (void)
882 PPC4xx_SYS_INFO sys_info;
884 get_sys_info (&sys_info);
885 val = (CONFIG_SYS_CLK_FREQ * sys_info.pllFbkDiv) / sys_info.pllOpbDiv;
890 #elif defined(CONFIG_405EX)
893 * TODO: We need to get the CPR registers and calculate these values correctly!!!!
894 * We need the specs!!!!
896 static unsigned char get_fbdv(unsigned char index)
898 unsigned char ret = 0;
899 /* This is table should be 256 bytes.
900 * Only take first 52 values.
902 unsigned char fbdv_tb[] = {
903 0x00, 0xff, 0x7f, 0xfd,
904 0x7a, 0xf5, 0x6a, 0xd5,
905 0x2a, 0xd4, 0x29, 0xd3,
906 0x26, 0xcc, 0x19, 0xb3,
907 0x67, 0xce, 0x1d, 0xbb,
908 0x77, 0xee, 0x5d, 0xba,
909 0x74, 0xe9, 0x52, 0xa5,
910 0x4b, 0x96, 0x2c, 0xd8,
911 0x31, 0xe3, 0x46, 0x8d,
912 0x1b, 0xb7, 0x6f, 0xde,
913 0x3d, 0xfb, 0x76, 0xed,
914 0x5a, 0xb5, 0x6b, 0xd6,
915 0x2d, 0xdb, 0x36, 0xec,
919 if ((index & 0x7f) == 0)
921 while (ret < sizeof (fbdv_tb)) {
922 if (fbdv_tb[ret] == index)
931 #define PLL_FBK_PLL_LOCAL 0
932 #define PLL_FBK_CPU 1
933 #define PLL_FBK_PERCLK 5
935 void get_sys_info (sys_info_t * sysInfo)
937 unsigned long sysClkPeriodPs = ONE_BILLION / (CONFIG_SYS_CLK_FREQ / 1000);
940 unsigned char fwdva[16] = {
941 1, 2, 14, 9, 4, 11, 16, 13,
942 12, 5, 6, 15, 10, 7, 8, 3,
944 unsigned char sel, cpudv0, plb2xDiv;
946 mfcpr(cpr0_plld, tmp);
949 * Determine forward divider A
951 sysInfo->pllFwdDiv = fwdva[((tmp >> 16) & 0x0f)]; /* FWDVA */
956 sysInfo->pllFbkDiv = get_fbdv(((tmp >> 24) & 0x0ff)); /* FBDV */
961 sysInfo->pllPlbDiv = 2;
966 mfcpr(cpr0_perd, tmp);
967 tmp = (tmp >> 24) & 0x03;
968 sysInfo->pllExtBusDiv = (tmp == 0) ? 4 : tmp;
973 mfcpr(cpr0_opbd, tmp);
974 tmp = (tmp >> 24) & 0x03;
975 sysInfo->pllOpbDiv = (tmp == 0) ? 4 : tmp;
977 /* Determine PLB2XDV0 */
978 mfcpr(cpr0_plbd, tmp);
979 tmp = (tmp >> 16) & 0x07;
980 plb2xDiv = (tmp == 0) ? 8 : tmp;
982 /* Determine CPUDV0 */
983 mfcpr(cpr0_cpud, tmp);
984 tmp = (tmp >> 24) & 0x07;
985 cpudv0 = (tmp == 0) ? 8 : tmp;
987 /* Determine SEL(5:7) in CPR0_PLLC */
988 mfcpr(cpr0_pllc, tmp);
989 sel = (tmp >> 24) & 0x07;
992 * Determine the M factor
993 * PLL local: M = FBDV
994 * CPU clock: M = FBDV * FWDVA * CPUDV0
995 * PerClk : M = FBDV * FWDVA * PLB2XDV0 * PLBDV0(2) * OPBDV0 * PERDV0
1000 m = sysInfo->pllFwdDiv * cpudv0;
1002 case PLL_FBK_PERCLK:
1003 m = sysInfo->pllFwdDiv * plb2xDiv * 2
1004 * sysInfo->pllOpbDiv * sysInfo->pllExtBusDiv;
1006 case PLL_FBK_PLL_LOCAL:
1009 printf("%s unknown m\n", __FUNCTION__);
1013 m *= sysInfo->pllFbkDiv;
1016 * Determine VCO clock frequency
1018 sysInfo->freqVCOHz = (1000000000000LL * (unsigned long long)m) /
1019 (unsigned long long)sysClkPeriodPs;
1022 * Determine CPU clock frequency
1024 sysInfo->freqProcessor = sysInfo->freqVCOHz / (sysInfo->pllFwdDiv * cpudv0);
1027 * Determine PLB clock frequency, ddr1x should be the same
1029 sysInfo->freqPLB = sysInfo->freqVCOHz / (sysInfo->pllFwdDiv * plb2xDiv * 2);
1030 sysInfo->freqOPB = sysInfo->freqPLB/sysInfo->pllOpbDiv;
1031 sysInfo->freqDDR = sysInfo->freqPLB;
1032 sysInfo->freqEBC = sysInfo->freqOPB / sysInfo->pllExtBusDiv;
1033 sysInfo->freqUART = sysInfo->freqPLB;
1036 /********************************************
1038 * return OPB bus freq in Hz
1039 *********************************************/
1040 ulong get_OPB_freq (void)
1044 PPC4xx_SYS_INFO sys_info;
1046 get_sys_info (&sys_info);
1047 val = sys_info.freqPLB / sys_info.pllOpbDiv;
1054 int get_clocks (void)
1056 #if defined(CONFIG_405GP) || defined(CONFIG_405CR) || \
1057 defined(CONFIG_405EP) || defined(CONFIG_405EZ) || \
1058 defined(CONFIG_405EX) || defined(CONFIG_405) || \
1060 sys_info_t sys_info;
1062 get_sys_info (&sys_info);
1063 gd->cpu_clk = sys_info.freqProcessor;
1064 gd->bus_clk = sys_info.freqPLB;
1066 #endif /* defined(CONFIG_405GP) || defined(CONFIG_405CR) */
1068 #ifdef CONFIG_IOP480
1069 gd->cpu_clk = 66000000;
1070 gd->bus_clk = 66000000;
1076 /********************************************
1078 * return PLB bus freq in Hz
1079 *********************************************/
1080 ulong get_bus_freq (ulong dummy)
1084 #if defined(CONFIG_405GP) || defined(CONFIG_405CR) || \
1085 defined(CONFIG_405EP) || defined(CONFIG_405EZ) || \
1086 defined(CONFIG_405EX) || defined(CONFIG_405) || \
1088 sys_info_t sys_info;
1090 get_sys_info (&sys_info);
1091 val = sys_info.freqPLB;
1093 #elif defined(CONFIG_IOP480)
1098 # error get_bus_freq() not implemented