Migrate UI cleanup phase 4 from MIPS into ARM
[tomato.git] / release / src-rt-6.x.4708 / shared / hndmips.c
blob70ea8fb01c6f2c9d3b4a2626f0713e3e33af5c30
1 /*
2 * BCM47XX Sonics SiliconBackplane MIPS core routines
4 * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved.
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
13 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
15 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
16 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 * $Id: hndmips.c 419467 2013-08-21 09:19:48Z $
21 #include <bcm_cfg.h>
22 #include <typedefs.h>
23 #include <bcmdefs.h>
24 #include <osl.h>
25 #include <bcmutils.h>
26 #include <siutils.h>
27 #include <bcmdevs.h>
28 #include <bcmnvram.h>
29 #include <hndsoc.h>
30 #include <sbchipc.h>
31 #include <sbmemc.h>
32 #include <mipsinc.h>
33 #include <mips33_core.h>
34 #include <mips74k_core.h>
35 #include <hndcpu.h>
36 #include <hndmips.h>
37 #include <hndpmu.h>
38 #include <dmemc_core.h>
40 /* debug/trace */
41 #ifdef BCMDBG_ERR
42 #define HNDMIPS_ERROR(args) printf args
43 #else
44 #define HNDMIPS_ERROR(args)
45 #endif /* BCMDBG_ERR */
47 #ifdef BCMDBG
48 #define HNDMIPS_MSG(args) printf args
49 #else
50 #define HNDMIPS_MSG(args)
51 #endif /* BCMDBG */
52 #define HNDMIPS_NONE(args)
54 /* sbipsflag register format, indexed by irq. */
55 static const uint32 sbips_int_mask[] = {
56 0, /* placeholder */
57 SBIPS_INT1_MASK,
58 SBIPS_INT2_MASK,
59 SBIPS_INT3_MASK,
60 SBIPS_INT4_MASK
63 static const uint32 sbips_int_shift[] = {
64 0, /* placeholder */
65 SBIPS_INT1_SHIFT,
66 SBIPS_INT2_SHIFT,
67 SBIPS_INT3_SHIFT,
68 SBIPS_INT4_SHIFT
72 * Map SB cores sharing the MIPS hardware IRQ0 to virtual dedicated OS IRQs.
73 * Per-port BSP code is required to provide necessary translations between
74 * the shared MIPS IRQ and the virtual OS IRQs based on SB core flag.
76 * See si_irq() for the mapping.
78 static uint shirq_map_base = 0;
81 * Returns the MIPS IRQ assignment of the current core. If unassigned,
82 * 0 is returned.
84 static uint
85 si_getirq(si_t *sih)
87 osl_t *osh;
88 uint idx;
89 void *regs;
90 sbconfig_t *sb;
91 uint32 flag, sbipsflag;
92 uint irq = 0;
94 osh = si_osh(sih);
95 flag = si_flag(sih);
97 idx = si_coreidx(sih);
99 if ((regs = si_setcore(sih, MIPS74K_CORE_ID, 0)) != NULL) {
100 /* IntMask1,2,3,4 regs are configured to enable propagation of
101 * backplane interrupts 0,1,2,3 to mips hw interrupts 1,2,3,4.
103 for (irq = 1; irq <= 4; irq++) {
104 if (R_REG(osh, &((mips74kregs_t *)regs)->intmask[irq]) &
105 (1 << flag))
106 break;
108 } else if ((regs = si_setcore(sih, MIPS33_CORE_ID, 0)) != NULL) {
109 sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF);
111 /* sbipsflag specifies which core is routed to interrupts 1 to 4 */
112 sbipsflag = R_REG(osh, &sb->sbipsflag);
113 for (irq = 1; irq <= 4; irq++) {
114 if (((sbipsflag & sbips_int_mask[irq]) >>
115 sbips_int_shift[irq]) == flag)
116 break;
118 } else {
119 ASSERT("Unknown processor core" == NULL);
120 return 1000; /* An invalid value */
123 /* If we didn't find it it must be in the shared int (0) */
124 if (irq == 5)
125 irq = 0;
127 si_setcoreidx(sih, idx);
129 return irq;
133 * Return the MIPS IRQ assignment of the current core. If necessary
134 * map cores sharing the MIPS hw IRQ0 to virtual dedicated OS IRQs.
136 uint
137 si_irq(si_t *sih)
139 uint irq = si_getirq(sih);
140 if (irq == 0 && shirq_map_base)
141 irq = si_flag(sih) + shirq_map_base;
142 return irq;
145 /* Clears the specified MIPS IRQ. */
146 static void
147 BCMINITFN(si_clearirq)(si_t *sih, uint irq)
149 osl_t *osh;
150 void *regs;
151 sbconfig_t *sb;
153 osh = si_osh(sih);
155 if ((regs = si_setcore(sih, MIPS74K_CORE_ID, 0)) != NULL) {
156 W_REG(osh, &((mips74kregs_t *)regs)->intmask[irq], 0);
157 } else if ((regs = si_setcore(sih, MIPS33_CORE_ID, 0)) != NULL) {
158 sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF);
159 if (irq == 0)
160 W_REG(osh, &sb->sbintvec, 0);
161 else
162 OR_REG(osh, &sb->sbipsflag, sbips_int_mask[irq]);
163 } else
164 ASSERT("Unknown processor core" == NULL);
168 * Assigns the specified MIPS IRQ to the specified core. Shared MIPS
169 * IRQ 0 may be assigned more than once.
171 * The old assignment to the specified core is removed first.
173 static void
174 BCMATTACHFN(si_setirq)(si_t *sih, uint irq, uint coreid, uint coreunit)
176 osl_t *osh;
177 void *regs;
178 sbconfig_t *sb;
179 uint32 flag;
180 uint oldirq;
182 osh = si_osh(sih);
184 regs = si_setcore(sih, coreid, coreunit);
185 ASSERT(regs);
186 flag = si_flag(sih);
187 oldirq = si_getirq(sih);
188 if (oldirq)
189 si_clearirq(sih, oldirq);
191 if ((regs = si_setcore(sih, MIPS74K_CORE_ID, 0)) != NULL) {
192 if (!oldirq)
193 AND_REG(osh, &((mips74kregs_t *)regs)->intmask[0], ~(1 << flag));
195 if (irq == 0)
196 OR_REG(osh, &((mips74kregs_t *)regs)->intmask[0], 1 << flag);
197 else {
198 W_REG(osh, &((mips74kregs_t *)regs)->intmask[irq], 1 << flag);
200 } else if ((regs = si_setcore(sih, MIPS33_CORE_ID, 0)) != NULL) {
201 sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF);
203 if (!oldirq)
204 AND_REG(osh, &sb->sbintvec, ~(1 << flag));
206 if (irq == 0)
207 OR_REG(osh, &sb->sbintvec, 1 << flag);
208 else {
209 flag <<= sbips_int_shift[irq];
210 ASSERT(!(flag & ~sbips_int_mask[irq]));
211 flag |= R_REG(osh, &sb->sbipsflag) & ~sbips_int_mask[irq];
212 W_REG(osh, &sb->sbipsflag, flag);
214 } else
215 ASSERT("Unknown processor core" == NULL);
219 * Initializes clocks and interrupts. SB and NVRAM access must be
220 * initialized prior to calling.
222 * 'shirqmap' enables virtual dedicated OS IRQ mapping if non-zero.
224 void
225 BCMATTACHFN(si_mips_init)(si_t *sih, uint shirqmap)
227 osl_t *osh;
228 uint32 c0reg;
229 ulong hz, ns, tmp;
230 chipcregs_t *cc;
231 uint irq;
233 osh = si_osh(sih);
235 /* Disable interrupts */
236 c0reg = MFC0(C0_STATUS, 0);
237 c0reg &= ~ST0_IE;
238 MTC0(C0_STATUS, 0, c0reg);
240 /* Figure out current SB clock speed */
241 if ((hz = si_clock(sih)) == 0)
242 hz = 100000000;
243 ns = 1000000000 / hz;
245 /* Setup external interface timing */
246 cc = si_setcoreidx(sih, SI_CC_IDX);
247 ASSERT(cc);
249 /* Set timing for the flash */
250 tmp = CEIL(10, ns) << FW_W3_SHIFT; /* W3 = 10nS */
251 tmp |= CEIL(10, ns) << FW_W1_SHIFT; /* W1 = 10nS */
252 tmp |= CEIL(120, ns); /* W0 = 120nS */
253 if (sih->ccrev < 9)
254 W_REG(osh, &cc->flash_waitcount, tmp);
256 if ((sih->ccrev < 9) ||
257 ((CHIPID(sih->chip) == BCM5350_CHIP_ID) && CHIPREV(sih->chiprev) == 0)) {
258 W_REG(osh, &cc->pcmcia_memwait, tmp);
261 /* Save shared IRQ mapping base */
262 shirq_map_base = shirqmap;
264 /* Chip specific initialization */
265 switch (CHIPID(sih->chip)) {
266 case BCM5350_CHIP_ID:
267 /* Clear interrupt map */
268 for (irq = 0; irq <= 4; irq++)
269 si_clearirq(sih, irq);
270 si_setirq(sih, 0, CC_CORE_ID, 0);
271 si_setirq(sih, 0, MIPS33_CORE_ID, 0);
272 si_setirq(sih, 1, D11_CORE_ID, 0);
273 si_setirq(sih, 2, ENET_CORE_ID, 0);
274 si_setirq(sih, 3, PCI_CORE_ID, 0);
275 si_setirq(sih, 4, USB_CORE_ID, 0);
276 break;
277 case BCM4785_CHIP_ID:
278 /* Reassign PCI to irq 4 */
279 si_setirq(sih, 4, PCI_CORE_ID, 0);
280 break;
281 case BCM4716_CHIP_ID:
282 case BCM4748_CHIP_ID:
283 /* Clear interrupt map */
284 for (irq = 0; irq <= 4; irq++)
285 si_clearirq(sih, irq);
286 si_setirq(sih, 1, D11_CORE_ID, 0);
287 si_setirq(sih, 2, GMAC_CORE_ID, 0);
288 si_setirq(sih, 3, USB20H_CORE_ID, 0);
289 si_setirq(sih, 4, PCIE_CORE_ID, 0);
290 si_setirq(sih, 0, CC_CORE_ID, 0);
291 si_setirq(sih, 0, I2S_CORE_ID, 0);
292 break;
293 case BCM5356_CHIP_ID:
294 case BCM47162_CHIP_ID:
295 case BCM53572_CHIP_ID:
296 /* Clear interrupt map */
297 for (irq = 0; irq <= 4; irq++)
298 si_clearirq(sih, irq);
299 si_setirq(sih, 1, D11_CORE_ID, 0);
300 si_setirq(sih, 2, GMAC_CORE_ID, 0);
301 si_setirq(sih, 0, CC_CORE_ID, 0);
302 break;
303 case BCM5357_CHIP_ID:
304 case BCM4749_CHIP_ID:
305 /* Clear interrupt map */
306 for (irq = 0; irq <= 4; irq++)
307 si_clearirq(sih, irq);
308 si_setirq(sih, 1, D11_CORE_ID, 0);
309 si_setirq(sih, 2, GMAC_CORE_ID, 0);
310 si_setirq(sih, 3, USB20H_CORE_ID, 0);
311 si_setirq(sih, 0, CC_CORE_ID, 0);
312 si_setirq(sih, 0, I2S_CORE_ID, 0);
313 break;
314 case BCM4706_CHIP_ID:
315 /* Clear interrupt map */
316 for (irq = 0; irq <= 4; irq++)
317 si_clearirq(sih, irq);
318 si_setirq(sih, 1, PCIE_CORE_ID, 0);
319 si_setirq(sih, 2, GMAC_CORE_ID, 0);
320 si_setirq(sih, 3, PCIE_CORE_ID, 1);
321 si_setirq(sih, 4, USB20H_CORE_ID, 0);
322 si_setirq(sih, 0, CC_CORE_ID, 0);
324 break;
328 /* Do any setup necessary to run a new image and jump to it. */
329 void
330 hnd_cpu_jumpto(void *addr)
332 void (*jumpto)(void) = addr;
334 (jumpto)();
337 uint32
338 BCMINITFN(si_cpu_clock)(si_t *sih)
340 osl_t *osh;
341 chipcregs_t *cc;
342 uint32 n, m;
343 uint idx;
344 uint32 pll_type, rate = 0;
347 osh = si_osh(sih);
349 if (sih->cccaps & CC_CAP_PMU)
350 return si_pmu_cpu_clock(sih, osh);
352 /* get index of the current core */
353 idx = si_coreidx(sih);
355 /* switch to chipc core */
356 cc = (chipcregs_t *)si_setcoreidx(sih, SI_CC_IDX);
357 ASSERT(cc);
359 pll_type = sih->cccaps & CC_CAP_PLL_MASK;
360 n = R_REG(osh, &cc->clockcontrol_n);
361 if ((pll_type == PLL_TYPE2) ||
362 (pll_type == PLL_TYPE4) ||
363 (pll_type == PLL_TYPE6) ||
364 (pll_type == PLL_TYPE7))
365 m = R_REG(osh, &cc->clockcontrol_m3);
366 else if (pll_type == PLL_TYPE5) {
367 rate = 200000000;
368 goto out;
369 } else if (pll_type == PLL_TYPE3) {
370 if (CHIPID(sih->chip) == BCM5365_CHIP_ID) {
371 rate = 200000000;
372 goto out;
374 /* 5350 uses m2 to control mips */
375 else
376 m = R_REG(osh, &cc->clockcontrol_m2);
377 } else
378 m = R_REG(osh, &cc->clockcontrol_sb);
380 /* calculate rate */
381 rate = si_clock_rate(pll_type, n, m);
383 if (pll_type == PLL_TYPE6)
384 rate = SB2MIPS_T6(rate);
386 out:
387 /* switch back to previous core */
388 si_setcoreidx(sih, idx);
390 return rate;
393 uint32
394 BCMINITFN(si_mem_clock)(si_t *sih)
396 osl_t *osh;
398 osh = si_osh(sih);
400 if (sih->cccaps & CC_CAP_PMU)
401 return si_pmu_mem_clock(sih, osh);
403 return si_clock(sih);
406 #define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4)
408 static void __attribute__ ((__noinline__))
409 ephy_poll_phyaccess(void)
411 asm("phypoll: \tlui $8, 0xb800\n\t"
412 "lw $9, 0x2180($8)\n\t"
413 "lui $8, 0x4000\n\t"
414 "and $9, $9, $8\n\t"
415 "bnez $9, phypoll\n\t"
416 "nop");
419 static void __attribute__ ((__noinline__))
420 coma_delay(void)
422 /* for (i = 0; i < 3000000; i++); */
423 asm("lui $8, 0x2d\n\t"
424 "ori $8,$8,0xc6c0\n\t"
425 "coma_delay_loop: \taddiu $8,$8,-1\n\t"
426 "bnez $8,coma_delay_loop\n\t"
427 "nop");
430 static void __attribute__ ((__noinline__))
431 do_router_coma(si_t *sih, void *dmem, int delay)
433 uint8 phy;
435 /* set jtag user reg 0 = 0x80 to set DDR pad power saving mode */
436 asm("lui $8, 0xb800");
437 asm("li $9, 0xff03ff3a"); /* (16 + addr) << 20 | 0xfe03ff3a */
438 asm("sw $9, 0x0034($8)");
439 asm("li $9, 0x80"); /* data */
440 asm("sw $9, 0x0038($8)");
441 asm("li $9, 0x80071f1f");
442 asm("sw $9, 0x0030($8)");
443 asm("sync");
445 coma_delay();
447 /* ephy ports powerdown */
449 /* robo_wreg 0x0 0xf 0x1f 0x2 */
450 asm("lui $8, 0xb800");
451 asm("li $9, 0x0090001e");
452 asm("sw $9, 0x2188($8)");
453 asm("sync");
454 asm("nop");
455 asm("lui $8, 0xb800");
456 asm("li $9, 0x701e0001");
457 asm("sw $9, 0x2180($8)");
458 asm("sync");
459 asm("nop");
461 ephy_poll_phyaccess();
463 asm("lui $8, 0xb800");
464 asm("li $9, 0x0090001e");
465 asm("sw $9, 0x2188($8)");
466 asm("sync");
467 asm("nop");
468 asm("lui $8, 0xb800");
469 asm("li $9, 0x781e001f");
470 asm("sw $9, 0x2180($8)");
471 asm("sync");
472 asm("nop");
474 ephy_poll_phyaccess();
476 asm("lui $8, 0xb800");
477 asm("li $9, 0x0090001e");
478 asm("sw $9, 0x2188($8)");
479 asm("sync");
480 asm("nop");
481 asm("lui $8, 0xb800");
482 asm("li $9, 0x711e0f01");
483 asm("sw $9, 0x2180($8)");
484 asm("sync");
485 asm("nop");
487 ephy_poll_phyaccess();
489 asm("lui $8, 0xb800");
490 asm("li $9, 0x0090001e");
491 asm("sw $9, 0x2188($8)");
492 asm("sync");
493 asm("nop");
494 asm("lui $8, 0xb800");
495 asm("li $9, 0x511e0000");
496 asm("sw $9, 0x2180($8)");
497 asm("sync");
498 asm("nop");
500 ephy_poll_phyaccess();
502 /* ports 0-5 writes start */
504 asm("li $10, 0");
506 for (phy = 0; phy < 5; phy++) {
508 asm("sll $11, $10, 16");
510 asm("li $9, 0x00900000");
511 asm("or $9, $9, $10");
512 asm("lui $8, 0xb800");
513 asm("sw $9, 0x2188($8)");
514 asm("sync");
515 asm("nop");
516 asm("li $9, 0x7f00008b");
517 asm("or $9, $9, $11");
518 asm("lui $8, 0xb800");
519 asm("sw $9, 0x2180($8)");
520 asm("sync");
521 asm("nop");
523 ephy_poll_phyaccess();
525 asm("li $9, 0x00900000");
526 asm("or $9, $9, $10");
527 asm("lui $8, 0xb800");
528 asm("sw $9, 0x2188($8)");
529 asm("sync");
530 asm("nop");
531 asm("li $9, 0x74006000");
532 asm("or $9, $9, $11");
533 asm("lui $8, 0xb800");
534 asm("sw $9, 0x2180($8)");
535 asm("sync");
536 asm("nop");
538 ephy_poll_phyaccess();
540 asm("li $9, 0x00900000");
541 asm("or $9, $9, $10");
542 asm("lui $8, 0xb800");
543 asm("sw $9, 0x2188($8)");
544 asm("sync");
545 asm("nop");
546 asm("li $9, 0x70000700");
547 asm("or $9, $9, $11");
548 asm("lui $8, 0xb800");
549 asm("sw $9, 0x2180($8)");
550 asm("sync");
551 asm("nop");
553 ephy_poll_phyaccess();
555 asm("li $9, 0x00900000");
556 asm("or $9, $9, $10");
557 asm("lui $8, 0xb800");
558 asm("sw $9, 0x2188($8)");
559 asm("sync");
560 asm("nop");
561 asm("li $9, 0x71001000");
562 asm("or $9, $9, $11");
563 asm("lui $8, 0xb800");
564 asm("sw $9, 0x2180($8)");
565 asm("sync");
566 asm("nop");
568 ephy_poll_phyaccess();
570 asm("li $9, 0x00900000");
571 asm("or $9, $9, $10");
572 asm("lui $8, 0xb800");
573 asm("sw $9, 0x2188($8)");
574 asm("sync");
575 asm("nop");
576 asm("li $9, 0x7f00000b");
577 asm("or $9, $9, $11");
578 asm("lui $8, 0xb800");
579 asm("sw $9, 0x2180($8)");
580 asm("sync");
581 asm("nop");
583 ephy_poll_phyaccess();
585 asm("addi $10, $10, 1");
588 coma_delay();
589 /* ports 0-5 writes end */
591 if (((CHIPID(sih->chip)) == BCM53572_CHIP_ID)) {
592 /* set ephy pll and bias power save through chipc registers */
593 asm("lui $8, 0xb800");
594 asm("li $9, 0x4");
595 asm("sw $9, 0x0650($8)");
596 asm("li $9, 0x8a60e001");
597 asm("sw $9, 0x0654($8)");
598 asm("sync");
599 asm("nop");
601 coma_delay();
603 asm("lui $8, 0xb800");
604 asm("li $9, 0x2");
605 asm("sw $9, 0x0650($8)");
606 asm("li $9, 0xcad0000f");
607 asm("sw $9, 0x0654($8)");
608 asm("sync");
609 asm("nop");
611 coma_delay();
613 /* Clear the dmems ddrctrl reg */
614 asm("lui $8, 0xb800");
615 asm("li $9, 0x0");
616 asm("sw $9, 0x41e4($8)");
617 asm("sync");
618 asm("nop");
620 coma_delay();
622 else {
623 /* A0 vs B0 steps */
624 if (sih->chiprev == 0) {
626 /* set jtag user reg 3 = 0x60000 to turn off ephy pll and bias power */
627 asm("lui $8, 0xb800");
628 asm("li $9, 0xff33ff3a"); /* (16 + addr) << 20 | 0xfe03ff3a */
629 asm("sw $9, 0x0034($8)");
630 asm("li $9, 0x60000"); /* data */
631 asm("sw $9, 0x0038($8)");
632 asm("li $9, 0x80071f1f");
633 asm("sw $9, 0x0030($8)");
634 asm("sync");
636 coma_delay();
637 } else {
639 /* set ephy pll and bias power power save through chipc registers */
640 asm("lui $8, 0xb800");
641 asm("li $9, 0x4");
642 asm("sw $9, 0x0650($8)");
643 asm("li $9, 0x8a60e001");
644 asm("sw $9, 0x0654($8)");
645 asm("sync");
646 asm("nop");
648 coma_delay();
650 asm("lui $8, 0xb800");
651 asm("li $9, 0x2");
652 asm("sw $9, 0x0650($8)");
653 asm("li $9, 0xcad0000f");
654 asm("sw $9, 0x0654($8)");
655 asm("sync");
656 asm("nop");
658 coma_delay();
662 /* set jtag user reg 7 = 0xc0 to turn off the pll and bias power of ephy */
663 asm("lui $8, 0xb800");
664 asm("li $9, 0xff73ff3a");
665 asm("sw $9, 0x0034($8)");
666 asm("li $9, 0xc0"); /* data */
667 asm("sw $9, 0x0038($8)");
668 asm("li $9, 0x80071f1f");
669 asm("sw $9, 0x0030($8)");
670 asm("sync");
672 coma_delay();
674 /* set gmac dmp io control = 0 */
675 asm("lui $8, 0xb810");
676 asm("li $9, 0x0");
677 asm("sw $9, 0x2408($8)");
678 asm("sync");
679 asm("nop");
681 coma_delay();
683 if (((CHIPID(sih->chip)) == BCM53572_CHIP_ID)) {
684 /* set ddr dmp io control = 0 */
685 asm("lui $8, 0xb810");
686 asm("li $9, 0x0");
687 asm("sw $9, 0x4408($8)");
688 asm("sync");
689 asm("nop");
690 /* put dmems in reset */
691 asm("li $9, 0x1");
692 asm("sw $9, 0x4800($8)");
693 asm("sync");
694 asm("nop");
695 } else {
696 /* set ddr dmp io control = 0 */
697 asm("lui $8, 0xb810");
698 asm("li $9, 0x0");
699 asm("sw $9, 0x5408($8)");
700 asm("sync");
701 asm("nop");
702 /* put dmemc in reset */
703 asm("li $9, 0x1");
704 asm("sw $9, 0x5800($8)");
705 asm("sync");
706 asm("nop");
709 coma_delay();
711 /* set PMU control = 1 */
712 asm("lui $8, 0xb800");
713 asm("li $9, 0x1");
714 asm("sw $9, 0x0600($8)");
715 asm("sync");
716 asm("nop");
718 coma_delay();
720 if (((CHIPID(sih->chip)) != BCM53572_CHIP_ID)) {
721 /* Set switching freq of internal 12V regulator to 600kHz */
722 asm("lui $8, 0xb800");
723 asm("li $9, 0x1");
724 asm("sw $9, 0x0658($8)");
725 asm("sync");
726 asm("nop");
727 asm("lui $8, 0xb800");
728 asm("li $9, 0x00018000");
729 asm("sw $9, 0x065c($8)");
730 asm("sync");
731 asm("nop");
733 coma_delay();
736 /* set mips dmp io control = 0 */
737 asm("lui $8, 0xb810");
738 asm("li $9, 0x0");
739 asm("sw $9, 0x3408($8)");
740 asm("sync");
741 asm("nop");
743 /* wait for watch dog timer done */
744 __asm__(
745 ".set\tmips3\n\t"
746 "sync\n\t"
747 "wait\n\t"
748 ".set\tmips0");
750 asm("nop");
751 asm("nop");
754 static void __attribute__ ((__noinline__))
755 BCMINITFN(aftercoma)(void)
760 void
761 si_router_coma(si_t *sih, int reset, int delay)
763 void *dmem = NULL;
764 chipcregs_t *cc;
765 uint ic_size, ic_lsize;
766 ulong start, end;
767 uint32 c0reg;
768 uint32 tmp;
769 int i;
770 osl_t *osh;
773 osh = si_osh(sih);
774 /* Disable interrupts */
776 c0reg = MFC0(C0_STATUS, 0);
777 tmp = (c0reg & ~(ALLINTS | ST0_IE));
778 MTC0(C0_STATUS, 0, tmp);
780 icache_probe(MFC0(C0_CONFIG, 1), &ic_size, &ic_lsize);
782 /* Put coma routine into the icache */
783 start = (ulong)&ephy_poll_phyaccess;
784 end = (ulong)&aftercoma;
785 for (i = 0; i < (end - start); i += ic_lsize)
786 cache_op(start + i, Fill_I);
788 /* Prepare JTAG registers */
789 si_setcore(sih, CC_CORE_ID, 0);
790 cc = (chipcregs_t *)si_setcoreidx(sih, SI_CC_IDX);
792 W_REG(osh, &cc->jtagctrl, 0x01);
793 W_REG(osh, &cc->jtagcmd, 0x80030000);
794 W_REG(osh, &cc->gpioouten, 0x0);
796 /* disable gpios */
797 W_REG(osh, &cc->gpioouten, 0x0);
798 W_REG(osh, &cc->chipcontrol_addr, 0x2);
799 W_REG(osh, &cc->chipcontrol_data, 0x04000600);
801 /* Set the watchdog */
802 if (((CHIPID(sih->chip)) == BCM5357_CHIP_ID) && (sih->chiprev == 0)) {
803 W_REG(osh, &cc->watchdog, reset*ILP_CLOCK);
804 } else {
805 si_watchdog_ms(sih, reset*1000);
808 if (((CHIPID(sih->chip)) == BCM53572_CHIP_ID))
809 dmem = (void *)si_setcore(sih, DMEMS_CORE_ID, 0);
810 else
811 dmem = (void *)si_setcore(sih, DMEMC_CORE_ID, 0);
813 do_router_coma(sih, dmem, delay);
816 #define PLL_ENTRIES_4706 1
817 static bool
818 BCMINITFN(mips_pmu_setclock_4706)(si_t *sih, uint32 mipsclock,
819 uint32 ddrclock, uint32 axiclock)
821 chipcregs_t *cc = NULL;
822 osl_t *osh;
823 uint idx, i;
824 bool ret = TRUE, boolChanged = FALSE;
825 /* 25MHz table for 4706 */
826 static uint32 BCMINITDATA(pll25mhz_table)[][3 + PLL_ENTRIES_4706] = {
827 /* cpu, ddr, axi, proc_PLL, */
828 { 200, 100, 50, 0xc0011080, },
829 { 300, 150, 75, 0xc00110c0, },
830 { 400, 200, 100, 0xc0011100, },
831 { 500, 250, 125, 0xc0011140, },
832 { 600, 300, 150, 0xc0011180, },
833 { 632, 316, 158, 0xc00157e8, },
834 { 650, 325, 162, 0xc00111a0, },
835 { 662, 331, 165, 0xc00111a8, },
838 static uint32 BCMINITDATA(pll25mhz_table_4706L)[][3 + PLL_ENTRIES_4706] = {
839 /* cpu, ddr, axi, proc_PLL, */
840 { 200, 100, 50, 0xc0011100, },
841 { 300, 150, 75, 0xc0011180, },
842 { 400, 200, 100, 0xc0011200, },
845 uint32 (*pll_table)[4] = pll25mhz_table;
847 /* Since we already in 4706 specific routine, we no longer check the chip id
848 * The 4706L PLL m value is default to 4, thus the n value needs to be doubled
849 * And since it supports the max frequency is 400MHz, we replace the pll table
850 * here
852 if (sih->chippkg == BCM4706L_PKG_ID) {
853 pll_table = pll25mhz_table_4706L;
856 osh = si_osh(sih);
858 /* get index of the current core */
859 idx = si_coreidx(sih);
861 /* switch to chipc core */
862 cc = (chipcregs_t *)si_setcoreidx(sih, SI_CC_IDX);
863 ASSERT(cc);
865 mipsclock /= 1000000;
866 ddrclock /= 1000000;
867 axiclock /= 1000000;
869 for (idx = 0; pll_table[idx][0] != 0; idx++) {
870 if ((mipsclock <= pll_table[idx][0]) &&
871 ((ddrclock == 0) || (ddrclock <= pll_table[idx][1])) &&
872 ((axiclock == 0) || (axiclock <= pll_table[idx][2])))
873 break;
876 if (pll_table[idx][0] == 0) {
877 ret = FALSE;
878 goto done;
881 for (i = 0; i < PLL_ENTRIES_4706; i++) {
882 W_REG(osh, &cc->pllcontrol_addr, PMU6_4706_PROCPLL_OFF + i);
883 (void)R_REG(osh, &cc->pllcontrol_addr);
884 if (R_REG(osh, &cc->pllcontrol_data) != pll_table[idx][i + 3]) {
885 W_REG(osh, &cc->pllcontrol_data, pll_table[idx][i + 3]);
886 boolChanged = TRUE;
890 if (boolChanged == FALSE)
891 goto done;
893 /* Wait for the last write */
894 (void)R_REG(osh, &cc->pllcontrol_data);
896 /* And now do the pll update */
897 W_REG(osh, &cc->pmucontrol,
898 R_REG(osh, &cc->pmucontrol) | PCTL_PLL_PLLCTL_UPD);
900 __asm__ __volatile__(
901 "nop\n"
902 "nop\n"
903 "nop\n"
904 "nop");
906 done:
907 si_setcoreidx(sih, idx);
908 return ret;
912 * Set the MIPS, backplane and DDR clocks as closely as possible in chips
913 * with a PMU. So far that means 4716, 47162, 5357, and 5356 all of which share
914 * the same PLL controls.
916 static bool
917 BCMINITFN(mips_pmu_setclock)(si_t *sih, uint32 mipsclock, uint32 ddrclock, uint32 axiclock)
919 osl_t *osh;
920 chipcregs_t *cc = NULL;
921 uint idx, i;
922 uint mainpll_pll0 = PMU4716_MAINPLL_PLL0;
923 bool ret = TRUE;
924 uint32 (*pll_table)[8];
926 /* 20MHz table for 4716, 4717, 4718, 47162, 5357 */
927 static uint32 BCMINITDATA(pll20mhz_table)[][8] = {
928 /* cpu, ddr, axi, pllctl12, pllctl13, pllctl14, pllctl15, pllctl16 */
929 { 66, 66, 66, 0x11100070, 0x00121212, 0x03c00000, 0x20000000, 0x200005c0 },
930 { 75, 75, 75, 0x11100070, 0x00101010, 0x03c00000, 0x20000000, 0x200005c0 },
931 { 80, 80, 80, 0x11100070, 0x000a0a0a, 0x02800000, 0x20000000, 0x200005c0 },
932 { 83, 83, 83, 0x11100070, 0x000c0c0c, 0x03200000, 0x20000000, 0x200005c0 },
933 { 100, 66, 66, 0x11100070, 0x0012120c, 0x03c00000, 0x30000000, 0x200005c0 },
934 { 100, 100, 100, 0x11100070, 0x000c0c0c, 0x03c00000, 0x20000000, 0x200005c0 },
935 { 120, 60, 60, 0x11100070, 0x00101008, 0x03000000, 0x40000000, 0x200005c0 },
936 { 120, 120, 120, 0x11100070, 0x00080808, 0x03000000, 0x20000000, 0x200005c0 },
937 { 125, 83, 83, 0x11100070, 0x000c0c08, 0x03200000, 0x30000000, 0x200005c0 },
938 { 133, 66, 66, 0x11100070, 0x0018180c, 0x05000000, 0x40000000, 0x200005c0 },
939 { 133, 133, 133, 0x11100070, 0x000c0c0c, 0x05000000, 0x20000000, 0x200005c0 },
940 { 148, 148, 74, 0x11100070, 0x00120909, 0x04300000, 0x28000000, 0x200005c0 },
941 { 150, 75, 75, 0x11100070, 0x00101008, 0x03c00000, 0x40000000, 0x200005c0 },
942 { 150, 100, 100, 0x11100070, 0x000c0c08, 0x03c00000, 0x30000000, 0x200005c0 },
943 { 150, 150, 75, 0x11100070, 0x00100808, 0x03c00000, 0x28000000, 0x200005c0 },
944 { 150, 150, 150, 0x11100070, 0x00080808, 0x03c00000, 0x20000000, 0x200005c0 },
945 { 155, 155, 77, 0x11100070, 0x00120909, 0x04600000, 0x28000000, 0x200005c0 },
946 { 155, 155, 155, 0x11100070, 0x00090909, 0x04600000, 0x20000000, 0x200005c0 },
947 { 166, 83, 83, 0x11100070, 0x000c0c06, 0x03200000, 0x40000000, 0x200005c0 },
948 { 166, 166, 83, 0x11100070, 0x000c0606, 0x03200000, 0x28000000, 0x200005c0 },
949 { 166, 166, 166, 0x11100070, 0x00060606, 0x03200000, 0x20000000, 0x200005c0 },
950 { 200, 200, 100, 0x11100070, 0x000c0606, 0x03c00000, 0x28000000, 0x200005c0 },
951 { 223, 148, 74, 0x11100070, 0x00120906, 0x04300000, 0x38000000, 0x200005c0 },
952 { 240, 120, 120, 0x11100070, 0x00080804, 0x03000000, 0x40000000, 0x200005c0 },
953 { 240, 240, 120, 0x11100070, 0x00080404, 0x03000000, 0x28000000, 0x200005c0 },
954 { 250, 166, 83, 0x11100070, 0x000c0604, 0x03200000, 0x38000000, 0x200005c0 },
955 { 250, 166, 166, 0x11100070, 0x00060604, 0x03200000, 0x30000000, 0x200005c0 },
956 { 266, 133, 133, 0x11100070, 0x000c0c06, 0x05000000, 0x40000000, 0x200005c0 },
957 { 266, 266, 133, 0x11100070, 0x000c0606, 0x05000000, 0x28000000, 0x200005c0 },
958 { 300, 100, 100, 0x11100070, 0x000c0c04, 0x03c00000, 0x60000000, 0x200005c0 },
959 { 300, 150, 75, 0x11100070, 0x00100804, 0x03c00000, 0x48000000, 0x200005c0 },
960 { 300, 150, 150, 0x11100070, 0x00080804, 0x03c00000, 0x40000000, 0x200005c0 },
961 { 300, 200, 100, 0x11100070, 0x000c0604, 0x03c00000, 0x38000000, 0x200005c0 },
962 { 320, 160, 80, 0x11100070, 0x00100804, 0x04000000, 0x48000000, 0x200005c0 },
963 { 320, 213, 106, 0x11100070, 0x000c0604, 0x04000000, 0x38000000, 0x200005c0 },
964 { 320, 240, 120, 0x11100070, 0x00080403, 0x03000000, 0x38000000, 0x200005c0 },
965 { 320, 256, 128, 0x11100070, 0x000a0504, 0x04000000, 0x38000000, 0x200005c0 },
966 { 330, 165, 82, 0x11100070, 0x00100804, 0x04200000, 0x48000000, 0x200005c0 },
967 { 330, 165, 165, 0x11100070, 0x00080804, 0x04200000, 0x40000000, 0x200005c0 },
968 { 333, 166, 83, 0x11100070, 0x000c0603, 0x03200000, 0x48000000, 0x200005c0 },
969 { 333, 166, 166, 0x11100070, 0x00060603, 0x03200000, 0x40000000, 0x200005c0 },
970 { 340, 226, 113, 0x11100070, 0x000c0604, 0x04400000, 0x38000000, 0x200005c0 },
971 { 350, 175, 87, 0x11100070, 0x00100804, 0x04600000, 0x48000000, 0x200005c0 },
972 { 353, 176, 88, 0x11100070, 0x000c0603, 0x03500000, 0x48000000, 0x200005c0 },
973 { 360, 240, 120, 0x11100070, 0x000c0604, 0x04800000, 0x38000000, 0x200005c0 },
974 { 370, 185, 92, 0x11100070, 0x00100804, 0x04a00000, 0x48000000, 0x200005c0 },
975 { 370, 246, 123, 0x11100070, 0x000c0604, 0x04a00000, 0x38000000, 0x200005c0 },
976 { 373, 186, 93, 0x11100070, 0x000c0603, 0x03800000, 0x48000000, 0x200005c0 },
977 { 400, 133, 133, 0x11100070, 0x000c0c04, 0x05000000, 0x60000000, 0x200005c0 },
978 { 400, 160, 80, 0x11100070, 0x00140a04, 0x05000000, 0x58000000, 0x200005c0 },
979 { 400, 160, 160, 0x11100070, 0x000a0a04, 0x05000000, 0x50000000, 0x200005c0 },
980 { 400, 200, 100, 0x11100070, 0x00100804, 0x05000000, 0x48000000, 0x200005c0 },
981 { 400, 266, 133, 0x11100070, 0x000c0604, 0x05000000, 0x38000000, 0x200005c0 },
982 { 426, 213, 106, 0x11100070, 0x000c0603, 0x04000000, 0x48000000, 0x200005c0 },
983 { 440, 220, 110, 0x11100070, 0x000c0603, 0x04200000, 0x48000000, 0x200005c0 },
984 { 446, 148, 74, 0x11100070, 0x00120903, 0x04300000, 0x68000000, 0x200005c0 },
985 { 453, 226, 113, 0x11100070, 0x000c0603, 0x04400000, 0x48000000, 0x200005c0 },
986 { 466, 233, 116, 0x11100070, 0x000c0603, 0x04600000, 0x48000000, 0x200005c0 },
987 { 480, 137, 68, 0x11100070, 0x000e0702, 0x03000000, 0x78000000, 0x200005c0 },
988 { 480, 137, 137, 0x11100070, 0x00070702, 0x03000000, 0x70000000, 0x200005c0 },
989 { 480, 160, 80, 0x11100070, 0x000c0602, 0x03000000, 0x68000000, 0x200005c0 },
990 { 480, 240, 120, 0x11100070, 0x00080402, 0x03000000, 0x48000000, 0x200005c0 },
991 { 500, 100, 100, 0x11100070, 0x000a0a02, 0x03200000, 0xa0000000, 0x200005c0 },
992 { 500, 166, 83, 0x11100070, 0x000c0602, 0x03200000, 0x68000000, 0x200005c0 },
993 { 500, 166, 166, 0x11100070, 0x00060602, 0x03200000, 0x60000000, 0x200005c0 },
994 { 500, 200, 100, 0x11100070, 0x000a0502, 0x03200000, 0x58000000, 0x200005c0 },
995 { 500, 250, 125, 0x11100070, 0x00080402, 0x03200000, 0x48000000, 0x200005c0 },
996 { 530, 176, 88, 0x11100070, 0x000c0602, 0x03500000, 0x68000000, 0x200005c0 },
997 { 530, 176, 176, 0x11100070, 0x00060602, 0x03500000, 0x60000000, 0x200005c0 },
998 { 530, 212, 106, 0x11100070, 0x000a0502, 0x03500000, 0x58000000, 0x200005c0 },
999 { 530, 265, 132, 0x11100070, 0x00080402, 0x03500000, 0x48000000, 0x200005c0 },
1000 { 533, 133, 133, 0x11100070, 0x000c0c03, 0x05000000, 0x80000000, 0x200005c0 },
1001 { 533, 266, 133, 0x11100070, 0x000c0603, 0x05000000, 0x48000000, 0x200005c0 },
1005 /* 25MHz table for 5356 */
1006 static uint32 BCMINITDATA(pll25mhz_table)[][8] = {
1007 /* cpu, ddr, axi, pllctl12, pllctl13, pllctl14, pllctl15, pllctl16 */
1008 { 66, 66, 66, 0x11100070, 0x00121212, 0x03000000, 0x20000000, 0x200005c0 },
1009 { 75, 75, 75, 0x11100070, 0x00101010, 0x03000000, 0x20000000, 0x200005c0 },
1010 { 80, 80, 80, 0x11100070, 0x000a0a0a, 0x02000000, 0x20000000, 0x200005c0 },
1011 { 83, 83, 83, 0x11100070, 0x000c0c0c, 0x02800000, 0x20000000, 0x200005c0 },
1012 { 100, 66, 66, 0x11100070, 0x0012120c, 0x03000000, 0x30000000, 0x200005c0 },
1013 { 100, 100, 100, 0x11100070, 0x000c0c0c, 0x03000000, 0x20000000, 0x200005c0 },
1014 { 125, 83, 83, 0x11100070, 0x000c0c08, 0x02800000, 0x30000000, 0x200005c0 },
1015 { 133, 133, 133, 0x11100070, 0x000c0c0c, 0x04000000, 0x20000000, 0x200005c0 },
1016 { 150, 75, 75, 0x11100070, 0x00101008, 0x03000000, 0x40000000, 0x200005c0 },
1017 { 150, 100, 100, 0x11100070, 0x000c0c08, 0x03000000, 0x30000000, 0x200005c0 },
1018 { 150, 150, 75, 0x11100070, 0x00100808, 0x03000000, 0x28000000, 0x200005c0 },
1019 { 150, 150, 150, 0x11100070, 0x00080808, 0x03000000, 0x20000000, 0x200005c0 },
1020 { 166, 83, 83, 0x11100070, 0x000c0c06, 0x02800000, 0x40000000, 0x200005c0 },
1021 { 166, 166, 83, 0x11100070, 0x000c0606, 0x02800000, 0x28000000, 0x200005c0 },
1022 { 166, 166, 166, 0x11100070, 0x00060606, 0x02800000, 0x20000000, 0x200005c0 },
1023 { 200, 133, 133, 0x11100070, 0x000c0c08, 0x04000000, 0x30000000, 0x200005c0 },
1024 { 200, 200, 100, 0x11100070, 0x000c0606, 0x03000000, 0x28000000, 0x200005c0 },
1025 { 250, 166, 83, 0x11100070, 0x000c0604, 0x02800000, 0x38000000, 0x200005c0 },
1026 { 250, 166, 166, 0x11100070, 0x00060604, 0x02800000, 0x30000000, 0x200005c0 },
1027 { 293, 195, 97, 0x11100070, 0x000c0604, 0x02f00000, 0x38000000, 0x200005c0 },
1028 { 300, 100, 100, 0x11100070, 0x000c0c04, 0x03000000, 0x60000000, 0x200005c0 },
1029 { 300, 120, 120, 0x11100070, 0x000a0a04, 0x03000000, 0x50000000, 0x200005c0 },
1030 { 300, 150, 75, 0x11100070, 0x00100804, 0x03000000, 0x48000000, 0x200005c0 },
1031 { 300, 150, 150, 0x11100070, 0x00080804, 0x03000000, 0x40000000, 0x200005c0 },
1032 { 300, 200, 100, 0x11100070, 0x000c0604, 0x03000000, 0x38000000, 0x200005c0 },
1033 { 332, 110, 110, 0x11100070, 0x000c0c04, 0x03540000, 0x6047ae14, 0x202c2820 },
1034 { 332, 133, 133, 0x11100070, 0x000a0a04, 0x03540000, 0x5047ae14, 0x202c2820 },
1035 { 332, 166, 83, 0x11100070, 0x00100804, 0x03540000, 0x4847ae14, 0x202c2820 },
1036 { 333, 111, 111, 0x11100070, 0x00090903, 0x02800000, 0x60000000, 0x200005c0 },
1037 { 333, 133, 133, 0x11100070, 0x000f0f06, 0x05000000, 0x50000000, 0x38000700 },
1038 { 333, 166, 83, 0x11100070, 0x000c0603, 0x02800000, 0x48000000, 0x200005c0 },
1039 { 333, 166, 166, 0x11100070, 0x00060603, 0x02800000, 0x40000000, 0x200005c0 },
1040 { 400, 133, 133, 0x11100070, 0x000c0c04, 0x04000000, 0x60000000, 0x200005c0 },
1041 { 400, 200, 100, 0x11100070, 0x000c0603, 0x03000000, 0x48000000, 0x200005c0 },
1042 { 400, 266, 133, 0x11100070, 0x000c0604, 0x04000000, 0x38000000, 0x200005c0 },
1043 { 500, 166, 83, 0x11100070, 0x000c0602, 0x02800000, 0x68000000, 0x200005c0 },
1044 { 500, 166, 166, 0x11100070, 0x00060602, 0x02800000, 0x60000000, 0x200005c0 },
1045 { 500, 200, 100, 0x11100070, 0x000a0502, 0x02800000, 0x58000000, 0x200005c0 },
1046 { 500, 250, 125, 0x11100070, 0x00080402, 0x02800000, 0x48000000, 0x200005c0 },
1050 if (CHIPID(sih->chip) == BCM4706_CHIP_ID)
1051 return mips_pmu_setclock_4706(sih, mipsclock, ddrclock, axiclock);
1053 /* By default use the 20MHz pll table */
1054 pll_table = pll20mhz_table;
1056 osh = si_osh(sih);
1058 /* Adjust the mainpll_pll0 address and pll table for 5356 */
1059 if (CHIPID(sih->chip) == BCM5356_CHIP_ID) {
1060 mainpll_pll0 = PMU5356_MAINPLL_PLL0;
1061 pll_table = pll25mhz_table;
1063 /* Adjust the mainpll_pll0 address and pll table for 5357 */
1064 if ((CHIPID(sih->chip) == BCM5357_CHIP_ID) ||
1065 (CHIPID(sih->chip) == BCM4749_CHIP_ID)) {
1066 mainpll_pll0 = PMU5357_MAINPLL_PLL0;
1067 pll_table = pll20mhz_table;
1070 /* get index of the current core */
1071 idx = si_coreidx(sih);
1073 /* switch to chipc core */
1074 cc = (chipcregs_t *)si_setcoreidx(sih, SI_CC_IDX);
1075 ASSERT(cc);
1077 mipsclock /= 1000000;
1078 ddrclock /= 1000000;
1079 axiclock /= 1000000;
1081 HNDMIPS_NONE(("Looking for %d/%d/%d\n", mipsclock, ddrclock, axiclock));
1083 for (idx = 0; pll_table[idx][0] != 0; idx++) {
1084 uint16 chippkg;
1085 /* Bypass pll entries that are not allowed */
1086 if ((((pll_table[idx][4] & 0xff) < 4) ||
1087 (((pll_table[idx][5] >> 20) & 0x1ff) > 0x50)) &&
1088 ((CHIPID(sih->chip) == BCM5357_CHIP_ID) ||
1089 (CHIPID(sih->chip) == BCM4749_CHIP_ID)) &&
1090 (((chippkg = R_REG(osh, &cc->sromotp[23])) & 0x80) == 0x80)) {
1091 continue;
1093 if ((mipsclock <= pll_table[idx][0]) &&
1094 ((ddrclock == 0) || (ddrclock <= pll_table[idx][1])) &&
1095 ((axiclock == 0) || (axiclock <= pll_table[idx][2])))
1096 break;
1099 if (pll_table[idx][0] == 0) {
1100 ret = FALSE;
1101 goto done;
1104 HNDMIPS_NONE(("Using entry %d: %d/%d/%d, 0x%08x, 0x%08x, 0x%08x, 0x%08x, %d\n", idx,
1105 pll_table[idx][0], pll_table[idx][1], pll_table[idx][2],
1106 pll_table[idx][3], pll_table[idx][4], pll_table[idx][5],
1107 pll_table[idx][6], pll_table[idx][7]));
1109 for (i = PMU5_PLL_P1P2_OFF; i <= PMU5_PLL_FMAB_OFF; i++) {
1110 W_REG(osh, &cc->pllcontrol_addr, mainpll_pll0 + i);
1111 (void)R_REG(osh, &cc->pllcontrol_addr);
1112 if (R_REG(osh, &cc->pllcontrol_data) != pll_table[idx][i + 3])
1113 break;
1116 /* All matched, no change needed */
1117 if (i == (PMU5_PLL_FMAB_OFF + 1))
1118 goto done;
1120 /* Write new PLL settings */
1121 for (i = PMU5_PLL_P1P2_OFF; i <= PMU5_PLL_PLLCTL_OFF; i++) {
1122 uint32 tmp;
1124 W_REG(osh, &cc->pllcontrol_addr, mainpll_pll0 + i);
1125 (void)R_REG(osh, &cc->pllcontrol_addr);
1126 tmp = pll_table[idx][i + 3];
1127 W_REG(osh, &cc->pllcontrol_data, tmp);
1129 /* Wait for the last write */
1130 (void)R_REG(osh, &cc->pllcontrol_data);
1132 if (CHIPID(sih->chip) == BCM47162_CHIP_ID) {
1133 /* In 47162, clear min_res_mask */
1134 W_REG(osh, &cc->min_res_mask,
1135 R_REG(osh, &cc->min_res_mask) & ~RES4716_PROC_HT_AVAIL);
1137 /* Reset, use chipcommon's watchdog, not the PMU */
1138 W_REG(osh, &cc->watchdog, 1000);
1140 /* And now do the pll update */
1141 W_REG(osh, &cc->pmucontrol,
1142 R_REG(osh, &cc->pmucontrol) | PCTL_PLL_PLLCTL_UPD);
1143 } else
1144 si_watchdog(sih, 100);
1146 /* wait for timer interrupt */
1147 while (1)
1148 __asm__ __volatile__(
1149 ".set\tmips3\n\t"
1150 "sync\n\t"
1151 "wait\n\t"
1152 ".set\tmips0");
1154 done:
1155 /* switch back to previous core */
1156 si_setcoreidx(sih, idx);
1158 return ret;
1161 static void
1162 BCMINITFN(handler)(void)
1164 __asm__(
1165 ".set\tmips32\n\t"
1166 "ssnop\n\t"
1167 "ssnop\n\t"
1168 /* Disable interrupts */
1169 /* MTC0(C0_STATUS, 0, MFC0(C0_STATUS, 0) & ~(ALLINTS | STO_IE)); */
1170 "mfc0 $15, $12\n\t"
1171 /* Just a Hack to not to use reg 'at' which was causing problems on 4704 A2 */
1172 "li $14, -31746\n\t"
1173 "and $15, $15, $14\n\t"
1174 "mtc0 $15, $12\n\t"
1175 "eret\n\t"
1176 "nop\n\t"
1177 "nop\n\t"
1178 ".set\tmips0");
1181 /* The following MUST come right after handler() */
1182 static void
1183 BCMINITFN(afterhandler)(void)
1188 * Set the MIPS, backplane and PCI clocks as closely as possible.
1190 * MIPS clocks synchronization function has been moved from PLL in chipcommon
1191 * core rev. 15 to a DLL inside the MIPS core in 4785.
1193 bool
1194 BCMINITFN(si_mips_setclock)(si_t *sih, uint32 mipsclock, uint32 siclock, uint32 pciclock)
1196 osl_t *osh;
1197 chipcregs_t *cc = NULL;
1198 mips33regs_t *mipsr = NULL;
1199 volatile uint32 *clockcontrol_n, *clockcontrol_sb, *clockcontrol_pci, *clockcontrol_m2;
1200 uint32 orig_n, orig_sb, orig_pci, orig_m2, orig_mips, orig_ratio_parm, orig_ratio_cfg;
1201 uint32 pll_type, sync_mode;
1202 uint ic_size, ic_lsize;
1203 uint idx, i;
1205 /* PLL configuration: type 3 */
1206 typedef struct {
1207 uint32 mipsclock;
1208 uint16 n;
1209 uint32 m2; /* that is the clockcontrol_m2 */
1210 } type3_table_t;
1211 static type3_table_t type3_table[] = {
1212 /* for 5350, mips clock is always double sb clock */
1213 { 150000000, 0x311, 0x4020005 },
1214 { 200000000, 0x311, 0x4020003 },
1217 /* PLL configuration: type 2, 4, 7 */
1218 typedef struct {
1219 uint32 mipsclock;
1220 uint32 sbclock;
1221 uint32 pciclock;
1222 uint16 n;
1223 uint32 sb;
1224 uint32 pci33;
1225 uint32 m2;
1226 uint32 m3;
1227 uint32 ratio_cfg;
1228 uint32 ratio_parm;
1229 uint32 dll_r1;
1230 uint32 dll_r2;
1231 } n4m_table_t;
1232 static n4m_table_t BCMINITDATA(type2_table)[] = {
1233 { 120000000, 60000000, 32000000, 0x0303, 0x01000200, 0x01000600, 0x01000200,
1234 0x05000200, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 },
1235 { 150000000, 75000000, 33333333, 0x0303, 0x01000100, 0x01000600, 0x01000100,
1236 0x05000100, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 },
1237 { 180000000, 80000000, 30000000, 0x0403, 0x01010000, 0x01020300, 0x01020600,
1238 0x05000100, 8, 0x012a00a9, 9 /* ratio 4/9 */, 0x012a00a9 },
1239 { 180000000, 90000000, 30000000, 0x0403, 0x01000100, 0x01020300, 0x01000100,
1240 0x05000100, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 },
1241 { 200000000, 100000000, 33333333, 0x0303, 0x02010000, 0x02040001, 0x02010000,
1242 0x06000001, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 },
1243 { 211200000, 105600000, 30171428, 0x0902, 0x01000200, 0x01030400, 0x01000200,
1244 0x05000200, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 },
1245 { 220800000, 110400000, 31542857, 0x1500, 0x01000200, 0x01030400, 0x01000200,
1246 0x05000200, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 },
1247 { 230400000, 115200000, 32000000, 0x0604, 0x01000200, 0x01020600, 0x01000200,
1248 0x05000200, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 },
1249 { 234000000, 104000000, 31200000, 0x0b01, 0x01010000, 0x01010700, 0x01020600,
1250 0x05000100, 8, 0x012a00a9, 9 /* ratio 4/9 */, 0x012a00a9 },
1251 { 240000000, 120000000, 33333333, 0x0803, 0x01000200, 0x01020600, 0x01000200,
1252 0x05000200, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 },
1253 { 252000000, 126000000, 33333333, 0x0504, 0x01000100, 0x01020500, 0x01000100,
1254 0x05000100, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 },
1255 { 264000000, 132000000, 33000000, 0x0903, 0x01000200, 0x01020700, 0x01000200,
1256 0x05000200, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 },
1257 { 270000000, 120000000, 30000000, 0x0703, 0x01010000, 0x01030400, 0x01020600,
1258 0x05000100, 8, 0x012a00a9, 9 /* ratio 4/9 */, 0x012a00a9 },
1259 { 276000000, 122666666, 31542857, 0x1500, 0x01010000, 0x01030400, 0x01020600,
1260 0x05000100, 8, 0x012a00a9, 9 /* ratio 4/9 */, 0x012a00a9 },
1261 { 280000000, 140000000, 31111111, 0x0503, 0x01000000, 0x01010600, 0x01000000,
1262 0x05000000, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 },
1263 { 288000000, 128000000, 32914285, 0x0604, 0x01010000, 0x01030400, 0x01020600,
1264 0x05000100, 8, 0x012a00a9, 9 /* ratio 4/9 */, 0x012a00a9 },
1265 { 288000000, 144000000, 32000000, 0x0404, 0x01000000, 0x01010600, 0x01000000,
1266 0x05000000, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 },
1267 { 300000000, 133333333, 33333333, 0x0803, 0x01010000, 0x01020600, 0x01010100,
1268 0x05000100, 8, 0x012a00a9, 9 /* ratio 4/9 */, 0x012a00a9 },
1269 { 300000000, 133333333, 37500000, 0x0803, 0x01010000, 0x01020500, 0x01010100,
1270 0x05000100, 8, 0x012a00a9, 9 /* ratio 4/9 */, 0x012a00a9 },
1271 { 300000000, 133333333, 42857142, 0x0803, 0x01010000, 0x01020400, 0x01010100,
1272 0x05000100, 8, 0x012a00a9, 9 /* ratio 4/9 */, 0x012a00a9 },
1273 { 300000000, 133333333, 50000000, 0x0803, 0x01010000, 0x01020300, 0x01010100,
1274 0x05000100, 8, 0x012a00a9, 9 /* ratio 4/9 */, 0x012a00a9 },
1275 { 300000000, 133333333, 60000000, 0x0803, 0x01010000, 0x01020200, 0x01010100,
1276 0x05000100, 8, 0x012a00a9, 9 /* ratio 4/9 */, 0x012a00a9 },
1277 { 300000000, 150000000, 33333333, 0x0803, 0x01000100, 0x01020600, 0x01010100,
1278 0x05000100, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 },
1279 { 300000000, 150000000, 37500000, 0x0803, 0x01000100, 0x01020500, 0x01010100,
1280 0x05000100, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 },
1281 { 300000000, 150000000, 42857142, 0x0803, 0x01000100, 0x01020400, 0x01010100,
1282 0x05000100, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 },
1283 { 300000000, 150000000, 50000000, 0x0803, 0x01000100, 0x01020300, 0x01010100,
1284 0x05000100, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 },
1285 { 300000000, 150000000, 60000000, 0x0803, 0x01000100, 0x01020200, 0x01010100,
1286 0x05000100, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 },
1287 { 330000000, 132000000, 33000000, 0x0903, 0x01000200, 0x00020200, 0x01010100,
1288 0x05000100, 0, 0, 10 /* ratio 4/10 */, 0x02520129 },
1289 { 330000000, 146666666, 33000000, 0x0903, 0x01010000, 0x00020200, 0x01010100,
1290 0x05000100, 0, 0, 9 /* ratio 4/9 */, 0x012a00a9 },
1291 { 330000000, 165000000, 33000000, 0x0903, 0x01000100, 0x00020200, 0x01010100,
1292 0x05000100, 0, 0, 8 /* ratio 4/8 */, 0x00aa0055 },
1293 { 330000000, 165000000, 41250000, 0x0903, 0x01000100, 0x00020100, 0x01010100,
1294 0x05000100, 0, 0, 8 /* ratio 4/8 */, 0x00aa0055 },
1295 { 330000000, 165000000, 55000000, 0x0903, 0x01000100, 0x00020000, 0x01010100,
1296 0x05000100, 0, 0, 8 /* ratio 4/8 */, 0x00aa0055 },
1297 { 360000000, 120000000, 32000000, 0x0a03, 0x01000300, 0x00010201, 0x01010200,
1298 0x05000100, 0, 0, 12 /* ratio 4/12 */, 0x04920492 },
1299 { 360000000, 144000000, 32000000, 0x0a03, 0x01000200, 0x00010201, 0x01010200,
1300 0x05000100, 0, 0, 10 /* ratio 4/10 */, 0x02520129 },
1301 { 360000000, 160000000, 32000000, 0x0a03, 0x01010000, 0x00010201, 0x01010200,
1302 0x05000100, 0, 0, 9 /* ratio 4/9 */, 0x012a00a9 },
1303 { 360000000, 180000000, 32000000, 0x0a03, 0x01000100, 0x00010201, 0x01010200,
1304 0x05000100, 0, 0, 8 /* ratio 4/8 */, 0x00aa0055 },
1305 { 360000000, 180000000, 40000000, 0x0a03, 0x01000100, 0x00010101, 0x01010200,
1306 0x05000100, 0, 0, 8 /* ratio 4/8 */, 0x00aa0055 },
1307 { 360000000, 180000000, 53333333, 0x0a03, 0x01000100, 0x00010001, 0x01010200,
1308 0x05000100, 0, 0, 8 /* ratio 4/8 */, 0x00aa0055 },
1309 { 390000000, 130000000, 32500000, 0x0b03, 0x01010100, 0x00020101, 0x01020100,
1310 0x05000100, 0, 0, 12 /* ratio 4/12 */, 0x04920492 },
1311 { 390000000, 156000000, 32500000, 0x0b03, 0x01000200, 0x00020101, 0x01020100,
1312 0x05000100, 0, 0, 10 /* ratio 4/10 */, 0x02520129 },
1313 { 390000000, 173000000, 32500000, 0x0b03, 0x01010000, 0x00020101, 0x01020100,
1314 0x05000100, 0, 0, 9 /* ratio 4/9 */, 0x012a00a9 },
1315 { 390000000, 195000000, 32500000, 0x0b03, 0x01000100, 0x00020101, 0x01020100,
1316 0x05000100, 0, 0, 8 /* ratio 4/8 */, 0x00aa0055 },
1318 static n4m_table_t BCMINITDATA(type4_table)[] = {
1319 { 120000000, 60000000, 0, 0x0009, 0x11020009, 0x01030203, 0x11020009, 0x04000009,
1320 11, 0x0aaa0555 },
1321 { 150000000, 75000000, 0, 0x0009, 0x11050002, 0x01030203, 0x11050002, 0x04000005,
1322 11, 0x0aaa0555 },
1323 { 192000000, 96000000, 0, 0x0702, 0x04000011, 0x11030011, 0x04000011, 0x04000003,
1324 11, 0x0aaa0555 },
1325 { 198000000, 99000000, 0, 0x0603, 0x11020005, 0x11030011, 0x11020005, 0x04000005,
1326 11, 0x0aaa0555 },
1327 { 200000000, 100000000, 0, 0x0009, 0x04020011, 0x11030011, 0x04020011, 0x04020003,
1328 11, 0x0aaa0555 },
1329 { 204000000, 102000000, 0, 0x0c02, 0x11020005, 0x01030303, 0x11020005, 0x04000005,
1330 11, 0x0aaa0555 },
1331 { 208000000, 104000000, 0, 0x0802, 0x11030002, 0x11090005, 0x11030002, 0x04000003,
1332 11, 0x0aaa0555 },
1333 { 210000000, 105000000, 0, 0x0209, 0x11020005, 0x01030303, 0x11020005, 0x04000005,
1334 11, 0x0aaa0555 },
1335 { 216000000, 108000000, 0, 0x0111, 0x11020005, 0x01030303, 0x11020005, 0x04000005,
1336 11, 0x0aaa0555 },
1337 { 224000000, 112000000, 0, 0x0205, 0x11030002, 0x02002103, 0x11030002, 0x04000003,
1338 11, 0x0aaa0555 },
1339 { 228000000, 101333333, 0, 0x0e02, 0x11030003, 0x11210005, 0x01030305, 0x04000005,
1340 8, 0x012a00a9 },
1341 { 228000000, 114000000, 0, 0x0e02, 0x11020005, 0x11210005, 0x11020005, 0x04000005,
1342 11, 0x0aaa0555 },
1343 { 240000000, 102857143, 0, 0x0109, 0x04000021, 0x01050203, 0x11030021, 0x04000003,
1344 13, 0x254a14a9 },
1345 { 240000000, 120000000, 0, 0x0109, 0x11030002, 0x01050203, 0x11030002, 0x04000003,
1346 11, 0x0aaa0555 },
1347 { 252000000, 100800000, 0, 0x0203, 0x04000009, 0x11050005, 0x02000209, 0x04000002,
1348 9, 0x02520129 },
1349 { 252000000, 126000000, 0, 0x0203, 0x04000005, 0x11050005, 0x04000005, 0x04000002,
1350 11, 0x0aaa0555 },
1351 { 264000000, 132000000, 0, 0x0602, 0x04000005, 0x11050005, 0x04000005, 0x04000002,
1352 11, 0x0aaa0555 },
1353 { 272000000, 116571428, 0, 0x0c02, 0x04000021, 0x02000909, 0x02000221, 0x04000003,
1354 13, 0x254a14a9 },
1355 { 280000000, 120000000, 0, 0x0209, 0x04000021, 0x01030303, 0x02000221, 0x04000003,
1356 13, 0x254a14a9 },
1357 { 288000000, 123428571, 0, 0x0111, 0x04000021, 0x01030303, 0x02000221, 0x04000003,
1358 13, 0x254a14a9 },
1359 { 300000000, 120000000, 0, 0x0009, 0x04000009, 0x01030203, 0x02000902, 0x04000002,
1360 9, 0x02520129 },
1361 { 300000000, 150000000, 0, 0x0009, 0x04000005, 0x01030203, 0x04000005, 0x04000002,
1362 11, 0x0aaa0555 }
1364 static n4m_table_t BCMINITDATA(type7_table)[] = {
1365 { 183333333, 91666666, 0, 0x0605, 0x04000011, 0x11030011, 0x04000011, 0x04000003,
1366 11, 0x0aaa0555 },
1367 { 187500000, 93750000, 0, 0x0a03, 0x04000011, 0x11030011, 0x04000011, 0x04000003,
1368 11, 0x0aaa0555 },
1369 { 196875000, 98437500, 0, 0x1003, 0x11020005, 0x11050011, 0x11020005, 0x04000005,
1370 11, 0x0aaa0555 },
1371 { 200000000, 100000000, 0, 0x0311, 0x04000011, 0x11030011, 0x04000009, 0x04000003,
1372 11, 0x0aaa0555 },
1373 { 200000000, 100000000, 0, 0x0311, 0x04020011, 0x11030011, 0x04020011, 0x04020003,
1374 11, 0x0aaa0555 },
1375 { 206250000, 103125000, 0, 0x1103, 0x11020005, 0x11050011, 0x11020005, 0x04000005,
1376 11, 0x0aaa0555 },
1377 { 212500000, 106250000, 0, 0x0c05, 0x11020005, 0x01030303, 0x11020005, 0x04000005,
1378 11, 0x0aaa0555 },
1379 { 215625000, 107812500, 0, 0x1203, 0x11090009, 0x11050005, 0x11020005, 0x04000005,
1380 11, 0x0aaa0555 },
1381 { 216666666, 108333333, 0, 0x0805, 0x11020003, 0x11030011, 0x11020003, 0x04000003,
1382 11, 0x0aaa0555 },
1383 { 225000000, 112500000, 0, 0x0d03, 0x11020003, 0x11030011, 0x11020003, 0x04000003,
1384 11, 0x0aaa0555 },
1385 { 233333333, 116666666, 0, 0x0905, 0x11020003, 0x11030011, 0x11020003, 0x04000003,
1386 11, 0x0aaa0555 },
1387 { 237500000, 118750000, 0, 0x0e05, 0x11020005, 0x11210005, 0x11020005, 0x04000005,
1388 11, 0x0aaa0555 },
1389 { 240000000, 120000000, 0, 0x0b11, 0x11020009, 0x11210009, 0x11020009, 0x04000009,
1390 11, 0x0aaa0555 },
1391 { 250000000, 125000000, 0, 0x0f03, 0x11020003, 0x11210003, 0x11020003, 0x04000003,
1392 11, 0x0aaa0555 }
1395 ulong start, end, dst;
1396 bool ret = FALSE;
1398 volatile uint32 *dll_ctrl = (volatile uint32 *)0xff400008;
1399 volatile uint32 *dll_r1 = (volatile uint32 *)0xff400010;
1400 volatile uint32 *dll_r2 = (volatile uint32 *)0xff400018;
1402 /* 5354 chipcommon pll setting can't be changed.
1403 * The PMU on power up comes up with the default clk frequency
1404 * of 240MHz
1406 if ((CHIPID(sih->chip) == BCM5354_CHIP_ID) || (CHIPID(sih->chip) == BCM53572_CHIP_ID))
1407 return TRUE;
1409 if (sih->cccaps & CC_CAP_PMU)
1410 return mips_pmu_setclock(sih, mipsclock, siclock, pciclock);
1412 osh = si_osh(sih);
1414 /* get index of the current core */
1415 idx = si_coreidx(sih);
1416 clockcontrol_m2 = NULL;
1418 /* switch to chipc core */
1419 cc = (chipcregs_t *)si_setcoreidx(sih, SI_CC_IDX);
1420 ASSERT(cc);
1422 pll_type = sih->cccaps & CC_CAP_PLL_MASK;
1423 if (pll_type == PLL_TYPE6) {
1424 clockcontrol_n = NULL;
1425 clockcontrol_sb = NULL;
1426 clockcontrol_pci = NULL;
1427 } else {
1428 clockcontrol_n = &cc->clockcontrol_n;
1429 clockcontrol_sb = &cc->clockcontrol_sb;
1430 clockcontrol_pci = &cc->clockcontrol_pci;
1431 clockcontrol_m2 = &cc->clockcontrol_m2;
1434 if (pll_type == PLL_TYPE6) {
1435 /* Silence compilers */
1436 orig_n = orig_sb = orig_pci = 0;
1437 } else {
1438 /* Store the current clock register values */
1439 orig_n = R_REG(osh, clockcontrol_n);
1440 orig_sb = R_REG(osh, clockcontrol_sb);
1441 orig_pci = R_REG(osh, clockcontrol_pci);
1444 if (pll_type == PLL_TYPE3) {
1445 /* 5350 */
1446 if (CHIPID(sih->chip) != BCM5365_CHIP_ID) {
1448 * Search for the closest MIPS clock less than or equal to
1449 * a preferred value.
1451 for (i = 0; i < ARRAYSIZE(type3_table); i++) {
1452 if (type3_table[i].mipsclock > mipsclock)
1453 break;
1455 if (i == 0) {
1456 ret = FALSE;
1457 goto done;
1458 } else {
1459 ret = TRUE;
1460 i--;
1462 ASSERT(type3_table[i].mipsclock <= mipsclock);
1464 /* No PLL change */
1465 orig_m2 = R_REG(osh, &cc->clockcontrol_m2);
1466 if ((orig_n == type3_table[i].n) &&
1467 (orig_m2 == type3_table[i].m2)) {
1468 goto done;
1471 /* Set the PLL controls */
1472 W_REG(osh, clockcontrol_n, type3_table[i].n);
1473 W_REG(osh, clockcontrol_m2, type3_table[i].m2);
1475 /* Reset */
1476 si_watchdog(sih, 1);
1477 while (1);
1479 } else if ((pll_type == PLL_TYPE2) ||
1480 (pll_type == PLL_TYPE4) ||
1481 (pll_type == PLL_TYPE6) ||
1482 (pll_type == PLL_TYPE7)) {
1483 n4m_table_t *table = NULL, *te;
1484 uint tabsz = 0;
1486 ASSERT(cc);
1488 orig_mips = R_REG(osh, &cc->clockcontrol_m3);
1490 switch (pll_type) {
1491 case PLL_TYPE6: {
1492 uint32 new_mips = 0;
1494 ret = TRUE;
1495 if (mipsclock <= SB2MIPS_T6(CC_T6_M1))
1496 new_mips = CC_T6_MMASK;
1498 if (orig_mips == new_mips)
1499 goto done;
1501 W_REG(osh, &cc->clockcontrol_m3, new_mips);
1502 goto end_fill;
1504 case PLL_TYPE2:
1505 table = type2_table;
1506 tabsz = ARRAYSIZE(type2_table);
1507 break;
1508 case PLL_TYPE4:
1509 table = type4_table;
1510 tabsz = ARRAYSIZE(type4_table);
1511 break;
1512 case PLL_TYPE7:
1513 table = type7_table;
1514 tabsz = ARRAYSIZE(type7_table);
1515 break;
1516 default:
1517 ASSERT("No table for plltype" == NULL);
1518 break;
1521 /* Store the current clock register values */
1522 orig_m2 = R_REG(osh, &cc->clockcontrol_m2);
1523 orig_ratio_parm = 0;
1524 orig_ratio_cfg = 0;
1526 /* Look up current ratio */
1527 for (i = 0; i < tabsz; i++) {
1528 if ((orig_n == table[i].n) &&
1529 (orig_sb == table[i].sb) &&
1530 (orig_pci == table[i].pci33) &&
1531 (orig_m2 == table[i].m2) &&
1532 (orig_mips == table[i].m3)) {
1533 orig_ratio_parm = table[i].ratio_parm;
1534 orig_ratio_cfg = table[i].ratio_cfg;
1535 break;
1539 /* Search for the closest MIPS clock greater or equal to a preferred value */
1540 for (i = 0; i < tabsz; i++) {
1541 ASSERT(table[i].mipsclock ==
1542 si_clock_rate(pll_type, table[i].n, table[i].m3));
1543 if ((mipsclock <= table[i].mipsclock) &&
1544 ((siclock == 0) || (siclock <= table[i].sbclock)) &&
1545 ((pciclock == 0) || (pciclock <= table[i].pciclock)))
1546 break;
1548 if (i == tabsz) {
1549 ret = FALSE;
1550 goto done;
1551 } else {
1552 te = &table[i];
1553 ret = TRUE;
1556 /* No PLL change */
1557 if ((orig_n == te->n) &&
1558 (orig_sb == te->sb) &&
1559 (orig_pci == te->pci33) &&
1560 (orig_m2 == te->m2) &&
1561 (orig_mips == te->m3))
1562 goto done;
1564 /* Set the PLL controls */
1565 W_REG(osh, clockcontrol_n, te->n);
1566 W_REG(osh, clockcontrol_sb, te->sb);
1567 W_REG(osh, clockcontrol_pci, te->pci33);
1568 W_REG(osh, &cc->clockcontrol_m2, te->m2);
1569 W_REG(osh, &cc->clockcontrol_m3, te->m3);
1571 /* Set the chipcontrol bit to change mipsref to the backplane divider if needed */
1572 if ((pll_type == PLL_TYPE7) && (te->sb != te->m2) &&
1573 (si_clock_rate(pll_type, te->n, te->m2) == 120000000))
1574 W_REG(osh, &cc->chipcontrol,
1575 R_REG(osh, &cc->chipcontrol) | 0x100);
1577 /* No ratio change */
1578 if (CHIPID(sih->chip) != BCM4785_CHIP_ID) {
1579 if (orig_ratio_parm == te->ratio_parm)
1580 goto end_fill;
1583 /* Preload the code into the cache */
1584 icache_probe(MFC0(C0_CONFIG, 1), &ic_size, &ic_lsize);
1585 if (CHIPID(sih->chip) == BCM4785_CHIP_ID) {
1586 start = ((ulong) &&start_fill_4785) & ~(ic_lsize - 1);
1587 end = ((ulong) &&end_fill_4785 + (ic_lsize - 1)) & ~(ic_lsize - 1);
1589 else {
1590 start = ((ulong) &&start_fill) & ~(ic_lsize - 1);
1591 end = ((ulong) &&end_fill + (ic_lsize - 1)) & ~(ic_lsize - 1);
1593 while (start < end) {
1594 cache_op(start, Fill_I);
1595 start += ic_lsize;
1598 /* 4785 clock freq change procedures */
1599 if (CHIPID(sih->chip) == BCM4785_CHIP_ID) {
1600 start_fill_4785:
1601 /* Switch to async */
1602 MTC0(C0_BROADCOM, 4, (1 << 22));
1604 /* Set clock ratio in MIPS */
1605 *dll_r1 = (*dll_r1 & 0xfffffff0) | (te->dll_r1 - 1);
1606 *dll_r2 = te->dll_r2;
1608 /* Enable new settings in MIPS */
1609 *dll_r1 = *dll_r1 | 0xc0000000;
1611 /* Set active cfg */
1612 MTC0(C0_BROADCOM, 2, MFC0(C0_BROADCOM, 2) | (1 << 3) | 1);
1614 /* Fake soft reset (clock cfg registers not reset) */
1615 MTC0(C0_BROADCOM, 5, MFC0(C0_BROADCOM, 5) | (1 << 2));
1617 /* Clear active cfg */
1618 MTC0(C0_BROADCOM, 2, MFC0(C0_BROADCOM, 2) & ~(1 << 3));
1620 /* set watchdog timer */
1621 W_REG(osh, &cc->watchdog, 20);
1622 (void) R_REG(osh, &cc->chipid);
1624 /* wait for timer interrupt */
1625 __asm__ __volatile__(
1626 ".set\tmips3\n\t"
1627 "sync\n\t"
1628 "wait\n\t"
1629 ".set\tmips0");
1630 end_fill_4785:
1631 while (1);
1633 /* Generic clock freq change procedures */
1634 else {
1635 /* Copy the handler */
1636 start = (ulong) &handler;
1637 end = (ulong) &afterhandler;
1638 dst = KSEG1ADDR(0x180);
1639 for (i = 0; i < (end - start); i += 4)
1640 *((ulong *)(dst + i)) = *((ulong *)(start + i));
1642 /* Preload the handler into the cache one line at a time */
1643 for (i = 0; i < (end - start); i += ic_lsize)
1644 cache_op(dst + i, Fill_I);
1646 /* Clear BEV bit */
1647 MTC0(C0_STATUS, 0, MFC0(C0_STATUS, 0) & ~ST0_BEV);
1649 /* Enable interrupts */
1650 MTC0(C0_STATUS, 0, MFC0(C0_STATUS, 0) | (ALLINTS | ST0_IE));
1652 /* Enable MIPS timer interrupt */
1653 mipsr = si_setcore(sih, MIPS33_CORE_ID, 0);
1654 ASSERT(mipsr);
1655 W_REG(osh, &mipsr->intmask, 1);
1657 start_fill:
1658 /* step 1, set clock ratios */
1659 MTC0(C0_BROADCOM, 3, te->ratio_parm);
1660 MTC0(C0_BROADCOM, 1, te->ratio_cfg);
1662 /* step 2: program timer intr */
1663 W_REG(osh, &mipsr->timer, 100);
1664 (void) R_REG(osh, &mipsr->timer);
1666 /* step 3, switch to async */
1667 sync_mode = MFC0(C0_BROADCOM, 4);
1668 MTC0(C0_BROADCOM, 4, 1 << 22);
1670 /* step 4, set cfg active */
1671 MTC0(C0_BROADCOM, 2, (1 << 3) | 1);
1673 /* steps 5 & 6 */
1674 __asm__ __volatile__(
1675 ".set\tmips3\n\t"
1676 "wait\n\t"
1677 ".set\tmips0");
1679 /* step 7, clear cfg active */
1680 MTC0(C0_BROADCOM, 2, 0);
1682 /* Additional Step: set back to orig sync mode */
1683 MTC0(C0_BROADCOM, 4, sync_mode);
1685 /* step 8, fake soft reset */
1686 MTC0(C0_BROADCOM, 5, MFC0(C0_BROADCOM, 5) | (1 << 2));
1688 end_fill:
1689 /* set watchdog timer */
1690 W_REG(osh, &cc->watchdog, 20);
1691 (void) R_REG(osh, &cc->chipid);
1693 /* wait for timer interrupt */
1694 __asm__ __volatile__(
1695 ".set\tmips3\n\t"
1696 "sync\n\t"
1697 "wait\n\t"
1698 ".set\tmips0");
1699 while (1);
1703 done:
1704 /* Enable 4785 DLL */
1705 if (CHIPID(sih->chip) == BCM4785_CHIP_ID) {
1706 uint32 tmp;
1708 /* set mask to 1e, enable DLL (bit 0) */
1709 *dll_ctrl |= 0x0041e021;
1711 /* enable aggressive hardware mode */
1712 *dll_ctrl |= 0x00000080;
1714 /* wait for lock flag to clear */
1715 while ((*dll_ctrl & 0x2) == 0);
1717 /* clear sticky flags (clear on write 1) */
1718 tmp = *dll_ctrl;
1719 *dll_ctrl = tmp;
1721 /* set mask to 5b'10001 */
1722 *dll_ctrl = (*dll_ctrl & 0xfffc1fff) | 0x00022000;
1724 /* enable sync mode */
1725 MTC0(C0_BROADCOM, 4, MFC0(C0_BROADCOM, 4) & 0xfe3fffff);
1726 (void)MFC0(C0_BROADCOM, 4);
1729 /* switch back to previous core */
1730 si_setcoreidx(sih, idx);
1732 return ret;
1735 void
1736 BCMINITFN(enable_pfc)(uint32 mode)
1738 uint32 prid;
1739 ulong start, end;
1740 uint ic_size, ic_lsize;
1742 prid = MFC0(C0_PRID, 0);
1743 if (!BCM330X(prid))
1744 return;
1746 /* enable prefetch cache if available */
1747 if (MFC0(C0_BROADCOM, 0) & BRCM_PFC_AVAIL) {
1748 /* If auto then choose the correct mode for this
1749 * platform, currently we only ever select one mode
1751 if (mode == PFC_AUTO)
1752 mode = PFC_INST;
1754 icache_probe(MFC0(C0_CONFIG, 1), &ic_size, &ic_lsize);
1756 start = ((ulong) &&setpfc_start) & ~(ic_lsize - 1);
1757 end = ((ulong) &&setpfc_end + (ic_lsize - 1)) & ~(ic_lsize - 1);
1759 /* Preload setpfc code into the cache one line at a time */
1760 while (start < end) {
1761 cache_op(start, Fill_I);
1762 start += ic_lsize;
1765 /* Now set the pfc */
1766 setpfc_start:
1767 /* write range */
1768 *(volatile uint32 *)PFC_CR1 = 0xffff0000;
1770 /* enable */
1771 *(volatile uint32 *)PFC_CR0 = mode;
1772 setpfc_end:
1773 /* Compiler foder */
1774 ic_size = 0;
1778 /* returns the ncdl value to be programmed into sdram_ncdl for calibration */
1779 uint32
1780 BCMINITFN(si_memc_get_ncdl)(si_t *sih)
1782 osl_t *osh;
1783 sbmemcregs_t *memc;
1784 uint32 ret = 0;
1785 uint32 config, rd, wr, misc, dqsg, cd, sm, sd;
1786 uint idx, rev;
1788 osh = si_osh(sih);
1790 idx = si_coreidx(sih);
1792 memc = (sbmemcregs_t *)si_setcore(sih, MEMC_CORE_ID, 0);
1793 if (memc == NULL)
1794 goto out;
1796 rev = si_corerev(sih);
1798 config = R_REG(osh, &memc->config);
1799 wr = R_REG(osh, &memc->wrncdlcor);
1800 rd = R_REG(osh, &memc->rdncdlcor);
1801 misc = R_REG(osh, &memc->miscdlyctl);
1802 dqsg = R_REG(osh, &memc->dqsgatencdl);
1804 rd &= MEMC_RDNCDLCOR_RD_MASK;
1805 wr &= MEMC_WRNCDLCOR_WR_MASK;
1806 dqsg &= MEMC_DQSGATENCDL_G_MASK;
1808 if (config & MEMC_CONFIG_DDR) {
1809 ret = (wr << 16) | (rd << 8) | dqsg;
1810 } else {
1811 if (rev > 0)
1812 cd = rd;
1813 else
1814 cd = (rd == MEMC_CD_THRESHOLD) ? rd : (wr + MEMC_CD_THRESHOLD);
1815 sm = (misc & MEMC_MISC_SM_MASK) >> MEMC_MISC_SM_SHIFT;
1816 sd = (misc & MEMC_MISC_SD_MASK) >> MEMC_MISC_SD_SHIFT;
1817 ret = (sm << 16) | (sd << 8) | cd;
1820 out:
1821 /* switch back to previous core */
1822 si_setcoreidx(sih, idx);
1824 return ret;
1827 void
1828 hnd_cpu_reset(si_t *sih)
1830 if (CHIPID(sih->chip) == BCM4785_CHIP_ID)
1831 MTC0(C0_BROADCOM, 4, (1 << 22));
1832 si_watchdog(sih, 1);
1833 if (CHIPID(sih->chip) == BCM4785_CHIP_ID) {
1834 __asm__ __volatile__(
1835 ".set\tmips3\n\t"
1836 "sync\n\t"
1837 "wait\n\t"
1838 ".set\tmips0");
1840 while (1);
1843 #if defined(BCMPERFSTATS)
1845 * CP0 Register 25 supports 4 semi-independent 32bit performance counters.
1846 * $25 select 0, 1, 2, and 3 are the counters. The counters *decrement* (who thought this one up?)
1847 * $25 select 4 and 5 each contain 2-16bit control fields, one for each of the 4 counters
1848 * $25 select 6 is the global perf control register.
1850 /* enable and start instruction counting */
1852 void
1853 hndmips_perf_cyclecount_enable(void)
1855 MTC0(C0_PERFORMANCE, 6, 0x80000200); /* global enable perf counters */
1856 MTC0(C0_PERFORMANCE, 4,
1857 0x8048 | MFC0(C0_PERFORMANCE, 4)); /* enable cycles counting for counter 0 */
1858 MTC0(C0_PERFORMANCE, 0, 0); /* zero counter zero */
1861 void
1862 hndmips_perf_instrcount_enable(void)
1864 MTC0(C0_PERFORMANCE, 6, 0x80000200); /* global enable perf counters */
1865 MTC0(C0_PERFORMANCE, 4,
1866 0x8044 | MFC0(C0_PERFORMANCE, 4)); /* enable instructions counting for counter 0 */
1867 MTC0(C0_PERFORMANCE, 0, 0); /* zero counter zero */
1870 /* enable and start I$ hit and I$ miss counting */
1871 void
1872 hndmips_perf_icachecount_enable(void)
1874 MTC0(C0_PERFORMANCE, 6, 0x80000218); /* enable I$ counting */
1875 MTC0(C0_PERFORMANCE, 4, 0x80148018); /* count I$ hits in cntr 0 and misses in cntr 1 */
1876 MTC0(C0_PERFORMANCE, 0, 0); /* zero counter 0 - # I$ hits */
1877 MTC0(C0_PERFORMANCE, 1, 0); /* zero counter 1 - # I$ misses */
1880 /* enable and start D$ hit and I$ miss counting */
1881 void
1882 hndmips_perf_dcachecount_enable(void)
1884 MTC0(C0_PERFORMANCE, 6, 0x80000211); /* enable D$ counting */
1885 MTC0(C0_PERFORMANCE, 4, 0x80248028); /* count D$ hits in cntr 0 and misses in cntr 1 */
1886 MTC0(C0_PERFORMANCE, 0, 0); /* zero counter 0 - # D$ hits */
1887 MTC0(C0_PERFORMANCE, 1, 0); /* zero counter 1 - # D$ misses */
1890 void
1891 hndmips_perf_icache_miss_enable()
1893 MTC0(C0_PERFORMANCE, 4,
1894 0x80140000 | MFC0(C0_PERFORMANCE, 4)); /* enable cache misses counting for counter 1 */
1895 MTC0(C0_PERFORMANCE, 1, 0); /* zero counter one */
1899 void
1900 hndmips_perf_icache_hit_enable()
1902 MTC0(C0_PERFORMANCE, 5, 0x8018 | MFC0(C0_PERFORMANCE, 5));
1903 /* enable cache hits counting for counter 2 */
1904 MTC0(C0_PERFORMANCE, 2, 0); /* zero counter 2 */
1907 uint32
1908 hndmips_perf_read_instrcount()
1910 return -(long)(MFC0(C0_PERFORMANCE, 0));
1913 uint32
1914 hndmips_perf_read_cache_miss()
1916 return -(long)(MFC0(C0_PERFORMANCE, 1));
1919 uint32
1920 hndmips_perf_read_cache_hit()
1922 return -(long)(MFC0(C0_PERFORMANCE, 2));
1925 #endif