cosmetics
[tomato.git] / release / src / shared / hndmips.c
blob088de47fb05747220bfc090420dcadfeedeea3cf
1 /*
2 * BCM47XX Sonics SiliconBackplane MIPS core routines
4 * Copyright 2007, Broadcom Corporation
5 * All Rights Reserved.
6 *
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$
15 #include <typedefs.h>
16 #include <bcmdefs.h>
17 #include <osl.h>
18 #include <bcmutils.h>
19 #include <sbutils.h>
20 #include <sbextif.h>
21 #include <bcmdevs.h>
22 #include <bcmnvram.h>
23 #include <sbconfig.h>
24 #include <sbchipc.h>
25 #include <sbmemc.h>
26 #include <mipsinc.h>
27 #include <sbhndmips.h>
28 #include <hndcpu.h>
29 #include <hndmips.h>
31 /* sbipsflag register format, indexed by irq. */
32 static const uint32 sbips_int_mask[] = {
33 0, /* placeholder */
34 SBIPS_INT1_MASK,
35 SBIPS_INT2_MASK,
36 SBIPS_INT3_MASK,
37 SBIPS_INT4_MASK
40 static const uint32 sbips_int_shift[] = {
41 0, /* placeholder */
42 SBIPS_INT1_SHIFT,
43 SBIPS_INT2_SHIFT,
44 SBIPS_INT3_SHIFT,
45 SBIPS_INT4_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,
59 * 0 is returned.
61 static uint
62 sb_getirq(sb_t *sbh)
64 osl_t *osh;
65 uint idx;
66 void *regs;
67 sbconfig_t *sb;
68 uint32 flag, sbipsflag;
69 uint irq = 0;
71 osh = sb_osh(sbh);
72 flag = sb_flag(sbh);
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)
83 break;
85 if (irq == 5)
86 irq = 0;
89 sb_setcoreidx(sbh, idx);
91 return irq;
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.
98 uint
99 sb_irq(sb_t *sbh)
101 uint irq = sb_getirq(sbh);
102 if (irq == 0 && shirq_map_base)
103 irq = sb_flag(sbh) + shirq_map_base;
104 return irq;
107 /* Clears the specified MIPS IRQ. */
108 static void
109 BCMINITFN(sb_clearirq)(sb_t *sbh, uint irq)
111 osl_t *osh;
112 void *regs;
113 sbconfig_t *sb;
115 osh = sb_osh(sbh);
117 regs = sb_setcore(sbh, SB_MIPS33, 0);
118 ASSERT(regs);
119 sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF);
121 if (irq == 0)
122 W_REG(osh, &sb->sbintvec, 0);
123 else
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.
133 static void
134 BCMINITFN(sb_setirq)(sb_t *sbh, uint irq, uint coreid, uint coreunit)
136 osl_t *osh;
137 void *regs;
138 sbconfig_t *sb;
139 uint32 flag;
140 uint oldirq;
142 osh = sb_osh(sbh);
144 regs = sb_setcore(sbh, coreid, coreunit);
145 ASSERT(regs);
146 flag = sb_flag(sbh);
147 oldirq = sb_getirq(sbh);
148 if (oldirq)
149 sb_clearirq(sbh, oldirq);
151 regs = sb_setcore(sbh, SB_MIPS33, 0);
152 ASSERT(regs);
153 sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF);
155 if (!oldirq)
156 AND_REG(osh, &sb->sbintvec, ~(1 << flag));
158 if (irq == 0)
159 OR_REG(osh, &sb->sbintvec, 1 << flag);
160 else {
161 flag <<= sbips_int_shift[irq];
162 ASSERT(!(flag & ~sbips_int_mask[irq]));
163 flag |= R_REG(osh, &sb->sbipsflag) & ~sbips_int_mask[irq];
164 W_REG(osh, &sb->sbipsflag, flag);
169 * Initializes clocks and interrupts. SB and NVRAM access must be
170 * initialized prior to calling.
172 * 'shirqmap' enables virtual dedicated OS IRQ mapping if non-zero.
174 void
175 BCMINITFN(sb_mips_init)(sb_t *sbh, uint shirqmap)
177 osl_t *osh;
178 ulong hz, ns, tmp;
179 chipcregs_t *cc;
180 uint irq;
182 osh = sb_osh(sbh);
184 /* Figure out current SB clock speed */
185 if ((hz = sb_clock(sbh)) == 0)
186 hz = 100000000;
187 ns = 1000000000 / hz;
189 /* Setup external interface timing */
190 cc = sb_setcore(sbh, SB_CC, 0);
191 ASSERT(cc);
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);
222 break;
223 case BCM4785_CHIP_ID:
224 /* Reassign PCI to irq 4 */
225 sb_setirq(sbh, 4, SB_PCI, 0);
226 break;
230 /* Do any setup necessary to run a new image and jump to it. */
231 void
232 hnd_cpu_jumpto(void *addr)
234 void (*jumpto)(void) = addr;
236 (jumpto)();
239 uint32
240 BCMINITFN(sb_cpu_clock)(sb_t *sbh)
242 chipcregs_t *cc;
243 uint32 n, m;
244 uint idx;
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);
253 ASSERT(cc);
255 /* 5354 chip uses a non programmable PLL of frequency 240MHz */
256 if (sb_chip(sbh) == BCM5354_CHIP_ID) {
257 rate = 240000000;
258 goto out;
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) {
269 rate = 200000000;
270 goto out;
271 } else if (pll_type == PLL_TYPE3) {
272 if (sb_chip(sbh) == BCM5365_CHIP_ID) {
273 rate = 200000000;
274 goto out;
276 /* 5350 uses m2 to control mips */
277 else
278 m = R_REG(osh, &cc->clockcontrol_m2);
279 } else
280 m = R_REG(osh, &cc->clockcontrol_sb);
282 /* calculate rate */
283 rate = sb_clock_rate(pll_type, n, m);
285 if (pll_type == PLL_TYPE6)
286 rate = SB2MIPS_T6(rate);
288 out:
289 /* switch back to previous core */
290 sb_setcoreidx(sbh, idx);
292 return rate;
295 #define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4)
297 static void
298 BCMINITFN(handler)(void)
300 __asm__(
301 ".set\tmips32\n\t"
302 "ssnop\n\t"
303 "ssnop\n\t"
304 /* Disable interrupts */
305 /* MTC0(C0_STATUS, 0, MFC0(C0_STATUS, 0) & ~(ALLINTS | STO_IE)); */
306 "mfc0 $15, $12\n\t"
307 /* Just a Hack to not to use reg 'at' which was causing problems on 4704 A2 */
308 "li $14, -31746\n\t"
309 "and $15, $15, $14\n\t"
310 "mtc0 $15, $12\n\t"
311 "eret\n\t"
312 "nop\n\t"
313 "nop\n\t"
314 ".set\tmips0");
317 /* The following MUST come right after handler() */
318 static void
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.
329 bool
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;
338 uint idx, i;
340 /* PLL configuration: type 1 */
341 typedef struct {
342 uint32 mipsclock;
343 uint16 n;
344 uint32 sb;
345 uint32 pci33;
346 uint32 pci25;
347 } n3m_table_t;
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 */
392 typedef struct {
393 uint32 mipsclock;
394 uint16 n;
395 uint32 m2; /* that is the clockcontrol_m2 */
396 } type3_table_t;
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 */
404 typedef struct {
405 uint32 mipsclock;
406 uint32 sbclock;
407 uint32 pciclock;
408 uint16 n;
409 uint32 sb;
410 uint32 pci33;
411 uint32 m2;
412 uint32 m3;
413 uint32 ratio_cfg;
414 uint32 ratio_parm;
415 uint32 d11_r1;
416 uint32 d11_r2;
417 } n4m_table_t;
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,
506 11, 0x0aaa0555 },
507 { 150000000, 75000000, 0, 0x0009, 0x11050002, 0x01030203, 0x11050002, 0x04000005,
508 11, 0x0aaa0555 },
509 { 192000000, 96000000, 0, 0x0702, 0x04000011, 0x11030011, 0x04000011, 0x04000003,
510 11, 0x0aaa0555 },
511 { 198000000, 99000000, 0, 0x0603, 0x11020005, 0x11030011, 0x11020005, 0x04000005,
512 11, 0x0aaa0555 },
513 { 200000000, 100000000, 0, 0x0009, 0x04020011, 0x11030011, 0x04020011, 0x04020003,
514 11, 0x0aaa0555 },
515 { 204000000, 102000000, 0, 0x0c02, 0x11020005, 0x01030303, 0x11020005, 0x04000005,
516 11, 0x0aaa0555 },
517 { 208000000, 104000000, 0, 0x0802, 0x11030002, 0x11090005, 0x11030002, 0x04000003,
518 11, 0x0aaa0555 },
519 { 210000000, 105000000, 0, 0x0209, 0x11020005, 0x01030303, 0x11020005, 0x04000005,
520 11, 0x0aaa0555 },
521 { 216000000, 108000000, 0, 0x0111, 0x11020005, 0x01030303, 0x11020005, 0x04000005,
522 11, 0x0aaa0555 },
523 { 224000000, 112000000, 0, 0x0205, 0x11030002, 0x02002103, 0x11030002, 0x04000003,
524 11, 0x0aaa0555 },
525 { 228000000, 101333333, 0, 0x0e02, 0x11030003, 0x11210005, 0x01030305, 0x04000005,
526 8, 0x012a00a9 },
527 { 228000000, 114000000, 0, 0x0e02, 0x11020005, 0x11210005, 0x11020005, 0x04000005,
528 11, 0x0aaa0555 },
529 { 240000000, 102857143, 0, 0x0109, 0x04000021, 0x01050203, 0x11030021, 0x04000003,
530 13, 0x254a14a9 },
531 { 240000000, 120000000, 0, 0x0109, 0x11030002, 0x01050203, 0x11030002, 0x04000003,
532 11, 0x0aaa0555 },
533 { 252000000, 100800000, 0, 0x0203, 0x04000009, 0x11050005, 0x02000209, 0x04000002,
534 9, 0x02520129 },
535 { 252000000, 126000000, 0, 0x0203, 0x04000005, 0x11050005, 0x04000005, 0x04000002,
536 11, 0x0aaa0555 },
537 { 264000000, 132000000, 0, 0x0602, 0x04000005, 0x11050005, 0x04000005, 0x04000002,
538 11, 0x0aaa0555 },
539 { 272000000, 116571428, 0, 0x0c02, 0x04000021, 0x02000909, 0x02000221, 0x04000003,
540 13, 0x254a14a9 },
541 { 280000000, 120000000, 0, 0x0209, 0x04000021, 0x01030303, 0x02000221, 0x04000003,
542 13, 0x254a14a9 },
543 { 288000000, 123428571, 0, 0x0111, 0x04000021, 0x01030303, 0x02000221, 0x04000003,
544 13, 0x254a14a9 },
545 { 300000000, 120000000, 0, 0x0009, 0x04000009, 0x01030203, 0x02000902, 0x04000002,
546 9, 0x02520129 },
547 { 300000000, 150000000, 0, 0x0009, 0x04000005, 0x01030203, 0x04000005, 0x04000002,
548 11, 0x0aaa0555 }
550 static n4m_table_t BCMINITDATA(type7_table)[] = {
551 { 183333333, 91666666, 0, 0x0605, 0x04000011, 0x11030011, 0x04000011, 0x04000003,
552 11, 0x0aaa0555 },
553 { 187500000, 93750000, 0, 0x0a03, 0x04000011, 0x11030011, 0x04000011, 0x04000003,
554 11, 0x0aaa0555 },
555 { 196875000, 98437500, 0, 0x1003, 0x11020005, 0x11050011, 0x11020005, 0x04000005,
556 11, 0x0aaa0555 },
557 { 200000000, 100000000, 0, 0x0311, 0x04000011, 0x11030011, 0x04000009, 0x04000003,
558 11, 0x0aaa0555 },
559 { 200000000, 100000000, 0, 0x0311, 0x04020011, 0x11030011, 0x04020011, 0x04020003,
560 11, 0x0aaa0555 },
561 { 206250000, 103125000, 0, 0x1103, 0x11020005, 0x11050011, 0x11020005, 0x04000005,
562 11, 0x0aaa0555 },
563 { 212500000, 106250000, 0, 0x0c05, 0x11020005, 0x01030303, 0x11020005, 0x04000005,
564 11, 0x0aaa0555 },
565 { 215625000, 107812500, 0, 0x1203, 0x11090009, 0x11050005, 0x11020005, 0x04000005,
566 11, 0x0aaa0555 },
567 { 216666666, 108333333, 0, 0x0805, 0x11020003, 0x11030011, 0x11020003, 0x04000003,
568 11, 0x0aaa0555 },
569 { 225000000, 112500000, 0, 0x0d03, 0x11020003, 0x11030011, 0x11020003, 0x04000003,
570 11, 0x0aaa0555 },
571 { 233333333, 116666666, 0, 0x0905, 0x11020003, 0x11030011, 0x11020003, 0x04000003,
572 11, 0x0aaa0555 },
573 { 237500000, 118750000, 0, 0x0e05, 0x11020005, 0x11210005, 0x11020005, 0x04000005,
574 11, 0x0aaa0555 },
575 { 240000000, 120000000, 0, 0x0b11, 0x11020009, 0x11210009, 0x11020009, 0x04000009,
576 11, 0x0aaa0555 },
577 { 250000000, 125000000, 0, 0x0f03, 0x11020003, 0x11210003, 0x11020003, 0x04000003,
578 11, 0x0aaa0555 }
581 ulong start, end, dst;
582 bool ret = FALSE;
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);
594 ASSERT(cc);
596 /* 5354 chipcommon pll setting can't be changed.
597 * The PMU on power up comes up with the default clk frequency
598 * of 240MHz
600 if (sb_chip(sbh) == BCM5354_CHIP_ID) {
601 ret = TRUE;
602 goto done;
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;
610 } else {
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;
620 } else {
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 */
629 if (pciclock == 0) {
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,
639 type1_table[i].sb));
640 if (type1_table[i].mipsclock > mipsclock)
641 break;
643 if (i == 0) {
644 ret = FALSE;
645 goto done;
646 } else {
647 ret = TRUE;
648 i--;
650 ASSERT(type1_table[i].mipsclock <= mipsclock);
652 /* No PLL change */
653 if ((orig_n == type1_table[i].n) &&
654 (orig_sb == type1_table[i].sb) &&
655 (orig_pci == type1_table[i].pci33))
656 goto done;
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);
663 else
664 W_REG(osh, clockcontrol_pci, type1_table[i].pci33);
666 /* Reset */
667 sb_watchdog(sbh, 1);
668 while (1);
669 } else if (pll_type == PLL_TYPE3) {
670 /* 5350 */
671 if (sb_chip(sbh) != BCM5365_CHIP_ID) {
673 * Search for the closest MIPS clock less than or equal to
674 * a preferred value.
676 for (i = 0; i < ARRAYSIZE(type3_table); i++) {
677 if (type3_table[i].mipsclock > mipsclock)
678 break;
680 if (i == 0) {
681 ret = FALSE;
682 goto done;
683 } else {
684 ret = TRUE;
685 i--;
687 ASSERT(type3_table[i].mipsclock <= mipsclock);
689 /* No PLL change */
690 orig_m2 = R_REG(osh, &cc->clockcontrol_m2);
691 if ((orig_n == type3_table[i].n) &&
692 (orig_m2 == type3_table[i].m2)) {
693 goto done;
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);
700 /* Reset */
701 sb_watchdog(sbh, 1);
702 while (1);
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;
709 uint tabsz = 0;
711 ASSERT(cc);
713 orig_mips = R_REG(osh, &cc->clockcontrol_m3);
715 switch (pll_type) {
716 case PLL_TYPE6: {
717 uint32 new_mips = 0;
719 ret = TRUE;
720 if (mipsclock <= SB2MIPS_T6(CC_T6_M1))
721 new_mips = CC_T6_MMASK;
723 if (orig_mips == new_mips)
724 goto done;
726 W_REG(osh, &cc->clockcontrol_m3, new_mips);
727 goto end_fill;
729 case PLL_TYPE2:
730 table = type2_table;
731 tabsz = ARRAYSIZE(type2_table);
732 break;
733 case PLL_TYPE4:
734 table = type4_table;
735 tabsz = ARRAYSIZE(type4_table);
736 break;
737 case PLL_TYPE7:
738 table = type7_table;
739 tabsz = ARRAYSIZE(type7_table);
740 break;
741 default:
742 ASSERT("No table for plltype" == NULL);
743 break;
746 /* Store the current clock register values */
747 orig_m2 = R_REG(osh, &cc->clockcontrol_m2);
748 orig_ratio_parm = 0;
749 orig_ratio_cfg = 0;
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;
760 break;
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)))
771 break;
773 if (i == tabsz) {
774 ret = FALSE;
775 goto done;
776 } else {
777 te = &table[i];
778 ret = TRUE;
781 /* No PLL change */
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))
787 goto done;
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)
805 goto end_fill;
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);
814 else {
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);
820 start += ic_lsize;
823 /* 4785 clock freq change procedures */
824 if (sb_chip(sbh) == BCM4785_CHIP_ID) {
825 start_fill_4785:
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;
836 /* Set active cfg */
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__(
851 ".set\tmips3\n\t"
852 "sync\n\t"
853 "wait\n\t"
854 ".set\tmips0");
855 end_fill_4785:
856 while (1);
858 /* Generic clock freq change procedures */
859 else {
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);
871 /* Clear BEV bit */
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);
879 ASSERT(mipsr);
880 W_REG(osh, &mipsr->intmask, 1);
882 start_fill:
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);
898 /* steps 5 & 6 */
899 __asm__ __volatile__(
900 ".set\tmips3\n\t"
901 "wait\n\t"
902 ".set\tmips0");
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));
913 end_fill:
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__(
920 ".set\tmips3\n\t"
921 "sync\n\t"
922 "wait\n\t"
923 ".set\tmips0");
924 while (1);
928 done:
929 /* Enable 4785 DLL */
930 if (sb_chip(sbh) == BCM4785_CHIP_ID) {
931 uint32 tmp;
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) */
943 tmp = *dll_ctrl;
944 *dll_ctrl = tmp;
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);
957 return ret;
960 void
961 BCMINITFN(enable_pfc)(uint32 mode)
963 ulong start, end;
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)
970 mode = PFC_INST;
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);
982 start += ic_lsize;
985 /* Now set the pfc */
986 setpfc_start:
987 /* write range */
988 *(volatile uint32 *)PFC_CR1 = 0xffff0000;
990 /* enable */
991 *(volatile uint32 *)PFC_CR0 = mode;
992 setpfc_end:
993 /* Compiler foder */
994 ic_size = 0;
998 /* returns the ncdl value to be programmed into sdram_ncdl for calibration */
999 uint32
1000 BCMINITFN(sb_memc_get_ncdl)(sb_t *sbh)
1002 osl_t *osh;
1003 sbmemcregs_t *memc;
1004 uint32 ret = 0;
1005 uint32 config, rd, wr, misc, dqsg, cd, sm, sd;
1006 uint idx, rev;
1008 osh = sb_osh(sbh);
1010 idx = sb_coreidx(sbh);
1012 memc = (sbmemcregs_t *)sb_setcore(sbh, SB_MEMC, 0);
1013 if (memc == 0)
1014 goto out;
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;
1030 } else {
1031 if (rev > 0)
1032 cd = rd;
1033 else
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;
1040 out:
1041 /* switch back to previous core */
1042 sb_setcoreidx(sbh, idx);
1044 return ret;
1047 void
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__(
1055 ".set\tmips3\n\t"
1056 "sync\n\t"
1057 "wait\n\t"
1058 ".set\tmips0");
1060 while (1);
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 */
1072 void
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 */
1081 void
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 */
1091 void
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 */
1101 void
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 */
1110 void
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 */
1119 void
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 */
1127 uint32
1128 hndmips_perf_read_instrcount()
1130 return -(long)(MFC0(C0_PERFORMANCE, 0));
1133 uint32
1134 hndmips_perf_read_cache_miss()
1136 return -(long)(MFC0(C0_PERFORMANCE, 1));
1139 uint32
1140 hndmips_perf_read_cache_hit()
1142 return -(long)(MFC0(C0_PERFORMANCE, 2));
1145 #endif