diff options
Diffstat (limited to 'openwrt/package/linux/kernel-source/arch/mips/brcm-boards/bcm947xx/sbmips.c')
-rw-r--r-- | openwrt/package/linux/kernel-source/arch/mips/brcm-boards/bcm947xx/sbmips.c | 951 |
1 files changed, 0 insertions, 951 deletions
diff --git a/openwrt/package/linux/kernel-source/arch/mips/brcm-boards/bcm947xx/sbmips.c b/openwrt/package/linux/kernel-source/arch/mips/brcm-boards/bcm947xx/sbmips.c deleted file mode 100644 index 6daaeb78c..000000000 --- a/openwrt/package/linux/kernel-source/arch/mips/brcm-boards/bcm947xx/sbmips.c +++ /dev/null @@ -1,951 +0,0 @@ -/* - * BCM47XX Sonics SiliconBackplane MIPS core routines - * - * Copyright 2004, Broadcom Corporation - * All Rights Reserved. - * - * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY - * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM - * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. - * - * $Id$ - */ - -#include <typedefs.h> -#include <osl.h> -#include <sbutils.h> -#include <bcmdevs.h> -#include <bcmnvram.h> -#include <bcmutils.h> -#include <hndmips.h> -#include <sbconfig.h> -#include <sbextif.h> -#include <sbchipc.h> -#include <sbmemc.h> - -/* - * Memory segments (32bit kernel mode addresses) - */ -#undef KUSEG -#undef KSEG0 -#undef KSEG1 -#undef KSEG2 -#undef KSEG3 -#define KUSEG 0x00000000 -#define KSEG0 0x80000000 -#define KSEG1 0xa0000000 -#define KSEG2 0xc0000000 -#define KSEG3 0xe0000000 - -/* - * Map an address to a certain kernel segment - */ -#undef KSEG0ADDR -#undef KSEG1ADDR -#undef KSEG2ADDR -#undef KSEG3ADDR -#define KSEG0ADDR(a) (((a) & 0x1fffffff) | KSEG0) -#define KSEG1ADDR(a) (((a) & 0x1fffffff) | KSEG1) -#define KSEG2ADDR(a) (((a) & 0x1fffffff) | KSEG2) -#define KSEG3ADDR(a) (((a) & 0x1fffffff) | KSEG3) - -/* - * The following macros are especially useful for __asm__ - * inline assembler. - */ -#ifndef __STR -#define __STR(x) #x -#endif -#ifndef STR -#define STR(x) __STR(x) -#endif - -/* ********************************************************************* - * CP0 Registers - ********************************************************************* */ - -#define C0_INX 0 /* CP0: TLB Index */ -#define C0_RAND 1 /* CP0: TLB Random */ -#define C0_TLBLO0 2 /* CP0: TLB EntryLo0 */ -#define C0_TLBLO C0_TLBLO0 /* CP0: TLB EntryLo0 */ -#define C0_TLBLO1 3 /* CP0: TLB EntryLo1 */ -#define C0_CTEXT 4 /* CP0: Context */ -#define C0_PGMASK 5 /* CP0: TLB PageMask */ -#define C0_WIRED 6 /* CP0: TLB Wired */ -#define C0_BADVADDR 8 /* CP0: Bad Virtual Address */ -#define C0_COUNT 9 /* CP0: Count */ -#define C0_TLBHI 10 /* CP0: TLB EntryHi */ -#define C0_COMPARE 11 /* CP0: Compare */ -#define C0_SR 12 /* CP0: Processor Status */ -#define C0_STATUS C0_SR /* CP0: Processor Status */ -#define C0_CAUSE 13 /* CP0: Exception Cause */ -#define C0_EPC 14 /* CP0: Exception PC */ -#define C0_PRID 15 /* CP0: Processor Revision Indentifier */ -#define C0_CONFIG 16 /* CP0: Config */ -#define C0_LLADDR 17 /* CP0: LLAddr */ -#define C0_WATCHLO 18 /* CP0: WatchpointLo */ -#define C0_WATCHHI 19 /* CP0: WatchpointHi */ -#define C0_XCTEXT 20 /* CP0: XContext */ -#define C0_DIAGNOSTIC 22 /* CP0: Diagnostic */ -#define C0_BROADCOM C0_DIAGNOSTIC /* CP0: Broadcom Register */ -#define C0_ECC 26 /* CP0: ECC */ -#define C0_CACHEERR 27 /* CP0: CacheErr */ -#define C0_TAGLO 28 /* CP0: TagLo */ -#define C0_TAGHI 29 /* CP0: TagHi */ -#define C0_ERREPC 30 /* CP0: ErrorEPC */ - -/* - * Macros to access the system control coprocessor - */ - -#define MFC0(source, sel) \ -({ \ - int __res; \ - __asm__ __volatile__( \ - ".set\tnoreorder\n\t" \ - ".set\tnoat\n\t" \ - ".word\t"STR(0x40010000 | ((source)<<11) | (sel))"\n\t" \ - "move\t%0,$1\n\t" \ - ".set\tat\n\t" \ - ".set\treorder" \ - :"=r" (__res) \ - : \ - :"$1"); \ - __res; \ -}) - -#define MTC0(source, sel, value) \ -do { \ - __asm__ __volatile__( \ - ".set\tnoreorder\n\t" \ - ".set\tnoat\n\t" \ - "move\t$1,%z0\n\t" \ - ".word\t"STR(0x40810000 | ((source)<<11) | (sel))"\n\t" \ - ".set\tat\n\t" \ - ".set\treorder" \ - : \ - :"Jr" (value) \ - :"$1"); \ -} while (0) - -/* - * R4x00 interrupt enable / cause bits - */ -#undef IE_SW0 -#undef IE_SW1 -#undef IE_IRQ0 -#undef IE_IRQ1 -#undef IE_IRQ2 -#undef IE_IRQ3 -#undef IE_IRQ4 -#undef IE_IRQ5 -#define IE_SW0 (1<< 8) -#define IE_SW1 (1<< 9) -#define IE_IRQ0 (1<<10) -#define IE_IRQ1 (1<<11) -#define IE_IRQ2 (1<<12) -#define IE_IRQ3 (1<<13) -#define IE_IRQ4 (1<<14) -#define IE_IRQ5 (1<<15) - -/* - * Bitfields in the R4xx0 cp0 status register - */ -#define ST0_IE 0x00000001 -#define ST0_EXL 0x00000002 -#define ST0_ERL 0x00000004 -#define ST0_KSU 0x00000018 -# define KSU_USER 0x00000010 -# define KSU_SUPERVISOR 0x00000008 -# define KSU_KERNEL 0x00000000 -#define ST0_UX 0x00000020 -#define ST0_SX 0x00000040 -#define ST0_KX 0x00000080 -#define ST0_DE 0x00010000 -#define ST0_CE 0x00020000 - -/* - * Status register bits available in all MIPS CPUs. - */ -#define ST0_IM 0x0000ff00 -#define ST0_CH 0x00040000 -#define ST0_SR 0x00100000 -#define ST0_TS 0x00200000 -#define ST0_BEV 0x00400000 -#define ST0_RE 0x02000000 -#define ST0_FR 0x04000000 -#define ST0_CU 0xf0000000 -#define ST0_CU0 0x10000000 -#define ST0_CU1 0x20000000 -#define ST0_CU2 0x40000000 -#define ST0_CU3 0x80000000 -#define ST0_XX 0x80000000 /* MIPS IV naming */ - -/* - * Cache Operations - */ - -#ifndef Fill_I -#define Fill_I 0x14 -#endif - -#define cache_unroll(base,op) \ - __asm__ __volatile__(" \ - .set noreorder; \ - .set mips3; \ - cache %1, (%0); \ - .set mips0; \ - .set reorder" \ - : \ - : "r" (base), \ - "i" (op)); - -/* - * These are the UART port assignments, expressed as offsets from the base - * register. These assignments should hold for any serial port based on - * a 8250, 16450, or 16550(A). - */ - -#define UART_MCR 4 /* Out: Modem Control Register */ -#define UART_MSR 6 /* In: Modem Status Register */ -#define UART_MCR_LOOP 0x10 /* Enable loopback test mode */ - -/* - * Returns TRUE if an external UART exists at the given base - * register. - */ -static bool -serial_exists(uint8 *regs) -{ - uint8 save_mcr, status1; - - save_mcr = R_REG(®s[UART_MCR]); - W_REG(®s[UART_MCR], UART_MCR_LOOP | 0x0a); - status1 = R_REG(®s[UART_MSR]) & 0xf0; - W_REG(®s[UART_MCR], save_mcr); - - return (status1 == 0x90); -} - -/* - * Initializes UART access. The callback function will be called once - * per found UART. -*/ -void -sb_serial_init(void *sbh, void (*add)(void *regs, uint irq, uint baud_base, uint reg_shift)) -{ - void *regs; - ulong base; - uint irq; - int i, n; - - if ((regs = sb_setcore(sbh, SB_EXTIF, 0))) { - extifregs_t *eir = (extifregs_t *) regs; - sbconfig_t *sb; - - /* Determine external UART register base */ - sb = (sbconfig_t *)((ulong) eir + SBCONFIGOFF); - base = EXTIF_CFGIF_BASE(sb_base(R_REG(&sb->sbadmatch1))); - - /* Determine IRQ */ - irq = sb_irq(sbh); - - /* Disable GPIO interrupt initially */ - W_REG(&eir->gpiointpolarity, 0); - W_REG(&eir->gpiointmask, 0); - - /* Search for external UARTs */ - n = 2; - for (i = 0; i < 2; i++) { - regs = (void *) REG_MAP(base + (i * 8), 8); - if (serial_exists(regs)) { - /* Set GPIO 1 to be the external UART IRQ */ - W_REG(&eir->gpiointmask, 2); - if (add) - add(regs, irq, 13500000, 0); - } - } - - /* Add internal UART if enabled */ - if (R_REG(&eir->corecontrol) & CC_UE) - if (add) - add((void *) &eir->uartdata, irq, sb_clock(sbh), 2); - } else if ((regs = sb_setcore(sbh, SB_CC, 0))) { - chipcregs_t *cc = (chipcregs_t *) regs; - uint32 rev, cap, pll, baud_base, div; - - /* Determine core revision and capabilities */ - rev = sb_corerev(sbh); - cap = R_REG(&cc->capabilities); - pll = cap & CAP_PLL_MASK; - - /* Determine IRQ */ - irq = sb_irq(sbh); - - if (pll == PLL_TYPE1) { - /* PLL clock */ - baud_base = sb_clock_rate(pll, - R_REG(&cc->clockcontrol_n), - R_REG(&cc->clockcontrol_m2)); - div = 1; - } else if (rev >= 3) { - /* Internal backplane clock */ - baud_base = sb_clock_rate(pll, - R_REG(&cc->clockcontrol_n), - R_REG(&cc->clockcontrol_sb)); - div = 2; /* Minimum divisor */ - W_REG(&cc->clkdiv, ((R_REG(&cc->clkdiv) & ~CLKD_UART) | div)); - } else { - /* Fixed internal backplane clock */ - baud_base = 88000000; - div = 48; - } - - /* Clock source depends on strapping if UartClkOverride is unset */ - if ((rev > 0) && ((R_REG(&cc->corecontrol) & CC_UARTCLKO) == 0)) { - if ((cap & CAP_UCLKSEL) == CAP_UINTCLK) { - /* Internal divided backplane clock */ - baud_base /= div; - } else { - /* Assume external clock of 1.8432 MHz */ - baud_base = 1843200; - } - } - - /* Add internal UARTs */ - n = cap & CAP_UARTS_MASK; - for (i = 0; i < n; i++) { - /* Register offset changed after revision 0 */ - if (rev) - regs = (void *)((ulong) &cc->uart0data + (i * 256)); - else - regs = (void *)((ulong) &cc->uart0data + (i * 8)); - - if (add) - add(regs, irq, baud_base, 0); - } - } -} - -/* Returns the SB interrupt flag of the current core. */ -uint32 -sb_flag(void *sbh) -{ - void *regs; - sbconfig_t *sb; - - regs = sb_coreregs(sbh); - sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF); - - return (R_REG(&sb->sbtpsflag) & SBTPS_NUM0_MASK); -} - -static const uint32 sbips_int_mask[] = { - 0, - SBIPS_INT1_MASK, - SBIPS_INT2_MASK, - SBIPS_INT3_MASK, - SBIPS_INT4_MASK -}; - -static const uint32 sbips_int_shift[] = { - 0, - 0, - SBIPS_INT2_SHIFT, - SBIPS_INT3_SHIFT, - SBIPS_INT4_SHIFT -}; - -/* - * Returns the MIPS IRQ assignment of the current core. If unassigned, - * 0 is returned. - */ -uint -sb_irq(void *sbh) -{ - uint idx; - void *regs; - sbconfig_t *sb; - uint32 flag, sbipsflag; - uint irq = 0; - - flag = sb_flag(sbh); - - idx = sb_coreidx(sbh); - - if ((regs = sb_setcore(sbh, SB_MIPS, 0)) || - (regs = sb_setcore(sbh, SB_MIPS33, 0))) { - sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF); - - /* sbipsflag specifies which core is routed to interrupts 1 to 4 */ - sbipsflag = R_REG(&sb->sbipsflag); - for (irq = 1; irq <= 4; irq++) { - if (((sbipsflag & sbips_int_mask[irq]) >> sbips_int_shift[irq]) == flag) - break; - } - if (irq == 5) - irq = 0; - } - - sb_setcoreidx(sbh, idx); - - return irq; -} - -/* Clears the specified MIPS IRQ. */ -static void -sb_clearirq(void *sbh, uint irq) -{ - void *regs; - sbconfig_t *sb; - - if (!(regs = sb_setcore(sbh, SB_MIPS, 0)) && - !(regs = sb_setcore(sbh, SB_MIPS33, 0))) - ASSERT(regs); - sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF); - - if (irq == 0) - W_REG(&sb->sbintvec, 0); - else - OR_REG(&sb->sbipsflag, sbips_int_mask[irq]); -} - -/* - * Assigns the specified MIPS IRQ to the specified core. Shared MIPS - * IRQ 0 may be assigned more than once. - */ -static void -sb_setirq(void *sbh, uint irq, uint coreid, uint coreunit) -{ - void *regs; - sbconfig_t *sb; - uint32 flag; - - regs = sb_setcore(sbh, coreid, coreunit); - ASSERT(regs); - flag = sb_flag(sbh); - - if (!(regs = sb_setcore(sbh, SB_MIPS, 0)) && - !(regs = sb_setcore(sbh, SB_MIPS33, 0))) - ASSERT(regs); - sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF); - - if (irq == 0) - OR_REG(&sb->sbintvec, 1 << flag); - else { - flag <<= sbips_int_shift[irq]; - ASSERT(!(flag & ~sbips_int_mask[irq])); - flag |= R_REG(&sb->sbipsflag) & ~sbips_int_mask[irq]; - W_REG(&sb->sbipsflag, flag); - } -} - -/* - * Initializes clocks and interrupts. SB and NVRAM access must be - * initialized prior to calling. - */ -void -sb_mips_init(void *sbh) -{ - ulong hz, ns, tmp; - extifregs_t *eir; - chipcregs_t *cc; - char *value; - uint irq; - - /* Figure out current SB clock speed */ - if ((hz = sb_clock(sbh)) == 0) - hz = 100000000; - ns = 1000000000 / hz; - - /* Setup external interface timing */ - if ((eir = sb_setcore(sbh, SB_EXTIF, 0))) { - /* Initialize extif so we can get to the LEDs and external UART */ - W_REG(&eir->prog_config, CF_EN); - - /* Set timing for the flash */ - tmp = CEIL(10, ns) << FW_W3_SHIFT; /* W3 = 10nS */ - tmp = tmp | (CEIL(40, ns) << FW_W1_SHIFT); /* W1 = 40nS */ - tmp = tmp | CEIL(120, ns); /* W0 = 120nS */ - W_REG(&eir->prog_waitcount, tmp); /* 0x01020a0c for a 100Mhz clock */ - - /* Set programmable interface timing for external uart */ - tmp = CEIL(10, ns) << FW_W3_SHIFT; /* W3 = 10nS */ - tmp = tmp | (CEIL(20, ns) << FW_W2_SHIFT); /* W2 = 20nS */ - tmp = tmp | (CEIL(100, ns) << FW_W1_SHIFT); /* W1 = 100nS */ - tmp = tmp | CEIL(120, ns); /* W0 = 120nS */ - W_REG(&eir->prog_waitcount, tmp); /* 0x01020a0c for a 100Mhz clock */ - } else if ((cc = sb_setcore(sbh, SB_CC, 0))) { - /* Set timing for the flash */ - tmp = CEIL(10, ns) << FW_W3_SHIFT; /* W3 = 10nS */ - tmp |= CEIL(10, ns) << FW_W1_SHIFT; /* W1 = 10nS */ - tmp |= CEIL(120, ns); /* W0 = 120nS */ - W_REG(&cc->flash_waitcount, tmp); - - W_REG(&cc->pcmcia_memwait, tmp); - } - - /* Chip specific initialization */ - switch (sb_chip(sbh)) { - case BCM4710_DEVICE_ID: - /* Clear interrupt map */ - for (irq = 0; irq <= 4; irq++) - sb_clearirq(sbh, irq); - sb_setirq(sbh, 0, SB_CODEC, 0); - sb_setirq(sbh, 0, SB_EXTIF, 0); - sb_setirq(sbh, 2, SB_ENET, 1); - sb_setirq(sbh, 3, SB_ILINE20, 0); - sb_setirq(sbh, 4, SB_PCI, 0); - ASSERT(eir); - value = nvram_get("et0phyaddr"); - if (value && !strcmp(value, "31")) { - /* Enable internal UART */ - W_REG(&eir->corecontrol, CC_UE); - /* Give USB its own interrupt */ - sb_setirq(sbh, 1, SB_USB, 0); - } else { - /* Disable internal UART */ - W_REG(&eir->corecontrol, 0); - /* Give Ethernet its own interrupt */ - sb_setirq(sbh, 1, SB_ENET, 0); - sb_setirq(sbh, 0, SB_USB, 0); - } - break; - case BCM4310_DEVICE_ID: - MTC0(C0_BROADCOM, 0, MFC0(C0_BROADCOM, 0) & ~(1 << 22)); - break; - } -} - -uint32 -sb_mips_clock(void *sbh) -{ - extifregs_t *eir; - chipcregs_t *cc; - uint32 n, m; - uint idx; - uint32 pll_type, rate = 0; - - /* get index of the current core */ - idx = sb_coreidx(sbh); - pll_type = PLL_TYPE1; - - /* switch to extif or chipc core */ - if ((eir = (extifregs_t *) sb_setcore(sbh, SB_EXTIF, 0))) { - n = R_REG(&eir->clockcontrol_n); - m = R_REG(&eir->clockcontrol_sb); - } else if ((cc = (chipcregs_t *) sb_setcore(sbh, SB_CC, 0))) { - pll_type = R_REG(&cc->capabilities) & CAP_PLL_MASK; - n = R_REG(&cc->clockcontrol_n); - if ((pll_type == PLL_TYPE2) || (pll_type == PLL_TYPE4)) - m = R_REG(&cc->clockcontrol_mips); - else if (pll_type == PLL_TYPE3) { - rate = 200000000; - goto out; - } else - m = R_REG(&cc->clockcontrol_sb); - } else - goto out; - - /* calculate rate */ - rate = sb_clock_rate(pll_type, n, m); - -out: - /* switch back to previous core */ - sb_setcoreidx(sbh, idx); - - return rate; -} - -static void -icache_probe(int *size, int *lsize) -{ - uint32 config1; - uint sets, ways; - - config1 = MFC0(C0_CONFIG, 1); - - /* Instruction Cache Size = Associativity * Line Size * Sets Per Way */ - if ((*lsize = ((config1 >> 19) & 7))) - *lsize = 2 << *lsize; - sets = 64 << ((config1 >> 22) & 7); - ways = 1 + ((config1 >> 16) & 7); - *size = *lsize * sets * ways; -} - -#define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4) - -static void -handler(void) -{ - /* Step 11 */ - __asm__ ( - ".set\tmips32\n\t" - "ssnop\n\t" - "ssnop\n\t" - /* Disable interrupts */ - /* MTC0(C0_STATUS, 0, MFC0(C0_STATUS, 0) & ~(ALLINTS | STO_IE)); */ - "mfc0 $15, $12\n\t" - "and $15, $15, -31746\n\t" - "mtc0 $15, $12\n\t" - "eret\n\t" - "nop\n\t" - "nop\n\t" - ".set\tmips0" - ); -} - -/* The following MUST come right after handler() */ -static void -afterhandler(void) -{ -} - -/* - * Set the MIPS, backplane and PCI clocks as closely as possible. - */ -bool -sb_mips_setclock(void *sbh, uint32 mipsclock, uint32 sbclock, uint32 pciclock) -{ - extifregs_t *eir = NULL; - chipcregs_t *cc = NULL; - mipsregs_t *mipsr = NULL; - volatile uint32 *clockcontrol_n, *clockcontrol_sb, *clockcontrol_pci; - uint32 orig_n, orig_sb, orig_pci, orig_m2, orig_mips, orig_ratio_parm, new_ratio; - uint32 pll_type, sync_mode; - uint idx, i; - typedef struct { - uint32 mipsclock; - uint16 n; - uint32 sb; - uint32 pci33; - uint32 pci25; - } n3m_table_t; - static n3m_table_t type1_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 */ - }; - typedef struct { - uint32 mipsclock; - uint32 sbclock; - uint16 n; - uint32 sb; - uint32 pci33; - uint32 m2; - uint32 m3; - uint32 ratio; - uint32 ratio_parm; - } n4m_table_t; - - static n4m_table_t type2_table[] = { - { 180000000, 80000000, 0x0403, 0x01010000, 0x01020300, 0x01020600, 0x05000100, 0x94, 0x012a0115 }, - { 180000000, 90000000, 0x0403, 0x01000100, 0x01020300, 0x01000100, 0x05000100, 0x21, 0x0aaa0555 }, - { 200000000, 100000000, 0x0303, 0x01000000, 0x01000600, 0x01000000, 0x05000000, 0x21, 0x0aaa0555 }, - { 211200000, 105600000, 0x0902, 0x01000200, 0x01030400, 0x01000200, 0x05000200, 0x21, 0x0aaa0555 }, - { 220800000, 110400000, 0x1500, 0x01000200, 0x01030400, 0x01000200, 0x05000200, 0x21, 0x0aaa0555 }, - { 230400000, 115200000, 0x0604, 0x01000200, 0x01020600, 0x01000200, 0x05000200, 0x21, 0x0aaa0555 }, - { 234000000, 104000000, 0x0b01, 0x01010000, 0x01010700, 0x01020600, 0x05000100, 0x94, 0x012a0115 }, - { 240000000, 120000000, 0x0803, 0x01000200, 0x01020600, 0x01000200, 0x05000200, 0x21, 0x0aaa0555 }, - { 252000000, 126000000, 0x0504, 0x01000100, 0x01020500, 0x01000100, 0x05000100, 0x21, 0x0aaa0555 }, - { 264000000, 132000000, 0x0903, 0x01000200, 0x01020700, 0x01000200, 0x05000200, 0x21, 0x0aaa0555 }, - { 270000000, 120000000, 0x0703, 0x01010000, 0x01030400, 0x01020600, 0x05000100, 0x94, 0x012a0115 }, - { 276000000, 122666666, 0x1500, 0x01010000, 0x01030400, 0x01020600, 0x05000100, 0x94, 0x012a0115 }, - { 280000000, 140000000, 0x0503, 0x01000000, 0x01010600, 0x01000000, 0x05000000, 0x21, 0x0aaa0555 }, - { 288000000, 128000000, 0x0604, 0x01010000, 0x01030400, 0x01020600, 0x05000100, 0x94, 0x012a0115 }, - { 288000000, 144000000, 0x0404, 0x01000000, 0x01010600, 0x01000000, 0x05000000, 0x21, 0x0aaa0555 }, - { 300000000, 133333333, 0x0803, 0x01010000, 0x01020600, 0x01020600, 0x05000100, 0x94, 0x012a0115 }, - { 300000000, 150000000, 0x0803, 0x01000100, 0x01020600, 0x01000100, 0x05000100, 0x21, 0x0aaa0555 } - }; - - static n4m_table_t type4_table[] = { - { 192000000, 96000000, 0x0702, 0x04020011, 0x11030011, 0x04020011, 0x04020003, 0x21, 0x0aaa0555 }, - { 200000000, 100000000, 0x0009, 0x04020011, 0x11030011, 0x04020011, 0x04020003, 0x21, 0x0aaa0555 }, - { 216000000, 108000000, 0x0111, 0x11020005, 0x01030303, 0x11020005, 0x04000005, 0x21, 0x0aaa0555 }, - { 228000000, 101333333, 0x0e02, 0x11030003, 0x11210005, 0x11030305, 0x04000005, 0x94, 0x012a00a9 }, - { 228000000, 114000000, 0x0e02, 0x11020005, 0x11210005, 0x11020005, 0x04000005, 0x21, 0x0aaa0555 }, - { 240000000, 120000000, 0x0109, 0x11030002, 0x01050203, 0x11030002, 0x04000003, 0x21, 0x0aaa0555 }, - { 252000000, 126000000, 0x0203, 0x04000005, 0x11050005, 0x04000005, 0x04000002, 0x21, 0x0aaa0555 }, - { 264000000, 132000000, 0x0602, 0x04000005, 0x11050005, 0x04000005, 0x04000002, 0x21, 0x0aaa0555 }, - { 272000000, 116571428, 0x0c02, 0x04000021, 0x02000909, 0x02000221, 0x04000003, 0x73, 0x254a14a9 }, - { 280000000, 120000000, 0x0209, 0x04000021, 0x01030303, 0x02000221, 0x04000003, 0x73, 0x254a14a9 }, - { 288000000, 123428571, 0x0111, 0x04000021, 0x01030303, 0x02000221, 0x04000003, 0x73, 0x254a14a9 }, - { 300000000, 120000000, 0x0009, 0x04000009, 0x01030203, 0x02000902, 0x04000002, 0x52, 0x02520129 } - }; - uint icache_size, ic_lsize; - ulong start, end, dst; - bool ret = FALSE; - - /* get index of the current core */ - idx = sb_coreidx(sbh); - - /* switch to extif or chipc core */ - if ((eir = (extifregs_t *) sb_setcore(sbh, SB_EXTIF, 0))) { - pll_type = PLL_TYPE1; - clockcontrol_n = &eir->clockcontrol_n; - clockcontrol_sb = &eir->clockcontrol_sb; - clockcontrol_pci = &eir->clockcontrol_pci; - } else if ((cc = (chipcregs_t *) sb_setcore(sbh, SB_CC, 0))) { - pll_type = R_REG(&cc->capabilities) & CAP_PLL_MASK; - clockcontrol_n = &cc->clockcontrol_n; - clockcontrol_sb = &cc->clockcontrol_sb; - clockcontrol_pci = &cc->clockcontrol_pci; - } else - goto done; - - /* Store the current clock register values */ - orig_n = R_REG(clockcontrol_n); - orig_sb = R_REG(clockcontrol_sb); - orig_pci = R_REG(clockcontrol_pci); - - if (pll_type == PLL_TYPE1) { - /* Keep the current PCI clock if not specified */ - if (pciclock == 0) { - pciclock = sb_clock_rate(pll_type, R_REG(clockcontrol_n), R_REG(clockcontrol_pci)); - pciclock = (pciclock <= 25000000) ? 25000000 : 33000000; - } - - /* Search for the closest MIPS clock less than or equal to a preferred value */ - for (i = 0; i < ARRAYSIZE(type1_table); i++) { - ASSERT(type1_table[i].mipsclock == - sb_clock_rate(pll_type, type1_table[i].n, type1_table[i].sb)); - if (type1_table[i].mipsclock > mipsclock) - break; - } - if (i == 0) { - ret = FALSE; - goto done; - } else { - ret = TRUE; - i--; - } - ASSERT(type1_table[i].mipsclock <= mipsclock); - - /* No PLL change */ - if ((orig_n == type1_table[i].n) && - (orig_sb == type1_table[i].sb) && - (orig_pci == type1_table[i].pci33)) - goto done; - - /* Set the PLL controls */ - W_REG(clockcontrol_n, type1_table[i].n); - W_REG(clockcontrol_sb, type1_table[i].sb); - if (pciclock == 25000000) - W_REG(clockcontrol_pci, type1_table[i].pci25); - else - W_REG(clockcontrol_pci, type1_table[i].pci33); - - /* Reset */ - sb_watchdog(sbh, 1); - while (1); - } else if ((pll_type == PLL_TYPE2) || (pll_type == PLL_TYPE4)) { - n4m_table_t *table = (pll_type == PLL_TYPE2) ? type2_table : type4_table; - uint tabsz = (pll_type == PLL_TYPE2) ? ARRAYSIZE(type2_table) : ARRAYSIZE(type4_table); - - ASSERT(cc); - - /* Store the current clock register values */ - orig_m2 = R_REG(&cc->clockcontrol_m2); - orig_mips = R_REG(&cc->clockcontrol_mips); - orig_ratio_parm = 0; - - /* Look up current ratio */ - for (i = 0; i < tabsz; i++) { - if ((orig_n == table[i].n) && - (orig_sb == table[i].sb) && - (orig_pci == table[i].pci33) && - (orig_m2 == table[i].m2) && - (orig_mips == table[i].m3)) { - orig_ratio_parm = table[i].ratio_parm; - break; - } - } - - /* Search for the closest MIPS clock greater or equal to a preferred value */ - for (i = 0; i < tabsz; i++) { - ASSERT(table[i].mipsclock == - sb_clock_rate(pll_type, table[i].n, table[i].m3)); - if ((mipsclock <= table[i].mipsclock) && - ((sbclock == 0) || (sbclock <= table[i].sbclock))) - break; - } - if (i == tabsz) { - ret = FALSE; - goto done; - } else { - ret = TRUE; - } - - /* No PLL change */ - if ((orig_n == table[i].n) && - (orig_sb == table[i].sb) && - (orig_pci == table[i].pci33) && - (orig_m2 == table[i].m2) && - (orig_mips == table[i].m3)) - goto done; - - /* Set the PLL controls */ - W_REG(clockcontrol_n, table[i].n); - W_REG(clockcontrol_sb, table[i].sb); - W_REG(clockcontrol_pci, table[i].pci33); - W_REG(&cc->clockcontrol_m2, table[i].m2); - W_REG(&cc->clockcontrol_mips, table[i].m3); - - /* No ratio change */ - if (orig_ratio_parm == table[i].ratio_parm) - goto end_fill; - - new_ratio = table[i].ratio_parm; - - icache_probe(&icache_size, &ic_lsize); - - /* Preload the code into the cache */ - start = ((ulong) &&start_fill) & ~(ic_lsize - 1); - end = ((ulong) &&end_fill + (ic_lsize - 1)) & ~(ic_lsize - 1); - while (start < end) { - cache_unroll(start, Fill_I); - start += ic_lsize; - } - - /* Copy the handler */ - start = (ulong) &handler; - end = (ulong) &afterhandler; - dst = KSEG1ADDR(0x180); - for (i = 0; i < (end - start); i += 4) - *((ulong *)(dst + i)) = *((ulong *)(start + i)); - - /* Preload handler into the cache one line at a time */ - for (i = 0; i < (end - start); i += 4) - cache_unroll(dst + i, Fill_I); - - /* Clear BEV bit */ - MTC0(C0_STATUS, 0, MFC0(C0_STATUS, 0) & ~ST0_BEV); - - /* Enable interrupts */ - MTC0(C0_STATUS, 0, MFC0(C0_STATUS, 0) | (ALLINTS | ST0_IE)); - - /* Enable MIPS timer interrupt */ - if (!(mipsr = sb_setcore(sbh, SB_MIPS, 0)) && - !(mipsr = sb_setcore(sbh, SB_MIPS33, 0))) - ASSERT(mipsr); - W_REG(&mipsr->intmask, 1); - - start_fill: - /* step 1, set clock ratios */ - MTC0(C0_BROADCOM, 3, new_ratio); - MTC0(C0_BROADCOM, 1, 8); - - /* step 2: program timer intr */ - W_REG(&mipsr->timer, 100); - (void) R_REG(&mipsr->timer); - - /* step 3, switch to async */ - sync_mode = MFC0(C0_BROADCOM, 4); - MTC0(C0_BROADCOM, 4, 1 << 22); - - /* step 4, set cfg active */ - MTC0(C0_BROADCOM, 2, 0x9); - - - /* steps 5 & 6 */ - __asm__ __volatile__ ( - ".set\tmips3\n\t" - "wait\n\t" - ".set\tmips0" - ); - - /* step 7, clear cfg_active */ - MTC0(C0_BROADCOM, 2, 0); - - /* Additional Step: set back to orig sync mode */ - MTC0(C0_BROADCOM, 4, sync_mode); - - /* step 8, fake soft reset */ - MTC0(C0_BROADCOM, 5, MFC0(C0_BROADCOM, 5) | 4); - - end_fill: - /* step 9 set watchdog timer */ - sb_watchdog(sbh, 20); - (void) R_REG(&cc->chipid); - - /* step 11 */ - __asm__ __volatile__ ( - ".set\tmips3\n\t" - "sync\n\t" - "wait\n\t" - ".set\tmips0" - ); - while (1); - } - -done: - /* switch back to previous core */ - sb_setcoreidx(sbh, idx); - - return ret; -} - - -/* returns the ncdl value to be programmed into sdram_ncdl for calibration */ -uint32 -sb_memc_get_ncdl(void *sbh) -{ - sbmemcregs_t *memc; - uint32 ret = 0; - uint32 config, rd, wr, misc, dqsg, cd, sm, sd; - uint idx, rev; - - idx = sb_coreidx(sbh); - - memc = (sbmemcregs_t *)sb_setcore(sbh, SB_MEMC, 0); - if (memc == 0) - goto out; - - rev = sb_corerev(sbh); - - config = R_REG(&memc->config); - wr = R_REG(&memc->wrncdlcor); - rd = R_REG(&memc->rdncdlcor); - misc = R_REG(&memc->miscdlyctl); - dqsg = R_REG(&memc->dqsgatencdl); - - rd &= MEMC_RDNCDLCOR_RD_MASK; - wr &= MEMC_WRNCDLCOR_WR_MASK; - dqsg &= MEMC_DQSGATENCDL_G_MASK; - - if (config & MEMC_CONFIG_DDR) { - ret = (wr << 16) | (rd << 8) | dqsg; - } else { - if (rev > 0) - cd = rd; - else - cd = (rd == MEMC_CD_THRESHOLD) ? rd : (wr + MEMC_CD_THRESHOLD); - sm = (misc & MEMC_MISC_SM_MASK) >> MEMC_MISC_SM_SHIFT; - sd = (misc & MEMC_MISC_SD_MASK) >> MEMC_MISC_SD_SHIFT; - ret = (sm << 16) | (sd << 8) | cd; - } - -out: - /* switch back to previous core */ - sb_setcoreidx(sbh, idx); - - return ret; -} |