~ubuntu-branches/ubuntu/maverick/u-boot-omap3/maverick

« back to all changes in this revision

Viewing changes to cpu/ppc4xx/speed.c

  • Committer: Bazaar Package Importer
  • Author(s): Oliver Grawert
  • Date: 2010-03-22 15:06:23 UTC
  • Revision ID: james.westby@ubuntu.com-20100322150623-i21g8rgiyl5dohag
Tags: upstream-2010.3git20100315
ImportĀ upstreamĀ versionĀ 2010.3git20100315

Show diffs side-by-side

added added

removed removed

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