uboot/arch/powerpc/cpu/mpc85xx/speed.c
<<
>>
Prefs
   1/*
   2 * Copyright 2004, 2007-2011 Freescale Semiconductor, Inc.
   3 *
   4 * (C) Copyright 2003 Motorola Inc.
   5 * Xianghua Xiao, (X.Xiao@motorola.com)
   6 *
   7 * (C) Copyright 2000
   8 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
   9 *
  10 * See file CREDITS for list of people who contributed to this
  11 * project.
  12 *
  13 * This program is free software; you can redistribute it and/or
  14 * modify it under the terms of the GNU General Public License as
  15 * published by the Free Software Foundation; either version 2 of
  16 * the License, or (at your option) any later version.
  17 *
  18 * This program is distributed in the hope that it will be useful,
  19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  21 * GNU General Public License for more details.
  22 *
  23 * You should have received a copy of the GNU General Public License
  24 * along with this program; if not, write to the Free Software
  25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  26 * MA 02111-1307 USA
  27 */
  28
  29#include <common.h>
  30#include <ppc_asm.tmpl>
  31#include <linux/compiler.h>
  32#include <asm/processor.h>
  33#include <asm/io.h>
  34
  35DECLARE_GLOBAL_DATA_PTR;
  36
  37/* --------------------------------------------------------------- */
  38
  39void get_sys_info (sys_info_t * sysInfo)
  40{
  41        volatile ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
  42#ifdef CONFIG_FSL_IFC
  43        struct fsl_ifc *ifc_regs = (void *)CONFIG_SYS_IFC_ADDR;
  44        u32 ccr;
  45#endif
  46#ifdef CONFIG_FSL_CORENET
  47        volatile ccsr_clk_t *clk = (void *)(CONFIG_SYS_FSL_CORENET_CLK_ADDR);
  48        unsigned int cpu;
  49
  50        const u8 core_cplx_PLL[16] = {
  51                [ 0] = 0,       /* CC1 PPL / 1 */
  52                [ 1] = 0,       /* CC1 PPL / 2 */
  53                [ 2] = 0,       /* CC1 PPL / 4 */
  54                [ 4] = 1,       /* CC2 PPL / 1 */
  55                [ 5] = 1,       /* CC2 PPL / 2 */
  56                [ 6] = 1,       /* CC2 PPL / 4 */
  57                [ 8] = 2,       /* CC3 PPL / 1 */
  58                [ 9] = 2,       /* CC3 PPL / 2 */
  59                [10] = 2,       /* CC3 PPL / 4 */
  60                [12] = 3,       /* CC4 PPL / 1 */
  61                [13] = 3,       /* CC4 PPL / 2 */
  62                [14] = 3,       /* CC4 PPL / 4 */
  63        };
  64
  65        const u8 core_cplx_PLL_div[16] = {
  66                [ 0] = 1,       /* CC1 PPL / 1 */
  67                [ 1] = 2,       /* CC1 PPL / 2 */
  68                [ 2] = 4,       /* CC1 PPL / 4 */
  69                [ 4] = 1,       /* CC2 PPL / 1 */
  70                [ 5] = 2,       /* CC2 PPL / 2 */
  71                [ 6] = 4,       /* CC2 PPL / 4 */
  72                [ 8] = 1,       /* CC3 PPL / 1 */
  73                [ 9] = 2,       /* CC3 PPL / 2 */
  74                [10] = 4,       /* CC3 PPL / 4 */
  75                [12] = 1,       /* CC4 PPL / 1 */
  76                [13] = 2,       /* CC4 PPL / 2 */
  77                [14] = 4,       /* CC4 PPL / 4 */
  78        };
  79        uint i, freqCC_PLL[6], rcw_tmp;
  80        uint ratio[6];
  81        unsigned long sysclk = CONFIG_SYS_CLK_FREQ;
  82        uint mem_pll_rat;
  83
  84        sysInfo->freqSystemBus = sysclk;
  85#ifdef CONFIG_DDR_CLK_FREQ
  86        sysInfo->freqDDRBus = CONFIG_DDR_CLK_FREQ;
  87#else
  88        sysInfo->freqDDRBus = sysclk;
  89#endif
  90
  91        sysInfo->freqSystemBus *= (in_be32(&gur->rcwsr[0]) >> 25) & 0x1f;
  92        mem_pll_rat = (in_be32(&gur->rcwsr[0]) >>
  93                        FSL_CORENET_RCWSR0_MEM_PLL_RAT_SHIFT)
  94                        & FSL_CORENET_RCWSR0_MEM_PLL_RAT_MASK;
  95        if (mem_pll_rat > 2)
  96                sysInfo->freqDDRBus *= mem_pll_rat;
  97        else
  98                sysInfo->freqDDRBus = sysInfo->freqSystemBus * mem_pll_rat;
  99
 100        ratio[0] = (in_be32(&clk->pllc1gsr) >> 1) & 0x3f;
 101        ratio[1] = (in_be32(&clk->pllc2gsr) >> 1) & 0x3f;
 102        ratio[2] = (in_be32(&clk->pllc3gsr) >> 1) & 0x3f;
 103        ratio[3] = (in_be32(&clk->pllc4gsr) >> 1) & 0x3f;
 104        ratio[4] = (in_be32(&clk->pllc5gsr) >> 1) & 0x3f;
 105        ratio[5] = (in_be32(&clk->pllc6gsr) >> 1) & 0x3f;
 106        for (i = 0; i < 6; i++) {
 107                if (ratio[i] > 4)
 108                        freqCC_PLL[i] = sysclk * ratio[i];
 109                else
 110                        freqCC_PLL[i] = sysInfo->freqSystemBus * ratio[i];
 111        }
 112#ifdef CONFIG_SYS_FSL_QORIQ_CHASSIS2
 113        /*
 114         * Each cluster has up to 4 cores, sharing the same PLL selection.
 115         * The cluster assignment is fixed per SoC. There is no way identify the
 116         * assignment so far, presuming the "first configuration" which is to
 117         * fill the lower cluster group first before moving up to next group.
 118         * PLL1, PLL2, PLL3 are cluster group A, feeding core 0~3 on cluster 1
 119         * and core 4~7 on cluster 2
 120         * PLL4, PLL5, PLL6 are cluster group B, feeding core 8~11 on cluster 3
 121         * and core 12~15 on cluster 4 if existing
 122         */
 123        for_each_cpu(i, cpu, cpu_numcores(), cpu_mask()) {
 124                u32 c_pll_sel = (in_be32(&clk->clkc0csr + (cpu / 4) * 8) >> 27)
 125                                & 0xf;
 126                u32 cplx_pll = core_cplx_PLL[c_pll_sel];
 127                if (cplx_pll > 3)
 128                        printf("Unsupported architecture configuration"
 129                                " in function %s\n", __func__);
 130                cplx_pll += (cpu / 8) * 3;
 131
 132                sysInfo->freqProcessor[cpu] =
 133                         freqCC_PLL[cplx_pll] / core_cplx_PLL_div[c_pll_sel];
 134        }
 135#define PME_CLK_SEL     0xe0000000
 136#define PME_CLK_SHIFT   29
 137#define FM1_CLK_SEL     0x1c000000
 138#define FM1_CLK_SHIFT   26
 139        rcw_tmp = in_be32(&gur->rcwsr[7]);
 140
 141#ifdef CONFIG_SYS_DPAA_PME
 142        switch ((rcw_tmp & PME_CLK_SEL) >> PME_CLK_SHIFT) {
 143        case 1:
 144                sysInfo->freqPME = freqCC_PLL[0];
 145                break;
 146        case 2:
 147                sysInfo->freqPME = freqCC_PLL[0] / 2;
 148                break;
 149        case 3:
 150                sysInfo->freqPME = freqCC_PLL[0] / 3;
 151                break;
 152        case 4:
 153                sysInfo->freqPME = freqCC_PLL[0] / 4;
 154                break;
 155        case 6:
 156                sysInfo->freqPME = freqCC_PLL[1] / 2;
 157                break;
 158        case 7:
 159                sysInfo->freqPME = freqCC_PLL[1] / 3;
 160                break;
 161        default:
 162                printf("Error: Unknown PME clock select!\n");
 163        case 0:
 164                sysInfo->freqPME = sysInfo->freqSystemBus / 2;
 165                break;
 166
 167        }
 168#endif
 169
 170#ifdef CONFIG_SYS_DPAA_QBMAN
 171        sysInfo->freqQMAN = sysInfo->freqSystemBus / 2;
 172#endif
 173
 174#ifdef CONFIG_SYS_DPAA_FMAN
 175        switch ((rcw_tmp & FM1_CLK_SEL) >> FM1_CLK_SHIFT) {
 176        case 1:
 177                sysInfo->freqFMan[0] = freqCC_PLL[3];
 178                break;
 179        case 2:
 180                sysInfo->freqFMan[0] = freqCC_PLL[3] / 2;
 181                break;
 182        case 3:
 183                sysInfo->freqFMan[0] = freqCC_PLL[3] / 3;
 184                break;
 185        case 4:
 186                sysInfo->freqFMan[0] = freqCC_PLL[3] / 4;
 187                break;
 188        case 6:
 189                sysInfo->freqFMan[0] = freqCC_PLL[4] / 2;
 190                break;
 191        case 7:
 192                sysInfo->freqFMan[0] = freqCC_PLL[4] / 3;
 193                break;
 194        default:
 195                printf("Error: Unknown FMan1 clock select!\n");
 196        case 0:
 197                sysInfo->freqFMan[0] = sysInfo->freqSystemBus / 2;
 198                break;
 199        }
 200#if (CONFIG_SYS_NUM_FMAN) == 2
 201#define FM2_CLK_SEL     0x00000038
 202#define FM2_CLK_SHIFT   3
 203        rcw_tmp = in_be32(&gur->rcwsr[15]);
 204        switch ((rcw_tmp & FM2_CLK_SEL) >> FM2_CLK_SHIFT) {
 205        case 1:
 206                sysInfo->freqFMan[1] = freqCC_PLL[4];
 207                break;
 208        case 2:
 209                sysInfo->freqFMan[1] = freqCC_PLL[4] / 2;
 210                break;
 211        case 3:
 212                sysInfo->freqFMan[1] = freqCC_PLL[4] / 3;
 213                break;
 214        case 4:
 215                sysInfo->freqFMan[1] = freqCC_PLL[4] / 4;
 216                break;
 217        case 6:
 218                sysInfo->freqFMan[1] = freqCC_PLL[3] / 2;
 219                break;
 220        case 7:
 221                sysInfo->freqFMan[1] = freqCC_PLL[3] / 3;
 222                break;
 223        default:
 224                printf("Error: Unknown FMan2 clock select!\n");
 225        case 0:
 226                sysInfo->freqFMan[1] = sysInfo->freqSystemBus / 2;
 227                break;
 228        }
 229#endif  /* CONFIG_SYS_NUM_FMAN == 2 */
 230#endif  /* CONFIG_SYS_DPAA_FMAN */
 231
 232#else /* CONFIG_SYS_FSL_QORIQ_CHASSIS2 */
 233
 234        for_each_cpu(i, cpu, cpu_numcores(), cpu_mask()) {
 235                u32 c_pll_sel = (in_be32(&clk->clkc0csr + cpu*8) >> 27) & 0xf;
 236                u32 cplx_pll = core_cplx_PLL[c_pll_sel];
 237
 238                sysInfo->freqProcessor[cpu] =
 239                         freqCC_PLL[cplx_pll] / core_cplx_PLL_div[c_pll_sel];
 240        }
 241#define PME_CLK_SEL     0x80000000
 242#define FM1_CLK_SEL     0x40000000
 243#define FM2_CLK_SEL     0x20000000
 244#define HWA_ASYNC_DIV   0x04000000
 245#if (CONFIG_SYS_FSL_NUM_CC_PLLS == 2)
 246#define HWA_CC_PLL      1
 247#elif (CONFIG_SYS_FSL_NUM_CC_PLLS == 3)
 248#define HWA_CC_PLL      2
 249#elif (CONFIG_SYS_FSL_NUM_CC_PLLS == 4)
 250#define HWA_CC_PLL      2
 251#else
 252#error CONFIG_SYS_FSL_NUM_CC_PLLS not set or unknown case
 253#endif
 254        rcw_tmp = in_be32(&gur->rcwsr[7]);
 255
 256#ifdef CONFIG_SYS_DPAA_PME
 257        if (rcw_tmp & PME_CLK_SEL) {
 258                if (rcw_tmp & HWA_ASYNC_DIV)
 259                        sysInfo->freqPME = freqCC_PLL[HWA_CC_PLL] / 4;
 260                else
 261                        sysInfo->freqPME = freqCC_PLL[HWA_CC_PLL] / 2;
 262        } else {
 263                sysInfo->freqPME = sysInfo->freqSystemBus / 2;
 264        }
 265#endif
 266
 267#ifdef CONFIG_SYS_DPAA_FMAN
 268        if (rcw_tmp & FM1_CLK_SEL) {
 269                if (rcw_tmp & HWA_ASYNC_DIV)
 270                        sysInfo->freqFMan[0] = freqCC_PLL[HWA_CC_PLL] / 4;
 271                else
 272                        sysInfo->freqFMan[0] = freqCC_PLL[HWA_CC_PLL] / 2;
 273        } else {
 274                sysInfo->freqFMan[0] = sysInfo->freqSystemBus / 2;
 275        }
 276#if (CONFIG_SYS_NUM_FMAN) == 2
 277        if (rcw_tmp & FM2_CLK_SEL) {
 278                if (rcw_tmp & HWA_ASYNC_DIV)
 279                        sysInfo->freqFMan[1] = freqCC_PLL[HWA_CC_PLL] / 4;
 280                else
 281                        sysInfo->freqFMan[1] = freqCC_PLL[HWA_CC_PLL] / 2;
 282        } else {
 283                sysInfo->freqFMan[1] = sysInfo->freqSystemBus / 2;
 284        }
 285#endif
 286#endif
 287
 288#endif /* CONFIG_SYS_FSL_QORIQ_CHASSIS2 */
 289
 290#else /* CONFIG_FSL_CORENET */
 291        uint plat_ratio, e500_ratio, half_freqSystemBus;
 292        int i;
 293#ifdef CONFIG_QE
 294        __maybe_unused u32 qe_ratio;
 295#endif
 296
 297        plat_ratio = (gur->porpllsr) & 0x0000003e;
 298        plat_ratio >>= 1;
 299        sysInfo->freqSystemBus = plat_ratio * CONFIG_SYS_CLK_FREQ;
 300
 301        /* Divide before multiply to avoid integer
 302         * overflow for processor speeds above 2GHz */
 303        half_freqSystemBus = sysInfo->freqSystemBus/2;
 304        for (i = 0; i < cpu_numcores(); i++) {
 305                e500_ratio = ((gur->porpllsr) >> (i * 8 + 16)) & 0x3f;
 306                sysInfo->freqProcessor[i] = e500_ratio * half_freqSystemBus;
 307        }
 308
 309        /* Note: freqDDRBus is the MCLK frequency, not the data rate. */
 310        sysInfo->freqDDRBus = sysInfo->freqSystemBus;
 311
 312#ifdef CONFIG_DDR_CLK_FREQ
 313        {
 314                u32 ddr_ratio = ((gur->porpllsr) & MPC85xx_PORPLLSR_DDR_RATIO)
 315                        >> MPC85xx_PORPLLSR_DDR_RATIO_SHIFT;
 316                if (ddr_ratio != 0x7)
 317                        sysInfo->freqDDRBus = ddr_ratio * CONFIG_DDR_CLK_FREQ;
 318        }
 319#endif
 320
 321#ifdef CONFIG_QE
 322#if defined(CONFIG_P1012) || defined(CONFIG_P1021) || defined(CONFIG_P1025)
 323        sysInfo->freqQE =  sysInfo->freqSystemBus;
 324#else
 325        qe_ratio = ((gur->porpllsr) & MPC85xx_PORPLLSR_QE_RATIO)
 326                        >> MPC85xx_PORPLLSR_QE_RATIO_SHIFT;
 327        sysInfo->freqQE = qe_ratio * CONFIG_SYS_CLK_FREQ;
 328#endif
 329#endif
 330
 331#ifdef CONFIG_SYS_DPAA_FMAN
 332                sysInfo->freqFMan[0] = sysInfo->freqSystemBus;
 333#endif
 334
 335#endif /* CONFIG_FSL_CORENET */
 336
 337#if defined(CONFIG_FSL_LBC)
 338        uint lcrr_div;
 339#if defined(CONFIG_SYS_LBC_LCRR)
 340        /* We will program LCRR to this value later */
 341        lcrr_div = CONFIG_SYS_LBC_LCRR & LCRR_CLKDIV;
 342#else
 343        lcrr_div = in_be32(&(LBC_BASE_ADDR)->lcrr) & LCRR_CLKDIV;
 344#endif
 345        if (lcrr_div == 2 || lcrr_div == 4 || lcrr_div == 8) {
 346#if defined(CONFIG_FSL_CORENET)
 347                /* If this is corenet based SoC, bit-representation
 348                 * for four times the clock divider values.
 349                 */
 350                lcrr_div *= 4;
 351#elif !defined(CONFIG_MPC8540) && !defined(CONFIG_MPC8541) && \
 352    !defined(CONFIG_MPC8555) && !defined(CONFIG_MPC8560)
 353                /*
 354                 * Yes, the entire PQ38 family use the same
 355                 * bit-representation for twice the clock divider values.
 356                 */
 357                lcrr_div *= 2;
 358#endif
 359                sysInfo->freqLocalBus = sysInfo->freqSystemBus / lcrr_div;
 360        } else {
 361                /* In case anyone cares what the unknown value is */
 362                sysInfo->freqLocalBus = lcrr_div;
 363        }
 364#endif
 365
 366#if defined(CONFIG_FSL_IFC)
 367        ccr = in_be32(&ifc_regs->ifc_ccr);
 368        ccr = ((ccr & IFC_CCR_CLK_DIV_MASK) >> IFC_CCR_CLK_DIV_SHIFT) + 1;
 369
 370        sysInfo->freqLocalBus = sysInfo->freqSystemBus / ccr;
 371#endif
 372}
 373
 374
 375int get_clocks (void)
 376{
 377        sys_info_t sys_info;
 378#ifdef CONFIG_MPC8544
 379        volatile ccsr_gur_t *gur = (void *) CONFIG_SYS_MPC85xx_GUTS_ADDR;
 380#endif
 381#if defined(CONFIG_CPM2)
 382        volatile ccsr_cpm_t *cpm = (ccsr_cpm_t *)CONFIG_SYS_MPC85xx_CPM_ADDR;
 383        uint sccr, dfbrg;
 384
 385        /* set VCO = 4 * BRG */
 386        cpm->im_cpm_intctl.sccr &= 0xfffffffc;
 387        sccr = cpm->im_cpm_intctl.sccr;
 388        dfbrg = (sccr & SCCR_DFBRG_MSK) >> SCCR_DFBRG_SHIFT;
 389#endif
 390        get_sys_info (&sys_info);
 391        gd->cpu_clk = sys_info.freqProcessor[0];
 392        gd->bus_clk = sys_info.freqSystemBus;
 393        gd->mem_clk = sys_info.freqDDRBus;
 394        gd->lbc_clk = sys_info.freqLocalBus;
 395
 396#ifdef CONFIG_QE
 397        gd->qe_clk = sys_info.freqQE;
 398        gd->brg_clk = gd->qe_clk / 2;
 399#endif
 400        /*
 401         * The base clock for I2C depends on the actual SOC.  Unfortunately,
 402         * there is no pattern that can be used to determine the frequency, so
 403         * the only choice is to look up the actual SOC number and use the value
 404         * for that SOC. This information is taken from application note
 405         * AN2919.
 406         */
 407#if defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || \
 408        defined(CONFIG_MPC8560) || defined(CONFIG_MPC8555)
 409        gd->i2c1_clk = sys_info.freqSystemBus;
 410#elif defined(CONFIG_MPC8544)
 411        /*
 412         * On the 8544, the I2C clock is the same as the SEC clock.  This can be
 413         * either CCB/2 or CCB/3, depending on the value of cfg_sec_freq. See
 414         * 4.4.3.3 of the 8544 RM.  Note that this might actually work for all
 415         * 85xx, but only the 8544 has cfg_sec_freq, so it's unknown if the
 416         * PORDEVSR2_SEC_CFG bit is 0 on all 85xx boards that are not an 8544.
 417         */
 418        if (gur->pordevsr2 & MPC85xx_PORDEVSR2_SEC_CFG)
 419                gd->i2c1_clk = sys_info.freqSystemBus / 3;
 420        else
 421                gd->i2c1_clk = sys_info.freqSystemBus / 2;
 422#else
 423        /* Most 85xx SOCs use CCB/2, so this is the default behavior. */
 424        gd->i2c1_clk = sys_info.freqSystemBus / 2;
 425#endif
 426        gd->i2c2_clk = gd->i2c1_clk;
 427
 428#if defined(CONFIG_FSL_ESDHC)
 429#if defined(CONFIG_MPC8569) || defined(CONFIG_P1010) ||\
 430       defined(CONFIG_P1014)
 431        gd->sdhc_clk = gd->bus_clk;
 432#else
 433        gd->sdhc_clk = gd->bus_clk / 2;
 434#endif
 435#endif /* defined(CONFIG_FSL_ESDHC) */
 436
 437#if defined(CONFIG_CPM2)
 438        gd->vco_out = 2*sys_info.freqSystemBus;
 439        gd->cpm_clk = gd->vco_out / 2;
 440        gd->scc_clk = gd->vco_out / 4;
 441        gd->brg_clk = gd->vco_out / (1 << (2 * (dfbrg + 1)));
 442#endif
 443
 444        if(gd->cpu_clk != 0) return (0);
 445        else return (1);
 446}
 447
 448
 449/********************************************
 450 * get_bus_freq
 451 * return system bus freq in Hz
 452 *********************************************/
 453ulong get_bus_freq (ulong dummy)
 454{
 455        return gd->bus_clk;
 456}
 457
 458/********************************************
 459 * get_ddr_freq
 460 * return ddr bus freq in Hz
 461 *********************************************/
 462ulong get_ddr_freq (ulong dummy)
 463{
 464        return gd->mem_clk;
 465}
 466