This source file includes following definitions.
- chip_11_errata
- ibm4xx_sdram_fixup_memsize
- ibm440spe_decode_bas
- ibm440spe_fixup_memsize
- ibm4xx_denali_get_cs
- ibm4xx_denali_fixup_memsize
- ibm44x_dbcr_reset
- ibm40x_dbcr_reset
- ibm4xx_quiesce_eth
- ibm4xx_fixup_ebc_ranges
- ibm440gp_fixup_clocks
- __fix_zero
- __ibm440eplike_fixup_clocks
- eplike_fixup_uart_clk
- ibm440ep_fixup_clocks
- ibm440gx_fixup_clocks
- ibm440spe_fixup_clocks
- ibm405gp_fixup_clocks
- ibm405ep_fixup_clocks
- ibm405ex_get_fwdva
- ibm405ex_get_fbdv
- ibm405ex_fixup_clocks
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 
  10 
  11 
  12 
  13 
  14 
  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 
  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 
  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         
  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         
 104 
 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 
 124 
 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 
 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 
 142 #define DDR_DDR2_MODE           0x1
 143 #define DDR_DDR2_MODE_SHIFT     0
 144 
 145 #define DDR_CS_MAP              0x3
 146 #define DDR_CS_MAP_SHIFT        8
 147 
 148 #define DDR_REDUC               0x1
 149 #define DDR_REDUC_SHIFT         16
 150 
 151 #define DDR_APIN                0x7
 152 #define DDR_APIN_SHIFT          24
 153 
 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 
 163 
 164 
 165 
 166 
 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         
 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         
 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         
 223         val = SDRAM0_READ(DDR0_14);
 224 
 225         if (DDR_GET_VAL(val, DDR_REDUC, DDR_REDUC_SHIFT))
 226                 dpath = 4; 
 227         else
 228                 dpath = 8; 
 229 
 230         
 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         
 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; 
 248         else
 249                 bank = 4; 
 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         
 289 
 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                 ; 
 299 }
 300 
 301 
 302 
 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 
 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                 
 341                 cpu = plb = sys_clk;
 342         } else {
 343                 if (sys0 & CPC0_SYS0_EXTSL)
 344                         
 345                         m = CPC0_SYS0_FWDVB(sys0) * opdv * epdv;
 346                 else
 347                         
 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         
 357         if ((mfpvr() & 0xf0000fff) == 0x40000440)
 358                 
 359                 tb = sys_clk;
 360         else
 361                 
 362                 tb = cpu;
 363 
 364         if (cr0 & CPC0_CR0_U0EC)
 365                 
 366                 uart0 = ser_clk;
 367         else
 368                 
 369                 uart0 = plb / CPC0_CR0_UDIV(cr0);
 370 
 371         if (cr0 & CPC0_CR0_U1EC)
 372                 
 373                 uart1 = ser_clk;
 374         else
 375                 
 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         
 402         u32 pllc  = CPR0_READ(DCRN_CPR0_PLLC);
 403         u32 plld  = CPR0_READ(DCRN_CPR0_PLLD);
 404 
 405         
 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         
 416         u32 clk_a, clk_b;
 417 
 418         
 419         u32 cpu, plb, opb, ebc, vco;
 420 
 421         
 422         u32 ccr1, tb = tmr_clk;
 423 
 424         if (pllc & 0x40000000) {
 425                 u32 m;
 426 
 427                 
 428                 switch ((pllc >> 24) & 7) {
 429                 case 0:
 430                         
 431                         m = ((pllc & 0x20000000) ? fwdvb : fwdva) * lfbdv;
 432                         break;
 433                 case 1:
 434                         
 435                         m = fwdva * pradv0;
 436                         break;
 437                 case 5:
 438                         
 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                 
 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         
 462         ccr1 = mfspr(SPRN_CCR1);
 463 
 464         
 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         
 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         
 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         
 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; 
 562         opdv = ((pllmr & 0x00018000) >> 15) + 1; 
 563         ppdv = ((pllmr & 0x00006000) >> 13) + 1; 
 564         epdv = ((pllmr & 0x00001800) >> 11) + 2; 
 565         udiv = ((cpc0_cr0 & 0x3e) >> 1) + 1;
 566 
 567         
 568         if ((mfpvr() & 0xfffffff0) == (0x50910951 & 0xfffffff0)) {
 569                 fwdvb = 8 - (pllmr & 0x00000007);
 570                 if (!(psr & 0x00001000)) 
 571                         if (psr & 0x00000020) 
 572                                 m = fwdvb * 2 * ppdv;
 573                         else
 574                                 m = fwdvb * cbdv * ppdv;
 575                 else if (psr & 0x00000020) 
 576                         if (psr & 0x00000800) 
 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                 
 597                 uart0 = ser_clk;
 598         else
 599                 uart0 = cpu / udiv;
 600 
 601         if (cpc0_cr0 & 0x40)
 602                 
 603                 uart1 = ser_clk;
 604         else
 605                 uart1 = cpu / udiv;
 606 
 607         
 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; 
 637         epdv = ((pllmr0 & 0x00000300) >> 8) + 2;  
 638         opdv = ((pllmr0 & 0x00003000) >> 12) + 1; 
 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         
 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         
 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         
 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         
 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  
 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         
 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         
 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         
 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         
 749         u32 cpu, plb, opb, ebc, vco, tb, uart0, uart1;
 750 
 751         
 752         if (pllc & 0x40000000) {
 753                 u32 m;
 754 
 755                 
 756                 switch ((pllc >> 24) & 7) {
 757                 case 0:
 758                         
 759                         m = fbdv;
 760                         break;
 761                 case 1:
 762                         
 763                         m = fbdv * fwdva * cpudv0;
 764                         break;
 765                 case 5:
 766                         
 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                 
 778                 vco = 0;
 779         }
 780 
 781         
 782         cpu = vco / (fwdva * cpudv0);
 783         
 784         plb = vco / (fwdva * plb2xdv0 * plbdv0);
 785         
 786         opb = plb / opbdv0;
 787         
 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 }