Root/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. */
30static 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
38static 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 */
53static uint shirq_map_base = 0;
54
55/* Returns the SB interrupt flag of the current core. */
56static 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 */
73uint 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. */
108static 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 */
132static void
133BCMINITFN(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 */
173void 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
267uint32
268BCMINITFN(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
330static 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() */
343static 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 */
352bool
353BCMINITFN(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
1099void 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 */
1137uint32 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
1185void 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
1206void 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
1213void 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 */
1221void 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 */
1230void 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
1238void 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
1244void 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
1251uint32 hndmips_perf_read_instrcount()
1252{
1253    return -(long)(MFC0(C0_PERFORMANCE, 0));
1254}
1255
1256uint32 hndmips_perf_read_cache_miss()
1257{
1258    return -(long)(MFC0(C0_PERFORMANCE, 1));
1259}
1260
1261uint32 hndmips_perf_read_cache_hit()
1262{
1263    return -(long)(MFC0(C0_PERFORMANCE, 2));
1264}
1265
1266#endif
1267

Archive Download this file



interactive