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