]> git.ipfire.org Git - people/ms/u-boot.git/blob - arch/ppc/cpu/ppc4xx/speed.c
nios2: Move individual board linker scripts to common script in cpu tree.
[people/ms/u-boot.git] / arch / ppc / 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