2 * Copyright 2007 David Gibson, IBM Corporation.
4 * Based on earlier code:
5 * Matt Porter <mporter@kernel.crashing.org>
6 * Copyright 2002-2005 MontaVista Software Inc.
8 * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
9 * Copyright (c) 2003, 2004 Zultys Technologies
11 * Copyright (C) 2009 Wind River Systems, Inc.
12 * Updated for supporting PPC405EX on Kilauea.
13 * Tiejun Chen <tiejun.chen@windriver.com>
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version
18 * 2 of the License, or (at your option) any later version.
28 static unsigned long chip_11_errata(unsigned long memsize)
34 switch (pvr & 0xf0000ff0) {
47 /* Read the 4xx SDRAM controller to get size of system memory. */
48 void ibm4xx_sdram_fixup_memsize(void)
51 unsigned long memsize, bank_config;
54 for (i = 0; i < ARRAY_SIZE(sdram_bxcr); i++) {
55 bank_config = SDRAM0_READ(sdram_bxcr[i]);
56 if (bank_config & SDRAM_CONFIG_BANK_ENABLE)
57 memsize += SDRAM_CONFIG_BANK_SIZE(bank_config);
60 memsize = chip_11_errata(memsize);
61 dt_fixup_memory(0, memsize);
64 /* Read the 440SPe MQ controller to get size of system memory. */
65 #define DCRN_MQ0_B0BAS 0x40
66 #define DCRN_MQ0_B1BAS 0x41
67 #define DCRN_MQ0_B2BAS 0x42
68 #define DCRN_MQ0_B3BAS 0x43
70 static u64 ibm440spe_decode_bas(u32 bas)
72 u64 base = ((u64)(bas & 0xFFE00000u)) << 2;
74 /* open coded because I'm paranoid about invalid values */
75 switch ((bas >> 4) & 0xFFF) {
79 return base + 0x000800000ull;
81 return base + 0x001000000ull;
83 return base + 0x002000000ull;
85 return base + 0x004000000ull;
87 return base + 0x008000000ull;
89 return base + 0x010000000ull;
91 return base + 0x020000000ull;
93 return base + 0x040000000ull;
95 return base + 0x080000000ull;
97 return base + 0x100000000ull;
99 printf("Memory BAS value 0x%08x unsupported !\n", bas);
103 void ibm440spe_fixup_memsize(void)
105 u64 banktop, memsize = 0;
107 /* Ultimately, we should directly construct the memory node
108 * so we are able to handle holes in the memory address space
110 banktop = ibm440spe_decode_bas(mfdcr(DCRN_MQ0_B0BAS));
111 if (banktop > memsize)
113 banktop = ibm440spe_decode_bas(mfdcr(DCRN_MQ0_B1BAS));
114 if (banktop > memsize)
116 banktop = ibm440spe_decode_bas(mfdcr(DCRN_MQ0_B2BAS));
117 if (banktop > memsize)
119 banktop = ibm440spe_decode_bas(mfdcr(DCRN_MQ0_B3BAS));
120 if (banktop > memsize)
123 dt_fixup_memory(0, memsize);
127 /* 4xx DDR1/2 Denali memory controller support */
137 #define DDR_START 0x1
138 #define DDR_START_SHIFT 0
139 #define DDR_MAX_CS_REG 0x3
140 #define DDR_MAX_CS_REG_SHIFT 24
141 #define DDR_MAX_COL_REG 0xf
142 #define DDR_MAX_COL_REG_SHIFT 16
143 #define DDR_MAX_ROW_REG 0xf
144 #define DDR_MAX_ROW_REG_SHIFT 8
146 #define DDR_DDR2_MODE 0x1
147 #define DDR_DDR2_MODE_SHIFT 0
149 #define DDR_CS_MAP 0x3
150 #define DDR_CS_MAP_SHIFT 8
152 #define DDR_REDUC 0x1
153 #define DDR_REDUC_SHIFT 16
156 #define DDR_APIN_SHIFT 24
158 #define DDR_COL_SZ 0x7
159 #define DDR_COL_SZ_SHIFT 8
160 #define DDR_BANK8 0x1
161 #define DDR_BANK8_SHIFT 0
163 #define DDR_GET_VAL(val, mask, shift) (((val) >> (shift)) & (mask))
166 * Some U-Boot versions set the number of chipselects to two
167 * for Sequoia/Rainier boards while they only have one chipselect
168 * hardwired. Hardcode the number of chipselects to one
169 * for sequioa/rainer board models or read the actual value
170 * from the memory controller register DDR0_10 otherwise.
172 static inline u32 ibm4xx_denali_get_cs(void)
178 devp = finddevice("/");
182 if (getprop(devp, "model", model, sizeof(model)) <= 0)
185 model[sizeof(model)-1] = 0;
187 if (!strcmp(model, "amcc,sequoia") ||
188 !strcmp(model, "amcc,rainier"))
193 val = SDRAM0_READ(DDR0_10);
195 val = DDR_GET_VAL(val, DDR_CS_MAP, DDR_CS_MAP_SHIFT);
205 void ibm4xx_denali_fixup_memsize(void)
207 u32 val, max_cs, max_col, max_row;
208 u32 cs, col, row, bank, dpath;
209 unsigned long memsize;
211 val = SDRAM0_READ(DDR0_02);
212 if (!DDR_GET_VAL(val, DDR_START, DDR_START_SHIFT))
213 fatal("DDR controller is not initialized\n");
215 /* get maximum cs col and row values */
216 max_cs = DDR_GET_VAL(val, DDR_MAX_CS_REG, DDR_MAX_CS_REG_SHIFT);
217 max_col = DDR_GET_VAL(val, DDR_MAX_COL_REG, DDR_MAX_COL_REG_SHIFT);
218 max_row = DDR_GET_VAL(val, DDR_MAX_ROW_REG, DDR_MAX_ROW_REG_SHIFT);
220 cs = ibm4xx_denali_get_cs();
222 fatal("No memory installed\n");
224 fatal("DDR wrong CS configuration\n");
226 /* get data path bytes */
227 val = SDRAM0_READ(DDR0_14);
229 if (DDR_GET_VAL(val, DDR_REDUC, DDR_REDUC_SHIFT))
230 dpath = 4; /* 32 bits */
232 dpath = 8; /* 64 bits */
234 /* get address pins (rows) */
235 val = SDRAM0_READ(DDR0_42);
237 row = DDR_GET_VAL(val, DDR_APIN, DDR_APIN_SHIFT);
239 fatal("DDR wrong APIN configuration\n");
242 /* get collomn size and banks */
243 val = SDRAM0_READ(DDR0_43);
245 col = DDR_GET_VAL(val, DDR_COL_SZ, DDR_COL_SZ_SHIFT);
247 fatal("DDR wrong COL configuration\n");
250 if (DDR_GET_VAL(val, DDR_BANK8, DDR_BANK8_SHIFT))
251 bank = 8; /* 8 banks */
253 bank = 4; /* 4 banks */
255 memsize = cs * (1 << (col+row)) * bank * dpath;
256 memsize = chip_11_errata(memsize);
257 dt_fixup_memory(0, memsize);
260 #define SPRN_DBCR0_40X 0x3F2
261 #define SPRN_DBCR0_44X 0x134
262 #define DBCR0_RST_SYSTEM 0x30000000
264 void ibm44x_dbcr_reset(void)
272 : "=&r"(tmp) : "i"(SPRN_DBCR0_44X), "i"(DBCR0_RST_SYSTEM)
277 void ibm40x_dbcr_reset(void)
285 : "=&r"(tmp) : "i"(SPRN_DBCR0_40X), "i"(DBCR0_RST_SYSTEM)
289 #define EMAC_RESET 0x20000000
290 void ibm4xx_quiesce_eth(u32 *emac0, u32 *emac1)
292 /* Quiesce the MAL and EMAC(s) since PIBS/OpenBIOS don't
300 mtdcr(DCRN_MAL0_CFG, MAL_RESET);
301 while (mfdcr(DCRN_MAL0_CFG) & MAL_RESET)
302 ; /* loop until reset takes effect */
305 /* Read 4xx EBC bus bridge registers to get mappings of the peripheral
306 * banks into the OPB address space */
307 void ibm4xx_fixup_ebc_ranges(const char *ebc)
311 u32 ranges[EBC_NUM_BANKS*4];
315 for (i = 0; i < EBC_NUM_BANKS; i++) {
316 mtdcr(DCRN_EBC0_CFGADDR, EBC_BXCR(i));
317 bxcr = mfdcr(DCRN_EBC0_CFGDATA);
319 if ((bxcr & EBC_BXCR_BU) != EBC_BXCR_BU_OFF) {
322 *p++ = bxcr & EBC_BXCR_BAS;
323 *p++ = EBC_BXCR_BANK_SIZE(bxcr);
327 devp = finddevice(ebc);
329 fatal("Couldn't locate EBC node %s\n\r", ebc);
331 setprop(devp, "ranges", ranges, (p - ranges) * sizeof(u32));
334 /* Calculate 440GP clocks */
335 void ibm440gp_fixup_clocks(unsigned int sys_clk, unsigned int ser_clk)
337 u32 sys0 = mfdcr(DCRN_CPC0_SYS0);
338 u32 cr0 = mfdcr(DCRN_CPC0_CR0);
339 u32 cpu, plb, opb, ebc, tb, uart0, uart1, m;
340 u32 opdv = CPC0_SYS0_OPDV(sys0);
341 u32 epdv = CPC0_SYS0_EPDV(sys0);
343 if (sys0 & CPC0_SYS0_BYPASS) {
344 /* Bypass system PLL */
347 if (sys0 & CPC0_SYS0_EXTSL)
349 m = CPC0_SYS0_FWDVB(sys0) * opdv * epdv;
352 m = CPC0_SYS0_FBDV(sys0) * CPC0_SYS0_FWDVA(sys0);
353 cpu = sys_clk * m / CPC0_SYS0_FWDVA(sys0);
354 plb = sys_clk * m / CPC0_SYS0_FWDVB(sys0);
360 /* FIXME: Check if this is for all 440GP, or just Ebony */
361 if ((mfpvr() & 0xf0000fff) == 0x40000440)
362 /* Rev. B 440GP, use external system clock */
365 /* Rev. C 440GP, errata force us to use internal clock */
368 if (cr0 & CPC0_CR0_U0EC)
369 /* External UART clock */
372 /* Internal UART clock */
373 uart0 = plb / CPC0_CR0_UDIV(cr0);
375 if (cr0 & CPC0_CR0_U1EC)
376 /* External UART clock */
379 /* Internal UART clock */
380 uart1 = plb / CPC0_CR0_UDIV(cr0);
382 printf("PPC440GP: SysClk = %dMHz (%x)\n\r",
383 (sys_clk + 500000) / 1000000, sys_clk);
385 dt_fixup_cpu_clocks(cpu, tb, 0);
387 dt_fixup_clock("/plb", plb);
388 dt_fixup_clock("/plb/opb", opb);
389 dt_fixup_clock("/plb/opb/ebc", ebc);
390 dt_fixup_clock("/plb/opb/serial@40000200", uart0);
391 dt_fixup_clock("/plb/opb/serial@40000300", uart1);
394 #define SPRN_CCR1 0x378
396 static inline u32 __fix_zero(u32 v, u32 def)
401 static unsigned int __ibm440eplike_fixup_clocks(unsigned int sys_clk,
402 unsigned int tmr_clk,
403 int per_clk_from_opb)
406 u32 pllc = CPR0_READ(DCRN_CPR0_PLLC);
407 u32 plld = CPR0_READ(DCRN_CPR0_PLLD);
410 u32 fbdv = __fix_zero((plld >> 24) & 0x1f, 32);
411 u32 fwdva = __fix_zero((plld >> 16) & 0xf, 16);
412 u32 fwdvb = __fix_zero((plld >> 8) & 7, 8);
413 u32 lfbdv = __fix_zero(plld & 0x3f, 64);
414 u32 pradv0 = __fix_zero((CPR0_READ(DCRN_CPR0_PRIMAD) >> 24) & 7, 8);
415 u32 prbdv0 = __fix_zero((CPR0_READ(DCRN_CPR0_PRIMBD) >> 24) & 7, 8);
416 u32 opbdv0 = __fix_zero((CPR0_READ(DCRN_CPR0_OPBD) >> 24) & 3, 4);
417 u32 perdv0 = __fix_zero((CPR0_READ(DCRN_CPR0_PERD) >> 24) & 3, 4);
419 /* Input clocks for primary dividers */
422 /* Resulting clocks */
423 u32 cpu, plb, opb, ebc, vco;
426 u32 ccr1, tb = tmr_clk;
428 if (pllc & 0x40000000) {
432 switch ((pllc >> 24) & 7) {
435 m = ((pllc & 0x20000000) ? fwdvb : fwdva) * lfbdv;
443 m = fwdvb * prbdv0 * opbdv0 * perdv0;
446 printf("WARNING ! Invalid PLL feedback source !\n");
455 /* Bypass system PLL */
457 clk_a = clk_b = sys_clk;
460 cpu = clk_a / pradv0;
461 plb = clk_b / prbdv0;
463 ebc = (per_clk_from_opb ? opb : plb) / perdv0;
465 /* Figure out timebase. Either CPU or default TmrClk */
466 ccr1 = mfspr(SPRN_CCR1);
468 /* If passed a 0 tmr_clk, force CPU clock */
471 mtspr(SPRN_CCR1, ccr1);
473 if ((ccr1 & 0x0080) == 0)
476 dt_fixup_cpu_clocks(cpu, tb, 0);
477 dt_fixup_clock("/plb", plb);
478 dt_fixup_clock("/plb/opb", opb);
479 dt_fixup_clock("/plb/opb/ebc", ebc);
484 static void eplike_fixup_uart_clk(int index, const char *path,
485 unsigned int ser_clk,
486 unsigned int plb_clk)
493 sdr = SDR0_READ(DCRN_SDR0_UART0);
496 sdr = SDR0_READ(DCRN_SDR0_UART1);
499 sdr = SDR0_READ(DCRN_SDR0_UART2);
502 sdr = SDR0_READ(DCRN_SDR0_UART3);
508 if (sdr & 0x00800000u)
511 clock = plb_clk / __fix_zero(sdr & 0xff, 256);
513 dt_fixup_clock(path, clock);
516 void ibm440ep_fixup_clocks(unsigned int sys_clk,
517 unsigned int ser_clk,
518 unsigned int tmr_clk)
520 unsigned int plb_clk = __ibm440eplike_fixup_clocks(sys_clk, tmr_clk, 0);
522 /* serial clocks need fixup based on int/ext */
523 eplike_fixup_uart_clk(0, "/plb/opb/serial@ef600300", ser_clk, plb_clk);
524 eplike_fixup_uart_clk(1, "/plb/opb/serial@ef600400", ser_clk, plb_clk);
525 eplike_fixup_uart_clk(2, "/plb/opb/serial@ef600500", ser_clk, plb_clk);
526 eplike_fixup_uart_clk(3, "/plb/opb/serial@ef600600", ser_clk, plb_clk);
529 void ibm440gx_fixup_clocks(unsigned int sys_clk,
530 unsigned int ser_clk,
531 unsigned int tmr_clk)
533 unsigned int plb_clk = __ibm440eplike_fixup_clocks(sys_clk, tmr_clk, 1);
535 /* serial clocks need fixup based on int/ext */
536 eplike_fixup_uart_clk(0, "/plb/opb/serial@40000200", ser_clk, plb_clk);
537 eplike_fixup_uart_clk(1, "/plb/opb/serial@40000300", ser_clk, plb_clk);
540 void ibm440spe_fixup_clocks(unsigned int sys_clk,
541 unsigned int ser_clk,
542 unsigned int tmr_clk)
544 unsigned int plb_clk = __ibm440eplike_fixup_clocks(sys_clk, tmr_clk, 1);
546 /* serial clocks need fixup based on int/ext */
547 eplike_fixup_uart_clk(0, "/plb/opb/serial@f0000200", ser_clk, plb_clk);
548 eplike_fixup_uart_clk(1, "/plb/opb/serial@f0000300", ser_clk, plb_clk);
549 eplike_fixup_uart_clk(2, "/plb/opb/serial@f0000600", ser_clk, plb_clk);
552 void ibm405gp_fixup_clocks(unsigned int sys_clk, unsigned int ser_clk)
554 u32 pllmr = mfdcr(DCRN_CPC0_PLLMR);
555 u32 cpc0_cr0 = mfdcr(DCRN_405_CPC0_CR0);
556 u32 cpc0_cr1 = mfdcr(DCRN_405_CPC0_CR1);
557 u32 psr = mfdcr(DCRN_405_CPC0_PSR);
558 u32 cpu, plb, opb, ebc, tb, uart0, uart1, m;
559 u32 fwdv, fwdvb, fbdv, cbdv, opdv, epdv, ppdv, udiv;
561 fwdv = (8 - ((pllmr & 0xe0000000) >> 29));
562 fbdv = (pllmr & 0x1e000000) >> 25;
565 cbdv = ((pllmr & 0x00060000) >> 17) + 1; /* CPU:PLB */
566 opdv = ((pllmr & 0x00018000) >> 15) + 1; /* PLB:OPB */
567 ppdv = ((pllmr & 0x00006000) >> 13) + 1; /* PLB:PCI */
568 epdv = ((pllmr & 0x00001800) >> 11) + 2; /* PLB:EBC */
569 udiv = ((cpc0_cr0 & 0x3e) >> 1) + 1;
571 /* check for 405GPr */
572 if ((mfpvr() & 0xfffffff0) == (0x50910951 & 0xfffffff0)) {
573 fwdvb = 8 - (pllmr & 0x00000007);
574 if (!(psr & 0x00001000)) /* PCI async mode enable == 0 */
575 if (psr & 0x00000020) /* New mode enable */
576 m = fwdvb * 2 * ppdv;
578 m = fwdvb * cbdv * ppdv;
579 else if (psr & 0x00000020) /* New mode enable */
580 if (psr & 0x00000800) /* PerClk synch mode */
581 m = fwdvb * 2 * epdv;
584 else if (epdv == fbdv)
585 m = fbdv * cbdv * epdv;
587 m = fbdv * fwdvb * cbdv;
589 cpu = sys_clk * m / fwdv;
590 plb = sys_clk * m / (fwdvb * cbdv);
592 m = fwdv * fbdv * cbdv;
593 cpu = sys_clk * m / fwdv;
600 /* uart0 uses the external clock */
606 /* uart1 uses the external clock */
611 /* setup the timebase clock to tick at the cpu frequency */
612 cpc0_cr1 = cpc0_cr1 & ~0x00800000;
613 mtdcr(DCRN_405_CPC0_CR1, cpc0_cr1);
616 dt_fixup_cpu_clocks(cpu, tb, 0);
617 dt_fixup_clock("/plb", plb);
618 dt_fixup_clock("/plb/opb", opb);
619 dt_fixup_clock("/plb/ebc", ebc);
620 dt_fixup_clock("/plb/opb/serial@ef600300", uart0);
621 dt_fixup_clock("/plb/opb/serial@ef600400", uart1);
625 void ibm405ep_fixup_clocks(unsigned int sys_clk)
627 u32 pllmr0 = mfdcr(DCRN_CPC0_PLLMR0);
628 u32 pllmr1 = mfdcr(DCRN_CPC0_PLLMR1);
629 u32 cpc0_ucr = mfdcr(DCRN_CPC0_UCR);
630 u32 cpu, plb, opb, ebc, uart0, uart1;
631 u32 fwdva, fwdvb, fbdv, cbdv, opdv, epdv;
632 u32 pllmr0_ccdv, tb, m;
634 fwdva = 8 - ((pllmr1 & 0x00070000) >> 16);
635 fwdvb = 8 - ((pllmr1 & 0x00007000) >> 12);
636 fbdv = (pllmr1 & 0x00f00000) >> 20;
640 cbdv = ((pllmr0 & 0x00030000) >> 16) + 1; /* CPU:PLB */
641 epdv = ((pllmr0 & 0x00000300) >> 8) + 2; /* PLB:EBC */
642 opdv = ((pllmr0 & 0x00003000) >> 12) + 1; /* PLB:OPB */
646 pllmr0_ccdv = ((pllmr0 & 0x00300000) >> 20) + 1;
647 if (pllmr1 & 0x80000000)
648 cpu = sys_clk * m / (fwdva * pllmr0_ccdv);
650 cpu = sys_clk / pllmr0_ccdv;
656 uart0 = cpu / (cpc0_ucr & 0x0000007f);
657 uart1 = cpu / ((cpc0_ucr & 0x00007f00) >> 8);
659 dt_fixup_cpu_clocks(cpu, tb, 0);
660 dt_fixup_clock("/plb", plb);
661 dt_fixup_clock("/plb/opb", opb);
662 dt_fixup_clock("/plb/ebc", ebc);
663 dt_fixup_clock("/plb/opb/serial@ef600300", uart0);
664 dt_fixup_clock("/plb/opb/serial@ef600400", uart1);
667 static u8 ibm405ex_fwdv_multi_bits[] = {
668 /* values for: 1 - 16 */
669 0x01, 0x02, 0x0e, 0x09, 0x04, 0x0b, 0x10, 0x0d, 0x0c, 0x05,
670 0x06, 0x0f, 0x0a, 0x07, 0x08, 0x03
673 u32 ibm405ex_get_fwdva(unsigned long cpr_fwdv)
677 for (index = 0; index < ARRAY_SIZE(ibm405ex_fwdv_multi_bits); index++)
678 if (cpr_fwdv == (u32)ibm405ex_fwdv_multi_bits[index])
684 static u8 ibm405ex_fbdv_multi_bits[] = {
685 /* values for: 1 - 100 */
686 0x00, 0xff, 0x7e, 0xfd, 0x7a, 0xf5, 0x6a, 0xd5, 0x2a, 0xd4,
687 0x29, 0xd3, 0x26, 0xcc, 0x19, 0xb3, 0x67, 0xce, 0x1d, 0xbb,
688 0x77, 0xee, 0x5d, 0xba, 0x74, 0xe9, 0x52, 0xa5, 0x4b, 0x96,
689 0x2c, 0xd8, 0x31, 0xe3, 0x46, 0x8d, 0x1b, 0xb7, 0x6f, 0xde,
690 0x3d, 0xfb, 0x76, 0xed, 0x5a, 0xb5, 0x6b, 0xd6, 0x2d, 0xdb,
691 0x36, 0xec, 0x59, 0xb2, 0x64, 0xc9, 0x12, 0xa4, 0x48, 0x91,
692 0x23, 0xc7, 0x0e, 0x9c, 0x38, 0xf0, 0x61, 0xc2, 0x05, 0x8b,
693 0x17, 0xaf, 0x5f, 0xbe, 0x7c, 0xf9, 0x72, 0xe5, 0x4a, 0x95,
694 0x2b, 0xd7, 0x2e, 0xdc, 0x39, 0xf3, 0x66, 0xcd, 0x1a, 0xb4,
695 0x68, 0xd1, 0x22, 0xc4, 0x09, 0x93, 0x27, 0xcf, 0x1e, 0xbc,
696 /* values for: 101 - 200 */
697 0x78, 0xf1, 0x62, 0xc5, 0x0a, 0x94, 0x28, 0xd0, 0x21, 0xc3,
698 0x06, 0x8c, 0x18, 0xb0, 0x60, 0xc1, 0x02, 0x84, 0x08, 0x90,
699 0x20, 0xc0, 0x01, 0x83, 0x07, 0x8f, 0x1f, 0xbf, 0x7f, 0xfe,
700 0x7d, 0xfa, 0x75, 0xea, 0x55, 0xaa, 0x54, 0xa9, 0x53, 0xa6,
701 0x4c, 0x99, 0x33, 0xe7, 0x4e, 0x9d, 0x3b, 0xf7, 0x6e, 0xdd,
702 0x3a, 0xf4, 0x69, 0xd2, 0x25, 0xcb, 0x16, 0xac, 0x58, 0xb1,
703 0x63, 0xc6, 0x0d, 0x9b, 0x37, 0xef, 0x5e, 0xbd, 0x7b, 0xf6,
704 0x6d, 0xda, 0x35, 0xeb, 0x56, 0xad, 0x5b, 0xb6, 0x6c, 0xd9,
705 0x32, 0xe4, 0x49, 0x92, 0x24, 0xc8, 0x11, 0xa3, 0x47, 0x8e,
706 0x1c, 0xb8, 0x70, 0xe1, 0x42, 0x85, 0x0b, 0x97, 0x2f, 0xdf,
707 /* values for: 201 - 255 */
708 0x3e, 0xfc, 0x79, 0xf2, 0x65, 0xca, 0x15, 0xab, 0x57, 0xae,
709 0x5c, 0xb9, 0x73, 0xe6, 0x4d, 0x9a, 0x34, 0xe8, 0x51, 0xa2,
710 0x44, 0x89, 0x13, 0xa7, 0x4f, 0x9e, 0x3c, 0xf8, 0x71, 0xe2,
711 0x45, 0x8a, 0x14, 0xa8, 0x50, 0xa1, 0x43, 0x86, 0x0c, 0x98,
712 0x30, 0xe0, 0x41, 0x82, 0x04, 0x88, 0x10, 0xa0, 0x40, 0x81,
713 0x03, 0x87, 0x0f, 0x9f, 0x3f /* END */
716 u32 ibm405ex_get_fbdv(unsigned long cpr_fbdv)
720 for (index = 0; index < ARRAY_SIZE(ibm405ex_fbdv_multi_bits); index++)
721 if (cpr_fbdv == (u32)ibm405ex_fbdv_multi_bits[index])
727 void ibm405ex_fixup_clocks(unsigned int sys_clk, unsigned int uart_clk)
730 u32 pllc = CPR0_READ(DCRN_CPR0_PLLC);
731 u32 plld = CPR0_READ(DCRN_CPR0_PLLD);
732 u32 cpud = CPR0_READ(DCRN_CPR0_PRIMAD);
733 u32 plbd = CPR0_READ(DCRN_CPR0_PRIMBD);
734 u32 opbd = CPR0_READ(DCRN_CPR0_OPBD);
735 u32 perd = CPR0_READ(DCRN_CPR0_PERD);
738 u32 fbdv = ibm405ex_get_fbdv(__fix_zero((plld >> 24) & 0xff, 1));
740 u32 fwdva = ibm405ex_get_fwdva(__fix_zero((plld >> 16) & 0x0f, 1));
742 u32 cpudv0 = __fix_zero((cpud >> 24) & 7, 8);
744 /* PLBDV0 is hardwared to 010. */
746 u32 plb2xdv0 = __fix_zero((plbd >> 16) & 7, 8);
748 u32 opbdv0 = __fix_zero((opbd >> 24) & 3, 4);
750 u32 perdv0 = __fix_zero((perd >> 24) & 3, 4);
752 /* Resulting clocks */
753 u32 cpu, plb, opb, ebc, vco, tb, uart0, uart1;
755 /* PLL's VCO is the source for primary forward ? */
756 if (pllc & 0x40000000) {
760 switch ((pllc >> 24) & 7) {
767 m = fbdv * fwdva * cpudv0;
771 m = fbdv * fwdva * plb2xdv0 * plbdv0 * opbdv0 * perdv0;
774 printf("WARNING ! Invalid PLL feedback source !\n");
778 vco = (unsigned int)(sys_clk * m);
781 /* Bypass system PLL */
785 /* CPU = VCO / ( FWDVA x CPUDV0) */
786 cpu = vco / (fwdva * cpudv0);
787 /* PLB = VCO / ( FWDVA x PLB2XDV0 x PLBDV0) */
788 plb = vco / (fwdva * plb2xdv0 * plbdv0);
789 /* OPB = PLB / OPBDV0 */
791 /* EBC = OPB / PERDV0 */
795 uart0 = uart1 = uart_clk;
797 dt_fixup_cpu_clocks(cpu, tb, 0);
798 dt_fixup_clock("/plb", plb);
799 dt_fixup_clock("/plb/opb", opb);
800 dt_fixup_clock("/plb/opb/ebc", ebc);
801 dt_fixup_clock("/plb/opb/serial@ef600200", uart0);
802 dt_fixup_clock("/plb/opb/serial@ef600300", uart1);