86e2970d24244725d7580d623c78a0364c70de36
[openwrt.git] / target / linux / brcm-2.4 / files / arch / mips / bcm947xx / sbmips.c
1 /*
2 * BCM47XX Sonics SiliconBackplane MIPS core routines
3 *
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.
11 *
12 * $Id$
13 */
14
15 #include <typedefs.h>
16 #include <bcmdefs.h>
17 #include <osl.h>
18 #include <sbutils.h>
19 #include <bcmdevs.h>
20 #include <bcmnvram.h>
21 #include <sbconfig.h>
22 #include <sbchipc.h>
23 #include <sbextif.h>
24 #include <sbmemc.h>
25 #include <mipsinc.h>
26 #include <sbhndmips.h>
27 #include <hndcpu.h>
28 #include <hndmips.h>
29
30 /* sbipsflag register format, indexed by irq. */
31 static const uint32 sbips_int_mask[] = {
32 0, /* placeholder */
33 SBIPS_INT1_MASK,
34 SBIPS_INT2_MASK,
35 SBIPS_INT3_MASK,
36 SBIPS_INT4_MASK
37 };
38
39 static const uint32 sbips_int_shift[] = {
40 0, /* placeholder */
41 SBIPS_INT1_SHIFT,
42 SBIPS_INT2_SHIFT,
43 SBIPS_INT3_SHIFT,
44 SBIPS_INT4_SHIFT
45 };
46
47 /*
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.
51 *
52 * See sb_irq() for the mapping.
53 */
54 static uint shirq_map_base = 0;
55
56 /* Returns the SB interrupt flag of the current core. */
57 static uint32 sb_getflag(sb_t * sbh)
58 {
59 osl_t *osh;
60 void *regs;
61 sbconfig_t *sb;
62
63 osh = sb_osh(sbh);
64 regs = sb_coreregs(sbh);
65 sb = (sbconfig_t *) ((ulong) regs + SBCONFIGOFF);
66
67 return (R_REG(osh, &sb->sbtpsflag) & SBTPS_NUM0_MASK);
68 }
69
70 /*
71 * Returns the MIPS IRQ assignment of the current core. If unassigned,
72 * 0 is returned.
73 */
74 uint sb_irq(sb_t * sbh)
75 {
76 osl_t *osh;
77 uint idx;
78 void *regs;
79 sbconfig_t *sb;
80 uint32 flag, sbipsflag;
81 uint irq = 0;
82
83 osh = sb_osh(sbh);
84 flag = sb_getflag(sbh);
85
86 idx = sb_coreidx(sbh);
87
88 if ((regs = sb_setcore(sbh, SB_MIPS, 0)) ||
89 (regs = sb_setcore(sbh, SB_MIPS33, 0))) {
90 sb = (sbconfig_t *) ((ulong) regs + SBCONFIGOFF);
91
92 /* sbipsflag specifies which core is routed to interrupts 1 to 4 */
93 sbipsflag = R_REG(osh, &sb->sbipsflag);
94 for (irq = 1; irq <= 4; irq++) {
95 if (((sbipsflag & sbips_int_mask[irq]) >>
96 sbips_int_shift[irq]) == flag)
97 break;
98 }
99 if (irq == 5)
100 irq = 0;
101 }
102
103 sb_setcoreidx(sbh, idx);
104
105 return irq;
106 }
107
108 /* Clears the specified MIPS IRQ. */
109 static void BCMINITFN(sb_clearirq) (sb_t * sbh, uint irq) {
110 osl_t *osh;
111 void *regs;
112 sbconfig_t *sb;
113
114 osh = sb_osh(sbh);
115
116 if (!(regs = sb_setcore(sbh, SB_MIPS, 0)) &&
117 !(regs = sb_setcore(sbh, SB_MIPS33, 0)))
118 ASSERT(regs);
119 sb = (sbconfig_t *) ((ulong) regs + SBCONFIGOFF);
120
121 if (irq == 0)
122 W_REG(osh, &sb->sbintvec, 0);
123 else
124 OR_REG(osh, &sb->sbipsflag, sbips_int_mask[irq]);
125 }
126
127 /*
128 * Assigns the specified MIPS IRQ to the specified core. Shared MIPS
129 * IRQ 0 may be assigned more than once.
130 *
131 * The old assignment to the specified core is removed first.
132 */
133 static void
134 BCMINITFN(sb_setirq) (sb_t * sbh, uint irq, uint coreid, uint coreunit) {
135 osl_t *osh;
136 void *regs;
137 sbconfig_t *sb;
138 uint32 flag;
139 uint oldirq;
140
141 osh = sb_osh(sbh);
142
143 regs = sb_setcore(sbh, coreid, coreunit);
144 ASSERT(regs);
145 flag = sb_getflag(sbh);
146 oldirq = sb_irq(sbh);
147 if (oldirq)
148 sb_clearirq(sbh, oldirq);
149
150 if (!(regs = sb_setcore(sbh, SB_MIPS, 0)) &&
151 !(regs = sb_setcore(sbh, SB_MIPS33, 0)))
152 ASSERT(regs);
153 sb = (sbconfig_t *) ((ulong) regs + SBCONFIGOFF);
154
155 if (!oldirq)
156 AND_REG(osh, &sb->sbintvec, ~(1 << flag));
157
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);
165 }
166 }
167
168 /*
169 * Initializes clocks and interrupts. SB and NVRAM access must be
170 * initialized prior to calling.
171 *
172 * 'shirqmap' enables virtual dedicated OS IRQ mapping if non-zero.
173 */
174 void BCMINITFN(sb_mips_init) (sb_t * sbh, uint shirqmap) {
175 osl_t *osh;
176 ulong hz, ns, tmp;
177 extifregs_t *eir;
178 chipcregs_t *cc;
179 char *value;
180 uint irq;
181
182 osh = sb_osh(sbh);
183
184 /* Figure out current SB clock speed */
185 if ((hz = sb_clock(sbh)) == 0)
186 hz = 100000000;
187 ns = 1000000000 / hz;
188
189 /* Setup external interface timing */
190 if ((eir = sb_setcore(sbh, SB_EXTIF, 0))) {
191 /* Initialize extif so we can get to the LEDs and external UART */
192 W_REG(osh, &eir->prog_config, CF_EN);
193
194 /* Set timing for the flash */
195 tmp = CEIL(10, ns) << FW_W3_SHIFT; /* W3 = 10nS */
196 tmp = tmp | (CEIL(40, ns) << FW_W1_SHIFT); /* W1 = 40nS */
197 tmp = tmp | CEIL(120, ns); /* W0 = 120nS */
198 W_REG(osh, &eir->prog_waitcount, tmp); /* 0x01020a0c for a 100Mhz clock */
199
200 /* Set programmable interface timing for external uart */
201 tmp = CEIL(10, ns) << FW_W3_SHIFT; /* W3 = 10nS */
202 tmp = tmp | (CEIL(20, ns) << FW_W2_SHIFT); /* W2 = 20nS */
203 tmp = tmp | (CEIL(100, ns) << FW_W1_SHIFT); /* W1 = 100nS */
204 tmp = tmp | CEIL(120, ns); /* W0 = 120nS */
205 W_REG(osh, &eir->prog_waitcount, tmp); /* 0x01020a0c for a 100Mhz clock */
206 } else if ((cc = sb_setcore(sbh, SB_CC, 0))) {
207 /* Set timing for the flash */
208 tmp = CEIL(10, ns) << FW_W3_SHIFT; /* W3 = 10nS */
209 tmp |= CEIL(10, ns) << FW_W1_SHIFT; /* W1 = 10nS */
210 tmp |= CEIL(120, ns); /* W0 = 120nS */
211 if ((sb_corerev(sbh) < 9) || (sb_chip(sbh) == 0x5365))
212 W_REG(osh, &cc->flash_waitcount, tmp);
213
214 if ((sb_corerev(sbh) < 9) ||
215 ((sb_chip(sbh) == BCM5350_CHIP_ID) && sb_chiprev(sbh) == 0)
216 || (sb_chip(sbh) == 0x5365)) {
217 W_REG(osh, &cc->pcmcia_memwait, tmp);
218 }
219
220 /* Save shared IRQ mapping base */
221 shirq_map_base = shirqmap;
222 }
223
224 /* Chip specific initialization */
225 switch (sb_chip(sbh)) {
226 case BCM4710_CHIP_ID:
227 /* Clear interrupt map */
228 for (irq = 0; irq <= 4; irq++)
229 sb_clearirq(sbh, irq);
230 sb_setirq(sbh, 0, SB_CODEC, 0);
231 sb_setirq(sbh, 0, SB_EXTIF, 0);
232 sb_setirq(sbh, 2, SB_ENET, 1);
233 sb_setirq(sbh, 3, SB_ILINE20, 0);
234 sb_setirq(sbh, 4, SB_PCI, 0);
235 ASSERT(eir);
236 value = nvram_get("et0phyaddr");
237 if (value && !strcmp(value, "31")) {
238 /* Enable internal UART */
239 W_REG(osh, &eir->corecontrol, CC_UE);
240 /* Give USB its own interrupt */
241 sb_setirq(sbh, 1, SB_USB, 0);
242 } else {
243 /* Disable internal UART */
244 W_REG(osh, &eir->corecontrol, 0);
245 /* Give Ethernet its own interrupt */
246 sb_setirq(sbh, 1, SB_ENET, 0);
247 sb_setirq(sbh, 0, SB_USB, 0);
248 }
249 break;
250 case BCM5350_CHIP_ID:
251 /* Clear interrupt map */
252 for (irq = 0; irq <= 4; irq++)
253 sb_clearirq(sbh, irq);
254 sb_setirq(sbh, 0, SB_CC, 0);
255 sb_setirq(sbh, 0, SB_MIPS33, 0);
256 sb_setirq(sbh, 1, SB_D11, 0);
257 sb_setirq(sbh, 2, SB_ENET, 0);
258 sb_setirq(sbh, 3, SB_PCI, 0);
259 sb_setirq(sbh, 4, SB_USB, 0);
260 break;
261 case BCM4785_CHIP_ID:
262 /* Reassign PCI to irq 4 */
263 sb_setirq(sbh, 4, SB_PCI, 0);
264 break;
265 }
266 }
267
268 uint32
269 BCMINITFN(sb_cpu_clock)(sb_t *sbh)
270 {
271 extifregs_t *eir;
272 chipcregs_t *cc;
273 uint32 n, m;
274 uint idx;
275 uint32 pll_type, rate = 0;
276
277 /* get index of the current core */
278 idx = sb_coreidx(sbh);
279 pll_type = PLL_TYPE1;
280
281 /* switch to extif or chipc core */
282 if ((eir = (extifregs_t *) sb_setcore(sbh, SB_EXTIF, 0))) {
283 n = R_REG(osh, &eir->clockcontrol_n);
284 m = R_REG(osh, &eir->clockcontrol_sb);
285 } else if ((cc = (chipcregs_t *) sb_setcore(sbh, SB_CC, 0))) {
286 /* 5354 chip uses a non programmable PLL of frequency 240MHz */
287 if (sb_chip(sbh) == BCM5354_CHIP_ID) {
288 rate = 240000000;
289 goto out;
290 }
291 pll_type = R_REG(osh, &cc->capabilities) & CC_CAP_PLL_MASK;
292 n = R_REG(osh, &cc->clockcontrol_n);
293 if ((pll_type == PLL_TYPE2) ||
294 (pll_type == PLL_TYPE4) ||
295 (pll_type == PLL_TYPE6) || (pll_type == PLL_TYPE7))
296 m = R_REG(osh, &cc->clockcontrol_m3);
297 else if (pll_type == PLL_TYPE5) {
298 rate = 200000000;
299 goto out;
300 } else if (pll_type == PLL_TYPE3) {
301 if (sb_chip(sbh) == BCM5365_CHIP_ID) {
302 rate = 200000000;
303 goto out;
304 }
305 /* 5350 uses m2 to control mips */
306 else
307 m = R_REG(osh, &cc->clockcontrol_m2);
308 } else
309 m = R_REG(osh, &cc->clockcontrol_sb);
310 } else
311 goto out;
312
313 /* calculate rate */
314 if (sb_chip(sbh) == 0x5365)
315 rate = 100000000;
316 else
317 rate = sb_clock_rate(pll_type, n, m);
318
319 if (pll_type == PLL_TYPE6)
320 rate = SB2MIPS_T6(rate);
321
322 out:
323 /* switch back to previous core */
324 sb_setcoreidx(sbh, idx);
325
326 return rate;
327 }
328
329 #define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4)
330
331 static void BCMINITFN(handler) (void) {
332 __asm__(".set\tmips32\n\t" "ssnop\n\t" "ssnop\n\t"
333 /* Disable interrupts */
334 /* MTC0(C0_STATUS, 0, MFC0(C0_STATUS, 0) & ~(ALLINTS | STO_IE)); */
335 "mfc0 $15, $12\n\t"
336 /* Just a Hack to not to use reg 'at' which was causing problems on 4704 A2 */
337 "li $14, -31746\n\t"
338 "and $15, $15, $14\n\t"
339 "mtc0 $15, $12\n\t" "eret\n\t" "nop\n\t" "nop\n\t"
340 ".set\tmips0");
341 }
342
343 /* The following MUST come right after handler() */
344 static void BCMINITFN(afterhandler) (void) {
345 }
346
347 /*
348 * Set the MIPS, backplane and PCI clocks as closely as possible.
349 *
350 * MIPS clocks synchronization function has been moved from PLL in chipcommon
351 * core rev. 15 to a DLL inside the MIPS core in 4785.
352 */
353 bool
354 BCMINITFN(sb_mips_setclock) (sb_t * sbh, uint32 mipsclock, uint32 sbclock,
355 uint32 pciclock) {
356 extifregs_t *eir = NULL;
357 chipcregs_t *cc = NULL;
358 mipsregs_t *mipsr = NULL;
359 volatile uint32 *clockcontrol_n, *clockcontrol_sb, *clockcontrol_pci,
360 *clockcontrol_m2;
361 uint32 orig_n, orig_sb, orig_pci, orig_m2, orig_mips, orig_ratio_parm,
362 orig_ratio_cfg;
363 uint32 pll_type, sync_mode;
364 uint ic_size, ic_lsize;
365 uint idx, i;
366
367 /* PLL configuration: type 1 */
368 typedef struct {
369 uint32 mipsclock;
370 uint16 n;
371 uint32 sb;
372 uint32 pci33;
373 uint32 pci25;
374 } n3m_table_t;
375 static n3m_table_t BCMINITDATA(type1_table)[] = {
376 /* 96.000 32.000 24.000 */
377 {
378 96000000, 0x0303, 0x04020011, 0x11030011, 0x11050011},
379 /* 100.000 33.333 25.000 */
380 {
381 100000000, 0x0009, 0x04020011, 0x11030011, 0x11050011},
382 /* 104.000 31.200 24.960 */
383 {
384 104000000, 0x0802, 0x04020011, 0x11050009, 0x11090009},
385 /* 108.000 32.400 24.923 */
386 {
387 108000000, 0x0403, 0x04020011, 0x11050009, 0x02000802},
388 /* 112.000 32.000 24.889 */
389 {
390 112000000, 0x0205, 0x04020011, 0x11030021, 0x02000403},
391 /* 115.200 32.000 24.000 */
392 {
393 115200000, 0x0303, 0x04020009, 0x11030011, 0x11050011},
394 /* 120.000 30.000 24.000 */
395 {
396 120000000, 0x0011, 0x04020011, 0x11050011, 0x11090011},
397 /* 124.800 31.200 24.960 */
398 {
399 124800000, 0x0802, 0x04020009, 0x11050009, 0x11090009},
400 /* 128.000 32.000 24.000 */
401 {
402 128000000, 0x0305, 0x04020011, 0x11050011, 0x02000305},
403 /* 132.000 33.000 24.750 */
404 {
405 132000000, 0x0603, 0x04020011, 0x11050011, 0x02000305},
406 /* 136.000 32.640 24.727 */
407 {
408 136000000, 0x0c02, 0x04020011, 0x11090009, 0x02000603},
409 /* 140.000 30.000 24.706 */
410 {
411 140000000, 0x0021, 0x04020011, 0x11050021, 0x02000c02},
412 /* 144.000 30.857 24.686 */
413 {
414 144000000, 0x0405, 0x04020011, 0x01020202, 0x11090021},
415 /* 150.857 33.000 24.000 */
416 {
417 150857142, 0x0605, 0x04020021, 0x02000305, 0x02000605},
418 /* 152.000 32.571 24.000 */
419 {
420 152000000, 0x0e02, 0x04020011, 0x11050021, 0x02000e02},
421 /* 156.000 31.200 24.960 */
422 {
423 156000000, 0x0802, 0x04020005, 0x11050009, 0x11090009},
424 /* 160.000 32.000 24.000 */
425 {
426 160000000, 0x0309, 0x04020011, 0x11090011, 0x02000309},
427 /* 163.200 32.640 24.727 */
428 {
429 163200000, 0x0c02, 0x04020009, 0x11090009, 0x02000603},
430 /* 168.000 32.000 24.889 */
431 {
432 168000000, 0x0205, 0x04020005, 0x11030021, 0x02000403},
433 /* 176.000 33.000 24.000 */
434 {
435 176000000, 0x0602, 0x04020003, 0x11050005, 0x02000602},};
436
437 /* PLL configuration: type 3 */
438 typedef struct {
439 uint32 mipsclock;
440 uint16 n;
441 uint32 m2; /* that is the clockcontrol_m2 */
442 } type3_table_t;
443 static type3_table_t type3_table[] = {
444 /* for 5350, mips clock is always double sb clock */
445 {150000000, 0x311, 0x4020005},
446 {200000000, 0x311, 0x4020003},
447 };
448
449 /* PLL configuration: type 2, 4, 7 */
450 typedef struct {
451 uint32 mipsclock;
452 uint32 sbclock;
453 uint32 pciclock;
454 uint16 n;
455 uint32 sb;
456 uint32 pci33;
457 uint32 m2;
458 uint32 m3;
459 uint32 ratio_cfg;
460 uint32 ratio_parm;
461 uint32 d11_r1;
462 uint32 d11_r2;
463 } n4m_table_t;
464 static n4m_table_t BCMINITDATA(type2_table)[] = {
465 {
466 120000000, 60000000, 32000000, 0x0303, 0x01000200,
467 0x01000600, 0x01000200, 0x05000200, 11, 0x0aaa0555,
468 8 /* ratio 4/8 */ ,
469 0x00aa0055}, {
470 150000000, 75000000, 33333333, 0x0303, 0x01000100,
471 0x01000600, 0x01000100, 0x05000100, 11, 0x0aaa0555,
472 8 /* ratio 4/8 */ ,
473 0x00aa0055}, {
474 180000000, 80000000, 30000000, 0x0403, 0x01010000,
475 0x01020300, 0x01020600, 0x05000100, 8, 0x012a00a9,
476 9 /* ratio 4/9 */ ,
477 0x012a00a9}, {
478 180000000, 90000000, 30000000, 0x0403, 0x01000100,
479 0x01020300, 0x01000100, 0x05000100, 11, 0x0aaa0555,
480 8 /* ratio 4/8 */ ,
481 0x00aa0055}, {
482 200000000, 100000000, 33333333, 0x0303, 0x02010000,
483 0x02040001, 0x02010000, 0x06000001, 11, 0x0aaa0555,
484 8 /* ratio 4/8 */ ,
485 0x00aa0055}, {
486 211200000, 105600000, 30171428, 0x0902, 0x01000200,
487 0x01030400, 0x01000200, 0x05000200, 11, 0x0aaa0555,
488 8 /* ratio 4/8 */ ,
489 0x00aa0055}, {
490 220800000, 110400000, 31542857, 0x1500, 0x01000200,
491 0x01030400, 0x01000200, 0x05000200, 11, 0x0aaa0555,
492 8 /* ratio 4/8 */ ,
493 0x00aa0055}, {
494 230400000, 115200000, 32000000, 0x0604, 0x01000200,
495 0x01020600, 0x01000200, 0x05000200, 11, 0x0aaa0555,
496 8 /* ratio 4/8 */ ,
497 0x00aa0055}, {
498 234000000, 104000000, 31200000, 0x0b01, 0x01010000,
499 0x01010700, 0x01020600, 0x05000100, 8, 0x012a00a9,
500 9 /* ratio 4/9 */ ,
501 0x012a00a9}, {
502 240000000, 120000000, 33333333, 0x0803, 0x01000200,
503 0x01020600, 0x01000200, 0x05000200, 11, 0x0aaa0555,
504 8 /* ratio 4/8 */ ,
505 0x00aa0055}, {
506 252000000, 126000000, 33333333, 0x0504, 0x01000100,
507 0x01020500, 0x01000100, 0x05000100, 11, 0x0aaa0555,
508 8 /* ratio 4/8 */ ,
509 0x00aa0055}, {
510 264000000, 132000000, 33000000, 0x0903, 0x01000200,
511 0x01020700, 0x01000200, 0x05000200, 11, 0x0aaa0555,
512 8 /* ratio 4/8 */ ,
513 0x00aa0055}, {
514 270000000, 120000000, 30000000, 0x0703, 0x01010000,
515 0x01030400, 0x01020600, 0x05000100, 8, 0x012a00a9,
516 9 /* ratio 4/9 */ ,
517 0x012a00a9}, {
518 276000000, 122666666, 31542857, 0x1500, 0x01010000,
519 0x01030400, 0x01020600, 0x05000100, 8, 0x012a00a9,
520 9 /* ratio 4/9 */ ,
521 0x012a00a9}, {
522 280000000, 140000000, 31111111, 0x0503, 0x01000000,
523 0x01010600, 0x01000000, 0x05000000, 11, 0x0aaa0555,
524 8 /* ratio 4/8 */ ,
525 0x00aa0055}, {
526 288000000, 128000000, 32914285, 0x0604, 0x01010000,
527 0x01030400, 0x01020600, 0x05000100, 8, 0x012a00a9,
528 9 /* ratio 4/9 */ ,
529 0x012a00a9}, {
530 288000000, 144000000, 32000000, 0x0404, 0x01000000,
531 0x01010600, 0x01000000, 0x05000000, 11, 0x0aaa0555,
532 8 /* ratio 4/8 */ ,
533 0x00aa0055}, {
534 300000000, 133333333, 33333333, 0x0803, 0x01010000,
535 0x01020600, 0x01010100, 0x05000100, 8, 0x012a00a9,
536 9 /* ratio 4/9 */ ,
537 0x012a00a9}, {
538 300000000, 133333333, 37500000, 0x0803, 0x01010000,
539 0x01020500, 0x01010100, 0x05000100, 8, 0x012a00a9,
540 9 /* ratio 4/9 */ ,
541 0x012a00a9}, {
542 300000000, 133333333, 42857142, 0x0803, 0x01010000,
543 0x01020400, 0x01010100, 0x05000100, 8, 0x012a00a9,
544 9 /* ratio 4/9 */ ,
545 0x012a00a9}, {
546 300000000, 133333333, 50000000, 0x0803, 0x01010000,
547 0x01020300, 0x01010100, 0x05000100, 8, 0x012a00a9,
548 9 /* ratio 4/9 */ ,
549 0x012a00a9}, {
550 300000000, 133333333, 60000000, 0x0803, 0x01010000,
551 0x01020200, 0x01010100, 0x05000100, 8, 0x012a00a9,
552 9 /* ratio 4/9 */ ,
553 0x012a00a9}, {
554 300000000, 150000000, 33333333, 0x0803, 0x01000100,
555 0x01020600, 0x01010100, 0x05000100, 11, 0x0aaa0555,
556 8 /* ratio 4/8 */ ,
557 0x00aa0055}, {
558 300000000, 150000000, 37500000, 0x0803, 0x01000100,
559 0x01020500, 0x01010100, 0x05000100, 11, 0x0aaa0555,
560 8 /* ratio 4/8 */ ,
561 0x00aa0055}, {
562 300000000, 150000000, 42857142, 0x0803, 0x01000100,
563 0x01020400, 0x01010100, 0x05000100, 11, 0x0aaa0555,
564 8 /* ratio 4/8 */ ,
565 0x00aa0055}, {
566 300000000, 150000000, 50000000, 0x0803, 0x01000100,
567 0x01020300, 0x01010100, 0x05000100, 11, 0x0aaa0555,
568 8 /* ratio 4/8 */ ,
569 0x00aa0055}, {
570 300000000, 150000000, 60000000, 0x0803, 0x01000100,
571 0x01020200, 0x01010100, 0x05000100, 11, 0x0aaa0555,
572 8 /* ratio 4/8 */ ,
573 0x00aa0055}, {
574 330000000, 132000000, 33000000, 0x0903, 0x01000200,
575 0x00020200, 0x01010100, 0x05000100, 0, 0,
576 10 /* ratio 4/10 */ , 0x02520129},
577 {
578 330000000, 146666666, 33000000, 0x0903, 0x01010000,
579 0x00020200, 0x01010100, 0x05000100, 0, 0,
580 9 /* ratio 4/9 */ , 0x012a00a9},
581 {
582 330000000, 165000000, 33000000, 0x0903, 0x01000100,
583 0x00020200, 0x01010100, 0x05000100, 0, 0,
584 8 /* ratio 4/8 */ , 0x00aa0055},
585 {
586 330000000, 165000000, 41250000, 0x0903, 0x01000100,
587 0x00020100, 0x01010100, 0x05000100, 0, 0,
588 8 /* ratio 4/8 */ , 0x00aa0055},
589 {
590 330000000, 165000000, 55000000, 0x0903, 0x01000100,
591 0x00020000, 0x01010100, 0x05000100, 0, 0,
592 8 /* ratio 4/8 */ , 0x00aa0055},
593 {
594 360000000, 120000000, 32000000, 0x0a03, 0x01000300,
595 0x00010201, 0x01010200, 0x05000100, 0, 0,
596 12 /* ratio 4/12 */ , 0x04920492},
597 {
598 360000000, 144000000, 32000000, 0x0a03, 0x01000200,
599 0x00010201, 0x01010200, 0x05000100, 0, 0,
600 10 /* ratio 4/10 */ , 0x02520129},
601 {
602 360000000, 160000000, 32000000, 0x0a03, 0x01010000,
603 0x00010201, 0x01010200, 0x05000100, 0, 0,
604 9 /* ratio 4/9 */ , 0x012a00a9},
605 {
606 360000000, 180000000, 32000000, 0x0a03, 0x01000100,
607 0x00010201, 0x01010200, 0x05000100, 0, 0,
608 8 /* ratio 4/8 */ , 0x00aa0055},
609 {
610 360000000, 180000000, 40000000, 0x0a03, 0x01000100,
611 0x00010101, 0x01010200, 0x05000100, 0, 0,
612 8 /* ratio 4/8 */ , 0x00aa0055},
613 {
614 360000000, 180000000, 53333333, 0x0a03, 0x01000100,
615 0x00010001, 0x01010200, 0x05000100, 0, 0,
616 8 /* ratio 4/8 */ , 0x00aa0055},
617 {
618 390000000, 130000000, 32500000, 0x0b03, 0x01010100,
619 0x00020101, 0x01020100, 0x05000100, 0, 0,
620 12 /* ratio 4/12 */ , 0x04920492},
621 {
622 390000000, 156000000, 32500000, 0x0b03, 0x01000200,
623 0x00020101, 0x01020100, 0x05000100, 0, 0,
624 10 /* ratio 4/10 */ , 0x02520129},
625 {
626 390000000, 173000000, 32500000, 0x0b03, 0x01010000,
627 0x00020101, 0x01020100, 0x05000100, 0, 0,
628 9 /* ratio 4/9 */ , 0x012a00a9},
629 {
630 390000000, 195000000, 32500000, 0x0b03, 0x01000100,
631 0x00020101, 0x01020100, 0x05000100, 0, 0,
632 8 /* ratio 4/8 */ , 0x00aa0055},
633 };
634 static n4m_table_t BCMINITDATA(type4_table)[] = {
635 {
636 120000000, 60000000, 0, 0x0009, 0x11020009, 0x01030203,
637 0x11020009, 0x04000009, 11, 0x0aaa0555}, {
638 150000000, 75000000, 0, 0x0009, 0x11050002, 0x01030203,
639 0x11050002, 0x04000005, 11, 0x0aaa0555}, {
640 192000000, 96000000, 0, 0x0702, 0x04000011, 0x11030011,
641 0x04000011, 0x04000003, 11, 0x0aaa0555}, {
642 198000000, 99000000, 0, 0x0603, 0x11020005, 0x11030011,
643 0x11020005, 0x04000005, 11, 0x0aaa0555}, {
644 200000000, 100000000, 0, 0x0009, 0x04020011, 0x11030011,
645 0x04020011, 0x04020003, 11, 0x0aaa0555}, {
646 204000000, 102000000, 0, 0x0c02, 0x11020005, 0x01030303,
647 0x11020005, 0x04000005, 11, 0x0aaa0555}, {
648 208000000, 104000000, 0, 0x0802, 0x11030002, 0x11090005,
649 0x11030002, 0x04000003, 11, 0x0aaa0555}, {
650 210000000, 105000000, 0, 0x0209, 0x11020005, 0x01030303,
651 0x11020005, 0x04000005, 11, 0x0aaa0555}, {
652 216000000, 108000000, 0, 0x0111, 0x11020005, 0x01030303,
653 0x11020005, 0x04000005, 11, 0x0aaa0555}, {
654 224000000, 112000000, 0, 0x0205, 0x11030002, 0x02002103,
655 0x11030002, 0x04000003, 11, 0x0aaa0555}, {
656 228000000, 101333333, 0, 0x0e02, 0x11030003, 0x11210005,
657 0x01030305, 0x04000005, 8, 0x012a00a9}, {
658 228000000, 114000000, 0, 0x0e02, 0x11020005, 0x11210005,
659 0x11020005, 0x04000005, 11, 0x0aaa0555}, {
660 240000000, 102857143, 0, 0x0109, 0x04000021, 0x01050203,
661 0x11030021, 0x04000003, 13, 0x254a14a9}, {
662 240000000, 120000000, 0, 0x0109, 0x11030002, 0x01050203,
663 0x11030002, 0x04000003, 11, 0x0aaa0555}, {
664 252000000, 100800000, 0, 0x0203, 0x04000009, 0x11050005,
665 0x02000209, 0x04000002, 9, 0x02520129}, {
666 252000000, 126000000, 0, 0x0203, 0x04000005, 0x11050005,
667 0x04000005, 0x04000002, 11, 0x0aaa0555}, {
668 264000000, 132000000, 0, 0x0602, 0x04000005, 0x11050005,
669 0x04000005, 0x04000002, 11, 0x0aaa0555}, {
670 272000000, 116571428, 0, 0x0c02, 0x04000021, 0x02000909,
671 0x02000221, 0x04000003, 13, 0x254a14a9}, {
672 280000000, 120000000, 0, 0x0209, 0x04000021, 0x01030303,
673 0x02000221, 0x04000003, 13, 0x254a14a9}, {
674 288000000, 123428571, 0, 0x0111, 0x04000021, 0x01030303,
675 0x02000221, 0x04000003, 13, 0x254a14a9}, {
676 300000000, 120000000, 0, 0x0009, 0x04000009, 0x01030203,
677 0x02000902, 0x04000002, 9, 0x02520129}, {
678 300000000, 150000000, 0, 0x0009, 0x04000005, 0x01030203,
679 0x04000005, 0x04000002, 11, 0x0aaa0555}
680 };
681 static n4m_table_t BCMINITDATA(type7_table)[] = {
682 {
683 183333333, 91666666, 0, 0x0605, 0x04000011, 0x11030011,
684 0x04000011, 0x04000003, 11, 0x0aaa0555}, {
685 187500000, 93750000, 0, 0x0a03, 0x04000011, 0x11030011,
686 0x04000011, 0x04000003, 11, 0x0aaa0555}, {
687 196875000, 98437500, 0, 0x1003, 0x11020005, 0x11050011,
688 0x11020005, 0x04000005, 11, 0x0aaa0555}, {
689 200000000, 100000000, 0, 0x0311, 0x04000011, 0x11030011,
690 0x04000009, 0x04000003, 11, 0x0aaa0555}, {
691 200000000, 100000000, 0, 0x0311, 0x04020011, 0x11030011,
692 0x04020011, 0x04020003, 11, 0x0aaa0555}, {
693 206250000, 103125000, 0, 0x1103, 0x11020005, 0x11050011,
694 0x11020005, 0x04000005, 11, 0x0aaa0555}, {
695 212500000, 106250000, 0, 0x0c05, 0x11020005, 0x01030303,
696 0x11020005, 0x04000005, 11, 0x0aaa0555}, {
697 215625000, 107812500, 0, 0x1203, 0x11090009, 0x11050005,
698 0x11020005, 0x04000005, 11, 0x0aaa0555}, {
699 216666666, 108333333, 0, 0x0805, 0x11020003, 0x11030011,
700 0x11020003, 0x04000003, 11, 0x0aaa0555}, {
701 225000000, 112500000, 0, 0x0d03, 0x11020003, 0x11030011,
702 0x11020003, 0x04000003, 11, 0x0aaa0555}, {
703 233333333, 116666666, 0, 0x0905, 0x11020003, 0x11030011,
704 0x11020003, 0x04000003, 11, 0x0aaa0555}, {
705 237500000, 118750000, 0, 0x0e05, 0x11020005, 0x11210005,
706 0x11020005, 0x04000005, 11, 0x0aaa0555}, {
707 240000000, 120000000, 0, 0x0b11, 0x11020009, 0x11210009,
708 0x11020009, 0x04000009, 11, 0x0aaa0555}, {
709 250000000, 125000000, 0, 0x0f03, 0x11020003, 0x11210003,
710 0x11020003, 0x04000003, 11, 0x0aaa0555}
711 };
712
713 ulong start, end, dst;
714 bool ret = FALSE;
715
716 volatile uint32 *dll_ctrl = (volatile uint32 *)0xff400008;
717 volatile uint32 *dll_r1 = (volatile uint32 *)0xff400010;
718 volatile uint32 *dll_r2 = (volatile uint32 *)0xff400018;
719
720 /* get index of the current core */
721 idx = sb_coreidx(sbh);
722 clockcontrol_m2 = NULL;
723
724 /* switch to chipc core */
725 /* switch to extif or chipc core */
726 if ((eir = (extifregs_t *) sb_setcore(sbh, SB_EXTIF, 0))) {
727 pll_type = PLL_TYPE1;
728 clockcontrol_n = &eir->clockcontrol_n;
729 clockcontrol_sb = &eir->clockcontrol_sb;
730 clockcontrol_pci = &eir->clockcontrol_pci;
731 clockcontrol_m2 = &cc->clockcontrol_m2;
732 } else if ((cc = (chipcregs_t *) sb_setcore(sbh, SB_CC, 0))) {
733 /* 5354 chipcommon pll setting can't be changed.
734 * The PMU on power up comes up with the default clk frequency
735 * of 240MHz
736 */
737 if (sb_chip(sbh) == BCM5354_CHIP_ID) {
738 ret = TRUE;
739 goto done;
740 }
741 pll_type = R_REG(osh, &cc->capabilities) & CC_CAP_PLL_MASK;
742 if (pll_type == PLL_TYPE6) {
743 clockcontrol_n = NULL;
744 clockcontrol_sb = NULL;
745 clockcontrol_pci = NULL;
746 } else {
747 clockcontrol_n = &cc->clockcontrol_n;
748 clockcontrol_sb = &cc->clockcontrol_sb;
749 clockcontrol_pci = &cc->clockcontrol_pci;
750 clockcontrol_m2 = &cc->clockcontrol_m2;
751 }
752 } else
753 goto done;
754
755 if (pll_type == PLL_TYPE6) {
756 /* Silence compilers */
757 orig_n = orig_sb = orig_pci = 0;
758 } else {
759 /* Store the current clock register values */
760 orig_n = R_REG(osh, clockcontrol_n);
761 orig_sb = R_REG(osh, clockcontrol_sb);
762 orig_pci = R_REG(osh, clockcontrol_pci);
763 }
764
765 if (pll_type == PLL_TYPE1) {
766 /* Keep the current PCI clock if not specified */
767 if (pciclock == 0) {
768 pciclock =
769 sb_clock_rate(pll_type, R_REG(osh, clockcontrol_n),
770 R_REG(osh, clockcontrol_pci));
771 pciclock = (pciclock <= 25000000) ? 25000000 : 33000000;
772 }
773
774 /* Search for the closest MIPS clock less than or equal to a preferred value */
775 for (i = 0; i < ARRAYSIZE(type1_table); i++) {
776 ASSERT(type1_table[i].mipsclock ==
777 sb_clock_rate(pll_type, type1_table[i].n,
778 type1_table[i].sb));
779 if (type1_table[i].mipsclock > mipsclock)
780 break;
781 }
782 if (i == 0) {
783 ret = FALSE;
784 goto done;
785 } else {
786 ret = TRUE;
787 i--;
788 }
789 ASSERT(type1_table[i].mipsclock <= mipsclock);
790
791 /* No PLL change */
792 if ((orig_n == type1_table[i].n) &&
793 (orig_sb == type1_table[i].sb) &&
794 (orig_pci == type1_table[i].pci33))
795 goto done;
796
797 /* Set the PLL controls */
798 W_REG(osh, clockcontrol_n, type1_table[i].n);
799 W_REG(osh, clockcontrol_sb, type1_table[i].sb);
800 if (pciclock == 25000000)
801 W_REG(osh, clockcontrol_pci, type1_table[i].pci25);
802 else
803 W_REG(osh, clockcontrol_pci, type1_table[i].pci33);
804
805 /* Reset */
806 sb_watchdog(sbh, 1);
807 while (1) ;
808 } else if (pll_type == PLL_TYPE3) {
809 /* 5350 */
810 if (sb_chip(sbh) != BCM5365_CHIP_ID) {
811 /*
812 * Search for the closest MIPS clock less than or equal to
813 * a preferred value.
814 */
815 for (i = 0; i < ARRAYSIZE(type3_table); i++) {
816 if (type3_table[i].mipsclock > mipsclock)
817 break;
818 }
819 if (i == 0) {
820 ret = FALSE;
821 goto done;
822 } else {
823 ret = TRUE;
824 i--;
825 }
826 ASSERT(type3_table[i].mipsclock <= mipsclock);
827
828 /* No PLL change */
829 orig_m2 = R_REG(osh, &cc->clockcontrol_m2);
830 if ((orig_n == type3_table[i].n)
831 && (orig_m2 == type3_table[i].m2)) {
832 goto done;
833 }
834
835 /* Set the PLL controls */
836 W_REG(osh, clockcontrol_n, type3_table[i].n);
837 W_REG(osh, clockcontrol_m2, type3_table[i].m2);
838
839 /* Reset */
840 sb_watchdog(sbh, 1);
841 while (1) ;
842 }
843 } else if ((pll_type == PLL_TYPE2) ||
844 (pll_type == PLL_TYPE4) ||
845 (pll_type == PLL_TYPE6) || (pll_type == PLL_TYPE7)) {
846 n4m_table_t *table = NULL, *te;
847 uint tabsz = 0;
848
849 ASSERT(cc);
850
851 orig_mips = R_REG(osh, &cc->clockcontrol_m3);
852
853 switch (pll_type) {
854 case PLL_TYPE6:
855 {
856 uint32 new_mips = 0;
857
858 ret = TRUE;
859 if (mipsclock <= SB2MIPS_T6(CC_T6_M1))
860 new_mips = CC_T6_MMASK;
861
862 if (orig_mips == new_mips)
863 goto done;
864
865 W_REG(osh, &cc->clockcontrol_m3, new_mips);
866 goto end_fill;
867 }
868 case PLL_TYPE2:
869 table = type2_table;
870 tabsz = ARRAYSIZE(type2_table);
871 break;
872 case PLL_TYPE4:
873 table = type4_table;
874 tabsz = ARRAYSIZE(type4_table);
875 break;
876 case PLL_TYPE7:
877 table = type7_table;
878 tabsz = ARRAYSIZE(type7_table);
879 break;
880 default:
881 ASSERT("No table for plltype" == NULL);
882 break;
883 }
884
885 /* Store the current clock register values */
886 orig_m2 = R_REG(osh, &cc->clockcontrol_m2);
887 orig_ratio_parm = 0;
888 orig_ratio_cfg = 0;
889
890 /* Look up current ratio */
891 for (i = 0; i < tabsz; i++) {
892 if ((orig_n == table[i].n) &&
893 (orig_sb == table[i].sb) &&
894 (orig_pci == table[i].pci33) &&
895 (orig_m2 == table[i].m2)
896 && (orig_mips == table[i].m3)) {
897 orig_ratio_parm = table[i].ratio_parm;
898 orig_ratio_cfg = table[i].ratio_cfg;
899 break;
900 }
901 }
902
903 /* Search for the closest MIPS clock greater or equal to a preferred value */
904 for (i = 0; i < tabsz; i++) {
905 ASSERT(table[i].mipsclock ==
906 sb_clock_rate(pll_type, table[i].n,
907 table[i].m3));
908 if ((mipsclock <= table[i].mipsclock)
909 && ((sbclock == 0) || (sbclock <= table[i].sbclock))
910 && ((pciclock == 0)
911 || (pciclock <= table[i].pciclock)))
912 break;
913 }
914 if (i == tabsz) {
915 ret = FALSE;
916 goto done;
917 } else {
918 te = &table[i];
919 ret = TRUE;
920 }
921
922 /* No PLL change */
923 if ((orig_n == te->n) &&
924 (orig_sb == te->sb) &&
925 (orig_pci == te->pci33) &&
926 (orig_m2 == te->m2) && (orig_mips == te->m3))
927 goto done;
928
929 /* Set the PLL controls */
930 W_REG(osh, clockcontrol_n, te->n);
931 W_REG(osh, clockcontrol_sb, te->sb);
932 W_REG(osh, clockcontrol_pci, te->pci33);
933 W_REG(osh, &cc->clockcontrol_m2, te->m2);
934 W_REG(osh, &cc->clockcontrol_m3, te->m3);
935
936 /* Set the chipcontrol bit to change mipsref to the backplane divider if needed */
937 if ((pll_type == PLL_TYPE7) && (te->sb != te->m2) &&
938 (sb_clock_rate(pll_type, te->n, te->m2) == 120000000))
939 W_REG(osh, &cc->chipcontrol,
940 R_REG(osh, &cc->chipcontrol) | 0x100);
941
942 /* No ratio change */
943 if (sb_chip(sbh) != BCM4785_CHIP_ID) {
944 if (orig_ratio_parm == te->ratio_parm)
945 goto end_fill;
946 }
947
948 /* Preload the code into the cache */
949 icache_probe(MFC0(C0_CONFIG, 1), &ic_size, &ic_lsize);
950 if (sb_chip(sbh) == BCM4785_CHIP_ID) {
951 start = ((ulong) && start_fill_4785) & ~(ic_lsize - 1);
952 end = ((ulong)
953 && end_fill_4785 + (ic_lsize - 1)) & ~(ic_lsize -
954 1);
955 } else {
956 start = ((ulong) && start_fill) & ~(ic_lsize - 1);
957 end = ((ulong)
958 && end_fill + (ic_lsize - 1)) & ~(ic_lsize - 1);
959 }
960 while (start < end) {
961 cache_op(start, Fill_I);
962 start += ic_lsize;
963 }
964
965 /* 4785 clock freq change procedures */
966 if (sb_chip(sbh) == BCM4785_CHIP_ID) {
967 start_fill_4785:
968 /* Switch to async */
969 MTC0(C0_BROADCOM, 4, (1 << 22));
970
971 /* Set clock ratio in MIPS */
972 *dll_r1 = (*dll_r1 & 0xfffffff0) | (te->d11_r1 - 1);
973 *dll_r2 = te->d11_r2;
974
975 /* Enable new settings in MIPS */
976 *dll_r1 = *dll_r1 | 0xc0000000;
977
978 /* Set active cfg */
979 MTC0(C0_BROADCOM, 2,
980 MFC0(C0_BROADCOM, 2) | (1 << 3) | 1);
981
982 /* Fake soft reset (clock cfg registers not reset) */
983 MTC0(C0_BROADCOM, 5, MFC0(C0_BROADCOM, 5) | (1 << 2));
984
985 /* Clear active cfg */
986 MTC0(C0_BROADCOM, 2, MFC0(C0_BROADCOM, 2) & ~(1 << 3));
987
988 /* set watchdog timer */
989 W_REG(osh, &cc->watchdog, 20);
990 (void)R_REG(osh, &cc->chipid);
991
992 /* wait for timer interrupt */
993 __asm__ __volatile__(".set\tmips3\n\t"
994 "sync\n\t" "wait\n\t"
995 ".set\tmips0");
996 end_fill_4785:
997 while (1) ;
998 }
999 /* Generic clock freq change procedures */
1000 else {
1001 /* Copy the handler */
1002 start = (ulong) & handler;
1003 end = (ulong) & afterhandler;
1004 dst = KSEG1ADDR(0x180);
1005 for (i = 0; i < (end - start); i += 4)
1006 *((ulong *) (dst + i)) =
1007 *((ulong *) (start + i));
1008
1009 /* Preload the handler into the cache one line at a time */
1010 for (i = 0; i < (end - start); i += ic_lsize)
1011 cache_op(dst + i, Fill_I);
1012
1013 /* Clear BEV bit */
1014 MTC0(C0_STATUS, 0, MFC0(C0_STATUS, 0) & ~ST0_BEV);
1015
1016 /* Enable interrupts */
1017 MTC0(C0_STATUS, 0,
1018 MFC0(C0_STATUS, 0) | (ALLINTS | ST0_IE));
1019
1020 /* Enable MIPS timer interrupt */
1021 if (!(mipsr = sb_setcore(sbh, SB_MIPS, 0)) &&
1022 !(mipsr = sb_setcore(sbh, SB_MIPS33, 0)))
1023 ASSERT(mipsr);
1024 W_REG(osh, &mipsr->intmask, 1);
1025
1026 start_fill:
1027 /* step 1, set clock ratios */
1028 MTC0(C0_BROADCOM, 3, te->ratio_parm);
1029 MTC0(C0_BROADCOM, 1, te->ratio_cfg);
1030
1031 /* step 2: program timer intr */
1032 W_REG(osh, &mipsr->timer, 100);
1033 (void)R_REG(osh, &mipsr->timer);
1034
1035 /* step 3, switch to async */
1036 sync_mode = MFC0(C0_BROADCOM, 4);
1037 MTC0(C0_BROADCOM, 4, 1 << 22);
1038
1039 /* step 4, set cfg active */
1040 MTC0(C0_BROADCOM, 2, (1 << 3) | 1);
1041
1042 /* steps 5 & 6 */
1043 __asm__ __volatile__(".set\tmips3\n\t" "wait\n\t"
1044 ".set\tmips0");
1045
1046 /* step 7, clear cfg active */
1047 MTC0(C0_BROADCOM, 2, 0);
1048
1049 /* Additional Step: set back to orig sync mode */
1050 MTC0(C0_BROADCOM, 4, sync_mode);
1051
1052 /* step 8, fake soft reset */
1053 MTC0(C0_BROADCOM, 5, MFC0(C0_BROADCOM, 5) | (1 << 2));
1054
1055 end_fill:
1056 /* set watchdog timer */
1057 W_REG(osh, &cc->watchdog, 20);
1058 (void)R_REG(osh, &cc->chipid);
1059
1060 /* wait for timer interrupt */
1061 __asm__ __volatile__(".set\tmips3\n\t"
1062 "sync\n\t" "wait\n\t"
1063 ".set\tmips0");
1064 while (1) ;
1065 }
1066 }
1067
1068 done:
1069 /* Enable 4785 DLL */
1070 if (sb_chip(sbh) == BCM4785_CHIP_ID) {
1071 uint32 tmp;
1072
1073 /* set mask to 1e, enable DLL (bit 0) */
1074 *dll_ctrl |= 0x0041e021;
1075
1076 /* enable aggressive hardware mode */
1077 *dll_ctrl |= 0x00000080;
1078
1079 /* wait for lock flag to clear */
1080 while ((*dll_ctrl & 0x2) == 0) ;
1081
1082 /* clear sticky flags (clear on write 1) */
1083 tmp = *dll_ctrl;
1084 *dll_ctrl = tmp;
1085
1086 /* set mask to 5b'10001 */
1087 *dll_ctrl = (*dll_ctrl & 0xfffc1fff) | 0x00022000;
1088
1089 /* enable sync mode */
1090 MTC0(C0_BROADCOM, 4, MFC0(C0_BROADCOM, 4) & 0xfe3fffff);
1091 (void)MFC0(C0_BROADCOM, 4);
1092 }
1093
1094 /* switch back to previous core */
1095 sb_setcoreidx(sbh, idx);
1096
1097 return ret;
1098 }
1099
1100 void BCMINITFN(enable_pfc) (uint32 mode) {
1101 ulong start, end;
1102 uint ic_size, ic_lsize;
1103
1104 /* If auto then choose the correct mode for this
1105 * platform, currently we only ever select one mode
1106 */
1107 if (mode == PFC_AUTO)
1108 mode = PFC_INST;
1109
1110 icache_probe(MFC0(C0_CONFIG, 1), &ic_size, &ic_lsize);
1111
1112 /* enable prefetch cache if available */
1113 if (MFC0(C0_BROADCOM, 0) & BRCM_PFC_AVAIL) {
1114 start = ((ulong) && setpfc_start) & ~(ic_lsize - 1);
1115 end = ((ulong)
1116 && setpfc_end + (ic_lsize - 1)) & ~(ic_lsize - 1);
1117
1118 /* Preload setpfc code into the cache one line at a time */
1119 while (start < end) {
1120 cache_op(start, Fill_I);
1121 start += ic_lsize;
1122 }
1123
1124 /* Now set the pfc */
1125 setpfc_start:
1126 /* write range */
1127 *(volatile uint32 *)PFC_CR1 = 0xffff0000;
1128
1129 /* enable */
1130 *(volatile uint32 *)PFC_CR0 = mode;
1131 setpfc_end:
1132 /* Compiler foder */
1133 ic_size = 0;
1134 }
1135 }
1136
1137 /* returns the ncdl value to be programmed into sdram_ncdl for calibration */
1138 uint32 BCMINITFN(sb_memc_get_ncdl) (sb_t * sbh) {
1139 osl_t *osh;
1140 sbmemcregs_t *memc;
1141 uint32 ret = 0;
1142 uint32 config, rd, wr, misc, dqsg, cd, sm, sd;
1143 uint idx, rev;
1144
1145 osh = sb_osh(sbh);
1146
1147 idx = sb_coreidx(sbh);
1148
1149 memc = (sbmemcregs_t *) sb_setcore(sbh, SB_MEMC, 0);
1150 if (memc == 0)
1151 goto out;
1152
1153 rev = sb_corerev(sbh);
1154
1155 config = R_REG(osh, &memc->config);
1156 wr = R_REG(osh, &memc->wrncdlcor);
1157 rd = R_REG(osh, &memc->rdncdlcor);
1158 misc = R_REG(osh, &memc->miscdlyctl);
1159 dqsg = R_REG(osh, &memc->dqsgatencdl);
1160
1161 rd &= MEMC_RDNCDLCOR_RD_MASK;
1162 wr &= MEMC_WRNCDLCOR_WR_MASK;
1163 dqsg &= MEMC_DQSGATENCDL_G_MASK;
1164
1165 if (config & MEMC_CONFIG_DDR) {
1166 ret = (wr << 16) | (rd << 8) | dqsg;
1167 } else {
1168 if (rev > 0)
1169 cd = rd;
1170 else
1171 cd = (rd ==
1172 MEMC_CD_THRESHOLD) ? rd : (wr +
1173 MEMC_CD_THRESHOLD);
1174 sm = (misc & MEMC_MISC_SM_MASK) >> MEMC_MISC_SM_SHIFT;
1175 sd = (misc & MEMC_MISC_SD_MASK) >> MEMC_MISC_SD_SHIFT;
1176 ret = (sm << 16) | (sd << 8) | cd;
1177 }
1178
1179 out:
1180 /* switch back to previous core */
1181 sb_setcoreidx(sbh, idx);
1182
1183 return ret;
1184 }
1185
1186 void hnd_cpu_reset(sb_t * sbh)
1187 {
1188 if (sb_chip(sbh) == BCM4785_CHIP_ID)
1189 MTC0(C0_BROADCOM, 4, (1 << 22));
1190 sb_watchdog(sbh, 1);
1191 if (sb_chip(sbh) == BCM4785_CHIP_ID) {
1192 __asm__ __volatile__(".set\tmips3\n\t"
1193 "sync\n\t" "wait\n\t" ".set\tmips0");
1194 }
1195 while (1) ;
1196 }
1197
1198 #if defined(BCMPERFSTATS)
1199 /*
1200 * CP0 Register 25 supports 4 semi-independent 32bit performance counters.
1201 * $25 select 0, 1, 2, and 3 are the counters. The counters *decrement* (who thought this one up?)
1202 * $25 select 4 and 5 each contain 2-16bit control fields, one for each of the 4 counters
1203 * $25 select 6 is the global perf control register.
1204 */
1205 /* enable and start instruction counting */
1206
1207 void hndmips_perf_cyclecount_enable(void)
1208 {
1209 MTC0(C0_PERFORMANCE, 6, 0x80000200); /* global enable perf counters */
1210 MTC0(C0_PERFORMANCE, 4, 0x8048 | MFC0(C0_PERFORMANCE, 4)); /* enable cycles counting for counter 0 */
1211 MTC0(C0_PERFORMANCE, 0, 0); /* zero counter zero */
1212 }
1213
1214 void hndmips_perf_instrcount_enable(void)
1215 {
1216 MTC0(C0_PERFORMANCE, 6, 0x80000200); /* global enable perf counters */
1217 MTC0(C0_PERFORMANCE, 4, 0x8044 | MFC0(C0_PERFORMANCE, 4)); /* enable instructions counting for counter 0 */
1218 MTC0(C0_PERFORMANCE, 0, 0); /* zero counter zero */
1219 }
1220
1221 /* enable and start I$ hit and I$ miss counting */
1222 void hndmips_perf_icachecount_enable(void)
1223 {
1224 MTC0(C0_PERFORMANCE, 6, 0x80000218); /* enable I$ counting */
1225 MTC0(C0_PERFORMANCE, 4, 0x80148018); /* count I$ hits in cntr 0 and misses in cntr 1 */
1226 MTC0(C0_PERFORMANCE, 0, 0); /* zero counter 0 - # I$ hits */
1227 MTC0(C0_PERFORMANCE, 1, 0); /* zero counter 1 - # I$ misses */
1228 }
1229
1230 /* enable and start D$ hit and I$ miss counting */
1231 void hndmips_perf_dcachecount_enable(void)
1232 {
1233 MTC0(C0_PERFORMANCE, 6, 0x80000211); /* enable D$ counting */
1234 MTC0(C0_PERFORMANCE, 4, 0x80248028); /* count D$ hits in cntr 0 and misses in cntr 1 */
1235 MTC0(C0_PERFORMANCE, 0, 0); /* zero counter 0 - # D$ hits */
1236 MTC0(C0_PERFORMANCE, 1, 0); /* zero counter 1 - # D$ misses */
1237 }
1238
1239 void hndmips_perf_icache_miss_enable()
1240 {
1241 MTC0(C0_PERFORMANCE, 4, 0x80140000 | MFC0(C0_PERFORMANCE, 4)); /* enable cache misses counting for counter 1 */
1242 MTC0(C0_PERFORMANCE, 1, 0); /* zero counter one */
1243 }
1244
1245 void hndmips_perf_icache_hit_enable()
1246 {
1247 MTC0(C0_PERFORMANCE, 5, 0x8018 | MFC0(C0_PERFORMANCE, 5));
1248 /* enable cache hits counting for counter 2 */
1249 MTC0(C0_PERFORMANCE, 2, 0); /* zero counter 2 */
1250 }
1251
1252 uint32 hndmips_perf_read_instrcount()
1253 {
1254 return -(long)(MFC0(C0_PERFORMANCE, 0));
1255 }
1256
1257 uint32 hndmips_perf_read_cache_miss()
1258 {
1259 return -(long)(MFC0(C0_PERFORMANCE, 1));
1260 }
1261
1262 uint32 hndmips_perf_read_cache_hit()
1263 {
1264 return -(long)(MFC0(C0_PERFORMANCE, 2));
1265 }
1266
1267 #endif
This page took 0.103556 seconds and 3 git commands to generate.