root/arch/powerpc/boot/4xx.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. chip_11_errata
  2. ibm4xx_sdram_fixup_memsize
  3. ibm440spe_decode_bas
  4. ibm440spe_fixup_memsize
  5. ibm4xx_denali_get_cs
  6. ibm4xx_denali_fixup_memsize
  7. ibm44x_dbcr_reset
  8. ibm40x_dbcr_reset
  9. ibm4xx_quiesce_eth
  10. ibm4xx_fixup_ebc_ranges
  11. ibm440gp_fixup_clocks
  12. __fix_zero
  13. __ibm440eplike_fixup_clocks
  14. eplike_fixup_uart_clk
  15. ibm440ep_fixup_clocks
  16. ibm440gx_fixup_clocks
  17. ibm440spe_fixup_clocks
  18. ibm405gp_fixup_clocks
  19. ibm405ep_fixup_clocks
  20. ibm405ex_get_fwdva
  21. ibm405ex_get_fbdv
  22. ibm405ex_fixup_clocks

   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 
  24 static 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. */
  44 void 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 
  66 static 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 
  99 void 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  */
 168 static 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 
 187 read_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 
 201 void 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 
 260 void 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 
 273 void 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
 286 void 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 */
 303 void 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 */
 331 void 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 
 392 static inline u32 __fix_zero(u32 v, u32 def)
 393 {
 394         return v ? v : def;
 395 }
 396 
 397 static 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 {
 450 bypass:
 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 
 480 static 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 
 512 void 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 
 525 void 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 
 536 void 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 
 548 void 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 
 621 void 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 
 663 static 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 
 669 u32 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 
 680 static 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 
 712 u32 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 
 723 void 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 {
 776 bypass:
 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 }

/* [<][>][^][v][top][bottom][index][help] */