diff options
Diffstat (limited to 'arch/mips/mips-boards/generic')
-rw-r--r-- | arch/mips/mips-boards/generic/Makefile | 1 | ||||
-rw-r--r-- | arch/mips/mips-boards/generic/amon.c | 80 | ||||
-rw-r--r-- | arch/mips/mips-boards/generic/init.c | 23 | ||||
-rw-r--r-- | arch/mips/mips-boards/generic/memory.c | 4 | ||||
-rw-r--r-- | arch/mips/mips-boards/generic/time.c | 31 |
5 files changed, 124 insertions, 15 deletions
diff --git a/arch/mips/mips-boards/generic/Makefile b/arch/mips/mips-boards/generic/Makefile index b31d8dfed1b..f7f87fc09d1 100644 --- a/arch/mips/mips-boards/generic/Makefile +++ b/arch/mips/mips-boards/generic/Makefile @@ -20,6 +20,7 @@ obj-y := reset.o display.o init.o memory.o \ cmdline.o time.o +obj-y += amon.o obj-$(CONFIG_EARLY_PRINTK) += console.o obj-$(CONFIG_PCI) += pci.o diff --git a/arch/mips/mips-boards/generic/amon.c b/arch/mips/mips-boards/generic/amon.c new file mode 100644 index 00000000000..b7633fda418 --- /dev/null +++ b/arch/mips/mips-boards/generic/amon.c @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2007 MIPS Technologies, Inc. + * All rights reserved. + + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Arbitrary Monitor interface + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/smp.h> + +#include <asm-mips/addrspace.h> +#include <asm-mips/mips-boards/launch.h> +#include <asm-mips/mipsmtregs.h> + +int amon_cpu_avail(int cpu) +{ + struct cpulaunch *launch = (struct cpulaunch *)KSEG0ADDR(CPULAUNCH); + + if (cpu < 0 || cpu >= NCPULAUNCH) { + pr_debug("avail: cpu%d is out of range\n", cpu); + return 0; + } + + launch += cpu; + if (!(launch->flags & LAUNCH_FREADY)) { + pr_debug("avail: cpu%d is not ready\n", cpu); + return 0; + } + if (launch->flags & (LAUNCH_FGO|LAUNCH_FGONE)) { + pr_debug("avail: too late.. cpu%d is already gone\n", cpu); + return 0; + } + + return 1; +} + +void amon_cpu_start(int cpu, + unsigned long pc, unsigned long sp, + unsigned long gp, unsigned long a0) +{ + volatile struct cpulaunch *launch = + (struct cpulaunch *)KSEG0ADDR(CPULAUNCH); + + if (!amon_cpu_avail(cpu)) + return; + if (cpu == smp_processor_id()) { + pr_debug("launch: I am cpu%d!\n", cpu); + return; + } + launch += cpu; + + pr_debug("launch: starting cpu%d\n", cpu); + + launch->pc = pc; + launch->gp = gp; + launch->sp = sp; + launch->a0 = a0; + + /* Make sure target sees parameters before the go bit */ + smp_mb(); + + launch->flags |= LAUNCH_FGO; + while ((launch->flags & LAUNCH_FGONE) == 0) + ; + pr_debug("launch: cpu%d gone!\n", cpu); +} diff --git a/arch/mips/mips-boards/generic/init.c b/arch/mips/mips-boards/generic/init.c index 1695dca5506..83b9dc73920 100644 --- a/arch/mips/mips-boards/generic/init.c +++ b/arch/mips/mips-boards/generic/init.c @@ -226,7 +226,7 @@ void __init kgdb_config(void) } #endif -void __init mips_nmi_setup(void) +static void __init mips_nmi_setup(void) { void *base; extern char except_vec_nmi; @@ -238,7 +238,7 @@ void __init mips_nmi_setup(void) flush_icache_range((unsigned long)base, (unsigned long)base + 0x80); } -void __init mips_ejtag_setup(void) +static void __init mips_ejtag_setup(void) { void *base; extern char except_vec_ejtag_debug; @@ -295,15 +295,21 @@ void __init prom_init(void) break; case MIPS_REVISION_CORID_CORE_MSC: case MIPS_REVISION_CORID_CORE_FPGA2: - case MIPS_REVISION_CORID_CORE_FPGA3: - case MIPS_REVISION_CORID_CORE_FPGA4: case MIPS_REVISION_CORID_CORE_24K: - case MIPS_REVISION_CORID_CORE_EMUL_MSC: + /* + * SOCit/ROCit support is essentially identical + * but make an attempt to distinguish them + */ mips_revision_sconid = MIPS_REVISION_SCON_SOCIT; break; + case MIPS_REVISION_CORID_CORE_FPGA3: + case MIPS_REVISION_CORID_CORE_FPGA4: + case MIPS_REVISION_CORID_CORE_FPGA5: + case MIPS_REVISION_CORID_CORE_EMUL_MSC: default: - mips_display_message("CC Error"); - while (1); /* We die here... */ + /* See above */ + mips_revision_sconid = MIPS_REVISION_SCON_ROCIT; + break; } } @@ -418,6 +424,9 @@ void __init prom_init(void) #ifdef CONFIG_SERIAL_8250_CONSOLE console_config(); #endif +#ifdef CONFIG_MIPS_CMP + register_smp_ops(&cmp_smp_ops); +#endif #ifdef CONFIG_MIPS_MT_SMP register_smp_ops(&vsmp_smp_ops); #endif diff --git a/arch/mips/mips-boards/generic/memory.c b/arch/mips/mips-boards/generic/memory.c index dc272c18823..5e443bba566 100644 --- a/arch/mips/mips-boards/generic/memory.c +++ b/arch/mips/mips-boards/generic/memory.c @@ -37,7 +37,7 @@ enum yamon_memtypes { yamon_prom, yamon_free, }; -struct prom_pmemblock mdesc[PROM_MAX_PMEMBLOCKS]; +static struct prom_pmemblock mdesc[PROM_MAX_PMEMBLOCKS]; #ifdef DEBUG static char *mtypes[3] = { @@ -50,7 +50,7 @@ static char *mtypes[3] = { /* determined physical memory size, not overridden by command line args */ unsigned long physical_memsize = 0L; -struct prom_pmemblock * __init prom_getmdesc(void) +static struct prom_pmemblock * __init prom_getmdesc(void) { char *memsize_str; unsigned int memsize; diff --git a/arch/mips/mips-boards/generic/time.c b/arch/mips/mips-boards/generic/time.c index b50e0fc406a..008fd82b584 100644 --- a/arch/mips/mips-boards/generic/time.c +++ b/arch/mips/mips-boards/generic/time.c @@ -55,16 +55,36 @@ unsigned long cpu_khz; static int mips_cpu_timer_irq; +static int mips_cpu_perf_irq; extern int cp0_perfcount_irq; +DEFINE_PER_CPU(unsigned int, tickcount); +#define tickcount_this_cpu __get_cpu_var(tickcount) +static unsigned long ledbitmask; + static void mips_timer_dispatch(void) { +#if defined(CONFIG_MIPS_MALTA) || defined(CONFIG_MIPS_ATLAS) + /* + * Yes, this is very tacky, won't work as expected with SMTC and + * dyntick will break it, + * but it gives me a nice warm feeling during debug + */ +#define LEDBAR 0xbf000408 + if (tickcount_this_cpu++ >= HZ) { + tickcount_this_cpu = 0; + change_bit(smp_processor_id(), &ledbitmask); + smp_wmb(); /* Make sure every one else sees the change */ + /* This will pick up any recent changes made by other CPU's */ + *(unsigned int *)LEDBAR = ledbitmask; + } +#endif do_IRQ(mips_cpu_timer_irq); } static void mips_perf_dispatch(void) { - do_IRQ(cp0_perfcount_irq); + do_IRQ(mips_cpu_perf_irq); } /* @@ -127,21 +147,20 @@ unsigned long read_persistent_clock(void) return mc146818_get_cmos_time(); } -void __init plat_perf_setup(void) +static void __init plat_perf_setup(void) { - cp0_perfcount_irq = -1; - #ifdef MSC01E_INT_BASE if (cpu_has_veic) { set_vi_handler(MSC01E_INT_PERFCTR, mips_perf_dispatch); - cp0_perfcount_irq = MSC01E_INT_BASE + MSC01E_INT_PERFCTR; + mips_cpu_perf_irq = MSC01E_INT_BASE + MSC01E_INT_PERFCTR; } else #endif if (cp0_perfcount_irq >= 0) { if (cpu_has_vint) set_vi_handler(cp0_perfcount_irq, mips_perf_dispatch); + mips_cpu_perf_irq = MIPS_CPU_IRQ_BASE + cp0_perfcount_irq; #ifdef CONFIG_SMP - set_irq_handler(cp0_perfcount_irq, handle_percpu_irq); + set_irq_handler(mips_cpu_perf_irq, handle_percpu_irq); #endif } } |