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