blob: 90066142de142aa7e8bb609f04ec263ef85e4348 [file] [log] [blame]
wdenkc6097192002-11-03 00:24:07 +00001/*
Stefan Roesedbbd1252007-10-05 17:10:59 +02002 * (C) Copyright 2000-2007
wdenkc6097192002-11-03 00:24:07 +00003 * 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
Wolfgang Denkd87080b2006-03-31 18:32:53 +020029DECLARE_GLOBAL_DATA_PTR;
wdenkc6097192002-11-03 00:24:07 +000030
31#define ONE_BILLION 1000000000
Marian Balakowicz6c5879f2006-06-30 16:30:46 +020032#ifdef DEBUG
33#define DEBUGF(fmt,args...) printf(fmt ,##args)
34#else
35#define DEBUGF(fmt,args...)
36#endif
wdenkc6097192002-11-03 00:24:07 +000037
38#if defined(CONFIG_405GP) || defined(CONFIG_405CR)
39
Stefan Roese087dfdb2007-10-21 08:12:41 +020040void get_sys_info (PPC4xx_SYS_INFO * sysInfo)
wdenkc6097192002-11-03 00:24:07 +000041{
42 unsigned long pllmr;
43 unsigned long sysClkPeriodPs = ONE_BILLION / (CONFIG_SYS_CLK_FREQ / 1000);
44 uint pvr = get_pvr();
45 unsigned long psr;
46 unsigned long m;
47
48 /*
49 * Read PLL Mode register
50 */
51 pllmr = mfdcr (pllmd);
52
53 /*
54 * Read Pin Strapping register
55 */
56 psr = mfdcr (strap);
57
58 /*
59 * Determine FWD_DIV.
60 */
61 sysInfo->pllFwdDiv = 8 - ((pllmr & PLLMR_FWD_DIV_MASK) >> 29);
62
63 /*
64 * Determine FBK_DIV.
65 */
66 sysInfo->pllFbkDiv = ((pllmr & PLLMR_FB_DIV_MASK) >> 25);
67 if (sysInfo->pllFbkDiv == 0) {
68 sysInfo->pllFbkDiv = 16;
69 }
70
71 /*
72 * Determine PLB_DIV.
73 */
74 sysInfo->pllPlbDiv = ((pllmr & PLLMR_CPU_TO_PLB_MASK) >> 17) + 1;
75
76 /*
77 * Determine PCI_DIV.
78 */
79 sysInfo->pllPciDiv = ((pllmr & PLLMR_PCI_TO_PLB_MASK) >> 13) + 1;
80
81 /*
82 * Determine EXTBUS_DIV.
83 */
84 sysInfo->pllExtBusDiv = ((pllmr & PLLMR_EXB_TO_PLB_MASK) >> 11) + 2;
85
86 /*
87 * Determine OPB_DIV.
88 */
89 sysInfo->pllOpbDiv = ((pllmr & PLLMR_OPB_TO_PLB_MASK) >> 15) + 1;
90
91 /*
92 * Check if PPC405GPr used (mask minor revision field)
93 */
stroesebaa3d522003-04-04 16:00:33 +000094 if ((pvr & 0xfffffff0) == (PVR_405GPR_RB & 0xfffffff0)) {
wdenkc6097192002-11-03 00:24:07 +000095 /*
96 * Determine FWD_DIV B (only PPC405GPr with new mode strapping).
97 */
98 sysInfo->pllFwdDivB = 8 - (pllmr & PLLMR_FWDB_DIV_MASK);
99
100 /*
101 * Determine factor m depending on PLL feedback clock source
102 */
103 if (!(psr & PSR_PCI_ASYNC_EN)) {
104 if (psr & PSR_NEW_MODE_EN) {
105 /*
106 * sync pci clock used as feedback (new mode)
107 */
108 m = 1 * sysInfo->pllFwdDivB * 2 * sysInfo->pllPciDiv;
109 } else {
110 /*
111 * sync pci clock used as feedback (legacy mode)
112 */
113 m = 1 * sysInfo->pllFwdDivB * sysInfo->pllPlbDiv * sysInfo->pllPciDiv;
114 }
115 } else if (psr & PSR_NEW_MODE_EN) {
116 if (psr & PSR_PERCLK_SYNC_MODE_EN) {
117 /*
118 * PerClk used as feedback (new mode)
119 */
120 m = 1 * sysInfo->pllFwdDivB * 2 * sysInfo->pllExtBusDiv;
121 } else {
122 /*
123 * CPU clock used as feedback (new mode)
124 */
125 m = sysInfo->pllFbkDiv * sysInfo->pllFwdDiv;
126 }
127 } else if (sysInfo->pllExtBusDiv == sysInfo->pllFbkDiv) {
128 /*
129 * PerClk used as feedback (legacy mode)
130 */
131 m = 1 * sysInfo->pllFwdDivB * sysInfo->pllPlbDiv * sysInfo->pllExtBusDiv;
132 } else {
133 /*
134 * PLB clock used as feedback (legacy mode)
135 */
136 m = sysInfo->pllFbkDiv * sysInfo->pllFwdDivB * sysInfo->pllPlbDiv;
137 }
138
stroeseb39392a2004-12-16 18:13:53 +0000139 sysInfo->freqVCOHz = (1000000000000LL * (unsigned long long)m) /
140 (unsigned long long)sysClkPeriodPs;
141 sysInfo->freqProcessor = sysInfo->freqVCOHz / sysInfo->pllFwdDiv;
142 sysInfo->freqPLB = sysInfo->freqVCOHz / (sysInfo->pllFwdDivB * sysInfo->pllPlbDiv);
wdenkc6097192002-11-03 00:24:07 +0000143 } else {
144 /*
145 * Check pllFwdDiv to see if running in bypass mode where the CPU speed
146 * is equal to the 405GP SYS_CLK_FREQ. If not in bypass mode, check VCO
147 * to make sure it is within the proper range.
148 * spec: VCO = SYS_CLOCK x FBKDIV x PLBDIV x FWDDIV
149 * Note freqVCO is calculated in Mhz to avoid errors introduced by rounding.
150 */
151 if (sysInfo->pllFwdDiv == 1) {
152 sysInfo->freqProcessor = CONFIG_SYS_CLK_FREQ;
153 sysInfo->freqPLB = CONFIG_SYS_CLK_FREQ / sysInfo->pllPlbDiv;
154 } else {
stroeseb39392a2004-12-16 18:13:53 +0000155 sysInfo->freqVCOHz = ( 1000000000000LL *
156 (unsigned long long)sysInfo->pllFwdDiv *
157 (unsigned long long)sysInfo->pllFbkDiv *
158 (unsigned long long)sysInfo->pllPlbDiv
159 ) / (unsigned long long)sysClkPeriodPs;
160 sysInfo->freqPLB = (ONE_BILLION / ((sysClkPeriodPs * 10) /
161 sysInfo->pllFbkDiv)) * 10000;
162 sysInfo->freqProcessor = sysInfo->freqPLB * sysInfo->pllPlbDiv;
wdenkc6097192002-11-03 00:24:07 +0000163 }
164 }
Stefan Roesefa8aea22007-10-22 07:33:52 +0200165
166 sysInfo->freqUART = sysInfo->freqProcessor;
wdenkc6097192002-11-03 00:24:07 +0000167}
168
169
170/********************************************
171 * get_OPB_freq
172 * return OPB bus freq in Hz
173 *********************************************/
174ulong get_OPB_freq (void)
175{
176 ulong val = 0;
177
Stefan Roese087dfdb2007-10-21 08:12:41 +0200178 PPC4xx_SYS_INFO sys_info;
wdenkc6097192002-11-03 00:24:07 +0000179
180 get_sys_info (&sys_info);
181 val = sys_info.freqPLB / sys_info.pllOpbDiv;
182
183 return val;
184}
185
186
187/********************************************
188 * get_PCI_freq
189 * return PCI bus freq in Hz
190 *********************************************/
191ulong get_PCI_freq (void)
192{
193 ulong val;
Stefan Roese087dfdb2007-10-21 08:12:41 +0200194 PPC4xx_SYS_INFO sys_info;
wdenkc6097192002-11-03 00:24:07 +0000195
196 get_sys_info (&sys_info);
197 val = sys_info.freqPLB / sys_info.pllPciDiv;
198 return val;
199}
200
201
202#elif defined(CONFIG_440)
Stefan Roesec157d8e2005-08-01 16:41:48 +0200203
Stefan Roese887e2ec2006-09-07 11:51:23 +0200204#if defined(CONFIG_440EP) || defined(CONFIG_440GR) || \
205 defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
Stefan Roesec157d8e2005-08-01 16:41:48 +0200206void get_sys_info (sys_info_t *sysInfo)
207{
208 unsigned long temp;
209 unsigned long reg;
210 unsigned long lfdiv;
211 unsigned long m;
212 unsigned long prbdv0;
213 /*
214 WARNING: ASSUMES the following:
215 ENG=1
216 PRADV0=1
217 PRBDV0=1
218 */
219
220 /* Decode CPR0_PLLD0 for divisors */
Stefan Roese087dfdb2007-10-21 08:12:41 +0200221 mfcpr(clk_plld, reg);
Stefan Roesec157d8e2005-08-01 16:41:48 +0200222 temp = (reg & PLLD_FWDVA_MASK) >> 16;
223 sysInfo->pllFwdDivA = temp ? temp : 16;
224 temp = (reg & PLLD_FWDVB_MASK) >> 8;
225 sysInfo->pllFwdDivB = temp ? temp: 8 ;
226 temp = (reg & PLLD_FBDV_MASK) >> 24;
227 sysInfo->pllFbkDiv = temp ? temp : 32;
228 lfdiv = reg & PLLD_LFBDV_MASK;
229
Stefan Roese087dfdb2007-10-21 08:12:41 +0200230 mfcpr(clk_opbd, reg);
Stefan Roesec157d8e2005-08-01 16:41:48 +0200231 temp = (reg & OPBDDV_MASK) >> 24;
232 sysInfo->pllOpbDiv = temp ? temp : 4;
233
Stefan Roese087dfdb2007-10-21 08:12:41 +0200234 mfcpr(clk_perd, reg);
Stefan Roesec157d8e2005-08-01 16:41:48 +0200235 temp = (reg & PERDV_MASK) >> 24;
236 sysInfo->pllExtBusDiv = temp ? temp : 8;
237
Stefan Roese087dfdb2007-10-21 08:12:41 +0200238 mfcpr(clk_primbd, reg);
Stefan Roesec157d8e2005-08-01 16:41:48 +0200239 temp = (reg & PRBDV_MASK) >> 24;
240 prbdv0 = temp ? temp : 8;
241
Stefan Roese087dfdb2007-10-21 08:12:41 +0200242 mfcpr(clk_spcid, reg);
Stefan Roesec157d8e2005-08-01 16:41:48 +0200243 temp = (reg & SPCID_MASK) >> 24;
244 sysInfo->pllPciDiv = temp ? temp : 4;
245
246 /* Calculate 'M' based on feedback source */
247 mfsdr(sdr_sdstp0, reg);
248 temp = (reg & PLLSYS0_SEL_MASK) >> 27;
249 if (temp == 0) { /* PLL output */
250 /* Figure which pll to use */
Stefan Roese087dfdb2007-10-21 08:12:41 +0200251 mfcpr(clk_pllc, reg);
Stefan Roesec157d8e2005-08-01 16:41:48 +0200252 temp = (reg & PLLC_SRC_MASK) >> 29;
253 if (!temp) /* PLLOUTA */
254 m = sysInfo->pllFbkDiv * lfdiv * sysInfo->pllFwdDivA;
255 else /* PLLOUTB */
256 m = sysInfo->pllFbkDiv * lfdiv * sysInfo->pllFwdDivB;
257 }
258 else if (temp == 1) /* CPU output */
259 m = sysInfo->pllFbkDiv * sysInfo->pllFwdDivA;
260 else /* PerClk */
261 m = sysInfo->pllExtBusDiv * sysInfo->pllOpbDiv * sysInfo->pllFwdDivB;
262
263 /* Now calculate the individual clocks */
264 sysInfo->freqVCOMhz = (m * CONFIG_SYS_CLK_FREQ) + (m>>1);
265 sysInfo->freqProcessor = sysInfo->freqVCOMhz/sysInfo->pllFwdDivA;
266 sysInfo->freqPLB = sysInfo->freqVCOMhz/sysInfo->pllFwdDivB/prbdv0;
267 sysInfo->freqOPB = sysInfo->freqPLB/sysInfo->pllOpbDiv;
Stefan Roesedbbd1252007-10-05 17:10:59 +0200268 sysInfo->freqEBC = sysInfo->freqPLB/sysInfo->pllExtBusDiv;
Stefan Roesec157d8e2005-08-01 16:41:48 +0200269 sysInfo->freqPCI = sysInfo->freqPLB/sysInfo->pllPciDiv;
Stefan Roesefa8aea22007-10-22 07:33:52 +0200270 sysInfo->freqUART = sysInfo->freqPLB;
Stefan Roesec157d8e2005-08-01 16:41:48 +0200271
272 /* Figure which timer source to use */
273 if (mfspr(ccr1) & 0x0080) { /* External Clock, assume same as SYS_CLK */
274 temp = sysInfo->freqProcessor / 2; /* Max extern clock speed */
275 if (CONFIG_SYS_CLK_FREQ > temp)
276 sysInfo->freqTmrClk = temp;
277 else
278 sysInfo->freqTmrClk = CONFIG_SYS_CLK_FREQ;
279 }
280 else /* Internal clock */
281 sysInfo->freqTmrClk = sysInfo->freqProcessor;
282}
Stefan Roesefa8aea22007-10-22 07:33:52 +0200283
Stefan Roesec157d8e2005-08-01 16:41:48 +0200284/********************************************
285 * get_PCI_freq
286 * return PCI bus freq in Hz
287 *********************************************/
288ulong get_PCI_freq (void)
289{
290 sys_info_t sys_info;
291 get_sys_info (&sys_info);
292 return sys_info.freqPCI;
293}
294
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200295#elif !defined(CONFIG_440GX) && !defined(CONFIG_440SP) && !defined(CONFIG_440SPE)
wdenkc6097192002-11-03 00:24:07 +0000296void get_sys_info (sys_info_t * sysInfo)
297{
298 unsigned long strp0;
299 unsigned long temp;
300 unsigned long m;
301
302 /* Extract configured divisors */
303 strp0 = mfdcr( cpc0_strp0 );
304 sysInfo->pllFwdDivA = 8 - ((strp0 & PLLSYS0_FWD_DIV_A_MASK) >> 15);
305 sysInfo->pllFwdDivB = 8 - ((strp0 & PLLSYS0_FWD_DIV_B_MASK) >> 12);
306 temp = (strp0 & PLLSYS0_FB_DIV_MASK) >> 18;
307 sysInfo->pllFbkDiv = temp ? temp : 16;
308 sysInfo->pllOpbDiv = 1 + ((strp0 & PLLSYS0_OPB_DIV_MASK) >> 10);
309 sysInfo->pllExtBusDiv = 1 + ((strp0 & PLLSYS0_EPB_DIV_MASK) >> 8);
310
311 /* Calculate 'M' based on feedback source */
312 if( strp0 & PLLSYS0_EXTSL_MASK )
313 m = sysInfo->pllExtBusDiv * sysInfo->pllOpbDiv * sysInfo->pllFwdDivB;
314 else
315 m = sysInfo->pllFbkDiv * sysInfo->pllFwdDivA;
316
317 /* Now calculate the individual clocks */
318 sysInfo->freqVCOMhz = (m * CONFIG_SYS_CLK_FREQ) + (m>>1);
319 sysInfo->freqProcessor = sysInfo->freqVCOMhz/sysInfo->pllFwdDivA;
320 sysInfo->freqPLB = sysInfo->freqVCOMhz/sysInfo->pllFwdDivB;
Stefan Roesec157d8e2005-08-01 16:41:48 +0200321 if( get_pvr() == PVR_440GP_RB ) /* Rev B divs an extra 2 -- geez! */
322 sysInfo->freqPLB >>= 1;
wdenkc6097192002-11-03 00:24:07 +0000323 sysInfo->freqOPB = sysInfo->freqPLB/sysInfo->pllOpbDiv;
Stefan Roesedbbd1252007-10-05 17:10:59 +0200324 sysInfo->freqEBC = sysInfo->freqOPB/sysInfo->pllExtBusDiv;
Stefan Roesefa8aea22007-10-22 07:33:52 +0200325 sysInfo->freqUART = sysInfo->freqPLB;
wdenkc6097192002-11-03 00:24:07 +0000326}
wdenkba56f622004-02-06 23:19:44 +0000327#else
328void get_sys_info (sys_info_t * sysInfo)
329{
330 unsigned long strp0;
331 unsigned long strp1;
332 unsigned long temp;
333 unsigned long temp1;
334 unsigned long lfdiv;
335 unsigned long m;
wdenk42dfe7a2004-03-14 22:25:36 +0000336 unsigned long prbdv0;
wdenkba56f622004-02-06 23:19:44 +0000337
Stefan Roese4745aca2007-02-20 10:57:08 +0100338#if defined(CONFIG_YUCCA)
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200339 unsigned long sys_freq;
340 unsigned long sys_per=0;
341 unsigned long msr;
342 unsigned long pci_clock_per;
343 unsigned long sdr_ddrpll;
344
345 /*-------------------------------------------------------------------------+
346 | Get the system clock period.
347 +-------------------------------------------------------------------------*/
348 sys_per = determine_sysper();
349
350 msr = (mfmsr () & ~(MSR_EE)); /* disable interrupts */
351
352 /*-------------------------------------------------------------------------+
353 | Calculate the system clock speed from the period.
354 +-------------------------------------------------------------------------*/
Stefan Roese4745aca2007-02-20 10:57:08 +0100355 sys_freq = (ONE_BILLION / sys_per) * 1000;
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200356#endif
357
wdenkba56f622004-02-06 23:19:44 +0000358 /* Extract configured divisors */
359 mfsdr( sdr_sdstp0,strp0 );
360 mfsdr( sdr_sdstp1,strp1 );
361
362 temp = ((strp0 & PLLSYS0_FWD_DIV_A_MASK) >> 8);
363 sysInfo->pllFwdDivA = temp ? temp : 16 ;
364 temp = ((strp0 & PLLSYS0_FWD_DIV_B_MASK) >> 5);
365 sysInfo->pllFwdDivB = temp ? temp: 8 ;
366 temp = (strp0 & PLLSYS0_FB_DIV_MASK) >> 12;
367 sysInfo->pllFbkDiv = temp ? temp : 32;
368 temp = (strp0 & PLLSYS0_OPB_DIV_MASK);
369 sysInfo->pllOpbDiv = temp ? temp : 4;
370 temp = (strp1 & PLLSYS1_PERCLK_DIV_MASK) >> 24;
371 sysInfo->pllExtBusDiv = temp ? temp : 4;
wdenk0e6d7982004-03-14 00:07:33 +0000372 prbdv0 = (strp0 >> 2) & 0x7;
wdenkba56f622004-02-06 23:19:44 +0000373
374 /* Calculate 'M' based on feedback source */
375 temp = (strp0 & PLLSYS0_SEL_MASK) >> 27;
376 temp1 = (strp1 & PLLSYS1_LF_DIV_MASK) >> 26;
377 lfdiv = temp1 ? temp1 : 64;
378 if (temp == 0) { /* PLL output */
379 /* Figure which pll to use */
380 temp = (strp0 & PLLSYS0_SRC_MASK) >> 30;
381 if (!temp)
382 m = sysInfo->pllFbkDiv * lfdiv * sysInfo->pllFwdDivA;
383 else
384 m = sysInfo->pllFbkDiv * lfdiv * sysInfo->pllFwdDivB;
385 }
386 else if (temp == 1) /* CPU output */
387 m = sysInfo->pllFbkDiv * sysInfo->pllFwdDivA;
388 else /* PerClk */
389 m = sysInfo->pllExtBusDiv * sysInfo->pllOpbDiv * sysInfo->pllFwdDivB;
390
391 /* Now calculate the individual clocks */
Stefan Roese4745aca2007-02-20 10:57:08 +0100392#if defined(CONFIG_YUCCA)
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200393 sysInfo->freqVCOMhz = (m * sys_freq) ;
394#else
Stefan Roese4745aca2007-02-20 10:57:08 +0100395 sysInfo->freqVCOMhz = (m * CONFIG_SYS_CLK_FREQ) + (m >> 1);
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200396#endif
wdenkba56f622004-02-06 23:19:44 +0000397 sysInfo->freqProcessor = sysInfo->freqVCOMhz/sysInfo->pllFwdDivA;
wdenk0e6d7982004-03-14 00:07:33 +0000398 sysInfo->freqPLB = sysInfo->freqVCOMhz/sysInfo->pllFwdDivB/prbdv0;
wdenkba56f622004-02-06 23:19:44 +0000399 sysInfo->freqOPB = sysInfo->freqPLB/sysInfo->pllOpbDiv;
Stefan Roesedbbd1252007-10-05 17:10:59 +0200400 sysInfo->freqEBC = sysInfo->freqOPB/sysInfo->pllExtBusDiv;
wdenkba56f622004-02-06 23:19:44 +0000401
Stefan Roese4745aca2007-02-20 10:57:08 +0100402#if defined(CONFIG_YUCCA)
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200403 /* Determine PCI Clock Period */
404 pci_clock_per = determine_pci_clock_per();
405 sysInfo->freqPCI = (ONE_BILLION/pci_clock_per) * 1000;
406 mfsdr(sdr_ddr0, sdr_ddrpll);
407 sysInfo->freqDDR = ((sysInfo->freqPLB) * SDR0_DDR0_DDRM_DECODE(sdr_ddrpll));
408#endif
409
Stefan Roesefa8aea22007-10-22 07:33:52 +0200410 sysInfo->freqUART = sysInfo->freqPLB;
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200411}
412
413#endif
414
Stefan Roese4745aca2007-02-20 10:57:08 +0100415#if defined(CONFIG_YUCCA)
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200416unsigned long determine_sysper(void)
417{
418 unsigned int fpga_clocking_reg;
419 unsigned int master_clock_selection;
420 unsigned long master_clock_per = 0;
421 unsigned long fb_div_selection;
422 unsigned int vco_div_reg_value;
423 unsigned long vco_div_selection;
424 unsigned long sys_per = 0;
425 int extClkVal;
426
427 /*-------------------------------------------------------------------------+
428 | Read FPGA reg 0 and reg 1 to get FPGA reg information
429 +-------------------------------------------------------------------------*/
430 fpga_clocking_reg = in16(FPGA_REG16);
431
432
433 /* Determine Master Clock Source Selection */
434 master_clock_selection = fpga_clocking_reg & FPGA_REG16_MASTER_CLK_MASK;
435
436 switch(master_clock_selection) {
437 case FPGA_REG16_MASTER_CLK_66_66:
438 master_clock_per = PERIOD_66_66MHZ;
439 break;
440 case FPGA_REG16_MASTER_CLK_50:
441 master_clock_per = PERIOD_50_00MHZ;
442 break;
443 case FPGA_REG16_MASTER_CLK_33_33:
444 master_clock_per = PERIOD_33_33MHZ;
445 break;
446 case FPGA_REG16_MASTER_CLK_25:
447 master_clock_per = PERIOD_25_00MHZ;
448 break;
449 case FPGA_REG16_MASTER_CLK_EXT:
450 if ((extClkVal==EXTCLK_33_33)
451 && (extClkVal==EXTCLK_50)
452 && (extClkVal==EXTCLK_66_66)
453 && (extClkVal==EXTCLK_83)) {
454 /* calculate master clock period from external clock value */
455 master_clock_per=(ONE_BILLION/extClkVal) * 1000;
456 } else {
457 /* Unsupported */
458 DEBUGF ("%s[%d] *** master clock selection failed ***\n", __FUNCTION__,__LINE__);
459 hang();
460 }
461 break;
462 default:
463 /* Unsupported */
464 DEBUGF ("%s[%d] *** master clock selection failed ***\n", __FUNCTION__,__LINE__);
465 hang();
466 break;
467 }
468
469 /* Determine FB divisors values */
470 if ((fpga_clocking_reg & FPGA_REG16_FB1_DIV_MASK) == FPGA_REG16_FB1_DIV_LOW) {
471 if ((fpga_clocking_reg & FPGA_REG16_FB2_DIV_MASK) == FPGA_REG16_FB2_DIV_LOW)
472 fb_div_selection = FPGA_FB_DIV_6;
473 else
474 fb_div_selection = FPGA_FB_DIV_12;
475 } else {
476 if ((fpga_clocking_reg & FPGA_REG16_FB2_DIV_MASK) == FPGA_REG16_FB2_DIV_LOW)
477 fb_div_selection = FPGA_FB_DIV_10;
478 else
479 fb_div_selection = FPGA_FB_DIV_20;
480 }
481
482 /* Determine VCO divisors values */
483 vco_div_reg_value = fpga_clocking_reg & FPGA_REG16_VCO_DIV_MASK;
484
485 switch(vco_div_reg_value) {
486 case FPGA_REG16_VCO_DIV_4:
487 vco_div_selection = FPGA_VCO_DIV_4;
488 break;
489 case FPGA_REG16_VCO_DIV_6:
490 vco_div_selection = FPGA_VCO_DIV_6;
491 break;
492 case FPGA_REG16_VCO_DIV_8:
493 vco_div_selection = FPGA_VCO_DIV_8;
494 break;
495 case FPGA_REG16_VCO_DIV_10:
496 default:
497 vco_div_selection = FPGA_VCO_DIV_10;
498 break;
499 }
500
501 if (master_clock_selection == FPGA_REG16_MASTER_CLK_EXT) {
502 switch(master_clock_per) {
503 case PERIOD_25_00MHZ:
504 if (fb_div_selection == FPGA_FB_DIV_12) {
505 if (vco_div_selection == FPGA_VCO_DIV_4)
506 sys_per = PERIOD_75_00MHZ;
507 if (vco_div_selection == FPGA_VCO_DIV_6)
508 sys_per = PERIOD_50_00MHZ;
509 }
510 break;
511 case PERIOD_33_33MHZ:
512 if (fb_div_selection == FPGA_FB_DIV_6) {
513 if (vco_div_selection == FPGA_VCO_DIV_4)
514 sys_per = PERIOD_50_00MHZ;
515 if (vco_div_selection == FPGA_VCO_DIV_6)
516 sys_per = PERIOD_33_33MHZ;
517 }
518 if (fb_div_selection == FPGA_FB_DIV_10) {
519 if (vco_div_selection == FPGA_VCO_DIV_4)
520 sys_per = PERIOD_83_33MHZ;
521 if (vco_div_selection == FPGA_VCO_DIV_10)
522 sys_per = PERIOD_33_33MHZ;
523 }
524 if (fb_div_selection == FPGA_FB_DIV_12) {
525 if (vco_div_selection == FPGA_VCO_DIV_4)
526 sys_per = PERIOD_100_00MHZ;
527 if (vco_div_selection == FPGA_VCO_DIV_6)
528 sys_per = PERIOD_66_66MHZ;
529 if (vco_div_selection == FPGA_VCO_DIV_8)
530 sys_per = PERIOD_50_00MHZ;
531 }
532 break;
533 case PERIOD_50_00MHZ:
534 if (fb_div_selection == FPGA_FB_DIV_6) {
535 if (vco_div_selection == FPGA_VCO_DIV_4)
536 sys_per = PERIOD_75_00MHZ;
537 if (vco_div_selection == FPGA_VCO_DIV_6)
538 sys_per = PERIOD_50_00MHZ;
539 }
540 if (fb_div_selection == FPGA_FB_DIV_10) {
541 if (vco_div_selection == FPGA_VCO_DIV_6)
542 sys_per = PERIOD_83_33MHZ;
543 if (vco_div_selection == FPGA_VCO_DIV_10)
544 sys_per = PERIOD_50_00MHZ;
545 }
546 if (fb_div_selection == FPGA_FB_DIV_12) {
547 if (vco_div_selection == FPGA_VCO_DIV_6)
548 sys_per = PERIOD_100_00MHZ;
549 if (vco_div_selection == FPGA_VCO_DIV_8)
550 sys_per = PERIOD_75_00MHZ;
551 }
552 break;
553 case PERIOD_66_66MHZ:
554 if (fb_div_selection == FPGA_FB_DIV_6) {
555 if (vco_div_selection == FPGA_VCO_DIV_4)
556 sys_per = PERIOD_100_00MHZ;
557 if (vco_div_selection == FPGA_VCO_DIV_6)
558 sys_per = PERIOD_66_66MHZ;
559 if (vco_div_selection == FPGA_VCO_DIV_8)
560 sys_per = PERIOD_50_00MHZ;
561 }
562 if (fb_div_selection == FPGA_FB_DIV_10) {
563 if (vco_div_selection == FPGA_VCO_DIV_8)
564 sys_per = PERIOD_83_33MHZ;
565 if (vco_div_selection == FPGA_VCO_DIV_10)
566 sys_per = PERIOD_66_66MHZ;
567 }
568 if (fb_div_selection == FPGA_FB_DIV_12) {
569 if (vco_div_selection == FPGA_VCO_DIV_8)
570 sys_per = PERIOD_100_00MHZ;
571 }
572 break;
573 default:
574 break;
575 }
576
577 if (sys_per == 0) {
578 /* Other combinations are not supported */
579 DEBUGF ("%s[%d] *** sys period compute failed ***\n", __FUNCTION__,__LINE__);
580 hang();
581 }
582 } else {
583 /* calcul system clock without cheking */
584 /* if engineering option clock no check is selected */
585 /* sys_per = master_clock_per * vco_div_selection / fb_div_selection */
586 sys_per = (master_clock_per/fb_div_selection) * vco_div_selection;
587 }
588
589 return(sys_per);
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200590}
591
592/*-------------------------------------------------------------------------+
593| determine_pci_clock_per.
594+-------------------------------------------------------------------------*/
595unsigned long determine_pci_clock_per(void)
596{
597 unsigned long pci_clock_selection, pci_period;
598
599 /*-------------------------------------------------------------------------+
600 | Read FPGA reg 6 to get PCI 0 FPGA reg information
601 +-------------------------------------------------------------------------*/
602 pci_clock_selection = in16(FPGA_REG16); /* was reg6 averifier */
603
604
605 pci_clock_selection = pci_clock_selection & FPGA_REG16_PCI0_CLK_MASK;
606
607 switch (pci_clock_selection) {
608 case FPGA_REG16_PCI0_CLK_133_33:
609 pci_period = PERIOD_133_33MHZ;
610 break;
611 case FPGA_REG16_PCI0_CLK_100:
612 pci_period = PERIOD_100_00MHZ;
613 break;
614 case FPGA_REG16_PCI0_CLK_66_66:
615 pci_period = PERIOD_66_66MHZ;
616 break;
617 default:
618 pci_period = PERIOD_33_33MHZ;;
619 break;
620 }
621
622 return(pci_period);
wdenkba56f622004-02-06 23:19:44 +0000623}
624#endif
wdenkc6097192002-11-03 00:24:07 +0000625
626ulong get_OPB_freq (void)
627{
628
629 sys_info_t sys_info;
630 get_sys_info (&sys_info);
631 return sys_info.freqOPB;
632}
633
wdenk028ab6b2004-02-23 23:54:43 +0000634#elif defined(CONFIG_XILINX_ML300)
635extern void get_sys_info (sys_info_t * sysInfo);
636extern ulong get_PCI_freq (void);
637
Wolfgang Denk7521af12005-10-09 01:04:33 +0200638#elif defined(CONFIG_AP1000)
Stefan Roesefa8aea22007-10-22 07:33:52 +0200639void get_sys_info (sys_info_t * sysInfo)
640{
Wolfgang Denk7521af12005-10-09 01:04:33 +0200641 sysInfo->freqProcessor = 240 * 1000 * 1000;
642 sysInfo->freqPLB = 80 * 1000 * 1000;
643 sysInfo->freqPCI = 33 * 1000 * 1000;
644}
645
wdenkc6097192002-11-03 00:24:07 +0000646#elif defined(CONFIG_405)
647
Stefan Roesefa8aea22007-10-22 07:33:52 +0200648void get_sys_info (sys_info_t * sysInfo)
649{
wdenkc6097192002-11-03 00:24:07 +0000650 sysInfo->freqVCOMhz=3125000;
651 sysInfo->freqProcessor=12*1000*1000;
652 sysInfo->freqPLB=50*1000*1000;
653 sysInfo->freqPCI=66*1000*1000;
wdenkc6097192002-11-03 00:24:07 +0000654}
655
stroeseb867d702003-05-23 11:18:02 +0000656#elif defined(CONFIG_405EP)
Stefan Roese087dfdb2007-10-21 08:12:41 +0200657void get_sys_info (PPC4xx_SYS_INFO * sysInfo)
stroeseb867d702003-05-23 11:18:02 +0000658{
659 unsigned long pllmr0;
660 unsigned long pllmr1;
661 unsigned long sysClkPeriodPs = ONE_BILLION / (CONFIG_SYS_CLK_FREQ / 1000);
662 unsigned long m;
663 unsigned long pllmr0_ccdv;
664
665 /*
666 * Read PLL Mode registers
667 */
668 pllmr0 = mfdcr (cpc0_pllmr0);
669 pllmr1 = mfdcr (cpc0_pllmr1);
670
671 /*
672 * Determine forward divider A
673 */
674 sysInfo->pllFwdDiv = 8 - ((pllmr1 & PLLMR1_FWDVA_MASK) >> 16);
675
676 /*
677 * Determine forward divider B (should be equal to A)
678 */
679 sysInfo->pllFwdDivB = 8 - ((pllmr1 & PLLMR1_FWDVB_MASK) >> 12);
680
681 /*
682 * Determine FBK_DIV.
683 */
684 sysInfo->pllFbkDiv = ((pllmr1 & PLLMR1_FBMUL_MASK) >> 20);
Stefan Roesefa8aea22007-10-22 07:33:52 +0200685 if (sysInfo->pllFbkDiv == 0)
stroeseb867d702003-05-23 11:18:02 +0000686 sysInfo->pllFbkDiv = 16;
stroeseb867d702003-05-23 11:18:02 +0000687
688 /*
689 * Determine PLB_DIV.
690 */
691 sysInfo->pllPlbDiv = ((pllmr0 & PLLMR0_CPU_TO_PLB_MASK) >> 16) + 1;
692
693 /*
694 * Determine PCI_DIV.
695 */
696 sysInfo->pllPciDiv = (pllmr0 & PLLMR0_PCI_TO_PLB_MASK) + 1;
697
698 /*
699 * Determine EXTBUS_DIV.
700 */
701 sysInfo->pllExtBusDiv = ((pllmr0 & PLLMR0_EXB_TO_PLB_MASK) >> 8) + 2;
702
703 /*
704 * Determine OPB_DIV.
705 */
706 sysInfo->pllOpbDiv = ((pllmr0 & PLLMR0_OPB_TO_PLB_MASK) >> 12) + 1;
707
708 /*
709 * Determine the M factor
710 */
711 m = sysInfo->pllFbkDiv * sysInfo->pllFwdDivB;
712
713 /*
714 * Determine VCO clock frequency
715 */
stroeseb39392a2004-12-16 18:13:53 +0000716 sysInfo->freqVCOHz = (1000000000000LL * (unsigned long long)m) /
717 (unsigned long long)sysClkPeriodPs;
stroeseb867d702003-05-23 11:18:02 +0000718
719 /*
720 * Determine CPU clock frequency
721 */
722 pllmr0_ccdv = ((pllmr0 & PLLMR0_CPU_DIV_MASK) >> 20) + 1;
723 if (pllmr1 & PLLMR1_SSCS_MASK) {
wdenke55ca7e2004-07-01 21:40:08 +0000724 /*
725 * This is true if FWDVA == FWDVB:
726 * sysInfo->freqProcessor = (CONFIG_SYS_CLK_FREQ * sysInfo->pllFbkDiv)
727 * / pllmr0_ccdv;
728 */
729 sysInfo->freqProcessor = (CONFIG_SYS_CLK_FREQ * sysInfo->pllFbkDiv * sysInfo->pllFwdDivB)
730 / sysInfo->pllFwdDiv / pllmr0_ccdv;
stroeseb867d702003-05-23 11:18:02 +0000731 } else {
732 sysInfo->freqProcessor = CONFIG_SYS_CLK_FREQ / pllmr0_ccdv;
733 }
734
735 /*
736 * Determine PLB clock frequency
737 */
738 sysInfo->freqPLB = sysInfo->freqProcessor / sysInfo->pllPlbDiv;
Stefan Roesedbbd1252007-10-05 17:10:59 +0200739
740 sysInfo->freqEBC = sysInfo->freqPLB / sysInfo->pllExtBusDiv;
Stefan Roesefa8aea22007-10-22 07:33:52 +0200741
742 sysInfo->freqUART = sysInfo->freqProcessor * pllmr0_ccdv;
stroeseb867d702003-05-23 11:18:02 +0000743}
744
745
746/********************************************
747 * get_OPB_freq
748 * return OPB bus freq in Hz
749 *********************************************/
750ulong get_OPB_freq (void)
751{
752 ulong val = 0;
753
Stefan Roese087dfdb2007-10-21 08:12:41 +0200754 PPC4xx_SYS_INFO sys_info;
stroeseb867d702003-05-23 11:18:02 +0000755
756 get_sys_info (&sys_info);
757 val = sys_info.freqPLB / sys_info.pllOpbDiv;
758
759 return val;
760}
761
762
763/********************************************
764 * get_PCI_freq
765 * return PCI bus freq in Hz
766 *********************************************/
767ulong get_PCI_freq (void)
768{
769 ulong val;
Stefan Roese087dfdb2007-10-21 08:12:41 +0200770 PPC4xx_SYS_INFO sys_info;
stroeseb867d702003-05-23 11:18:02 +0000771
772 get_sys_info (&sys_info);
773 val = sys_info.freqPLB / sys_info.pllPciDiv;
774 return val;
775}
776
Stefan Roesee01bd212007-03-21 13:38:59 +0100777#elif defined(CONFIG_405EZ)
Stefan Roese087dfdb2007-10-21 08:12:41 +0200778void get_sys_info (PPC4xx_SYS_INFO * sysInfo)
Stefan Roesee01bd212007-03-21 13:38:59 +0100779{
780 unsigned long cpr_plld;
Stefan Roese273db7e2007-08-13 09:05:33 +0200781 unsigned long cpr_pllc;
Stefan Roesee01bd212007-03-21 13:38:59 +0100782 unsigned long cpr_primad;
783 unsigned long sysClkPeriodPs = ONE_BILLION / (CONFIG_SYS_CLK_FREQ/1000);
784 unsigned long primad_cpudv;
785 unsigned long m;
786
787 /*
788 * Read PLL Mode registers
789 */
790 mfcpr(cprplld, cpr_plld);
Stefan Roese273db7e2007-08-13 09:05:33 +0200791 mfcpr(cprpllc, cpr_pllc);
Stefan Roesee01bd212007-03-21 13:38:59 +0100792
793 /*
794 * Determine forward divider A
795 */
796 sysInfo->pllFwdDiv = ((cpr_plld & PLLD_FWDVA_MASK) >> 16);
797
798 /*
Stefan Roese273db7e2007-08-13 09:05:33 +0200799 * Determine forward divider B
Stefan Roesee01bd212007-03-21 13:38:59 +0100800 */
801 sysInfo->pllFwdDivB = ((cpr_plld & PLLD_FWDVB_MASK) >> 8);
Stefan Roese273db7e2007-08-13 09:05:33 +0200802 if (sysInfo->pllFwdDivB == 0)
Stefan Roesee01bd212007-03-21 13:38:59 +0100803 sysInfo->pllFwdDivB = 8;
Stefan Roesee01bd212007-03-21 13:38:59 +0100804
805 /*
806 * Determine FBK_DIV.
807 */
808 sysInfo->pllFbkDiv = ((cpr_plld & PLLD_FBDV_MASK) >> 24);
Stefan Roese273db7e2007-08-13 09:05:33 +0200809 if (sysInfo->pllFbkDiv == 0)
Stefan Roesee01bd212007-03-21 13:38:59 +0100810 sysInfo->pllFbkDiv = 256;
Stefan Roesee01bd212007-03-21 13:38:59 +0100811
812 /*
813 * Read CPR_PRIMAD register
814 */
815 mfcpr(cprprimad, cpr_primad);
Stefan Roesefa8aea22007-10-22 07:33:52 +0200816
Stefan Roesee01bd212007-03-21 13:38:59 +0100817 /*
818 * Determine PLB_DIV.
819 */
820 sysInfo->pllPlbDiv = ((cpr_primad & PRIMAD_PLBDV_MASK) >> 16);
Stefan Roese273db7e2007-08-13 09:05:33 +0200821 if (sysInfo->pllPlbDiv == 0)
Stefan Roesee01bd212007-03-21 13:38:59 +0100822 sysInfo->pllPlbDiv = 16;
Stefan Roesee01bd212007-03-21 13:38:59 +0100823
824 /*
825 * Determine EXTBUS_DIV.
826 */
827 sysInfo->pllExtBusDiv = (cpr_primad & PRIMAD_EBCDV_MASK);
Stefan Roese273db7e2007-08-13 09:05:33 +0200828 if (sysInfo->pllExtBusDiv == 0)
Stefan Roesee01bd212007-03-21 13:38:59 +0100829 sysInfo->pllExtBusDiv = 16;
Stefan Roesee01bd212007-03-21 13:38:59 +0100830
831 /*
832 * Determine OPB_DIV.
833 */
834 sysInfo->pllOpbDiv = ((cpr_primad & PRIMAD_OPBDV_MASK) >> 8);
Stefan Roese273db7e2007-08-13 09:05:33 +0200835 if (sysInfo->pllOpbDiv == 0)
Stefan Roesee01bd212007-03-21 13:38:59 +0100836 sysInfo->pllOpbDiv = 16;
Stefan Roesee01bd212007-03-21 13:38:59 +0100837
838 /*
839 * Determine the M factor
840 */
Stefan Roese273db7e2007-08-13 09:05:33 +0200841 if (cpr_pllc & PLLC_SRC_MASK)
842 m = sysInfo->pllFbkDiv * sysInfo->pllFwdDivB;
843 else
844 m = sysInfo->pllFbkDiv * sysInfo->pllFwdDiv;
Stefan Roesee01bd212007-03-21 13:38:59 +0100845
846 /*
847 * Determine VCO clock frequency
848 */
849 sysInfo->freqVCOHz = (1000000000000LL * (unsigned long long)m) /
850 (unsigned long long)sysClkPeriodPs;
851
852 /*
853 * Determine CPU clock frequency
854 */
855 primad_cpudv = ((cpr_primad & PRIMAD_CPUDV_MASK) >> 24);
Stefan Roese273db7e2007-08-13 09:05:33 +0200856 if (primad_cpudv == 0)
Stefan Roesee01bd212007-03-21 13:38:59 +0100857 primad_cpudv = 16;
Stefan Roesee01bd212007-03-21 13:38:59 +0100858
Stefan Roese273db7e2007-08-13 09:05:33 +0200859 sysInfo->freqProcessor = (CONFIG_SYS_CLK_FREQ * m) /
860 sysInfo->pllFwdDiv / primad_cpudv;
Stefan Roesee01bd212007-03-21 13:38:59 +0100861
862 /*
863 * Determine PLB clock frequency
864 */
Stefan Roese273db7e2007-08-13 09:05:33 +0200865 sysInfo->freqPLB = (CONFIG_SYS_CLK_FREQ * m) /
866 sysInfo->pllFwdDiv / sysInfo->pllPlbDiv;
Stefan Roesedbbd1252007-10-05 17:10:59 +0200867
868 sysInfo->freqEBC = (CONFIG_SYS_CLK_FREQ * sysInfo->pllFbkDiv) /
869 sysInfo->pllExtBusDiv;
Stefan Roesefa8aea22007-10-22 07:33:52 +0200870
871 sysInfo->freqUART = sysInfo->freqVCOHz;
Stefan Roesee01bd212007-03-21 13:38:59 +0100872}
873
874/********************************************
875 * get_OPB_freq
876 * return OPB bus freq in Hz
877 *********************************************/
878ulong get_OPB_freq (void)
879{
880 ulong val = 0;
881
Stefan Roese087dfdb2007-10-21 08:12:41 +0200882 PPC4xx_SYS_INFO sys_info;
Stefan Roesee01bd212007-03-21 13:38:59 +0100883
884 get_sys_info (&sys_info);
885 val = (CONFIG_SYS_CLK_FREQ * sys_info.pllFbkDiv) / sys_info.pllOpbDiv;
886
887 return val;
888}
889
Stefan Roesedbbd1252007-10-05 17:10:59 +0200890#elif defined(CONFIG_405EX)
891
892/*
893 * TODO: We need to get the CPR registers and calculate these values correctly!!!!
894 * We need the specs!!!!
895 */
896static unsigned char get_fbdv(unsigned char index)
897{
898 unsigned char ret = 0;
899 /* This is table should be 256 bytes.
900 * Only take first 52 values.
901 */
902 unsigned char fbdv_tb[] = {
903 0x00, 0xff, 0x7f, 0xfd,
904 0x7a, 0xf5, 0x6a, 0xd5,
905 0x2a, 0xd4, 0x29, 0xd3,
906 0x26, 0xcc, 0x19, 0xb3,
907 0x67, 0xce, 0x1d, 0xbb,
908 0x77, 0xee, 0x5d, 0xba,
909 0x74, 0xe9, 0x52, 0xa5,
910 0x4b, 0x96, 0x2c, 0xd8,
911 0x31, 0xe3, 0x46, 0x8d,
912 0x1b, 0xb7, 0x6f, 0xde,
913 0x3d, 0xfb, 0x76, 0xed,
914 0x5a, 0xb5, 0x6b, 0xd6,
915 0x2d, 0xdb, 0x36, 0xec,
916
917 };
918
919 if ((index & 0x7f) == 0)
920 return 1;
921 while (ret < sizeof (fbdv_tb)) {
922 if (fbdv_tb[ret] == index)
923 break;
924 ret++;
925 }
926 ret++;
927
928 return ret;
929}
930
931#define PLL_FBK_PLL_LOCAL 0
932#define PLL_FBK_CPU 1
933#define PLL_FBK_PERCLK 5
934
935void get_sys_info (sys_info_t * sysInfo)
936{
937 unsigned long sysClkPeriodPs = ONE_BILLION / (CONFIG_SYS_CLK_FREQ / 1000);
938 unsigned long m = 1;
939 unsigned int tmp;
940 unsigned char fwdva[16] = {
941 1, 2, 14, 9, 4, 11, 16, 13,
942 12, 5, 6, 15, 10, 7, 8, 3,
943 };
944 unsigned char sel, cpudv0, plb2xDiv;
945
946 mfcpr(cpr0_plld, tmp);
947
948 /*
949 * Determine forward divider A
950 */
951 sysInfo->pllFwdDiv = fwdva[((tmp >> 16) & 0x0f)]; /* FWDVA */
952
953 /*
954 * Determine FBK_DIV.
955 */
956 sysInfo->pllFbkDiv = get_fbdv(((tmp >> 24) & 0x0ff)); /* FBDV */
957
958 /*
959 * Determine PLBDV0
960 */
961 sysInfo->pllPlbDiv = 2;
962
963 /*
964 * Determine PERDV0
965 */
966 mfcpr(cpr0_perd, tmp);
967 tmp = (tmp >> 24) & 0x03;
968 sysInfo->pllExtBusDiv = (tmp == 0) ? 4 : tmp;
969
970 /*
971 * Determine OPBDV0
972 */
973 mfcpr(cpr0_opbd, tmp);
974 tmp = (tmp >> 24) & 0x03;
975 sysInfo->pllOpbDiv = (tmp == 0) ? 4 : tmp;
976
977 /* Determine PLB2XDV0 */
978 mfcpr(cpr0_plbd, tmp);
979 tmp = (tmp >> 16) & 0x07;
980 plb2xDiv = (tmp == 0) ? 8 : tmp;
981
982 /* Determine CPUDV0 */
983 mfcpr(cpr0_cpud, tmp);
984 tmp = (tmp >> 24) & 0x07;
985 cpudv0 = (tmp == 0) ? 8 : tmp;
986
987 /* Determine SEL(5:7) in CPR0_PLLC */
988 mfcpr(cpr0_pllc, tmp);
989 sel = (tmp >> 24) & 0x07;
990
991 /*
992 * Determine the M factor
993 * PLL local: M = FBDV
994 * CPU clock: M = FBDV * FWDVA * CPUDV0
995 * PerClk : M = FBDV * FWDVA * PLB2XDV0 * PLBDV0(2) * OPBDV0 * PERDV0
996 *
997 */
998 switch (sel) {
999 case PLL_FBK_CPU:
1000 m = sysInfo->pllFwdDiv * cpudv0;
1001 break;
1002 case PLL_FBK_PERCLK:
1003 m = sysInfo->pllFwdDiv * plb2xDiv * 2
1004 * sysInfo->pllOpbDiv * sysInfo->pllExtBusDiv;
1005 break;
1006 case PLL_FBK_PLL_LOCAL:
1007 break;
1008 default:
1009 printf("%s unknown m\n", __FUNCTION__);
1010 return;
1011
1012 }
1013 m *= sysInfo->pllFbkDiv;
1014
1015 /*
1016 * Determine VCO clock frequency
1017 */
1018 sysInfo->freqVCOHz = (1000000000000LL * (unsigned long long)m) /
1019 (unsigned long long)sysClkPeriodPs;
1020
1021 /*
1022 * Determine CPU clock frequency
1023 */
1024 sysInfo->freqProcessor = sysInfo->freqVCOHz / (sysInfo->pllFwdDiv * cpudv0);
1025
1026 /*
1027 * Determine PLB clock frequency, ddr1x should be the same
1028 */
1029 sysInfo->freqPLB = sysInfo->freqVCOHz / (sysInfo->pllFwdDiv * plb2xDiv * 2);
1030 sysInfo->freqOPB = sysInfo->freqPLB/sysInfo->pllOpbDiv;
1031 sysInfo->freqDDR = sysInfo->freqPLB;
1032 sysInfo->freqEBC = sysInfo->freqOPB / sysInfo->pllExtBusDiv;
Stefan Roesefa8aea22007-10-22 07:33:52 +02001033 sysInfo->freqUART = sysInfo->freqPLB;
Stefan Roesedbbd1252007-10-05 17:10:59 +02001034}
1035
1036/********************************************
1037 * get_OPB_freq
1038 * return OPB bus freq in Hz
1039 *********************************************/
1040ulong get_OPB_freq (void)
1041{
1042 ulong val = 0;
1043
Stefan Roese087dfdb2007-10-21 08:12:41 +02001044 PPC4xx_SYS_INFO sys_info;
Stefan Roesedbbd1252007-10-05 17:10:59 +02001045
1046 get_sys_info (&sys_info);
1047 val = sys_info.freqPLB / sys_info.pllOpbDiv;
1048
1049 return val;
1050}
1051
wdenkc6097192002-11-03 00:24:07 +00001052#endif
1053
1054int get_clocks (void)
1055{
Stefan Roesee01bd212007-03-21 13:38:59 +01001056#if defined(CONFIG_405GP) || defined(CONFIG_405CR) || \
1057 defined(CONFIG_405EP) || defined(CONFIG_405EZ) || \
Stefan Roesedbbd1252007-10-05 17:10:59 +02001058 defined(CONFIG_405EX) || defined(CONFIG_405) || \
1059 defined(CONFIG_440)
wdenkc6097192002-11-03 00:24:07 +00001060 sys_info_t sys_info;
1061
1062 get_sys_info (&sys_info);
1063 gd->cpu_clk = sys_info.freqProcessor;
1064 gd->bus_clk = sys_info.freqPLB;
1065
1066#endif /* defined(CONFIG_405GP) || defined(CONFIG_405CR) */
1067
1068#ifdef CONFIG_IOP480
wdenkc6097192002-11-03 00:24:07 +00001069 gd->cpu_clk = 66000000;
1070 gd->bus_clk = 66000000;
1071#endif
1072 return (0);
1073}
1074
1075
1076/********************************************
1077 * get_bus_freq
1078 * return PLB bus freq in Hz
1079 *********************************************/
1080ulong get_bus_freq (ulong dummy)
1081{
1082 ulong val;
1083
Stefan Roesee01bd212007-03-21 13:38:59 +01001084#if defined(CONFIG_405GP) || defined(CONFIG_405CR) || \
1085 defined(CONFIG_405EP) || defined(CONFIG_405EZ) || \
Stefan Roesedbbd1252007-10-05 17:10:59 +02001086 defined(CONFIG_405EX) || defined(CONFIG_405) || \
1087 defined(CONFIG_440)
wdenkc6097192002-11-03 00:24:07 +00001088 sys_info_t sys_info;
1089
1090 get_sys_info (&sys_info);
1091 val = sys_info.freqPLB;
1092
1093#elif defined(CONFIG_IOP480)
1094
1095 val = 66;
1096
1097#else
1098# error get_bus_freq() not implemented
1099#endif
1100
1101 return val;
1102}