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;
168 /********************************************
170 * return OPB bus freq in Hz
171 *********************************************/
172 ulong get_OPB_freq (void)
176 PPC4xx_SYS_INFO sys_info;
178 get_sys_info (&sys_info);
179 val = sys_info.freqPLB / sys_info.pllOpbDiv;
185 /********************************************
187 * return PCI bus freq in Hz
188 *********************************************/
189 ulong get_PCI_freq (void)
192 PPC4xx_SYS_INFO sys_info;
194 get_sys_info (&sys_info);
195 val = sys_info.freqPLB / sys_info.pllPciDiv;
200 #elif defined(CONFIG_440)
202 #if defined(CONFIG_440EP) || defined(CONFIG_440GR) || \
203 defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
204 void get_sys_info (sys_info_t *sysInfo)
210 unsigned long prbdv0;
212 WARNING: ASSUMES the following:
218 /* Decode CPR0_PLLD0 for divisors */
219 mfcpr(clk_plld, reg);
220 temp = (reg & PLLD_FWDVA_MASK) >> 16;
221 sysInfo->pllFwdDivA = temp ? temp : 16;
222 temp = (reg & PLLD_FWDVB_MASK) >> 8;
223 sysInfo->pllFwdDivB = temp ? temp: 8 ;
224 temp = (reg & PLLD_FBDV_MASK) >> 24;
225 sysInfo->pllFbkDiv = temp ? temp : 32;
226 lfdiv = reg & PLLD_LFBDV_MASK;
228 mfcpr(clk_opbd, reg);
229 temp = (reg & OPBDDV_MASK) >> 24;
230 sysInfo->pllOpbDiv = temp ? temp : 4;
232 mfcpr(clk_perd, reg);
233 temp = (reg & PERDV_MASK) >> 24;
234 sysInfo->pllExtBusDiv = temp ? temp : 8;
236 mfcpr(clk_primbd, reg);
237 temp = (reg & PRBDV_MASK) >> 24;
238 prbdv0 = temp ? temp : 8;
240 mfcpr(clk_spcid, reg);
241 temp = (reg & SPCID_MASK) >> 24;
242 sysInfo->pllPciDiv = temp ? temp : 4;
244 /* Calculate 'M' based on feedback source */
245 mfsdr(sdr_sdstp0, reg);
246 temp = (reg & PLLSYS0_SEL_MASK) >> 27;
247 if (temp == 0) { /* PLL output */
248 /* Figure which pll to use */
249 mfcpr(clk_pllc, reg);
250 temp = (reg & PLLC_SRC_MASK) >> 29;
251 if (!temp) /* PLLOUTA */
252 m = sysInfo->pllFbkDiv * lfdiv * sysInfo->pllFwdDivA;
254 m = sysInfo->pllFbkDiv * lfdiv * sysInfo->pllFwdDivB;
256 else if (temp == 1) /* CPU output */
257 m = sysInfo->pllFbkDiv * sysInfo->pllFwdDivA;
259 m = sysInfo->pllExtBusDiv * sysInfo->pllOpbDiv * sysInfo->pllFwdDivB;
261 /* Now calculate the individual clocks */
262 sysInfo->freqVCOMhz = (m * CONFIG_SYS_CLK_FREQ) + (m>>1);
263 sysInfo->freqProcessor = sysInfo->freqVCOMhz/sysInfo->pllFwdDivA;
264 sysInfo->freqPLB = sysInfo->freqVCOMhz/sysInfo->pllFwdDivB/prbdv0;
265 sysInfo->freqOPB = sysInfo->freqPLB/sysInfo->pllOpbDiv;
266 sysInfo->freqEBC = sysInfo->freqPLB/sysInfo->pllExtBusDiv;
267 sysInfo->freqPCI = sysInfo->freqPLB/sysInfo->pllPciDiv;
269 /* Figure which timer source to use */
270 if (mfspr(ccr1) & 0x0080) { /* External Clock, assume same as SYS_CLK */
271 temp = sysInfo->freqProcessor / 2; /* Max extern clock speed */
272 if (CONFIG_SYS_CLK_FREQ > temp)
273 sysInfo->freqTmrClk = temp;
275 sysInfo->freqTmrClk = CONFIG_SYS_CLK_FREQ;
277 else /* Internal clock */
278 sysInfo->freqTmrClk = sysInfo->freqProcessor;
280 /********************************************
282 * return PCI bus freq in Hz
283 *********************************************/
284 ulong get_PCI_freq (void)
287 get_sys_info (&sys_info);
288 return sys_info.freqPCI;
291 #elif !defined(CONFIG_440GX) && !defined(CONFIG_440SP) && !defined(CONFIG_440SPE)
292 void get_sys_info (sys_info_t * sysInfo)
298 /* Extract configured divisors */
299 strp0 = mfdcr( cpc0_strp0 );
300 sysInfo->pllFwdDivA = 8 - ((strp0 & PLLSYS0_FWD_DIV_A_MASK) >> 15);
301 sysInfo->pllFwdDivB = 8 - ((strp0 & PLLSYS0_FWD_DIV_B_MASK) >> 12);
302 temp = (strp0 & PLLSYS0_FB_DIV_MASK) >> 18;
303 sysInfo->pllFbkDiv = temp ? temp : 16;
304 sysInfo->pllOpbDiv = 1 + ((strp0 & PLLSYS0_OPB_DIV_MASK) >> 10);
305 sysInfo->pllExtBusDiv = 1 + ((strp0 & PLLSYS0_EPB_DIV_MASK) >> 8);
307 /* Calculate 'M' based on feedback source */
308 if( strp0 & PLLSYS0_EXTSL_MASK )
309 m = sysInfo->pllExtBusDiv * sysInfo->pllOpbDiv * sysInfo->pllFwdDivB;
311 m = sysInfo->pllFbkDiv * sysInfo->pllFwdDivA;
313 /* Now calculate the individual clocks */
314 sysInfo->freqVCOMhz = (m * CONFIG_SYS_CLK_FREQ) + (m>>1);
315 sysInfo->freqProcessor = sysInfo->freqVCOMhz/sysInfo->pllFwdDivA;
316 sysInfo->freqPLB = sysInfo->freqVCOMhz/sysInfo->pllFwdDivB;
317 if( get_pvr() == PVR_440GP_RB ) /* Rev B divs an extra 2 -- geez! */
318 sysInfo->freqPLB >>= 1;
319 sysInfo->freqOPB = sysInfo->freqPLB/sysInfo->pllOpbDiv;
320 sysInfo->freqEBC = sysInfo->freqOPB/sysInfo->pllExtBusDiv;
324 void get_sys_info (sys_info_t * sysInfo)
332 unsigned long prbdv0;
334 #if defined(CONFIG_YUCCA)
335 unsigned long sys_freq;
336 unsigned long sys_per=0;
338 unsigned long pci_clock_per;
339 unsigned long sdr_ddrpll;
341 /*-------------------------------------------------------------------------+
342 | Get the system clock period.
343 +-------------------------------------------------------------------------*/
344 sys_per = determine_sysper();
346 msr = (mfmsr () & ~(MSR_EE)); /* disable interrupts */
348 /*-------------------------------------------------------------------------+
349 | Calculate the system clock speed from the period.
350 +-------------------------------------------------------------------------*/
351 sys_freq = (ONE_BILLION / sys_per) * 1000;
354 /* Extract configured divisors */
355 mfsdr( sdr_sdstp0,strp0 );
356 mfsdr( sdr_sdstp1,strp1 );
358 temp = ((strp0 & PLLSYS0_FWD_DIV_A_MASK) >> 8);
359 sysInfo->pllFwdDivA = temp ? temp : 16 ;
360 temp = ((strp0 & PLLSYS0_FWD_DIV_B_MASK) >> 5);
361 sysInfo->pllFwdDivB = temp ? temp: 8 ;
362 temp = (strp0 & PLLSYS0_FB_DIV_MASK) >> 12;
363 sysInfo->pllFbkDiv = temp ? temp : 32;
364 temp = (strp0 & PLLSYS0_OPB_DIV_MASK);
365 sysInfo->pllOpbDiv = temp ? temp : 4;
366 temp = (strp1 & PLLSYS1_PERCLK_DIV_MASK) >> 24;
367 sysInfo->pllExtBusDiv = temp ? temp : 4;
368 prbdv0 = (strp0 >> 2) & 0x7;
370 /* Calculate 'M' based on feedback source */
371 temp = (strp0 & PLLSYS0_SEL_MASK) >> 27;
372 temp1 = (strp1 & PLLSYS1_LF_DIV_MASK) >> 26;
373 lfdiv = temp1 ? temp1 : 64;
374 if (temp == 0) { /* PLL output */
375 /* Figure which pll to use */
376 temp = (strp0 & PLLSYS0_SRC_MASK) >> 30;
378 m = sysInfo->pllFbkDiv * lfdiv * sysInfo->pllFwdDivA;
380 m = sysInfo->pllFbkDiv * lfdiv * sysInfo->pllFwdDivB;
382 else if (temp == 1) /* CPU output */
383 m = sysInfo->pllFbkDiv * sysInfo->pllFwdDivA;
385 m = sysInfo->pllExtBusDiv * sysInfo->pllOpbDiv * sysInfo->pllFwdDivB;
387 /* Now calculate the individual clocks */
388 #if defined(CONFIG_YUCCA)
389 sysInfo->freqVCOMhz = (m * sys_freq) ;
391 sysInfo->freqVCOMhz = (m * CONFIG_SYS_CLK_FREQ) + (m >> 1);
393 sysInfo->freqProcessor = sysInfo->freqVCOMhz/sysInfo->pllFwdDivA;
394 sysInfo->freqPLB = sysInfo->freqVCOMhz/sysInfo->pllFwdDivB/prbdv0;
395 sysInfo->freqOPB = sysInfo->freqPLB/sysInfo->pllOpbDiv;
396 sysInfo->freqEBC = sysInfo->freqOPB/sysInfo->pllExtBusDiv;
398 #if defined(CONFIG_YUCCA)
399 /* Determine PCI Clock Period */
400 pci_clock_per = determine_pci_clock_per();
401 sysInfo->freqPCI = (ONE_BILLION/pci_clock_per) * 1000;
402 mfsdr(sdr_ddr0, sdr_ddrpll);
403 sysInfo->freqDDR = ((sysInfo->freqPLB) * SDR0_DDR0_DDRM_DECODE(sdr_ddrpll));
411 #if defined(CONFIG_YUCCA)
412 unsigned long determine_sysper(void)
414 unsigned int fpga_clocking_reg;
415 unsigned int master_clock_selection;
416 unsigned long master_clock_per = 0;
417 unsigned long fb_div_selection;
418 unsigned int vco_div_reg_value;
419 unsigned long vco_div_selection;
420 unsigned long sys_per = 0;
423 /*-------------------------------------------------------------------------+
424 | Read FPGA reg 0 and reg 1 to get FPGA reg information
425 +-------------------------------------------------------------------------*/
426 fpga_clocking_reg = in16(FPGA_REG16);
429 /* Determine Master Clock Source Selection */
430 master_clock_selection = fpga_clocking_reg & FPGA_REG16_MASTER_CLK_MASK;
432 switch(master_clock_selection) {
433 case FPGA_REG16_MASTER_CLK_66_66:
434 master_clock_per = PERIOD_66_66MHZ;
436 case FPGA_REG16_MASTER_CLK_50:
437 master_clock_per = PERIOD_50_00MHZ;
439 case FPGA_REG16_MASTER_CLK_33_33:
440 master_clock_per = PERIOD_33_33MHZ;
442 case FPGA_REG16_MASTER_CLK_25:
443 master_clock_per = PERIOD_25_00MHZ;
445 case FPGA_REG16_MASTER_CLK_EXT:
446 if ((extClkVal==EXTCLK_33_33)
447 && (extClkVal==EXTCLK_50)
448 && (extClkVal==EXTCLK_66_66)
449 && (extClkVal==EXTCLK_83)) {
450 /* calculate master clock period from external clock value */
451 master_clock_per=(ONE_BILLION/extClkVal) * 1000;
454 DEBUGF ("%s[%d] *** master clock selection failed ***\n", __FUNCTION__,__LINE__);
460 DEBUGF ("%s[%d] *** master clock selection failed ***\n", __FUNCTION__,__LINE__);
465 /* Determine FB divisors values */
466 if ((fpga_clocking_reg & FPGA_REG16_FB1_DIV_MASK) == FPGA_REG16_FB1_DIV_LOW) {
467 if ((fpga_clocking_reg & FPGA_REG16_FB2_DIV_MASK) == FPGA_REG16_FB2_DIV_LOW)
468 fb_div_selection = FPGA_FB_DIV_6;
470 fb_div_selection = FPGA_FB_DIV_12;
472 if ((fpga_clocking_reg & FPGA_REG16_FB2_DIV_MASK) == FPGA_REG16_FB2_DIV_LOW)
473 fb_div_selection = FPGA_FB_DIV_10;
475 fb_div_selection = FPGA_FB_DIV_20;
478 /* Determine VCO divisors values */
479 vco_div_reg_value = fpga_clocking_reg & FPGA_REG16_VCO_DIV_MASK;
481 switch(vco_div_reg_value) {
482 case FPGA_REG16_VCO_DIV_4:
483 vco_div_selection = FPGA_VCO_DIV_4;
485 case FPGA_REG16_VCO_DIV_6:
486 vco_div_selection = FPGA_VCO_DIV_6;
488 case FPGA_REG16_VCO_DIV_8:
489 vco_div_selection = FPGA_VCO_DIV_8;
491 case FPGA_REG16_VCO_DIV_10:
493 vco_div_selection = FPGA_VCO_DIV_10;
497 if (master_clock_selection == FPGA_REG16_MASTER_CLK_EXT) {
498 switch(master_clock_per) {
499 case PERIOD_25_00MHZ:
500 if (fb_div_selection == FPGA_FB_DIV_12) {
501 if (vco_div_selection == FPGA_VCO_DIV_4)
502 sys_per = PERIOD_75_00MHZ;
503 if (vco_div_selection == FPGA_VCO_DIV_6)
504 sys_per = PERIOD_50_00MHZ;
507 case PERIOD_33_33MHZ:
508 if (fb_div_selection == FPGA_FB_DIV_6) {
509 if (vco_div_selection == FPGA_VCO_DIV_4)
510 sys_per = PERIOD_50_00MHZ;
511 if (vco_div_selection == FPGA_VCO_DIV_6)
512 sys_per = PERIOD_33_33MHZ;
514 if (fb_div_selection == FPGA_FB_DIV_10) {
515 if (vco_div_selection == FPGA_VCO_DIV_4)
516 sys_per = PERIOD_83_33MHZ;
517 if (vco_div_selection == FPGA_VCO_DIV_10)
518 sys_per = PERIOD_33_33MHZ;
520 if (fb_div_selection == FPGA_FB_DIV_12) {
521 if (vco_div_selection == FPGA_VCO_DIV_4)
522 sys_per = PERIOD_100_00MHZ;
523 if (vco_div_selection == FPGA_VCO_DIV_6)
524 sys_per = PERIOD_66_66MHZ;
525 if (vco_div_selection == FPGA_VCO_DIV_8)
526 sys_per = PERIOD_50_00MHZ;
529 case PERIOD_50_00MHZ:
530 if (fb_div_selection == FPGA_FB_DIV_6) {
531 if (vco_div_selection == FPGA_VCO_DIV_4)
532 sys_per = PERIOD_75_00MHZ;
533 if (vco_div_selection == FPGA_VCO_DIV_6)
534 sys_per = PERIOD_50_00MHZ;
536 if (fb_div_selection == FPGA_FB_DIV_10) {
537 if (vco_div_selection == FPGA_VCO_DIV_6)
538 sys_per = PERIOD_83_33MHZ;
539 if (vco_div_selection == FPGA_VCO_DIV_10)
540 sys_per = PERIOD_50_00MHZ;
542 if (fb_div_selection == FPGA_FB_DIV_12) {
543 if (vco_div_selection == FPGA_VCO_DIV_6)
544 sys_per = PERIOD_100_00MHZ;
545 if (vco_div_selection == FPGA_VCO_DIV_8)
546 sys_per = PERIOD_75_00MHZ;
549 case PERIOD_66_66MHZ:
550 if (fb_div_selection == FPGA_FB_DIV_6) {
551 if (vco_div_selection == FPGA_VCO_DIV_4)
552 sys_per = PERIOD_100_00MHZ;
553 if (vco_div_selection == FPGA_VCO_DIV_6)
554 sys_per = PERIOD_66_66MHZ;
555 if (vco_div_selection == FPGA_VCO_DIV_8)
556 sys_per = PERIOD_50_00MHZ;
558 if (fb_div_selection == FPGA_FB_DIV_10) {
559 if (vco_div_selection == FPGA_VCO_DIV_8)
560 sys_per = PERIOD_83_33MHZ;
561 if (vco_div_selection == FPGA_VCO_DIV_10)
562 sys_per = PERIOD_66_66MHZ;
564 if (fb_div_selection == FPGA_FB_DIV_12) {
565 if (vco_div_selection == FPGA_VCO_DIV_8)
566 sys_per = PERIOD_100_00MHZ;
574 /* Other combinations are not supported */
575 DEBUGF ("%s[%d] *** sys period compute failed ***\n", __FUNCTION__,__LINE__);
579 /* calcul system clock without cheking */
580 /* if engineering option clock no check is selected */
581 /* sys_per = master_clock_per * vco_div_selection / fb_div_selection */
582 sys_per = (master_clock_per/fb_div_selection) * vco_div_selection;
588 /*-------------------------------------------------------------------------+
589 | determine_pci_clock_per.
590 +-------------------------------------------------------------------------*/
591 unsigned long determine_pci_clock_per(void)
593 unsigned long pci_clock_selection, pci_period;
595 /*-------------------------------------------------------------------------+
596 | Read FPGA reg 6 to get PCI 0 FPGA reg information
597 +-------------------------------------------------------------------------*/
598 pci_clock_selection = in16(FPGA_REG16); /* was reg6 averifier */
601 pci_clock_selection = pci_clock_selection & FPGA_REG16_PCI0_CLK_MASK;
603 switch (pci_clock_selection) {
604 case FPGA_REG16_PCI0_CLK_133_33:
605 pci_period = PERIOD_133_33MHZ;
607 case FPGA_REG16_PCI0_CLK_100:
608 pci_period = PERIOD_100_00MHZ;
610 case FPGA_REG16_PCI0_CLK_66_66:
611 pci_period = PERIOD_66_66MHZ;
614 pci_period = PERIOD_33_33MHZ;;
622 ulong get_OPB_freq (void)
626 get_sys_info (&sys_info);
627 return sys_info.freqOPB;
630 #elif defined(CONFIG_XILINX_ML300)
631 extern void get_sys_info (sys_info_t * sysInfo);
632 extern ulong get_PCI_freq (void);
634 #elif defined(CONFIG_AP1000)
635 void get_sys_info (sys_info_t * sysInfo) {
636 sysInfo->freqProcessor = 240 * 1000 * 1000;
637 sysInfo->freqPLB = 80 * 1000 * 1000;
638 sysInfo->freqPCI = 33 * 1000 * 1000;
641 #elif defined(CONFIG_405)
643 void get_sys_info (sys_info_t * sysInfo) {
645 sysInfo->freqVCOMhz=3125000;
646 sysInfo->freqProcessor=12*1000*1000;
647 sysInfo->freqPLB=50*1000*1000;
648 sysInfo->freqPCI=66*1000*1000;
652 #elif defined(CONFIG_405EP)
653 void get_sys_info (PPC4xx_SYS_INFO * sysInfo)
655 unsigned long pllmr0;
656 unsigned long pllmr1;
657 unsigned long sysClkPeriodPs = ONE_BILLION / (CONFIG_SYS_CLK_FREQ / 1000);
659 unsigned long pllmr0_ccdv;
662 * Read PLL Mode registers
664 pllmr0 = mfdcr (cpc0_pllmr0);
665 pllmr1 = mfdcr (cpc0_pllmr1);
668 * Determine forward divider A
670 sysInfo->pllFwdDiv = 8 - ((pllmr1 & PLLMR1_FWDVA_MASK) >> 16);
673 * Determine forward divider B (should be equal to A)
675 sysInfo->pllFwdDivB = 8 - ((pllmr1 & PLLMR1_FWDVB_MASK) >> 12);
680 sysInfo->pllFbkDiv = ((pllmr1 & PLLMR1_FBMUL_MASK) >> 20);
681 if (sysInfo->pllFbkDiv == 0) {
682 sysInfo->pllFbkDiv = 16;
688 sysInfo->pllPlbDiv = ((pllmr0 & PLLMR0_CPU_TO_PLB_MASK) >> 16) + 1;
693 sysInfo->pllPciDiv = (pllmr0 & PLLMR0_PCI_TO_PLB_MASK) + 1;
696 * Determine EXTBUS_DIV.
698 sysInfo->pllExtBusDiv = ((pllmr0 & PLLMR0_EXB_TO_PLB_MASK) >> 8) + 2;
703 sysInfo->pllOpbDiv = ((pllmr0 & PLLMR0_OPB_TO_PLB_MASK) >> 12) + 1;
706 * Determine the M factor
708 m = sysInfo->pllFbkDiv * sysInfo->pllFwdDivB;
711 * Determine VCO clock frequency
713 sysInfo->freqVCOHz = (1000000000000LL * (unsigned long long)m) /
714 (unsigned long long)sysClkPeriodPs;
717 * Determine CPU clock frequency
719 pllmr0_ccdv = ((pllmr0 & PLLMR0_CPU_DIV_MASK) >> 20) + 1;
720 if (pllmr1 & PLLMR1_SSCS_MASK) {
722 * This is true if FWDVA == FWDVB:
723 * sysInfo->freqProcessor = (CONFIG_SYS_CLK_FREQ * sysInfo->pllFbkDiv)
726 sysInfo->freqProcessor = (CONFIG_SYS_CLK_FREQ * sysInfo->pllFbkDiv * sysInfo->pllFwdDivB)
727 / sysInfo->pllFwdDiv / pllmr0_ccdv;
729 sysInfo->freqProcessor = CONFIG_SYS_CLK_FREQ / pllmr0_ccdv;
733 * Determine PLB clock frequency
735 sysInfo->freqPLB = sysInfo->freqProcessor / sysInfo->pllPlbDiv;
737 sysInfo->freqEBC = sysInfo->freqPLB / sysInfo->pllExtBusDiv;
741 /********************************************
743 * return OPB bus freq in Hz
744 *********************************************/
745 ulong get_OPB_freq (void)
749 PPC4xx_SYS_INFO sys_info;
751 get_sys_info (&sys_info);
752 val = sys_info.freqPLB / sys_info.pllOpbDiv;
758 /********************************************
760 * return PCI bus freq in Hz
761 *********************************************/
762 ulong get_PCI_freq (void)
765 PPC4xx_SYS_INFO sys_info;
767 get_sys_info (&sys_info);
768 val = sys_info.freqPLB / sys_info.pllPciDiv;
772 #elif defined(CONFIG_405EZ)
773 void get_sys_info (PPC4xx_SYS_INFO * sysInfo)
775 unsigned long cpr_plld;
776 unsigned long cpr_pllc;
777 unsigned long cpr_primad;
778 unsigned long sysClkPeriodPs = ONE_BILLION / (CONFIG_SYS_CLK_FREQ/1000);
779 unsigned long primad_cpudv;
783 * Read PLL Mode registers
785 mfcpr(cprplld, cpr_plld);
786 mfcpr(cprpllc, cpr_pllc);
789 * Determine forward divider A
791 sysInfo->pllFwdDiv = ((cpr_plld & PLLD_FWDVA_MASK) >> 16);
794 * Determine forward divider B
796 sysInfo->pllFwdDivB = ((cpr_plld & PLLD_FWDVB_MASK) >> 8);
797 if (sysInfo->pllFwdDivB == 0)
798 sysInfo->pllFwdDivB = 8;
803 sysInfo->pllFbkDiv = ((cpr_plld & PLLD_FBDV_MASK) >> 24);
804 if (sysInfo->pllFbkDiv == 0)
805 sysInfo->pllFbkDiv = 256;
808 * Read CPR_PRIMAD register
810 mfcpr(cprprimad, cpr_primad);
814 sysInfo->pllPlbDiv = ((cpr_primad & PRIMAD_PLBDV_MASK) >> 16);
815 if (sysInfo->pllPlbDiv == 0)
816 sysInfo->pllPlbDiv = 16;
819 * Determine EXTBUS_DIV.
821 sysInfo->pllExtBusDiv = (cpr_primad & PRIMAD_EBCDV_MASK);
822 if (sysInfo->pllExtBusDiv == 0)
823 sysInfo->pllExtBusDiv = 16;
828 sysInfo->pllOpbDiv = ((cpr_primad & PRIMAD_OPBDV_MASK) >> 8);
829 if (sysInfo->pllOpbDiv == 0)
830 sysInfo->pllOpbDiv = 16;
833 * Determine the M factor
835 if (cpr_pllc & PLLC_SRC_MASK)
836 m = sysInfo->pllFbkDiv * sysInfo->pllFwdDivB;
838 m = sysInfo->pllFbkDiv * sysInfo->pllFwdDiv;
841 * Determine VCO clock frequency
843 sysInfo->freqVCOHz = (1000000000000LL * (unsigned long long)m) /
844 (unsigned long long)sysClkPeriodPs;
847 * Determine CPU clock frequency
849 primad_cpudv = ((cpr_primad & PRIMAD_CPUDV_MASK) >> 24);
850 if (primad_cpudv == 0)
853 sysInfo->freqProcessor = (CONFIG_SYS_CLK_FREQ * m) /
854 sysInfo->pllFwdDiv / primad_cpudv;
857 * Determine PLB clock frequency
859 sysInfo->freqPLB = (CONFIG_SYS_CLK_FREQ * m) /
860 sysInfo->pllFwdDiv / sysInfo->pllPlbDiv;
862 sysInfo->freqEBC = (CONFIG_SYS_CLK_FREQ * sysInfo->pllFbkDiv) /
863 sysInfo->pllExtBusDiv;
866 /********************************************
868 * return OPB bus freq in Hz
869 *********************************************/
870 ulong get_OPB_freq (void)
874 PPC4xx_SYS_INFO sys_info;
876 get_sys_info (&sys_info);
877 val = (CONFIG_SYS_CLK_FREQ * sys_info.pllFbkDiv) / sys_info.pllOpbDiv;
882 #elif defined(CONFIG_405EX)
885 * TODO: We need to get the CPR registers and calculate these values correctly!!!!
886 * We need the specs!!!!
888 static unsigned char get_fbdv(unsigned char index)
890 unsigned char ret = 0;
891 /* This is table should be 256 bytes.
892 * Only take first 52 values.
894 unsigned char fbdv_tb[] = {
895 0x00, 0xff, 0x7f, 0xfd,
896 0x7a, 0xf5, 0x6a, 0xd5,
897 0x2a, 0xd4, 0x29, 0xd3,
898 0x26, 0xcc, 0x19, 0xb3,
899 0x67, 0xce, 0x1d, 0xbb,
900 0x77, 0xee, 0x5d, 0xba,
901 0x74, 0xe9, 0x52, 0xa5,
902 0x4b, 0x96, 0x2c, 0xd8,
903 0x31, 0xe3, 0x46, 0x8d,
904 0x1b, 0xb7, 0x6f, 0xde,
905 0x3d, 0xfb, 0x76, 0xed,
906 0x5a, 0xb5, 0x6b, 0xd6,
907 0x2d, 0xdb, 0x36, 0xec,
911 if ((index & 0x7f) == 0)
913 while (ret < sizeof (fbdv_tb)) {
914 if (fbdv_tb[ret] == index)
923 #define PLL_FBK_PLL_LOCAL 0
924 #define PLL_FBK_CPU 1
925 #define PLL_FBK_PERCLK 5
927 void get_sys_info (sys_info_t * sysInfo)
929 unsigned long sysClkPeriodPs = ONE_BILLION / (CONFIG_SYS_CLK_FREQ / 1000);
932 unsigned char fwdva[16] = {
933 1, 2, 14, 9, 4, 11, 16, 13,
934 12, 5, 6, 15, 10, 7, 8, 3,
936 unsigned char sel, cpudv0, plb2xDiv;
938 mfcpr(cpr0_plld, tmp);
941 * Determine forward divider A
943 sysInfo->pllFwdDiv = fwdva[((tmp >> 16) & 0x0f)]; /* FWDVA */
948 sysInfo->pllFbkDiv = get_fbdv(((tmp >> 24) & 0x0ff)); /* FBDV */
953 sysInfo->pllPlbDiv = 2;
958 mfcpr(cpr0_perd, tmp);
959 tmp = (tmp >> 24) & 0x03;
960 sysInfo->pllExtBusDiv = (tmp == 0) ? 4 : tmp;
965 mfcpr(cpr0_opbd, tmp);
966 tmp = (tmp >> 24) & 0x03;
967 sysInfo->pllOpbDiv = (tmp == 0) ? 4 : tmp;
969 /* Determine PLB2XDV0 */
970 mfcpr(cpr0_plbd, tmp);
971 tmp = (tmp >> 16) & 0x07;
972 plb2xDiv = (tmp == 0) ? 8 : tmp;
974 /* Determine CPUDV0 */
975 mfcpr(cpr0_cpud, tmp);
976 tmp = (tmp >> 24) & 0x07;
977 cpudv0 = (tmp == 0) ? 8 : tmp;
979 /* Determine SEL(5:7) in CPR0_PLLC */
980 mfcpr(cpr0_pllc, tmp);
981 sel = (tmp >> 24) & 0x07;
984 * Determine the M factor
985 * PLL local: M = FBDV
986 * CPU clock: M = FBDV * FWDVA * CPUDV0
987 * PerClk : M = FBDV * FWDVA * PLB2XDV0 * PLBDV0(2) * OPBDV0 * PERDV0
992 m = sysInfo->pllFwdDiv * cpudv0;
995 m = sysInfo->pllFwdDiv * plb2xDiv * 2
996 * sysInfo->pllOpbDiv * sysInfo->pllExtBusDiv;
998 case PLL_FBK_PLL_LOCAL:
1001 printf("%s unknown m\n", __FUNCTION__);
1005 m *= sysInfo->pllFbkDiv;
1008 * Determine VCO clock frequency
1010 sysInfo->freqVCOHz = (1000000000000LL * (unsigned long long)m) /
1011 (unsigned long long)sysClkPeriodPs;
1014 * Determine CPU clock frequency
1016 sysInfo->freqProcessor = sysInfo->freqVCOHz / (sysInfo->pllFwdDiv * cpudv0);
1019 * Determine PLB clock frequency, ddr1x should be the same
1021 sysInfo->freqPLB = sysInfo->freqVCOHz / (sysInfo->pllFwdDiv * plb2xDiv * 2);
1022 sysInfo->freqOPB = sysInfo->freqPLB/sysInfo->pllOpbDiv;
1023 sysInfo->freqDDR = sysInfo->freqPLB;
1024 sysInfo->freqEBC = sysInfo->freqOPB / sysInfo->pllExtBusDiv;
1027 /********************************************
1029 * return OPB bus freq in Hz
1030 *********************************************/
1031 ulong get_OPB_freq (void)
1035 PPC4xx_SYS_INFO sys_info;
1037 get_sys_info (&sys_info);
1038 val = sys_info.freqPLB / sys_info.pllOpbDiv;
1045 int get_clocks (void)
1047 #if defined(CONFIG_405GP) || defined(CONFIG_405CR) || \
1048 defined(CONFIG_405EP) || defined(CONFIG_405EZ) || \
1049 defined(CONFIG_405EX) || defined(CONFIG_405) || \
1051 sys_info_t sys_info;
1053 get_sys_info (&sys_info);
1054 gd->cpu_clk = sys_info.freqProcessor;
1055 gd->bus_clk = sys_info.freqPLB;
1057 #endif /* defined(CONFIG_405GP) || defined(CONFIG_405CR) */
1059 #ifdef CONFIG_IOP480
1060 gd->cpu_clk = 66000000;
1061 gd->bus_clk = 66000000;
1067 /********************************************
1069 * return PLB bus freq in Hz
1070 *********************************************/
1071 ulong get_bus_freq (ulong dummy)
1075 #if defined(CONFIG_405GP) || defined(CONFIG_405CR) || \
1076 defined(CONFIG_405EP) || defined(CONFIG_405EZ) || \
1077 defined(CONFIG_405EX) || defined(CONFIG_405) || \
1079 sys_info_t sys_info;
1081 get_sys_info (&sys_info);
1082 val = sys_info.freqPLB;
1084 #elif defined(CONFIG_IOP480)
1089 # error get_bus_freq() not implemented