2 * BCM47XX Sonics SiliconBackplane MIPS core routines
4 * Copyright 2006, 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.
12 * $Id: hndmips.c,v 1.1.1.1 2006/02/27 03:43:16 honor Exp $
27 #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. */
65 regs
= sb_coreregs(sbh
);
66 sb
= (sbconfig_t
*)((ulong
) regs
+ SBCONFIGOFF
);
68 return (R_REG(osh
, &sb
->sbtpsflag
) & SBTPS_NUM0_MASK
);
72 * Returns the MIPS IRQ assignment of the current core. If unassigned,
82 uint32 flag
, sbipsflag
;
86 flag
= sb_getflag(sbh
);
88 idx
= sb_coreidx(sbh
);
90 if ((regs
= sb_setcore(sbh
, SB_MIPS
, 0)) ||
91 (regs
= sb_setcore(sbh
, SB_MIPS33
, 0))) {
92 sb
= (sbconfig_t
*)((ulong
) regs
+ SBCONFIGOFF
);
94 /* sbipsflag specifies which core is routed to interrupts 1 to 4 */
95 sbipsflag
= R_REG(osh
, &sb
->sbipsflag
);
96 for (irq
= 1; irq
<= 4; irq
++) {
97 if (((sbipsflag
& sbips_int_mask
[irq
]) >> sbips_int_shift
[irq
]) == flag
)
104 sb_setcoreidx(sbh
, idx
);
109 /* Clears the specified MIPS IRQ. */
111 BCMINITFN(sb_clearirq
)(sb_t
*sbh
, uint irq
)
119 if (!(regs
= sb_setcore(sbh
, SB_MIPS
, 0)) &&
120 !(regs
= sb_setcore(sbh
, SB_MIPS33
, 0)))
122 sb
= (sbconfig_t
*)((ulong
) regs
+ SBCONFIGOFF
);
125 W_REG(osh
, &sb
->sbintvec
, 0);
127 OR_REG(osh
, &sb
->sbipsflag
, sbips_int_mask
[irq
]);
131 * Assigns the specified MIPS IRQ to the specified core. Shared MIPS
132 * IRQ 0 may be assigned more than once.
134 * The old assignment to the specified core is removed first.
137 BCMINITFN(sb_setirq
)(sb_t
*sbh
, uint irq
, uint coreid
, uint coreunit
)
147 regs
= sb_setcore(sbh
, coreid
, coreunit
);
149 flag
= sb_getflag(sbh
);
150 oldirq
= sb_irq(sbh
);
152 sb_clearirq(sbh
, oldirq
);
154 if (!(regs
= sb_setcore(sbh
, SB_MIPS
, 0)) &&
155 !(regs
= sb_setcore(sbh
, SB_MIPS33
, 0)))
157 sb
= (sbconfig_t
*)((ulong
) regs
+ SBCONFIGOFF
);
160 AND_REG(osh
, &sb
->sbintvec
, ~(1 << flag
));
163 OR_REG(osh
, &sb
->sbintvec
, 1 << flag
);
165 flag
<<= sbips_int_shift
[irq
];
166 ASSERT(!(flag
& ~sbips_int_mask
[irq
]));
167 flag
|= R_REG(osh
, &sb
->sbipsflag
) & ~sbips_int_mask
[irq
];
168 W_REG(osh
, &sb
->sbipsflag
, flag
);
173 * Initializes clocks and interrupts. SB and NVRAM access must be
174 * initialized prior to calling.
176 * 'shirqmap' enables virtual dedicated OS IRQ mapping if non-zero.
179 BCMINITFN(sb_mips_init
)(sb_t
*sbh
, uint shirqmap
)
190 /* Figure out current SB clock speed */
191 if ((hz
= sb_clock(sbh
)) == 0)
193 ns
= 1000000000 / hz
;
195 /* Setup external interface timing */
196 if ((eir
= sb_setcore(sbh
, SB_EXTIF
, 0))) {
197 /* Initialize extif so we can get to the LEDs and external UART */
198 W_REG(osh
, &eir
->prog_config
, CF_EN
);
200 /* Set timing for the flash */
201 tmp
= CEIL(10, ns
) << FW_W3_SHIFT
; /* W3 = 10nS */
202 tmp
= tmp
| (CEIL(40, ns
) << FW_W1_SHIFT
); /* W1 = 40nS */
203 tmp
= tmp
| CEIL(120, ns
); /* W0 = 120nS */
204 W_REG(osh
, &eir
->prog_waitcount
, tmp
); /* 0x01020a0c for a 100Mhz clock */
206 /* Set programmable interface timing for external uart */
207 tmp
= CEIL(10, ns
) << FW_W3_SHIFT
; /* W3 = 10nS */
208 tmp
= tmp
| (CEIL(20, ns
) << FW_W2_SHIFT
); /* W2 = 20nS */
209 tmp
= tmp
| (CEIL(100, ns
) << FW_W1_SHIFT
); /* W1 = 100nS */
210 tmp
= tmp
| CEIL(120, ns
); /* W0 = 120nS */
211 W_REG(osh
, &eir
->prog_waitcount
, tmp
); /* 0x01020a0c for a 100Mhz clock */
212 } else if ((cc
= sb_setcore(sbh
, SB_CC
, 0))) {
213 /* Set timing for the flash */
214 tmp
= CEIL(10, ns
) << FW_W3_SHIFT
; /* W3 = 10nS */
215 tmp
|= CEIL(10, ns
) << FW_W1_SHIFT
; /* W1 = 10nS */
216 tmp
|= CEIL(120, ns
); /* W0 = 120nS */
217 if ((sb_corerev(sbh
) < 9) ||
218 (BCMINIT(sb_chip
)(sbh
) == 0x5365))
219 W_REG(osh
, &cc
->flash_waitcount
, tmp
);
221 if ((sb_corerev(sbh
) < 9) ||
222 ((sb_chip(sbh
) == BCM5350_CHIP_ID
) && sb_chiprev(sbh
) == 0) ||
223 (BCMINIT(sb_chip
)(sbh
) == 0x5365)) {
224 W_REG(osh
, &cc
->pcmcia_memwait
, tmp
);
227 /* Save shared IRQ mapping base */
228 shirq_map_base
= shirqmap
;
231 /* Chip specific initialization */
232 switch (sb_chip(sbh
)) {
233 case BCM4710_CHIP_ID
:
234 /* Clear interrupt map */
235 for (irq
= 0; irq
<= 4; irq
++)
236 sb_clearirq(sbh
, irq
);
237 sb_setirq(sbh
, 0, SB_CODEC
, 0);
238 sb_setirq(sbh
, 0, SB_EXTIF
, 0);
239 sb_setirq(sbh
, 2, SB_ENET
, 1);
240 sb_setirq(sbh
, 3, SB_ILINE20
, 0);
241 sb_setirq(sbh
, 4, SB_PCI
, 0);
243 value
= nvram_get("et0phyaddr");
244 if (value
&& !strcmp(value
, "31")) {
245 /* Enable internal UART */
246 W_REG(osh
, &eir
->corecontrol
, CC_UE
);
247 /* Give USB its own interrupt */
248 sb_setirq(sbh
, 1, SB_USB
, 0);
250 /* Disable internal UART */
251 W_REG(osh
, &eir
->corecontrol
, 0);
252 /* Give Ethernet its own interrupt */
253 sb_setirq(sbh
, 1, SB_ENET
, 0);
254 sb_setirq(sbh
, 0, SB_USB
, 0);
257 case BCM5350_CHIP_ID
:
258 /* Clear interrupt map */
259 for (irq
= 0; irq
<= 4; irq
++)
260 sb_clearirq(sbh
, irq
);
261 sb_setirq(sbh
, 0, SB_CC
, 0);
262 sb_setirq(sbh
, 0, SB_MIPS33
, 0);
263 sb_setirq(sbh
, 1, SB_D11
, 0);
264 sb_setirq(sbh
, 2, SB_ENET
, 0);
265 sb_setirq(sbh
, 3, SB_PCI
, 0);
266 sb_setirq(sbh
, 4, SB_USB
, 0);
268 case BCM4785_CHIP_ID
:
269 /* Reassign PCI to irq 4 */
270 sb_setirq(sbh
, 4, SB_PCI
, 0);
276 BCMINITFN(sb_cpu_clock
)(sb_t
*sbh
)
282 uint32 pll_type
, rate
= 0;
284 /* get index of the current core */
285 idx
= sb_coreidx(sbh
);
286 pll_type
= PLL_TYPE1
;
288 /* switch to extif or chipc core */
289 if ((eir
= (extifregs_t
*) sb_setcore(sbh
, SB_EXTIF
, 0))) {
290 n
= R_REG(osh
, &eir
->clockcontrol_n
);
291 m
= R_REG(osh
, &eir
->clockcontrol_sb
);
292 } else if ((cc
= (chipcregs_t
*) sb_setcore(sbh
, SB_CC
, 0))) {
293 pll_type
= R_REG(osh
, &cc
->capabilities
) & CAP_PLL_MASK
;
294 n
= R_REG(osh
, &cc
->clockcontrol_n
);
295 if ((pll_type
== PLL_TYPE2
) ||
296 (pll_type
== PLL_TYPE4
) ||
297 (pll_type
== PLL_TYPE6
) ||
298 (pll_type
== PLL_TYPE7
))
299 m
= R_REG(osh
, &cc
->clockcontrol_m3
);
300 else if (pll_type
== PLL_TYPE5
) {
304 else if (pll_type
== PLL_TYPE3
) {
305 if (sb_chip(sbh
) == BCM5365_CHIP_ID
) {
309 /* 5350 uses m2 to control mips */
311 m
= R_REG(osh
, &cc
->clockcontrol_m2
);
313 m
= R_REG(osh
, &cc
->clockcontrol_sb
);
319 if (BCMINIT(sb_chip
)(sbh
) == 0x5365)
322 rate
= sb_clock_rate(pll_type
, n
, m
);
324 if (pll_type
== PLL_TYPE6
)
325 rate
= SB2MIPS_T6(rate
);
328 /* switch back to previous core */
329 sb_setcoreidx(sbh
, idx
);
334 #define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4)
337 BCMINITFN(handler
)(void)
343 /* Disable interrupts */
344 /* MTC0(C0_STATUS, 0, MFC0(C0_STATUS, 0) & ~(ALLINTS | STO_IE)); */
346 /* Just a Hack to not to use reg 'at' which was causing problems on 4704 A2 */
348 "and $15, $15, $14\n\t"
356 /* The following MUST come right after handler() */
358 BCMINITFN(afterhandler
)(void)
363 * Set the MIPS, backplane and PCI clocks as closely as possible.
365 * MIPS clocks synchronization function has been moved from PLL in chipcommon
366 * core rev. 15 to a DLL inside the MIPS core in 4785.
369 BCMINITFN(sb_mips_setclock
)(sb_t
*sbh
, uint32 mipsclock
, uint32 sbclock
, uint32 pciclock
)
371 extifregs_t
*eir
= NULL
;
372 chipcregs_t
*cc
= NULL
;
373 mipsregs_t
*mipsr
= NULL
;
374 volatile uint32
*clockcontrol_n
, *clockcontrol_sb
, *clockcontrol_pci
, *clockcontrol_m2
;
375 uint32 orig_n
, orig_sb
, orig_pci
, orig_m2
, orig_mips
, orig_ratio_parm
, orig_ratio_cfg
;
376 uint32 pll_type
, sync_mode
;
377 uint ic_size
, ic_lsize
;
380 /* PLL configuration: type 1 */
388 static n3m_table_t
BCMINITDATA(type1_table
)[] = {
389 /* 96.000 32.000 24.000 */
390 { 96000000, 0x0303, 0x04020011, 0x11030011, 0x11050011 },
391 /* 100.000 33.333 25.000 */
392 { 100000000, 0x0009, 0x04020011, 0x11030011, 0x11050011 },
393 /* 104.000 31.200 24.960 */
394 { 104000000, 0x0802, 0x04020011, 0x11050009, 0x11090009 },
395 /* 108.000 32.400 24.923 */
396 { 108000000, 0x0403, 0x04020011, 0x11050009, 0x02000802 },
397 /* 112.000 32.000 24.889 */
398 { 112000000, 0x0205, 0x04020011, 0x11030021, 0x02000403 },
399 /* 115.200 32.000 24.000 */
400 { 115200000, 0x0303, 0x04020009, 0x11030011, 0x11050011 },
401 /* 120.000 30.000 24.000 */
402 { 120000000, 0x0011, 0x04020011, 0x11050011, 0x11090011 },
403 /* 124.800 31.200 24.960 */
404 { 124800000, 0x0802, 0x04020009, 0x11050009, 0x11090009 },
405 /* 128.000 32.000 24.000 */
406 { 128000000, 0x0305, 0x04020011, 0x11050011, 0x02000305 },
407 /* 132.000 33.000 24.750 */
408 { 132000000, 0x0603, 0x04020011, 0x11050011, 0x02000305 },
409 /* 136.000 32.640 24.727 */
410 { 136000000, 0x0c02, 0x04020011, 0x11090009, 0x02000603 },
411 /* 140.000 30.000 24.706 */
412 { 140000000, 0x0021, 0x04020011, 0x11050021, 0x02000c02 },
413 /* 144.000 30.857 24.686 */
414 { 144000000, 0x0405, 0x04020011, 0x01020202, 0x11090021 },
415 /* 150.857 33.000 24.000 */
416 { 150857142, 0x0605, 0x04020021, 0x02000305, 0x02000605 },
417 /* 152.000 32.571 24.000 */
418 { 152000000, 0x0e02, 0x04020011, 0x11050021, 0x02000e02 },
419 /* 156.000 31.200 24.960 */
420 { 156000000, 0x0802, 0x04020005, 0x11050009, 0x11090009 },
421 /* 160.000 32.000 24.000 */
422 { 160000000, 0x0309, 0x04020011, 0x11090011, 0x02000309 },
423 /* 163.200 32.640 24.727 */
424 { 163200000, 0x0c02, 0x04020009, 0x11090009, 0x02000603 },
425 /* 168.000 32.000 24.889 */
426 { 168000000, 0x0205, 0x04020005, 0x11030021, 0x02000403 },
427 /* 176.000 33.000 24.000 */
428 { 176000000, 0x0602, 0x04020003, 0x11050005, 0x02000602 },
431 /* PLL configuration: type 3 */
435 uint32 m2
; /* that is the clockcontrol_m2 */
437 static type3_table_t type3_table
[] = {
438 /* for 5350, mips clock is always double sb clock */
439 { 150000000, 0x311, 0x4020005 },
440 { 200000000, 0x311, 0x4020003 },
443 /* PLL configuration: type 2, 4, 7 */
457 static n4m_table_t
BCMINITDATA(type2_table
)[] = {
458 { 120000000, 60000000, 0x0303, 0x01000200, 0x01000600, 0x01000200, 0x05000200, 11,
459 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 },
460 { 150000000, 75000000, 0x0303, 0x01000100, 0x01000600, 0x01000100, 0x05000100, 11,
461 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 },
462 { 180000000, 80000000, 0x0403, 0x01010000, 0x01020300, 0x01020600, 0x05000100, 8,
463 0x012a00a9, 9 /* ratio 4/9 */, 0x012a00a9 },
464 { 180000000, 90000000, 0x0403, 0x01000100, 0x01020300, 0x01000100, 0x05000100, 11,
465 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 },
466 { 200000000, 100000000, 0x0303, 0x02010000, 0x02040001, 0x02010000, 0x06000001, 11,
467 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 },
468 { 211200000, 105600000, 0x0902, 0x01000200, 0x01030400, 0x01000200, 0x05000200, 11,
469 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 },
470 { 220800000, 110400000, 0x1500, 0x01000200, 0x01030400, 0x01000200, 0x05000200, 11,
471 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 },
472 { 230400000, 115200000, 0x0604, 0x01000200, 0x01020600, 0x01000200, 0x05000200, 11,
473 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 },
474 { 234000000, 104000000, 0x0b01, 0x01010000, 0x01010700, 0x01020600, 0x05000100, 8,
475 0x012a00a9, 9 /* ratio 4/9 */, 0x012a00a9 },
476 { 240000000, 120000000, 0x0803, 0x01000200, 0x01020600, 0x01000200, 0x05000200, 11,
477 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 },
478 { 252000000, 126000000, 0x0504, 0x01000100, 0x01020500, 0x01000100, 0x05000100, 11,
479 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 },
480 { 264000000, 132000000, 0x0903, 0x01000200, 0x01020700, 0x01000200, 0x05000200, 11,
481 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 },
482 { 270000000, 120000000, 0x0703, 0x01010000, 0x01030400, 0x01020600, 0x05000100, 8,
483 0x012a00a9, 9 /* ratio 4/9 */, 0x012a00a9 },
484 { 276000000, 122666666, 0x1500, 0x01010000, 0x01030400, 0x01020600, 0x05000100, 8,
485 0x012a00a9, 9 /* ratio 4/9 */, 0x012a00a9 },
486 { 280000000, 140000000, 0x0503, 0x01000000, 0x01010600, 0x01000000, 0x05000000, 11,
487 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 },
488 { 288000000, 128000000, 0x0604, 0x01010000, 0x01030400, 0x01020600, 0x05000100, 8,
489 0x012a00a9, 9 /* ratio 4/9 */, 0x012a00a9 },
490 { 288000000, 144000000, 0x0404, 0x01000000, 0x01010600, 0x01000000, 0x05000000, 11,
491 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 },
492 { 300000000, 133333333, 0x0803, 0x01010000, 0x01020600, 0x01010100, 0x05000100, 8,
493 0x012a00a9, 9 /* ratio 4/9 */, 0x012a00a9 },
494 { 300000000, 150000000, 0x0803, 0x01000100, 0x01020600, 0x01010100, 0x05000100, 11,
495 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 },
496 { 330000000, 132000000, 0x0903, 0x01000200, 0x00020200, 0x01010100, 0x05000100, 0,
497 0, 10 /* ratio 4/10 */, 0x02520129 },
498 { 330000000, 146666666, 0x0903, 0x01010000, 0x00020200, 0x01010100, 0x05000100, 0,
499 0, 9 /* ratio 4/9 */, 0x012a00a9 },
500 { 330000000, 165000000, 0x0903, 0x01000100, 0x00020200, 0x01010100, 0x05000100, 0,
501 0, 8 /* ratio 4/8 */, 0x00aa0055 },
502 { 360000000, 120000000, 0x0a03, 0x01000300, 0x00010201, 0x01010200, 0x05000100, 0,
503 0, 12 /* ratio 4/12 */, 0x04920492 },
504 { 360000000, 144000000, 0x0a03, 0x01000200, 0x00010201, 0x01010200, 0x05000100, 0,
505 0, 10 /* ratio 4/10 */, 0x02520129 },
506 { 360000000, 160000000, 0x0a03, 0x01010000, 0x00010201, 0x01010200, 0x05000100, 0,
507 0, 9 /* ratio 4/9 */, 0x012a00a9 },
508 { 360000000, 180000000, 0x0a03, 0x01000100, 0x00010201, 0x01010200, 0x05000100, 0,
509 0, 8 /* ratio 4/8 */, 0x00aa0055 },
510 { 390000000, 130000000, 0x0b03, 0x01010100, 0x00020101, 0x01020100, 0x05000100, 0,
511 0, 12 /* ratio 4/12 */, 0x04920492 },
512 { 390000000, 156000000, 0x0b03, 0x01000200, 0x00020101, 0x01020100, 0x05000100, 0,
513 0, 10 /* ratio 4/10 */, 0x02520129 },
514 { 390000000, 173000000, 0x0b03, 0x01010000, 0x00020101, 0x01020100, 0x05000100, 0,
515 0, 9 /* ratio 4/9 */, 0x012a00a9 },
516 { 390000000, 195000000, 0x0b03, 0x01000100, 0x00020101, 0x01020100, 0x05000100, 0,
517 0, 8 /* ratio 4/8 */, 0x00aa0055 },
519 static n4m_table_t
BCMINITDATA(type4_table
)[] = {
520 { 120000000, 60000000, 0x0009, 0x11020009, 0x01030203, 0x11020009, 0x04000009, 11,
522 { 150000000, 75000000, 0x0009, 0x11050002, 0x01030203, 0x11050002, 0x04000005, 11,
524 { 192000000, 96000000, 0x0702, 0x04000011, 0x11030011, 0x04000011, 0x04000003, 11,
526 { 198000000, 99000000, 0x0603, 0x11020005, 0x11030011, 0x11020005, 0x04000005, 11,
528 { 200000000, 100000000, 0x0009, 0x04020011, 0x11030011, 0x04020011, 0x04020003, 11,
530 { 204000000, 102000000, 0x0c02, 0x11020005, 0x01030303, 0x11020005, 0x04000005, 11,
532 { 208000000, 104000000, 0x0802, 0x11030002, 0x11090005, 0x11030002, 0x04000003, 11,
534 { 210000000, 105000000, 0x0209, 0x11020005, 0x01030303, 0x11020005, 0x04000005, 11,
536 { 216000000, 108000000, 0x0111, 0x11020005, 0x01030303, 0x11020005, 0x04000005, 11,
538 { 224000000, 112000000, 0x0205, 0x11030002, 0x02002103, 0x11030002, 0x04000003, 11,
540 { 228000000, 101333333, 0x0e02, 0x11030003, 0x11210005, 0x01030305, 0x04000005, 8,
542 { 228000000, 114000000, 0x0e02, 0x11020005, 0x11210005, 0x11020005, 0x04000005, 11,
544 { 240000000, 102857143, 0x0109, 0x04000021, 0x01050203, 0x11030021, 0x04000003, 13,
546 { 240000000, 120000000, 0x0109, 0x11030002, 0x01050203, 0x11030002, 0x04000003, 11,
548 { 252000000, 100800000, 0x0203, 0x04000009, 0x11050005, 0x02000209, 0x04000002, 9,
550 { 252000000, 126000000, 0x0203, 0x04000005, 0x11050005, 0x04000005, 0x04000002, 11,
552 { 264000000, 132000000, 0x0602, 0x04000005, 0x11050005, 0x04000005, 0x04000002, 11,
554 { 272000000, 116571428, 0x0c02, 0x04000021, 0x02000909, 0x02000221, 0x04000003, 13,
556 { 280000000, 120000000, 0x0209, 0x04000021, 0x01030303, 0x02000221, 0x04000003, 13,
558 { 288000000, 123428571, 0x0111, 0x04000021, 0x01030303, 0x02000221, 0x04000003, 13,
560 { 300000000, 120000000, 0x0009, 0x04000009, 0x01030203, 0x02000902, 0x04000002, 9,
562 { 300000000, 150000000, 0x0009, 0x04000005, 0x01030203, 0x04000005, 0x04000002, 11,
565 static n4m_table_t
BCMINITDATA(type7_table
)[] = {
566 { 183333333, 91666666, 0x0605, 0x04000011, 0x11030011, 0x04000011, 0x04000003, 11,
568 { 187500000, 93750000, 0x0a03, 0x04000011, 0x11030011, 0x04000011, 0x04000003, 11,
570 { 196875000, 98437500, 0x1003, 0x11020005, 0x11050011, 0x11020005, 0x04000005, 11,
572 { 200000000, 100000000, 0x0311, 0x04000011, 0x11030011, 0x04000009, 0x04000003, 11,
574 { 200000000, 100000000, 0x0311, 0x04020011, 0x11030011, 0x04020011, 0x04020003, 11,
576 { 206250000, 103125000, 0x1103, 0x11020005, 0x11050011, 0x11020005, 0x04000005, 11,
578 { 212500000, 106250000, 0x0c05, 0x11020005, 0x01030303, 0x11020005, 0x04000005, 11,
580 { 215625000, 107812500, 0x1203, 0x11090009, 0x11050005, 0x11020005, 0x04000005, 11,
582 { 216666666, 108333333, 0x0805, 0x11020003, 0x11030011, 0x11020003, 0x04000003, 11,
584 { 225000000, 112500000, 0x0d03, 0x11020003, 0x11030011, 0x11020003, 0x04000003, 11,
586 { 233333333, 116666666, 0x0905, 0x11020003, 0x11030011, 0x11020003, 0x04000003, 11,
588 { 237500000, 118750000, 0x0e05, 0x11020005, 0x11210005, 0x11020005, 0x04000005, 11,
590 { 240000000, 120000000, 0x0b11, 0x11020009, 0x11210009, 0x11020009, 0x04000009, 11,
592 { 250000000, 125000000, 0x0f03, 0x11020003, 0x11210003, 0x11020003, 0x04000003, 11,
596 ulong start
, end
, dst
;
599 volatile uint32
*dll_ctrl
= (volatile uint32
*)0xff400008;
600 volatile uint32
*dll_r1
= (volatile uint32
*)0xff400010;
601 volatile uint32
*dll_r2
= (volatile uint32
*)0xff400018;
603 /* get index of the current core */
604 idx
= sb_coreidx(sbh
);
605 clockcontrol_m2
= NULL
;
607 /* switch to extif or chipc core */
608 if ((eir
= (extifregs_t
*) sb_setcore(sbh
, SB_EXTIF
, 0))) {
609 pll_type
= PLL_TYPE1
;
610 clockcontrol_n
= &eir
->clockcontrol_n
;
611 clockcontrol_sb
= &eir
->clockcontrol_sb
;
612 clockcontrol_pci
= &eir
->clockcontrol_pci
;
613 clockcontrol_m2
= &cc
->clockcontrol_m2
;
614 } else if ((cc
= (chipcregs_t
*) sb_setcore(sbh
, SB_CC
, 0))) {
615 pll_type
= R_REG(osh
, &cc
->capabilities
) & CAP_PLL_MASK
;
616 if (pll_type
== PLL_TYPE6
) {
617 clockcontrol_n
= NULL
;
618 clockcontrol_sb
= NULL
;
619 clockcontrol_pci
= NULL
;
621 clockcontrol_n
= &cc
->clockcontrol_n
;
622 clockcontrol_sb
= &cc
->clockcontrol_sb
;
623 clockcontrol_pci
= &cc
->clockcontrol_pci
;
624 clockcontrol_m2
= &cc
->clockcontrol_m2
;
629 if (pll_type
== PLL_TYPE6
) {
630 /* Silence compilers */
631 orig_n
= orig_sb
= orig_pci
= 0;
633 /* Store the current clock register values */
634 orig_n
= R_REG(osh
, clockcontrol_n
);
635 orig_sb
= R_REG(osh
, clockcontrol_sb
);
636 orig_pci
= R_REG(osh
, clockcontrol_pci
);
639 if (pll_type
== PLL_TYPE1
) {
640 /* Keep the current PCI clock if not specified */
642 pciclock
= sb_clock_rate(pll_type
, R_REG(osh
, clockcontrol_n
),
643 R_REG(osh
, clockcontrol_pci
));
644 pciclock
= (pciclock
<= 25000000) ? 25000000 : 33000000;
647 /* Search for the closest MIPS clock less than or equal to a preferred value */
648 for (i
= 0; i
< ARRAYSIZE(type1_table
); i
++) {
649 ASSERT(type1_table
[i
].mipsclock
==
650 sb_clock_rate(pll_type
, type1_table
[i
].n
,
652 if (type1_table
[i
].mipsclock
> mipsclock
)
662 ASSERT(type1_table
[i
].mipsclock
<= mipsclock
);
665 if ((orig_n
== type1_table
[i
].n
) &&
666 (orig_sb
== type1_table
[i
].sb
) &&
667 (orig_pci
== type1_table
[i
].pci33
))
670 /* Set the PLL controls */
671 W_REG(osh
, clockcontrol_n
, type1_table
[i
].n
);
672 W_REG(osh
, clockcontrol_sb
, type1_table
[i
].sb
);
673 if (pciclock
== 25000000)
674 W_REG(osh
, clockcontrol_pci
, type1_table
[i
].pci25
);
676 W_REG(osh
, clockcontrol_pci
, type1_table
[i
].pci33
);
681 } else if (pll_type
== PLL_TYPE3
) {
683 if (sb_chip(sbh
) != BCM5365_CHIP_ID
) {
685 * Search for the closest MIPS clock less than or equal to
688 for (i
= 0; i
< ARRAYSIZE(type3_table
); i
++) {
689 if (type3_table
[i
].mipsclock
> mipsclock
)
699 ASSERT(type3_table
[i
].mipsclock
<= mipsclock
);
702 orig_m2
= R_REG(osh
, &cc
->clockcontrol_m2
);
703 if ((orig_n
== type3_table
[i
].n
) &&
704 (orig_m2
== type3_table
[i
].m2
)) {
708 /* Set the PLL controls */
709 W_REG(osh
, clockcontrol_n
, type3_table
[i
].n
);
710 W_REG(osh
, clockcontrol_m2
, type3_table
[i
].m2
);
716 } else if ((pll_type
== PLL_TYPE2
) ||
717 (pll_type
== PLL_TYPE4
) ||
718 (pll_type
== PLL_TYPE6
) ||
719 (pll_type
== PLL_TYPE7
)) {
720 n4m_table_t
*table
= NULL
, *te
;
725 orig_mips
= R_REG(osh
, &cc
->clockcontrol_m3
);
732 if (mipsclock
<= SB2MIPS_T6(CC_T6_M1
))
733 new_mips
= CC_T6_MMASK
;
735 if (orig_mips
== new_mips
)
738 W_REG(osh
, &cc
->clockcontrol_m3
, new_mips
);
743 tabsz
= ARRAYSIZE(type2_table
);
747 tabsz
= ARRAYSIZE(type4_table
);
751 tabsz
= ARRAYSIZE(type7_table
);
754 ASSERT("No table for plltype" == NULL
);
758 /* Store the current clock register values */
759 orig_m2
= R_REG(osh
, &cc
->clockcontrol_m2
);
763 /* Look up current ratio */
764 for (i
= 0; i
< tabsz
; i
++) {
765 if ((orig_n
== table
[i
].n
) &&
766 (orig_sb
== table
[i
].sb
) &&
767 (orig_pci
== table
[i
].pci33
) &&
768 (orig_m2
== table
[i
].m2
) &&
769 (orig_mips
== table
[i
].m3
)) {
770 orig_ratio_parm
= table
[i
].ratio_parm
;
771 orig_ratio_cfg
= table
[i
].ratio_cfg
;
776 /* Search for the closest MIPS clock greater or equal to a preferred value */
777 for (i
= 0; i
< tabsz
; i
++) {
778 ASSERT(table
[i
].mipsclock
==
779 sb_clock_rate(pll_type
, table
[i
].n
, table
[i
].m3
));
780 if ((mipsclock
<= table
[i
].mipsclock
) &&
781 ((sbclock
== 0) || (sbclock
<= table
[i
].sbclock
)))
793 if ((orig_n
== te
->n
) &&
794 (orig_sb
== te
->sb
) &&
795 (orig_pci
== te
->pci33
) &&
796 (orig_m2
== te
->m2
) &&
797 (orig_mips
== te
->m3
))
800 /* Set the PLL controls */
801 W_REG(osh
, clockcontrol_n
, te
->n
);
802 W_REG(osh
, clockcontrol_sb
, te
->sb
);
803 W_REG(osh
, clockcontrol_pci
, te
->pci33
);
804 W_REG(osh
, &cc
->clockcontrol_m2
, te
->m2
);
805 W_REG(osh
, &cc
->clockcontrol_m3
, te
->m3
);
807 /* Set the chipcontrol bit to change mipsref to the backplane divider if needed */
808 if ((pll_type
== PLL_TYPE7
) && (te
->sb
!= te
->m2
) &&
809 (sb_clock_rate(pll_type
, te
->n
, te
->m2
) == 120000000))
810 W_REG(osh
, &cc
->chipcontrol
,
811 R_REG(osh
, &cc
->chipcontrol
) | 0x100);
813 /* No ratio change */
814 if (sb_chip(sbh
) != BCM4785_CHIP_ID
) {
815 if (orig_ratio_parm
== te
->ratio_parm
)
819 /* Preload the code into the cache */
820 icache_probe(MFC0(C0_CONFIG
, 1), &ic_size
, &ic_lsize
);
821 if (sb_chip(sbh
) == BCM4785_CHIP_ID
) {
822 start
= ((ulong
) &&start_fill_4785
) & ~(ic_lsize
- 1);
823 end
= ((ulong
) &&end_fill_4785
+ (ic_lsize
- 1)) & ~(ic_lsize
- 1);
826 start
= ((ulong
) &&start_fill
) & ~(ic_lsize
- 1);
827 end
= ((ulong
) &&end_fill
+ (ic_lsize
- 1)) & ~(ic_lsize
- 1);
829 while (start
< end
) {
830 cache_op(start
, Fill_I
);
834 /* Copy the handler */
835 start
= (ulong
) &handler
;
836 end
= (ulong
) &afterhandler
;
837 dst
= KSEG1ADDR(0x180);
838 for (i
= 0; i
< (end
- start
); i
+= 4)
839 *((ulong
*)(dst
+ i
)) = *((ulong
*)(start
+ i
));
841 /* Preload the handler into the cache one line at a time */
842 for (i
= 0; i
< (end
- start
); i
+= ic_lsize
)
843 cache_op(dst
+ i
, Fill_I
);
846 MTC0(C0_STATUS
, 0, MFC0(C0_STATUS
, 0) & ~ST0_BEV
);
848 /* Enable interrupts */
849 MTC0(C0_STATUS
, 0, MFC0(C0_STATUS
, 0) | (ALLINTS
| ST0_IE
));
851 /* 4785 clock freq change procedures */
852 if (sb_chip(sbh
) == BCM4785_CHIP_ID
) {
854 /* Switch to async */
855 MTC0(C0_BROADCOM
, 4, (1 << 22));
857 /* Set clock ratio in MIPS */
858 *dll_r1
= (*dll_r1
& 0xfffffff0) | (te
->d11_r1
- 1);
859 *dll_r2
= te
->d11_r2
;
861 /* Enable new settings in MIPS */
862 *dll_r1
= *dll_r1
| 0xc0000000;
865 MTC0(C0_BROADCOM
, 2, MFC0(C0_BROADCOM
, 2) | (1 << 3) | 1);
867 /* Fake soft reset (clock cfg registers not reset) */
868 MTC0(C0_BROADCOM
, 5, MFC0(C0_BROADCOM
, 5) | (1 << 2));
870 /* Clear active cfg */
871 MTC0(C0_BROADCOM
, 2, MFC0(C0_BROADCOM
, 2) & ~(1 << 3));
873 /* set watchdog timer */
874 W_REG(osh
, &cc
->watchdog
, 20);
875 (void) R_REG(osh
, &cc
->chipid
);
877 /* wait for timer interrupt */
878 __asm__
__volatile__(
886 /* Generic clock freq change procedures */
888 /* Enable MIPS timer interrupt */
889 if (!(mipsr
= sb_setcore(sbh
, SB_MIPS
, 0)) &&
890 !(mipsr
= sb_setcore(sbh
, SB_MIPS33
, 0)))
892 W_REG(osh
, &mipsr
->intmask
, 1);
895 /* step 1, set clock ratios */
896 MTC0(C0_BROADCOM
, 3, te
->ratio_parm
);
897 MTC0(C0_BROADCOM
, 1, te
->ratio_cfg
);
899 /* step 2: program timer intr */
900 W_REG(osh
, &mipsr
->timer
, 100);
901 (void) R_REG(osh
, &mipsr
->timer
);
903 /* step 3, switch to async */
904 sync_mode
= MFC0(C0_BROADCOM
, 4);
905 MTC0(C0_BROADCOM
, 4, 1 << 22);
907 /* step 4, set cfg active */
908 MTC0(C0_BROADCOM
, 2, (1 << 3) | 1);
911 __asm__
__volatile__(
916 /* step 7, clear cfg active */
917 MTC0(C0_BROADCOM
, 2, 0);
919 /* Additional Step: set back to orig sync mode */
920 MTC0(C0_BROADCOM
, 4, sync_mode
);
922 /* step 8, fake soft reset */
923 MTC0(C0_BROADCOM
, 5, MFC0(C0_BROADCOM
, 5) | (1 << 2));
926 /* set watchdog timer */
927 W_REG(osh
, &cc
->watchdog
, 20);
928 (void) R_REG(osh
, &cc
->chipid
);
930 /* wait for timer interrupt */
931 __asm__
__volatile__(
941 /* Enable 4785 DLL */
942 if (sb_chip(sbh
) == BCM4785_CHIP_ID
) {
945 /* set mask to 1e, enable DLL (bit 0) */
946 *dll_ctrl
|= 0x0041e021;
948 /* enable aggressive hardware mode */
949 *dll_ctrl
|= 0x00000080;
951 /* wait for lock flag to clear */
952 while ((*dll_ctrl
& 0x2) == 0);
954 /* clear sticky flags (clear on write 1) */
958 /* set mask to 5b'10001 */
959 *dll_ctrl
= (*dll_ctrl
& 0xfffc1fff) | 0x00022000;
961 /* enable sync mode */
962 MTC0(C0_BROADCOM
, 4, MFC0(C0_BROADCOM
, 4) & 0xfe3fffff);
963 (void)MFC0(C0_BROADCOM
, 4);
966 /* switch back to previous core */
967 sb_setcoreidx(sbh
, idx
);
973 BCMINITFN(enable_pfc
)(uint32 mode
)
976 uint ic_size
, ic_lsize
;
978 /* If auto then choose the correct mode for this
979 * platform, currently we only ever select one mode
981 if (mode
== PFC_AUTO
)
984 icache_probe(MFC0(C0_CONFIG
, 1), &ic_size
, &ic_lsize
);
986 /* enable prefetch cache if available */
987 if (MFC0(C0_BROADCOM
, 0) & BRCM_PFC_AVAIL
) {
988 start
= ((ulong
) &&setpfc_start
) & ~(ic_lsize
- 1);
989 end
= ((ulong
) &&setpfc_end
+ (ic_lsize
- 1)) & ~(ic_lsize
- 1);
991 /* Preload setpfc code into the cache one line at a time */
992 while (start
< end
) {
993 cache_op(start
, Fill_I
);
997 /* Now set the pfc */
1000 *(volatile uint32
*)PFC_CR1
= 0xffff0000;
1003 *(volatile uint32
*)PFC_CR0
= mode
;
1005 /* Compiler foder */
1010 /* returns the ncdl value to be programmed into sdram_ncdl for calibration */
1012 BCMINITFN(sb_memc_get_ncdl
)(sb_t
*sbh
)
1017 uint32 config
, rd
, wr
, misc
, dqsg
, cd
, sm
, sd
;
1022 idx
= sb_coreidx(sbh
);
1024 memc
= (sbmemcregs_t
*)sb_setcore(sbh
, SB_MEMC
, 0);
1028 rev
= sb_corerev(sbh
);
1030 config
= R_REG(osh
, &memc
->config
);
1031 wr
= R_REG(osh
, &memc
->wrncdlcor
);
1032 rd
= R_REG(osh
, &memc
->rdncdlcor
);
1033 misc
= R_REG(osh
, &memc
->miscdlyctl
);
1034 dqsg
= R_REG(osh
, &memc
->dqsgatencdl
);
1036 rd
&= MEMC_RDNCDLCOR_RD_MASK
;
1037 wr
&= MEMC_WRNCDLCOR_WR_MASK
;
1038 dqsg
&= MEMC_DQSGATENCDL_G_MASK
;
1040 if (config
& MEMC_CONFIG_DDR
) {
1041 ret
= (wr
<< 16) | (rd
<< 8) | dqsg
;
1046 cd
= (rd
== MEMC_CD_THRESHOLD
) ? rd
: (wr
+ MEMC_CD_THRESHOLD
);
1047 sm
= (misc
& MEMC_MISC_SM_MASK
) >> MEMC_MISC_SM_SHIFT
;
1048 sd
= (misc
& MEMC_MISC_SD_MASK
) >> MEMC_MISC_SD_SHIFT
;
1049 ret
= (sm
<< 16) | (sd
<< 8) | cd
;
1053 /* switch back to previous core */
1054 sb_setcoreidx(sbh
, idx
);
1059 #if defined(BCMPERFSTATS)
1061 * CP0 Register 25 supports 4 semi-independent 32bit performance counters.
1062 * $25 select 0, 1, 2, and 3 are the counters. The counters *decrement* (who thought this one up?)
1063 * $25 select 4 and 5 each contain 2-16bit control fields, one for each of the 4 counters
1064 * $25 select 6 is the global perf control register.
1066 /* enable and start instruction counting */
1069 hndmips_perf_instrcount_enable()
1071 MTC0(C0_PERFORMANCE
, 6, 0x80000200); /* global enable perf counters */
1072 MTC0(C0_PERFORMANCE
, 4,
1073 0x8044 | MFC0(C0_PERFORMANCE
, 4)); /* enable instruction counting for counter 0 */
1074 MTC0(C0_PERFORMANCE
, 0, 0); /* zero counter zero */
1077 /* enable and start I$ hit and I$ miss counting */
1079 hndmips_perf_icachecount_enable(void)
1081 MTC0(C0_PERFORMANCE
, 6, 0x80000218); /* enable I$ counting */
1082 MTC0(C0_PERFORMANCE
, 4, 0x80148018); /* count I$ hits in cntr 0 and misses in cntr 1 */
1083 MTC0(C0_PERFORMANCE
, 0, 0); /* zero counter 0 - # I$ hits */
1084 MTC0(C0_PERFORMANCE
, 1, 0); /* zero counter 1 - # I$ misses */
1087 /* enable and start D$ hit and I$ miss counting */
1089 hndmips_perf_dcachecount_enable(void)
1091 MTC0(C0_PERFORMANCE
, 6, 0x80000211); /* enable D$ counting */
1092 MTC0(C0_PERFORMANCE
, 4, 0x80248028); /* count D$ hits in cntr 0 and misses in cntr 1 */
1093 MTC0(C0_PERFORMANCE
, 0, 0); /* zero counter 0 - # D$ hits */
1094 MTC0(C0_PERFORMANCE
, 1, 0); /* zero counter 1 - # D$ misses */
1098 hndmips_perf_icache_miss_enable()
1100 MTC0(C0_PERFORMANCE
, 4,
1101 0x80140000 | MFC0(C0_PERFORMANCE
, 4)); /* enable cache misses counting for counter 1 */
1102 MTC0(C0_PERFORMANCE
, 1, 0); /* zero counter one */
1107 hndmips_perf_icache_hit_enable()
1109 MTC0(C0_PERFORMANCE
, 5, 0x8018 | MFC0(C0_PERFORMANCE
, 5));
1110 /* enable cache hits counting for counter 2 */
1111 MTC0(C0_PERFORMANCE
, 2, 0); /* zero counter 2 */
1115 hndmips_perf_read_instrcount()
1117 return -(long)(MFC0(C0_PERFORMANCE
, 0));
1121 hndmips_perf_read_cache_miss()
1123 return -(long)(MFC0(C0_PERFORMANCE
, 1));
1127 hndmips_perf_read_cache_hit()
1129 return -(long)(MFC0(C0_PERFORMANCE
, 2));
1132 #endif /* BCMINTERNAL | BCMPERFSTATS */