add all source code from linksys/broadcom which is free, to cvs for better maintainen...
[openwrt.git] / package / linux / kernel-source / arch / mips / brcm-boards / bcm947xx / sbmips.c
1 /*
2  * BCM47XX Sonics SiliconBackplane MIPS core routines
3  *
4  * Copyright 2004, Broadcom Corporation
5  * All Rights Reserved.
6  * 
7  * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
8  * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
9  * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
10  * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
11  *
12  * $Id$
13  */
14
15 #include <typedefs.h>
16 #include <osl.h>
17 #include <sbutils.h>
18 #include <bcmdevs.h>
19 #include <bcmnvram.h>
20 #include <bcmutils.h>
21 #include <hndmips.h>
22 #include <sbconfig.h>
23 #include <sbextif.h>
24 #include <sbchipc.h>
25 #include <sbmemc.h>
26
27 /*
28  * Memory segments (32bit kernel mode addresses)
29  */
30 #undef KUSEG
31 #undef KSEG0
32 #undef KSEG1
33 #undef KSEG2
34 #undef KSEG3
35 #define KUSEG           0x00000000
36 #define KSEG0           0x80000000
37 #define KSEG1           0xa0000000
38 #define KSEG2           0xc0000000
39 #define KSEG3           0xe0000000
40
41 /*
42  * Map an address to a certain kernel segment
43  */
44 #undef KSEG0ADDR
45 #undef KSEG1ADDR
46 #undef KSEG2ADDR
47 #undef KSEG3ADDR
48 #define KSEG0ADDR(a)            (((a) & 0x1fffffff) | KSEG0)
49 #define KSEG1ADDR(a)            (((a) & 0x1fffffff) | KSEG1)
50 #define KSEG2ADDR(a)            (((a) & 0x1fffffff) | KSEG2)
51 #define KSEG3ADDR(a)            (((a) & 0x1fffffff) | KSEG3)
52
53 /*
54  * The following macros are especially useful for __asm__
55  * inline assembler.
56  */
57 #ifndef __STR
58 #define __STR(x) #x
59 #endif
60 #ifndef STR
61 #define STR(x) __STR(x)
62 #endif
63
64 /*  *********************************************************************
65     *  CP0 Registers 
66     ********************************************************************* */
67
68 #define C0_INX          0               /* CP0: TLB Index */
69 #define C0_RAND         1               /* CP0: TLB Random */
70 #define C0_TLBLO0       2               /* CP0: TLB EntryLo0 */
71 #define C0_TLBLO        C0_TLBLO0       /* CP0: TLB EntryLo0 */
72 #define C0_TLBLO1       3               /* CP0: TLB EntryLo1 */
73 #define C0_CTEXT        4               /* CP0: Context */
74 #define C0_PGMASK       5               /* CP0: TLB PageMask */
75 #define C0_WIRED        6               /* CP0: TLB Wired */
76 #define C0_BADVADDR     8               /* CP0: Bad Virtual Address */
77 #define C0_COUNT        9               /* CP0: Count */
78 #define C0_TLBHI        10              /* CP0: TLB EntryHi */
79 #define C0_COMPARE      11              /* CP0: Compare */
80 #define C0_SR           12              /* CP0: Processor Status */
81 #define C0_STATUS       C0_SR           /* CP0: Processor Status */
82 #define C0_CAUSE        13              /* CP0: Exception Cause */
83 #define C0_EPC          14              /* CP0: Exception PC */
84 #define C0_PRID         15              /* CP0: Processor Revision Indentifier */
85 #define C0_CONFIG       16              /* CP0: Config */
86 #define C0_LLADDR       17              /* CP0: LLAddr */
87 #define C0_WATCHLO      18              /* CP0: WatchpointLo */
88 #define C0_WATCHHI      19              /* CP0: WatchpointHi */
89 #define C0_XCTEXT       20              /* CP0: XContext */
90 #define C0_DIAGNOSTIC   22              /* CP0: Diagnostic */
91 #define C0_BROADCOM     C0_DIAGNOSTIC   /* CP0: Broadcom Register */
92 #define C0_ECC          26              /* CP0: ECC */
93 #define C0_CACHEERR     27              /* CP0: CacheErr */
94 #define C0_TAGLO        28              /* CP0: TagLo */
95 #define C0_TAGHI        29              /* CP0: TagHi */
96 #define C0_ERREPC       30              /* CP0: ErrorEPC */
97
98 /*
99  * Macros to access the system control coprocessor
100  */
101
102 #define MFC0(source, sel)                                       \
103 ({                                                              \
104         int __res;                                              \
105         __asm__ __volatile__(                                   \
106         ".set\tnoreorder\n\t"                                   \
107         ".set\tnoat\n\t"                                        \
108         ".word\t"STR(0x40010000 | ((source)<<11) | (sel))"\n\t" \
109         "move\t%0,$1\n\t"                                       \
110         ".set\tat\n\t"                                          \
111         ".set\treorder"                                         \
112         :"=r" (__res)                                           \
113         :                                                       \
114         :"$1");                                                 \
115         __res;                                                  \
116 })
117
118 #define MTC0(source, sel, value)                                \
119 do {                                                            \
120         __asm__ __volatile__(                                   \
121         ".set\tnoreorder\n\t"                                   \
122         ".set\tnoat\n\t"                                        \
123         "move\t$1,%z0\n\t"                                      \
124         ".word\t"STR(0x40810000 | ((source)<<11) | (sel))"\n\t" \
125         ".set\tat\n\t"                                          \
126         ".set\treorder"                                         \
127         :                                                       \
128         :"Jr" (value)                                           \
129         :"$1");                                                 \
130 } while (0)
131
132 /*
133  * R4x00 interrupt enable / cause bits
134  */
135 #undef IE_SW0
136 #undef IE_SW1
137 #undef IE_IRQ0
138 #undef IE_IRQ1
139 #undef IE_IRQ2
140 #undef IE_IRQ3
141 #undef IE_IRQ4
142 #undef IE_IRQ5
143 #define IE_SW0          (1<< 8)
144 #define IE_SW1          (1<< 9)
145 #define IE_IRQ0         (1<<10)
146 #define IE_IRQ1         (1<<11)
147 #define IE_IRQ2         (1<<12)
148 #define IE_IRQ3         (1<<13)
149 #define IE_IRQ4         (1<<14)
150 #define IE_IRQ5         (1<<15)
151
152 /*
153  * Bitfields in the R4xx0 cp0 status register
154  */
155 #define ST0_IE                  0x00000001
156 #define ST0_EXL                 0x00000002
157 #define ST0_ERL                 0x00000004
158 #define ST0_KSU                 0x00000018
159 #  define KSU_USER              0x00000010
160 #  define KSU_SUPERVISOR        0x00000008
161 #  define KSU_KERNEL            0x00000000
162 #define ST0_UX                  0x00000020
163 #define ST0_SX                  0x00000040
164 #define ST0_KX                  0x00000080
165 #define ST0_DE                  0x00010000
166 #define ST0_CE                  0x00020000
167
168 /*
169  * Status register bits available in all MIPS CPUs.
170  */
171 #define ST0_IM                  0x0000ff00
172 #define ST0_CH                  0x00040000
173 #define ST0_SR                  0x00100000
174 #define ST0_TS                  0x00200000
175 #define ST0_BEV                 0x00400000
176 #define ST0_RE                  0x02000000
177 #define ST0_FR                  0x04000000
178 #define ST0_CU                  0xf0000000
179 #define ST0_CU0                 0x10000000
180 #define ST0_CU1                 0x20000000
181 #define ST0_CU2                 0x40000000
182 #define ST0_CU3                 0x80000000
183 #define ST0_XX                  0x80000000      /* MIPS IV naming */
184
185 /*
186  * Cache Operations
187  */
188
189 #ifndef Fill_I
190 #define Fill_I                  0x14
191 #endif
192
193 #define cache_unroll(base,op)                   \
194         __asm__ __volatile__("                  \
195                 .set noreorder;                 \
196                 .set mips3;                     \
197                 cache %1, (%0);                 \
198                 .set mips0;                     \
199                 .set reorder"                   \
200                 :                               \
201                 : "r" (base),                   \
202                   "i" (op));
203
204 /* 
205  * These are the UART port assignments, expressed as offsets from the base
206  * register.  These assignments should hold for any serial port based on
207  * a 8250, 16450, or 16550(A).
208  */
209
210 #define UART_MCR        4       /* Out: Modem Control Register */
211 #define UART_MSR        6       /* In:  Modem Status Register */
212 #define UART_MCR_LOOP   0x10    /* Enable loopback test mode */
213
214 /* 
215  * Returns TRUE if an external UART exists at the given base
216  * register.
217  */
218 static bool
219 serial_exists(uint8 *regs)
220 {
221         uint8 save_mcr, status1;
222
223         save_mcr = R_REG(&regs[UART_MCR]);
224         W_REG(&regs[UART_MCR], UART_MCR_LOOP | 0x0a);
225         status1 = R_REG(&regs[UART_MSR]) & 0xf0;
226         W_REG(&regs[UART_MCR], save_mcr);
227
228         return (status1 == 0x90);
229 }
230
231 /* 
232  * Initializes UART access. The callback function will be called once
233  * per found UART.
234 */
235 void
236 sb_serial_init(void *sbh, void (*add)(void *regs, uint irq, uint baud_base, uint reg_shift))
237 {
238         void *regs;
239         ulong base;
240         uint irq;
241         int i, n;
242
243         if ((regs = sb_setcore(sbh, SB_EXTIF, 0))) {
244                 extifregs_t *eir = (extifregs_t *) regs;
245                 sbconfig_t *sb;
246
247                 /* Determine external UART register base */
248                 sb = (sbconfig_t *)((ulong) eir + SBCONFIGOFF);
249                 base = EXTIF_CFGIF_BASE(sb_base(R_REG(&sb->sbadmatch1)));
250
251                 /* Determine IRQ */
252                 irq = sb_irq(sbh);
253
254                 /* Disable GPIO interrupt initially */
255                 W_REG(&eir->gpiointpolarity, 0);
256                 W_REG(&eir->gpiointmask, 0);
257
258                 /* Search for external UARTs */
259                 n = 2;
260                 for (i = 0; i < 2; i++) {
261                         regs = (void *) REG_MAP(base + (i * 8), 8);
262                         if (serial_exists(regs)) {
263                                 /* Set GPIO 1 to be the external UART IRQ */
264                                 W_REG(&eir->gpiointmask, 2);
265                                 if (add)
266                                         add(regs, irq, 13500000, 0);
267                         }
268                 }
269
270                 /* Add internal UART if enabled */
271                 if (R_REG(&eir->corecontrol) & CC_UE)
272                         if (add)
273                                 add((void *) &eir->uartdata, irq, sb_clock(sbh), 2);
274         } else if ((regs = sb_setcore(sbh, SB_CC, 0))) {
275                 chipcregs_t *cc = (chipcregs_t *) regs;
276                 uint32 rev, cap, pll, baud_base, div;
277
278                 /* Determine core revision and capabilities */
279                 rev = sb_corerev(sbh);
280                 cap = R_REG(&cc->capabilities);
281                 pll = cap & CAP_PLL_MASK;
282
283                 /* Determine IRQ */
284                 irq = sb_irq(sbh);
285
286                 if (pll == PLL_TYPE1) {
287                         /* PLL clock */
288                         baud_base = sb_clock_rate(pll,
289                                                   R_REG(&cc->clockcontrol_n),
290                                                   R_REG(&cc->clockcontrol_m2));
291                         div = 1;
292                 } else if (rev >= 3) {
293                         /* Internal backplane clock */
294                         baud_base = sb_clock_rate(pll,
295                                                   R_REG(&cc->clockcontrol_n),
296                                                   R_REG(&cc->clockcontrol_sb));
297                         div = 2;        /* Minimum divisor */
298                         W_REG(&cc->clkdiv, ((R_REG(&cc->clkdiv) & ~CLKD_UART) | div));
299                 } else {
300                         /* Fixed internal backplane clock */
301                         baud_base = 88000000;
302                         div = 48;
303                 }
304
305                 /* Clock source depends on strapping if UartClkOverride is unset */
306                 if ((rev > 0) && ((R_REG(&cc->corecontrol) & CC_UARTCLKO) == 0)) {
307                         if ((cap & CAP_UCLKSEL) == CAP_UINTCLK) {
308                                 /* Internal divided backplane clock */
309                                 baud_base /= div;
310                         } else {
311                                 /* Assume external clock of 1.8432 MHz */
312                                 baud_base = 1843200;
313                         }
314                 }
315
316                 /* Add internal UARTs */
317                 n = cap & CAP_UARTS_MASK;
318                 for (i = 0; i < n; i++) {
319                         /* Register offset changed after revision 0 */
320                         if (rev)
321                                 regs = (void *)((ulong) &cc->uart0data + (i * 256));
322                         else
323                                 regs = (void *)((ulong) &cc->uart0data + (i * 8));
324
325                         if (add)
326                                 add(regs, irq, baud_base, 0);
327                 }
328         }
329 }
330
331 /* Returns the SB interrupt flag of the current core. */
332 uint32
333 sb_flag(void *sbh)
334 {
335         void *regs;
336         sbconfig_t *sb;
337
338         regs = sb_coreregs(sbh);
339         sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF);
340
341         return (R_REG(&sb->sbtpsflag) & SBTPS_NUM0_MASK);
342 }
343
344 static const uint32 sbips_int_mask[] = {
345         0,
346         SBIPS_INT1_MASK,
347         SBIPS_INT2_MASK,
348         SBIPS_INT3_MASK,
349         SBIPS_INT4_MASK
350 };
351
352 static const uint32 sbips_int_shift[] = {
353         0,
354         0,
355         SBIPS_INT2_SHIFT,
356         SBIPS_INT3_SHIFT,
357         SBIPS_INT4_SHIFT
358 };
359
360 /* 
361  * Returns the MIPS IRQ assignment of the current core. If unassigned,
362  * 0 is returned.
363  */
364 uint
365 sb_irq(void *sbh)
366 {
367         uint idx;
368         void *regs;
369         sbconfig_t *sb;
370         uint32 flag, sbipsflag;
371         uint irq = 0;
372
373         flag = sb_flag(sbh);
374
375         idx = sb_coreidx(sbh);
376
377         if ((regs = sb_setcore(sbh, SB_MIPS, 0)) ||
378             (regs = sb_setcore(sbh, SB_MIPS33, 0))) {
379                 sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF);
380
381                 /* sbipsflag specifies which core is routed to interrupts 1 to 4 */
382                 sbipsflag = R_REG(&sb->sbipsflag);
383                 for (irq = 1; irq <= 4; irq++) {
384                         if (((sbipsflag & sbips_int_mask[irq]) >> sbips_int_shift[irq]) == flag)
385                                 break;
386                 }
387                 if (irq == 5)
388                         irq = 0;
389         }
390
391         sb_setcoreidx(sbh, idx);
392
393         return irq;
394 }
395
396 /* Clears the specified MIPS IRQ. */
397 static void
398 sb_clearirq(void *sbh, uint irq)
399 {
400         void *regs;
401         sbconfig_t *sb;
402
403         if (!(regs = sb_setcore(sbh, SB_MIPS, 0)) &&
404             !(regs = sb_setcore(sbh, SB_MIPS33, 0)))
405                 ASSERT(regs);
406         sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF);
407
408         if (irq == 0)
409                 W_REG(&sb->sbintvec, 0);
410         else
411                 OR_REG(&sb->sbipsflag, sbips_int_mask[irq]);
412 }
413
414 /* 
415  * Assigns the specified MIPS IRQ to the specified core. Shared MIPS
416  * IRQ 0 may be assigned more than once.
417  */
418 static void
419 sb_setirq(void *sbh, uint irq, uint coreid, uint coreunit)
420 {
421         void *regs;
422         sbconfig_t *sb;
423         uint32 flag;
424
425         regs = sb_setcore(sbh, coreid, coreunit);
426         ASSERT(regs);
427         flag = sb_flag(sbh);
428
429         if (!(regs = sb_setcore(sbh, SB_MIPS, 0)) &&
430             !(regs = sb_setcore(sbh, SB_MIPS33, 0)))
431                 ASSERT(regs);
432         sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF);
433
434         if (irq == 0)
435                 OR_REG(&sb->sbintvec, 1 << flag);
436         else {
437                 flag <<= sbips_int_shift[irq];
438                 ASSERT(!(flag & ~sbips_int_mask[irq]));
439                 flag |= R_REG(&sb->sbipsflag) & ~sbips_int_mask[irq];
440                 W_REG(&sb->sbipsflag, flag);
441         }
442 }       
443
444 /* 
445  * Initializes clocks and interrupts. SB and NVRAM access must be
446  * initialized prior to calling.
447  */
448 void
449 sb_mips_init(void *sbh)
450 {
451         ulong hz, ns, tmp;
452         extifregs_t *eir;
453         chipcregs_t *cc;
454         char *value;
455         uint irq;
456
457         /* Figure out current SB clock speed */
458         if ((hz = sb_clock(sbh)) == 0)
459                 hz = 100000000;
460         ns = 1000000000 / hz;
461
462         /* Setup external interface timing */
463         if ((eir = sb_setcore(sbh, SB_EXTIF, 0))) {
464                 /* Initialize extif so we can get to the LEDs and external UART */
465                 W_REG(&eir->prog_config, CF_EN);
466
467                 /* Set timing for the flash */
468                 tmp = CEIL(10, ns) << FW_W3_SHIFT;      /* W3 = 10nS */
469                 tmp = tmp | (CEIL(40, ns) << FW_W1_SHIFT); /* W1 = 40nS */
470                 tmp = tmp | CEIL(120, ns);              /* W0 = 120nS */
471                 W_REG(&eir->prog_waitcount, tmp);       /* 0x01020a0c for a 100Mhz clock */
472
473                 /* Set programmable interface timing for external uart */
474                 tmp = CEIL(10, ns) << FW_W3_SHIFT;      /* W3 = 10nS */
475                 tmp = tmp | (CEIL(20, ns) << FW_W2_SHIFT); /* W2 = 20nS */
476                 tmp = tmp | (CEIL(100, ns) << FW_W1_SHIFT); /* W1 = 100nS */
477                 tmp = tmp | CEIL(120, ns);              /* W0 = 120nS */
478                 W_REG(&eir->prog_waitcount, tmp);       /* 0x01020a0c for a 100Mhz clock */
479         } else if ((cc = sb_setcore(sbh, SB_CC, 0))) {
480                 /* Set timing for the flash */
481                 tmp = CEIL(10, ns) << FW_W3_SHIFT;      /* W3 = 10nS */
482                 tmp |= CEIL(10, ns) << FW_W1_SHIFT;     /* W1 = 10nS */
483                 tmp |= CEIL(120, ns);                   /* W0 = 120nS */
484                 W_REG(&cc->flash_waitcount, tmp);
485
486                 W_REG(&cc->pcmcia_memwait, tmp);
487         }
488
489         /* Chip specific initialization */
490         switch (sb_chip(sbh)) {
491         case BCM4710_DEVICE_ID:
492                 /* Clear interrupt map */
493                 for (irq = 0; irq <= 4; irq++)
494                         sb_clearirq(sbh, irq);
495                 sb_setirq(sbh, 0, SB_CODEC, 0);
496                 sb_setirq(sbh, 0, SB_EXTIF, 0);
497                 sb_setirq(sbh, 2, SB_ENET, 1);
498                 sb_setirq(sbh, 3, SB_ILINE20, 0);
499                 sb_setirq(sbh, 4, SB_PCI, 0);
500                 ASSERT(eir);
501                 value = nvram_get("et0phyaddr");
502                 if (value && !strcmp(value, "31")) {
503                         /* Enable internal UART */
504                         W_REG(&eir->corecontrol, CC_UE);
505                         /* Give USB its own interrupt */
506                         sb_setirq(sbh, 1, SB_USB, 0);
507                 } else {
508                         /* Disable internal UART */
509                         W_REG(&eir->corecontrol, 0);
510                         /* Give Ethernet its own interrupt */
511                         sb_setirq(sbh, 1, SB_ENET, 0);
512                         sb_setirq(sbh, 0, SB_USB, 0);
513                 }
514                 break;
515         case BCM4310_DEVICE_ID:
516                 MTC0(C0_BROADCOM, 0, MFC0(C0_BROADCOM, 0) & ~(1 << 22));
517                 break;
518         }
519 }
520
521 uint32
522 sb_mips_clock(void *sbh)
523 {
524         extifregs_t *eir;
525         chipcregs_t *cc;
526         uint32 n, m;
527         uint idx;
528         uint32 pll_type, rate = 0;
529
530         /* get index of the current core */
531         idx = sb_coreidx(sbh);
532         pll_type = PLL_TYPE1;
533
534         /* switch to extif or chipc core */
535         if ((eir = (extifregs_t *) sb_setcore(sbh, SB_EXTIF, 0))) {
536                 n = R_REG(&eir->clockcontrol_n);
537                 m = R_REG(&eir->clockcontrol_sb);
538         } else if ((cc = (chipcregs_t *) sb_setcore(sbh, SB_CC, 0))) {
539                 pll_type = R_REG(&cc->capabilities) & CAP_PLL_MASK;
540                 n = R_REG(&cc->clockcontrol_n);
541                 if ((pll_type == PLL_TYPE2) || (pll_type == PLL_TYPE4))
542                         m = R_REG(&cc->clockcontrol_mips);
543                 else if (pll_type == PLL_TYPE3) {
544                         rate = 200000000;
545                         goto out;
546                 } else
547                         m = R_REG(&cc->clockcontrol_sb);
548         } else
549                 goto out;
550
551         /* calculate rate */
552         rate = sb_clock_rate(pll_type, n, m);
553
554 out:
555         /* switch back to previous core */
556         sb_setcoreidx(sbh, idx);
557
558         return rate;
559 }
560
561 static void
562 icache_probe(int *size, int *lsize)
563 {
564         uint32 config1;
565         uint sets, ways;
566
567         config1 = MFC0(C0_CONFIG, 1);
568
569         /* Instruction Cache Size = Associativity * Line Size * Sets Per Way */
570         if ((*lsize = ((config1 >> 19) & 7)))
571                 *lsize = 2 << *lsize;
572         sets = 64 << ((config1 >> 22) & 7);
573         ways = 1 + ((config1 >> 16) & 7);
574         *size = *lsize * sets * ways;
575 }
576
577 #define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4)
578
579 static void
580 handler(void)
581 {
582         /* Step 11 */
583         __asm__ (
584                 ".set\tmips32\n\t"
585                 "ssnop\n\t"
586                 "ssnop\n\t"
587         /* Disable interrupts */
588         /*      MTC0(C0_STATUS, 0, MFC0(C0_STATUS, 0) & ~(ALLINTS | STO_IE)); */
589                 "mfc0 $15, $12\n\t"
590                 "and $15, $15, -31746\n\t"
591                 "mtc0 $15, $12\n\t"
592                 "eret\n\t"
593                 "nop\n\t"
594                 "nop\n\t"
595                 ".set\tmips0"
596         );
597 }
598
599 /* The following MUST come right after handler() */
600 static void
601 afterhandler(void)
602 {
603 }
604
605 /*
606  * Set the MIPS, backplane and PCI clocks as closely as possible.
607  */
608 bool
609 sb_mips_setclock(void *sbh, uint32 mipsclock, uint32 sbclock, uint32 pciclock)
610 {
611         extifregs_t *eir = NULL;
612         chipcregs_t *cc = NULL;
613         mipsregs_t *mipsr = NULL;
614         volatile uint32 *clockcontrol_n, *clockcontrol_sb, *clockcontrol_pci;
615         uint32 orig_n, orig_sb, orig_pci, orig_m2, orig_mips, orig_ratio_parm, new_ratio;
616         uint32 pll_type, sync_mode;
617         uint idx, i;
618         typedef struct {
619                 uint32 mipsclock;
620                 uint16 n;
621                 uint32 sb;
622                 uint32 pci33;
623                 uint32 pci25;
624         } n3m_table_t;
625         static n3m_table_t type1_table[] = {
626                 {  96000000, 0x0303, 0x04020011, 0x11030011, 0x11050011 }, /*  96.000 32.000 24.000 */
627                 { 100000000, 0x0009, 0x04020011, 0x11030011, 0x11050011 }, /* 100.000 33.333 25.000 */
628                 { 104000000, 0x0802, 0x04020011, 0x11050009, 0x11090009 }, /* 104.000 31.200 24.960 */
629                 { 108000000, 0x0403, 0x04020011, 0x11050009, 0x02000802 }, /* 108.000 32.400 24.923 */
630                 { 112000000, 0x0205, 0x04020011, 0x11030021, 0x02000403 }, /* 112.000 32.000 24.889 */
631                 { 115200000, 0x0303, 0x04020009, 0x11030011, 0x11050011 }, /* 115.200 32.000 24.000 */
632                 { 120000000, 0x0011, 0x04020011, 0x11050011, 0x11090011 }, /* 120.000 30.000 24.000 */
633                 { 124800000, 0x0802, 0x04020009, 0x11050009, 0x11090009 }, /* 124.800 31.200 24.960 */
634                 { 128000000, 0x0305, 0x04020011, 0x11050011, 0x02000305 }, /* 128.000 32.000 24.000 */
635                 { 132000000, 0x0603, 0x04020011, 0x11050011, 0x02000305 }, /* 132.000 33.000 24.750 */
636                 { 136000000, 0x0c02, 0x04020011, 0x11090009, 0x02000603 }, /* 136.000 32.640 24.727 */
637                 { 140000000, 0x0021, 0x04020011, 0x11050021, 0x02000c02 }, /* 140.000 30.000 24.706 */
638                 { 144000000, 0x0405, 0x04020011, 0x01020202, 0x11090021 }, /* 144.000 30.857 24.686 */
639                 { 150857142, 0x0605, 0x04020021, 0x02000305, 0x02000605 }, /* 150.857 33.000 24.000 */
640                 { 152000000, 0x0e02, 0x04020011, 0x11050021, 0x02000e02 }, /* 152.000 32.571 24.000 */
641                 { 156000000, 0x0802, 0x04020005, 0x11050009, 0x11090009 }, /* 156.000 31.200 24.960 */
642                 { 160000000, 0x0309, 0x04020011, 0x11090011, 0x02000309 }, /* 160.000 32.000 24.000 */
643                 { 163200000, 0x0c02, 0x04020009, 0x11090009, 0x02000603 }, /* 163.200 32.640 24.727 */
644                 { 168000000, 0x0205, 0x04020005, 0x11030021, 0x02000403 }, /* 168.000 32.000 24.889 */
645                 { 176000000, 0x0602, 0x04020003, 0x11050005, 0x02000602 }, /* 176.000 33.000 24.000 */
646         };
647         typedef struct {
648                 uint32 mipsclock;
649                 uint32 sbclock;
650                 uint16 n;
651                 uint32 sb;
652                 uint32 pci33;
653                 uint32 m2;
654                 uint32 m3;
655                 uint32 ratio;
656                 uint32 ratio_parm;
657         } n4m_table_t;
658
659         static n4m_table_t type2_table[] = {
660                 { 180000000,  80000000, 0x0403, 0x01010000, 0x01020300, 0x01020600, 0x05000100, 0x94, 0x012a0115 },
661                 { 180000000,  90000000, 0x0403, 0x01000100, 0x01020300, 0x01000100, 0x05000100, 0x21, 0x0aaa0555 },
662                 { 200000000, 100000000, 0x0303, 0x01000000, 0x01000600, 0x01000000, 0x05000000, 0x21, 0x0aaa0555 },
663                 { 211200000, 105600000, 0x0902, 0x01000200, 0x01030400, 0x01000200, 0x05000200, 0x21, 0x0aaa0555 },
664                 { 220800000, 110400000, 0x1500, 0x01000200, 0x01030400, 0x01000200, 0x05000200, 0x21, 0x0aaa0555 },
665                 { 230400000, 115200000, 0x0604, 0x01000200, 0x01020600, 0x01000200, 0x05000200, 0x21, 0x0aaa0555 },
666                 { 234000000, 104000000, 0x0b01, 0x01010000, 0x01010700, 0x01020600, 0x05000100, 0x94, 0x012a0115 },
667                 { 240000000, 120000000, 0x0803, 0x01000200, 0x01020600, 0x01000200, 0x05000200, 0x21, 0x0aaa0555 },
668                 { 252000000, 126000000, 0x0504, 0x01000100, 0x01020500, 0x01000100, 0x05000100, 0x21, 0x0aaa0555 },
669                 { 264000000, 132000000, 0x0903, 0x01000200, 0x01020700, 0x01000200, 0x05000200, 0x21, 0x0aaa0555 },
670                 { 270000000, 120000000, 0x0703, 0x01010000, 0x01030400, 0x01020600, 0x05000100, 0x94, 0x012a0115 },
671                 { 276000000, 122666666, 0x1500, 0x01010000, 0x01030400, 0x01020600, 0x05000100, 0x94, 0x012a0115 },
672                 { 280000000, 140000000, 0x0503, 0x01000000, 0x01010600, 0x01000000, 0x05000000, 0x21, 0x0aaa0555 },
673                 { 288000000, 128000000, 0x0604, 0x01010000, 0x01030400, 0x01020600, 0x05000100, 0x94, 0x012a0115 },
674                 { 288000000, 144000000, 0x0404, 0x01000000, 0x01010600, 0x01000000, 0x05000000, 0x21, 0x0aaa0555 },
675                 { 300000000, 133333333, 0x0803, 0x01010000, 0x01020600, 0x01020600, 0x05000100, 0x94, 0x012a0115 },
676                 { 300000000, 150000000, 0x0803, 0x01000100, 0x01020600, 0x01000100, 0x05000100, 0x21, 0x0aaa0555 }
677         };
678
679         static n4m_table_t type4_table[] = {
680                 { 192000000,  96000000, 0x0702, 0x04020011, 0x11030011, 0x04020011, 0x04020003, 0x21, 0x0aaa0555 },
681                 { 200000000, 100000000, 0x0009, 0x04020011, 0x11030011, 0x04020011, 0x04020003, 0x21, 0x0aaa0555 },
682                 { 216000000, 108000000, 0x0111, 0x11020005, 0x01030303, 0x11020005, 0x04000005, 0x21, 0x0aaa0555 },
683                 { 228000000, 101333333, 0x0e02, 0x11030003, 0x11210005, 0x11030305, 0x04000005, 0x94, 0x012a00a9 },
684                 { 228000000, 114000000, 0x0e02, 0x11020005, 0x11210005, 0x11020005, 0x04000005, 0x21, 0x0aaa0555 },
685                 { 240000000, 120000000, 0x0109, 0x11030002, 0x01050203, 0x11030002, 0x04000003, 0x21, 0x0aaa0555 },
686                 { 252000000, 126000000, 0x0203, 0x04000005, 0x11050005, 0x04000005, 0x04000002, 0x21, 0x0aaa0555 },
687                 { 264000000, 132000000, 0x0602, 0x04000005, 0x11050005, 0x04000005, 0x04000002, 0x21, 0x0aaa0555 },
688                 { 272000000, 116571428, 0x0c02, 0x04000021, 0x02000909, 0x02000221, 0x04000003, 0x73, 0x254a14a9 },
689                 { 280000000, 120000000, 0x0209, 0x04000021, 0x01030303, 0x02000221, 0x04000003, 0x73, 0x254a14a9 },
690                 { 288000000, 123428571, 0x0111, 0x04000021, 0x01030303, 0x02000221, 0x04000003, 0x73, 0x254a14a9 },
691                 { 300000000, 120000000, 0x0009, 0x04000009, 0x01030203, 0x02000902, 0x04000002, 0x52, 0x02520129 }
692         };
693         uint icache_size, ic_lsize;
694         ulong start, end, dst;
695         bool ret = FALSE;
696
697         /* get index of the current core */
698         idx = sb_coreidx(sbh);
699
700         /* switch to extif or chipc core */
701         if ((eir = (extifregs_t *) sb_setcore(sbh, SB_EXTIF, 0))) {
702                 pll_type = PLL_TYPE1;
703                 clockcontrol_n = &eir->clockcontrol_n;
704                 clockcontrol_sb = &eir->clockcontrol_sb;
705                 clockcontrol_pci = &eir->clockcontrol_pci;
706         } else if ((cc = (chipcregs_t *) sb_setcore(sbh, SB_CC, 0))) {
707                 pll_type = R_REG(&cc->capabilities) & CAP_PLL_MASK;
708                 clockcontrol_n = &cc->clockcontrol_n;
709                 clockcontrol_sb = &cc->clockcontrol_sb;
710                 clockcontrol_pci = &cc->clockcontrol_pci;
711         } else
712                 goto done;
713
714         /* Store the current clock register values */
715         orig_n = R_REG(clockcontrol_n);
716         orig_sb = R_REG(clockcontrol_sb);
717         orig_pci = R_REG(clockcontrol_pci);
718
719         if (pll_type == PLL_TYPE1) {
720                 /* Keep the current PCI clock if not specified */
721                 if (pciclock == 0) {
722                         pciclock = sb_clock_rate(pll_type, R_REG(clockcontrol_n), R_REG(clockcontrol_pci));
723                         pciclock = (pciclock <= 25000000) ? 25000000 : 33000000;
724                 }
725
726                 /* Search for the closest MIPS clock less than or equal to a preferred value */
727                 for (i = 0; i < ARRAYSIZE(type1_table); i++) {
728                         ASSERT(type1_table[i].mipsclock ==
729                                sb_clock_rate(pll_type, type1_table[i].n, type1_table[i].sb));
730                         if (type1_table[i].mipsclock > mipsclock)
731                                 break;
732                 }
733                 if (i == 0) {
734                         ret = FALSE;
735                         goto done;
736                 } else {
737                         ret = TRUE;
738                         i--;
739                 }
740                 ASSERT(type1_table[i].mipsclock <= mipsclock);
741
742                 /* No PLL change */
743                 if ((orig_n == type1_table[i].n) &&
744                     (orig_sb == type1_table[i].sb) &&
745                     (orig_pci == type1_table[i].pci33))
746                         goto done;
747
748                 /* Set the PLL controls */
749                 W_REG(clockcontrol_n, type1_table[i].n);
750                 W_REG(clockcontrol_sb, type1_table[i].sb);
751                 if (pciclock == 25000000)
752                         W_REG(clockcontrol_pci, type1_table[i].pci25);
753                 else
754                         W_REG(clockcontrol_pci, type1_table[i].pci33);
755
756                 /* Reset */
757                 sb_watchdog(sbh, 1);
758                 while (1);
759         } else if ((pll_type == PLL_TYPE2) || (pll_type == PLL_TYPE4)) {
760                 n4m_table_t *table = (pll_type == PLL_TYPE2) ? type2_table : type4_table;
761                 uint tabsz = (pll_type == PLL_TYPE2) ? ARRAYSIZE(type2_table) : ARRAYSIZE(type4_table);
762
763                 ASSERT(cc);
764
765                 /* Store the current clock register values */
766                 orig_m2 = R_REG(&cc->clockcontrol_m2);
767                 orig_mips = R_REG(&cc->clockcontrol_mips);
768                 orig_ratio_parm = 0;
769
770                 /* Look up current ratio */
771                 for (i = 0; i < tabsz; i++) {
772                         if ((orig_n == table[i].n) &&
773                             (orig_sb == table[i].sb) &&
774                             (orig_pci == table[i].pci33) &&
775                             (orig_m2 == table[i].m2) &&
776                             (orig_mips == table[i].m3)) {
777                                 orig_ratio_parm = table[i].ratio_parm;
778                                 break;
779                         }
780                 }
781
782                 /* Search for the closest MIPS clock greater or equal to a preferred value */
783                 for (i = 0; i < tabsz; i++) {
784                         ASSERT(table[i].mipsclock ==
785                                sb_clock_rate(pll_type, table[i].n, table[i].m3));
786                         if ((mipsclock <= table[i].mipsclock) &&
787                             ((sbclock == 0) || (sbclock <= table[i].sbclock)))
788                                 break;
789                 }
790                 if (i == tabsz) {
791                         ret = FALSE;
792                         goto done;
793                 } else {
794                         ret = TRUE;
795                 }
796
797                 /* No PLL change */
798                 if ((orig_n == table[i].n) &&
799                     (orig_sb == table[i].sb) &&
800                     (orig_pci == table[i].pci33) &&
801                     (orig_m2 == table[i].m2) &&
802                     (orig_mips == table[i].m3))
803                         goto done;
804
805                 /* Set the PLL controls */
806                 W_REG(clockcontrol_n, table[i].n);
807                 W_REG(clockcontrol_sb, table[i].sb);
808                 W_REG(clockcontrol_pci, table[i].pci33);
809                 W_REG(&cc->clockcontrol_m2, table[i].m2);
810                 W_REG(&cc->clockcontrol_mips, table[i].m3);
811
812                 /* No ratio change */
813                 if (orig_ratio_parm == table[i].ratio_parm)
814                         goto end_fill;
815
816                 new_ratio = table[i].ratio_parm;
817
818                 icache_probe(&icache_size, &ic_lsize);
819
820                 /* Preload the code into the cache */
821                 start = ((ulong) &&start_fill) & ~(ic_lsize - 1);
822                 end = ((ulong) &&end_fill + (ic_lsize - 1)) & ~(ic_lsize - 1);
823                 while (start < end) {
824                         cache_unroll(start, Fill_I);
825                         start += ic_lsize;
826                 }
827
828                 /* Copy the handler */
829                 start = (ulong) &handler;
830                 end = (ulong) &afterhandler;
831                 dst = KSEG1ADDR(0x180);
832                 for (i = 0; i < (end - start); i += 4)
833                         *((ulong *)(dst + i)) = *((ulong *)(start + i));
834                 
835                 /* Preload handler into the cache one line at a time */
836                 for (i = 0; i < (end - start); i += 4)
837                         cache_unroll(dst + i, Fill_I);
838
839                 /* Clear BEV bit */
840                 MTC0(C0_STATUS, 0, MFC0(C0_STATUS, 0) & ~ST0_BEV);
841
842                 /* Enable interrupts */
843                 MTC0(C0_STATUS, 0, MFC0(C0_STATUS, 0) | (ALLINTS | ST0_IE));
844
845                 /* Enable MIPS timer interrupt */
846                 if (!(mipsr = sb_setcore(sbh, SB_MIPS, 0)) &&
847                     !(mipsr = sb_setcore(sbh, SB_MIPS33, 0)))
848                         ASSERT(mipsr);
849                 W_REG(&mipsr->intmask, 1);
850
851         start_fill:
852                 /* step 1, set clock ratios */
853                 MTC0(C0_BROADCOM, 3, new_ratio);
854                 MTC0(C0_BROADCOM, 1, 8);
855
856                 /* step 2: program timer intr */
857                 W_REG(&mipsr->timer, 100);
858                 (void) R_REG(&mipsr->timer);
859
860                 /* step 3, switch to async */
861                 sync_mode = MFC0(C0_BROADCOM, 4);
862                 MTC0(C0_BROADCOM, 4, 1 << 22);
863
864                 /* step 4, set cfg active */
865                 MTC0(C0_BROADCOM, 2, 0x9);
866
867
868                 /* steps 5 & 6 */ 
869                 __asm__ __volatile__ (
870                         ".set\tmips3\n\t"
871                         "wait\n\t"
872                         ".set\tmips0"
873                 );
874
875                 /* step 7, clear cfg_active */
876                 MTC0(C0_BROADCOM, 2, 0);
877                 
878                 /* Additional Step: set back to orig sync mode */
879                 MTC0(C0_BROADCOM, 4, sync_mode);
880
881                 /* step 8, fake soft reset */
882                 MTC0(C0_BROADCOM, 5, MFC0(C0_BROADCOM, 5) | 4);
883
884         end_fill:
885                 /* step 9 set watchdog timer */
886                 sb_watchdog(sbh, 20);
887                 (void) R_REG(&cc->chipid);
888
889                 /* step 11 */
890                 __asm__ __volatile__ (
891                         ".set\tmips3\n\t"
892                         "sync\n\t"
893                         "wait\n\t"
894                         ".set\tmips0"
895                 );
896                 while (1);
897         }
898
899 done:
900         /* switch back to previous core */
901         sb_setcoreidx(sbh, idx);
902
903         return ret;
904 }
905
906
907 /* returns the ncdl value to be programmed into sdram_ncdl for calibration */
908 uint32
909 sb_memc_get_ncdl(void *sbh)
910 {
911         sbmemcregs_t *memc;
912         uint32 ret = 0;
913         uint32 config, rd, wr, misc, dqsg, cd, sm, sd;
914         uint idx, rev;
915
916         idx = sb_coreidx(sbh);
917
918         memc = (sbmemcregs_t *)sb_setcore(sbh, SB_MEMC, 0);
919         if (memc == 0)
920                 goto out;
921
922         rev = sb_corerev(sbh);
923
924         config = R_REG(&memc->config);
925         wr = R_REG(&memc->wrncdlcor);
926         rd = R_REG(&memc->rdncdlcor);
927         misc = R_REG(&memc->miscdlyctl);
928         dqsg = R_REG(&memc->dqsgatencdl);
929
930         rd &= MEMC_RDNCDLCOR_RD_MASK;
931         wr &= MEMC_WRNCDLCOR_WR_MASK; 
932         dqsg &= MEMC_DQSGATENCDL_G_MASK;
933
934         if (config & MEMC_CONFIG_DDR) {
935                 ret = (wr << 16) | (rd << 8) | dqsg;
936         } else {
937                 if (rev > 0)
938                         cd = rd;
939                 else
940                         cd = (rd == MEMC_CD_THRESHOLD) ? rd : (wr + MEMC_CD_THRESHOLD);
941                 sm = (misc & MEMC_MISC_SM_MASK) >> MEMC_MISC_SM_SHIFT;
942                 sd = (misc & MEMC_MISC_SD_MASK) >> MEMC_MISC_SD_SHIFT;
943                 ret = (sm << 16) | (sd << 8) | cd;
944         }
945
946 out:
947         /* switch back to previous core */
948         sb_setcoreidx(sbh, idx);
949
950         return ret;
951 }