uboot/cpu/ppc4xx/speed.c
<<
>>
Prefs
   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
  29DECLARE_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
  42void 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 *********************************************/
 178ulong 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)
 193static 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
 199u32 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
 210static 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
 242u32 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 */
 257void 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)
 313void 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 *********************************************/
 396ulong 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)
 405void 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)
 439void 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)
 528unsigned 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+-------------------------------------------------------------------------*/
 707unsigned 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)
 739extern void get_sys_info (sys_info_t * sysInfo);
 740extern ulong get_PCI_freq (void);
 741
 742#elif defined(CONFIG_AP1000)
 743void 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
 752void 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)
 761void 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 *********************************************/
 856ulong 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)
 867void 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 */
 976static 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
1015void 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
1118int 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 *********************************************/
1144ulong 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)
1169ulong 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
1178