2 * BCM47XX Sonics SiliconBackplane MIPS core routines
4 * Copyright 2007, Broadcom Corporation
7 * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
8 * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
9 * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
10 * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
26 #include <sbhndmips.h>
30 /* sbipsflag register format, indexed by irq. */
31 static const uint32 sbips_int_mask
[] = {
39 static const uint32 sbips_int_shift
[] = {
48 * Map SB cores sharing the MIPS hardware IRQ0 to virtual dedicated OS IRQs.
49 * Per-port BSP code is required to provide necessary translations between
50 * the shared MIPS IRQ and the virtual OS IRQs based on SB core flag.
52 * See sb_irq() for the mapping.
54 static uint shirq_map_base
= 0;
56 /* Returns the SB interrupt flag of the current core. */
57 static uint32
sb_getflag(sb_t
* sbh
)
64 regs
= sb_coreregs(sbh
);
65 sb
= (sbconfig_t
*) ((ulong
) regs
+ SBCONFIGOFF
);
67 return (R_REG(osh
, &sb
->sbtpsflag
) & SBTPS_NUM0_MASK
);
71 * Returns the MIPS IRQ assignment of the current core. If unassigned,
74 uint
sb_irq(sb_t
* sbh
)
80 uint32 flag
, sbipsflag
;
84 flag
= sb_getflag(sbh
);
86 idx
= sb_coreidx(sbh
);
88 if ((regs
= sb_setcore(sbh
, SB_MIPS
, 0)) ||
89 (regs
= sb_setcore(sbh
, SB_MIPS33
, 0))) {
90 sb
= (sbconfig_t
*) ((ulong
) regs
+ SBCONFIGOFF
);
92 /* sbipsflag specifies which core is routed to interrupts 1 to 4 */
93 sbipsflag
= R_REG(osh
, &sb
->sbipsflag
);
94 for (irq
= 1; irq
<= 4; irq
++) {
95 if (((sbipsflag
& sbips_int_mask
[irq
]) >>
96 sbips_int_shift
[irq
]) == flag
)
103 sb_setcoreidx(sbh
, idx
);
108 /* Clears the specified MIPS IRQ. */
109 static void BCMINITFN(sb_clearirq
) (sb_t
* sbh
, uint irq
) {
116 if (!(regs
= sb_setcore(sbh
, SB_MIPS
, 0)) &&
117 !(regs
= sb_setcore(sbh
, SB_MIPS33
, 0)))
119 sb
= (sbconfig_t
*) ((ulong
) regs
+ SBCONFIGOFF
);
122 W_REG(osh
, &sb
->sbintvec
, 0);
124 OR_REG(osh
, &sb
->sbipsflag
, sbips_int_mask
[irq
]);
128 * Assigns the specified MIPS IRQ to the specified core. Shared MIPS
129 * IRQ 0 may be assigned more than once.
131 * The old assignment to the specified core is removed first.
134 BCMINITFN(sb_setirq
) (sb_t
* sbh
, uint irq
, uint coreid
, uint coreunit
) {
143 regs
= sb_setcore(sbh
, coreid
, coreunit
);
145 flag
= sb_getflag(sbh
);
146 oldirq
= sb_irq(sbh
);
148 sb_clearirq(sbh
, oldirq
);
150 if (!(regs
= sb_setcore(sbh
, SB_MIPS
, 0)) &&
151 !(regs
= sb_setcore(sbh
, SB_MIPS33
, 0)))
153 sb
= (sbconfig_t
*) ((ulong
) regs
+ SBCONFIGOFF
);
156 AND_REG(osh
, &sb
->sbintvec
, ~(1 << flag
));
159 OR_REG(osh
, &sb
->sbintvec
, 1 << flag
);
161 flag
<<= sbips_int_shift
[irq
];
162 ASSERT(!(flag
& ~sbips_int_mask
[irq
]));
163 flag
|= R_REG(osh
, &sb
->sbipsflag
) & ~sbips_int_mask
[irq
];
164 W_REG(osh
, &sb
->sbipsflag
, flag
);
169 * Initializes clocks and interrupts. SB and NVRAM access must be
170 * initialized prior to calling.
172 * 'shirqmap' enables virtual dedicated OS IRQ mapping if non-zero.
174 void BCMINITFN(sb_mips_init
) (sb_t
* sbh
, uint shirqmap
) {
184 /* Figure out current SB clock speed */
185 if ((hz
= sb_clock(sbh
)) == 0)
187 ns
= 1000000000 / hz
;
189 /* Setup external interface timing */
190 if ((eir
= sb_setcore(sbh
, SB_EXTIF
, 0))) {
191 /* Initialize extif so we can get to the LEDs and external UART */
192 W_REG(osh
, &eir
->prog_config
, CF_EN
);
194 /* Set timing for the flash */
195 tmp
= CEIL(10, ns
) << FW_W3_SHIFT
; /* W3 = 10nS */
196 tmp
= tmp
| (CEIL(40, ns
) << FW_W1_SHIFT
); /* W1 = 40nS */
197 tmp
= tmp
| CEIL(120, ns
); /* W0 = 120nS */
198 W_REG(osh
, &eir
->prog_waitcount
, tmp
); /* 0x01020a0c for a 100Mhz clock */
200 /* Set programmable interface timing for external uart */
201 tmp
= CEIL(10, ns
) << FW_W3_SHIFT
; /* W3 = 10nS */
202 tmp
= tmp
| (CEIL(20, ns
) << FW_W2_SHIFT
); /* W2 = 20nS */
203 tmp
= tmp
| (CEIL(100, ns
) << FW_W1_SHIFT
); /* W1 = 100nS */
204 tmp
= tmp
| CEIL(120, ns
); /* W0 = 120nS */
205 W_REG(osh
, &eir
->prog_waitcount
, tmp
); /* 0x01020a0c for a 100Mhz clock */
206 } else if ((cc
= sb_setcore(sbh
, SB_CC
, 0))) {
207 /* Set timing for the flash */
208 tmp
= CEIL(10, ns
) << FW_W3_SHIFT
; /* W3 = 10nS */
209 tmp
|= CEIL(10, ns
) << FW_W1_SHIFT
; /* W1 = 10nS */
210 tmp
|= CEIL(120, ns
); /* W0 = 120nS */
211 if ((sb_corerev(sbh
) < 9) || (sb_chip(sbh
) == 0x5365))
212 W_REG(osh
, &cc
->flash_waitcount
, tmp
);
214 if ((sb_corerev(sbh
) < 9) ||
215 ((sb_chip(sbh
) == BCM5350_CHIP_ID
) && sb_chiprev(sbh
) == 0)
216 || (sb_chip(sbh
) == 0x5365)) {
217 W_REG(osh
, &cc
->pcmcia_memwait
, tmp
);
220 /* Save shared IRQ mapping base */
221 shirq_map_base
= shirqmap
;
224 /* Chip specific initialization */
225 switch (sb_chip(sbh
)) {
226 case BCM4710_CHIP_ID
:
227 /* Clear interrupt map */
228 for (irq
= 0; irq
<= 4; irq
++)
229 sb_clearirq(sbh
, irq
);
230 sb_setirq(sbh
, 0, SB_CODEC
, 0);
231 sb_setirq(sbh
, 0, SB_EXTIF
, 0);
232 sb_setirq(sbh
, 2, SB_ENET
, 1);
233 sb_setirq(sbh
, 3, SB_ILINE20
, 0);
234 sb_setirq(sbh
, 4, SB_PCI
, 0);
236 value
= nvram_get("et0phyaddr");
237 if (value
&& !strcmp(value
, "31")) {
238 /* Enable internal UART */
239 W_REG(osh
, &eir
->corecontrol
, CC_UE
);
240 /* Give USB its own interrupt */
241 sb_setirq(sbh
, 1, SB_USB
, 0);
243 /* Disable internal UART */
244 W_REG(osh
, &eir
->corecontrol
, 0);
245 /* Give Ethernet its own interrupt */
246 sb_setirq(sbh
, 1, SB_ENET
, 0);
247 sb_setirq(sbh
, 0, SB_USB
, 0);
250 case BCM5350_CHIP_ID
:
251 /* Clear interrupt map */
252 for (irq
= 0; irq
<= 4; irq
++)
253 sb_clearirq(sbh
, irq
);
254 sb_setirq(sbh
, 0, SB_CC
, 0);
255 sb_setirq(sbh
, 0, SB_MIPS33
, 0);
256 sb_setirq(sbh
, 1, SB_D11
, 0);
257 sb_setirq(sbh
, 2, SB_ENET
, 0);
258 sb_setirq(sbh
, 3, SB_PCI
, 0);
259 sb_setirq(sbh
, 4, SB_USB
, 0);
261 case BCM4785_CHIP_ID
:
262 /* Reassign PCI to irq 4 */
263 sb_setirq(sbh
, 4, SB_PCI
, 0);
269 BCMINITFN(sb_cpu_clock
)(sb_t
*sbh
)
275 uint32 pll_type
, rate
= 0;
277 /* get index of the current core */
278 idx
= sb_coreidx(sbh
);
279 pll_type
= PLL_TYPE1
;
281 /* switch to extif or chipc core */
282 if ((eir
= (extifregs_t
*) sb_setcore(sbh
, SB_EXTIF
, 0))) {
283 n
= R_REG(osh
, &eir
->clockcontrol_n
);
284 m
= R_REG(osh
, &eir
->clockcontrol_sb
);
285 } else if ((cc
= (chipcregs_t
*) sb_setcore(sbh
, SB_CC
, 0))) {
286 /* 5354 chip uses a non programmable PLL of frequency 240MHz */
287 if (sb_chip(sbh
) == BCM5354_CHIP_ID
) {
291 pll_type
= R_REG(osh
, &cc
->capabilities
) & CC_CAP_PLL_MASK
;
292 n
= R_REG(osh
, &cc
->clockcontrol_n
);
293 if ((pll_type
== PLL_TYPE2
) ||
294 (pll_type
== PLL_TYPE4
) ||
295 (pll_type
== PLL_TYPE6
) || (pll_type
== PLL_TYPE7
))
296 m
= R_REG(osh
, &cc
->clockcontrol_m3
);
297 else if (pll_type
== PLL_TYPE5
) {
300 } else if (pll_type
== PLL_TYPE3
) {
301 if (sb_chip(sbh
) == BCM5365_CHIP_ID
) {
305 /* 5350 uses m2 to control mips */
307 m
= R_REG(osh
, &cc
->clockcontrol_m2
);
309 m
= R_REG(osh
, &cc
->clockcontrol_sb
);
314 if (sb_chip(sbh
) == 0x5365)
317 rate
= sb_clock_rate(pll_type
, n
, m
);
319 if (pll_type
== PLL_TYPE6
)
320 rate
= SB2MIPS_T6(rate
);
323 /* switch back to previous core */
324 sb_setcoreidx(sbh
, idx
);
329 #define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4)
331 static void BCMINITFN(handler
) (void) {
332 __asm__(".set\tmips32\n\t" "ssnop\n\t" "ssnop\n\t"
333 /* Disable interrupts */
334 /* MTC0(C0_STATUS, 0, MFC0(C0_STATUS, 0) & ~(ALLINTS | STO_IE)); */
336 /* Just a Hack to not to use reg 'at' which was causing problems on 4704 A2 */
338 "and $15, $15, $14\n\t"
339 "mtc0 $15, $12\n\t" "eret\n\t" "nop\n\t" "nop\n\t"
343 /* The following MUST come right after handler() */
344 static void BCMINITFN(afterhandler
) (void) {
348 * Set the MIPS, backplane and PCI clocks as closely as possible.
350 * MIPS clocks synchronization function has been moved from PLL in chipcommon
351 * core rev. 15 to a DLL inside the MIPS core in 4785.
354 BCMINITFN(sb_mips_setclock
) (sb_t
* sbh
, uint32 mipsclock
, uint32 sbclock
,
356 extifregs_t
*eir
= NULL
;
357 chipcregs_t
*cc
= NULL
;
358 mipsregs_t
*mipsr
= NULL
;
359 volatile uint32
*clockcontrol_n
, *clockcontrol_sb
, *clockcontrol_pci
,
361 uint32 orig_n
, orig_sb
, orig_pci
, orig_m2
, orig_mips
, orig_ratio_parm
,
363 uint32 pll_type
, sync_mode
;
364 uint ic_size
, ic_lsize
;
367 /* PLL configuration: type 1 */
375 static n3m_table_t
BCMINITDATA(type1_table
)[] = {
376 /* 96.000 32.000 24.000 */
378 96000000, 0x0303, 0x04020011, 0x11030011, 0x11050011},
379 /* 100.000 33.333 25.000 */
381 100000000, 0x0009, 0x04020011, 0x11030011, 0x11050011},
382 /* 104.000 31.200 24.960 */
384 104000000, 0x0802, 0x04020011, 0x11050009, 0x11090009},
385 /* 108.000 32.400 24.923 */
387 108000000, 0x0403, 0x04020011, 0x11050009, 0x02000802},
388 /* 112.000 32.000 24.889 */
390 112000000, 0x0205, 0x04020011, 0x11030021, 0x02000403},
391 /* 115.200 32.000 24.000 */
393 115200000, 0x0303, 0x04020009, 0x11030011, 0x11050011},
394 /* 120.000 30.000 24.000 */
396 120000000, 0x0011, 0x04020011, 0x11050011, 0x11090011},
397 /* 124.800 31.200 24.960 */
399 124800000, 0x0802, 0x04020009, 0x11050009, 0x11090009},
400 /* 128.000 32.000 24.000 */
402 128000000, 0x0305, 0x04020011, 0x11050011, 0x02000305},
403 /* 132.000 33.000 24.750 */
405 132000000, 0x0603, 0x04020011, 0x11050011, 0x02000305},
406 /* 136.000 32.640 24.727 */
408 136000000, 0x0c02, 0x04020011, 0x11090009, 0x02000603},
409 /* 140.000 30.000 24.706 */
411 140000000, 0x0021, 0x04020011, 0x11050021, 0x02000c02},
412 /* 144.000 30.857 24.686 */
414 144000000, 0x0405, 0x04020011, 0x01020202, 0x11090021},
415 /* 150.857 33.000 24.000 */
417 150857142, 0x0605, 0x04020021, 0x02000305, 0x02000605},
418 /* 152.000 32.571 24.000 */
420 152000000, 0x0e02, 0x04020011, 0x11050021, 0x02000e02},
421 /* 156.000 31.200 24.960 */
423 156000000, 0x0802, 0x04020005, 0x11050009, 0x11090009},
424 /* 160.000 32.000 24.000 */
426 160000000, 0x0309, 0x04020011, 0x11090011, 0x02000309},
427 /* 163.200 32.640 24.727 */
429 163200000, 0x0c02, 0x04020009, 0x11090009, 0x02000603},
430 /* 168.000 32.000 24.889 */
432 168000000, 0x0205, 0x04020005, 0x11030021, 0x02000403},
433 /* 176.000 33.000 24.000 */
435 176000000, 0x0602, 0x04020003, 0x11050005, 0x02000602},};
437 /* PLL configuration: type 3 */
441 uint32 m2
; /* that is the clockcontrol_m2 */
443 static type3_table_t type3_table
[] = {
444 /* for 5350, mips clock is always double sb clock */
445 {150000000, 0x311, 0x4020005},
446 {200000000, 0x311, 0x4020003},
449 /* PLL configuration: type 2, 4, 7 */
464 static n4m_table_t
BCMINITDATA(type2_table
)[] = {
466 120000000, 60000000, 32000000, 0x0303, 0x01000200,
467 0x01000600, 0x01000200, 0x05000200, 11, 0x0aaa0555,
470 150000000, 75000000, 33333333, 0x0303, 0x01000100,
471 0x01000600, 0x01000100, 0x05000100, 11, 0x0aaa0555,
474 180000000, 80000000, 30000000, 0x0403, 0x01010000,
475 0x01020300, 0x01020600, 0x05000100, 8, 0x012a00a9,
478 180000000, 90000000, 30000000, 0x0403, 0x01000100,
479 0x01020300, 0x01000100, 0x05000100, 11, 0x0aaa0555,
482 200000000, 100000000, 33333333, 0x0303, 0x02010000,
483 0x02040001, 0x02010000, 0x06000001, 11, 0x0aaa0555,
486 211200000, 105600000, 30171428, 0x0902, 0x01000200,
487 0x01030400, 0x01000200, 0x05000200, 11, 0x0aaa0555,
490 220800000, 110400000, 31542857, 0x1500, 0x01000200,
491 0x01030400, 0x01000200, 0x05000200, 11, 0x0aaa0555,
494 230400000, 115200000, 32000000, 0x0604, 0x01000200,
495 0x01020600, 0x01000200, 0x05000200, 11, 0x0aaa0555,
498 234000000, 104000000, 31200000, 0x0b01, 0x01010000,
499 0x01010700, 0x01020600, 0x05000100, 8, 0x012a00a9,
502 240000000, 120000000, 33333333, 0x0803, 0x01000200,
503 0x01020600, 0x01000200, 0x05000200, 11, 0x0aaa0555,
506 252000000, 126000000, 33333333, 0x0504, 0x01000100,
507 0x01020500, 0x01000100, 0x05000100, 11, 0x0aaa0555,
510 264000000, 132000000, 33000000, 0x0903, 0x01000200,
511 0x01020700, 0x01000200, 0x05000200, 11, 0x0aaa0555,
514 270000000, 120000000, 30000000, 0x0703, 0x01010000,
515 0x01030400, 0x01020600, 0x05000100, 8, 0x012a00a9,
518 276000000, 122666666, 31542857, 0x1500, 0x01010000,
519 0x01030400, 0x01020600, 0x05000100, 8, 0x012a00a9,
522 280000000, 140000000, 31111111, 0x0503, 0x01000000,
523 0x01010600, 0x01000000, 0x05000000, 11, 0x0aaa0555,
526 288000000, 128000000, 32914285, 0x0604, 0x01010000,
527 0x01030400, 0x01020600, 0x05000100, 8, 0x012a00a9,
530 288000000, 144000000, 32000000, 0x0404, 0x01000000,
531 0x01010600, 0x01000000, 0x05000000, 11, 0x0aaa0555,
534 300000000, 133333333, 33333333, 0x0803, 0x01010000,
535 0x01020600, 0x01010100, 0x05000100, 8, 0x012a00a9,
538 300000000, 133333333, 37500000, 0x0803, 0x01010000,
539 0x01020500, 0x01010100, 0x05000100, 8, 0x012a00a9,
542 300000000, 133333333, 42857142, 0x0803, 0x01010000,
543 0x01020400, 0x01010100, 0x05000100, 8, 0x012a00a9,
546 300000000, 133333333, 50000000, 0x0803, 0x01010000,
547 0x01020300, 0x01010100, 0x05000100, 8, 0x012a00a9,
550 300000000, 133333333, 60000000, 0x0803, 0x01010000,
551 0x01020200, 0x01010100, 0x05000100, 8, 0x012a00a9,
554 300000000, 150000000, 33333333, 0x0803, 0x01000100,
555 0x01020600, 0x01010100, 0x05000100, 11, 0x0aaa0555,
558 300000000, 150000000, 37500000, 0x0803, 0x01000100,
559 0x01020500, 0x01010100, 0x05000100, 11, 0x0aaa0555,
562 300000000, 150000000, 42857142, 0x0803, 0x01000100,
563 0x01020400, 0x01010100, 0x05000100, 11, 0x0aaa0555,
566 300000000, 150000000, 50000000, 0x0803, 0x01000100,
567 0x01020300, 0x01010100, 0x05000100, 11, 0x0aaa0555,
570 300000000, 150000000, 60000000, 0x0803, 0x01000100,
571 0x01020200, 0x01010100, 0x05000100, 11, 0x0aaa0555,
574 330000000, 132000000, 33000000, 0x0903, 0x01000200,
575 0x00020200, 0x01010100, 0x05000100, 0, 0,
576 10 /* ratio 4/10 */ , 0x02520129},
578 330000000, 146666666, 33000000, 0x0903, 0x01010000,
579 0x00020200, 0x01010100, 0x05000100, 0, 0,
580 9 /* ratio 4/9 */ , 0x012a00a9},
582 330000000, 165000000, 33000000, 0x0903, 0x01000100,
583 0x00020200, 0x01010100, 0x05000100, 0, 0,
584 8 /* ratio 4/8 */ , 0x00aa0055},
586 330000000, 165000000, 41250000, 0x0903, 0x01000100,
587 0x00020100, 0x01010100, 0x05000100, 0, 0,
588 8 /* ratio 4/8 */ , 0x00aa0055},
590 330000000, 165000000, 55000000, 0x0903, 0x01000100,
591 0x00020000, 0x01010100, 0x05000100, 0, 0,
592 8 /* ratio 4/8 */ , 0x00aa0055},
594 360000000, 120000000, 32000000, 0x0a03, 0x01000300,
595 0x00010201, 0x01010200, 0x05000100, 0, 0,
596 12 /* ratio 4/12 */ , 0x04920492},
598 360000000, 144000000, 32000000, 0x0a03, 0x01000200,
599 0x00010201, 0x01010200, 0x05000100, 0, 0,
600 10 /* ratio 4/10 */ , 0x02520129},
602 360000000, 160000000, 32000000, 0x0a03, 0x01010000,
603 0x00010201, 0x01010200, 0x05000100, 0, 0,
604 9 /* ratio 4/9 */ , 0x012a00a9},
606 360000000, 180000000, 32000000, 0x0a03, 0x01000100,
607 0x00010201, 0x01010200, 0x05000100, 0, 0,
608 8 /* ratio 4/8 */ , 0x00aa0055},
610 360000000, 180000000, 40000000, 0x0a03, 0x01000100,
611 0x00010101, 0x01010200, 0x05000100, 0, 0,
612 8 /* ratio 4/8 */ , 0x00aa0055},
614 360000000, 180000000, 53333333, 0x0a03, 0x01000100,
615 0x00010001, 0x01010200, 0x05000100, 0, 0,
616 8 /* ratio 4/8 */ , 0x00aa0055},
618 390000000, 130000000, 32500000, 0x0b03, 0x01010100,
619 0x00020101, 0x01020100, 0x05000100, 0, 0,
620 12 /* ratio 4/12 */ , 0x04920492},
622 390000000, 156000000, 32500000, 0x0b03, 0x01000200,
623 0x00020101, 0x01020100, 0x05000100, 0, 0,
624 10 /* ratio 4/10 */ , 0x02520129},
626 390000000, 173000000, 32500000, 0x0b03, 0x01010000,
627 0x00020101, 0x01020100, 0x05000100, 0, 0,
628 9 /* ratio 4/9 */ , 0x012a00a9},
630 390000000, 195000000, 32500000, 0x0b03, 0x01000100,
631 0x00020101, 0x01020100, 0x05000100, 0, 0,
632 8 /* ratio 4/8 */ , 0x00aa0055},
634 static n4m_table_t
BCMINITDATA(type4_table
)[] = {
636 120000000, 60000000, 0, 0x0009, 0x11020009, 0x01030203,
637 0x11020009, 0x04000009, 11, 0x0aaa0555}, {
638 150000000, 75000000, 0, 0x0009, 0x11050002, 0x01030203,
639 0x11050002, 0x04000005, 11, 0x0aaa0555}, {
640 192000000, 96000000, 0, 0x0702, 0x04000011, 0x11030011,
641 0x04000011, 0x04000003, 11, 0x0aaa0555}, {
642 198000000, 99000000, 0, 0x0603, 0x11020005, 0x11030011,
643 0x11020005, 0x04000005, 11, 0x0aaa0555}, {
644 200000000, 100000000, 0, 0x0009, 0x04020011, 0x11030011,
645 0x04020011, 0x04020003, 11, 0x0aaa0555}, {
646 204000000, 102000000, 0, 0x0c02, 0x11020005, 0x01030303,
647 0x11020005, 0x04000005, 11, 0x0aaa0555}, {
648 208000000, 104000000, 0, 0x0802, 0x11030002, 0x11090005,
649 0x11030002, 0x04000003, 11, 0x0aaa0555}, {
650 210000000, 105000000, 0, 0x0209, 0x11020005, 0x01030303,
651 0x11020005, 0x04000005, 11, 0x0aaa0555}, {
652 216000000, 108000000, 0, 0x0111, 0x11020005, 0x01030303,
653 0x11020005, 0x04000005, 11, 0x0aaa0555}, {
654 224000000, 112000000, 0, 0x0205, 0x11030002, 0x02002103,
655 0x11030002, 0x04000003, 11, 0x0aaa0555}, {
656 228000000, 101333333, 0, 0x0e02, 0x11030003, 0x11210005,
657 0x01030305, 0x04000005, 8, 0x012a00a9}, {
658 228000000, 114000000, 0, 0x0e02, 0x11020005, 0x11210005,
659 0x11020005, 0x04000005, 11, 0x0aaa0555}, {
660 240000000, 102857143, 0, 0x0109, 0x04000021, 0x01050203,
661 0x11030021, 0x04000003, 13, 0x254a14a9}, {
662 240000000, 120000000, 0, 0x0109, 0x11030002, 0x01050203,
663 0x11030002, 0x04000003, 11, 0x0aaa0555}, {
664 252000000, 100800000, 0, 0x0203, 0x04000009, 0x11050005,
665 0x02000209, 0x04000002, 9, 0x02520129}, {
666 252000000, 126000000, 0, 0x0203, 0x04000005, 0x11050005,
667 0x04000005, 0x04000002, 11, 0x0aaa0555}, {
668 264000000, 132000000, 0, 0x0602, 0x04000005, 0x11050005,
669 0x04000005, 0x04000002, 11, 0x0aaa0555}, {
670 272000000, 116571428, 0, 0x0c02, 0x04000021, 0x02000909,
671 0x02000221, 0x04000003, 13, 0x254a14a9}, {
672 280000000, 120000000, 0, 0x0209, 0x04000021, 0x01030303,
673 0x02000221, 0x04000003, 13, 0x254a14a9}, {
674 288000000, 123428571, 0, 0x0111, 0x04000021, 0x01030303,
675 0x02000221, 0x04000003, 13, 0x254a14a9}, {
676 300000000, 120000000, 0, 0x0009, 0x04000009, 0x01030203,
677 0x02000902, 0x04000002, 9, 0x02520129}, {
678 300000000, 150000000, 0, 0x0009, 0x04000005, 0x01030203,
679 0x04000005, 0x04000002, 11, 0x0aaa0555}
681 static n4m_table_t
BCMINITDATA(type7_table
)[] = {
683 183333333, 91666666, 0, 0x0605, 0x04000011, 0x11030011,
684 0x04000011, 0x04000003, 11, 0x0aaa0555}, {
685 187500000, 93750000, 0, 0x0a03, 0x04000011, 0x11030011,
686 0x04000011, 0x04000003, 11, 0x0aaa0555}, {
687 196875000, 98437500, 0, 0x1003, 0x11020005, 0x11050011,
688 0x11020005, 0x04000005, 11, 0x0aaa0555}, {
689 200000000, 100000000, 0, 0x0311, 0x04000011, 0x11030011,
690 0x04000009, 0x04000003, 11, 0x0aaa0555}, {
691 200000000, 100000000, 0, 0x0311, 0x04020011, 0x11030011,
692 0x04020011, 0x04020003, 11, 0x0aaa0555}, {
693 206250000, 103125000, 0, 0x1103, 0x11020005, 0x11050011,
694 0x11020005, 0x04000005, 11, 0x0aaa0555}, {
695 212500000, 106250000, 0, 0x0c05, 0x11020005, 0x01030303,
696 0x11020005, 0x04000005, 11, 0x0aaa0555}, {
697 215625000, 107812500, 0, 0x1203, 0x11090009, 0x11050005,
698 0x11020005, 0x04000005, 11, 0x0aaa0555}, {
699 216666666, 108333333, 0, 0x0805, 0x11020003, 0x11030011,
700 0x11020003, 0x04000003, 11, 0x0aaa0555}, {
701 225000000, 112500000, 0, 0x0d03, 0x11020003, 0x11030011,
702 0x11020003, 0x04000003, 11, 0x0aaa0555}, {
703 233333333, 116666666, 0, 0x0905, 0x11020003, 0x11030011,
704 0x11020003, 0x04000003, 11, 0x0aaa0555}, {
705 237500000, 118750000, 0, 0x0e05, 0x11020005, 0x11210005,
706 0x11020005, 0x04000005, 11, 0x0aaa0555}, {
707 240000000, 120000000, 0, 0x0b11, 0x11020009, 0x11210009,
708 0x11020009, 0x04000009, 11, 0x0aaa0555}, {
709 250000000, 125000000, 0, 0x0f03, 0x11020003, 0x11210003,
710 0x11020003, 0x04000003, 11, 0x0aaa0555}
713 ulong start
, end
, dst
;
716 volatile uint32
*dll_ctrl
= (volatile uint32
*)0xff400008;
717 volatile uint32
*dll_r1
= (volatile uint32
*)0xff400010;
718 volatile uint32
*dll_r2
= (volatile uint32
*)0xff400018;
720 /* get index of the current core */
721 idx
= sb_coreidx(sbh
);
722 clockcontrol_m2
= NULL
;
724 /* switch to chipc core */
725 /* switch to extif or chipc core */
726 if ((eir
= (extifregs_t
*) sb_setcore(sbh
, SB_EXTIF
, 0))) {
727 pll_type
= PLL_TYPE1
;
728 clockcontrol_n
= &eir
->clockcontrol_n
;
729 clockcontrol_sb
= &eir
->clockcontrol_sb
;
730 clockcontrol_pci
= &eir
->clockcontrol_pci
;
731 clockcontrol_m2
= &cc
->clockcontrol_m2
;
732 } else if ((cc
= (chipcregs_t
*) sb_setcore(sbh
, SB_CC
, 0))) {
733 /* 5354 chipcommon pll setting can't be changed.
734 * The PMU on power up comes up with the default clk frequency
737 if (sb_chip(sbh
) == BCM5354_CHIP_ID
) {
741 pll_type
= R_REG(osh
, &cc
->capabilities
) & CC_CAP_PLL_MASK
;
742 if (pll_type
== PLL_TYPE6
) {
743 clockcontrol_n
= NULL
;
744 clockcontrol_sb
= NULL
;
745 clockcontrol_pci
= NULL
;
747 clockcontrol_n
= &cc
->clockcontrol_n
;
748 clockcontrol_sb
= &cc
->clockcontrol_sb
;
749 clockcontrol_pci
= &cc
->clockcontrol_pci
;
750 clockcontrol_m2
= &cc
->clockcontrol_m2
;
755 if (pll_type
== PLL_TYPE6
) {
756 /* Silence compilers */
757 orig_n
= orig_sb
= orig_pci
= 0;
759 /* Store the current clock register values */
760 orig_n
= R_REG(osh
, clockcontrol_n
);
761 orig_sb
= R_REG(osh
, clockcontrol_sb
);
762 orig_pci
= R_REG(osh
, clockcontrol_pci
);
765 if (pll_type
== PLL_TYPE1
) {
766 /* Keep the current PCI clock if not specified */
769 sb_clock_rate(pll_type
, R_REG(osh
, clockcontrol_n
),
770 R_REG(osh
, clockcontrol_pci
));
771 pciclock
= (pciclock
<= 25000000) ? 25000000 : 33000000;
774 /* Search for the closest MIPS clock less than or equal to a preferred value */
775 for (i
= 0; i
< ARRAYSIZE(type1_table
); i
++) {
776 ASSERT(type1_table
[i
].mipsclock
==
777 sb_clock_rate(pll_type
, type1_table
[i
].n
,
779 if (type1_table
[i
].mipsclock
> mipsclock
)
789 ASSERT(type1_table
[i
].mipsclock
<= mipsclock
);
792 if ((orig_n
== type1_table
[i
].n
) &&
793 (orig_sb
== type1_table
[i
].sb
) &&
794 (orig_pci
== type1_table
[i
].pci33
))
797 /* Set the PLL controls */
798 W_REG(osh
, clockcontrol_n
, type1_table
[i
].n
);
799 W_REG(osh
, clockcontrol_sb
, type1_table
[i
].sb
);
800 if (pciclock
== 25000000)
801 W_REG(osh
, clockcontrol_pci
, type1_table
[i
].pci25
);
803 W_REG(osh
, clockcontrol_pci
, type1_table
[i
].pci33
);
808 } else if (pll_type
== PLL_TYPE3
) {
810 if (sb_chip(sbh
) != BCM5365_CHIP_ID
) {
812 * Search for the closest MIPS clock less than or equal to
815 for (i
= 0; i
< ARRAYSIZE(type3_table
); i
++) {
816 if (type3_table
[i
].mipsclock
> mipsclock
)
826 ASSERT(type3_table
[i
].mipsclock
<= mipsclock
);
829 orig_m2
= R_REG(osh
, &cc
->clockcontrol_m2
);
830 if ((orig_n
== type3_table
[i
].n
)
831 && (orig_m2
== type3_table
[i
].m2
)) {
835 /* Set the PLL controls */
836 W_REG(osh
, clockcontrol_n
, type3_table
[i
].n
);
837 W_REG(osh
, clockcontrol_m2
, type3_table
[i
].m2
);
843 } else if ((pll_type
== PLL_TYPE2
) ||
844 (pll_type
== PLL_TYPE4
) ||
845 (pll_type
== PLL_TYPE6
) || (pll_type
== PLL_TYPE7
)) {
846 n4m_table_t
*table
= NULL
, *te
;
851 orig_mips
= R_REG(osh
, &cc
->clockcontrol_m3
);
859 if (mipsclock
<= SB2MIPS_T6(CC_T6_M1
))
860 new_mips
= CC_T6_MMASK
;
862 if (orig_mips
== new_mips
)
865 W_REG(osh
, &cc
->clockcontrol_m3
, new_mips
);
870 tabsz
= ARRAYSIZE(type2_table
);
874 tabsz
= ARRAYSIZE(type4_table
);
878 tabsz
= ARRAYSIZE(type7_table
);
881 ASSERT("No table for plltype" == NULL
);
885 /* Store the current clock register values */
886 orig_m2
= R_REG(osh
, &cc
->clockcontrol_m2
);
890 /* Look up current ratio */
891 for (i
= 0; i
< tabsz
; i
++) {
892 if ((orig_n
== table
[i
].n
) &&
893 (orig_sb
== table
[i
].sb
) &&
894 (orig_pci
== table
[i
].pci33
) &&
895 (orig_m2
== table
[i
].m2
)
896 && (orig_mips
== table
[i
].m3
)) {
897 orig_ratio_parm
= table
[i
].ratio_parm
;
898 orig_ratio_cfg
= table
[i
].ratio_cfg
;
903 /* Search for the closest MIPS clock greater or equal to a preferred value */
904 for (i
= 0; i
< tabsz
; i
++) {
905 ASSERT(table
[i
].mipsclock
==
906 sb_clock_rate(pll_type
, table
[i
].n
,
908 if ((mipsclock
<= table
[i
].mipsclock
)
909 && ((sbclock
== 0) || (sbclock
<= table
[i
].sbclock
))
911 || (pciclock
<= table
[i
].pciclock
)))
923 if ((orig_n
== te
->n
) &&
924 (orig_sb
== te
->sb
) &&
925 (orig_pci
== te
->pci33
) &&
926 (orig_m2
== te
->m2
) && (orig_mips
== te
->m3
))
929 /* Set the PLL controls */
930 W_REG(osh
, clockcontrol_n
, te
->n
);
931 W_REG(osh
, clockcontrol_sb
, te
->sb
);
932 W_REG(osh
, clockcontrol_pci
, te
->pci33
);
933 W_REG(osh
, &cc
->clockcontrol_m2
, te
->m2
);
934 W_REG(osh
, &cc
->clockcontrol_m3
, te
->m3
);
936 /* Set the chipcontrol bit to change mipsref to the backplane divider if needed */
937 if ((pll_type
== PLL_TYPE7
) && (te
->sb
!= te
->m2
) &&
938 (sb_clock_rate(pll_type
, te
->n
, te
->m2
) == 120000000))
939 W_REG(osh
, &cc
->chipcontrol
,
940 R_REG(osh
, &cc
->chipcontrol
) | 0x100);
942 /* No ratio change */
943 if (sb_chip(sbh
) != BCM4785_CHIP_ID
) {
944 if (orig_ratio_parm
== te
->ratio_parm
)
948 /* Preload the code into the cache */
949 icache_probe(MFC0(C0_CONFIG
, 1), &ic_size
, &ic_lsize
);
950 if (sb_chip(sbh
) == BCM4785_CHIP_ID
) {
951 start
= ((ulong
) && start_fill_4785
) & ~(ic_lsize
- 1);
953 && end_fill_4785
+ (ic_lsize
- 1)) & ~(ic_lsize
-
956 start
= ((ulong
) && start_fill
) & ~(ic_lsize
- 1);
958 && end_fill
+ (ic_lsize
- 1)) & ~(ic_lsize
- 1);
960 while (start
< end
) {
961 cache_op(start
, Fill_I
);
965 /* 4785 clock freq change procedures */
966 if (sb_chip(sbh
) == BCM4785_CHIP_ID
) {
968 /* Switch to async */
969 MTC0(C0_BROADCOM
, 4, (1 << 22));
971 /* Set clock ratio in MIPS */
972 *dll_r1
= (*dll_r1
& 0xfffffff0) | (te
->d11_r1
- 1);
973 *dll_r2
= te
->d11_r2
;
975 /* Enable new settings in MIPS */
976 *dll_r1
= *dll_r1
| 0xc0000000;
980 MFC0(C0_BROADCOM
, 2) | (1 << 3) | 1);
982 /* Fake soft reset (clock cfg registers not reset) */
983 MTC0(C0_BROADCOM
, 5, MFC0(C0_BROADCOM
, 5) | (1 << 2));
985 /* Clear active cfg */
986 MTC0(C0_BROADCOM
, 2, MFC0(C0_BROADCOM
, 2) & ~(1 << 3));
988 /* set watchdog timer */
989 W_REG(osh
, &cc
->watchdog
, 20);
990 (void)R_REG(osh
, &cc
->chipid
);
992 /* wait for timer interrupt */
993 __asm__
__volatile__(".set\tmips3\n\t"
994 "sync\n\t" "wait\n\t"
999 /* Generic clock freq change procedures */
1001 /* Copy the handler */
1002 start
= (ulong
) & handler
;
1003 end
= (ulong
) & afterhandler
;
1004 dst
= KSEG1ADDR(0x180);
1005 for (i
= 0; i
< (end
- start
); i
+= 4)
1006 *((ulong
*) (dst
+ i
)) =
1007 *((ulong
*) (start
+ i
));
1009 /* Preload the handler into the cache one line at a time */
1010 for (i
= 0; i
< (end
- start
); i
+= ic_lsize
)
1011 cache_op(dst
+ i
, Fill_I
);
1014 MTC0(C0_STATUS
, 0, MFC0(C0_STATUS
, 0) & ~ST0_BEV
);
1016 /* Enable interrupts */
1018 MFC0(C0_STATUS
, 0) | (ALLINTS
| ST0_IE
));
1020 /* Enable MIPS timer interrupt */
1021 if (!(mipsr
= sb_setcore(sbh
, SB_MIPS
, 0)) &&
1022 !(mipsr
= sb_setcore(sbh
, SB_MIPS33
, 0)))
1024 W_REG(osh
, &mipsr
->intmask
, 1);
1027 /* step 1, set clock ratios */
1028 MTC0(C0_BROADCOM
, 3, te
->ratio_parm
);
1029 MTC0(C0_BROADCOM
, 1, te
->ratio_cfg
);
1031 /* step 2: program timer intr */
1032 W_REG(osh
, &mipsr
->timer
, 100);
1033 (void)R_REG(osh
, &mipsr
->timer
);
1035 /* step 3, switch to async */
1036 sync_mode
= MFC0(C0_BROADCOM
, 4);
1037 MTC0(C0_BROADCOM
, 4, 1 << 22);
1039 /* step 4, set cfg active */
1040 MTC0(C0_BROADCOM
, 2, (1 << 3) | 1);
1043 __asm__
__volatile__(".set\tmips3\n\t" "wait\n\t"
1046 /* step 7, clear cfg active */
1047 MTC0(C0_BROADCOM
, 2, 0);
1049 /* Additional Step: set back to orig sync mode */
1050 MTC0(C0_BROADCOM
, 4, sync_mode
);
1052 /* step 8, fake soft reset */
1053 MTC0(C0_BROADCOM
, 5, MFC0(C0_BROADCOM
, 5) | (1 << 2));
1056 /* set watchdog timer */
1057 W_REG(osh
, &cc
->watchdog
, 20);
1058 (void)R_REG(osh
, &cc
->chipid
);
1060 /* wait for timer interrupt */
1061 __asm__
__volatile__(".set\tmips3\n\t"
1062 "sync\n\t" "wait\n\t"
1069 /* Enable 4785 DLL */
1070 if (sb_chip(sbh
) == BCM4785_CHIP_ID
) {
1073 /* set mask to 1e, enable DLL (bit 0) */
1074 *dll_ctrl
|= 0x0041e021;
1076 /* enable aggressive hardware mode */
1077 *dll_ctrl
|= 0x00000080;
1079 /* wait for lock flag to clear */
1080 while ((*dll_ctrl
& 0x2) == 0) ;
1082 /* clear sticky flags (clear on write 1) */
1086 /* set mask to 5b'10001 */
1087 *dll_ctrl
= (*dll_ctrl
& 0xfffc1fff) | 0x00022000;
1089 /* enable sync mode */
1090 MTC0(C0_BROADCOM
, 4, MFC0(C0_BROADCOM
, 4) & 0xfe3fffff);
1091 (void)MFC0(C0_BROADCOM
, 4);
1094 /* switch back to previous core */
1095 sb_setcoreidx(sbh
, idx
);
1100 void BCMINITFN(enable_pfc
) (uint32 mode
) {
1102 uint ic_size
, ic_lsize
;
1104 /* If auto then choose the correct mode for this
1105 * platform, currently we only ever select one mode
1107 if (mode
== PFC_AUTO
)
1110 icache_probe(MFC0(C0_CONFIG
, 1), &ic_size
, &ic_lsize
);
1112 /* enable prefetch cache if available */
1113 if (MFC0(C0_BROADCOM
, 0) & BRCM_PFC_AVAIL
) {
1114 start
= ((ulong
) && setpfc_start
) & ~(ic_lsize
- 1);
1116 && setpfc_end
+ (ic_lsize
- 1)) & ~(ic_lsize
- 1);
1118 /* Preload setpfc code into the cache one line at a time */
1119 while (start
< end
) {
1120 cache_op(start
, Fill_I
);
1124 /* Now set the pfc */
1127 *(volatile uint32
*)PFC_CR1
= 0xffff0000;
1130 *(volatile uint32
*)PFC_CR0
= mode
;
1132 /* Compiler foder */
1137 /* returns the ncdl value to be programmed into sdram_ncdl for calibration */
1138 uint32
BCMINITFN(sb_memc_get_ncdl
) (sb_t
* sbh
) {
1142 uint32 config
, rd
, wr
, misc
, dqsg
, cd
, sm
, sd
;
1147 idx
= sb_coreidx(sbh
);
1149 memc
= (sbmemcregs_t
*) sb_setcore(sbh
, SB_MEMC
, 0);
1153 rev
= sb_corerev(sbh
);
1155 config
= R_REG(osh
, &memc
->config
);
1156 wr
= R_REG(osh
, &memc
->wrncdlcor
);
1157 rd
= R_REG(osh
, &memc
->rdncdlcor
);
1158 misc
= R_REG(osh
, &memc
->miscdlyctl
);
1159 dqsg
= R_REG(osh
, &memc
->dqsgatencdl
);
1161 rd
&= MEMC_RDNCDLCOR_RD_MASK
;
1162 wr
&= MEMC_WRNCDLCOR_WR_MASK
;
1163 dqsg
&= MEMC_DQSGATENCDL_G_MASK
;
1165 if (config
& MEMC_CONFIG_DDR
) {
1166 ret
= (wr
<< 16) | (rd
<< 8) | dqsg
;
1172 MEMC_CD_THRESHOLD
) ? rd
: (wr
+
1174 sm
= (misc
& MEMC_MISC_SM_MASK
) >> MEMC_MISC_SM_SHIFT
;
1175 sd
= (misc
& MEMC_MISC_SD_MASK
) >> MEMC_MISC_SD_SHIFT
;
1176 ret
= (sm
<< 16) | (sd
<< 8) | cd
;
1180 /* switch back to previous core */
1181 sb_setcoreidx(sbh
, idx
);
1186 void hnd_cpu_reset(sb_t
* sbh
)
1188 if (sb_chip(sbh
) == BCM4785_CHIP_ID
)
1189 MTC0(C0_BROADCOM
, 4, (1 << 22));
1190 sb_watchdog(sbh
, 1);
1191 if (sb_chip(sbh
) == BCM4785_CHIP_ID
) {
1192 __asm__
__volatile__(".set\tmips3\n\t"
1193 "sync\n\t" "wait\n\t" ".set\tmips0");
1198 #if defined(BCMPERFSTATS)
1200 * CP0 Register 25 supports 4 semi-independent 32bit performance counters.
1201 * $25 select 0, 1, 2, and 3 are the counters. The counters *decrement* (who thought this one up?)
1202 * $25 select 4 and 5 each contain 2-16bit control fields, one for each of the 4 counters
1203 * $25 select 6 is the global perf control register.
1205 /* enable and start instruction counting */
1207 void hndmips_perf_cyclecount_enable(void)
1209 MTC0(C0_PERFORMANCE
, 6, 0x80000200); /* global enable perf counters */
1210 MTC0(C0_PERFORMANCE
, 4, 0x8048 | MFC0(C0_PERFORMANCE
, 4)); /* enable cycles counting for counter 0 */
1211 MTC0(C0_PERFORMANCE
, 0, 0); /* zero counter zero */
1214 void hndmips_perf_instrcount_enable(void)
1216 MTC0(C0_PERFORMANCE
, 6, 0x80000200); /* global enable perf counters */
1217 MTC0(C0_PERFORMANCE
, 4, 0x8044 | MFC0(C0_PERFORMANCE
, 4)); /* enable instructions counting for counter 0 */
1218 MTC0(C0_PERFORMANCE
, 0, 0); /* zero counter zero */
1221 /* enable and start I$ hit and I$ miss counting */
1222 void hndmips_perf_icachecount_enable(void)
1224 MTC0(C0_PERFORMANCE
, 6, 0x80000218); /* enable I$ counting */
1225 MTC0(C0_PERFORMANCE
, 4, 0x80148018); /* count I$ hits in cntr 0 and misses in cntr 1 */
1226 MTC0(C0_PERFORMANCE
, 0, 0); /* zero counter 0 - # I$ hits */
1227 MTC0(C0_PERFORMANCE
, 1, 0); /* zero counter 1 - # I$ misses */
1230 /* enable and start D$ hit and I$ miss counting */
1231 void hndmips_perf_dcachecount_enable(void)
1233 MTC0(C0_PERFORMANCE
, 6, 0x80000211); /* enable D$ counting */
1234 MTC0(C0_PERFORMANCE
, 4, 0x80248028); /* count D$ hits in cntr 0 and misses in cntr 1 */
1235 MTC0(C0_PERFORMANCE
, 0, 0); /* zero counter 0 - # D$ hits */
1236 MTC0(C0_PERFORMANCE
, 1, 0); /* zero counter 1 - # D$ misses */
1239 void hndmips_perf_icache_miss_enable()
1241 MTC0(C0_PERFORMANCE
, 4, 0x80140000 | MFC0(C0_PERFORMANCE
, 4)); /* enable cache misses counting for counter 1 */
1242 MTC0(C0_PERFORMANCE
, 1, 0); /* zero counter one */
1245 void hndmips_perf_icache_hit_enable()
1247 MTC0(C0_PERFORMANCE
, 5, 0x8018 | MFC0(C0_PERFORMANCE
, 5));
1248 /* enable cache hits counting for counter 2 */
1249 MTC0(C0_PERFORMANCE
, 2, 0); /* zero counter 2 */
1252 uint32
hndmips_perf_read_instrcount()
1254 return -(long)(MFC0(C0_PERFORMANCE
, 0));
1257 uint32
hndmips_perf_read_cache_miss()
1259 return -(long)(MFC0(C0_PERFORMANCE
, 1));
1262 uint32
hndmips_perf_read_cache_hit()
1264 return -(long)(MFC0(C0_PERFORMANCE
, 2));