linux/arch/powerpc/boot/4xx.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * Copyright 2007 David Gibson, IBM Corporation.
   4 *
   5 * Based on earlier code:
   6 *   Matt Porter <mporter@kernel.crashing.org>
   7 *   Copyright 2002-2005 MontaVista Software Inc.
   8 *
   9 *   Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
  10 *   Copyright (c) 2003, 2004 Zultys Technologies
  11 *
  12 * Copyright (C) 2009 Wind River Systems, Inc.
  13 *   Updated for supporting PPC405EX on Kilauea.
  14 *   Tiejun Chen <tiejun.chen@windriver.com>
  15 */
  16#include <stddef.h>
  17#include "types.h"
  18#include "string.h"
  19#include "stdio.h"
  20#include "ops.h"
  21#include "reg.h"
  22#include "dcr.h"
  23
  24static unsigned long chip_11_errata(unsigned long memsize)
  25{
  26        unsigned long pvr;
  27
  28        pvr = mfpvr();
  29
  30        switch (pvr & 0xf0000ff0) {
  31                case 0x40000850:
  32                case 0x400008d0:
  33                case 0x200008d0:
  34                        memsize -= 4096;
  35                        break;
  36                default:
  37                        break;
  38        }
  39
  40        return memsize;
  41}
  42
  43/* Read the 4xx SDRAM controller to get size of system memory. */
  44void ibm4xx_sdram_fixup_memsize(void)
  45{
  46        int i;
  47        unsigned long memsize, bank_config;
  48
  49        memsize = 0;
  50        for (i = 0; i < ARRAY_SIZE(sdram_bxcr); i++) {
  51                bank_config = SDRAM0_READ(sdram_bxcr[i]);
  52                if (bank_config & SDRAM_CONFIG_BANK_ENABLE)
  53                        memsize += SDRAM_CONFIG_BANK_SIZE(bank_config);
  54        }
  55
  56        memsize = chip_11_errata(memsize);
  57        dt_fixup_memory(0, memsize);
  58}
  59
  60/* Read the 440SPe MQ controller to get size of system memory. */
  61#define DCRN_MQ0_B0BAS          0x40
  62#define DCRN_MQ0_B1BAS          0x41
  63#define DCRN_MQ0_B2BAS          0x42
  64#define DCRN_MQ0_B3BAS          0x43
  65
  66static u64 ibm440spe_decode_bas(u32 bas)
  67{
  68        u64 base = ((u64)(bas & 0xFFE00000u)) << 2;
  69
  70        /* open coded because I'm paranoid about invalid values */
  71        switch ((bas >> 4) & 0xFFF) {
  72        case 0:
  73                return 0;
  74        case 0xffc:
  75                return base + 0x000800000ull;
  76        case 0xff8:
  77                return base + 0x001000000ull;
  78        case 0xff0:
  79                return base + 0x002000000ull;
  80        case 0xfe0:
  81                return base + 0x004000000ull;
  82        case 0xfc0:
  83                return base + 0x008000000ull;
  84        case 0xf80:
  85                return base + 0x010000000ull;
  86        case 0xf00:
  87                return base + 0x020000000ull;
  88        case 0xe00:
  89                return base + 0x040000000ull;
  90        case 0xc00:
  91                return base + 0x080000000ull;
  92        case 0x800:
  93                return base + 0x100000000ull;
  94        }
  95        printf("Memory BAS value 0x%08x unsupported !\n", bas);
  96        return 0;
  97}
  98
  99void ibm440spe_fixup_memsize(void)
 100{
 101        u64 banktop, memsize = 0;
 102
 103        /* Ultimately, we should directly construct the memory node
 104         * so we are able to handle holes in the memory address space
 105         */
 106        banktop = ibm440spe_decode_bas(mfdcr(DCRN_MQ0_B0BAS));
 107        if (banktop > memsize)
 108                memsize = banktop;
 109        banktop = ibm440spe_decode_bas(mfdcr(DCRN_MQ0_B1BAS));
 110        if (banktop > memsize)
 111                memsize = banktop;
 112        banktop = ibm440spe_decode_bas(mfdcr(DCRN_MQ0_B2BAS));
 113        if (banktop > memsize)
 114                memsize = banktop;
 115        banktop = ibm440spe_decode_bas(mfdcr(DCRN_MQ0_B3BAS));
 116        if (banktop > memsize)
 117                memsize = banktop;
 118
 119        dt_fixup_memory(0, memsize);
 120}
 121
 122
 123/* 4xx DDR1/2 Denali memory controller support */
 124/* DDR0 registers */
 125#define DDR0_02                 2
 126#define DDR0_08                 8
 127#define DDR0_10                 10
 128#define DDR0_14                 14
 129#define DDR0_42                 42
 130#define DDR0_43                 43
 131
 132/* DDR0_02 */
 133#define DDR_START               0x1
 134#define DDR_START_SHIFT         0
 135#define DDR_MAX_CS_REG          0x3
 136#define DDR_MAX_CS_REG_SHIFT    24
 137#define DDR_MAX_COL_REG         0xf
 138#define DDR_MAX_COL_REG_SHIFT   16
 139#define DDR_MAX_ROW_REG         0xf
 140#define DDR_MAX_ROW_REG_SHIFT   8
 141/* DDR0_08 */
 142#define DDR_DDR2_MODE           0x1
 143#define DDR_DDR2_MODE_SHIFT     0
 144/* DDR0_10 */
 145#define DDR_CS_MAP              0x3
 146#define DDR_CS_MAP_SHIFT        8
 147/* DDR0_14 */
 148#define DDR_REDUC               0x1
 149#define DDR_REDUC_SHIFT         16
 150/* DDR0_42 */
 151#define DDR_APIN                0x7
 152#define DDR_APIN_SHIFT          24
 153/* DDR0_43 */
 154#define DDR_COL_SZ              0x7
 155#define DDR_COL_SZ_SHIFT        8
 156#define DDR_BANK8               0x1
 157#define DDR_BANK8_SHIFT         0
 158
 159#define DDR_GET_VAL(val, mask, shift)   (((val) >> (shift)) & (mask))
 160
 161/*
 162 * Some U-Boot versions set the number of chipselects to two
 163 * for Sequoia/Rainier boards while they only have one chipselect
 164 * hardwired. Hardcode the number of chipselects to one
 165 * for sequioa/rainer board models or read the actual value
 166 * from the memory controller register DDR0_10 otherwise.
 167 */
 168static inline u32 ibm4xx_denali_get_cs(void)
 169{
 170        void *devp;
 171        char model[64];
 172        u32 val, cs;
 173
 174        devp = finddevice("/");
 175        if (!devp)
 176                goto read_cs;
 177
 178        if (getprop(devp, "model", model, sizeof(model)) <= 0)
 179                goto read_cs;
 180
 181        model[sizeof(model)-1] = 0;
 182
 183        if (!strcmp(model, "amcc,sequoia") ||
 184            !strcmp(model, "amcc,rainier"))
 185                return 1;
 186
 187read_cs:
 188        /* get CS value */
 189        val = SDRAM0_READ(DDR0_10);
 190
 191        val = DDR_GET_VAL(val, DDR_CS_MAP, DDR_CS_MAP_SHIFT);
 192        cs = 0;
 193        while (val) {
 194                if (val & 0x1)
 195                        cs++;
 196                val = val >> 1;
 197        }
 198        return cs;
 199}
 200
 201void ibm4xx_denali_fixup_memsize(void)
 202{
 203        u32 val, max_cs, max_col, max_row;
 204        u32 cs, col, row, bank, dpath;
 205        unsigned long memsize;
 206
 207        val = SDRAM0_READ(DDR0_02);
 208        if (!DDR_GET_VAL(val, DDR_START, DDR_START_SHIFT))
 209                fatal("DDR controller is not initialized\n");
 210
 211        /* get maximum cs col and row values */
 212        max_cs  = DDR_GET_VAL(val, DDR_MAX_CS_REG, DDR_MAX_CS_REG_SHIFT);
 213        max_col = DDR_GET_VAL(val, DDR_MAX_COL_REG, DDR_MAX_COL_REG_SHIFT);
 214        max_row = DDR_GET_VAL(val, DDR_MAX_ROW_REG, DDR_MAX_ROW_REG_SHIFT);
 215
 216        cs = ibm4xx_denali_get_cs();
 217        if (!cs)
 218                fatal("No memory installed\n");
 219        if (cs > max_cs)
 220                fatal("DDR wrong CS configuration\n");
 221
 222        /* get data path bytes */
 223        val = SDRAM0_READ(DDR0_14);
 224
 225        if (DDR_GET_VAL(val, DDR_REDUC, DDR_REDUC_SHIFT))
 226                dpath = 4; /* 32 bits */
 227        else
 228                dpath = 8; /* 64 bits */
 229
 230        /* get address pins (rows) */
 231        val = SDRAM0_READ(DDR0_42);
 232
 233        row = DDR_GET_VAL(val, DDR_APIN, DDR_APIN_SHIFT);
 234        if (row > max_row)
 235                fatal("DDR wrong APIN configuration\n");
 236        row = max_row - row;
 237
 238        /* get collomn size and banks */
 239        val = SDRAM0_READ(DDR0_43);
 240
 241        col = DDR_GET_VAL(val, DDR_COL_SZ, DDR_COL_SZ_SHIFT);
 242        if (col > max_col)
 243                fatal("DDR wrong COL configuration\n");
 244        col = max_col - col;
 245
 246        if (DDR_GET_VAL(val, DDR_BANK8, DDR_BANK8_SHIFT))
 247                bank = 8; /* 8 banks */
 248        else
 249                bank = 4; /* 4 banks */
 250
 251        memsize = cs * (1 << (col+row)) * bank * dpath;
 252        memsize = chip_11_errata(memsize);
 253        dt_fixup_memory(0, memsize);
 254}
 255
 256#define SPRN_DBCR0_40X 0x3F2
 257#define SPRN_DBCR0_44X 0x134
 258#define DBCR0_RST_SYSTEM 0x30000000
 259
 260void ibm44x_dbcr_reset(void)
 261{
 262        unsigned long tmp;
 263
 264        asm volatile (
 265                "mfspr  %0,%1\n"
 266                "oris   %0,%0,%2@h\n"
 267                "mtspr  %1,%0"
 268                : "=&r"(tmp) : "i"(SPRN_DBCR0_44X), "i"(DBCR0_RST_SYSTEM)
 269                );
 270
 271}
 272
 273void ibm40x_dbcr_reset(void)
 274{
 275        unsigned long tmp;
 276
 277        asm volatile (
 278                "mfspr  %0,%1\n"
 279                "oris   %0,%0,%2@h\n"
 280                "mtspr  %1,%0"
 281                : "=&r"(tmp) : "i"(SPRN_DBCR0_40X), "i"(DBCR0_RST_SYSTEM)
 282                );
 283}
 284
 285#define EMAC_RESET 0x20000000
 286void ibm4xx_quiesce_eth(u32 *emac0, u32 *emac1)
 287{
 288        /* Quiesce the MAL and EMAC(s) since PIBS/OpenBIOS don't
 289         * do this for us
 290         */
 291        if (emac0)
 292                *emac0 = EMAC_RESET;
 293        if (emac1)
 294                *emac1 = EMAC_RESET;
 295
 296        mtdcr(DCRN_MAL0_CFG, MAL_RESET);
 297        while (mfdcr(DCRN_MAL0_CFG) & MAL_RESET)
 298                ; /* loop until reset takes effect */
 299}
 300
 301/* Read 4xx EBC bus bridge registers to get mappings of the peripheral
 302 * banks into the OPB address space */
 303void ibm4xx_fixup_ebc_ranges(const char *ebc)
 304{
 305        void *devp;
 306        u32 bxcr;
 307        u32 ranges[EBC_NUM_BANKS*4];
 308        u32 *p = ranges;
 309        int i;
 310
 311        for (i = 0; i < EBC_NUM_BANKS; i++) {
 312                mtdcr(DCRN_EBC0_CFGADDR, EBC_BXCR(i));
 313                bxcr = mfdcr(DCRN_EBC0_CFGDATA);
 314
 315                if ((bxcr & EBC_BXCR_BU) != EBC_BXCR_BU_OFF) {
 316                        *p++ = i;
 317                        *p++ = 0;
 318                        *p++ = bxcr & EBC_BXCR_BAS;
 319                        *p++ = EBC_BXCR_BANK_SIZE(bxcr);
 320                }
 321        }
 322
 323        devp = finddevice(ebc);
 324        if (! devp)
 325                fatal("Couldn't locate EBC node %s\n\r", ebc);
 326
 327        setprop(devp, "ranges", ranges, (p - ranges) * sizeof(u32));
 328}
 329
 330/* Calculate 440GP clocks */
 331void ibm440gp_fixup_clocks(unsigned int sys_clk, unsigned int ser_clk)
 332{
 333        u32 sys0 = mfdcr(DCRN_CPC0_SYS0);
 334        u32 cr0 = mfdcr(DCRN_CPC0_CR0);
 335        u32 cpu, plb, opb, ebc, tb, uart0, uart1, m;
 336        u32 opdv = CPC0_SYS0_OPDV(sys0);
 337        u32 epdv = CPC0_SYS0_EPDV(sys0);
 338
 339        if (sys0 & CPC0_SYS0_BYPASS) {
 340                /* Bypass system PLL */
 341                cpu = plb = sys_clk;
 342        } else {
 343                if (sys0 & CPC0_SYS0_EXTSL)
 344                        /* PerClk */
 345                        m = CPC0_SYS0_FWDVB(sys0) * opdv * epdv;
 346                else
 347                        /* CPU clock */
 348                        m = CPC0_SYS0_FBDV(sys0) * CPC0_SYS0_FWDVA(sys0);
 349                cpu = sys_clk * m / CPC0_SYS0_FWDVA(sys0);
 350                plb = sys_clk * m / CPC0_SYS0_FWDVB(sys0);
 351        }
 352
 353        opb = plb / opdv;
 354        ebc = opb / epdv;
 355
 356        /* FIXME: Check if this is for all 440GP, or just Ebony */
 357        if ((mfpvr() & 0xf0000fff) == 0x40000440)
 358                /* Rev. B 440GP, use external system clock */
 359                tb = sys_clk;
 360        else
 361                /* Rev. C 440GP, errata force us to use internal clock */
 362                tb = cpu;
 363
 364        if (cr0 & CPC0_CR0_U0EC)
 365                /* External UART clock */
 366                uart0 = ser_clk;
 367        else
 368                /* Internal UART clock */
 369                uart0 = plb / CPC0_CR0_UDIV(cr0);
 370
 371        if (cr0 & CPC0_CR0_U1EC)
 372                /* External UART clock */
 373                uart1 = ser_clk;
 374        else
 375                /* Internal UART clock */
 376                uart1 = plb / CPC0_CR0_UDIV(cr0);
 377
 378        printf("PPC440GP: SysClk = %dMHz (%x)\n\r",
 379               (sys_clk + 500000) / 1000000, sys_clk);
 380
 381        dt_fixup_cpu_clocks(cpu, tb, 0);
 382
 383        dt_fixup_clock("/plb", plb);
 384        dt_fixup_clock("/plb/opb", opb);
 385        dt_fixup_clock("/plb/opb/ebc", ebc);
 386        dt_fixup_clock("/plb/opb/serial@40000200", uart0);
 387        dt_fixup_clock("/plb/opb/serial@40000300", uart1);
 388}
 389
 390#define SPRN_CCR1 0x378
 391
 392static inline u32 __fix_zero(u32 v, u32 def)
 393{
 394        return v ? v : def;
 395}
 396
 397static unsigned int __ibm440eplike_fixup_clocks(unsigned int sys_clk,
 398                                                unsigned int tmr_clk,
 399                                                int per_clk_from_opb)
 400{
 401        /* PLL config */
 402        u32 pllc  = CPR0_READ(DCRN_CPR0_PLLC);
 403        u32 plld  = CPR0_READ(DCRN_CPR0_PLLD);
 404
 405        /* Dividers */
 406        u32 fbdv   = __fix_zero((plld >> 24) & 0x1f, 32);
 407        u32 fwdva  = __fix_zero((plld >> 16) & 0xf, 16);
 408        u32 fwdvb  = __fix_zero((plld >> 8) & 7, 8);
 409        u32 lfbdv  = __fix_zero(plld & 0x3f, 64);
 410        u32 pradv0 = __fix_zero((CPR0_READ(DCRN_CPR0_PRIMAD) >> 24) & 7, 8);
 411        u32 prbdv0 = __fix_zero((CPR0_READ(DCRN_CPR0_PRIMBD) >> 24) & 7, 8);
 412        u32 opbdv0 = __fix_zero((CPR0_READ(DCRN_CPR0_OPBD) >> 24) & 3, 4);
 413        u32 perdv0 = __fix_zero((CPR0_READ(DCRN_CPR0_PERD) >> 24) & 3, 4);
 414
 415        /* Input clocks for primary dividers */
 416        u32 clk_a, clk_b;
 417
 418        /* Resulting clocks */
 419        u32 cpu, plb, opb, ebc, vco;
 420
 421        /* Timebase */
 422        u32 ccr1, tb = tmr_clk;
 423
 424        if (pllc & 0x40000000) {
 425                u32 m;
 426
 427                /* Feedback path */
 428                switch ((pllc >> 24) & 7) {
 429                case 0:
 430                        /* PLLOUTx */
 431                        m = ((pllc & 0x20000000) ? fwdvb : fwdva) * lfbdv;
 432                        break;
 433                case 1:
 434                        /* CPU */
 435                        m = fwdva * pradv0;
 436                        break;
 437                case 5:
 438                        /* PERClk */
 439                        m = fwdvb * prbdv0 * opbdv0 * perdv0;
 440                        break;
 441                default:
 442                        printf("WARNING ! Invalid PLL feedback source !\n");
 443                        goto bypass;
 444                }
 445                m *= fbdv;
 446                vco = sys_clk * m;
 447                clk_a = vco / fwdva;
 448                clk_b = vco / fwdvb;
 449        } else {
 450bypass:
 451                /* Bypass system PLL */
 452                vco = 0;
 453                clk_a = clk_b = sys_clk;
 454        }
 455
 456        cpu = clk_a / pradv0;
 457        plb = clk_b / prbdv0;
 458        opb = plb / opbdv0;
 459        ebc = (per_clk_from_opb ? opb : plb) / perdv0;
 460
 461        /* Figure out timebase.  Either CPU or default TmrClk */
 462        ccr1 = mfspr(SPRN_CCR1);
 463
 464        /* If passed a 0 tmr_clk, force CPU clock */
 465        if (tb == 0) {
 466                ccr1 &= ~0x80u;
 467                mtspr(SPRN_CCR1, ccr1);
 468        }
 469        if ((ccr1 & 0x0080) == 0)
 470                tb = cpu;
 471
 472        dt_fixup_cpu_clocks(cpu, tb, 0);
 473        dt_fixup_clock("/plb", plb);
 474        dt_fixup_clock("/plb/opb", opb);
 475        dt_fixup_clock("/plb/opb/ebc", ebc);
 476
 477        return plb;
 478}
 479
 480static void eplike_fixup_uart_clk(int index, const char *path,
 481                                  unsigned int ser_clk,
 482                                  unsigned int plb_clk)
 483{
 484        unsigned int sdr;
 485        unsigned int clock;
 486
 487        switch (index) {
 488        case 0:
 489                sdr = SDR0_READ(DCRN_SDR0_UART0);
 490                break;
 491        case 1:
 492                sdr = SDR0_READ(DCRN_SDR0_UART1);
 493                break;
 494        case 2:
 495                sdr = SDR0_READ(DCRN_SDR0_UART2);
 496                break;
 497        case 3:
 498                sdr = SDR0_READ(DCRN_SDR0_UART3);
 499                break;
 500        default:
 501                return;
 502        }
 503
 504        if (sdr & 0x00800000u)
 505                clock = ser_clk;
 506        else
 507                clock = plb_clk / __fix_zero(sdr & 0xff, 256);
 508
 509        dt_fixup_clock(path, clock);
 510}
 511
 512void ibm440ep_fixup_clocks(unsigned int sys_clk,
 513                           unsigned int ser_clk,
 514                           unsigned int tmr_clk)
 515{
 516        unsigned int plb_clk = __ibm440eplike_fixup_clocks(sys_clk, tmr_clk, 0);
 517
 518        /* serial clocks need fixup based on int/ext */
 519        eplike_fixup_uart_clk(0, "/plb/opb/serial@ef600300", ser_clk, plb_clk);
 520        eplike_fixup_uart_clk(1, "/plb/opb/serial@ef600400", ser_clk, plb_clk);
 521        eplike_fixup_uart_clk(2, "/plb/opb/serial@ef600500", ser_clk, plb_clk);
 522        eplike_fixup_uart_clk(3, "/plb/opb/serial@ef600600", ser_clk, plb_clk);
 523}
 524
 525void ibm440gx_fixup_clocks(unsigned int sys_clk,
 526                           unsigned int ser_clk,
 527                           unsigned int tmr_clk)
 528{
 529        unsigned int plb_clk = __ibm440eplike_fixup_clocks(sys_clk, tmr_clk, 1);
 530
 531        /* serial clocks need fixup based on int/ext */
 532        eplike_fixup_uart_clk(0, "/plb/opb/serial@40000200", ser_clk, plb_clk);
 533        eplike_fixup_uart_clk(1, "/plb/opb/serial@40000300", ser_clk, plb_clk);
 534}
 535
 536void ibm440spe_fixup_clocks(unsigned int sys_clk,
 537                            unsigned int ser_clk,
 538                            unsigned int tmr_clk)
 539{
 540        unsigned int plb_clk = __ibm440eplike_fixup_clocks(sys_clk, tmr_clk, 1);
 541
 542        /* serial clocks need fixup based on int/ext */
 543        eplike_fixup_uart_clk(0, "/plb/opb/serial@f0000200", ser_clk, plb_clk);
 544        eplike_fixup_uart_clk(1, "/plb/opb/serial@f0000300", ser_clk, plb_clk);
 545        eplike_fixup_uart_clk(2, "/plb/opb/serial@f0000600", ser_clk, plb_clk);
 546}
 547
 548void ibm405gp_fixup_clocks(unsigned int sys_clk, unsigned int ser_clk)
 549{
 550        u32 pllmr = mfdcr(DCRN_CPC0_PLLMR);
 551        u32 cpc0_cr0 = mfdcr(DCRN_405_CPC0_CR0);
 552        u32 cpc0_cr1 = mfdcr(DCRN_405_CPC0_CR1);
 553        u32 psr = mfdcr(DCRN_405_CPC0_PSR);
 554        u32 cpu, plb, opb, ebc, tb, uart0, uart1, m;
 555        u32 fwdv, fwdvb, fbdv, cbdv, opdv, epdv, ppdv, udiv;
 556
 557        fwdv = (8 - ((pllmr & 0xe0000000) >> 29));
 558        fbdv = (pllmr & 0x1e000000) >> 25;
 559        if (fbdv == 0)
 560                fbdv = 16;
 561        cbdv = ((pllmr & 0x00060000) >> 17) + 1; /* CPU:PLB */
 562        opdv = ((pllmr & 0x00018000) >> 15) + 1; /* PLB:OPB */
 563        ppdv = ((pllmr & 0x00006000) >> 13) + 1; /* PLB:PCI */
 564        epdv = ((pllmr & 0x00001800) >> 11) + 2; /* PLB:EBC */
 565        udiv = ((cpc0_cr0 & 0x3e) >> 1) + 1;
 566
 567        /* check for 405GPr */
 568        if ((mfpvr() & 0xfffffff0) == (0x50910951 & 0xfffffff0)) {
 569                fwdvb = 8 - (pllmr & 0x00000007);
 570                if (!(psr & 0x00001000)) /* PCI async mode enable == 0 */
 571                        if (psr & 0x00000020) /* New mode enable */
 572                                m = fwdvb * 2 * ppdv;
 573                        else
 574                                m = fwdvb * cbdv * ppdv;
 575                else if (psr & 0x00000020) /* New mode enable */
 576                        if (psr & 0x00000800) /* PerClk synch mode */
 577                                m = fwdvb * 2 * epdv;
 578                        else
 579                                m = fbdv * fwdv;
 580                else if (epdv == fbdv)
 581                        m = fbdv * cbdv * epdv;
 582                else
 583                        m = fbdv * fwdvb * cbdv;
 584
 585                cpu = sys_clk * m / fwdv;
 586                plb = sys_clk * m / (fwdvb * cbdv);
 587        } else {
 588                m = fwdv * fbdv * cbdv;
 589                cpu = sys_clk * m / fwdv;
 590                plb = cpu / cbdv;
 591        }
 592        opb = plb / opdv;
 593        ebc = plb / epdv;
 594
 595        if (cpc0_cr0 & 0x80)
 596                /* uart0 uses the external clock */
 597                uart0 = ser_clk;
 598        else
 599                uart0 = cpu / udiv;
 600
 601        if (cpc0_cr0 & 0x40)
 602                /* uart1 uses the external clock */
 603                uart1 = ser_clk;
 604        else
 605                uart1 = cpu / udiv;
 606
 607        /* setup the timebase clock to tick at the cpu frequency */
 608        cpc0_cr1 = cpc0_cr1 & ~0x00800000;
 609        mtdcr(DCRN_405_CPC0_CR1, cpc0_cr1);
 610        tb = cpu;
 611
 612        dt_fixup_cpu_clocks(cpu, tb, 0);
 613        dt_fixup_clock("/plb", plb);
 614        dt_fixup_clock("/plb/opb", opb);
 615        dt_fixup_clock("/plb/ebc", ebc);
 616        dt_fixup_clock("/plb/opb/serial@ef600300", uart0);
 617        dt_fixup_clock("/plb/opb/serial@ef600400", uart1);
 618}
 619
 620
 621void ibm405ep_fixup_clocks(unsigned int sys_clk)
 622{
 623        u32 pllmr0 = mfdcr(DCRN_CPC0_PLLMR0);
 624        u32 pllmr1 = mfdcr(DCRN_CPC0_PLLMR1);
 625        u32 cpc0_ucr = mfdcr(DCRN_CPC0_UCR);
 626        u32 cpu, plb, opb, ebc, uart0, uart1;
 627        u32 fwdva, fwdvb, fbdv, cbdv, opdv, epdv;
 628        u32 pllmr0_ccdv, tb, m;
 629
 630        fwdva = 8 - ((pllmr1 & 0x00070000) >> 16);
 631        fwdvb = 8 - ((pllmr1 & 0x00007000) >> 12);
 632        fbdv = (pllmr1 & 0x00f00000) >> 20;
 633        if (fbdv == 0)
 634                fbdv = 16;
 635
 636        cbdv = ((pllmr0 & 0x00030000) >> 16) + 1; /* CPU:PLB */
 637        epdv = ((pllmr0 & 0x00000300) >> 8) + 2;  /* PLB:EBC */
 638        opdv = ((pllmr0 & 0x00003000) >> 12) + 1; /* PLB:OPB */
 639
 640        m = fbdv * fwdvb;
 641
 642        pllmr0_ccdv = ((pllmr0 & 0x00300000) >> 20) + 1;
 643        if (pllmr1 & 0x80000000)
 644                cpu = sys_clk * m / (fwdva * pllmr0_ccdv);
 645        else
 646                cpu = sys_clk / pllmr0_ccdv;
 647
 648        plb = cpu / cbdv;
 649        opb = plb / opdv;
 650        ebc = plb / epdv;
 651        tb = cpu;
 652        uart0 = cpu / (cpc0_ucr & 0x0000007f);
 653        uart1 = cpu / ((cpc0_ucr & 0x00007f00) >> 8);
 654
 655        dt_fixup_cpu_clocks(cpu, tb, 0);
 656        dt_fixup_clock("/plb", plb);
 657        dt_fixup_clock("/plb/opb", opb);
 658        dt_fixup_clock("/plb/ebc", ebc);
 659        dt_fixup_clock("/plb/opb/serial@ef600300", uart0);
 660        dt_fixup_clock("/plb/opb/serial@ef600400", uart1);
 661}
 662
 663static u8 ibm405ex_fwdv_multi_bits[] = {
 664        /* values for:  1 - 16 */
 665        0x01, 0x02, 0x0e, 0x09, 0x04, 0x0b, 0x10, 0x0d, 0x0c, 0x05,
 666        0x06, 0x0f, 0x0a, 0x07, 0x08, 0x03
 667};
 668
 669u32 ibm405ex_get_fwdva(unsigned long cpr_fwdv)
 670{
 671        u32 index;
 672
 673        for (index = 0; index < ARRAY_SIZE(ibm405ex_fwdv_multi_bits); index++)
 674                if (cpr_fwdv == (u32)ibm405ex_fwdv_multi_bits[index])
 675                        return index + 1;
 676
 677        return 0;
 678}
 679
 680static u8 ibm405ex_fbdv_multi_bits[] = {
 681        /* values for:  1 - 100 */
 682        0x00, 0xff, 0x7e, 0xfd, 0x7a, 0xf5, 0x6a, 0xd5, 0x2a, 0xd4,
 683        0x29, 0xd3, 0x26, 0xcc, 0x19, 0xb3, 0x67, 0xce, 0x1d, 0xbb,
 684        0x77, 0xee, 0x5d, 0xba, 0x74, 0xe9, 0x52, 0xa5, 0x4b, 0x96,
 685        0x2c, 0xd8, 0x31, 0xe3, 0x46, 0x8d, 0x1b, 0xb7, 0x6f, 0xde,
 686        0x3d, 0xfb, 0x76, 0xed, 0x5a, 0xb5, 0x6b, 0xd6, 0x2d, 0xdb,
 687        0x36, 0xec, 0x59, 0xb2, 0x64, 0xc9, 0x12, 0xa4, 0x48, 0x91,
 688        0x23, 0xc7, 0x0e, 0x9c, 0x38, 0xf0, 0x61, 0xc2, 0x05, 0x8b,
 689        0x17, 0xaf, 0x5f, 0xbe, 0x7c, 0xf9, 0x72, 0xe5, 0x4a, 0x95,
 690        0x2b, 0xd7, 0x2e, 0xdc, 0x39, 0xf3, 0x66, 0xcd, 0x1a, 0xb4,
 691        0x68, 0xd1, 0x22, 0xc4, 0x09, 0x93, 0x27, 0xcf, 0x1e, 0xbc,
 692        /* values for:  101 - 200 */
 693        0x78, 0xf1, 0x62, 0xc5, 0x0a, 0x94, 0x28, 0xd0, 0x21, 0xc3,
 694        0x06, 0x8c, 0x18, 0xb0, 0x60, 0xc1, 0x02, 0x84, 0x08, 0x90,
 695        0x20, 0xc0, 0x01, 0x83, 0x07, 0x8f, 0x1f, 0xbf, 0x7f, 0xfe,
 696        0x7d, 0xfa, 0x75, 0xea, 0x55, 0xaa, 0x54, 0xa9, 0x53, 0xa6,
 697        0x4c, 0x99, 0x33, 0xe7, 0x4e, 0x9d, 0x3b, 0xf7, 0x6e, 0xdd,
 698        0x3a, 0xf4, 0x69, 0xd2, 0x25, 0xcb, 0x16, 0xac, 0x58, 0xb1,
 699        0x63, 0xc6, 0x0d, 0x9b, 0x37, 0xef, 0x5e, 0xbd, 0x7b, 0xf6,
 700        0x6d, 0xda, 0x35, 0xeb, 0x56, 0xad, 0x5b, 0xb6, 0x6c, 0xd9,
 701        0x32, 0xe4, 0x49, 0x92, 0x24, 0xc8, 0x11, 0xa3, 0x47, 0x8e,
 702        0x1c, 0xb8, 0x70, 0xe1, 0x42, 0x85, 0x0b, 0x97, 0x2f, 0xdf,
 703        /* values for:  201 - 255 */
 704        0x3e, 0xfc, 0x79, 0xf2, 0x65, 0xca, 0x15, 0xab, 0x57, 0xae,
 705        0x5c, 0xb9, 0x73, 0xe6, 0x4d, 0x9a, 0x34, 0xe8, 0x51, 0xa2,
 706        0x44, 0x89, 0x13, 0xa7, 0x4f, 0x9e, 0x3c, 0xf8, 0x71, 0xe2,
 707        0x45, 0x8a, 0x14, 0xa8, 0x50, 0xa1, 0x43, 0x86, 0x0c, 0x98,
 708        0x30, 0xe0, 0x41, 0x82, 0x04, 0x88, 0x10, 0xa0, 0x40, 0x81,
 709        0x03, 0x87, 0x0f, 0x9f, 0x3f  /* END */
 710};
 711
 712u32 ibm405ex_get_fbdv(unsigned long cpr_fbdv)
 713{
 714        u32 index;
 715
 716        for (index = 0; index < ARRAY_SIZE(ibm405ex_fbdv_multi_bits); index++)
 717                if (cpr_fbdv == (u32)ibm405ex_fbdv_multi_bits[index])
 718                        return index + 1;
 719
 720        return 0;
 721}
 722
 723void ibm405ex_fixup_clocks(unsigned int sys_clk, unsigned int uart_clk)
 724{
 725        /* PLL config */
 726        u32 pllc  = CPR0_READ(DCRN_CPR0_PLLC);
 727        u32 plld  = CPR0_READ(DCRN_CPR0_PLLD);
 728        u32 cpud  = CPR0_READ(DCRN_CPR0_PRIMAD);
 729        u32 plbd  = CPR0_READ(DCRN_CPR0_PRIMBD);
 730        u32 opbd  = CPR0_READ(DCRN_CPR0_OPBD);
 731        u32 perd  = CPR0_READ(DCRN_CPR0_PERD);
 732
 733        /* Dividers */
 734        u32 fbdv   = ibm405ex_get_fbdv(__fix_zero((plld >> 24) & 0xff, 1));
 735
 736        u32 fwdva  = ibm405ex_get_fwdva(__fix_zero((plld >> 16) & 0x0f, 1));
 737
 738        u32 cpudv0 = __fix_zero((cpud >> 24) & 7, 8);
 739
 740        /* PLBDV0 is hardwared to 010. */
 741        u32 plbdv0 = 2;
 742        u32 plb2xdv0 = __fix_zero((plbd >> 16) & 7, 8);
 743
 744        u32 opbdv0 = __fix_zero((opbd >> 24) & 3, 4);
 745
 746        u32 perdv0 = __fix_zero((perd >> 24) & 3, 4);
 747
 748        /* Resulting clocks */
 749        u32 cpu, plb, opb, ebc, vco, tb, uart0, uart1;
 750
 751        /* PLL's VCO is the source for primary forward ? */
 752        if (pllc & 0x40000000) {
 753                u32 m;
 754
 755                /* Feedback path */
 756                switch ((pllc >> 24) & 7) {
 757                case 0:
 758                        /* PLLOUTx */
 759                        m = fbdv;
 760                        break;
 761                case 1:
 762                        /* CPU */
 763                        m = fbdv * fwdva * cpudv0;
 764                        break;
 765                case 5:
 766                        /* PERClk */
 767                        m = fbdv * fwdva * plb2xdv0 * plbdv0 * opbdv0 * perdv0;
 768                        break;
 769                default:
 770                        printf("WARNING ! Invalid PLL feedback source !\n");
 771                        goto bypass;
 772                }
 773
 774                vco = (unsigned int)(sys_clk * m);
 775        } else {
 776bypass:
 777                /* Bypass system PLL */
 778                vco = 0;
 779        }
 780
 781        /* CPU = VCO / ( FWDVA x CPUDV0) */
 782        cpu = vco / (fwdva * cpudv0);
 783        /* PLB = VCO / ( FWDVA x PLB2XDV0 x PLBDV0) */
 784        plb = vco / (fwdva * plb2xdv0 * plbdv0);
 785        /* OPB = PLB / OPBDV0 */
 786        opb = plb / opbdv0;
 787        /* EBC = OPB / PERDV0 */
 788        ebc = opb / perdv0;
 789
 790        tb = cpu;
 791        uart0 = uart1 = uart_clk;
 792
 793        dt_fixup_cpu_clocks(cpu, tb, 0);
 794        dt_fixup_clock("/plb", plb);
 795        dt_fixup_clock("/plb/opb", opb);
 796        dt_fixup_clock("/plb/opb/ebc", ebc);
 797        dt_fixup_clock("/plb/opb/serial@ef600200", uart0);
 798        dt_fixup_clock("/plb/opb/serial@ef600300", uart1);
 799}
 800