📄 sb_utils.c
字号:
/* ********************************************************************* * Broadcom Common Firmware Environment (CFE) * * Silicon Backplane utilities File: sb_utils.c * ********************************************************************* * * Copyright 2003,2004 * Broadcom Corporation. All rights reserved. * * This software is furnished under license and may be used and * copied only in accordance with the following terms and * conditions. Subject to these conditions, you may download, * copy, install, use, modify and distribute modified or unmodified * copies of this software in source and/or binary form. No title * or ownership is transferred hereby. * * 1) Any source code used, modified or distributed must reproduce * and retain this copyright notice and list of conditions * as they appear in the source file. * * 2) No right is granted to use any trade name, trademark, or * logo of Broadcom Corporation. The "Broadcom Corporation" * name may not be used to endorse or promote products derived * from this software without the prior written permission of * Broadcom Corporation. * * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. ********************************************************************* *//* * Misc utility routines for accessing chip-specific features * of SiliconBackplane-based chips. */#include "cfe.h"#include "sbmips32.h"#include "sb_bp.h"#include "sb_utils.h"/* * Depending on the chip, either the Chip Common or the External * Interface core provides global state and control. These are * mutually exclusive. The corresponding registers in the two cores * have compatible formats, but the core base address and the register * offsets depend on the core. */#if defined(SB_EXTIF_BASE)#include "sb_extif.h"#elif defined(SB_CHIPC_BASE)#include "sb_chipc.h"#else#error "Neither EXT_IF nor CHIPC defined"#endif#define ASSERT(x) \ do { if (!(x)) printf("sb_utils: assertion failed\n"); } while (0)/* Sharable clock related definitions and calculations. *//* PLL types */#define PLL_NONE 0x00000000#define PLL_N3M 0x00010000#define PLL_N4M 0x00020000#define PLL_TYPE3 0x00030000#define PLL_TYPE4 0x00008000#define CC_CLOCK_BASE 24000000 /* Half the clock freq. *//* bcm4710 (N3M) Clock Control magic field values */#define CC_F6_2 0x02 /* A factor of 2 in */#define CC_F6_3 0x03 /* 6-bit fields like */#define CC_F6_4 0x05 /* N1, M1 or M3 */#define CC_F6_5 0x09#define CC_F6_6 0x11#define CC_F6_7 0x21#define CC_F5_BIAS 5 /* 5-bit fields get this added */#define CC_MC_BYPASS 0x08#define CC_MC_M1 0x04#define CC_MC_M1M2 0x02#define CC_MC_M1M2M3 0x01#define CC_MC_M1M3 0x11/* bcm5836 (N4M) Clock Control magic field values (ditto) */#define CC_T2_BIAS 2 /* N1, N2, M1 & M3 bias */#define CC_T2M2_BIAS 3 /* M2 bias */#define CC_T2MC_M1BYP 1#define CC_T2MC_M2BYP 2#define CC_T2MC_M3BYP 4static inline uint32_tfactor6(uint32_t x){ switch (x) { case CC_F6_2: return 2; case CC_F6_3: return 3; case CC_F6_4: return 4; case CC_F6_5: return 5; case CC_F6_6: return 6; case CC_F6_7: return 7; default: return 0; }}/* * Calculate the PLL output frequency given a set of clockcontrol * values (CC_CLOCK_BASE assumed fixed). */static uint32_tsb_clock_rate(uint32_t pll_type, uint32_t n, uint32_t m){ uint32_t n1, n2, clock, m1, m2, m3, mc; n1 = G_CCN_N1(n); n2 = G_CCN_N2(n); if (pll_type == PLL_N3M) { n1 = factor6(n1); n2 += CC_F5_BIAS; } else if (pll_type == PLL_N4M) { n1 += CC_T2_BIAS; n2 += CC_T2_BIAS; } else if (pll_type == PLL_TYPE3) { return 100000000; /* NB: for SB only */ } else { ASSERT(0); return 0; } clock = CC_CLOCK_BASE * n1 * n2; if (clock == 0) return 0; m1 = G_CCM_M1(m); m2 = G_CCM_M2(m); m3 = G_CCM_M3(m); mc = G_CCM_MC(m); if (pll_type == PLL_N3M) { m1 = factor6(m1); m2 += CC_F5_BIAS; m3 = factor6(m3); switch (mc) { case CC_MC_BYPASS: return clock; case CC_MC_M1: return clock / m1; case CC_MC_M1M2: return clock / (m1 * m2); case CC_MC_M1M2M3: return clock / (m1 * m2 * m3); case CC_MC_M1M3: return clock / (m1 * m3); default: return 0; } } else if (pll_type == PLL_N4M) { m1 += CC_T2_BIAS; m2 += CC_T2M2_BIAS; m3 += CC_T2_BIAS; if ((mc & CC_T2MC_M1BYP) == 0) clock /= m1; if ((mc & CC_T2MC_M2BYP) == 0) clock /= m2; if ((mc & CC_T2MC_M3BYP) == 0) clock /= m3; return clock; } else { ASSERT(0); return 0; }}#if defined(SB_EXTIF_BASE)/* Note: For EXTIF cores, the PLL must be N3M (aka TYPE1). *//* Access EXTIF "enumeration" space */#define READCSR(x) \ (*(volatile uint32_t *)PHYS_TO_K1(SB_EXTIF_BASE+(x)))#define WRITECSR(x,v) \ (*(volatile uint32_t *)PHYS_TO_K1(SB_EXTIF_BASE+(x)) = (v))/* * Reset the entire chip and copy master clock registers to the slaves. */voidsb_chip_reset(void){ /* instant NMI from watchdog timeout after 1 tick */ WRITECSR(R_WATCHDOGCNTR, 1); while (1) ;}/* Return the current speed the SB is running at */uint32_tsb_clock(void){ uint32_t clockcontrol_n, clockcontrol_sb; clockcontrol_n = READCSR(R_CLOCKCONTROLN); clockcontrol_sb = READCSR(R_CLOCKCONTROLSB); return sb_clock_rate(PLL_N3M, clockcontrol_n, clockcontrol_sb);}/* Return the current speed the CPU is running at. */uint32_tsb_cpu_clock(void){ /* For EXTIF parts, cpu and backplane clocks are identical. */ return sb_clock();}/* Set the current speed of the SB to the desired rate (as closely as possible) */intsb_setclock(uint32_t sb, uint32_t pci){ uint32_t old_n, old_sb, old_pci; uint32_t new_n, new_sb, new_pci; uint i; static const struct { uint32_t clock; uint16_t n; uint32_t sb; uint32_t m33; uint32_t m25; } sb_clock_table[] = { { 96000000, 0x0303, 0x04020011, 0x11030011, 0x11050011 }, /* 96.000 32.000 24.000 */ { 100000000, 0x0009, 0x04020011, 0x11030011, 0x11050011 }, /* 100.000 33.333 25.000 */ { 104000000, 0x0802, 0x04020011, 0x11050009, 0x11090009 }, /* 104.000 31.200 24.960 */ { 108000000, 0x0403, 0x04020011, 0x11050009, 0x02000802 }, /* 108.000 32.400 24.923 */ { 112000000, 0x0205, 0x04020011, 0x11030021, 0x02000403 }, /* 112.000 32.000 24.889 */ { 115200000, 0x0303, 0x04020009, 0x11030011, 0x11050011 }, /* 115.200 32.000 24.000 */ { 120000000, 0x0011, 0x04020011, 0x11050011, 0x11090011 }, /* 120.000 30.000 24.000 */ { 124800000, 0x0802, 0x04020009, 0x11050009, 0x11090009 }, /* 124.800 31.200 24.960 */ { 128000000, 0x0305, 0x04020011, 0x11050011, 0x02000305 }, /* 128.000 32.000 24.000 */ { 132000000, 0x0603, 0x04020011, 0x11050011, 0x02000305 }, /* 132.000 33.000 24.750 */ { 136000000, 0x0c02, 0x04020011, 0x11090009, 0x02000603 }, /* 136.000 32.640 24.727 */ { 140000000, 0x0021, 0x04020011, 0x11050021, 0x02000c02 }, /* 140.000 30.000 24.706 */ { 144000000, 0x0405, 0x04020011, 0x01020202, 0x11090021 }, /* 144.000 30.857 24.686 */ { 150857142, 0x0605, 0x04020021, 0x02000305, 0x02000605 }, /* 150.857 33.000 24.000 */ { 152000000, 0x0e02, 0x04020011, 0x11050021, 0x02000e02 }, /* 152.000 32.571 24.000 */ { 156000000, 0x0802, 0x04020005, 0x11050009, 0x11090009 }, /* 156.000 31.200 24.960 */ { 160000000, 0x0309, 0x04020011, 0x11090011, 0x02000309 }, /* 160.000 32.000 24.000 */ { 163200000, 0x0c02, 0x04020009, 0x11090009, 0x02000603 }, /* 163.200 32.640 24.727 */ { 168000000, 0x0205, 0x04020005, 0x11030021, 0x02000403 }, /* 168.000 32.000 24.889 */ { 176000000, 0x0602, 0x04020003, 0x11050005, 0x02000602 }, /* 176.000 33.000 24.000 */ }; uint sb_clock_entries = sizeof(sb_clock_table)/sizeof(sb_clock_table[0]); /* Store the current clock reg values */ old_n = READCSR(R_CLOCKCONTROLN); old_sb = READCSR(R_CLOCKCONTROLSB); old_pci = READCSR(R_CLOCKCONTROLPCI); /* keep current pci clock if not specified */ if (pci == 0) { pci = sb_clock_rate(PLL_N3M, old_n, old_pci); } pci = (pci <= 25000000) ? 25000000 : 33000000; /* Find a supported clock setting no faster than the request. */ if (sb < sb_clock_table[0].clock) return 0; for (i = sb_clock_entries-1; i > 0; i--) { if (sb >= sb_clock_table[i].clock) break; } new_n = sb_clock_table[i].n; new_sb = sb_clock_table[i].sb; new_pci = pci == 25000000 ? sb_clock_table[i].m25 : sb_clock_table[i].m33; if (old_n != new_n || old_sb != new_sb || old_pci != new_pci) { /* Reset to install the new clocks if any changed. */ WRITECSR(R_CLOCKCONTROLN, new_n); WRITECSR(R_CLOCKCONTROLSB, new_sb); WRITECSR(R_CLOCKCONTROLPCI, new_pci); /* Clock MII at 25 MHz. */ WRITECSR(R_CLOCKCONTROLMII, sb_clock_table[i].m25); /* No return from chip reset. */ sb_chip_reset(); } return 1;}#elif defined(SB_CHIPC_BASE)/* Access CHIPC "enumeration" space */#define READCSR(x) \ (*(volatile uint32_t *)PHYS_TO_K1(SB_CHIPC_BASE+(x)))#define WRITECSR(x,v) \ (*(volatile uint32_t *)PHYS_TO_K1(SB_CHIPC_BASE+(x)) = (v))voidsb_chip_reset(void){ /* instant NMI from watchdog timeout after 1 tick */ WRITECSR(R_WATCHDOGCNTR, 1); while (1) /* Use 'wait' instead? */ ;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -