From f6e2373ad6148476464fc7bb2610c6450c18cd2a Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Tue, 10 Jul 2007 17:32:56 +0100 Subject: [MIPS] MIPSsim: Move code away from the other MIPS Inc. BSP code. It shares no code at all. While at it also fix up the beginning bitrot. Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 1 + arch/mips/Makefile | 2 +- arch/mips/kernel/head.S | 7 +- arch/mips/mips-boards/sim/Makefile | 24 ---- arch/mips/mips-boards/sim/sim_cmdline.c | 35 ------ arch/mips/mips-boards/sim/sim_console.c | 40 ------ arch/mips/mips-boards/sim/sim_mem.c | 115 ------------------ arch/mips/mips-boards/sim/sim_platform.c | 35 ------ arch/mips/mips-boards/sim/sim_setup.c | 98 --------------- arch/mips/mips-boards/sim/sim_smp.c | 115 ------------------ arch/mips/mips-boards/sim/sim_time.c | 202 ------------------------------- arch/mips/mipssim/Makefile | 24 ++++ arch/mips/mipssim/sim_cmdline.c | 35 ++++++ arch/mips/mipssim/sim_console.c | 40 ++++++ arch/mips/mipssim/sim_int.c | 88 ++++++++++++++ arch/mips/mipssim/sim_mem.c | 115 ++++++++++++++++++ arch/mips/mipssim/sim_platform.c | 35 ++++++ arch/mips/mipssim/sim_setup.c | 98 +++++++++++++++ arch/mips/mipssim/sim_smp.c | 123 +++++++++++++++++++ arch/mips/mipssim/sim_time.c | 200 ++++++++++++++++++++++++++++++ 20 files changed, 762 insertions(+), 670 deletions(-) delete mode 100644 arch/mips/mips-boards/sim/Makefile delete mode 100644 arch/mips/mips-boards/sim/sim_cmdline.c delete mode 100644 arch/mips/mips-boards/sim/sim_console.c delete mode 100644 arch/mips/mips-boards/sim/sim_mem.c delete mode 100644 arch/mips/mips-boards/sim/sim_platform.c delete mode 100644 arch/mips/mips-boards/sim/sim_setup.c delete mode 100644 arch/mips/mips-boards/sim/sim_smp.c delete mode 100644 arch/mips/mips-boards/sim/sim_time.c create mode 100644 arch/mips/mipssim/Makefile create mode 100644 arch/mips/mipssim/sim_cmdline.c create mode 100644 arch/mips/mipssim/sim_console.c create mode 100644 arch/mips/mipssim/sim_int.c create mode 100644 arch/mips/mipssim/sim_mem.c create mode 100644 arch/mips/mipssim/sim_platform.c create mode 100644 arch/mips/mipssim/sim_setup.c create mode 100644 arch/mips/mipssim/sim_smp.c create mode 100644 arch/mips/mipssim/sim_time.c (limited to 'arch') diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 37977db6eff..734b61f663b 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -251,6 +251,7 @@ config MIPS_SIM select SYS_HAS_EARLY_PRINTK select SYS_SUPPORTS_32BIT_KERNEL select SYS_SUPPORTS_BIG_ENDIAN + select SYS_SUPPORTS_MULTITHREADING select SYS_SUPPORTS_LITTLE_ENDIAN help This option enables support for MIPS Technologies MIPSsim software diff --git a/arch/mips/Makefile b/arch/mips/Makefile index 2b19605b738..077eb0bd1c7 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -327,7 +327,7 @@ load-$(CONFIG_MIPS_SEAD) += 0xffffffff80100000 # # MIPS SIM # -core-$(CONFIG_MIPS_SIM) += arch/mips/mips-boards/sim/ +core-$(CONFIG_MIPS_SIM) += arch/mips/mipssim/ cflags-$(CONFIG_MIPS_SIM) += -Iinclude/asm-mips/mach-sim load-$(CONFIG_MIPS_SIM) += 0x80100000 diff --git a/arch/mips/kernel/head.S b/arch/mips/kernel/head.S index 6f57ca44291..1f096aa35bc 100644 --- a/arch/mips/kernel/head.S +++ b/arch/mips/kernel/head.S @@ -138,15 +138,14 @@ EXPORT(stext) # used for profiling EXPORT(_stext) -#ifdef CONFIG_MIPS_SIM +#ifndef CONFIG_MIPS_SIM /* * Give us a fighting chance of running if execution beings at the * kernel load address. This is needed because this platform does * not have a ELF loader yet. */ - j kernel_entry -#endif __INIT +#endif NESTED(kernel_entry, 16, sp) # kernel entry point @@ -197,9 +196,7 @@ NESTED(kernel_entry, 16, sp) # kernel entry point j start_kernel END(kernel_entry) -#ifdef CONFIG_QEMU __INIT -#endif #ifdef CONFIG_SMP /* diff --git a/arch/mips/mips-boards/sim/Makefile b/arch/mips/mips-boards/sim/Makefile deleted file mode 100644 index dc0bfda1142..00000000000 --- a/arch/mips/mips-boards/sim/Makefile +++ /dev/null @@ -1,24 +0,0 @@ -# -# Copyright (C) 2005 MIPS Technologies, Inc. All rights reserved. -# Copyright (C) 2007 MIPS Technologies, Inc. -# written by Ralf Baechle (ralf@linux-mips.org) -# -# 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. -# - -obj-y := sim_platform.o sim_setup.o sim_mem.o sim_time.o sim_int.o \ - sim_cmdline.o - -obj-$(CONFIG_EARLY_PRINTK) += sim_console.o -obj-$(CONFIG_SMP) += sim_smp.o diff --git a/arch/mips/mips-boards/sim/sim_cmdline.c b/arch/mips/mips-boards/sim/sim_cmdline.c deleted file mode 100644 index c63021a5dc6..00000000000 --- a/arch/mips/mips-boards/sim/sim_cmdline.c +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2005 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. - * - */ -#include -#include -#include - -extern char arcs_cmdline[]; - -char * __init prom_getcmdline(void) -{ - return arcs_cmdline; -} - -void __init prom_init_cmdline(void) -{ - char *cp; - cp = arcs_cmdline; - /* Get boot line from environment? */ - *cp = '\0'; -} diff --git a/arch/mips/mips-boards/sim/sim_console.c b/arch/mips/mips-boards/sim/sim_console.c deleted file mode 100644 index de595a9ccb2..00000000000 --- a/arch/mips/mips-boards/sim/sim_console.c +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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. - * - * Carsten Langgaard, carstenl@mips.com - * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved. - * Copyright (C) 2007 MIPS Technologies, Inc. - * written by Ralf Baechle - */ -#include -#include -#include - -static inline unsigned int serial_in(int offset) -{ - return inb(0x3f8 + offset); -} - -static inline void serial_out(int offset, int value) -{ - outb(value, 0x3f8 + offset); -} - -void __init prom_putchar(char c) -{ - while ((serial_in(UART_LSR) & UART_LSR_THRE) == 0) - ; - - serial_out(UART_TX, c); -} diff --git a/arch/mips/mips-boards/sim/sim_mem.c b/arch/mips/mips-boards/sim/sim_mem.c deleted file mode 100644 index e408ef0bcd6..00000000000 --- a/arch/mips/mips-boards/sim/sim_mem.c +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (C) 2005 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. - * - */ -#include -#include -#include -#include - -#include -#include -#include - -#include - -/*#define DEBUG*/ - -enum simmem_memtypes { - simmem_reserved = 0, - simmem_free, -}; -struct prom_pmemblock mdesc[PROM_MAX_PMEMBLOCKS]; - -#ifdef DEBUG -static char *mtypes[3] = { - "SIM reserved memory", - "SIM free memory", -}; -#endif - -struct prom_pmemblock * __init prom_getmdesc(void) -{ - unsigned int memsize; - - memsize = 0x02000000; - pr_info("Setting default memory size 0x%08x\n", memsize); - - memset(mdesc, 0, sizeof(mdesc)); - - mdesc[0].type = simmem_reserved; - mdesc[0].base = 0x00000000; - mdesc[0].size = 0x00001000; - - mdesc[1].type = simmem_free; - mdesc[1].base = 0x00001000; - mdesc[1].size = 0x000ff000; - - mdesc[2].type = simmem_reserved; - mdesc[2].base = 0x00100000; - mdesc[2].size = CPHYSADDR(PFN_ALIGN(&_end)) - mdesc[2].base; - - mdesc[3].type = simmem_free; - mdesc[3].base = CPHYSADDR(PFN_ALIGN(&_end)); - mdesc[3].size = memsize - mdesc[3].base; - - return &mdesc[0]; -} - -static int __init prom_memtype_classify (unsigned int type) -{ - switch (type) { - case simmem_free: - return BOOT_MEM_RAM; - case simmem_reserved: - default: - return BOOT_MEM_RESERVED; - } -} - -void __init prom_meminit(void) -{ - struct prom_pmemblock *p; - - p = prom_getmdesc(); - - while (p->size) { - long type; - unsigned long base, size; - - type = prom_memtype_classify (p->type); - base = p->base; - size = p->size; - - add_memory_region(base, size, type); - p++; - } -} - -void __init prom_free_prom_memory(void) -{ - int i; - unsigned long addr; - - for (i = 0; i < boot_mem_map.nr_map; i++) { - if (boot_mem_map.map[i].type != BOOT_MEM_ROM_DATA) - continue; - - addr = boot_mem_map.map[i].addr; - free_init_pages("prom memory", - addr, addr + boot_mem_map.map[i].size); - } -} diff --git a/arch/mips/mips-boards/sim/sim_platform.c b/arch/mips/mips-boards/sim/sim_platform.c deleted file mode 100644 index 53210a8c5de..00000000000 --- a/arch/mips/mips-boards/sim/sim_platform.c +++ /dev/null @@ -1,35 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (C) 2007 by Ralf Baechle (ralf@linux-mips.org) - */ -#include -#include -#include -#include - -static char mipsnet_string[] = "mipsnet"; - -static struct platform_device eth1_device = { - .name = mipsnet_string, - .id = 0, -}; - -/* - * Create a platform device for the GPI port that receives the - * image data from the embedded camera. - */ -static int __init mipsnet_devinit(void) -{ - int err; - - err = platform_device_register(ð1_device); - if (err) - printk(KERN_ERR "%s: registration failed\n", mipsnet_string); - - return err; -} - -device_initcall(mipsnet_devinit); diff --git a/arch/mips/mips-boards/sim/sim_setup.c b/arch/mips/mips-boards/sim/sim_setup.c deleted file mode 100644 index b705f09e57c..00000000000 --- a/arch/mips/mips-boards/sim/sim_setup.c +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (C) 2005 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. - * - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -extern void sim_time_init(void); -static void __init serial_init(void); -unsigned int _isbonito = 0; - -extern void __init sanitize_tlb_entries(void); - - -const char *get_system_type(void) -{ - return "MIPSsim"; -} - -void __init plat_mem_setup(void) -{ - set_io_port_base(0xbfd00000); - - serial_init(); - - board_time_init = sim_time_init; - pr_info("Linux started...\n"); - -#ifdef CONFIG_MIPS_MT_SMP - sanitize_tlb_entries(); -#endif -} - -void prom_init(void) -{ - set_io_port_base(0xbfd00000); - - pr_info("\nLINUX started...\n"); - prom_init_cmdline(); - prom_meminit(); -} - - -static void __init serial_init(void) -{ -#ifdef CONFIG_SERIAL_8250 - struct uart_port s; - - memset(&s, 0, sizeof(s)); - - s.iobase = 0x3f8; - - /* hardware int 4 - the serial int, is CPU int 6 - but poll for now */ - s.irq = 0; - s.uartclk = BASE_BAUD * 16; - s.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST; - s.iotype = UPIO_PORT; - s.regshift = 0; - s.timeout = 4; - - if (early_serial_setup(&s) != 0) { - printk(KERN_ERR "Serial setup failed!\n"); - } - -#endif -} diff --git a/arch/mips/mips-boards/sim/sim_smp.c b/arch/mips/mips-boards/sim/sim_smp.c deleted file mode 100644 index cb47863ecf1..00000000000 --- a/arch/mips/mips-boards/sim/sim_smp.c +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (C) 2005 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. - * - */ -/* - * Simulator Platform-specific hooks for SMP operation - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef CONFIG_MIPS_MT_SMTC -#include -#endif /* CONFIG_MIPS_MT_SMTC */ - -/* VPE/SMP Prototype implements platform interfaces directly */ -#if !defined(CONFIG_MIPS_MT_SMP) - -/* - * Cause the specified action to be performed on a targeted "CPU" - */ - -void core_send_ipi(int cpu, unsigned int action) -{ -#ifdef CONFIG_MIPS_MT_SMTC - smtc_send_ipi(cpu, LINUX_SMP_IPI, action); -#endif /* CONFIG_MIPS_MT_SMTC */ -/* "CPU" may be TC of same VPE, VPE of same CPU, or different CPU */ - -} - -/* - * Platform "CPU" startup hook - */ - -void prom_boot_secondary(int cpu, struct task_struct *idle) -{ -#ifdef CONFIG_MIPS_MT_SMTC - smtc_boot_secondary(cpu, idle); -#endif /* CONFIG_MIPS_MT_SMTC */ -} - -/* - * Post-config but pre-boot cleanup entry point - */ - -void prom_init_secondary(void) -{ -#ifdef CONFIG_MIPS_MT_SMTC - void smtc_init_secondary(void); - - smtc_init_secondary(); -#endif /* CONFIG_MIPS_MT_SMTC */ -} - -/* - * Platform SMP pre-initialization - */ - -void prom_prepare_cpus(unsigned int max_cpus) -{ -#ifdef CONFIG_MIPS_MT_SMTC - /* - * As noted above, we can assume a single CPU for now - * but it may be multithreaded. - */ - - if (read_c0_config3() & (1<<2)) { - mipsmt_prepare_cpus(max_cpus); - } -#endif /* CONFIG_MIPS_MT_SMTC */ -} - -/* - * SMP initialization finalization entry point - */ - -void prom_smp_finish(void) -{ -#ifdef CONFIG_MIPS_MT_SMTC - smtc_smp_finish(); -#endif /* CONFIG_MIPS_MT_SMTC */ -} - -/* - * Hook for after all CPUs are online - */ - -void prom_cpus_done(void) -{ -#ifdef CONFIG_MIPS_MT_SMTC - -#endif /* CONFIG_MIPS_MT_SMTC */ -} -#endif /* CONFIG_MIPS32R2_MT_SMP */ diff --git a/arch/mips/mips-boards/sim/sim_time.c b/arch/mips/mips-boards/sim/sim_time.c deleted file mode 100644 index 7224ffe31d3..00000000000 --- a/arch/mips/mips-boards/sim/sim_time.c +++ /dev/null @@ -1,202 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - - -unsigned long cpu_khz; - -irqreturn_t sim_timer_interrupt(int irq, void *dev_id) -{ -#ifdef CONFIG_SMP - int cpu = smp_processor_id(); - - /* - * CPU 0 handles the global timer interrupt job - * resets count/compare registers to trigger next timer int. - */ -#ifndef CONFIG_MIPS_MT_SMTC - if (cpu == 0) { - timer_interrupt(irq, dev_id); - } - else { - /* Everyone else needs to reset the timer int here as - ll_local_timer_interrupt doesn't */ - /* - * FIXME: need to cope with counter underflow. - * More support needs to be added to kernel/time for - * counter/timer interrupts on multiple CPU's - */ - write_c0_compare (read_c0_count() + ( mips_hpt_frequency/HZ)); - } -#else /* SMTC */ - /* - * In SMTC system, one Count/Compare set exists per VPE. - * Which TC within a VPE gets the interrupt is essentially - * random - we only know that it shouldn't be one with - * IXMT set. Whichever TC gets the interrupt needs to - * send special interprocessor interrupts to the other - * TCs to make sure that they schedule, etc. - * - * That code is specific to the SMTC kernel, not to - * the simulation platform, so it's invoked from - * the general MIPS timer_interrupt routine. - * - * We have a problem in that the interrupt vector code - * had to turn off the timer IM bit to avoid redundant - * entries, but we may never get to mips_cpu_irq_end - * to turn it back on again if the scheduler gets - * involved. So we clear the pending timer here, - * and re-enable the mask... - */ - - int vpflags = dvpe(); - write_c0_compare (read_c0_count() - 1); - clear_c0_cause(0x100 << cp0_compare_irq); - set_c0_status(0x100 << cp0_compare_irq); - irq_enable_hazard(); - evpe(vpflags); - - if(cpu_data[cpu].vpe_id == 0) timer_interrupt(irq, dev_id); - else write_c0_compare (read_c0_count() + ( mips_hpt_frequency/HZ)); - smtc_timer_broadcast(cpu_data[cpu].vpe_id); - -#endif /* CONFIG_MIPS_MT_SMTC */ - - /* - * every CPU should do profiling and process accounting - */ - local_timer_interrupt (irq, dev_id); - return IRQ_HANDLED; -#else - return timer_interrupt (irq, dev_id); -#endif -} - - - -/* - * Estimate CPU frequency. Sets mips_hpt_frequency as a side-effect - */ -static unsigned int __init estimate_cpu_frequency(void) -{ - unsigned int prid = read_c0_prid() & 0xffff00; - unsigned int count; - -#if 1 - /* - * hardwire the board frequency to 12MHz. - */ - - if ((prid == (PRID_COMP_MIPS | PRID_IMP_20KC)) || - (prid == (PRID_COMP_MIPS | PRID_IMP_25KF))) - count = 12000000; - else - count = 6000000; -#else - unsigned int flags; - - local_irq_save(flags); - - /* Start counter exactly on falling edge of update flag */ - while (CMOS_READ(RTC_REG_A) & RTC_UIP); - while (!(CMOS_READ(RTC_REG_A) & RTC_UIP)); - - /* Start r4k counter. */ - write_c0_count(0); - - /* Read counter exactly on falling edge of update flag */ - while (CMOS_READ(RTC_REG_A) & RTC_UIP); - while (!(CMOS_READ(RTC_REG_A) & RTC_UIP)); - - count = read_c0_count(); - - /* restore interrupts */ - local_irq_restore(flags); -#endif - - mips_hpt_frequency = count; - - if ((prid != (PRID_COMP_MIPS | PRID_IMP_20KC)) && - (prid != (PRID_COMP_MIPS | PRID_IMP_25KF))) - count *= 2; - - count += 5000; /* round */ - count -= count%10000; - - return count; -} - -void __init sim_time_init(void) -{ - unsigned int est_freq, flags; - - local_irq_save(flags); - - - /* Set Data mode - binary. */ - CMOS_WRITE(CMOS_READ(RTC_CONTROL) | RTC_DM_BINARY, RTC_CONTROL); - - - est_freq = estimate_cpu_frequency (); - - printk("CPU frequency %d.%02d MHz\n", est_freq/1000000, - (est_freq%1000000)*100/1000000); - - cpu_khz = est_freq / 1000; - - local_irq_restore(flags); -} - -static int mips_cpu_timer_irq; - -static void mips_timer_dispatch(void) -{ - do_IRQ(mips_cpu_timer_irq); -} - - -void __init plat_timer_setup(struct irqaction *irq) -{ - if (cpu_has_veic) { - set_vi_handler(MSC01E_INT_CPUCTR, mips_timer_dispatch); - mips_cpu_timer_irq = MSC01E_INT_BASE + MSC01E_INT_CPUCTR; - } - else { - if (cpu_has_vint) - set_vi_handler(cp0_compare_irq, mips_timer_dispatch); - mips_cpu_timer_irq = MIPS_CPU_IRQ_BASE + cp0_compare_irq; - } - - /* we are using the cpu counter for timer interrupts */ - irq->handler = sim_timer_interrupt; - setup_irq(mips_cpu_timer_irq, irq); - -#ifdef CONFIG_SMP - /* irq_desc(riptor) is a global resource, when the interrupt overlaps - on seperate cpu's the first one tries to handle the second interrupt. - The effect is that the int remains disabled on the second cpu. - Mark the interrupt with IRQ_PER_CPU to avoid any confusion */ - irq_desc[mips_cpu_timer_irq].flags |= IRQ_PER_CPU; - set_irq_handler(mips_cpu_timer_irq, handle_percpu_irq); -#endif -} diff --git a/arch/mips/mipssim/Makefile b/arch/mips/mipssim/Makefile new file mode 100644 index 00000000000..dc0bfda1142 --- /dev/null +++ b/arch/mips/mipssim/Makefile @@ -0,0 +1,24 @@ +# +# Copyright (C) 2005 MIPS Technologies, Inc. All rights reserved. +# Copyright (C) 2007 MIPS Technologies, Inc. +# written by Ralf Baechle (ralf@linux-mips.org) +# +# 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. +# + +obj-y := sim_platform.o sim_setup.o sim_mem.o sim_time.o sim_int.o \ + sim_cmdline.o + +obj-$(CONFIG_EARLY_PRINTK) += sim_console.o +obj-$(CONFIG_SMP) += sim_smp.o diff --git a/arch/mips/mipssim/sim_cmdline.c b/arch/mips/mipssim/sim_cmdline.c new file mode 100644 index 00000000000..c63021a5dc6 --- /dev/null +++ b/arch/mips/mipssim/sim_cmdline.c @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2005 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. + * + */ +#include +#include +#include + +extern char arcs_cmdline[]; + +char * __init prom_getcmdline(void) +{ + return arcs_cmdline; +} + +void __init prom_init_cmdline(void) +{ + char *cp; + cp = arcs_cmdline; + /* Get boot line from environment? */ + *cp = '\0'; +} diff --git a/arch/mips/mipssim/sim_console.c b/arch/mips/mipssim/sim_console.c new file mode 100644 index 00000000000..a2f41672cd5 --- /dev/null +++ b/arch/mips/mipssim/sim_console.c @@ -0,0 +1,40 @@ +/* + * 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. + * + * Carsten Langgaard, carstenl@mips.com + * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved. + * Copyright (C) 2007 MIPS Technologies, Inc. + * written by Ralf Baechle + */ +#include +#include +#include + +static inline unsigned int serial_in(int offset) +{ + return inb(0x3f8 + offset); +} + +static inline void serial_out(int offset, int value) +{ + outb(value, 0x3f8 + offset); +} + +void __init prom_putchar(char c) +{ + while ((serial_in(UART_LSR) & UART_LSR_THRE) == 0) + ; + + serial_out(UART_TX, c); +} diff --git a/arch/mips/mipssim/sim_int.c b/arch/mips/mipssim/sim_int.c new file mode 100644 index 00000000000..d86b37235cf --- /dev/null +++ b/arch/mips/mipssim/sim_int.c @@ -0,0 +1,88 @@ +/* + * Copyright (C) 1999, 2005 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. + * + */ +#include +#include +#include +#include +#include +#include +#include + +static inline int clz(unsigned long x) +{ + __asm__ ( + " .set push \n" + " .set mips32 \n" + " clz %0, %1 \n" + " .set pop \n" + : "=r" (x) + : "r" (x)); + + return x; +} + +/* + * Version of ffs that only looks at bits 12..15. + */ +static inline unsigned int irq_ffs(unsigned int pending) +{ +#if defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64) + return -clz(pending) + 31 - CAUSEB_IP; +#else + unsigned int a0 = 7; + unsigned int t0; + + t0 = s0 & 0xf000; + t0 = t0 < 1; + t0 = t0 << 2; + a0 = a0 - t0; + s0 = s0 << t0; + + t0 = s0 & 0xc000; + t0 = t0 < 1; + t0 = t0 << 1; + a0 = a0 - t0; + s0 = s0 << t0; + + t0 = s0 & 0x8000; + t0 = t0 < 1; + /* t0 = t0 << 2; */ + a0 = a0 - t0; + /* s0 = s0 << t0; */ + + return a0; +#endif +} + +asmlinkage void plat_irq_dispatch(void) +{ + unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM; + int irq; + + irq = irq_ffs(pending); + + if (irq > 0) + do_IRQ(MIPSCPU_INT_BASE + irq); + else + spurious_interrupt(); +} + +void __init arch_init_irq(void) +{ + mips_cpu_irq_init(); +} diff --git a/arch/mips/mipssim/sim_mem.c b/arch/mips/mipssim/sim_mem.c new file mode 100644 index 00000000000..2312483eb83 --- /dev/null +++ b/arch/mips/mipssim/sim_mem.c @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2005 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. + * + */ +#include +#include +#include +#include + +#include +#include +#include + +#include + +/*#define DEBUG*/ + +enum simmem_memtypes { + simmem_reserved = 0, + simmem_free, +}; +struct prom_pmemblock mdesc[PROM_MAX_PMEMBLOCKS]; + +#ifdef DEBUG +static char *mtypes[3] = { + "SIM reserved memory", + "SIM free memory", +}; +#endif + +struct prom_pmemblock * __init prom_getmdesc(void) +{ + unsigned int memsize; + + memsize = 0x02000000; + pr_info("Setting default memory size 0x%08x\n", memsize); + + memset(mdesc, 0, sizeof(mdesc)); + + mdesc[0].type = simmem_reserved; + mdesc[0].base = 0x00000000; + mdesc[0].size = 0x00001000; + + mdesc[1].type = simmem_free; + mdesc[1].base = 0x00001000; + mdesc[1].size = 0x000ff000; + + mdesc[2].type = simmem_reserved; + mdesc[2].base = 0x00100000; + mdesc[2].size = CPHYSADDR(PFN_ALIGN(&_end)) - mdesc[2].base; + + mdesc[3].type = simmem_free; + mdesc[3].base = CPHYSADDR(PFN_ALIGN(&_end)); + mdesc[3].size = memsize - mdesc[3].base; + + return &mdesc[0]; +} + +static int __init prom_memtype_classify (unsigned int type) +{ + switch (type) { + case simmem_free: + return BOOT_MEM_RAM; + case simmem_reserved: + default: + return BOOT_MEM_RESERVED; + } +} + +void __init prom_meminit(void) +{ + struct prom_pmemblock *p; + + p = prom_getmdesc(); + + while (p->size) { + long type; + unsigned long base, size; + + type = prom_memtype_classify (p->type); + base = p->base; + size = p->size; + + add_memory_region(base, size, type); + p++; + } +} + +void __init prom_free_prom_memory(void) +{ + int i; + unsigned long addr; + + for (i = 0; i < boot_mem_map.nr_map; i++) { + if (boot_mem_map.map[i].type != BOOT_MEM_ROM_DATA) + continue; + + addr = boot_mem_map.map[i].addr; + free_init_pages("prom memory", + addr, addr + boot_mem_map.map[i].size); + } +} diff --git a/arch/mips/mipssim/sim_platform.c b/arch/mips/mipssim/sim_platform.c new file mode 100644 index 00000000000..53210a8c5de --- /dev/null +++ b/arch/mips/mipssim/sim_platform.c @@ -0,0 +1,35 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2007 by Ralf Baechle (ralf@linux-mips.org) + */ +#include +#include +#include +#include + +static char mipsnet_string[] = "mipsnet"; + +static struct platform_device eth1_device = { + .name = mipsnet_string, + .id = 0, +}; + +/* + * Create a platform device for the GPI port that receives the + * image data from the embedded camera. + */ +static int __init mipsnet_devinit(void) +{ + int err; + + err = platform_device_register(ð1_device); + if (err) + printk(KERN_ERR "%s: registration failed\n", mipsnet_string); + + return err; +} + +device_initcall(mipsnet_devinit); diff --git a/arch/mips/mipssim/sim_setup.c b/arch/mips/mipssim/sim_setup.c new file mode 100644 index 00000000000..3643582bdad --- /dev/null +++ b/arch/mips/mipssim/sim_setup.c @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2005 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + + +extern void sim_time_init(void); +static void __init serial_init(void); +unsigned int _isbonito = 0; + +extern void __init sanitize_tlb_entries(void); + + +const char *get_system_type(void) +{ + return "MIPSsim"; +} + +void __init plat_mem_setup(void) +{ + set_io_port_base(0xbfd00000); + + serial_init(); + + board_time_init = sim_time_init; + pr_info("Linux started...\n"); + +#ifdef CONFIG_MIPS_MT_SMP + sanitize_tlb_entries(); +#endif +} + +void __init prom_init(void) +{ + set_io_port_base(0xbfd00000); + + pr_info("\nLINUX started...\n"); + prom_init_cmdline(); + prom_meminit(); +} + + +static void __init serial_init(void) +{ +#ifdef CONFIG_SERIAL_8250 + struct uart_port s; + + memset(&s, 0, sizeof(s)); + + s.iobase = 0x3f8; + + /* hardware int 4 - the serial int, is CPU int 6 + but poll for now */ + s.irq = 0; + s.uartclk = BASE_BAUD * 16; + s.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST; + s.iotype = UPIO_PORT; + s.regshift = 0; + s.timeout = 4; + + if (early_serial_setup(&s) != 0) { + printk(KERN_ERR "Serial setup failed!\n"); + } + +#endif +} diff --git a/arch/mips/mipssim/sim_smp.c b/arch/mips/mipssim/sim_smp.c new file mode 100644 index 00000000000..38fa807b99f --- /dev/null +++ b/arch/mips/mipssim/sim_smp.c @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2005 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. + * + */ +/* + * Simulator Platform-specific hooks for SMP operation + */ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#ifdef CONFIG_MIPS_MT_SMTC +#include +#endif /* CONFIG_MIPS_MT_SMTC */ + +/* VPE/SMP Prototype implements platform interfaces directly */ +#if !defined(CONFIG_MIPS_MT_SMP) + +/* + * Cause the specified action to be performed on a targeted "CPU" + */ + +void core_send_ipi(int cpu, unsigned int action) +{ +#ifdef CONFIG_MIPS_MT_SMTC + smtc_send_ipi(cpu, LINUX_SMP_IPI, action); +#endif /* CONFIG_MIPS_MT_SMTC */ +/* "CPU" may be TC of same VPE, VPE of same CPU, or different CPU */ + +} + +/* + * Platform "CPU" startup hook + */ + +void prom_boot_secondary(int cpu, struct task_struct *idle) +{ +#ifdef CONFIG_MIPS_MT_SMTC + smtc_boot_secondary(cpu, idle); +#endif /* CONFIG_MIPS_MT_SMTC */ +} + +/* + * Post-config but pre-boot cleanup entry point + */ + +void prom_init_secondary(void) +{ +#ifdef CONFIG_MIPS_MT_SMTC + void smtc_init_secondary(void); + + smtc_init_secondary(); +#endif /* CONFIG_MIPS_MT_SMTC */ +} + +void plat_smp_setup(void) +{ +#ifdef CONFIG_MIPS_MT_SMTC + if (read_c0_config3() & (1 << 2)) + mipsmt_build_cpu_map(0); +#endif /* CONFIG_MIPS_MT_SMTC */ +} + +/* + * Platform SMP pre-initialization + */ + +void plat_prepare_cpus(unsigned int max_cpus) +{ +#ifdef CONFIG_MIPS_MT_SMTC + /* + * As noted above, we can assume a single CPU for now + * but it may be multithreaded. + */ + + if (read_c0_config3() & (1 << 2)) { + mipsmt_prepare_cpus(); + } +#endif /* CONFIG_MIPS_MT_SMTC */ +} + +/* + * SMP initialization finalization entry point + */ + +void prom_smp_finish(void) +{ +#ifdef CONFIG_MIPS_MT_SMTC + smtc_smp_finish(); +#endif /* CONFIG_MIPS_MT_SMTC */ +} + +/* + * Hook for after all CPUs are online + */ + +void prom_cpus_done(void) +{ +#ifdef CONFIG_MIPS_MT_SMTC + +#endif /* CONFIG_MIPS_MT_SMTC */ +} +#endif /* CONFIG_MIPS32R2_MT_SMP */ diff --git a/arch/mips/mipssim/sim_time.c b/arch/mips/mipssim/sim_time.c new file mode 100644 index 00000000000..874a18e8ac2 --- /dev/null +++ b/arch/mips/mipssim/sim_time.c @@ -0,0 +1,200 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + + +unsigned long cpu_khz; + +irqreturn_t sim_timer_interrupt(int irq, void *dev_id) +{ +#ifdef CONFIG_SMP + int cpu = smp_processor_id(); + + /* + * CPU 0 handles the global timer interrupt job + * resets count/compare registers to trigger next timer int. + */ +#ifndef CONFIG_MIPS_MT_SMTC + if (cpu == 0) { + timer_interrupt(irq, dev_id); + } else { + /* Everyone else needs to reset the timer int here as + ll_local_timer_interrupt doesn't */ + /* + * FIXME: need to cope with counter underflow. + * More support needs to be added to kernel/time for + * counter/timer interrupts on multiple CPU's + */ + write_c0_compare (read_c0_count() + ( mips_hpt_frequency/HZ)); + } +#else /* SMTC */ + /* + * In SMTC system, one Count/Compare set exists per VPE. + * Which TC within a VPE gets the interrupt is essentially + * random - we only know that it shouldn't be one with + * IXMT set. Whichever TC gets the interrupt needs to + * send special interprocessor interrupts to the other + * TCs to make sure that they schedule, etc. + * + * That code is specific to the SMTC kernel, not to + * the simulation platform, so it's invoked from + * the general MIPS timer_interrupt routine. + * + * We have a problem in that the interrupt vector code + * had to turn off the timer IM bit to avoid redundant + * entries, but we may never get to mips_cpu_irq_end + * to turn it back on again if the scheduler gets + * involved. So we clear the pending timer here, + * and re-enable the mask... + */ + + int vpflags = dvpe(); + write_c0_compare (read_c0_count() - 1); + clear_c0_cause(0x100 << cp0_compare_irq); + set_c0_status(0x100 << cp0_compare_irq); + irq_enable_hazard(); + evpe(vpflags); + + if (cpu_data[cpu].vpe_id == 0) + timer_interrupt(irq, dev_id); + else + write_c0_compare (read_c0_count() + ( mips_hpt_frequency/HZ)); + smtc_timer_broadcast(cpu_data[cpu].vpe_id); + +#endif /* CONFIG_MIPS_MT_SMTC */ + + /* + * every CPU should do profiling and process accounting + */ + local_timer_interrupt (irq, dev_id); + + return IRQ_HANDLED; +#else + return timer_interrupt (irq, dev_id); +#endif +} + + + +/* + * Estimate CPU frequency. Sets mips_hpt_frequency as a side-effect + */ +static unsigned int __init estimate_cpu_frequency(void) +{ + unsigned int prid = read_c0_prid() & 0xffff00; + unsigned int count; + +#if 1 + /* + * hardwire the board frequency to 12MHz. + */ + + if ((prid == (PRID_COMP_MIPS | PRID_IMP_20KC)) || + (prid == (PRID_COMP_MIPS | PRID_IMP_25KF))) + count = 12000000; + else + count = 6000000; +#else + unsigned int flags; + + local_irq_save(flags); + + /* Start counter exactly on falling edge of update flag */ + while (CMOS_READ(RTC_REG_A) & RTC_UIP); + while (!(CMOS_READ(RTC_REG_A) & RTC_UIP)); + + /* Start r4k counter. */ + write_c0_count(0); + + /* Read counter exactly on falling edge of update flag */ + while (CMOS_READ(RTC_REG_A) & RTC_UIP); + while (!(CMOS_READ(RTC_REG_A) & RTC_UIP)); + + count = read_c0_count(); + + /* restore interrupts */ + local_irq_restore(flags); +#endif + + mips_hpt_frequency = count; + + if ((prid != (PRID_COMP_MIPS | PRID_IMP_20KC)) && + (prid != (PRID_COMP_MIPS | PRID_IMP_25KF))) + count *= 2; + + count += 5000; /* round */ + count -= count%10000; + + return count; +} + +void __init sim_time_init(void) +{ + unsigned int est_freq, flags; + + local_irq_save(flags); + + /* Set Data mode - binary. */ + CMOS_WRITE(CMOS_READ(RTC_CONTROL) | RTC_DM_BINARY, RTC_CONTROL); + + est_freq = estimate_cpu_frequency (); + + printk(KERN_INFO "CPU frequency %d.%02d MHz\n", est_freq / 1000000, + (est_freq % 1000000) * 100 / 1000000); + + cpu_khz = est_freq / 1000; + + local_irq_restore(flags); +} + +static int mips_cpu_timer_irq; + +static void mips_timer_dispatch(void) +{ + do_IRQ(mips_cpu_timer_irq); +} + + +void __init plat_timer_setup(struct irqaction *irq) +{ + if (cpu_has_veic) { + set_vi_handler(MSC01E_INT_CPUCTR, mips_timer_dispatch); + mips_cpu_timer_irq = MSC01E_INT_BASE + MSC01E_INT_CPUCTR; + } else { + if (cpu_has_vint) + set_vi_handler(cp0_compare_irq, mips_timer_dispatch); + mips_cpu_timer_irq = MIPS_CPU_IRQ_BASE + cp0_compare_irq; + } + + /* we are using the cpu counter for timer interrupts */ + irq->handler = sim_timer_interrupt; + setup_irq(mips_cpu_timer_irq, irq); + +#ifdef CONFIG_SMP + /* irq_desc(riptor) is a global resource, when the interrupt overlaps + on seperate cpu's the first one tries to handle the second interrupt. + The effect is that the int remains disabled on the second cpu. + Mark the interrupt with IRQ_PER_CPU to avoid any confusion */ + irq_desc[mips_cpu_timer_irq].flags |= IRQ_PER_CPU; + set_irq_handler(mips_cpu_timer_irq, handle_percpu_irq); +#endif +} -- cgit v1.2.3