~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/powerpc/boot/4xx.c

Version: ~ [ linux-5.9.1 ] ~ [ linux-5.8.16 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.72 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.152 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.202 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.240 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.240 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.85 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  * Copyright 2007 David Gibson, IBM Corporation.
  3  *
  4  * Based on earlier code:
  5  *   Matt Porter <mporter@kernel.crashing.org>
  6  *   Copyright 2002-2005 MontaVista Software Inc.
  7  *
  8  *   Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
  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 <tiejun.chen@windriver.com>
 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. */
 48 void ibm4xx_sdram_fixup_memsize(void)
 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 
103 void ibm440spe_fixup_memsize(void)
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 
195         val = DDR_GET_VAL(val, DDR_CS_MAP, DDR_CS_MAP_SHIFT);
196         cs = 0;
197         while (val) {
198                 if (val & 0x1)
199                         cs++;
200                 val = val >> 1;
201         }
202         return cs;
203 }
204 
205 void ibm4xx_denali_fixup_memsize(void)
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);
212         if (!DDR_GET_VAL(val, DDR_START, DDR_START_SHIFT))
213                 fatal("DDR controller is not initialized\n");
214 
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);
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 
229         if (DDR_GET_VAL(val, DDR_REDUC, DDR_REDUC_SHIFT))
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 
245         col = DDR_GET_VAL(val, DDR_COL_SZ, DDR_COL_SZ_SHIFT);
246         if (col > max_col)
247                 fatal("DDR wrong COL configuration\n");
248         col = max_col - col;
249 
250         if (DDR_GET_VAL(val, DDR_BANK8, DDR_BANK8_SHIFT))
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 
264 void ibm44x_dbcr_reset(void)
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 
277 void ibm40x_dbcr_reset(void)
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 
300         mtdcr(DCRN_MAL0_CFG, MAL_RESET);
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++) {
316                 mtdcr(DCRN_EBC0_CFGADDR, EBC_BXCR(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);
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);
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);
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;
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);
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);
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 }
804 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp