aboutsummaryrefslogtreecommitdiff
path: root/arch/mips
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips')
-rw-r--r--arch/mips/Kconfig63
-rw-r--r--arch/mips/Makefile2
-rw-r--r--arch/mips/au1000/Kconfig1
-rw-r--r--arch/mips/au1000/common/irq.c32
-rw-r--r--arch/mips/au1000/common/time.c22
-rw-r--r--arch/mips/au1000/mtx-1/Makefile3
-rw-r--r--arch/mips/au1000/mtx-1/platform.c77
-rw-r--r--arch/mips/au1000/pb1200/Makefile2
-rw-r--r--arch/mips/au1000/pb1200/board_setup.c6
-rw-r--r--arch/mips/au1000/pb1200/irqmap.c100
-rw-r--r--arch/mips/basler/excite/excite_setup.c21
-rw-r--r--arch/mips/configs/db1000_defconfig1
-rw-r--r--arch/mips/configs/db1100_defconfig1
-rw-r--r--arch/mips/configs/db1200_defconfig1
-rw-r--r--arch/mips/configs/db1500_defconfig1
-rw-r--r--arch/mips/configs/db1550_defconfig1
-rw-r--r--arch/mips/configs/pb1100_defconfig1
-rw-r--r--arch/mips/configs/pb1500_defconfig1
-rw-r--r--arch/mips/configs/pb1550_defconfig1
-rw-r--r--arch/mips/configs/sb1250-swarm_defconfig2
-rw-r--r--arch/mips/gt64120/wrppmc/time.c6
-rw-r--r--arch/mips/jazz/irq.c27
-rw-r--r--arch/mips/jmr3927/rbhma3100/setup.c83
-rw-r--r--arch/mips/kernel/Makefile7
-rw-r--r--arch/mips/kernel/cevt-bcm1480.c153
-rw-r--r--arch/mips/kernel/cevt-gt641xx.c12
-rw-r--r--arch/mips/kernel/cevt-r4k.c55
-rw-r--r--arch/mips/kernel/cevt-sb1250.c152
-rw-r--r--arch/mips/kernel/cevt-txx9.c171
-rw-r--r--arch/mips/kernel/cpu-probe.c5
-rw-r--r--arch/mips/kernel/csrc-bcm1480.c54
-rw-r--r--arch/mips/kernel/csrc-r4k.c29
-rw-r--r--arch/mips/kernel/csrc-sb1250.c70
-rw-r--r--arch/mips/kernel/genex.S2
-rw-r--r--arch/mips/kernel/i8253.c25
-rw-r--r--arch/mips/kernel/irixsig.c9
-rw-r--r--arch/mips/kernel/irq-rm7000.c2
-rw-r--r--arch/mips/kernel/irq-rm9000.c2
-rw-r--r--arch/mips/kernel/irq_cpu.c2
-rw-r--r--arch/mips/kernel/proc.c2
-rw-r--r--arch/mips/kernel/ptrace.c18
-rw-r--r--arch/mips/kernel/ptrace32.c4
-rw-r--r--arch/mips/kernel/scall64-n32.S2
-rw-r--r--arch/mips/kernel/setup.c31
-rw-r--r--arch/mips/kernel/smp-up.c67
-rw-r--r--arch/mips/kernel/smtc.c57
-rw-r--r--arch/mips/kernel/syscall.c9
-rw-r--r--arch/mips/kernel/time.c180
-rw-r--r--arch/mips/kernel/traps.c68
-rw-r--r--arch/mips/kernel/vmlinux.lds.S32
-rw-r--r--arch/mips/kernel/vpe.c22
-rw-r--r--arch/mips/lasat/interrupt.c22
-rw-r--r--arch/mips/lasat/setup.c7
-rw-r--r--arch/mips/math-emu/ieee754.c2
-rw-r--r--arch/mips/math-emu/ieee754dp.c2
-rw-r--r--arch/mips/math-emu/ieee754sp.c2
-rw-r--r--arch/mips/mips-boards/generic/time.c52
-rw-r--r--arch/mips/mipssim/sim_time.c48
-rw-r--r--arch/mips/mm/c-r3k.c60
-rw-r--r--arch/mips/mm/c-r4k.c28
-rw-r--r--arch/mips/mm/cerr-sb1.c6
-rw-r--r--arch/mips/mm/dma-default.c39
-rw-r--r--arch/mips/mm/init.c45
-rw-r--r--arch/mips/pci/fixup-pmcmsp.c2
-rw-r--r--arch/mips/pci/fixup-sni.c23
-rw-r--r--arch/mips/pci/fixup-tb0219.c2
-rw-r--r--arch/mips/pci/ops-pmcmsp.c2
-rw-r--r--arch/mips/pci/pci-lasat.c32
-rw-r--r--arch/mips/pci/pci-vr41xx.c1
-rw-r--r--arch/mips/pmc-sierra/Kconfig2
-rw-r--r--arch/mips/pmc-sierra/msp71xx/msp_serial.c2
-rw-r--r--arch/mips/qemu/Makefile3
-rw-r--r--arch/mips/qemu/q-console.c26
-rw-r--r--arch/mips/qemu/q-firmware.c6
-rw-r--r--arch/mips/qemu/q-irq.c1
-rw-r--r--arch/mips/qemu/q-setup.c3
-rw-r--r--arch/mips/sgi-ip22/ip22-eisa.c134
-rw-r--r--arch/mips/sgi-ip22/ip22-nvram.c40
-rw-r--r--arch/mips/sgi-ip27/ip27-timer.c11
-rw-r--r--arch/mips/sgi-ip32/ip32-irq.c152
-rw-r--r--arch/mips/sgi-ip32/ip32-platform.c2
-rw-r--r--arch/mips/sibyte/Kconfig14
-rw-r--r--arch/mips/sibyte/bcm1480/irq.c61
-rw-r--r--arch/mips/sibyte/bcm1480/time.c162
-rw-r--r--arch/mips/sibyte/sb1250/irq.c38
-rw-r--r--arch/mips/sibyte/sb1250/time.c194
-rw-r--r--arch/mips/sni/pcimt.c2
-rw-r--r--arch/mips/sni/time.c87
-rw-r--r--arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c17
-rw-r--r--arch/mips/tx4938/toshiba_rbtx4938/setup.c19
-rw-r--r--arch/mips/vr41xx/Kconfig6
-rw-r--r--arch/mips/vr41xx/common/icu.c2
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(&gt641xx_timer_lock, flags);
+ spin_lock(&gt641xx_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(&gt641xx_timer_lock, flags);
+ spin_unlock(&gt641xx_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(&gt641xx_timer_lock, flags);
+ spin_lock(&gt641xx_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(&gt641xx_timer_lock, flags);
+ spin_unlock(&gt641xx_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 = &gt641xx_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(&gt641xx_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(&current->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;
}