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.
27 #include <sbhndmips.h>
31 /* sbipsflag register format, indexed by irq. */
32 static const uint32 sbips_int_mask
[] = {
40 static const uint32 sbips_int_shift
[] = {
49 * Map SB cores sharing the MIPS hardware IRQ0 to virtual dedicated OS IRQs.
50 * Per-port BSP code is required to provide necessary translations between
51 * the shared MIPS IRQ and the virtual OS IRQs based on SB core flag.
53 * See sb_irq() for the mapping.
55 static uint shirq_map_base
= 0;
58 * Returns the MIPS IRQ assignment of the current core. If unassigned,
68 uint32 flag
, sbipsflag
;
74 idx
= sb_coreidx(sbh
);
76 if ((regs
= sb_setcore(sbh
, SB_MIPS33
, 0)) != NULL
) {
77 sb
= (sbconfig_t
*)((ulong
) regs
+ SBCONFIGOFF
);
79 /* sbipsflag specifies which core is routed to interrupts 1 to 4 */
80 sbipsflag
= R_REG(osh
, &sb
->sbipsflag
);
81 for (irq
= 1; irq
<= 4; irq
++) {
82 if (((sbipsflag
& sbips_int_mask
[irq
]) >> sbips_int_shift
[irq
]) == flag
)
89 sb_setcoreidx(sbh
, idx
);
95 * Return the MIPS IRQ assignment of the current core. If necessary
96 * map cores sharing the MIPS hw IRQ0 to virtual dedicated OS IRQs.
101 uint irq
= sb_getirq(sbh
);
102 if (irq
== 0 && shirq_map_base
)
103 irq
= sb_flag(sbh
) + shirq_map_base
;
107 /* Clears the specified MIPS IRQ. */
109 BCMINITFN(sb_clearirq
)(sb_t
*sbh
, uint irq
)
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
)
144 regs
= sb_setcore(sbh
, coreid
, coreunit
);
147 oldirq
= sb_getirq(sbh
);
149 sb_clearirq(sbh
, oldirq
);
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.
175 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 cc
= sb_setcore(sbh
, SB_CC
, 0);
193 /* Set timing for the flash */
194 tmp
= CEIL(10, ns
) << FW_W3_SHIFT
; /* W3 = 10nS */
195 tmp
|= CEIL(10, ns
) << FW_W1_SHIFT
; /* W1 = 10nS */
196 tmp
|= CEIL(120, ns
); /* W0 = 120nS */
197 if ((sbh
->ccrev
< 9) ||
198 (sb_chip(sbh
) == BCM5365_CHIP_ID
))
199 W_REG(osh
, &cc
->flash_waitcount
, tmp
);
201 if ((sbh
->ccrev
< 9) ||
202 (sb_chip(sbh
) == BCM5365_CHIP_ID
) ||
203 ((sb_chip(sbh
) == BCM5350_CHIP_ID
) && sb_chiprev(sbh
) == 0)) {
204 W_REG(osh
, &cc
->pcmcia_memwait
, tmp
);
207 /* Save shared IRQ mapping base */
208 shirq_map_base
= shirqmap
;
210 /* Chip specific initialization */
211 switch (sb_chip(sbh
)) {
212 case BCM5350_CHIP_ID
:
213 /* Clear interrupt map */
214 for (irq
= 0; irq
<= 4; irq
++)
215 sb_clearirq(sbh
, irq
);
216 sb_setirq(sbh
, 0, SB_CC
, 0);
217 sb_setirq(sbh
, 0, SB_MIPS33
, 0);
218 sb_setirq(sbh
, 1, SB_D11
, 0);
219 sb_setirq(sbh
, 2, SB_ENET
, 0);
220 sb_setirq(sbh
, 3, SB_PCI
, 0);
221 sb_setirq(sbh
, 4, SB_USB
, 0);
223 case BCM4785_CHIP_ID
:
224 /* Reassign PCI to irq 4 */
225 sb_setirq(sbh
, 4, SB_PCI
, 0);
230 /* Do any setup necessary to run a new image and jump to it. */
232 hnd_cpu_jumpto(void *addr
)
234 void (*jumpto
)(void) = addr
;
240 BCMINITFN(sb_cpu_clock
)(sb_t
*sbh
)
245 uint32 pll_type
, rate
= 0;
247 /* get index of the current core */
248 idx
= sb_coreidx(sbh
);
249 pll_type
= PLL_TYPE1
;
251 /* switch to chipc core */
252 cc
= (chipcregs_t
*) sb_setcore(sbh
, SB_CC
, 0);
255 /* 5354 chip uses a non programmable PLL of frequency 240MHz */
256 if (sb_chip(sbh
) == BCM5354_CHIP_ID
) {
261 pll_type
= sbh
->cccaps
& CC_CAP_PLL_MASK
;
262 n
= R_REG(osh
, &cc
->clockcontrol_n
);
263 if ((pll_type
== PLL_TYPE2
) ||
264 (pll_type
== PLL_TYPE4
) ||
265 (pll_type
== PLL_TYPE6
) ||
266 (pll_type
== PLL_TYPE7
))
267 m
= R_REG(osh
, &cc
->clockcontrol_m3
);
268 else if (pll_type
== PLL_TYPE5
) {
271 } else if (pll_type
== PLL_TYPE3
) {
272 if (sb_chip(sbh
) == BCM5365_CHIP_ID
) {
276 /* 5350 uses m2 to control mips */
278 m
= R_REG(osh
, &cc
->clockcontrol_m2
);
280 m
= R_REG(osh
, &cc
->clockcontrol_sb
);
283 rate
= sb_clock_rate(pll_type
, n
, m
);
285 if (pll_type
== PLL_TYPE6
)
286 rate
= SB2MIPS_T6(rate
);
289 /* switch back to previous core */
290 sb_setcoreidx(sbh
, idx
);
295 #define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4)
298 BCMINITFN(handler
)(void)
304 /* Disable interrupts */
305 /* MTC0(C0_STATUS, 0, MFC0(C0_STATUS, 0) & ~(ALLINTS | STO_IE)); */
307 /* Just a Hack to not to use reg 'at' which was causing problems on 4704 A2 */
309 "and $15, $15, $14\n\t"
317 /* The following MUST come right after handler() */
319 BCMINITFN(afterhandler
)(void)
324 * Set the MIPS, backplane and PCI clocks as closely as possible.
326 * MIPS clocks synchronization function has been moved from PLL in chipcommon
327 * core rev. 15 to a DLL inside the MIPS core in 4785.
330 BCMINITFN(sb_mips_setclock
)(sb_t
*sbh
, uint32 mipsclock
, uint32 sbclock
, uint32 pciclock
)
332 chipcregs_t
*cc
= NULL
;
333 mipsregs_t
*mipsr
= NULL
;
334 volatile uint32
*clockcontrol_n
, *clockcontrol_sb
, *clockcontrol_pci
, *clockcontrol_m2
;
335 uint32 orig_n
, orig_sb
, orig_pci
, orig_m2
, orig_mips
, orig_ratio_parm
, orig_ratio_cfg
;
336 uint32 pll_type
, sync_mode
;
337 uint ic_size
, ic_lsize
;
340 /* PLL configuration: type 1 */
348 static n3m_table_t
BCMINITDATA(type1_table
)[] = {
349 /* 96.000 32.000 24.000 */
350 { 96000000, 0x0303, 0x04020011, 0x11030011, 0x11050011 },
351 /* 100.000 33.333 25.000 */
352 { 100000000, 0x0009, 0x04020011, 0x11030011, 0x11050011 },
353 /* 104.000 31.200 24.960 */
354 { 104000000, 0x0802, 0x04020011, 0x11050009, 0x11090009 },
355 /* 108.000 32.400 24.923 */
356 { 108000000, 0x0403, 0x04020011, 0x11050009, 0x02000802 },
357 /* 112.000 32.000 24.889 */
358 { 112000000, 0x0205, 0x04020011, 0x11030021, 0x02000403 },
359 /* 115.200 32.000 24.000 */
360 { 115200000, 0x0303, 0x04020009, 0x11030011, 0x11050011 },
361 /* 120.000 30.000 24.000 */
362 { 120000000, 0x0011, 0x04020011, 0x11050011, 0x11090011 },
363 /* 124.800 31.200 24.960 */
364 { 124800000, 0x0802, 0x04020009, 0x11050009, 0x11090009 },
365 /* 128.000 32.000 24.000 */
366 { 128000000, 0x0305, 0x04020011, 0x11050011, 0x02000305 },
367 /* 132.000 33.000 24.750 */
368 { 132000000, 0x0603, 0x04020011, 0x11050011, 0x02000305 },
369 /* 136.000 32.640 24.727 */
370 { 136000000, 0x0c02, 0x04020011, 0x11090009, 0x02000603 },
371 /* 140.000 30.000 24.706 */
372 { 140000000, 0x0021, 0x04020011, 0x11050021, 0x02000c02 },
373 /* 144.000 30.857 24.686 */
374 { 144000000, 0x0405, 0x04020011, 0x01020202, 0x11090021 },
375 /* 150.857 33.000 24.000 */
376 { 150857142, 0x0605, 0x04020021, 0x02000305, 0x02000605 },
377 /* 152.000 32.571 24.000 */
378 { 152000000, 0x0e02, 0x04020011, 0x11050021, 0x02000e02 },
379 /* 156.000 31.200 24.960 */
380 { 156000000, 0x0802, 0x04020005, 0x11050009, 0x11090009 },
381 /* 160.000 32.000 24.000 */
382 { 160000000, 0x0309, 0x04020011, 0x11090011, 0x02000309 },
383 /* 163.200 32.640 24.727 */
384 { 163200000, 0x0c02, 0x04020009, 0x11090009, 0x02000603 },
385 /* 168.000 32.000 24.889 */
386 { 168000000, 0x0205, 0x04020005, 0x11030021, 0x02000403 },
387 /* 176.000 33.000 24.000 */
388 { 176000000, 0x0602, 0x04020003, 0x11050005, 0x02000602 },
391 /* PLL configuration: type 3 */
395 uint32 m2
; /* that is the clockcontrol_m2 */
397 static type3_table_t type3_table
[] = {
398 /* for 5350, mips clock is always double sb clock */
399 { 150000000, 0x311, 0x4020005 },
400 { 200000000, 0x311, 0x4020003 },
403 /* PLL configuration: type 2, 4, 7 */
418 static n4m_table_t
BCMINITDATA(type2_table
)[] = {
419 { 120000000, 60000000, 32000000, 0x0303, 0x01000200, 0x01000600, 0x01000200,
420 0x05000200, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 },
421 { 150000000, 75000000, 33333333, 0x0303, 0x01000100, 0x01000600, 0x01000100,
422 0x05000100, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 },
423 { 180000000, 80000000, 30000000, 0x0403, 0x01010000, 0x01020300, 0x01020600,
424 0x05000100, 8, 0x012a00a9, 9 /* ratio 4/9 */, 0x012a00a9 },
425 { 180000000, 90000000, 30000000, 0x0403, 0x01000100, 0x01020300, 0x01000100,
426 0x05000100, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 },
427 { 200000000, 100000000, 33333333, 0x0303, 0x02010000, 0x02040001, 0x02010000,
428 0x06000001, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 },
429 { 211200000, 105600000, 30171428, 0x0902, 0x01000200, 0x01030400, 0x01000200,
430 0x05000200, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 },
431 { 220800000, 110400000, 31542857, 0x1500, 0x01000200, 0x01030400, 0x01000200,
432 0x05000200, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 },
433 { 230400000, 115200000, 32000000, 0x0604, 0x01000200, 0x01020600, 0x01000200,
434 0x05000200, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 },
435 { 234000000, 104000000, 31200000, 0x0b01, 0x01010000, 0x01010700, 0x01020600,
436 0x05000100, 8, 0x012a00a9, 9 /* ratio 4/9 */, 0x012a00a9 },
437 { 240000000, 120000000, 33333333, 0x0803, 0x01000200, 0x01020600, 0x01000200,
438 0x05000200, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 },
439 { 252000000, 126000000, 33333333, 0x0504, 0x01000100, 0x01020500, 0x01000100,
440 0x05000100, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 },
441 { 264000000, 132000000, 33000000, 0x0903, 0x01000200, 0x01020700, 0x01000200,
442 0x05000200, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 },
443 { 270000000, 120000000, 30000000, 0x0703, 0x01010000, 0x01030400, 0x01020600,
444 0x05000100, 8, 0x012a00a9, 9 /* ratio 4/9 */, 0x012a00a9 },
445 { 276000000, 122666666, 31542857, 0x1500, 0x01010000, 0x01030400, 0x01020600,
446 0x05000100, 8, 0x012a00a9, 9 /* ratio 4/9 */, 0x012a00a9 },
447 { 280000000, 140000000, 31111111, 0x0503, 0x01000000, 0x01010600, 0x01000000,
448 0x05000000, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 },
449 { 288000000, 128000000, 32914285, 0x0604, 0x01010000, 0x01030400, 0x01020600,
450 0x05000100, 8, 0x012a00a9, 9 /* ratio 4/9 */, 0x012a00a9 },
451 { 288000000, 144000000, 32000000, 0x0404, 0x01000000, 0x01010600, 0x01000000,
452 0x05000000, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 },
453 { 300000000, 133333333, 33333333, 0x0803, 0x01010000, 0x01020600, 0x01010100,
454 0x05000100, 8, 0x012a00a9, 9 /* ratio 4/9 */, 0x012a00a9 },
455 { 300000000, 133333333, 37500000, 0x0803, 0x01010000, 0x01020500, 0x01010100,
456 0x05000100, 8, 0x012a00a9, 9 /* ratio 4/9 */, 0x012a00a9 },
457 { 300000000, 133333333, 42857142, 0x0803, 0x01010000, 0x01020400, 0x01010100,
458 0x05000100, 8, 0x012a00a9, 9 /* ratio 4/9 */, 0x012a00a9 },
459 { 300000000, 133333333, 50000000, 0x0803, 0x01010000, 0x01020300, 0x01010100,
460 0x05000100, 8, 0x012a00a9, 9 /* ratio 4/9 */, 0x012a00a9 },
461 { 300000000, 133333333, 60000000, 0x0803, 0x01010000, 0x01020200, 0x01010100,
462 0x05000100, 8, 0x012a00a9, 9 /* ratio 4/9 */, 0x012a00a9 },
463 { 300000000, 150000000, 33333333, 0x0803, 0x01000100, 0x01020600, 0x01010100,
464 0x05000100, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 },
465 { 300000000, 150000000, 37500000, 0x0803, 0x01000100, 0x01020500, 0x01010100,
466 0x05000100, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 },
467 { 300000000, 150000000, 42857142, 0x0803, 0x01000100, 0x01020400, 0x01010100,
468 0x05000100, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 },
469 { 300000000, 150000000, 50000000, 0x0803, 0x01000100, 0x01020300, 0x01010100,
470 0x05000100, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 },
471 { 300000000, 150000000, 60000000, 0x0803, 0x01000100, 0x01020200, 0x01010100,
472 0x05000100, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 },
473 { 330000000, 132000000, 33000000, 0x0903, 0x01000200, 0x00020200, 0x01010100,
474 0x05000100, 0, 0, 10 /* ratio 4/10 */, 0x02520129 },
475 { 330000000, 146666666, 33000000, 0x0903, 0x01010000, 0x00020200, 0x01010100,
476 0x05000100, 0, 0, 9 /* ratio 4/9 */, 0x012a00a9 },
477 { 330000000, 165000000, 33000000, 0x0903, 0x01000100, 0x00020200, 0x01010100,
478 0x05000100, 0, 0, 8 /* ratio 4/8 */, 0x00aa0055 },
479 { 330000000, 165000000, 41250000, 0x0903, 0x01000100, 0x00020100, 0x01010100,
480 0x05000100, 0, 0, 8 /* ratio 4/8 */, 0x00aa0055 },
481 { 330000000, 165000000, 55000000, 0x0903, 0x01000100, 0x00020000, 0x01010100,
482 0x05000100, 0, 0, 8 /* ratio 4/8 */, 0x00aa0055 },
483 { 360000000, 120000000, 32000000, 0x0a03, 0x01000300, 0x00010201, 0x01010200,
484 0x05000100, 0, 0, 12 /* ratio 4/12 */, 0x04920492 },
485 { 360000000, 144000000, 32000000, 0x0a03, 0x01000200, 0x00010201, 0x01010200,
486 0x05000100, 0, 0, 10 /* ratio 4/10 */, 0x02520129 },
487 { 360000000, 160000000, 32000000, 0x0a03, 0x01010000, 0x00010201, 0x01010200,
488 0x05000100, 0, 0, 9 /* ratio 4/9 */, 0x012a00a9 },
489 { 360000000, 180000000, 32000000, 0x0a03, 0x01000100, 0x00010201, 0x01010200,
490 0x05000100, 0, 0, 8 /* ratio 4/8 */, 0x00aa0055 },
491 { 360000000, 180000000, 40000000, 0x0a03, 0x01000100, 0x00010101, 0x01010200,
492 0x05000100, 0, 0, 8 /* ratio 4/8 */, 0x00aa0055 },
493 { 360000000, 180000000, 53333333, 0x0a03, 0x01000100, 0x00010001, 0x01010200,
494 0x05000100, 0, 0, 8 /* ratio 4/8 */, 0x00aa0055 },
495 { 390000000, 130000000, 32500000, 0x0b03, 0x01010100, 0x00020101, 0x01020100,
496 0x05000100, 0, 0, 12 /* ratio 4/12 */, 0x04920492 },
497 { 390000000, 156000000, 32500000, 0x0b03, 0x01000200, 0x00020101, 0x01020100,
498 0x05000100, 0, 0, 10 /* ratio 4/10 */, 0x02520129 },
499 { 390000000, 173000000, 32500000, 0x0b03, 0x01010000, 0x00020101, 0x01020100,
500 0x05000100, 0, 0, 9 /* ratio 4/9 */, 0x012a00a9 },
501 { 390000000, 195000000, 32500000, 0x0b03, 0x01000100, 0x00020101, 0x01020100,
502 0x05000100, 0, 0, 8 /* ratio 4/8 */, 0x00aa0055 },
504 static n4m_table_t
BCMINITDATA(type4_table
)[] = {
505 { 120000000, 60000000, 0, 0x0009, 0x11020009, 0x01030203, 0x11020009, 0x04000009,
507 { 150000000, 75000000, 0, 0x0009, 0x11050002, 0x01030203, 0x11050002, 0x04000005,
509 { 192000000, 96000000, 0, 0x0702, 0x04000011, 0x11030011, 0x04000011, 0x04000003,
511 { 198000000, 99000000, 0, 0x0603, 0x11020005, 0x11030011, 0x11020005, 0x04000005,
513 { 200000000, 100000000, 0, 0x0009, 0x04020011, 0x11030011, 0x04020011, 0x04020003,
515 { 204000000, 102000000, 0, 0x0c02, 0x11020005, 0x01030303, 0x11020005, 0x04000005,
517 { 208000000, 104000000, 0, 0x0802, 0x11030002, 0x11090005, 0x11030002, 0x04000003,
519 { 210000000, 105000000, 0, 0x0209, 0x11020005, 0x01030303, 0x11020005, 0x04000005,
521 { 216000000, 108000000, 0, 0x0111, 0x11020005, 0x01030303, 0x11020005, 0x04000005,
523 { 224000000, 112000000, 0, 0x0205, 0x11030002, 0x02002103, 0x11030002, 0x04000003,
525 { 228000000, 101333333, 0, 0x0e02, 0x11030003, 0x11210005, 0x01030305, 0x04000005,
527 { 228000000, 114000000, 0, 0x0e02, 0x11020005, 0x11210005, 0x11020005, 0x04000005,
529 { 240000000, 102857143, 0, 0x0109, 0x04000021, 0x01050203, 0x11030021, 0x04000003,
531 { 240000000, 120000000, 0, 0x0109, 0x11030002, 0x01050203, 0x11030002, 0x04000003,
533 { 252000000, 100800000, 0, 0x0203, 0x04000009, 0x11050005, 0x02000209, 0x04000002,
535 { 252000000, 126000000, 0, 0x0203, 0x04000005, 0x11050005, 0x04000005, 0x04000002,
537 { 264000000, 132000000, 0, 0x0602, 0x04000005, 0x11050005, 0x04000005, 0x04000002,
539 { 272000000, 116571428, 0, 0x0c02, 0x04000021, 0x02000909, 0x02000221, 0x04000003,
541 { 280000000, 120000000, 0, 0x0209, 0x04000021, 0x01030303, 0x02000221, 0x04000003,
543 { 288000000, 123428571, 0, 0x0111, 0x04000021, 0x01030303, 0x02000221, 0x04000003,
545 { 300000000, 120000000, 0, 0x0009, 0x04000009, 0x01030203, 0x02000902, 0x04000002,
547 { 300000000, 150000000, 0, 0x0009, 0x04000005, 0x01030203, 0x04000005, 0x04000002,
550 static n4m_table_t
BCMINITDATA(type7_table
)[] = {
551 { 183333333, 91666666, 0, 0x0605, 0x04000011, 0x11030011, 0x04000011, 0x04000003,
553 { 187500000, 93750000, 0, 0x0a03, 0x04000011, 0x11030011, 0x04000011, 0x04000003,
555 { 196875000, 98437500, 0, 0x1003, 0x11020005, 0x11050011, 0x11020005, 0x04000005,
557 { 200000000, 100000000, 0, 0x0311, 0x04000011, 0x11030011, 0x04000009, 0x04000003,
559 { 200000000, 100000000, 0, 0x0311, 0x04020011, 0x11030011, 0x04020011, 0x04020003,
561 { 206250000, 103125000, 0, 0x1103, 0x11020005, 0x11050011, 0x11020005, 0x04000005,
563 { 212500000, 106250000, 0, 0x0c05, 0x11020005, 0x01030303, 0x11020005, 0x04000005,
565 { 215625000, 107812500, 0, 0x1203, 0x11090009, 0x11050005, 0x11020005, 0x04000005,
567 { 216666666, 108333333, 0, 0x0805, 0x11020003, 0x11030011, 0x11020003, 0x04000003,
569 { 225000000, 112500000, 0, 0x0d03, 0x11020003, 0x11030011, 0x11020003, 0x04000003,
571 { 233333333, 116666666, 0, 0x0905, 0x11020003, 0x11030011, 0x11020003, 0x04000003,
573 { 237500000, 118750000, 0, 0x0e05, 0x11020005, 0x11210005, 0x11020005, 0x04000005,
575 { 240000000, 120000000, 0, 0x0b11, 0x11020009, 0x11210009, 0x11020009, 0x04000009,
577 { 250000000, 125000000, 0, 0x0f03, 0x11020003, 0x11210003, 0x11020003, 0x04000003,
581 ulong start
, end
, dst
;
584 volatile uint32
*dll_ctrl
= (volatile uint32
*)0xff400008;
585 volatile uint32
*dll_r1
= (volatile uint32
*)0xff400010;
586 volatile uint32
*dll_r2
= (volatile uint32
*)0xff400018;
588 /* get index of the current core */
589 idx
= sb_coreidx(sbh
);
590 clockcontrol_m2
= NULL
;
592 /* switch to chipc core */
593 cc
= (chipcregs_t
*) sb_setcore(sbh
, SB_CC
, 0);
596 /* 5354 chipcommon pll setting can't be changed.
597 * The PMU on power up comes up with the default clk frequency
600 if (sb_chip(sbh
) == BCM5354_CHIP_ID
) {
605 pll_type
= sbh
->cccaps
& CC_CAP_PLL_MASK
;
606 if (pll_type
== PLL_TYPE6
) {
607 clockcontrol_n
= NULL
;
608 clockcontrol_sb
= NULL
;
609 clockcontrol_pci
= NULL
;
611 clockcontrol_n
= &cc
->clockcontrol_n
;
612 clockcontrol_sb
= &cc
->clockcontrol_sb
;
613 clockcontrol_pci
= &cc
->clockcontrol_pci
;
614 clockcontrol_m2
= &cc
->clockcontrol_m2
;
617 if (pll_type
== PLL_TYPE6
) {
618 /* Silence compilers */
619 orig_n
= orig_sb
= orig_pci
= 0;
621 /* Store the current clock register values */
622 orig_n
= R_REG(osh
, clockcontrol_n
);
623 orig_sb
= R_REG(osh
, clockcontrol_sb
);
624 orig_pci
= R_REG(osh
, clockcontrol_pci
);
627 if (pll_type
== PLL_TYPE1
) {
628 /* Keep the current PCI clock if not specified */
630 pciclock
= sb_clock_rate(pll_type
, R_REG(osh
, clockcontrol_n
),
631 R_REG(osh
, clockcontrol_pci
));
632 pciclock
= (pciclock
<= 25000000) ? 25000000 : 33000000;
635 /* Search for the closest MIPS clock less than or equal to a preferred value */
636 for (i
= 0; i
< ARRAYSIZE(type1_table
); i
++) {
637 ASSERT(type1_table
[i
].mipsclock
==
638 sb_clock_rate(pll_type
, type1_table
[i
].n
,
640 if (type1_table
[i
].mipsclock
> mipsclock
)
650 ASSERT(type1_table
[i
].mipsclock
<= mipsclock
);
653 if ((orig_n
== type1_table
[i
].n
) &&
654 (orig_sb
== type1_table
[i
].sb
) &&
655 (orig_pci
== type1_table
[i
].pci33
))
658 /* Set the PLL controls */
659 W_REG(osh
, clockcontrol_n
, type1_table
[i
].n
);
660 W_REG(osh
, clockcontrol_sb
, type1_table
[i
].sb
);
661 if (pciclock
== 25000000)
662 W_REG(osh
, clockcontrol_pci
, type1_table
[i
].pci25
);
664 W_REG(osh
, clockcontrol_pci
, type1_table
[i
].pci33
);
669 } else if (pll_type
== PLL_TYPE3
) {
671 if (sb_chip(sbh
) != BCM5365_CHIP_ID
) {
673 * Search for the closest MIPS clock less than or equal to
676 for (i
= 0; i
< ARRAYSIZE(type3_table
); i
++) {
677 if (type3_table
[i
].mipsclock
> mipsclock
)
687 ASSERT(type3_table
[i
].mipsclock
<= mipsclock
);
690 orig_m2
= R_REG(osh
, &cc
->clockcontrol_m2
);
691 if ((orig_n
== type3_table
[i
].n
) &&
692 (orig_m2
== type3_table
[i
].m2
)) {
696 /* Set the PLL controls */
697 W_REG(osh
, clockcontrol_n
, type3_table
[i
].n
);
698 W_REG(osh
, clockcontrol_m2
, type3_table
[i
].m2
);
704 } else if ((pll_type
== PLL_TYPE2
) ||
705 (pll_type
== PLL_TYPE4
) ||
706 (pll_type
== PLL_TYPE6
) ||
707 (pll_type
== PLL_TYPE7
)) {
708 n4m_table_t
*table
= NULL
, *te
;
713 orig_mips
= R_REG(osh
, &cc
->clockcontrol_m3
);
720 if (mipsclock
<= SB2MIPS_T6(CC_T6_M1
))
721 new_mips
= CC_T6_MMASK
;
723 if (orig_mips
== new_mips
)
726 W_REG(osh
, &cc
->clockcontrol_m3
, new_mips
);
731 tabsz
= ARRAYSIZE(type2_table
);
735 tabsz
= ARRAYSIZE(type4_table
);
739 tabsz
= ARRAYSIZE(type7_table
);
742 ASSERT("No table for plltype" == NULL
);
746 /* Store the current clock register values */
747 orig_m2
= R_REG(osh
, &cc
->clockcontrol_m2
);
751 /* Look up current ratio */
752 for (i
= 0; i
< tabsz
; i
++) {
753 if ((orig_n
== table
[i
].n
) &&
754 (orig_sb
== table
[i
].sb
) &&
755 (orig_pci
== table
[i
].pci33
) &&
756 (orig_m2
== table
[i
].m2
) &&
757 (orig_mips
== table
[i
].m3
)) {
758 orig_ratio_parm
= table
[i
].ratio_parm
;
759 orig_ratio_cfg
= table
[i
].ratio_cfg
;
764 /* Search for the closest MIPS clock greater or equal to a preferred value */
765 for (i
= 0; i
< tabsz
; i
++) {
766 ASSERT(table
[i
].mipsclock
==
767 sb_clock_rate(pll_type
, table
[i
].n
, table
[i
].m3
));
768 if ((mipsclock
<= table
[i
].mipsclock
) &&
769 ((sbclock
== 0) || (sbclock
<= table
[i
].sbclock
)) &&
770 ((pciclock
== 0) || (pciclock
<= table
[i
].pciclock
)))
782 if ((orig_n
== te
->n
) &&
783 (orig_sb
== te
->sb
) &&
784 (orig_pci
== te
->pci33
) &&
785 (orig_m2
== te
->m2
) &&
786 (orig_mips
== te
->m3
))
789 /* Set the PLL controls */
790 W_REG(osh
, clockcontrol_n
, te
->n
);
791 W_REG(osh
, clockcontrol_sb
, te
->sb
);
792 W_REG(osh
, clockcontrol_pci
, te
->pci33
);
793 W_REG(osh
, &cc
->clockcontrol_m2
, te
->m2
);
794 W_REG(osh
, &cc
->clockcontrol_m3
, te
->m3
);
796 /* Set the chipcontrol bit to change mipsref to the backplane divider if needed */
797 if ((pll_type
== PLL_TYPE7
) && (te
->sb
!= te
->m2
) &&
798 (sb_clock_rate(pll_type
, te
->n
, te
->m2
) == 120000000))
799 W_REG(osh
, &cc
->chipcontrol
,
800 R_REG(osh
, &cc
->chipcontrol
) | 0x100);
802 /* No ratio change */
803 if (sb_chip(sbh
) != BCM4785_CHIP_ID
) {
804 if (orig_ratio_parm
== te
->ratio_parm
)
808 /* Preload the code into the cache */
809 icache_probe(MFC0(C0_CONFIG
, 1), &ic_size
, &ic_lsize
);
810 if (sb_chip(sbh
) == BCM4785_CHIP_ID
) {
811 start
= ((ulong
) &&start_fill_4785
) & ~(ic_lsize
- 1);
812 end
= ((ulong
) &&end_fill_4785
+ (ic_lsize
- 1)) & ~(ic_lsize
- 1);
815 start
= ((ulong
) &&start_fill
) & ~(ic_lsize
- 1);
816 end
= ((ulong
) &&end_fill
+ (ic_lsize
- 1)) & ~(ic_lsize
- 1);
818 while (start
< end
) {
819 cache_op(start
, Fill_I
);
823 /* 4785 clock freq change procedures */
824 if (sb_chip(sbh
) == BCM4785_CHIP_ID
) {
826 /* Switch to async */
827 MTC0(C0_BROADCOM
, 4, (1 << 22));
829 /* Set clock ratio in MIPS */
830 *dll_r1
= (*dll_r1
& 0xfffffff0) | (te
->d11_r1
- 1);
831 *dll_r2
= te
->d11_r2
;
833 /* Enable new settings in MIPS */
834 *dll_r1
= *dll_r1
| 0xc0000000;
837 MTC0(C0_BROADCOM
, 2, MFC0(C0_BROADCOM
, 2) | (1 << 3) | 1);
839 /* Fake soft reset (clock cfg registers not reset) */
840 MTC0(C0_BROADCOM
, 5, MFC0(C0_BROADCOM
, 5) | (1 << 2));
842 /* Clear active cfg */
843 MTC0(C0_BROADCOM
, 2, MFC0(C0_BROADCOM
, 2) & ~(1 << 3));
845 /* set watchdog timer */
846 W_REG(osh
, &cc
->watchdog
, 20);
847 (void) R_REG(osh
, &cc
->chipid
);
849 /* wait for timer interrupt */
850 __asm__
__volatile__(
858 /* Generic clock freq change procedures */
860 /* Copy the handler */
861 start
= (ulong
) &handler
;
862 end
= (ulong
) &afterhandler
;
863 dst
= KSEG1ADDR(0x180);
864 for (i
= 0; i
< (end
- start
); i
+= 4)
865 *((ulong
*)(dst
+ i
)) = *((ulong
*)(start
+ i
));
867 /* Preload the handler into the cache one line at a time */
868 for (i
= 0; i
< (end
- start
); i
+= ic_lsize
)
869 cache_op(dst
+ i
, Fill_I
);
872 MTC0(C0_STATUS
, 0, MFC0(C0_STATUS
, 0) & ~ST0_BEV
);
874 /* Enable interrupts */
875 MTC0(C0_STATUS
, 0, MFC0(C0_STATUS
, 0) | (ALLINTS
| ST0_IE
));
877 /* Enable MIPS timer interrupt */
878 mipsr
= sb_setcore(sbh
, SB_MIPS33
, 0);
880 W_REG(osh
, &mipsr
->intmask
, 1);
883 /* step 1, set clock ratios */
884 MTC0(C0_BROADCOM
, 3, te
->ratio_parm
);
885 MTC0(C0_BROADCOM
, 1, te
->ratio_cfg
);
887 /* step 2: program timer intr */
888 W_REG(osh
, &mipsr
->timer
, 100);
889 (void) R_REG(osh
, &mipsr
->timer
);
891 /* step 3, switch to async */
892 sync_mode
= MFC0(C0_BROADCOM
, 4);
893 MTC0(C0_BROADCOM
, 4, 1 << 22);
895 /* step 4, set cfg active */
896 MTC0(C0_BROADCOM
, 2, (1 << 3) | 1);
899 __asm__
__volatile__(
904 /* step 7, clear cfg active */
905 MTC0(C0_BROADCOM
, 2, 0);
907 /* Additional Step: set back to orig sync mode */
908 MTC0(C0_BROADCOM
, 4, sync_mode
);
910 /* step 8, fake soft reset */
911 MTC0(C0_BROADCOM
, 5, MFC0(C0_BROADCOM
, 5) | (1 << 2));
914 /* set watchdog timer */
915 W_REG(osh
, &cc
->watchdog
, 20);
916 (void) R_REG(osh
, &cc
->chipid
);
918 /* wait for timer interrupt */
919 __asm__
__volatile__(
929 /* Enable 4785 DLL */
930 if (sb_chip(sbh
) == BCM4785_CHIP_ID
) {
933 /* set mask to 1e, enable DLL (bit 0) */
934 *dll_ctrl
|= 0x0041e021;
936 /* enable aggressive hardware mode */
937 *dll_ctrl
|= 0x00000080;
939 /* wait for lock flag to clear */
940 while ((*dll_ctrl
& 0x2) == 0);
942 /* clear sticky flags (clear on write 1) */
946 /* set mask to 5b'10001 */
947 *dll_ctrl
= (*dll_ctrl
& 0xfffc1fff) | 0x00022000;
949 /* enable sync mode */
950 MTC0(C0_BROADCOM
, 4, MFC0(C0_BROADCOM
, 4) & 0xfe3fffff);
951 (void)MFC0(C0_BROADCOM
, 4);
954 /* switch back to previous core */
955 sb_setcoreidx(sbh
, idx
);
961 BCMINITFN(enable_pfc
)(uint32 mode
)
964 uint ic_size
, ic_lsize
;
966 /* If auto then choose the correct mode for this
967 * platform, currently we only ever select one mode
969 if (mode
== PFC_AUTO
)
972 icache_probe(MFC0(C0_CONFIG
, 1), &ic_size
, &ic_lsize
);
974 /* enable prefetch cache if available */
975 if (MFC0(C0_BROADCOM
, 0) & BRCM_PFC_AVAIL
) {
976 start
= ((ulong
) &&setpfc_start
) & ~(ic_lsize
- 1);
977 end
= ((ulong
) &&setpfc_end
+ (ic_lsize
- 1)) & ~(ic_lsize
- 1);
979 /* Preload setpfc code into the cache one line at a time */
980 while (start
< end
) {
981 cache_op(start
, Fill_I
);
985 /* Now set the pfc */
988 *(volatile uint32
*)PFC_CR1
= 0xffff0000;
991 *(volatile uint32
*)PFC_CR0
= mode
;
998 /* returns the ncdl value to be programmed into sdram_ncdl for calibration */
1000 BCMINITFN(sb_memc_get_ncdl
)(sb_t
*sbh
)
1005 uint32 config
, rd
, wr
, misc
, dqsg
, cd
, sm
, sd
;
1010 idx
= sb_coreidx(sbh
);
1012 memc
= (sbmemcregs_t
*)sb_setcore(sbh
, SB_MEMC
, 0);
1016 rev
= sb_corerev(sbh
);
1018 config
= R_REG(osh
, &memc
->config
);
1019 wr
= R_REG(osh
, &memc
->wrncdlcor
);
1020 rd
= R_REG(osh
, &memc
->rdncdlcor
);
1021 misc
= R_REG(osh
, &memc
->miscdlyctl
);
1022 dqsg
= R_REG(osh
, &memc
->dqsgatencdl
);
1024 rd
&= MEMC_RDNCDLCOR_RD_MASK
;
1025 wr
&= MEMC_WRNCDLCOR_WR_MASK
;
1026 dqsg
&= MEMC_DQSGATENCDL_G_MASK
;
1028 if (config
& MEMC_CONFIG_DDR
) {
1029 ret
= (wr
<< 16) | (rd
<< 8) | dqsg
;
1034 cd
= (rd
== MEMC_CD_THRESHOLD
) ? rd
: (wr
+ MEMC_CD_THRESHOLD
);
1035 sm
= (misc
& MEMC_MISC_SM_MASK
) >> MEMC_MISC_SM_SHIFT
;
1036 sd
= (misc
& MEMC_MISC_SD_MASK
) >> MEMC_MISC_SD_SHIFT
;
1037 ret
= (sm
<< 16) | (sd
<< 8) | cd
;
1041 /* switch back to previous core */
1042 sb_setcoreidx(sbh
, idx
);
1048 hnd_cpu_reset(sb_t
*sbh
)
1050 if (sb_chip(sbh
) == BCM4785_CHIP_ID
)
1051 MTC0(C0_BROADCOM
, 4, (1 << 22));
1052 sb_watchdog(sbh
, 1);
1053 if (sb_chip(sbh
) == BCM4785_CHIP_ID
) {
1054 __asm__
__volatile__(
1063 #if defined(CONFIG_BCMPERFSTATS)
1065 * CP0 Register 25 supports 4 semi-independent 32bit performance counters.
1066 * $25 select 0, 1, 2, and 3 are the counters. The counters *decrement* (who thought this one up?)
1067 * $25 select 4 and 5 each contain 2-16bit control fields, one for each of the 4 counters
1068 * $25 select 6 is the global perf control register.
1070 /* enable and start instruction counting */
1073 hndmips_perf_cyclecount_enable(void)
1075 MTC0(C0_PERFORMANCE
, 6, 0x80000200); /* global enable perf counters */
1076 MTC0(C0_PERFORMANCE
, 4,
1077 0x8048 | MFC0(C0_PERFORMANCE
, 4)); /* enable cycles counting for counter 0 */
1078 MTC0(C0_PERFORMANCE
, 0, 0); /* zero counter zero */
1082 hndmips_perf_instrcount_enable(void)
1084 MTC0(C0_PERFORMANCE
, 6, 0x80000200); /* global enable perf counters */
1085 MTC0(C0_PERFORMANCE
, 4,
1086 0x8044 | MFC0(C0_PERFORMANCE
, 4)); /* enable instructions counting for counter 0 */
1087 MTC0(C0_PERFORMANCE
, 0, 0); /* zero counter zero */
1090 /* enable and start I$ hit and I$ miss counting */
1092 hndmips_perf_icachecount_enable(void)
1094 MTC0(C0_PERFORMANCE
, 6, 0x80000218); /* enable I$ counting */
1095 MTC0(C0_PERFORMANCE
, 4, 0x80148018); /* count I$ hits in cntr 0 and misses in cntr 1 */
1096 MTC0(C0_PERFORMANCE
, 0, 0); /* zero counter 0 - # I$ hits */
1097 MTC0(C0_PERFORMANCE
, 1, 0); /* zero counter 1 - # I$ misses */
1100 /* enable and start D$ hit and I$ miss counting */
1102 hndmips_perf_dcachecount_enable(void)
1104 MTC0(C0_PERFORMANCE
, 6, 0x80000211); /* enable D$ counting */
1105 MTC0(C0_PERFORMANCE
, 4, 0x80248028); /* count D$ hits in cntr 0 and misses in cntr 1 */
1106 MTC0(C0_PERFORMANCE
, 0, 0); /* zero counter 0 - # D$ hits */
1107 MTC0(C0_PERFORMANCE
, 1, 0); /* zero counter 1 - # D$ misses */
1111 hndmips_perf_icache_miss_enable()
1113 MTC0(C0_PERFORMANCE
, 4,
1114 0x80140000 | MFC0(C0_PERFORMANCE
, 4)); /* enable cache misses counting for counter 1 */
1115 MTC0(C0_PERFORMANCE
, 1, 0); /* zero counter one */
1120 hndmips_perf_icache_hit_enable()
1122 MTC0(C0_PERFORMANCE
, 5, 0x8018 | MFC0(C0_PERFORMANCE
, 5));
1123 /* enable cache hits counting for counter 2 */
1124 MTC0(C0_PERFORMANCE
, 2, 0); /* zero counter 2 */
1128 hndmips_perf_read_instrcount()
1130 return -(long)(MFC0(C0_PERFORMANCE
, 0));
1134 hndmips_perf_read_cache_miss()
1136 return -(long)(MFC0(C0_PERFORMANCE
, 1));
1140 hndmips_perf_read_cache_hit()
1142 return -(long)(MFC0(C0_PERFORMANCE
, 2));