TomatoVPN 1.27vpn3.6 release
[tomato.git] / release / src / shared / sbmips.c
blob63f48e27a44a733489ee865e49252b29fc64ce4a
1 /*
2 * BCM47XX Sonics SiliconBackplane MIPS core routines
4 * Copyright 2005, 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.
12 * $Id: sbmips.c,v 1.3 2005/03/07 08:35:32 kanki Exp $
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 #include <mipsinc.h>
28 /*
29 * Returns TRUE if an external UART exists at the given base
30 * register.
32 static bool
33 BCMINITFN(serial_exists)(uint8 *regs)
35 uint8 save_mcr, status1;
37 save_mcr = R_REG(&regs[UART_MCR]);
38 W_REG(&regs[UART_MCR], UART_MCR_LOOP | 0x0a);
39 status1 = R_REG(&regs[UART_MSR]) & 0xf0;
40 W_REG(&regs[UART_MCR], save_mcr);
42 return (status1 == 0x90);
45 /*
46 * Initializes UART access. The callback function will be called once
47 * per found UART.
49 void
50 BCMINITFN(sb_serial_init)(void *sbh, void (*add)(void *regs, uint irq, uint baud_base, uint reg_shift))
52 void *regs;
53 ulong base;
54 uint irq;
55 int i, n;
57 if ((regs = sb_setcore(sbh, SB_EXTIF, 0))) {
58 extifregs_t *eir = (extifregs_t *) regs;
59 sbconfig_t *sb;
61 /* Determine external UART register base */
62 sb = (sbconfig_t *)((ulong) eir + SBCONFIGOFF);
63 base = EXTIF_CFGIF_BASE(sb_base(R_REG(&sb->sbadmatch1)));
65 /* Determine IRQ */
66 irq = sb_irq(sbh);
68 /* Disable GPIO interrupt initially */
69 W_REG(&eir->gpiointpolarity, 0);
70 W_REG(&eir->gpiointmask, 0);
72 /* Search for external UARTs */
73 n = 2;
74 for (i = 0; i < 2; i++) {
75 regs = (void *) REG_MAP(base + (i * 8), 8);
76 if (BCMINIT(serial_exists)(regs)) {
77 /* Set GPIO 1 to be the external UART IRQ */
78 W_REG(&eir->gpiointmask, 2);
79 if (add)
80 add(regs, irq, 13500000, 0);
84 /* Add internal UART if enabled */
85 if (R_REG(&eir->corecontrol) & CC_UE)
86 if (add)
87 add((void *) &eir->uartdata, irq, sb_clock(sbh), 2);
88 } else if ((regs = sb_setcore(sbh, SB_CC, 0))) {
89 chipcregs_t *cc = (chipcregs_t *) regs;
90 uint32 rev, cap, pll, baud_base, div;
92 /* Determine core revision and capabilities */
93 rev = sb_corerev(sbh);
94 cap = R_REG(&cc->capabilities);
95 pll = cap & CAP_PLL_MASK;
97 /* Determine IRQ */
98 irq = sb_irq(sbh);
100 if (pll == PLL_TYPE1) {
101 /* PLL clock */
102 baud_base = sb_clock_rate(pll,
103 R_REG(&cc->clockcontrol_n),
104 R_REG(&cc->clockcontrol_m2));
105 div = 1;
106 } else {
107 if (rev >= 11) {
108 /* Fixed ALP clock */
109 baud_base = 20000000;
110 div = 1;
111 /* Set the override bit so we don't divide it */
112 W_REG(&cc->corecontrol, CC_UARTCLKO);
113 } else if (rev >= 3) {
114 /* Internal backplane clock */
115 baud_base = sb_clock(sbh);
116 div = 2; /* Minimum divisor */
117 W_REG(&cc->clkdiv,
118 ((R_REG(&cc->clkdiv) & ~CLKD_UART) | div));
119 } else {
120 /* Fixed internal backplane clock */
121 baud_base = 88000000;
122 div = 48;
125 /* Clock source depends on strapping if UartClkOverride is unset */
126 if ((rev > 0) &&
127 ((R_REG(&cc->corecontrol) & CC_UARTCLKO) == 0)) {
128 if ((cap & CAP_UCLKSEL) == CAP_UINTCLK) {
129 /* Internal divided backplane clock */
130 baud_base /= div;
131 } else {
132 /* Assume external clock of 1.8432 MHz */
133 baud_base = 1843200;
138 /* Add internal UARTs */
139 n = cap & CAP_UARTS_MASK;
140 for (i = 0; i < n; i++) {
141 /* Register offset changed after revision 0 */
142 if (rev)
143 regs = (void *)((ulong) &cc->uart0data + (i * 256));
144 else
145 regs = (void *)((ulong) &cc->uart0data + (i * 8));
147 if (add)
148 add(regs, irq, baud_base, 0);
154 * Initialize jtag master and return handle for
155 * jtag_rwreg. Returns NULL on failure.
157 void *
158 sb_jtagm_init(void *sbh, uint clkd, bool exttap)
160 void *regs;
162 if ((regs = sb_setcore(sbh, SB_CC, 0)) != NULL) {
163 chipcregs_t *cc = (chipcregs_t *) regs;
164 uint32 tmp;
167 * Determine jtagm availability from
168 * core revision and capabilities.
170 tmp = sb_corerev(sbh);
172 * Corerev 10 has jtagm, but the only chip
173 * with it does not have a mips, and
174 * the layout of the jtagcmd register is
175 * different. We'll only accept >= 11.
177 if (tmp < 11)
178 return (NULL);
180 tmp = R_REG(&cc->capabilities);
181 if ((tmp & CAP_JTAGP) == 0)
182 return (NULL);
184 /* Set clock divider if requested */
185 if (clkd != 0) {
186 tmp = R_REG(&cc->clkdiv);
187 tmp = (tmp & ~CLKD_JTAG) |
188 ((clkd << CLKD_JTAG_SHIFT) & CLKD_JTAG);
189 W_REG(&cc->clkdiv, tmp);
192 /* Enable jtagm */
193 tmp = JCTRL_EN | (exttap ? JCTRL_EXT_EN : 0);
194 W_REG(&cc->jtagctrl, tmp);
197 return (regs);
200 void
201 sb_jtagm_disable(void *h)
203 chipcregs_t *cc = (chipcregs_t *)h;
205 W_REG(&cc->jtagctrl, R_REG(&cc->jtagctrl) & ~JCTRL_EN);
209 * Read/write a jtag register. Assumes a target with
210 * 8 bit IR and 32 bit DR.
212 #define IRWIDTH 8
213 #define DRWIDTH 32
214 uint32
215 jtag_rwreg(void *h, uint32 ir, uint32 dr)
217 chipcregs_t *cc = (chipcregs_t *) h;
218 uint32 tmp;
220 W_REG(&cc->jtagir, ir);
221 W_REG(&cc->jtagdr, dr);
222 tmp = JCMD_START | JCMD_ACC_IRDR |
223 ((IRWIDTH - 1) << JCMD_IRW_SHIFT) |
224 (DRWIDTH - 1);
225 W_REG(&cc->jtagcmd, tmp);
226 while (((tmp = R_REG(&cc->jtagcmd)) & JCMD_BUSY) == JCMD_BUSY) {
227 /* OSL_DELAY(1); */
230 tmp = R_REG(&cc->jtagdr);
231 return (tmp);
234 /* Returns the SB interrupt flag of the current core. */
235 uint32
236 sb_flag(void *sbh)
238 void *regs;
239 sbconfig_t *sb;
241 regs = sb_coreregs(sbh);
242 sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF);
244 return (R_REG(&sb->sbtpsflag) & SBTPS_NUM0_MASK);
247 static const uint32 sbips_int_mask[] = {
249 SBIPS_INT1_MASK,
250 SBIPS_INT2_MASK,
251 SBIPS_INT3_MASK,
252 SBIPS_INT4_MASK
255 static const uint32 sbips_int_shift[] = {
258 SBIPS_INT2_SHIFT,
259 SBIPS_INT3_SHIFT,
260 SBIPS_INT4_SHIFT
264 * Returns the MIPS IRQ assignment of the current core. If unassigned,
265 * 0 is returned.
267 uint
268 sb_irq(void *sbh)
270 uint idx;
271 void *regs;
272 sbconfig_t *sb;
273 uint32 flag, sbipsflag;
274 uint irq = 0;
276 flag = sb_flag(sbh);
278 idx = sb_coreidx(sbh);
280 if ((regs = sb_setcore(sbh, SB_MIPS, 0)) ||
281 (regs = sb_setcore(sbh, SB_MIPS33, 0))) {
282 sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF);
284 /* sbipsflag specifies which core is routed to interrupts 1 to 4 */
285 sbipsflag = R_REG(&sb->sbipsflag);
286 for (irq = 1; irq <= 4; irq++) {
287 if (((sbipsflag & sbips_int_mask[irq]) >> sbips_int_shift[irq]) == flag)
288 break;
290 if (irq == 5)
291 irq = 0;
294 sb_setcoreidx(sbh, idx);
296 return irq;
299 /* Clears the specified MIPS IRQ. */
300 static void
301 BCMINITFN(sb_clearirq)(void *sbh, uint irq)
303 void *regs;
304 sbconfig_t *sb;
306 if (!(regs = sb_setcore(sbh, SB_MIPS, 0)) &&
307 !(regs = sb_setcore(sbh, SB_MIPS33, 0)))
308 ASSERT(regs);
309 sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF);
311 if (irq == 0)
312 W_REG(&sb->sbintvec, 0);
313 else
314 OR_REG(&sb->sbipsflag, sbips_int_mask[irq]);
318 * Assigns the specified MIPS IRQ to the specified core. Shared MIPS
319 * IRQ 0 may be assigned more than once.
321 static void
322 BCMINITFN(sb_setirq)(void *sbh, uint irq, uint coreid, uint coreunit)
324 void *regs;
325 sbconfig_t *sb;
326 uint32 flag;
328 regs = sb_setcore(sbh, coreid, coreunit);
329 ASSERT(regs);
330 flag = sb_flag(sbh);
332 if (!(regs = sb_setcore(sbh, SB_MIPS, 0)) &&
333 !(regs = sb_setcore(sbh, SB_MIPS33, 0)))
334 ASSERT(regs);
335 sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF);
337 if (irq == 0)
338 OR_REG(&sb->sbintvec, 1 << flag);
339 else {
340 flag <<= sbips_int_shift[irq];
341 ASSERT(!(flag & ~sbips_int_mask[irq]));
342 flag |= R_REG(&sb->sbipsflag) & ~sbips_int_mask[irq];
343 W_REG(&sb->sbipsflag, flag);
348 * Initializes clocks and interrupts. SB and NVRAM access must be
349 * initialized prior to calling.
351 void
352 BCMINITFN(sb_mips_init)(void *sbh)
354 ulong hz, ns, tmp;
355 extifregs_t *eir;
356 chipcregs_t *cc;
357 char *value;
358 uint irq;
360 /* Figure out current SB clock speed */
361 if ((hz = sb_clock(sbh)) == 0)
362 hz = 100000000;
363 ns = 1000000000 / hz;
365 /* Setup external interface timing */
366 if ((eir = sb_setcore(sbh, SB_EXTIF, 0))) {
367 /* Initialize extif so we can get to the LEDs and external UART */
368 W_REG(&eir->prog_config, CF_EN);
370 /* Set timing for the flash */
371 tmp = CEIL(10, ns) << FW_W3_SHIFT; /* W3 = 10nS */
372 tmp = tmp | (CEIL(40, ns) << FW_W1_SHIFT); /* W1 = 40nS */
373 tmp = tmp | CEIL(120, ns); /* W0 = 120nS */
374 W_REG(&eir->prog_waitcount, tmp); /* 0x01020a0c for a 100Mhz clock */
376 /* Set programmable interface timing for external uart */
377 tmp = CEIL(10, ns) << FW_W3_SHIFT; /* W3 = 10nS */
378 tmp = tmp | (CEIL(20, ns) << FW_W2_SHIFT); /* W2 = 20nS */
379 tmp = tmp | (CEIL(100, ns) << FW_W1_SHIFT); /* W1 = 100nS */
380 tmp = tmp | CEIL(120, ns); /* W0 = 120nS */
381 W_REG(&eir->prog_waitcount, tmp); /* 0x01020a0c for a 100Mhz clock */
382 } else if ((cc = sb_setcore(sbh, SB_CC, 0))) {
383 //==================================tallest===============================================
384 /* set register for external IO to control LED. */
385 W_REG(&cc->prog_config, 0x11);
386 tmp = CEIL(10, ns) << FW_W3_SHIFT; /* W3 = 10nS */
387 tmp = tmp | (CEIL(40, ns) << FW_W1_SHIFT); /* W1 = 40nS */
388 tmp = tmp | CEIL(240, ns); /* W0 = 120nS */
389 W_REG(&cc->prog_waitcount, tmp); /* 0x01020a0c for a 100Mhz clock */
390 //========================================================================================
391 /* Set timing for the flash */
392 tmp = CEIL(10, ns) << FW_W3_SHIFT; /* W3 = 10nS */
393 tmp |= CEIL(10, ns) << FW_W1_SHIFT; /* W1 = 10nS */
394 tmp |= CEIL(120, ns); /* W0 = 120nS */
395 if (sb_corerev(sbh) < 9)
396 W_REG(&cc->flash_waitcount, tmp);
398 if ( (sb_corerev(sbh) < 9) ||
399 ((BCMINIT(sb_chip)(sbh) == BCM5350_DEVICE_ID) && BCMINIT(sb_chiprev)(sbh) == 0) ) {
400 W_REG(&cc->pcmcia_memwait, tmp);
404 /* Chip specific initialization */
405 switch (BCMINIT(sb_chip)(sbh)) {
406 case BCM4710_DEVICE_ID:
407 /* Clear interrupt map */
408 for (irq = 0; irq <= 4; irq++)
409 BCMINIT(sb_clearirq)(sbh, irq);
410 BCMINIT(sb_setirq)(sbh, 0, SB_CODEC, 0);
411 BCMINIT(sb_setirq)(sbh, 0, SB_EXTIF, 0);
412 BCMINIT(sb_setirq)(sbh, 2, SB_ENET, 1);
413 BCMINIT(sb_setirq)(sbh, 3, SB_ILINE20, 0);
414 BCMINIT(sb_setirq)(sbh, 4, SB_PCI, 0);
415 ASSERT(eir);
416 value = BCMINIT(nvram_get)("et0phyaddr");
417 if (value && !strcmp(value, "31")) {
418 /* Enable internal UART */
419 W_REG(&eir->corecontrol, CC_UE);
420 /* Give USB its own interrupt */
421 BCMINIT(sb_setirq)(sbh, 1, SB_USB, 0);
422 } else {
423 /* Disable internal UART */
424 W_REG(&eir->corecontrol, 0);
425 /* Give Ethernet its own interrupt */
426 BCMINIT(sb_setirq)(sbh, 1, SB_ENET, 0);
427 BCMINIT(sb_setirq)(sbh, 0, SB_USB, 0);
429 break;
430 case BCM4310_DEVICE_ID:
431 MTC0(C0_BROADCOM, 0, MFC0(C0_BROADCOM, 0) & ~(1 << 22));
432 break;
433 case BCM5350_DEVICE_ID:
434 /* Clear interrupt map */
435 for (irq = 0; irq <= 4; irq++)
436 BCMINIT(sb_clearirq)(sbh, irq);
437 BCMINIT(sb_setirq)(sbh, 0, SB_CC, 0);
438 BCMINIT(sb_setirq)(sbh, 1, SB_D11, 0);
439 BCMINIT(sb_setirq)(sbh, 2, SB_ENET, 0);
440 BCMINIT(sb_setirq)(sbh, 3, SB_IPSEC, 0);
441 BCMINIT(sb_setirq)(sbh, 4, SB_USB, 0);
442 break;
446 uint32
447 BCMINITFN(sb_mips_clock)(void *sbh)
449 extifregs_t *eir;
450 chipcregs_t *cc;
451 uint32 n, m;
452 uint idx;
453 uint32 pll_type, rate = 0;
455 /* get index of the current core */
456 idx = sb_coreidx(sbh);
457 pll_type = PLL_TYPE1;
459 /* switch to extif or chipc core */
460 if ((eir = (extifregs_t *) sb_setcore(sbh, SB_EXTIF, 0))) {
461 n = R_REG(&eir->clockcontrol_n);
462 m = R_REG(&eir->clockcontrol_sb);
463 } else if ((cc = (chipcregs_t *) sb_setcore(sbh, SB_CC, 0))) {
464 pll_type = R_REG(&cc->capabilities) & CAP_PLL_MASK;
465 n = R_REG(&cc->clockcontrol_n);
466 if ((pll_type == PLL_TYPE2) ||
467 (pll_type == PLL_TYPE4) ||
468 (pll_type == PLL_TYPE6) ||
469 (pll_type == PLL_TYPE7))
470 m = R_REG(&cc->clockcontrol_mips);
471 else if (pll_type == PLL_TYPE5) {
472 rate = 200000000;
473 goto out;
475 else if (pll_type == PLL_TYPE3) {
476 if (BCMINIT(sb_chip)(sbh) == BCM5365_DEVICE_ID) { /* 5365 is also type3 */
477 rate = 200000000;
478 goto out;
479 } else
480 m = R_REG(&cc->clockcontrol_m2); /* 5350 uses m2 to control mips */
481 } else
482 m = R_REG(&cc->clockcontrol_sb);
483 } else
484 goto out;
486 /* calculate rate */
487 rate = sb_clock_rate(pll_type, n, m);
489 if (pll_type == PLL_TYPE6)
490 rate = SB2MIPS_T6(rate);
492 out:
493 /* switch back to previous core */
494 sb_setcoreidx(sbh, idx);
496 return rate;
499 #define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4)
501 static void
502 BCMINITFN(handler)(void)
504 /* Step 11 */
505 __asm__ (
506 ".set\tmips32\n\t"
507 "ssnop\n\t"
508 "ssnop\n\t"
509 /* Disable interrupts */
510 /* MTC0(C0_STATUS, 0, MFC0(C0_STATUS, 0) & ~(ALLINTS | STO_IE)); */
511 "mfc0 $15, $12\n\t"
512 /* Just a Hack to not to use reg 'at' which was causing problems on 4704 A2 */
513 "li $14, -31746\n\t"
514 "and $15, $15, $14\n\t"
515 "mtc0 $15, $12\n\t"
516 "eret\n\t"
517 "nop\n\t"
518 "nop\n\t"
519 ".set\tmips0"
523 /* The following MUST come right after handler() */
524 static void
525 BCMINITFN(afterhandler)(void)
530 * Set the MIPS, backplane and PCI clocks as closely as possible.
532 bool
533 BCMINITFN(sb_mips_setclock)(void *sbh, uint32 mipsclock, uint32 sbclock, uint32 pciclock)
535 extifregs_t *eir = NULL;
536 chipcregs_t *cc = NULL;
537 mipsregs_t *mipsr = NULL;
538 volatile uint32 *clockcontrol_n, *clockcontrol_sb, *clockcontrol_pci, *clockcontrol_m2;
539 uint32 orig_n, orig_sb, orig_pci, orig_m2, orig_mips, orig_ratio_parm, orig_ratio_cfg;
540 uint32 pll_type, sync_mode;
541 uint ic_size, ic_lsize;
542 uint idx, i;
543 typedef struct {
544 uint32 mipsclock;
545 uint16 n;
546 uint32 sb;
547 uint32 pci33;
548 uint32 pci25;
549 } n3m_table_t;
550 static n3m_table_t BCMINITDATA(type1_table)[] = {
551 { 96000000, 0x0303, 0x04020011, 0x11030011, 0x11050011 }, /* 96.000 32.000 24.000 */
552 { 100000000, 0x0009, 0x04020011, 0x11030011, 0x11050011 }, /* 100.000 33.333 25.000 */
553 { 104000000, 0x0802, 0x04020011, 0x11050009, 0x11090009 }, /* 104.000 31.200 24.960 */
554 { 108000000, 0x0403, 0x04020011, 0x11050009, 0x02000802 }, /* 108.000 32.400 24.923 */
555 { 112000000, 0x0205, 0x04020011, 0x11030021, 0x02000403 }, /* 112.000 32.000 24.889 */
556 { 115200000, 0x0303, 0x04020009, 0x11030011, 0x11050011 }, /* 115.200 32.000 24.000 */
557 { 120000000, 0x0011, 0x04020011, 0x11050011, 0x11090011 }, /* 120.000 30.000 24.000 */
558 { 124800000, 0x0802, 0x04020009, 0x11050009, 0x11090009 }, /* 124.800 31.200 24.960 */
559 { 128000000, 0x0305, 0x04020011, 0x11050011, 0x02000305 }, /* 128.000 32.000 24.000 */
560 { 132000000, 0x0603, 0x04020011, 0x11050011, 0x02000305 }, /* 132.000 33.000 24.750 */
561 { 136000000, 0x0c02, 0x04020011, 0x11090009, 0x02000603 }, /* 136.000 32.640 24.727 */
562 { 140000000, 0x0021, 0x04020011, 0x11050021, 0x02000c02 }, /* 140.000 30.000 24.706 */
563 { 144000000, 0x0405, 0x04020011, 0x01020202, 0x11090021 }, /* 144.000 30.857 24.686 */
564 { 150857142, 0x0605, 0x04020021, 0x02000305, 0x02000605 }, /* 150.857 33.000 24.000 */
565 { 152000000, 0x0e02, 0x04020011, 0x11050021, 0x02000e02 }, /* 152.000 32.571 24.000 */
566 { 156000000, 0x0802, 0x04020005, 0x11050009, 0x11090009 }, /* 156.000 31.200 24.960 */
567 { 160000000, 0x0309, 0x04020011, 0x11090011, 0x02000309 }, /* 160.000 32.000 24.000 */
568 { 163200000, 0x0c02, 0x04020009, 0x11090009, 0x02000603 }, /* 163.200 32.640 24.727 */
569 { 168000000, 0x0205, 0x04020005, 0x11030021, 0x02000403 }, /* 168.000 32.000 24.889 */
570 { 176000000, 0x0602, 0x04020003, 0x11050005, 0x02000602 }, /* 176.000 33.000 24.000 */
572 typedef struct {
573 uint32 mipsclock;
574 uint16 n;
575 uint32 m2; /* that is the clockcontrol_m2 */
576 } type3_table_t;
577 static type3_table_t type3_table[] = { /* for 5350, mips clock is always double sb clock */
578 { 150000000, 0x311, 0x4020005 },
579 { 200000000, 0x311, 0x4020003 },
581 typedef struct {
582 uint32 mipsclock;
583 uint32 sbclock;
584 uint16 n;
585 uint32 sb;
586 uint32 pci33;
587 uint32 m2;
588 uint32 m3;
589 uint32 ratio_cfg;
590 uint32 ratio_parm;
591 } n4m_table_t;
593 static n4m_table_t BCMINITDATA(type2_table)[] = {
594 { 180000000, 80000000, 0x0403, 0x01010000, 0x01020300, 0x01020600, 0x05000100, 8, 0x012a00a9 },
595 { 180000000, 90000000, 0x0403, 0x01000100, 0x01020300, 0x01000100, 0x05000100, 11, 0x0aaa0555 },
596 { 200000000, 100000000, 0x0303, 0x02010000, 0x02040001, 0x02010000, 0x06000001, 11, 0x0aaa0555 },
597 { 211200000, 105600000, 0x0902, 0x01000200, 0x01030400, 0x01000200, 0x05000200, 11, 0x0aaa0555 },
598 { 220800000, 110400000, 0x1500, 0x01000200, 0x01030400, 0x01000200, 0x05000200, 11, 0x0aaa0555 },
599 { 230400000, 115200000, 0x0604, 0x01000200, 0x01020600, 0x01000200, 0x05000200, 11, 0x0aaa0555 },
600 { 234000000, 104000000, 0x0b01, 0x01010000, 0x01010700, 0x01020600, 0x05000100, 8, 0x012a00a9 },
601 { 240000000, 120000000, 0x0803, 0x01000200, 0x01020600, 0x01000200, 0x05000200, 11, 0x0aaa0555 },
602 { 252000000, 126000000, 0x0504, 0x01000100, 0x01020500, 0x01000100, 0x05000100, 11, 0x0aaa0555 },
603 { 264000000, 132000000, 0x0903, 0x01000200, 0x01020700, 0x01000200, 0x05000200, 11, 0x0aaa0555 },
604 { 270000000, 120000000, 0x0703, 0x01010000, 0x01030400, 0x01020600, 0x05000100, 8, 0x012a00a9 },
605 { 276000000, 122666666, 0x1500, 0x01010000, 0x01030400, 0x01020600, 0x05000100, 8, 0x012a00a9 },
606 { 280000000, 140000000, 0x0503, 0x01000000, 0x01010600, 0x01000000, 0x05000000, 11, 0x0aaa0555 },
607 { 288000000, 128000000, 0x0604, 0x01010000, 0x01030400, 0x01020600, 0x05000100, 8, 0x012a00a9 },
608 { 288000000, 144000000, 0x0404, 0x01000000, 0x01010600, 0x01000000, 0x05000000, 11, 0x0aaa0555 },
609 { 300000000, 133333333, 0x0803, 0x01010000, 0x01020600, 0x01020600, 0x05000100, 8, 0x012a00a9 },
610 { 300000000, 150000000, 0x0803, 0x01000100, 0x01020600, 0x01000100, 0x05000100, 11, 0x0aaa0555 }
613 static n4m_table_t BCMINITDATA(type4_table)[] = {
614 { 192000000, 96000000, 0x0702, 0x04000011, 0x11030011, 0x04000011, 0x04000003, 11, 0x0aaa0555 },
615 { 198000000, 99000000, 0x0603, 0x11020005, 0x11030011, 0x11020005, 0x04000005, 11, 0x0aaa0555 },
616 { 200000000, 100000000, 0x0009, 0x04020011, 0x11030011, 0x04020011, 0x04020003, 11, 0x0aaa0555 },
617 { 204000000, 102000000, 0x0c02, 0x11020005, 0x01030303, 0x11020005, 0x04000005, 11, 0x0aaa0555 },
618 { 208000000, 104000000, 0x0802, 0x11030002, 0x11090005, 0x11030002, 0x04000003, 11, 0x0aaa0555 },
619 { 210000000, 105000000, 0x0209, 0x11020005, 0x01030303, 0x11020005, 0x04000005, 11, 0x0aaa0555 },
620 { 216000000, 108000000, 0x0111, 0x11020005, 0x01030303, 0x11020005, 0x04000005, 11, 0x0aaa0555 },
621 { 224000000, 112000000, 0x0205, 0x11030002, 0x02002103, 0x11030002, 0x04000003, 11, 0x0aaa0555 },
622 { 228000000, 101333333, 0x0e02, 0x11030003, 0x11210005, 0x01030305, 0x04000005, 8, 0x012a00a9 },
623 { 228000000, 114000000, 0x0e02, 0x11020005, 0x11210005, 0x11020005, 0x04000005, 11, 0x0aaa0555 },
624 { 240000000, 102857143, 0x0109, 0x04000021, 0x01050203, 0x11030021, 0x04000003, 13, 0x254a14a9 },
625 { 240000000, 120000000, 0x0109, 0x11030002, 0x01050203, 0x11030002, 0x04000003, 11, 0x0aaa0555 },
626 { 252000000, 100800000, 0x0203, 0x04000009, 0x11050005, 0x02000209, 0x04000002, 9, 0x02520129 },
627 { 252000000, 126000000, 0x0203, 0x04000005, 0x11050005, 0x04000005, 0x04000002, 11, 0x0aaa0555 },
628 { 264000000, 132000000, 0x0602, 0x04000005, 0x11050005, 0x04000005, 0x04000002, 11, 0x0aaa0555 },
629 { 272000000, 116571428, 0x0c02, 0x04000021, 0x02000909, 0x02000221, 0x04000003, 13, 0x254a14a9 },
630 { 280000000, 120000000, 0x0209, 0x04000021, 0x01030303, 0x02000221, 0x04000003, 13, 0x254a14a9 },
631 { 288000000, 123428571, 0x0111, 0x04000021, 0x01030303, 0x02000221, 0x04000003, 13, 0x254a14a9 },
632 { 300000000, 120000000, 0x0009, 0x04000009, 0x01030203, 0x02000902, 0x04000002, 9, 0x02520129 },
633 { 300000000, 150000000, 0x0009, 0x04000005, 0x01030203, 0x04000005, 0x04000002, 11, 0x0aaa0555 }
636 static n4m_table_t BCMINITDATA(type7_table)[] = {
637 { 183333333, 91666666, 0x0605, 0x04000011, 0x11030011, 0x04000011, 0x04000003, 11, 0x0aaa0555 },
638 { 187500000, 93750000, 0x0a03, 0x04000011, 0x11030011, 0x04000011, 0x04000003, 11, 0x0aaa0555 },
639 { 196875000, 98437500, 0x1003, 0x11020005, 0x11050011, 0x11020005, 0x04000005, 11, 0x0aaa0555 },
640 { 200000000, 100000000, 0x0311, 0x04000011, 0x11030011, 0x04000009, 0x04000003, 11, 0x0aaa0555 },
641 { 200000000, 100000000, 0x0311, 0x04020011, 0x11030011, 0x04020011, 0x04020003, 11, 0x0aaa0555 },
642 { 206250000, 103125000, 0x1103, 0x11020005, 0x11050011, 0x11020005, 0x04000005, 11, 0x0aaa0555 },
643 { 212500000, 106250000, 0x0c05, 0x11020005, 0x01030303, 0x11020005, 0x04000005, 11, 0x0aaa0555 },
644 { 215625000, 107812500, 0x1203, 0x11090009, 0x11050005, 0x11020005, 0x04000005, 11, 0x0aaa0555 },
645 { 216666666, 108333333, 0x0805, 0x11020003, 0x11030011, 0x11020003, 0x04000003, 11, 0x0aaa0555 },
646 { 225000000, 112500000, 0x0d03, 0x11020003, 0x11030011, 0x11020003, 0x04000003, 11, 0x0aaa0555 },
647 { 233333333, 116666666, 0x0905, 0x11020003, 0x11030011, 0x11020003, 0x04000003, 11, 0x0aaa0555 },
648 { 237500000, 118750000, 0x0e05, 0x11020005, 0x11210005, 0x11020005, 0x04000005, 11, 0x0aaa0555 },
649 { 240000000, 120000000, 0x0b11, 0x11020009, 0x11210009, 0x11020009, 0x04000009, 11, 0x0aaa0555 },
650 { 250000000, 125000000, 0x0f03, 0x11020003, 0x11210003, 0x11020003, 0x04000003, 11, 0x0aaa0555 }
653 ulong start, end, dst;
654 bool ret = FALSE;
656 /* get index of the current core */
657 idx = sb_coreidx(sbh);
658 clockcontrol_m2 = NULL;
660 /* switch to extif or chipc core */
661 if ((eir = (extifregs_t *) sb_setcore(sbh, SB_EXTIF, 0))) {
662 pll_type = PLL_TYPE1;
663 clockcontrol_n = &eir->clockcontrol_n;
664 clockcontrol_sb = &eir->clockcontrol_sb;
665 clockcontrol_pci = &eir->clockcontrol_pci;
666 clockcontrol_m2 = &cc->clockcontrol_m2;
667 } else if ((cc = (chipcregs_t *) sb_setcore(sbh, SB_CC, 0))) {
668 pll_type = R_REG(&cc->capabilities) & CAP_PLL_MASK;
669 if (pll_type == PLL_TYPE6) {
670 clockcontrol_n = NULL;
671 clockcontrol_sb = NULL;
672 clockcontrol_pci = NULL;
673 } else {
674 clockcontrol_n = &cc->clockcontrol_n;
675 clockcontrol_sb = &cc->clockcontrol_sb;
676 clockcontrol_pci = &cc->clockcontrol_pci;
677 clockcontrol_m2 = &cc->clockcontrol_m2;
679 } else
680 goto done;
682 if (pll_type == PLL_TYPE6) {
683 /* Silence compilers */
684 orig_n = orig_sb = orig_pci = 0;
685 } else {
686 /* Store the current clock register values */
687 orig_n = R_REG(clockcontrol_n);
688 orig_sb = R_REG(clockcontrol_sb);
689 orig_pci = R_REG(clockcontrol_pci);
692 if (pll_type == PLL_TYPE1) {
693 /* Keep the current PCI clock if not specified */
694 if (pciclock == 0) {
695 pciclock = sb_clock_rate(pll_type, R_REG(clockcontrol_n), R_REG(clockcontrol_pci));
696 pciclock = (pciclock <= 25000000) ? 25000000 : 33000000;
699 /* Search for the closest MIPS clock less than or equal to a preferred value */
700 for (i = 0; i < ARRAYSIZE(BCMINIT(type1_table)); i++) {
701 ASSERT(BCMINIT(type1_table)[i].mipsclock ==
702 sb_clock_rate(pll_type, BCMINIT(type1_table)[i].n, BCMINIT(type1_table)[i].sb));
703 if (BCMINIT(type1_table)[i].mipsclock > mipsclock)
704 break;
706 if (i == 0) {
707 ret = FALSE;
708 goto done;
709 } else {
710 ret = TRUE;
711 i--;
713 ASSERT(BCMINIT(type1_table)[i].mipsclock <= mipsclock);
715 /* No PLL change */
716 if ((orig_n == BCMINIT(type1_table)[i].n) &&
717 (orig_sb == BCMINIT(type1_table)[i].sb) &&
718 (orig_pci == BCMINIT(type1_table)[i].pci33))
719 goto done;
721 /* Set the PLL controls */
722 W_REG(clockcontrol_n, BCMINIT(type1_table)[i].n);
723 W_REG(clockcontrol_sb, BCMINIT(type1_table)[i].sb);
724 if (pciclock == 25000000)
725 W_REG(clockcontrol_pci, BCMINIT(type1_table)[i].pci25);
726 else
727 W_REG(clockcontrol_pci, BCMINIT(type1_table)[i].pci33);
729 /* Reset */
730 sb_watchdog(sbh, 1);
732 while (1);
733 } else if ((pll_type == PLL_TYPE3) &&
734 (BCMINIT(sb_chip)(sbh) != BCM5365_DEVICE_ID)) {
735 /* 5350 */
736 /* Search for the closest MIPS clock less than or equal to a preferred value */
738 for (i = 0; i < ARRAYSIZE(type3_table); i++) {
739 if (type3_table[i].mipsclock > mipsclock)
740 break;
742 if (i == 0) {
743 ret = FALSE;
744 goto done;
745 } else {
746 ret = TRUE;
747 i--;
749 ASSERT(type3_table[i].mipsclock <= mipsclock);
751 /* No PLL change */
752 orig_m2 = R_REG(&cc->clockcontrol_m2);
753 if ((orig_n == type3_table[i].n) &&
754 (orig_m2 == type3_table[i].m2)) {
755 goto done;
758 /* Set the PLL controls */
759 W_REG(clockcontrol_n, type3_table[i].n);
760 W_REG(clockcontrol_m2, type3_table[i].m2);
762 /* Reset */
763 sb_watchdog(sbh, 1);
764 while (1);
765 } else if ((pll_type == PLL_TYPE2) ||
766 (pll_type == PLL_TYPE4) ||
767 (pll_type == PLL_TYPE6) ||
768 (pll_type == PLL_TYPE7)) {
769 n4m_table_t *table = NULL, *te;
770 uint tabsz = 0;
772 ASSERT(cc);
774 orig_mips = R_REG(&cc->clockcontrol_mips);
776 if (pll_type == PLL_TYPE6) {
777 uint32 new_mips = 0;
779 ret = TRUE;
780 if (mipsclock <= SB2MIPS_T6(CC_T6_M1))
781 new_mips = CC_T6_MMASK;
783 if (orig_mips == new_mips)
784 goto done;
786 W_REG(&cc->clockcontrol_mips, new_mips);
787 goto end_fill;
790 if (pll_type == PLL_TYPE2) {
791 table = BCMINIT(type2_table);
792 tabsz = ARRAYSIZE(BCMINIT(type2_table));
793 } else if (pll_type == PLL_TYPE4) {
794 table = BCMINIT(type4_table);
795 tabsz = ARRAYSIZE(BCMINIT(type4_table));
796 } else if (pll_type == PLL_TYPE7) {
797 table = BCMINIT(type7_table);
798 tabsz = ARRAYSIZE(BCMINIT(type7_table));
799 } else
800 ASSERT((char *)"No table for plltype" == NULL);
802 /* Store the current clock register values */
803 orig_m2 = R_REG(&cc->clockcontrol_m2);
804 orig_ratio_parm = 0;
805 orig_ratio_cfg = 0;
807 /* Look up current ratio */
808 for (i = 0; i < tabsz; i++) {
809 if ((orig_n == table[i].n) &&
810 (orig_sb == table[i].sb) &&
811 (orig_pci == table[i].pci33) &&
812 (orig_m2 == table[i].m2) &&
813 (orig_mips == table[i].m3)) {
814 orig_ratio_parm = table[i].ratio_parm;
815 orig_ratio_cfg = table[i].ratio_cfg;
816 break;
820 /* Search for the closest MIPS clock greater or equal to a preferred value */
821 for (i = 0; i < tabsz; i++) {
822 ASSERT(table[i].mipsclock ==
823 sb_clock_rate(pll_type, table[i].n, table[i].m3));
824 if ((mipsclock <= table[i].mipsclock) &&
825 ((sbclock == 0) || (sbclock <= table[i].sbclock)))
826 break;
828 if (i == tabsz) {
829 ret = FALSE;
830 goto done;
831 } else {
832 te = &table[i];
833 ret = TRUE;
836 /* No PLL change */
837 if ((orig_n == te->n) &&
838 (orig_sb == te->sb) &&
839 (orig_pci == te->pci33) &&
840 (orig_m2 == te->m2) &&
841 (orig_mips == te->m3))
842 goto done;
844 /* Set the PLL controls */
845 W_REG(clockcontrol_n, te->n);
846 W_REG(clockcontrol_sb, te->sb);
847 W_REG(clockcontrol_pci, te->pci33);
848 W_REG(&cc->clockcontrol_m2, te->m2);
849 W_REG(&cc->clockcontrol_mips, te->m3);
851 /* Set the chipcontrol bit to change mipsref to the backplane divider if needed */
852 if ((pll_type == PLL_TYPE7) &&
853 (te->sb != te->m2) &&
854 (sb_clock_rate(pll_type, te->n, te->m2) == 120000000))
855 W_REG(&cc->chipcontrol, R_REG(&cc->chipcontrol) | 0x100);
857 /* No ratio change */
858 if (orig_ratio_parm == te->ratio_parm)
859 goto end_fill;
861 icache_probe(MFC0(C0_CONFIG, 1), &ic_size, &ic_lsize);
863 /* Preload the code into the cache */
864 start = ((ulong) &&start_fill) & ~(ic_lsize - 1);
865 end = ((ulong) &&end_fill + (ic_lsize - 1)) & ~(ic_lsize - 1);
866 while (start < end) {
867 cache_unroll(start, Fill_I);
868 start += ic_lsize;
871 /* Copy the handler */
872 start = (ulong) &BCMINIT(handler);
873 end = (ulong) &BCMINIT(afterhandler);
874 dst = KSEG1ADDR(0x180);
875 for (i = 0; i < (end - start); i += 4)
876 *((ulong *)(dst + i)) = *((ulong *)(start + i));
878 /* Preload handler into the cache one line at a time */
879 for (i = 0; i < (end - start); i += 4)
880 cache_unroll(dst + i, Fill_I);
882 /* Clear BEV bit */
883 MTC0(C0_STATUS, 0, MFC0(C0_STATUS, 0) & ~ST0_BEV);
885 /* Enable interrupts */
886 MTC0(C0_STATUS, 0, MFC0(C0_STATUS, 0) | (ALLINTS | ST0_IE));
888 /* Enable MIPS timer interrupt */
889 if (!(mipsr = sb_setcore(sbh, SB_MIPS, 0)) &&
890 !(mipsr = sb_setcore(sbh, SB_MIPS33, 0)))
891 ASSERT(mipsr);
892 W_REG(&mipsr->intmask, 1);
894 start_fill:
895 /* step 1, set clock ratios */
896 MTC0(C0_BROADCOM, 3, te->ratio_parm);
897 MTC0(C0_BROADCOM, 1, te->ratio_cfg);
899 /* step 2: program timer intr */
900 W_REG(&mipsr->timer, 100);
901 (void) R_REG(&mipsr->timer);
903 /* step 3, switch to async */
904 sync_mode = MFC0(C0_BROADCOM, 4);
905 MTC0(C0_BROADCOM, 4, 1 << 22);
907 /* step 4, set cfg active */
908 MTC0(C0_BROADCOM, 2, 0x9);
911 /* steps 5 & 6 */
912 __asm__ __volatile__ (
913 ".set\tmips3\n\t"
914 "wait\n\t"
915 ".set\tmips0"
918 /* step 7, clear cfg_active */
919 MTC0(C0_BROADCOM, 2, 0);
921 /* Additional Step: set back to orig sync mode */
922 MTC0(C0_BROADCOM, 4, sync_mode);
924 /* step 8, fake soft reset */
925 MTC0(C0_BROADCOM, 5, MFC0(C0_BROADCOM, 5) | 4);
927 end_fill:
928 /* step 9 set watchdog timer */
929 sb_watchdog(sbh, 20);
930 (void) R_REG(&cc->chipid);
932 /* step 11 */
933 __asm__ __volatile__ (
934 ".set\tmips3\n\t"
935 "sync\n\t"
936 "wait\n\t"
937 ".set\tmips0"
939 while (1);
942 done:
943 /* switch back to previous core */
944 sb_setcoreidx(sbh, idx);
946 return ret;
950 /* returns the ncdl value to be programmed into sdram_ncdl for calibration */
951 uint32
952 BCMINITFN(sb_memc_get_ncdl)(void *sbh)
954 sbmemcregs_t *memc;
955 uint32 ret = 0;
956 uint32 config, rd, wr, misc, dqsg, cd, sm, sd;
957 uint idx, rev;
959 idx = sb_coreidx(sbh);
961 memc = (sbmemcregs_t *)sb_setcore(sbh, SB_MEMC, 0);
962 if (memc == 0)
963 goto out;
965 rev = sb_corerev(sbh);
967 config = R_REG(&memc->config);
968 wr = R_REG(&memc->wrncdlcor);
969 rd = R_REG(&memc->rdncdlcor);
970 misc = R_REG(&memc->miscdlyctl);
971 dqsg = R_REG(&memc->dqsgatencdl);
973 rd &= MEMC_RDNCDLCOR_RD_MASK;
974 wr &= MEMC_WRNCDLCOR_WR_MASK;
975 dqsg &= MEMC_DQSGATENCDL_G_MASK;
977 if (config & MEMC_CONFIG_DDR) {
978 ret = (wr << 16) | (rd << 8) | dqsg;
979 } else {
980 if (rev > 0)
981 cd = rd;
982 else
983 cd = (rd == MEMC_CD_THRESHOLD) ? rd : (wr + MEMC_CD_THRESHOLD);
984 sm = (misc & MEMC_MISC_SM_MASK) >> MEMC_MISC_SM_SHIFT;
985 sd = (misc & MEMC_MISC_SD_MASK) >> MEMC_MISC_SD_SHIFT;
986 ret = (sm << 16) | (sd << 8) | cd;
989 out:
990 /* switch back to previous core */
991 sb_setcoreidx(sbh, idx);
993 return ret;
996 /* returns the PFC values to be used based on the chip ID*/
998 uint32
999 BCMINITFN(sb_mips_get_pfc)(void *sbh)
1001 if (BCMINIT(sb_chip)(sbh) == BCM5350_DEVICE_ID)
1002 return 0x11;
1003 else
1004 return 0x15;