Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
4xx.c
Go to the documentation of this file.
1 /*
2  * Copyright 2007 David Gibson, IBM Corporation.
3  *
4  * Based on earlier code:
5  * Matt Porter <[email protected]>
6  * Copyright 2002-2005 MontaVista Software Inc.
7  *
8  * Eugene Surovegin <[email protected]> or <[email protected]>
9  * Copyright (c) 2003, 2004 Zultys Technologies
10  *
11  * Copyright (C) 2009 Wind River Systems, Inc.
12  * Updated for supporting PPC405EX on Kilauea.
13  * Tiejun Chen <[email protected]>
14  *
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.
19  */
20 #include <stddef.h>
21 #include "types.h"
22 #include "string.h"
23 #include "stdio.h"
24 #include "ops.h"
25 #include "reg.h"
26 #include "dcr.h"
27 
28 static unsigned long chip_11_errata(unsigned long memsize)
29 {
30  unsigned long pvr;
31 
32  pvr = mfpvr();
33 
34  switch (pvr & 0xf0000ff0) {
35  case 0x40000850:
36  case 0x400008d0:
37  case 0x200008d0:
38  memsize -= 4096;
39  break;
40  default:
41  break;
42  }
43 
44  return memsize;
45 }
46 
47 /* Read the 4xx SDRAM controller to get size of system memory. */
49 {
50  int i;
51  unsigned long memsize, bank_config;
52 
53  memsize = 0;
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);
58  }
59 
60  memsize = chip_11_errata(memsize);
61  dt_fixup_memory(0, memsize);
62 }
63 
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
69 
70 static u64 ibm440spe_decode_bas(u32 bas)
71 {
72  u64 base = ((u64)(bas & 0xFFE00000u)) << 2;
73 
74  /* open coded because I'm paranoid about invalid values */
75  switch ((bas >> 4) & 0xFFF) {
76  case 0:
77  return 0;
78  case 0xffc:
79  return base + 0x000800000ull;
80  case 0xff8:
81  return base + 0x001000000ull;
82  case 0xff0:
83  return base + 0x002000000ull;
84  case 0xfe0:
85  return base + 0x004000000ull;
86  case 0xfc0:
87  return base + 0x008000000ull;
88  case 0xf80:
89  return base + 0x010000000ull;
90  case 0xf00:
91  return base + 0x020000000ull;
92  case 0xe00:
93  return base + 0x040000000ull;
94  case 0xc00:
95  return base + 0x080000000ull;
96  case 0x800:
97  return base + 0x100000000ull;
98  }
99  printf("Memory BAS value 0x%08x unsupported !\n", bas);
100  return 0;
101 }
102 
104 {
105  u64 banktop, memsize = 0;
106 
107  /* Ultimately, we should directly construct the memory node
108  * so we are able to handle holes in the memory address space
109  */
110  banktop = ibm440spe_decode_bas(mfdcr(DCRN_MQ0_B0BAS));
111  if (banktop > memsize)
112  memsize = banktop;
113  banktop = ibm440spe_decode_bas(mfdcr(DCRN_MQ0_B1BAS));
114  if (banktop > memsize)
115  memsize = banktop;
116  banktop = ibm440spe_decode_bas(mfdcr(DCRN_MQ0_B2BAS));
117  if (banktop > memsize)
118  memsize = banktop;
119  banktop = ibm440spe_decode_bas(mfdcr(DCRN_MQ0_B3BAS));
120  if (banktop > memsize)
121  memsize = banktop;
122 
123  dt_fixup_memory(0, memsize);
124 }
125 
126 
127 /* 4xx DDR1/2 Denali memory controller support */
128 /* DDR0 registers */
129 #define DDR0_02 2
130 #define DDR0_08 8
131 #define DDR0_10 10
132 #define DDR0_14 14
133 #define DDR0_42 42
134 #define DDR0_43 43
135 
136 /* DDR0_02 */
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
145 /* DDR0_08 */
146 #define DDR_DDR2_MODE 0x1
147 #define DDR_DDR2_MODE_SHIFT 0
148 /* DDR0_10 */
149 #define DDR_CS_MAP 0x3
150 #define DDR_CS_MAP_SHIFT 8
151 /* DDR0_14 */
152 #define DDR_REDUC 0x1
153 #define DDR_REDUC_SHIFT 16
154 /* DDR0_42 */
155 #define DDR_APIN 0x7
156 #define DDR_APIN_SHIFT 24
157 /* DDR0_43 */
158 #define DDR_COL_SZ 0x7
159 #define DDR_COL_SZ_SHIFT 8
160 #define DDR_BANK8 0x1
161 #define DDR_BANK8_SHIFT 0
162 
163 #define DDR_GET_VAL(val, mask, shift) (((val) >> (shift)) & (mask))
164 
165 /*
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.
171  */
172 static inline u32 ibm4xx_denali_get_cs(void)
173 {
174  void *devp;
175  char model[64];
176  u32 val, cs;
177 
178  devp = finddevice("/");
179  if (!devp)
180  goto read_cs;
181 
182  if (getprop(devp, "model", model, sizeof(model)) <= 0)
183  goto read_cs;
184 
185  model[sizeof(model)-1] = 0;
186 
187  if (!strcmp(model, "amcc,sequoia") ||
188  !strcmp(model, "amcc,rainier"))
189  return 1;
190 
191 read_cs:
192  /* get CS value */
193  val = SDRAM0_READ(DDR0_10);
194 
196  cs = 0;
197  while (val) {
198  if (val & 0x1)
199  cs++;
200  val = val >> 1;
201  }
202  return cs;
203 }
204 
206 {
207  u32 val, max_cs, max_col, max_row;
208  u32 cs, col, row, bank, dpath;
209  unsigned long memsize;
210 
211  val = SDRAM0_READ(DDR0_02);
213  fatal("DDR controller is not initialized\n");
214 
215  /* get maximum cs col and row values */
219 
220  cs = ibm4xx_denali_get_cs();
221  if (!cs)
222  fatal("No memory installed\n");
223  if (cs > max_cs)
224  fatal("DDR wrong CS configuration\n");
225 
226  /* get data path bytes */
227  val = SDRAM0_READ(DDR0_14);
228 
230  dpath = 4; /* 32 bits */
231  else
232  dpath = 8; /* 64 bits */
233 
234  /* get address pins (rows) */
235  val = SDRAM0_READ(DDR0_42);
236 
237  row = DDR_GET_VAL(val, DDR_APIN, DDR_APIN_SHIFT);
238  if (row > max_row)
239  fatal("DDR wrong APIN configuration\n");
240  row = max_row - row;
241 
242  /* get collomn size and banks */
243  val = SDRAM0_READ(DDR0_43);
244 
246  if (col > max_col)
247  fatal("DDR wrong COL configuration\n");
248  col = max_col - col;
249 
251  bank = 8; /* 8 banks */
252  else
253  bank = 4; /* 4 banks */
254 
255  memsize = cs * (1 << (col+row)) * bank * dpath;
256  memsize = chip_11_errata(memsize);
257  dt_fixup_memory(0, memsize);
258 }
259 
260 #define SPRN_DBCR0_40X 0x3F2
261 #define SPRN_DBCR0_44X 0x134
262 #define DBCR0_RST_SYSTEM 0x30000000
263 
265 {
266  unsigned long tmp;
267 
268  asm volatile (
269  "mfspr %0,%1\n"
270  "oris %0,%0,%2@h\n"
271  "mtspr %1,%0"
272  : "=&r"(tmp) : "i"(SPRN_DBCR0_44X), "i"(DBCR0_RST_SYSTEM)
273  );
274 
275 }
276 
278 {
279  unsigned long tmp;
280 
281  asm volatile (
282  "mfspr %0,%1\n"
283  "oris %0,%0,%2@h\n"
284  "mtspr %1,%0"
285  : "=&r"(tmp) : "i"(SPRN_DBCR0_40X), "i"(DBCR0_RST_SYSTEM)
286  );
287 }
288 
289 #define EMAC_RESET 0x20000000
290 void ibm4xx_quiesce_eth(u32 *emac0, u32 *emac1)
291 {
292  /* Quiesce the MAL and EMAC(s) since PIBS/OpenBIOS don't
293  * do this for us
294  */
295  if (emac0)
296  *emac0 = EMAC_RESET;
297  if (emac1)
298  *emac1 = EMAC_RESET;
299 
301  while (mfdcr(DCRN_MAL0_CFG) & MAL_RESET)
302  ; /* loop until reset takes effect */
303 }
304 
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)
308 {
309  void *devp;
310  u32 bxcr;
311  u32 ranges[EBC_NUM_BANKS*4];
312  u32 *p = ranges;
313  int i;
314 
315  for (i = 0; i < EBC_NUM_BANKS; i++) {
317  bxcr = mfdcr(DCRN_EBC0_CFGDATA);
318 
319  if ((bxcr & EBC_BXCR_BU) != EBC_BXCR_BU_OFF) {
320  *p++ = i;
321  *p++ = 0;
322  *p++ = bxcr & EBC_BXCR_BAS;
323  *p++ = EBC_BXCR_BANK_SIZE(bxcr);
324  }
325  }
326 
327  devp = finddevice(ebc);
328  if (! devp)
329  fatal("Couldn't locate EBC node %s\n\r", ebc);
330 
331  setprop(devp, "ranges", ranges, (p - ranges) * sizeof(u32));
332 }
333 
334 /* Calculate 440GP clocks */
335 void ibm440gp_fixup_clocks(unsigned int sys_clk, unsigned int ser_clk)
336 {
337  u32 sys0 = mfdcr(DCRN_CPC0_SYS0);
339  u32 cpu, plb, opb, ebc, tb, uart0, uart1, m;
340  u32 opdv = CPC0_SYS0_OPDV(sys0);
341  u32 epdv = CPC0_SYS0_EPDV(sys0);
342 
343  if (sys0 & CPC0_SYS0_BYPASS) {
344  /* Bypass system PLL */
345  cpu = plb = sys_clk;
346  } else {
347  if (sys0 & CPC0_SYS0_EXTSL)
348  /* PerClk */
349  m = CPC0_SYS0_FWDVB(sys0) * opdv * epdv;
350  else
351  /* CPU clock */
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);
355  }
356 
357  opb = plb / opdv;
358  ebc = opb / epdv;
359 
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 */
363  tb = sys_clk;
364  else
365  /* Rev. C 440GP, errata force us to use internal clock */
366  tb = cpu;
367 
368  if (cr0 & CPC0_CR0_U0EC)
369  /* External UART clock */
370  uart0 = ser_clk;
371  else
372  /* Internal UART clock */
373  uart0 = plb / CPC0_CR0_UDIV(cr0);
374 
375  if (cr0 & CPC0_CR0_U1EC)
376  /* External UART clock */
377  uart1 = ser_clk;
378  else
379  /* Internal UART clock */
380  uart1 = plb / CPC0_CR0_UDIV(cr0);
381 
382  printf("PPC440GP: SysClk = %dMHz (%x)\n\r",
383  (sys_clk + 500000) / 1000000, sys_clk);
384 
385  dt_fixup_cpu_clocks(cpu, tb, 0);
386 
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);
392 }
393 
394 #define SPRN_CCR1 0x378
395 
396 static inline u32 __fix_zero(u32 v, u32 def)
397 {
398  return v ? v : def;
399 }
400 
401 static unsigned int __ibm440eplike_fixup_clocks(unsigned int sys_clk,
402  unsigned int tmr_clk,
403  int per_clk_from_opb)
404 {
405  /* PLL config */
406  u32 pllc = CPR0_READ(DCRN_CPR0_PLLC);
407  u32 plld = CPR0_READ(DCRN_CPR0_PLLD);
408 
409  /* Dividers */
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);
418 
419  /* Input clocks for primary dividers */
420  u32 clk_a, clk_b;
421 
422  /* Resulting clocks */
423  u32 cpu, plb, opb, ebc, vco;
424 
425  /* Timebase */
426  u32 ccr1, tb = tmr_clk;
427 
428  if (pllc & 0x40000000) {
429  u32 m;
430 
431  /* Feedback path */
432  switch ((pllc >> 24) & 7) {
433  case 0:
434  /* PLLOUTx */
435  m = ((pllc & 0x20000000) ? fwdvb : fwdva) * lfbdv;
436  break;
437  case 1:
438  /* CPU */
439  m = fwdva * pradv0;
440  break;
441  case 5:
442  /* PERClk */
443  m = fwdvb * prbdv0 * opbdv0 * perdv0;
444  break;
445  default:
446  printf("WARNING ! Invalid PLL feedback source !\n");
447  goto bypass;
448  }
449  m *= fbdv;
450  vco = sys_clk * m;
451  clk_a = vco / fwdva;
452  clk_b = vco / fwdvb;
453  } else {
454 bypass:
455  /* Bypass system PLL */
456  vco = 0;
457  clk_a = clk_b = sys_clk;
458  }
459 
460  cpu = clk_a / pradv0;
461  plb = clk_b / prbdv0;
462  opb = plb / opbdv0;
463  ebc = (per_clk_from_opb ? opb : plb) / perdv0;
464 
465  /* Figure out timebase. Either CPU or default TmrClk */
466  ccr1 = mfspr(SPRN_CCR1);
467 
468  /* If passed a 0 tmr_clk, force CPU clock */
469  if (tb == 0) {
470  ccr1 &= ~0x80u;
471  mtspr(SPRN_CCR1, ccr1);
472  }
473  if ((ccr1 & 0x0080) == 0)
474  tb = cpu;
475 
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);
480 
481  return plb;
482 }
483 
484 static void eplike_fixup_uart_clk(int index, const char *path,
485  unsigned int ser_clk,
486  unsigned int plb_clk)
487 {
488  unsigned int sdr;
489  unsigned int clock;
490 
491  switch (index) {
492  case 0:
493  sdr = SDR0_READ(DCRN_SDR0_UART0);
494  break;
495  case 1:
496  sdr = SDR0_READ(DCRN_SDR0_UART1);
497  break;
498  case 2:
499  sdr = SDR0_READ(DCRN_SDR0_UART2);
500  break;
501  case 3:
502  sdr = SDR0_READ(DCRN_SDR0_UART3);
503  break;
504  default:
505  return;
506  }
507 
508  if (sdr & 0x00800000u)
509  clock = ser_clk;
510  else
511  clock = plb_clk / __fix_zero(sdr & 0xff, 256);
512 
513  dt_fixup_clock(path, clock);
514 }
515 
516 void ibm440ep_fixup_clocks(unsigned int sys_clk,
517  unsigned int ser_clk,
518  unsigned int tmr_clk)
519 {
520  unsigned int plb_clk = __ibm440eplike_fixup_clocks(sys_clk, tmr_clk, 0);
521 
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);
527 }
528 
529 void ibm440gx_fixup_clocks(unsigned int sys_clk,
530  unsigned int ser_clk,
531  unsigned int tmr_clk)
532 {
533  unsigned int plb_clk = __ibm440eplike_fixup_clocks(sys_clk, tmr_clk, 1);
534 
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);
538 }
539 
540 void ibm440spe_fixup_clocks(unsigned int sys_clk,
541  unsigned int ser_clk,
542  unsigned int tmr_clk)
543 {
544  unsigned int plb_clk = __ibm440eplike_fixup_clocks(sys_clk, tmr_clk, 1);
545 
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);
550 }
551 
552 void ibm405gp_fixup_clocks(unsigned int sys_clk, unsigned int ser_clk)
553 {
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);
558  u32 cpu, plb, opb, ebc, tb, uart0, uart1, m;
559  u32 fwdv, fwdvb, fbdv, cbdv, opdv, epdv, ppdv, udiv;
560 
561  fwdv = (8 - ((pllmr & 0xe0000000) >> 29));
562  fbdv = (pllmr & 0x1e000000) >> 25;
563  if (fbdv == 0)
564  fbdv = 16;
565  cbdv = ((pllmr & 0x00060000) >> 17) + 1; /* CPU:PLB */
566  opdv = ((pllmr & 0x00018000) >> 15) + 1; /* PLB:OPB */
567  ppdv = ((pllmr & 0x00001800) >> 13) + 1; /* PLB:PCI */
568  epdv = ((pllmr & 0x00001800) >> 11) + 2; /* PLB:EBC */
569  udiv = ((cpc0_cr0 & 0x3e) >> 1) + 1;
570 
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;
577  else
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;
582  else
583  m = fbdv * fwdv;
584  else if (epdv == fbdv)
585  m = fbdv * cbdv * epdv;
586  else
587  m = fbdv * fwdvb * cbdv;
588 
589  cpu = sys_clk * m / fwdv;
590  plb = sys_clk * m / (fwdvb * cbdv);
591  } else {
592  m = fwdv * fbdv * cbdv;
593  cpu = sys_clk * m / fwdv;
594  plb = cpu / cbdv;
595  }
596  opb = plb / opdv;
597  ebc = plb / epdv;
598 
599  if (cpc0_cr0 & 0x80)
600  /* uart0 uses the external clock */
601  uart0 = ser_clk;
602  else
603  uart0 = cpu / udiv;
604 
605  if (cpc0_cr0 & 0x40)
606  /* uart1 uses the external clock */
607  uart1 = ser_clk;
608  else
609  uart1 = cpu / udiv;
610 
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);
614  tb = cpu;
615 
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);
622 }
623 
624 
625 void ibm405ep_fixup_clocks(unsigned int sys_clk)
626 {
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;
633 
634  fwdva = 8 - ((pllmr1 & 0x00070000) >> 16);
635  fwdvb = 8 - ((pllmr1 & 0x00007000) >> 12);
636  fbdv = (pllmr1 & 0x00f00000) >> 20;
637  if (fbdv == 0)
638  fbdv = 16;
639 
640  cbdv = ((pllmr0 & 0x00030000) >> 16) + 1; /* CPU:PLB */
641  epdv = ((pllmr0 & 0x00000300) >> 8) + 2; /* PLB:EBC */
642  opdv = ((pllmr0 & 0x00003000) >> 12) + 1; /* PLB:OPB */
643 
644  m = fbdv * fwdvb;
645 
646  pllmr0_ccdv = ((pllmr0 & 0x00300000) >> 20) + 1;
647  if (pllmr1 & 0x80000000)
648  cpu = sys_clk * m / (fwdva * pllmr0_ccdv);
649  else
650  cpu = sys_clk / pllmr0_ccdv;
651 
652  plb = cpu / cbdv;
653  opb = plb / opdv;
654  ebc = plb / epdv;
655  tb = cpu;
656  uart0 = cpu / (cpc0_ucr & 0x0000007f);
657  uart1 = cpu / ((cpc0_ucr & 0x00007f00) >> 8);
658 
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);
665 }
666 
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
671 };
672 
673 u32 ibm405ex_get_fwdva(unsigned long cpr_fwdv)
674 {
675  u32 index;
676 
677  for (index = 0; index < ARRAY_SIZE(ibm405ex_fwdv_multi_bits); index++)
678  if (cpr_fwdv == (u32)ibm405ex_fwdv_multi_bits[index])
679  return index + 1;
680 
681  return 0;
682 }
683 
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 */
714 };
715 
716 u32 ibm405ex_get_fbdv(unsigned long cpr_fbdv)
717 {
718  u32 index;
719 
720  for (index = 0; index < ARRAY_SIZE(ibm405ex_fbdv_multi_bits); index++)
721  if (cpr_fbdv == (u32)ibm405ex_fbdv_multi_bits[index])
722  return index + 1;
723 
724  return 0;
725 }
726 
727 void ibm405ex_fixup_clocks(unsigned int sys_clk, unsigned int uart_clk)
728 {
729  /* PLL config */
730  u32 pllc = CPR0_READ(DCRN_CPR0_PLLC);
731  u32 plld = CPR0_READ(DCRN_CPR0_PLLD);
734  u32 opbd = CPR0_READ(DCRN_CPR0_OPBD);
735  u32 perd = CPR0_READ(DCRN_CPR0_PERD);
736 
737  /* Dividers */
738  u32 fbdv = ibm405ex_get_fbdv(__fix_zero((plld >> 24) & 0xff, 1));
739 
740  u32 fwdva = ibm405ex_get_fwdva(__fix_zero((plld >> 16) & 0x0f, 1));
741 
742  u32 cpudv0 = __fix_zero((cpud >> 24) & 7, 8);
743 
744  /* PLBDV0 is hardwared to 010. */
745  u32 plbdv0 = 2;
746  u32 plb2xdv0 = __fix_zero((plbd >> 16) & 7, 8);
747 
748  u32 opbdv0 = __fix_zero((opbd >> 24) & 3, 4);
749 
750  u32 perdv0 = __fix_zero((perd >> 24) & 3, 4);
751 
752  /* Resulting clocks */
753  u32 cpu, plb, opb, ebc, vco, tb, uart0, uart1;
754 
755  /* PLL's VCO is the source for primary forward ? */
756  if (pllc & 0x40000000) {
757  u32 m;
758 
759  /* Feedback path */
760  switch ((pllc >> 24) & 7) {
761  case 0:
762  /* PLLOUTx */
763  m = fbdv;
764  break;
765  case 1:
766  /* CPU */
767  m = fbdv * fwdva * cpudv0;
768  break;
769  case 5:
770  /* PERClk */
771  m = fbdv * fwdva * plb2xdv0 * plbdv0 * opbdv0 * perdv0;
772  break;
773  default:
774  printf("WARNING ! Invalid PLL feedback source !\n");
775  goto bypass;
776  }
777 
778  vco = (unsigned int)(sys_clk * m);
779  } else {
780 bypass:
781  /* Bypass system PLL */
782  vco = 0;
783  }
784 
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 */
790  opb = plb / opbdv0;
791  /* EBC = OPB / PERDV0 */
792  ebc = opb / perdv0;
793 
794  tb = cpu;
795  uart0 = uart1 = uart_clk;
796 
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);
803 }