]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - arch/powerpc/cpu/ppc4xx/speed.c
Merge branch 'master' of git://git.denx.de/u-boot-ppc4xx
[karo-tx-uboot.git] / arch / powerpc / cpu / ppc4xx / speed.c
1 /*
2  * (C) Copyright 2000-2008
3  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4  *
5  * See file CREDITS for list of people who contributed to this
6  * project.
7  *
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.
12  *
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.
17  *
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,
21  * MA 02111-1307 USA
22  */
23
24 #include <common.h>
25 #include <ppc_asm.tmpl>
26 #include <ppc4xx.h>
27 #include <asm/processor.h>
28
29 DECLARE_GLOBAL_DATA_PTR;
30
31 #define ONE_BILLION        1000000000
32 #ifdef DEBUG
33 #define DEBUGF(fmt,args...) printf(fmt ,##args)
34 #else
35 #define DEBUGF(fmt,args...)
36 #endif
37
38 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
39
40 #if defined(CONFIG_405GP) || defined(CONFIG_405CR)
41
42 void get_sys_info (PPC4xx_SYS_INFO * sysInfo)
43 {
44         unsigned long pllmr;
45         unsigned long sysClkPeriodPs = ONE_BILLION / (CONFIG_SYS_CLK_FREQ / 1000);
46         uint pvr = get_pvr();
47         unsigned long psr;
48         unsigned long m;
49
50         /*
51          * Read PLL Mode register
52          */
53         pllmr = mfdcr (CPC0_PLLMR);
54
55         /*
56          * Read Pin Strapping register
57          */
58         psr = mfdcr (CPC0_PSR);
59
60         /*
61          * Determine FWD_DIV.
62          */
63         sysInfo->pllFwdDiv = 8 - ((pllmr & PLLMR_FWD_DIV_MASK) >> 29);
64
65         /*
66          * Determine FBK_DIV.
67          */
68         sysInfo->pllFbkDiv = ((pllmr & PLLMR_FB_DIV_MASK) >> 25);
69         if (sysInfo->pllFbkDiv == 0) {
70                 sysInfo->pllFbkDiv = 16;
71         }
72
73         /*
74          * Determine PLB_DIV.
75          */
76         sysInfo->pllPlbDiv = ((pllmr & PLLMR_CPU_TO_PLB_MASK) >> 17) + 1;
77
78         /*
79          * Determine PCI_DIV.
80          */
81         sysInfo->pllPciDiv = ((pllmr & PLLMR_PCI_TO_PLB_MASK) >> 13) + 1;
82
83         /*
84          * Determine EXTBUS_DIV.
85          */
86         sysInfo->pllExtBusDiv = ((pllmr & PLLMR_EXB_TO_PLB_MASK) >> 11) + 2;
87
88         /*
89          * Determine OPB_DIV.
90          */
91         sysInfo->pllOpbDiv = ((pllmr & PLLMR_OPB_TO_PLB_MASK) >> 15) + 1;
92
93         /*
94          * Check if PPC405GPr used (mask minor revision field)
95          */
96         if ((pvr & 0xfffffff0) == (PVR_405GPR_RB & 0xfffffff0)) {
97                 /*
98                  * Determine FWD_DIV B (only PPC405GPr with new mode strapping).
99                  */
100                 sysInfo->pllFwdDivB = 8 - (pllmr & PLLMR_FWDB_DIV_MASK);
101
102                 /*
103                  * Determine factor m depending on PLL feedback clock source
104                  */
105                 if (!(psr & PSR_PCI_ASYNC_EN)) {
106                         if (psr & PSR_NEW_MODE_EN) {
107                                 /*
108                                  * sync pci clock used as feedback (new mode)
109                                  */
110                                 m = 1 * sysInfo->pllFwdDivB * 2 * sysInfo->pllPciDiv;
111                         } else {
112                                 /*
113                                  * sync pci clock used as feedback (legacy mode)
114                                  */
115                                 m = 1 * sysInfo->pllFwdDivB * sysInfo->pllPlbDiv * sysInfo->pllPciDiv;
116                         }
117                 } else if (psr & PSR_NEW_MODE_EN) {
118                         if (psr & PSR_PERCLK_SYNC_MODE_EN) {
119                                 /*
120                                  * PerClk used as feedback (new mode)
121                                  */
122                                 m = 1 * sysInfo->pllFwdDivB * 2 * sysInfo->pllExtBusDiv;
123                         } else {
124                                 /*
125                                  * CPU clock used as feedback (new mode)
126                                  */
127                                 m = sysInfo->pllFbkDiv * sysInfo->pllFwdDiv;
128                         }
129                 } else if (sysInfo->pllExtBusDiv == sysInfo->pllFbkDiv) {
130                         /*
131                          * PerClk used as feedback (legacy mode)
132                          */
133                         m = 1 * sysInfo->pllFwdDivB * sysInfo->pllPlbDiv * sysInfo->pllExtBusDiv;
134                 } else {
135                         /*
136                          * PLB clock used as feedback (legacy mode)
137                          */
138                         m = sysInfo->pllFbkDiv * sysInfo->pllFwdDivB * sysInfo->pllPlbDiv;
139                 }
140
141                 sysInfo->freqVCOHz = (1000000000000LL * (unsigned long long)m) /
142                         (unsigned long long)sysClkPeriodPs;
143                 sysInfo->freqProcessor = sysInfo->freqVCOHz / sysInfo->pllFwdDiv;
144                 sysInfo->freqPLB = sysInfo->freqVCOHz / (sysInfo->pllFwdDivB * sysInfo->pllPlbDiv);
145         } else {
146                 /*
147                  * Check pllFwdDiv to see if running in bypass mode where the CPU speed
148                  * is equal to the 405GP SYS_CLK_FREQ. If not in bypass mode, check VCO
149                  * to make sure it is within the proper range.
150                  *    spec:    VCO = SYS_CLOCK x FBKDIV x PLBDIV x FWDDIV
151                  * Note freqVCO is calculated in MHz to avoid errors introduced by rounding.
152                  */
153                 if (sysInfo->pllFwdDiv == 1) {
154                         sysInfo->freqProcessor = CONFIG_SYS_CLK_FREQ;
155                         sysInfo->freqPLB = CONFIG_SYS_CLK_FREQ / sysInfo->pllPlbDiv;
156                 } else {
157                         sysInfo->freqVCOHz = ( 1000000000000LL *
158                                                (unsigned long long)sysInfo->pllFwdDiv *
159                                                (unsigned long long)sysInfo->pllFbkDiv *
160                                                (unsigned long long)sysInfo->pllPlbDiv
161                                 ) / (unsigned long long)sysClkPeriodPs;
162                         sysInfo->freqPLB = (ONE_BILLION / ((sysClkPeriodPs * 10) /
163                                                            sysInfo->pllFbkDiv)) * 10000;
164                         sysInfo->freqProcessor = sysInfo->freqPLB * sysInfo->pllPlbDiv;
165                 }
166         }
167
168         sysInfo->freqOPB = sysInfo->freqPLB / sysInfo->pllOpbDiv;
169         sysInfo->freqEBC = sysInfo->freqPLB / sysInfo->pllExtBusDiv;
170         sysInfo->freqUART = sysInfo->freqProcessor;
171 }
172
173
174 /********************************************
175  * get_PCI_freq
176  * return PCI bus freq in Hz
177  *********************************************/
178 ulong get_PCI_freq (void)
179 {
180         ulong val;
181         PPC4xx_SYS_INFO sys_info;
182
183         get_sys_info (&sys_info);
184         val = sys_info.freqPLB / sys_info.pllPciDiv;
185         return val;
186 }
187
188
189 #elif defined(CONFIG_440)
190
191 #if defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
192     defined(CONFIG_460SX)
193 static u8 pll_fwdv_multi_bits[] = {
194         /* values for:  1 - 16 */
195         0x00, 0x01, 0x0f, 0x04, 0x09, 0x0a, 0x0d, 0x0e, 0x03, 0x0c,
196         0x05, 0x08, 0x07, 0x02, 0x0b, 0x06
197 };
198
199 u32 get_cpr0_fwdv(unsigned long cpr_reg_fwdv)
200 {
201         u32 index;
202
203         for (index = 0; index < ARRAY_SIZE(pll_fwdv_multi_bits); index++)
204                 if (cpr_reg_fwdv == (u32)pll_fwdv_multi_bits[index])
205                         return index + 1;
206
207         return 0;
208 }
209
210 static u8 pll_fbdv_multi_bits[] = {
211         /* values for:  1 - 100 */
212         0x00, 0xff, 0x7e, 0xfd, 0x7a, 0xf5, 0x6a, 0xd5, 0x2a, 0xd4,
213         0x29, 0xd3, 0x26, 0xcc, 0x19, 0xb3, 0x67, 0xce, 0x1d, 0xbb,
214         0x77, 0xee, 0x5d, 0xba, 0x74, 0xe9, 0x52, 0xa5, 0x4b, 0x96,
215         0x2c, 0xd8, 0x31, 0xe3, 0x46, 0x8d, 0x1b, 0xb7, 0x6f, 0xde,
216         0x3d, 0xfb, 0x76, 0xed, 0x5a, 0xb5, 0x6b, 0xd6, 0x2d, 0xdb,
217         0x36, 0xec, 0x59, 0xb2, 0x64, 0xc9, 0x12, 0xa4, 0x48, 0x91,
218         0x23, 0xc7, 0x0e, 0x9c, 0x38, 0xf0, 0x61, 0xc2, 0x05, 0x8b,
219         0x17, 0xaf, 0x5f, 0xbe, 0x7c, 0xf9, 0x72, 0xe5, 0x4a, 0x95,
220         0x2b, 0xd7, 0x2e, 0xdc, 0x39, 0xf3, 0x66, 0xcd, 0x1a, 0xb4,
221         0x68, 0xd1, 0x22, 0xc4, 0x09, 0x93, 0x27, 0xcf, 0x1e, 0xbc,
222         /* values for:  101 - 200 */
223         0x78, 0xf1, 0x62, 0xc5, 0x0a, 0x94, 0x28, 0xd0, 0x21, 0xc3,
224         0x06, 0x8c, 0x18, 0xb0, 0x60, 0xc1, 0x02, 0x84, 0x08, 0x90,
225         0x20, 0xc0, 0x01, 0x83, 0x07, 0x8f, 0x1f, 0xbf, 0x7f, 0xfe,
226         0x7d, 0xfa, 0x75, 0xea, 0x55, 0xaa, 0x54, 0xa9, 0x53, 0xa6,
227         0x4c, 0x99, 0x33, 0xe7, 0x4e, 0x9d, 0x3b, 0xf7, 0x6e, 0xdd,
228         0x3a, 0xf4, 0x69, 0xd2, 0x25, 0xcb, 0x16, 0xac, 0x58, 0xb1,
229         0x63, 0xc6, 0x0d, 0x9b, 0x37, 0xef, 0x5e, 0xbd, 0x7b, 0xf6,
230         0x6d, 0xda, 0x35, 0xeb, 0x56, 0xad, 0x5b, 0xb6, 0x6c, 0xd9,
231         0x32, 0xe4, 0x49, 0x92, 0x24, 0xc8, 0x11, 0xa3, 0x47, 0x8e,
232         0x1c, 0xb8, 0x70, 0xe1, 0x42, 0x85, 0x0b, 0x97, 0x2f, 0xdf,
233         /* values for:  201 - 255 */
234         0x3e, 0xfc, 0x79, 0xf2, 0x65, 0xca, 0x15, 0xab, 0x57, 0xae,
235         0x5c, 0xb9, 0x73, 0xe6, 0x4d, 0x9a, 0x34, 0xe8, 0x51, 0xa2,
236         0x44, 0x89, 0x13, 0xa7, 0x4f, 0x9e, 0x3c, 0xf8, 0x71, 0xe2,
237         0x45, 0x8a, 0x14, 0xa8, 0x50, 0xa1, 0x43, 0x86, 0x0c, 0x98,
238         0x30, 0xe0, 0x41, 0x82, 0x04, 0x88, 0x10, 0xa0, 0x40, 0x81,
239         0x03, 0x87, 0x0f, 0x9f, 0x3f  /* END */
240 };
241
242 u32 get_cpr0_fbdv(unsigned long cpr_reg_fbdv)
243 {
244         u32 index;
245
246         for (index = 0; index < ARRAY_SIZE(pll_fbdv_multi_bits); index++)
247                 if (cpr_reg_fbdv == (u32)pll_fbdv_multi_bits[index])
248                         return index + 1;
249
250         return 0;
251 }
252
253 /*
254  * AMCC_TODO: verify this routine against latest EAS, cause stuff changed
255  *            with latest EAS
256  */
257 void get_sys_info (sys_info_t * sysInfo)
258 {
259         unsigned long strp0;
260         unsigned long strp1;
261         unsigned long temp;
262         unsigned long m;
263         unsigned long plbedv0;
264
265         /* Extract configured divisors */
266         mfsdr(SDR0_SDSTP0, strp0);
267         mfsdr(SDR0_SDSTP1, strp1);
268
269         temp = ((strp0 & PLLSYS0_FWD_DIV_A_MASK) >> 4);
270         sysInfo->pllFwdDivA = get_cpr0_fwdv(temp);
271
272         temp = (strp0 & PLLSYS0_FWD_DIV_B_MASK);
273         sysInfo->pllFwdDivB = get_cpr0_fwdv(temp);
274
275         temp = (strp0 & PLLSYS0_FB_DIV_MASK) >> 8;
276         sysInfo->pllFbkDiv = get_cpr0_fbdv(temp);
277
278         temp = (strp1 & PLLSYS0_OPB_DIV_MASK) >> 26;
279         sysInfo->pllOpbDiv = temp ? temp : 4;
280
281         /* AMCC_TODO: verify the SDR0_SDSTP1.PERDV0 value sysInfo->pllExtBusDiv */
282         temp = (strp1 & PLLSYS0_PERCLK_DIV_MASK) >> 24;
283         sysInfo->pllExtBusDiv = temp ? temp : 4;
284
285         temp = (strp1 & PLLSYS0_PLBEDV0_DIV_MASK) >> 29;
286         plbedv0 = temp ? temp: 8;
287
288         /* Calculate 'M' based on feedback source */
289         temp = (strp0 & PLLSYS0_SEL_MASK) >> 27;
290         if (temp == 0) {
291                 /* PLL internal feedback */
292                 m = sysInfo->pllFbkDiv;
293         } else {
294                 /* PLL PerClk feedback */
295                 m = sysInfo->pllFwdDivA * plbedv0 * sysInfo->pllOpbDiv *
296                         sysInfo->pllExtBusDiv;
297         }
298
299         /* Now calculate the individual clocks */
300         sysInfo->freqVCOMhz = (m * CONFIG_SYS_CLK_FREQ) + (m >> 1);
301         sysInfo->freqProcessor = sysInfo->freqVCOMhz/sysInfo->pllFwdDivA;
302         sysInfo->freqPLB = sysInfo->freqVCOMhz / sysInfo->pllFwdDivA / plbedv0;
303         sysInfo->freqOPB = sysInfo->freqPLB / sysInfo->pllOpbDiv;
304         sysInfo->freqEBC = sysInfo->freqOPB / sysInfo->pllExtBusDiv;
305         sysInfo->freqDDR = sysInfo->freqPLB;
306         sysInfo->freqUART = sysInfo->freqPLB;
307
308         return;
309 }
310
311 #elif defined(CONFIG_440EP) || defined(CONFIG_440GR) || \
312     defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
313 void get_sys_info (sys_info_t *sysInfo)
314 {
315         unsigned long temp;
316         unsigned long reg;
317         unsigned long lfdiv;
318         unsigned long m;
319         unsigned long prbdv0;
320         /*
321           WARNING: ASSUMES the following:
322           ENG=1
323           PRADV0=1
324           PRBDV0=1
325         */
326
327         /* Decode CPR0_PLLD0 for divisors */
328         mfcpr(CPR0_PLLD, reg);
329         temp = (reg & PLLD_FWDVA_MASK) >> 16;
330         sysInfo->pllFwdDivA = temp ? temp : 16;
331         temp = (reg & PLLD_FWDVB_MASK) >> 8;
332         sysInfo->pllFwdDivB = temp ? temp: 8 ;
333         temp = (reg & PLLD_FBDV_MASK) >> 24;
334         sysInfo->pllFbkDiv = temp ? temp : 32;
335         lfdiv = reg & PLLD_LFBDV_MASK;
336
337         mfcpr(CPR0_OPBD0, reg);
338         temp = (reg & OPBDDV_MASK) >> 24;
339         sysInfo->pllOpbDiv = temp ? temp : 4;
340
341         mfcpr(CPR0_PERD, reg);
342         temp = (reg & PERDV_MASK) >> 24;
343         sysInfo->pllExtBusDiv = temp ? temp : 8;
344
345         mfcpr(CPR0_PRIMBD0, reg);
346         temp = (reg & PRBDV_MASK) >> 24;
347         prbdv0 = temp ? temp : 8;
348
349         mfcpr(CPR0_SPCID, reg);
350         temp = (reg & SPCID_MASK) >> 24;
351         sysInfo->pllPciDiv = temp ? temp : 4;
352
353         /* Calculate 'M' based on feedback source */
354         mfsdr(SDR0_SDSTP0, reg);
355         temp = (reg & PLLSYS0_SEL_MASK) >> 27;
356         if (temp == 0) { /* PLL output */
357                 /* Figure which pll to use */
358                 mfcpr(CPR0_PLLC, reg);
359                 temp = (reg & PLLC_SRC_MASK) >> 29;
360                 if (!temp) /* PLLOUTA */
361                         m = sysInfo->pllFbkDiv * lfdiv * sysInfo->pllFwdDivA;
362                 else       /* PLLOUTB */
363                         m = sysInfo->pllFbkDiv * lfdiv * sysInfo->pllFwdDivB;
364         }
365         else if (temp == 1) /* CPU output */
366                 m = sysInfo->pllFbkDiv * sysInfo->pllFwdDivA;
367         else /* PerClk */
368                 m = sysInfo->pllExtBusDiv * sysInfo->pllOpbDiv * sysInfo->pllFwdDivB;
369
370         /* Now calculate the individual clocks */
371         sysInfo->freqVCOMhz = (m * CONFIG_SYS_CLK_FREQ) + (m>>1);
372         sysInfo->freqProcessor = sysInfo->freqVCOMhz/sysInfo->pllFwdDivA;
373         sysInfo->freqPLB = sysInfo->freqVCOMhz/sysInfo->pllFwdDivB/prbdv0;
374         sysInfo->freqOPB = sysInfo->freqPLB/sysInfo->pllOpbDiv;
375         sysInfo->freqEBC = sysInfo->freqPLB/sysInfo->pllExtBusDiv;
376         sysInfo->freqPCI = sysInfo->freqPLB/sysInfo->pllPciDiv;
377         sysInfo->freqUART = sysInfo->freqPLB;
378
379         /* Figure which timer source to use */
380         if (mfspr(SPRN_CCR1) & 0x0080) {
381                 /* External Clock, assume same as SYS_CLK */
382                 temp = sysInfo->freqProcessor / 2;  /* Max extern clock speed */
383                 if (CONFIG_SYS_CLK_FREQ > temp)
384                         sysInfo->freqTmrClk = temp;
385                 else
386                         sysInfo->freqTmrClk = CONFIG_SYS_CLK_FREQ;
387         }
388         else  /* Internal clock */
389                 sysInfo->freqTmrClk = sysInfo->freqProcessor;
390 }
391
392 /********************************************
393  * get_PCI_freq
394  * return PCI bus freq in Hz
395  *********************************************/
396 ulong get_PCI_freq (void)
397 {
398         sys_info_t sys_info;
399         get_sys_info (&sys_info);
400         return sys_info.freqPCI;
401 }
402
403 #elif !defined(CONFIG_440GX) && !defined(CONFIG_440SP) && !defined(CONFIG_440SPE) \
404         && !defined(CONFIG_XILINX_440)
405 void get_sys_info (sys_info_t * sysInfo)
406 {
407         unsigned long strp0;
408         unsigned long temp;
409         unsigned long m;
410
411         /* Extract configured divisors */
412         strp0 = mfdcr( CPC0_STRP0 );
413         sysInfo->pllFwdDivA = 8 - ((strp0 & PLLSYS0_FWD_DIV_A_MASK) >> 15);
414         sysInfo->pllFwdDivB = 8 - ((strp0 & PLLSYS0_FWD_DIV_B_MASK) >> 12);
415         temp = (strp0 & PLLSYS0_FB_DIV_MASK) >> 18;
416         sysInfo->pllFbkDiv = temp ? temp : 16;
417         sysInfo->pllOpbDiv = 1 + ((strp0 & PLLSYS0_OPB_DIV_MASK) >> 10);
418         sysInfo->pllExtBusDiv = 1 + ((strp0 & PLLSYS0_EPB_DIV_MASK) >> 8);
419
420         /* Calculate 'M' based on feedback source */
421         if( strp0 & PLLSYS0_EXTSL_MASK )
422                 m = sysInfo->pllExtBusDiv * sysInfo->pllOpbDiv * sysInfo->pllFwdDivB;
423         else
424                 m = sysInfo->pllFbkDiv * sysInfo->pllFwdDivA;
425
426         /* Now calculate the individual clocks */
427         sysInfo->freqVCOMhz = (m * CONFIG_SYS_CLK_FREQ) + (m>>1);
428         sysInfo->freqProcessor = sysInfo->freqVCOMhz/sysInfo->pllFwdDivA;
429         sysInfo->freqPLB = sysInfo->freqVCOMhz/sysInfo->pllFwdDivB;
430         if( get_pvr() == PVR_440GP_RB ) /* Rev B divs an extra 2 -- geez! */
431                 sysInfo->freqPLB >>= 1;
432         sysInfo->freqOPB = sysInfo->freqPLB/sysInfo->pllOpbDiv;
433         sysInfo->freqEBC = sysInfo->freqOPB/sysInfo->pllExtBusDiv;
434         sysInfo->freqUART = sysInfo->freqPLB;
435 }
436 #else
437
438 #if !defined(CONFIG_XILINX_440)
439 void get_sys_info (sys_info_t * sysInfo)
440 {
441         unsigned long strp0;
442         unsigned long strp1;
443         unsigned long temp;
444         unsigned long temp1;
445         unsigned long lfdiv;
446         unsigned long m;
447         unsigned long prbdv0;
448
449 #if defined(CONFIG_YUCCA)
450         unsigned long sys_freq;
451         unsigned long sys_per=0;
452         unsigned long msr;
453         unsigned long pci_clock_per;
454         unsigned long sdr_ddrpll;
455
456         /*-------------------------------------------------------------------------+
457          | Get the system clock period.
458          +-------------------------------------------------------------------------*/
459         sys_per = determine_sysper();
460
461         msr = (mfmsr () & ~(MSR_EE));   /* disable interrupts */
462
463         /*-------------------------------------------------------------------------+
464          | Calculate the system clock speed from the period.
465          +-------------------------------------------------------------------------*/
466         sys_freq = (ONE_BILLION / sys_per) * 1000;
467 #endif
468
469         /* Extract configured divisors */
470         mfsdr( SDR0_SDSTP0,strp0 );
471         mfsdr( SDR0_SDSTP1,strp1 );
472
473         temp = ((strp0 & PLLSYS0_FWD_DIV_A_MASK) >> 8);
474         sysInfo->pllFwdDivA = temp ? temp : 16 ;
475         temp = ((strp0 & PLLSYS0_FWD_DIV_B_MASK) >> 5);
476         sysInfo->pllFwdDivB = temp ? temp: 8 ;
477         temp = (strp0 & PLLSYS0_FB_DIV_MASK) >> 12;
478         sysInfo->pllFbkDiv = temp ? temp : 32;
479         temp = (strp0 & PLLSYS0_OPB_DIV_MASK);
480         sysInfo->pllOpbDiv = temp ? temp : 4;
481         temp = (strp1 & PLLSYS1_PERCLK_DIV_MASK) >> 24;
482         sysInfo->pllExtBusDiv = temp ? temp : 4;
483         prbdv0 = (strp0 >> 2) & 0x7;
484
485         /* Calculate 'M' based on feedback source */
486         temp = (strp0 & PLLSYS0_SEL_MASK) >> 27;
487         temp1 = (strp1 & PLLSYS1_LF_DIV_MASK) >> 26;
488         lfdiv = temp1 ? temp1 : 64;
489         if (temp == 0) { /* PLL output */
490                 /* Figure which pll to use */
491                 temp = (strp0 & PLLSYS0_SRC_MASK) >> 30;
492                 if (!temp)
493                         m = sysInfo->pllFbkDiv * lfdiv * sysInfo->pllFwdDivA;
494                 else
495                         m = sysInfo->pllFbkDiv * lfdiv * sysInfo->pllFwdDivB;
496         }
497         else if (temp == 1) /* CPU output */
498                 m = sysInfo->pllFbkDiv * sysInfo->pllFwdDivA;
499         else /* PerClk */
500                 m = sysInfo->pllExtBusDiv * sysInfo->pllOpbDiv * sysInfo->pllFwdDivB;
501
502         /* Now calculate the individual clocks */
503 #if defined(CONFIG_YUCCA)
504         sysInfo->freqVCOMhz = (m * sys_freq) ;
505 #else
506         sysInfo->freqVCOMhz = (m * CONFIG_SYS_CLK_FREQ) + (m >> 1);
507 #endif
508         sysInfo->freqProcessor = sysInfo->freqVCOMhz/sysInfo->pllFwdDivA;
509         sysInfo->freqPLB = sysInfo->freqVCOMhz/sysInfo->pllFwdDivB/prbdv0;
510         sysInfo->freqOPB = sysInfo->freqPLB/sysInfo->pllOpbDiv;
511         sysInfo->freqEBC = sysInfo->freqOPB/sysInfo->pllExtBusDiv;
512
513 #if defined(CONFIG_YUCCA)
514         /* Determine PCI Clock Period */
515         pci_clock_per = determine_pci_clock_per();
516         sysInfo->freqPCI = (ONE_BILLION/pci_clock_per) * 1000;
517         mfsdr(SDR0_DDR0, sdr_ddrpll);
518         sysInfo->freqDDR = ((sysInfo->freqPLB) * SDR0_DDR0_DDRM_DECODE(sdr_ddrpll));
519 #endif
520
521         sysInfo->freqUART = sysInfo->freqPLB;
522 }
523
524 #endif
525 #endif /* CONFIG_XILINX_440 */
526
527 #if defined(CONFIG_YUCCA)
528 unsigned long determine_sysper(void)
529 {
530         unsigned int fpga_clocking_reg;
531         unsigned int master_clock_selection;
532         unsigned long master_clock_per = 0;
533         unsigned long fb_div_selection;
534         unsigned int vco_div_reg_value;
535         unsigned long vco_div_selection;
536         unsigned long sys_per = 0;
537         int extClkVal;
538
539         /*-------------------------------------------------------------------------+
540          | Read FPGA reg 0 and reg 1 to get FPGA reg information
541          +-------------------------------------------------------------------------*/
542         fpga_clocking_reg = in16(FPGA_REG16);
543
544
545         /* Determine Master Clock Source Selection */
546         master_clock_selection = fpga_clocking_reg & FPGA_REG16_MASTER_CLK_MASK;
547
548         switch(master_clock_selection) {
549                 case FPGA_REG16_MASTER_CLK_66_66:
550                         master_clock_per = PERIOD_66_66MHZ;
551                         break;
552                 case FPGA_REG16_MASTER_CLK_50:
553                         master_clock_per = PERIOD_50_00MHZ;
554                         break;
555                 case FPGA_REG16_MASTER_CLK_33_33:
556                         master_clock_per = PERIOD_33_33MHZ;
557                         break;
558                 case FPGA_REG16_MASTER_CLK_25:
559                         master_clock_per = PERIOD_25_00MHZ;
560                         break;
561                 case FPGA_REG16_MASTER_CLK_EXT:
562                         if ((extClkVal==EXTCLK_33_33)
563                                         && (extClkVal==EXTCLK_50)
564                                         && (extClkVal==EXTCLK_66_66)
565                                         && (extClkVal==EXTCLK_83)) {
566                                 /* calculate master clock period from external clock value */
567                                 master_clock_per=(ONE_BILLION/extClkVal) * 1000;
568                         } else {
569                                 /* Unsupported */
570                                 DEBUGF ("%s[%d] *** master clock selection failed ***\n", __FUNCTION__,__LINE__);
571                                 hang();
572                         }
573                         break;
574                 default:
575                         /* Unsupported */
576                         DEBUGF ("%s[%d] *** master clock selection failed ***\n", __FUNCTION__,__LINE__);
577                         hang();
578                         break;
579         }
580
581         /* Determine FB divisors values */
582         if ((fpga_clocking_reg & FPGA_REG16_FB1_DIV_MASK) == FPGA_REG16_FB1_DIV_LOW) {
583                 if ((fpga_clocking_reg & FPGA_REG16_FB2_DIV_MASK) == FPGA_REG16_FB2_DIV_LOW)
584                         fb_div_selection = FPGA_FB_DIV_6;
585                 else
586                         fb_div_selection = FPGA_FB_DIV_12;
587         } else {
588                 if ((fpga_clocking_reg & FPGA_REG16_FB2_DIV_MASK) == FPGA_REG16_FB2_DIV_LOW)
589                         fb_div_selection = FPGA_FB_DIV_10;
590                 else
591                         fb_div_selection = FPGA_FB_DIV_20;
592         }
593
594         /* Determine VCO divisors values */
595         vco_div_reg_value = fpga_clocking_reg & FPGA_REG16_VCO_DIV_MASK;
596
597         switch(vco_div_reg_value) {
598                 case FPGA_REG16_VCO_DIV_4:
599                         vco_div_selection = FPGA_VCO_DIV_4;
600                         break;
601                 case FPGA_REG16_VCO_DIV_6:
602                         vco_div_selection = FPGA_VCO_DIV_6;
603                         break;
604                 case FPGA_REG16_VCO_DIV_8:
605                         vco_div_selection = FPGA_VCO_DIV_8;
606                         break;
607                 case FPGA_REG16_VCO_DIV_10:
608                 default:
609                         vco_div_selection = FPGA_VCO_DIV_10;
610                         break;
611         }
612
613         if (master_clock_selection == FPGA_REG16_MASTER_CLK_EXT) {
614                 switch(master_clock_per) {
615                         case PERIOD_25_00MHZ:
616                                 if (fb_div_selection == FPGA_FB_DIV_12) {
617                                         if (vco_div_selection == FPGA_VCO_DIV_4)
618                                                 sys_per = PERIOD_75_00MHZ;
619                                         if (vco_div_selection == FPGA_VCO_DIV_6)
620                                                 sys_per = PERIOD_50_00MHZ;
621                                 }
622                                 break;
623                         case PERIOD_33_33MHZ:
624                                 if (fb_div_selection == FPGA_FB_DIV_6) {
625                                         if (vco_div_selection == FPGA_VCO_DIV_4)
626                                                 sys_per = PERIOD_50_00MHZ;
627                                         if (vco_div_selection == FPGA_VCO_DIV_6)
628                                                 sys_per = PERIOD_33_33MHZ;
629                                 }
630                                 if (fb_div_selection == FPGA_FB_DIV_10) {
631                                         if (vco_div_selection == FPGA_VCO_DIV_4)
632                                                 sys_per = PERIOD_83_33MHZ;
633                                         if (vco_div_selection == FPGA_VCO_DIV_10)
634                                                 sys_per = PERIOD_33_33MHZ;
635                                 }
636                                 if (fb_div_selection == FPGA_FB_DIV_12) {
637                                         if (vco_div_selection == FPGA_VCO_DIV_4)
638                                                 sys_per = PERIOD_100_00MHZ;
639                                         if (vco_div_selection == FPGA_VCO_DIV_6)
640                                                 sys_per = PERIOD_66_66MHZ;
641                                         if (vco_div_selection == FPGA_VCO_DIV_8)
642                                                 sys_per = PERIOD_50_00MHZ;
643                                 }
644                                 break;
645                         case PERIOD_50_00MHZ:
646                                 if (fb_div_selection == FPGA_FB_DIV_6) {
647                                         if (vco_div_selection == FPGA_VCO_DIV_4)
648                                                 sys_per = PERIOD_75_00MHZ;
649                                         if (vco_div_selection == FPGA_VCO_DIV_6)
650                                                 sys_per = PERIOD_50_00MHZ;
651                                 }
652                                 if (fb_div_selection == FPGA_FB_DIV_10) {
653                                         if (vco_div_selection == FPGA_VCO_DIV_6)
654                                                 sys_per = PERIOD_83_33MHZ;
655                                         if (vco_div_selection == FPGA_VCO_DIV_10)
656                                                 sys_per = PERIOD_50_00MHZ;
657                                 }
658                                 if (fb_div_selection == FPGA_FB_DIV_12) {
659                                         if (vco_div_selection == FPGA_VCO_DIV_6)
660                                                 sys_per = PERIOD_100_00MHZ;
661                                         if (vco_div_selection == FPGA_VCO_DIV_8)
662                                                 sys_per = PERIOD_75_00MHZ;
663                                 }
664                                 break;
665                         case PERIOD_66_66MHZ:
666                                 if (fb_div_selection == FPGA_FB_DIV_6) {
667                                         if (vco_div_selection == FPGA_VCO_DIV_4)
668                                                 sys_per = PERIOD_100_00MHZ;
669                                         if (vco_div_selection == FPGA_VCO_DIV_6)
670                                                 sys_per = PERIOD_66_66MHZ;
671                                         if (vco_div_selection == FPGA_VCO_DIV_8)
672                                                 sys_per = PERIOD_50_00MHZ;
673                                 }
674                                 if (fb_div_selection == FPGA_FB_DIV_10) {
675                                         if (vco_div_selection == FPGA_VCO_DIV_8)
676                                                 sys_per = PERIOD_83_33MHZ;
677                                         if (vco_div_selection == FPGA_VCO_DIV_10)
678                                                 sys_per = PERIOD_66_66MHZ;
679                                 }
680                                 if (fb_div_selection == FPGA_FB_DIV_12) {
681                                         if (vco_div_selection == FPGA_VCO_DIV_8)
682                                                 sys_per = PERIOD_100_00MHZ;
683                                 }
684                                 break;
685                         default:
686                                 break;
687                 }
688
689                 if (sys_per == 0) {
690                         /* Other combinations are not supported */
691                         DEBUGF ("%s[%d] *** sys period compute failed ***\n", __FUNCTION__,__LINE__);
692                         hang();
693                 }
694         } else {
695                 /* calcul system clock without cheking */
696                 /* if engineering option clock no check is selected */
697                 /* sys_per = master_clock_per * vco_div_selection / fb_div_selection */
698                 sys_per = (master_clock_per/fb_div_selection) * vco_div_selection;
699         }
700
701         return(sys_per);
702 }
703
704 /*-------------------------------------------------------------------------+
705 | determine_pci_clock_per.
706 +-------------------------------------------------------------------------*/
707 unsigned long determine_pci_clock_per(void)
708 {
709         unsigned long pci_clock_selection,  pci_period;
710
711         /*-------------------------------------------------------------------------+
712          | Read FPGA reg 6 to get PCI 0 FPGA reg information
713          +-------------------------------------------------------------------------*/
714         pci_clock_selection = in16(FPGA_REG16); /* was reg6 averifier */
715
716
717         pci_clock_selection = pci_clock_selection & FPGA_REG16_PCI0_CLK_MASK;
718
719         switch (pci_clock_selection) {
720                 case FPGA_REG16_PCI0_CLK_133_33:
721                         pci_period = PERIOD_133_33MHZ;
722                         break;
723                 case FPGA_REG16_PCI0_CLK_100:
724                         pci_period = PERIOD_100_00MHZ;
725                         break;
726                 case FPGA_REG16_PCI0_CLK_66_66:
727                         pci_period = PERIOD_66_66MHZ;
728                         break;
729                 default:
730                         pci_period = PERIOD_33_33MHZ;;
731                         break;
732         }
733
734         return(pci_period);
735 }
736 #endif
737
738 #elif defined(CONFIG_XILINX_405)
739 extern void get_sys_info (sys_info_t * sysInfo);
740 extern ulong get_PCI_freq (void);
741
742 #elif defined(CONFIG_AP1000)
743 void get_sys_info (sys_info_t * sysInfo)
744 {
745         sysInfo->freqProcessor = 240 * 1000 * 1000;
746         sysInfo->freqPLB = 80 * 1000 * 1000;
747         sysInfo->freqPCI = 33 * 1000 * 1000;
748 }
749
750 #elif defined(CONFIG_405)
751
752 void get_sys_info (sys_info_t * sysInfo)
753 {
754         sysInfo->freqVCOMhz=3125000;
755         sysInfo->freqProcessor=12*1000*1000;
756         sysInfo->freqPLB=50*1000*1000;
757         sysInfo->freqPCI=66*1000*1000;
758 }
759
760 #elif defined(CONFIG_405EP)
761 void get_sys_info (PPC4xx_SYS_INFO * sysInfo)
762 {
763         unsigned long pllmr0;
764         unsigned long pllmr1;
765         unsigned long sysClkPeriodPs = ONE_BILLION / (CONFIG_SYS_CLK_FREQ / 1000);
766         unsigned long m;
767         unsigned long pllmr0_ccdv;
768
769         /*
770          * Read PLL Mode registers
771          */
772         pllmr0 = mfdcr (CPC0_PLLMR0);
773         pllmr1 = mfdcr (CPC0_PLLMR1);
774
775         /*
776          * Determine forward divider A
777          */
778         sysInfo->pllFwdDiv = 8 - ((pllmr1 & PLLMR1_FWDVA_MASK) >> 16);
779
780         /*
781          * Determine forward divider B (should be equal to A)
782          */
783         sysInfo->pllFwdDivB = 8 - ((pllmr1 & PLLMR1_FWDVB_MASK) >> 12);
784
785         /*
786          * Determine FBK_DIV.
787          */
788         sysInfo->pllFbkDiv = ((pllmr1 & PLLMR1_FBMUL_MASK) >> 20);
789         if (sysInfo->pllFbkDiv == 0)
790                 sysInfo->pllFbkDiv = 16;
791
792         /*
793          * Determine PLB_DIV.
794          */
795         sysInfo->pllPlbDiv = ((pllmr0 & PLLMR0_CPU_TO_PLB_MASK) >> 16) + 1;
796
797         /*
798          * Determine PCI_DIV.
799          */
800         sysInfo->pllPciDiv = (pllmr0 & PLLMR0_PCI_TO_PLB_MASK) + 1;
801
802         /*
803          * Determine EXTBUS_DIV.
804          */
805         sysInfo->pllExtBusDiv = ((pllmr0 & PLLMR0_EXB_TO_PLB_MASK) >> 8) + 2;
806
807         /*
808          * Determine OPB_DIV.
809          */
810         sysInfo->pllOpbDiv = ((pllmr0 & PLLMR0_OPB_TO_PLB_MASK) >> 12) + 1;
811
812         /*
813          * Determine the M factor
814          */
815         m = sysInfo->pllFbkDiv * sysInfo->pllFwdDivB;
816
817         /*
818          * Determine VCO clock frequency
819          */
820         sysInfo->freqVCOHz = (1000000000000LL * (unsigned long long)m) /
821                 (unsigned long long)sysClkPeriodPs;
822
823         /*
824          * Determine CPU clock frequency
825          */
826         pllmr0_ccdv = ((pllmr0 & PLLMR0_CPU_DIV_MASK) >> 20) + 1;
827         if (pllmr1 & PLLMR1_SSCS_MASK) {
828                 /*
829                  * This is true if FWDVA == FWDVB:
830                  * sysInfo->freqProcessor = (CONFIG_SYS_CLK_FREQ * sysInfo->pllFbkDiv)
831                  *      / pllmr0_ccdv;
832                  */
833                 sysInfo->freqProcessor = (CONFIG_SYS_CLK_FREQ * sysInfo->pllFbkDiv * sysInfo->pllFwdDivB)
834                         / sysInfo->pllFwdDiv / pllmr0_ccdv;
835         } else {
836                 sysInfo->freqProcessor = CONFIG_SYS_CLK_FREQ / pllmr0_ccdv;
837         }
838
839         /*
840          * Determine PLB clock frequency
841          */
842         sysInfo->freqPLB = sysInfo->freqProcessor / sysInfo->pllPlbDiv;
843
844         sysInfo->freqEBC = sysInfo->freqPLB / sysInfo->pllExtBusDiv;
845
846         sysInfo->freqOPB = sysInfo->freqPLB / sysInfo->pllOpbDiv;
847
848         sysInfo->freqUART = sysInfo->freqProcessor * pllmr0_ccdv;
849 }
850
851
852 /********************************************
853  * get_PCI_freq
854  * return PCI bus freq in Hz
855  *********************************************/
856 ulong get_PCI_freq (void)
857 {
858         ulong val;
859         PPC4xx_SYS_INFO sys_info;
860
861         get_sys_info (&sys_info);
862         val = sys_info.freqPLB / sys_info.pllPciDiv;
863         return val;
864 }
865
866 #elif defined(CONFIG_405EZ)
867 void get_sys_info (PPC4xx_SYS_INFO * sysInfo)
868 {
869         unsigned long cpr_plld;
870         unsigned long cpr_pllc;
871         unsigned long cpr_primad;
872         unsigned long sysClkPeriodPs = ONE_BILLION / (CONFIG_SYS_CLK_FREQ/1000);
873         unsigned long primad_cpudv;
874         unsigned long m;
875         unsigned long plloutb;
876
877         /*
878          * Read PLL Mode registers
879          */
880         mfcpr(CPR0_PLLD, cpr_plld);
881         mfcpr(CPR0_PLLC, cpr_pllc);
882
883         /*
884          * Determine forward divider A
885          */
886         sysInfo->pllFwdDiv = ((cpr_plld & PLLD_FWDVA_MASK) >> 16);
887
888         /*
889          * Determine forward divider B
890          */
891         sysInfo->pllFwdDivB = ((cpr_plld & PLLD_FWDVB_MASK) >> 8);
892         if (sysInfo->pllFwdDivB == 0)
893                 sysInfo->pllFwdDivB = 8;
894
895         /*
896          * Determine FBK_DIV.
897          */
898         sysInfo->pllFbkDiv = ((cpr_plld & PLLD_FBDV_MASK) >> 24);
899         if (sysInfo->pllFbkDiv == 0)
900                 sysInfo->pllFbkDiv = 256;
901
902         /*
903          * Read CPR_PRIMAD register
904          */
905         mfcpr(CPC0_PRIMAD, cpr_primad);
906
907         /*
908          * Determine PLB_DIV.
909          */
910         sysInfo->pllPlbDiv = ((cpr_primad & PRIMAD_PLBDV_MASK) >> 16);
911         if (sysInfo->pllPlbDiv == 0)
912                 sysInfo->pllPlbDiv = 16;
913
914         /*
915          * Determine EXTBUS_DIV.
916          */
917         sysInfo->pllExtBusDiv = (cpr_primad & PRIMAD_EBCDV_MASK);
918         if (sysInfo->pllExtBusDiv == 0)
919                 sysInfo->pllExtBusDiv = 16;
920
921         /*
922          * Determine OPB_DIV.
923          */
924         sysInfo->pllOpbDiv = ((cpr_primad & PRIMAD_OPBDV_MASK) >> 8);
925         if (sysInfo->pllOpbDiv == 0)
926                 sysInfo->pllOpbDiv = 16;
927
928         /*
929          * Determine the M factor
930          */
931         if (cpr_pllc & PLLC_SRC_MASK)
932                 m = sysInfo->pllFbkDiv * sysInfo->pllFwdDivB;
933         else
934                 m = sysInfo->pllFbkDiv * sysInfo->pllFwdDiv;
935
936         /*
937          * Determine VCO clock frequency
938          */
939         sysInfo->freqVCOHz = (1000000000000LL * (unsigned long long)m) /
940                 (unsigned long long)sysClkPeriodPs;
941
942         /*
943          * Determine CPU clock frequency
944          */
945         primad_cpudv = ((cpr_primad & PRIMAD_CPUDV_MASK) >> 24);
946         if (primad_cpudv == 0)
947                 primad_cpudv = 16;
948
949         sysInfo->freqProcessor = (CONFIG_SYS_CLK_FREQ * m) /
950                 sysInfo->pllFwdDiv / primad_cpudv;
951
952         /*
953          * Determine PLB clock frequency
954          */
955         sysInfo->freqPLB = (CONFIG_SYS_CLK_FREQ * m) /
956                 sysInfo->pllFwdDiv / sysInfo->pllPlbDiv;
957
958         sysInfo->freqOPB = (CONFIG_SYS_CLK_FREQ * sysInfo->pllFbkDiv) /
959                 sysInfo->pllOpbDiv;
960
961         sysInfo->freqEBC = (CONFIG_SYS_CLK_FREQ * sysInfo->pllFbkDiv) /
962                 sysInfo->pllExtBusDiv;
963
964         plloutb = ((CONFIG_SYS_CLK_FREQ * ((cpr_pllc & PLLC_SRC_MASK) ?
965                 sysInfo->pllFwdDivB : sysInfo->pllFwdDiv) * sysInfo->pllFbkDiv) /
966                 sysInfo->pllFwdDivB);
967         sysInfo->freqUART = plloutb;
968 }
969
970 #elif defined(CONFIG_405EX)
971
972 /*
973  * TODO: We need to get the CPR registers and calculate these values correctly!!!!
974  *   We need the specs!!!!
975  */
976 static unsigned char get_fbdv(unsigned char index)
977 {
978         unsigned char ret = 0;
979         /* This is table should be 256 bytes.
980          * Only take first 52 values.
981          */
982         unsigned char fbdv_tb[] = {
983                 0x00, 0xff, 0x7f, 0xfd,
984                 0x7a, 0xf5, 0x6a, 0xd5,
985                 0x2a, 0xd4, 0x29, 0xd3,
986                 0x26, 0xcc, 0x19, 0xb3,
987                 0x67, 0xce, 0x1d, 0xbb,
988                 0x77, 0xee, 0x5d, 0xba,
989                 0x74, 0xe9, 0x52, 0xa5,
990                 0x4b, 0x96, 0x2c, 0xd8,
991                 0x31, 0xe3, 0x46, 0x8d,
992                 0x1b, 0xb7, 0x6f, 0xde,
993                 0x3d, 0xfb, 0x76, 0xed,
994                 0x5a, 0xb5, 0x6b, 0xd6,
995                 0x2d, 0xdb, 0x36, 0xec,
996
997         };
998
999         if ((index & 0x7f) == 0)
1000                 return 1;
1001         while (ret < sizeof (fbdv_tb)) {
1002                 if (fbdv_tb[ret] == index)
1003                         break;
1004                 ret++;
1005         }
1006         ret++;
1007
1008         return ret;
1009 }
1010
1011 #define PLL_FBK_PLL_LOCAL       0
1012 #define PLL_FBK_CPU             1
1013 #define PLL_FBK_PERCLK          5
1014
1015 void get_sys_info (sys_info_t * sysInfo)
1016 {
1017         unsigned long sysClkPeriodPs = ONE_BILLION / (CONFIG_SYS_CLK_FREQ / 1000);
1018         unsigned long m = 1;
1019         unsigned int  tmp;
1020         unsigned char fwdva[16] = {
1021                 1, 2, 14, 9, 4, 11, 16, 13,
1022                 12, 5, 6, 15, 10, 7, 8, 3,
1023         };
1024         unsigned char sel, cpudv0, plb2xDiv;
1025
1026         mfcpr(CPR0_PLLD, tmp);
1027
1028         /*
1029          * Determine forward divider A
1030          */
1031         sysInfo->pllFwdDiv = fwdva[((tmp >> 16) & 0x0f)];       /* FWDVA */
1032
1033         /*
1034          * Determine FBK_DIV.
1035          */
1036         sysInfo->pllFbkDiv = get_fbdv(((tmp >> 24) & 0x0ff)); /* FBDV */
1037
1038         /*
1039          * Determine PLBDV0
1040          */
1041         sysInfo->pllPlbDiv = 2;
1042
1043         /*
1044          * Determine PERDV0
1045          */
1046         mfcpr(CPR0_PERD, tmp);
1047         tmp = (tmp >> 24) & 0x03;
1048         sysInfo->pllExtBusDiv = (tmp == 0) ? 4 : tmp;
1049
1050         /*
1051          * Determine OPBDV0
1052          */
1053         mfcpr(CPR0_OPBD0, tmp);
1054         tmp = (tmp >> 24) & 0x03;
1055         sysInfo->pllOpbDiv = (tmp == 0) ? 4 : tmp;
1056
1057         /* Determine PLB2XDV0 */
1058         mfcpr(CPR0_PLBD, tmp);
1059         tmp = (tmp >> 16) & 0x07;
1060         plb2xDiv = (tmp == 0) ? 8 : tmp;
1061
1062         /* Determine CPUDV0 */
1063         mfcpr(CPR0_CPUD, tmp);
1064         tmp = (tmp >> 24) & 0x07;
1065         cpudv0 = (tmp == 0) ? 8 : tmp;
1066
1067         /* Determine SEL(5:7) in CPR0_PLLC */
1068         mfcpr(CPR0_PLLC, tmp);
1069         sel = (tmp >> 24) & 0x07;
1070
1071         /*
1072          * Determine the M factor
1073          * PLL local: M = FBDV
1074          * CPU clock: M = FBDV * FWDVA * CPUDV0
1075          * PerClk       : M = FBDV * FWDVA * PLB2XDV0 * PLBDV0(2) * OPBDV0 * PERDV0
1076          *
1077          */
1078         switch (sel) {
1079         case PLL_FBK_CPU:
1080                 m = sysInfo->pllFwdDiv * cpudv0;
1081                 break;
1082         case PLL_FBK_PERCLK:
1083                 m = sysInfo->pllFwdDiv * plb2xDiv * 2
1084                         * sysInfo->pllOpbDiv * sysInfo->pllExtBusDiv;
1085                 break;
1086         case PLL_FBK_PLL_LOCAL:
1087                 break;
1088         default:
1089                 printf("%s unknown m\n", __FUNCTION__);
1090                 return;
1091
1092         }
1093         m *= sysInfo->pllFbkDiv;
1094
1095         /*
1096          * Determine VCO clock frequency
1097          */
1098         sysInfo->freqVCOHz = (1000000000000LL * (unsigned long long)m) /
1099                 (unsigned long long)sysClkPeriodPs;
1100
1101         /*
1102          * Determine CPU clock frequency
1103          */
1104         sysInfo->freqProcessor = sysInfo->freqVCOHz / (sysInfo->pllFwdDiv * cpudv0);
1105
1106         /*
1107          * Determine PLB clock frequency, ddr1x should be the same
1108          */
1109         sysInfo->freqPLB = sysInfo->freqVCOHz / (sysInfo->pllFwdDiv * plb2xDiv * 2);
1110         sysInfo->freqOPB = sysInfo->freqPLB/sysInfo->pllOpbDiv;
1111         sysInfo->freqDDR = sysInfo->freqPLB;
1112         sysInfo->freqEBC = sysInfo->freqOPB / sysInfo->pllExtBusDiv;
1113         sysInfo->freqUART = sysInfo->freqPLB;
1114 }
1115
1116 #endif
1117
1118 int get_clocks (void)
1119 {
1120 #if defined(CONFIG_405GP) || defined(CONFIG_405CR) || \
1121     defined(CONFIG_405EP) || defined(CONFIG_405EZ) || \
1122     defined(CONFIG_405EX) || defined(CONFIG_405) || \
1123     defined(CONFIG_440)
1124         sys_info_t sys_info;
1125
1126         get_sys_info (&sys_info);
1127         gd->cpu_clk = sys_info.freqProcessor;
1128         gd->bus_clk = sys_info.freqPLB;
1129
1130 #endif  /* defined(CONFIG_405GP) || defined(CONFIG_405CR) */
1131
1132 #ifdef CONFIG_IOP480
1133         gd->cpu_clk = 66000000;
1134         gd->bus_clk = 66000000;
1135 #endif
1136         return (0);
1137 }
1138
1139
1140 /********************************************
1141  * get_bus_freq
1142  * return PLB bus freq in Hz
1143  *********************************************/
1144 ulong get_bus_freq (ulong dummy)
1145 {
1146         ulong val;
1147
1148 #if defined(CONFIG_405GP) || defined(CONFIG_405CR) || \
1149     defined(CONFIG_405EP) || defined(CONFIG_405EZ) || \
1150     defined(CONFIG_405EX) || defined(CONFIG_405) || \
1151     defined(CONFIG_440)
1152         sys_info_t sys_info;
1153
1154         get_sys_info (&sys_info);
1155         val = sys_info.freqPLB;
1156
1157 #elif defined(CONFIG_IOP480)
1158
1159         val = 66;
1160
1161 #else
1162 # error get_bus_freq() not implemented
1163 #endif
1164
1165         return val;
1166 }
1167
1168 #if !defined(CONFIG_IOP480)
1169 ulong get_OPB_freq (void)
1170 {
1171         PPC4xx_SYS_INFO sys_info;
1172
1173         get_sys_info (&sys_info);
1174
1175         return sys_info.freqOPB;
1176 }
1177 #endif