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