2 * BCM47XX Sonics SiliconBackplane MIPS core routines
4 * Copyright (C) 2010, Broadcom Corporation. All Rights Reserved.
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.
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,v 1.63.10.6 2011-01-26 08:19:49 Exp $
32 #include <mips33_core.h>
33 #include <mips74k_core.h>
37 #include <dmemc_core.h>
41 #define HNDMIPS_ERROR(args) printf args
43 #define HNDMIPS_ERROR(args)
44 #endif /* BCMDBG_ERR */
47 #define HNDMIPS_MSG(args) printf args
49 #define HNDMIPS_MSG(args)
51 #define HNDMIPS_NONE(args)
53 /* sbipsflag register format, indexed by irq. */
54 static const uint32 sbips_int_mask
[] = {
62 static const uint32 sbips_int_shift
[] = {
71 * Map SB cores sharing the MIPS hardware IRQ0 to virtual dedicated OS IRQs.
72 * Per-port BSP code is required to provide necessary translations between
73 * the shared MIPS IRQ and the virtual OS IRQs based on SB core flag.
75 * See si_irq() for the mapping.
77 static uint shirq_map_base
= 0;
80 * Returns the MIPS IRQ assignment of the current core. If unassigned,
90 uint32 flag
, sbipsflag
;
96 idx
= si_coreidx(sih
);
98 if ((regs
= si_setcore(sih
, MIPS74K_CORE_ID
, 0)) != NULL
) {
99 /* IntMask1,2,3,4 regs are configured to enable propagation of
100 * backplane interrupts 0,1,2,3 to mips hw interrupts 1,2,3,4.
102 for (irq
= 1; irq
<= 4; irq
++) {
103 if (R_REG(osh
, &((mips74kregs_t
*)regs
)->intmask
[irq
]) &
107 } else if ((regs
= si_setcore(sih
, MIPS33_CORE_ID
, 0)) != NULL
) {
108 sb
= (sbconfig_t
*)((ulong
) regs
+ SBCONFIGOFF
);
110 /* sbipsflag specifies which core is routed to interrupts 1 to 4 */
111 sbipsflag
= R_REG(osh
, &sb
->sbipsflag
);
112 for (irq
= 1; irq
<= 4; irq
++) {
113 if (((sbipsflag
& sbips_int_mask
[irq
]) >>
114 sbips_int_shift
[irq
]) == flag
)
118 ASSERT("Unknown processor core" == NULL
);
119 return 1000; /* An invalid value */
122 /* If we didn't find it it must be in the shared int (0) */
126 si_setcoreidx(sih
, idx
);
132 * Return the MIPS IRQ assignment of the current core. If necessary
133 * map cores sharing the MIPS hw IRQ0 to virtual dedicated OS IRQs.
138 uint irq
= si_getirq(sih
);
139 if (irq
== 0 && shirq_map_base
)
140 irq
= si_flag(sih
) + shirq_map_base
;
144 /* Clears the specified MIPS IRQ. */
146 BCMINITFN(si_clearirq
)(si_t
*sih
, uint irq
)
154 if ((regs
= si_setcore(sih
, MIPS74K_CORE_ID
, 0)) != NULL
) {
155 W_REG(osh
, &((mips74kregs_t
*)regs
)->intmask
[irq
], 0);
156 } else if ((regs
= si_setcore(sih
, MIPS33_CORE_ID
, 0)) != NULL
) {
157 sb
= (sbconfig_t
*)((ulong
) regs
+ SBCONFIGOFF
);
159 W_REG(osh
, &sb
->sbintvec
, 0);
161 OR_REG(osh
, &sb
->sbipsflag
, sbips_int_mask
[irq
]);
163 ASSERT("Unknown processor core" == NULL
);
167 * Assigns the specified MIPS IRQ to the specified core. Shared MIPS
168 * IRQ 0 may be assigned more than once.
170 * The old assignment to the specified core is removed first.
173 BCMATTACHFN(si_setirq
)(si_t
*sih
, uint irq
, uint coreid
, uint coreunit
)
183 regs
= si_setcore(sih
, coreid
, coreunit
);
186 oldirq
= si_getirq(sih
);
188 si_clearirq(sih
, oldirq
);
190 if ((regs
= si_setcore(sih
, MIPS74K_CORE_ID
, 0)) != NULL
) {
192 AND_REG(osh
, &((mips74kregs_t
*)regs
)->intmask
[0], ~(1 << flag
));
195 OR_REG(osh
, &((mips74kregs_t
*)regs
)->intmask
[0], 1 << flag
);
197 W_REG(osh
, &((mips74kregs_t
*)regs
)->intmask
[irq
], 1 << flag
);
199 } else if ((regs
= si_setcore(sih
, MIPS33_CORE_ID
, 0)) != NULL
) {
200 sb
= (sbconfig_t
*)((ulong
) regs
+ SBCONFIGOFF
);
203 AND_REG(osh
, &sb
->sbintvec
, ~(1 << flag
));
206 OR_REG(osh
, &sb
->sbintvec
, 1 << flag
);
208 flag
<<= sbips_int_shift
[irq
];
209 ASSERT(!(flag
& ~sbips_int_mask
[irq
]));
210 flag
|= R_REG(osh
, &sb
->sbipsflag
) & ~sbips_int_mask
[irq
];
211 W_REG(osh
, &sb
->sbipsflag
, flag
);
214 ASSERT("Unknown processor core" == NULL
);
218 * Initializes clocks and interrupts. SB and NVRAM access must be
219 * initialized prior to calling.
221 * 'shirqmap' enables virtual dedicated OS IRQ mapping if non-zero.
224 BCMATTACHFN(si_mips_init
)(si_t
*sih
, uint shirqmap
)
234 /* Disable interrupts */
235 c0reg
= MFC0(C0_STATUS
, 0);
237 MTC0(C0_STATUS
, 0, c0reg
);
239 /* Figure out current SB clock speed */
240 if ((hz
= si_clock(sih
)) == 0)
242 ns
= 1000000000 / hz
;
244 /* Setup external interface timing */
245 cc
= si_setcoreidx(sih
, SI_CC_IDX
);
248 /* Set timing for the flash */
249 tmp
= CEIL(10, ns
) << FW_W3_SHIFT
; /* W3 = 10nS */
250 tmp
|= CEIL(10, ns
) << FW_W1_SHIFT
; /* W1 = 10nS */
251 tmp
|= CEIL(120, ns
); /* W0 = 120nS */
253 W_REG(osh
, &cc
->flash_waitcount
, tmp
);
255 if ((sih
->ccrev
< 9) ||
256 ((CHIPID(sih
->chip
) == BCM5350_CHIP_ID
) && CHIPREV(sih
->chiprev
) == 0)) {
257 W_REG(osh
, &cc
->pcmcia_memwait
, tmp
);
260 /* Save shared IRQ mapping base */
261 shirq_map_base
= shirqmap
;
263 /* Chip specific initialization */
264 switch (CHIPID(sih
->chip
)) {
265 case BCM5350_CHIP_ID
:
266 /* Clear interrupt map */
267 for (irq
= 0; irq
<= 4; irq
++)
268 si_clearirq(sih
, irq
);
269 si_setirq(sih
, 0, CC_CORE_ID
, 0);
270 si_setirq(sih
, 0, MIPS33_CORE_ID
, 0);
271 si_setirq(sih
, 1, D11_CORE_ID
, 0);
272 si_setirq(sih
, 2, ENET_CORE_ID
, 0);
273 si_setirq(sih
, 3, PCI_CORE_ID
, 0);
274 si_setirq(sih
, 4, USB_CORE_ID
, 0);
276 case BCM4785_CHIP_ID
:
277 /* Reassign PCI to irq 4 */
278 si_setirq(sih
, 4, PCI_CORE_ID
, 0);
280 case BCM4716_CHIP_ID
:
281 case BCM4748_CHIP_ID
:
282 /* Clear interrupt map */
283 for (irq
= 0; irq
<= 4; irq
++)
284 si_clearirq(sih
, irq
);
285 si_setirq(sih
, 1, D11_CORE_ID
, 0);
286 si_setirq(sih
, 2, GMAC_CORE_ID
, 0);
287 si_setirq(sih
, 3, USB20H_CORE_ID
, 0);
288 si_setirq(sih
, 4, PCIE_CORE_ID
, 0);
289 si_setirq(sih
, 0, CC_CORE_ID
, 0);
290 si_setirq(sih
, 0, I2S_CORE_ID
, 0);
292 case BCM5356_CHIP_ID
:
293 case BCM47162_CHIP_ID
:
294 case BCM53572_CHIP_ID
:
295 /* Clear interrupt map */
296 for (irq
= 0; irq
<= 4; irq
++)
297 si_clearirq(sih
, irq
);
298 si_setirq(sih
, 1, D11_CORE_ID
, 0);
299 si_setirq(sih
, 2, GMAC_CORE_ID
, 0);
300 si_setirq(sih
, 0, CC_CORE_ID
, 0);
302 case BCM5357_CHIP_ID
:
303 /* Clear interrupt map */
304 for (irq
= 0; irq
<= 4; irq
++)
305 si_clearirq(sih
, irq
);
306 si_setirq(sih
, 1, D11_CORE_ID
, 0);
307 si_setirq(sih
, 2, GMAC_CORE_ID
, 0);
308 si_setirq(sih
, 3, USB20H_CORE_ID
, 0);
309 si_setirq(sih
, 0, CC_CORE_ID
, 0);
310 si_setirq(sih
, 0, I2S_CORE_ID
, 0);
312 case BCM4706_CHIP_ID
:
313 /* Clear interrupt map */
314 for (irq
= 0; irq
<= 4; irq
++)
315 si_clearirq(sih
, irq
);
316 si_setirq(sih
, 1, PCIE_CORE_ID
, 0);
317 si_setirq(sih
, 2, GMAC_CORE_ID
, 0);
318 si_setirq(sih
, 3, PCIE_CORE_ID
, 1);
319 si_setirq(sih
, 4, USB20H_CORE_ID
, 0);
320 si_setirq(sih
, 0, CC_CORE_ID
, 0);
326 /* Do any setup necessary to run a new image and jump to it. */
328 hnd_cpu_jumpto(void *addr
)
330 void (*jumpto
)(void) = addr
;
336 BCMINITFN(si_cpu_clock
)(si_t
*sih
)
342 uint32 pll_type
, rate
= 0;
347 if (sih
->cccaps
& CC_CAP_PMU
)
348 return si_pmu_cpu_clock(sih
, osh
);
350 /* get index of the current core */
351 idx
= si_coreidx(sih
);
353 /* switch to chipc core */
354 cc
= (chipcregs_t
*)si_setcoreidx(sih
, SI_CC_IDX
);
357 pll_type
= sih
->cccaps
& CC_CAP_PLL_MASK
;
358 n
= R_REG(osh
, &cc
->clockcontrol_n
);
359 if ((pll_type
== PLL_TYPE2
) ||
360 (pll_type
== PLL_TYPE4
) ||
361 (pll_type
== PLL_TYPE6
) ||
362 (pll_type
== PLL_TYPE7
))
363 m
= R_REG(osh
, &cc
->clockcontrol_m3
);
364 else if (pll_type
== PLL_TYPE5
) {
367 } else if (pll_type
== PLL_TYPE3
) {
368 if (CHIPID(sih
->chip
) == BCM5365_CHIP_ID
) {
372 /* 5350 uses m2 to control mips */
374 m
= R_REG(osh
, &cc
->clockcontrol_m2
);
376 m
= R_REG(osh
, &cc
->clockcontrol_sb
);
379 rate
= si_clock_rate(pll_type
, n
, m
);
381 if (pll_type
== PLL_TYPE6
)
382 rate
= SB2MIPS_T6(rate
);
385 /* switch back to previous core */
386 si_setcoreidx(sih
, idx
);
392 BCMINITFN(si_mem_clock
)(si_t
*sih
)
398 if (sih
->cccaps
& CC_CAP_PMU
)
399 return si_pmu_mem_clock(sih
, osh
);
401 return si_clock(sih
);
404 #define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4)
406 static void __attribute__ ((__noinline__
))
407 ephy_poll_phyaccess(void)
409 asm("phypoll: \tlui $8, 0xb800\n\t"
410 "lw $9, 0x2180($8)\n\t"
413 "bnez $9, phypoll\n\t"
417 static void __attribute__ ((__noinline__
))
420 /* for (i = 0; i < 3000000; i++); */
421 asm("lui $8, 0x2d\n\t"
422 "ori $8,$8,0xc6c0\n\t"
423 "coma_delay_loop: \taddiu $8,$8,-1\n\t"
424 "bnez $8,coma_delay_loop\n\t"
428 static void __attribute__ ((__noinline__
))
429 do_router_coma(si_t
*sih
, void *dmem
, int delay_val
)
433 /* set jtag user reg 0 = 0x80 to set DDR pad power saving mode */
434 asm("lui $8, 0xb800");
435 asm("li $9, 0xff03ff3a"); /* (16 + addr) << 20 | 0xfe03ff3a */
436 asm("sw $9, 0x0034($8)");
437 asm("li $9, 0x80"); /* data */
438 asm("sw $9, 0x0038($8)");
439 asm("li $9, 0x80071f1f");
440 asm("sw $9, 0x0030($8)");
445 /* ephy ports powerdown */
447 /* robo_wreg 0x0 0xf 0x1f 0x2 */
448 asm("lui $8, 0xb800");
449 asm("li $9, 0x0090001e");
450 asm("sw $9, 0x2188($8)");
453 asm("lui $8, 0xb800");
454 asm("li $9, 0x701e0001");
455 asm("sw $9, 0x2180($8)");
459 ephy_poll_phyaccess();
461 asm("lui $8, 0xb800");
462 asm("li $9, 0x0090001e");
463 asm("sw $9, 0x2188($8)");
466 asm("lui $8, 0xb800");
467 asm("li $9, 0x781e001f");
468 asm("sw $9, 0x2180($8)");
472 ephy_poll_phyaccess();
474 asm("lui $8, 0xb800");
475 asm("li $9, 0x0090001e");
476 asm("sw $9, 0x2188($8)");
479 asm("lui $8, 0xb800");
480 asm("li $9, 0x711e0f01");
481 asm("sw $9, 0x2180($8)");
485 ephy_poll_phyaccess();
487 asm("lui $8, 0xb800");
488 asm("li $9, 0x0090001e");
489 asm("sw $9, 0x2188($8)");
492 asm("lui $8, 0xb800");
493 asm("li $9, 0x511e0000");
494 asm("sw $9, 0x2180($8)");
498 ephy_poll_phyaccess();
500 /* ports 0-5 writes start */
504 for (phy
= 0; phy
< 5; phy
++) {
506 asm("sll $11, $10, 16");
508 asm("li $9, 0x00900000");
509 asm("or $9, $9, $10");
510 asm("lui $8, 0xb800");
511 asm("sw $9, 0x2188($8)");
514 asm("li $9, 0x7f00008b");
515 asm("or $9, $9, $11");
516 asm("lui $8, 0xb800");
517 asm("sw $9, 0x2180($8)");
521 ephy_poll_phyaccess();
523 asm("li $9, 0x00900000");
524 asm("or $9, $9, $10");
525 asm("lui $8, 0xb800");
526 asm("sw $9, 0x2188($8)");
529 asm("li $9, 0x74006000");
530 asm("or $9, $9, $11");
531 asm("lui $8, 0xb800");
532 asm("sw $9, 0x2180($8)");
536 ephy_poll_phyaccess();
538 asm("li $9, 0x00900000");
539 asm("or $9, $9, $10");
540 asm("lui $8, 0xb800");
541 asm("sw $9, 0x2188($8)");
544 asm("li $9, 0x70000700");
545 asm("or $9, $9, $11");
546 asm("lui $8, 0xb800");
547 asm("sw $9, 0x2180($8)");
551 ephy_poll_phyaccess();
553 asm("li $9, 0x00900000");
554 asm("or $9, $9, $10");
555 asm("lui $8, 0xb800");
556 asm("sw $9, 0x2188($8)");
559 asm("li $9, 0x71001000");
560 asm("or $9, $9, $11");
561 asm("lui $8, 0xb800");
562 asm("sw $9, 0x2180($8)");
566 ephy_poll_phyaccess();
568 asm("li $9, 0x00900000");
569 asm("or $9, $9, $10");
570 asm("lui $8, 0xb800");
571 asm("sw $9, 0x2188($8)");
574 asm("li $9, 0x7f00000b");
575 asm("or $9, $9, $11");
576 asm("lui $8, 0xb800");
577 asm("sw $9, 0x2180($8)");
581 ephy_poll_phyaccess();
583 asm("addi $10, $10, 1");
587 /* ports 0-5 writes end */
589 if (((CHIPID(sih
->chip
)) == BCM53572_CHIP_ID
)) {
590 /* set ephy pll and bias power save through chipc registers */
591 asm("lui $8, 0xb800");
593 asm("sw $9, 0x0650($8)");
594 asm("li $9, 0x8a60e001");
595 asm("sw $9, 0x0654($8)");
601 asm("lui $8, 0xb800");
603 asm("sw $9, 0x0650($8)");
604 asm("li $9, 0xcad0000f");
605 asm("sw $9, 0x0654($8)");
611 /* Clear the dmems ddrctrl reg */
612 asm("lui $8, 0xb800");
614 asm("sw $9, 0x41e4($8)");
622 if (sih
->chiprev
== 0) {
624 /* set jtag user reg 3 = 0x60000 to turn off ephy pll and bias power */
625 asm("lui $8, 0xb800");
626 asm("li $9, 0xff33ff3a"); /* (16 + addr) << 20 | 0xfe03ff3a */
627 asm("sw $9, 0x0034($8)");
628 asm("li $9, 0x60000"); /* data */
629 asm("sw $9, 0x0038($8)");
630 asm("li $9, 0x80071f1f");
631 asm("sw $9, 0x0030($8)");
637 /* set ephy pll and bias power power save through chipc registers */
638 asm("lui $8, 0xb800");
640 asm("sw $9, 0x0650($8)");
641 asm("li $9, 0x8a60e001");
642 asm("sw $9, 0x0654($8)");
648 asm("lui $8, 0xb800");
650 asm("sw $9, 0x0650($8)");
651 asm("li $9, 0xcad0000f");
652 asm("sw $9, 0x0654($8)");
660 /* set jtag user reg 7 = 0xc0 to turn off the pll and bias power of ephy */
661 asm("lui $8, 0xb800");
662 asm("li $9, 0xff73ff3a");
663 asm("sw $9, 0x0034($8)");
664 asm("li $9, 0xc0"); /* data */
665 asm("sw $9, 0x0038($8)");
666 asm("li $9, 0x80071f1f");
667 asm("sw $9, 0x0030($8)");
672 /* set gmac dmp io control = 0 */
673 asm("lui $8, 0xb810");
675 asm("sw $9, 0x2408($8)");
681 if (((CHIPID(sih
->chip
)) == BCM53572_CHIP_ID
)) {
682 /* set ddr dmp io control = 0 */
683 asm("lui $8, 0xb810");
685 asm("sw $9, 0x4408($8)");
688 /* put dmems in reset */
690 asm("sw $9, 0x4800($8)");
694 /* set ddr dmp io control = 0 */
695 asm("lui $8, 0xb810");
697 asm("sw $9, 0x5408($8)");
700 /* put dmemc in reset */
702 asm("sw $9, 0x5800($8)");
709 /* set PMU control = 1 */
710 asm("lui $8, 0xb800");
712 asm("sw $9, 0x0600($8)");
718 if (((CHIPID(sih
->chip
)) != BCM53572_CHIP_ID
)) {
719 /* Set switching freq of internal 12V regulator to 600kHz */
720 asm("lui $8, 0xb800");
722 asm("sw $9, 0x0658($8)");
725 asm("lui $8, 0xb800");
726 asm("li $9, 0x00018000");
727 asm("sw $9, 0x065c($8)");
734 /* set mips dmp io control = 0 */
735 asm("lui $8, 0xb810");
737 asm("sw $9, 0x3408($8)");
741 /* wait for watch dog timer done */
752 static void __attribute__ ((__noinline__
))
753 BCMINITFN(aftercoma
)(void)
759 si_router_coma(si_t
*sih
, int reset
, int delay_val
)
764 uint ic_size
, ic_lsize
;
772 /* Disable interrupts */
774 c0reg
= MFC0(C0_STATUS
, 0);
775 tmp
= (c0reg
& ~(ALLINTS
| ST0_IE
));
776 MTC0(C0_STATUS
, 0, tmp
);
778 icache_probe(MFC0(C0_CONFIG
, 1), &ic_size
, &ic_lsize
);
780 /* Put coma routine into the icache */
781 start
= (ulong
)&ephy_poll_phyaccess
;
782 end
= (ulong
)&aftercoma
;
783 for (i
= 0; i
< (end
- start
); i
+= ic_lsize
)
784 cache_op(start
+ i
, Fill_I
);
786 /* Prepare JTAG registers */
787 si_setcore(sih
, CC_CORE_ID
, 0);
788 cc
= (chipcregs_t
*)si_setcoreidx(sih
, SI_CC_IDX
);
790 W_REG(osh
, &cc
->jtagctrl
, 0x01);
791 W_REG(osh
, &cc
->jtagcmd
, 0x80030000);
792 W_REG(osh
, &cc
->gpioouten
, 0x0);
795 W_REG(osh
, &cc
->gpioouten
, 0x0);
796 W_REG(osh
, &cc
->chipcontrol_addr
, 0x2);
797 W_REG(osh
, &cc
->chipcontrol_data
, 0x04000600);
799 /* Set the watchdog */
800 if (sih
->chiprev
== 0) {
801 W_REG(osh
, &cc
->watchdog
, reset
*ILP_CLOCK
);
803 si_watchdog_ms(sih
, reset
*1000);
805 if (((CHIPID(sih
->chip
)) == BCM53572_CHIP_ID
))
806 dmem
= (void *)si_setcore(sih
, DMEMS_CORE_ID
, 0);
808 dmem
= (void *)si_setcore(sih
, DMEMC_CORE_ID
, 0);
810 do_router_coma(sih
, dmem
, delay_val
);
814 BCMINITFN(dmc_phyctl
)(osl_t
*osh
, dmemcregs_t
*dmc0
, uint32 phyctl_val
)
818 _dmemcregs_t
*dmc
= (_dmemcregs_t
*)dmc0
;
820 SET_REG(osh
, &dmc
->control
[9], DMC09_SREFRESH
, DMC09_SREFRESH
);
821 SET_REG(osh
, &dmc
->control
[9], DMC09_START
, 0);
823 SET_REG(osh
, &dmc
->control
[147], (1 << 16), (phyctl_val
& (1 << 16)));
824 SET_REG(osh
, &dmc
->control
[148], (1 << 16), (phyctl_val
& (1 << 16)));
825 SET_REG(osh
, &dmc
->control
[149], 0x7, (phyctl_val
& 0x7));
826 SET_REG(osh
, &dmc
->control
[150], 0x7, (phyctl_val
& 0x7));
834 SET_REG(osh
, &dmc
->control
[9], DMC09_START
, DMC09_START
);
837 while ((R_REG(osh
, &dmc
->control
[4]) & DMC04_DLLLOCK
) == 0);
840 for (i
= 0; i
< 3000000; i
++);
842 val
= R_REG(osh
, &dmc
->control
[5]) & 0x1;
845 val1
= R_REG(osh
, &dmc
->control
[144]) >> 3;
846 val
= (R_REG(osh
, &dmc
->control
[140]) & ~0x03ff0000) | (val1
<< 16);
847 W_REG(osh
, &dmc
->control
[140], val
);
848 val
= (R_REG(osh
, &dmc
->control
[142]) & ~0x1ff8000) | (((val1
* 3) & 0x3ff) << 15);
849 W_REG(osh
, &dmc
->control
[142], val
);
850 val1
= R_REG(osh
, &dmc
->control
[145]) >> 3;
851 val
= (R_REG(osh
, &dmc
->control
[141]) & ~0x03ff0000) | (val1
<< 16);
852 W_REG(osh
, &dmc
->control
[141], val
);
853 val
= (R_REG(osh
, &dmc
->control
[143]) & ~0x1ff8000) | (((val1
* 3) & 0x3ff) << 15);
854 W_REG(osh
, &dmc
->control
[143], val
);
857 for (i
= 0; i
< 1000000; i
++);
859 SET_REG(osh
, &dmc
->control
[9], DMC09_SREFRESH
, 0);
863 BCMINITFN(afterphyctl
)(void)
868 si_dmc_phyctl(si_t
*sih
, uint32 phyctl_val
)
871 chipcregs_t
*cc
= NULL
;
872 dmemcregs_t
*dmc
= NULL
;
877 /* get index of the current core */
878 idx
= si_coreidx(sih
);
880 /* switch to chipc core */
881 cc
= (chipcregs_t
*)si_setcoreidx(sih
, SI_CC_IDX
);
883 if ((dmc
= (dmemcregs_t
*)si_setcore(sih
, DMEMC_CORE_ID
, 0)) != NULL
) {
884 uint ic_size
, ic_lsize
;
889 /* Enable mips interrupt */
890 c0reg
= MFC0(C0_STATUS
, 0);
891 tmp
= (c0reg
& ~ALLINTS
) | IE_IRQ0
;
892 MTC0(C0_STATUS
, 0, tmp
);
894 /* Enable PMU interrupt */
895 OR_REG(osh
, &cc
->intmask
, CI_PMU
);
897 icache_probe(MFC0(C0_CONFIG
, 1), &ic_size
, &ic_lsize
);
899 /* Put dmc_phyctl routine into the icache */
900 start
= (ulong
)&dmc_phyctl
;
901 end
= (ulong
)&afterphyctl
;
902 for (i
= 0; i
< (end
- start
); i
+= ic_lsize
)
903 cache_op(start
+ i
, Fill_I
);
905 /* Program PMU timer */
906 tmp
= R_REG(osh
, &cc
->res_req_timer
);
909 W_REG(osh
, &cc
->res_req_timer
, tmp
);
911 dmc_phyctl(osh
, dmc
, phyctl_val
);
913 /* Clear PMU interrupt */
914 W_REG(osh
, &cc
->pmustatus
, 0x40);
916 /* Restore mips interrupt mask */
917 MTC0(C0_STATUS
, 0, c0reg
);
919 /* switch back to previous core */
920 si_setcoreidx(sih
, idx
);
924 BCMINITFN(sdsleep
)(osl_t
*osh
, dmemcregs_t
*dmc0
)
928 _dmemcregs_t
*dmc
= (_dmemcregs_t
*)dmc0
;
930 SET_REG(osh
, &dmc
->control
[9], DMC09_SREFRESH
, DMC09_SREFRESH
);
931 SET_REG(osh
, &dmc
->control
[9], DMC09_START
, 0);
939 SET_REG(osh
, &dmc
->control
[9], DMC09_START
, DMC09_START
);
942 while ((R_REG(osh
, &dmc
->control
[4]) & DMC04_DLLLOCK
) == 0);
945 for (i
= 0; i
< 3000000; i
++);
947 val
= R_REG(osh
, &dmc
->control
[5]) & 0x1;
950 val1
= R_REG(osh
, &dmc
->control
[144]) >> 3;
951 val
= (R_REG(osh
, &dmc
->control
[140]) & ~0x03ff0000) | (val1
<< 16);
952 W_REG(osh
, &dmc
->control
[140], val
);
953 val
= (R_REG(osh
, &dmc
->control
[142]) & ~0x1ff8000) | (((val1
* 3) & 0x3ff) << 15);
954 W_REG(osh
, &dmc
->control
[142], val
);
955 val1
= R_REG(osh
, &dmc
->control
[145]) >> 3;
956 val
= (R_REG(osh
, &dmc
->control
[141]) & ~0x03ff0000) | (val1
<< 16);
957 W_REG(osh
, &dmc
->control
[141], val
);
958 val
= (R_REG(osh
, &dmc
->control
[143]) & ~0x1ff8000) | (((val1
* 3) & 0x3ff) << 15);
959 W_REG(osh
, &dmc
->control
[143], val
);
962 for (i
= 0; i
< 1000000; i
++);
964 SET_REG(osh
, &dmc
->control
[9], DMC09_SREFRESH
, 0);
968 BCMINITFN(aftersdsleep
)(void)
972 #define PLL_ENTRIES_4706 1
974 BCMINITFN(mips_pmu_setclock_4706
)(si_t
*sih
, uint32 mipsclock
,
975 uint32 ddrclock
, uint32 axiclock
)
977 chipcregs_t
*cc
= NULL
;
979 bool ret
= TRUE
, boolChanged
= FALSE
;
982 /* 25MHz table for 4706 */
983 static uint32
BCMINITDATA(pll25mhz_table
)[][3 + PLL_ENTRIES_4706
] = {
984 /* cpu, ddr, axi, proc_PLL, */
985 { 200, 100, 50, 0xc0011080, },
986 { 300, 150, 75, 0xc00110c0, },
987 { 400, 200, 100, 0xc0011100, },
988 { 500, 250, 125, 0xc0011140, },
989 { 600, 300, 150, 0xc0011180, },
990 { 632, 316, 158, 0xc00157e8, },
991 { 650, 325, 162, 0xc00111a0, },
992 { 662, 331, 165, 0xc00111a8, },
995 uint32 (*pll_table
)[4] = pll25mhz_table
;
999 /* get index of the current core */
1000 idx
= si_coreidx(sih
);
1002 /* switch to chipc core */
1003 cc
= (chipcregs_t
*)si_setcoreidx(sih
, SI_CC_IDX
);
1006 mipsclock
/= 1000000;
1007 ddrclock
/= 1000000;
1008 axiclock
/= 1000000;
1010 for (idx
= 0; pll_table
[idx
][0] != 0; idx
++) {
1011 if ((mipsclock
<= pll_table
[idx
][0]) &&
1012 ((ddrclock
== 0) || (ddrclock
<= pll_table
[idx
][1])) &&
1013 ((axiclock
== 0) || (axiclock
<= pll_table
[idx
][2])))
1017 if (pll_table
[idx
][0] == 0) {
1022 for (i
= 0; i
< PLL_ENTRIES_4706
; i
++) {
1023 W_REG(osh
, &cc
->pllcontrol_addr
, PMU6_4706_PROCPLL_OFF
+ i
);
1024 (void)R_REG(osh
, &cc
->pllcontrol_addr
);
1025 if (R_REG(osh
, &cc
->pllcontrol_data
) != pll_table
[idx
][i
+ 3]) {
1026 W_REG(osh
, &cc
->pllcontrol_data
, pll_table
[idx
][i
+ 3]);
1031 if (boolChanged
== FALSE
)
1034 /* Wait for the last write */
1035 (void)R_REG(osh
, &cc
->pllcontrol_data
);
1037 /* And now do the pll update */
1038 W_REG(osh
, &cc
->pmucontrol
,
1039 R_REG(osh
, &cc
->pmucontrol
) | PCTL_PLL_PLLCTL_UPD
);
1041 __asm__
__volatile__(
1048 si_setcoreidx(sih
, idx
);
1053 * Set the MIPS, backplane and DDR clocks as closely as possible in chips
1054 * with a PMU. So far that means 4716, 47162, 5357, and 5356 all of which share
1055 * the same PLL controls.
1058 BCMINITFN(mips_pmu_setclock
)(si_t
*sih
, uint32 mipsclock
, uint32 ddrclock
, uint32 axiclock
)
1061 chipcregs_t
*cc
= NULL
;
1062 dmemcregs_t
*dmc
= NULL
;
1066 uint mainpll_pll0
= PMU4716_MAINPLL_PLL0
;
1068 uint32 (*pll_table
)[8];
1070 /* 20MHz table for 4716, 4717, 4718, 47162, 5357 */
1071 static uint32
BCMINITDATA(pll20mhz_table
)[][8] = {
1072 /* cpu, ddr, axi, pllctl12, pllctl13, pllctl14, pllctl15, pllctl16 */
1073 { 66, 66, 66, 0x11100070, 0x00121212, 0x03c00000, 0x20000000, 0x200005c0 },
1074 { 75, 75, 75, 0x11100070, 0x00101010, 0x03c00000, 0x20000000, 0x200005c0 },
1075 { 80, 80, 80, 0x11100070, 0x000a0a0a, 0x02800000, 0x20000000, 0x200005c0 },
1076 { 83, 83, 83, 0x11100070, 0x000c0c0c, 0x03200000, 0x20000000, 0x200005c0 },
1077 { 100, 66, 66, 0x11100070, 0x0012120c, 0x03c00000, 0x30000000, 0x200005c0 },
1078 { 100, 100, 100, 0x11100070, 0x000c0c0c, 0x03c00000, 0x20000000, 0x200005c0 },
1079 { 120, 60, 60, 0x11100070, 0x00101008, 0x03000000, 0x40000000, 0x200005c0 },
1080 { 120, 120, 120, 0x11100070, 0x00080808, 0x03000000, 0x20000000, 0x200005c0 },
1081 { 125, 83, 83, 0x11100070, 0x000c0c08, 0x03200000, 0x30000000, 0x200005c0 },
1082 { 133, 66, 66, 0x11100070, 0x0018180c, 0x05000000, 0x40000000, 0x200005c0 },
1083 { 133, 133, 133, 0x11100070, 0x000c0c0c, 0x05000000, 0x20000000, 0x200005c0 },
1084 { 148, 148, 74, 0x11100070, 0x00120909, 0x04300000, 0x28000000, 0x200005c0 },
1085 { 150, 75, 75, 0x11100070, 0x00101008, 0x03c00000, 0x40000000, 0x200005c0 },
1086 { 150, 100, 100, 0x11100070, 0x000c0c08, 0x03c00000, 0x30000000, 0x200005c0 },
1087 { 150, 150, 75, 0x11100070, 0x00100808, 0x03c00000, 0x28000000, 0x200005c0 },
1088 { 150, 150, 150, 0x11100070, 0x00080808, 0x03c00000, 0x20000000, 0x200005c0 },
1089 { 155, 155, 77, 0x11100070, 0x00120909, 0x04600000, 0x28000000, 0x200005c0 },
1090 { 155, 155, 155, 0x11100070, 0x00090909, 0x04600000, 0x20000000, 0x200005c0 },
1091 { 166, 83, 83, 0x11100070, 0x000c0c06, 0x03200000, 0x40000000, 0x200005c0 },
1092 { 166, 166, 83, 0x11100070, 0x000c0606, 0x03200000, 0x28000000, 0x200005c0 },
1093 { 166, 166, 166, 0x11100070, 0x00060606, 0x03200000, 0x20000000, 0x200005c0 },
1094 { 200, 200, 100, 0x11100070, 0x000c0606, 0x03c00000, 0x28000000, 0x200005c0 },
1095 { 223, 148, 74, 0x11100070, 0x00120906, 0x04300000, 0x38000000, 0x200005c0 },
1096 { 240, 120, 120, 0x11100070, 0x00080804, 0x03000000, 0x40000000, 0x200005c0 },
1097 { 240, 240, 120, 0x11100070, 0x00080404, 0x03000000, 0x28000000, 0x200005c0 },
1098 { 250, 166, 83, 0x11100070, 0x000c0604, 0x03200000, 0x38000000, 0x200005c0 },
1099 { 250, 166, 166, 0x11100070, 0x00060604, 0x03200000, 0x30000000, 0x200005c0 },
1100 { 266, 133, 133, 0x11100070, 0x000c0c06, 0x05000000, 0x40000000, 0x200005c0 },
1101 { 266, 266, 133, 0x11100070, 0x000c0606, 0x05000000, 0x28000000, 0x200005c0 },
1102 { 300, 100, 100, 0x11100070, 0x000c0c04, 0x03c00000, 0x60000000, 0x200005c0 },
1103 { 300, 150, 75, 0x11100070, 0x00100804, 0x03c00000, 0x48000000, 0x200005c0 },
1104 { 300, 150, 150, 0x11100070, 0x00080804, 0x03c00000, 0x40000000, 0x200005c0 },
1105 { 300, 200, 100, 0x11100070, 0x000c0604, 0x03c00000, 0x38000000, 0x200005c0 },
1106 { 320, 160, 80, 0x11100070, 0x00100804, 0x04000000, 0x48000000, 0x200005c0 },
1107 { 320, 213, 106, 0x11100070, 0x000c0604, 0x04000000, 0x38000000, 0x200005c0 },
1108 { 320, 240, 120, 0x11100070, 0x00080403, 0x03000000, 0x38000000, 0x200005c0 },
1109 { 320, 256, 128, 0x11100070, 0x000a0504, 0x04000000, 0x38000000, 0x200005c0 },
1110 { 330, 165, 82, 0x11100070, 0x00100804, 0x04200000, 0x48000000, 0x200005c0 },
1111 { 330, 165, 165, 0x11100070, 0x00080804, 0x04200000, 0x40000000, 0x200005c0 },
1112 { 333, 166, 83, 0x11100070, 0x000c0603, 0x03200000, 0x48000000, 0x200005c0 },
1113 { 333, 166, 166, 0x11100070, 0x00060603, 0x03200000, 0x40000000, 0x200005c0 },
1114 { 340, 226, 113, 0x11100070, 0x000c0604, 0x04400000, 0x38000000, 0x200005c0 },
1115 { 350, 175, 87, 0x11100070, 0x00100804, 0x04600000, 0x48000000, 0x200005c0 },
1116 { 353, 176, 88, 0x11100070, 0x000c0603, 0x03500000, 0x48000000, 0x200005c0 },
1117 { 360, 240, 120, 0x11100070, 0x000c0604, 0x04800000, 0x38000000, 0x200005c0 },
1118 { 370, 185, 92, 0x11100070, 0x00100804, 0x04a00000, 0x48000000, 0x200005c0 },
1119 { 370, 246, 123, 0x11100070, 0x000c0604, 0x04a00000, 0x38000000, 0x200005c0 },
1120 { 373, 186, 93, 0x11100070, 0x000c0603, 0x03800000, 0x48000000, 0x200005c0 },
1121 { 400, 133, 133, 0x11100070, 0x000c0c04, 0x05000000, 0x60000000, 0x200005c0 },
1122 { 400, 160, 80, 0x11100070, 0x00140a04, 0x05000000, 0x58000000, 0x200005c0 },
1123 { 400, 160, 160, 0x11100070, 0x000a0a04, 0x05000000, 0x50000000, 0x200005c0 },
1124 { 400, 200, 100, 0x11100070, 0x00100804, 0x05000000, 0x48000000, 0x200005c0 },
1125 { 400, 266, 133, 0x11100070, 0x000c0604, 0x05000000, 0x38000000, 0x200005c0 },
1126 { 426, 213, 106, 0x11100070, 0x000c0603, 0x04000000, 0x48000000, 0x200005c0 },
1127 { 440, 220, 110, 0x11100070, 0x000c0603, 0x04200000, 0x48000000, 0x200005c0 },
1128 { 446, 148, 74, 0x11100070, 0x00120903, 0x04300000, 0x68000000, 0x200005c0 },
1129 { 453, 226, 113, 0x11100070, 0x000c0603, 0x04400000, 0x48000000, 0x200005c0 },
1130 { 466, 233, 116, 0x11100070, 0x000c0603, 0x04600000, 0x48000000, 0x200005c0 },
1131 { 480, 137, 68, 0x11100070, 0x000e0702, 0x03000000, 0x78000000, 0x200005c0 },
1132 { 480, 137, 137, 0x11100070, 0x00070702, 0x03000000, 0x70000000, 0x200005c0 },
1133 { 480, 160, 80, 0x11100070, 0x000c0602, 0x03000000, 0x68000000, 0x200005c0 },
1134 { 480, 240, 120, 0x11100070, 0x00080402, 0x03000000, 0x48000000, 0x200005c0 },
1135 { 500, 100, 100, 0x11100070, 0x000a0a02, 0x03200000, 0xa0000000, 0x200005c0 },
1136 { 500, 166, 83, 0x11100070, 0x000c0602, 0x03200000, 0x68000000, 0x200005c0 },
1137 { 500, 166, 166, 0x11100070, 0x00060602, 0x03200000, 0x60000000, 0x200005c0 },
1138 { 500, 200, 100, 0x11100070, 0x000a0502, 0x03200000, 0x58000000, 0x200005c0 },
1139 { 500, 250, 125, 0x11100070, 0x00080402, 0x03200000, 0x48000000, 0x200005c0 },
1140 { 530, 176, 88, 0x11100070, 0x000c0602, 0x03500000, 0x68000000, 0x200005c0 },
1141 { 530, 176, 176, 0x11100070, 0x00060602, 0x03500000, 0x60000000, 0x200005c0 },
1142 { 530, 212, 106, 0x11100070, 0x000a0502, 0x03500000, 0x58000000, 0x200005c0 },
1143 { 530, 265, 132, 0x11100070, 0x00080402, 0x03500000, 0x48000000, 0x200005c0 },
1144 { 533, 133, 133, 0x11100070, 0x000c0c03, 0x05000000, 0x80000000, 0x200005c0 },
1145 { 533, 266, 133, 0x11100070, 0x000c0603, 0x05000000, 0x48000000, 0x200005c0 },
1149 /* 25MHz table for 5356 */
1150 static uint32
BCMINITDATA(pll25mhz_table
)[][8] = {
1151 /* cpu, ddr, axi, pllctl12, pllctl13, pllctl14, pllctl15, pllctl16 */
1152 { 66, 66, 66, 0x11100070, 0x00121212, 0x03000000, 0x20000000, 0x200005c0 },
1153 { 75, 75, 75, 0x11100070, 0x00101010, 0x03000000, 0x20000000, 0x200005c0 },
1154 { 80, 80, 80, 0x11100070, 0x000a0a0a, 0x02000000, 0x20000000, 0x200005c0 },
1155 { 83, 83, 83, 0x11100070, 0x000c0c0c, 0x02800000, 0x20000000, 0x200005c0 },
1156 { 100, 66, 66, 0x11100070, 0x0012120c, 0x03000000, 0x30000000, 0x200005c0 },
1157 { 100, 100, 100, 0x11100070, 0x000c0c0c, 0x03000000, 0x20000000, 0x200005c0 },
1158 { 125, 83, 83, 0x11100070, 0x000c0c08, 0x02800000, 0x30000000, 0x200005c0 },
1159 { 133, 133, 133, 0x11100070, 0x000c0c0c, 0x04000000, 0x20000000, 0x200005c0 },
1160 { 150, 75, 75, 0x11100070, 0x00101008, 0x03000000, 0x40000000, 0x200005c0 },
1161 { 150, 100, 100, 0x11100070, 0x000c0c08, 0x03000000, 0x30000000, 0x200005c0 },
1162 { 150, 150, 75, 0x11100070, 0x00100808, 0x03000000, 0x28000000, 0x200005c0 },
1163 { 150, 150, 150, 0x11100070, 0x00080808, 0x03000000, 0x20000000, 0x200005c0 },
1164 { 166, 83, 83, 0x11100070, 0x000c0c06, 0x02800000, 0x40000000, 0x200005c0 },
1165 { 166, 166, 83, 0x11100070, 0x000c0606, 0x02800000, 0x28000000, 0x200005c0 },
1166 { 166, 166, 166, 0x11100070, 0x00060606, 0x02800000, 0x20000000, 0x200005c0 },
1167 { 200, 133, 133, 0x11100070, 0x000c0c08, 0x04000000, 0x30000000, 0x200005c0 },
1168 { 200, 200, 100, 0x11100070, 0x000c0606, 0x03000000, 0x28000000, 0x200005c0 },
1169 { 250, 166, 83, 0x11100070, 0x000c0604, 0x02800000, 0x38000000, 0x200005c0 },
1170 { 250, 166, 166, 0x11100070, 0x00060604, 0x02800000, 0x30000000, 0x200005c0 },
1171 { 293, 195, 97, 0x11100070, 0x000c0604, 0x02f00000, 0x38000000, 0x200005c0 },
1172 { 300, 100, 100, 0x11100070, 0x000c0c04, 0x03000000, 0x60000000, 0x200005c0 },
1173 { 300, 120, 120, 0x11100070, 0x000a0a04, 0x03000000, 0x50000000, 0x200005c0 },
1174 { 300, 150, 75, 0x11100070, 0x00100804, 0x03000000, 0x48000000, 0x200005c0 },
1175 { 300, 150, 150, 0x11100070, 0x00080804, 0x03000000, 0x40000000, 0x200005c0 },
1176 { 300, 200, 100, 0x11100070, 0x000c0604, 0x03000000, 0x38000000, 0x200005c0 },
1177 { 332, 110, 110, 0x11100070, 0x000c0c04, 0x03540000, 0x6047ae14, 0x202c2820 },
1178 { 332, 133, 133, 0x11100070, 0x000a0a04, 0x03540000, 0x5047ae14, 0x202c2820 },
1179 { 332, 166, 83, 0x11100070, 0x00100804, 0x03540000, 0x4847ae14, 0x202c2820 },
1180 { 333, 111, 111, 0x11100070, 0x00090903, 0x02800000, 0x60000000, 0x200005c0 },
1181 { 333, 133, 133, 0x11100070, 0x000f0f06, 0x05000000, 0x50000000, 0x38000700 },
1182 { 333, 166, 83, 0x11100070, 0x000c0603, 0x02800000, 0x48000000, 0x200005c0 },
1183 { 333, 166, 166, 0x11100070, 0x00060603, 0x02800000, 0x40000000, 0x200005c0 },
1184 { 400, 133, 133, 0x11100070, 0x000c0c04, 0x04000000, 0x60000000, 0x200005c0 },
1185 { 400, 200, 100, 0x11100070, 0x000c0603, 0x03000000, 0x48000000, 0x200005c0 },
1186 { 400, 266, 133, 0x11100070, 0x000c0604, 0x04000000, 0x38000000, 0x200005c0 },
1187 { 500, 166, 83, 0x11100070, 0x000c0602, 0x02800000, 0x68000000, 0x200005c0 },
1188 { 500, 166, 166, 0x11100070, 0x00060602, 0x02800000, 0x60000000, 0x200005c0 },
1189 { 500, 200, 100, 0x11100070, 0x000a0502, 0x02800000, 0x58000000, 0x200005c0 },
1190 { 500, 250, 125, 0x11100070, 0x00080402, 0x02800000, 0x48000000, 0x200005c0 },
1194 if (CHIPID(sih
->chip
) == BCM4706_CHIP_ID
)
1195 return mips_pmu_setclock_4706(sih
, mipsclock
, ddrclock
, axiclock
);
1197 /* By default use the 20MHz pll table */
1198 pll_table
= pll20mhz_table
;
1202 /* Adjust the mainpll_pll0 address and pll table for 5356 */
1203 if (CHIPID(sih
->chip
) == BCM5356_CHIP_ID
) {
1204 mainpll_pll0
= PMU5356_MAINPLL_PLL0
;
1205 pll_table
= pll25mhz_table
;
1207 /* Adjust the mainpll_pll0 address and pll table for 5357 */
1208 if (CHIPID(sih
->chip
) == BCM5357_CHIP_ID
) {
1209 mainpll_pll0
= PMU5357_MAINPLL_PLL0
;
1210 pll_table
= pll20mhz_table
;
1213 /* get index of the current core */
1214 idx
= si_coreidx(sih
);
1216 /* switch to chipc core */
1217 cc
= (chipcregs_t
*)si_setcoreidx(sih
, SI_CC_IDX
);
1220 mipsclock
/= 1000000;
1221 ddrclock
/= 1000000;
1222 axiclock
/= 1000000;
1224 HNDMIPS_NONE(("Looking for %d/%d/%d\n", mipsclock
, ddrclock
, axiclock
));
1226 for (idx
= 0; pll_table
[idx
][0] != 0; idx
++) {
1228 /* Bypass pll entries that are not allowed */
1229 if ((((pll_table
[idx
][4] & 0xff) < 4) ||
1230 (((pll_table
[idx
][5] >> 20) & 0x1ff) > 0x50)) &&
1231 (CHIPID(sih
->chip
) == BCM5357_CHIP_ID
) &&
1232 (((chippkg
= R_REG(osh
, &cc
->sromotp
[23])) & 0x80) == 0x80)) {
1235 if ((mipsclock
<= pll_table
[idx
][0]) &&
1236 ((ddrclock
== 0) || (ddrclock
<= pll_table
[idx
][1])) &&
1237 ((axiclock
== 0) || (axiclock
<= pll_table
[idx
][2])))
1241 if (pll_table
[idx
][0] == 0) {
1246 HNDMIPS_NONE(("Using entry %d: %d/%d/%d, 0x%08x, 0x%08x, 0x%08x, 0x%08x, %d\n", idx
,
1247 pll_table
[idx
][0], pll_table
[idx
][1], pll_table
[idx
][2],
1248 pll_table
[idx
][3], pll_table
[idx
][4], pll_table
[idx
][5],
1249 pll_table
[idx
][6], pll_table
[idx
][7]));
1251 for (i
= PMU5_PLL_P1P2_OFF
; i
<= PMU5_PLL_FMAB_OFF
; i
++) {
1252 W_REG(osh
, &cc
->pllcontrol_addr
, mainpll_pll0
+ i
);
1253 (void)R_REG(osh
, &cc
->pllcontrol_addr
);
1254 if (R_REG(osh
, &cc
->pllcontrol_data
) != pll_table
[idx
][i
+ 3])
1258 /* All matched, no change needed */
1259 if (i
== (PMU5_PLL_FMAB_OFF
+ 1))
1262 /* Write new PLL settings */
1263 for (i
= PMU5_PLL_P1P2_OFF
; i
<= PMU5_PLL_PLLCTL_OFF
; i
++) {
1266 W_REG(osh
, &cc
->pllcontrol_addr
, mainpll_pll0
+ i
);
1267 (void)R_REG(osh
, &cc
->pllcontrol_addr
);
1268 tmp
= pll_table
[idx
][i
+ 3];
1269 W_REG(osh
, &cc
->pllcontrol_data
, tmp
);
1271 /* Wait for the last write */
1272 (void)R_REG(osh
, &cc
->pllcontrol_data
);
1274 /* For chips that support changing clocks on the fly, use the new clocks changing scheme */
1275 if ((regs
= si_setcore(sih
, MIPS74K_CORE_ID
, 0)) != NULL
)
1276 chclk_otf
= ((si_core_sflags(sih
, 0, 0) & SISF_CHG_CLK_OTF_PRESENT
) != 0);
1278 ((dmc
= (dmemcregs_t
*)si_setcore(sih
, DMEMC_CORE_ID
, 0)) != NULL
)) {
1279 uint ic_size
, ic_lsize
;
1284 /* Enable mips interrupt */
1285 c0reg
= MFC0(C0_STATUS
, 0);
1286 tmp
= (c0reg
& ~ALLINTS
) | IE_IRQ0
;
1287 MTC0(C0_STATUS
, 0, tmp
);
1289 /* Enable PMU interrupt */
1290 OR_REG(osh
, &cc
->intmask
, CI_PMU
);
1292 icache_probe(MFC0(C0_CONFIG
, 1), &ic_size
, &ic_lsize
);
1294 /* Put sdsleep routine into the icache */
1295 start
= (ulong
)&sdsleep
;
1296 end
= (ulong
)&aftersdsleep
;
1297 for (i
= 0; i
< (end
- start
); i
+= ic_lsize
)
1298 cache_op(start
+ i
, Fill_I
);
1300 /* Program PMU timer */
1301 tmp
= R_REG(osh
, &cc
->res_req_timer
);
1304 W_REG(osh
, &cc
->res_req_timer
, tmp
);
1306 /* Set change clock */
1307 W_REG(osh
, &cc
->chipcontrol_addr
, 0x1);
1308 SET_REG(osh
, &cc
->chipcontrol_data
, (1 << 3), (1 << 3));
1312 /* Clear change clock */
1313 W_REG(osh
, &cc
->chipcontrol_addr
, 0x1);
1314 SET_REG(osh
, &cc
->chipcontrol_data
, (1 << 3), 0);
1316 /* Clear PMU interrupt */
1317 W_REG(osh
, &cc
->pmustatus
, 0x40);
1319 /* Restore mips interrupt mask */
1320 MTC0(C0_STATUS
, 0, c0reg
);
1325 if (CHIPID(sih
->chip
) == BCM47162_CHIP_ID
) {
1326 /* In 47162, clear min_res_mask */
1327 W_REG(osh
, &cc
->min_res_mask
,
1328 R_REG(osh
, &cc
->min_res_mask
) & ~RES4716_PROC_HT_AVAIL
);
1330 /* Reset, use chipcommon's watchdog, not the PMU */
1331 W_REG(osh
, &cc
->watchdog
, 1000);
1333 /* And now do the pll update */
1334 W_REG(osh
, &cc
->pmucontrol
,
1335 R_REG(osh
, &cc
->pmucontrol
) | PCTL_PLL_PLLCTL_UPD
);
1337 si_watchdog(sih
, 100);
1339 /* wait for timer interrupt */
1341 __asm__
__volatile__(
1348 /* switch back to previous core */
1349 si_setcoreidx(sih
, idx
);
1355 BCMINITFN(handler
)(void)
1361 /* Disable interrupts */
1362 /* MTC0(C0_STATUS, 0, MFC0(C0_STATUS, 0) & ~(ALLINTS | STO_IE)); */
1364 /* Just a Hack to not to use reg 'at' which was causing problems on 4704 A2 */
1365 "li $14, -31746\n\t"
1366 "and $15, $15, $14\n\t"
1374 /* The following MUST come right after handler() */
1376 BCMINITFN(afterhandler
)(void)
1381 * Set the MIPS, backplane and PCI clocks as closely as possible.
1383 * MIPS clocks synchronization function has been moved from PLL in chipcommon
1384 * core rev. 15 to a DLL inside the MIPS core in 4785.
1387 BCMINITFN(si_mips_setclock
)(si_t
*sih
, uint32 mipsclock
, uint32 siclock
, uint32 pciclock
)
1390 chipcregs_t
*cc
= NULL
;
1391 mips33regs_t
*mipsr
= NULL
;
1392 volatile uint32
*clockcontrol_n
, *clockcontrol_sb
, *clockcontrol_pci
, *clockcontrol_m2
;
1393 uint32 orig_n
, orig_sb
, orig_pci
, orig_m2
, orig_mips
, orig_ratio_parm
, orig_ratio_cfg
;
1394 uint32 pll_type
, sync_mode
;
1395 uint ic_size
, ic_lsize
;
1398 /* PLL configuration: type 3 */
1402 uint32 m2
; /* that is the clockcontrol_m2 */
1404 static type3_table_t type3_table
[] = {
1405 /* for 5350, mips clock is always double sb clock */
1406 { 150000000, 0x311, 0x4020005 },
1407 { 200000000, 0x311, 0x4020003 },
1410 /* PLL configuration: type 2, 4, 7 */
1425 static n4m_table_t
BCMINITDATA(type2_table
)[] = {
1426 { 120000000, 60000000, 32000000, 0x0303, 0x01000200, 0x01000600, 0x01000200,
1427 0x05000200, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 },
1428 { 150000000, 75000000, 33333333, 0x0303, 0x01000100, 0x01000600, 0x01000100,
1429 0x05000100, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 },
1430 { 180000000, 80000000, 30000000, 0x0403, 0x01010000, 0x01020300, 0x01020600,
1431 0x05000100, 8, 0x012a00a9, 9 /* ratio 4/9 */, 0x012a00a9 },
1432 { 180000000, 90000000, 30000000, 0x0403, 0x01000100, 0x01020300, 0x01000100,
1433 0x05000100, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 },
1434 { 200000000, 100000000, 33333333, 0x0303, 0x02010000, 0x02040001, 0x02010000,
1435 0x06000001, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 },
1436 { 211200000, 105600000, 30171428, 0x0902, 0x01000200, 0x01030400, 0x01000200,
1437 0x05000200, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 },
1438 { 220800000, 110400000, 31542857, 0x1500, 0x01000200, 0x01030400, 0x01000200,
1439 0x05000200, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 },
1440 { 230400000, 115200000, 32000000, 0x0604, 0x01000200, 0x01020600, 0x01000200,
1441 0x05000200, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 },
1442 { 234000000, 104000000, 31200000, 0x0b01, 0x01010000, 0x01010700, 0x01020600,
1443 0x05000100, 8, 0x012a00a9, 9 /* ratio 4/9 */, 0x012a00a9 },
1444 { 240000000, 120000000, 33333333, 0x0803, 0x01000200, 0x01020600, 0x01000200,
1445 0x05000200, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 },
1446 { 252000000, 126000000, 33333333, 0x0504, 0x01000100, 0x01020500, 0x01000100,
1447 0x05000100, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 },
1448 { 264000000, 132000000, 33000000, 0x0903, 0x01000200, 0x01020700, 0x01000200,
1449 0x05000200, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 },
1450 { 270000000, 120000000, 30000000, 0x0703, 0x01010000, 0x01030400, 0x01020600,
1451 0x05000100, 8, 0x012a00a9, 9 /* ratio 4/9 */, 0x012a00a9 },
1452 { 276000000, 122666666, 31542857, 0x1500, 0x01010000, 0x01030400, 0x01020600,
1453 0x05000100, 8, 0x012a00a9, 9 /* ratio 4/9 */, 0x012a00a9 },
1454 { 280000000, 140000000, 31111111, 0x0503, 0x01000000, 0x01010600, 0x01000000,
1455 0x05000000, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 },
1456 { 288000000, 128000000, 32914285, 0x0604, 0x01010000, 0x01030400, 0x01020600,
1457 0x05000100, 8, 0x012a00a9, 9 /* ratio 4/9 */, 0x012a00a9 },
1458 { 288000000, 144000000, 32000000, 0x0404, 0x01000000, 0x01010600, 0x01000000,
1459 0x05000000, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 },
1460 { 300000000, 133333333, 33333333, 0x0803, 0x01010000, 0x01020600, 0x01010100,
1461 0x05000100, 8, 0x012a00a9, 9 /* ratio 4/9 */, 0x012a00a9 },
1462 { 300000000, 133333333, 37500000, 0x0803, 0x01010000, 0x01020500, 0x01010100,
1463 0x05000100, 8, 0x012a00a9, 9 /* ratio 4/9 */, 0x012a00a9 },
1464 { 300000000, 133333333, 42857142, 0x0803, 0x01010000, 0x01020400, 0x01010100,
1465 0x05000100, 8, 0x012a00a9, 9 /* ratio 4/9 */, 0x012a00a9 },
1466 { 300000000, 133333333, 50000000, 0x0803, 0x01010000, 0x01020300, 0x01010100,
1467 0x05000100, 8, 0x012a00a9, 9 /* ratio 4/9 */, 0x012a00a9 },
1468 { 300000000, 133333333, 60000000, 0x0803, 0x01010000, 0x01020200, 0x01010100,
1469 0x05000100, 8, 0x012a00a9, 9 /* ratio 4/9 */, 0x012a00a9 },
1470 { 300000000, 150000000, 33333333, 0x0803, 0x01000100, 0x01020600, 0x01010100,
1471 0x05000100, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 },
1472 { 300000000, 150000000, 37500000, 0x0803, 0x01000100, 0x01020500, 0x01010100,
1473 0x05000100, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 },
1474 { 300000000, 150000000, 42857142, 0x0803, 0x01000100, 0x01020400, 0x01010100,
1475 0x05000100, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 },
1476 { 300000000, 150000000, 50000000, 0x0803, 0x01000100, 0x01020300, 0x01010100,
1477 0x05000100, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 },
1478 { 300000000, 150000000, 60000000, 0x0803, 0x01000100, 0x01020200, 0x01010100,
1479 0x05000100, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 },
1480 { 330000000, 132000000, 33000000, 0x0903, 0x01000200, 0x00020200, 0x01010100,
1481 0x05000100, 0, 0, 10 /* ratio 4/10 */, 0x02520129 },
1482 { 330000000, 146666666, 33000000, 0x0903, 0x01010000, 0x00020200, 0x01010100,
1483 0x05000100, 0, 0, 9 /* ratio 4/9 */, 0x012a00a9 },
1484 { 330000000, 165000000, 33000000, 0x0903, 0x01000100, 0x00020200, 0x01010100,
1485 0x05000100, 0, 0, 8 /* ratio 4/8 */, 0x00aa0055 },
1486 { 330000000, 165000000, 41250000, 0x0903, 0x01000100, 0x00020100, 0x01010100,
1487 0x05000100, 0, 0, 8 /* ratio 4/8 */, 0x00aa0055 },
1488 { 330000000, 165000000, 55000000, 0x0903, 0x01000100, 0x00020000, 0x01010100,
1489 0x05000100, 0, 0, 8 /* ratio 4/8 */, 0x00aa0055 },
1490 { 360000000, 120000000, 32000000, 0x0a03, 0x01000300, 0x00010201, 0x01010200,
1491 0x05000100, 0, 0, 12 /* ratio 4/12 */, 0x04920492 },
1492 { 360000000, 144000000, 32000000, 0x0a03, 0x01000200, 0x00010201, 0x01010200,
1493 0x05000100, 0, 0, 10 /* ratio 4/10 */, 0x02520129 },
1494 { 360000000, 160000000, 32000000, 0x0a03, 0x01010000, 0x00010201, 0x01010200,
1495 0x05000100, 0, 0, 9 /* ratio 4/9 */, 0x012a00a9 },
1496 { 360000000, 180000000, 32000000, 0x0a03, 0x01000100, 0x00010201, 0x01010200,
1497 0x05000100, 0, 0, 8 /* ratio 4/8 */, 0x00aa0055 },
1498 { 360000000, 180000000, 40000000, 0x0a03, 0x01000100, 0x00010101, 0x01010200,
1499 0x05000100, 0, 0, 8 /* ratio 4/8 */, 0x00aa0055 },
1500 { 360000000, 180000000, 53333333, 0x0a03, 0x01000100, 0x00010001, 0x01010200,
1501 0x05000100, 0, 0, 8 /* ratio 4/8 */, 0x00aa0055 },
1502 { 390000000, 130000000, 32500000, 0x0b03, 0x01010100, 0x00020101, 0x01020100,
1503 0x05000100, 0, 0, 12 /* ratio 4/12 */, 0x04920492 },
1504 { 390000000, 156000000, 32500000, 0x0b03, 0x01000200, 0x00020101, 0x01020100,
1505 0x05000100, 0, 0, 10 /* ratio 4/10 */, 0x02520129 },
1506 { 390000000, 173000000, 32500000, 0x0b03, 0x01010000, 0x00020101, 0x01020100,
1507 0x05000100, 0, 0, 9 /* ratio 4/9 */, 0x012a00a9 },
1508 { 390000000, 195000000, 32500000, 0x0b03, 0x01000100, 0x00020101, 0x01020100,
1509 0x05000100, 0, 0, 8 /* ratio 4/8 */, 0x00aa0055 },
1511 static n4m_table_t
BCMINITDATA(type4_table
)[] = {
1512 { 120000000, 60000000, 0, 0x0009, 0x11020009, 0x01030203, 0x11020009, 0x04000009,
1514 { 150000000, 75000000, 0, 0x0009, 0x11050002, 0x01030203, 0x11050002, 0x04000005,
1516 { 192000000, 96000000, 0, 0x0702, 0x04000011, 0x11030011, 0x04000011, 0x04000003,
1518 { 198000000, 99000000, 0, 0x0603, 0x11020005, 0x11030011, 0x11020005, 0x04000005,
1520 { 200000000, 100000000, 0, 0x0009, 0x04020011, 0x11030011, 0x04020011, 0x04020003,
1522 { 204000000, 102000000, 0, 0x0c02, 0x11020005, 0x01030303, 0x11020005, 0x04000005,
1524 { 208000000, 104000000, 0, 0x0802, 0x11030002, 0x11090005, 0x11030002, 0x04000003,
1526 { 210000000, 105000000, 0, 0x0209, 0x11020005, 0x01030303, 0x11020005, 0x04000005,
1528 { 216000000, 108000000, 0, 0x0111, 0x11020005, 0x01030303, 0x11020005, 0x04000005,
1530 { 224000000, 112000000, 0, 0x0205, 0x11030002, 0x02002103, 0x11030002, 0x04000003,
1532 { 228000000, 101333333, 0, 0x0e02, 0x11030003, 0x11210005, 0x01030305, 0x04000005,
1534 { 228000000, 114000000, 0, 0x0e02, 0x11020005, 0x11210005, 0x11020005, 0x04000005,
1536 { 240000000, 102857143, 0, 0x0109, 0x04000021, 0x01050203, 0x11030021, 0x04000003,
1538 { 240000000, 120000000, 0, 0x0109, 0x11030002, 0x01050203, 0x11030002, 0x04000003,
1540 { 252000000, 100800000, 0, 0x0203, 0x04000009, 0x11050005, 0x02000209, 0x04000002,
1542 { 252000000, 126000000, 0, 0x0203, 0x04000005, 0x11050005, 0x04000005, 0x04000002,
1544 { 264000000, 132000000, 0, 0x0602, 0x04000005, 0x11050005, 0x04000005, 0x04000002,
1546 { 272000000, 116571428, 0, 0x0c02, 0x04000021, 0x02000909, 0x02000221, 0x04000003,
1548 { 280000000, 120000000, 0, 0x0209, 0x04000021, 0x01030303, 0x02000221, 0x04000003,
1550 { 288000000, 123428571, 0, 0x0111, 0x04000021, 0x01030303, 0x02000221, 0x04000003,
1552 { 300000000, 120000000, 0, 0x0009, 0x04000009, 0x01030203, 0x02000902, 0x04000002,
1554 { 300000000, 150000000, 0, 0x0009, 0x04000005, 0x01030203, 0x04000005, 0x04000002,
1557 static n4m_table_t
BCMINITDATA(type7_table
)[] = {
1558 { 183333333, 91666666, 0, 0x0605, 0x04000011, 0x11030011, 0x04000011, 0x04000003,
1560 { 187500000, 93750000, 0, 0x0a03, 0x04000011, 0x11030011, 0x04000011, 0x04000003,
1562 { 196875000, 98437500, 0, 0x1003, 0x11020005, 0x11050011, 0x11020005, 0x04000005,
1564 { 200000000, 100000000, 0, 0x0311, 0x04000011, 0x11030011, 0x04000009, 0x04000003,
1566 { 200000000, 100000000, 0, 0x0311, 0x04020011, 0x11030011, 0x04020011, 0x04020003,
1568 { 206250000, 103125000, 0, 0x1103, 0x11020005, 0x11050011, 0x11020005, 0x04000005,
1570 { 212500000, 106250000, 0, 0x0c05, 0x11020005, 0x01030303, 0x11020005, 0x04000005,
1572 { 215625000, 107812500, 0, 0x1203, 0x11090009, 0x11050005, 0x11020005, 0x04000005,
1574 { 216666666, 108333333, 0, 0x0805, 0x11020003, 0x11030011, 0x11020003, 0x04000003,
1576 { 225000000, 112500000, 0, 0x0d03, 0x11020003, 0x11030011, 0x11020003, 0x04000003,
1578 { 233333333, 116666666, 0, 0x0905, 0x11020003, 0x11030011, 0x11020003, 0x04000003,
1580 { 237500000, 118750000, 0, 0x0e05, 0x11020005, 0x11210005, 0x11020005, 0x04000005,
1582 { 240000000, 120000000, 0, 0x0b11, 0x11020009, 0x11210009, 0x11020009, 0x04000009,
1584 { 250000000, 125000000, 0, 0x0f03, 0x11020003, 0x11210003, 0x11020003, 0x04000003,
1588 ulong start
, end
, dst
;
1591 volatile uint32
*dll_ctrl
= (volatile uint32
*)0xff400008;
1592 volatile uint32
*dll_r1
= (volatile uint32
*)0xff400010;
1593 volatile uint32
*dll_r2
= (volatile uint32
*)0xff400018;
1595 /* 5354 chipcommon pll setting can't be changed.
1596 * The PMU on power up comes up with the default clk frequency
1599 if ((CHIPID(sih
->chip
) == BCM5354_CHIP_ID
) || (CHIPID(sih
->chip
) == BCM53572_CHIP_ID
))
1602 if (sih
->cccaps
& CC_CAP_PMU
)
1603 return mips_pmu_setclock(sih
, mipsclock
, siclock
, pciclock
);
1607 /* get index of the current core */
1608 idx
= si_coreidx(sih
);
1609 clockcontrol_m2
= NULL
;
1611 /* switch to chipc core */
1612 cc
= (chipcregs_t
*)si_setcoreidx(sih
, SI_CC_IDX
);
1615 pll_type
= sih
->cccaps
& CC_CAP_PLL_MASK
;
1616 if (pll_type
== PLL_TYPE6
) {
1617 clockcontrol_n
= NULL
;
1618 clockcontrol_sb
= NULL
;
1619 clockcontrol_pci
= NULL
;
1621 clockcontrol_n
= &cc
->clockcontrol_n
;
1622 clockcontrol_sb
= &cc
->clockcontrol_sb
;
1623 clockcontrol_pci
= &cc
->clockcontrol_pci
;
1624 clockcontrol_m2
= &cc
->clockcontrol_m2
;
1627 if (pll_type
== PLL_TYPE6
) {
1628 /* Silence compilers */
1629 orig_n
= orig_sb
= orig_pci
= 0;
1631 /* Store the current clock register values */
1632 orig_n
= R_REG(osh
, clockcontrol_n
);
1633 orig_sb
= R_REG(osh
, clockcontrol_sb
);
1634 orig_pci
= R_REG(osh
, clockcontrol_pci
);
1637 if (pll_type
== PLL_TYPE3
) {
1639 if (CHIPID(sih
->chip
) != BCM5365_CHIP_ID
) {
1641 * Search for the closest MIPS clock less than or equal to
1642 * a preferred value.
1644 for (i
= 0; i
< ARRAYSIZE(type3_table
); i
++) {
1645 if (type3_table
[i
].mipsclock
> mipsclock
)
1655 ASSERT(type3_table
[i
].mipsclock
<= mipsclock
);
1658 orig_m2
= R_REG(osh
, &cc
->clockcontrol_m2
);
1659 if ((orig_n
== type3_table
[i
].n
) &&
1660 (orig_m2
== type3_table
[i
].m2
)) {
1664 /* Set the PLL controls */
1665 W_REG(osh
, clockcontrol_n
, type3_table
[i
].n
);
1666 W_REG(osh
, clockcontrol_m2
, type3_table
[i
].m2
);
1669 si_watchdog(sih
, 1);
1672 } else if ((pll_type
== PLL_TYPE2
) ||
1673 (pll_type
== PLL_TYPE4
) ||
1674 (pll_type
== PLL_TYPE6
) ||
1675 (pll_type
== PLL_TYPE7
)) {
1676 n4m_table_t
*table
= NULL
, *te
;
1681 orig_mips
= R_REG(osh
, &cc
->clockcontrol_m3
);
1685 uint32 new_mips
= 0;
1688 if (mipsclock
<= SB2MIPS_T6(CC_T6_M1
))
1689 new_mips
= CC_T6_MMASK
;
1691 if (orig_mips
== new_mips
)
1694 W_REG(osh
, &cc
->clockcontrol_m3
, new_mips
);
1698 table
= type2_table
;
1699 tabsz
= ARRAYSIZE(type2_table
);
1702 table
= type4_table
;
1703 tabsz
= ARRAYSIZE(type4_table
);
1706 table
= type7_table
;
1707 tabsz
= ARRAYSIZE(type7_table
);
1710 ASSERT("No table for plltype" == NULL
);
1714 /* Store the current clock register values */
1715 orig_m2
= R_REG(osh
, &cc
->clockcontrol_m2
);
1716 orig_ratio_parm
= 0;
1719 /* Look up current ratio */
1720 for (i
= 0; i
< tabsz
; i
++) {
1721 if ((orig_n
== table
[i
].n
) &&
1722 (orig_sb
== table
[i
].sb
) &&
1723 (orig_pci
== table
[i
].pci33
) &&
1724 (orig_m2
== table
[i
].m2
) &&
1725 (orig_mips
== table
[i
].m3
)) {
1726 orig_ratio_parm
= table
[i
].ratio_parm
;
1727 orig_ratio_cfg
= table
[i
].ratio_cfg
;
1732 /* Search for the closest MIPS clock greater or equal to a preferred value */
1733 for (i
= 0; i
< tabsz
; i
++) {
1734 ASSERT(table
[i
].mipsclock
==
1735 si_clock_rate(pll_type
, table
[i
].n
, table
[i
].m3
));
1736 if ((mipsclock
<= table
[i
].mipsclock
) &&
1737 ((siclock
== 0) || (siclock
<= table
[i
].sbclock
)) &&
1738 ((pciclock
== 0) || (pciclock
<= table
[i
].pciclock
)))
1750 if ((orig_n
== te
->n
) &&
1751 (orig_sb
== te
->sb
) &&
1752 (orig_pci
== te
->pci33
) &&
1753 (orig_m2
== te
->m2
) &&
1754 (orig_mips
== te
->m3
))
1757 /* Set the PLL controls */
1758 W_REG(osh
, clockcontrol_n
, te
->n
);
1759 W_REG(osh
, clockcontrol_sb
, te
->sb
);
1760 W_REG(osh
, clockcontrol_pci
, te
->pci33
);
1761 W_REG(osh
, &cc
->clockcontrol_m2
, te
->m2
);
1762 W_REG(osh
, &cc
->clockcontrol_m3
, te
->m3
);
1764 /* Set the chipcontrol bit to change mipsref to the backplane divider if needed */
1765 if ((pll_type
== PLL_TYPE7
) && (te
->sb
!= te
->m2
) &&
1766 (si_clock_rate(pll_type
, te
->n
, te
->m2
) == 120000000))
1767 W_REG(osh
, &cc
->chipcontrol
,
1768 R_REG(osh
, &cc
->chipcontrol
) | 0x100);
1770 /* No ratio change */
1771 if (CHIPID(sih
->chip
) != BCM4785_CHIP_ID
) {
1772 if (orig_ratio_parm
== te
->ratio_parm
)
1776 /* Preload the code into the cache */
1777 icache_probe(MFC0(C0_CONFIG
, 1), &ic_size
, &ic_lsize
);
1778 if (CHIPID(sih
->chip
) == BCM4785_CHIP_ID
) {
1779 start
= ((ulong
) &&start_fill_4785
) & ~(ic_lsize
- 1);
1780 end
= ((ulong
) &&end_fill_4785
+ (ic_lsize
- 1)) & ~(ic_lsize
- 1);
1783 start
= ((ulong
) &&start_fill
) & ~(ic_lsize
- 1);
1784 end
= ((ulong
) &&end_fill
+ (ic_lsize
- 1)) & ~(ic_lsize
- 1);
1786 while (start
< end
) {
1787 cache_op(start
, Fill_I
);
1791 /* 4785 clock freq change procedures */
1792 if (CHIPID(sih
->chip
) == BCM4785_CHIP_ID
) {
1794 /* Switch to async */
1795 MTC0(C0_BROADCOM
, 4, (1 << 22));
1797 /* Set clock ratio in MIPS */
1798 *dll_r1
= (*dll_r1
& 0xfffffff0) | (te
->dll_r1
- 1);
1799 *dll_r2
= te
->dll_r2
;
1801 /* Enable new settings in MIPS */
1802 *dll_r1
= *dll_r1
| 0xc0000000;
1804 /* Set active cfg */
1805 MTC0(C0_BROADCOM
, 2, MFC0(C0_BROADCOM
, 2) | (1 << 3) | 1);
1807 /* Fake soft reset (clock cfg registers not reset) */
1808 MTC0(C0_BROADCOM
, 5, MFC0(C0_BROADCOM
, 5) | (1 << 2));
1810 /* Clear active cfg */
1811 MTC0(C0_BROADCOM
, 2, MFC0(C0_BROADCOM
, 2) & ~(1 << 3));
1813 /* set watchdog timer */
1814 W_REG(osh
, &cc
->watchdog
, 20);
1815 (void) R_REG(osh
, &cc
->chipid
);
1817 /* wait for timer interrupt */
1818 __asm__
__volatile__(
1826 /* Generic clock freq change procedures */
1828 /* Copy the handler */
1829 start
= (ulong
) &handler
;
1830 end
= (ulong
) &afterhandler
;
1831 dst
= KSEG1ADDR(0x180);
1832 for (i
= 0; i
< (end
- start
); i
+= 4)
1833 *((ulong
*)(dst
+ i
)) = *((ulong
*)(start
+ i
));
1835 /* Preload the handler into the cache one line at a time */
1836 for (i
= 0; i
< (end
- start
); i
+= ic_lsize
)
1837 cache_op(dst
+ i
, Fill_I
);
1840 MTC0(C0_STATUS
, 0, MFC0(C0_STATUS
, 0) & ~ST0_BEV
);
1842 /* Enable interrupts */
1843 MTC0(C0_STATUS
, 0, MFC0(C0_STATUS
, 0) | (ALLINTS
| ST0_IE
));
1845 /* Enable MIPS timer interrupt */
1846 mipsr
= si_setcore(sih
, MIPS33_CORE_ID
, 0);
1848 W_REG(osh
, &mipsr
->intmask
, 1);
1851 /* step 1, set clock ratios */
1852 MTC0(C0_BROADCOM
, 3, te
->ratio_parm
);
1853 MTC0(C0_BROADCOM
, 1, te
->ratio_cfg
);
1855 /* step 2: program timer intr */
1856 W_REG(osh
, &mipsr
->timer
, 100);
1857 (void) R_REG(osh
, &mipsr
->timer
);
1859 /* step 3, switch to async */
1860 sync_mode
= MFC0(C0_BROADCOM
, 4);
1861 MTC0(C0_BROADCOM
, 4, 1 << 22);
1863 /* step 4, set cfg active */
1864 MTC0(C0_BROADCOM
, 2, (1 << 3) | 1);
1867 __asm__
__volatile__(
1872 /* step 7, clear cfg active */
1873 MTC0(C0_BROADCOM
, 2, 0);
1875 /* Additional Step: set back to orig sync mode */
1876 MTC0(C0_BROADCOM
, 4, sync_mode
);
1878 /* step 8, fake soft reset */
1879 MTC0(C0_BROADCOM
, 5, MFC0(C0_BROADCOM
, 5) | (1 << 2));
1882 /* set watchdog timer */
1883 W_REG(osh
, &cc
->watchdog
, 20);
1884 (void) R_REG(osh
, &cc
->chipid
);
1886 /* wait for timer interrupt */
1887 __asm__
__volatile__(
1897 /* Enable 4785 DLL */
1898 if (CHIPID(sih
->chip
) == BCM4785_CHIP_ID
) {
1901 /* set mask to 1e, enable DLL (bit 0) */
1902 *dll_ctrl
|= 0x0041e021;
1904 /* enable aggressive hardware mode */
1905 *dll_ctrl
|= 0x00000080;
1907 /* wait for lock flag to clear */
1908 while ((*dll_ctrl
& 0x2) == 0);
1910 /* clear sticky flags (clear on write 1) */
1914 /* set mask to 5b'10001 */
1915 *dll_ctrl
= (*dll_ctrl
& 0xfffc1fff) | 0x00022000;
1917 /* enable sync mode */
1918 MTC0(C0_BROADCOM
, 4, MFC0(C0_BROADCOM
, 4) & 0xfe3fffff);
1919 (void)MFC0(C0_BROADCOM
, 4);
1922 /* switch back to previous core */
1923 si_setcoreidx(sih
, idx
);
1929 BCMINITFN(enable_pfc
)(uint32 mode
)
1933 uint ic_size
, ic_lsize
;
1935 prid
= MFC0(C0_PRID
, 0);
1939 /* enable prefetch cache if available */
1940 if (MFC0(C0_BROADCOM
, 0) & BRCM_PFC_AVAIL
) {
1941 /* If auto then choose the correct mode for this
1942 * platform, currently we only ever select one mode
1944 if (mode
== PFC_AUTO
)
1947 icache_probe(MFC0(C0_CONFIG
, 1), &ic_size
, &ic_lsize
);
1949 start
= ((ulong
) &&setpfc_start
) & ~(ic_lsize
- 1);
1950 end
= ((ulong
) &&setpfc_end
+ (ic_lsize
- 1)) & ~(ic_lsize
- 1);
1952 /* Preload setpfc code into the cache one line at a time */
1953 while (start
< end
) {
1954 cache_op(start
, Fill_I
);
1958 /* Now set the pfc */
1961 *(volatile uint32
*)PFC_CR1
= 0xffff0000;
1964 *(volatile uint32
*)PFC_CR0
= mode
;
1966 /* Compiler foder */
1971 /* returns the ncdl value to be programmed into sdram_ncdl for calibration */
1973 BCMINITFN(si_memc_get_ncdl
)(si_t
*sih
)
1978 uint32 config
, rd
, wr
, misc
, dqsg
, cd
, sm
, sd
;
1983 idx
= si_coreidx(sih
);
1985 memc
= (sbmemcregs_t
*)si_setcore(sih
, MEMC_CORE_ID
, 0);
1989 rev
= si_corerev(sih
);
1991 config
= R_REG(osh
, &memc
->config
);
1992 wr
= R_REG(osh
, &memc
->wrncdlcor
);
1993 rd
= R_REG(osh
, &memc
->rdncdlcor
);
1994 misc
= R_REG(osh
, &memc
->miscdlyctl
);
1995 dqsg
= R_REG(osh
, &memc
->dqsgatencdl
);
1997 rd
&= MEMC_RDNCDLCOR_RD_MASK
;
1998 wr
&= MEMC_WRNCDLCOR_WR_MASK
;
1999 dqsg
&= MEMC_DQSGATENCDL_G_MASK
;
2001 if (config
& MEMC_CONFIG_DDR
) {
2002 ret
= (wr
<< 16) | (rd
<< 8) | dqsg
;
2007 cd
= (rd
== MEMC_CD_THRESHOLD
) ? rd
: (wr
+ MEMC_CD_THRESHOLD
);
2008 sm
= (misc
& MEMC_MISC_SM_MASK
) >> MEMC_MISC_SM_SHIFT
;
2009 sd
= (misc
& MEMC_MISC_SD_MASK
) >> MEMC_MISC_SD_SHIFT
;
2010 ret
= (sm
<< 16) | (sd
<< 8) | cd
;
2014 /* switch back to previous core */
2015 si_setcoreidx(sih
, idx
);
2021 hnd_cpu_reset(si_t
*sih
)
2023 if (CHIPID(sih
->chip
) == BCM4785_CHIP_ID
)
2024 MTC0(C0_BROADCOM
, 4, (1 << 22));
2025 si_watchdog(sih
, 1);
2026 if (CHIPID(sih
->chip
) == BCM4785_CHIP_ID
) {
2027 __asm__
__volatile__(
2036 #if defined(BCMPERFSTATS)
2038 * CP0 Register 25 supports 4 semi-independent 32bit performance counters.
2039 * $25 select 0, 1, 2, and 3 are the counters. The counters *decrement* (who thought this one up?)
2040 * $25 select 4 and 5 each contain 2-16bit control fields, one for each of the 4 counters
2041 * $25 select 6 is the global perf control register.
2043 /* enable and start instruction counting */
2046 hndmips_perf_cyclecount_enable(void)
2048 MTC0(C0_PERFORMANCE
, 6, 0x80000200); /* global enable perf counters */
2049 MTC0(C0_PERFORMANCE
, 4,
2050 0x8048 | MFC0(C0_PERFORMANCE
, 4)); /* enable cycles counting for counter 0 */
2051 MTC0(C0_PERFORMANCE
, 0, 0); /* zero counter zero */
2055 hndmips_perf_instrcount_enable(void)
2057 MTC0(C0_PERFORMANCE
, 6, 0x80000200); /* global enable perf counters */
2058 MTC0(C0_PERFORMANCE
, 4,
2059 0x8044 | MFC0(C0_PERFORMANCE
, 4)); /* enable instructions counting for counter 0 */
2060 MTC0(C0_PERFORMANCE
, 0, 0); /* zero counter zero */
2063 /* enable and start I$ hit and I$ miss counting */
2065 hndmips_perf_icachecount_enable(void)
2067 MTC0(C0_PERFORMANCE
, 6, 0x80000218); /* enable I$ counting */
2068 MTC0(C0_PERFORMANCE
, 4, 0x80148018); /* count I$ hits in cntr 0 and misses in cntr 1 */
2069 MTC0(C0_PERFORMANCE
, 0, 0); /* zero counter 0 - # I$ hits */
2070 MTC0(C0_PERFORMANCE
, 1, 0); /* zero counter 1 - # I$ misses */
2073 /* enable and start D$ hit and I$ miss counting */
2075 hndmips_perf_dcachecount_enable(void)
2077 MTC0(C0_PERFORMANCE
, 6, 0x80000211); /* enable D$ counting */
2078 MTC0(C0_PERFORMANCE
, 4, 0x80248028); /* count D$ hits in cntr 0 and misses in cntr 1 */
2079 MTC0(C0_PERFORMANCE
, 0, 0); /* zero counter 0 - # D$ hits */
2080 MTC0(C0_PERFORMANCE
, 1, 0); /* zero counter 1 - # D$ misses */
2084 hndmips_perf_icache_miss_enable()
2086 MTC0(C0_PERFORMANCE
, 4,
2087 0x80140000 | MFC0(C0_PERFORMANCE
, 4)); /* enable cache misses counting for counter 1 */
2088 MTC0(C0_PERFORMANCE
, 1, 0); /* zero counter one */
2093 hndmips_perf_icache_hit_enable()
2095 MTC0(C0_PERFORMANCE
, 5, 0x8018 | MFC0(C0_PERFORMANCE
, 5));
2096 /* enable cache hits counting for counter 2 */
2097 MTC0(C0_PERFORMANCE
, 2, 0); /* zero counter 2 */
2101 hndmips_perf_read_instrcount()
2103 return -(long)(MFC0(C0_PERFORMANCE
, 0));
2107 hndmips_perf_read_cache_miss()
2109 return -(long)(MFC0(C0_PERFORMANCE
, 1));
2113 hndmips_perf_read_cache_hit()
2115 return -(long)(MFC0(C0_PERFORMANCE
, 2));