summaryrefslogtreecommitdiffstats
path: root/openwrt/package/linux/kernel-source/arch/mips/brcm-boards/bcm947xx/sbmips.c
diff options
context:
space:
mode:
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.c951
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(&regs[UART_MCR]);
- W_REG(&regs[UART_MCR], UART_MCR_LOOP | 0x0a);
- status1 = R_REG(&regs[UART_MSR]) & 0xf0;
- W_REG(&regs[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;
-}