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.
25 #include <sbhndmips.h>
29 /* sbipsflag register format, indexed by irq. */
30 static const uint32 sbips_int_mask
[] = {
38 static const uint32 sbips_int_shift
[] = {
47 * Map SB cores sharing the MIPS hardware IRQ0 to virtual dedicated OS IRQs.
48 * Per-port BSP code is required to provide necessary translations between
49 * the shared MIPS IRQ and the virtual OS IRQs based on SB core flag.
51 * See sb_irq() for the mapping.
53 static uint shirq_map_base
= 0;
55 /* Returns the SB interrupt flag of the current core. */
56 static uint32
sb_getflag(sb_t
* sbh
)
63 regs
= sb_coreregs(sbh
);
64 sb
= (sbconfig_t
*) ((ulong
) regs
+ SBCONFIGOFF
);
66 return (R_REG(osh
, &sb
->sbtpsflag
) & SBTPS_NUM0_MASK
);
70 * Returns the MIPS IRQ assignment of the current core. If unassigned,
73 uint
sb_irq(sb_t
* sbh
)
79 uint32 flag
, sbipsflag
;
83 flag
= sb_getflag(sbh
);
85 idx
= sb_coreidx(sbh
);
87 if ((regs
= sb_setcore(sbh
, SB_MIPS
, 0)) ||
88 (regs
= sb_setcore(sbh
, SB_MIPS33
, 0))) {
89 sb
= (sbconfig_t
*) ((ulong
) regs
+ SBCONFIGOFF
);
91 /* sbipsflag specifies which core is routed to interrupts 1 to 4 */
92 sbipsflag
= R_REG(osh
, &sb
->sbipsflag
);
93 for (irq
= 1; irq
<= 4; irq
++) {
94 if (((sbipsflag
& sbips_int_mask
[irq
]) >>
95 sbips_int_shift
[irq
]) == flag
)
102 sb_setcoreidx(sbh
, idx
);
107 /* Clears the specified MIPS IRQ. */
108 static void BCMINITFN(sb_clearirq
) (sb_t
* sbh
, uint irq
) {
115 if (!(regs
= sb_setcore(sbh
, SB_MIPS
, 0)) &&
116 !(regs
= sb_setcore(sbh
, SB_MIPS33
, 0)))
118 sb
= (sbconfig_t
*) ((ulong
) regs
+ SBCONFIGOFF
);
121 W_REG(osh
, &sb
->sbintvec
, 0);
123 OR_REG(osh
, &sb
->sbipsflag
, sbips_int_mask
[irq
]);
127 * Assigns the specified MIPS IRQ to the specified core. Shared MIPS
128 * IRQ 0 may be assigned more than once.
130 * The old assignment to the specified core is removed first.
133 BCMINITFN(sb_setirq
) (sb_t
* sbh
, uint irq
, uint coreid
, uint coreunit
) {
142 regs
= sb_setcore(sbh
, coreid
, coreunit
);
144 flag
= sb_getflag(sbh
);
145 oldirq
= sb_irq(sbh
);
147 sb_clearirq(sbh
, oldirq
);
149 if (!(regs
= sb_setcore(sbh
, SB_MIPS
, 0)) &&
150 !(regs
= sb_setcore(sbh
, SB_MIPS33
, 0)))
152 sb
= (sbconfig_t
*) ((ulong
) regs
+ SBCONFIGOFF
);
155 AND_REG(osh
, &sb
->sbintvec
, ~(1 << flag
));
158 OR_REG(osh
, &sb
->sbintvec
, 1 << flag
);
160 flag
<<= sbips_int_shift
[irq
];
161 ASSERT(!(flag
& ~sbips_int_mask
[irq
]));
162 flag
|= R_REG(osh
, &sb
->sbipsflag
) & ~sbips_int_mask
[irq
];
163 W_REG(osh
, &sb
->sbipsflag
, flag
);
168 * Initializes clocks and interrupts. SB and NVRAM access must be
169 * initialized prior to calling.
171 * 'shirqmap' enables virtual dedicated OS IRQ mapping if non-zero.
173 void BCMINITFN(sb_mips_init
) (sb_t
* sbh
, uint shirqmap
) {
183 /* Figure out current SB clock speed */
184 if ((hz
= sb_clock(sbh
)) == 0)
186 ns
= 1000000000 / hz
;
188 /* Setup external interface timing */
189 if ((eir
= sb_setcore(sbh
, SB_EXTIF
, 0))) {
190 /* Initialize extif so we can get to the LEDs and external UART */
191 W_REG(osh
, &eir
->prog_config
, CF_EN
);
193 /* Set timing for the flash */
194 tmp
= CEIL(10, ns
) << FW_W3_SHIFT
; /* W3 = 10nS */
195 tmp
= tmp
| (CEIL(40, ns
) << FW_W1_SHIFT
); /* W1 = 40nS */
196 tmp
= tmp
| CEIL(120, ns
); /* W0 = 120nS */
197 W_REG(osh
, &eir
->prog_waitcount
, tmp
); /* 0x01020a0c for a 100Mhz clock */
199 /* Set programmable interface timing for external uart */
200 tmp
= CEIL(10, ns
) << FW_W3_SHIFT
; /* W3 = 10nS */
201 tmp
= tmp
| (CEIL(20, ns
) << FW_W2_SHIFT
); /* W2 = 20nS */
202 tmp
= tmp
| (CEIL(100, ns
) << FW_W1_SHIFT
); /* W1 = 100nS */
203 tmp
= tmp
| CEIL(120, ns
); /* W0 = 120nS */
204 W_REG(osh
, &eir
->prog_waitcount
, tmp
); /* 0x01020a0c for a 100Mhz clock */
205 } else if ((cc
= sb_setcore(sbh
, SB_CC
, 0))) {
206 /* Set timing for the flash */
207 tmp
= CEIL(10, ns
) << FW_W3_SHIFT
; /* W3 = 10nS */
208 tmp
|= CEIL(10, ns
) << FW_W1_SHIFT
; /* W1 = 10nS */
209 tmp
|= CEIL(120, ns
); /* W0 = 120nS */
210 if ((sb_corerev(sbh
) < 9) || (sb_chip(sbh
) == 0x5365))
211 W_REG(osh
, &cc
->flash_waitcount
, tmp
);
213 if ((sb_corerev(sbh
) < 9) ||
214 ((sb_chip(sbh
) == BCM5350_CHIP_ID
) && sb_chiprev(sbh
) == 0)
215 || (sb_chip(sbh
) == 0x5365)) {
216 W_REG(osh
, &cc
->pcmcia_memwait
, tmp
);
219 /* Save shared IRQ mapping base */
220 shirq_map_base
= shirqmap
;
223 /* Chip specific initialization */
224 switch (sb_chip(sbh
)) {
225 case BCM4710_CHIP_ID
:
226 /* Clear interrupt map */
227 for (irq
= 0; irq
<= 4; irq
++)
228 sb_clearirq(sbh
, irq
);
229 sb_setirq(sbh
, 0, SB_CODEC
, 0);
230 sb_setirq(sbh
, 0, SB_EXTIF
, 0);
231 sb_setirq(sbh
, 2, SB_ENET
, 1);
232 sb_setirq(sbh
, 3, SB_ILINE20
, 0);
233 sb_setirq(sbh
, 4, SB_PCI
, 0);
235 value
= nvram_get("et0phyaddr");
236 if (value
&& !strcmp(value
, "31")) {
237 /* Enable internal UART */
238 W_REG(osh
, &eir
->corecontrol
, CC_UE
);
239 /* Give USB its own interrupt */
240 sb_setirq(sbh
, 1, SB_USB
, 0);
242 /* Disable internal UART */
243 W_REG(osh
, &eir
->corecontrol
, 0);
244 /* Give Ethernet its own interrupt */
245 sb_setirq(sbh
, 1, SB_ENET
, 0);
246 sb_setirq(sbh
, 0, SB_USB
, 0);
249 case BCM5350_CHIP_ID
:
250 /* Clear interrupt map */
251 for (irq
= 0; irq
<= 4; irq
++)
252 sb_clearirq(sbh
, irq
);
253 sb_setirq(sbh
, 0, SB_CC
, 0);
254 sb_setirq(sbh
, 0, SB_MIPS33
, 0);
255 sb_setirq(sbh
, 1, SB_D11
, 0);
256 sb_setirq(sbh
, 2, SB_ENET
, 0);
257 sb_setirq(sbh
, 3, SB_PCI
, 0);
258 sb_setirq(sbh
, 4, SB_USB
, 0);
260 case BCM4785_CHIP_ID
:
261 /* Reassign PCI to irq 4 */
262 sb_setirq(sbh
, 4, SB_PCI
, 0);
268 BCMINITFN(sb_cpu_clock
)(sb_t
*sbh
)
274 uint32 pll_type
, rate
= 0;
276 /* get index of the current core */
277 idx
= sb_coreidx(sbh
);
278 pll_type
= PLL_TYPE1
;
280 /* switch to extif or chipc core */
281 if ((eir
= (extifregs_t
*) sb_setcore(sbh
, SB_EXTIF
, 0))) {
282 n
= R_REG(osh
, &eir
->clockcontrol_n
);
283 m
= R_REG(osh
, &eir
->clockcontrol_sb
);
284 } else if ((cc
= (chipcregs_t
*) sb_setcore(sbh
, SB_CC
, 0))) {
285 /* 5354 chip uses a non programmable PLL of frequency 240MHz */
286 if (sb_chip(sbh
) == BCM5354_CHIP_ID
) {
290 pll_type
= R_REG(osh
, &cc
->capabilities
) & CC_CAP_PLL_MASK
;
291 n
= R_REG(osh
, &cc
->clockcontrol_n
);
292 if ((pll_type
== PLL_TYPE2
) ||
293 (pll_type
== PLL_TYPE4
) ||
294 (pll_type
== PLL_TYPE6
) || (pll_type
== PLL_TYPE7
))
295 m
= R_REG(osh
, &cc
->clockcontrol_m3
);
296 else if (pll_type
== PLL_TYPE5
) {
299 } else if (pll_type
== PLL_TYPE3
) {
300 if (sb_chip(sbh
) == BCM5365_CHIP_ID
) {
304 /* 5350 uses m2 to control mips */
306 m
= R_REG(osh
, &cc
->clockcontrol_m2
);
308 m
= R_REG(osh
, &cc
->clockcontrol_sb
);
313 if (sb_chip(sbh
) == 0x5365)
316 rate
= sb_clock_rate(pll_type
, n
, m
);
318 if (pll_type
== PLL_TYPE6
)
319 rate
= SB2MIPS_T6(rate
);
322 /* switch back to previous core */
323 sb_setcoreidx(sbh
, idx
);
328 #define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4)
330 static void BCMINITFN(handler
) (void) {
331 __asm__(".set\tmips32\n\t" "ssnop\n\t" "ssnop\n\t"
332 /* Disable interrupts */
333 /* MTC0(C0_STATUS, 0, MFC0(C0_STATUS, 0) & ~(ALLINTS | STO_IE)); */
335 /* Just a Hack to not to use reg 'at' which was causing problems on 4704 A2 */
337 "and $15, $15, $14\n\t"
338 "mtc0 $15, $12\n\t" "eret\n\t" "nop\n\t" "nop\n\t"
342 /* The following MUST come right after handler() */
343 static void BCMINITFN(afterhandler
) (void) {
347 * Set the MIPS, backplane and PCI clocks as closely as possible.
349 * MIPS clocks synchronization function has been moved from PLL in chipcommon
350 * core rev. 15 to a DLL inside the MIPS core in 4785.
353 BCMINITFN(sb_mips_setclock
) (sb_t
* sbh
, uint32 mipsclock
, uint32 sbclock
,
355 extifregs_t
*eir
= NULL
;
356 chipcregs_t
*cc
= NULL
;
357 mipsregs_t
*mipsr
= NULL
;
358 volatile uint32
*clockcontrol_n
, *clockcontrol_sb
, *clockcontrol_pci
,
360 uint32 orig_n
, orig_sb
, orig_pci
, orig_m2
, orig_mips
, orig_ratio_parm
,
362 uint32 pll_type
, sync_mode
;
363 uint ic_size
, ic_lsize
;
366 /* PLL configuration: type 1 */
374 static n3m_table_t
BCMINITDATA(type1_table
)[] = {
375 /* 96.000 32.000 24.000 */
377 96000000, 0x0303, 0x04020011, 0x11030011, 0x11050011},
378 /* 100.000 33.333 25.000 */
380 100000000, 0x0009, 0x04020011, 0x11030011, 0x11050011},
381 /* 104.000 31.200 24.960 */
383 104000000, 0x0802, 0x04020011, 0x11050009, 0x11090009},
384 /* 108.000 32.400 24.923 */
386 108000000, 0x0403, 0x04020011, 0x11050009, 0x02000802},
387 /* 112.000 32.000 24.889 */
389 112000000, 0x0205, 0x04020011, 0x11030021, 0x02000403},
390 /* 115.200 32.000 24.000 */
392 115200000, 0x0303, 0x04020009, 0x11030011, 0x11050011},
393 /* 120.000 30.000 24.000 */
395 120000000, 0x0011, 0x04020011, 0x11050011, 0x11090011},
396 /* 124.800 31.200 24.960 */
398 124800000, 0x0802, 0x04020009, 0x11050009, 0x11090009},
399 /* 128.000 32.000 24.000 */
401 128000000, 0x0305, 0x04020011, 0x11050011, 0x02000305},
402 /* 132.000 33.000 24.750 */
404 132000000, 0x0603, 0x04020011, 0x11050011, 0x02000305},
405 /* 136.000 32.640 24.727 */
407 136000000, 0x0c02, 0x04020011, 0x11090009, 0x02000603},
408 /* 140.000 30.000 24.706 */
410 140000000, 0x0021, 0x04020011, 0x11050021, 0x02000c02},
411 /* 144.000 30.857 24.686 */
413 144000000, 0x0405, 0x04020011, 0x01020202, 0x11090021},
414 /* 150.857 33.000 24.000 */
416 150857142, 0x0605, 0x04020021, 0x02000305, 0x02000605},
417 /* 152.000 32.571 24.000 */
419 152000000, 0x0e02, 0x04020011, 0x11050021, 0x02000e02},
420 /* 156.000 31.200 24.960 */
422 156000000, 0x0802, 0x04020005, 0x11050009, 0x11090009},
423 /* 160.000 32.000 24.000 */
425 160000000, 0x0309, 0x04020011, 0x11090011, 0x02000309},
426 /* 163.200 32.640 24.727 */
428 163200000, 0x0c02, 0x04020009, 0x11090009, 0x02000603},
429 /* 168.000 32.000 24.889 */
431 168000000, 0x0205, 0x04020005, 0x11030021, 0x02000403},
432 /* 176.000 33.000 24.000 */
434 176000000, 0x0602, 0x04020003, 0x11050005, 0x02000602},};
436 /* PLL configuration: type 3 */
440 uint32 m2
; /* that is the clockcontrol_m2 */
442 static type3_table_t type3_table
[] = {
443 /* for 5350, mips clock is always double sb clock */
444 {150000000, 0x311, 0x4020005},
445 {200000000, 0x311, 0x4020003},
448 /* PLL configuration: type 2, 4, 7 */
463 static n4m_table_t
BCMINITDATA(type2_table
)[] = {
465 120000000, 60000000, 32000000, 0x0303, 0x01000200,
466 0x01000600, 0x01000200, 0x05000200, 11, 0x0aaa0555,
469 150000000, 75000000, 33333333, 0x0303, 0x01000100,
470 0x01000600, 0x01000100, 0x05000100, 11, 0x0aaa0555,
473 180000000, 80000000, 30000000, 0x0403, 0x01010000,
474 0x01020300, 0x01020600, 0x05000100, 8, 0x012a00a9,
477 180000000, 90000000, 30000000, 0x0403, 0x01000100,
478 0x01020300, 0x01000100, 0x05000100, 11, 0x0aaa0555,
481 200000000, 100000000, 33333333, 0x0303, 0x02010000,
482 0x02040001, 0x02010000, 0x06000001, 11, 0x0aaa0555,
485 211200000, 105600000, 30171428, 0x0902, 0x01000200,
486 0x01030400, 0x01000200, 0x05000200, 11, 0x0aaa0555,
489 220800000, 110400000, 31542857, 0x1500, 0x01000200,
490 0x01030400, 0x01000200, 0x05000200, 11, 0x0aaa0555,
493 230400000, 115200000, 32000000, 0x0604, 0x01000200,
494 0x01020600, 0x01000200, 0x05000200, 11, 0x0aaa0555,
497 234000000, 104000000, 31200000, 0x0b01, 0x01010000,
498 0x01010700, 0x01020600, 0x05000100, 8, 0x012a00a9,
501 240000000, 120000000, 33333333, 0x0803, 0x01000200,
502 0x01020600, 0x01000200, 0x05000200, 11, 0x0aaa0555,
505 252000000, 126000000, 33333333, 0x0504, 0x01000100,
506 0x01020500, 0x01000100, 0x05000100, 11, 0x0aaa0555,
509 264000000, 132000000, 33000000, 0x0903, 0x01000200,
510 0x01020700, 0x01000200, 0x05000200, 11, 0x0aaa0555,
513 270000000, 120000000, 30000000, 0x0703, 0x01010000,
514 0x01030400, 0x01020600, 0x05000100, 8, 0x012a00a9,
517 276000000, 122666666, 31542857, 0x1500, 0x01010000,
518 0x01030400, 0x01020600, 0x05000100, 8, 0x012a00a9,
521 280000000, 140000000, 31111111, 0x0503, 0x01000000,
522 0x01010600, 0x01000000, 0x05000000, 11, 0x0aaa0555,
525 288000000, 128000000, 32914285, 0x0604, 0x01010000,
526 0x01030400, 0x01020600, 0x05000100, 8, 0x012a00a9,
529 288000000, 144000000, 32000000, 0x0404, 0x01000000,
530 0x01010600, 0x01000000, 0x05000000, 11, 0x0aaa0555,
533 300000000, 133333333, 33333333, 0x0803, 0x01010000,
534 0x01020600, 0x01010100, 0x05000100, 8, 0x012a00a9,
537 300000000, 133333333, 37500000, 0x0803, 0x01010000,
538 0x01020500, 0x01010100, 0x05000100, 8, 0x012a00a9,
541 300000000, 133333333, 42857142, 0x0803, 0x01010000,
542 0x01020400, 0x01010100, 0x05000100, 8, 0x012a00a9,
545 300000000, 133333333, 50000000, 0x0803, 0x01010000,
546 0x01020300, 0x01010100, 0x05000100, 8, 0x012a00a9,
549 300000000, 133333333, 60000000, 0x0803, 0x01010000,
550 0x01020200, 0x01010100, 0x05000100, 8, 0x012a00a9,
553 300000000, 150000000, 33333333, 0x0803, 0x01000100,
554 0x01020600, 0x01010100, 0x05000100, 11, 0x0aaa0555,
557 300000000, 150000000, 37500000, 0x0803, 0x01000100,
558 0x01020500, 0x01010100, 0x05000100, 11, 0x0aaa0555,
561 300000000, 150000000, 42857142, 0x0803, 0x01000100,
562 0x01020400, 0x01010100, 0x05000100, 11, 0x0aaa0555,
565 300000000, 150000000, 50000000, 0x0803, 0x01000100,
566 0x01020300, 0x01010100, 0x05000100, 11, 0x0aaa0555,
569 300000000, 150000000, 60000000, 0x0803, 0x01000100,
570 0x01020200, 0x01010100, 0x05000100, 11, 0x0aaa0555,
573 330000000, 132000000, 33000000, 0x0903, 0x01000200,
574 0x00020200, 0x01010100, 0x05000100, 0, 0,
575 10 /* ratio 4/10 */ , 0x02520129},
577 330000000, 146666666, 33000000, 0x0903, 0x01010000,
578 0x00020200, 0x01010100, 0x05000100, 0, 0,
579 9 /* ratio 4/9 */ , 0x012a00a9},
581 330000000, 165000000, 33000000, 0x0903, 0x01000100,
582 0x00020200, 0x01010100, 0x05000100, 0, 0,
583 8 /* ratio 4/8 */ , 0x00aa0055},
585 330000000, 165000000, 41250000, 0x0903, 0x01000100,
586 0x00020100, 0x01010100, 0x05000100, 0, 0,
587 8 /* ratio 4/8 */ , 0x00aa0055},
589 330000000, 165000000, 55000000, 0x0903, 0x01000100,
590 0x00020000, 0x01010100, 0x05000100, 0, 0,
591 8 /* ratio 4/8 */ , 0x00aa0055},
593 360000000, 120000000, 32000000, 0x0a03, 0x01000300,
594 0x00010201, 0x01010200, 0x05000100, 0, 0,
595 12 /* ratio 4/12 */ , 0x04920492},
597 360000000, 144000000, 32000000, 0x0a03, 0x01000200,
598 0x00010201, 0x01010200, 0x05000100, 0, 0,
599 10 /* ratio 4/10 */ , 0x02520129},
601 360000000, 160000000, 32000000, 0x0a03, 0x01010000,
602 0x00010201, 0x01010200, 0x05000100, 0, 0,
603 9 /* ratio 4/9 */ , 0x012a00a9},
605 360000000, 180000000, 32000000, 0x0a03, 0x01000100,
606 0x00010201, 0x01010200, 0x05000100, 0, 0,
607 8 /* ratio 4/8 */ , 0x00aa0055},
609 360000000, 180000000, 40000000, 0x0a03, 0x01000100,
610 0x00010101, 0x01010200, 0x05000100, 0, 0,
611 8 /* ratio 4/8 */ , 0x00aa0055},
613 360000000, 180000000, 53333333, 0x0a03, 0x01000100,
614 0x00010001, 0x01010200, 0x05000100, 0, 0,
615 8 /* ratio 4/8 */ , 0x00aa0055},
617 390000000, 130000000, 32500000, 0x0b03, 0x01010100,
618 0x00020101, 0x01020100, 0x05000100, 0, 0,
619 12 /* ratio 4/12 */ , 0x04920492},
621 390000000, 156000000, 32500000, 0x0b03, 0x01000200,
622 0x00020101, 0x01020100, 0x05000100, 0, 0,
623 10 /* ratio 4/10 */ , 0x02520129},
625 390000000, 173000000, 32500000, 0x0b03, 0x01010000,
626 0x00020101, 0x01020100, 0x05000100, 0, 0,
627 9 /* ratio 4/9 */ , 0x012a00a9},
629 390000000, 195000000, 32500000, 0x0b03, 0x01000100,
630 0x00020101, 0x01020100, 0x05000100, 0, 0,
631 8 /* ratio 4/8 */ , 0x00aa0055},
633 static n4m_table_t
BCMINITDATA(type4_table
)[] = {
635 120000000, 60000000, 0, 0x0009, 0x11020009, 0x01030203,
636 0x11020009, 0x04000009, 11, 0x0aaa0555}, {
637 150000000, 75000000, 0, 0x0009, 0x11050002, 0x01030203,
638 0x11050002, 0x04000005, 11, 0x0aaa0555}, {
639 192000000, 96000000, 0, 0x0702, 0x04000011, 0x11030011,
640 0x04000011, 0x04000003, 11, 0x0aaa0555}, {
641 198000000, 99000000, 0, 0x0603, 0x11020005, 0x11030011,
642 0x11020005, 0x04000005, 11, 0x0aaa0555}, {
643 200000000, 100000000, 0, 0x0009, 0x04020011, 0x11030011,
644 0x04020011, 0x04020003, 11, 0x0aaa0555}, {
645 204000000, 102000000, 0, 0x0c02, 0x11020005, 0x01030303,
646 0x11020005, 0x04000005, 11, 0x0aaa0555}, {
647 208000000, 104000000, 0, 0x0802, 0x11030002, 0x11090005,
648 0x11030002, 0x04000003, 11, 0x0aaa0555}, {
649 210000000, 105000000, 0, 0x0209, 0x11020005, 0x01030303,
650 0x11020005, 0x04000005, 11, 0x0aaa0555}, {
651 216000000, 108000000, 0, 0x0111, 0x11020005, 0x01030303,
652 0x11020005, 0x04000005, 11, 0x0aaa0555}, {
653 224000000, 112000000, 0, 0x0205, 0x11030002, 0x02002103,
654 0x11030002, 0x04000003, 11, 0x0aaa0555}, {
655 228000000, 101333333, 0, 0x0e02, 0x11030003, 0x11210005,
656 0x01030305, 0x04000005, 8, 0x012a00a9}, {
657 228000000, 114000000, 0, 0x0e02, 0x11020005, 0x11210005,
658 0x11020005, 0x04000005, 11, 0x0aaa0555}, {
659 240000000, 102857143, 0, 0x0109, 0x04000021, 0x01050203,
660 0x11030021, 0x04000003, 13, 0x254a14a9}, {
661 240000000, 120000000, 0, 0x0109, 0x11030002, 0x01050203,
662 0x11030002, 0x04000003, 11, 0x0aaa0555}, {
663 252000000, 100800000, 0, 0x0203, 0x04000009, 0x11050005,
664 0x02000209, 0x04000002, 9, 0x02520129}, {
665 252000000, 126000000, 0, 0x0203, 0x04000005, 0x11050005,
666 0x04000005, 0x04000002, 11, 0x0aaa0555}, {
667 264000000, 132000000, 0, 0x0602, 0x04000005, 0x11050005,
668 0x04000005, 0x04000002, 11, 0x0aaa0555}, {
669 272000000, 116571428, 0, 0x0c02, 0x04000021, 0x02000909,
670 0x02000221, 0x04000003, 13, 0x254a14a9}, {
671 280000000, 120000000, 0, 0x0209, 0x04000021, 0x01030303,
672 0x02000221, 0x04000003, 13, 0x254a14a9}, {
673 288000000, 123428571, 0, 0x0111, 0x04000021, 0x01030303,
674 0x02000221, 0x04000003, 13, 0x254a14a9}, {
675 300000000, 120000000, 0, 0x0009, 0x04000009, 0x01030203,
676 0x02000902, 0x04000002, 9, 0x02520129}, {
677 300000000, 150000000, 0, 0x0009, 0x04000005, 0x01030203,
678 0x04000005, 0x04000002, 11, 0x0aaa0555}
680 static n4m_table_t
BCMINITDATA(type7_table
)[] = {
682 183333333, 91666666, 0, 0x0605, 0x04000011, 0x11030011,
683 0x04000011, 0x04000003, 11, 0x0aaa0555}, {
684 187500000, 93750000, 0, 0x0a03, 0x04000011, 0x11030011,
685 0x04000011, 0x04000003, 11, 0x0aaa0555}, {
686 196875000, 98437500, 0, 0x1003, 0x11020005, 0x11050011,
687 0x11020005, 0x04000005, 11, 0x0aaa0555}, {
688 200000000, 100000000, 0, 0x0311, 0x04000011, 0x11030011,
689 0x04000009, 0x04000003, 11, 0x0aaa0555}, {
690 200000000, 100000000, 0, 0x0311, 0x04020011, 0x11030011,
691 0x04020011, 0x04020003, 11, 0x0aaa0555}, {
692 206250000, 103125000, 0, 0x1103, 0x11020005, 0x11050011,
693 0x11020005, 0x04000005, 11, 0x0aaa0555}, {
694 212500000, 106250000, 0, 0x0c05, 0x11020005, 0x01030303,
695 0x11020005, 0x04000005, 11, 0x0aaa0555}, {
696 215625000, 107812500, 0, 0x1203, 0x11090009, 0x11050005,
697 0x11020005, 0x04000005, 11, 0x0aaa0555}, {
698 216666666, 108333333, 0, 0x0805, 0x11020003, 0x11030011,
699 0x11020003, 0x04000003, 11, 0x0aaa0555}, {
700 225000000, 112500000, 0, 0x0d03, 0x11020003, 0x11030011,
701 0x11020003, 0x04000003, 11, 0x0aaa0555}, {
702 233333333, 116666666, 0, 0x0905, 0x11020003, 0x11030011,
703 0x11020003, 0x04000003, 11, 0x0aaa0555}, {
704 237500000, 118750000, 0, 0x0e05, 0x11020005, 0x11210005,
705 0x11020005, 0x04000005, 11, 0x0aaa0555}, {
706 240000000, 120000000, 0, 0x0b11, 0x11020009, 0x11210009,
707 0x11020009, 0x04000009, 11, 0x0aaa0555}, {
708 250000000, 125000000, 0, 0x0f03, 0x11020003, 0x11210003,
709 0x11020003, 0x04000003, 11, 0x0aaa0555}
712 ulong start
, end
, dst
;
715 volatile uint32
*dll_ctrl
= (volatile uint32
*)0xff400008;
716 volatile uint32
*dll_r1
= (volatile uint32
*)0xff400010;
717 volatile uint32
*dll_r2
= (volatile uint32
*)0xff400018;
719 /* get index of the current core */
720 idx
= sb_coreidx(sbh
);
721 clockcontrol_m2
= NULL
;
723 /* switch to chipc core */
724 /* switch to extif or chipc core */
725 if ((eir
= (extifregs_t
*) sb_setcore(sbh
, SB_EXTIF
, 0))) {
726 pll_type
= PLL_TYPE1
;
727 clockcontrol_n
= &eir
->clockcontrol_n
;
728 clockcontrol_sb
= &eir
->clockcontrol_sb
;
729 clockcontrol_pci
= &eir
->clockcontrol_pci
;
730 clockcontrol_m2
= &cc
->clockcontrol_m2
;
731 } else if ((cc
= (chipcregs_t
*) sb_setcore(sbh
, SB_CC
, 0))) {
732 /* 5354 chipcommon pll setting can't be changed.
733 * The PMU on power up comes up with the default clk frequency
736 if (sb_chip(sbh
) == BCM5354_CHIP_ID
) {
740 pll_type
= R_REG(osh
, &cc
->capabilities
) & CC_CAP_PLL_MASK
;
741 if (pll_type
== PLL_TYPE6
) {
742 clockcontrol_n
= NULL
;
743 clockcontrol_sb
= NULL
;
744 clockcontrol_pci
= NULL
;
746 clockcontrol_n
= &cc
->clockcontrol_n
;
747 clockcontrol_sb
= &cc
->clockcontrol_sb
;
748 clockcontrol_pci
= &cc
->clockcontrol_pci
;
749 clockcontrol_m2
= &cc
->clockcontrol_m2
;
754 if (pll_type
== PLL_TYPE6
) {
755 /* Silence compilers */
756 orig_n
= orig_sb
= orig_pci
= 0;
758 /* Store the current clock register values */
759 orig_n
= R_REG(osh
, clockcontrol_n
);
760 orig_sb
= R_REG(osh
, clockcontrol_sb
);
761 orig_pci
= R_REG(osh
, clockcontrol_pci
);
764 if (pll_type
== PLL_TYPE1
) {
765 /* Keep the current PCI clock if not specified */
768 sb_clock_rate(pll_type
, R_REG(osh
, clockcontrol_n
),
769 R_REG(osh
, clockcontrol_pci
));
770 pciclock
= (pciclock
<= 25000000) ? 25000000 : 33000000;
773 /* Search for the closest MIPS clock less than or equal to a preferred value */
774 for (i
= 0; i
< ARRAYSIZE(type1_table
); i
++) {
775 ASSERT(type1_table
[i
].mipsclock
==
776 sb_clock_rate(pll_type
, type1_table
[i
].n
,
778 if (type1_table
[i
].mipsclock
> mipsclock
)
788 ASSERT(type1_table
[i
].mipsclock
<= mipsclock
);
791 if ((orig_n
== type1_table
[i
].n
) &&
792 (orig_sb
== type1_table
[i
].sb
) &&
793 (orig_pci
== type1_table
[i
].pci33
))
796 /* Set the PLL controls */
797 W_REG(osh
, clockcontrol_n
, type1_table
[i
].n
);
798 W_REG(osh
, clockcontrol_sb
, type1_table
[i
].sb
);
799 if (pciclock
== 25000000)
800 W_REG(osh
, clockcontrol_pci
, type1_table
[i
].pci25
);
802 W_REG(osh
, clockcontrol_pci
, type1_table
[i
].pci33
);
807 } else if (pll_type
== PLL_TYPE3
) {
809 if (sb_chip(sbh
) != BCM5365_CHIP_ID
) {
811 * Search for the closest MIPS clock less than or equal to
814 for (i
= 0; i
< ARRAYSIZE(type3_table
); i
++) {
815 if (type3_table
[i
].mipsclock
> mipsclock
)
825 ASSERT(type3_table
[i
].mipsclock
<= mipsclock
);
828 orig_m2
= R_REG(osh
, &cc
->clockcontrol_m2
);
829 if ((orig_n
== type3_table
[i
].n
)
830 && (orig_m2
== type3_table
[i
].m2
)) {
834 /* Set the PLL controls */
835 W_REG(osh
, clockcontrol_n
, type3_table
[i
].n
);
836 W_REG(osh
, clockcontrol_m2
, type3_table
[i
].m2
);
842 } else if ((pll_type
== PLL_TYPE2
) ||
843 (pll_type
== PLL_TYPE4
) ||
844 (pll_type
== PLL_TYPE6
) || (pll_type
== PLL_TYPE7
)) {
845 n4m_table_t
*table
= NULL
, *te
;
850 orig_mips
= R_REG(osh
, &cc
->clockcontrol_m3
);
858 if (mipsclock
<= SB2MIPS_T6(CC_T6_M1
))
859 new_mips
= CC_T6_MMASK
;
861 if (orig_mips
== new_mips
)
864 W_REG(osh
, &cc
->clockcontrol_m3
, new_mips
);
869 tabsz
= ARRAYSIZE(type2_table
);
873 tabsz
= ARRAYSIZE(type4_table
);
877 tabsz
= ARRAYSIZE(type7_table
);
880 ASSERT("No table for plltype" == NULL
);
884 /* Store the current clock register values */
885 orig_m2
= R_REG(osh
, &cc
->clockcontrol_m2
);
889 /* Look up current ratio */
890 for (i
= 0; i
< tabsz
; i
++) {
891 if ((orig_n
== table
[i
].n
) &&
892 (orig_sb
== table
[i
].sb
) &&
893 (orig_pci
== table
[i
].pci33
) &&
894 (orig_m2
== table
[i
].m2
)
895 && (orig_mips
== table
[i
].m3
)) {
896 orig_ratio_parm
= table
[i
].ratio_parm
;
897 orig_ratio_cfg
= table
[i
].ratio_cfg
;
902 /* Search for the closest MIPS clock greater or equal to a preferred value */
903 for (i
= 0; i
< tabsz
; i
++) {
904 ASSERT(table
[i
].mipsclock
==
905 sb_clock_rate(pll_type
, table
[i
].n
,
907 if ((mipsclock
<= table
[i
].mipsclock
)
908 && ((sbclock
== 0) || (sbclock
<= table
[i
].sbclock
))
910 || (pciclock
<= table
[i
].pciclock
)))
922 if ((orig_n
== te
->n
) &&
923 (orig_sb
== te
->sb
) &&
924 (orig_pci
== te
->pci33
) &&
925 (orig_m2
== te
->m2
) && (orig_mips
== te
->m3
))
928 /* Set the PLL controls */
929 W_REG(osh
, clockcontrol_n
, te
->n
);
930 W_REG(osh
, clockcontrol_sb
, te
->sb
);
931 W_REG(osh
, clockcontrol_pci
, te
->pci33
);
932 W_REG(osh
, &cc
->clockcontrol_m2
, te
->m2
);
933 W_REG(osh
, &cc
->clockcontrol_m3
, te
->m3
);
935 /* Set the chipcontrol bit to change mipsref to the backplane divider if needed */
936 if ((pll_type
== PLL_TYPE7
) && (te
->sb
!= te
->m2
) &&
937 (sb_clock_rate(pll_type
, te
->n
, te
->m2
) == 120000000))
938 W_REG(osh
, &cc
->chipcontrol
,
939 R_REG(osh
, &cc
->chipcontrol
) | 0x100);
941 /* No ratio change */
942 if (sb_chip(sbh
) != BCM4785_CHIP_ID
) {
943 if (orig_ratio_parm
== te
->ratio_parm
)
947 /* Preload the code into the cache */
948 icache_probe(MFC0(C0_CONFIG
, 1), &ic_size
, &ic_lsize
);
949 if (sb_chip(sbh
) == BCM4785_CHIP_ID
) {
950 start
= ((ulong
) && start_fill_4785
) & ~(ic_lsize
- 1);
952 && end_fill_4785
+ (ic_lsize
- 1)) & ~(ic_lsize
-
955 start
= ((ulong
) && start_fill
) & ~(ic_lsize
- 1);
957 && end_fill
+ (ic_lsize
- 1)) & ~(ic_lsize
- 1);
959 while (start
< end
) {
960 cache_op(start
, Fill_I
);
964 /* 4785 clock freq change procedures */
965 if (sb_chip(sbh
) == BCM4785_CHIP_ID
) {
967 /* Switch to async */
968 MTC0(C0_BROADCOM
, 4, (1 << 22));
970 /* Set clock ratio in MIPS */
971 *dll_r1
= (*dll_r1
& 0xfffffff0) | (te
->d11_r1
- 1);
972 *dll_r2
= te
->d11_r2
;
974 /* Enable new settings in MIPS */
975 *dll_r1
= *dll_r1
| 0xc0000000;
979 MFC0(C0_BROADCOM
, 2) | (1 << 3) | 1);
981 /* Fake soft reset (clock cfg registers not reset) */
982 MTC0(C0_BROADCOM
, 5, MFC0(C0_BROADCOM
, 5) | (1 << 2));
984 /* Clear active cfg */
985 MTC0(C0_BROADCOM
, 2, MFC0(C0_BROADCOM
, 2) & ~(1 << 3));
987 /* set watchdog timer */
988 W_REG(osh
, &cc
->watchdog
, 20);
989 (void)R_REG(osh
, &cc
->chipid
);
991 /* wait for timer interrupt */
992 __asm__
__volatile__(".set\tmips3\n\t"
993 "sync\n\t" "wait\n\t"
998 /* Generic clock freq change procedures */
1000 /* Copy the handler */
1001 start
= (ulong
) & handler
;
1002 end
= (ulong
) & afterhandler
;
1003 dst
= KSEG1ADDR(0x180);
1004 for (i
= 0; i
< (end
- start
); i
+= 4)
1005 *((ulong
*) (dst
+ i
)) =
1006 *((ulong
*) (start
+ i
));
1008 /* Preload the handler into the cache one line at a time */
1009 for (i
= 0; i
< (end
- start
); i
+= ic_lsize
)
1010 cache_op(dst
+ i
, Fill_I
);
1013 MTC0(C0_STATUS
, 0, MFC0(C0_STATUS
, 0) & ~ST0_BEV
);
1015 /* Enable interrupts */
1017 MFC0(C0_STATUS
, 0) | (ALLINTS
| ST0_IE
));
1019 /* Enable MIPS timer interrupt */
1020 if (!(mipsr
= sb_setcore(sbh
, SB_MIPS
, 0)) &&
1021 !(mipsr
= sb_setcore(sbh
, SB_MIPS33
, 0)))
1023 W_REG(osh
, &mipsr
->intmask
, 1);
1026 /* step 1, set clock ratios */
1027 MTC0(C0_BROADCOM
, 3, te
->ratio_parm
);
1028 MTC0(C0_BROADCOM
, 1, te
->ratio_cfg
);
1030 /* step 2: program timer intr */
1031 W_REG(osh
, &mipsr
->timer
, 100);
1032 (void)R_REG(osh
, &mipsr
->timer
);
1034 /* step 3, switch to async */
1035 sync_mode
= MFC0(C0_BROADCOM
, 4);
1036 MTC0(C0_BROADCOM
, 4, 1 << 22);
1038 /* step 4, set cfg active */
1039 MTC0(C0_BROADCOM
, 2, (1 << 3) | 1);
1042 __asm__
__volatile__(".set\tmips3\n\t" "wait\n\t"
1045 /* step 7, clear cfg active */
1046 MTC0(C0_BROADCOM
, 2, 0);
1048 /* Additional Step: set back to orig sync mode */
1049 MTC0(C0_BROADCOM
, 4, sync_mode
);
1051 /* step 8, fake soft reset */
1052 MTC0(C0_BROADCOM
, 5, MFC0(C0_BROADCOM
, 5) | (1 << 2));
1055 /* set watchdog timer */
1056 W_REG(osh
, &cc
->watchdog
, 20);
1057 (void)R_REG(osh
, &cc
->chipid
);
1059 /* wait for timer interrupt */
1060 __asm__
__volatile__(".set\tmips3\n\t"
1061 "sync\n\t" "wait\n\t"
1068 /* Enable 4785 DLL */
1069 if (sb_chip(sbh
) == BCM4785_CHIP_ID
) {
1072 /* set mask to 1e, enable DLL (bit 0) */
1073 *dll_ctrl
|= 0x0041e021;
1075 /* enable aggressive hardware mode */
1076 *dll_ctrl
|= 0x00000080;
1078 /* wait for lock flag to clear */
1079 while ((*dll_ctrl
& 0x2) == 0) ;
1081 /* clear sticky flags (clear on write 1) */
1085 /* set mask to 5b'10001 */
1086 *dll_ctrl
= (*dll_ctrl
& 0xfffc1fff) | 0x00022000;
1088 /* enable sync mode */
1089 MTC0(C0_BROADCOM
, 4, MFC0(C0_BROADCOM
, 4) & 0xfe3fffff);
1090 (void)MFC0(C0_BROADCOM
, 4);
1093 /* switch back to previous core */
1094 sb_setcoreidx(sbh
, idx
);
1099 void BCMINITFN(enable_pfc
) (uint32 mode
) {
1101 uint ic_size
, ic_lsize
;
1103 /* If auto then choose the correct mode for this
1104 * platform, currently we only ever select one mode
1106 if (mode
== PFC_AUTO
)
1109 icache_probe(MFC0(C0_CONFIG
, 1), &ic_size
, &ic_lsize
);
1111 /* enable prefetch cache if available */
1112 if (MFC0(C0_BROADCOM
, 0) & BRCM_PFC_AVAIL
) {
1113 start
= ((ulong
) && setpfc_start
) & ~(ic_lsize
- 1);
1115 && setpfc_end
+ (ic_lsize
- 1)) & ~(ic_lsize
- 1);
1117 /* Preload setpfc code into the cache one line at a time */
1118 while (start
< end
) {
1119 cache_op(start
, Fill_I
);
1123 /* Now set the pfc */
1126 *(volatile uint32
*)PFC_CR1
= 0xffff0000;
1129 *(volatile uint32
*)PFC_CR0
= mode
;
1131 /* Compiler foder */
1136 /* returns the ncdl value to be programmed into sdram_ncdl for calibration */
1137 uint32
BCMINITFN(sb_memc_get_ncdl
) (sb_t
* sbh
) {
1141 uint32 config
, rd
, wr
, misc
, dqsg
, cd
, sm
, sd
;
1146 idx
= sb_coreidx(sbh
);
1148 memc
= (sbmemcregs_t
*) sb_setcore(sbh
, SB_MEMC
, 0);
1152 rev
= sb_corerev(sbh
);
1154 config
= R_REG(osh
, &memc
->config
);
1155 wr
= R_REG(osh
, &memc
->wrncdlcor
);
1156 rd
= R_REG(osh
, &memc
->rdncdlcor
);
1157 misc
= R_REG(osh
, &memc
->miscdlyctl
);
1158 dqsg
= R_REG(osh
, &memc
->dqsgatencdl
);
1160 rd
&= MEMC_RDNCDLCOR_RD_MASK
;
1161 wr
&= MEMC_WRNCDLCOR_WR_MASK
;
1162 dqsg
&= MEMC_DQSGATENCDL_G_MASK
;
1164 if (config
& MEMC_CONFIG_DDR
) {
1165 ret
= (wr
<< 16) | (rd
<< 8) | dqsg
;
1171 MEMC_CD_THRESHOLD
) ? rd
: (wr
+
1173 sm
= (misc
& MEMC_MISC_SM_MASK
) >> MEMC_MISC_SM_SHIFT
;
1174 sd
= (misc
& MEMC_MISC_SD_MASK
) >> MEMC_MISC_SD_SHIFT
;
1175 ret
= (sm
<< 16) | (sd
<< 8) | cd
;
1179 /* switch back to previous core */
1180 sb_setcoreidx(sbh
, idx
);
1185 void hnd_cpu_reset(sb_t
* sbh
)
1187 if (sb_chip(sbh
) == BCM4785_CHIP_ID
)
1188 MTC0(C0_BROADCOM
, 4, (1 << 22));
1189 sb_watchdog(sbh
, 1);
1190 if (sb_chip(sbh
) == BCM4785_CHIP_ID
) {
1191 __asm__
__volatile__(".set\tmips3\n\t"
1192 "sync\n\t" "wait\n\t" ".set\tmips0");
1197 #if defined(BCMPERFSTATS)
1199 * CP0 Register 25 supports 4 semi-independent 32bit performance counters.
1200 * $25 select 0, 1, 2, and 3 are the counters. The counters *decrement* (who thought this one up?)
1201 * $25 select 4 and 5 each contain 2-16bit control fields, one for each of the 4 counters
1202 * $25 select 6 is the global perf control register.
1204 /* enable and start instruction counting */
1206 void hndmips_perf_cyclecount_enable(void)
1208 MTC0(C0_PERFORMANCE
, 6, 0x80000200); /* global enable perf counters */
1209 MTC0(C0_PERFORMANCE
, 4, 0x8048 | MFC0(C0_PERFORMANCE
, 4)); /* enable cycles counting for counter 0 */
1210 MTC0(C0_PERFORMANCE
, 0, 0); /* zero counter zero */
1213 void hndmips_perf_instrcount_enable(void)
1215 MTC0(C0_PERFORMANCE
, 6, 0x80000200); /* global enable perf counters */
1216 MTC0(C0_PERFORMANCE
, 4, 0x8044 | MFC0(C0_PERFORMANCE
, 4)); /* enable instructions counting for counter 0 */
1217 MTC0(C0_PERFORMANCE
, 0, 0); /* zero counter zero */
1220 /* enable and start I$ hit and I$ miss counting */
1221 void hndmips_perf_icachecount_enable(void)
1223 MTC0(C0_PERFORMANCE
, 6, 0x80000218); /* enable I$ counting */
1224 MTC0(C0_PERFORMANCE
, 4, 0x80148018); /* count I$ hits in cntr 0 and misses in cntr 1 */
1225 MTC0(C0_PERFORMANCE
, 0, 0); /* zero counter 0 - # I$ hits */
1226 MTC0(C0_PERFORMANCE
, 1, 0); /* zero counter 1 - # I$ misses */
1229 /* enable and start D$ hit and I$ miss counting */
1230 void hndmips_perf_dcachecount_enable(void)
1232 MTC0(C0_PERFORMANCE
, 6, 0x80000211); /* enable D$ counting */
1233 MTC0(C0_PERFORMANCE
, 4, 0x80248028); /* count D$ hits in cntr 0 and misses in cntr 1 */
1234 MTC0(C0_PERFORMANCE
, 0, 0); /* zero counter 0 - # D$ hits */
1235 MTC0(C0_PERFORMANCE
, 1, 0); /* zero counter 1 - # D$ misses */
1238 void hndmips_perf_icache_miss_enable()
1240 MTC0(C0_PERFORMANCE
, 4, 0x80140000 | MFC0(C0_PERFORMANCE
, 4)); /* enable cache misses counting for counter 1 */
1241 MTC0(C0_PERFORMANCE
, 1, 0); /* zero counter one */
1244 void hndmips_perf_icache_hit_enable()
1246 MTC0(C0_PERFORMANCE
, 5, 0x8018 | MFC0(C0_PERFORMANCE
, 5));
1247 /* enable cache hits counting for counter 2 */
1248 MTC0(C0_PERFORMANCE
, 2, 0); /* zero counter 2 */
1251 uint32
hndmips_perf_read_instrcount()
1253 return -(long)(MFC0(C0_PERFORMANCE
, 0));
1256 uint32
hndmips_perf_read_cache_miss()
1258 return -(long)(MFC0(C0_PERFORMANCE
, 1));
1261 uint32
hndmips_perf_read_cache_hit()
1263 return -(long)(MFC0(C0_PERFORMANCE
, 2));