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