OSDN Git Service

smb3: Add defines for new information level, FileIdInformation
[tomoyo/tomoyo-test1.git] / arch / powerpc / boot / 4xx.c
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 }