diff options
Diffstat (limited to 'arch/mips')
92 files changed, 1679 insertions, 1377 deletions
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 61262c5f9c6..455bd1f560a 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -22,6 +22,7 @@ config MACH_ALCHEMY config BASLER_EXCITE bool "Basler eXcite smart camera" select CEVT_R4K + select CSRC_R4K select DMA_COHERENT select HW_HAS_PCI select IRQ_CPU @@ -49,6 +50,7 @@ config BASLER_EXCITE_PROTOTYPE config BCM47XX bool "BCM47XX based boards" select CEVT_R4K + select CSRC_R4K select DMA_NONCOHERENT select HW_HAS_PCI select IRQ_CPU @@ -66,6 +68,7 @@ config BCM47XX config MIPS_COBALT bool "Cobalt Server" select CEVT_R4K + select CSRC_R4K select CEVT_GT641XX select DMA_NONCOHERENT select HW_HAS_PCI @@ -85,6 +88,7 @@ config MACH_DECSTATION bool "DECstations" select BOOT_ELF32 select CEVT_R4K + select CSRC_R4K select DMA_NONCOHERENT select NO_IOPORT select IRQ_CPU @@ -117,6 +121,7 @@ config MACH_JAZZ select ARC32 select ARCH_MAY_HAVE_PC_FDC select CEVT_R4K + select CSRC_R4K select GENERIC_ISA_DMA select IRQ_CPU select I8253 @@ -137,6 +142,7 @@ config MACH_JAZZ config LASAT bool "LASAT Networks platforms" select CEVT_R4K + select CSRC_R4K select DMA_NONCOHERENT select SYS_HAS_EARLY_PRINTK select HW_HAS_PCI @@ -154,6 +160,7 @@ config LEMOTE_FULONG bool "Lemote Fulong mini-PC" select ARCH_SPARSEMEM_ENABLE select CEVT_R4K + select CSRC_R4K select SYS_HAS_CPU_LOONGSON2 select DMA_NONCOHERENT select BOOT_ELF32 @@ -179,6 +186,7 @@ config MIPS_ATLAS bool "MIPS Atlas board" select BOOT_ELF32 select CEVT_R4K + select CSRC_R4K select DMA_NONCOHERENT select SYS_HAS_EARLY_PRINTK select IRQ_CPU @@ -210,6 +218,7 @@ config MIPS_MALTA select ARCH_MAY_HAVE_PC_FDC select BOOT_ELF32 select CEVT_R4K + select CSRC_R4K select DMA_NONCOHERENT select GENERIC_ISA_DMA select IRQ_CPU @@ -241,6 +250,7 @@ config MIPS_MALTA config MIPS_SEAD bool "MIPS SEAD board" select CEVT_R4K + select CSRC_R4K select IRQ_CPU select DMA_NONCOHERENT select SYS_HAS_EARLY_PRINTK @@ -260,6 +270,7 @@ config MIPS_SEAD config MIPS_SIM bool 'MIPS simulator (MIPSsim)' select CEVT_R4K + select CSRC_R4K select DMA_NONCOHERENT select SYS_HAS_EARLY_PRINTK select IRQ_CPU @@ -278,6 +289,7 @@ config MIPS_SIM config MARKEINS bool "NEC EMMA2RH Mark-eins" select CEVT_R4K + select CSRC_R4K select DMA_NONCOHERENT select HW_HAS_PCI select IRQ_CPU @@ -293,6 +305,7 @@ config MARKEINS config MACH_VR41XX bool "NEC VR4100 series based machines" select CEVT_R4K + select CSRC_R4K select SYS_HAS_CPU_VR41XX select GENERIC_HARDIRQS_NO__DO_IRQ @@ -330,6 +343,7 @@ config PMC_MSP config PMC_YOSEMITE bool "PMC-Sierra Yosemite eval board" select CEVT_R4K + select CSRC_R4K select DMA_COHERENT select HW_HAS_PCI select IRQ_CPU @@ -351,6 +365,7 @@ config PMC_YOSEMITE config QEMU bool "Qemu" select CEVT_R4K + select CSRC_R4K select DMA_COHERENT select GENERIC_ISA_DMA select HAVE_STD_PC_SERIAL_PORT @@ -361,10 +376,10 @@ config QEMU select PCSPEAKER select SWAP_IO_SPACE select SYS_HAS_CPU_MIPS32_R1 + select SYS_HAS_EARLY_PRINTK select SYS_SUPPORTS_32BIT_KERNEL select SYS_SUPPORTS_BIG_ENDIAN select SYS_SUPPORTS_LITTLE_ENDIAN - select ARCH_SPARSEMEM_ENABLE select GENERIC_HARDIRQS_NO__DO_IRQ select NR_CPUS_DEFAULT_1 select SYS_SUPPORTS_SMP @@ -382,9 +397,11 @@ config SGI_IP22 select ARC32 select BOOT_ELF32 select CEVT_R4K + select CSRC_R4K select DMA_NONCOHERENT select HW_HAS_EISA select I8253 + select I8259 select IP22_CPU_SCACHE select IRQ_CPU select GENERIC_ISA_DMA_SUPPORT_BROKEN @@ -427,6 +444,7 @@ config SGI_IP32 select ARC32 select BOOT_ELF32 select CEVT_R4K + select CSRC_R4K select DMA_NONCOHERENT select HW_HAS_PCI select IRQ_CPU @@ -498,6 +516,7 @@ config SIBYTE_SWARM select SYS_SUPPORTS_HIGHMEM select SYS_SUPPORTS_KGDB select SYS_SUPPORTS_LITTLE_ENDIAN + select ZONE_DMA32 if 64BIT config SIBYTE_LITTLESUR bool "Sibyte BCM91250C2-LittleSur" @@ -546,7 +565,9 @@ config SIBYTE_BIGSUR select SWAP_IO_SPACE select SYS_HAS_CPU_SB1 select SYS_SUPPORTS_BIG_ENDIAN + select SYS_SUPPORTS_HIGHMEM select SYS_SUPPORTS_LITTLE_ENDIAN + select ZONE_DMA32 if 64BIT config SNI_RM bool "SNI RM200/300/400" @@ -555,6 +576,7 @@ config SNI_RM select ARCH_MAY_HAVE_PC_FDC select BOOT_ELF32 select CEVT_R4K + select CSRC_R4K select DMA_NONCOHERENT select GENERIC_ISA_DMA select HW_HAS_EISA @@ -583,6 +605,7 @@ config SNI_RM config TOSHIBA_JMR3927 bool "Toshiba JMR-TX3927 board" + select CEVT_TXX9 select DMA_NONCOHERENT select HW_HAS_PCI select MIPS_TX3927 @@ -597,6 +620,8 @@ config TOSHIBA_JMR3927 config TOSHIBA_RBTX4927 bool "Toshiba RBTX49[23]7 board" select CEVT_R4K + select CSRC_R4K + select CEVT_TXX9 select DMA_NONCOHERENT select HAS_TXX9_SERIAL select HW_HAS_PCI @@ -618,6 +643,8 @@ config TOSHIBA_RBTX4927 config TOSHIBA_RBTX4938 bool "Toshiba RBTX4938 board" select CEVT_R4K + select CSRC_R4K + select CEVT_TXX9 select DMA_NONCOHERENT select HAS_TXX9_SERIAL select HW_HAS_PCI @@ -638,6 +665,7 @@ config TOSHIBA_RBTX4938 config WR_PPMC bool "Wind River PPMC board" select CEVT_R4K + select CSRC_R4K select IRQ_CPU select BOOT_ELF32 select DMA_NONCOHERENT @@ -730,12 +758,30 @@ config ARCH_MAY_HAVE_PC_FDC config BOOT_RAW bool +config CEVT_BCM1480 + bool + config CEVT_GT641XX bool config CEVT_R4K bool +config CEVT_SB1250 + bool + +config CEVT_TXX9 + bool + +config CSRC_BCM1480 + bool + +config CSRC_R4K + bool + +config CSRC_SB1250 + bool + config CFE bool @@ -1390,7 +1436,6 @@ config MIPS_MT_SMP depends on SYS_SUPPORTS_MULTITHREADING select CPU_MIPSR2_IRQ_VI select CPU_MIPSR2_IRQ_EI - select CPU_MIPSR2_SRS select MIPS_MT select NR_CPUS_DEFAULT_2 select SMP @@ -1407,7 +1452,6 @@ config MIPS_MT_SMTC select GENERIC_CLOCKEVENTS_BROADCAST select CPU_MIPSR2_IRQ_VI select CPU_MIPSR2_IRQ_EI - select CPU_MIPSR2_SRS select MIPS_MT select NR_CPUS_DEFAULT_8 select SMP @@ -1434,7 +1478,6 @@ config MIPS_VPE_LOADER depends on SYS_SUPPORTS_MULTITHREADING select CPU_MIPSR2_IRQ_VI select CPU_MIPSR2_IRQ_EI - select CPU_MIPSR2_SRS select MIPS_MT help Includes a loader for loading an elf relocatable object @@ -1563,12 +1606,6 @@ config CPU_MIPSR2_IRQ_VI config CPU_MIPSR2_IRQ_EI bool -# -# Shadow registers are an R2 feature -# -config CPU_MIPSR2_SRS - bool - config CPU_HAS_SYNC bool depends on !CPU_R3000 @@ -1630,6 +1667,9 @@ config ARCH_DISCONTIGMEM_ENABLE or have huge holes in the physical address space for other reasons. See <file:Documentation/vm/numa> for more. +config ARCH_POPULATES_NODE_MAP + def_bool y + config ARCH_SPARSEMEM_ENABLE bool select SPARSEMEM_STATIC @@ -1935,6 +1975,9 @@ config I8253 config PCSPEAKER bool +config ZONE_DMA32 + bool + source "drivers/pcmcia/Kconfig" source "drivers/pci/hotplug/Kconfig" diff --git a/arch/mips/Makefile b/arch/mips/Makefile index 23c17755eca..a1f8d8b96b0 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -44,7 +44,7 @@ endif ifneq ($(SUBARCH),$(ARCH)) ifeq ($(CROSS_COMPILE),) - CROSS_COMPILE := $(call cc-cross-prefix, $(tool-archpref)-linux- $(tool-archpref)-gnu-linux- $(tool-archpref)-unknown-gnu-linux-) + CROSS_COMPILE := $(call cc-cross-prefix, $(tool-archpref)-linux- $(tool-archpref)-linux-gnu- $(tool-archpref)-unknown-linux-gnu-) endif endif diff --git a/arch/mips/au1000/Kconfig b/arch/mips/au1000/Kconfig index b36cec58a9a..05d1354aad3 100644 --- a/arch/mips/au1000/Kconfig +++ b/arch/mips/au1000/Kconfig @@ -138,6 +138,7 @@ config SOC_AU1X00 bool select 64BIT_PHYS_ADDR select CEVT_R4K + select CSRC_R4K select IRQ_CPU select SYS_HAS_CPU_MIPS32_R1 select SYS_SUPPORTS_32BIT_KERNEL diff --git a/arch/mips/au1000/common/irq.c b/arch/mips/au1000/common/irq.c index 59e932a928d..ddfb7f0a17a 100644 --- a/arch/mips/au1000/common/irq.c +++ b/arch/mips/au1000/common/irq.c @@ -318,38 +318,6 @@ static struct irq_chip level_irq_type = { .end = end_irq, }; -#ifdef CONFIG_PM -void startup_match20_interrupt(irq_handler_t handler) -{ - struct irq_desc *desc = &irq_desc[AU1000_TOY_MATCH2_INT]; - - static struct irqaction action; - memset(&action, 0, sizeof(struct irqaction)); - - /* - * This is a big problem.... since we didn't use request_irq - * when kernel/irq.c calls probe_irq_xxx this interrupt will - * be probed for usage. This will end up disabling the device :( - * Give it a bogus "action" pointer -- this will keep it from - * getting auto-probed! - * - * By setting the status to match that of request_irq() we - * can avoid it. --cgray - */ - action.dev_id = handler; - action.flags = IRQF_DISABLED; - cpus_clear(action.mask); - action.name = "Au1xxx TOY"; - action.handler = handler; - action.next = NULL; - - desc->action = &action; - desc->status &= ~(IRQ_DISABLED | IRQ_AUTODETECT | IRQ_WAITING | IRQ_INPROGRESS); - - local_enable_irq(AU1000_TOY_MATCH2_INT); -} -#endif - static void __init setup_local_irq(unsigned int irq_nr, int type, int int_req) { unsigned int bit = irq_nr - AU1000_INTC0_INT_BASE; diff --git a/arch/mips/au1000/common/time.c b/arch/mips/au1000/common/time.c index 2556399708b..f113b512d7b 100644 --- a/arch/mips/au1000/common/time.c +++ b/arch/mips/au1000/common/time.c @@ -67,7 +67,7 @@ static DEFINE_SPINLOCK(time_lock); unsigned long wtimer; #ifdef CONFIG_PM -irqreturn_t counter0_irq(int irq, void *dev_id) +static irqreturn_t counter0_irq(int irq, void *dev_id) { unsigned long pc0; int time_elapsed; @@ -117,6 +117,13 @@ irqreturn_t counter0_irq(int irq, void *dev_id) return IRQ_HANDLED; } +struct irqaction counter0_action = { + .handler = counter0_irq, + .flags = IRQF_DISABLED, + .name = "alchemy-toy", + .dev_id = NULL, +}; + /* When we wakeup from sleep, we have to "catch up" on all of the * timer ticks we have missed. */ @@ -221,7 +228,7 @@ unsigned long cal_r4koff(void) return (cpu_speed / HZ); } -void __init plat_timer_setup(struct irqaction *irq) +void __init plat_time_init(void) { unsigned int est_freq; @@ -255,15 +262,10 @@ void __init plat_timer_setup(struct irqaction *irq) * we do this. */ if (no_au1xxx_32khz) { - unsigned int c0_status; - printk("WARNING: no 32KHz clock found.\n"); - /* Ensure we get CPO_COUNTER interrupts. - */ - c0_status = read_c0_status(); - c0_status |= IE_IRQ5; - write_c0_status(c0_status); + /* Ensure we get CPO_COUNTER interrupts. */ + set_c0_status(IE_IRQ5); } else { while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C0S); @@ -280,7 +282,7 @@ void __init plat_timer_setup(struct irqaction *irq) au_writel(last_match20 + MATCH20_INC, SYS_TOYMATCH2); au_sync(); while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20); - startup_match20_interrupt(counter0_irq); + setup_irq(AU1000_TOY_MATCH2_INT, &counter0_action); /* We can use the real 'wait' instruction. */ diff --git a/arch/mips/au1000/mtx-1/Makefile b/arch/mips/au1000/mtx-1/Makefile index 764bf9f7e28..85a90941de4 100644 --- a/arch/mips/au1000/mtx-1/Makefile +++ b/arch/mips/au1000/mtx-1/Makefile @@ -8,3 +8,6 @@ # lib-y := init.o board_setup.o irqmap.o +obj-y := platform.o + +EXTRA_CFLAGS += -Werror diff --git a/arch/mips/au1000/mtx-1/platform.c b/arch/mips/au1000/mtx-1/platform.c new file mode 100644 index 00000000000..49c0fb409fe --- /dev/null +++ b/arch/mips/au1000/mtx-1/platform.c @@ -0,0 +1,77 @@ +/* + * MTX-1 platform devices registration + * + * Copyright (C) 2007, Florian Fainelli <florian@openwrt.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <linux/init.h> +#include <linux/types.h> +#include <linux/platform_device.h> +#include <linux/leds.h> + +#include <asm/gpio.h> + +static struct resource mtx1_wdt_res[] = { + [0] = { + .start = 15, + .end = 15, + .name = "mtx1-wdt-gpio", + .flags = IORESOURCE_IRQ, + } +}; + +static struct platform_device mtx1_wdt = { + .name = "mtx1-wdt", + .id = 0, + .num_resources = ARRAY_SIZE(mtx1_wdt_res), + .resource = mtx1_wdt_res, +}; + +static struct gpio_led default_leds[] = { + { + .name = "mtx1:green", + .gpio = 211, + }, { + .name = "mtx1:red", + .gpio = 212, + }, +}; + +static struct gpio_led_platform_data mtx1_led_data = { + .num_leds = ARRAY_SIZE(default_leds), + .leds = default_leds, +}; + +static struct platform_device mtx1_gpio_leds = { + .name = "leds-gpio", + .id = -1, + .dev = { + .platform_data = &mtx1_led_data, + } +}; + +static struct __initdata platform_device * mtx1_devs[] = { + &mtx1_gpio_leds, + &mtx1_wdt +}; + +static int __init mtx1_register_devices(void) +{ + return platform_add_devices(mtx1_devs, ARRAY_SIZE(mtx1_devs)); +} + +arch_initcall(mtx1_register_devices); diff --git a/arch/mips/au1000/pb1200/Makefile b/arch/mips/au1000/pb1200/Makefile index 22b673cf55a..970b1b1d5cd 100644 --- a/arch/mips/au1000/pb1200/Makefile +++ b/arch/mips/au1000/pb1200/Makefile @@ -3,3 +3,5 @@ # lib-y := init.o board_setup.o irqmap.o + +EXTRA_CFLAGS += -Werror diff --git a/arch/mips/au1000/pb1200/board_setup.c b/arch/mips/au1000/pb1200/board_setup.c index 5dbc9868f59..b98bebfa87c 100644 --- a/arch/mips/au1000/pb1200/board_setup.c +++ b/arch/mips/au1000/pb1200/board_setup.c @@ -68,9 +68,11 @@ void board_reset(void) void __init board_setup(void) { char *argptr = NULL; - u32 pin_func; #if 0 + { + u32 pin_func; + /* Enable PSC1 SYNC for AC97. Normaly done in audio driver, * but it is board specific code, so put it here. */ @@ -81,11 +83,13 @@ void __init board_setup(void) au_writel(0, (u32)bcsr|0x10); /* turn off pcmcia power */ au_sync(); + } #endif #if defined(CONFIG_I2C_AU1550) { u32 freq0, clksrc; + u32 pin_func; /* Select SMBUS in CPLD */ bcsr->resets &= ~(BCSR_RESETS_PCS0MUX); diff --git a/arch/mips/au1000/pb1200/irqmap.c b/arch/mips/au1000/pb1200/irqmap.c index bdf00e2a35e..c096be4ed4e 100644 --- a/arch/mips/au1000/pb1200/irqmap.c +++ b/arch/mips/au1000/pb1200/irqmap.c @@ -94,51 +94,41 @@ inline void pb1200_disable_irq(unsigned int irq_nr) bcsr->intclr = 1<<(irq_nr - PB1200_INT_BEGIN); } -static unsigned int pb1200_startup_irq( unsigned int irq_nr ) +static unsigned int pb1200_setup_cascade(void) { - if (++pb1200_cascade_en == 1) - { - request_irq(AU1000_GPIO_7, &pb1200_cascade_handler, - 0, "Pb1200 Cascade", (void *)&pb1200_cascade_handler ); -#ifdef CONFIG_MIPS_PB1200 - /* We have a problem with CPLD rev3. Enable a workaround */ - if( ((bcsr->whoami & BCSR_WHOAMI_CPLD)>>4) <= 3) - { - printk("\nWARNING!!!\n"); - printk("\nWARNING!!!\n"); - printk("\nWARNING!!!\n"); - printk("\nWARNING!!!\n"); - printk("\nWARNING!!!\n"); - printk("\nWARNING!!!\n"); - printk("Pb1200 must be at CPLD rev4. Please have Pb1200\n"); - printk("updated to latest revision. This software will not\n"); - printk("work on anything less than CPLD rev4\n"); - printk("\nWARNING!!!\n"); - printk("\nWARNING!!!\n"); - printk("\nWARNING!!!\n"); - printk("\nWARNING!!!\n"); - printk("\nWARNING!!!\n"); - printk("\nWARNING!!!\n"); - while(1); - } -#endif - } - pb1200_enable_irq(irq_nr); + int err; + + err = request_irq(AU1000_GPIO_7, &pb1200_cascade_handler, + 0, "Pb1200 Cascade", &pb1200_cascade_handler); + if (err) + return err; + return 0; } -static void pb1200_shutdown_irq( unsigned int irq_nr ) +static unsigned int pb1200_startup_irq(unsigned int irq) { - pb1200_disable_irq(irq_nr); - if (--pb1200_cascade_en == 0) - { - free_irq(AU1000_GPIO_7, &pb1200_cascade_handler ); + if (++pb1200_cascade_en == 1) { + int res; + + res = pb1200_setup_cascade(); + if (res) + return res; } - return; + + pb1200_enable_irq(irq); + + return 0; } -static struct irq_chip external_irq_type = +static void pb1200_shutdown_irq(unsigned int irq) { + pb1200_disable_irq(irq); + if (--pb1200_cascade_en == 0) + free_irq(AU1000_GPIO_7, &pb1200_cascade_handler); +} + +static struct irq_chip external_irq_type = { #ifdef CONFIG_MIPS_PB1200 .name = "Pb1200 Ext", #endif @@ -155,16 +145,38 @@ static struct irq_chip external_irq_type = void _board_init_irq(void) { - int irq_nr; + unsigned int irq; - for (irq_nr = PB1200_INT_BEGIN; irq_nr <= PB1200_INT_END; irq_nr++) - { - set_irq_chip_and_handler(irq_nr, &external_irq_type, +#ifdef CONFIG_MIPS_PB1200 + /* We have a problem with CPLD rev3. Enable a workaround */ + if (((bcsr->whoami & BCSR_WHOAMI_CPLD) >> 4) <= 3) { + printk("\nWARNING!!!\n"); + printk("\nWARNING!!!\n"); + printk("\nWARNING!!!\n"); + printk("\nWARNING!!!\n"); + printk("\nWARNING!!!\n"); + printk("\nWARNING!!!\n"); + printk("Pb1200 must be at CPLD rev4. Please have Pb1200\n"); + printk("updated to latest revision. This software will not\n"); + printk("work on anything less than CPLD rev4\n"); + printk("\nWARNING!!!\n"); + printk("\nWARNING!!!\n"); + printk("\nWARNING!!!\n"); + printk("\nWARNING!!!\n"); + printk("\nWARNING!!!\n"); + printk("\nWARNING!!!\n"); + panic("Game over. Your score is 0."); + } +#endif + + for (irq = PB1200_INT_BEGIN; irq <= PB1200_INT_END; irq++) { + set_irq_chip_and_handler(irq, &external_irq_type, handle_level_irq); - pb1200_disable_irq(irq_nr); + pb1200_disable_irq(irq); } - /* GPIO_7 can not be hooked here, so it is hooked upon first - request of any source attached to the cascade */ + /* + * GPIO_7 can not be hooked here, so it is hooked upon first + * request of any source attached to the cascade + */ } - diff --git a/arch/mips/basler/excite/excite_setup.c b/arch/mips/basler/excite/excite_setup.c index 404ca9284b3..6dd8f0d46d0 100644 --- a/arch/mips/basler/excite/excite_setup.c +++ b/arch/mips/basler/excite/excite_setup.c @@ -68,24 +68,23 @@ DEFINE_SPINLOCK(titan_lock); int titan_irqflags; +/* + * The eXcite platform uses the alternate timer interrupt + * + * Fixme: At the time of this writing cevt-r4k.c doesn't yet know about how + * to handle the alternate timer interrupt of the RM9000. + */ void __init plat_time_init(void) { const u32 modebit5 = ocd_readl(0x00e4); - unsigned int - mult = ((modebit5 >> 11) & 0x1f) + 2, - div = ((modebit5 >> 16) & 0x1f) + 2; + unsigned int mult = ((modebit5 >> 11) & 0x1f) + 2; + unsigned int div = ((modebit5 >> 16) & 0x1f) + 2; - if (div == 33) div = 1; + if (div == 33) + div = 1; mips_hpt_frequency = EXCITE_CPU_EXT_CLOCK * mult / div / 2; } -void __init plat_timer_setup(struct irqaction *irq) -{ - /* The eXcite platform uses the alternate timer interrupt */ - set_c0_intcontrol(0x80); - setup_irq(TIMER_IRQ, irq); -} - static int __init excite_init_console(void) { #if defined(CONFIG_SERIAL_8250) diff --git a/arch/mips/configs/db1000_defconfig b/arch/mips/configs/db1000_defconfig index 885b633647e..5a8b7acb7dd 100644 --- a/arch/mips/configs/db1000_defconfig +++ b/arch/mips/configs/db1000_defconfig @@ -738,7 +738,6 @@ CONFIG_HW_CONSOLE=y CONFIG_VT_HW_CONSOLE_BINDING=y # CONFIG_SERIAL_NONSTANDARD is not set # CONFIG_AU1X00_GPIO is not set -# CONFIG_TS_AU1X00_ADS7846 is not set # # Serial drivers diff --git a/arch/mips/configs/db1100_defconfig b/arch/mips/configs/db1100_defconfig index e3c3a07e8a7..d4ed90bca26 100644 --- a/arch/mips/configs/db1100_defconfig +++ b/arch/mips/configs/db1100_defconfig @@ -714,7 +714,6 @@ CONFIG_HW_CONSOLE=y CONFIG_VT_HW_CONSOLE_BINDING=y # CONFIG_SERIAL_NONSTANDARD is not set # CONFIG_AU1X00_GPIO is not set -# CONFIG_TS_AU1X00_ADS7846 is not set # # Serial drivers diff --git a/arch/mips/configs/db1200_defconfig b/arch/mips/configs/db1200_defconfig index 9aa7c3ebfa3..a055657e698 100644 --- a/arch/mips/configs/db1200_defconfig +++ b/arch/mips/configs/db1200_defconfig @@ -775,7 +775,6 @@ CONFIG_HW_CONSOLE=y CONFIG_VT_HW_CONSOLE_BINDING=y # CONFIG_SERIAL_NONSTANDARD is not set # CONFIG_AU1X00_GPIO is not set -# CONFIG_TS_AU1X00_ADS7846 is not set # # Serial drivers diff --git a/arch/mips/configs/db1500_defconfig b/arch/mips/configs/db1500_defconfig index 99240668bca..0ad08cf446e 100644 --- a/arch/mips/configs/db1500_defconfig +++ b/arch/mips/configs/db1500_defconfig @@ -811,7 +811,6 @@ CONFIG_SERIO_RAW=m # CONFIG_VT is not set # CONFIG_SERIAL_NONSTANDARD is not set # CONFIG_AU1X00_GPIO is not set -# CONFIG_TS_AU1X00_ADS7846 is not set # # Serial drivers diff --git a/arch/mips/configs/db1550_defconfig b/arch/mips/configs/db1550_defconfig index 19992f76c60..057c7d429c8 100644 --- a/arch/mips/configs/db1550_defconfig +++ b/arch/mips/configs/db1550_defconfig @@ -856,7 +856,6 @@ CONFIG_SERIO_RAW=m # CONFIG_VT is not set # CONFIG_SERIAL_NONSTANDARD is not set # CONFIG_AU1X00_GPIO is not set -# CONFIG_TS_AU1X00_ADS7846 is not set # # Serial drivers diff --git a/arch/mips/configs/pb1100_defconfig b/arch/mips/configs/pb1100_defconfig index d53fa8f8e09..703d28db05b 100644 --- a/arch/mips/configs/pb1100_defconfig +++ b/arch/mips/configs/pb1100_defconfig @@ -731,7 +731,6 @@ CONFIG_HW_CONSOLE=y CONFIG_VT_HW_CONSOLE_BINDING=y # CONFIG_SERIAL_NONSTANDARD is not set # CONFIG_AU1X00_GPIO is not set -# CONFIG_TS_AU1X00_ADS7846 is not set # # Serial drivers diff --git a/arch/mips/configs/pb1500_defconfig b/arch/mips/configs/pb1500_defconfig index dc4aa0c6684..82f0c5cee0d 100644 --- a/arch/mips/configs/pb1500_defconfig +++ b/arch/mips/configs/pb1500_defconfig @@ -849,7 +849,6 @@ CONFIG_SERIO_RAW=m # CONFIG_VT is not set # CONFIG_SERIAL_NONSTANDARD is not set # CONFIG_AU1X00_GPIO is not set -# CONFIG_TS_AU1X00_ADS7846 is not set # # Serial drivers diff --git a/arch/mips/configs/pb1550_defconfig b/arch/mips/configs/pb1550_defconfig index 24428e13002..147a4fc7fdd 100644 --- a/arch/mips/configs/pb1550_defconfig +++ b/arch/mips/configs/pb1550_defconfig @@ -842,7 +842,6 @@ CONFIG_SERIO_RAW=m # CONFIG_VT is not set # CONFIG_SERIAL_NONSTANDARD is not set # CONFIG_AU1X00_GPIO is not set -# CONFIG_TS_AU1X00_ADS7846 is not set # # Serial drivers diff --git a/arch/mips/configs/sb1250-swarm_defconfig b/arch/mips/configs/sb1250-swarm_defconfig index 49dfcef2518..c2798229cbf 100644 --- a/arch/mips/configs/sb1250-swarm_defconfig +++ b/arch/mips/configs/sb1250-swarm_defconfig @@ -468,7 +468,7 @@ CONFIG_BLK_DEV_IDEFLOPPY=y # CONFIG_IDE_GENERIC=y # CONFIG_BLK_DEV_IDEPCI is not set -# CONFIG_BLK_DEV_IDE_SWARM is not set +CONFIG_BLK_DEV_IDE_SWARM=y # CONFIG_IDE_ARM is not set # CONFIG_BLK_DEV_IDEDMA is not set # CONFIG_IDEDMA_AUTO is not set diff --git a/arch/mips/gt64120/wrppmc/time.c b/arch/mips/gt64120/wrppmc/time.c index b207e7f1417..668dbd5f12c 100644 --- a/arch/mips/gt64120/wrppmc/time.c +++ b/arch/mips/gt64120/wrppmc/time.c @@ -19,12 +19,6 @@ #define WRPPMC_CPU_CLK_FREQ 40000000 /* 40MHZ */ -void __init plat_timer_setup(struct irqaction *irq) -{ - /* Install ISR for timer interrupt */ - setup_irq(WRPPMC_MIPS_TIMER_IRQ, irq); -} - /* * Estimate CPU frequency. Sets mips_hpt_frequency as a side-effect * diff --git a/arch/mips/jazz/irq.c b/arch/mips/jazz/irq.c index ae25b480723..d7f8a782aae 100644 --- a/arch/mips/jazz/irq.c +++ b/arch/mips/jazz/irq.c @@ -97,9 +97,10 @@ asmlinkage void plat_irq_dispatch(void) if (pending & IE_IRQ4) { r4030_read_reg32(JAZZ_TIMER_REGISTER); do_IRQ(JAZZ_TIMER_IRQ); - } else if (pending & IE_IRQ2) - do_IRQ(r4030_read_reg32(JAZZ_EISA_IRQ_ACK)); - else if (pending & IE_IRQ1) { + } else if (pending & IE_IRQ2) { + irq = *(volatile u8 *)JAZZ_EISA_IRQ_ACK; + do_IRQ(irq); + } else if (pending & IE_IRQ1) { irq = *(volatile u8 *)JAZZ_IO_IRQ_SOURCE >> 2; if (likely(irq > 0)) do_IRQ(irq + JAZZ_IRQ_START - 1); @@ -117,16 +118,16 @@ static void r4030_set_mode(enum clock_event_mode mode, struct clock_event_device r4030_clockevent = { .name = "r4030", .features = CLOCK_EVT_FEAT_PERIODIC, - .rating = 100, + .rating = 300, .irq = JAZZ_TIMER_IRQ, - .cpumask = CPU_MASK_CPU0, .set_mode = r4030_set_mode, }; static irqreturn_t r4030_timer_interrupt(int irq, void *dev_id) { - r4030_clockevent.event_handler(&r4030_clockevent); + struct clock_event_device *cd = dev_id; + cd->event_handler(cd); return IRQ_HANDLED; } @@ -134,15 +135,22 @@ static struct irqaction r4030_timer_irqaction = { .handler = r4030_timer_interrupt, .flags = IRQF_DISABLED, .mask = CPU_MASK_CPU0, - .name = "timer", + .name = "R4030 timer", }; void __init plat_time_init(void) { - struct irqaction *irq = &r4030_timer_irqaction; + struct clock_event_device *cd = &r4030_clockevent; + struct irqaction *action = &r4030_timer_irqaction; + unsigned int cpu = smp_processor_id(); BUG_ON(HZ != 100); + cd->cpumask = cpumask_of_cpu(cpu); + clockevents_register_device(cd); + action->dev_id = cd; + setup_irq(JAZZ_TIMER_IRQ, action); + /* * Set clock to 100Hz. * @@ -150,8 +158,5 @@ void __init plat_time_init(void) * a programmable 4-bit divider. This makes it fairly inflexible. */ r4030_write_reg32(JAZZ_TIMER_INTERVAL, 9); - setup_irq(JAZZ_TIMER_IRQ, irq); - - clockevents_register_device(&r4030_clockevent); setup_pit_timer(); } diff --git a/arch/mips/jmr3927/rbhma3100/setup.c b/arch/mips/jmr3927/rbhma3100/setup.c index edb9e59248e..06e01c8f4e3 100644 --- a/arch/mips/jmr3927/rbhma3100/setup.c +++ b/arch/mips/jmr3927/rbhma3100/setup.c @@ -27,17 +27,13 @@ * Copyright (C) 2007 Ralf Baechle (ralf@linux-mips.org) */ -#include <linux/clockchips.h> #include <linux/init.h> #include <linux/kernel.h> #include <linux/kdev_t.h> #include <linux/types.h> -#include <linux/sched.h> #include <linux/pci.h> #include <linux/ide.h> -#include <linux/irq.h> #include <linux/ioport.h> -#include <linux/param.h> /* for HZ */ #include <linux/delay.h> #include <linux/pm.h> #include <linux/platform_device.h> @@ -48,17 +44,13 @@ #endif #include <asm/addrspace.h> -#include <asm/time.h> +#include <asm/txx9tmr.h> #include <asm/reboot.h> #include <asm/jmr3927/jmr3927.h> #include <asm/mipsregs.h> extern void puts(const char *cp); -/* Tick Timer divider */ -#define JMR3927_TIMER_CCD 0 /* 1/2 */ -#define JMR3927_TIMER_CLK (JMR3927_IMCLK / (2 << JMR3927_TIMER_CCD)) - /* don't enable - see errata */ static int jmr3927_ccfg_toeon; @@ -93,66 +85,12 @@ static void jmr3927_machine_power_off(void) while (1); } -static cycle_t jmr3927_hpt_read(void) -{ - /* We assume this function is called xtime_lock held. */ - return jiffies * (JMR3927_TIMER_CLK / HZ) + jmr3927_tmrptr->trr; -} - -static void jmr3927_set_mode(enum clock_event_mode mode, - struct clock_event_device *evt) -{ - /* Nothing to do here */ -} - -struct clock_event_device jmr3927_clock_event_device = { - .name = "MIPS", - .features = CLOCK_EVT_FEAT_PERIODIC, - .shift = 32, - .rating = 300, - .cpumask = CPU_MASK_CPU0, - .irq = JMR3927_IRQ_TICK, - .set_mode = jmr3927_set_mode, -}; - -static irqreturn_t jmr3927_timer_interrupt(int irq, void *dev_id) -{ - struct clock_event_device *cd = &jmr3927_clock_event_device; - - jmr3927_tmrptr->tisr = 0; /* ack interrupt */ - - cd->event_handler(cd); - - return IRQ_HANDLED; -} - -static struct irqaction jmr3927_timer_irqaction = { - .handler = jmr3927_timer_interrupt, - .flags = IRQF_DISABLED | IRQF_PERCPU, - .name = "jmr3927-timer", -}; - void __init plat_time_init(void) { - struct clock_event_device *cd; - - clocksource_mips.read = jmr3927_hpt_read; - mips_hpt_frequency = JMR3927_TIMER_CLK; - - jmr3927_tmrptr->cpra = JMR3927_TIMER_CLK / HZ; - jmr3927_tmrptr->itmr = TXx927_TMTITMR_TIIE | TXx927_TMTITMR_TZCE; - jmr3927_tmrptr->ccdr = JMR3927_TIMER_CCD; - jmr3927_tmrptr->tcr = - TXx927_TMTCR_TCE | TXx927_TMTCR_CCDE | TXx927_TMTCR_TMODE_ITVL; - - cd = &jmr3927_clock_event_device; - /* Calculate the min / max delta */ - cd->mult = div_sc((unsigned long) JMR3927_IMCLK, NSEC_PER_SEC, 32); - cd->max_delta_ns = clockevent_delta2ns(0x7fffffff, cd); - cd->min_delta_ns = clockevent_delta2ns(0x300, cd); - clockevents_register_device(cd); - - setup_irq(JMR3927_IRQ_TICK, &jmr3927_timer_irqaction); + txx9_clockevent_init(TX3927_TMR_REG(0), + TXX9_IRQ_BASE + JMR3927_IRQ_IRC_TMR(0), + JMR3927_IMCLK); + txx9_clocksource_init(TX3927_TMR_REG(1), JMR3927_IMCLK); } #define DO_WRITE_THROUGH @@ -317,15 +255,8 @@ static void __init tx3927_setup(void) tx3927_ccfgptr->ccfg, tx3927_ccfgptr->pcfg); /* TMR */ - /* disable all timers */ - for (i = 0; i < TX3927_NR_TMR; i++) { - tx3927_tmrptr(i)->tcr = TXx927_TMTCR_CRE; - tx3927_tmrptr(i)->tisr = 0; - tx3927_tmrptr(i)->cpra = 0xffffffff; - tx3927_tmrptr(i)->itmr = 0; - tx3927_tmrptr(i)->ccdr = 0; - tx3927_tmrptr(i)->pgmr = 0; - } + for (i = 0; i < TX3927_NR_TMR; i++) + txx9_tmr_init(TX3927_TMR_REG(i)); /* DMA */ tx3927_dmaptr->mcr = 0; diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile index d7745c8976f..ffa08362de1 100644 --- a/arch/mips/kernel/Makefile +++ b/arch/mips/kernel/Makefile @@ -8,8 +8,14 @@ obj-y += cpu-probe.o branch.o entry.o genex.o irq.o process.o \ ptrace.o reset.o semaphore.o setup.o signal.o syscall.o \ time.o topology.o traps.o unaligned.o +obj-$(CONFIG_CEVT_BCM1480) += cevt-bcm1480.o obj-$(CONFIG_CEVT_R4K) += cevt-r4k.o obj-$(CONFIG_CEVT_GT641XX) += cevt-gt641xx.o +obj-$(CONFIG_CEVT_SB1250) += cevt-sb1250.o +obj-$(CONFIG_CEVT_TXX9) += cevt-txx9.o +obj-$(CONFIG_CSRC_BCM1480) += csrc-bcm1480.o +obj-$(CONFIG_CSRC_R4K) += csrc-r4k.o +obj-$(CONFIG_CSRC_SB1250) += csrc-sb1250.o binfmt_irix-objs := irixelf.o irixinv.o irixioctl.o irixsig.o \ irix5sys.o sysirix.o @@ -38,6 +44,7 @@ obj-$(CONFIG_CPU_TX49XX) += r4k_fpu.o r4k_switch.o obj-$(CONFIG_CPU_VR41XX) += r4k_fpu.o r4k_switch.o obj-$(CONFIG_SMP) += smp.o +obj-$(CONFIG_SMP_UP) += smp-up.o obj-$(CONFIG_MIPS_MT) += mips-mt.o obj-$(CONFIG_MIPS_MT_FPAFF) += mips-mt-fpaff.o diff --git a/arch/mips/kernel/cevt-bcm1480.c b/arch/mips/kernel/cevt-bcm1480.c new file mode 100644 index 00000000000..0a57f86945f --- /dev/null +++ b/arch/mips/kernel/cevt-bcm1480.c @@ -0,0 +1,153 @@ +/* + * Copyright (C) 2000,2001,2004 Broadcom Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that 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 <linux/clockchips.h> +#include <linux/interrupt.h> +#include <linux/percpu.h> + +#include <asm/addrspace.h> +#include <asm/io.h> +#include <asm/time.h> + +#include <asm/sibyte/bcm1480_regs.h> +#include <asm/sibyte/sb1250_regs.h> +#include <asm/sibyte/bcm1480_int.h> +#include <asm/sibyte/bcm1480_scd.h> + +#include <asm/sibyte/sb1250.h> + +#define IMR_IP2_VAL K_BCM1480_INT_MAP_I0 +#define IMR_IP3_VAL K_BCM1480_INT_MAP_I1 +#define IMR_IP4_VAL K_BCM1480_INT_MAP_I2 + +/* + * The general purpose timer ticks at 1MHz independent if + * the rest of the system + */ +static void sibyte_set_mode(enum clock_event_mode mode, + struct clock_event_device *evt) +{ + unsigned int cpu = smp_processor_id(); + void __iomem *cfg, *init; + + cfg = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)); + init = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT)); + + switch (mode) { + case CLOCK_EVT_MODE_PERIODIC: + __raw_writeq(0, cfg); + __raw_writeq((V_SCD_TIMER_FREQ / HZ) - 1, init); + __raw_writeq(M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS, + cfg); + break; + + case CLOCK_EVT_MODE_ONESHOT: + /* Stop the timer until we actually program a shot */ + case CLOCK_EVT_MODE_SHUTDOWN: + __raw_writeq(0, cfg); + break; + + case CLOCK_EVT_MODE_UNUSED: /* shuddup gcc */ + case CLOCK_EVT_MODE_RESUME: + ; + } +} + +static int sibyte_next_event(unsigned long delta, struct clock_event_device *cd) +{ + unsigned int cpu = smp_processor_id(); + void __iomem *cfg, *init; + + cfg = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)); + init = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT)); + + __raw_writeq(0, cfg); + __raw_writeq(delta - 1, init); + __raw_writeq(M_SCD_TIMER_ENABLE, cfg); + + return 0; +} + +static irqreturn_t sibyte_counter_handler(int irq, void *dev_id) +{ + unsigned int cpu = smp_processor_id(); + struct clock_event_device *cd = dev_id; + void __iomem *cfg; + unsigned long tmode; + + if (cd->mode == CLOCK_EVT_MODE_PERIODIC) + tmode = M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS; + else + tmode = 0; + + /* ACK interrupt */ + cfg = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)); + ____raw_writeq(tmode, cfg); + + cd->event_handler(cd); + + return IRQ_HANDLED; +} + +static DEFINE_PER_CPU(struct clock_event_device, sibyte_hpt_clockevent); +static DEFINE_PER_CPU(struct irqaction, sibyte_hpt_irqaction); +static DEFINE_PER_CPU(char [18], sibyte_hpt_name); + +void __cpuinit sb1480_clockevent_init(void) +{ + unsigned int cpu = smp_processor_id(); + unsigned int irq = K_BCM1480_INT_TIMER_0 + cpu; + struct irqaction *action = &per_cpu(sibyte_hpt_irqaction, cpu); + struct clock_event_device *cd = &per_cpu(sibyte_hpt_clockevent, cpu); + unsigned char *name = per_cpu(sibyte_hpt_name, cpu); + + BUG_ON(cpu > 3); /* Only have 4 general purpose timers */ + + sprintf(name, "bcm1480-counter-%d", cpu); + cd->name = name; + cd->features = CLOCK_EVT_FEAT_PERIODIC | + CLOCK_EVT_FEAT_ONESHOT; + clockevent_set_clock(cd, V_SCD_TIMER_FREQ); + cd->max_delta_ns = clockevent_delta2ns(0x7fffff, cd); + cd->min_delta_ns = clockevent_delta2ns(2, cd); + cd->rating = 200; + cd->irq = irq; + cd->cpumask = cpumask_of_cpu(cpu); + cd->set_next_event = sibyte_next_event; + cd->set_mode = sibyte_set_mode; + clockevents_register_device(cd); + + bcm1480_mask_irq(cpu, irq); + + /* + * Map the timer interrupt to IP[4] of this cpu + */ + __raw_writeq(IMR_IP4_VAL, + IOADDR(A_BCM1480_IMR_REGISTER(cpu, + R_BCM1480_IMR_INTERRUPT_MAP_BASE_H) + (irq << 3))); + + bcm1480_unmask_irq(cpu, irq); + + action->handler = sibyte_counter_handler; + action->flags = IRQF_DISABLED | IRQF_PERCPU; + action->mask = cpumask_of_cpu(cpu); + action->name = name; + action->dev_id = cd; + + irq_set_affinity(irq, cpumask_of_cpu(cpu)); + setup_irq(irq, action); +} diff --git a/arch/mips/kernel/cevt-gt641xx.c b/arch/mips/kernel/cevt-gt641xx.c index 4c651b2680f..c36772631fe 100644 --- a/arch/mips/kernel/cevt-gt641xx.c +++ b/arch/mips/kernel/cevt-gt641xx.c @@ -49,10 +49,9 @@ int gt641xx_timer0_state(void) static int gt641xx_timer0_set_next_event(unsigned long delta, struct clock_event_device *evt) { - unsigned long flags; u32 ctrl; - spin_lock_irqsave(>641xx_timer_lock, flags); + spin_lock(>641xx_timer_lock); ctrl = GT_READ(GT_TC_CONTROL_OFS); ctrl &= ~(GT_TC_CONTROL_ENTC0_MSK | GT_TC_CONTROL_SELTC0_MSK); @@ -61,7 +60,7 @@ static int gt641xx_timer0_set_next_event(unsigned long delta, GT_WRITE(GT_TC0_OFS, delta); GT_WRITE(GT_TC_CONTROL_OFS, ctrl); - spin_unlock_irqrestore(>641xx_timer_lock, flags); + spin_unlock(>641xx_timer_lock); return 0; } @@ -69,10 +68,9 @@ static int gt641xx_timer0_set_next_event(unsigned long delta, static void gt641xx_timer0_set_mode(enum clock_event_mode mode, struct clock_event_device *evt) { - unsigned long flags; u32 ctrl; - spin_lock_irqsave(>641xx_timer_lock, flags); + spin_lock(>641xx_timer_lock); ctrl = GT_READ(GT_TC_CONTROL_OFS); ctrl &= ~(GT_TC_CONTROL_ENTC0_MSK | GT_TC_CONTROL_SELTC0_MSK); @@ -90,7 +88,7 @@ static void gt641xx_timer0_set_mode(enum clock_event_mode mode, GT_WRITE(GT_TC_CONTROL_OFS, ctrl); - spin_unlock_irqrestore(>641xx_timer_lock, flags); + spin_unlock(>641xx_timer_lock); } static void gt641xx_timer0_event_handler(struct clock_event_device *dev) @@ -133,9 +131,9 @@ static int __init gt641xx_timer0_clockevent_init(void) cd = >641xx_timer0_clockevent; cd->rating = 200 + gt641xx_base_clock / 10000000; + clockevent_set_clock(cd, gt641xx_base_clock); cd->max_delta_ns = clockevent_delta2ns(0x7fffffff, cd); cd->min_delta_ns = clockevent_delta2ns(0x300, cd); - clockevent_set_clock(cd, gt641xx_base_clock); clockevents_register_device(>641xx_timer0_clockevent); diff --git a/arch/mips/kernel/cevt-r4k.c b/arch/mips/kernel/cevt-r4k.c index ae2984fff58..24a2d907aa0 100644 --- a/arch/mips/kernel/cevt-r4k.c +++ b/arch/mips/kernel/cevt-r4k.c @@ -28,7 +28,7 @@ static int mips_next_event(unsigned long delta, cnt = read_c0_count(); cnt += delta; write_c0_compare(cnt); - res = ((long)(read_c0_count() - cnt ) > 0) ? -ETIME : 0; + res = ((int)(read_c0_count() - cnt) > 0) ? -ETIME : 0; #ifdef CONFIG_MIPS_MT_SMTC evpe(vpflags); local_irq_restore(flags); @@ -179,7 +179,7 @@ static int c0_compare_int_pending(void) static int c0_compare_int_usable(void) { - const unsigned int delta = 0x300000; + unsigned int delta; unsigned int cnt; /* @@ -192,11 +192,17 @@ static int c0_compare_int_usable(void) return 0; } - cnt = read_c0_count(); - cnt += delta; - write_c0_compare(cnt); + for (delta = 0x10; delta <= 0x400000; delta <<= 1) { + cnt = read_c0_count(); + cnt += delta; + write_c0_compare(cnt); + irq_disable_hazard(); + if ((int)(read_c0_count() - cnt) < 0) + break; + /* increase delta if the timer was already expired */ + } - while ((long)(read_c0_count() - cnt) <= 0) + while ((int)(read_c0_count() - cnt) <= 0) ; /* Wait for expiry */ if (!c0_compare_int_pending()) @@ -213,15 +219,15 @@ static int c0_compare_int_usable(void) return 1; } -void __cpuinit mips_clockevent_init(void) +int __cpuinit mips_clockevent_init(void) { uint64_t mips_freq = mips_hpt_frequency; unsigned int cpu = smp_processor_id(); struct clock_event_device *cd; - unsigned int irq = MIPS_CPU_IRQ_BASE + 7; + unsigned int irq; - if (!cpu_has_counter) - return; + if (!cpu_has_counter || !mips_hpt_frequency) + return -ENXIO; #ifdef CONFIG_MIPS_MT_SMTC setup_smtc_dummy_clockevent_device(); @@ -231,11 +237,20 @@ void __cpuinit mips_clockevent_init(void) * device. */ if (cpu) - return; + return 0; #endif if (!c0_compare_int_usable()) - return; + return -ENXIO; + + /* + * With vectored interrupts things are getting platform specific. + * get_c0_compare_int is a hook to allow a platform to return the + * interrupt number of it's liking. + */ + irq = MIPS_CPU_IRQ_BASE + cp0_compare_irq; + if (get_c0_compare_int) + irq = get_c0_compare_int(); cd = &per_cpu(mips_clockevent_device, cpu); @@ -261,13 +276,17 @@ void __cpuinit mips_clockevent_init(void) clockevents_register_device(cd); - if (!cp0_timer_irq_installed) { + if (cp0_timer_irq_installed) + return 0; + + cp0_timer_irq_installed = 1; + #ifdef CONFIG_MIPS_MT_SMTC #define CPUCTR_IMASKBIT (0x100 << cp0_compare_irq) - setup_irq_smtc(irq, &c0_compare_irqaction, CPUCTR_IMASKBIT); + setup_irq_smtc(irq, &c0_compare_irqaction, CPUCTR_IMASKBIT); #else - setup_irq(irq, &c0_compare_irqaction); -#endif /* CONFIG_MIPS_MT_SMTC */ - cp0_timer_irq_installed = 1; - } + setup_irq(irq, &c0_compare_irqaction); +#endif + + return 0; } diff --git a/arch/mips/kernel/cevt-sb1250.c b/arch/mips/kernel/cevt-sb1250.c new file mode 100644 index 00000000000..63ac3ad462b --- /dev/null +++ b/arch/mips/kernel/cevt-sb1250.c @@ -0,0 +1,152 @@ +/* + * Copyright (C) 2000, 2001 Broadcom Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that 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 <linux/clockchips.h> +#include <linux/interrupt.h> +#include <linux/percpu.h> + +#include <asm/addrspace.h> +#include <asm/io.h> +#include <asm/time.h> + +#include <asm/sibyte/sb1250.h> +#include <asm/sibyte/sb1250_regs.h> +#include <asm/sibyte/sb1250_int.h> +#include <asm/sibyte/sb1250_scd.h> + +#define IMR_IP2_VAL K_INT_MAP_I0 +#define IMR_IP3_VAL K_INT_MAP_I1 +#define IMR_IP4_VAL K_INT_MAP_I2 + +/* + * The general purpose timer ticks at 1MHz independent if + * the rest of the system + */ +static void sibyte_set_mode(enum clock_event_mode mode, + struct clock_event_device *evt) +{ + unsigned int cpu = smp_processor_id(); + void __iomem *cfg, *init; + + cfg = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)); + init = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT)); + + switch (mode) { + case CLOCK_EVT_MODE_PERIODIC: + __raw_writeq(0, cfg); + __raw_writeq((V_SCD_TIMER_FREQ / HZ) - 1, init); + __raw_writeq(M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS, + cfg); + break; + + case CLOCK_EVT_MODE_ONESHOT: + /* Stop the timer until we actually program a shot */ + case CLOCK_EVT_MODE_SHUTDOWN: + __raw_writeq(0, cfg); + break; + + case CLOCK_EVT_MODE_UNUSED: /* shuddup gcc */ + case CLOCK_EVT_MODE_RESUME: + ; + } +} + +static int sibyte_next_event(unsigned long delta, struct clock_event_device *cd) +{ + unsigned int cpu = smp_processor_id(); + void __iomem *cfg, *init; + + cfg = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)); + init = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT)); + + __raw_writeq(0, cfg); + __raw_writeq(delta - 1, init); + __raw_writeq(M_SCD_TIMER_ENABLE, cfg); + + return 0; +} + +static irqreturn_t sibyte_counter_handler(int irq, void *dev_id) +{ + unsigned int cpu = smp_processor_id(); + struct clock_event_device *cd = dev_id; + void __iomem *cfg; + unsigned long tmode; + + if (cd->mode == CLOCK_EVT_MODE_PERIODIC) + tmode = M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS; + else + tmode = 0; + + /* ACK interrupt */ + cfg = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)); + ____raw_writeq(tmode, cfg); + + cd->event_handler(cd); + + return IRQ_HANDLED; +} + +static DEFINE_PER_CPU(struct clock_event_device, sibyte_hpt_clockevent); +static DEFINE_PER_CPU(struct irqaction, sibyte_hpt_irqaction); +static DEFINE_PER_CPU(char [18], sibyte_hpt_name); + +void __cpuinit sb1250_clockevent_init(void) +{ + unsigned int cpu = smp_processor_id(); + unsigned int irq = K_INT_TIMER_0 + cpu; + struct irqaction *action = &per_cpu(sibyte_hpt_irqaction, cpu); + struct clock_event_device *cd = &per_cpu(sibyte_hpt_clockevent, cpu); + unsigned char *name = per_cpu(sibyte_hpt_name, cpu); + + /* Only have 4 general purpose timers, and we use last one as hpt */ + BUG_ON(cpu > 2); + + sprintf(name, "sb1250-counter-%d", cpu); + cd->name = name; + cd->features = CLOCK_EVT_FEAT_PERIODIC | + CLOCK_EVT_FEAT_ONESHOT; + clockevent_set_clock(cd, V_SCD_TIMER_FREQ); + cd->max_delta_ns = clockevent_delta2ns(0x7fffff, cd); + cd->min_delta_ns = clockevent_delta2ns(2, cd); + cd->rating = 200; + cd->irq = irq; + cd->cpumask = cpumask_of_cpu(cpu); + cd->set_next_event = sibyte_next_event; + cd->set_mode = sibyte_set_mode; + clockevents_register_device(cd); + + sb1250_mask_irq(cpu, irq); + + /* + * Map the timer interrupt to IP[4] of this cpu + */ + __raw_writeq(IMR_IP4_VAL, + IOADDR(A_IMR_REGISTER(cpu, R_IMR_INTERRUPT_MAP_BASE) + + (irq << 3))); + + sb1250_unmask_irq(cpu, irq); + + action->handler = sibyte_counter_handler; + action->flags = IRQF_DISABLED | IRQF_PERCPU; + action->mask = cpumask_of_cpu(cpu); + action->name = name; + action->dev_id = cd; + + irq_set_affinity(irq, cpumask_of_cpu(cpu)); + setup_irq(irq, action); +} diff --git a/arch/mips/kernel/cevt-txx9.c b/arch/mips/kernel/cevt-txx9.c new file mode 100644 index 00000000000..795cb8fb0d7 --- /dev/null +++ b/arch/mips/kernel/cevt-txx9.c @@ -0,0 +1,171 @@ +/* + * 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. + * + * Based on linux/arch/mips/kernel/cevt-r4k.c, + * linux/arch/mips/jmr3927/rbhma3100/setup.c + * + * Copyright 2001 MontaVista Software Inc. + * Copyright (C) 2000-2001 Toshiba Corporation + * Copyright (C) 2007 MIPS Technologies, Inc. + * Copyright (C) 2007 Ralf Baechle <ralf@linux-mips.org> + */ +#include <linux/init.h> +#include <linux/interrupt.h> +#include <asm/time.h> +#include <asm/txx9tmr.h> + +#define TCR_BASE (TXx9_TMTCR_CCDE | TXx9_TMTCR_CRE | TXx9_TMTCR_TMODE_ITVL) +#define TIMER_CCD 0 /* 1/2 */ +#define TIMER_CLK(imclk) ((imclk) / (2 << TIMER_CCD)) + +static struct txx9_tmr_reg __iomem *txx9_cs_tmrptr; + +static cycle_t txx9_cs_read(void) +{ + return __raw_readl(&txx9_cs_tmrptr->trr); +} + +/* Use 1 bit smaller width to use full bits in that width */ +#define TXX9_CLOCKSOURCE_BITS (TXX9_TIMER_BITS - 1) + +static struct clocksource txx9_clocksource = { + .name = "TXx9", + .rating = 200, + .read = txx9_cs_read, + .mask = CLOCKSOURCE_MASK(TXX9_CLOCKSOURCE_BITS), + .flags = CLOCK_SOURCE_IS_CONTINUOUS, +}; + +void __init txx9_clocksource_init(unsigned long baseaddr, + unsigned int imbusclk) +{ + struct txx9_tmr_reg __iomem *tmrptr; + + clocksource_set_clock(&txx9_clocksource, TIMER_CLK(imbusclk)); + clocksource_register(&txx9_clocksource); + + tmrptr = ioremap(baseaddr, sizeof(struct txx9_tmr_reg)); + __raw_writel(TCR_BASE, &tmrptr->tcr); + __raw_writel(0, &tmrptr->tisr); + __raw_writel(TIMER_CCD, &tmrptr->ccdr); + __raw_writel(TXx9_TMITMR_TZCE, &tmrptr->itmr); + __raw_writel(1 << TXX9_CLOCKSOURCE_BITS, &tmrptr->cpra); + __raw_writel(TCR_BASE | TXx9_TMTCR_TCE, &tmrptr->tcr); + txx9_cs_tmrptr = tmrptr; +} + +static struct txx9_tmr_reg __iomem *txx9_tmrptr; + +static void txx9tmr_stop_and_clear(struct txx9_tmr_reg __iomem *tmrptr) +{ + /* stop and reset counter */ + __raw_writel(TCR_BASE, &tmrptr->tcr); + /* clear pending interrupt */ + __raw_writel(0, &tmrptr->tisr); +} + +static void txx9tmr_set_mode(enum clock_event_mode mode, + struct clock_event_device *evt) +{ + struct txx9_tmr_reg __iomem *tmrptr = txx9_tmrptr; + + txx9tmr_stop_and_clear(tmrptr); + switch (mode) { + case CLOCK_EVT_MODE_PERIODIC: + __raw_writel(TXx9_TMITMR_TIIE | TXx9_TMITMR_TZCE, + &tmrptr->itmr); + /* start timer */ + __raw_writel(((u64)(NSEC_PER_SEC / HZ) * evt->mult) >> + evt->shift, + &tmrptr->cpra); + __raw_writel(TCR_BASE | TXx9_TMTCR_TCE, &tmrptr->tcr); + break; + case CLOCK_EVT_MODE_SHUTDOWN: + case CLOCK_EVT_MODE_UNUSED: + __raw_writel(0, &tmrptr->itmr); + break; + case CLOCK_EVT_MODE_ONESHOT: + __raw_writel(TXx9_TMITMR_TIIE, &tmrptr->itmr); + break; + case CLOCK_EVT_MODE_RESUME: + __raw_writel(TIMER_CCD, &tmrptr->ccdr); + __raw_writel(0, &tmrptr->itmr); + break; + } +} + +static int txx9tmr_set_next_event(unsigned long delta, + struct clock_event_device *evt) +{ + struct txx9_tmr_reg __iomem *tmrptr = txx9_tmrptr; + + txx9tmr_stop_and_clear(tmrptr); + /* start timer */ + __raw_writel(delta, &tmrptr->cpra); + __raw_writel(TCR_BASE | TXx9_TMTCR_TCE, &tmrptr->tcr); + return 0; +} + +static struct clock_event_device txx9tmr_clock_event_device = { + .name = "TXx9", + .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, + .rating = 200, + .cpumask = CPU_MASK_CPU0, + .set_mode = txx9tmr_set_mode, + .set_next_event = txx9tmr_set_next_event, +}; + +static irqreturn_t txx9tmr_interrupt(int irq, void *dev_id) +{ + struct clock_event_device *cd = &txx9tmr_clock_event_device; + struct txx9_tmr_reg __iomem *tmrptr = txx9_tmrptr; + + __raw_writel(0, &tmrptr->tisr); /* ack interrupt */ + cd->event_handler(cd); + return IRQ_HANDLED; +} + +static struct irqaction txx9tmr_irq = { + .handler = txx9tmr_interrupt, + .flags = IRQF_DISABLED | IRQF_PERCPU, + .name = "txx9tmr", +}; + +void __init txx9_clockevent_init(unsigned long baseaddr, int irq, + unsigned int imbusclk) +{ + struct clock_event_device *cd = &txx9tmr_clock_event_device; + struct txx9_tmr_reg __iomem *tmrptr; + + tmrptr = ioremap(baseaddr, sizeof(struct txx9_tmr_reg)); + txx9tmr_stop_and_clear(tmrptr); + __raw_writel(TIMER_CCD, &tmrptr->ccdr); + __raw_writel(0, &tmrptr->itmr); + txx9_tmrptr = tmrptr; + + clockevent_set_clock(cd, TIMER_CLK(imbusclk)); + cd->max_delta_ns = + clockevent_delta2ns(0xffffffff >> (32 - TXX9_TIMER_BITS), cd); + cd->min_delta_ns = clockevent_delta2ns(0xf, cd); + cd->irq = irq; + clockevents_register_device(cd); + setup_irq(irq, &txx9tmr_irq); + printk(KERN_INFO "TXx9: clockevent device at 0x%lx, irq %d\n", + baseaddr, irq); +} + +void __init txx9_tmr_init(unsigned long baseaddr) +{ + struct txx9_tmr_reg __iomem *tmrptr; + + tmrptr = ioremap(baseaddr, sizeof(struct txx9_tmr_reg)); + __raw_writel(TXx9_TMTCR_CRE, &tmrptr->tcr); + __raw_writel(0, &tmrptr->tisr); + __raw_writel(0xffffffff, &tmrptr->cpra); + __raw_writel(0, &tmrptr->itmr); + __raw_writel(0, &tmrptr->ccdr); + __raw_writel(0, &tmrptr->pgmr); + iounmap(tmrptr); +} diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index c8c47a2d197..5c2794391bf 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -943,6 +943,11 @@ __init void cpu_probe(void) } __cpu_name[cpu] = cpu_to_name(c); + + if (cpu_has_mips_r2) + c->srsets = ((read_c0_srsctl() >> 26) & 0x0f) + 1; + else + c->srsets = 1; } __init void cpu_report(void) diff --git a/arch/mips/kernel/csrc-bcm1480.c b/arch/mips/kernel/csrc-bcm1480.c new file mode 100644 index 00000000000..868745e7184 --- /dev/null +++ b/arch/mips/kernel/csrc-bcm1480.c @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2000,2001,2004 Broadcom Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that 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 <linux/clocksource.h> + +#include <asm/addrspace.h> +#include <asm/io.h> +#include <asm/time.h> + +#include <asm/sibyte/bcm1480_regs.h> +#include <asm/sibyte/sb1250_regs.h> +#include <asm/sibyte/bcm1480_int.h> +#include <asm/sibyte/bcm1480_scd.h> + +#include <asm/sibyte/sb1250.h> + +static cycle_t bcm1480_hpt_read(void) +{ + return (cycle_t) __raw_readq(IOADDR(A_SCD_ZBBUS_CYCLE_COUNT)); +} + +struct clocksource bcm1480_clocksource = { + .name = "zbbus-cycles", + .rating = 200, + .read = bcm1480_hpt_read, + .mask = CLOCKSOURCE_MASK(64), + .flags = CLOCK_SOURCE_IS_CONTINUOUS, +}; + +void __init sb1480_clocksource_init(void) +{ + struct clocksource *cs = &bcm1480_clocksource; + unsigned int plldiv; + unsigned long zbbus; + + plldiv = G_BCM1480_SYS_PLL_DIV(__raw_readq(IOADDR(A_SCD_SYSTEM_CFG))); + zbbus = ((plldiv >> 1) * 50000000) + ((plldiv & 1) * 25000000); + clocksource_set_clock(cs, zbbus); + clocksource_register(cs); +} diff --git a/arch/mips/kernel/csrc-r4k.c b/arch/mips/kernel/csrc-r4k.c new file mode 100644 index 00000000000..74c5c62365a --- /dev/null +++ b/arch/mips/kernel/csrc-r4k.c @@ -0,0 +1,29 @@ +/* + * 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 + */ + +static cycle_t c0_hpt_read(void) +{ + return read_c0_count(); +} + +static struct clocksource clocksource_mips = { + .name = "MIPS", + .read = c0_hpt_read, + .mask = CLOCKSOURCE_MASK(32), + .flags = CLOCK_SOURCE_IS_CONTINUOUS, +}; + +static void __init init_mips_clocksource(void) +{ + /* Calclate a somewhat reasonable rating value */ + clocksource_mips.rating = 200 + mips_hpt_frequency / 10000000; + + clocksource_set_clock(&clocksource_mips, mips_hpt_frequency); + + clocksource_register(&clocksource_mips); +} diff --git a/arch/mips/kernel/csrc-sb1250.c b/arch/mips/kernel/csrc-sb1250.c new file mode 100644 index 00000000000..92212bbb8e4 --- /dev/null +++ b/arch/mips/kernel/csrc-sb1250.c @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2000, 2001 Broadcom Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that 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 <linux/clocksource.h> + +#include <asm/addrspace.h> +#include <asm/io.h> +#include <asm/time.h> + +#include <asm/sibyte/sb1250.h> +#include <asm/sibyte/sb1250_regs.h> +#include <asm/sibyte/sb1250_int.h> +#include <asm/sibyte/sb1250_scd.h> + +#define SB1250_HPT_NUM 3 +#define SB1250_HPT_VALUE M_SCD_TIMER_CNT /* max value */ + +/* + * The HPT is free running from SB1250_HPT_VALUE down to 0 then starts over + * again. + */ +static cycle_t sb1250_hpt_read(void) +{ + unsigned int count; + + count = G_SCD_TIMER_CNT(__raw_readq(IOADDR(A_SCD_TIMER_REGISTER(SB1250_HPT_NUM, R_SCD_TIMER_CNT)))); + + return SB1250_HPT_VALUE - count; +} + +struct clocksource bcm1250_clocksource = { + .name = "bcm1250-counter-3", + .rating = 200, + .read = sb1250_hpt_read, + .mask = CLOCKSOURCE_MASK(23), + .flags = CLOCK_SOURCE_IS_CONTINUOUS, +}; + +void __init sb1250_clocksource_init(void) +{ + struct clocksource *cs = &bcm1250_clocksource; + + /* Setup hpt using timer #3 but do not enable irq for it */ + __raw_writeq(0, + IOADDR(A_SCD_TIMER_REGISTER(SB1250_HPT_NUM, + R_SCD_TIMER_CFG))); + __raw_writeq(SB1250_HPT_VALUE, + IOADDR(A_SCD_TIMER_REGISTER(SB1250_HPT_NUM, + R_SCD_TIMER_INIT))); + __raw_writeq(M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS, + IOADDR(A_SCD_TIMER_REGISTER(SB1250_HPT_NUM, + R_SCD_TIMER_CFG))); + + clocksource_set_clock(cs, V_SCD_TIMER_FREQ); + clocksource_register(cs); +} diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S index c0f19d638b9..e76a76bf0b3 100644 --- a/arch/mips/kernel/genex.S +++ b/arch/mips/kernel/genex.S @@ -146,7 +146,7 @@ NESTED(handle_int, PT_SIZE, sp) and k0, ST0_IEP bnez k0, 1f - mfc0 k0, EP0_EPC + mfc0 k0, CP0_EPC .set noreorder j k0 rfe diff --git a/arch/mips/kernel/i8253.c b/arch/mips/kernel/i8253.c index 5d9830df359..c2d497ceffd 100644 --- a/arch/mips/kernel/i8253.c +++ b/arch/mips/kernel/i8253.c @@ -12,8 +12,9 @@ #include <asm/delay.h> #include <asm/i8253.h> #include <asm/io.h> +#include <asm/time.h> -static DEFINE_SPINLOCK(i8253_lock); +DEFINE_SPINLOCK(i8253_lock); /* * Initialize the PIT timer. @@ -87,11 +88,10 @@ struct clock_event_device pit_clockevent = { .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, .set_mode = init_pit_timer, .set_next_event = pit_next_event, - .shift = 32, .irq = 0, }; -irqreturn_t timer_interrupt(int irq, void *dev_id) +static irqreturn_t timer_interrupt(int irq, void *dev_id) { pit_clockevent.event_handler(&pit_clockevent); @@ -111,19 +111,20 @@ static struct irqaction irq0 = { */ void __init setup_pit_timer(void) { + struct clock_event_device *cd = &pit_clockevent; + unsigned int cpu = smp_processor_id(); + /* * Start pit with the boot cpu mask and make it global after the * IO_APIC has been initialized. */ - pit_clockevent.cpumask = cpumask_of_cpu(0); - pit_clockevent.mult = div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC, 32); - pit_clockevent.max_delta_ns = - clockevent_delta2ns(0x7FFF, &pit_clockevent); - pit_clockevent.min_delta_ns = - clockevent_delta2ns(0xF, &pit_clockevent); - clockevents_register_device(&pit_clockevent); - - irq0.mask = cpumask_of_cpu(0); + cd->cpumask = cpumask_of_cpu(cpu); + clockevent_set_clock(cd, CLOCK_TICK_RATE); + cd->max_delta_ns = clockevent_delta2ns(0x7FFF, cd); + cd->min_delta_ns = clockevent_delta2ns(0xF, cd); + clockevents_register_device(cd); + + irq0.mask = cpumask_of_cpu(cpu); setup_irq(0, &irq0); } diff --git a/arch/mips/kernel/irixsig.c b/arch/mips/kernel/irixsig.c index a0a91056fda..5b10ac133ec 100644 --- a/arch/mips/kernel/irixsig.c +++ b/arch/mips/kernel/irixsig.c @@ -24,8 +24,12 @@ #define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP))) +#define _IRIX_NSIG 128 +#define _IRIX_NSIG_BPW BITS_PER_LONG +#define _IRIX_NSIG_WORDS (_IRIX_NSIG / _IRIX_NSIG_BPW) + typedef struct { - unsigned long sig[4]; + unsigned long sig[_IRIX_NSIG_WORDS]; } irix_sigset_t; struct sigctx_irix5 { @@ -426,6 +430,7 @@ asmlinkage int irix_sigprocmask(int how, irix_sigset_t __user *new, break; default: + spin_unlock_irq(¤t->sighand->siglock); return -EINVAL; } recalc_sigpending(); @@ -527,7 +532,7 @@ asmlinkage int irix_sigpoll_sys(unsigned long __user *set, expire = schedule_timeout_interruptible(expire); - for (i=0; i<=4; i++) + for (i=0; i < _IRIX_NSIG_WORDS; i++) tmp |= (current->pending.signal.sig[i] & kset.sig[i]); if (tmp) diff --git a/arch/mips/kernel/irq-rm7000.c b/arch/mips/kernel/irq-rm7000.c index 25073288348..971adf6ef4f 100644 --- a/arch/mips/kernel/irq-rm7000.c +++ b/arch/mips/kernel/irq-rm7000.c @@ -44,5 +44,5 @@ void __init rm7k_cpu_irq_init(void) for (i = base; i < base + 4; i++) set_irq_chip_and_handler(i, &rm7k_irq_controller, - handle_level_irq); + handle_percpu_irq); } diff --git a/arch/mips/kernel/irq-rm9000.c b/arch/mips/kernel/irq-rm9000.c index ae83d2df6f3..7b04583bd80 100644 --- a/arch/mips/kernel/irq-rm9000.c +++ b/arch/mips/kernel/irq-rm9000.c @@ -104,5 +104,5 @@ void __init rm9k_cpu_irq_init(void) rm9000_perfcount_irq = base + 1; set_irq_chip_and_handler(rm9000_perfcount_irq, &rm9k_perfcounter_irq, - handle_level_irq); + handle_percpu_irq); } diff --git a/arch/mips/kernel/irq_cpu.c b/arch/mips/kernel/irq_cpu.c index 7b66e03b589..0ee2567b780 100644 --- a/arch/mips/kernel/irq_cpu.c +++ b/arch/mips/kernel/irq_cpu.c @@ -116,5 +116,5 @@ void __init mips_cpu_irq_init(void) for (i = irq_base + 2; i < irq_base + 8; i++) set_irq_chip_and_handler(i, &mips_cpu_irq_controller, - handle_level_irq); + handle_percpu_irq); } diff --git a/arch/mips/kernel/proc.c b/arch/mips/kernel/proc.c index efd2d131412..6e6e947cce1 100644 --- a/arch/mips/kernel/proc.c +++ b/arch/mips/kernel/proc.c @@ -60,6 +60,8 @@ static int show_cpuinfo(struct seq_file *m, void *v) cpu_has_dsp ? " dsp" : "", cpu_has_mipsmt ? " mt" : "" ); + seq_printf(m, "shadow register sets\t: %d\n", + cpu_data[n].srsets); sprintf(fmt, "VCE%%c exceptions\t\t: %s\n", cpu_has_vce ? "%u" : "not available"); diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c index 999f7853de2..35234b92b9a 100644 --- a/arch/mips/kernel/ptrace.c +++ b/arch/mips/kernel/ptrace.c @@ -65,13 +65,13 @@ int ptrace_getregs(struct task_struct *child, __s64 __user *data) regs = task_pt_regs(child); for (i = 0; i < 32; i++) - __put_user(regs->regs[i], data + i); - __put_user(regs->lo, data + EF_LO - EF_R0); - __put_user(regs->hi, data + EF_HI - EF_R0); - __put_user(regs->cp0_epc, data + EF_CP0_EPC - EF_R0); - __put_user(regs->cp0_badvaddr, data + EF_CP0_BADVADDR - EF_R0); - __put_user(regs->cp0_status, data + EF_CP0_STATUS - EF_R0); - __put_user(regs->cp0_cause, data + EF_CP0_CAUSE - EF_R0); + __put_user((long)regs->regs[i], data + i); + __put_user((long)regs->lo, data + EF_LO - EF_R0); + __put_user((long)regs->hi, data + EF_HI - EF_R0); + __put_user((long)regs->cp0_epc, data + EF_CP0_EPC - EF_R0); + __put_user((long)regs->cp0_badvaddr, data + EF_CP0_BADVADDR - EF_R0); + __put_user((long)regs->cp0_status, data + EF_CP0_STATUS - EF_R0); + __put_user((long)regs->cp0_cause, data + EF_CP0_CAUSE - EF_R0); return 0; } @@ -390,11 +390,11 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) } case PTRACE_GETREGS: - ret = ptrace_getregs(child, (__u64 __user *) data); + ret = ptrace_getregs(child, (__s64 __user *) data); break; case PTRACE_SETREGS: - ret = ptrace_setregs(child, (__u64 __user *) data); + ret = ptrace_setregs(child, (__s64 __user *) data); break; case PTRACE_GETFPREGS: diff --git a/arch/mips/kernel/ptrace32.c b/arch/mips/kernel/ptrace32.c index f2bffed94fa..76818be6ba7 100644 --- a/arch/mips/kernel/ptrace32.c +++ b/arch/mips/kernel/ptrace32.c @@ -346,11 +346,11 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data) } case PTRACE_GETREGS: - ret = ptrace_getregs(child, (__u64 __user *) (__u64) data); + ret = ptrace_getregs(child, (__s64 __user *) (__u64) data); break; case PTRACE_SETREGS: - ret = ptrace_setregs(child, (__u64 __user *) (__u64) data); + ret = ptrace_setregs(child, (__s64 __user *) (__u64) data); break; case PTRACE_GETFPREGS: diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S index 118be24224f..01993ec3368 100644 --- a/arch/mips/kernel/scall64-n32.S +++ b/arch/mips/kernel/scall64-n32.S @@ -293,7 +293,7 @@ EXPORT(sysn32_call_table) PTR sys_ni_syscall /* 6170, was get_kernel_syms */ PTR sys_ni_syscall /* was query_module */ PTR sys_quotactl - PTR sys_nfsservctl + PTR compat_sys_nfsservctl PTR sys_ni_syscall /* res. for getpmsg */ PTR sys_ni_syscall /* 6175 for putpmsg */ PTR sys_ni_syscall /* res. for afs_syscall */ diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c index a06a27d6cfc..7f6ddcb5d48 100644 --- a/arch/mips/kernel/setup.c +++ b/arch/mips/kernel/setup.c @@ -269,7 +269,7 @@ static void __init bootmem_init(void) static void __init bootmem_init(void) { - unsigned long reserved_end; + unsigned long init_begin, reserved_end; unsigned long mapstart = ~0UL; unsigned long bootmap_size; int i; @@ -342,6 +342,35 @@ static void __init bootmem_init(void) */ bootmap_size = init_bootmem_node(NODE_DATA(0), mapstart, min_low_pfn, max_low_pfn); + + + init_begin = PFN_UP(__pa_symbol(&__init_begin)); + for (i = 0; i < boot_mem_map.nr_map; i++) { + unsigned long start, end; + + start = PFN_UP(boot_mem_map.map[i].addr); + end = PFN_DOWN(boot_mem_map.map[i].addr + + boot_mem_map.map[i].size); + + if (start <= init_begin) + start = init_begin; + if (start >= end) + continue; + +#ifndef CONFIG_HIGHMEM + if (end > max_low_pfn) + end = max_low_pfn; + + /* + * ... finally, is the area going away? + */ + if (end <= start) + continue; +#endif + + add_active_range(0, start, end); + } + /* * Register fully available low RAM pages with the bootmem allocator. */ diff --git a/arch/mips/kernel/smp-up.c b/arch/mips/kernel/smp-up.c new file mode 100644 index 00000000000..ead6c30eeb1 --- /dev/null +++ b/arch/mips/kernel/smp-up.c @@ -0,0 +1,67 @@ +/* + * 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) 2006, 07 by Ralf Baechle (ralf@linux-mips.org) + * + * Symmetric Uniprocessor (TM) Support + */ +#include <linux/kernel.h> +#include <linux/sched.h> + +/* + * Send inter-processor interrupt + */ +void up_send_ipi_single(int cpu, unsigned int action) +{ + panic(KERN_ERR "%s called", __func__); +} + +static inline void up_send_ipi_mask(cpumask_t mask, unsigned int action) +{ + panic(KERN_ERR "%s called", __func__); +} + +/* + * After we've done initial boot, this function is called to allow the + * board code to clean up state, if needed + */ +void __cpuinit up_init_secondary(void) +{ +} + +void __cpuinit up_smp_finish(void) +{ +} + +/* Hook for after all CPUs are online */ +void up_cpus_done(void) +{ +} + +/* + * Firmware CPU startup hook + */ +void __cpuinit up_boot_secondary(int cpu, struct task_struct *idle) +{ +} + +void __init up_smp_setup(void) +{ +} + +void __init up_prepare_cpus(unsigned int max_cpus) +{ +} + +struct plat_smp_ops up_smp_ops = { + .send_ipi_single = up_send_ipi_single, + .send_ipi_mask = up_send_ipi_mask, + .init_secondary = up_init_secondary, + .smp_finish = up_smp_finish, + .cpus_done = up_cpus_done, + .boot_secondary = up_boot_secondary, + .smp_setup = up_smp_setup, + .prepare_cpus = up_prepare_cpus, +}; diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c index a8c1a698d58..9c92d42996c 100644 --- a/arch/mips/kernel/smtc.c +++ b/arch/mips/kernel/smtc.c @@ -88,11 +88,19 @@ unsigned int smtc_status = 0; /* Boot command line configuration overrides */ +static int vpe0limit; static int ipibuffers = 0; static int nostlb = 0; static int asidmask = 0; unsigned long smtc_asid_mask = 0xff; +static int __init vpe0tcs(char *str) +{ + get_option(&str, &vpe0limit); + + return 1; +} + static int __init ipibufs(char *str) { get_option(&str, &ipibuffers); @@ -125,6 +133,7 @@ static int __init asidmask_set(char *str) return 1; } +__setup("vpe0tcs=", vpe0tcs); __setup("ipibufs=", ipibufs); __setup("nostlb", stlb_disable); __setup("asidmask=", asidmask_set); @@ -340,7 +349,7 @@ static void smtc_tc_setup(int vpe, int tc, int cpu) void mipsmt_prepare_cpus(void) { - int i, vpe, tc, ntc, nvpe, tcpervpe, slop, cpu; + int i, vpe, tc, ntc, nvpe, tcpervpe[NR_CPUS], slop, cpu; unsigned long flags; unsigned long val; int nipi; @@ -401,8 +410,39 @@ void mipsmt_prepare_cpus(void) ntc = NR_CPUS; if (tclimit > 0 && ntc > tclimit) ntc = tclimit; - tcpervpe = ntc / nvpe; - slop = ntc % nvpe; /* Residual TCs, < NVPE */ + slop = ntc % nvpe; + for (i = 0; i < nvpe; i++) { + tcpervpe[i] = ntc / nvpe; + if (slop) { + if((slop - i) > 0) tcpervpe[i]++; + } + } + /* Handle command line override for VPE0 */ + if (vpe0limit > ntc) vpe0limit = ntc; + if (vpe0limit > 0) { + int slopslop; + if (vpe0limit < tcpervpe[0]) { + /* Reducing TC count - distribute to others */ + slop = tcpervpe[0] - vpe0limit; + slopslop = slop % (nvpe - 1); + tcpervpe[0] = vpe0limit; + for (i = 1; i < nvpe; i++) { + tcpervpe[i] += slop / (nvpe - 1); + if(slopslop && ((slopslop - (i - 1) > 0))) + tcpervpe[i]++; + } + } else if (vpe0limit > tcpervpe[0]) { + /* Increasing TC count - steal from others */ + slop = vpe0limit - tcpervpe[0]; + slopslop = slop % (nvpe - 1); + tcpervpe[0] = vpe0limit; + for (i = 1; i < nvpe; i++) { + tcpervpe[i] -= slop / (nvpe - 1); + if(slopslop && ((slopslop - (i - 1) > 0))) + tcpervpe[i]--; + } + } + } /* Set up shared TLB */ smtc_configure_tlb(); @@ -416,7 +456,7 @@ void mipsmt_prepare_cpus(void) if (vpe != 0) printk(", "); printk("VPE %d: TC", vpe); - for (i = 0; i < tcpervpe; i++) { + for (i = 0; i < tcpervpe[vpe]; i++) { /* * TC 0 is bound to VPE 0 at reset, * and is presumably executing this @@ -429,15 +469,6 @@ void mipsmt_prepare_cpus(void) printk(" %d", tc); tc++; } - if (slop) { - if (tc != 0) { - smtc_tc_setup(vpe, tc, cpu); - cpu++; - } - printk(" %d", tc); - tc++; - slop--; - } if (vpe != 0) { /* * Clear any stale software interrupts from VPE's Cause diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c index b95fe93dd64..af1bdc89748 100644 --- a/arch/mips/kernel/syscall.c +++ b/arch/mips/kernel/syscall.c @@ -73,7 +73,14 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, task_size = STACK_TOP; + if (len > task_size) + return -ENOMEM; + if (flags & MAP_FIXED) { + /* Even MAP_FIXED mappings must reside within task_size. */ + if (task_size - len < addr) + return -EINVAL; + /* * We do not accept a shared mapping if it would violate * cache aliasing constraints. @@ -83,8 +90,6 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, return addr; } - if (len > task_size) - return -ENOMEM; do_color_align = 0; if (filp || (flags & MAP_SHARED)) do_color_align = 1; diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c index 6c6849a8f13..52075426c37 100644 --- a/arch/mips/kernel/time.c +++ b/arch/mips/kernel/time.c @@ -3,42 +3,31 @@ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net * Copyright (c) 2003, 2004 Maciej W. Rozycki * - * Common time service routines for MIPS machines. See - * Documentation/mips/time.README. + * Common time service routines for MIPS machines. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. */ +#include <linux/bug.h> #include <linux/clockchips.h> #include <linux/types.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/sched.h> #include <linux/param.h> -#include <linux/profile.h> #include <linux/time.h> #include <linux/timex.h> #include <linux/smp.h> -#include <linux/kernel_stat.h> #include <linux/spinlock.h> -#include <linux/interrupt.h> #include <linux/module.h> -#include <linux/kallsyms.h> -#include <asm/bootinfo.h> -#include <asm/cache.h> -#include <asm/compiler.h> -#include <asm/cpu.h> #include <asm/cpu-features.h> #include <asm/div64.h> -#include <asm/sections.h> #include <asm/smtc_ipi.h> #include <asm/time.h> -#include <irq.h> - /* * forward reference */ @@ -61,40 +50,8 @@ int update_persistent_clock(struct timespec now) return rtc_mips_set_mmss(now.tv_sec); } -/* - * Null high precision timer functions for systems lacking one. - */ -static cycle_t null_hpt_read(void) -{ - return 0; -} - -/* - * High precision timer functions for a R4k-compatible timer. - */ -static cycle_t c0_hpt_read(void) -{ - return read_c0_count(); -} - int (*mips_timer_state)(void); -/* - * local_timer_interrupt() does profiling and process accounting - * on a per-CPU basis. - * - * In UP mode, it is invoked from the (global) timer_interrupt. - * - * In SMP mode, it might invoked by per-CPU timer interrupt, or - * a broadcasted inter-processor interrupt which itself is triggered - * by the global timer interrupt. - */ -void local_timer_interrupt(int irq, void *dev_id) -{ - profile_tick(CPU_PROFILING); - update_process_times(user_mode(get_irq_regs())); -} - int null_perf_irq(void) { return 0; @@ -115,62 +72,10 @@ EXPORT_SYMBOL(perf_irq); * (only needed if you intended to use cpu counter as timer interrupt * source) * 2) calculate a couple of cached variables for later usage - * 3) plat_timer_setup() - - * a) (optional) over-write any choices made above by time_init(). - * b) machine specific code should setup the timer irqaction. - * c) enable the timer interrupt */ unsigned int mips_hpt_frequency; -static unsigned int __init calibrate_hpt(void) -{ - cycle_t frequency, hpt_start, hpt_end, hpt_count, hz; - - const int loops = HZ / 10; - int log_2_loops = 0; - int i; - - /* - * We want to calibrate for 0.1s, but to avoid a 64-bit - * division we round the number of loops up to the nearest - * power of 2. - */ - while (loops > 1 << log_2_loops) - log_2_loops++; - i = 1 << log_2_loops; - - /* - * Wait for a rising edge of the timer interrupt. - */ - while (mips_timer_state()); - while (!mips_timer_state()); - - /* - * Now see how many high precision timer ticks happen - * during the calculated number of periods between timer - * interrupts. - */ - hpt_start = clocksource_mips.read(); - do { - while (mips_timer_state()); - while (!mips_timer_state()); - } while (--i); - hpt_end = clocksource_mips.read(); - - hpt_count = (hpt_end - hpt_start) & clocksource_mips.mask; - hz = HZ; - frequency = hpt_count * hz; - - return frequency >> log_2_loops; -} - -struct clocksource clocksource_mips = { - .name = "MIPS", - .mask = CLOCKSOURCE_MASK(32), - .flags = CLOCK_SOURCE_IS_CONTINUOUS, -}; - void __init clocksource_set_clock(struct clocksource *cs, unsigned int clock) { u64 temp; @@ -204,55 +109,60 @@ void __cpuinit clockevent_set_clock(struct clock_event_device *cd, cd->mult = (u32) temp; } -static void __init init_mips_clocksource(void) +void __init __weak plat_time_init(void) { - if (!mips_hpt_frequency || clocksource_mips.read == null_hpt_read) - return; - - /* Calclate a somewhat reasonable rating value */ - clocksource_mips.rating = 200 + mips_hpt_frequency / 10000000; - - clocksource_set_clock(&clocksource_mips, mips_hpt_frequency); - - clocksource_register(&clocksource_mips); } -void __init __weak plat_time_init(void) +/* + * This function exists in order to cause an error due to a duplicate + * definition if platform code should have its own implementation. The hook + * to use instead is plat_time_init. plat_time_init does not receive the + * irqaction pointer argument anymore. This is because any function which + * initializes an interrupt timer now takes care of its own request_irq rsp. + * setup_irq calls and each clock_event_device should use its own + * struct irqrequest. + */ +void __init plat_timer_setup(void) { + BUG(); } -void __init __weak plat_timer_setup(struct irqaction *irq) +static __init int cpu_has_mfc0_count_bug(void) { + switch (current_cpu_type()) { + case CPU_R4000PC: + case CPU_R4000SC: + case CPU_R4000MC: + /* + * V3.0 is documented as suffering from the mfc0 from count bug. + * Afaik this is the last version of the R4000. Later versions + * were marketed as R4400. + */ + return 1; + + case CPU_R4400PC: + case CPU_R4400SC: + case CPU_R4400MC: + /* + * The published errata for the R4400 upto 3.0 say the CPU + * has the mfc0 from count bug. + */ + if ((current_cpu_data.processor_id & 0xff) <= 0x30) + return 1; + + /* + * I don't have erratas for newer R4400 so be paranoid. + */ + return 1; + } + + return 0; } void __init time_init(void) { plat_time_init(); - /* Choose appropriate high precision timer routines. */ - if (!cpu_has_counter && !clocksource_mips.read) - /* No high precision timer -- sorry. */ - clocksource_mips.read = null_hpt_read; - else if (!mips_hpt_frequency && !mips_timer_state) { - /* A high precision timer of unknown frequency. */ - if (!clocksource_mips.read) - /* No external high precision timer -- use R4k. */ - clocksource_mips.read = c0_hpt_read; - } else { - /* We know counter frequency. Or we can get it. */ - if (!clocksource_mips.read) { - /* No external high precision timer -- use R4k. */ - clocksource_mips.read = c0_hpt_read; - } - if (!mips_hpt_frequency) - mips_hpt_frequency = calibrate_hpt(); - - /* Report the high precision timer rate for a reference. */ - printk("Using %u.%03u MHz high precision timer.\n", - ((mips_hpt_frequency + 500) / 1000) / 1000, - ((mips_hpt_frequency + 500) / 1000) % 1000); - } - - init_mips_clocksource(); - mips_clockevent_init(); + if (mips_clockevent_init() || !cpu_has_mfc0_count_bug()) + init_mips_clocksource(); } diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index fa500787152..23e73d0650a 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -1100,59 +1100,6 @@ void *set_except_vector(int n, void *addr) return (void *)old_handler; } -#ifdef CONFIG_CPU_MIPSR2_SRS -/* - * MIPSR2 shadow register set allocation - * FIXME: SMP... - */ - -static struct shadow_registers { - /* - * Number of shadow register sets supported - */ - unsigned long sr_supported; - /* - * Bitmap of allocated shadow registers - */ - unsigned long sr_allocated; -} shadow_registers; - -static void mips_srs_init(void) -{ - shadow_registers.sr_supported = ((read_c0_srsctl() >> 26) & 0x0f) + 1; - printk(KERN_INFO "%ld MIPSR2 register sets available\n", - shadow_registers.sr_supported); - shadow_registers.sr_allocated = 1; /* Set 0 used by kernel */ -} - -int mips_srs_max(void) -{ - return shadow_registers.sr_supported; -} - -int mips_srs_alloc(void) -{ - struct shadow_registers *sr = &shadow_registers; - int set; - -again: - set = find_first_zero_bit(&sr->sr_allocated, sr->sr_supported); - if (set >= sr->sr_supported) - return -1; - - if (test_and_set_bit(set, &sr->sr_allocated)) - goto again; - - return set; -} - -void mips_srs_free(int set) -{ - struct shadow_registers *sr = &shadow_registers; - - clear_bit(set, &sr->sr_allocated); -} - static asmlinkage void do_default_vi(void) { show_regs(get_irq_regs()); @@ -1163,6 +1110,7 @@ static void *set_vi_srs_handler(int n, vi_handler_t addr, int srs) { unsigned long handler; unsigned long old_handler = vi_handlers[n]; + int srssets = current_cpu_data.srsets; u32 *w; unsigned char *b; @@ -1178,7 +1126,7 @@ static void *set_vi_srs_handler(int n, vi_handler_t addr, int srs) b = (unsigned char *)(ebase + 0x200 + n*VECTORSPACING); - if (srs >= mips_srs_max()) + if (srs >= srssets) panic("Shadow register set %d not supported", srs); if (cpu_has_veic) { @@ -1186,7 +1134,7 @@ static void *set_vi_srs_handler(int n, vi_handler_t addr, int srs) board_bind_eic_interrupt(n, srs); } else if (cpu_has_vint) { /* SRSMap is only defined if shadow sets are implemented */ - if (mips_srs_max() > 1) + if (srssets > 1) change_c0_srsmap(0xf << n*4, srs << n*4); } @@ -1253,14 +1201,6 @@ void *set_vi_handler(int n, vi_handler_t addr) return set_vi_srs_handler(n, addr, 0); } -#else - -static inline void mips_srs_init(void) -{ -} - -#endif /* CONFIG_CPU_MIPSR2_SRS */ - /* * This is used by native signal handling */ @@ -1503,8 +1443,6 @@ void __init trap_init(void) else ebase = CAC_BASE; - mips_srs_init(); - per_cpu_trap_init(); /* diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S index 2781cff1485..5fc2398bdb7 100644 --- a/arch/mips/kernel/vmlinux.lds.S +++ b/arch/mips/kernel/vmlinux.lds.S @@ -63,21 +63,23 @@ SECTIONS /* writeable */ .data : { /* Data */ - . = . + DATAOFFSET; /* for CONFIG_MAPPED_KERNEL */ - /* - * This ALIGN is needed as a workaround for a bug a gcc bug upto 4.1 which - * limits the maximum alignment to at most 32kB and results in the following - * warning: - * - * CC arch/mips/kernel/init_task.o - * arch/mips/kernel/init_task.c:30: warning: alignment of ‘init_thread_union’ - * is greater than maximum object file alignment. Using 32768 - */ - . = ALIGN(_PAGE_SIZE); - *(.data.init_task) - - DATA_DATA - CONSTRUCTORS + . = . + DATAOFFSET; /* for CONFIG_MAPPED_KERNEL */ + /* + * This ALIGN is needed as a workaround for a bug a + * gcc bug upto 4.1 which limits the maximum alignment + * to at most 32kB and results in the following + * warning: + * + * CC arch/mips/kernel/init_task.o + * arch/mips/kernel/init_task.c:30: warning: alignment + * of ‘init_thread_union’ is greater than maximum + * object file alignment. Using 32768 + */ + . = ALIGN(_PAGE_SIZE); + *(.data.init_task) + + DATA_DATA + CONSTRUCTORS } _gp = . + 0x8000; .lit8 : { diff --git a/arch/mips/kernel/vpe.c b/arch/mips/kernel/vpe.c index df8cbe4c7c0..c06eb812a95 100644 --- a/arch/mips/kernel/vpe.c +++ b/arch/mips/kernel/vpe.c @@ -470,7 +470,7 @@ static int apply_r_mips_lo16(struct module *me, uint32_t *location, */ if (v != l->value) { printk(KERN_DEBUG "VPE loader: " - "apply_r_mips_lo16/hi16: " + "apply_r_mips_lo16/hi16: \t" "inconsistent value information\n"); return -ENOEXEC; } @@ -629,7 +629,7 @@ static void simplify_symbols(Elf_Shdr * sechdrs, break; case SHN_MIPS_SCOMMON: - printk(KERN_DEBUG "simplify_symbols: ignoring SHN_MIPS_SCOMMON" + printk(KERN_DEBUG "simplify_symbols: ignoring SHN_MIPS_SCOMMON " "symbol <%s> st_shndx %d\n", strtab + sym[i].st_name, sym[i].st_shndx); // .sbss section @@ -942,8 +942,8 @@ static int vpe_elfload(struct vpe * v) if (phdr->p_type != PT_LOAD) continue; - memcpy((void *)phdr->p_vaddr, (char *)hdr + phdr->p_offset, phdr->p_filesz); - memset((void *)phdr->p_vaddr + phdr->p_filesz, 0, phdr->p_memsz - phdr->p_filesz); + memcpy((void *)phdr->p_paddr, (char *)hdr + phdr->p_offset, phdr->p_filesz); + memset((void *)phdr->p_paddr + phdr->p_filesz, 0, phdr->p_memsz - phdr->p_filesz); phdr++; } @@ -1003,6 +1003,7 @@ static void cleanup_tc(struct tc *tc) write_tc_c0_tcstatus(tmp); write_tc_c0_tchalt(TCHALT_H); + mips_ihb(); /* bind it to anything other than VPE1 */ // write_tc_c0_tcbind(read_tc_c0_tcbind() & ~TCBIND_CURVPE); // | TCBIND_CURVPE @@ -1235,9 +1236,12 @@ int vpe_free(vpe_handle vpe) settc(t->index); write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() & ~VPECONF0_VPA); - /* mark the TC unallocated and halt'ed */ - write_tc_c0_tcstatus(read_tc_c0_tcstatus() & ~TCSTATUS_A); + /* halt the TC */ write_tc_c0_tchalt(TCHALT_H); + mips_ihb(); + + /* mark the TC unallocated */ + write_tc_c0_tcstatus(read_tc_c0_tcstatus() & ~TCSTATUS_A); v->state = VPE_STATE_UNUSED; @@ -1533,14 +1537,16 @@ static int __init vpe_module_init(void) t->pvpe = get_vpe(0); /* set the parent vpe */ } + /* halt the TC */ + write_tc_c0_tchalt(TCHALT_H); + mips_ihb(); + tmp = read_tc_c0_tcstatus(); /* mark not activated and not dynamically allocatable */ tmp &= ~(TCSTATUS_A | TCSTATUS_DA); tmp |= TCSTATUS_IXMT; /* interrupt exempt */ write_tc_c0_tcstatus(tmp); - - write_tc_c0_tchalt(TCHALT_H); } } diff --git a/arch/mips/lasat/interrupt.c b/arch/mips/lasat/interrupt.c index ba9692be356..cfeab669782 100644 --- a/arch/mips/lasat/interrupt.c +++ b/arch/mips/lasat/interrupt.c @@ -19,17 +19,14 @@ * Lasat boards. */ #include <linux/init.h> -#include <linux/irq.h> -#include <linux/sched.h> -#include <linux/slab.h> #include <linux/interrupt.h> -#include <linux/kernel_stat.h> +#include <linux/irq.h> #include <asm/bootinfo.h> #include <asm/irq_cpu.h> #include <asm/lasat/lasatint.h> -#include <asm/time.h> -#include <asm/gdb-stub.h> + +#include <irq.h> static volatile int *lasat_int_status; static volatile int *lasat_int_mask; @@ -97,12 +94,18 @@ asmlinkage void plat_irq_dispatch(void) /* if int_status == 0, then the interrupt has already been cleared */ if (int_status) { - irq = LASATINT_BASE + ls1bit32(int_status); + irq = LASAT_IRQ_BASE + ls1bit32(int_status); do_IRQ(irq); } } +static struct irqaction cascade = { + .handler = no_action, + .mask = CPU_MASK_NONE, + .name = "cascade", +}; + void __init arch_init_irq(void) { int i; @@ -127,6 +130,9 @@ void __init arch_init_irq(void) } mips_cpu_irq_init(); - for (i = LASATINT_BASE; i <= LASATINT_END; i++) + + for (i = LASAT_IRQ_BASE; i <= LASAT_IRQ_END; i++) set_irq_chip_and_handler(i, &lasat_irq_type, handle_level_irq); + + setup_irq(LASAT_CASCADE_IRQ, &cascade); } diff --git a/arch/mips/lasat/setup.c b/arch/mips/lasat/setup.c index 54827d0174b..e072da4ff3b 100644 --- a/arch/mips/lasat/setup.c +++ b/arch/mips/lasat/setup.c @@ -117,14 +117,11 @@ static struct notifier_block lasat_panic_block[] = } }; -void plat_time_init(void) +void __init plat_time_init(void) { mips_hpt_frequency = lasat_board_info.li_cpu_hz / 2; -} -void __init plat_timer_setup(struct irqaction *irq) -{ - change_c0_status(ST0_IM, IE_IRQ0 | IE_IRQ5); + change_c0_status(ST0_IM, IE_IRQ0); } void __init plat_mem_setup(void) diff --git a/arch/mips/math-emu/ieee754.c b/arch/mips/math-emu/ieee754.c index 946aee33178..cb1b6822711 100644 --- a/arch/mips/math-emu/ieee754.c +++ b/arch/mips/math-emu/ieee754.c @@ -108,6 +108,7 @@ int ieee754si_xcpt(int r, const char *op, ...) ax.rv.si = r; va_start(ax.ap, op); ieee754_xcpt(&ax); + va_end(ax.ap); return ax.rv.si; } @@ -122,5 +123,6 @@ s64 ieee754di_xcpt(s64 r, const char *op, ...) ax.rv.di = r; va_start(ax.ap, op); ieee754_xcpt(&ax); + va_end(ax.ap); return ax.rv.di; } diff --git a/arch/mips/math-emu/ieee754dp.c b/arch/mips/math-emu/ieee754dp.c index 3e214aac4b1..6d2d89f3247 100644 --- a/arch/mips/math-emu/ieee754dp.c +++ b/arch/mips/math-emu/ieee754dp.c @@ -57,6 +57,7 @@ ieee754dp ieee754dp_xcpt(ieee754dp r, const char *op, ...) ax.rv.dp = r; va_start(ax.ap, op); ieee754_xcpt(&ax); + va_end(ax.ap); return ax.rv.dp; } @@ -83,6 +84,7 @@ ieee754dp ieee754dp_nanxcpt(ieee754dp r, const char *op, ...) ax.rv.dp = r; va_start(ax.ap, op); ieee754_xcpt(&ax); + va_end(ax.ap); return ax.rv.dp; } diff --git a/arch/mips/math-emu/ieee754sp.c b/arch/mips/math-emu/ieee754sp.c index adda851cd04..463534045ab 100644 --- a/arch/mips/math-emu/ieee754sp.c +++ b/arch/mips/math-emu/ieee754sp.c @@ -58,6 +58,7 @@ ieee754sp ieee754sp_xcpt(ieee754sp r, const char *op, ...) ax.rv.sp = r; va_start(ax.ap, op); ieee754_xcpt(&ax); + va_end(ax.ap); return ax.rv.sp; } @@ -84,6 +85,7 @@ ieee754sp ieee754sp_nanxcpt(ieee754sp r, const char *op, ...) ax.rv.sp = r; va_start(ax.ap, op); ieee754_xcpt(&ax); + va_end(ax.ap); return ax.rv.sp; } diff --git a/arch/mips/mips-boards/generic/time.c b/arch/mips/mips-boards/generic/time.c index 9d6243a8c15..f02ce6308e5 100644 --- a/arch/mips/mips-boards/generic/time.c +++ b/arch/mips/mips-boards/generic/time.c @@ -127,26 +127,6 @@ unsigned long read_persistent_clock(void) return mc146818_get_cmos_time(); } -void __init plat_time_init(void) -{ - unsigned int est_freq; - - /* 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; - - mips_scroll_message(); -#ifdef CONFIG_I8253 /* Only Malta has a PIT */ - setup_pit_timer(); -#endif -} - void __init plat_perf_setup(void) { cp0_perfcount_irq = -1; @@ -166,14 +146,13 @@ void __init plat_perf_setup(void) } } -void __init plat_timer_setup(struct irqaction *irq) +unsigned int __init get_c0_compare_int(void) { #ifdef MSC01E_INT_BASE if (cpu_has_veic) { set_vi_handler(MSC01E_INT_CPUCTR, mips_timer_dispatch); mips_cpu_timer_irq = MSC01E_INT_BASE + MSC01E_INT_CPUCTR; - } - else + } else #endif { if (cpu_has_vint) @@ -181,13 +160,26 @@ void __init plat_timer_setup(struct irqaction *irq) mips_cpu_timer_irq = MIPS_CPU_IRQ_BASE + cp0_compare_irq; } -#ifdef CONFIG_MIPS_MT_SMTC - setup_irq_smtc(mips_cpu_timer_irq, irq, 0x100 << cp0_compare_irq); -#else - setup_irq(mips_cpu_timer_irq, irq); -#endif /* CONFIG_MIPS_MT_SMTC */ -#ifdef CONFIG_SMP - set_irq_handler(mips_cpu_timer_irq, handle_percpu_irq); + return mips_cpu_timer_irq; +} + +void __init plat_time_init(void) +{ + unsigned int est_freq; + + /* 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; + + mips_scroll_message(); +#ifdef CONFIG_I8253 /* Only Malta has a PIT */ + setup_pit_timer(); #endif plat_perf_setup(); diff --git a/arch/mips/mipssim/sim_time.c b/arch/mips/mipssim/sim_time.c index e7fa0d1078a..e39bbe989da 100644 --- a/arch/mips/mipssim/sim_time.c +++ b/arch/mips/mipssim/sim_time.c @@ -75,25 +75,6 @@ static unsigned int __init estimate_cpu_frequency(void) return count; } -void __init plat_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) @@ -102,26 +83,33 @@ static void mips_timer_dispatch(void) } -void __init plat_timer_setup(struct irqaction *irq) +unsigned __init get_c0_compare_int(void) { +#ifdef MSC01E_INT_BASE if (cpu_has_veic) { set_vi_handler(MSC01E_INT_CPUCTR, mips_timer_dispatch); mips_cpu_timer_irq = MSC01E_INT_BASE + MSC01E_INT_CPUCTR; } else { +#endif 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 */ - setup_irq(mips_cpu_timer_irq, irq); + return mips_cpu_timer_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 +void __init plat_time_init(void) +{ + unsigned int est_freq; + + /* 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; } diff --git a/arch/mips/mm/c-r3k.c b/arch/mips/mm/c-r3k.c index c55312f6fd3..562abb77d1d 100644 --- a/arch/mips/mm/c-r3k.c +++ b/arch/mips/mm/c-r3k.c @@ -7,7 +7,7 @@ * Tx39XX R4k style caches added. HK * Copyright (C) 1998, 1999, 2000 Harald Koerfgen * Copyright (C) 1998 Gleb Raiko & Vladimir Roganov - * Copyright (C) 2001, 2004 Maciej W. Rozycki + * Copyright (C) 2001, 2004, 2007 Maciej W. Rozycki */ #include <linux/init.h> #include <linux/kernel.h> @@ -26,8 +26,6 @@ static unsigned long icache_size, dcache_size; /* Size in bytes */ static unsigned long icache_lsize, dcache_lsize; /* Size in bytes */ -#undef DEBUG_CACHE - unsigned long __init r3k_cache_size(unsigned long ca_flags) { unsigned long flags, status, dummy, size; @@ -217,26 +215,6 @@ static void r3k_flush_dcache_range(unsigned long start, unsigned long end) write_c0_status(flags); } -static inline unsigned long get_phys_page(unsigned long addr, - struct mm_struct *mm) -{ - pgd_t *pgd; - pud_t *pud; - pmd_t *pmd; - pte_t *pte; - unsigned long physpage; - - pgd = pgd_offset(mm, addr); - pud = pud_offset(pgd, addr); - pmd = pmd_offset(pud, addr); - pte = pte_offset(pmd, addr); - - if ((physpage = pte_val(*pte)) & _PAGE_VALID) - return KSEG0ADDR(physpage & PAGE_MASK); - - return 0; -} - static inline void r3k_flush_cache_all(void) { } @@ -252,12 +230,40 @@ static void r3k_flush_cache_mm(struct mm_struct *mm) } static void r3k_flush_cache_range(struct vm_area_struct *vma, - unsigned long start, unsigned long end) + unsigned long start, unsigned long end) { } -static void r3k_flush_cache_page(struct vm_area_struct *vma, unsigned long page, unsigned long pfn) +static void r3k_flush_cache_page(struct vm_area_struct *vma, + unsigned long addr, unsigned long pfn) { + unsigned long kaddr = KSEG0ADDR(pfn << PAGE_SHIFT); + int exec = vma->vm_flags & VM_EXEC; + struct mm_struct *mm = vma->vm_mm; + pgd_t *pgdp; + pud_t *pudp; + pmd_t *pmdp; + pte_t *ptep; + + pr_debug("cpage[%08lx,%08lx]\n", + cpu_context(smp_processor_id(), mm), addr); + + /* No ASID => no such page in the cache. */ + if (cpu_context(smp_processor_id(), mm) == 0) + return; + + pgdp = pgd_offset(mm, addr); + pudp = pud_offset(pgdp, addr); + pmdp = pmd_offset(pudp, addr); + ptep = pte_offset(pmdp, addr); + + /* Invalid => no such page in the cache. */ + if (!(pte_val(*ptep) & _PAGE_PRESENT)) + return; + + r3k_flush_dcache_range(kaddr, kaddr + PAGE_SIZE); + if (exec) + r3k_flush_icache_range(kaddr, kaddr + PAGE_SIZE); } static void local_r3k_flush_data_cache_page(void *addr) @@ -272,9 +278,7 @@ static void r3k_flush_cache_sigtramp(unsigned long addr) { unsigned long flags; -#ifdef DEBUG_CACHE - printk("csigtramp[%08lx]", addr); -#endif + pr_debug("csigtramp[%08lx]\n", addr); flags = read_c0_status(); diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c index d7088331fb0..9355f1c9325 100644 --- a/arch/mips/mm/c-r4k.c +++ b/arch/mips/mm/c-r4k.c @@ -7,6 +7,7 @@ * Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Ralf Baechle (ralf@gnu.org) * Copyright (C) 1999, 2000 Silicon Graphics, Inc. */ +#include <linux/hardirq.h> #include <linux/init.h> #include <linux/highmem.h> #include <linux/kernel.h> @@ -345,11 +346,26 @@ static void r4k___flush_cache_all(void) r4k_on_each_cpu(local_r4k___flush_cache_all, NULL, 1, 1); } +static inline int has_valid_asid(const struct mm_struct *mm) +{ +#if defined(CONFIG_MIPS_MT_SMP) || defined(CONFIG_MIPS_MT_SMTC) + int i; + + for_each_online_cpu(i) + if (cpu_context(i, mm)) + return 1; + + return 0; +#else + return cpu_context(smp_processor_id(), mm); +#endif +} + static inline void local_r4k_flush_cache_range(void * args) { struct vm_area_struct *vma = args; - if (!(cpu_context(smp_processor_id(), vma->vm_mm))) + if (!(has_valid_asid(vma->vm_mm))) return; r4k_blast_dcache(); @@ -368,7 +384,7 @@ static inline void local_r4k_flush_cache_mm(void * args) { struct mm_struct *mm = args; - if (!cpu_context(smp_processor_id(), mm)) + if (!has_valid_asid(mm)) return; /* @@ -420,7 +436,7 @@ static inline void local_r4k_flush_cache_page(void *args) * If ownes no valid ASID yet, cannot possibly have gotten * this page into the cache. */ - if (cpu_context(smp_processor_id(), mm) == 0) + if (!has_valid_asid(mm)) return; addr &= PAGE_MASK; @@ -492,7 +508,11 @@ static inline void local_r4k_flush_data_cache_page(void * addr) static void r4k_flush_data_cache_page(unsigned long addr) { - r4k_on_each_cpu(local_r4k_flush_data_cache_page, (void *) addr, 1, 1); + if (in_atomic()) + local_r4k_flush_data_cache_page((void *)addr); + else + r4k_on_each_cpu(local_r4k_flush_data_cache_page, (void *) addr, + 1, 1); } struct flush_icache_range_args { diff --git a/arch/mips/mm/cerr-sb1.c b/arch/mips/mm/cerr-sb1.c index e7f539e3284..1bd1f18ac23 100644 --- a/arch/mips/mm/cerr-sb1.c +++ b/arch/mips/mm/cerr-sb1.c @@ -154,7 +154,7 @@ static void check_bus_watcher(void) if (status & ~(1UL << 31)) { l2_err = csr_in32(IOADDR(A_BUS_L2_ERRORS)); #ifdef DUMP_L2_ECC_TAG_ON_ERROR - l2_tag = in64(IO_SPACE_BASE | A_L2_ECC_TAG); + l2_tag = in64(IOADDR(A_L2_ECC_TAG)); #endif memio_err = csr_in32(IOADDR(A_BUS_MEM_IO_ERRORS)); printk("Bus watcher error counters: %08x %08x\n", l2_err, memio_err); @@ -183,9 +183,9 @@ asmlinkage void sb1_cache_error(void) #ifdef CONFIG_SIBYTE_BW_TRACE /* Freeze the trace buffer now */ #if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80) - csr_out32(M_BCM1480_SCD_TRACE_CFG_FREEZE, IO_SPACE_BASE | A_SCD_TRACE_CFG); + csr_out32(M_BCM1480_SCD_TRACE_CFG_FREEZE, IOADDR(A_SCD_TRACE_CFG)); #else - csr_out32(M_SCD_TRACE_CFG_FREEZE, IO_SPACE_BASE | A_SCD_TRACE_CFG); + csr_out32(M_SCD_TRACE_CFG_FREEZE, IOADDR(A_SCD_TRACE_CFG)); #endif printk("Trace buffer frozen\n"); #endif diff --git a/arch/mips/mm/dma-default.c b/arch/mips/mm/dma-default.c index b1b40527658..ae76795685c 100644 --- a/arch/mips/mm/dma-default.c +++ b/arch/mips/mm/dma-default.c @@ -12,8 +12,8 @@ #include <linux/dma-mapping.h> #include <linux/mm.h> #include <linux/module.h> -#include <linux/string.h> #include <linux/scatterlist.h> +#include <linux/string.h> #include <asm/cache.h> #include <asm/io.h> @@ -40,16 +40,38 @@ static inline int cpu_is_noncoherent_r10000(struct device *dev) current_cpu_type() == CPU_R12000); } +static gfp_t massage_gfp_flags(const struct device *dev, gfp_t gfp) +{ + /* ignore region specifiers */ + gfp &= ~(__GFP_DMA | __GFP_DMA32 | __GFP_HIGHMEM); + +#ifdef CONFIG_ZONE_DMA32 + if (dev == NULL) + gfp |= __GFP_DMA; + else if (dev->coherent_dma_mask < DMA_BIT_MASK(24)) + gfp |= __GFP_DMA; + else +#endif +#ifdef CONFIG_ZONE_DMA32 + if (dev->coherent_dma_mask < DMA_BIT_MASK(32)) + gfp |= __GFP_DMA32; + else +#endif + ; + + /* Don't invoke OOM killer */ + gfp |= __GFP_NORETRY; + + return gfp; +} + void *dma_alloc_noncoherent(struct device *dev, size_t size, dma_addr_t * dma_handle, gfp_t gfp) { void *ret; - /* ignore region specifiers */ - gfp &= ~(__GFP_DMA | __GFP_HIGHMEM); + gfp = massage_gfp_flags(dev, gfp); - if (dev == NULL || (dev->coherent_dma_mask < 0xffffffff)) - gfp |= GFP_DMA; ret = (void *) __get_free_pages(gfp, get_order(size)); if (ret != NULL) { @@ -67,11 +89,8 @@ void *dma_alloc_coherent(struct device *dev, size_t size, { void *ret; - /* ignore region specifiers */ - gfp &= ~(__GFP_DMA | __GFP_HIGHMEM); + gfp = massage_gfp_flags(dev, gfp); - if (dev == NULL || (dev->coherent_dma_mask < 0xffffffff)) - gfp |= GFP_DMA; ret = (void *) __get_free_pages(gfp, get_order(size)); if (ret) { @@ -343,7 +362,7 @@ int dma_supported(struct device *dev, u64 mask) * so we can't guarantee allocations that must be * within a tighter range than GFP_DMA.. */ - if (mask < 0x00ffffff) + if (mask < DMA_BIT_MASK(24)) return 0; return 1; diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c index 110ee7656b4..480dec04f55 100644 --- a/arch/mips/mm/init.c +++ b/arch/mips/mm/init.c @@ -347,11 +347,8 @@ static int __init page_is_ram(unsigned long pagenr) void __init paging_init(void) { - unsigned long zones_size[MAX_NR_ZONES] = { 0, }; -#ifndef CONFIG_FLATMEM - unsigned long zholes_size[MAX_NR_ZONES] = { 0, }; - unsigned long i, j, pfn; -#endif + unsigned long max_zone_pfns[MAX_NR_ZONES]; + unsigned long lastpfn; pagetable_init(); @@ -361,35 +358,27 @@ void __init paging_init(void) kmap_coherent_init(); #ifdef CONFIG_ZONE_DMA - if (min_low_pfn < MAX_DMA_PFN && MAX_DMA_PFN <= max_low_pfn) { - zones_size[ZONE_DMA] = MAX_DMA_PFN - min_low_pfn; - zones_size[ZONE_NORMAL] = max_low_pfn - MAX_DMA_PFN; - } else if (max_low_pfn < MAX_DMA_PFN) - zones_size[ZONE_DMA] = max_low_pfn - min_low_pfn; - else + max_zone_pfns[ZONE_DMA] = MAX_DMA_PFN; #endif - zones_size[ZONE_NORMAL] = max_low_pfn - min_low_pfn; - +#ifdef CONFIG_ZONE_DMA32 + max_zone_pfns[ZONE_DMA32] = MAX_DMA32_PFN; +#endif + max_zone_pfns[ZONE_NORMAL] = max_low_pfn; + lastpfn = max_low_pfn; #ifdef CONFIG_HIGHMEM - zones_size[ZONE_HIGHMEM] = highend_pfn - highstart_pfn; + max_zone_pfns[ZONE_HIGHMEM] = highend_pfn; + lastpfn = highend_pfn; - if (cpu_has_dc_aliases && zones_size[ZONE_HIGHMEM]) { + if (cpu_has_dc_aliases && max_low_pfn != highend_pfn) { printk(KERN_WARNING "This processor doesn't support highmem." - " %ldk highmem ignored\n", zones_size[ZONE_HIGHMEM]); - zones_size[ZONE_HIGHMEM] = 0; + " %ldk highmem ignored\n", + (highend_pfn - max_low_pfn) << (PAGE_SHIFT - 10)); + max_zone_pfns[ZONE_HIGHMEM] = max_low_pfn; + lastpfn = max_low_pfn; } #endif -#ifdef CONFIG_FLATMEM - free_area_init(zones_size); -#else - pfn = min_low_pfn; - for (i = 0; i < MAX_NR_ZONES; i++) - for (j = 0; j < zones_size[i]; j++, pfn++) - if (!page_is_ram(pfn)) - zholes_size[i]++; - free_area_init_node(0, NODE_DATA(0), zones_size, 0, zholes_size); -#endif + free_area_init_nodes(max_zone_pfns); } static struct kcore_list kcore_mem, kcore_vmalloc; @@ -426,7 +415,7 @@ void __init mem_init(void) #ifdef CONFIG_HIGHMEM for (tmp = highstart_pfn; tmp < highend_pfn; tmp++) { - struct page *page = mem_map + tmp; + struct page *page = pfn_to_page(tmp); if (!page_is_ram(tmp)) { SetPageReserved(page); diff --git a/arch/mips/pci/fixup-pmcmsp.c b/arch/mips/pci/fixup-pmcmsp.c index 00261211dbf..65735b1b766 100644 --- a/arch/mips/pci/fixup-pmcmsp.c +++ b/arch/mips/pci/fixup-pmcmsp.c @@ -202,7 +202,7 @@ int pcibios_plat_dev_init(struct pci_dev *dev) * RETURNS: IRQ number * ****************************************************************************/ -int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) +int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) { #if !defined(CONFIG_PMC_MSP7120_GW) && !defined(CONFIG_PMC_MSP7120_EVAL) printk(KERN_WARNING "PCI: unknown board, no PCI IRQs assigned.\n"); diff --git a/arch/mips/pci/fixup-sni.c b/arch/mips/pci/fixup-sni.c index a45bedd1723..5c8a79bb266 100644 --- a/arch/mips/pci/fixup-sni.c +++ b/arch/mips/pci/fixup-sni.c @@ -113,6 +113,16 @@ static char irq_tab_pcit[13][5] __initdata = { { 0, INTA, INTB, INTC, INTD }, /* Slot 5 */ }; +static char irq_tab_pcit_cplus[13][5] __initdata = { + /* INTA INTB INTC INTD */ + { 0, 0, 0, 0, 0 }, /* HOST bridge */ + { 0, INTB, INTC, INTD, INTA }, /* PCI Slot 9 */ + { 0, 0, 0, 0, 0 }, /* PCI-EISA */ + { 0, 0, 0, 0, 0 }, /* Unused */ + { 0, INTA, INTB, INTC, INTD }, /* PCI-PCI bridge */ + { 0, INTB, INTC, INTD, INTA }, /* fixup */ +}; + static inline int is_rm300_revd(void) { unsigned char csmsr = *(volatile unsigned char *)PCIMT_CSMSR; @@ -123,8 +133,19 @@ static inline int is_rm300_revd(void) int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) { switch (sni_brd_type) { - case SNI_BRD_PCI_TOWER: case SNI_BRD_PCI_TOWER_CPLUS: + if (slot == 4) { + /* + * SNI messed up interrupt wiring for onboard + * PCI bus 1; we need to fix this up here + */ + while (dev && dev->bus->number != 1) + dev = dev->bus->self; + if (dev && dev->devfn >= PCI_DEVFN(4, 0)) + slot = 5; + } + return irq_tab_pcit_cplus[slot][pin]; + case SNI_BRD_PCI_TOWER: return irq_tab_pcit[slot][pin]; case SNI_BRD_PCI_MTOWER: diff --git a/arch/mips/pci/fixup-tb0219.c b/arch/mips/pci/fixup-tb0219.c index 720a2b720c5..ed87733f679 100644 --- a/arch/mips/pci/fixup-tb0219.c +++ b/arch/mips/pci/fixup-tb0219.c @@ -2,7 +2,7 @@ * fixup-tb0219.c, The TANBAC TB0219 specific PCI fixups. * * Copyright (C) 2003 Megasolution Inc. <matsu@megasolution.jp> - * Copyright (C) 2004 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * Copyright (C) 2004-2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/arch/mips/pci/ops-pmcmsp.c b/arch/mips/pci/ops-pmcmsp.c index 059eade96f2..109c95ca698 100644 --- a/arch/mips/pci/ops-pmcmsp.c +++ b/arch/mips/pci/ops-pmcmsp.c @@ -404,7 +404,7 @@ int msp_pcibios_config_access(unsigned char access_type, if (pciirqflag == 0) { request_irq(MSP_INT_PCI,/* Hardcoded internal MSP7120 wiring */ bpci_interrupt, - SA_SHIRQ | SA_INTERRUPT, + IRQF_SHARED | IRQF_DISABLED, "PMC MSP PCI Host", preg); pciirqflag = ~0; diff --git a/arch/mips/pci/pci-lasat.c b/arch/mips/pci/pci-lasat.c index 174f314933b..e70ae3236e0 100644 --- a/arch/mips/pci/pci-lasat.c +++ b/arch/mips/pci/pci-lasat.c @@ -5,12 +5,14 @@ * * Copyright (C) 2000, 2001, 04 Keith M Wesolowski */ -#include <linux/kernel.h> #include <linux/init.h> +#include <linux/kernel.h> #include <linux/pci.h> #include <linux/types.h> + #include <asm/bootinfo.h> -#include <asm/lasat/lasatint.h> + +#include <irq.h> extern struct pci_ops nile4_pci_ops; extern struct pci_ops gt64xxx_pci0_ops; @@ -55,15 +57,15 @@ static int __init lasat_pci_setup(void) arch_initcall(lasat_pci_setup); -#define LASATINT_ETH1 (LASATINT_BASE + 0) -#define LASATINT_ETH0 (LASATINT_BASE + 1) -#define LASATINT_HDC (LASATINT_BASE + 2) -#define LASATINT_COMP (LASATINT_BASE + 3) -#define LASATINT_HDLC (LASATINT_BASE + 4) -#define LASATINT_PCIA (LASATINT_BASE + 5) -#define LASATINT_PCIB (LASATINT_BASE + 6) -#define LASATINT_PCIC (LASATINT_BASE + 7) -#define LASATINT_PCID (LASATINT_BASE + 8) +#define LASAT_IRQ_ETH1 (LASAT_IRQ_BASE + 0) +#define LASAT_IRQ_ETH0 (LASAT_IRQ_BASE + 1) +#define LASAT_IRQ_HDC (LASAT_IRQ_BASE + 2) +#define LASAT_IRQ_COMP (LASAT_IRQ_BASE + 3) +#define LASAT_IRQ_HDLC (LASAT_IRQ_BASE + 4) +#define LASAT_IRQ_PCIA (LASAT_IRQ_BASE + 5) +#define LASAT_IRQ_PCIB (LASAT_IRQ_BASE + 6) +#define LASAT_IRQ_PCIC (LASAT_IRQ_BASE + 7) +#define LASAT_IRQ_PCID (LASAT_IRQ_BASE + 8) int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) { @@ -71,13 +73,13 @@ int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) case 1: case 2: case 3: - return LASATINT_PCIA + (((slot-1) + (pin-1)) % 4); + return LASAT_IRQ_PCIA + (((slot-1) + (pin-1)) % 4); case 4: - return LASATINT_ETH1; /* Ethernet 1 (LAN 2) */ + return LASAT_IRQ_ETH1; /* Ethernet 1 (LAN 2) */ case 5: - return LASATINT_ETH0; /* Ethernet 0 (LAN 1) */ + return LASAT_IRQ_ETH0; /* Ethernet 0 (LAN 1) */ case 6: - return LASATINT_HDC; /* IDE controller */ + return LASAT_IRQ_HDC; /* IDE controller */ default: return 0xff; /* Illegal */ } diff --git a/arch/mips/pci/pci-vr41xx.c b/arch/mips/pci/pci-vr41xx.c index 240df9e3381..33c4f683d06 100644 --- a/arch/mips/pci/pci-vr41xx.c +++ b/arch/mips/pci/pci-vr41xx.c @@ -154,6 +154,7 @@ static int __init vr41xx_pciu_init(void) pciu_write(PCICLKSELREG, QUARTER_VTCLOCK); else { printk(KERN_ERR "PCI Clock is over 33MHz.\n"); + iounmap(pciu_base); return -EINVAL; } diff --git a/arch/mips/pmc-sierra/Kconfig b/arch/mips/pmc-sierra/Kconfig index 6b293ce0935..90261b83db0 100644 --- a/arch/mips/pmc-sierra/Kconfig +++ b/arch/mips/pmc-sierra/Kconfig @@ -5,12 +5,14 @@ choice config PMC_MSP4200_EVAL bool "PMC-Sierra MSP4200 Eval Board" select CEVT_R4K + select CSRC_R4K select IRQ_MSP_SLP select HW_HAS_PCI config PMC_MSP4200_GW bool "PMC-Sierra MSP4200 VoIP Gateway" select CEVT_R4K + select CSRC_R4K select IRQ_MSP_SLP select HW_HAS_PCI diff --git a/arch/mips/pmc-sierra/msp71xx/msp_serial.c b/arch/mips/pmc-sierra/msp71xx/msp_serial.c index 15e7b8000b4..9de34302e5f 100644 --- a/arch/mips/pmc-sierra/msp71xx/msp_serial.c +++ b/arch/mips/pmc-sierra/msp71xx/msp_serial.c @@ -122,7 +122,7 @@ void __init msp_serial_setup(void) up.uartclk = uartclk; up.regshift = 2; up.iotype = UPIO_DWAPB; /* UPIO_MEM like */ - up.flags = STD_COM_FLAGS; + up.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST; up.type = PORT_16550A; up.line = 0; up.private_data = (void*)UART0_STATUS_REG; diff --git a/arch/mips/qemu/Makefile b/arch/mips/qemu/Makefile index cec24c117f6..2ba4ef34b4a 100644 --- a/arch/mips/qemu/Makefile +++ b/arch/mips/qemu/Makefile @@ -4,6 +4,7 @@ obj-y = q-firmware.o q-irq.o q-mem.o q-setup.o q-reset.o -obj-$(CONFIG_SMP) += q-smp.o +obj-$(CONFIG_EARLY_PRINTK) += q-console.o +obj-$(CONFIG_SMP) += q-smp.o EXTRA_CFLAGS += -Werror diff --git a/arch/mips/qemu/q-console.c b/arch/mips/qemu/q-console.c new file mode 100644 index 00000000000..81101ae5017 --- /dev/null +++ b/arch/mips/qemu/q-console.c @@ -0,0 +1,26 @@ +#include <linux/console.h> +#include <linux/init.h> +#include <linux/serial_reg.h> +#include <asm/io.h> + +#define PORT(offset) (0x3f8 + (offset)) + +static inline unsigned int serial_in(int offset) +{ + return inb(PORT(offset)); +} + +static inline void serial_out(int offset, int value) +{ + outb(value, PORT(offset)); +} + +int prom_putchar(char c) +{ + while ((serial_in(UART_LSR) & UART_LSR_THRE) == 0) + ; + + serial_out(UART_TX, c); + + return 1; +} diff --git a/arch/mips/qemu/q-firmware.c b/arch/mips/qemu/q-firmware.c index c2239b41758..3ed43f416cd 100644 --- a/arch/mips/qemu/q-firmware.c +++ b/arch/mips/qemu/q-firmware.c @@ -2,6 +2,9 @@ #include <linux/string.h> #include <asm/addrspace.h> #include <asm/bootinfo.h> +#include <asm/io.h> + +#define QEMU_PORT_BASE 0xb4000000 void __init prom_init(void) { @@ -15,4 +18,7 @@ void __init prom_init(void) } else { add_memory_region(0x0<<20, 0x10<<20, BOOT_MEM_RAM); } + + + set_io_port_base(QEMU_PORT_BASE); } diff --git a/arch/mips/qemu/q-irq.c b/arch/mips/qemu/q-irq.c index 4681757460a..11f98476788 100644 --- a/arch/mips/qemu/q-irq.c +++ b/arch/mips/qemu/q-irq.c @@ -1,4 +1,5 @@ #include <linux/init.h> +#include <linux/interrupt.h> #include <linux/linkage.h> #include <asm/i8259.h> diff --git a/arch/mips/qemu/q-setup.c b/arch/mips/qemu/q-setup.c index 23d34c1917c..969cedc8d8b 100644 --- a/arch/mips/qemu/q-setup.c +++ b/arch/mips/qemu/q-setup.c @@ -6,8 +6,6 @@ extern void qemu_reboot_setup(void); -#define QEMU_PORT_BASE 0xb4000000 - const char *get_system_type(void) { return "Qemu"; @@ -20,6 +18,5 @@ void __init plat_time_init(void) void __init plat_mem_setup(void) { - set_io_port_base(QEMU_PORT_BASE); qemu_reboot_setup(); } diff --git a/arch/mips/sgi-ip22/ip22-eisa.c b/arch/mips/sgi-ip22/ip22-eisa.c index 26854fb11e7..1617241d273 100644 --- a/arch/mips/sgi-ip22/ip22-eisa.c +++ b/arch/mips/sgi-ip22/ip22-eisa.c @@ -36,6 +36,7 @@ #include <asm/sgi/ioc.h> #include <asm/sgi/mc.h> #include <asm/sgi/ip22.h> +#include <asm/i8259.h> /* I2 has four EISA slots. */ #define IP22_EISA_MAX_SLOTS 4 @@ -93,126 +94,11 @@ static irqreturn_t ip22_eisa_intr(int irq, void *dev_id) return IRQ_NONE; } -static void enable_eisa1_irq(unsigned int irq) -{ - u8 mask; - - mask = inb(EISA_INT1_MASK); - mask &= ~((u8) (1 << irq)); - outb(mask, EISA_INT1_MASK); -} - -static unsigned int startup_eisa1_irq(unsigned int irq) -{ - u8 edge; - - /* Only use edge interrupts for EISA */ - - edge = inb(EISA_INT1_EDGE_LEVEL); - edge &= ~((u8) (1 << irq)); - outb(edge, EISA_INT1_EDGE_LEVEL); - - enable_eisa1_irq(irq); - return 0; -} - -static void disable_eisa1_irq(unsigned int irq) -{ - u8 mask; - - mask = inb(EISA_INT1_MASK); - mask |= ((u8) (1 << irq)); - outb(mask, EISA_INT1_MASK); -} - -static void mask_and_ack_eisa1_irq(unsigned int irq) -{ - disable_eisa1_irq(irq); - - outb(0x20, EISA_INT1_CTRL); -} - -static void end_eisa1_irq(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) - enable_eisa1_irq(irq); -} - -static struct irq_chip ip22_eisa1_irq_type = { - .name = "IP22 EISA", - .startup = startup_eisa1_irq, - .ack = mask_and_ack_eisa1_irq, - .mask = disable_eisa1_irq, - .mask_ack = mask_and_ack_eisa1_irq, - .unmask = enable_eisa1_irq, - .end = end_eisa1_irq, -}; - -static void enable_eisa2_irq(unsigned int irq) -{ - u8 mask; - - mask = inb(EISA_INT2_MASK); - mask &= ~((u8) (1 << (irq - 8))); - outb(mask, EISA_INT2_MASK); -} - -static unsigned int startup_eisa2_irq(unsigned int irq) -{ - u8 edge; - - /* Only use edge interrupts for EISA */ - - edge = inb(EISA_INT2_EDGE_LEVEL); - edge &= ~((u8) (1 << (irq - 8))); - outb(edge, EISA_INT2_EDGE_LEVEL); - - enable_eisa2_irq(irq); - return 0; -} - -static void disable_eisa2_irq(unsigned int irq) -{ - u8 mask; - - mask = inb(EISA_INT2_MASK); - mask |= ((u8) (1 << (irq - 8))); - outb(mask, EISA_INT2_MASK); -} - -static void mask_and_ack_eisa2_irq(unsigned int irq) -{ - disable_eisa2_irq(irq); - - outb(0x20, EISA_INT2_CTRL); -} - -static void end_eisa2_irq(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) - enable_eisa2_irq(irq); -} - -static struct irq_chip ip22_eisa2_irq_type = { - .name = "IP22 EISA", - .startup = startup_eisa2_irq, - .ack = mask_and_ack_eisa2_irq, - .mask = disable_eisa2_irq, - .mask_ack = mask_and_ack_eisa2_irq, - .unmask = enable_eisa2_irq, - .end = end_eisa2_irq, -}; - static struct irqaction eisa_action = { .handler = ip22_eisa_intr, .name = "EISA", }; -static struct irqaction cascade_action = { - .handler = no_action, - .name = "EISA cascade", -}; - int __init ip22_eisa_init(void) { int i, c; @@ -248,29 +134,13 @@ int __init ip22_eisa_init(void) outb(1, EISA_EXT_NMI_RESET_CTRL); udelay(50); /* Wait long enough for the dust to settle */ outb(0, EISA_EXT_NMI_RESET_CTRL); - outb(0x11, EISA_INT1_CTRL); - outb(0x11, EISA_INT2_CTRL); - outb(0, EISA_INT1_MASK); - outb(8, EISA_INT2_MASK); - outb(4, EISA_INT1_MASK); - outb(2, EISA_INT2_MASK); - outb(1, EISA_INT1_MASK); - outb(1, EISA_INT2_MASK); - outb(0xfb, EISA_INT1_MASK); - outb(0xff, EISA_INT2_MASK); outb(0, EISA_DMA2_WRITE_SINGLE); - for (i = SGINT_EISA; i < (SGINT_EISA + EISA_MAX_IRQ); i++) { - if (i < (SGINT_EISA + 8)) - set_irq_chip(i, &ip22_eisa1_irq_type); - else - set_irq_chip(i, &ip22_eisa2_irq_type); - } + init_i8259_irqs(); /* Cannot use request_irq because of kmalloc not being ready at such * an early stage. Yes, I've been bitten... */ setup_irq(SGI_EISA_IRQ, &eisa_action); - setup_irq(SGINT_EISA + 2, &cascade_action); EISA_bus = 1; return 0; diff --git a/arch/mips/sgi-ip22/ip22-nvram.c b/arch/mips/sgi-ip22/ip22-nvram.c index e19d60d5fcc..0177566475d 100644 --- a/arch/mips/sgi-ip22/ip22-nvram.c +++ b/arch/mips/sgi-ip22/ip22-nvram.c @@ -32,19 +32,19 @@ for (x=0; x<100000; x++) __asm__ __volatile__(""); }) #define eeprom_cs_on(ptr) ({ \ - *ptr &= ~EEPROM_DATO; \ - *ptr &= ~EEPROM_ECLK; \ - *ptr &= ~EEPROM_EPROT; \ - delay(); \ - *ptr |= EEPROM_CSEL; \ - *ptr |= EEPROM_ECLK; }) + __raw_writel(__raw_readl(ptr) & ~EEPROM_DATO, ptr); \ + __raw_writel(__raw_readl(ptr) & ~EEPROM_ECLK, ptr); \ + __raw_writel(__raw_readl(ptr) & ~EEPROM_EPROT, ptr); \ + delay(); \ + __raw_writel(__raw_readl(ptr) | EEPROM_CSEL, ptr); \ + __raw_writel(__raw_readl(ptr) | EEPROM_ECLK, ptr); }) #define eeprom_cs_off(ptr) ({ \ - *ptr &= ~EEPROM_ECLK; \ - *ptr &= ~EEPROM_CSEL; \ - *ptr |= EEPROM_EPROT; \ - *ptr |= EEPROM_ECLK; }) + __raw_writel(__raw_readl(ptr) & ~EEPROM_ECLK, ptr); \ + __raw_writel(__raw_readl(ptr) & ~EEPROM_CSEL, ptr); \ + __raw_writel(__raw_readl(ptr) | EEPROM_EPROT, ptr); \ + __raw_writel(__raw_readl(ptr) | EEPROM_ECLK, ptr); }) #define BITS_IN_COMMAND 11 /* @@ -60,15 +60,17 @@ static inline void eeprom_cmd(unsigned int *ctrl, unsigned cmd, unsigned reg) ser_cmd = cmd | (reg << (16 - BITS_IN_COMMAND)); for (i = 0; i < BITS_IN_COMMAND; i++) { if (ser_cmd & (1<<15)) /* if high order bit set */ - writel(readl(ctrl) | EEPROM_DATO, ctrl); + __raw_writel(__raw_readl(ctrl) | EEPROM_DATO, ctrl); else - writel(readl(ctrl) & ~EEPROM_DATO, ctrl); - writel(readl(ctrl) & ~EEPROM_ECLK, ctrl); - writel(readl(ctrl) | EEPROM_ECLK, ctrl); + __raw_writel(__raw_readl(ctrl) & ~EEPROM_DATO, ctrl); + __raw_writel(__raw_readl(ctrl) & ~EEPROM_ECLK, ctrl); + delay(); + __raw_writel(__raw_readl(ctrl) | EEPROM_ECLK, ctrl); + delay(); ser_cmd <<= 1; } /* see data sheet timing diagram */ - writel(readl(ctrl) & ~EEPROM_DATO, ctrl); + __raw_writel(__raw_readl(ctrl) & ~EEPROM_DATO, ctrl); } unsigned short ip22_eeprom_read(unsigned int *ctrl, int reg) @@ -76,18 +78,18 @@ unsigned short ip22_eeprom_read(unsigned int *ctrl, int reg) unsigned short res = 0; int i; - writel(readl(ctrl) & ~EEPROM_EPROT, ctrl); + __raw_writel(__raw_readl(ctrl) & ~EEPROM_EPROT, ctrl); eeprom_cs_on(ctrl); eeprom_cmd(ctrl, EEPROM_READ, reg); /* clock the data ouf of serial mem */ for (i = 0; i < 16; i++) { - writel(readl(ctrl) & ~EEPROM_ECLK, ctrl); + __raw_writel(__raw_readl(ctrl) & ~EEPROM_ECLK, ctrl); delay(); - writel(readl(ctrl) | EEPROM_ECLK, ctrl); + __raw_writel(__raw_readl(ctrl) | EEPROM_ECLK, ctrl); delay(); res <<= 1; - if (readl(ctrl) & EEPROM_DATI) + if (__raw_readl(ctrl) & EEPROM_DATI) res |= 1; } diff --git a/arch/mips/sgi-ip27/ip27-timer.c b/arch/mips/sgi-ip27/ip27-timer.c index f5dccf01da1..08d45369be4 100644 --- a/arch/mips/sgi-ip27/ip27-timer.c +++ b/arch/mips/sgi-ip27/ip27-timer.c @@ -131,12 +131,12 @@ static struct irq_chip rt_irq_type = { static int rt_next_event(unsigned long delta, struct clock_event_device *evt) { unsigned int cpu = smp_processor_id(); - int slice = cputoslice(cpu) == 0; + int slice = cputoslice(cpu); unsigned long cnt; cnt = LOCAL_HUB_L(PI_RT_COUNT); cnt += delta; - LOCAL_HUB_S(slice ? PI_RT_COMPARE_A : PI_RT_COMPARE_B, cnt); + LOCAL_HUB_S(PI_RT_COMPARE_A + PI_COUNT_OFFSET * slice, cnt); return LOCAL_HUB_L(PI_RT_COUNT) >= cnt ? -ETIME : 0; } @@ -164,9 +164,12 @@ static irqreturn_t hub_rt_counter_handler(int irq, void *dev_id) { struct clock_event_device *cd = dev_id; unsigned int cpu = smp_processor_id(); - int slice = cputoslice(cpu) == 0; + int slice = cputoslice(cpu); - LOCAL_HUB_S(slice ? PI_RT_PEND_A : PI_RT_PEND_B, 0); /* Ack */ + /* + * Ack + */ + LOCAL_HUB_S(PI_RT_PEND_A + PI_COUNT_OFFSET * slice, 0); cd->event_handler(cd); return IRQ_HANDLED; diff --git a/arch/mips/sgi-ip32/ip32-irq.c b/arch/mips/sgi-ip32/ip32-irq.c index 7e8094f617b..cab7cc22ab6 100644 --- a/arch/mips/sgi-ip32/ip32-irq.c +++ b/arch/mips/sgi-ip32/ip32-irq.c @@ -40,13 +40,6 @@ static void inline flush_mace_bus(void) mace->perif.ctrl.misc; } -#undef DEBUG_IRQ -#ifdef DEBUG_IRQ -#define DBG(x...) printk(x) -#else -#define DBG(x...) -#endif - /* * O2 irq map * @@ -125,6 +118,7 @@ struct irqaction memerr_irq = { .mask = CPU_MASK_NONE, .name = "CRIME memory error", }; + struct irqaction cpuerr_irq = { .handler = crime_cpuerr_intr, .flags = IRQF_DISABLED, @@ -139,46 +133,70 @@ struct irqaction cpuerr_irq = { static uint64_t crime_mask; -static void enable_crime_irq(unsigned int irq) +static inline void crime_enable_irq(unsigned int irq) { - crime_mask |= 1 << (irq - 1); + unsigned int bit = irq - CRIME_IRQ_BASE; + + crime_mask |= 1 << bit; crime->imask = crime_mask; } -static void disable_crime_irq(unsigned int irq) +static inline void crime_disable_irq(unsigned int irq) { - crime_mask &= ~(1 << (irq - 1)); + unsigned int bit = irq - CRIME_IRQ_BASE; + + crime_mask &= ~(1 << bit); crime->imask = crime_mask; flush_crime_bus(); } -static void mask_and_ack_crime_irq(unsigned int irq) +static void crime_level_mask_and_ack_irq(unsigned int irq) +{ + crime_disable_irq(irq); +} + +static void crime_level_end_irq(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) + crime_enable_irq(irq); +} + +static struct irq_chip crime_level_interrupt = { + .name = "IP32 CRIME", + .ack = crime_level_mask_and_ack_irq, + .mask = crime_disable_irq, + .mask_ack = crime_level_mask_and_ack_irq, + .unmask = crime_enable_irq, + .end = crime_level_end_irq, +}; + +static void crime_edge_mask_and_ack_irq(unsigned int irq) { + unsigned int bit = irq - CRIME_IRQ_BASE; + uint64_t crime_int; + /* Edge triggered interrupts must be cleared. */ - if ((irq >= CRIME_GBE0_IRQ && irq <= CRIME_GBE3_IRQ) - || (irq >= CRIME_RE_EMPTY_E_IRQ && irq <= CRIME_RE_IDLE_E_IRQ) - || (irq >= CRIME_SOFT0_IRQ && irq <= CRIME_SOFT2_IRQ)) { - uint64_t crime_int; - crime_int = crime->hard_int; - crime_int &= ~(1 << (irq - 1)); - crime->hard_int = crime_int; - } - disable_crime_irq(irq); + + crime_int = crime->hard_int; + crime_int &= ~(1 << bit); + crime->hard_int = crime_int; + + crime_disable_irq(irq); } -static void end_crime_irq(unsigned int irq) +static void crime_edge_end_irq(unsigned int irq) { if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) - enable_crime_irq(irq); + crime_enable_irq(irq); } -static struct irq_chip ip32_crime_interrupt = { - .name = "IP32 CRIME", - .ack = mask_and_ack_crime_irq, - .mask = disable_crime_irq, - .mask_ack = mask_and_ack_crime_irq, - .unmask = enable_crime_irq, - .end = end_crime_irq, +static struct irq_chip crime_edge_interrupt = { + .name = "IP32 CRIME", + .ack = crime_edge_mask_and_ack_irq, + .mask = crime_disable_irq, + .mask_ack = crime_edge_mask_and_ack_irq, + .unmask = crime_enable_irq, + .end = crime_edge_end_irq, }; /* @@ -191,18 +209,18 @@ static unsigned long macepci_mask; static void enable_macepci_irq(unsigned int irq) { - macepci_mask |= MACEPCI_CONTROL_INT(irq - 9); + macepci_mask |= MACEPCI_CONTROL_INT(irq - MACEPCI_SCSI0_IRQ); mace->pci.control = macepci_mask; - crime_mask |= 1 << (irq - 1); + crime_mask |= 1 << (irq - CRIME_IRQ_BASE); crime->imask = crime_mask; } static void disable_macepci_irq(unsigned int irq) { - crime_mask &= ~(1 << (irq - 1)); + crime_mask &= ~(1 << (irq - CRIME_IRQ_BASE)); crime->imask = crime_mask; flush_crime_bus(); - macepci_mask &= ~MACEPCI_CONTROL_INT(irq - 9); + macepci_mask &= ~MACEPCI_CONTROL_INT(irq - MACEPCI_SCSI0_IRQ); mace->pci.control = macepci_mask; flush_mace_bus(); } @@ -265,7 +283,7 @@ static void enable_maceisa_irq(unsigned int irq) { unsigned int crime_int = 0; - DBG("maceisa enable: %u\n", irq); + pr_debug("maceisa enable: %u\n", irq); switch (irq) { case MACEISA_AUDIO_SW_IRQ ... MACEISA_AUDIO3_MERR_IRQ: @@ -278,10 +296,10 @@ static void enable_maceisa_irq(unsigned int irq) crime_int = MACE_SUPERIO_INT; break; } - DBG("crime_int %08x enabled\n", crime_int); + pr_debug("crime_int %08x enabled\n", crime_int); crime_mask |= crime_int; crime->imask = crime_mask; - maceisa_mask |= 1 << (irq - 33); + maceisa_mask |= 1 << (irq - MACEISA_AUDIO_SW_IRQ); mace->perif.ctrl.imask = maceisa_mask; } @@ -289,12 +307,12 @@ static void disable_maceisa_irq(unsigned int irq) { unsigned int crime_int = 0; - maceisa_mask &= ~(1 << (irq - 33)); - if(!(maceisa_mask & MACEISA_AUDIO_INT)) + maceisa_mask &= ~(1 << (irq - MACEISA_AUDIO_SW_IRQ)); + if (!(maceisa_mask & MACEISA_AUDIO_INT)) crime_int |= MACE_AUDIO_INT; - if(!(maceisa_mask & MACEISA_MISC_INT)) + if (!(maceisa_mask & MACEISA_MISC_INT)) crime_int |= MACE_MISC_INT; - if(!(maceisa_mask & MACEISA_SUPERIO_INT)) + if (!(maceisa_mask & MACEISA_SUPERIO_INT)) crime_int |= MACE_SUPERIO_INT; crime_mask &= ~crime_int; crime->imask = crime_mask; @@ -313,7 +331,7 @@ static void mask_and_ack_maceisa_irq(unsigned int irq) case MACEISA_SERIAL2_TDMAPR_IRQ: /* edge triggered */ mace_int = mace->perif.ctrl.istat; - mace_int &= ~(1 << (irq - 33)); + mace_int &= ~(1 << (irq - MACEISA_AUDIO_SW_IRQ)); mace->perif.ctrl.istat = mace_int; break; } @@ -327,12 +345,12 @@ static void end_maceisa_irq(unsigned irq) } static struct irq_chip ip32_maceisa_interrupt = { - .name = "IP32 MACE ISA", - .ack = mask_and_ack_maceisa_irq, - .mask = disable_maceisa_irq, - .mask_ack = mask_and_ack_maceisa_irq, - .unmask = enable_maceisa_irq, - .end = end_maceisa_irq, + .name = "IP32 MACE ISA", + .ack = mask_and_ack_maceisa_irq, + .mask = disable_maceisa_irq, + .mask_ack = mask_and_ack_maceisa_irq, + .unmask = enable_maceisa_irq, + .end = end_maceisa_irq, }; /* This is used for regular non-ISA, non-PCI MACE interrupts. That means @@ -341,13 +359,17 @@ static struct irq_chip ip32_maceisa_interrupt = { static void enable_mace_irq(unsigned int irq) { - crime_mask |= 1 << (irq - 1); + unsigned int bit = irq - CRIME_IRQ_BASE; + + crime_mask |= (1 << bit); crime->imask = crime_mask; } static void disable_mace_irq(unsigned int irq) { - crime_mask &= ~(1 << (irq - 1)); + unsigned int bit = irq - CRIME_IRQ_BASE; + + crime_mask &= ~(1 << bit); crime->imask = crime_mask; flush_crime_bus(); } @@ -411,7 +433,7 @@ static void ip32_irq0(void) irq = __ffs(mace_int & maceisa_mask) + MACEISA_AUDIO_SW_IRQ; } - DBG("*irq %u*\n", irq); + pr_debug("*irq %u*\n", irq); do_IRQ(irq); } @@ -471,24 +493,32 @@ void __init arch_init_irq(void) mace->perif.ctrl.imask = 0; mips_cpu_irq_init(); - for (irq = MIPS_CPU_IRQ_BASE + 8; irq <= IP32_IRQ_MAX; irq++) { - struct irq_chip *chip; - + for (irq = CRIME_IRQ_BASE; irq <= IP32_IRQ_MAX; irq++) { switch (irq) { case MACE_VID_IN1_IRQ ... MACE_PCI_BRIDGE_IRQ: - chip = &ip32_mace_interrupt; + set_irq_chip(irq, &ip32_mace_interrupt); break; case MACEPCI_SCSI0_IRQ ... MACEPCI_SHARED2_IRQ: - chip = &ip32_macepci_interrupt; + set_irq_chip(irq, &ip32_macepci_interrupt); + break; + case CRIME_GBE0_IRQ ... CRIME_GBE3_IRQ: + set_irq_chip(irq, &crime_edge_interrupt); + break; + case CRIME_CPUERR_IRQ: + case CRIME_MEMERR_IRQ: + set_irq_chip(irq, &crime_level_interrupt); break; - case CRIME_GBE0_IRQ ... CRIME_VICE_IRQ: - chip = &ip32_crime_interrupt; + case CRIME_RE_EMPTY_E_IRQ ... CRIME_RE_IDLE_E_IRQ: + case CRIME_SOFT0_IRQ ... CRIME_SOFT2_IRQ: + set_irq_chip(irq, &crime_edge_interrupt); + break; + case CRIME_VICE_IRQ: + set_irq_chip(irq, &crime_edge_interrupt); break; default: - chip = &ip32_maceisa_interrupt; + set_irq_chip(irq, &ip32_maceisa_interrupt); + break; } - - set_irq_chip(irq, chip); } setup_irq(CRIME_MEMERR_IRQ, &memerr_irq); setup_irq(CRIME_CPUERR_IRQ, &cpuerr_irq); diff --git a/arch/mips/sgi-ip32/ip32-platform.c b/arch/mips/sgi-ip32/ip32-platform.c index 7309e48d163..77febd68fcd 100644 --- a/arch/mips/sgi-ip32/ip32-platform.c +++ b/arch/mips/sgi-ip32/ip32-platform.c @@ -42,7 +42,7 @@ static struct platform_device uart8250_device = { static int __init uart8250_init(void) { uart8250_data[0].membase = (void __iomem *) &mace->isa.serial1; - uart8250_data[1].membase = (void __iomem *) &mace->isa.serial1; + uart8250_data[1].membase = (void __iomem *) &mace->isa.serial2; return platform_device_register(&uart8250_device); } diff --git a/arch/mips/sibyte/Kconfig b/arch/mips/sibyte/Kconfig index e8fb880272b..366b19d33f7 100644 --- a/arch/mips/sibyte/Kconfig +++ b/arch/mips/sibyte/Kconfig @@ -1,5 +1,7 @@ config SIBYTE_SB1250 bool + select CEVT_SB1250 + select CSRC_SB1250 select HW_HAS_PCI select IRQ_CPU select SIBYTE_ENABLE_LDT_IF_PCI @@ -9,6 +11,8 @@ config SIBYTE_SB1250 config SIBYTE_BCM1120 bool + select CEVT_SB1250 + select CSRC_SB1250 select IRQ_CPU select SIBYTE_BCM112X select SIBYTE_HAS_ZBUS_PROFILING @@ -16,6 +20,8 @@ config SIBYTE_BCM1120 config SIBYTE_BCM1125 bool + select CEVT_SB1250 + select CSRC_SB1250 select HW_HAS_PCI select IRQ_CPU select SIBYTE_BCM112X @@ -24,6 +30,8 @@ config SIBYTE_BCM1125 config SIBYTE_BCM1125H bool + select CEVT_SB1250 + select CSRC_SB1250 select HW_HAS_PCI select IRQ_CPU select SIBYTE_BCM112X @@ -33,12 +41,16 @@ config SIBYTE_BCM1125H config SIBYTE_BCM112X bool + select CEVT_SB1250 + select CSRC_SB1250 select IRQ_CPU select SIBYTE_SB1xxx_SOC select SIBYTE_HAS_ZBUS_PROFILING config SIBYTE_BCM1x80 bool + select CEVT_BCM1480 + select CSRC_BCM1480 select HW_HAS_PCI select IRQ_CPU select SIBYTE_HAS_ZBUS_PROFILING @@ -47,6 +59,8 @@ config SIBYTE_BCM1x80 config SIBYTE_BCM1x55 bool + select CEVT_BCM1480 + select CSRC_BCM1480 select HW_HAS_PCI select IRQ_CPU select SIBYTE_SB1xxx_SOC diff --git a/arch/mips/sibyte/bcm1480/irq.c b/arch/mips/sibyte/bcm1480/irq.c index 10299bafeab..db372a0f106 100644 --- a/arch/mips/sibyte/bcm1480/irq.c +++ b/arch/mips/sibyte/bcm1480/irq.c @@ -265,42 +265,6 @@ void __init init_bcm1480_irqs(void) } } - -static irqreturn_t bcm1480_dummy_handler(int irq, void *dev_id) -{ - return IRQ_NONE; -} - -static struct irqaction bcm1480_dummy_action = { - .handler = bcm1480_dummy_handler, - .flags = 0, - .mask = CPU_MASK_NONE, - .name = "bcm1480-private", - .next = NULL, - .dev_id = 0 -}; - -int bcm1480_steal_irq(int irq) -{ - struct irq_desc *desc = irq_desc + irq; - unsigned long flags; - int retval = 0; - - if (irq >= BCM1480_NR_IRQS) - return -EINVAL; - - spin_lock_irqsave(&desc->lock, flags); - /* Don't allow sharing at all for these */ - if (desc->action != NULL) - retval = -EBUSY; - else { - desc->action = &bcm1480_dummy_action; - desc->depth = 0; - } - spin_unlock_irqrestore(&desc->lock, flags); - return 0; -} - /* * init_IRQ is called early in the boot sequence from init/main.c. It * is responsible for setting up the interrupt mapper and installing the @@ -329,7 +293,6 @@ int bcm1480_steal_irq(int irq) void __init arch_init_irq(void) { - unsigned int i, cpu; u64 tmp; unsigned int imask = STATUSF_IP4 | STATUSF_IP3 | STATUSF_IP2 | @@ -386,8 +349,6 @@ void __init arch_init_irq(void) __raw_writeq(tmp, IOADDR(A_BCM1480_IMR_REGISTER(cpu, R_BCM1480_IMR_INTERRUPT_MASK_L))); } - bcm1480_steal_irq(K_BCM1480_INT_MBOX_0_0); - /* * Note that the timer interrupts are also mapped, but this is * done in bcm1480_time_init(). Also, the profiling driver @@ -409,12 +370,11 @@ void __init arch_init_irq(void) #endif /* Setup uart 1 settings, mapper */ /* QQQ FIXME */ - __raw_writeq(M_DUART_IMR_BRK, IO_SPACE_BASE + A_DUART_IMRREG(kgdb_port)); + __raw_writeq(M_DUART_IMR_BRK, IOADDR(A_DUART_IMRREG(kgdb_port))); - bcm1480_steal_irq(kgdb_irq); __raw_writeq(IMR_IP6_VAL, - IO_SPACE_BASE + A_BCM1480_IMR_REGISTER(0, R_BCM1480_IMR_INTERRUPT_MAP_BASE_H) + - (kgdb_irq<<3)); + IOADDR(A_BCM1480_IMR_REGISTER(0, R_BCM1480_IMR_INTERRUPT_MAP_BASE_H) + + (kgdb_irq << 3))); bcm1480_unmask_irq(0, kgdb_irq); #ifdef CONFIG_GDB_CONSOLE @@ -452,18 +412,6 @@ static void bcm1480_kgdb_interrupt(void) extern void bcm1480_mailbox_interrupt(void); -static inline void dispatch_ip4(void) -{ - int cpu = smp_processor_id(); - int irq = K_BCM1480_INT_TIMER_0 + cpu; - - /* Reset the timer */ - __raw_writeq(M_SCD_TIMER_ENABLE|M_SCD_TIMER_MODE_CONTINUOUS, - IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG))); - - do_IRQ(irq); -} - static inline void dispatch_ip2(void) { unsigned long long mask_h, mask_l; @@ -491,6 +439,7 @@ static inline void dispatch_ip2(void) asmlinkage void plat_irq_dispatch(void) { + unsigned int cpu = smp_processor_id(); unsigned int pending; #ifdef CONFIG_SIBYTE_BCM1480_PROF @@ -507,7 +456,7 @@ asmlinkage void plat_irq_dispatch(void) #endif if (pending & CAUSEF_IP4) - dispatch_ip4(); + do_IRQ(K_BCM1480_INT_TIMER_0 + cpu); #ifdef CONFIG_SMP else if (pending & CAUSEF_IP3) bcm1480_mailbox_interrupt(); diff --git a/arch/mips/sibyte/bcm1480/time.c b/arch/mips/sibyte/bcm1480/time.c index 610f0253954..1680a68952a 100644 --- a/arch/mips/sibyte/bcm1480/time.c +++ b/arch/mips/sibyte/bcm1480/time.c @@ -15,166 +15,10 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include <linux/clockchips.h> -#include <linux/interrupt.h> -#include <linux/irq.h> -#include <linux/percpu.h> -#include <linux/spinlock.h> +#include <linux/init.h> -#include <asm/addrspace.h> -#include <asm/time.h> -#include <asm/io.h> - -#include <asm/sibyte/bcm1480_regs.h> -#include <asm/sibyte/sb1250_regs.h> -#include <asm/sibyte/bcm1480_int.h> -#include <asm/sibyte/bcm1480_scd.h> - -#include <asm/sibyte/sb1250.h> - - -#define IMR_IP2_VAL K_BCM1480_INT_MAP_I0 -#define IMR_IP3_VAL K_BCM1480_INT_MAP_I1 -#define IMR_IP4_VAL K_BCM1480_INT_MAP_I2 - -extern int bcm1480_steal_irq(int irq); - -/* - * The general purpose timer ticks at 1MHz independent if - * the rest of the system - */ -static void sibyte_set_mode(enum clock_event_mode mode, - struct clock_event_device *evt) -{ - unsigned int cpu = smp_processor_id(); - void __iomem *timer_cfg, *timer_init; - - timer_cfg = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)); - timer_init = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT)); - - switch (mode) { - case CLOCK_EVT_MODE_PERIODIC: - __raw_writeq(0, timer_cfg); - __raw_writeq((V_SCD_TIMER_FREQ / HZ) - 1, timer_init); - __raw_writeq(M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS, - timer_cfg); - break; - - case CLOCK_EVT_MODE_ONESHOT: - /* Stop the timer until we actually program a shot */ - case CLOCK_EVT_MODE_SHUTDOWN: - __raw_writeq(0, timer_cfg); - break; - - case CLOCK_EVT_MODE_UNUSED: /* shuddup gcc */ - case CLOCK_EVT_MODE_RESUME: - ; - } -} - -static int sibyte_next_event(unsigned long delta, struct clock_event_device *cd) -{ - unsigned int cpu = smp_processor_id(); - void __iomem *timer_init; - unsigned int cnt; - int res; - - timer_init = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT)); - cnt = __raw_readq(timer_init); - cnt += delta; - __raw_writeq(cnt, timer_init); - res = ((long)(__raw_readq(timer_init) - cnt ) > 0) ? -ETIME : 0; - - return res; -} - -static irqreturn_t sibyte_counter_handler(int irq, void *dev_id) -{ - unsigned int cpu = smp_processor_id(); - struct clock_event_device *cd = dev_id; - void __iomem *timer_cfg; - - timer_cfg = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)); - - /* Reset the timer */ - __raw_writeq(M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS, - timer_cfg); - cd->event_handler(cd); - - return IRQ_HANDLED; -} - -static DEFINE_PER_CPU(struct clock_event_device, sibyte_hpt_clockevent); -static DEFINE_PER_CPU(struct irqaction, sibyte_hpt_irqaction); -static DEFINE_PER_CPU(char [18], sibyte_hpt_name); - -void __cpuinit sb1480_clockevent_init(void) -{ - unsigned int cpu = smp_processor_id(); - unsigned int irq = K_BCM1480_INT_TIMER_0 + cpu; - struct irqaction *action = &per_cpu(sibyte_hpt_irqaction, cpu); - struct clock_event_device *cd = &per_cpu(sibyte_hpt_clockevent, cpu); - unsigned char *name = per_cpu(sibyte_hpt_name, cpu); - - BUG_ON(cpu > 3); /* Only have 4 general purpose timers */ - - sprintf(name, "bcm1480-counter %d", cpu); - cd->name = name; - cd->features = CLOCK_EVT_FEAT_PERIODIC | - CLOCK_EVT_MODE_ONESHOT; - clockevent_set_clock(cd, V_SCD_TIMER_FREQ); - cd->max_delta_ns = clockevent_delta2ns(0x7fffff, cd); - cd->min_delta_ns = clockevent_delta2ns(1, cd); - cd->rating = 200; - cd->irq = irq; - cd->cpumask = cpumask_of_cpu(cpu); - cd->set_next_event = sibyte_next_event; - cd->set_mode = sibyte_set_mode; - clockevents_register_device(cd); - - bcm1480_mask_irq(cpu, irq); - - /* - * Map timer interrupt to IP[4] of this cpu - */ - __raw_writeq(IMR_IP4_VAL, - IOADDR(A_BCM1480_IMR_REGISTER(cpu, - R_BCM1480_IMR_INTERRUPT_MAP_BASE_H) + (irq << 3))); - - bcm1480_unmask_irq(cpu, irq); - bcm1480_steal_irq(irq); - - action->handler = sibyte_counter_handler; - action->flags = IRQF_DISABLED | IRQF_PERCPU; - action->name = name; - action->dev_id = cd; - setup_irq(irq, action); -} - -static cycle_t bcm1480_hpt_read(void) -{ - return (cycle_t) __raw_readq(IOADDR(A_SCD_ZBBUS_CYCLE_COUNT)); -} - -struct clocksource bcm1480_clocksource = { - .name = "zbbus-cycles", - .rating = 200, - .read = bcm1480_hpt_read, - .mask = CLOCKSOURCE_MASK(64), - .flags = CLOCK_SOURCE_IS_CONTINUOUS, -}; - -void __init sb1480_clocksource_init(void) -{ - struct clocksource *cs = &bcm1480_clocksource; - unsigned int plldiv; - unsigned long zbbus; - - plldiv = G_BCM1480_SYS_PLL_DIV(__raw_readq(IOADDR(A_SCD_SYSTEM_CFG))); - zbbus = ((plldiv >> 1) * 50000000) + ((plldiv & 1) * 25000000); - clocksource_set_clock(cs, zbbus); - clocksource_register(cs); -} +extern void sb1480_clockevent_init(void); +extern void sb1480_clocksource_init(void); void __init plat_time_init(void) { diff --git a/arch/mips/sibyte/sb1250/irq.c b/arch/mips/sibyte/sb1250/irq.c index 53780a179d1..eac9065ffe0 100644 --- a/arch/mips/sibyte/sb1250/irq.c +++ b/arch/mips/sibyte/sb1250/irq.c @@ -236,41 +236,6 @@ void __init init_sb1250_irqs(void) } -static irqreturn_t sb1250_dummy_handler(int irq, void *dev_id) -{ - return IRQ_NONE; -} - -static struct irqaction sb1250_dummy_action = { - .handler = sb1250_dummy_handler, - .flags = 0, - .mask = CPU_MASK_NONE, - .name = "sb1250-private", - .next = NULL, - .dev_id = 0 -}; - -int sb1250_steal_irq(int irq) -{ - struct irq_desc *desc = irq_desc + irq; - unsigned long flags; - int retval = 0; - - if (irq >= SB1250_NR_IRQS) - return -EINVAL; - - spin_lock_irqsave(&desc->lock, flags); - /* Don't allow sharing at all for these */ - if (desc->action != NULL) - retval = -EBUSY; - else { - desc->action = &sb1250_dummy_action; - desc->depth = 0; - } - spin_unlock_irqrestore(&desc->lock, flags); - return 0; -} - /* * arch_init_irq is called early in the boot sequence from init/main.c via * init_IRQ. It is responsible for setting up the interrupt mapper and @@ -342,8 +307,6 @@ void __init arch_init_irq(void) __raw_writeq(tmp, IOADDR(A_IMR_REGISTER(0, R_IMR_INTERRUPT_MASK))); __raw_writeq(tmp, IOADDR(A_IMR_REGISTER(1, R_IMR_INTERRUPT_MASK))); - sb1250_steal_irq(K_INT_MBOX_0); - /* * Note that the timer interrupts are also mapped, but this is * done in sb1250_time_init(). Also, the profiling driver @@ -367,7 +330,6 @@ void __init arch_init_irq(void) __raw_writeq(M_DUART_IMR_BRK, IOADDR(A_DUART_IMRREG(kgdb_port))); - sb1250_steal_irq(kgdb_irq); __raw_writeq(IMR_IP6_VAL, IOADDR(A_IMR_REGISTER(0, R_IMR_INTERRUPT_MAP_BASE) + diff --git a/arch/mips/sibyte/sb1250/time.c b/arch/mips/sibyte/sb1250/time.c index a41e908bc21..68337bf7a5a 100644 --- a/arch/mips/sibyte/sb1250/time.c +++ b/arch/mips/sibyte/sb1250/time.c @@ -15,198 +15,10 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#include <linux/init.h> -/* - * These are routines to set up and handle interrupts from the - * sb1250 general purpose timer 0. We're using the timer as a - * system clock, so we set it up to run at 100 Hz. On every - * interrupt, we update our idea of what the time of day is, - * then call do_timer() in the architecture-independent kernel - * code to do general bookkeeping (e.g. update jiffies, run - * bottom halves, etc.) - */ -#include <linux/clockchips.h> -#include <linux/interrupt.h> -#include <linux/sched.h> -#include <linux/spinlock.h> -#include <linux/kernel_stat.h> - -#include <asm/irq.h> -#include <asm/addrspace.h> -#include <asm/time.h> -#include <asm/io.h> - -#include <asm/sibyte/sb1250.h> -#include <asm/sibyte/sb1250_regs.h> -#include <asm/sibyte/sb1250_int.h> -#include <asm/sibyte/sb1250_scd.h> - - -#define IMR_IP2_VAL K_INT_MAP_I0 -#define IMR_IP3_VAL K_INT_MAP_I1 -#define IMR_IP4_VAL K_INT_MAP_I2 - -#define SB1250_HPT_NUM 3 -#define SB1250_HPT_VALUE M_SCD_TIMER_CNT /* max value */ - - -extern int sb1250_steal_irq(int irq); - -/* - * The general purpose timer ticks at 1 Mhz independent if - * the rest of the system - */ -static void sibyte_set_mode(enum clock_event_mode mode, - struct clock_event_device *evt) -{ - unsigned int cpu = smp_processor_id(); - void __iomem *timer_cfg, *timer_init; - - timer_cfg = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)); - timer_init = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT)); - - switch(mode) { - case CLOCK_EVT_MODE_PERIODIC: - __raw_writeq(0, timer_cfg); - __raw_writeq((V_SCD_TIMER_FREQ / HZ) - 1, timer_init); - __raw_writeq(M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS, - timer_cfg); - break; - - case CLOCK_EVT_MODE_ONESHOT: - /* Stop the timer until we actually program a shot */ - case CLOCK_EVT_MODE_SHUTDOWN: - __raw_writeq(0, timer_cfg); - break; - - case CLOCK_EVT_MODE_UNUSED: /* shuddup gcc */ - case CLOCK_EVT_MODE_RESUME: - ; - } -} - -static int -sibyte_next_event(unsigned long delta, struct clock_event_device *evt) -{ - unsigned int cpu = smp_processor_id(); - void __iomem *timer_cfg, *timer_init; - - timer_cfg = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)); - timer_init = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT)); - - __raw_writeq(0, timer_cfg); - __raw_writeq(delta, timer_init); - __raw_writeq(M_SCD_TIMER_ENABLE, timer_cfg); - - return 0; -} - -static irqreturn_t sibyte_counter_handler(int irq, void *dev_id) -{ - unsigned int cpu = smp_processor_id(); - struct clock_event_device *cd = dev_id; - - /* ACK interrupt */ - ____raw_writeq(M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS, - IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG))); - - cd->event_handler(cd); - - return IRQ_HANDLED; -} - -static struct irqaction sibyte_irqaction = { - .handler = sibyte_counter_handler, - .flags = IRQF_DISABLED | IRQF_PERCPU, - .name = "timer", -}; - -static DEFINE_PER_CPU(struct clock_event_device, sibyte_hpt_clockevent); -static DEFINE_PER_CPU(struct irqaction, sibyte_hpt_irqaction); -static DEFINE_PER_CPU(char [18], sibyte_hpt_name); - -void __cpuinit sb1250_clockevent_init(void) -{ - unsigned int cpu = smp_processor_id(); - unsigned int irq = K_INT_TIMER_0 + cpu; - struct irqaction *action = &per_cpu(sibyte_hpt_irqaction, cpu); - struct clock_event_device *cd = &per_cpu(sibyte_hpt_clockevent, cpu); - unsigned char *name = per_cpu(sibyte_hpt_name, cpu); - - /* Only have 4 general purpose timers, and we use last one as hpt */ - BUG_ON(cpu > 2); - - sprintf(name, "bcm1480-counter %d", cpu); - cd->name = name; - cd->features = CLOCK_EVT_FEAT_PERIODIC | - CLOCK_EVT_MODE_ONESHOT; - clockevent_set_clock(cd, V_SCD_TIMER_FREQ); - cd->max_delta_ns = clockevent_delta2ns(0x7fffff, cd); - cd->min_delta_ns = clockevent_delta2ns(1, cd); - cd->rating = 200; - cd->irq = irq; - cd->cpumask = cpumask_of_cpu(cpu); - cd->set_next_event = sibyte_next_event; - cd->set_mode = sibyte_set_mode; - clockevents_register_device(cd); - - sb1250_mask_irq(cpu, irq); - - /* Map the timer interrupt to ip[4] of this cpu */ - __raw_writeq(IMR_IP4_VAL, - IOADDR(A_IMR_REGISTER(cpu, R_IMR_INTERRUPT_MAP_BASE) + - (irq << 3))); - cd->cpumask = cpumask_of_cpu(0); - - sb1250_unmask_irq(cpu, irq); - sb1250_steal_irq(irq); - - action->handler = sibyte_counter_handler; - action->flags = IRQF_DISABLED | IRQF_PERCPU; - action->name = name; - action->dev_id = cd; - setup_irq(irq, &sibyte_irqaction); -} - -/* - * The HPT is free running from SB1250_HPT_VALUE down to 0 then starts over - * again. - */ -static cycle_t sb1250_hpt_read(void) -{ - unsigned int count; - - count = G_SCD_TIMER_CNT(__raw_readq(IOADDR(A_SCD_TIMER_REGISTER(SB1250_HPT_NUM, R_SCD_TIMER_CNT)))); - - return SB1250_HPT_VALUE - count; -} - -struct clocksource bcm1250_clocksource = { - .name = "MIPS", - .rating = 200, - .read = sb1250_hpt_read, - .mask = CLOCKSOURCE_MASK(23), - .flags = CLOCK_SOURCE_IS_CONTINUOUS, -}; - -void __init sb1250_clocksource_init(void) -{ - struct clocksource *cs = &bcm1250_clocksource; - - /* Setup hpt using timer #3 but do not enable irq for it */ - __raw_writeq(0, - IOADDR(A_SCD_TIMER_REGISTER(SB1250_HPT_NUM, - R_SCD_TIMER_CFG))); - __raw_writeq(SB1250_HPT_VALUE, - IOADDR(A_SCD_TIMER_REGISTER(SB1250_HPT_NUM, - R_SCD_TIMER_INIT))); - __raw_writeq(M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS, - IOADDR(A_SCD_TIMER_REGISTER(SB1250_HPT_NUM, - R_SCD_TIMER_CFG))); - - clocksource_set_clock(cs, V_SCD_TIMER_FREQ); - clocksource_register(cs); -} +extern void sb1250_clocksource_init(void); +extern void sb1250_clockevent_init(void); void __init plat_time_init(void) { diff --git a/arch/mips/sni/pcimt.c b/arch/mips/sni/pcimt.c index 4df070f2ff5..834650f371e 100644 --- a/arch/mips/sni/pcimt.c +++ b/arch/mips/sni/pcimt.c @@ -244,7 +244,7 @@ static void pcimt_hwint1(void) if (pend & IT_EISA) { int irq; /* - * Note: ASIC PCI's builtin interrupt achknowledge feature is + * Note: ASIC PCI's builtin interrupt acknowledge feature is * broken. Using it may result in loss of some or all i8259 * interrupts, so don't use PCIMT_INT_ACKNOWLEDGE ... */ diff --git a/arch/mips/sni/time.c b/arch/mips/sni/time.c index 0910b35cb71..6f339af08d2 100644 --- a/arch/mips/sni/time.c +++ b/arch/mips/sni/time.c @@ -1,6 +1,7 @@ #include <linux/types.h> #include <linux/interrupt.h> #include <linux/time.h> +#include <linux/clockchips.h> #include <asm/i8253.h> #include <asm/sni.h> @@ -11,27 +12,78 @@ #define SNI_COUNTER2_DIV 64 #define SNI_COUNTER0_DIV ((SNI_CLOCK_TICK_RATE / SNI_COUNTER2_DIV) / HZ) -static void sni_a20r_timer_ack(void) +static void a20r_set_mode(enum clock_event_mode mode, + struct clock_event_device *evt) { - *(volatile u8 *)A20R_PT_TIM0_ACK = 0x0; wmb(); + switch (mode) { + case CLOCK_EVT_MODE_PERIODIC: + *(volatile u8 *)(A20R_PT_CLOCK_BASE + 12) = 0x34; + wmb(); + *(volatile u8 *)(A20R_PT_CLOCK_BASE + 0) = SNI_COUNTER0_DIV; + wmb(); + *(volatile u8 *)(A20R_PT_CLOCK_BASE + 0) = SNI_COUNTER0_DIV >> 8; + wmb(); + + *(volatile u8 *)(A20R_PT_CLOCK_BASE + 12) = 0xb4; + wmb(); + *(volatile u8 *)(A20R_PT_CLOCK_BASE + 8) = SNI_COUNTER2_DIV; + wmb(); + *(volatile u8 *)(A20R_PT_CLOCK_BASE + 8) = SNI_COUNTER2_DIV >> 8; + wmb(); + + break; + case CLOCK_EVT_MODE_ONESHOT: + case CLOCK_EVT_MODE_UNUSED: + case CLOCK_EVT_MODE_SHUTDOWN: + break; + case CLOCK_EVT_MODE_RESUME: + break; + } } +static struct clock_event_device a20r_clockevent_device = { + .name = "a20r-timer", + .features = CLOCK_EVT_FEAT_PERIODIC, + + /* .mult, .shift, .max_delta_ns and .min_delta_ns left uninitialized */ + + .rating = 300, + .irq = SNI_A20R_IRQ_TIMER, + .set_mode = a20r_set_mode, +}; + +static irqreturn_t a20r_interrupt(int irq, void *dev_id) +{ + struct clock_event_device *cd = dev_id; + + *(volatile u8 *)A20R_PT_TIM0_ACK = 0; + wmb(); + + cd->event_handler(cd); + + return IRQ_HANDLED; +} + +static struct irqaction a20r_irqaction = { + .handler = a20r_interrupt, + .flags = IRQF_DISABLED | IRQF_PERCPU, + .name = "a20r-timer", +}; + /* * a20r platform uses 2 counters to divide the input frequency. * Counter 2 output is connected to Counter 0 & 1 input. */ -static void __init sni_a20r_timer_setup(struct irqaction *irq) +static void __init sni_a20r_timer_setup(void) { - *(volatile u8 *)(A20R_PT_CLOCK_BASE + 12) = 0x34; wmb(); - *(volatile u8 *)(A20R_PT_CLOCK_BASE + 0) = (SNI_COUNTER0_DIV) & 0xff; wmb(); - *(volatile u8 *)(A20R_PT_CLOCK_BASE + 0) = (SNI_COUNTER0_DIV >> 8) & 0xff; wmb(); - - *(volatile u8 *)(A20R_PT_CLOCK_BASE + 12) = 0xb4; wmb(); - *(volatile u8 *)(A20R_PT_CLOCK_BASE + 8) = (SNI_COUNTER2_DIV) & 0xff; wmb(); - *(volatile u8 *)(A20R_PT_CLOCK_BASE + 8) = (SNI_COUNTER2_DIV >> 8) & 0xff; wmb(); - - setup_irq(SNI_A20R_IRQ_TIMER, irq); - mips_timer_ack = sni_a20r_timer_ack; + struct clock_event_device *cd = &a20r_clockevent_device; + struct irqaction *action = &a20r_irqaction; + unsigned int cpu = smp_processor_id(); + + cd->cpumask = cpumask_of_cpu(cpu); + clockevents_register_device(cd); + action->dev_id = cd; + setup_irq(SNI_A20R_IRQ_TIMER, &a20r_irqaction); } #define SNI_8254_TICK_RATE 1193182UL @@ -118,18 +170,13 @@ void __init plat_time_init(void) mips_hpt_frequency = r4k_tick * HZ; - setup_pit_timer(); -} - -void __init plat_timer_setup(struct irqaction *irq) -{ switch (sni_brd_type) { case SNI_BRD_10: case SNI_BRD_10NEW: case SNI_BRD_TOWER_OASIC: case SNI_BRD_MINITOWER: - sni_a20r_timer_setup(irq); - break; + sni_a20r_timer_setup(); + break; } } diff --git a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c index c7470fba618..0299595ce1c 100644 --- a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c +++ b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c @@ -63,6 +63,7 @@ #include <asm/processor.h> #include <asm/reboot.h> #include <asm/time.h> +#include <asm/txx9tmr.h> #include <linux/bootmem.h> #include <linux/blkdev.h> #ifdef CONFIG_TOSHIBA_FPCIB0 @@ -93,7 +94,6 @@ #define TOSHIBA_RBTX4927_SETUP_EFWFU ( 1 << 3 ) #define TOSHIBA_RBTX4927_SETUP_SETUP ( 1 << 4 ) -#define TOSHIBA_RBTX4927_SETUP_TIME_INIT ( 1 << 5 ) #define TOSHIBA_RBTX4927_SETUP_PCIBIOS ( 1 << 7 ) #define TOSHIBA_RBTX4927_SETUP_PCI1 ( 1 << 8 ) #define TOSHIBA_RBTX4927_SETUP_PCI2 ( 1 << 9 ) @@ -130,7 +130,6 @@ extern void toshiba_rbtx4927_power_off(void); int tx4927_using_backplane = 0; -extern void gt64120_time_init(void); extern void toshiba_rbtx4927_irq_setup(void); char *prom_getcmdline(void); @@ -721,6 +720,7 @@ void toshiba_rbtx4927_power_off(void) void __init toshiba_rbtx4927_setup(void) { + int i; u32 cp0_config; char *argptr; @@ -764,6 +764,9 @@ void __init toshiba_rbtx4927_setup(void) _machine_halt = toshiba_rbtx4927_halt; pm_power_off = toshiba_rbtx4927_power_off; + for (i = 0; i < TX4927_NR_TMR; i++) + txx9_tmr_init(TX4927_TMR_REG(0) & 0xfffffffffULL); + #ifdef CONFIG_PCI /* PCIC */ @@ -892,7 +895,6 @@ void __init toshiba_rbtx4927_setup(void) #ifdef CONFIG_SERIAL_TXX9 { extern int early_serial_txx9_setup(struct uart_port *port); - int i; struct uart_port req; for(i = 0; i < 2; i++) { memset(&req, 0, sizeof(req)); @@ -937,12 +939,11 @@ void __init toshiba_rbtx4927_setup(void) void __init toshiba_rbtx4927_time_init(void) { - TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_TIME_INIT, "-\n"); - mips_hpt_frequency = tx4927_cpu_clock / 2; - - TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_TIME_INIT, "+\n"); - + if (tx4927_ccfgptr->ccfg & TX4927_CCFG_TINTDIS) + txx9_clockevent_init(TX4927_TMR_REG(0) & 0xfffffffffULL, + TXX9_IRQ_BASE + 17, + 50000000); } static int __init toshiba_rbtx4927_rtc_init(void) diff --git a/arch/mips/tx4938/toshiba_rbtx4938/setup.c b/arch/mips/tx4938/toshiba_rbtx4938/setup.c index ceecaf49895..4a8152375ef 100644 --- a/arch/mips/tx4938/toshiba_rbtx4938/setup.c +++ b/arch/mips/tx4938/toshiba_rbtx4938/setup.c @@ -26,6 +26,7 @@ #include <asm/reboot.h> #include <asm/irq.h> #include <asm/time.h> +#include <asm/txx9tmr.h> #include <asm/uaccess.h> #include <asm/io.h> #include <asm/bootinfo.h> @@ -773,15 +774,8 @@ void __init tx4938_board_setup(void) } /* TMR */ - /* disable all timers */ - for (i = 0; i < TX4938_NR_TMR; i++) { - tx4938_tmrptr(i)->tcr = 0x00000020; - tx4938_tmrptr(i)->tisr = 0; - tx4938_tmrptr(i)->cpra = 0xffffffff; - tx4938_tmrptr(i)->itmr = 0; - tx4938_tmrptr(i)->ccdr = 0; - tx4938_tmrptr(i)->pgmr = 0; - } + for (i = 0; i < TX4938_NR_TMR; i++) + txx9_tmr_init(TX4938_TMR_REG(i) & 0xfffffffffULL); /* enable DMA */ TX4938_WR64(0xff1fb150, TX4938_DMA_MCR_MSTEN); @@ -852,12 +846,13 @@ void tx4938_report_pcic_status(void) #endif /* CONFIG_PCI */ -/* We use onchip r4k counter or TMR timer as our system wide timer - * interrupt running at 100HZ. */ - void __init plat_time_init(void) { mips_hpt_frequency = txx9_cpu_clock / 2; + if (tx4938_ccfgptr->ccfg & TX4938_CCFG_TINTDIS) + txx9_clockevent_init(TX4938_TMR_REG(0) & 0xfffffffffULL, + TXX9_IRQ_BASE + TX4938_IR_TMR(0), + txx9_gbus_clock / 2); } void __init toshiba_rbtx4938_setup(void) diff --git a/arch/mips/vr41xx/Kconfig b/arch/mips/vr41xx/Kconfig index eeb089f20c0..559acc09c81 100644 --- a/arch/mips/vr41xx/Kconfig +++ b/arch/mips/vr41xx/Kconfig @@ -6,6 +6,7 @@ choice config CASIO_E55 bool "CASIO CASSIOPEIA E-10/15/55/65" select CEVT_R4K + select CSRC_R4K select DMA_NONCOHERENT select IRQ_CPU select ISA @@ -15,6 +16,7 @@ config CASIO_E55 config IBM_WORKPAD bool "IBM WorkPad z50" select CEVT_R4K + select CSRC_R4K select DMA_NONCOHERENT select IRQ_CPU select ISA @@ -24,6 +26,7 @@ config IBM_WORKPAD config NEC_CMBVR4133 bool "NEC CMB-VR4133" select CEVT_R4K + select CSRC_R4K select DMA_NONCOHERENT select IRQ_CPU select HW_HAS_PCI @@ -33,6 +36,7 @@ config NEC_CMBVR4133 config TANBAC_TB022X bool "TANBAC VR4131 multichip module and TANBAC VR4131DIMM" select CEVT_R4K + select CSRC_R4K select DMA_NONCOHERENT select IRQ_CPU select HW_HAS_PCI @@ -48,6 +52,7 @@ config TANBAC_TB022X config VICTOR_MPC30X bool "Victor MP-C303/304" select CEVT_R4K + select CSRC_R4K select DMA_NONCOHERENT select IRQ_CPU select HW_HAS_PCI @@ -58,6 +63,7 @@ config VICTOR_MPC30X config ZAO_CAPCELLA bool "ZAO Networks Capcella" select CEVT_R4K + select CSRC_R4K select DMA_NONCOHERENT select IRQ_CPU select HW_HAS_PCI diff --git a/arch/mips/vr41xx/common/icu.c b/arch/mips/vr41xx/common/icu.c index 1899601e586..3f23d9fda66 100644 --- a/arch/mips/vr41xx/common/icu.c +++ b/arch/mips/vr41xx/common/icu.c @@ -525,6 +525,7 @@ static inline int set_sysint1_assign(unsigned int irq, unsigned char assign) intassign1 |= (uint16_t)assign << 9; break; default: + spin_unlock_irq(&desc->lock); return -EINVAL; } @@ -592,6 +593,7 @@ static inline int set_sysint2_assign(unsigned int irq, unsigned char assign) intassign3 |= (uint16_t)assign << 12; break; default: + spin_unlock_irq(&desc->lock); return -EINVAL; } |