blob: 4baee7774c50a976aadb4f38b2ee0a2798d91c15 [file] [log] [blame]
wdenkc6097192002-11-03 00:24:07 +00001/*
Stefan Roesecc019d12008-03-11 15:05:50 +01002 * (C) Copyright 2000-2008
wdenkc6097192002-11-03 00:24:07 +00003 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4 *
Wolfgang Denkd79de1d2013-07-08 09:37:19 +02005 * SPDX-License-Identifier: GPL-2.0+
wdenkc6097192002-11-03 00:24:07 +00006 */
7
8#include <common.h>
9#include <ppc_asm.tmpl>
Stefan Roese247e9d72010-09-09 19:18:00 +020010#include <asm/ppc4xx.h>
wdenkc6097192002-11-03 00:24:07 +000011#include <asm/processor.h>
12
Wolfgang Denk6405a152006-03-31 18:32:53 +020013DECLARE_GLOBAL_DATA_PTR;
wdenkc6097192002-11-03 00:24:07 +000014
15#define ONE_BILLION 1000000000
Marian Balakowicz49d0eee2006-06-30 16:30:46 +020016#ifdef DEBUG
17#define DEBUGF(fmt,args...) printf(fmt ,##args)
18#else
19#define DEBUGF(fmt,args...)
20#endif
wdenkc6097192002-11-03 00:24:07 +000021
Matthias Fuchse54a67f2013-08-07 12:10:38 +020022#if defined(CONFIG_405GP)
wdenkc6097192002-11-03 00:24:07 +000023
Stefan Roeseedd73f22007-10-21 08:12:41 +020024void get_sys_info (PPC4xx_SYS_INFO * sysInfo)
wdenkc6097192002-11-03 00:24:07 +000025{
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 */
Stefan Roese918010a2009-09-09 16:25:29 +020035 pllmr = mfdcr (CPC0_PLLMR);
wdenkc6097192002-11-03 00:24:07 +000036
37 /*
38 * Read Pin Strapping register
39 */
Stefan Roese918010a2009-09-09 16:25:29 +020040 psr = mfdcr (CPC0_PSR);
wdenkc6097192002-11-03 00:24:07 +000041
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 */
stroeseff90f802003-04-04 16:00:33 +000078 if ((pvr & 0xfffffff0) == (PVR_405GPR_RB & 0xfffffff0)) {
wdenkc6097192002-11-03 00:24:07 +000079 /*
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
stroese5d542f12004-12-16 18:13:53 +0000123 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);
wdenkc6097192002-11-03 00:24:07 +0000127 } 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
Wolfgang Denkaf0501a2008-10-19 02:35:50 +0200133 * Note freqVCO is calculated in MHz to avoid errors introduced by rounding.
wdenkc6097192002-11-03 00:24:07 +0000134 */
135 if (sysInfo->pllFwdDiv == 1) {
136 sysInfo->freqProcessor = CONFIG_SYS_CLK_FREQ;
137 sysInfo->freqPLB = CONFIG_SYS_CLK_FREQ / sysInfo->pllPlbDiv;
138 } else {
stroese5d542f12004-12-16 18:13:53 +0000139 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;
wdenkc6097192002-11-03 00:24:07 +0000147 }
148 }
Stefan Roese628d3922007-10-22 07:33:52 +0200149
Stefan Roese11f51692009-09-14 11:13:34 +0200150 sysInfo->freqOPB = sysInfo->freqPLB / sysInfo->pllOpbDiv;
Matthias Fuchs3c70edc2008-04-18 17:24:32 +0200151 sysInfo->freqEBC = sysInfo->freqPLB / sysInfo->pllExtBusDiv;
Stefan Roese628d3922007-10-22 07:33:52 +0200152 sysInfo->freqUART = sysInfo->freqProcessor;
wdenkc6097192002-11-03 00:24:07 +0000153}
154
155
156/********************************************
wdenkc6097192002-11-03 00:24:07 +0000157 * get_PCI_freq
158 * return PCI bus freq in Hz
159 *********************************************/
160ulong get_PCI_freq (void)
161{
162 ulong val;
Stefan Roeseedd73f22007-10-21 08:12:41 +0200163 PPC4xx_SYS_INFO sys_info;
wdenkc6097192002-11-03 00:24:07 +0000164
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)
Stefan Roese326c9712005-08-01 16:41:48 +0200172
Feng Kan224bc962008-07-08 22:47:31 -0700173#if defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
Tirumala Marri95ac4282010-09-28 14:15:14 -0700174 defined(CONFIG_460SX) || defined(CONFIG_APM821XX)
Stefan Roesecc019d12008-03-11 15:05:50 +0100175static 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,
Dave Mitchell05e89742008-05-07 09:00:23 -0700207 0x20, 0xc0, 0x01, 0x83, 0x07, 0x8f, 0x1f, 0xbf, 0x7f, 0xfe,
Stefan Roesecc019d12008-03-11 15:05:50 +0100208 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
Tirumala Marri95ac4282010-09-28 14:15:14 -0700235#if defined(CONFIG_APM821XX)
236
237void get_sys_info(sys_info_t *sysInfo)
238{
239 unsigned long plld;
240 unsigned long temp;
241 unsigned long mul;
242 unsigned long cpudv;
243 unsigned long plb2dv;
244 unsigned long ddr2dv;
245
246 /* Calculate Forward divisor A and Feeback divisor */
247 mfcpr(CPR0_PLLD, plld);
248
249 temp = CPR0_PLLD_FWDVA(plld);
250 sysInfo->pllFwdDivA = get_cpr0_fwdv(temp);
251
252 temp = CPR0_PLLD_FDV(plld);
253 sysInfo->pllFbkDiv = get_cpr0_fbdv(temp);
254
255 /* Calculate OPB clock divisor */
256 mfcpr(CPR0_OPBD, temp);
257 temp = CPR0_OPBD_OPBDV(temp);
258 sysInfo->pllOpbDiv = temp ? temp : 4;
259
260 /* Calculate Peripheral clock divisor */
261 mfcpr(CPR0_PERD, temp);
262 temp = CPR0_PERD_PERDV(temp);
263 sysInfo->pllExtBusDiv = temp ? temp : 4;
264
265 /* Calculate CPU clock divisor */
266 mfcpr(CPR0_CPUD, temp);
267 temp = CPR0_CPUD_CPUDV(temp);
268 cpudv = temp ? temp : 8;
269
270 /* Calculate PLB2 clock divisor */
271 mfcpr(CPR0_PLB2D, temp);
272 temp = CPR0_PLB2D_PLB2DV(temp);
273 plb2dv = temp ? temp : 4;
274
275 /* Calculate DDR2 clock divisor */
276 mfcpr(CPR0_DDR2D, temp);
277 temp = CPR0_DDR2D_DDR2DV(temp);
278 ddr2dv = temp ? temp : 4;
279
280 /* Calculate 'M' based on feedback source */
281 mfcpr(CPR0_PLLC, temp);
282 temp = CPR0_PLLC_SEL(temp);
283 if (temp == 0) {
284 /* PLL internal feedback */
285 mul = sysInfo->pllFbkDiv;
286 } else {
287 /* PLL PerClk feedback */
288 mul = sysInfo->pllFwdDivA * sysInfo->pllFbkDiv * cpudv
289 * plb2dv * 2 * sysInfo->pllOpbDiv *
290 sysInfo->pllExtBusDiv;
291 }
292
293 /* Now calculate the individual clocks */
294 sysInfo->freqVCOMhz = (mul * CONFIG_SYS_CLK_FREQ) + (mul >> 1);
295 sysInfo->freqProcessor = sysInfo->freqVCOMhz /
296 sysInfo->pllFwdDivA / cpudv;
297 sysInfo->freqPLB = sysInfo->freqVCOMhz /
298 sysInfo->pllFwdDivA / cpudv / plb2dv / 2;
299 sysInfo->freqOPB = sysInfo->freqPLB / sysInfo->pllOpbDiv;
300 sysInfo->freqEBC = sysInfo->freqOPB / sysInfo->pllExtBusDiv;
301 sysInfo->freqDDR = sysInfo->freqVCOMhz /
302 sysInfo->pllFwdDivA / cpudv / ddr2dv / 2;
303 sysInfo->freqUART = sysInfo->freqPLB;
304}
305
306#else
Stefan Roesecc019d12008-03-11 15:05:50 +0100307/*
308 * AMCC_TODO: verify this routine against latest EAS, cause stuff changed
309 * with latest EAS
310 */
311void get_sys_info (sys_info_t * sysInfo)
312{
313 unsigned long strp0;
314 unsigned long strp1;
315 unsigned long temp;
316 unsigned long m;
317 unsigned long plbedv0;
318
319 /* Extract configured divisors */
Stefan Roese918010a2009-09-09 16:25:29 +0200320 mfsdr(SDR0_SDSTP0, strp0);
321 mfsdr(SDR0_SDSTP1, strp1);
Stefan Roesecc019d12008-03-11 15:05:50 +0100322
323 temp = ((strp0 & PLLSYS0_FWD_DIV_A_MASK) >> 4);
324 sysInfo->pllFwdDivA = get_cpr0_fwdv(temp);
325
326 temp = (strp0 & PLLSYS0_FWD_DIV_B_MASK);
327 sysInfo->pllFwdDivB = get_cpr0_fwdv(temp);
328
329 temp = (strp0 & PLLSYS0_FB_DIV_MASK) >> 8;
330 sysInfo->pllFbkDiv = get_cpr0_fbdv(temp);
331
332 temp = (strp1 & PLLSYS0_OPB_DIV_MASK) >> 26;
333 sysInfo->pllOpbDiv = temp ? temp : 4;
334
335 /* AMCC_TODO: verify the SDR0_SDSTP1.PERDV0 value sysInfo->pllExtBusDiv */
336 temp = (strp1 & PLLSYS0_PERCLK_DIV_MASK) >> 24;
337 sysInfo->pllExtBusDiv = temp ? temp : 4;
338
339 temp = (strp1 & PLLSYS0_PLBEDV0_DIV_MASK) >> 29;
340 plbedv0 = temp ? temp: 8;
341
342 /* Calculate 'M' based on feedback source */
343 temp = (strp0 & PLLSYS0_SEL_MASK) >> 27;
344 if (temp == 0) {
345 /* PLL internal feedback */
346 m = sysInfo->pllFbkDiv;
347 } else {
348 /* PLL PerClk feedback */
349 m = sysInfo->pllFwdDivA * plbedv0 * sysInfo->pllOpbDiv *
350 sysInfo->pllExtBusDiv;
351 }
352
353 /* Now calculate the individual clocks */
354 sysInfo->freqVCOMhz = (m * CONFIG_SYS_CLK_FREQ) + (m >> 1);
355 sysInfo->freqProcessor = sysInfo->freqVCOMhz/sysInfo->pllFwdDivA;
356 sysInfo->freqPLB = sysInfo->freqVCOMhz / sysInfo->pllFwdDivA / plbedv0;
357 sysInfo->freqOPB = sysInfo->freqPLB / sysInfo->pllOpbDiv;
358 sysInfo->freqEBC = sysInfo->freqOPB / sysInfo->pllExtBusDiv;
359 sysInfo->freqDDR = sysInfo->freqPLB;
360 sysInfo->freqUART = sysInfo->freqPLB;
361
362 return;
363}
Tirumala Marri95ac4282010-09-28 14:15:14 -0700364#endif
Stefan Roesecc019d12008-03-11 15:05:50 +0100365
366#elif defined(CONFIG_440EP) || defined(CONFIG_440GR) || \
Stefan Roese42fbddd2006-09-07 11:51:23 +0200367 defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
Stefan Roese326c9712005-08-01 16:41:48 +0200368void get_sys_info (sys_info_t *sysInfo)
369{
370 unsigned long temp;
371 unsigned long reg;
372 unsigned long lfdiv;
373 unsigned long m;
374 unsigned long prbdv0;
375 /*
376 WARNING: ASSUMES the following:
377 ENG=1
378 PRADV0=1
379 PRBDV0=1
380 */
381
382 /* Decode CPR0_PLLD0 for divisors */
Stefan Roese918010a2009-09-09 16:25:29 +0200383 mfcpr(CPR0_PLLD, reg);
Stefan Roese326c9712005-08-01 16:41:48 +0200384 temp = (reg & PLLD_FWDVA_MASK) >> 16;
385 sysInfo->pllFwdDivA = temp ? temp : 16;
386 temp = (reg & PLLD_FWDVB_MASK) >> 8;
387 sysInfo->pllFwdDivB = temp ? temp: 8 ;
388 temp = (reg & PLLD_FBDV_MASK) >> 24;
389 sysInfo->pllFbkDiv = temp ? temp : 32;
390 lfdiv = reg & PLLD_LFBDV_MASK;
391
Niklaus Giger728bd0a2009-10-04 20:04:20 +0200392 mfcpr(CPR0_OPBD0, reg);
Stefan Roese326c9712005-08-01 16:41:48 +0200393 temp = (reg & OPBDDV_MASK) >> 24;
394 sysInfo->pllOpbDiv = temp ? temp : 4;
395
Stefan Roese918010a2009-09-09 16:25:29 +0200396 mfcpr(CPR0_PERD, reg);
Stefan Roese326c9712005-08-01 16:41:48 +0200397 temp = (reg & PERDV_MASK) >> 24;
398 sysInfo->pllExtBusDiv = temp ? temp : 8;
399
Niklaus Giger728bd0a2009-10-04 20:04:20 +0200400 mfcpr(CPR0_PRIMBD0, reg);
Stefan Roese326c9712005-08-01 16:41:48 +0200401 temp = (reg & PRBDV_MASK) >> 24;
402 prbdv0 = temp ? temp : 8;
403
Stefan Roese918010a2009-09-09 16:25:29 +0200404 mfcpr(CPR0_SPCID, reg);
Stefan Roese326c9712005-08-01 16:41:48 +0200405 temp = (reg & SPCID_MASK) >> 24;
406 sysInfo->pllPciDiv = temp ? temp : 4;
407
408 /* Calculate 'M' based on feedback source */
Stefan Roese918010a2009-09-09 16:25:29 +0200409 mfsdr(SDR0_SDSTP0, reg);
Stefan Roese326c9712005-08-01 16:41:48 +0200410 temp = (reg & PLLSYS0_SEL_MASK) >> 27;
411 if (temp == 0) { /* PLL output */
412 /* Figure which pll to use */
Stefan Roese918010a2009-09-09 16:25:29 +0200413 mfcpr(CPR0_PLLC, reg);
Stefan Roese326c9712005-08-01 16:41:48 +0200414 temp = (reg & PLLC_SRC_MASK) >> 29;
415 if (!temp) /* PLLOUTA */
416 m = sysInfo->pllFbkDiv * lfdiv * sysInfo->pllFwdDivA;
417 else /* PLLOUTB */
418 m = sysInfo->pllFbkDiv * lfdiv * sysInfo->pllFwdDivB;
419 }
420 else if (temp == 1) /* CPU output */
421 m = sysInfo->pllFbkDiv * sysInfo->pllFwdDivA;
422 else /* PerClk */
423 m = sysInfo->pllExtBusDiv * sysInfo->pllOpbDiv * sysInfo->pllFwdDivB;
424
425 /* Now calculate the individual clocks */
426 sysInfo->freqVCOMhz = (m * CONFIG_SYS_CLK_FREQ) + (m>>1);
427 sysInfo->freqProcessor = sysInfo->freqVCOMhz/sysInfo->pllFwdDivA;
428 sysInfo->freqPLB = sysInfo->freqVCOMhz/sysInfo->pllFwdDivB/prbdv0;
429 sysInfo->freqOPB = sysInfo->freqPLB/sysInfo->pllOpbDiv;
Stefan Roese153b3e22007-10-05 17:10:59 +0200430 sysInfo->freqEBC = sysInfo->freqPLB/sysInfo->pllExtBusDiv;
Stefan Roese326c9712005-08-01 16:41:48 +0200431 sysInfo->freqPCI = sysInfo->freqPLB/sysInfo->pllPciDiv;
Stefan Roese628d3922007-10-22 07:33:52 +0200432 sysInfo->freqUART = sysInfo->freqPLB;
Stefan Roese326c9712005-08-01 16:41:48 +0200433
434 /* Figure which timer source to use */
Matthias Fuchs730b2d22009-07-22 17:27:56 +0200435 if (mfspr(SPRN_CCR1) & 0x0080) {
436 /* External Clock, assume same as SYS_CLK */
Stefan Roese326c9712005-08-01 16:41:48 +0200437 temp = sysInfo->freqProcessor / 2; /* Max extern clock speed */
438 if (CONFIG_SYS_CLK_FREQ > temp)
439 sysInfo->freqTmrClk = temp;
440 else
441 sysInfo->freqTmrClk = CONFIG_SYS_CLK_FREQ;
442 }
443 else /* Internal clock */
444 sysInfo->freqTmrClk = sysInfo->freqProcessor;
445}
Stefan Roese628d3922007-10-22 07:33:52 +0200446
Stefan Roese326c9712005-08-01 16:41:48 +0200447/********************************************
448 * get_PCI_freq
449 * return PCI bus freq in Hz
450 *********************************************/
451ulong get_PCI_freq (void)
452{
453 sys_info_t sys_info;
454 get_sys_info (&sys_info);
455 return sys_info.freqPCI;
456}
457
Ricardo Ribalda Delgado95c50202008-07-17 11:44:12 +0200458#elif !defined(CONFIG_440GX) && !defined(CONFIG_440SP) && !defined(CONFIG_440SPE) \
459 && !defined(CONFIG_XILINX_440)
wdenkc6097192002-11-03 00:24:07 +0000460void get_sys_info (sys_info_t * sysInfo)
461{
462 unsigned long strp0;
463 unsigned long temp;
464 unsigned long m;
465
466 /* Extract configured divisors */
Stefan Roese918010a2009-09-09 16:25:29 +0200467 strp0 = mfdcr( CPC0_STRP0 );
wdenkc6097192002-11-03 00:24:07 +0000468 sysInfo->pllFwdDivA = 8 - ((strp0 & PLLSYS0_FWD_DIV_A_MASK) >> 15);
469 sysInfo->pllFwdDivB = 8 - ((strp0 & PLLSYS0_FWD_DIV_B_MASK) >> 12);
470 temp = (strp0 & PLLSYS0_FB_DIV_MASK) >> 18;
471 sysInfo->pllFbkDiv = temp ? temp : 16;
472 sysInfo->pllOpbDiv = 1 + ((strp0 & PLLSYS0_OPB_DIV_MASK) >> 10);
473 sysInfo->pllExtBusDiv = 1 + ((strp0 & PLLSYS0_EPB_DIV_MASK) >> 8);
474
475 /* Calculate 'M' based on feedback source */
476 if( strp0 & PLLSYS0_EXTSL_MASK )
477 m = sysInfo->pllExtBusDiv * sysInfo->pllOpbDiv * sysInfo->pllFwdDivB;
478 else
479 m = sysInfo->pllFbkDiv * sysInfo->pllFwdDivA;
480
481 /* Now calculate the individual clocks */
482 sysInfo->freqVCOMhz = (m * CONFIG_SYS_CLK_FREQ) + (m>>1);
483 sysInfo->freqProcessor = sysInfo->freqVCOMhz/sysInfo->pllFwdDivA;
484 sysInfo->freqPLB = sysInfo->freqVCOMhz/sysInfo->pllFwdDivB;
Stefan Roese326c9712005-08-01 16:41:48 +0200485 if( get_pvr() == PVR_440GP_RB ) /* Rev B divs an extra 2 -- geez! */
486 sysInfo->freqPLB >>= 1;
wdenkc6097192002-11-03 00:24:07 +0000487 sysInfo->freqOPB = sysInfo->freqPLB/sysInfo->pllOpbDiv;
Stefan Roese153b3e22007-10-05 17:10:59 +0200488 sysInfo->freqEBC = sysInfo->freqOPB/sysInfo->pllExtBusDiv;
Stefan Roese628d3922007-10-22 07:33:52 +0200489 sysInfo->freqUART = sysInfo->freqPLB;
wdenkc6097192002-11-03 00:24:07 +0000490}
wdenk544e9732004-02-06 23:19:44 +0000491#else
Ricardo Ribalda Delgado95c50202008-07-17 11:44:12 +0200492
493#if !defined(CONFIG_XILINX_440)
wdenk544e9732004-02-06 23:19:44 +0000494void get_sys_info (sys_info_t * sysInfo)
495{
496 unsigned long strp0;
497 unsigned long strp1;
498 unsigned long temp;
499 unsigned long temp1;
500 unsigned long lfdiv;
501 unsigned long m;
wdenkc35ba4e2004-03-14 22:25:36 +0000502 unsigned long prbdv0;
wdenk544e9732004-02-06 23:19:44 +0000503
Stefan Roesea8856e32007-02-20 10:57:08 +0100504#if defined(CONFIG_YUCCA)
Marian Balakowicz49d0eee2006-06-30 16:30:46 +0200505 unsigned long sys_freq;
506 unsigned long sys_per=0;
507 unsigned long msr;
508 unsigned long pci_clock_per;
509 unsigned long sdr_ddrpll;
510
511 /*-------------------------------------------------------------------------+
512 | Get the system clock period.
513 +-------------------------------------------------------------------------*/
514 sys_per = determine_sysper();
515
516 msr = (mfmsr () & ~(MSR_EE)); /* disable interrupts */
517
518 /*-------------------------------------------------------------------------+
519 | Calculate the system clock speed from the period.
520 +-------------------------------------------------------------------------*/
Stefan Roesea8856e32007-02-20 10:57:08 +0100521 sys_freq = (ONE_BILLION / sys_per) * 1000;
Marian Balakowicz49d0eee2006-06-30 16:30:46 +0200522#endif
523
wdenk544e9732004-02-06 23:19:44 +0000524 /* Extract configured divisors */
Stefan Roese918010a2009-09-09 16:25:29 +0200525 mfsdr( SDR0_SDSTP0,strp0 );
526 mfsdr( SDR0_SDSTP1,strp1 );
wdenk544e9732004-02-06 23:19:44 +0000527
528 temp = ((strp0 & PLLSYS0_FWD_DIV_A_MASK) >> 8);
529 sysInfo->pllFwdDivA = temp ? temp : 16 ;
530 temp = ((strp0 & PLLSYS0_FWD_DIV_B_MASK) >> 5);
531 sysInfo->pllFwdDivB = temp ? temp: 8 ;
532 temp = (strp0 & PLLSYS0_FB_DIV_MASK) >> 12;
533 sysInfo->pllFbkDiv = temp ? temp : 32;
534 temp = (strp0 & PLLSYS0_OPB_DIV_MASK);
535 sysInfo->pllOpbDiv = temp ? temp : 4;
536 temp = (strp1 & PLLSYS1_PERCLK_DIV_MASK) >> 24;
537 sysInfo->pllExtBusDiv = temp ? temp : 4;
wdenk00fe1612004-03-14 00:07:33 +0000538 prbdv0 = (strp0 >> 2) & 0x7;
wdenk544e9732004-02-06 23:19:44 +0000539
540 /* Calculate 'M' based on feedback source */
541 temp = (strp0 & PLLSYS0_SEL_MASK) >> 27;
542 temp1 = (strp1 & PLLSYS1_LF_DIV_MASK) >> 26;
543 lfdiv = temp1 ? temp1 : 64;
544 if (temp == 0) { /* PLL output */
545 /* Figure which pll to use */
546 temp = (strp0 & PLLSYS0_SRC_MASK) >> 30;
547 if (!temp)
548 m = sysInfo->pllFbkDiv * lfdiv * sysInfo->pllFwdDivA;
549 else
550 m = sysInfo->pllFbkDiv * lfdiv * sysInfo->pllFwdDivB;
551 }
552 else if (temp == 1) /* CPU output */
553 m = sysInfo->pllFbkDiv * sysInfo->pllFwdDivA;
554 else /* PerClk */
555 m = sysInfo->pllExtBusDiv * sysInfo->pllOpbDiv * sysInfo->pllFwdDivB;
556
557 /* Now calculate the individual clocks */
Stefan Roesea8856e32007-02-20 10:57:08 +0100558#if defined(CONFIG_YUCCA)
Marian Balakowicz49d0eee2006-06-30 16:30:46 +0200559 sysInfo->freqVCOMhz = (m * sys_freq) ;
560#else
Stefan Roesea8856e32007-02-20 10:57:08 +0100561 sysInfo->freqVCOMhz = (m * CONFIG_SYS_CLK_FREQ) + (m >> 1);
Marian Balakowicz49d0eee2006-06-30 16:30:46 +0200562#endif
wdenk544e9732004-02-06 23:19:44 +0000563 sysInfo->freqProcessor = sysInfo->freqVCOMhz/sysInfo->pllFwdDivA;
wdenk00fe1612004-03-14 00:07:33 +0000564 sysInfo->freqPLB = sysInfo->freqVCOMhz/sysInfo->pllFwdDivB/prbdv0;
wdenk544e9732004-02-06 23:19:44 +0000565 sysInfo->freqOPB = sysInfo->freqPLB/sysInfo->pllOpbDiv;
Stefan Roese153b3e22007-10-05 17:10:59 +0200566 sysInfo->freqEBC = sysInfo->freqOPB/sysInfo->pllExtBusDiv;
wdenk544e9732004-02-06 23:19:44 +0000567
Stefan Roesea8856e32007-02-20 10:57:08 +0100568#if defined(CONFIG_YUCCA)
Marian Balakowicz49d0eee2006-06-30 16:30:46 +0200569 /* Determine PCI Clock Period */
570 pci_clock_per = determine_pci_clock_per();
571 sysInfo->freqPCI = (ONE_BILLION/pci_clock_per) * 1000;
Stefan Roese918010a2009-09-09 16:25:29 +0200572 mfsdr(SDR0_DDR0, sdr_ddrpll);
Marian Balakowicz49d0eee2006-06-30 16:30:46 +0200573 sysInfo->freqDDR = ((sysInfo->freqPLB) * SDR0_DDR0_DDRM_DECODE(sdr_ddrpll));
574#endif
575
Stefan Roese628d3922007-10-22 07:33:52 +0200576 sysInfo->freqUART = sysInfo->freqPLB;
Marian Balakowicz49d0eee2006-06-30 16:30:46 +0200577}
578
579#endif
Ricardo Ribalda Delgado95c50202008-07-17 11:44:12 +0200580#endif /* CONFIG_XILINX_440 */
Marian Balakowicz49d0eee2006-06-30 16:30:46 +0200581
Stefan Roesea8856e32007-02-20 10:57:08 +0100582#if defined(CONFIG_YUCCA)
Marian Balakowicz49d0eee2006-06-30 16:30:46 +0200583unsigned long determine_sysper(void)
584{
585 unsigned int fpga_clocking_reg;
586 unsigned int master_clock_selection;
587 unsigned long master_clock_per = 0;
588 unsigned long fb_div_selection;
589 unsigned int vco_div_reg_value;
590 unsigned long vco_div_selection;
591 unsigned long sys_per = 0;
592 int extClkVal;
593
594 /*-------------------------------------------------------------------------+
595 | Read FPGA reg 0 and reg 1 to get FPGA reg information
596 +-------------------------------------------------------------------------*/
597 fpga_clocking_reg = in16(FPGA_REG16);
598
599
600 /* Determine Master Clock Source Selection */
601 master_clock_selection = fpga_clocking_reg & FPGA_REG16_MASTER_CLK_MASK;
602
603 switch(master_clock_selection) {
604 case FPGA_REG16_MASTER_CLK_66_66:
605 master_clock_per = PERIOD_66_66MHZ;
606 break;
607 case FPGA_REG16_MASTER_CLK_50:
608 master_clock_per = PERIOD_50_00MHZ;
609 break;
610 case FPGA_REG16_MASTER_CLK_33_33:
611 master_clock_per = PERIOD_33_33MHZ;
612 break;
613 case FPGA_REG16_MASTER_CLK_25:
614 master_clock_per = PERIOD_25_00MHZ;
615 break;
616 case FPGA_REG16_MASTER_CLK_EXT:
617 if ((extClkVal==EXTCLK_33_33)
618 && (extClkVal==EXTCLK_50)
619 && (extClkVal==EXTCLK_66_66)
620 && (extClkVal==EXTCLK_83)) {
621 /* calculate master clock period from external clock value */
622 master_clock_per=(ONE_BILLION/extClkVal) * 1000;
623 } else {
624 /* Unsupported */
625 DEBUGF ("%s[%d] *** master clock selection failed ***\n", __FUNCTION__,__LINE__);
626 hang();
627 }
628 break;
629 default:
630 /* Unsupported */
631 DEBUGF ("%s[%d] *** master clock selection failed ***\n", __FUNCTION__,__LINE__);
632 hang();
633 break;
634 }
635
636 /* Determine FB divisors values */
637 if ((fpga_clocking_reg & FPGA_REG16_FB1_DIV_MASK) == FPGA_REG16_FB1_DIV_LOW) {
638 if ((fpga_clocking_reg & FPGA_REG16_FB2_DIV_MASK) == FPGA_REG16_FB2_DIV_LOW)
639 fb_div_selection = FPGA_FB_DIV_6;
640 else
641 fb_div_selection = FPGA_FB_DIV_12;
642 } else {
643 if ((fpga_clocking_reg & FPGA_REG16_FB2_DIV_MASK) == FPGA_REG16_FB2_DIV_LOW)
644 fb_div_selection = FPGA_FB_DIV_10;
645 else
646 fb_div_selection = FPGA_FB_DIV_20;
647 }
648
649 /* Determine VCO divisors values */
650 vco_div_reg_value = fpga_clocking_reg & FPGA_REG16_VCO_DIV_MASK;
651
652 switch(vco_div_reg_value) {
653 case FPGA_REG16_VCO_DIV_4:
654 vco_div_selection = FPGA_VCO_DIV_4;
655 break;
656 case FPGA_REG16_VCO_DIV_6:
657 vco_div_selection = FPGA_VCO_DIV_6;
658 break;
659 case FPGA_REG16_VCO_DIV_8:
660 vco_div_selection = FPGA_VCO_DIV_8;
661 break;
662 case FPGA_REG16_VCO_DIV_10:
663 default:
664 vco_div_selection = FPGA_VCO_DIV_10;
665 break;
666 }
667
668 if (master_clock_selection == FPGA_REG16_MASTER_CLK_EXT) {
669 switch(master_clock_per) {
670 case PERIOD_25_00MHZ:
671 if (fb_div_selection == FPGA_FB_DIV_12) {
672 if (vco_div_selection == FPGA_VCO_DIV_4)
673 sys_per = PERIOD_75_00MHZ;
674 if (vco_div_selection == FPGA_VCO_DIV_6)
675 sys_per = PERIOD_50_00MHZ;
676 }
677 break;
678 case PERIOD_33_33MHZ:
679 if (fb_div_selection == FPGA_FB_DIV_6) {
680 if (vco_div_selection == FPGA_VCO_DIV_4)
681 sys_per = PERIOD_50_00MHZ;
682 if (vco_div_selection == FPGA_VCO_DIV_6)
683 sys_per = PERIOD_33_33MHZ;
684 }
685 if (fb_div_selection == FPGA_FB_DIV_10) {
686 if (vco_div_selection == FPGA_VCO_DIV_4)
687 sys_per = PERIOD_83_33MHZ;
688 if (vco_div_selection == FPGA_VCO_DIV_10)
689 sys_per = PERIOD_33_33MHZ;
690 }
691 if (fb_div_selection == FPGA_FB_DIV_12) {
692 if (vco_div_selection == FPGA_VCO_DIV_4)
693 sys_per = PERIOD_100_00MHZ;
694 if (vco_div_selection == FPGA_VCO_DIV_6)
695 sys_per = PERIOD_66_66MHZ;
696 if (vco_div_selection == FPGA_VCO_DIV_8)
697 sys_per = PERIOD_50_00MHZ;
698 }
699 break;
700 case PERIOD_50_00MHZ:
701 if (fb_div_selection == FPGA_FB_DIV_6) {
702 if (vco_div_selection == FPGA_VCO_DIV_4)
703 sys_per = PERIOD_75_00MHZ;
704 if (vco_div_selection == FPGA_VCO_DIV_6)
705 sys_per = PERIOD_50_00MHZ;
706 }
707 if (fb_div_selection == FPGA_FB_DIV_10) {
708 if (vco_div_selection == FPGA_VCO_DIV_6)
709 sys_per = PERIOD_83_33MHZ;
710 if (vco_div_selection == FPGA_VCO_DIV_10)
711 sys_per = PERIOD_50_00MHZ;
712 }
713 if (fb_div_selection == FPGA_FB_DIV_12) {
714 if (vco_div_selection == FPGA_VCO_DIV_6)
715 sys_per = PERIOD_100_00MHZ;
716 if (vco_div_selection == FPGA_VCO_DIV_8)
717 sys_per = PERIOD_75_00MHZ;
718 }
719 break;
720 case PERIOD_66_66MHZ:
721 if (fb_div_selection == FPGA_FB_DIV_6) {
722 if (vco_div_selection == FPGA_VCO_DIV_4)
723 sys_per = PERIOD_100_00MHZ;
724 if (vco_div_selection == FPGA_VCO_DIV_6)
725 sys_per = PERIOD_66_66MHZ;
726 if (vco_div_selection == FPGA_VCO_DIV_8)
727 sys_per = PERIOD_50_00MHZ;
728 }
729 if (fb_div_selection == FPGA_FB_DIV_10) {
730 if (vco_div_selection == FPGA_VCO_DIV_8)
731 sys_per = PERIOD_83_33MHZ;
732 if (vco_div_selection == FPGA_VCO_DIV_10)
733 sys_per = PERIOD_66_66MHZ;
734 }
735 if (fb_div_selection == FPGA_FB_DIV_12) {
736 if (vco_div_selection == FPGA_VCO_DIV_8)
737 sys_per = PERIOD_100_00MHZ;
738 }
739 break;
740 default:
741 break;
742 }
743
744 if (sys_per == 0) {
745 /* Other combinations are not supported */
746 DEBUGF ("%s[%d] *** sys period compute failed ***\n", __FUNCTION__,__LINE__);
747 hang();
748 }
749 } else {
750 /* calcul system clock without cheking */
751 /* if engineering option clock no check is selected */
752 /* sys_per = master_clock_per * vco_div_selection / fb_div_selection */
753 sys_per = (master_clock_per/fb_div_selection) * vco_div_selection;
754 }
755
756 return(sys_per);
Marian Balakowicz49d0eee2006-06-30 16:30:46 +0200757}
758
759/*-------------------------------------------------------------------------+
760| determine_pci_clock_per.
761+-------------------------------------------------------------------------*/
762unsigned long determine_pci_clock_per(void)
763{
764 unsigned long pci_clock_selection, pci_period;
765
766 /*-------------------------------------------------------------------------+
767 | Read FPGA reg 6 to get PCI 0 FPGA reg information
768 +-------------------------------------------------------------------------*/
769 pci_clock_selection = in16(FPGA_REG16); /* was reg6 averifier */
770
771
772 pci_clock_selection = pci_clock_selection & FPGA_REG16_PCI0_CLK_MASK;
773
774 switch (pci_clock_selection) {
775 case FPGA_REG16_PCI0_CLK_133_33:
776 pci_period = PERIOD_133_33MHZ;
777 break;
778 case FPGA_REG16_PCI0_CLK_100:
779 pci_period = PERIOD_100_00MHZ;
780 break;
781 case FPGA_REG16_PCI0_CLK_66_66:
782 pci_period = PERIOD_66_66MHZ;
783 break;
784 default:
785 pci_period = PERIOD_33_33MHZ;;
786 break;
787 }
788
789 return(pci_period);
wdenk544e9732004-02-06 23:19:44 +0000790}
791#endif
wdenkc6097192002-11-03 00:24:07 +0000792
Michal Simek594c7b52008-06-24 09:54:09 +0200793#elif defined(CONFIG_XILINX_405)
wdenke537b3b2004-02-23 23:54:43 +0000794extern void get_sys_info (sys_info_t * sysInfo);
795extern ulong get_PCI_freq (void);
796
wdenkc6097192002-11-03 00:24:07 +0000797#elif defined(CONFIG_405)
798
Stefan Roese628d3922007-10-22 07:33:52 +0200799void get_sys_info (sys_info_t * sysInfo)
800{
wdenkc6097192002-11-03 00:24:07 +0000801 sysInfo->freqVCOMhz=3125000;
802 sysInfo->freqProcessor=12*1000*1000;
803 sysInfo->freqPLB=50*1000*1000;
804 sysInfo->freqPCI=66*1000*1000;
wdenkc6097192002-11-03 00:24:07 +0000805}
806
stroese434979e2003-05-23 11:18:02 +0000807#elif defined(CONFIG_405EP)
Stefan Roeseedd73f22007-10-21 08:12:41 +0200808void get_sys_info (PPC4xx_SYS_INFO * sysInfo)
stroese434979e2003-05-23 11:18:02 +0000809{
810 unsigned long pllmr0;
811 unsigned long pllmr1;
812 unsigned long sysClkPeriodPs = ONE_BILLION / (CONFIG_SYS_CLK_FREQ / 1000);
813 unsigned long m;
814 unsigned long pllmr0_ccdv;
815
816 /*
817 * Read PLL Mode registers
818 */
Stefan Roese918010a2009-09-09 16:25:29 +0200819 pllmr0 = mfdcr (CPC0_PLLMR0);
820 pllmr1 = mfdcr (CPC0_PLLMR1);
stroese434979e2003-05-23 11:18:02 +0000821
822 /*
823 * Determine forward divider A
824 */
825 sysInfo->pllFwdDiv = 8 - ((pllmr1 & PLLMR1_FWDVA_MASK) >> 16);
826
827 /*
828 * Determine forward divider B (should be equal to A)
829 */
830 sysInfo->pllFwdDivB = 8 - ((pllmr1 & PLLMR1_FWDVB_MASK) >> 12);
831
832 /*
833 * Determine FBK_DIV.
834 */
835 sysInfo->pllFbkDiv = ((pllmr1 & PLLMR1_FBMUL_MASK) >> 20);
Stefan Roese628d3922007-10-22 07:33:52 +0200836 if (sysInfo->pllFbkDiv == 0)
stroese434979e2003-05-23 11:18:02 +0000837 sysInfo->pllFbkDiv = 16;
stroese434979e2003-05-23 11:18:02 +0000838
839 /*
840 * Determine PLB_DIV.
841 */
842 sysInfo->pllPlbDiv = ((pllmr0 & PLLMR0_CPU_TO_PLB_MASK) >> 16) + 1;
843
844 /*
845 * Determine PCI_DIV.
846 */
847 sysInfo->pllPciDiv = (pllmr0 & PLLMR0_PCI_TO_PLB_MASK) + 1;
848
849 /*
850 * Determine EXTBUS_DIV.
851 */
852 sysInfo->pllExtBusDiv = ((pllmr0 & PLLMR0_EXB_TO_PLB_MASK) >> 8) + 2;
853
854 /*
855 * Determine OPB_DIV.
856 */
857 sysInfo->pllOpbDiv = ((pllmr0 & PLLMR0_OPB_TO_PLB_MASK) >> 12) + 1;
858
859 /*
860 * Determine the M factor
861 */
862 m = sysInfo->pllFbkDiv * sysInfo->pllFwdDivB;
863
864 /*
865 * Determine VCO clock frequency
866 */
stroese5d542f12004-12-16 18:13:53 +0000867 sysInfo->freqVCOHz = (1000000000000LL * (unsigned long long)m) /
868 (unsigned long long)sysClkPeriodPs;
stroese434979e2003-05-23 11:18:02 +0000869
870 /*
871 * Determine CPU clock frequency
872 */
873 pllmr0_ccdv = ((pllmr0 & PLLMR0_CPU_DIV_MASK) >> 20) + 1;
874 if (pllmr1 & PLLMR1_SSCS_MASK) {
wdenk99874b42004-07-01 21:40:08 +0000875 /*
876 * This is true if FWDVA == FWDVB:
877 * sysInfo->freqProcessor = (CONFIG_SYS_CLK_FREQ * sysInfo->pllFbkDiv)
878 * / pllmr0_ccdv;
879 */
880 sysInfo->freqProcessor = (CONFIG_SYS_CLK_FREQ * sysInfo->pllFbkDiv * sysInfo->pllFwdDivB)
881 / sysInfo->pllFwdDiv / pllmr0_ccdv;
stroese434979e2003-05-23 11:18:02 +0000882 } else {
883 sysInfo->freqProcessor = CONFIG_SYS_CLK_FREQ / pllmr0_ccdv;
884 }
885
886 /*
887 * Determine PLB clock frequency
888 */
889 sysInfo->freqPLB = sysInfo->freqProcessor / sysInfo->pllPlbDiv;
Stefan Roese153b3e22007-10-05 17:10:59 +0200890
891 sysInfo->freqEBC = sysInfo->freqPLB / sysInfo->pllExtBusDiv;
Stefan Roese628d3922007-10-22 07:33:52 +0200892
Dirk Eibach14857e82009-07-10 14:47:32 +0200893 sysInfo->freqOPB = sysInfo->freqPLB / sysInfo->pllOpbDiv;
894
Stefan Roese628d3922007-10-22 07:33:52 +0200895 sysInfo->freqUART = sysInfo->freqProcessor * pllmr0_ccdv;
stroese434979e2003-05-23 11:18:02 +0000896}
897
898
899/********************************************
stroese434979e2003-05-23 11:18:02 +0000900 * get_PCI_freq
901 * return PCI bus freq in Hz
902 *********************************************/
903ulong get_PCI_freq (void)
904{
905 ulong val;
Stefan Roeseedd73f22007-10-21 08:12:41 +0200906 PPC4xx_SYS_INFO sys_info;
stroese434979e2003-05-23 11:18:02 +0000907
908 get_sys_info (&sys_info);
909 val = sys_info.freqPLB / sys_info.pllPciDiv;
910 return val;
911}
912
Stefan Roese17ffbc82007-03-21 13:38:59 +0100913#elif defined(CONFIG_405EZ)
Stefan Roeseedd73f22007-10-21 08:12:41 +0200914void get_sys_info (PPC4xx_SYS_INFO * sysInfo)
Stefan Roese17ffbc82007-03-21 13:38:59 +0100915{
916 unsigned long cpr_plld;
Stefan Roese87476ba2007-08-13 09:05:33 +0200917 unsigned long cpr_pllc;
Stefan Roese17ffbc82007-03-21 13:38:59 +0100918 unsigned long cpr_primad;
919 unsigned long sysClkPeriodPs = ONE_BILLION / (CONFIG_SYS_CLK_FREQ/1000);
920 unsigned long primad_cpudv;
921 unsigned long m;
Stefan Roese17b2d592009-09-11 17:07:55 +0200922 unsigned long plloutb;
Stefan Roese17ffbc82007-03-21 13:38:59 +0100923
924 /*
925 * Read PLL Mode registers
926 */
Stefan Roese918010a2009-09-09 16:25:29 +0200927 mfcpr(CPR0_PLLD, cpr_plld);
928 mfcpr(CPR0_PLLC, cpr_pllc);
Stefan Roese17ffbc82007-03-21 13:38:59 +0100929
930 /*
931 * Determine forward divider A
932 */
933 sysInfo->pllFwdDiv = ((cpr_plld & PLLD_FWDVA_MASK) >> 16);
934
935 /*
Stefan Roese87476ba2007-08-13 09:05:33 +0200936 * Determine forward divider B
Stefan Roese17ffbc82007-03-21 13:38:59 +0100937 */
938 sysInfo->pllFwdDivB = ((cpr_plld & PLLD_FWDVB_MASK) >> 8);
Stefan Roese87476ba2007-08-13 09:05:33 +0200939 if (sysInfo->pllFwdDivB == 0)
Stefan Roese17ffbc82007-03-21 13:38:59 +0100940 sysInfo->pllFwdDivB = 8;
Stefan Roese17ffbc82007-03-21 13:38:59 +0100941
942 /*
943 * Determine FBK_DIV.
944 */
945 sysInfo->pllFbkDiv = ((cpr_plld & PLLD_FBDV_MASK) >> 24);
Stefan Roese87476ba2007-08-13 09:05:33 +0200946 if (sysInfo->pllFbkDiv == 0)
Stefan Roese17ffbc82007-03-21 13:38:59 +0100947 sysInfo->pllFbkDiv = 256;
Stefan Roese17ffbc82007-03-21 13:38:59 +0100948
949 /*
950 * Read CPR_PRIMAD register
951 */
Stefan Roese8cb251a2010-09-12 06:21:37 +0200952 mfcpr(CPR0_PRIMAD, cpr_primad);
Stefan Roese628d3922007-10-22 07:33:52 +0200953
Stefan Roese17ffbc82007-03-21 13:38:59 +0100954 /*
955 * Determine PLB_DIV.
956 */
957 sysInfo->pllPlbDiv = ((cpr_primad & PRIMAD_PLBDV_MASK) >> 16);
Stefan Roese87476ba2007-08-13 09:05:33 +0200958 if (sysInfo->pllPlbDiv == 0)
Stefan Roese17ffbc82007-03-21 13:38:59 +0100959 sysInfo->pllPlbDiv = 16;
Stefan Roese17ffbc82007-03-21 13:38:59 +0100960
961 /*
962 * Determine EXTBUS_DIV.
963 */
964 sysInfo->pllExtBusDiv = (cpr_primad & PRIMAD_EBCDV_MASK);
Stefan Roese87476ba2007-08-13 09:05:33 +0200965 if (sysInfo->pllExtBusDiv == 0)
Stefan Roese17ffbc82007-03-21 13:38:59 +0100966 sysInfo->pllExtBusDiv = 16;
Stefan Roese17ffbc82007-03-21 13:38:59 +0100967
968 /*
969 * Determine OPB_DIV.
970 */
971 sysInfo->pllOpbDiv = ((cpr_primad & PRIMAD_OPBDV_MASK) >> 8);
Stefan Roese87476ba2007-08-13 09:05:33 +0200972 if (sysInfo->pllOpbDiv == 0)
Stefan Roese17ffbc82007-03-21 13:38:59 +0100973 sysInfo->pllOpbDiv = 16;
Stefan Roese17ffbc82007-03-21 13:38:59 +0100974
975 /*
976 * Determine the M factor
977 */
Stefan Roese87476ba2007-08-13 09:05:33 +0200978 if (cpr_pllc & PLLC_SRC_MASK)
979 m = sysInfo->pllFbkDiv * sysInfo->pllFwdDivB;
980 else
981 m = sysInfo->pllFbkDiv * sysInfo->pllFwdDiv;
Stefan Roese17ffbc82007-03-21 13:38:59 +0100982
983 /*
984 * Determine VCO clock frequency
985 */
986 sysInfo->freqVCOHz = (1000000000000LL * (unsigned long long)m) /
987 (unsigned long long)sysClkPeriodPs;
988
989 /*
990 * Determine CPU clock frequency
991 */
992 primad_cpudv = ((cpr_primad & PRIMAD_CPUDV_MASK) >> 24);
Stefan Roese87476ba2007-08-13 09:05:33 +0200993 if (primad_cpudv == 0)
Stefan Roese17ffbc82007-03-21 13:38:59 +0100994 primad_cpudv = 16;
Stefan Roese17ffbc82007-03-21 13:38:59 +0100995
Stefan Roese87476ba2007-08-13 09:05:33 +0200996 sysInfo->freqProcessor = (CONFIG_SYS_CLK_FREQ * m) /
997 sysInfo->pllFwdDiv / primad_cpudv;
Stefan Roese17ffbc82007-03-21 13:38:59 +0100998
999 /*
1000 * Determine PLB clock frequency
1001 */
Stefan Roese87476ba2007-08-13 09:05:33 +02001002 sysInfo->freqPLB = (CONFIG_SYS_CLK_FREQ * m) /
1003 sysInfo->pllFwdDiv / sysInfo->pllPlbDiv;
Stefan Roese153b3e22007-10-05 17:10:59 +02001004
Stefan Roese11f51692009-09-14 11:13:34 +02001005 sysInfo->freqOPB = (CONFIG_SYS_CLK_FREQ * sysInfo->pllFbkDiv) /
1006 sysInfo->pllOpbDiv;
1007
Stefan Roese153b3e22007-10-05 17:10:59 +02001008 sysInfo->freqEBC = (CONFIG_SYS_CLK_FREQ * sysInfo->pllFbkDiv) /
1009 sysInfo->pllExtBusDiv;
Stefan Roese628d3922007-10-22 07:33:52 +02001010
Stefan Roese17b2d592009-09-11 17:07:55 +02001011 plloutb = ((CONFIG_SYS_CLK_FREQ * ((cpr_pllc & PLLC_SRC_MASK) ?
1012 sysInfo->pllFwdDivB : sysInfo->pllFwdDiv) * sysInfo->pllFbkDiv) /
1013 sysInfo->pllFwdDivB);
1014 sysInfo->freqUART = plloutb;
Stefan Roese17ffbc82007-03-21 13:38:59 +01001015}
1016
Stefan Roese153b3e22007-10-05 17:10:59 +02001017#elif defined(CONFIG_405EX)
1018
1019/*
1020 * TODO: We need to get the CPR registers and calculate these values correctly!!!!
1021 * We need the specs!!!!
1022 */
1023static unsigned char get_fbdv(unsigned char index)
1024{
1025 unsigned char ret = 0;
1026 /* This is table should be 256 bytes.
1027 * Only take first 52 values.
1028 */
1029 unsigned char fbdv_tb[] = {
1030 0x00, 0xff, 0x7f, 0xfd,
1031 0x7a, 0xf5, 0x6a, 0xd5,
1032 0x2a, 0xd4, 0x29, 0xd3,
1033 0x26, 0xcc, 0x19, 0xb3,
1034 0x67, 0xce, 0x1d, 0xbb,
1035 0x77, 0xee, 0x5d, 0xba,
1036 0x74, 0xe9, 0x52, 0xa5,
1037 0x4b, 0x96, 0x2c, 0xd8,
1038 0x31, 0xe3, 0x46, 0x8d,
1039 0x1b, 0xb7, 0x6f, 0xde,
1040 0x3d, 0xfb, 0x76, 0xed,
1041 0x5a, 0xb5, 0x6b, 0xd6,
1042 0x2d, 0xdb, 0x36, 0xec,
1043
1044 };
1045
1046 if ((index & 0x7f) == 0)
1047 return 1;
1048 while (ret < sizeof (fbdv_tb)) {
1049 if (fbdv_tb[ret] == index)
1050 break;
1051 ret++;
1052 }
1053 ret++;
1054
1055 return ret;
1056}
1057
1058#define PLL_FBK_PLL_LOCAL 0
1059#define PLL_FBK_CPU 1
1060#define PLL_FBK_PERCLK 5
1061
1062void get_sys_info (sys_info_t * sysInfo)
1063{
1064 unsigned long sysClkPeriodPs = ONE_BILLION / (CONFIG_SYS_CLK_FREQ / 1000);
1065 unsigned long m = 1;
1066 unsigned int tmp;
1067 unsigned char fwdva[16] = {
1068 1, 2, 14, 9, 4, 11, 16, 13,
1069 12, 5, 6, 15, 10, 7, 8, 3,
1070 };
1071 unsigned char sel, cpudv0, plb2xDiv;
1072
Stefan Roese918010a2009-09-09 16:25:29 +02001073 mfcpr(CPR0_PLLD, tmp);
Stefan Roese153b3e22007-10-05 17:10:59 +02001074
1075 /*
1076 * Determine forward divider A
1077 */
1078 sysInfo->pllFwdDiv = fwdva[((tmp >> 16) & 0x0f)]; /* FWDVA */
1079
1080 /*
1081 * Determine FBK_DIV.
1082 */
1083 sysInfo->pllFbkDiv = get_fbdv(((tmp >> 24) & 0x0ff)); /* FBDV */
1084
1085 /*
1086 * Determine PLBDV0
1087 */
1088 sysInfo->pllPlbDiv = 2;
1089
1090 /*
1091 * Determine PERDV0
1092 */
Stefan Roese918010a2009-09-09 16:25:29 +02001093 mfcpr(CPR0_PERD, tmp);
Stefan Roese153b3e22007-10-05 17:10:59 +02001094 tmp = (tmp >> 24) & 0x03;
1095 sysInfo->pllExtBusDiv = (tmp == 0) ? 4 : tmp;
1096
1097 /*
1098 * Determine OPBDV0
1099 */
Niklaus Giger728bd0a2009-10-04 20:04:20 +02001100 mfcpr(CPR0_OPBD0, tmp);
Stefan Roese153b3e22007-10-05 17:10:59 +02001101 tmp = (tmp >> 24) & 0x03;
1102 sysInfo->pllOpbDiv = (tmp == 0) ? 4 : tmp;
1103
1104 /* Determine PLB2XDV0 */
Stefan Roese918010a2009-09-09 16:25:29 +02001105 mfcpr(CPR0_PLBD, tmp);
Stefan Roese153b3e22007-10-05 17:10:59 +02001106 tmp = (tmp >> 16) & 0x07;
1107 plb2xDiv = (tmp == 0) ? 8 : tmp;
1108
1109 /* Determine CPUDV0 */
Stefan Roese918010a2009-09-09 16:25:29 +02001110 mfcpr(CPR0_CPUD, tmp);
Stefan Roese153b3e22007-10-05 17:10:59 +02001111 tmp = (tmp >> 24) & 0x07;
1112 cpudv0 = (tmp == 0) ? 8 : tmp;
1113
1114 /* Determine SEL(5:7) in CPR0_PLLC */
Stefan Roese918010a2009-09-09 16:25:29 +02001115 mfcpr(CPR0_PLLC, tmp);
Stefan Roese153b3e22007-10-05 17:10:59 +02001116 sel = (tmp >> 24) & 0x07;
1117
1118 /*
1119 * Determine the M factor
1120 * PLL local: M = FBDV
1121 * CPU clock: M = FBDV * FWDVA * CPUDV0
1122 * PerClk : M = FBDV * FWDVA * PLB2XDV0 * PLBDV0(2) * OPBDV0 * PERDV0
1123 *
1124 */
1125 switch (sel) {
1126 case PLL_FBK_CPU:
1127 m = sysInfo->pllFwdDiv * cpudv0;
1128 break;
1129 case PLL_FBK_PERCLK:
1130 m = sysInfo->pllFwdDiv * plb2xDiv * 2
1131 * sysInfo->pllOpbDiv * sysInfo->pllExtBusDiv;
1132 break;
Wolfgang Denka1be4762008-05-20 16:00:29 +02001133 case PLL_FBK_PLL_LOCAL:
Stefan Roese153b3e22007-10-05 17:10:59 +02001134 break;
1135 default:
1136 printf("%s unknown m\n", __FUNCTION__);
1137 return;
1138
1139 }
1140 m *= sysInfo->pllFbkDiv;
1141
1142 /*
1143 * Determine VCO clock frequency
1144 */
1145 sysInfo->freqVCOHz = (1000000000000LL * (unsigned long long)m) /
1146 (unsigned long long)sysClkPeriodPs;
1147
1148 /*
1149 * Determine CPU clock frequency
1150 */
1151 sysInfo->freqProcessor = sysInfo->freqVCOHz / (sysInfo->pllFwdDiv * cpudv0);
1152
1153 /*
1154 * Determine PLB clock frequency, ddr1x should be the same
1155 */
1156 sysInfo->freqPLB = sysInfo->freqVCOHz / (sysInfo->pllFwdDiv * plb2xDiv * 2);
1157 sysInfo->freqOPB = sysInfo->freqPLB/sysInfo->pllOpbDiv;
1158 sysInfo->freqDDR = sysInfo->freqPLB;
1159 sysInfo->freqEBC = sysInfo->freqOPB / sysInfo->pllExtBusDiv;
Stefan Roese628d3922007-10-22 07:33:52 +02001160 sysInfo->freqUART = sysInfo->freqPLB;
Stefan Roese153b3e22007-10-05 17:10:59 +02001161}
1162
wdenkc6097192002-11-03 00:24:07 +00001163#endif
1164
1165int get_clocks (void)
1166{
wdenkc6097192002-11-03 00:24:07 +00001167 sys_info_t sys_info;
1168
1169 get_sys_info (&sys_info);
1170 gd->cpu_clk = sys_info.freqProcessor;
1171 gd->bus_clk = sys_info.freqPLB;
1172
wdenkc6097192002-11-03 00:24:07 +00001173 return (0);
1174}
1175
1176
1177/********************************************
1178 * get_bus_freq
1179 * return PLB bus freq in Hz
1180 *********************************************/
1181ulong get_bus_freq (ulong dummy)
1182{
1183 ulong val;
1184
Matthias Fuchse54a67f2013-08-07 12:10:38 +02001185#if defined(CONFIG_405GP) || \
Stefan Roese17ffbc82007-03-21 13:38:59 +01001186 defined(CONFIG_405EP) || defined(CONFIG_405EZ) || \
Stefan Roese153b3e22007-10-05 17:10:59 +02001187 defined(CONFIG_405EX) || defined(CONFIG_405) || \
1188 defined(CONFIG_440)
wdenkc6097192002-11-03 00:24:07 +00001189 sys_info_t sys_info;
1190
1191 get_sys_info (&sys_info);
1192 val = sys_info.freqPLB;
wdenkc6097192002-11-03 00:24:07 +00001193#else
1194# error get_bus_freq() not implemented
1195#endif
1196
1197 return val;
1198}
Stefan Roese11f51692009-09-14 11:13:34 +02001199
Stefan Roese11f51692009-09-14 11:13:34 +02001200ulong get_OPB_freq (void)
1201{
1202 PPC4xx_SYS_INFO sys_info;
1203
1204 get_sys_info (&sys_info);
1205
1206 return sys_info.freqOPB;
1207}