1/*  *********************************************************************
2    *  Broadcom Common Firmware Environment (CFE)
3    *
4    *  Silicon Backplane utilities       	File: sb_utils.c
5    *
6    *********************************************************************
7    *
8    *  Copyright 2003,2004
9    *  Broadcom Corporation. All rights reserved.
10    *
11    *  This software is furnished under license and may be used and
12    *  copied only in accordance with the following terms and
13    *  conditions.  Subject to these conditions, you may download,
14    *  copy, install, use, modify and distribute modified or unmodified
15    *  copies of this software in source and/or binary form.  No title
16    *  or ownership is transferred hereby.
17    *
18    *  1) Any source code used, modified or distributed must reproduce
19    *     and retain this copyright notice and list of conditions
20    *     as they appear in the source file.
21    *
22    *  2) No right is granted to use any trade name, trademark, or
23    *     logo of Broadcom Corporation.  The "Broadcom Corporation"
24    *     name may not be used to endorse or promote products derived
25    *     from this software without the prior written permission of
26    *     Broadcom Corporation.
27    *
28    *  3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
29    *     IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
30    *     WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
31    *     PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
32    *     SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
33    *     PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
34    *     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
35    *     (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
36    *     GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
37    *     BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
38    *     OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
39    *     TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
40    *     THE POSSIBILITY OF SUCH DAMAGE.
41    ********************************************************************* */
42
43/*
44 * Misc utility routines for accessing chip-specific features
45 * of SiliconBackplane-based chips.
46 */
47
48#include "cfe.h"
49
50#include "sbmips32.h"
51#include "sb_bp.h"
52#include "sb_utils.h"
53
54/*
55 * Depending on the chip, either the Chip Common or the External
56 * Interface core provides global state and control.  These are
57 * mutually exclusive.  The corresponding registers in the two cores
58 * have compatible formats, but the core base address and the register
59 * offsets depend on the core.
60 */
61
62#if defined(SB_EXTIF_BASE)
63#include "sb_extif.h"
64#elif defined(SB_CHIPC_BASE)
65#include "sb_chipc.h"
66#else
67#error "Neither EXT_IF nor CHIPC defined"
68#endif
69
70
71#define ASSERT(x) \
72  do { if (!(x)) printf("sb_utils: assertion failed\n"); } while (0)
73
74/* Sharable clock related definitions and calculations. */
75
76/* PLL types */
77
78#define PLL_NONE        0x00000000
79#define PLL_N3M         0x00010000
80#define PLL_N4M         0x00020000
81#define PLL_TYPE3       0x00030000
82#define PLL_TYPE4       0x00008000
83
84#define CC_CLOCK_BASE   24000000      /* Half the clock freq. */
85
86/* bcm4710 (N3M) Clock Control magic field values */
87
88#define CC_F6_2         0x02          /* A factor of 2 in */
89#define CC_F6_3         0x03          /*  6-bit fields like */
90#define CC_F6_4         0x05          /*  N1, M1 or M3 */
91#define CC_F6_5         0x09
92#define CC_F6_6         0x11
93#define CC_F6_7         0x21
94
95#define CC_F5_BIAS      5             /* 5-bit fields get this added */
96
97#define CC_MC_BYPASS    0x08
98#define CC_MC_M1        0x04
99#define CC_MC_M1M2      0x02
100#define CC_MC_M1M2M3    0x01
101#define CC_MC_M1M3      0x11
102
103/* bcm5836 (N4M) Clock Control magic field values (ditto) */
104
105#define	CC_T2_BIAS      2             /* N1, N2, M1 & M3 bias */
106#define	CC_T2M2_BIAS    3             /* M2 bias */
107
108#define	CC_T2MC_M1BYP   1
109#define	CC_T2MC_M2BYP   2
110#define	CC_T2MC_M3BYP 	4
111
112
113static inline uint32_t
114factor6(uint32_t x)
115{
116    switch (x) {
117	case CC_F6_2:	return 2;
118	case CC_F6_3:	return 3;
119	case CC_F6_4:	return 4;
120	case CC_F6_5:	return 5;
121	case CC_F6_6:	return 6;
122	case CC_F6_7:	return 7;
123	default:	return 0;
124	}
125}
126
127/*
128 * Calculate the PLL output frequency given a set of clockcontrol
129 * values (CC_CLOCK_BASE assumed fixed).
130 */
131
132static uint32_t
133sb_clock_rate(uint32_t pll_type, uint32_t n, uint32_t m)
134{
135    uint32_t n1, n2, clock, m1, m2, m3, mc;
136
137    n1 = G_CCN_N1(n);
138    n2 = G_CCN_N2(n);
139
140    if (pll_type == PLL_N3M) {
141	n1 = factor6(n1);
142	n2 += CC_F5_BIAS;
143	}
144    else if (pll_type == PLL_N4M) {
145	n1 += CC_T2_BIAS;
146	n2 += CC_T2_BIAS;
147	}
148    else if (pll_type == PLL_TYPE3) {
149	return 100000000;                 /* NB: for SB only */
150	}
151    else {
152        ASSERT(0);
153	return 0;
154	}
155
156    clock = CC_CLOCK_BASE * n1 * n2;
157
158    if (clock == 0)
159	return 0;
160
161    m1 = G_CCM_M1(m);
162    m2 = G_CCM_M2(m);
163    m3 = G_CCM_M3(m);
164    mc = G_CCM_MC(m);
165
166    if (pll_type == PLL_N3M) {
167	m1 = factor6(m1);
168	m2 += CC_F5_BIAS;
169	m3 = factor6(m3);
170
171	switch (mc) {
172	    case CC_MC_BYPASS:	return clock;
173	    case CC_MC_M1:	return clock / m1;
174	    case CC_MC_M1M2:	return clock / (m1 * m2);
175	    case CC_MC_M1M2M3:	return clock / (m1 * m2 * m3);
176	    case CC_MC_M1M3:	return clock / (m1 * m3);
177	    default:		return 0;
178	    }
179	}
180    else if (pll_type == PLL_N4M) {
181	m1 += CC_T2_BIAS;
182	m2 += CC_T2M2_BIAS;
183	m3 += CC_T2_BIAS;
184	if ((mc & CC_T2MC_M1BYP) == 0)
185	    clock /= m1;
186	if ((mc & CC_T2MC_M2BYP) == 0)
187	    clock /= m2;
188	if ((mc & CC_T2MC_M3BYP) == 0)
189	    clock /= m3;
190	return clock;
191	}
192    else {
193	ASSERT(0);
194	return 0;
195	}
196}
197
198
199#if defined(SB_EXTIF_BASE)
200
201/* Note: For EXTIF cores, the PLL must be N3M (aka TYPE1). */
202
203/* Access EXTIF "enumeration" space */
204
205#define READCSR(x)   \
206  (*(volatile uint32_t *)PHYS_TO_K1(SB_EXTIF_BASE+(x)))
207#define WRITECSR(x,v) \
208  (*(volatile uint32_t *)PHYS_TO_K1(SB_EXTIF_BASE+(x)) = (v))
209
210/*
211 * Reset the entire chip and copy master clock registers to the slaves.
212 */
213
214void
215sb_chip_reset(void)
216{
217    /* instant NMI from watchdog timeout after 1 tick */
218    WRITECSR(R_WATCHDOGCNTR, 1);
219    while (1)
220	;
221}
222
223
224/* Return the current speed the SB is running at */
225uint32_t
226sb_clock(void)
227{
228    uint32_t clockcontrol_n, clockcontrol_sb;
229
230    clockcontrol_n = READCSR(R_CLOCKCONTROLN);
231    clockcontrol_sb = READCSR(R_CLOCKCONTROLSB);
232
233    return sb_clock_rate(PLL_N3M, clockcontrol_n, clockcontrol_sb);
234}
235
236/* Return the current speed the CPU is running at. */
237uint32_t
238sb_cpu_clock(void)
239{
240    /* For EXTIF parts, cpu and backplane clocks are identical. */
241    return sb_clock();
242}
243
244
245/* Set the current speed of the SB to the desired rate (as closely as
246   possible) */
247int
248sb_setclock(uint32_t sb, uint32_t pci)
249{
250    uint32_t old_n, old_sb, old_pci;
251    uint32_t new_n, new_sb, new_pci;
252    uint i;
253    static const struct {
254		uint32_t clock;
255		uint16_t n;
256		uint32_t sb;
257		uint32_t m33;
258		uint32_t m25;
259    } sb_clock_table[] = {
260	{  96000000, 0x0303, 0x04020011, 0x11030011, 0x11050011 },
261	/*  96.000 32.000 24.000 */
262	{ 100000000, 0x0009, 0x04020011, 0x11030011, 0x11050011 },
263	/* 100.000 33.333 25.000 */
264	{ 104000000, 0x0802, 0x04020011, 0x11050009, 0x11090009 },
265	/* 104.000 31.200 24.960 */
266	{ 108000000, 0x0403, 0x04020011, 0x11050009, 0x02000802 },
267	/* 108.000 32.400 24.923 */
268	{ 112000000, 0x0205, 0x04020011, 0x11030021, 0x02000403 },
269	/* 112.000 32.000 24.889 */
270	{ 115200000, 0x0303, 0x04020009, 0x11030011, 0x11050011 },
271	/* 115.200 32.000 24.000 */
272	{ 120000000, 0x0011, 0x04020011, 0x11050011, 0x11090011 },
273	/* 120.000 30.000 24.000 */
274	{ 124800000, 0x0802, 0x04020009, 0x11050009, 0x11090009 },
275	/* 124.800 31.200 24.960 */
276	{ 128000000, 0x0305, 0x04020011, 0x11050011, 0x02000305 },
277	/* 128.000 32.000 24.000 */
278	{ 132000000, 0x0603, 0x04020011, 0x11050011, 0x02000305 },
279	/* 132.000 33.000 24.750 */
280	{ 136000000, 0x0c02, 0x04020011, 0x11090009, 0x02000603 },
281	/* 136.000 32.640 24.727 */
282	{ 140000000, 0x0021, 0x04020011, 0x11050021, 0x02000c02 },
283	/* 140.000 30.000 24.706 */
284	{ 144000000, 0x0405, 0x04020011, 0x01020202, 0x11090021 },
285	/* 144.000 30.857 24.686 */
286	{ 150857142, 0x0605, 0x04020021, 0x02000305, 0x02000605 },
287	/* 150.857 33.000 24.000 */
288	{ 152000000, 0x0e02, 0x04020011, 0x11050021, 0x02000e02 },
289	/* 152.000 32.571 24.000 */
290	{ 156000000, 0x0802, 0x04020005, 0x11050009, 0x11090009 },
291	/* 156.000 31.200 24.960 */
292	{ 160000000, 0x0309, 0x04020011, 0x11090011, 0x02000309 },
293	/* 160.000 32.000 24.000 */
294	{ 163200000, 0x0c02, 0x04020009, 0x11090009, 0x02000603 },
295	/* 163.200 32.640 24.727 */
296	{ 168000000, 0x0205, 0x04020005, 0x11030021, 0x02000403 },
297	/* 168.000 32.000 24.889 */
298	{ 176000000, 0x0602, 0x04020003, 0x11050005, 0x02000602 },
299	/* 176.000 33.000 24.000 */
300    };
301    uint sb_clock_entries = sizeof(sb_clock_table)/sizeof(sb_clock_table[0]);
302
303    /* Store the current clock reg values */
304    old_n = READCSR(R_CLOCKCONTROLN);
305    old_sb = READCSR(R_CLOCKCONTROLSB);
306    old_pci = READCSR(R_CLOCKCONTROLPCI);
307
308    /* keep current pci clock if not specified */
309    if (pci == 0) {
310	pci = sb_clock_rate(PLL_N3M, old_n, old_pci);
311	}
312    pci = (pci <= 25000000) ? 25000000 : 33000000;
313
314    /* Find a supported clock setting no faster than the request. */
315    if (sb < sb_clock_table[0].clock)
316	return 0;
317    for (i = sb_clock_entries-1; i > 0; i--) {
318	if (sb >= sb_clock_table[i].clock)
319	    break;
320	}
321
322    new_n = sb_clock_table[i].n;
323    new_sb = sb_clock_table[i].sb;
324    new_pci = pci == 25000000 ? sb_clock_table[i].m25 : sb_clock_table[i].m33;
325
326    if (old_n != new_n || old_sb != new_sb || old_pci != new_pci) {
327	/* Reset to install the new clocks if any changed. */
328	WRITECSR(R_CLOCKCONTROLN, new_n);
329	WRITECSR(R_CLOCKCONTROLSB, new_sb);
330	WRITECSR(R_CLOCKCONTROLPCI, new_pci);
331	/* Clock MII at 25 MHz. */
332	WRITECSR(R_CLOCKCONTROLMII, sb_clock_table[i].m25);
333
334	/* No return from chip reset. */
335	sb_chip_reset();
336	}
337
338    return 1;
339}
340
341#elif defined(SB_CHIPC_BASE)
342
343/* Access CHIPC "enumeration" space */
344
345#define READCSR(x)    \
346  (*(volatile uint32_t *)PHYS_TO_K1(SB_CHIPC_BASE+(x)))
347#define WRITECSR(x,v) \
348  (*(volatile uint32_t *)PHYS_TO_K1(SB_CHIPC_BASE+(x)) = (v))
349
350void
351sb_chip_reset(void)
352{
353    /* instant NMI from watchdog timeout after 1 tick */
354    WRITECSR(R_WATCHDOGCNTR, 1);
355    while (1)   /* Use 'wait' instead? */
356	;
357}
358
359/* Return the current speed the SB is running at. */
360uint32_t
361sb_clock(void)
362{
363    uint32_t corecap;
364    uint32_t clockcontrol_n, clockcontrol_sb;
365    uint32_t pll_type;
366
367    corecap = READCSR(R_CORECAPABILITIES);
368    switch (G_CORECAP_PL(corecap)) {
369	case K_PL_4710:  pll_type = PLL_N3M;  break;
370	case K_PL_4704:  pll_type = PLL_N4M;  break;
371	case K_PL_5365:  pll_type = PLL_TYPE3; break;
372	default:         pll_type = PLL_NONE; break;
373	}
374    clockcontrol_n = READCSR(R_CLOCKCONTROLN);
375    clockcontrol_sb = READCSR(R_CLOCKCONTROLSB);
376
377    return sb_clock_rate(pll_type, clockcontrol_n, clockcontrol_sb);
378}
379
380/* Return the current speed the CPU is running at. */
381uint32_t
382sb_cpu_clock(void)
383{
384    uint32_t corecap;
385    uint32_t clockcontrol_n, clockcontrol_m;
386    uint32_t pll_type;
387
388    corecap = READCSR(R_CORECAPABILITIES);
389    clockcontrol_n = READCSR(R_CLOCKCONTROLN);
390    switch (G_CORECAP_PL(corecap)) {
391	case K_PL_4710:
392	    pll_type = PLL_N3M;
393	    clockcontrol_m = READCSR(R_CLOCKCONTROLM0);
394	    break;
395	case K_PL_4704:
396	    pll_type = PLL_N4M;
397	    clockcontrol_m = READCSR(R_CLOCKCONTROLM3);
398	    break;
399	case K_PL_5365:
400	    pll_type = PLL_TYPE3;
401	    return 200000000;     /* until PLL_TYPE3 is documented */
402	    break;
403	default:
404	    pll_type = PLL_NONE;
405	    clockcontrol_m = 0;
406	    break;
407	}
408
409    return sb_clock_rate(pll_type, clockcontrol_n, clockcontrol_m);
410}
411
412
413/* Set the current speed of the CPU to the desired rate (as closely as
414   possible).  XXX Currently, cannot change CPU:SB ratio. */
415int
416sb_setclock(uint32_t cpu, uint32_t pci)
417{
418    typedef struct {
419	uint32_t mipsclock;
420	uint32_t sbclock;
421	uint16_t n;
422	uint32_t sb;           /* aka m0 */
423	uint32_t pci33;        /* aka m1 */
424	uint32_t m2;           /* aka mii/uart/mipsref */
425	uint32_t m3;           /* aka mips */
426	uint32_t ratio;        /* cpu:sb */
427	uint32_t ratio_parm;   /* for CP0 register 22, sel 3 (ClkSync) */
428    } n4m_table_t;
429
430    /* XXX 9:4 ratio parm was 0x012a0115.  Current value from BMIPS docs. */
431    static const n4m_table_t type2_table[] = {
432	{ 180000000,  80000000, 0x0403, 0x01010000, 0x01020300,
433	  0x01020600, 0x05000100, 0x94, 0x012a00a9 },
434	{ 180000000,  90000000, 0x0403, 0x01000100, 0x01020300,
435	  0x01000100, 0x05000100, 0x21, 0x0aaa0555 },
436	{ 200000000, 100000000, 0x0303, 0x01000000, 0x01000600,
437	  0x01000000, 0x05000000, 0x21, 0x0aaa0555 },
438	{ 211200000, 105600000, 0x0902, 0x01000200, 0x01030400,
439	  0x01000200, 0x05000200, 0x21, 0x0aaa0555 },
440	{ 220800000, 110400000, 0x1500, 0x01000200, 0x01030400,
441	  0x01000200, 0x05000200, 0x21, 0x0aaa0555 },
442	{ 230400000, 115200000, 0x0604, 0x01000200, 0x01020600,
443	  0x01000200, 0x05000200, 0x21, 0x0aaa0555 },
444	{ 234000000, 104000000, 0x0b01, 0x01010000, 0x01010700,
445	  0x01020600, 0x05000100, 0x94, 0x012a00a9 },
446	{ 240000000, 120000000,	0x0803,	0x01000200, 0x01020600,
447	  0x01000200, 0x05000200, 0x21, 0x0aaa0555 },
448	{ 252000000, 126000000,	0x0504,	0x01000100, 0x01020500,
449	  0x01000100, 0x05000100, 0x21, 0x0aaa0555 },
450	{ 264000000, 132000000, 0x0903, 0x01000200, 0x01020700,
451	  0x01000200, 0x05000200, 0x21, 0x0aaa0555 },
452	{ 270000000, 120000000, 0x0703, 0x01010000, 0x01030400,
453	  0x01020600, 0x05000100, 0x94, 0x012a00a9 },
454	{ 276000000, 122666666, 0x1500, 0x01010000, 0x01030400,
455	  0x01020600, 0x05000100, 0x94, 0x012a00a9 },
456	{ 280000000, 140000000, 0x0503, 0x01000000, 0x01010600,
457	  0x01000000, 0x05000000, 0x21, 0x0aaa0555 },
458	{ 288000000, 128000000, 0x0604, 0x01010000, 0x01030400,
459	  0x01020600, 0x05000100, 0x94, 0x012a00a9 },
460	{ 288000000, 144000000, 0x0404, 0x01000000, 0x01010600,
461	  0x01000000, 0x05000000, 0x21, 0x0aaa0555 },
462	{ 300000000, 133333333, 0x0803, 0x01010000, 0x01020600,
463	  0x01020600, 0x05000100, 0x94, 0x012a00a9 },
464	{ 300000000, 150000000, 0x0803, 0x01000100, 0x01020600,
465	  0x01000100, 0x05000100, 0x21, 0x0aaa0555 }
466    };
467
468    static const n4m_table_t type4_table[] = {
469	{ 192000000,  96000000, 0x0702,	0x04020011, 0x11030011,
470	  0x04020011, 0x04020003, 0x21, 0x0aaa0555 },
471	{ 200000000, 100000000, 0x0009,	0x04020011, 0x11030011,
472	  0x04020011, 0x04020003, 0x21, 0x0aaa0555 },
473	{ 216000000, 108000000, 0x0211, 0x11020005, 0x11030303,
474	  0x11020005, 0x04000005, 0x21, 0x0aaa0555 },
475	{ 228000000, 101333333, 0x0e02, 0x11030003, 0x11210005,
476	  0x11030305, 0x04000005, 0x94, 0x012a00a9 },
477	{ 228000000, 114000000, 0x0e02, 0x11020005, 0x11210005,
478	  0x11020005, 0x04000005, 0x21, 0x0aaa0555 },
479	{ 240000000, 120000000,	0x0109,	0x11030002, 0x01050203,
480	  0x11030002, 0x04000003, 0x21, 0x0aaa0555 },
481	{ 252000000, 126000000,	0x0203,	0x04000005, 0x11050005,
482	  0x04000005, 0x04000002, 0x21, 0x0aaa0555 },
483	{ 264000000, 132000000, 0x0602, 0x04000005, 0x11050005,
484	  0x04000005, 0x04000002, 0x21, 0x0aaa0555 },
485	{ 272000000, 116571428, 0x0c02, 0x04000021, 0x02000909,
486	  0x02000221, 0x04000003, 0x73, 0x254a14a9 },
487	{ 280000000, 120000000, 0x0209, 0x04000021, 0x01030303,
488	  0x02000221, 0x04000003, 0x73, 0x254a14a9 },
489	{ 288000000, 123428571, 0x0111, 0x04000021, 0x01030303,
490	  0x02000221, 0x04000003, 0x73, 0x254a14a9 },
491	{ 300000000, 120000000, 0x0009, 0x04000009, 0x01030203,
492	  0x02000902, 0x04000002, 0x52, 0x02520129 }
493    };
494
495    const n4m_table_t *clock_table;
496    uint clock_entries;
497    uint i;
498    uint32_t old_n;
499    uint32_t old_m0, old_m1, old_m2, old_m3;
500    uint32_t new_n;
501    uint32_t new_m0, new_m1, new_m2, new_m3;
502    uint32_t old_ratio, new_ratio;
503    uint32_t corecap;
504    uint32_t pll_type;
505
506    clock_table = NULL;  clock_entries = 0;   /* defaults */
507
508    corecap = READCSR(R_CORECAPABILITIES);
509    switch (G_CORECAP_PL(corecap)) {
510	case K_PL_4710:    /* XXX Does this ever occur for CHIPC parts? */
511	    pll_type = PLL_N3M;
512	    break;
513	case K_PL_4704:
514	    pll_type = PLL_N4M;
515	    clock_table = type2_table;
516	    clock_entries = sizeof(type2_table)/sizeof(n4m_table_t);
517	    break;
518	case K_PL_5365:
519	    pll_type = PLL_TYPE3;
520	    clock_table = NULL;
521	    return 200000000;     /* until PLL_TYPE3 is documented */
522	    break;
523	case 0:    /* XXX Fix for expanded field. */
524	    pll_type = PLL_TYPE4;
525	    clock_entries = sizeof(type4_table)/sizeof(n4m_table_t);
526	    break;
527	default:
528	    pll_type = PLL_NONE;
529	    break;
530	}
531
532    if (clock_table == NULL)
533	return 0;
534
535    /* Remember the current settings */
536    old_n = READCSR(R_CLOCKCONTROLN);
537    old_m0 = READCSR(R_CLOCKCONTROLM0);
538    old_m1 = READCSR(R_CLOCKCONTROLM1);
539    old_m2 = READCSR(R_CLOCKCONTROLM2);
540    old_m3 = READCSR(R_CLOCKCONTROLM3);
541
542    /* Match to deduce current cpu:sb ratio. */
543    old_ratio = 0;
544    for (i = 0; i < clock_entries; i++) {
545	if (old_n == clock_table[i].n
546	    && old_m0 == clock_table[i].sb && old_m1 == clock_table[i].pci33
547	    && old_m2 == clock_table[i].m2 && old_m3 == clock_table[i].m3) {
548	    old_ratio = clock_table[i].ratio;
549	    break;
550	    }
551	}
552    if (i == clock_entries) {
553	/* No match; look for the supported ratios. */
554	uint32_t mips_clk = sb_clock_rate(pll_type, old_n, old_m3);
555	uint32_t sb_clk = sb_clock_rate(pll_type, old_n, old_m0);
556
557	if (mips_clk == 2*sb_clk)
558	    old_ratio = 0x21;
559	else if (mips_clk == (sb_clk/4)*9)
560	    old_ratio = 0x94;
561	}
562    if (old_ratio == 0)
563	return 0;
564
565    /* Find a supported CPU clock setting no faster than the request. */
566    new_ratio = 0;
567    if (cpu < clock_table[0].mipsclock)
568	return 0;
569    for (i = clock_entries-1; i > 0; i--) {
570	if (cpu >= clock_table[i].mipsclock)
571	    break;
572	}
573
574    new_ratio = clock_table[i].ratio;
575    if (new_ratio != old_ratio)  /* For now, can't change ratios. */
576	return 0;
577
578    new_n = clock_table[i].n;
579    new_m0 = clock_table[i].sb;
580    new_m1 = clock_table[i].pci33;
581    new_m2 = clock_table[i].m2;
582    new_m3 = clock_table[i].m3;
583
584    if (old_n != new_n || old_m0 != new_m0 || old_m1 != new_m1
585	|| old_m2 != new_m2 || old_m3 != new_m3) {
586	/* Reset to install the new clocks if any changed. */
587	WRITECSR(R_CLOCKCONTROLN, new_n);
588	WRITECSR(R_CLOCKCONTROLM0, new_m0);
589	WRITECSR(R_CLOCKCONTROLM1, new_m1);
590	WRITECSR(R_CLOCKCONTROLM2, new_m2);
591	WRITECSR(R_CLOCKCONTROLM3, new_m3);
592
593	/* No return from chip reset. */
594	sb_chip_reset();
595	}
596
597    return 1;
598}
599
600
601/* Return the reference clock being supplied to the internal UART(s). */
602uint32_t
603sb_uart_clock(void)
604{
605    uint32_t coreid, corecap, corectl;
606    uint32_t pll_type;
607    uint32_t cc_n, cc_m;
608    uint32_t clock, div;
609
610    coreid = READCSR(R_SBIDHIGH);
611    corecap = READCSR(R_CORECAPABILITIES);
612    switch (G_CORECAP_PL(corecap)) {
613	case K_PL_4710:  pll_type = PLL_N3M;   break;
614	case K_PL_4704:  pll_type = PLL_N4M;   break;
615	case K_PL_5365:  pll_type = PLL_TYPE3; break;
616	default:         pll_type = PLL_NONE;  break;
617	}
618
619    cc_n = READCSR(R_CLOCKCONTROLN);
620    if (pll_type == PLL_N3M) {
621	cc_m = READCSR(R_CLOCKCONTROLM2);
622        clock = sb_clock_rate(PLL_N3M, cc_n, cc_m);
623	div = 1;
624	}
625    else if (pll_type == PLL_TYPE3) {
626	/* 5365 type clock, not documented */
627	clock = 100000000;
628	div = 54;  /* clock/1843200 */
629	WRITECSR(R_UARTCLOCKDIV, div);
630	}
631    else {
632	if (G_SBID_RV(coreid) >= 3) {
633	    /* Internal backplane clock. */
634	    cc_m = READCSR(R_CLOCKCONTROLSB);
635	    clock = sb_clock_rate(PLL_N4M, cc_n, cc_m);
636	    div = clock/1843200;
637	    WRITECSR(R_UARTCLOCKDIV, div);
638	    }
639	else {
640	    /* Fixed internal backplane clock (4310, certain 4306). */
641	    clock = 88000000;
642	    div = 48;
643	    }
644	}
645
646    /* Clock source depends on strapping if UartClkOverride is unset. */
647    corectl = READCSR(R_CORECONTROL);
648    if ((G_SBID_RV(coreid) > 0) && ((corectl & M_CORECTL_CO) == 0)) {
649	if (G_CORECAP_CS(corecap) == K_CS_INTERNAL) {
650	    /* Internal divided backplane clock */
651	    clock /= div;
652            }
653	else {
654	    /* Assume external clock of 1.8432 MHz */
655	    clock = 1843200;
656	    }
657	}
658
659    return clock;
660}
661#endif /* SB_CHIPC_BASE */
662
663
664/* Backplane interrupt mapping. */
665
666#if defined(SB_MIPS_BASE)
667#define SB_CPU_BASE SB_MIPS_BASE
668#elif defined(SB_MIPS33_BASE)
669#define SB_CPU_BASE SB_MIPS33_BASE
670#else
671#error "Neither MIPS nor MIPS33 core defined"
672#endif
673
674#define READREG(b,x)     (*(uint32_t *)PHYS_TO_K1((b)+(x)))
675#define WRITEREG(b,x,v)  (*(uint32_t *)PHYS_TO_K1((b)+(x)) = (v))
676
677/*
678 * Map the interrupt index for a core (SBTPSFlagNum0 in SBTPSFlag
679 * register) into the (external) interrupt priorities (IPn) defined by
680 * the MIPS architecture.
681 *
682 * The mapping of backplane interrupts to MIPS interrupts is
683 * controlled by the CPU core's SBIPSFLAG register.  Note that any
684 * interrupt source not mapped by the four SBIPSFLAG fields will be
685 * directed to IP0 (level 2) and must additionally be enabled in the
686 * SBINTVEC register.  */
687
688unsigned int
689sb_map_irq(unsigned int flagnum)
690{
691    unsigned int ip;
692    uint32_t ipsflags, intvec;
693
694    ipsflags = READREG(SB_CPU_BASE, R_SBIPSFLAG);
695
696    if (flagnum == G_SBISF_F1(ipsflags))
697        ip = 1;
698    else if (flagnum == G_SBISF_F2(ipsflags))
699        ip = 2;
700    else if (flagnum == G_SBISF_F3(ipsflags))
701        ip = 3;
702    else if (flagnum == G_SBISF_F4(ipsflags))
703        ip = 4;
704    else {
705	intvec = READREG(SB_CPU_BASE, R_SBINTVEC);
706	intvec |= (1 << flagnum);
707	WRITEREG(SB_CPU_BASE, R_SBINTVEC, intvec);
708	ip = 0;
709	}
710
711    return ip;
712}
713