Merge branch '4.2-fixes' into mips-for-linux-next
authorRalf Baechle <ralf@linux-mips.org>
Thu, 3 Sep 2015 12:06:33 +0000 (14:06 +0200)
committerRalf Baechle <ralf@linux-mips.org>
Thu, 3 Sep 2015 12:06:33 +0000 (14:06 +0200)
194 files changed:
Documentation/devicetree/bindings/timer/img,pistachio-gptimer.txt [new file with mode: 0644]
Documentation/features/debug/uprobes/arch-support.txt
Documentation/sysrq.txt
arch/mips/Kconfig
arch/mips/Kconfig.debug
arch/mips/alchemy/Kconfig
arch/mips/alchemy/board-gpr.c
arch/mips/alchemy/board-mtx1.c
arch/mips/alchemy/common/Makefile
arch/mips/alchemy/common/irq.c
arch/mips/alchemy/common/time.c
arch/mips/alchemy/devboards/bcsr.c
arch/mips/alchemy/devboards/db1000.c
arch/mips/alchemy/devboards/db1300.c
arch/mips/alchemy/devboards/db1550.c
arch/mips/alchemy/devboards/pm.c
arch/mips/ar7/gpio.c
arch/mips/ar7/platform.c
arch/mips/ar7/setup.c
arch/mips/ath79/Makefile
arch/mips/ath79/common.h
arch/mips/ath79/gpio.c [deleted file]
arch/mips/ath79/irq.c
arch/mips/bcm47xx/buttons.c
arch/mips/bcm63xx/irq.c
arch/mips/boot/compressed/Makefile
arch/mips/boot/dts/netlogic/xlp_evp.dts
arch/mips/boot/dts/netlogic/xlp_fvp.dts
arch/mips/boot/dts/netlogic/xlp_gvp.dts
arch/mips/boot/dts/netlogic/xlp_rvp.dts
arch/mips/boot/dts/netlogic/xlp_svp.dts
arch/mips/cavium-octeon/executive/cvmx-helper-board.c
arch/mips/cavium-octeon/executive/cvmx-helper-util.c
arch/mips/cavium-octeon/executive/cvmx-helper-xaui.c
arch/mips/cavium-octeon/executive/cvmx-helper.c
arch/mips/cavium-octeon/executive/cvmx-pko.c
arch/mips/cavium-octeon/octeon-irq.c
arch/mips/include/asm/Kbuild
arch/mips/include/asm/abi.h
arch/mips/include/asm/asmmacro.h
arch/mips/include/asm/cdmm.h
arch/mips/include/asm/cevt-r4k.h
arch/mips/include/asm/cpu-features.h
arch/mips/include/asm/cpu-type.h
arch/mips/include/asm/cpu.h
arch/mips/include/asm/debug.h [deleted file]
arch/mips/include/asm/elf.h
arch/mips/include/asm/fpu.h
arch/mips/include/asm/gpio.h [deleted file]
arch/mips/include/asm/irq.h
arch/mips/include/asm/kdebug.h
arch/mips/include/asm/linkage.h
arch/mips/include/asm/maar.h
arch/mips/include/asm/mach-ar7/ar7.h
arch/mips/include/asm/mach-ar7/gpio.h [deleted file]
arch/mips/include/asm/mach-ath25/gpio.h [deleted file]
arch/mips/include/asm/mach-ath79/gpio.h [deleted file]
arch/mips/include/asm/mach-au1x00/gpio-au1000.h
arch/mips/include/asm/mach-au1x00/gpio.h [deleted file]
arch/mips/include/asm/mach-bcm47xx/gpio.h [deleted file]
arch/mips/include/asm/mach-bcm63xx/gpio.h [deleted file]
arch/mips/include/asm/mach-cavium-octeon/gpio.h [deleted file]
arch/mips/include/asm/mach-generic/gpio.h [deleted file]
arch/mips/include/asm/mach-jz4740/gpio.h
arch/mips/include/asm/mach-lantiq/gpio.h [deleted file]
arch/mips/include/asm/mach-loongson64/gpio.h [deleted file]
arch/mips/include/asm/mach-pistachio/gpio.h [deleted file]
arch/mips/include/asm/mach-rc32434/gpio.h
arch/mips/include/asm/mips-cm.h
arch/mips/include/asm/mips-cpc.h
arch/mips/include/asm/mipsregs.h
arch/mips/include/asm/msa.h
arch/mips/include/asm/octeon/cvmx-bootinfo.h
arch/mips/include/asm/octeon/cvmx-pip.h
arch/mips/include/asm/octeon/cvmx-pko.h
arch/mips/include/asm/octeon/cvmx-pow-defs.h
arch/mips/include/asm/octeon/cvmx-pow.h
arch/mips/include/asm/octeon/cvmx-wqe.h
arch/mips/include/asm/pgtable-bits.h
arch/mips/include/asm/pgtable.h
arch/mips/include/asm/processor.h
arch/mips/include/asm/ptrace.h
arch/mips/include/asm/signal.h
arch/mips/include/asm/spinlock.h
arch/mips/include/asm/switch_to.h
arch/mips/include/asm/thread_info.h
arch/mips/include/asm/time.h
arch/mips/include/asm/tlbdebug.h
arch/mips/include/asm/uprobes.h [new file with mode: 0644]
arch/mips/include/asm/vpe.h
arch/mips/include/uapi/asm/break.h
arch/mips/include/uapi/asm/hwcap.h [new file with mode: 0644]
arch/mips/include/uapi/asm/inst.h
arch/mips/include/uapi/asm/sigcontext.h
arch/mips/include/uapi/asm/ucontext.h [new file with mode: 0644]
arch/mips/jazz/irq.c
arch/mips/jz4740/gpio.c
arch/mips/jz4740/time.c
arch/mips/kernel/Makefile
arch/mips/kernel/asm-offsets.c
arch/mips/kernel/cevt-bcm1480.c
arch/mips/kernel/cevt-ds1287.c
arch/mips/kernel/cevt-gt641xx.c
arch/mips/kernel/cevt-r4k.c
arch/mips/kernel/cevt-sb1250.c
arch/mips/kernel/cevt-txx9.c
arch/mips/kernel/cpu-probe.c
arch/mips/kernel/idle.c
arch/mips/kernel/mips-cm.c
arch/mips/kernel/mips-cpc.c
arch/mips/kernel/perf_event_mipsxx.c
arch/mips/kernel/pm-cps.c
arch/mips/kernel/ptrace.c
arch/mips/kernel/r4k_fpu.S
arch/mips/kernel/r4k_switch.S
arch/mips/kernel/signal-common.h
arch/mips/kernel/signal.c
arch/mips/kernel/signal32.c
arch/mips/kernel/signal_n32.c
arch/mips/kernel/spram.c
arch/mips/kernel/sysrq.c
arch/mips/kernel/traps.c
arch/mips/kernel/unaligned.c
arch/mips/kernel/uprobes.c [new file with mode: 0644]
arch/mips/kernel/vpe.c
arch/mips/lasat/sysctl.c
arch/mips/lib/dump_tlb.c
arch/mips/lib/r3k_dump_tlb.c
arch/mips/loongson32/common/time.c
arch/mips/loongson64/common/cs5536/cs5536_mfgpt.c
arch/mips/loongson64/loongson-3/hpet.c
arch/mips/math-emu/Makefile
arch/mips/math-emu/cp1emu.c
arch/mips/math-emu/dp_2008class.c [new file with mode: 0644]
arch/mips/math-emu/dp_fmax.c [new file with mode: 0644]
arch/mips/math-emu/dp_fmin.c [new file with mode: 0644]
arch/mips/math-emu/dp_maddf.c [new file with mode: 0644]
arch/mips/math-emu/dp_msubf.c [new file with mode: 0644]
arch/mips/math-emu/dsemul.c
arch/mips/math-emu/ieee754.h
arch/mips/math-emu/ieee754int.h
arch/mips/math-emu/me-debugfs.c
arch/mips/math-emu/sp_2008class.c [new file with mode: 0644]
arch/mips/math-emu/sp_fmax.c [new file with mode: 0644]
arch/mips/math-emu/sp_fmin.c [new file with mode: 0644]
arch/mips/math-emu/sp_maddf.c [new file with mode: 0644]
arch/mips/math-emu/sp_msubf.c [new file with mode: 0644]
arch/mips/mm/c-r4k.c
arch/mips/mm/dma-default.c
arch/mips/mm/fault.c
arch/mips/mm/init.c
arch/mips/mm/sc-mips.c
arch/mips/mm/tlb-r3k.c
arch/mips/mti-malta/malta-init.c
arch/mips/mti-malta/malta-int.c
arch/mips/mti-malta/malta-memory.c
arch/mips/netlogic/common/irq.c
arch/mips/netlogic/common/smp.c
arch/mips/netlogic/xlp/ahci-init-xlp2.c
arch/mips/netlogic/xlp/nlm_hal.c
arch/mips/oprofile/common.c
arch/mips/oprofile/op_model_mipsxx.c
arch/mips/pci/msi-xlp.c
arch/mips/pci/ops-emma2rh.c
arch/mips/pci/pci-ar71xx.c
arch/mips/pci/pci-ar724x.c
arch/mips/pci/pci-lantiq.c
arch/mips/pci/pci-rt3883.c
arch/mips/pistachio/Kconfig [new file with mode: 0644]
arch/mips/pmcs-msp71xx/msp_irq_cic.c
arch/mips/ralink/cevt-rt3352.c
arch/mips/rb532/devices.c
arch/mips/rb532/gpio.c
arch/mips/sgi-ip27/ip27-timer.c
arch/mips/sibyte/common/bus_watcher.c
arch/mips/sni/time.c
arch/mips/txx9/generic/setup.c
drivers/ata/pata_rb532_cf.c
drivers/bus/mips_cdmm.c
drivers/clocksource/Kconfig
drivers/clocksource/Makefile
drivers/clocksource/mips-gic-timer.c
drivers/clocksource/time-pistachio.c [new file with mode: 0644]
drivers/gpio/Makefile
drivers/gpio/gpio-ath79.c [new file with mode: 0644]
drivers/input/misc/rb532_button.c
drivers/irqchip/irq-mips-gic.c
drivers/net/ethernet/ti/cpmac.c
drivers/staging/octeon/ethernet-rx.c
drivers/staging/octeon/ethernet-tx.c
drivers/staging/octeon/ethernet-util.h
drivers/staging/octeon/ethernet.c
drivers/tty/mips_ejtag_fdc.c
include/linux/irqchip/mips-gic.h

diff --git a/Documentation/devicetree/bindings/timer/img,pistachio-gptimer.txt b/Documentation/devicetree/bindings/timer/img,pistachio-gptimer.txt
new file mode 100644 (file)
index 0000000..7afce80
--- /dev/null
@@ -0,0 +1,28 @@
+* Pistachio general-purpose timer based clocksource
+
+Required properties:
+ - compatible: "img,pistachio-gptimer".
+ - reg: Address range of the timer registers.
+ - interrupts: An interrupt for each of the four timers
+ - clocks: Should contain a clock specifier for each entry in clock-names
+ - clock-names: Should contain the following entries:
+                "sys", interface clock
+                "slow", slow counter clock
+                "fast", fast counter clock
+ - img,cr-periph: Must contain a phandle to the peripheral control
+                 syscon node.
+
+Example:
+       timer: timer@18102000 {
+               compatible = "img,pistachio-gptimer";
+               reg = <0x18102000 0x100>;
+               interrupts = <GIC_SHARED 60 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SHARED 61 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SHARED 62 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SHARED 63 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&clk_periph PERIPH_CLK_COUNTER_FAST>,
+                        <&clk_periph PERIPH_CLK_COUNTER_SLOW>,
+                        <&cr_periph SYS_CLK_TIMER>;
+               clock-names = "fast", "slow", "sys";
+               img,cr-periph = <&cr_periph>;
+       };
index 4efe36c3ace93b8c1a65eaf10e7640b4b34d3289..d605c3fc38fd5cd920230b8057e16a2f180eec1b 100644 (file)
@@ -22,7 +22,7 @@
     |        m68k: | TODO |
     |       metag: | TODO |
     |  microblaze: | TODO |
-    |        mips: | TODO |
+    |        mips: |  ok  |
     |     mn10300: | TODO |
     |       nios2: | TODO |
     |    openrisc: | TODO |
index 0e307c94809a02586d59c13ca8c56985b632cfaf..267f39386f99f77de3993f980652c6b28a7c76d3 100644 (file)
@@ -119,6 +119,7 @@ On all -  write a character to /proc/sysrq-trigger.  e.g.:
 
 'x'    - Used by xmon interface on ppc/powerpc platforms.
           Show global PMU Registers on sparc64.
+          Dump all TLB entries on MIPS.
 
 'y'    - Show global CPU Registers [SPARC-64 specific]
 
index 199a8357838cb24bde2ce5ed5dec7db62feb8d2e..233d338c24b4a67a367128c2fb8afaec0c2e463f 100644 (file)
@@ -1,8 +1,10 @@
 config MIPS
        bool
        default y
+       select ARCH_SUPPORTS_UPROBES
        select ARCH_MIGHT_HAVE_PC_PARPORT
        select ARCH_MIGHT_HAVE_PC_SERIO
+       select ARCH_USE_CMPXCHG_LOCKREF if 64BIT
        select HAVE_CONTEXT_TRACKING
        select HAVE_GENERIC_DMA_COHERENT
        select HAVE_IDE
@@ -13,7 +15,6 @@ config MIPS
        select HAVE_ARCH_SECCOMP_FILTER
        select HAVE_ARCH_TRACEHOOK
        select HAVE_BPF_JIT if !CPU_MICROMIPS
-       select ARCH_HAVE_CUSTOM_GPIO_H
        select HAVE_FUNCTION_TRACER
        select HAVE_DYNAMIC_FTRACE
        select HAVE_FTRACE_MCOUNT_RECORD
@@ -408,6 +409,7 @@ config MIPS_MALTA
        select CEVT_R4K
        select CSRC_R4K
        select CLKSRC_MIPS_GIC
+       select COMMON_CLK
        select DMA_MAYBE_COHERENT
        select GENERIC_ISA_DMA
        select HAVE_PCSPKR_PLATFORM
@@ -458,6 +460,7 @@ config MIPS_SEAD3
        select CEVT_R4K
        select CSRC_R4K
        select CLKSRC_MIPS_GIC
+       select COMMON_CLK
        select CPU_MIPSR2_IRQ_VI
        select CPU_MIPSR2_IRQ_EI
        select DMA_NONCOHERENT
@@ -898,6 +901,7 @@ config NLM_XLP_BOARD
        select SYS_SUPPORTS_32BIT_KERNEL
        select SYS_SUPPORTS_64BIT_KERNEL
        select ARCH_PHYS_ADDR_T_64BIT
+       select ARCH_REQUIRE_GPIOLIB
        select SYS_SUPPORTS_BIG_ENDIAN
        select SYS_SUPPORTS_LITTLE_ENDIAN
        select SYS_SUPPORTS_HIGHMEM
@@ -947,6 +951,7 @@ source "arch/mips/jazz/Kconfig"
 source "arch/mips/jz4740/Kconfig"
 source "arch/mips/lantiq/Kconfig"
 source "arch/mips/lasat/Kconfig"
+source "arch/mips/pistachio/Kconfig"
 source "arch/mips/pmcs-msp71xx/Kconfig"
 source "arch/mips/ralink/Kconfig"
 source "arch/mips/sgi-ip27/Kconfig"
@@ -1040,6 +1045,9 @@ config FW_CFE
 config ARCH_DMA_ADDR_T_64BIT
        def_bool (HIGHMEM && ARCH_PHYS_ADDR_T_64BIT) || 64BIT
 
+config ARCH_SUPPORTS_UPROBES
+       bool
+
 config DMA_MAYBE_COHERENT
        select DMA_NONCOHERENT
        bool
@@ -1367,7 +1375,7 @@ config CPU_MIPS32_R2
          otherwise CPU_MIPS32_R1 is a safe bet for any MIPS32 system.
 
 config CPU_MIPS32_R6
-       bool "MIPS32 Release 6 (EXPERIMENTAL)"
+       bool "MIPS32 Release 6"
        depends on SYS_HAS_CPU_MIPS32_R6
        select CPU_HAS_PREFETCH
        select CPU_SUPPORTS_32BIT_KERNEL
@@ -1418,7 +1426,7 @@ config CPU_MIPS64_R2
          otherwise CPU_MIPS64_R1 is a safe bet for any MIPS64 system.
 
 config CPU_MIPS64_R6
-       bool "MIPS64 Release 6 (EXPERIMENTAL)"
+       bool "MIPS64 Release 6"
        depends on SYS_HAS_CPU_MIPS64_R6
        select CPU_HAS_PREFETCH
        select CPU_SUPPORTS_32BIT_KERNEL
@@ -1968,6 +1976,7 @@ config 32BIT
        select TRAD_SIGNALS
        help
          Select this option if you want to build a 32-bit kernel.
+
 config 64BIT
        bool "64-bit kernel"
        depends on CPU_SUPPORTS_64BIT_KERNEL && SYS_SUPPORTS_64BIT_KERNEL
@@ -2113,7 +2122,7 @@ config CPU_R4K_CACHE_TLB
 
 config MIPS_MT_SMP
        bool "MIPS MT SMP support (1 TC on each available VPE)"
-       depends on SYS_SUPPORTS_MULTITHREADING
+       depends on SYS_SUPPORTS_MULTITHREADING && !CPU_MIPSR6
        select CPU_MIPSR2_IRQ_VI
        select CPU_MIPSR2_IRQ_EI
        select SYNC_R4K
@@ -2214,7 +2223,7 @@ config MIPS_VPE_APSP_API_MT
 
 config MIPS_CMP
        bool "MIPS CMP framework support (DEPRECATED)"
-       depends on SYS_SUPPORTS_MIPS_CMP
+       depends on SYS_SUPPORTS_MIPS_CMP && !CPU_MIPSR6
        select MIPS_GIC_IPI
        select SMP
        select SYNC_R4K
@@ -2231,7 +2240,7 @@ config MIPS_CMP
 
 config MIPS_CPS
        bool "MIPS Coherent Processing System support"
-       depends on SYS_SUPPORTS_MIPS_CPS
+       depends on SYS_SUPPORTS_MIPS_CPS && !CPU_MIPSR6
        select MIPS_CM
        select MIPS_CPC
        select MIPS_CPS_PM if HOTPLUG_CPU
@@ -2306,7 +2315,7 @@ config CPU_MICROMIPS
 endchoice
 
 config CPU_HAS_MSA
-       bool "Support for the MIPS SIMD Architecture (EXPERIMENTAL)"
+       bool "Support for the MIPS SIMD Architecture"
        depends on CPU_SUPPORTS_MSA
        depends on 64BIT || MIPS_O32_FP64_SUPPORT
        help
@@ -2646,7 +2655,7 @@ config SECCOMP
          If unsure, say Y. Only embedded should say N here.
 
 config MIPS_O32_FP64_SUPPORT
-       bool "Support for O32 binaries using 64-bit FP (EXPERIMENTAL)"
+       bool "Support for O32 binaries using 64-bit FP"
        depends on 32BIT || MIPS32_O32
        help
          When this is enabled, the kernel will support use of 64-bit floating
index 3a2b775e845893513e2ab187ca95955e0be17848..e250524021aca8ec7e1b79bfd0b4f088d96f109d 100644 (file)
@@ -87,15 +87,6 @@ config SB1XXX_CORELIS
          Select compile flags that produce code that can be processed by the
          Corelis mksym utility and UDB Emulator.
 
-config RUNTIME_DEBUG
-       bool "Enable run-time debugging"
-       depends on DEBUG_KERNEL
-       help
-         If you say Y here, some debugging macros will do run-time checking.
-         If you say N here, those macros will mostly turn to no-ops.  See
-         arch/mips/include/asm/debug.h for debugging macros.
-         If unsure, say N.
-
 config DEBUG_ZBOOT
        bool "Enable compressed kernel support debugging"
        depends on DEBUG_KERNEL && SYS_SUPPORTS_ZBOOT
index b9628983d62097cbfb6bcd842f6165118993cfeb..7fa24881b708ce1583791bf5b78e5922b8299d5a 100644 (file)
@@ -6,13 +6,6 @@ config ALCHEMY_GPIOINT_AU1000
 config ALCHEMY_GPIOINT_AU1300
        bool
 
-# select this in your board config if you don't want to use the gpio
-# namespace as documented in the manuals.  In this case however you need
-# to create the necessary gpio_* functions in your board code/headers!
-# see arch/mips/include/asm/mach-au1x00/gpio.h   for more information.
-config ALCHEMY_GPIO_INDIRECT
-       def_bool n
-
 choice
        prompt "Machine type"
        depends on MIPS_ALCHEMY
index acf9a2a37f5a055a0c794d7aa62a46e75527f6a4..79efe4c6e636a3a6482553db53e3310b1cfcc6ed 100644 (file)
@@ -34,6 +34,7 @@
 #include <asm/idle.h>
 #include <asm/reboot.h>
 #include <asm/mach-au1x00/au1000.h>
+#include <asm/mach-au1x00/gpio-au1000.h>
 #include <prom.h>
 
 const char *get_system_type(void)
index 1e3b102389ef51b7749755a0bd42953dfbb3fb36..85bb75669b0d59797a626f40610292f2f60e0bb2 100644 (file)
@@ -32,6 +32,7 @@
 #include <asm/bootinfo.h>
 #include <asm/reboot.h>
 #include <asm/mach-au1x00/au1000.h>
+#include <asm/mach-au1x00/gpio-au1000.h>
 #include <asm/mach-au1x00/au1xxx_eth.h>
 #include <prom.h>
 
index f64744f3b59f77192f4ce1b76f32f96ed4e607f7..23800b8e67e5e468f5f6a5c49ef6ae188263ce56 100644 (file)
@@ -5,10 +5,5 @@
 # Makefile for the Alchemy Au1xx0 CPUs, generic files.
 #
 
-obj-y += prom.o time.o clock.o platform.o power.o \
+obj-y += prom.o time.o clock.o platform.o power.o gpiolib.o \
         setup.o sleeper.o dma.o dbdma.o vss.o irq.o usb.o
-
-# optional gpiolib support
-ifeq ($(CONFIG_ALCHEMY_GPIO_INDIRECT),)
- obj-$(CONFIG_GPIOLIB) += gpiolib.o
-endif
index 6cb60abfdcc909b0aea310736a9fa5052d8e9d6b..4c496c50edf699a6ed426f4f3d658bd2919cf6db 100644 (file)
@@ -491,7 +491,7 @@ static int au1x_ic_settype(struct irq_data *d, unsigned int flow_type)
        default:
                ret = -EINVAL;
        }
-       __irq_set_chip_handler_name_locked(d->irq, chip, handler, name);
+       irq_set_chip_handler_name_locked(d, chip, handler, name);
 
        wmb();
 
@@ -703,7 +703,7 @@ static int au1300_gpic_settype(struct irq_data *d, unsigned int type)
                return -EINVAL;
        }
 
-       __irq_set_chip_handler_name_locked(d->irq, &au1300_gpic, hdl, name);
+       irq_set_chip_handler_name_locked(d, &au1300_gpic, hdl, name);
 
        au1300_gpic_chgcfg(d->irq - ALCHEMY_GPIC_INT_BASE, GPIC_CFG_IC_MASK, s);
 
index 50e17e13c18bbc653f4d06d60255f232c6cb0b94..f99d3ec17a459237a05dd76253ed7ef26d5bbca9 100644 (file)
@@ -69,11 +69,6 @@ static int au1x_rtcmatch2_set_next_event(unsigned long delta,
        return 0;
 }
 
-static void au1x_rtcmatch2_set_mode(enum clock_event_mode mode,
-                                   struct clock_event_device *cd)
-{
-}
-
 static irqreturn_t au1x_rtcmatch2_irq(int irq, void *dev_id)
 {
        struct clock_event_device *cd = dev_id;
@@ -86,7 +81,6 @@ static struct clock_event_device au1x_rtcmatch2_clockdev = {
        .features       = CLOCK_EVT_FEAT_ONESHOT,
        .rating         = 1500,
        .set_next_event = au1x_rtcmatch2_set_next_event,
-       .set_mode       = au1x_rtcmatch2_set_mode,
        .cpumask        = cpu_all_mask,
 };
 
index c98c9ea3372c53797d317f9b43c2614c82b0f58d..324ad72d7c3622414280af50ab579e5dd107f3eb 100644 (file)
@@ -8,6 +8,7 @@
  */
 
 #include <linux/interrupt.h>
+#include <linux/irqchip/chained_irq.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
 #include <linux/irq.h>
@@ -88,10 +89,11 @@ EXPORT_SYMBOL_GPL(bcsr_mod);
 static void bcsr_csc_handler(unsigned int irq, struct irq_desc *d)
 {
        unsigned short bisr = __raw_readw(bcsr_virt + BCSR_REG_INTSTAT);
+       struct irq_chip *chip = irq_desc_get_chip(d);
 
-       disable_irq_nosync(irq);
+       chained_irq_enter(chip, d);
        generic_handle_irq(bcsr_csc_base + __ffs(bisr));
-       enable_irq(irq);
+       chained_irq_exit(chip, d);
 }
 
 static void bcsr_irq_mask(struct irq_data *d)
index 001102e197f19757eccb98b29a04ba8e75c60fce..bdeed9d13c6fe01c0c804b695af44efd16817f46 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/spi/spi_gpio.h>
 #include <linux/spi/ads7846.h>
 #include <asm/mach-au1x00/au1000.h>
+#include <asm/mach-au1x00/gpio-au1000.h>
 #include <asm/mach-au1x00/au1000_dma.h>
 #include <asm/mach-au1x00/au1100_mmc.h>
 #include <asm/mach-db1x00/bcsr.h>
index 1c64fdbe4c813c41f1a4bdb68150336e428bfb21..b58077008a5384a98e74bd76ef222a70bcca48a1 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/wm97xx.h>
 
 #include <asm/mach-au1x00/au1000.h>
+#include <asm/mach-au1x00/gpio-au1300.h>
 #include <asm/mach-au1x00/au1100_mmc.h>
 #include <asm/mach-au1x00/au1200fb.h>
 #include <asm/mach-au1x00/au1xxx_dbdma.h>
index 0fd5177e35ab27bf2fa86dcbdf7e20c58073ddf0..5740bcfdfc7f622b76402a3c0551e3c475ea7099 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/spi/flash.h>
 #include <asm/bootinfo.h>
 #include <asm/mach-au1x00/au1000.h>
+#include <asm/mach-au1x00/gpio-au1000.h>
 #include <asm/mach-au1x00/au1xxx_eth.h>
 #include <asm/mach-au1x00/au1xxx_dbdma.h>
 #include <asm/mach-au1x00/au1xxx_psc.h>
index bfeb8f3c0be66dc1a2aa3091bf9af111bc31e904..93024dc6b314d904dc297ec5691975b5fd35ea6c 100644 (file)
@@ -9,7 +9,7 @@
 #include <linux/suspend.h>
 #include <linux/sysfs.h>
 #include <asm/mach-au1x00/au1000.h>
-#include <asm/mach-au1x00/gpio.h>
+#include <asm/mach-au1x00/gpio-au1000.h>
 #include <asm/mach-db1x00/bcsr.h>
 
 /*
index d8dbd8f0c1d2924308da51f309e4b4f16a9c7111..f4930456eb8e8181098c6035dccdd1203d72ea18 100644 (file)
 #include <linux/module.h>
 #include <linux/gpio.h>
 
-#include <asm/mach-ar7/gpio.h>
+#include <asm/mach-ar7/ar7.h>
+
+#define AR7_GPIO_MAX 32
+#define TITAN_GPIO_MAX 51
 
 struct ar7_gpio_chip {
        void __iomem            *regs;
index be9ff1673ded7f2d20bbffa7897b9ac70dcedb07..462a252ea6e62364cbc276a80b5d5463abb64581 100644 (file)
@@ -39,7 +39,6 @@
 
 #include <asm/addrspace.h>
 #include <asm/mach-ar7/ar7.h>
-#include <asm/mach-ar7/gpio.h>
 #include <asm/mach-ar7/prom.h>
 
 /*****************************************************************************
index 820b7a313d9bfd593cdaa63e6374f0cf4bd15d6a..7bb9a670bb73574ce208cfc75d6a5b9945d9f35a 100644 (file)
@@ -23,7 +23,6 @@
 #include <asm/reboot.h>
 #include <asm/mach-ar7/ar7.h>
 #include <asm/mach-ar7/prom.h>
-#include <asm/mach-ar7/gpio.h>
 
 static void ar7_machine_restart(char *command)
 {
index 5c9ff692ff3ca93ec1946f98095890983357b55d..fcc382cfc77091594093d8e01e814dc9bcd4060f 100644 (file)
@@ -8,7 +8,7 @@
 # under the terms of the GNU General Public License version 2 as published
 # by the Free Software Foundation.
 
-obj-y  := prom.o setup.o irq.o common.o clock.o gpio.o
+obj-y  := prom.o setup.o irq.o common.o clock.o
 
 obj-$(CONFIG_EARLY_PRINTK)             += early_printk.o
 obj-$(CONFIG_PCI)                      += pci.o
index e5ea71277f0cf9fc19d3dd95e71afab2a8d84197..ca7cc19adfea7f01154c55f44e47b5f863499843 100644 (file)
@@ -25,9 +25,6 @@ unsigned long ath79_get_sys_clk_rate(const char *id);
 void ath79_ddr_ctrl_init(void);
 void ath79_ddr_wb_flush(unsigned int reg);
 
-void ath79_gpio_function_enable(u32 mask);
-void ath79_gpio_function_disable(u32 mask);
-void ath79_gpio_function_setup(u32 set, u32 clear);
 void ath79_gpio_init(void);
 
 #endif /* __ATH79_COMMON_H */
diff --git a/arch/mips/ath79/gpio.c b/arch/mips/ath79/gpio.c
deleted file mode 100644 (file)
index f59ccb2..0000000
+++ /dev/null
@@ -1,279 +0,0 @@
-/*
- *  Atheros AR71XX/AR724X/AR913X GPIO API support
- *
- *  Copyright (C) 2010-2011 Jaiganesh Narayanan <jnarayanan@atheros.com>
- *  Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
- *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
- *
- *  Parts of this file are based on Atheros' 2.6.15/2.6.31 BSP
- *
- *  This program is free software; you can redistribute it and/or modify it
- *  under the terms of the GNU General Public License version 2 as published
- *  by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/spinlock.h>
-#include <linux/io.h>
-#include <linux/ioport.h>
-#include <linux/gpio.h>
-#include <linux/platform_data/gpio-ath79.h>
-#include <linux/of_device.h>
-
-#include <asm/mach-ath79/ar71xx_regs.h>
-#include <asm/mach-ath79/ath79.h>
-#include "common.h"
-
-static void __iomem *ath79_gpio_base;
-static u32 ath79_gpio_count;
-static DEFINE_SPINLOCK(ath79_gpio_lock);
-
-static void __ath79_gpio_set_value(unsigned gpio, int value)
-{
-       void __iomem *base = ath79_gpio_base;
-
-       if (value)
-               __raw_writel(1 << gpio, base + AR71XX_GPIO_REG_SET);
-       else
-               __raw_writel(1 << gpio, base + AR71XX_GPIO_REG_CLEAR);
-}
-
-static int __ath79_gpio_get_value(unsigned gpio)
-{
-       return (__raw_readl(ath79_gpio_base + AR71XX_GPIO_REG_IN) >> gpio) & 1;
-}
-
-static int ath79_gpio_get_value(struct gpio_chip *chip, unsigned offset)
-{
-       return __ath79_gpio_get_value(offset);
-}
-
-static void ath79_gpio_set_value(struct gpio_chip *chip,
-                                 unsigned offset, int value)
-{
-       __ath79_gpio_set_value(offset, value);
-}
-
-static int ath79_gpio_direction_input(struct gpio_chip *chip,
-                                      unsigned offset)
-{
-       void __iomem *base = ath79_gpio_base;
-       unsigned long flags;
-
-       spin_lock_irqsave(&ath79_gpio_lock, flags);
-
-       __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_OE) & ~(1 << offset),
-                    base + AR71XX_GPIO_REG_OE);
-
-       spin_unlock_irqrestore(&ath79_gpio_lock, flags);
-
-       return 0;
-}
-
-static int ath79_gpio_direction_output(struct gpio_chip *chip,
-                                       unsigned offset, int value)
-{
-       void __iomem *base = ath79_gpio_base;
-       unsigned long flags;
-
-       spin_lock_irqsave(&ath79_gpio_lock, flags);
-
-       if (value)
-               __raw_writel(1 << offset, base + AR71XX_GPIO_REG_SET);
-       else
-               __raw_writel(1 << offset, base + AR71XX_GPIO_REG_CLEAR);
-
-       __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_OE) | (1 << offset),
-                    base + AR71XX_GPIO_REG_OE);
-
-       spin_unlock_irqrestore(&ath79_gpio_lock, flags);
-
-       return 0;
-}
-
-static int ar934x_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
-{
-       void __iomem *base = ath79_gpio_base;
-       unsigned long flags;
-
-       spin_lock_irqsave(&ath79_gpio_lock, flags);
-
-       __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_OE) | (1 << offset),
-                    base + AR71XX_GPIO_REG_OE);
-
-       spin_unlock_irqrestore(&ath79_gpio_lock, flags);
-
-       return 0;
-}
-
-static int ar934x_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
-                                       int value)
-{
-       void __iomem *base = ath79_gpio_base;
-       unsigned long flags;
-
-       spin_lock_irqsave(&ath79_gpio_lock, flags);
-
-       if (value)
-               __raw_writel(1 << offset, base + AR71XX_GPIO_REG_SET);
-       else
-               __raw_writel(1 << offset, base + AR71XX_GPIO_REG_CLEAR);
-
-       __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_OE) & ~(1 << offset),
-                    base + AR71XX_GPIO_REG_OE);
-
-       spin_unlock_irqrestore(&ath79_gpio_lock, flags);
-
-       return 0;
-}
-
-static struct gpio_chip ath79_gpio_chip = {
-       .label                  = "ath79",
-       .get                    = ath79_gpio_get_value,
-       .set                    = ath79_gpio_set_value,
-       .direction_input        = ath79_gpio_direction_input,
-       .direction_output       = ath79_gpio_direction_output,
-       .base                   = 0,
-};
-
-static void __iomem *ath79_gpio_get_function_reg(void)
-{
-       u32 reg = 0;
-
-       if (soc_is_ar71xx() ||
-           soc_is_ar724x() ||
-           soc_is_ar913x() ||
-           soc_is_ar933x())
-               reg = AR71XX_GPIO_REG_FUNC;
-       else if (soc_is_ar934x())
-               reg = AR934X_GPIO_REG_FUNC;
-       else
-               BUG();
-
-       return ath79_gpio_base + reg;
-}
-
-void ath79_gpio_function_setup(u32 set, u32 clear)
-{
-       void __iomem *reg = ath79_gpio_get_function_reg();
-       unsigned long flags;
-
-       spin_lock_irqsave(&ath79_gpio_lock, flags);
-
-       __raw_writel((__raw_readl(reg) & ~clear) | set, reg);
-       /* flush write */
-       __raw_readl(reg);
-
-       spin_unlock_irqrestore(&ath79_gpio_lock, flags);
-}
-
-void ath79_gpio_function_enable(u32 mask)
-{
-       ath79_gpio_function_setup(mask, 0);
-}
-
-void ath79_gpio_function_disable(u32 mask)
-{
-       ath79_gpio_function_setup(0, mask);
-}
-
-static const struct of_device_id ath79_gpio_of_match[] = {
-       { .compatible = "qca,ar7100-gpio" },
-       { .compatible = "qca,ar9340-gpio" },
-       {},
-};
-
-static int ath79_gpio_probe(struct platform_device *pdev)
-{
-       struct ath79_gpio_platform_data *pdata = pdev->dev.platform_data;
-       struct device_node *np = pdev->dev.of_node;
-       struct resource *res;
-       bool oe_inverted;
-       int err;
-
-       if (np) {
-               err = of_property_read_u32(np, "ngpios", &ath79_gpio_count);
-               if (err) {
-                       dev_err(&pdev->dev, "ngpios property is not valid\n");
-                       return err;
-               }
-               if (ath79_gpio_count >= 32) {
-                       dev_err(&pdev->dev, "ngpios must be less than 32\n");
-                       return -EINVAL;
-               }
-               oe_inverted = of_device_is_compatible(np, "qca,ar9340-gpio");
-       } else if (pdata) {
-               ath79_gpio_count = pdata->ngpios;
-               oe_inverted = pdata->oe_inverted;
-       } else {
-               dev_err(&pdev->dev, "No DT node or platform data found\n");
-               return -EINVAL;
-       }
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       ath79_gpio_base = devm_ioremap_nocache(
-               &pdev->dev, res->start, resource_size(res));
-       if (!ath79_gpio_base)
-               return -ENOMEM;
-
-       ath79_gpio_chip.dev = &pdev->dev;
-       ath79_gpio_chip.ngpio = ath79_gpio_count;
-       if (oe_inverted) {
-               ath79_gpio_chip.direction_input = ar934x_gpio_direction_input;
-               ath79_gpio_chip.direction_output = ar934x_gpio_direction_output;
-       }
-
-       err = gpiochip_add(&ath79_gpio_chip);
-       if (err) {
-               dev_err(&pdev->dev,
-                       "cannot add AR71xx GPIO chip, error=%d", err);
-               return err;
-       }
-
-       return 0;
-}
-
-static struct platform_driver ath79_gpio_driver = {
-       .driver = {
-               .name = "ath79-gpio",
-               .of_match_table = ath79_gpio_of_match,
-       },
-       .probe = ath79_gpio_probe,
-};
-
-module_platform_driver(ath79_gpio_driver);
-
-int gpio_get_value(unsigned gpio)
-{
-       if (gpio < ath79_gpio_count)
-               return __ath79_gpio_get_value(gpio);
-
-       return __gpio_get_value(gpio);
-}
-EXPORT_SYMBOL(gpio_get_value);
-
-void gpio_set_value(unsigned gpio, int value)
-{
-       if (gpio < ath79_gpio_count)
-               __ath79_gpio_set_value(gpio, value);
-       else
-               __gpio_set_value(gpio, value);
-}
-EXPORT_SYMBOL(gpio_set_value);
-
-int gpio_to_irq(unsigned gpio)
-{
-       /* FIXME */
-       return -EINVAL;
-}
-EXPORT_SYMBOL(gpio_to_irq);
-
-int irq_to_gpio(unsigned irq)
-{
-       /* FIXME */
-       return -EINVAL;
-}
-EXPORT_SYMBOL(irq_to_gpio);
index afb009603f7fad138ccc12a1c26ffc7bd5422bf6..807132b838b24914d072c6ed81a0f86b2e57d56a 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/interrupt.h>
 #include <linux/irqchip.h>
 #include <linux/of_irq.h>
-#include "../../../drivers/irqchip/irqchip.h"
 
 #include <asm/irq_cpu.h>
 #include <asm/mipsregs.h>
@@ -124,8 +123,6 @@ static void ar934x_ip2_irq_dispatch(unsigned int irq, struct irq_desc *desc)
 {
        u32 status;
 
-       disable_irq_nosync(irq);
-
        status = ath79_reset_rr(AR934X_RESET_REG_PCIE_WMAC_INT_STATUS);
 
        if (status & AR934X_PCIE_WMAC_INT_PCIE_ALL) {
@@ -137,8 +134,6 @@ static void ar934x_ip2_irq_dispatch(unsigned int irq, struct irq_desc *desc)
        } else {
                spurious_interrupt();
        }
-
-       enable_irq(irq);
 }
 
 static void ar934x_ip2_irq_init(void)
@@ -157,14 +152,12 @@ static void qca955x_ip2_irq_dispatch(unsigned int irq, struct irq_desc *desc)
 {
        u32 status;
 
-       disable_irq_nosync(irq);
-
        status = ath79_reset_rr(QCA955X_RESET_REG_EXT_INT_STATUS);
        status &= QCA955X_EXT_INT_PCIE_RC1_ALL | QCA955X_EXT_INT_WMAC_ALL;
 
        if (status == 0) {
                spurious_interrupt();
-               goto enable;
+               return;
        }
 
        if (status & QCA955X_EXT_INT_PCIE_RC1_ALL) {
@@ -176,17 +169,12 @@ static void qca955x_ip2_irq_dispatch(unsigned int irq, struct irq_desc *desc)
                /* TODO: flush DDR? */
                generic_handle_irq(ATH79_IP2_IRQ(1));
        }
-
-enable:
-       enable_irq(irq);
 }
 
 static void qca955x_ip3_irq_dispatch(unsigned int irq, struct irq_desc *desc)
 {
        u32 status;
 
-       disable_irq_nosync(irq);
-
        status = ath79_reset_rr(QCA955X_RESET_REG_EXT_INT_STATUS);
        status &= QCA955X_EXT_INT_PCIE_RC2_ALL |
                  QCA955X_EXT_INT_USB1 |
@@ -194,7 +182,7 @@ static void qca955x_ip3_irq_dispatch(unsigned int irq, struct irq_desc *desc)
 
        if (status == 0) {
                spurious_interrupt();
-               goto enable;
+               return;
        }
 
        if (status & QCA955X_EXT_INT_USB1) {
@@ -211,9 +199,6 @@ static void qca955x_ip3_irq_dispatch(unsigned int irq, struct irq_desc *desc)
                /* TODO: flush DDR? */
                generic_handle_irq(ATH79_IP3_IRQ(2));
        }
-
-enable:
-       enable_irq(irq);
 }
 
 static void qca955x_irq_init(void)
index 08a4abf09a33e9b069680a965a9dbe3b69a091d9..52caa75bfe4e5eb1ec43b0e4152fbb1230d0ae21 100644 (file)
@@ -396,10 +396,9 @@ static int __init bcm47xx_buttons_copy(const struct gpio_keys_button *buttons,
 {
        size_t size = nbuttons * sizeof(*buttons);
 
-       bcm47xx_button_pdata.buttons = kmalloc(size, GFP_KERNEL);
+       bcm47xx_button_pdata.buttons = kmemdup(buttons, size, GFP_KERNEL);
        if (!bcm47xx_button_pdata.buttons)
                return -ENOMEM;
-       memcpy(bcm47xx_button_pdata.buttons, buttons, size);
        bcm47xx_button_pdata.nbuttons = nbuttons;
 
        return 0;
index e3e808a6c54261841638e975ae8518aaee1fa2f0..1a47ec2a09062b59bf76b1b4de9270435698b88e 100644 (file)
@@ -60,7 +60,7 @@ static inline int enable_irq_for_cpu(int cpu, struct irq_data *d,
        if (m)
                enable &= cpumask_test_cpu(cpu, m);
        else if (irqd_affinity_was_set(d))
-               enable &= cpumask_test_cpu(cpu, d->affinity);
+               enable &= cpumask_test_cpu(cpu, irq_data_get_affinity_mask(d));
 #endif
        return enable;
 }
@@ -365,9 +365,9 @@ static int bcm63xx_external_irq_set_type(struct irq_data *d,
 
        irqd_set_trigger_type(d, flow_type);
        if (flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
-               __irq_set_handler_locked(d->irq, handle_level_irq);
+               irq_set_handler_locked(d, handle_level_irq);
        else
-               __irq_set_handler_locked(d->irq, handle_edge_irq);
+               irq_set_handler_locked(d, handle_edge_irq);
 
        return IRQ_SET_MASK_OK_NOCOPY;
 }
index dc91bde10d622e3d3fd90f77646f33f3232b6a9b..d5bdee115f22f73058d464e5cc88aee8abc7cf46 100644 (file)
@@ -78,7 +78,7 @@ endif
 
 vmlinuzobjs-y += $(obj)/piggy.o
 
-quiet_cmd_zld = LD     $@
+quiet_cmd_zld = LD      $@
       cmd_zld = $(LD) $(LDFLAGS) -Ttext $(VMLINUZ_LOAD_ADDRESS) -T $< $(vmlinuzobjs-y) -o $@
 quiet_cmd_strip = STRIP          $@
       cmd_strip = $(STRIP) -s $@
index 89ad04808c024758232fb2afeb06ac0e68a7dde3..ec16ec2d8d02765a8d2f935c07e0b08f563dddf0 100644 (file)
                                read-only;
                        };
                };
+
+               gpio: xlp_gpio@34100 {
+                       compatible = "netlogic,xlp832-gpio";
+                       reg = <0 0x34100 0x1000>;
+                       #gpio-cells = <2>;
+                       gpio-controller;
+
+                       #interrupt-cells = <2>;
+                       interrupt-parent = <&pic>;
+                       interrupts = <39>;
+                       interrupt-controller;
+               };
        };
 
        chosen {
index 63e62b7bd75892dddd28e360522ff19b93985278..4bcebe641d8e9ff5ad5579251d3b5d60c175f3c7 100644 (file)
                                read-only;
                        };
                };
+
+               gpio: xlp_gpio@34100 {
+                       compatible = "netlogic,xlp208-gpio";
+                       reg = <0 0x34100 0x1000>;
+                       #gpio-cells = <2>;
+                       gpio-controller;
+
+                       #interrupt-cells = <2>;
+                       interrupt-parent = <&pic>;
+                       interrupts = <39>;
+                       interrupt-controller;
+               };
        };
 
        chosen {
index bb4ecd1d47fc295bb2b5d330e044a780b44533a2..b3ccb82ad7e4c54cf2b2b12ae044f03939e6b741 100644 (file)
                        };
                };
 
+               gpio: xlp_gpio@114100 {
+                       compatible = "netlogic,xlp980-gpio";
+                       reg = <0 0x114100 0x1000>;
+                       #gpio-cells = <2>;
+                       gpio-controller;
+
+                       #interrupt-cells = <2>;
+                       interrupt-parent = <&pic>;
+                       interrupts = <39>;
+                       interrupt-controller;
+               };
        };
 
        chosen {
index 7188aed2ea2ed96000566fe48ea9f89eab8373e0..3783639a318aad230d5aa2297b518cf69d023342 100644 (file)
                        };
                };
 
+               gpio: xlp_gpio@114100 {
+                       compatible = "netlogic,xlp532-gpio";
+                       reg = <0 0x114100 0x1000>;
+                       #gpio-cells = <2>;
+                       gpio-controller;
+
+                       #interrupt-cells = <2>;
+                       interrupt-parent = <&pic>;
+                       interrupts = <39>;
+                       interrupt-controller;
+               };
        };
 
        chosen {
index 1ebd00edaacc4490d3f95db0484aeb008787faca..44d6640c14412353d0ec31f02bca45276863f3db 100644 (file)
                                read-only;
                        };
                };
+
+               gpio: xlp_gpio@34100 {
+                       compatible = "netlogic,xlp316-gpio";
+                       reg = <0 0x34100 0x1000>;
+                       #gpio-cells = <2>;
+                       gpio-controller;
+
+                       #interrupt-cells = <2>;
+                       interrupt-parent = <&pic>;
+                       interrupts = <39>;
+                       interrupt-controller;
+               };
        };
 
        chosen {
index 9eb0feef441721362ee5e699e2788c1ffaf3b391..36e30d65ba05bc4237a656670c18eea447f1232a 100644 (file)
@@ -195,6 +195,12 @@ int cvmx_helper_board_get_mii_address(int ipd_port)
                        return 8;
                else
                        return -1;
+       case CVMX_BOARD_TYPE_KONTRON_S1901:
+               if (ipd_port == CVMX_HELPER_BOARD_MGMT_IPD_PORT)
+                       return 1;
+               else
+                       return -1;
+
        }
 
        /* Some unknown board. Somebody forgot to update this function... */
index 453d7f66459aabd517990dd4e0efdf07fd679f2d..b45b2975746db79342e74bb9146c167824786e87 100644 (file)
@@ -95,9 +95,9 @@ int cvmx_helper_dump_packet(cvmx_wqe_t *work)
        uint8_t *data_address;
        uint8_t *end_of_data;
 
-       cvmx_dprintf("Packet Length:   %u\n", work->len);
-       cvmx_dprintf("    Input Port:  %u\n", work->ipprt);
-       cvmx_dprintf("    QoS:         %u\n", work->qos);
+       cvmx_dprintf("Packet Length:   %u\n", work->word1.len);
+       cvmx_dprintf("    Input Port:  %u\n", cvmx_wqe_get_port(work));
+       cvmx_dprintf("    QoS:         %u\n", cvmx_wqe_get_qos(work));
        cvmx_dprintf("    Buffers:     %u\n", work->word2.s.bufs);
 
        if (work->word2.s.bufs == 0) {
@@ -127,7 +127,7 @@ int cvmx_helper_dump_packet(cvmx_wqe_t *work)
                }
        } else
                buffer_ptr = work->packet_ptr;
-       remaining_bytes = work->len;
+       remaining_bytes = work->word1.len;
 
        while (remaining_bytes) {
                start_of_buffer =
@@ -382,6 +382,10 @@ int cvmx_helper_get_ipd_port(int interface, int port)
                return port + 32;
        case 3:
                return port + 36;
+       case 4:
+               return port + 40;
+       case 5:
+               return port + 44;
        }
        return -1;
 }
@@ -404,6 +408,10 @@ int cvmx_helper_get_interface_num(int ipd_port)
                return 2;
        else if (ipd_port < 40)
                return 3;
+       else if (ipd_port < 44)
+               return 4;
+       else if (ipd_port < 48)
+               return 5;
        else
                cvmx_dprintf("cvmx_helper_get_interface_num: Illegal IPD "
                             "port number\n");
@@ -428,6 +436,10 @@ int cvmx_helper_get_interface_index_num(int ipd_port)
                return ipd_port & 3;
        else if (ipd_port < 40)
                return ipd_port & 3;
+       else if (ipd_port < 44)
+               return ipd_port & 3;
+       else if (ipd_port < 48)
+               return ipd_port & 3;
        else
                cvmx_dprintf("cvmx_helper_get_interface_index_num: "
                             "Illegal IPD port number\n");
index 7653b7e92197f01d5091847172bb9c1087b2f29c..a56ee590de1f36b50a4f2f7bc962f01e224bc141 100644 (file)
@@ -124,6 +124,13 @@ int __cvmx_helper_xaui_enable(int interface)
        union cvmx_gmxx_tx_int_en gmx_tx_int_en;
        union cvmx_pcsxx_int_en_reg pcsx_int_en_reg;
 
+       /* Setup PKND */
+       if (octeon_has_feature(OCTEON_FEATURE_PKND)) {
+               gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(0, interface));
+               gmx_cfg.s.pknd = cvmx_helper_get_ipd_port(interface, 0);
+               cvmx_write_csr(CVMX_GMXX_PRTX_CFG(0, interface), gmx_cfg.u64);
+       }
+
        /* (1) Interface has already been enabled. */
 
        /* (2) Disable GMX. */
@@ -151,7 +158,12 @@ int __cvmx_helper_xaui_enable(int interface)
        /* (4)c Aply reset sequence */
        xauiCtl.u64 = cvmx_read_csr(CVMX_PCSXX_CONTROL1_REG(interface));
        xauiCtl.s.lo_pwr = 0;
-       xauiCtl.s.reset = 1;
+
+       /* Issuing a reset here seems to hang some CN68XX chips. */
+       if (!OCTEON_IS_MODEL(OCTEON_CN68XX_PASS1_X) &&
+           !OCTEON_IS_MODEL(OCTEON_CN68XX_PASS2_X))
+               xauiCtl.s.reset = 1;
+
        cvmx_write_csr(CVMX_PCSXX_CONTROL1_REG(interface), xauiCtl.u64);
 
        /* Wait for PCS to come out of reset */
index 7e5cf7a5e2f3264b637e820dca92635d468e7465..376701f41cc28eb6a78f227836b105af843a794b 100644 (file)
@@ -83,6 +83,8 @@ static cvmx_helper_link_info_t
  */
 int cvmx_helper_get_number_of_interfaces(void)
 {
+       if (OCTEON_IS_MODEL(OCTEON_CN68XX))
+               return 9;
        if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN52XX))
                return 4;
        else
@@ -656,6 +658,21 @@ static int __cvmx_helper_global_setup_pko(void)
        fau_to.s.tout_val = 0xfff;
        fau_to.s.tout_enb = 0;
        cvmx_write_csr(CVMX_IOB_FAU_TIMEOUT, fau_to.u64);
+
+       if (OCTEON_IS_MODEL(OCTEON_CN68XX)) {
+               union cvmx_pko_reg_min_pkt min_pkt;
+
+               min_pkt.u64 = 0;
+               min_pkt.s.size1 = 59;
+               min_pkt.s.size2 = 59;
+               min_pkt.s.size3 = 59;
+               min_pkt.s.size4 = 59;
+               min_pkt.s.size5 = 59;
+               min_pkt.s.size6 = 59;
+               min_pkt.s.size7 = 59;
+               cvmx_write_csr(CVMX_PKO_REG_MIN_PKT, min_pkt.u64);
+       }
+
        return 0;
 }
 
index 008b881cdf6477be82045ede5fa76867724f26cb..87be167a7a6ae07ce1b71f574d47471f5781f6ee 100644 (file)
  * Internal state of packet output
  */
 
+static int __cvmx_pko_int(int interface, int index)
+{
+       switch (interface) {
+       case 0:
+               return index;
+       case 1:
+               return 4;
+       case 2:
+               return index + 0x08;
+       case 3:
+               return index + 0x0c;
+       case 4:
+               return index + 0x10;
+       case 5:
+               return 0x1c;
+       case 6:
+               return 0x1d;
+       case 7:
+               return 0x1e;
+       case 8:
+               return 0x1f;
+       default:
+               return -1;
+       }
+}
+
+static void __cvmx_pko_iport_config(int pko_port)
+{
+       int queue;
+       const int num_queues = 1;
+       const int base_queue = pko_port;
+       const int static_priority_end = 1;
+       const int static_priority_base = 1;
+
+       for (queue = 0; queue < num_queues; queue++) {
+               union cvmx_pko_mem_iqueue_ptrs config;
+               cvmx_cmd_queue_result_t cmd_res;
+               uint64_t *buf_ptr;
+
+               config.u64              = 0;
+               config.s.index          = queue;
+               config.s.qid            = base_queue + queue;
+               config.s.ipid           = pko_port;
+               config.s.tail           = (queue == (num_queues - 1));
+               config.s.s_tail         = (queue == static_priority_end);
+               config.s.static_p       = (static_priority_base >= 0);
+               config.s.static_q       = (queue <= static_priority_end);
+               config.s.qos_mask       = 0xff;
+
+               cmd_res = cvmx_cmd_queue_initialize(
+                               CVMX_CMD_QUEUE_PKO(base_queue + queue),
+                               CVMX_PKO_MAX_QUEUE_DEPTH,
+                               CVMX_FPA_OUTPUT_BUFFER_POOL,
+                               (CVMX_FPA_OUTPUT_BUFFER_POOL_SIZE -
+                                CVMX_PKO_COMMAND_BUFFER_SIZE_ADJUST * 8));
+
+               WARN(cmd_res,
+                    "%s: cmd_res=%d pko_port=%d base_queue=%d num_queues=%d queue=%d\n",
+                       __func__, (int)cmd_res, pko_port, base_queue,
+                       num_queues, queue);
+
+               buf_ptr = (uint64_t *)cvmx_cmd_queue_buffer(
+                               CVMX_CMD_QUEUE_PKO(base_queue + queue));
+               config.s.buf_ptr = cvmx_ptr_to_phys(buf_ptr) >> 7;
+               CVMX_SYNCWS;
+               cvmx_write_csr(CVMX_PKO_MEM_IQUEUE_PTRS, config.u64);
+       }
+}
+
+static void __cvmx_pko_queue_alloc_o68(void)
+{
+       int port;
+
+       for (port = 0; port < 48; port++)
+               __cvmx_pko_iport_config(port);
+}
+
+static void __cvmx_pko_port_map_o68(void)
+{
+       int port;
+       int interface, index;
+       cvmx_helper_interface_mode_t mode;
+       union cvmx_pko_mem_iport_ptrs config;
+
+       /*
+        * Initialize every iport with the invalid eid.
+        */
+       config.u64 = 0;
+       config.s.eid = 31; /* Invalid */
+       for (port = 0; port < 128; port++) {
+               config.s.ipid = port;
+               cvmx_write_csr(CVMX_PKO_MEM_IPORT_PTRS, config.u64);
+       }
+
+       /*
+        * Set up PKO_MEM_IPORT_PTRS
+        */
+       for (port = 0; port < 48; port++) {
+               interface = cvmx_helper_get_interface_num(port);
+               index = cvmx_helper_get_interface_index_num(port);
+               mode = cvmx_helper_interface_get_mode(interface);
+               if (mode == CVMX_HELPER_INTERFACE_MODE_DISABLED)
+                       continue;
+
+               config.s.ipid = port;
+               config.s.qos_mask = 0xff;
+               config.s.crc = 1;
+               config.s.min_pkt = 1;
+               config.s.intr = __cvmx_pko_int(interface, index);
+               config.s.eid = config.s.intr;
+               config.s.pipe = (mode == CVMX_HELPER_INTERFACE_MODE_LOOP) ?
+                       index : port;
+               cvmx_write_csr(CVMX_PKO_MEM_IPORT_PTRS, config.u64);
+       }
+}
+
+static void __cvmx_pko_chip_init(void)
+{
+       int i;
+
+       if (OCTEON_IS_MODEL(OCTEON_CN68XX)) {
+               __cvmx_pko_port_map_o68();
+               __cvmx_pko_queue_alloc_o68();
+               return;
+       }
+
+       /*
+        * Initialize queues
+        */
+       for (i = 0; i < CVMX_PKO_MAX_OUTPUT_QUEUES; i++) {
+               const uint64_t priority = 8;
+
+               cvmx_pko_config_port(CVMX_PKO_MEM_QUEUE_PTRS_ILLEGAL_PID, i, 1,
+                                    &priority);
+       }
+}
+
 /**
  * Call before any other calls to initialize the packet
  * output system.  This does chip global config, and should only be
 
 void cvmx_pko_initialize_global(void)
 {
-       int i;
-       uint64_t priority = 8;
        union cvmx_pko_reg_cmd_buf config;
 
        /*
@@ -62,9 +197,10 @@ void cvmx_pko_initialize_global(void)
 
        cvmx_write_csr(CVMX_PKO_REG_CMD_BUF, config.u64);
 
-       for (i = 0; i < CVMX_PKO_MAX_OUTPUT_QUEUES; i++)
-               cvmx_pko_config_port(CVMX_PKO_MEM_QUEUE_PTRS_ILLEGAL_PID, i, 1,
-                                    &priority);
+       /*
+        * Chip-specific setup.
+        */
+       __cvmx_pko_chip_init();
 
        /*
         * If we aren't using all of the queues optimize PKO's
@@ -212,6 +348,9 @@ cvmx_pko_status_t cvmx_pko_config_port(uint64_t port, uint64_t base_queue,
        int static_priority_base = -1;
        int static_priority_end = -1;
 
+       if (OCTEON_IS_MODEL(OCTEON_CN68XX))
+               return CVMX_PKO_SUCCESS;
+
        if ((port >= CVMX_PKO_NUM_OUTPUT_PORTS)
            && (port != CVMX_PKO_MEM_QUEUE_PTRS_ILLEGAL_PID)) {
                cvmx_dprintf("ERROR: cvmx_pko_config_port: Invalid port %llu\n",
index d8124a3c5a85308927f2daaaf92781bb2d27fc64..f26c3c661cca9eae9051f2f822a8ef61fd8c63a0 100644 (file)
@@ -225,13 +225,14 @@ static int next_cpu_for_irq(struct irq_data *data)
 
 #ifdef CONFIG_SMP
        int cpu;
-       int weight = cpumask_weight(data->affinity);
+       struct cpumask *mask = irq_data_get_affinity_mask(data);
+       int weight = cpumask_weight(mask);
        struct octeon_ciu_chip_data *cd = irq_data_get_irq_chip_data(data);
 
        if (weight > 1) {
                cpu = cd->current_cpu;
                for (;;) {
-                       cpu = cpumask_next(cpu, data->affinity);
+                       cpu = cpumask_next(cpu, mask);
                        if (cpu >= nr_cpu_ids) {
                                cpu = -1;
                                continue;
@@ -240,7 +241,7 @@ static int next_cpu_for_irq(struct irq_data *data)
                        }
                }
        } else if (weight == 1) {
-               cpu = cpumask_first(data->affinity);
+               cpu = cpumask_first(mask);
        } else {
                cpu = smp_processor_id();
        }
@@ -662,6 +663,11 @@ static int octeon_irq_ciu_gpio_set_type(struct irq_data *data, unsigned int t)
        irqd_set_trigger_type(data, t);
        octeon_irq_gpio_setup(data);
 
+       if (irqd_get_trigger_type(data) & IRQ_TYPE_EDGE_BOTH)
+               irq_set_handler_locked(data, handle_edge_irq);
+       else
+               irq_set_handler_locked(data, handle_level_irq);
+
        return IRQ_SET_MASK_OK;
 }
 
@@ -696,32 +702,23 @@ static void octeon_irq_ciu_gpio_ack(struct irq_data *data)
        cvmx_write_csr(CVMX_GPIO_INT_CLR, mask);
 }
 
-static void octeon_irq_handle_trigger(unsigned int irq, struct irq_desc *desc)
-{
-       struct irq_data *data = irq_desc_get_irq_data(desc);
-
-       if (irqd_get_trigger_type(data) & IRQ_TYPE_EDGE_BOTH)
-               handle_edge_irq(irq, desc);
-       else
-               handle_level_irq(irq, desc);
-}
-
 #ifdef CONFIG_SMP
 
 static void octeon_irq_cpu_offline_ciu(struct irq_data *data)
 {
        int cpu = smp_processor_id();
        cpumask_t new_affinity;
+       struct cpumask *mask = irq_data_get_affinity_mask(data);
 
-       if (!cpumask_test_cpu(cpu, data->affinity))
+       if (!cpumask_test_cpu(cpu, mask))
                return;
 
-       if (cpumask_weight(data->affinity) > 1) {
+       if (cpumask_weight(mask) > 1) {
                /*
                 * It has multi CPU affinity, just remove this CPU
                 * from the affinity set.
                 */
-               cpumask_copy(&new_affinity, data->affinity);
+               cpumask_copy(&new_affinity, mask);
                cpumask_clear_cpu(cpu, &new_affinity);
        } else {
                /* Otherwise, put it on lowest numbered online CPU. */
@@ -1227,8 +1224,13 @@ static int octeon_irq_gpio_map(struct irq_domain *d,
                octeon_irq_ciu_to_irq[line][bit] != 0)
                return -EINVAL;
 
+       /*
+        * Default to handle_level_irq. If the DT contains a different
+        * trigger type, it will call the irq_set_type callback and
+        * the handler gets updated.
+        */
        r = octeon_irq_set_ciu_mapping(virq, line, bit, hw,
-               octeon_irq_gpio_chip, octeon_irq_handle_trigger);
+                                      octeon_irq_gpio_chip, handle_level_irq);
        return r;
 }
 
index 1f8546081d2068f3adaef34892354b9e6fb2119f..40ec4ca3f946a9238afa6e0edd25c0440f86a36b 100644 (file)
@@ -16,6 +16,5 @@ generic-y += sections.h
 generic-y += segment.h
 generic-y += serial.h
 generic-y += trace_clock.h
-generic-y += ucontext.h
 generic-y += user.h
 generic-y += xor.h
index 7186bb51b89b2adea15bced173787c2513b924af..37f84078e78abbe3f6b85841461c8bccc62d6c9a 100644 (file)
@@ -20,6 +20,10 @@ struct mips_abi {
                                     struct pt_regs *regs, sigset_t *set);
        const unsigned long     rt_signal_return_offset;
        const unsigned long     restart;
+
+       unsigned        off_sc_fpregs;
+       unsigned        off_sc_fpc_csr;
+       unsigned        off_sc_used_math;
 };
 
 #endif /* _ASM_ABI_H */
index 76317a70200d18048404438bd85b69fb8bf8ec3e..867f924b05c79522a2d397d0002bc8a1397319e2 100644 (file)
        .set    pop
        .endm
 
+       .macro  ld_b    wd, off, base
+       .set    push
+       .set    mips32r2
+       .set    msa
+       ld.b    $w\wd, \off(\base)
+       .set    pop
+       .endm
+
+       .macro  ld_h    wd, off, base
+       .set    push
+       .set    mips32r2
+       .set    msa
+       ld.h    $w\wd, \off(\base)
+       .set    pop
+       .endm
+
+       .macro  ld_w    wd, off, base
+       .set    push
+       .set    mips32r2
+       .set    msa
+       ld.w    $w\wd, \off(\base)
+       .set    pop
+       .endm
+
        .macro  ld_d    wd, off, base
        .set    push
        .set    mips32r2
        .set    pop
        .endm
 
+       .macro  st_b    wd, off, base
+       .set    push
+       .set    mips32r2
+       .set    msa
+       st.b    $w\wd, \off(\base)
+       .set    pop
+       .endm
+
+       .macro  st_h    wd, off, base
+       .set    push
+       .set    mips32r2
+       .set    msa
+       st.h    $w\wd, \off(\base)
+       .set    pop
+       .endm
+
+       .macro  st_w    wd, off, base
+       .set    push
+       .set    mips32r2
+       .set    msa
+       st.w    $w\wd, \off(\base)
+       .set    pop
+       .endm
+
        .macro  st_d    wd, off, base
        .set    push
        .set    mips32r2
 #ifdef CONFIG_CPU_MICROMIPS
 #define CFC_MSA_INSN           0x587e0056
 #define CTC_MSA_INSN           0x583e0816
+#define LDB_MSA_INSN           0x58000807
+#define LDH_MSA_INSN           0x58000817
+#define LDW_MSA_INSN           0x58000827
 #define LDD_MSA_INSN           0x58000837
+#define STB_MSA_INSN           0x5800080f
+#define STH_MSA_INSN           0x5800081f
+#define STW_MSA_INSN           0x5800082f
 #define STD_MSA_INSN           0x5800083f
 #define COPY_UW_MSA_INSN       0x58f00056
 #define COPY_UD_MSA_INSN       0x58f80056
 #else
 #define CFC_MSA_INSN           0x787e0059
 #define CTC_MSA_INSN           0x783e0819
+#define LDB_MSA_INSN           0x78000820
+#define LDH_MSA_INSN           0x78000821
+#define LDW_MSA_INSN           0x78000822
 #define LDD_MSA_INSN           0x78000823
+#define STB_MSA_INSN           0x78000824
+#define STH_MSA_INSN           0x78000825
+#define STW_MSA_INSN           0x78000826
 #define STD_MSA_INSN           0x78000827
 #define COPY_UW_MSA_INSN       0x78f00059
 #define COPY_UD_MSA_INSN       0x78f80059
        .set    pop
        .endm
 
+       .macro  ld_b    wd, off, base
+       .set    push
+       .set    noat
+       SET_HARDFLOAT
+       addu    $1, \base, \off
+       .word   LDB_MSA_INSN | (\wd << 6)
+       .set    pop
+       .endm
+
+       .macro  ld_h    wd, off, base
+       .set    push
+       .set    noat
+       SET_HARDFLOAT
+       addu    $1, \base, \off
+       .word   LDH_MSA_INSN | (\wd << 6)
+       .set    pop
+       .endm
+
+       .macro  ld_w    wd, off, base
+       .set    push
+       .set    noat
+       SET_HARDFLOAT
+       addu    $1, \base, \off
+       .word   LDW_MSA_INSN | (\wd << 6)
+       .set    pop
+       .endm
+
        .macro  ld_d    wd, off, base
        .set    push
        .set    noat
        .set    pop
        .endm
 
+       .macro  st_b    wd, off, base
+       .set    push
+       .set    noat
+       SET_HARDFLOAT
+       addu    $1, \base, \off
+       .word   STB_MSA_INSN | (\wd << 6)
+       .set    pop
+       .endm
+
+       .macro  st_h    wd, off, base
+       .set    push
+       .set    noat
+       SET_HARDFLOAT
+       addu    $1, \base, \off
+       .word   STH_MSA_INSN | (\wd << 6)
+       .set    pop
+       .endm
+
+       .macro  st_w    wd, off, base
+       .set    push
+       .set    noat
+       SET_HARDFLOAT
+       addu    $1, \base, \off
+       .word   STW_MSA_INSN | (\wd << 6)
+       .set    pop
+       .endm
+
        .macro  st_d    wd, off, base
        .set    push
        .set    noat
index 16e22ce9719fdf7b801bd7c003fc916019d9dd71..bece2064cc8cbf24f6c36c603b501c6b0dc19edd 100644 (file)
@@ -53,7 +53,7 @@ struct mips_cdmm_driver {
  * mips_cdmm_phys_base() - Choose a physical base address for CDMM region.
  *
  * Picking a suitable physical address at which to map the CDMM region is
- * platform specific, so this weak function can be defined by platform code to
+ * platform specific, so this function can be defined by platform code to
  * pick a suitable value if none is configured by the bootloader.
  *
  * This address must be 32kB aligned, and the region occupies a maximum of 32kB
@@ -61,7 +61,7 @@ struct mips_cdmm_driver {
  *
  * Returns:    Physical base address for CDMM region, or 0 on failure.
  */
-phys_addr_t __weak mips_cdmm_phys_base(void);
+phys_addr_t mips_cdmm_phys_base(void);
 
 extern struct bus_type mips_cdmm_bustype;
 void __iomem *mips_cdmm_early_probe(unsigned int dev_type);
index f0edf6fcd002b926687f156cbed222338c53fb8e..2e13a038d2600d74ca45b70b098314cf891a96b4 100644 (file)
@@ -21,7 +21,6 @@ DECLARE_PER_CPU(struct clock_event_device, mips_clockevent_device);
 
 void mips_event_handler(struct clock_event_device *dev);
 int c0_compare_int_usable(void);
-void mips_set_clock_mode(enum clock_event_mode, struct clock_event_device *);
 irqreturn_t c0_compare_interrupt(int, void *);
 
 extern struct irqaction c0_compare_irqaction;
index f25de771f7ed228478b54c6acbb559d1f36f46d0..9801ac9826554ca0d8ab2e27e21ad6305f18da67 100644 (file)
 # define cpu_has_cdmm          (cpu_data[0].options & MIPS_CPU_CDMM)
 #endif
 
+#ifndef cpu_has_small_pages
+# define cpu_has_small_pages   (cpu_data[0].options & MIPS_CPU_SP)
+#endif
+
 #endif /* __ASM_CPU_FEATURES_H */
index d41e8e2848253146bd12ceed71794ea51bd488b5..abee2bfd10dc1dce791ae5691417303d58b08ce6 100644 (file)
@@ -77,6 +77,10 @@ static inline int __pure __get_cpu_type(const int cpu_type)
         */
 #endif
 
+#ifdef CONFIG_SYS_HAS_CPU_MIPS64_R6
+       case CPU_I6400:
+#endif
+
 #ifdef CONFIG_SYS_HAS_CPU_R3000
        case CPU_R2000:
        case CPU_R3000:
index e46e40602af3cc0f584847d967d969b53985f775..cd89e9855775276ea7c3a185d9e61b3702f06b6f 100644 (file)
 #define PRID_IMP_PROAPTIV_MP   0xa300
 #define PRID_IMP_M5150         0xa700
 #define PRID_IMP_P5600         0xa800
+#define PRID_IMP_I6400         0xa900
 
 /*
  * These are the PRID's for when 23:16 == PRID_COMP_SIBYTE
@@ -307,6 +308,7 @@ enum cpu_type_enum {
        CPU_ALCHEMY, CPU_PR4450, CPU_BMIPS32, CPU_BMIPS3300, CPU_BMIPS4350,
        CPU_BMIPS4380, CPU_BMIPS5000, CPU_JZRISC, CPU_LOONGSON1, CPU_M14KC,
        CPU_M14KEC, CPU_INTERAPTIV, CPU_P5600, CPU_PROAPTIV, CPU_1074K, CPU_M5150,
+       CPU_I6400,
 
        /*
         * MIPS64 class processors
@@ -382,6 +384,7 @@ enum cpu_type_enum {
 #define MIPS_CPU_XPA           0x2000000000ull /* CPU supports Extended Physical Addressing */
 #define MIPS_CPU_CDMM          0x4000000000ull /* CPU has Common Device Memory Map */
 #define MIPS_CPU_BP_GHIST      0x8000000000ull /* R12K+ Branch Prediction Global History */
+#define MIPS_CPU_SP            0x10000000000ull /* Small (1KB) page support */
 
 /*
  * CPU ASE encodings
diff --git a/arch/mips/include/asm/debug.h b/arch/mips/include/asm/debug.h
deleted file mode 100644 (file)
index 1fd5a2b..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Debug macros for run-time debugging.
- * Turned on/off with CONFIG_RUNTIME_DEBUG option.
- *
- * Copyright (C) 2001 MontaVista Software Inc.
- * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
- *
- * 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.
- *
- */
-
-#ifndef _ASM_DEBUG_H
-#define _ASM_DEBUG_H
-
-
-/*
- * run-time macros for catching spurious errors.  Eable CONFIG_RUNTIME_DEBUG in
- * kernel hacking config menu to use them.
- *
- * Use them as run-time debugging aid.  NEVER USE THEM AS ERROR HANDLING CODE!!!
- */
-
-#ifdef CONFIG_RUNTIME_DEBUG
-
-#include <linux/kernel.h>
-
-#define db_assert(x)  if (!(x)) { \
-       panic("assertion failed at %s:%d: %s", __FILE__, __LINE__, #x); }
-#define db_warn(x)  if (!(x)) { \
-       printk(KERN_WARNING "warning at %s:%d: %s", __FILE__, __LINE__, #x); }
-#define db_verify(x, y) db_assert(x y)
-#define db_verify_warn(x, y) db_warn(x y)
-#define db_run(x)  do { x; } while (0)
-
-#else
-
-#define db_assert(x)
-#define db_warn(x)
-#define db_verify(x, y) x
-#define db_verify_warn(x, y) x
-#define db_run(x)
-
-#endif
-
-#endif /* _ASM_DEBUG_H */
index f19e890b99d2744ae4984ea54e2ca9e5128ce7fe..53b26933b12cea365457f95172fbde6990043ff1 100644 (file)
@@ -382,7 +382,9 @@ do {                                                                        \
    instruction set this cpu supports.  This could be done in userspace,
    but it's not easy, and we've already done it here.  */
 
-#define ELF_HWCAP      (0)
+#define ELF_HWCAP      (elf_hwcap)
+extern unsigned int elf_hwcap;
+#include <asm/hwcap.h>
 
 /*
  * This yields a string that ld.so will use to load implementation
index 1b062518983525f0065841c628b4ac10b047aeb2..9cbf383b8834c7551820930b0dc98a66895012fa 100644 (file)
@@ -164,25 +164,30 @@ static inline int own_fpu(int restore)
        return ret;
 }
 
-static inline void lose_fpu(int save)
+static inline void lose_fpu_inatomic(int save, struct task_struct *tsk)
 {
-       preempt_disable();
        if (is_msa_enabled()) {
                if (save) {
-                       save_msa(current);
-                       current->thread.fpu.fcr31 =
+                       save_msa(tsk);
+                       tsk->thread.fpu.fcr31 =
                                        read_32bit_cp1_register(CP1_STATUS);
                }
                disable_msa();
-               clear_thread_flag(TIF_USEDMSA);
+               clear_tsk_thread_flag(tsk, TIF_USEDMSA);
                __disable_fpu();
        } else if (is_fpu_owner()) {
                if (save)
-                       _save_fp(current);
+                       _save_fp(tsk);
                __disable_fpu();
        }
-       KSTK_STATUS(current) &= ~ST0_CU1;
-       clear_thread_flag(TIF_USEDFPU);
+       KSTK_STATUS(tsk) &= ~ST0_CU1;
+       clear_tsk_thread_flag(tsk, TIF_USEDFPU);
+}
+
+static inline void lose_fpu(int save)
+{
+       preempt_disable();
+       lose_fpu_inatomic(save, current);
        preempt_enable();
 }
 
diff --git a/arch/mips/include/asm/gpio.h b/arch/mips/include/asm/gpio.h
deleted file mode 100644 (file)
index 06e46fa..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __ASM_MIPS_GPIO_H
-#define __ASM_MIPS_GPIO_H
-
-#include <gpio.h>
-
-#endif /* __ASM_MIPS_GPIO_H */
index f0db99f8defe9b5ef17a7f39e6861916a85acd12..15e0fecbc300fd9752023931984fe277a73da876 100644 (file)
@@ -49,7 +49,7 @@ extern int cp0_compare_irq_shift;
 extern int cp0_perfcount_irq;
 extern int cp0_fdc_irq;
 
-extern int __weak get_c0_fdc_int(void);
+extern int get_c0_fdc_int(void);
 
 void arch_trigger_all_cpu_backtrace(bool);
 #define arch_trigger_all_cpu_backtrace arch_trigger_all_cpu_backtrace
index cba22ab7ad4d5fd9087aeb8181c6c45ba3398a8c..8e3d08e739c18d95a9bea3cbaf8ef315a2738457 100644 (file)
@@ -11,7 +11,9 @@ enum die_val {
        DIE_PAGE_FAULT,
        DIE_BREAK,
        DIE_SSTEPBP,
-       DIE_MSAFP
+       DIE_MSAFP,
+       DIE_UPROBE,
+       DIE_UPROBE_XOL,
 };
 
 #endif /* _ASM_MIPS_KDEBUG_H */
index 2767dda9e309100f40142567a970d6a4a1b07a4a..99651b0ea7c726a81393127f8a18d873515a0fe6 100644 (file)
@@ -5,7 +5,6 @@
 #include <asm/asm.h>
 #endif
 
-#define __weak __attribute__((weak))
 #define cond_syscall(x) asm(".weak\t" #x "\n" #x "\t=\tsys_ni_syscall")
 #define SYSCALL_ALIAS(alias, name)                                     \
        asm ( #alias " = " #name "\n\t.globl " #alias)
index 6c62b0f899c0fdae992bd2a3f7c5bcb5eb38ba0d..b02891f9caaf1d8ffecf14b0e0fa7be5b7fb33c8 100644 (file)
@@ -26,7 +26,7 @@
  *
  * Return:     The number of MAAR pairs configured.
  */
-unsigned __weak platform_maar_init(unsigned num_pairs);
+unsigned platform_maar_init(unsigned num_pairs);
 
 /**
  * write_maar_pair() - write to a pair of MAARs
index a47ea0c852483aba4ccfb8d833fb29d277b14147..468cbd61b9067129857b75f1dde57406d9ad45c1 100644 (file)
@@ -203,4 +203,8 @@ static inline void ar7_device_off(u32 bit)
 int __init ar7_gpio_init(void);
 void __init ar7_init_clocks(void);
 
+/* Board specific GPIO functions */
+int ar7_gpio_enable(unsigned gpio);
+int ar7_gpio_disable(unsigned gpio);
+
 #endif /* __AR7_H__ */
diff --git a/arch/mips/include/asm/mach-ar7/gpio.h b/arch/mips/include/asm/mach-ar7/gpio.h
deleted file mode 100644 (file)
index c177cd1..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2007-2009 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
- */
-
-#ifndef __AR7_GPIO_H__
-#define __AR7_GPIO_H__
-
-#include <asm/mach-ar7/ar7.h>
-
-#define AR7_GPIO_MAX 32
-#define TITAN_GPIO_MAX 51
-#define NR_BUILTIN_GPIO TITAN_GPIO_MAX
-
-#define gpio_to_irq(gpio)      -1
-
-#define gpio_get_value __gpio_get_value
-#define gpio_set_value __gpio_set_value
-
-#define gpio_cansleep __gpio_cansleep
-
-/* Board specific GPIO functions */
-int ar7_gpio_enable(unsigned gpio);
-int ar7_gpio_disable(unsigned gpio);
-
-#include <asm-generic/gpio.h>
-
-#endif
diff --git a/arch/mips/include/asm/mach-ath25/gpio.h b/arch/mips/include/asm/mach-ath25/gpio.h
deleted file mode 100644 (file)
index 713564b..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-#ifndef __ASM_MACH_ATH25_GPIO_H
-#define __ASM_MACH_ATH25_GPIO_H
-
-#include <asm-generic/gpio.h>
-
-#define gpio_get_value __gpio_get_value
-#define gpio_set_value __gpio_set_value
-#define gpio_cansleep __gpio_cansleep
-#define gpio_to_irq __gpio_to_irq
-
-static inline int irq_to_gpio(unsigned irq)
-{
-       return -EINVAL;
-}
-
-#endif /* __ASM_MACH_ATH25_GPIO_H */
diff --git a/arch/mips/include/asm/mach-ath79/gpio.h b/arch/mips/include/asm/mach-ath79/gpio.h
deleted file mode 100644 (file)
index 60dcb62..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- *  Atheros AR71XX/AR724X/AR913X GPIO API definitions
- *
- *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
- *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
- *
- *  This program is free software; you can redistribute it and/or modify it
- *  under the terms of the GNU General Public License version 2 as published
- *  by the Free Software Foundation.
- *
- */
-
-#ifndef __ASM_MACH_ATH79_GPIO_H
-#define __ASM_MACH_ATH79_GPIO_H
-
-#define ARCH_NR_GPIOS  64
-#include <asm-generic/gpio.h>
-
-int gpio_to_irq(unsigned gpio);
-int irq_to_gpio(unsigned irq);
-int gpio_get_value(unsigned gpio);
-void gpio_set_value(unsigned gpio, int value);
-
-#define gpio_cansleep  __gpio_cansleep
-
-#endif /* __ASM_MACH_ATH79_GPIO_H */
index 9785e4ebb450f662c6a8da940decf4969cd63aec..adde1fa5097e6c34dd85cfa96146d97e21647135 100644 (file)
@@ -266,6 +266,17 @@ static inline int alchemy_gpio1_to_irq(int gpio)
        return -ENXIO;
 }
 
+/* On Au1000, Au1500 and Au1100 GPIOs won't work as inputs before
+ * SYS_PININPUTEN is written to at least once.  On Au1550/Au1200/Au1300 this
+ * register enables use of GPIOs as wake source.
+ */
+static inline void alchemy_gpio1_input_enable(void)
+{
+       void __iomem *base = (void __iomem *)KSEG1ADDR(AU1000_SYS_PHYS_ADDR);
+       __raw_writel(0, base + 0x110);          /* the write op is key */
+       wmb();
+}
+
 /*
  * GPIO2 block macros for common linux GPIO functions. The 'gpio'
  * parameter must be in range of ALCHEMY_GPIO2_BASE..ALCHEMY_GPIO2_MAX.
@@ -518,141 +529,4 @@ static inline int alchemy_irq_to_gpio(int irq)
        return -ENXIO;
 }
 
-/**********************************************************************/
-
-/* Linux gpio framework integration.
- *
- * 4 use cases of Au1000-Au1200 GPIOS:
- *(1) GPIOLIB=y, ALCHEMY_GPIO_INDIRECT=y:
- *     Board must register gpiochips.
- *(2) GPIOLIB=y, ALCHEMY_GPIO_INDIRECT=n:
- *     2 (1 for Au1000) gpio_chips are registered.
- *
- *(3) GPIOLIB=n, ALCHEMY_GPIO_INDIRECT=y:
- *     the boards' gpio.h must provide the linux gpio wrapper functions,
- *
- *(4) GPIOLIB=n, ALCHEMY_GPIO_INDIRECT=n:
- *     inlinable gpio functions are provided which enable access to the
- *     Au1000 gpios only by using the numbers straight out of the data-
- *     sheets.
-
- * Cases 1 and 3 are intended for boards which want to provide their own
- * GPIO namespace and -operations (i.e. for example you have 8 GPIOs
- * which are in part provided by spare Au1000 GPIO pins and in part by
- * an external FPGA but you still want them to be accssible in linux
- * as gpio0-7. The board can of course use the alchemy_gpioX_* functions
- * as required).
- */
-
-#ifndef CONFIG_GPIOLIB
-
-#ifdef CONFIG_ALCHEMY_GPIOINT_AU1000
-
-#ifndef CONFIG_ALCHEMY_GPIO_INDIRECT   /* case (4) */
-
-static inline int gpio_direction_input(int gpio)
-{
-       return alchemy_gpio_direction_input(gpio);
-}
-
-static inline int gpio_direction_output(int gpio, int v)
-{
-       return alchemy_gpio_direction_output(gpio, v);
-}
-
-static inline int gpio_get_value(int gpio)
-{
-       return alchemy_gpio_get_value(gpio);
-}
-
-static inline void gpio_set_value(int gpio, int v)
-{
-       alchemy_gpio_set_value(gpio, v);
-}
-
-static inline int gpio_get_value_cansleep(unsigned gpio)
-{
-       return gpio_get_value(gpio);
-}
-
-static inline void gpio_set_value_cansleep(unsigned gpio, int value)
-{
-       gpio_set_value(gpio, value);
-}
-
-static inline int gpio_is_valid(int gpio)
-{
-       return alchemy_gpio_is_valid(gpio);
-}
-
-static inline int gpio_cansleep(int gpio)
-{
-       return alchemy_gpio_cansleep(gpio);
-}
-
-static inline int gpio_to_irq(int gpio)
-{
-       return alchemy_gpio_to_irq(gpio);
-}
-
-static inline int irq_to_gpio(int irq)
-{
-       return alchemy_irq_to_gpio(irq);
-}
-
-static inline int gpio_request(unsigned gpio, const char *label)
-{
-       return 0;
-}
-
-static inline int gpio_request_one(unsigned gpio,
-                                       unsigned long flags, const char *label)
-{
-       return 0;
-}
-
-static inline int gpio_request_array(struct gpio *array, size_t num)
-{
-       return 0;
-}
-
-static inline void gpio_free(unsigned gpio)
-{
-}
-
-static inline void gpio_free_array(struct gpio *array, size_t num)
-{
-}
-
-static inline int gpio_set_debounce(unsigned gpio, unsigned debounce)
-{
-       return -ENOSYS;
-}
-
-static inline int gpio_export(unsigned gpio, bool direction_may_change)
-{
-       return -ENOSYS;
-}
-
-static inline int gpio_export_link(struct device *dev, const char *name,
-                                  unsigned gpio)
-{
-       return -ENOSYS;
-}
-
-static inline int gpio_sysfs_set_active_low(unsigned gpio, int value)
-{
-       return -ENOSYS;
-}
-
-static inline void gpio_unexport(unsigned gpio)
-{
-}
-
-#endif /* !CONFIG_ALCHEMY_GPIO_INDIRECT */
-
-#endif /* CONFIG_ALCHEMY_GPIOINT_AU1000 */
-
-#endif /* !CONFIG_GPIOLIB */
-
 #endif /* _ALCHEMY_GPIO_AU1000_H_ */
diff --git a/arch/mips/include/asm/mach-au1x00/gpio.h b/arch/mips/include/asm/mach-au1x00/gpio.h
deleted file mode 100644 (file)
index 22e7ff1..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Alchemy GPIO support.
- *
- * With CONFIG_GPIOLIB=y different types of on-chip GPIO can be supported within
- *  the same kernel image.
- * With CONFIG_GPIOLIB=n, your board must select ALCHEMY_GPIOINT_AU1XXX for the
- *  appropriate CPU type (AU1000 currently).
- */
-
-#ifndef _ALCHEMY_GPIO_H_
-#define _ALCHEMY_GPIO_H_
-
-#include <asm/mach-au1x00/au1000.h>
-#include <asm/mach-au1x00/gpio-au1000.h>
-#include <asm/mach-au1x00/gpio-au1300.h>
-
-/* On Au1000, Au1500 and Au1100 GPIOs won't work as inputs before
- * SYS_PININPUTEN is written to at least once.  On Au1550/Au1200/Au1300 this
- * register enables use of GPIOs as wake source.
- */
-static inline void alchemy_gpio1_input_enable(void)
-{
-       void __iomem *base = (void __iomem *)KSEG1ADDR(AU1000_SYS_PHYS_ADDR);
-       __raw_writel(0, base + 0x110);          /* the write op is key */
-       wmb();
-}
-
-
-/* Linux gpio framework integration.
-*
-* 4 use cases of Alchemy GPIOS:
-*(1) GPIOLIB=y, ALCHEMY_GPIO_INDIRECT=y:
-*      Board must register gpiochips.
-*(2) GPIOLIB=y, ALCHEMY_GPIO_INDIRECT=n:
-*      A gpiochip for the 75 GPIOs is registered.
-*
-*(3) GPIOLIB=n, ALCHEMY_GPIO_INDIRECT=y:
-*      the boards' gpio.h must provide the linux gpio wrapper functions,
-*
-*(4) GPIOLIB=n, ALCHEMY_GPIO_INDIRECT=n:
-*      inlinable gpio functions are provided which enable access to the
-*      Au1300 gpios only by using the numbers straight out of the data-
-*      sheets.
-
-* Cases 1 and 3 are intended for boards which want to provide their own
-* GPIO namespace and -operations (i.e. for example you have 8 GPIOs
-* which are in part provided by spare Au1300 GPIO pins and in part by
-* an external FPGA but you still want them to be accssible in linux
-* as gpio0-7. The board can of course use the alchemy_gpioX_* functions
-* as required).
-*/
-
-#ifdef CONFIG_GPIOLIB
-
-/* wraps the cpu-dependent irq_to_gpio functions */
-/* FIXME: gpiolib needs an irq_to_gpio hook */
-static inline int __au_irq_to_gpio(unsigned int irq)
-{
-       switch (alchemy_get_cputype()) {
-       case ALCHEMY_CPU_AU1000...ALCHEMY_CPU_AU1200:
-               return alchemy_irq_to_gpio(irq);
-       case ALCHEMY_CPU_AU1300:
-               return au1300_irq_to_gpio(irq);
-       }
-       return -EINVAL;
-}
-
-
-/* using gpiolib to provide up to 2 gpio_chips for on-chip gpios */
-#ifndef CONFIG_ALCHEMY_GPIO_INDIRECT   /* case (2) */
-
-/* get everything through gpiolib */
-#define gpio_to_irq    __gpio_to_irq
-#define gpio_get_value __gpio_get_value
-#define gpio_set_value __gpio_set_value
-#define gpio_cansleep  __gpio_cansleep
-#define irq_to_gpio    __au_irq_to_gpio
-
-#include <asm-generic/gpio.h>
-
-#endif /* !CONFIG_ALCHEMY_GPIO_INDIRECT */
-
-
-#endif /* CONFIG_GPIOLIB */
-
-#endif /* _ALCHEMY_GPIO_H_ */
diff --git a/arch/mips/include/asm/mach-bcm47xx/gpio.h b/arch/mips/include/asm/mach-bcm47xx/gpio.h
deleted file mode 100644 (file)
index 90daefa..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifndef __ASM_MIPS_MACH_BCM47XX_GPIO_H
-#define __ASM_MIPS_MACH_BCM47XX_GPIO_H
-
-#include <asm-generic/gpio.h>
-
-#define gpio_get_value __gpio_get_value
-#define gpio_set_value __gpio_set_value
-
-#define gpio_cansleep __gpio_cansleep
-#define gpio_to_irq __gpio_to_irq
-
-static inline int irq_to_gpio(unsigned int irq)
-{
-       return -EINVAL;
-}
-
-#endif
diff --git a/arch/mips/include/asm/mach-bcm63xx/gpio.h b/arch/mips/include/asm/mach-bcm63xx/gpio.h
deleted file mode 100644 (file)
index 1eb534d..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-#ifndef __ASM_MIPS_MACH_BCM63XX_GPIO_H
-#define __ASM_MIPS_MACH_BCM63XX_GPIO_H
-
-#include <bcm63xx_gpio.h>
-
-#define gpio_to_irq(gpio)      -1
-
-#define gpio_get_value __gpio_get_value
-#define gpio_set_value __gpio_set_value
-
-#define gpio_cansleep __gpio_cansleep
-
-#include <asm-generic/gpio.h>
-
-#endif /* __ASM_MIPS_MACH_BCM63XX_GPIO_H */
diff --git a/arch/mips/include/asm/mach-cavium-octeon/gpio.h b/arch/mips/include/asm/mach-cavium-octeon/gpio.h
deleted file mode 100644 (file)
index 34e9f7a..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-#ifndef __ASM_MACH_CAVIUM_OCTEON_GPIO_H
-#define __ASM_MACH_CAVIUM_OCTEON_GPIO_H
-
-#ifdef CONFIG_GPIOLIB
-#define gpio_get_value __gpio_get_value
-#define gpio_set_value __gpio_set_value
-#define gpio_cansleep  __gpio_cansleep
-#else
-int gpio_request(unsigned gpio, const char *label);
-void gpio_free(unsigned gpio);
-int gpio_direction_input(unsigned gpio);
-int gpio_direction_output(unsigned gpio, int value);
-int gpio_get_value(unsigned gpio);
-void gpio_set_value(unsigned gpio, int value);
-#endif
-
-#include <asm-generic/gpio.h>
-
-#define gpio_to_irq    __gpio_to_irq
-
-#endif /* __ASM_MACH_GENERIC_GPIO_H */
diff --git a/arch/mips/include/asm/mach-generic/gpio.h b/arch/mips/include/asm/mach-generic/gpio.h
deleted file mode 100644 (file)
index b4e7020..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-#ifndef __ASM_MACH_GENERIC_GPIO_H
-#define __ASM_MACH_GENERIC_GPIO_H
-
-#ifdef CONFIG_GPIOLIB
-#define gpio_get_value __gpio_get_value
-#define gpio_set_value __gpio_set_value
-#define gpio_cansleep  __gpio_cansleep
-#else
-int gpio_request(unsigned gpio, const char *label);
-void gpio_free(unsigned gpio);
-int gpio_direction_input(unsigned gpio);
-int gpio_direction_output(unsigned gpio, int value);
-int gpio_get_value(unsigned gpio);
-void gpio_set_value(unsigned gpio, int value);
-#endif
-int gpio_to_irq(unsigned gpio);
-int irq_to_gpio(unsigned irq);
-
-#include <asm-generic/gpio.h>          /* cansleep wrappers */
-
-#endif /* __ASM_MACH_GENERIC_GPIO_H */
index eaacba79cf18c9905731f7e0760d6697de795b23..bf8c3e1860e713cb548f18bdb86c0eb822229b4c 100644 (file)
@@ -73,8 +73,6 @@ int jz_gpio_port_direction_output(int port, uint32_t mask);
 void jz_gpio_port_set_value(int port, uint32_t value, uint32_t mask);
 uint32_t jz_gpio_port_get_value(int port, uint32_t mask);
 
-#include <asm/mach-generic/gpio.h>
-
 #define JZ_GPIO_PORTA(x) ((x) + 32 * 0)
 #define JZ_GPIO_PORTB(x) ((x) + 32 * 1)
 #define JZ_GPIO_PORTC(x) ((x) + 32 * 2)
diff --git a/arch/mips/include/asm/mach-lantiq/gpio.h b/arch/mips/include/asm/mach-lantiq/gpio.h
deleted file mode 100644 (file)
index 9ba1cae..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef __ASM_MIPS_MACH_LANTIQ_GPIO_H
-#define __ASM_MIPS_MACH_LANTIQ_GPIO_H
-
-#define gpio_to_irq __gpio_to_irq
-
-#define gpio_get_value __gpio_get_value
-#define gpio_set_value __gpio_set_value
-
-#define gpio_cansleep __gpio_cansleep
-
-#include <asm-generic/gpio.h>
-
-#endif
diff --git a/arch/mips/include/asm/mach-loongson64/gpio.h b/arch/mips/include/asm/mach-loongson64/gpio.h
deleted file mode 100644 (file)
index b3b2169..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Loongson GPIO Support
- *
- * Copyright (c) 2008  Richard Liu, STMicroelectronics <richard.liu@st.com>
- * Copyright (c) 2008-2010  Arnaud Patard <apatard@mandriva.com>
- * Copyright (c) 2014  Huacai Chen <chenhc@lemote.com>
- *
- * 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.
- */
-
-#ifndef __LOONGSON_GPIO_H
-#define __LOONGSON_GPIO_H
-
-#include <asm-generic/gpio.h>
-
-#define gpio_get_value __gpio_get_value
-#define gpio_set_value __gpio_set_value
-#define gpio_cansleep __gpio_cansleep
-
-/* The chip can do interrupt
- * but it has not been tested and doc not clear
- */
-static inline int gpio_to_irq(int gpio)
-{
-       return -EINVAL;
-}
-
-static inline int irq_to_gpio(int gpio)
-{
-       return -EINVAL;
-}
-
-#endif /* __LOONGSON_GPIO_H */
diff --git a/arch/mips/include/asm/mach-pistachio/gpio.h b/arch/mips/include/asm/mach-pistachio/gpio.h
deleted file mode 100644 (file)
index 6c1649c..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Pistachio IRQ setup
- *
- * Copyright (C) 2014 Google, Inc.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- */
-
-#ifndef __ASM_MACH_PISTACHIO_GPIO_H
-#define __ASM_MACH_PISTACHIO_GPIO_H
-
-#include <asm-generic/gpio.h>
-
-#define gpio_get_value __gpio_get_value
-#define gpio_set_value __gpio_set_value
-#define gpio_cansleep  __gpio_cansleep
-#define gpio_to_irq    __gpio_to_irq
-
-#endif /* __ASM_MACH_PISTACHIO_GPIO_H */
index 4dee0a34250c39bf86c450aff7a7e7efb8f6fb70..db211212ce79ef9d5d24c956d45500354137b59e 100644 (file)
 #ifndef _RC32434_GPIO_H_
 #define _RC32434_GPIO_H_
 
-#include <linux/types.h>
-#include <asm-generic/gpio.h>
-
-#define NR_BUILTIN_GPIO                32
-
-#define gpio_get_value __gpio_get_value
-#define gpio_set_value __gpio_set_value
-#define gpio_cansleep  __gpio_cansleep
-
-#define gpio_to_irq(gpio)      (8 + 4 * 32 + gpio)
-#define irq_to_gpio(irq)       (irq - (8 + 4 * 32))
-
 struct rb532_gpio_reg {
        u32   gpiofunc;   /* GPIO Function Register
                           * gpiofunc[x]==0 bit = gpio
index edc7ee95269e73d26747f82b41915d8b8f3c8e68..d75b75e78ebb4749355f95a1709202b9f2d069af 100644 (file)
@@ -33,6 +33,29 @@ extern void __iomem *mips_cm_l2sync_base;
  */
 extern phys_addr_t __mips_cm_phys_base(void);
 
+/*
+ * mips_cm_is64 - determine CM register width
+ *
+ * The CM register width is processor and CM specific. A 64-bit processor
+ * usually has a 64-bit CM and a 32-bit one has a 32-bit CM but a 64-bit
+ * processor could come with a 32-bit CM. Moreover, accesses on 64-bit CMs
+ * can be done either using regular 64-bit load/store instructions, or 32-bit
+ * load/store instruction on 32-bit register pairs. We opt for using 64-bit
+ * accesses on 64-bit CMs and kernels and 32-bit in any other case.
+ *
+ * It's set to 0 for 32-bit accesses and 1 for 64-bit accesses.
+ */
+extern int mips_cm_is64;
+
+/**
+ * mips_cm_error_report - Report CM cache errors
+ */
+#ifdef CONFIG_MIPS_CM
+extern void mips_cm_error_report(void);
+#else
+static inline void mips_cm_error_report(void) {}
+#endif
+
 /**
  * mips_cm_probe - probe for a Coherence Manager
  *
@@ -90,20 +113,46 @@ static inline bool mips_cm_has_l2sync(void)
 
 /* Macros to ease the creation of register access functions */
 #define BUILD_CM_R_(name, off)                                 \
-static inline u32 __iomem *addr_gcr_##name(void)               \
+static inline unsigned long __iomem *addr_gcr_##name(void)     \
 {                                                              \
-       return (u32 __iomem *)(mips_cm_base + (off));           \
+       return (unsigned long __iomem *)(mips_cm_base + (off)); \
 }                                                              \
                                                                \
-static inline u32 read_gcr_##name(void)                                \
+static inline u32 read32_gcr_##name(void)                      \
 {                                                              \
        return __raw_readl(addr_gcr_##name());                  \
+}                                                              \
+                                                               \
+static inline u64 read64_gcr_##name(void)                      \
+{                                                              \
+       return __raw_readq(addr_gcr_##name());                  \
+}                                                              \
+                                                               \
+static inline unsigned long read_gcr_##name(void)              \
+{                                                              \
+       if (mips_cm_is64)                                       \
+               return read64_gcr_##name();                     \
+       else                                                    \
+               return read32_gcr_##name();                     \
 }
 
 #define BUILD_CM__W(name, off)                                 \
-static inline void write_gcr_##name(u32 value)                 \
+static inline void write32_gcr_##name(u32 value)               \
 {                                                              \
        __raw_writel(value, addr_gcr_##name());                 \
+}                                                              \
+                                                               \
+static inline void write64_gcr_##name(u64 value)               \
+{                                                              \
+       __raw_writeq(value, addr_gcr_##name());                 \
+}                                                              \
+                                                               \
+static inline void write_gcr_##name(unsigned long value)       \
+{                                                              \
+       if (mips_cm_is64)                                       \
+               write64_gcr_##name(value);                      \
+       else                                                    \
+               write32_gcr_##name(value);                      \
 }
 
 #define BUILD_CM_RW(name, off)                                 \
@@ -144,6 +193,7 @@ BUILD_CM_RW(reg3_base,              MIPS_CM_GCB_OFS + 0xc0)
 BUILD_CM_RW(reg3_mask,         MIPS_CM_GCB_OFS + 0xc8)
 BUILD_CM_R_(gic_status,                MIPS_CM_GCB_OFS + 0xd0)
 BUILD_CM_R_(cpc_status,                MIPS_CM_GCB_OFS + 0xf0)
+BUILD_CM_RW(l2_config,         MIPS_CM_GCB_OFS + 0x130)
 
 /* Core Local & Core Other register accessor functions */
 BUILD_CM_Cx_RW(reset_release,  0x00)
@@ -189,6 +239,13 @@ BUILD_CM_Cx_R_(tcid_8_priority,    0x80)
 #define CM_GCR_REV_MINOR_SHF                   0
 #define CM_GCR_REV_MINOR_MSK                   (_ULCAST_(0xff) << 0)
 
+#define CM_ENCODE_REV(major, minor) \
+               (((major) << CM_GCR_REV_MAJOR_SHF) | \
+                ((minor) << CM_GCR_REV_MINOR_SHF))
+
+#define CM_REV_CM2                             CM_ENCODE_REV(6, 0)
+#define CM_REV_CM3                             CM_ENCODE_REV(8, 0)
+
 /* GCR_ERROR_CAUSE register fields */
 #define CM_GCR_ERROR_CAUSE_ERRTYPE_SHF         27
 #define CM_GCR_ERROR_CAUSE_ERRTYPE_MSK         (_ULCAST_(0x1f) << 27)
@@ -249,6 +306,16 @@ BUILD_CM_Cx_R_(tcid_8_priority,    0x80)
 #define CM_GCR_CPC_STATUS_EX_SHF               0
 #define CM_GCR_CPC_STATUS_EX_MSK               (_ULCAST_(0x1) << 0)
 
+/* GCR_L2_CONFIG register fields */
+#define CM_GCR_L2_CONFIG_BYPASS_SHF            20
+#define CM_GCR_L2_CONFIG_BYPASS_MSK            (_ULCAST_(0x1) << 20)
+#define CM_GCR_L2_CONFIG_SET_SIZE_SHF          12
+#define CM_GCR_L2_CONFIG_SET_SIZE_MSK          (_ULCAST_(0xf) << 12)
+#define CM_GCR_L2_CONFIG_LINE_SIZE_SHF         8
+#define CM_GCR_L2_CONFIG_LINE_SIZE_MSK         (_ULCAST_(0xf) << 8)
+#define CM_GCR_L2_CONFIG_ASSOC_SHF             0
+#define CM_GCR_L2_CONFIG_ASSOC_MSK             (_ULCAST_(0xff) << 0)
+
 /* GCR_Cx_COHERENCE register fields */
 #define CM_GCR_Cx_COHERENCE_COHDOMAINEN_SHF    0
 #define CM_GCR_Cx_COHERENCE_COHDOMAINEN_MSK    (_ULCAST_(0xff) << 0)
@@ -324,4 +391,18 @@ static inline int mips_cm_l2sync(void)
        return 0;
 }
 
+/**
+ * mips_cm_revision() - return CM revision
+ *
+ * Return: The revision of the CM, from GCR_REV, or 0 if no CM is present. The
+ * return value should be checked against the CM_REV_* macros.
+ */
+static inline int mips_cm_revision(void)
+{
+       if (!mips_cm_present())
+               return 0;
+
+       return read_gcr_rev();
+}
+
 #endif /* __MIPS_ASM_MIPS_CM_H__ */
index 1cebe8c790513e2fe954397cfd4e8ec8055178ad..f386f32702f17f75782ba9a58ffe5fa0ee37e186 100644 (file)
@@ -27,16 +27,6 @@ extern void __iomem *mips_cpc_base;
  */
 extern phys_addr_t mips_cpc_default_phys_base(void);
 
-/**
- * mips_cpc_phys_base - retrieve the physical base address of the CPC
- *
- * This function returns the physical base address of the Cluster Power
- * Controller memory mapped registers, or 0 if no Cluster Power Controller
- * is present. It may be overriden by individual platforms which determine
- * this address in a different way.
- */
-extern phys_addr_t __weak mips_cpc_phys_base(void);
-
 /**
  * mips_cpc_probe - probe for a Cluster Power Controller
  *
index c5b0956a853027897716050e46be33006912e981..d3cd8eac81e3a76baf455dd95e881cfd9c72eed9 100644 (file)
 #define CP0_TX39_CACHE $7
 
 
+/* Generic EntryLo bit definitions */
+#define ENTRYLO_G              (_ULCAST_(1) << 0)
+#define ENTRYLO_V              (_ULCAST_(1) << 1)
+#define ENTRYLO_D              (_ULCAST_(1) << 2)
+#define ENTRYLO_C_SHIFT                3
+#define ENTRYLO_C              (_ULCAST_(7) << ENTRYLO_C_SHIFT)
+
+/* R3000 EntryLo bit definitions */
+#define R3K_ENTRYLO_G          (_ULCAST_(1) << 8)
+#define R3K_ENTRYLO_V          (_ULCAST_(1) << 9)
+#define R3K_ENTRYLO_D          (_ULCAST_(1) << 10)
+#define R3K_ENTRYLO_N          (_ULCAST_(1) << 11)
+
+/* MIPS32/64 EntryLo bit definitions */
+#ifdef CONFIG_64BIT
+/* as read by dmfc0 */
+#define MIPS_ENTRYLO_XI                (_ULCAST_(1) << 62)
+#define MIPS_ENTRYLO_RI                (_ULCAST_(1) << 63)
+#else
+/* as read by mfc0 */
+#define MIPS_ENTRYLO_XI                (_ULCAST_(1) << 30)
+#define MIPS_ENTRYLO_RI                (_ULCAST_(1) << 31)
+#endif
+
 /*
  * Values for PageMask register
  */
 #define PG_ESP         (_ULCAST_(1) <<  28)
 #define PG_IEC         (_ULCAST_(1) <<  27)
 
+/* MIPS32/64 EntryHI bit definitions */
+#define MIPS_ENTRYHI_EHINV     (_ULCAST_(1) << 10)
+
 /*
  * R4x00 interrupt enable / cause bits
  */
 
 #define MIPS_CONF7_IAR         (_ULCAST_(1) << 10)
 #define MIPS_CONF7_AR          (_ULCAST_(1) << 16)
+/* FTLB probability bits for R6 */
+#define MIPS_CONF7_FTLBP_SHIFT (18)
 
 /* MAAR bit definitions */
 #define MIPS_MAAR_ADDR         ((BIT_ULL(BITS_PER_LONG - 12) - 1) << 12)
 #define MIPS_MAAR_S            (_ULCAST_(1) << 1)
 #define MIPS_MAAR_V            (_ULCAST_(1) << 0)
 
-/*  EntryHI bit definition */
-#define MIPS_ENTRYHI_EHINV     (_ULCAST_(1) << 10)
-
-/* R3000 EntryLo bit definitions */
-#define R3K_ENTRYLO_G          (_ULCAST_(1) << 8)
-#define R3K_ENTRYLO_V          (_ULCAST_(1) << 9)
-#define R3K_ENTRYLO_D          (_ULCAST_(1) << 10)
-#define R3K_ENTRYLO_N          (_ULCAST_(1) << 11)
-
-/* R4000 compatible EntryLo bit definitions */
-#define MIPS_ENTRYLO_G         (_ULCAST_(1) << 0)
-#define MIPS_ENTRYLO_V         (_ULCAST_(1) << 1)
-#define MIPS_ENTRYLO_D         (_ULCAST_(1) << 2)
-#define MIPS_ENTRYLO_C_SHIFT   3
-#define MIPS_ENTRYLO_C         (_ULCAST_(7) << MIPS_ENTRYLO_C_SHIFT)
-#ifdef CONFIG_64BIT
-/* as read by dmfc0 */
-#define MIPS_ENTRYLO_XI                (_ULCAST_(1) << 62)
-#define MIPS_ENTRYLO_RI                (_ULCAST_(1) << 63)
-#else
-/* as read by mfc0 */
-#define MIPS_ENTRYLO_XI                (_ULCAST_(1) << 30)
-#define MIPS_ENTRYLO_RI                (_ULCAST_(1) << 31)
-#endif
-
 /* CMGCRBase bit definitions */
 #define MIPS_CMGCRB_BASE       11
 #define MIPS_CMGCRF_BASE       (~_ULCAST_((1 << MIPS_CMGCRB_BASE) - 1))
@@ -932,7 +936,7 @@ do {                                                                \
  */
 
 #define __read_32bit_c0_register(source, sel)                          \
-({ int __res;                                                          \
+({ unsigned int __res;                                                 \
        if (sel == 0)                                                   \
                __asm__ __volatile__(                                   \
                        "mfc0\t%0, " #source "\n\t"                     \
@@ -1014,7 +1018,7 @@ do {                                                                      \
  * On RM7000/RM9000 these are uses to access cop0 set 1 registers
  */
 #define __read_32bit_c0_ctrl_register(source)                          \
-({ int __res;                                                          \
+({ unsigned int __res;                                                 \
        __asm__ __volatile__(                                           \
                "cfc0\t%0, " #source "\n\t"                             \
                : "=r" (__res));                                        \
@@ -1471,7 +1475,7 @@ do {                                                                      \
  */
 #define _read_32bit_cp1_register(source, gas_hardfloat)                        \
 ({                                                                     \
-       int __res;                                                      \
+       unsigned int __res;                                             \
                                                                        \
        __asm__ __volatile__(                                           \
        "       .set    push                                    \n"     \
index af5638b12c756794b72df9adaeee27a828e1ddc7..bbb85fe21642f0e7f01b45bd4ba70076ed7a8b4c 100644 (file)
 
 #ifndef __ASSEMBLY__
 
+#include <asm/inst.h>
+
 extern void _save_msa(struct task_struct *);
 extern void _restore_msa(struct task_struct *);
 extern void _init_msa_upper(void);
 
+extern void read_msa_wr_b(unsigned idx, union fpureg *to);
+extern void read_msa_wr_h(unsigned idx, union fpureg *to);
+extern void read_msa_wr_w(unsigned idx, union fpureg *to);
+extern void read_msa_wr_d(unsigned idx, union fpureg *to);
+
+/**
+ * read_msa_wr() - Read a single MSA vector register
+ * @idx:       The index of the vector register to read
+ * @to:                The FPU register union to store the registers value in
+ * @fmt:       The format of the data in the vector register
+ *
+ * Read the value of MSA vector register idx into the FPU register
+ * union to, using the format fmt.
+ */
+static inline void read_msa_wr(unsigned idx, union fpureg *to,
+                              enum msa_2b_fmt fmt)
+{
+       switch (fmt) {
+       case msa_fmt_b:
+               read_msa_wr_b(idx, to);
+               break;
+
+       case msa_fmt_h:
+               read_msa_wr_h(idx, to);
+               break;
+
+       case msa_fmt_w:
+               read_msa_wr_w(idx, to);
+               break;
+
+       case msa_fmt_d:
+               read_msa_wr_d(idx, to);
+               break;
+
+       default:
+               BUG();
+       }
+}
+
+extern void write_msa_wr_b(unsigned idx, union fpureg *from);
+extern void write_msa_wr_h(unsigned idx, union fpureg *from);
+extern void write_msa_wr_w(unsigned idx, union fpureg *from);
+extern void write_msa_wr_d(unsigned idx, union fpureg *from);
+
+/**
+ * write_msa_wr() - Write a single MSA vector register
+ * @idx:       The index of the vector register to write
+ * @from:      The FPU register union to take the registers value from
+ * @fmt:       The format of the data in the vector register
+ *
+ * Write the value from the FPU register union from into MSA vector
+ * register idx, using the format fmt.
+ */
+static inline void write_msa_wr(unsigned idx, union fpureg *from,
+                               enum msa_2b_fmt fmt)
+{
+       switch (fmt) {
+       case msa_fmt_b:
+               write_msa_wr_b(idx, from);
+               break;
+
+       case msa_fmt_h:
+               write_msa_wr_h(idx, from);
+               break;
+
+       case msa_fmt_w:
+               write_msa_wr_w(idx, from);
+               break;
+
+       case msa_fmt_d:
+               write_msa_wr_d(idx, from);
+               break;
+
+       default:
+               BUG();
+       }
+}
+
 static inline void enable_msa(void)
 {
        if (cpu_has_msa) {
index c373d95b5e2cfa5202108d263249ac5594ed67a2..d92cf59bdae63491201f247edb1bac5b1a30555e 100644 (file)
@@ -284,6 +284,7 @@ enum cvmx_board_types_enum {
        CVMX_BOARD_TYPE_CUST_PRIVATE_MIN = 20001,
        CVMX_BOARD_TYPE_UBNT_E100 = 20002,
        CVMX_BOARD_TYPE_CUST_DSR1000N = 20006,
+       CVMX_BOARD_TYPE_KONTRON_S1901 = 21901,
        CVMX_BOARD_TYPE_CUST_PRIVATE_MAX = 30000,
 
        /* The remaining range is reserved for future use. */
@@ -384,6 +385,7 @@ static inline const char *cvmx_board_type_to_string(enum
                ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_PRIVATE_MIN)
                ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_UBNT_E100)
                ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_DSR1000N)
+               ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_KONTRON_S1901)
                ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_PRIVATE_MAX)
        }
        return "Unsupported Board";
index df69bfd2b006bc01f300094a8ae1a571058ef101..c210154ad941fa7099d4c6da2e4dc7fe12b73133 100644 (file)
@@ -37,7 +37,7 @@
 #include <asm/octeon/cvmx-fpa.h>
 #include <asm/octeon/cvmx-pip-defs.h>
 
-#define CVMX_PIP_NUM_INPUT_PORTS               40
+#define CVMX_PIP_NUM_INPUT_PORTS               48
 #define CVMX_PIP_NUM_WATCHERS                  4
 
 /*
index 3da59bb8ce24fbb4c14b15f539d074805ddfde75..5f47f76ed510a53dd760bedf911d3d1414d8a4de 100644 (file)
@@ -542,6 +542,9 @@ static inline int cvmx_pko_get_base_queue_per_core(int port, int core)
  */
 static inline int cvmx_pko_get_base_queue(int port)
 {
+       if (OCTEON_IS_MODEL(OCTEON_CN68XX))
+               return port;
+
        return cvmx_pko_get_base_queue_per_core(port, 0);
 }
 
index 9020ef443736d41939e1cffb484f964b607aff8b..6a3db4b068ffc238805627040c8beda4475f8091 100644 (file)
 #define CVMX_POW_WQ_INT_THRX(offset) (CVMX_ADD_IO_SEG(0x0001670000000080ull) + ((offset) & 15) * 8)
 #define CVMX_POW_WS_PCX(offset) (CVMX_ADD_IO_SEG(0x0001670000000280ull) + ((offset) & 15) * 8)
 
+#define CVMX_SSO_WQ_INT (CVMX_ADD_IO_SEG(0x0001670000001000ull))
+#define CVMX_SSO_WQ_IQ_DIS (CVMX_ADD_IO_SEG(0x0001670000001010ull))
+#define CVMX_SSO_WQ_INT_PC (CVMX_ADD_IO_SEG(0x0001670000001020ull))
+#define CVMX_SSO_PPX_GRP_MSK(offset) (CVMX_ADD_IO_SEG(0x0001670000006000ull) + ((offset) & 31) * 8)
+#define CVMX_SSO_WQ_INT_THRX(offset) (CVMX_ADD_IO_SEG(0x0001670000007000ull) + ((offset) & 63) * 8)
+
 union cvmx_pow_bist_stat {
        uint64_t u64;
        struct cvmx_pow_bist_stat_s {
@@ -1286,4 +1292,27 @@ union cvmx_pow_ws_pcx {
        struct cvmx_pow_ws_pcx_s cnf71xx;
 };
 
+union cvmx_sso_wq_int_thrx {
+       uint64_t u64;
+       struct {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_33_63:31;
+               uint64_t tc_en:1;
+               uint64_t tc_thr:4;
+               uint64_t reserved_26_27:2;
+               uint64_t ds_thr:12;
+               uint64_t reserved_12_13:2;
+               uint64_t iq_thr:12;
+#else
+               uint64_t iq_thr:12;
+               uint64_t reserved_12_13:2;
+               uint64_t ds_thr:12;
+               uint64_t reserved_26_27:2;
+               uint64_t tc_thr:4;
+               uint64_t tc_en:1;
+               uint64_t reserved_33_63:31;
+#endif
+       } s;
+};
+
 #endif
index d5565d758dddd4836b1933f65ce76705b2a7702b..51531563f8dc9123498270064e03c1796e02643a 100644 (file)
@@ -1810,10 +1810,11 @@ static inline void cvmx_pow_work_submit(cvmx_wqe_t *wqp, uint32_t tag,
        cvmx_addr_t ptr;
        cvmx_pow_tag_req_t tag_req;
 
-       wqp->qos = qos;
-       wqp->tag = tag;
-       wqp->tag_type = tag_type;
-       wqp->grp = grp;
+       wqp->word1.tag = tag;
+       wqp->word1.tag_type = tag_type;
+
+       cvmx_wqe_set_qos(wqp, qos);
+       cvmx_wqe_set_grp(wqp, grp);
 
        tag_req.u64 = 0;
        tag_req.s.op = CVMX_POW_TAG_OP_ADDWQ;
index 2d6d0c7127a755b5a0b94dac10198be2c87eaa57..0d697aa786d4c836b8fae7ffd4261af2dfaf3dd6 100644 (file)
@@ -193,6 +193,53 @@ typedef union {
                uint64_t bufs:8;
 #endif
        } s;
+       struct {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t bufs:8;
+               uint64_t ip_offset:8;
+               uint64_t vlan_valid:1;
+               uint64_t vlan_stacked:1;
+               uint64_t unassigned:1;
+               uint64_t vlan_cfi:1;
+               uint64_t vlan_id:12;
+               uint64_t port:12;               /* MAC/PIP port number. */
+               uint64_t dec_ipcomp:1;
+               uint64_t tcp_or_udp:1;
+               uint64_t dec_ipsec:1;
+               uint64_t is_v6:1;
+               uint64_t software:1;
+               uint64_t L4_error:1;
+               uint64_t is_frag:1;
+               uint64_t IP_exc:1;
+               uint64_t is_bcast:1;
+               uint64_t is_mcast:1;
+               uint64_t not_IP:1;
+               uint64_t rcv_error:1;
+               uint64_t err_code:8;
+#else
+               uint64_t err_code:8;
+               uint64_t rcv_error:1;
+               uint64_t not_IP:1;
+               uint64_t is_mcast:1;
+               uint64_t is_bcast:1;
+               uint64_t IP_exc:1;
+               uint64_t is_frag:1;
+               uint64_t L4_error:1;
+               uint64_t software:1;
+               uint64_t is_v6:1;
+               uint64_t dec_ipsec:1;
+               uint64_t tcp_or_udp:1;
+               uint64_t dec_ipcomp:1;
+               uint64_t port:12;
+               uint64_t vlan_id:12;
+               uint64_t vlan_cfi:1;
+               uint64_t unassigned:1;
+               uint64_t vlan_stacked:1;
+               uint64_t vlan_valid:1;
+               uint64_t ip_offset:8;
+               uint64_t bufs:8;
+#endif
+       } s_cn68xx;
 
        /* use this to get at the 16 vlan bits */
        struct {
@@ -355,6 +402,146 @@ typedef union {
 
 } cvmx_pip_wqe_word2;
 
+union cvmx_pip_wqe_word0 {
+       struct {
+#ifdef __BIG_ENDIAN_BITFIELD
+               /**
+                * raw chksum result generated by the HW
+                */
+               uint16_t hw_chksum;
+               /**
+                * Field unused by hardware - available for software
+                */
+               uint8_t unused;
+               /**
+                * Next pointer used by hardware for list maintenance.
+                * May be written/read by HW before the work queue
+                * entry is scheduled to a PP (Only 36 bits used in
+                * Octeon 1)
+                */
+               uint64_t next_ptr:40;
+#else
+               uint64_t next_ptr:40;
+               uint8_t unused;
+               uint16_t hw_chksum;
+#endif
+       } cn38xx;
+       struct {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t l4ptr:8;       /* 56..63 */
+               uint64_t unused0:8;     /* 48..55 */
+               uint64_t l3ptr:8;       /* 40..47 */
+               uint64_t l2ptr:8;       /* 32..39 */
+               uint64_t unused1:18;    /* 14..31 */
+               uint64_t bpid:6;        /* 8..13 */
+               uint64_t unused2:2;     /* 6..7 */
+               uint64_t pknd:6;        /* 0..5 */
+#else
+               uint64_t pknd:6;        /* 0..5 */
+               uint64_t unused2:2;     /* 6..7 */
+               uint64_t bpid:6;        /* 8..13 */
+               uint64_t unused1:18;    /* 14..31 */
+               uint64_t l2ptr:8;       /* 32..39 */
+               uint64_t l3ptr:8;       /* 40..47 */
+               uint64_t unused0:8;     /* 48..55 */
+               uint64_t l4ptr:8;       /* 56..63 */
+#endif
+       } cn68xx;
+};
+
+union cvmx_wqe_word0 {
+       uint64_t u64;
+       union cvmx_pip_wqe_word0 pip;
+};
+
+union cvmx_wqe_word1 {
+       uint64_t u64;
+       struct {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t len:16;
+               uint64_t varies:14;
+               /**
+                * the type of the tag (ORDERED, ATOMIC, NULL)
+                */
+               uint64_t tag_type:2;
+               uint64_t tag:32;
+#else
+               uint64_t tag:32;
+               uint64_t tag_type:2;
+               uint64_t varies:14;
+               uint64_t len:16;
+#endif
+       };
+       struct {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t len:16;
+               uint64_t zero_0:1;
+               /**
+                * HW sets this to what it thought the priority of
+                * the input packet was
+                */
+               uint64_t qos:3;
+
+               uint64_t zero_1:1;
+               /**
+                * the group that the work queue entry will be scheduled to
+                */
+               uint64_t grp:6;
+               uint64_t zero_2:3;
+               uint64_t tag_type:2;
+               uint64_t tag:32;
+#else
+               uint64_t tag:32;
+               uint64_t tag_type:2;
+               uint64_t zero_2:3;
+               uint64_t grp:6;
+               uint64_t zero_1:1;
+               uint64_t qos:3;
+               uint64_t zero_0:1;
+               uint64_t len:16;
+#endif
+       } cn68xx;
+       struct {
+#ifdef __BIG_ENDIAN_BITFIELD
+               /**
+                * HW sets to the total number of bytes in the packet
+                */
+               uint64_t len:16;
+               /**
+                * HW sets this to input physical port
+                */
+               uint64_t ipprt:6;
+
+               /**
+                * HW sets this to what it thought the priority of
+                * the input packet was
+                */
+               uint64_t qos:3;
+
+               /**
+                * the group that the work queue entry will be scheduled to
+                */
+               uint64_t grp:4;
+               /**
+                * the type of the tag (ORDERED, ATOMIC, NULL)
+                */
+               uint64_t tag_type:3;
+               /**
+                * the synchronization/ordering tag
+                */
+               uint64_t tag:32;
+#else
+               uint64_t tag:32;
+               uint64_t tag_type:2;
+               uint64_t zero_2:1;
+               uint64_t grp:4;
+               uint64_t qos:3;
+               uint64_t ipprt:6;
+               uint64_t len:16;
+#endif
+       } cn38xx;
+};
+
 /**
  * Work queue entry format
  *
@@ -366,70 +553,13 @@ typedef struct {
      * WORD 0
      * HW WRITE: the following 64 bits are filled by HW when a packet arrives
      */
-
-#ifdef __BIG_ENDIAN_BITFIELD
-    /**
-     * raw chksum result generated by the HW
-     */
-       uint16_t hw_chksum;
-    /**
-     * Field unused by hardware - available for software
-     */
-       uint8_t unused;
-    /**
-     * Next pointer used by hardware for list maintenance.
-     * May be written/read by HW before the work queue
-     *          entry is scheduled to a PP
-     * (Only 36 bits used in Octeon 1)
-     */
-       uint64_t next_ptr:40;
-#else
-       uint64_t next_ptr:40;
-       uint8_t unused;
-       uint16_t hw_chksum;
-#endif
+       union cvmx_wqe_word0 word0;
 
     /*****************************************************************
      * WORD 1
      * HW WRITE: the following 64 bits are filled by HW when a packet arrives
      */
-
-#ifdef __BIG_ENDIAN_BITFIELD
-    /**
-     * HW sets to the total number of bytes in the packet
-     */
-       uint64_t len:16;
-    /**
-     * HW sets this to input physical port
-     */
-       uint64_t ipprt:6;
-
-    /**
-     * HW sets this to what it thought the priority of the input packet was
-     */
-       uint64_t qos:3;
-
-    /**
-     * the group that the work queue entry will be scheduled to
-     */
-       uint64_t grp:4;
-    /**
-     * the type of the tag (ORDERED, ATOMIC, NULL)
-     */
-       uint64_t tag_type:3;
-    /**
-     * the synchronization/ordering tag
-     */
-       uint64_t tag:32;
-#else
-       uint64_t tag:32;
-       uint64_t tag_type:2;
-       uint64_t zero_2:1;
-       uint64_t grp:4;
-       uint64_t qos:3;
-       uint64_t ipprt:6;
-       uint64_t len:16;
-#endif
+       union cvmx_wqe_word1 word1;
 
     /**
      * WORD 2 HW WRITE: the following 64-bits are filled in by
@@ -465,4 +595,64 @@ typedef struct {
 
 } CVMX_CACHE_LINE_ALIGNED cvmx_wqe_t;
 
+static inline int cvmx_wqe_get_port(cvmx_wqe_t *work)
+{
+       int port;
+
+       if (octeon_has_feature(OCTEON_FEATURE_CN68XX_WQE))
+               port = work->word2.s_cn68xx.port;
+       else
+               port = work->word1.cn38xx.ipprt;
+
+       return port;
+}
+
+static inline void cvmx_wqe_set_port(cvmx_wqe_t *work, int port)
+{
+       if (octeon_has_feature(OCTEON_FEATURE_CN68XX_WQE))
+               work->word2.s_cn68xx.port = port;
+       else
+               work->word1.cn38xx.ipprt = port;
+}
+
+static inline int cvmx_wqe_get_grp(cvmx_wqe_t *work)
+{
+       int grp;
+
+       if (octeon_has_feature(OCTEON_FEATURE_CN68XX_WQE))
+               grp = work->word1.cn68xx.grp;
+       else
+               grp = work->word1.cn38xx.grp;
+
+       return grp;
+}
+
+static inline void cvmx_wqe_set_grp(cvmx_wqe_t *work, int grp)
+{
+       if (octeon_has_feature(OCTEON_FEATURE_CN68XX_WQE))
+               work->word1.cn68xx.grp = grp;
+       else
+               work->word1.cn38xx.grp = grp;
+}
+
+static inline int cvmx_wqe_get_qos(cvmx_wqe_t *work)
+{
+       int qos;
+
+       if (octeon_has_feature(OCTEON_FEATURE_CN68XX_WQE))
+               qos = work->word1.cn68xx.qos;
+       else
+               qos = work->word1.cn38xx.qos;
+
+       return qos;
+}
+
+static inline void cvmx_wqe_set_qos(cvmx_wqe_t *work, int qos)
+{
+       if (octeon_has_feature(OCTEON_FEATURE_CN68XX_WQE))
+               work->word1.cn68xx.qos = qos;
+       else
+               work->word1.cn38xx.qos = qos;
+}
+
 #endif /* __CVMX_WQE_H__ */
index 46017419bb6eb50c380036b73aaed53a342eb640..ff7ad91c85db325b27dacb8987c9e1b930088855 100644 (file)
@@ -244,7 +244,7 @@ static inline uint64_t pte_to_entrylo(unsigned long pte_val)
 #define _CACHE_CACHABLE_NONCOHERENT (3<<_CACHE_SHIFT)  /* LOONGSON       */
 #define _CACHE_CACHABLE_COHERENT    (3<<_CACHE_SHIFT)  /* LOONGSON-3     */
 
-#elif defined(CONFIG_MACH_JZ4740)
+#elif defined(CONFIG_MACH_INGENIC)
 
 /* Ingenic uses the WA bit to achieve write-combine memory writes */
 #define _CACHE_UNCACHED_ACCELERATED (1<<_CACHE_SHIFT)
index ae85694752644339af22557a5ae424cde8271400..8957f15e21ec4c911e8ebe017ea8cb4ea1276ad4 100644 (file)
@@ -393,6 +393,8 @@ static inline pgprot_t pgprot_noncached(pgprot_t _prot)
        return __pgprot(prot);
 }
 
+#define pgprot_writecombine pgprot_writecombine
+
 static inline pgprot_t pgprot_writecombine(pgprot_t _prot)
 {
        unsigned long prot = pgprot_val(_prot);
index 9b3b48e21c221ffdcfc04ec9cae6165576043225..59ee6dcf6eed9fd2b336347b0d674070baf9f298 100644 (file)
@@ -275,6 +275,7 @@ struct thread_struct {
        unsigned long cp0_badvaddr;     /* Last user fault */
        unsigned long cp0_baduaddr;     /* Last kernel fault accessing USEG */
        unsigned long error_code;
+       unsigned long trap_nr;
 #ifdef CONFIG_CPU_CAVIUM_OCTEON
        struct octeon_cop2_state cp2 __attribute__ ((__aligned__(128)));
        struct octeon_cvmseg_state cvmseg __attribute__ ((__aligned__(128)));
@@ -341,6 +342,7 @@ struct thread_struct {
        .cp0_badvaddr           = 0,                            \
        .cp0_baduaddr           = 0,                            \
        .error_code             = 0,                            \
+       .trap_nr                = 0,                            \
        /*                                                      \
         * Platform specific cop2 registers(null if no COP2)    \
         */                                                     \
index ffc320389f40a011ac6c66ef9c453fce23e38c34..f6fc6aac54963fcebcf7a55e094ec32689923ea7 100644 (file)
 #include <linux/linkage.h>
 #include <linux/types.h>
 #include <asm/isadep.h>
+#include <asm/page.h>
+#include <asm/thread_info.h>
 #include <uapi/asm/ptrace.h>
 
 /*
  * This struct defines the way the registers are stored on the stack during a
  * system call/exception. As usual the registers k0/k1 aren't being saved.
+ *
+ * If you add a register here, also add it to regoffset_table[] in
+ * arch/mips/kernel/ptrace.c.
  */
 struct pt_regs {
 #ifdef CONFIG_32BIT
@@ -43,8 +48,83 @@ struct pt_regs {
        unsigned long long mpl[6];        /* MTM{0-5} */
        unsigned long long mtp[6];        /* MTP{0-5} */
 #endif
+       unsigned long __last[0];
 } __aligned(8);
 
+static inline unsigned long kernel_stack_pointer(struct pt_regs *regs)
+{
+       return regs->regs[31];
+}
+
+/*
+ * Don't use asm-generic/ptrace.h it defines FP accessors that don't make
+ * sense on MIPS.  We rather want an error if they get invoked.
+ */
+
+static inline void instruction_pointer_set(struct pt_regs *regs,
+                                           unsigned long val)
+{
+       regs->cp0_epc = val;
+}
+
+/* Query offset/name of register from its name/offset */
+extern int regs_query_register_offset(const char *name);
+#define MAX_REG_OFFSET (offsetof(struct pt_regs, __last))
+
+/**
+ * regs_get_register() - get register value from its offset
+ * @regs:       pt_regs from which register value is gotten.
+ * @offset:     offset number of the register.
+ *
+ * regs_get_register returns the value of a register. The @offset is the
+ * offset of the register in struct pt_regs address which specified by @regs.
+ * If @offset is bigger than MAX_REG_OFFSET, this returns 0.
+ */
+static inline unsigned long regs_get_register(struct pt_regs *regs,
+                                              unsigned int offset)
+{
+       if (unlikely(offset > MAX_REG_OFFSET))
+               return 0;
+
+       return *(unsigned long *)((unsigned long)regs + offset);
+}
+
+/**
+ * regs_within_kernel_stack() - check the address in the stack
+ * @regs:       pt_regs which contains kernel stack pointer.
+ * @addr:       address which is checked.
+ *
+ * regs_within_kernel_stack() checks @addr is within the kernel stack page(s).
+ * If @addr is within the kernel stack, it returns true. If not, returns false.
+ */
+static inline int regs_within_kernel_stack(struct pt_regs *regs,
+                                           unsigned long addr)
+{
+       return ((addr & ~(THREAD_SIZE - 1))  ==
+               (kernel_stack_pointer(regs) & ~(THREAD_SIZE - 1)));
+}
+
+/**
+ * regs_get_kernel_stack_nth() - get Nth entry of the stack
+ * @regs:       pt_regs which contains kernel stack pointer.
+ * @n:          stack entry number.
+ *
+ * regs_get_kernel_stack_nth() returns @n th entry of the kernel stack which
+ * is specified by @regs. If the @n th entry is NOT in the kernel stack,
+ * this returns 0.
+ */
+static inline unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs,
+                                                      unsigned int n)
+{
+       unsigned long *addr = (unsigned long *)kernel_stack_pointer(regs);
+
+       addr += n;
+       if (regs_within_kernel_stack(regs, (unsigned long)addr))
+               return *addr;
+       else
+               return 0;
+}
+
 struct task_struct;
 
 extern int ptrace_getregs(struct task_struct *child,
index 8efe5a9e2c3e68a1ab5cffe718fe58bbd815abb4..003e273eff4cef853b27a6b348be4d87de882774 100644 (file)
@@ -23,4 +23,7 @@
 
 #define __ARCH_HAS_IRIX_SIGACTION
 
+extern int protected_save_fp_context(void __user *sc);
+extern int protected_restore_fp_context(void __user *sc);
+
 #endif /* _ASM_SIGNAL_H */
index 9de4ba43dcd11aa9a9e029b936e7f1a488977f53..40196bebe849a0c825cc8a61e40b03440d14f31e 100644 (file)
@@ -42,6 +42,11 @@ static inline int arch_spin_is_locked(arch_spinlock_t *lock)
        return ((counters >> 16) ^ counters) & 0xffff;
 }
 
+static inline int arch_spin_value_unlocked(arch_spinlock_t lock)
+{
+       return lock.h.serving_now == lock.h.ticket;
+}
+
 #define arch_spin_lock_flags(lock, flags) arch_spin_lock(lock)
 #define arch_spin_unlock_wait(x) \
        while (arch_spin_is_locked(x)) { cpu_relax(); }
index 7163cd7fdd69a622892e4be83acbe0450e8f2af0..28b5d84a5022a13c7b9c782ad446c30bdff06b29 100644 (file)
 #include <asm/watch.h>
 #include <asm/dsp.h>
 #include <asm/cop2.h>
-#include <asm/msa.h>
+#include <asm/fpu.h>
 
 struct task_struct;
 
-enum {
-       FP_SAVE_NONE    = 0,
-       FP_SAVE_VECTOR  = -1,
-       FP_SAVE_SCALAR  = 1,
-};
-
 /**
  * resume - resume execution of a task
  * @prev:      The task previously executed.
  * @next:      The task to begin executing.
  * @next_ti:   task_thread_info(next).
- * @fp_save:   Which, if any, FP context to save for prev.
  *
  * This function is used whilst scheduling to save the context of prev & load
  * the context of next. Returns prev.
  */
 extern asmlinkage struct task_struct *resume(struct task_struct *prev,
-               struct task_struct *next, struct thread_info *next_ti,
-               s32 fp_save);
+               struct task_struct *next, struct thread_info *next_ti);
 
 extern unsigned int ll_bit;
 extern struct task_struct *ll_task;
@@ -83,45 +75,38 @@ do {        if (cpu_has_rw_llb) {                                           \
        }                                                               \
 } while (0)
 
+/*
+ * For newly created kernel threads switch_to() will return to
+ * ret_from_kernel_thread, newly created user threads to ret_from_fork.
+ * That is, everything following resume() will be skipped for new threads.
+ * So everything that matters to new threads should be placed before resume().
+ */
 #define switch_to(prev, next, last)                                    \
 do {                                                                   \
-       u32 __c0_stat;                                                  \
-       s32 __fpsave = FP_SAVE_NONE;                                    \
        __mips_mt_fpaff_switch_to(prev);                                \
-       if (cpu_has_dsp)                                                \
+       lose_fpu_inatomic(1, prev);                                     \
+       if (cpu_has_dsp) {                                              \
                __save_dsp(prev);                                       \
-       if (cop2_present && (KSTK_STATUS(prev) & ST0_CU2)) {            \
-               if (cop2_lazy_restore)                                  \
-                       KSTK_STATUS(prev) &= ~ST0_CU2;                  \
-               __c0_stat = read_c0_status();                           \
-               write_c0_status(__c0_stat | ST0_CU2);                   \
-               cop2_save(prev);                                        \
-               write_c0_status(__c0_stat & ~ST0_CU2);                  \
+               __restore_dsp(next);                                    \
        }                                                               \
-       __clear_software_ll_bit();                                      \
-       if (test_and_clear_tsk_thread_flag(prev, TIF_USEDFPU))          \
-               __fpsave = FP_SAVE_SCALAR;                              \
-       if (test_and_clear_tsk_thread_flag(prev, TIF_USEDMSA))          \
-               __fpsave = FP_SAVE_VECTOR;                              \
-       (last) = resume(prev, next, task_thread_info(next), __fpsave);  \
-} while (0)
-
-#define finish_arch_switch(prev)                                       \
-do {                                                                   \
-       u32 __c0_stat;                                                  \
-       if (cop2_present && !cop2_lazy_restore &&                       \
-                       (KSTK_STATUS(current) & ST0_CU2)) {             \
-               __c0_stat = read_c0_status();                           \
-               write_c0_status(__c0_stat | ST0_CU2);                   \
-               cop2_restore(current);                                  \
-               write_c0_status(__c0_stat & ~ST0_CU2);                  \
+       if (cop2_present) {                                             \
+               set_c0_status(ST0_CU2);                                 \
+               if ((KSTK_STATUS(prev) & ST0_CU2)) {                    \
+                       if (cop2_lazy_restore)                          \
+                               KSTK_STATUS(prev) &= ~ST0_CU2;          \
+                       cop2_save(prev);                                \
+               }                                                       \
+               if (KSTK_STATUS(next) & ST0_CU2 &&                      \
+                   !cop2_lazy_restore) {                               \
+                       cop2_restore(next);                             \
+               }                                                       \
+               clear_c0_status(ST0_CU2);                               \
        }                                                               \
-       if (cpu_has_dsp)                                                \
-               __restore_dsp(current);                                 \
+       __clear_software_ll_bit();                                      \
        if (cpu_has_userlocal)                                          \
-               write_c0_userlocal(current_thread_info()->tp_value);    \
+               write_c0_userlocal(task_thread_info(next)->tp_value);   \
        __restore_watch();                                              \
-       disable_msa();                                                  \
+       (last) = resume(prev, next, task_thread_info(next));            \
 } while (0)
 
 #endif /* _ASM_SWITCH_TO_H */
index 9c0014e87c1746fbe23555d7f2cd72885d1b68a5..e309d8fcb5167b40abdca4f07c82d5d97665d1bc 100644 (file)
@@ -99,6 +99,7 @@ static inline struct thread_info *current_thread_info(void)
 #define TIF_SYSCALL_AUDIT      3       /* syscall auditing active */
 #define TIF_SECCOMP            4       /* secure computing */
 #define TIF_NOTIFY_RESUME      5       /* callback before returning to user */
+#define TIF_UPROBE             6       /* breakpointed or singlestepping */
 #define TIF_RESTORE_SIGMASK    9       /* restore signal mask in do_signal() */
 #define TIF_USEDFPU            16      /* FPU was used by this task this quantum (SMP) */
 #define TIF_MEMDIE             18      /* is terminating due to OOM killer */
@@ -122,6 +123,7 @@ static inline struct thread_info *current_thread_info(void)
 #define _TIF_SYSCALL_AUDIT     (1<<TIF_SYSCALL_AUDIT)
 #define _TIF_SECCOMP           (1<<TIF_SECCOMP)
 #define _TIF_NOTIFY_RESUME     (1<<TIF_NOTIFY_RESUME)
+#define _TIF_UPROBE            (1<<TIF_UPROBE)
 #define _TIF_USEDFPU           (1<<TIF_USEDFPU)
 #define _TIF_NOHZ              (1<<TIF_NOHZ)
 #define _TIF_FIXADE            (1<<TIF_FIXADE)
@@ -146,7 +148,8 @@ static inline struct thread_info *current_thread_info(void)
 
 /* work to do on interrupt/exception return */
 #define _TIF_WORK_MASK         \
-       (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_NOTIFY_RESUME)
+       (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_NOTIFY_RESUME |     \
+        _TIF_UPROBE)
 /* work to do on any return to u-space */
 #define _TIF_ALLWORK_MASK      (_TIF_NOHZ | _TIF_WORK_MASK |           \
                                 _TIF_WORK_SYSCALL_EXIT |               \
index 8ab2874225c446d6984e42e42827add90089ea8c..17d4cd20f18c1498ac3416267f31980a56f54245 100644 (file)
@@ -51,7 +51,7 @@ extern int __weak get_c0_perfcount_int(void);
 /*
  * Initialize the calling CPU's compare interrupt as clockevent device
  */
-extern unsigned int __weak get_c0_compare_int(void);
+extern unsigned int get_c0_compare_int(void);
 extern int r4k_clockevent_init(void);
 
 static inline int mips_clockevent_init(void)
index bb8f5c29c3d9f9a5e0c72c4497993fec46fcfae2..3a25a8780ac76b9d420ca66c2b319674c5c8932a 100644 (file)
@@ -11,6 +11,7 @@
 /*
  * TLB debugging functions:
  */
+extern void dump_tlb_regs(void);
 extern void dump_tlb_all(void);
 
 #endif /* __ASM_TLBDEBUG_H */
diff --git a/arch/mips/include/asm/uprobes.h b/arch/mips/include/asm/uprobes.h
new file mode 100644 (file)
index 0000000..34c325c
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+#ifndef __ASM_UPROBES_H
+#define __ASM_UPROBES_H
+
+#include <linux/notifier.h>
+#include <linux/types.h>
+
+#include <asm/break.h>
+#include <asm/inst.h>
+
+/*
+ * We want this to be defined as union mips_instruction but that makes the
+ * generic code blow up.
+ */
+typedef u32 uprobe_opcode_t;
+
+/*
+ * Classic MIPS (note this implementation doesn't consider microMIPS yet)
+ * instructions are always 4 bytes but in order to deal with branches and
+ * their delay slots, we treat instructions as having 8 bytes maximum.
+ */
+#define MAX_UINSN_BYTES                        8
+#define UPROBE_XOL_SLOT_BYTES          128     /* Max. cache line size */
+
+#define UPROBE_BRK_UPROBE              0x000d000d      /* break 13 */
+#define UPROBE_BRK_UPROBE_XOL          0x000e000d      /* break 14 */
+
+#define UPROBE_SWBP_INSN               UPROBE_BRK_UPROBE
+#define UPROBE_SWBP_INSN_SIZE          4
+
+struct arch_uprobe {
+       unsigned long   resume_epc;
+       u32     insn[2];
+       u32     ixol[2];
+       union   mips_instruction orig_inst[MAX_UINSN_BYTES / 4];
+};
+
+struct arch_uprobe_task {
+       unsigned long saved_trap_nr;
+};
+
+extern int arch_uprobe_analyze_insn(struct arch_uprobe *aup,
+       struct mm_struct *mm, unsigned long addr);
+extern int arch_uprobe_pre_xol(struct arch_uprobe *aup, struct pt_regs *regs);
+extern int arch_uprobe_post_xol(struct arch_uprobe *aup, struct pt_regs *regs);
+extern bool arch_uprobe_xol_was_trapped(struct task_struct *tsk);
+extern int arch_uprobe_exception_notify(struct notifier_block *self,
+       unsigned long val, void *data);
+extern void arch_uprobe_abort_xol(struct arch_uprobe *aup,
+       struct pt_regs *regs);
+extern unsigned long arch_uretprobe_hijack_return_addr(
+       unsigned long trampoline_vaddr, struct pt_regs *regs);
+
+#endif /* __ASM_UPROBES_H */
index 7849f3978feafe09cd0d9e712526bcc13d5e6c37..80e70dbd1f6417aaecf22871e8e82fefc130f8bf 100644 (file)
@@ -122,7 +122,7 @@ void release_vpe(struct vpe *v);
 void *alloc_progmem(unsigned long len);
 void release_progmem(void *ptr);
 
-int __weak vpe_run(struct vpe *v);
+int vpe_run(struct vpe *v);
 void cleanup_tc(struct tc *tc);
 
 int __init vpe_module_init(void);
index 002c39ea20c3e26baf1d1f25d0985ea925841670..9c4265cbf151812e6c67b94265c4d19216e5d542 100644 (file)
@@ -21,6 +21,8 @@
 #define BRK_DIVZERO    7       /* Divide by zero check */
 #define BRK_RANGE      8       /* Range error check */
 #define BRK_BUG                12      /* Used by BUG() */
+#define BRK_UPROBE     13      /* See <asm/uprobes.h> */
+#define BRK_UPROBE_XOL 14      /* See <asm/uprobes.h> */
 #define BRK_MEMU       514     /* Used by FPU emulator */
 #define BRK_KPROBE_BP  515     /* Kprobe break */
 #define BRK_KPROBE_SSTEPBP 516 /* Kprobe single step software implementation */
diff --git a/arch/mips/include/uapi/asm/hwcap.h b/arch/mips/include/uapi/asm/hwcap.h
new file mode 100644 (file)
index 0000000..c7484a7
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef _UAPI_ASM_HWCAP_H
+#define _UAPI_ASM_HWCAP_H
+
+/* HWCAP flags */
+#define HWCAP_MIPS_R6          (1 << 0)
+#define HWCAP_MIPS_MSA         (1 << 1)
+
+#endif /* _UAPI_ASM_HWCAP_H */
index fc0cf5ac0cf72ce28a38eec08a422719343ba4e4..9b44d5a816fa3ee64faf18a80c7f415dfb681a4d 100644 (file)
@@ -26,7 +26,7 @@ enum major_op {
        cop0_op, cop1_op, cop2_op, cop1x_op,
        beql_op, bnel_op, blezl_op, bgtzl_op,
        daddi_op, cbcond1_op = daddi_op, daddiu_op, ldl_op, ldr_op,
-       spec2_op, jalx_op, mdmx_op, spec3_op,
+       spec2_op, jalx_op, mdmx_op, msa_op = mdmx_op, spec3_op,
        lb_op, lh_op, lwl_op, lw_op,
        lbu_op, lhu_op, lwr_op, lwu_op,
        sb_op, sh_op, swl_op, sw_op,
@@ -167,8 +167,13 @@ enum cop1_sdw_func {
        fround_op    =  0x0c, ftrunc_op    =  0x0d,
        fceil_op     =  0x0e, ffloor_op    =  0x0f,
        fmovc_op     =  0x11, fmovz_op     =  0x12,
-       fmovn_op     =  0x13, frecip_op    =  0x15,
-       frsqrt_op    =  0x16, fcvts_op     =  0x20,
+       fmovn_op     =  0x13, fseleqz_op   =  0x14,
+       frecip_op    =  0x15, frsqrt_op    =  0x16,
+       fselnez_op   =  0x17, fmaddf_op    =  0x18,
+       fmsubf_op    =  0x19, frint_op     =  0x1a,
+       fclass_op    =  0x1b, fmin_op      =  0x1c,
+       fmina_op     =  0x1d, fmax_op      =  0x1e,
+       fmaxa_op     =  0x1f, fcvts_op     =  0x20,
        fcvtd_op     =  0x21, fcvte_op     =  0x22,
        fcvtw_op     =  0x24, fcvtl_op     =  0x25,
        fcmp_op      =  0x30
@@ -220,6 +225,24 @@ enum bshfl_func {
        seh_op  = 0x18,
 };
 
+/*
+ * func field for MSA MI10 format.
+ */
+enum msa_mi10_func {
+       msa_ld_op = 8,
+       msa_st_op = 9,
+};
+
+/*
+ * MSA 2 bit format fields.
+ */
+enum msa_2b_fmt {
+       msa_fmt_b = 0,
+       msa_fmt_h = 1,
+       msa_fmt_w = 2,
+       msa_fmt_d = 3,
+};
+
 /*
  * (microMIPS) Major opcodes.
  */
@@ -611,6 +634,16 @@ struct v_format {                          /* MDMX vector format */
        ;)))))))
 };
 
+struct msa_mi10_format {               /* MSA MI10 */
+       __BITFIELD_FIELD(unsigned int opcode : 6,
+       __BITFIELD_FIELD(signed int s10 : 10,
+       __BITFIELD_FIELD(unsigned int rs : 5,
+       __BITFIELD_FIELD(unsigned int wd : 5,
+       __BITFIELD_FIELD(unsigned int func : 4,
+       __BITFIELD_FIELD(unsigned int df : 2,
+       ;))))))
+};
+
 struct spec3_format {   /* SPEC3 */
        __BITFIELD_FIELD(unsigned int opcode:6,
        __BITFIELD_FIELD(unsigned int rs:5,
@@ -888,6 +921,7 @@ union mips_instruction {
        struct p_format p_format;
        struct f_format f_format;
        struct ma_format ma_format;
+       struct msa_mi10_format msa_mi10_format;
        struct b_format b_format;
        struct ps_format ps_format;
        struct v_format v_format;
index 9081d88ae44f31a1bf0c2e4d5c4ae1bdc0e487db..5cbd9ae6421faa23948af2704222ff312adfda0d 100644 (file)
 #include <linux/types.h>
 #include <asm/sgidefs.h>
 
+/* scalar FP context was used */
+#define USED_FP                        (1 << 0)
+
+/* the value of Status.FR when context was saved */
+#define USED_FR1               (1 << 1)
+
+/* FR=1, but with odd singles in bits 63:32 of preceding even double */
+#define USED_HYBRID_FPRS       (1 << 2)
+
+/* extended context was used, see struct extcontext for details */
+#define USED_EXTCONTEXT                (1 << 3)
+
 #if _MIPS_SIM == _MIPS_SIM_ABI32
 
 /*
diff --git a/arch/mips/include/uapi/asm/ucontext.h b/arch/mips/include/uapi/asm/ucontext.h
new file mode 100644 (file)
index 0000000..2320144
--- /dev/null
@@ -0,0 +1,65 @@
+#ifndef __MIPS_UAPI_ASM_UCONTEXT_H
+#define __MIPS_UAPI_ASM_UCONTEXT_H
+
+/**
+ * struct extcontext - extended context header structure
+ * @magic:     magic value identifying the type of extended context
+ * @size:      the size in bytes of the enclosing structure
+ *
+ * Extended context structures provide context which does not fit within struct
+ * sigcontext. They are placed sequentially in memory at the end of struct
+ * ucontext and struct sigframe, with each extended context structure beginning
+ * with a header defined by this struct. The type of context represented is
+ * indicated by the magic field. Userland may check each extended context
+ * structure against magic values that it recognises. The size field allows any
+ * unrecognised context to be skipped, allowing for future expansion. The end
+ * of the extended context data is indicated by the magic value
+ * END_EXTCONTEXT_MAGIC.
+ */
+struct extcontext {
+       unsigned int            magic;
+       unsigned int            size;
+};
+
+/**
+ * struct msa_extcontext - MSA extended context structure
+ * @ext:       the extended context header, with magic == MSA_EXTCONTEXT_MAGIC
+ * @wr:                the most significant 64 bits of each MSA vector register
+ * @csr:       the value of the MSA control & status register
+ *
+ * If MSA context is live for a task at the time a signal is delivered to it,
+ * this structure will hold the MSA context of the task as it was prior to the
+ * signal delivery.
+ */
+struct msa_extcontext {
+       struct extcontext       ext;
+#define MSA_EXTCONTEXT_MAGIC   0x784d5341      /* xMSA */
+
+       unsigned long long      wr[32];
+       unsigned int            csr;
+};
+
+#define END_EXTCONTEXT_MAGIC   0x78454e44      /* xEND */
+
+/**
+ * struct ucontext - user context structure
+ * @uc_flags:
+ * @uc_link:
+ * @uc_stack:
+ * @uc_mcontext:       holds basic processor state
+ * @uc_sigmask:
+ * @uc_extcontext:     holds extended processor state
+ */
+struct ucontext {
+       /* Historic fields matching asm-generic */
+       unsigned long           uc_flags;
+       struct ucontext         *uc_link;
+       stack_t                 uc_stack;
+       struct sigcontext       uc_mcontext;
+       sigset_t                uc_sigmask;
+
+       /* Extended context structures may follow ucontext */
+       unsigned long long      uc_extcontext[0];
+};
+
+#endif /* __MIPS_UAPI_ASM_UCONTEXT_H */
index e1ea4f625f7a455795c07cc7d5e155edfbb2bd95..5d6828b2a750c2d3bf982e3a96415cdc7f6b451f 100644 (file)
@@ -110,18 +110,11 @@ asmlinkage void plat_irq_dispatch(void)
        }
 }
 
-static void r4030_set_mode(enum clock_event_mode mode,
-                          struct clock_event_device *evt)
-{
-       /* Nothing to do ...  */
-}
-
 struct clock_event_device r4030_clockevent = {
        .name           = "r4030",
        .features       = CLOCK_EVT_FEAT_PERIODIC,
        .rating         = 300,
        .irq            = JAZZ_TIMER_IRQ,
-       .set_mode       = r4030_set_mode,
 };
 
 static irqreturn_t r4030_timer_interrupt(int irq, void *dev_id)
index 54c80d42a88d60d0a9f4eac2270c163a0fa2501f..6cd69fdaa1c5f95f9ce06ab31b1177c73a7f650f 100644 (file)
@@ -231,6 +231,13 @@ static int jz_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
        return 0;
 }
 
+static int jz_gpio_to_irq(struct gpio_chip *chip, unsigned gpio)
+{
+       struct jz_gpio_chip *jz_gpio = gpio_chip_to_jz_gpio_chip(chip);
+
+       return jz_gpio->irq_base + gpio;
+}
+
 int jz_gpio_port_direction_input(int port, uint32_t mask)
 {
        writel(mask, GPIO_TO_REG(port, JZ_REG_GPIO_DIRECTION_CLEAR));
@@ -262,18 +269,6 @@ uint32_t jz_gpio_port_get_value(int port, uint32_t mask)
 }
 EXPORT_SYMBOL(jz_gpio_port_get_value);
 
-int gpio_to_irq(unsigned gpio)
-{
-       return JZ4740_IRQ_GPIO(0) + gpio;
-}
-EXPORT_SYMBOL_GPL(gpio_to_irq);
-
-int irq_to_gpio(unsigned irq)
-{
-       return irq - JZ4740_IRQ_GPIO(0);
-}
-EXPORT_SYMBOL_GPL(irq_to_gpio);
-
 #define IRQ_TO_BIT(irq) BIT(irq_to_gpio(irq) & 0x1f)
 
 static void jz_gpio_check_trigger_both(struct jz_gpio_chip *chip, unsigned int irq)
@@ -403,6 +398,7 @@ static int jz_gpio_irq_set_wake(struct irq_data *data, unsigned int on)
                .get = jz_gpio_get_value, \
                .direction_output = jz_gpio_direction_output, \
                .direction_input = jz_gpio_direction_input, \
+               .to_irq = jz_gpio_to_irq, \
                .base = JZ4740_GPIO_BASE_ ## _bank, \
                .ngpio = JZ4740_GPIO_NUM_ ## _bank, \
        }, \
@@ -423,8 +419,8 @@ static void jz4740_gpio_chip_init(struct jz_gpio_chip *chip, unsigned int id)
        chip->base = ioremap(JZ4740_GPIO_BASE_ADDR + (id * 0x100), 0x100);
 
        chip->irq = JZ4740_IRQ_INTC_GPIO(id);
-       irq_set_handler_data(chip->irq, chip);
-       irq_set_chained_handler(chip->irq, jz_gpio_irq_demux_handler);
+       irq_set_chained_handler_and_data(chip->irq,
+                                        jz_gpio_irq_demux_handler, chip);
 
        gc = irq_alloc_generic_chip(chip->gpio_chip.label, 1, chip->irq_base,
                chip->base, handle_level_irq);
index 7ab47fee1be8fdf24ae76dd3a0787221890eaa10..1f7ca2c9f26259c52382e091dbef166a41e046f6 100644 (file)
@@ -58,7 +58,7 @@ static irqreturn_t jz4740_clockevent_irq(int irq, void *devid)
 
        jz4740_timer_ack_full(TIMER_CLOCKEVENT);
 
-       if (cd->mode != CLOCK_EVT_MODE_PERIODIC)
+       if (!clockevent_state_periodic(cd))
                jz4740_timer_disable(TIMER_CLOCKEVENT);
 
        cd->event_handler(cd);
@@ -66,24 +66,29 @@ static irqreturn_t jz4740_clockevent_irq(int irq, void *devid)
        return IRQ_HANDLED;
 }
 
-static void jz4740_clockevent_set_mode(enum clock_event_mode mode,
-       struct clock_event_device *cd)
+static int jz4740_clockevent_set_periodic(struct clock_event_device *evt)
 {
-       switch (mode) {
-       case CLOCK_EVT_MODE_PERIODIC:
-               jz4740_timer_set_count(TIMER_CLOCKEVENT, 0);
-               jz4740_timer_set_period(TIMER_CLOCKEVENT, jz4740_jiffies_per_tick);
-       case CLOCK_EVT_MODE_RESUME:
-               jz4740_timer_irq_full_enable(TIMER_CLOCKEVENT);
-               jz4740_timer_enable(TIMER_CLOCKEVENT);
-               break;
-       case CLOCK_EVT_MODE_ONESHOT:
-       case CLOCK_EVT_MODE_SHUTDOWN:
-               jz4740_timer_disable(TIMER_CLOCKEVENT);
-               break;
-       default:
-               break;
-       }
+       jz4740_timer_set_count(TIMER_CLOCKEVENT, 0);
+       jz4740_timer_set_period(TIMER_CLOCKEVENT, jz4740_jiffies_per_tick);
+       jz4740_timer_irq_full_enable(TIMER_CLOCKEVENT);
+       jz4740_timer_enable(TIMER_CLOCKEVENT);
+
+       return 0;
+}
+
+static int jz4740_clockevent_resume(struct clock_event_device *evt)
+{
+       jz4740_timer_irq_full_enable(TIMER_CLOCKEVENT);
+       jz4740_timer_enable(TIMER_CLOCKEVENT);
+
+       return 0;
+}
+
+static int jz4740_clockevent_shutdown(struct clock_event_device *evt)
+{
+       jz4740_timer_disable(TIMER_CLOCKEVENT);
+
+       return 0;
 }
 
 static int jz4740_clockevent_set_next(unsigned long evt,
@@ -100,7 +105,10 @@ static struct clock_event_device jz4740_clockevent = {
        .name = "jz4740-timer",
        .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
        .set_next_event = jz4740_clockevent_set_next,
-       .set_mode = jz4740_clockevent_set_mode,
+       .set_state_shutdown = jz4740_clockevent_shutdown,
+       .set_state_periodic = jz4740_clockevent_set_periodic,
+       .set_state_oneshot = jz4740_clockevent_shutdown,
+       .tick_resume = jz4740_clockevent_resume,
        .rating = 200,
 #ifdef CONFIG_MACH_JZ4740
        .irq = JZ4740_IRQ_TCU0,
index 3f5cf8aff6f344756b7a08441a771795b944828a..a61435b1ceb122e446016c4f2250f24b802bfb30 100644 (file)
@@ -100,6 +100,7 @@ obj-$(CONFIG_PERF_EVENTS)   += perf_event.o
 obj-$(CONFIG_HW_PERF_EVENTS)   += perf_event_mipsxx.o
 
 obj-$(CONFIG_JUMP_LABEL)       += jump_label.o
+obj-$(CONFIG_UPROBES)          += uprobes.o
 
 obj-$(CONFIG_MIPS_CM)          += mips-cm.o
 obj-$(CONFIG_MIPS_CPC)         += mips-cpc.o
index 072fab13645d503a3b71381fec8c5976f570a905..154e2039ea5ef13fe9ba8935eb01475031283913 100644 (file)
@@ -128,6 +128,7 @@ void output_thread_defines(void)
               thread.cp0_baduaddr);
        OFFSET(THREAD_ECODE, task_struct, \
               thread.error_code);
+       OFFSET(THREAD_TRAPNO, task_struct, thread.trap_nr);
        BLANK();
 }
 
@@ -245,17 +246,6 @@ void output_sc_defines(void)
 }
 #endif
 
-#ifdef CONFIG_MIPS32_COMPAT
-void output_sc32_defines(void)
-{
-       COMMENT("Linux 32-bit sigcontext offsets.");
-       OFFSET(SC32_FPREGS, sigcontext32, sc_fpregs);
-       OFFSET(SC32_FPC_CSR, sigcontext32, sc_fpc_csr);
-       OFFSET(SC32_FPC_EIR, sigcontext32, sc_fpc_eir);
-       BLANK();
-}
-#endif
-
 void output_signal_defined(void)
 {
        COMMENT("Linux signal numbers.");
index 7976457184b1801771fdcd31e7b9e40b3633992b..940ac00e9129acc261369efee579545eb8028215 100644 (file)
@@ -40,8 +40,8 @@
  * 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)
+
+static int sibyte_set_periodic(struct clock_event_device *evt)
 {
        unsigned int cpu = smp_processor_id();
        void __iomem *cfg, *init;
@@ -49,24 +49,22 @@ static void sibyte_set_mode(enum clock_event_mode mode,
        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:
-               ;
-       }
+       __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);
+       return 0;
+}
+
+static int sibyte_shutdown(struct clock_event_device *evt)
+{
+       unsigned int cpu = smp_processor_id();
+       void __iomem *cfg;
+
+       cfg = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG));
+
+       /* Stop the timer until we actually program a shot */
+       __raw_writeq(0, cfg);
+       return 0;
 }
 
 static int sibyte_next_event(unsigned long delta, struct clock_event_device *cd)
@@ -91,7 +89,7 @@ static irqreturn_t sibyte_counter_handler(int irq, void *dev_id)
        void __iomem *cfg;
        unsigned long tmode;
 
-       if (cd->mode == CLOCK_EVT_MODE_PERIODIC)
+       if (clockevent_state_periodic(cd))
                tmode = M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS;
        else
                tmode = 0;
@@ -130,7 +128,9 @@ void sb1480_clockevent_init(void)
        cd->irq                 = irq;
        cd->cpumask             = cpumask_of(cpu);
        cd->set_next_event      = sibyte_next_event;
-       cd->set_mode            = sibyte_set_mode;
+       cd->set_state_shutdown  = sibyte_shutdown;
+       cd->set_state_periodic  = sibyte_set_periodic;
+       cd->set_state_oneshot   = sibyte_shutdown;
        clockevents_register_device(cd);
 
        bcm1480_mask_irq(cpu, irq);
index ff1f01b72270fdd4e4051799fc93580b884dcd23..77a5ddf53f57e50b96432897bc9b04012e57fedf 100644 (file)
@@ -59,27 +59,32 @@ static int ds1287_set_next_event(unsigned long delta,
        return -EINVAL;
 }
 
-static void ds1287_set_mode(enum clock_event_mode mode,
-                           struct clock_event_device *evt)
+static int ds1287_shutdown(struct clock_event_device *evt)
 {
        u8 val;
 
        spin_lock(&rtc_lock);
 
        val = CMOS_READ(RTC_REG_B);
+       val &= ~RTC_PIE;
+       CMOS_WRITE(val, RTC_REG_B);
 
-       switch (mode) {
-       case CLOCK_EVT_MODE_PERIODIC:
-               val |= RTC_PIE;
-               break;
-       default:
-               val &= ~RTC_PIE;
-               break;
-       }
+       spin_unlock(&rtc_lock);
+       return 0;
+}
 
+static int ds1287_set_periodic(struct clock_event_device *evt)
+{
+       u8 val;
+
+       spin_lock(&rtc_lock);
+
+       val = CMOS_READ(RTC_REG_B);
+       val |= RTC_PIE;
        CMOS_WRITE(val, RTC_REG_B);
 
        spin_unlock(&rtc_lock);
+       return 0;
 }
 
 static void ds1287_event_handler(struct clock_event_device *dev)
@@ -87,11 +92,13 @@ static void ds1287_event_handler(struct clock_event_device *dev)
 }
 
 static struct clock_event_device ds1287_clockevent = {
-       .name           = "ds1287",
-       .features       = CLOCK_EVT_FEAT_PERIODIC,
-       .set_next_event = ds1287_set_next_event,
-       .set_mode       = ds1287_set_mode,
-       .event_handler  = ds1287_event_handler,
+       .name                   = "ds1287",
+       .features               = CLOCK_EVT_FEAT_PERIODIC,
+       .set_next_event         = ds1287_set_next_event,
+       .set_state_shutdown     = ds1287_shutdown,
+       .set_state_periodic     = ds1287_set_periodic,
+       .tick_resume            = ds1287_shutdown,
+       .event_handler          = ds1287_event_handler,
 };
 
 static irqreturn_t ds1287_interrupt(int irq, void *dev_id)
index f069460751ab931d10077875556ad0eec90d8bac..66040051151d3c0f27574627f08fb4cd17511acb 100644 (file)
@@ -64,8 +64,7 @@ static int gt641xx_timer0_set_next_event(unsigned long delta,
        return 0;
 }
 
-static void gt641xx_timer0_set_mode(enum clock_event_mode mode,
-                                   struct clock_event_device *evt)
+static int gt641xx_timer0_shutdown(struct clock_event_device *evt)
 {
        u32 ctrl;
 
@@ -73,21 +72,39 @@ static void gt641xx_timer0_set_mode(enum clock_event_mode mode,
 
        ctrl = GT_READ(GT_TC_CONTROL_OFS);
        ctrl &= ~(GT_TC_CONTROL_ENTC0_MSK | GT_TC_CONTROL_SELTC0_MSK);
+       GT_WRITE(GT_TC_CONTROL_OFS, ctrl);
+
+       raw_spin_unlock(&gt641xx_timer_lock);
+       return 0;
+}
+
+static int gt641xx_timer0_set_oneshot(struct clock_event_device *evt)
+{
+       u32 ctrl;
+
+       raw_spin_lock(&gt641xx_timer_lock);
+
+       ctrl = GT_READ(GT_TC_CONTROL_OFS);
+       ctrl &= ~GT_TC_CONTROL_SELTC0_MSK;
+       ctrl |= GT_TC_CONTROL_ENTC0_MSK;
+       GT_WRITE(GT_TC_CONTROL_OFS, ctrl);
+
+       raw_spin_unlock(&gt641xx_timer_lock);
+       return 0;
+}
 
-       switch (mode) {
-       case CLOCK_EVT_MODE_PERIODIC:
-               ctrl |= GT_TC_CONTROL_ENTC0_MSK | GT_TC_CONTROL_SELTC0_MSK;
-               break;
-       case CLOCK_EVT_MODE_ONESHOT:
-               ctrl |= GT_TC_CONTROL_ENTC0_MSK;
-               break;
-       default:
-               break;
-       }
+static int gt641xx_timer0_set_periodic(struct clock_event_device *evt)
+{
+       u32 ctrl;
+
+       raw_spin_lock(&gt641xx_timer_lock);
 
+       ctrl = GT_READ(GT_TC_CONTROL_OFS);
+       ctrl |= GT_TC_CONTROL_ENTC0_MSK | GT_TC_CONTROL_SELTC0_MSK;
        GT_WRITE(GT_TC_CONTROL_OFS, ctrl);
 
        raw_spin_unlock(&gt641xx_timer_lock);
+       return 0;
 }
 
 static void gt641xx_timer0_event_handler(struct clock_event_device *dev)
@@ -95,12 +112,16 @@ static void gt641xx_timer0_event_handler(struct clock_event_device *dev)
 }
 
 static struct clock_event_device gt641xx_timer0_clockevent = {
-       .name           = "gt641xx-timer0",
-       .features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
-       .irq            = GT641XX_TIMER0_IRQ,
-       .set_next_event = gt641xx_timer0_set_next_event,
-       .set_mode       = gt641xx_timer0_set_mode,
-       .event_handler  = gt641xx_timer0_event_handler,
+       .name                   = "gt641xx-timer0",
+       .features               = CLOCK_EVT_FEAT_PERIODIC |
+                                 CLOCK_EVT_FEAT_ONESHOT,
+       .irq                    = GT641XX_TIMER0_IRQ,
+       .set_next_event         = gt641xx_timer0_set_next_event,
+       .set_state_shutdown     = gt641xx_timer0_shutdown,
+       .set_state_periodic     = gt641xx_timer0_set_periodic,
+       .set_state_oneshot      = gt641xx_timer0_set_oneshot,
+       .tick_resume            = gt641xx_timer0_shutdown,
+       .event_handler          = gt641xx_timer0_event_handler,
 };
 
 static irqreturn_t gt641xx_timer0_interrupt(int irq, void *dev_id)
index d70c4d893219ebe2bff50341025c5c3fb4f750ca..8dfe6a6e14809b992774bd7362761021b802bd15 100644 (file)
@@ -28,12 +28,6 @@ static int mips_next_event(unsigned long delta,
        return res;
 }
 
-void mips_set_clock_mode(enum clock_event_mode mode,
-                               struct clock_event_device *evt)
-{
-       /* Nothing to do ...  */
-}
-
 DEFINE_PER_CPU(struct clock_event_device, mips_clockevent_device);
 int cp0_timer_irq_installed;
 
@@ -174,6 +168,11 @@ int c0_compare_int_usable(void)
        return 1;
 }
 
+unsigned int __weak get_c0_compare_int(void)
+{
+       return MIPS_CPU_IRQ_BASE + cp0_compare_irq;
+}
+
 int r4k_clockevent_init(void)
 {
        unsigned int cpu = smp_processor_id();
@@ -189,11 +188,9 @@ int r4k_clockevent_init(void)
        /*
         * 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.
+        * interrupt number of its liking.
         */
-       irq = MIPS_CPU_IRQ_BASE + cp0_compare_irq;
-       if (get_c0_compare_int)
-               irq = get_c0_compare_int();
+       irq = get_c0_compare_int();
 
        cd = &per_cpu(mips_clockevent_device, cpu);
 
@@ -212,7 +209,6 @@ int r4k_clockevent_init(void)
        cd->irq                 = irq;
        cd->cpumask             = cpumask_of(cpu);
        cd->set_next_event      = mips_next_event;
-       cd->set_mode            = mips_set_clock_mode;
        cd->event_handler       = mips_event_handler;
 
        clockevents_register_device(cd);
index 5ea6d6b1de1504f39f5d0e670c7439775dab1083..3d860efd63b97295e9c68147493cdca52a396a4f 100644 (file)
  * 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)
+
+static int sibyte_shutdown(struct clock_event_device *evt)
+{
+       void __iomem *cfg;
+
+       cfg = IOADDR(A_SCD_TIMER_REGISTER(smp_processor_id(), R_SCD_TIMER_CFG));
+
+       /* Stop the timer until we actually program a shot */
+       __raw_writeq(0, cfg);
+
+       return 0;
+}
+
+static int sibyte_set_periodic(struct clock_event_device *evt)
 {
        unsigned int cpu = smp_processor_id();
        void __iomem *cfg, *init;
@@ -47,24 +59,11 @@ static void sibyte_set_mode(enum clock_event_mode mode,
        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:
-               ;
-       }
+       __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);
+
+       return 0;
 }
 
 static int sibyte_next_event(unsigned long delta, struct clock_event_device *cd)
@@ -89,7 +88,7 @@ static irqreturn_t sibyte_counter_handler(int irq, void *dev_id)
        void __iomem *cfg;
        unsigned long tmode;
 
-       if (cd->mode == CLOCK_EVT_MODE_PERIODIC)
+       if (clockevent_state_periodic(cd))
                tmode = M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS;
        else
                tmode = 0;
@@ -129,7 +128,9 @@ void sb1250_clockevent_init(void)
        cd->irq                 = irq;
        cd->cpumask             = cpumask_of(cpu);
        cd->set_next_event      = sibyte_next_event;
-       cd->set_mode            = sibyte_set_mode;
+       cd->set_state_shutdown  = sibyte_shutdown;
+       cd->set_state_periodic  = sibyte_set_periodic;
+       cd->set_state_oneshot   = sibyte_shutdown;
        clockevents_register_device(cd);
 
        sb1250_mask_irq(cpu, irq);
index 723932441ecc7105864c31f3225fbd921cc92260..537eefdf838fec40cc0a947008c01ea0084ca0b3 100644 (file)
@@ -85,36 +85,54 @@ static void txx9tmr_stop_and_clear(struct txx9_tmr_reg __iomem *tmrptr)
        __raw_writel(0, &tmrptr->tisr);
 }
 
-static void txx9tmr_set_mode(enum clock_event_mode mode,
-                            struct clock_event_device *evt)
+static int txx9tmr_set_state_periodic(struct clock_event_device *evt)
 {
        struct txx9_clock_event_device *txx9_cd =
                container_of(evt, struct txx9_clock_event_device, cd);
        struct txx9_tmr_reg __iomem *tmrptr = txx9_cd->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;
-       }
+
+       __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);
+       return 0;
+}
+
+static int txx9tmr_set_state_oneshot(struct clock_event_device *evt)
+{
+       struct txx9_clock_event_device *txx9_cd =
+               container_of(evt, struct txx9_clock_event_device, cd);
+       struct txx9_tmr_reg __iomem *tmrptr = txx9_cd->tmrptr;
+
+       txx9tmr_stop_and_clear(tmrptr);
+       __raw_writel(TXx9_TMITMR_TIIE, &tmrptr->itmr);
+       return 0;
+}
+
+static int txx9tmr_set_state_shutdown(struct clock_event_device *evt)
+{
+       struct txx9_clock_event_device *txx9_cd =
+               container_of(evt, struct txx9_clock_event_device, cd);
+       struct txx9_tmr_reg __iomem *tmrptr = txx9_cd->tmrptr;
+
+       txx9tmr_stop_and_clear(tmrptr);
+       __raw_writel(0, &tmrptr->itmr);
+       return 0;
+}
+
+static int txx9tmr_tick_resume(struct clock_event_device *evt)
+{
+       struct txx9_clock_event_device *txx9_cd =
+               container_of(evt, struct txx9_clock_event_device, cd);
+       struct txx9_tmr_reg __iomem *tmrptr = txx9_cd->tmrptr;
+
+       txx9tmr_stop_and_clear(tmrptr);
+       __raw_writel(TIMER_CCD, &tmrptr->ccdr);
+       __raw_writel(0, &tmrptr->itmr);
+       return 0;
 }
 
 static int txx9tmr_set_next_event(unsigned long delta,
@@ -133,12 +151,15 @@ static int txx9tmr_set_next_event(unsigned long delta,
 
 static struct txx9_clock_event_device txx9_clock_event_device = {
        .cd = {
-               .name           = "TXx9",
-               .features       = CLOCK_EVT_FEAT_PERIODIC |
-                                 CLOCK_EVT_FEAT_ONESHOT,
-               .rating         = 200,
-               .set_mode       = txx9tmr_set_mode,
-               .set_next_event = txx9tmr_set_next_event,
+               .name                   = "TXx9",
+               .features               = CLOCK_EVT_FEAT_PERIODIC |
+                                         CLOCK_EVT_FEAT_ONESHOT,
+               .rating                 = 200,
+               .set_state_shutdown     = txx9tmr_set_state_shutdown,
+               .set_state_periodic     = txx9tmr_set_state_periodic,
+               .set_state_oneshot      = txx9tmr_set_state_oneshot,
+               .tick_resume            = txx9tmr_tick_resume,
+               .set_next_event         = txx9tmr_set_next_event,
        },
 };
 
index dbe0792fc9c1bd99c4c452aa998d825662d55ec4..571a8e6ea5bd0048a840bc539135f27c32fec621 100644 (file)
@@ -32,6 +32,9 @@
 #include <asm/spram.h>
 #include <asm/uaccess.h>
 
+/* Hardware capabilities */
+unsigned int elf_hwcap __read_mostly;
+
 /*
  * Get the FPU Implementation/Revision.
  */
@@ -188,7 +191,7 @@ __setup("nohtw", htw_disable);
 static int mips_ftlb_disabled;
 static int mips_has_ftlb_configured;
 
-static void set_ftlb_enable(struct cpuinfo_mips *c, int enable);
+static int set_ftlb_enable(struct cpuinfo_mips *c, int enable);
 
 static int __init ftlb_disable(char *s)
 {
@@ -202,7 +205,10 @@ static int __init ftlb_disable(char *s)
                return 1;
 
        /* Disable it in the boot cpu */
-       set_ftlb_enable(&cpu_data[0], 0);
+       if (set_ftlb_enable(&cpu_data[0], 0)) {
+               pr_warn("Can't turn FTLB off\n");
+               return 1;
+       }
 
        back_to_back_c0_hazard();
 
@@ -364,30 +370,41 @@ static unsigned int calculate_ftlb_probability(struct cpuinfo_mips *c)
                return 3;
 }
 
-static void set_ftlb_enable(struct cpuinfo_mips *c, int enable)
+static int set_ftlb_enable(struct cpuinfo_mips *c, int enable)
 {
-       unsigned int config6;
+       unsigned int config;
 
        /* It's implementation dependent how the FTLB can be enabled */
        switch (c->cputype) {
        case CPU_PROAPTIV:
        case CPU_P5600:
                /* proAptiv & related cores use Config6 to enable the FTLB */
-               config6 = read_c0_config6();
+               config = read_c0_config6();
                /* Clear the old probability value */
-               config6 &= ~(3 << MIPS_CONF6_FTLBP_SHIFT);
+               config &= ~(3 << MIPS_CONF6_FTLBP_SHIFT);
                if (enable)
                        /* Enable FTLB */
-                       write_c0_config6(config6 |
+                       write_c0_config6(config |
                                         (calculate_ftlb_probability(c)
                                          << MIPS_CONF6_FTLBP_SHIFT)
                                         | MIPS_CONF6_FTLBEN);
                else
                        /* Disable FTLB */
-                       write_c0_config6(config6 &  ~MIPS_CONF6_FTLBEN);
-               back_to_back_c0_hazard();
+                       write_c0_config6(config &  ~MIPS_CONF6_FTLBEN);
                break;
+       case CPU_I6400:
+               /* I6400 & related cores use Config7 to configure FTLB */
+               config = read_c0_config7();
+               /* Clear the old probability value */
+               config &= ~(3 << MIPS_CONF7_FTLBP_SHIFT);
+               write_c0_config7(config | (calculate_ftlb_probability(c)
+                                          << MIPS_CONF7_FTLBP_SHIFT));
+               break;
+       default:
+               return 1;
        }
+
+       return 0;
 }
 
 static inline unsigned int decode_config0(struct cpuinfo_mips *c)
@@ -524,6 +541,8 @@ static inline unsigned int decode_config3(struct cpuinfo_mips *c)
        }
        if (config3 & MIPS_CONF3_CDMM)
                c->options |= MIPS_CPU_CDMM;
+       if (config3 & MIPS_CONF3_SP)
+               c->options |= MIPS_CPU_SP;
 
        return config3 & MIPS_CONF_M;
 }
@@ -540,7 +559,16 @@ static inline unsigned int decode_config4(struct cpuinfo_mips *c)
        if (cpu_has_tlb) {
                if (((config4 & MIPS_CONF4_IE) >> 29) == 2)
                        c->options |= MIPS_CPU_TLBINV;
-               mmuextdef = config4 & MIPS_CONF4_MMUEXTDEF;
+               /*
+                * This is a bit ugly. R6 has dropped that field from
+                * config4 and the only valid configuration is VTLB+FTLB so
+                * set a good value for mmuextdef for that case.
+                */
+               if (cpu_has_mips_r6)
+                       mmuextdef = MIPS_CONF4_MMUEXTDEF_VTLBSIZEEXT;
+               else
+                       mmuextdef = config4 & MIPS_CONF4_MMUEXTDEF;
+
                switch (mmuextdef) {
                case MIPS_CONF4_MMUEXTDEF_MMUSIZEEXT:
                        c->tlbsize += (config4 & MIPS_CONF4_MMUSIZEEXT) * 0x40;
@@ -1121,6 +1149,10 @@ static inline void cpu_probe_mips(struct cpuinfo_mips *c, unsigned int cpu)
                c->cputype = CPU_P5600;
                __cpu_name[cpu] = "MIPS P5600";
                break;
+       case PRID_IMP_I6400:
+               c->cputype = CPU_I6400;
+               __cpu_name[cpu] = "MIPS I6400";
+               break;
        case PRID_IMP_M5150:
                c->cputype = CPU_M5150;
                __cpu_name[cpu] = "MIPS M5150";
@@ -1492,10 +1524,14 @@ void cpu_probe(void)
        else
                c->srsets = 1;
 
+       if (cpu_has_mips_r6)
+               elf_hwcap |= HWCAP_MIPS_R6;
+
        if (cpu_has_msa) {
                c->msa_id = cpu_get_msa_id();
                WARN(c->msa_id & MSA_IR_WRPF,
                     "Vector register partitioning unimplemented!");
+               elf_hwcap |= HWCAP_MIPS_MSA;
        }
 
        cpu_probe_vmbits(c);
index e4f62b7875d24b068ee44000b1ad7f8b7b5a38d4..ab1478d5a4db1b247caa94527925da0d005adf10 100644 (file)
@@ -196,6 +196,7 @@ void __init check_wait(void)
        case CPU_INTERAPTIV:
        case CPU_M5150:
        case CPU_QEMU_GENERIC:
+       case CPU_I6400:
                cpu_wait = r4k_wait;
                if (read_c0_config7() & MIPS_CONF7_WII)
                        cpu_wait = r4k_wait_irqoff;
index 85bbe9b9675972fd7f919b4b3774781410f8fbe4..b8ceee576cdfce2e22e1b2d8ffab6f90bf69f6b8 100644 (file)
 
 void __iomem *mips_cm_base;
 void __iomem *mips_cm_l2sync_base;
+int mips_cm_is64;
+
+static char *cm2_tr[8] = {
+       "mem",  "gcr",  "gic",  "mmio",
+       "0x04", "cpc", "0x06", "0x07"
+};
+
+/* CM3 Tag ECC transation type */
+static char *cm3_tr[16] = {
+       [0x0] = "ReqNoData",
+       [0x1] = "0x1",
+       [0x2] = "ReqWData",
+       [0x3] = "0x3",
+       [0x4] = "IReqNoResp",
+       [0x5] = "IReqWResp",
+       [0x6] = "IReqNoRespDat",
+       [0x7] = "IReqWRespDat",
+       [0x8] = "RespNoData",
+       [0x9] = "RespDataFol",
+       [0xa] = "RespWData",
+       [0xb] = "RespDataOnly",
+       [0xc] = "IRespNoData",
+       [0xd] = "IRespDataFol",
+       [0xe] = "IRespWData",
+       [0xf] = "IRespDataOnly"
+};
+
+static char *cm2_cmd[32] = {
+       [0x00] = "0x00",
+       [0x01] = "Legacy Write",
+       [0x02] = "Legacy Read",
+       [0x03] = "0x03",
+       [0x04] = "0x04",
+       [0x05] = "0x05",
+       [0x06] = "0x06",
+       [0x07] = "0x07",
+       [0x08] = "Coherent Read Own",
+       [0x09] = "Coherent Read Share",
+       [0x0a] = "Coherent Read Discard",
+       [0x0b] = "Coherent Ready Share Always",
+       [0x0c] = "Coherent Upgrade",
+       [0x0d] = "Coherent Writeback",
+       [0x0e] = "0x0e",
+       [0x0f] = "0x0f",
+       [0x10] = "Coherent Copyback",
+       [0x11] = "Coherent Copyback Invalidate",
+       [0x12] = "Coherent Invalidate",
+       [0x13] = "Coherent Write Invalidate",
+       [0x14] = "Coherent Completion Sync",
+       [0x15] = "0x15",
+       [0x16] = "0x16",
+       [0x17] = "0x17",
+       [0x18] = "0x18",
+       [0x19] = "0x19",
+       [0x1a] = "0x1a",
+       [0x1b] = "0x1b",
+       [0x1c] = "0x1c",
+       [0x1d] = "0x1d",
+       [0x1e] = "0x1e",
+       [0x1f] = "0x1f"
+};
+
+/* CM3 Tag ECC command type */
+static char *cm3_cmd[16] = {
+       [0x0] = "Legacy Read",
+       [0x1] = "Legacy Write",
+       [0x2] = "Coherent Read Own",
+       [0x3] = "Coherent Read Share",
+       [0x4] = "Coherent Read Discard",
+       [0x5] = "Coherent Evicted",
+       [0x6] = "Coherent Upgrade",
+       [0x7] = "Coherent Upgrade for Store Conditional",
+       [0x8] = "Coherent Writeback",
+       [0x9] = "Coherent Write Invalidate",
+       [0xa] = "0xa",
+       [0xb] = "0xb",
+       [0xc] = "0xc",
+       [0xd] = "0xd",
+       [0xe] = "0xe",
+       [0xf] = "0xf"
+};
+
+/* CM3 Tag ECC command group */
+static char *cm3_cmd_group[8] = {
+       [0x0] = "Normal",
+       [0x1] = "Registers",
+       [0x2] = "TLB",
+       [0x3] = "0x3",
+       [0x4] = "L1I",
+       [0x5] = "L1D",
+       [0x6] = "L3",
+       [0x7] = "L2"
+};
+
+static char *cm2_core[8] = {
+       "Invalid/OK",   "Invalid/Data",
+       "Shared/OK",    "Shared/Data",
+       "Modified/OK",  "Modified/Data",
+       "Exclusive/OK", "Exclusive/Data"
+};
+
+static char *cm2_causes[32] = {
+       "None", "GC_WR_ERR", "GC_RD_ERR", "COH_WR_ERR",
+       "COH_RD_ERR", "MMIO_WR_ERR", "MMIO_RD_ERR", "0x07",
+       "0x08", "0x09", "0x0a", "0x0b",
+       "0x0c", "0x0d", "0x0e", "0x0f",
+       "0x10", "0x11", "0x12", "0x13",
+       "0x14", "0x15", "0x16", "INTVN_WR_ERR",
+       "INTVN_RD_ERR", "0x19", "0x1a", "0x1b",
+       "0x1c", "0x1d", "0x1e", "0x1f"
+};
+
+static char *cm3_causes[32] = {
+       "0x0", "MP_CORRECTABLE_ECC_ERR", "MP_REQUEST_DECODE_ERR",
+       "MP_UNCORRECTABLE_ECC_ERR", "MP_PARITY_ERR", "MP_COHERENCE_ERR",
+       "CMBIU_REQUEST_DECODE_ERR", "CMBIU_PARITY_ERR", "CMBIU_AXI_RESP_ERR",
+       "0x9", "RBI_BUS_ERR", "0xb", "0xc", "0xd", "0xe", "0xf", "0x10",
+       "0x11", "0x12", "0x13", "0x14", "0x15", "0x16", "0x17", "0x18",
+       "0x19", "0x1a", "0x1b", "0x1c", "0x1d", "0x1e", "0x1f"
+};
 
 phys_addr_t __mips_cm_phys_base(void)
 {
        u32 config3 = read_c0_config3();
-       u32 cmgcr;
+       unsigned long cmgcr;
 
        /* Check the CMGCRBase register is implemented */
        if (!(config3 & MIPS_CONF3_CMGCR))
@@ -81,6 +201,13 @@ int mips_cm_probe(void)
        phys_addr_t addr;
        u32 base_reg;
 
+       /*
+        * No need to probe again if we have already been
+        * here before.
+        */
+       if (mips_cm_base)
+               return 0;
+
        addr = mips_cm_phys_base();
        BUG_ON((addr & CM_GCR_BASE_GCRBASE_MSK) != addr);
        if (!addr)
@@ -117,5 +244,133 @@ int mips_cm_probe(void)
        /* probe for an L2-only sync region */
        mips_cm_probe_l2sync();
 
+       /* determine register width for this CM */
+       mips_cm_is64 = config_enabled(CONFIG_64BIT) && (mips_cm_revision() >= CM_REV_CM3);
+
        return 0;
 }
+
+void mips_cm_error_report(void)
+{
+       unsigned long revision = mips_cm_revision();
+       /*
+        * CM3 has a 64-bit Error cause register with 0:57 containing the error
+        * info and 63:58 the error type. For old CMs, everything is contained
+        * in a single 32-bit register (0:26 and 31:27 respectively). Even
+        * though the cm_error is u64, we will simply ignore the upper word
+        * for CM2.
+        */
+       u64 cm_error = read_gcr_error_cause();
+       int cm_error_cause_sft = CM_GCR_ERROR_CAUSE_ERRTYPE_SHF +
+                                ((revision >= CM_REV_CM3) ? 31 : 0);
+       unsigned long cm_addr = read_gcr_error_addr();
+       unsigned long cm_other = read_gcr_error_mult();
+       int ocause, cause;
+       char buf[256];
+
+       if (!mips_cm_present())
+               return;
+
+       cause = cm_error >> cm_error_cause_sft;
+
+       if (!cause)
+               /* All good */
+               return;
+
+       ocause = cm_other >> CM_GCR_ERROR_MULT_ERR2ND_SHF;
+       if (revision < CM_REV_CM3) { /* CM2 */
+               if (cause < 16) {
+                       unsigned long cca_bits = (cm_error >> 15) & 7;
+                       unsigned long tr_bits = (cm_error >> 12) & 7;
+                       unsigned long cmd_bits = (cm_error >> 7) & 0x1f;
+                       unsigned long stag_bits = (cm_error >> 3) & 15;
+                       unsigned long sport_bits = (cm_error >> 0) & 7;
+
+                       snprintf(buf, sizeof(buf),
+                                "CCA=%lu TR=%s MCmd=%s STag=%lu "
+                                "SPort=%lu\n", cca_bits, cm2_tr[tr_bits],
+                                cm2_cmd[cmd_bits], stag_bits, sport_bits);
+               } else {
+                       /* glob state & sresp together */
+                       unsigned long c3_bits = (cm_error >> 18) & 7;
+                       unsigned long c2_bits = (cm_error >> 15) & 7;
+                       unsigned long c1_bits = (cm_error >> 12) & 7;
+                       unsigned long c0_bits = (cm_error >> 9) & 7;
+                       unsigned long sc_bit = (cm_error >> 8) & 1;
+                       unsigned long cmd_bits = (cm_error >> 3) & 0x1f;
+                       unsigned long sport_bits = (cm_error >> 0) & 7;
+
+                       snprintf(buf, sizeof(buf),
+                                "C3=%s C2=%s C1=%s C0=%s SC=%s "
+                                "MCmd=%s SPort=%lu\n",
+                                cm2_core[c3_bits], cm2_core[c2_bits],
+                                cm2_core[c1_bits], cm2_core[c0_bits],
+                                sc_bit ? "True" : "False",
+                                cm2_cmd[cmd_bits], sport_bits);
+               }
+                       pr_err("CM_ERROR=%08llx %s <%s>\n", cm_error,
+                              cm2_causes[cause], buf);
+               pr_err("CM_ADDR =%08lx\n", cm_addr);
+               pr_err("CM_OTHER=%08lx %s\n", cm_other, cm2_causes[ocause]);
+       } else { /* CM3 */
+       /* Used by cause == {1,2,3} */
+               unsigned long core_id_bits = (cm_error >> 22) & 0xf;
+               unsigned long vp_id_bits = (cm_error >> 18) & 0xf;
+               unsigned long cmd_bits = (cm_error >> 14) & 0xf;
+               unsigned long cmd_group_bits = (cm_error >> 11) & 0xf;
+               unsigned long cm3_cca_bits = (cm_error >> 8) & 7;
+               unsigned long mcp_bits = (cm_error >> 5) & 0xf;
+               unsigned long cm3_tr_bits = (cm_error >> 1) & 0xf;
+               unsigned long sched_bit = cm_error & 0x1;
+
+               if (cause == 1 || cause == 3) { /* Tag ECC */
+                       unsigned long tag_ecc = (cm_error >> 57) & 0x1;
+                       unsigned long tag_way_bits = (cm_error >> 29) & 0xffff;
+                       unsigned long dword_bits = (cm_error >> 49) & 0xff;
+                       unsigned long data_way_bits = (cm_error >> 45) & 0xf;
+                       unsigned long data_sets_bits = (cm_error >> 29) & 0xfff;
+                       unsigned long bank_bit = (cm_error >> 28) & 0x1;
+                       snprintf(buf, sizeof(buf),
+                                "%s ECC Error: Way=%lu (DWORD=%lu, Sets=%lu)"
+                                "Bank=%lu CoreID=%lu VPID=%lu Command=%s"
+                                "Command Group=%s CCA=%lu MCP=%d"
+                                "Transaction type=%s Scheduler=%lu\n",
+                                tag_ecc ? "TAG" : "DATA",
+                                tag_ecc ? (unsigned long)ffs(tag_way_bits) - 1 :
+                                data_way_bits, bank_bit, dword_bits,
+                                data_sets_bits,
+                                core_id_bits, vp_id_bits,
+                                cm3_cmd[cmd_bits],
+                                cm3_cmd_group[cmd_group_bits],
+                                cm3_cca_bits, 1 << mcp_bits,
+                                cm3_tr[cm3_tr_bits], sched_bit);
+               } else if (cause == 2) {
+                       unsigned long data_error_type = (cm_error >> 41) & 0xfff;
+                       unsigned long data_decode_cmd = (cm_error >> 37) & 0xf;
+                       unsigned long data_decode_group = (cm_error >> 34) & 0x7;
+                       unsigned long data_decode_destination_id = (cm_error >> 28) & 0x3f;
+
+                       snprintf(buf, sizeof(buf),
+                                "Decode Request Error: Type=%lu, Command=%lu"
+                                "Command Group=%lu Destination ID=%lu"
+                                "CoreID=%lu VPID=%lu Command=%s"
+                                "Command Group=%s CCA=%lu MCP=%d"
+                                "Transaction type=%s Scheduler=%lu\n",
+                                data_error_type, data_decode_cmd,
+                                data_decode_group, data_decode_destination_id,
+                                core_id_bits, vp_id_bits,
+                                cm3_cmd[cmd_bits],
+                                cm3_cmd_group[cmd_group_bits],
+                                cm3_cca_bits, 1 << mcp_bits,
+                                cm3_tr[cm3_tr_bits], sched_bit);
+               }
+
+               pr_err("CM_ERROR=%llx %s <%s>\n", cm_error,
+                      cm3_causes[cause], buf);
+               pr_err("CM_ADDR =%lx\n", cm_addr);
+               pr_err("CM_OTHER=%lx %s\n", cm_other, cm3_causes[ocause]);
+       }
+
+       /* reprime cause register */
+       write_gcr_error_cause(0);
+}
index 11964501c4b05624387a0c9a203b51259ea2d53a..8af4d627b68b96d0d998ee7c4a06176af8234138 100644 (file)
@@ -21,9 +21,16 @@ static DEFINE_PER_CPU_ALIGNED(spinlock_t, cpc_core_lock);
 
 static DEFINE_PER_CPU_ALIGNED(unsigned long, cpc_core_lock_flags);
 
-phys_addr_t __weak mips_cpc_phys_base(void)
+/**
+ * mips_cpc_phys_base - retrieve the physical base address of the CPC
+ *
+ * This function returns the physical base address of the Cluster Power
+ * Controller memory mapped registers, or 0 if no Cluster Power Controller
+ * is present.
+ */
+static phys_addr_t mips_cpc_phys_base(void)
 {
-       u32 cpc_base;
+       unsigned long cpc_base;
 
        if (!mips_cm_present())
                return 0;
index cc1b6fadf08989a8048a6dc304a9f58f1c29228e..d7b8dd43147a44e7a400efc4b5e2019e015f82b9 100644 (file)
@@ -1556,6 +1556,7 @@ static const struct mips_perf_event *mipsxx_pmu_map_raw_event(u64 config)
 #endif
                break;
        case CPU_P5600:
+       case CPU_I6400:
                /* 8-bit event numbers */
                raw_id = config & 0x1ff;
                base_id = raw_id & 0xff;
@@ -1717,6 +1718,11 @@ init_hw_perf_events(void)
                mipspmu.general_event_map = &mipsxxcore_event_map2;
                mipspmu.cache_event_map = &mipsxxcore_cache_map2;
                break;
+       case CPU_I6400:
+               mipspmu.name = "mips/I6400";
+               mipspmu.general_event_map = &mipsxxcore_event_map2;
+               mipspmu.cache_event_map = &mipsxxcore_cache_map2;
+               break;
        case CPU_1004K:
                mipspmu.name = "mips/1004K";
                mipspmu.general_event_map = &mipsxxcore_event_map;
index 06147179a175b7ea5d8c02a502e4b20653dd8b3d..f63a289977cc5f34d5ee52daf61f1065153166a1 100644 (file)
@@ -267,6 +267,7 @@ static int __init cps_gen_flush_fsb(u32 **pp, struct uasm_label **pl,
 
        /* CPUs which do not require the workaround */
        case CPU_P5600:
+       case CPU_I6400:
                return 0;
 
        default:
@@ -671,6 +672,7 @@ static int __init cps_pm_init(void)
        case CPU_PROAPTIV:
        case CPU_M5150:
        case CPU_P5600:
+       case CPU_I6400:
                stype_intervention = 0x2;
                stype_memory = 0x3;
                stype_ordering = 0x10;
index e933a309f2ea5fa4498153a9b6a3caa0af4a1587..4f0ac78d17f196e7c34de33af8bdcd4f708392e3 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/regset.h>
 #include <linux/smp.h>
 #include <linux/security.h>
+#include <linux/stddef.h>
 #include <linux/tracehook.h>
 #include <linux/audit.h>
 #include <linux/seccomp.h>
@@ -490,6 +491,93 @@ enum mips_regset {
        REGSET_FPR,
 };
 
+struct pt_regs_offset {
+       const char *name;
+       int offset;
+};
+
+#define REG_OFFSET_NAME(reg, r) {                                      \
+       .name = #reg,                                                   \
+       .offset = offsetof(struct pt_regs, r)                           \
+}
+
+#define REG_OFFSET_END {                                               \
+       .name = NULL,                                                   \
+       .offset = 0                                                     \
+}
+
+static const struct pt_regs_offset regoffset_table[] = {
+       REG_OFFSET_NAME(r0, regs[0]),
+       REG_OFFSET_NAME(r1, regs[1]),
+       REG_OFFSET_NAME(r2, regs[2]),
+       REG_OFFSET_NAME(r3, regs[3]),
+       REG_OFFSET_NAME(r4, regs[4]),
+       REG_OFFSET_NAME(r5, regs[5]),
+       REG_OFFSET_NAME(r6, regs[6]),
+       REG_OFFSET_NAME(r7, regs[7]),
+       REG_OFFSET_NAME(r8, regs[8]),
+       REG_OFFSET_NAME(r9, regs[9]),
+       REG_OFFSET_NAME(r10, regs[10]),
+       REG_OFFSET_NAME(r11, regs[11]),
+       REG_OFFSET_NAME(r12, regs[12]),
+       REG_OFFSET_NAME(r13, regs[13]),
+       REG_OFFSET_NAME(r14, regs[14]),
+       REG_OFFSET_NAME(r15, regs[15]),
+       REG_OFFSET_NAME(r16, regs[16]),
+       REG_OFFSET_NAME(r17, regs[17]),
+       REG_OFFSET_NAME(r18, regs[18]),
+       REG_OFFSET_NAME(r19, regs[19]),
+       REG_OFFSET_NAME(r20, regs[20]),
+       REG_OFFSET_NAME(r21, regs[21]),
+       REG_OFFSET_NAME(r22, regs[22]),
+       REG_OFFSET_NAME(r23, regs[23]),
+       REG_OFFSET_NAME(r24, regs[24]),
+       REG_OFFSET_NAME(r25, regs[25]),
+       REG_OFFSET_NAME(r26, regs[26]),
+       REG_OFFSET_NAME(r27, regs[27]),
+       REG_OFFSET_NAME(r28, regs[28]),
+       REG_OFFSET_NAME(r29, regs[29]),
+       REG_OFFSET_NAME(r30, regs[30]),
+       REG_OFFSET_NAME(r31, regs[31]),
+       REG_OFFSET_NAME(c0_status, cp0_status),
+       REG_OFFSET_NAME(hi, hi),
+       REG_OFFSET_NAME(lo, lo),
+#ifdef CONFIG_CPU_HAS_SMARTMIPS
+       REG_OFFSET_NAME(acx, acx),
+#endif
+       REG_OFFSET_NAME(c0_badvaddr, cp0_badvaddr),
+       REG_OFFSET_NAME(c0_cause, cp0_cause),
+       REG_OFFSET_NAME(c0_epc, cp0_epc),
+#ifdef CONFIG_MIPS_MT_SMTC
+       REG_OFFSET_NAME(c0_tcstatus, cp0_tcstatus),
+#endif
+#ifdef CONFIG_CPU_CAVIUM_OCTEON
+       REG_OFFSET_NAME(mpl0, mpl[0]),
+       REG_OFFSET_NAME(mpl1, mpl[1]),
+       REG_OFFSET_NAME(mpl2, mpl[2]),
+       REG_OFFSET_NAME(mtp0, mtp[0]),
+       REG_OFFSET_NAME(mtp1, mtp[1]),
+       REG_OFFSET_NAME(mtp2, mtp[2]),
+#endif
+       REG_OFFSET_END,
+};
+
+/**
+ * regs_query_register_offset() - query register offset from its name
+ * @name:       the name of a register
+ *
+ * regs_query_register_offset() returns the offset of a register in struct
+ * pt_regs from its name. If the name is invalid, this returns -EINVAL;
+ */
+int regs_query_register_offset(const char *name)
+{
+        const struct pt_regs_offset *roff;
+        for (roff = regoffset_table; roff->name != NULL; roff++)
+                if (!strcmp(roff->name, name))
+                        return roff->offset;
+        return -EINVAL;
+}
+
 #if defined(CONFIG_32BIT) || defined(CONFIG_MIPS32_O32)
 
 static const struct user_regset mips_regsets[] = {
index 1d88af26ba82a0c3ee58ff8ff3b2b1661dad9455..f09546ee2cdc907dc02e4c391c103ba381e35a5e 100644 (file)
@@ -13,6 +13,7 @@
  * Copyright (C) 1999, 2001 Silicon Graphics, Inc.
  */
 #include <asm/asm.h>
+#include <asm/asmmacro.h>
 #include <asm/errno.h>
 #include <asm/fpregdef.h>
 #include <asm/mipsregs.h>
 
        .set    noreorder
 
+/**
+ * _save_fp_context() - save FP context from the FPU
+ * @a0 - pointer to fpregs field of sigcontext
+ * @a1 - pointer to fpc_csr field of sigcontext
+ *
+ * Save FP context, including the 32 FP data registers and the FP
+ * control & status register, from the FPU to signal context.
+ */
 LEAF(_save_fp_context)
        .set    push
        SET_HARDFLOAT
@@ -54,117 +63,60 @@ LEAF(_save_fp_context)
         nop
 #endif
        /* Store the 16 odd double precision registers */
-       EX      sdc1 $f1, SC_FPREGS+8(a0)
-       EX      sdc1 $f3, SC_FPREGS+24(a0)
-       EX      sdc1 $f5, SC_FPREGS+40(a0)
-       EX      sdc1 $f7, SC_FPREGS+56(a0)
-       EX      sdc1 $f9, SC_FPREGS+72(a0)
-       EX      sdc1 $f11, SC_FPREGS+88(a0)
-       EX      sdc1 $f13, SC_FPREGS+104(a0)
-       EX      sdc1 $f15, SC_FPREGS+120(a0)
-       EX      sdc1 $f17, SC_FPREGS+136(a0)
-       EX      sdc1 $f19, SC_FPREGS+152(a0)
-       EX      sdc1 $f21, SC_FPREGS+168(a0)
-       EX      sdc1 $f23, SC_FPREGS+184(a0)
-       EX      sdc1 $f25, SC_FPREGS+200(a0)
-       EX      sdc1 $f27, SC_FPREGS+216(a0)
-       EX      sdc1 $f29, SC_FPREGS+232(a0)
-       EX      sdc1 $f31, SC_FPREGS+248(a0)
+       EX      sdc1 $f1, 8(a0)
+       EX      sdc1 $f3, 24(a0)
+       EX      sdc1 $f5, 40(a0)
+       EX      sdc1 $f7, 56(a0)
+       EX      sdc1 $f9, 72(a0)
+       EX      sdc1 $f11, 88(a0)
+       EX      sdc1 $f13, 104(a0)
+       EX      sdc1 $f15, 120(a0)
+       EX      sdc1 $f17, 136(a0)
+       EX      sdc1 $f19, 152(a0)
+       EX      sdc1 $f21, 168(a0)
+       EX      sdc1 $f23, 184(a0)
+       EX      sdc1 $f25, 200(a0)
+       EX      sdc1 $f27, 216(a0)
+       EX      sdc1 $f29, 232(a0)
+       EX      sdc1 $f31, 248(a0)
 1:     .set    pop
 #endif
 
        .set push
        SET_HARDFLOAT
        /* Store the 16 even double precision registers */
-       EX      sdc1 $f0, SC_FPREGS+0(a0)
-       EX      sdc1 $f2, SC_FPREGS+16(a0)
-       EX      sdc1 $f4, SC_FPREGS+32(a0)
-       EX      sdc1 $f6, SC_FPREGS+48(a0)
-       EX      sdc1 $f8, SC_FPREGS+64(a0)
-       EX      sdc1 $f10, SC_FPREGS+80(a0)
-       EX      sdc1 $f12, SC_FPREGS+96(a0)
-       EX      sdc1 $f14, SC_FPREGS+112(a0)
-       EX      sdc1 $f16, SC_FPREGS+128(a0)
-       EX      sdc1 $f18, SC_FPREGS+144(a0)
-       EX      sdc1 $f20, SC_FPREGS+160(a0)
-       EX      sdc1 $f22, SC_FPREGS+176(a0)
-       EX      sdc1 $f24, SC_FPREGS+192(a0)
-       EX      sdc1 $f26, SC_FPREGS+208(a0)
-       EX      sdc1 $f28, SC_FPREGS+224(a0)
-       EX      sdc1 $f30, SC_FPREGS+240(a0)
-       EX      sw t1, SC_FPC_CSR(a0)
+       EX      sdc1 $f0, 0(a0)
+       EX      sdc1 $f2, 16(a0)
+       EX      sdc1 $f4, 32(a0)
+       EX      sdc1 $f6, 48(a0)
+       EX      sdc1 $f8, 64(a0)
+       EX      sdc1 $f10, 80(a0)
+       EX      sdc1 $f12, 96(a0)
+       EX      sdc1 $f14, 112(a0)
+       EX      sdc1 $f16, 128(a0)
+       EX      sdc1 $f18, 144(a0)
+       EX      sdc1 $f20, 160(a0)
+       EX      sdc1 $f22, 176(a0)
+       EX      sdc1 $f24, 192(a0)
+       EX      sdc1 $f26, 208(a0)
+       EX      sdc1 $f28, 224(a0)
+       EX      sdc1 $f30, 240(a0)
+       EX      sw t1, 0(a1)
        jr      ra
         li     v0, 0                                   # success
        .set pop
        END(_save_fp_context)
 
-#ifdef CONFIG_MIPS32_COMPAT
-       /* Save 32-bit process floating point context */
-LEAF(_save_fp_context32)
-       .set push
-       .set MIPS_ISA_ARCH_LEVEL_RAW
-       SET_HARDFLOAT
-       cfc1    t1, fcr31
-
-#ifndef CONFIG_CPU_MIPS64_R6
-       mfc0    t0, CP0_STATUS
-       sll     t0, t0, 5
-       bgez    t0, 1f                  # skip storing odd if FR=0
-        nop
-#endif
-
-       /* Store the 16 odd double precision registers */
-       EX      sdc1 $f1, SC32_FPREGS+8(a0)
-       EX      sdc1 $f3, SC32_FPREGS+24(a0)
-       EX      sdc1 $f5, SC32_FPREGS+40(a0)
-       EX      sdc1 $f7, SC32_FPREGS+56(a0)
-       EX      sdc1 $f9, SC32_FPREGS+72(a0)
-       EX      sdc1 $f11, SC32_FPREGS+88(a0)
-       EX      sdc1 $f13, SC32_FPREGS+104(a0)
-       EX      sdc1 $f15, SC32_FPREGS+120(a0)
-       EX      sdc1 $f17, SC32_FPREGS+136(a0)
-       EX      sdc1 $f19, SC32_FPREGS+152(a0)
-       EX      sdc1 $f21, SC32_FPREGS+168(a0)
-       EX      sdc1 $f23, SC32_FPREGS+184(a0)
-       EX      sdc1 $f25, SC32_FPREGS+200(a0)
-       EX      sdc1 $f27, SC32_FPREGS+216(a0)
-       EX      sdc1 $f29, SC32_FPREGS+232(a0)
-       EX      sdc1 $f31, SC32_FPREGS+248(a0)
-
-       /* Store the 16 even double precision registers */
-1:     EX      sdc1 $f0, SC32_FPREGS+0(a0)
-       EX      sdc1 $f2, SC32_FPREGS+16(a0)
-       EX      sdc1 $f4, SC32_FPREGS+32(a0)
-       EX      sdc1 $f6, SC32_FPREGS+48(a0)
-       EX      sdc1 $f8, SC32_FPREGS+64(a0)
-       EX      sdc1 $f10, SC32_FPREGS+80(a0)
-       EX      sdc1 $f12, SC32_FPREGS+96(a0)
-       EX      sdc1 $f14, SC32_FPREGS+112(a0)
-       EX      sdc1 $f16, SC32_FPREGS+128(a0)
-       EX      sdc1 $f18, SC32_FPREGS+144(a0)
-       EX      sdc1 $f20, SC32_FPREGS+160(a0)
-       EX      sdc1 $f22, SC32_FPREGS+176(a0)
-       EX      sdc1 $f24, SC32_FPREGS+192(a0)
-       EX      sdc1 $f26, SC32_FPREGS+208(a0)
-       EX      sdc1 $f28, SC32_FPREGS+224(a0)
-       EX      sdc1 $f30, SC32_FPREGS+240(a0)
-       EX      sw t1, SC32_FPC_CSR(a0)
-       cfc1    t0, $0                          # implementation/version
-       EX      sw t0, SC32_FPC_EIR(a0)
-       .set pop
-
-       jr      ra
-        li     v0, 0                                   # success
-       END(_save_fp_context32)
-#endif
-
-/*
- * Restore FPU state:
- *  - fp gp registers
- *  - cp1 status/control register
+/**
+ * _restore_fp_context() - restore FP context to the FPU
+ * @a0 - pointer to fpregs field of sigcontext
+ * @a1 - pointer to fpc_csr field of sigcontext
+ *
+ * Restore FP context, including the 32 FP data registers and the FP
+ * control & status register, from signal context to the FPU.
  */
 LEAF(_restore_fp_context)
-       EX      lw t1, SC_FPC_CSR(a0)
+       EX      lw t1, 0(a1)
 
 #if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPS32_R2)  || \
                defined(CONFIG_CPU_MIPS32_R6)
@@ -178,101 +130,231 @@ LEAF(_restore_fp_context)
        bgez    t0, 1f                  # skip loading odd if FR=0
         nop
 #endif
-       EX      ldc1 $f1, SC_FPREGS+8(a0)
-       EX      ldc1 $f3, SC_FPREGS+24(a0)
-       EX      ldc1 $f5, SC_FPREGS+40(a0)
-       EX      ldc1 $f7, SC_FPREGS+56(a0)
-       EX      ldc1 $f9, SC_FPREGS+72(a0)
-       EX      ldc1 $f11, SC_FPREGS+88(a0)
-       EX      ldc1 $f13, SC_FPREGS+104(a0)
-       EX      ldc1 $f15, SC_FPREGS+120(a0)
-       EX      ldc1 $f17, SC_FPREGS+136(a0)
-       EX      ldc1 $f19, SC_FPREGS+152(a0)
-       EX      ldc1 $f21, SC_FPREGS+168(a0)
-       EX      ldc1 $f23, SC_FPREGS+184(a0)
-       EX      ldc1 $f25, SC_FPREGS+200(a0)
-       EX      ldc1 $f27, SC_FPREGS+216(a0)
-       EX      ldc1 $f29, SC_FPREGS+232(a0)
-       EX      ldc1 $f31, SC_FPREGS+248(a0)
+       EX      ldc1 $f1, 8(a0)
+       EX      ldc1 $f3, 24(a0)
+       EX      ldc1 $f5, 40(a0)
+       EX      ldc1 $f7, 56(a0)
+       EX      ldc1 $f9, 72(a0)
+       EX      ldc1 $f11, 88(a0)
+       EX      ldc1 $f13, 104(a0)
+       EX      ldc1 $f15, 120(a0)
+       EX      ldc1 $f17, 136(a0)
+       EX      ldc1 $f19, 152(a0)
+       EX      ldc1 $f21, 168(a0)
+       EX      ldc1 $f23, 184(a0)
+       EX      ldc1 $f25, 200(a0)
+       EX      ldc1 $f27, 216(a0)
+       EX      ldc1 $f29, 232(a0)
+       EX      ldc1 $f31, 248(a0)
 1:     .set pop
 #endif
        .set push
        SET_HARDFLOAT
-       EX      ldc1 $f0, SC_FPREGS+0(a0)
-       EX      ldc1 $f2, SC_FPREGS+16(a0)
-       EX      ldc1 $f4, SC_FPREGS+32(a0)
-       EX      ldc1 $f6, SC_FPREGS+48(a0)
-       EX      ldc1 $f8, SC_FPREGS+64(a0)
-       EX      ldc1 $f10, SC_FPREGS+80(a0)
-       EX      ldc1 $f12, SC_FPREGS+96(a0)
-       EX      ldc1 $f14, SC_FPREGS+112(a0)
-       EX      ldc1 $f16, SC_FPREGS+128(a0)
-       EX      ldc1 $f18, SC_FPREGS+144(a0)
-       EX      ldc1 $f20, SC_FPREGS+160(a0)
-       EX      ldc1 $f22, SC_FPREGS+176(a0)
-       EX      ldc1 $f24, SC_FPREGS+192(a0)
-       EX      ldc1 $f26, SC_FPREGS+208(a0)
-       EX      ldc1 $f28, SC_FPREGS+224(a0)
-       EX      ldc1 $f30, SC_FPREGS+240(a0)
+       EX      ldc1 $f0, 0(a0)
+       EX      ldc1 $f2, 16(a0)
+       EX      ldc1 $f4, 32(a0)
+       EX      ldc1 $f6, 48(a0)
+       EX      ldc1 $f8, 64(a0)
+       EX      ldc1 $f10, 80(a0)
+       EX      ldc1 $f12, 96(a0)
+       EX      ldc1 $f14, 112(a0)
+       EX      ldc1 $f16, 128(a0)
+       EX      ldc1 $f18, 144(a0)
+       EX      ldc1 $f20, 160(a0)
+       EX      ldc1 $f22, 176(a0)
+       EX      ldc1 $f24, 192(a0)
+       EX      ldc1 $f26, 208(a0)
+       EX      ldc1 $f28, 224(a0)
+       EX      ldc1 $f30, 240(a0)
        ctc1    t1, fcr31
        .set pop
        jr      ra
         li     v0, 0                                   # success
        END(_restore_fp_context)
 
-#ifdef CONFIG_MIPS32_COMPAT
-LEAF(_restore_fp_context32)
-       /* Restore an o32 sigcontext.  */
-       .set push
-       SET_HARDFLOAT
-       EX      lw t1, SC32_FPC_CSR(a0)
+#ifdef CONFIG_CPU_HAS_MSA
 
-#ifndef CONFIG_CPU_MIPS64_R6
-       mfc0    t0, CP0_STATUS
-       sll     t0, t0, 5
-       bgez    t0, 1f                  # skip loading odd if FR=0
+       .macro  op_one_wr       op, idx, base
+       .align  4
+\idx:  \op     \idx, 0, \base
+       jr      ra
         nop
-#endif
+       .endm
 
-       EX      ldc1 $f1, SC32_FPREGS+8(a0)
-       EX      ldc1 $f3, SC32_FPREGS+24(a0)
-       EX      ldc1 $f5, SC32_FPREGS+40(a0)
-       EX      ldc1 $f7, SC32_FPREGS+56(a0)
-       EX      ldc1 $f9, SC32_FPREGS+72(a0)
-       EX      ldc1 $f11, SC32_FPREGS+88(a0)
-       EX      ldc1 $f13, SC32_FPREGS+104(a0)
-       EX      ldc1 $f15, SC32_FPREGS+120(a0)
-       EX      ldc1 $f17, SC32_FPREGS+136(a0)
-       EX      ldc1 $f19, SC32_FPREGS+152(a0)
-       EX      ldc1 $f21, SC32_FPREGS+168(a0)
-       EX      ldc1 $f23, SC32_FPREGS+184(a0)
-       EX      ldc1 $f25, SC32_FPREGS+200(a0)
-       EX      ldc1 $f27, SC32_FPREGS+216(a0)
-       EX      ldc1 $f29, SC32_FPREGS+232(a0)
-       EX      ldc1 $f31, SC32_FPREGS+248(a0)
+       .macro  op_msa_wr       name, op
+LEAF(\name)
+       .set            push
+       .set            noreorder
+       sll             t0, a0, 4
+       PTR_LA          t1, 0f
+       PTR_ADDU        t0, t0, t1
+       jr              t0
+         nop
+       op_one_wr       \op, 0, a1
+       op_one_wr       \op, 1, a1
+       op_one_wr       \op, 2, a1
+       op_one_wr       \op, 3, a1
+       op_one_wr       \op, 4, a1
+       op_one_wr       \op, 5, a1
+       op_one_wr       \op, 6, a1
+       op_one_wr       \op, 7, a1
+       op_one_wr       \op, 8, a1
+       op_one_wr       \op, 9, a1
+       op_one_wr       \op, 10, a1
+       op_one_wr       \op, 11, a1
+       op_one_wr       \op, 12, a1
+       op_one_wr       \op, 13, a1
+       op_one_wr       \op, 14, a1
+       op_one_wr       \op, 15, a1
+       op_one_wr       \op, 16, a1
+       op_one_wr       \op, 17, a1
+       op_one_wr       \op, 18, a1
+       op_one_wr       \op, 19, a1
+       op_one_wr       \op, 20, a1
+       op_one_wr       \op, 21, a1
+       op_one_wr       \op, 22, a1
+       op_one_wr       \op, 23, a1
+       op_one_wr       \op, 24, a1
+       op_one_wr       \op, 25, a1
+       op_one_wr       \op, 26, a1
+       op_one_wr       \op, 27, a1
+       op_one_wr       \op, 28, a1
+       op_one_wr       \op, 29, a1
+       op_one_wr       \op, 30, a1
+       op_one_wr       \op, 31, a1
+       .set            pop
+       END(\name)
+       .endm
 
-1:     EX      ldc1 $f0, SC32_FPREGS+0(a0)
-       EX      ldc1 $f2, SC32_FPREGS+16(a0)
-       EX      ldc1 $f4, SC32_FPREGS+32(a0)
-       EX      ldc1 $f6, SC32_FPREGS+48(a0)
-       EX      ldc1 $f8, SC32_FPREGS+64(a0)
-       EX      ldc1 $f10, SC32_FPREGS+80(a0)
-       EX      ldc1 $f12, SC32_FPREGS+96(a0)
-       EX      ldc1 $f14, SC32_FPREGS+112(a0)
-       EX      ldc1 $f16, SC32_FPREGS+128(a0)
-       EX      ldc1 $f18, SC32_FPREGS+144(a0)
-       EX      ldc1 $f20, SC32_FPREGS+160(a0)
-       EX      ldc1 $f22, SC32_FPREGS+176(a0)
-       EX      ldc1 $f24, SC32_FPREGS+192(a0)
-       EX      ldc1 $f26, SC32_FPREGS+208(a0)
-       EX      ldc1 $f28, SC32_FPREGS+224(a0)
-       EX      ldc1 $f30, SC32_FPREGS+240(a0)
-       ctc1    t1, fcr31
+       op_msa_wr       read_msa_wr_b, st_b
+       op_msa_wr       read_msa_wr_h, st_h
+       op_msa_wr       read_msa_wr_w, st_w
+       op_msa_wr       read_msa_wr_d, st_d
+
+       op_msa_wr       write_msa_wr_b, ld_b
+       op_msa_wr       write_msa_wr_h, ld_h
+       op_msa_wr       write_msa_wr_w, ld_w
+       op_msa_wr       write_msa_wr_d, ld_d
+
+#endif /* CONFIG_CPU_HAS_MSA */
+
+#ifdef CONFIG_CPU_HAS_MSA
+
+       .macro  save_msa_upper  wr, off, base
+       .set    push
+       .set    noat
+#ifdef CONFIG_64BIT
+       copy_u_d \wr, 1
+       EX sd   $1, \off(\base)
+#elif defined(CONFIG_CPU_LITTLE_ENDIAN)
+       copy_u_w \wr, 2
+       EX sw   $1, \off(\base)
+       copy_u_w \wr, 3
+       EX sw   $1, (\off+4)(\base)
+#else /* CONFIG_CPU_BIG_ENDIAN */
+       copy_u_w \wr, 2
+       EX sw   $1, (\off+4)(\base)
+       copy_u_w \wr, 3
+       EX sw   $1, \off(\base)
+#endif
+       .set    pop
+       .endm
+
+LEAF(_save_msa_all_upper)
+       save_msa_upper  0, 0x00, a0
+       save_msa_upper  1, 0x08, a0
+       save_msa_upper  2, 0x10, a0
+       save_msa_upper  3, 0x18, a0
+       save_msa_upper  4, 0x20, a0
+       save_msa_upper  5, 0x28, a0
+       save_msa_upper  6, 0x30, a0
+       save_msa_upper  7, 0x38, a0
+       save_msa_upper  8, 0x40, a0
+       save_msa_upper  9, 0x48, a0
+       save_msa_upper  10, 0x50, a0
+       save_msa_upper  11, 0x58, a0
+       save_msa_upper  12, 0x60, a0
+       save_msa_upper  13, 0x68, a0
+       save_msa_upper  14, 0x70, a0
+       save_msa_upper  15, 0x78, a0
+       save_msa_upper  16, 0x80, a0
+       save_msa_upper  17, 0x88, a0
+       save_msa_upper  18, 0x90, a0
+       save_msa_upper  19, 0x98, a0
+       save_msa_upper  20, 0xa0, a0
+       save_msa_upper  21, 0xa8, a0
+       save_msa_upper  22, 0xb0, a0
+       save_msa_upper  23, 0xb8, a0
+       save_msa_upper  24, 0xc0, a0
+       save_msa_upper  25, 0xc8, a0
+       save_msa_upper  26, 0xd0, a0
+       save_msa_upper  27, 0xd8, a0
+       save_msa_upper  28, 0xe0, a0
+       save_msa_upper  29, 0xe8, a0
+       save_msa_upper  30, 0xf0, a0
+       save_msa_upper  31, 0xf8, a0
        jr      ra
-        li     v0, 0                                   # success
-       .set pop
-       END(_restore_fp_context32)
+        li     v0, 0
+       END(_save_msa_all_upper)
+
+       .macro  restore_msa_upper       wr, off, base
+       .set    push
+       .set    noat
+#ifdef CONFIG_64BIT
+       EX ld   $1, \off(\base)
+       insert_d \wr, 1
+#elif defined(CONFIG_CPU_LITTLE_ENDIAN)
+       EX lw   $1, \off(\base)
+       insert_w \wr, 2
+       EX lw   $1, (\off+4)(\base)
+       insert_w \wr, 3
+#else /* CONFIG_CPU_BIG_ENDIAN */
+       EX lw   $1, (\off+4)(\base)
+       insert_w \wr, 2
+       EX lw   $1, \off(\base)
+       insert_w \wr, 3
 #endif
+       .set    pop
+       .endm
+
+LEAF(_restore_msa_all_upper)
+       restore_msa_upper       0, 0x00, a0
+       restore_msa_upper       1, 0x08, a0
+       restore_msa_upper       2, 0x10, a0
+       restore_msa_upper       3, 0x18, a0
+       restore_msa_upper       4, 0x20, a0
+       restore_msa_upper       5, 0x28, a0
+       restore_msa_upper       6, 0x30, a0
+       restore_msa_upper       7, 0x38, a0
+       restore_msa_upper       8, 0x40, a0
+       restore_msa_upper       9, 0x48, a0
+       restore_msa_upper       10, 0x50, a0
+       restore_msa_upper       11, 0x58, a0
+       restore_msa_upper       12, 0x60, a0
+       restore_msa_upper       13, 0x68, a0
+       restore_msa_upper       14, 0x70, a0
+       restore_msa_upper       15, 0x78, a0
+       restore_msa_upper       16, 0x80, a0
+       restore_msa_upper       17, 0x88, a0
+       restore_msa_upper       18, 0x90, a0
+       restore_msa_upper       19, 0x98, a0
+       restore_msa_upper       20, 0xa0, a0
+       restore_msa_upper       21, 0xa8, a0
+       restore_msa_upper       22, 0xb0, a0
+       restore_msa_upper       23, 0xb8, a0
+       restore_msa_upper       24, 0xc0, a0
+       restore_msa_upper       25, 0xc8, a0
+       restore_msa_upper       26, 0xd0, a0
+       restore_msa_upper       27, 0xd8, a0
+       restore_msa_upper       28, 0xe0, a0
+       restore_msa_upper       29, 0xe8, a0
+       restore_msa_upper       30, 0xf0, a0
+       restore_msa_upper       31, 0xf8, a0
+       jr      ra
+        li     v0, 0
+       END(_restore_msa_all_upper)
+
+#endif /* CONFIG_CPU_HAS_MSA */
 
        .set    reorder
 
index 04cbbde3521bc11cd8a1f6c678b2e6fa6bac0529..92cd0516ecf51ee40715824b26ab48be8146cce8 100644 (file)
@@ -34,7 +34,7 @@
 #ifndef USE_ALTERNATE_RESUME_IMPL
 /*
  * task_struct *resume(task_struct *prev, task_struct *next,
- *                    struct thread_info *next_ti, s32 fp_save)
+ *                    struct thread_info *next_ti)
  */
        .align  5
        LEAF(resume)
        cpu_save_nonscratch a0
        LONG_S  ra, THREAD_REG31(a0)
 
-       /*
-        * Check whether we need to save any FP context. FP context is saved
-        * iff the process has used the context with the scalar FPU or the MSA
-        * ASE in the current time slice, as indicated by _TIF_USEDFPU and
-        * _TIF_USEDMSA respectively. switch_to will have set fp_save
-        * accordingly to an FP_SAVE_ enum value.
-        */
-       beqz    a3, 2f
-
-       /*
-        * We do. Clear the saved CU1 bit for prev, such that next time it is
-        * scheduled it will start in userland with the FPU disabled. If the
-        * task uses the FPU then it will be enabled again via the do_cpu trap.
-        * This allows us to lazily restore the FP context.
-        */
-       PTR_L   t3, TASK_THREAD_INFO(a0)
-       LONG_L  t0, ST_OFF(t3)
-       li      t1, ~ST0_CU1
-       and     t0, t0, t1
-       LONG_S  t0, ST_OFF(t3)
-
-       /* Check whether we're saving scalar or vector context. */
-       bgtz    a3, 1f
-
-       /* Save 128b MSA vector context + scalar FP control & status. */
-       .set push
-       SET_HARDFLOAT
-       cfc1    t1, fcr31
-       msa_save_all    a0
-       .set pop        /* SET_HARDFLOAT */
-
-       sw      t1, THREAD_FCR31(a0)
-       b       2f
-
-1:     /* Save 32b/64b scalar FP context. */
-       fpu_save_double a0 t0 t1                # c0_status passed in t0
-                                               # clobbers t1
-2:
-
 #if defined(CONFIG_CC_STACKPROTECTOR) && !defined(CONFIG_SMP)
        PTR_LA  t8, __stack_chk_guard
        LONG_L  t9, TASK_STACK_CANARY(a1)
index 0b85f827cd1836165fe4d146ec1d543953edeb7b..f50d48435c6803e0202bc7cb11689eb1e4cd5a83 100644 (file)
@@ -31,4 +31,13 @@ extern int fpcsr_pending(unsigned int __user *fpcsr);
 #define lock_fpu_owner()       ({ preempt_disable(); pagefault_disable(); })
 #define unlock_fpu_owner()     ({ pagefault_enable(); preempt_enable(); })
 
+/* Assembly functions to move context to/from the FPU */
+extern asmlinkage int
+_save_fp_context(void __user *fpregs, void __user *csr);
+extern asmlinkage int
+_restore_fp_context(void __user *fpregs, void __user *csr);
+
+extern asmlinkage int _save_msa_all_upper(void __user *buf);
+extern asmlinkage int _restore_msa_all_upper(void __user *buf);
+
 #endif /* __SIGNAL_COMMON_H */
index 6a28c792d862c03b09a8f9cfdcd40d2879c401b0..2fec67bfc457cc969056f6f46258c0f00992be83 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/wait.h>
 #include <linux/ptrace.h>
 #include <linux/unistd.h>
+#include <linux/uprobes.h>
 #include <linux/compiler.h>
 #include <linux/syscalls.h>
 #include <linux/uaccess.h>
 #include <asm/vdso.h>
 #include <asm/dsp.h>
 #include <asm/inst.h>
+#include <asm/msa.h>
 
 #include "signal-common.h"
 
-static int (*save_fp_context)(struct sigcontext __user *sc);
-static int (*restore_fp_context)(struct sigcontext __user *sc);
-
-extern asmlinkage int _save_fp_context(struct sigcontext __user *sc);
-extern asmlinkage int _restore_fp_context(struct sigcontext __user *sc);
+static int (*save_fp_context)(void __user *sc);
+static int (*restore_fp_context)(void __user *sc);
 
 struct sigframe {
        u32 sf_ass[4];          /* argument save space for o32 */
        u32 sf_pad[2];          /* Was: signal trampoline */
+
+       /* Matches struct ucontext from its uc_mcontext field onwards */
        struct sigcontext sf_sc;
        sigset_t sf_mask;
+       unsigned long long sf_extcontext[0];
 };
 
 struct rt_sigframe {
@@ -65,43 +67,255 @@ struct rt_sigframe {
  * Thread saved context copy to/from a signal context presumed to be on the
  * user stack, and therefore accessed with appropriate macros from uaccess.h.
  */
-static int copy_fp_to_sigcontext(struct sigcontext __user *sc)
+static int copy_fp_to_sigcontext(void __user *sc)
 {
+       struct mips_abi *abi = current->thread.abi;
+       uint64_t __user *fpregs = sc + abi->off_sc_fpregs;
+       uint32_t __user *csr = sc + abi->off_sc_fpc_csr;
        int i;
        int err = 0;
+       int inc = test_thread_flag(TIF_32BIT_FPREGS) ? 2 : 1;
 
-       for (i = 0; i < NUM_FPU_REGS; i++) {
+       for (i = 0; i < NUM_FPU_REGS; i += inc) {
                err |=
                    __put_user(get_fpr64(&current->thread.fpu.fpr[i], 0),
-                              &sc->sc_fpregs[i]);
+                              &fpregs[i]);
        }
-       err |= __put_user(current->thread.fpu.fcr31, &sc->sc_fpc_csr);
+       err |= __put_user(current->thread.fpu.fcr31, csr);
 
        return err;
 }
 
-static int copy_fp_from_sigcontext(struct sigcontext __user *sc)
+static int copy_fp_from_sigcontext(void __user *sc)
 {
+       struct mips_abi *abi = current->thread.abi;
+       uint64_t __user *fpregs = sc + abi->off_sc_fpregs;
+       uint32_t __user *csr = sc + abi->off_sc_fpc_csr;
        int i;
        int err = 0;
+       int inc = test_thread_flag(TIF_32BIT_FPREGS) ? 2 : 1;
        u64 fpr_val;
 
-       for (i = 0; i < NUM_FPU_REGS; i++) {
-               err |= __get_user(fpr_val, &sc->sc_fpregs[i]);
+       for (i = 0; i < NUM_FPU_REGS; i += inc) {
+               err |= __get_user(fpr_val, &fpregs[i]);
                set_fpr64(&current->thread.fpu.fpr[i], 0, fpr_val);
        }
-       err |= __get_user(current->thread.fpu.fcr31, &sc->sc_fpc_csr);
+       err |= __get_user(current->thread.fpu.fcr31, csr);
 
        return err;
 }
 
+/*
+ * Wrappers for the assembly _{save,restore}_fp_context functions.
+ */
+static int save_hw_fp_context(void __user *sc)
+{
+       struct mips_abi *abi = current->thread.abi;
+       uint64_t __user *fpregs = sc + abi->off_sc_fpregs;
+       uint32_t __user *csr = sc + abi->off_sc_fpc_csr;
+
+       return _save_fp_context(fpregs, csr);
+}
+
+static int restore_hw_fp_context(void __user *sc)
+{
+       struct mips_abi *abi = current->thread.abi;
+       uint64_t __user *fpregs = sc + abi->off_sc_fpregs;
+       uint32_t __user *csr = sc + abi->off_sc_fpc_csr;
+
+       return _restore_fp_context(fpregs, csr);
+}
+
+/*
+ * Extended context handling.
+ */
+
+static inline void __user *sc_to_extcontext(void __user *sc)
+{
+       struct ucontext __user *uc;
+
+       /*
+        * We can just pretend the sigcontext is always embedded in a struct
+        * ucontext here, because the offset from sigcontext to extended
+        * context is the same in the struct sigframe case.
+        */
+       uc = container_of(sc, struct ucontext, uc_mcontext);
+       return &uc->uc_extcontext;
+}
+
+static int save_msa_extcontext(void __user *buf)
+{
+       struct msa_extcontext __user *msa = buf;
+       uint64_t val;
+       int i, err;
+
+       if (!thread_msa_context_live())
+               return 0;
+
+       /*
+        * Ensure that we can't lose the live MSA context between checking
+        * for it & writing it to memory.
+        */
+       preempt_disable();
+
+       if (is_msa_enabled()) {
+               /*
+                * There are no EVA versions of the vector register load/store
+                * instructions, so MSA context has to be saved to kernel memory
+                * and then copied to user memory. The save to kernel memory
+                * should already have been done when handling scalar FP
+                * context.
+                */
+               BUG_ON(config_enabled(CONFIG_EVA));
+
+               err = __put_user(read_msa_csr(), &msa->csr);
+               err |= _save_msa_all_upper(&msa->wr);
+
+               preempt_enable();
+       } else {
+               preempt_enable();
+
+               err = __put_user(current->thread.fpu.msacsr, &msa->csr);
+
+               for (i = 0; i < NUM_FPU_REGS; i++) {
+                       val = get_fpr64(&current->thread.fpu.fpr[i], 1);
+                       err |= __put_user(val, &msa->wr[i]);
+               }
+       }
+
+       err |= __put_user(MSA_EXTCONTEXT_MAGIC, &msa->ext.magic);
+       err |= __put_user(sizeof(*msa), &msa->ext.size);
+
+       return err ? -EFAULT : sizeof(*msa);
+}
+
+static int restore_msa_extcontext(void __user *buf, unsigned int size)
+{
+       struct msa_extcontext __user *msa = buf;
+       unsigned long long val;
+       unsigned int csr;
+       int i, err;
+
+       if (size != sizeof(*msa))
+               return -EINVAL;
+
+       err = get_user(csr, &msa->csr);
+       if (err)
+               return err;
+
+       preempt_disable();
+
+       if (is_msa_enabled()) {
+               /*
+                * There are no EVA versions of the vector register load/store
+                * instructions, so MSA context has to be copied to kernel
+                * memory and later loaded to registers. The same is true of
+                * scalar FP context, so FPU & MSA should have already been
+                * disabled whilst handling scalar FP context.
+                */
+               BUG_ON(config_enabled(CONFIG_EVA));
+
+               write_msa_csr(csr);
+               err |= _restore_msa_all_upper(&msa->wr);
+               preempt_enable();
+       } else {
+               preempt_enable();
+
+               current->thread.fpu.msacsr = csr;
+
+               for (i = 0; i < NUM_FPU_REGS; i++) {
+                       err |= __get_user(val, &msa->wr[i]);
+                       set_fpr64(&current->thread.fpu.fpr[i], 1, val);
+               }
+       }
+
+       return err;
+}
+
+static int save_extcontext(void __user *buf)
+{
+       int sz;
+
+       sz = save_msa_extcontext(buf);
+       if (sz < 0)
+               return sz;
+       buf += sz;
+
+       /* If no context was saved then trivially return */
+       if (!sz)
+               return 0;
+
+       /* Write the end marker */
+       if (__put_user(END_EXTCONTEXT_MAGIC, (u32 *)buf))
+               return -EFAULT;
+
+       sz += sizeof(((struct extcontext *)NULL)->magic);
+       return sz;
+}
+
+static int restore_extcontext(void __user *buf)
+{
+       struct extcontext ext;
+       int err;
+
+       while (1) {
+               err = __get_user(ext.magic, (unsigned int *)buf);
+               if (err)
+                       return err;
+
+               if (ext.magic == END_EXTCONTEXT_MAGIC)
+                       return 0;
+
+               err = __get_user(ext.size, (unsigned int *)(buf
+                       + offsetof(struct extcontext, size)));
+               if (err)
+                       return err;
+
+               switch (ext.magic) {
+               case MSA_EXTCONTEXT_MAGIC:
+                       err = restore_msa_extcontext(buf, ext.size);
+                       break;
+
+               default:
+                       err = -EINVAL;
+                       break;
+               }
+
+               if (err)
+                       return err;
+
+               buf += ext.size;
+       }
+}
+
 /*
  * Helper routines
  */
-static int protected_save_fp_context(struct sigcontext __user *sc)
+int protected_save_fp_context(void __user *sc)
 {
+       struct mips_abi *abi = current->thread.abi;
+       uint64_t __user *fpregs = sc + abi->off_sc_fpregs;
+       uint32_t __user *csr = sc + abi->off_sc_fpc_csr;
+       uint32_t __user *used_math = sc + abi->off_sc_used_math;
+       unsigned int used, ext_sz;
        int err;
-#ifndef CONFIG_EVA
+
+       used = used_math() ? USED_FP : 0;
+       if (!used)
+               goto fp_done;
+
+       if (!test_thread_flag(TIF_32BIT_FPREGS))
+               used |= USED_FR1;
+       if (test_thread_flag(TIF_HYBRID_FPREGS))
+               used |= USED_HYBRID_FPRS;
+
+       /*
+        * EVA does not have userland equivalents of ldc1 or sdc1, so
+        * save to the kernel FP context & copy that to userland below.
+        */
+       if (config_enabled(CONFIG_EVA))
+               lose_fpu(1);
+
        while (1) {
                lock_fpu_owner();
                if (is_fpu_owner()) {
@@ -114,27 +328,57 @@ static int protected_save_fp_context(struct sigcontext __user *sc)
                if (likely(!err))
                        break;
                /* touch the sigcontext and try again */
-               err = __put_user(0, &sc->sc_fpregs[0]) |
-                       __put_user(0, &sc->sc_fpregs[31]) |
-                       __put_user(0, &sc->sc_fpc_csr);
+               err = __put_user(0, &fpregs[0]) |
+                       __put_user(0, &fpregs[31]) |
+                       __put_user(0, csr);
                if (err)
-                       break;  /* really bad sigcontext */
+                       return err;     /* really bad sigcontext */
        }
-#else
-       /*
-        * EVA does not have FPU EVA instructions so saving fpu context directly
-        * does not work.
-        */
-       lose_fpu(1);
-       err = save_fp_context(sc); /* this might fail */
-#endif
-       return err;
+
+fp_done:
+       ext_sz = err = save_extcontext(sc_to_extcontext(sc));
+       if (err < 0)
+               return err;
+       used |= ext_sz ? USED_EXTCONTEXT : 0;
+
+       return __put_user(used, used_math);
 }
 
-static int protected_restore_fp_context(struct sigcontext __user *sc)
+int protected_restore_fp_context(void __user *sc)
 {
-       int err, tmp __maybe_unused;
-#ifndef CONFIG_EVA
+       struct mips_abi *abi = current->thread.abi;
+       uint64_t __user *fpregs = sc + abi->off_sc_fpregs;
+       uint32_t __user *csr = sc + abi->off_sc_fpc_csr;
+       uint32_t __user *used_math = sc + abi->off_sc_used_math;
+       unsigned int used;
+       int err, sig = 0, tmp __maybe_unused;
+
+       err = __get_user(used, used_math);
+       conditional_used_math(used & USED_FP);
+
+       /*
+        * The signal handler may have used FPU; give it up if the program
+        * doesn't want it following sigreturn.
+        */
+       if (err || !(used & USED_FP))
+               lose_fpu(0);
+       if (err)
+               return err;
+       if (!(used & USED_FP))
+               goto fp_done;
+
+       err = sig = fpcsr_pending(csr);
+       if (err < 0)
+               return err;
+
+       /*
+        * EVA does not have userland equivalents of ldc1 or sdc1, so we
+        * disable the FPU here such that the code below simply copies to
+        * the kernel FP context.
+        */
+       if (config_enabled(CONFIG_EVA))
+               lose_fpu(0);
+
        while (1) {
                lock_fpu_owner();
                if (is_fpu_owner()) {
@@ -147,28 +391,24 @@ static int protected_restore_fp_context(struct sigcontext __user *sc)
                if (likely(!err))
                        break;
                /* touch the sigcontext and try again */
-               err = __get_user(tmp, &sc->sc_fpregs[0]) |
-                       __get_user(tmp, &sc->sc_fpregs[31]) |
-                       __get_user(tmp, &sc->sc_fpc_csr);
+               err = __get_user(tmp, &fpregs[0]) |
+                       __get_user(tmp, &fpregs[31]) |
+                       __get_user(tmp, csr);
                if (err)
                        break;  /* really bad sigcontext */
        }
-#else
-       /*
-        * EVA does not have FPU EVA instructions so restoring fpu context
-        * directly does not work.
-        */
-       lose_fpu(0);
-       err = restore_fp_context(sc); /* this might fail */
-#endif
-       return err;
+
+fp_done:
+       if (used & USED_EXTCONTEXT)
+               err |= restore_extcontext(sc_to_extcontext(sc));
+
+       return err ?: sig;
 }
 
 int setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
 {
        int err = 0;
        int i;
-       unsigned int used_math;
 
        err |= __put_user(regs->cp0_epc, &sc->sc_pc);
 
@@ -191,19 +431,38 @@ int setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
                err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp);
        }
 
-       used_math = !!used_math();
-       err |= __put_user(used_math, &sc->sc_used_math);
 
-       if (used_math) {
-               /*
-                * Save FPU state to signal context. Signal handler
-                * will "inherit" current FPU state.
-                */
-               err |= protected_save_fp_context(sc);
-       }
+       /*
+        * Save FPU state to signal context. Signal handler
+        * will "inherit" current FPU state.
+        */
+       err |= protected_save_fp_context(sc);
+
        return err;
 }
 
+static size_t extcontext_max_size(void)
+{
+       size_t sz = 0;
+
+       /*
+        * The assumption here is that between this point & the point at which
+        * the extended context is saved the size of the context should only
+        * ever be able to shrink (if the task is preempted), but never grow.
+        * That is, what this function returns is an upper bound on the size of
+        * the extended context for the current task at the current time.
+        */
+
+       if (thread_msa_context_live())
+               sz += sizeof(struct msa_extcontext);
+
+       /* If any context is saved then we'll append the end marker */
+       if (sz)
+               sz += sizeof(((struct extcontext *)NULL)->magic);
+
+       return sz;
+}
+
 int fpcsr_pending(unsigned int __user *fpcsr)
 {
        int err, sig = 0;
@@ -223,21 +482,8 @@ int fpcsr_pending(unsigned int __user *fpcsr)
        return err ?: sig;
 }
 
-static int
-check_and_restore_fp_context(struct sigcontext __user *sc)
-{
-       int err, sig;
-
-       err = sig = fpcsr_pending(&sc->sc_fpc_csr);
-       if (err > 0)
-               err = 0;
-       err |= protected_restore_fp_context(sc);
-       return err ?: sig;
-}
-
 int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
 {
-       unsigned int used_math;
        unsigned long treg;
        int err = 0;
        int i;
@@ -265,19 +511,7 @@ int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
        for (i = 1; i < 32; i++)
                err |= __get_user(regs->regs[i], &sc->sc_regs[i]);
 
-       err |= __get_user(used_math, &sc->sc_used_math);
-       conditional_used_math(used_math);
-
-       if (used_math) {
-               /* restore fpu context if we have used it before */
-               if (!err)
-                       err = check_and_restore_fp_context(sc);
-       } else {
-               /* signal handler may have used FPU.  Give it up. */
-               lose_fpu(0);
-       }
-
-       return err;
+       return err ?: protected_restore_fp_context(sc);
 }
 
 void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs,
@@ -285,6 +519,9 @@ void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs,
 {
        unsigned long sp;
 
+       /* Leave space for potential extended context */
+       frame_size += extcontext_max_size();
+
        /* Default to using normal stack */
        sp = regs->regs[29];
 
@@ -520,7 +757,11 @@ struct mips_abi mips_abi = {
        .setup_rt_frame = setup_rt_frame,
        .rt_signal_return_offset =
                offsetof(struct mips_vdso, rt_signal_trampoline),
-       .restart        = __NR_restart_syscall
+       .restart        = __NR_restart_syscall,
+
+       .off_sc_fpregs = offsetof(struct sigcontext, sc_fpregs),
+       .off_sc_fpc_csr = offsetof(struct sigcontext, sc_fpc_csr),
+       .off_sc_used_math = offsetof(struct sigcontext, sc_used_math),
 };
 
 static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
@@ -616,6 +857,9 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, void *unused,
 
        user_exit();
 
+       if (thread_info_flags & _TIF_UPROBE)
+               uprobe_notify_resume(regs);
+
        /* deal with pending signal delivery */
        if (thread_info_flags & _TIF_SIGPENDING)
                do_signal(regs);
@@ -629,43 +873,46 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, void *unused,
 }
 
 #ifdef CONFIG_SMP
-#ifndef CONFIG_EVA
-static int smp_save_fp_context(struct sigcontext __user *sc)
+static int smp_save_fp_context(void __user *sc)
 {
        return raw_cpu_has_fpu
-              ? _save_fp_context(sc)
+              ? save_hw_fp_context(sc)
               : copy_fp_to_sigcontext(sc);
 }
 
-static int smp_restore_fp_context(struct sigcontext __user *sc)
+static int smp_restore_fp_context(void __user *sc)
 {
        return raw_cpu_has_fpu
-              ? _restore_fp_context(sc)
+              ? restore_hw_fp_context(sc)
               : copy_fp_from_sigcontext(sc);
 }
-#endif /* CONFIG_EVA */
 #endif
 
 static int signal_setup(void)
 {
-#ifndef CONFIG_EVA
+       /*
+        * The offset from sigcontext to extended context should be the same
+        * regardless of the type of signal, such that userland can always know
+        * where to look if it wishes to find the extended context structures.
+        */
+       BUILD_BUG_ON((offsetof(struct sigframe, sf_extcontext) -
+                     offsetof(struct sigframe, sf_sc)) !=
+                    (offsetof(struct rt_sigframe, rs_uc.uc_extcontext) -
+                     offsetof(struct rt_sigframe, rs_uc.uc_mcontext)));
+
 #ifdef CONFIG_SMP
        /* For now just do the cpu_has_fpu check when the functions are invoked */
        save_fp_context = smp_save_fp_context;
        restore_fp_context = smp_restore_fp_context;
 #else
        if (cpu_has_fpu) {
-               save_fp_context = _save_fp_context;
-               restore_fp_context = _restore_fp_context;
+               save_fp_context = save_hw_fp_context;
+               restore_fp_context = restore_hw_fp_context;
        } else {
                save_fp_context = copy_fp_to_sigcontext;
                restore_fp_context = copy_fp_from_sigcontext;
        }
 #endif /* CONFIG_SMP */
-#else
-       save_fp_context = copy_fp_to_sigcontext;
-       restore_fp_context = copy_fp_from_sigcontext;
-#endif
 
        return 0;
 }
index 5d7f2634996fd4920f0a4c94e00cd42fae5934b1..f7e89524e3166fc23b0ea7ae08c10137d75de74e 100644 (file)
 
 #include "signal-common.h"
 
-static int (*save_fp_context32)(struct sigcontext32 __user *sc);
-static int (*restore_fp_context32)(struct sigcontext32 __user *sc);
-
-extern asmlinkage int _save_fp_context32(struct sigcontext32 __user *sc);
-extern asmlinkage int _restore_fp_context32(struct sigcontext32 __user *sc);
-
 /*
  * Including <asm/unistd.h> would give use the 64-bit syscall numbers ...
  */
@@ -74,99 +68,11 @@ struct rt_sigframe32 {
        struct ucontext32 rs_uc;
 };
 
-/*
- * Thread saved context copy to/from a signal context presumed to be on the
- * user stack, and therefore accessed with appropriate macros from uaccess.h.
- */
-static int copy_fp_to_sigcontext32(struct sigcontext32 __user *sc)
-{
-       int i;
-       int err = 0;
-       int inc = test_thread_flag(TIF_32BIT_FPREGS) ? 2 : 1;
-
-       for (i = 0; i < NUM_FPU_REGS; i += inc) {
-               err |=
-                   __put_user(get_fpr64(&current->thread.fpu.fpr[i], 0),
-                              &sc->sc_fpregs[i]);
-       }
-       err |= __put_user(current->thread.fpu.fcr31, &sc->sc_fpc_csr);
-
-       return err;
-}
-
-static int copy_fp_from_sigcontext32(struct sigcontext32 __user *sc)
-{
-       int i;
-       int err = 0;
-       int inc = test_thread_flag(TIF_32BIT_FPREGS) ? 2 : 1;
-       u64 fpr_val;
-
-       for (i = 0; i < NUM_FPU_REGS; i += inc) {
-               err |= __get_user(fpr_val, &sc->sc_fpregs[i]);
-               set_fpr64(&current->thread.fpu.fpr[i], 0, fpr_val);
-       }
-       err |= __get_user(current->thread.fpu.fcr31, &sc->sc_fpc_csr);
-
-       return err;
-}
-
-/*
- * sigcontext handlers
- */
-static int protected_save_fp_context32(struct sigcontext32 __user *sc)
-{
-       int err;
-       while (1) {
-               lock_fpu_owner();
-               if (is_fpu_owner()) {
-                       err = save_fp_context32(sc);
-                       unlock_fpu_owner();
-               } else {
-                       unlock_fpu_owner();
-                       err = copy_fp_to_sigcontext32(sc);
-               }
-               if (likely(!err))
-                       break;
-               /* touch the sigcontext and try again */
-               err = __put_user(0, &sc->sc_fpregs[0]) |
-                       __put_user(0, &sc->sc_fpregs[31]) |
-                       __put_user(0, &sc->sc_fpc_csr);
-               if (err)
-                       break;  /* really bad sigcontext */
-       }
-       return err;
-}
-
-static int protected_restore_fp_context32(struct sigcontext32 __user *sc)
-{
-       int err, tmp __maybe_unused;
-       while (1) {
-               lock_fpu_owner();
-               if (is_fpu_owner()) {
-                       err = restore_fp_context32(sc);
-                       unlock_fpu_owner();
-               } else {
-                       unlock_fpu_owner();
-                       err = copy_fp_from_sigcontext32(sc);
-               }
-               if (likely(!err))
-                       break;
-               /* touch the sigcontext and try again */
-               err = __get_user(tmp, &sc->sc_fpregs[0]) |
-                       __get_user(tmp, &sc->sc_fpregs[31]) |
-                       __get_user(tmp, &sc->sc_fpc_csr);
-               if (err)
-                       break;  /* really bad sigcontext */
-       }
-       return err;
-}
-
 static int setup_sigcontext32(struct pt_regs *regs,
                              struct sigcontext32 __user *sc)
 {
        int err = 0;
        int i;
-       u32 used_math;
 
        err |= __put_user(regs->cp0_epc, &sc->sc_pc);
 
@@ -186,35 +92,18 @@ static int setup_sigcontext32(struct pt_regs *regs,
                err |= __put_user(mflo3(), &sc->sc_lo3);
        }
 
-       used_math = !!used_math();
-       err |= __put_user(used_math, &sc->sc_used_math);
+       /*
+        * Save FPU state to signal context.  Signal handler
+        * will "inherit" current FPU state.
+        */
+       err |= protected_save_fp_context(sc);
 
-       if (used_math) {
-               /*
-                * Save FPU state to signal context.  Signal handler
-                * will "inherit" current FPU state.
-                */
-               err |= protected_save_fp_context32(sc);
-       }
        return err;
 }
 
-static int
-check_and_restore_fp_context32(struct sigcontext32 __user *sc)
-{
-       int err, sig;
-
-       err = sig = fpcsr_pending(&sc->sc_fpc_csr);
-       if (err > 0)
-               err = 0;
-       err |= protected_restore_fp_context32(sc);
-       return err ?: sig;
-}
-
 static int restore_sigcontext32(struct pt_regs *regs,
                                struct sigcontext32 __user *sc)
 {
-       u32 used_math;
        int err = 0;
        s32 treg;
        int i;
@@ -238,70 +127,7 @@ static int restore_sigcontext32(struct pt_regs *regs,
        for (i = 1; i < 32; i++)
                err |= __get_user(regs->regs[i], &sc->sc_regs[i]);
 
-       err |= __get_user(used_math, &sc->sc_used_math);
-       conditional_used_math(used_math);
-
-       if (used_math) {
-               /* restore fpu context if we have used it before */
-               if (!err)
-                       err = check_and_restore_fp_context32(sc);
-       } else {
-               /* signal handler may have used FPU.  Give it up. */
-               lose_fpu(0);
-       }
-
-       return err;
-}
-
-/*
- *
- */
-extern void __put_sigset_unknown_nsig(void);
-extern void __get_sigset_unknown_nsig(void);
-
-static inline int put_sigset(const sigset_t *kbuf, compat_sigset_t __user *ubuf)
-{
-       int err = 0;
-
-       if (!access_ok(VERIFY_WRITE, ubuf, sizeof(*ubuf)))
-               return -EFAULT;
-
-       switch (_NSIG_WORDS) {
-       default:
-               __put_sigset_unknown_nsig();
-       case 2:
-               err |= __put_user(kbuf->sig[1] >> 32, &ubuf->sig[3]);
-               err |= __put_user(kbuf->sig[1] & 0xffffffff, &ubuf->sig[2]);
-       case 1:
-               err |= __put_user(kbuf->sig[0] >> 32, &ubuf->sig[1]);
-               err |= __put_user(kbuf->sig[0] & 0xffffffff, &ubuf->sig[0]);
-       }
-
-       return err;
-}
-
-static inline int get_sigset(sigset_t *kbuf, const compat_sigset_t __user *ubuf)
-{
-       int err = 0;
-       unsigned long sig[4];
-
-       if (!access_ok(VERIFY_READ, ubuf, sizeof(*ubuf)))
-               return -EFAULT;
-
-       switch (_NSIG_WORDS) {
-       default:
-               __get_sigset_unknown_nsig();
-       case 2:
-               err |= __get_user(sig[3], &ubuf->sig[3]);
-               err |= __get_user(sig[2], &ubuf->sig[2]);
-               kbuf->sig[1] = sig[2] | (sig[3] << 32);
-       case 1:
-               err |= __get_user(sig[1], &ubuf->sig[1]);
-               err |= __get_user(sig[0], &ubuf->sig[0]);
-               kbuf->sig[0] = sig[0] | (sig[1] << 32);
-       }
-
-       return err;
+       return err ?: protected_restore_fp_context(sc);
 }
 
 /*
@@ -585,20 +411,9 @@ struct mips_abi mips_abi_32 = {
        .setup_rt_frame = setup_rt_frame_32,
        .rt_signal_return_offset =
                offsetof(struct mips_vdso, o32_rt_signal_trampoline),
-       .restart        = __NR_O32_restart_syscall
-};
-
-static int signal32_init(void)
-{
-       if (cpu_has_fpu) {
-               save_fp_context32 = _save_fp_context32;
-               restore_fp_context32 = _restore_fp_context32;
-       } else {
-               save_fp_context32 = copy_fp_to_sigcontext32;
-               restore_fp_context32 = copy_fp_from_sigcontext32;
-       }
+       .restart        = __NR_O32_restart_syscall,
 
-       return 0;
-}
-
-arch_initcall(signal32_init);
+       .off_sc_fpregs = offsetof(struct sigcontext32, sc_fpregs),
+       .off_sc_fpc_csr = offsetof(struct sigcontext32, sc_fpc_csr),
+       .off_sc_used_math = offsetof(struct sigcontext32, sc_used_math),
+};
index f1d4751eead09875c9746163267d93a57abea416..0d017fdcaf07aa50c583e644f4dc1f21d9ab80ee 100644 (file)
@@ -153,5 +153,9 @@ struct mips_abi mips_abi_n32 = {
        .setup_rt_frame = setup_rt_frame_n32,
        .rt_signal_return_offset =
                offsetof(struct mips_vdso, n32_rt_signal_trampoline),
-       .restart        = __NR_N32_restart_syscall
+       .restart        = __NR_N32_restart_syscall,
+
+       .off_sc_fpregs = offsetof(struct sigcontext, sc_fpregs),
+       .off_sc_fpc_csr = offsetof(struct sigcontext, sc_fpc_csr),
+       .off_sc_used_math = offsetof(struct sigcontext, sc_used_math),
 };
index d1168d7c31e8ef37c51568b93cf676e9a6c3ef81..8489c88f9932310b7732e1ec396ca2fb2000078c 100644 (file)
@@ -209,6 +209,7 @@ void spram_config(void)
        case CPU_PROAPTIV:
        case CPU_P5600:
        case CPU_QEMU_GENERIC:
+       case CPU_I6400:
                config0 = read_c0_config();
                /* FIXME: addresses are Malta specific */
                if (config0 & (1<<24)) {
index 5b539f5fc9d9d6a5d6d48d2bf5ea8aed1b78d8ea..5f055393092dec3ac7704a22e72e672c08a22029 100644 (file)
@@ -21,24 +21,12 @@ static DEFINE_SPINLOCK(show_lock);
 
 static void sysrq_tlbdump_single(void *dummy)
 {
-       const int field = 2 * sizeof(unsigned long);
        unsigned long flags;
 
        spin_lock_irqsave(&show_lock, flags);
 
        pr_info("CPU%d:\n", smp_processor_id());
-       pr_info("Index  : %0x\n", read_c0_index());
-       pr_info("Pagemask: %0x\n", read_c0_pagemask());
-       pr_info("EntryHi : %0*lx\n", field, read_c0_entryhi());
-       pr_info("EntryLo0: %0*lx\n", field, read_c0_entrylo0());
-       pr_info("EntryLo1: %0*lx\n", field, read_c0_entrylo1());
-       pr_info("Wired   : %0x\n", read_c0_wired());
-       pr_info("Pagegrain: %0x\n", read_c0_pagegrain());
-       if (cpu_has_htw) {
-               pr_info("PWField : %0*lx\n", field, read_c0_pwfield());
-               pr_info("PWSize  : %0*lx\n", field, read_c0_pwsize());
-               pr_info("PWCtl   : %0x\n", read_c0_pwctl());
-       }
+       dump_tlb_regs();
        pr_info("\n");
        dump_tlb_all();
        pr_info("\n");
index 8ea28e6ab37dead56439dc37871b6b18e8ec02d5..fdb392b27e8109f8b02a1b09b3a3d95cdbd20f14 100644 (file)
@@ -370,11 +370,6 @@ void show_registers(struct pt_regs *regs)
        set_fs(old_fs);
 }
 
-static int regs_to_trapnr(struct pt_regs *regs)
-{
-       return (regs->cp0_cause >> 2) & 0x1f;
-}
-
 static DEFINE_RAW_SPINLOCK(die_lock);
 
 void __noreturn die(const char *str, struct pt_regs *regs)
@@ -384,7 +379,7 @@ void __noreturn die(const char *str, struct pt_regs *regs)
 
        oops_enter();
 
-       if (notify_die(DIE_OOPS, str, regs, 0, regs_to_trapnr(regs),
+       if (notify_die(DIE_OOPS, str, regs, 0, current->thread.trap_nr,
                       SIGSEGV) == NOTIFY_STOP)
                sig = 0;
 
@@ -470,7 +465,7 @@ asmlinkage void do_be(struct pt_regs *regs)
        printk(KERN_ALERT "%s bus error, epc == %0*lx, ra == %0*lx\n",
               data ? "Data" : "Instruction",
               field, regs->cp0_epc, field, regs->regs[31]);
-       if (notify_die(DIE_OOPS, "bus error", regs, 0, regs_to_trapnr(regs),
+       if (notify_die(DIE_OOPS, "bus error", regs, 0, current->thread.trap_nr,
                       SIGBUS) == NOTIFY_STOP)
                goto out;
 
@@ -826,7 +821,7 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31)
        int sig;
 
        prev_state = exception_enter();
-       if (notify_die(DIE_FP, "FP exception", regs, 0, regs_to_trapnr(regs),
+       if (notify_die(DIE_FP, "FP exception", regs, 0, current->thread.trap_nr,
                       SIGFPE) == NOTIFY_STOP)
                goto out;
 
@@ -882,11 +877,12 @@ void do_trap_or_bp(struct pt_regs *regs, unsigned int code,
        char b[40];
 
 #ifdef CONFIG_KGDB_LOW_LEVEL_TRAP
-       if (kgdb_ll_trap(DIE_TRAP, str, regs, code, regs_to_trapnr(regs), SIGTRAP) == NOTIFY_STOP)
+       if (kgdb_ll_trap(DIE_TRAP, str, regs, code, current->thread.trap_nr,
+                        SIGTRAP) == NOTIFY_STOP)
                return;
 #endif /* CONFIG_KGDB_LOW_LEVEL_TRAP */
 
-       if (notify_die(DIE_TRAP, str, regs, code, regs_to_trapnr(regs),
+       if (notify_die(DIE_TRAP, str, regs, code, current->thread.trap_nr,
                       SIGTRAP) == NOTIFY_STOP)
                return;
 
@@ -948,6 +944,7 @@ asmlinkage void do_bp(struct pt_regs *regs)
                set_fs(KERNEL_DS);
 
        prev_state = exception_enter();
+       current->thread.trap_nr = (regs->cp0_cause >> 2) & 0x1f;
        if (get_isa16_mode(regs->cp0_epc)) {
                u16 instr[2];
 
@@ -987,15 +984,27 @@ asmlinkage void do_bp(struct pt_regs *regs)
         * pertain to them.
         */
        switch (bcode) {
+       case BRK_UPROBE:
+               if (notify_die(DIE_UPROBE, "uprobe", regs, bcode,
+                              current->thread.trap_nr, SIGTRAP) == NOTIFY_STOP)
+                       goto out;
+               else
+                       break;
+       case BRK_UPROBE_XOL:
+               if (notify_die(DIE_UPROBE_XOL, "uprobe_xol", regs, bcode,
+                              current->thread.trap_nr, SIGTRAP) == NOTIFY_STOP)
+                       goto out;
+               else
+                       break;
        case BRK_KPROBE_BP:
                if (notify_die(DIE_BREAK, "debug", regs, bcode,
-                              regs_to_trapnr(regs), SIGTRAP) == NOTIFY_STOP)
+                              current->thread.trap_nr, SIGTRAP) == NOTIFY_STOP)
                        goto out;
                else
                        break;
        case BRK_KPROBE_SSTEPBP:
                if (notify_die(DIE_SSTEPBP, "single_step", regs, bcode,
-                              regs_to_trapnr(regs), SIGTRAP) == NOTIFY_STOP)
+                              current->thread.trap_nr, SIGTRAP) == NOTIFY_STOP)
                        goto out;
                else
                        break;
@@ -1028,6 +1037,7 @@ asmlinkage void do_tr(struct pt_regs *regs)
                set_fs(get_ds());
 
        prev_state = exception_enter();
+       current->thread.trap_nr = (regs->cp0_cause >> 2) & 0x1f;
        if (get_isa16_mode(regs->cp0_epc)) {
                if (__get_user(instr[0], (u16 __user *)(epc + 0)) ||
                    __get_user(instr[1], (u16 __user *)(epc + 2)))
@@ -1094,8 +1104,9 @@ asmlinkage void do_ri(struct pt_regs *regs)
 no_r2_instr:
 
        prev_state = exception_enter();
+       current->thread.trap_nr = (regs->cp0_cause >> 2) & 0x1f;
 
-       if (notify_die(DIE_RI, "RI Fault", regs, 0, regs_to_trapnr(regs),
+       if (notify_die(DIE_RI, "RI Fault", regs, 0, current->thread.trap_nr,
                       SIGILL) == NOTIFY_STOP)
                goto out;
 
@@ -1444,8 +1455,9 @@ asmlinkage void do_msa_fpe(struct pt_regs *regs, unsigned int msacsr)
        enum ctx_state prev_state;
 
        prev_state = exception_enter();
+       current->thread.trap_nr = (regs->cp0_cause >> 2) & 0x1f;
        if (notify_die(DIE_MSAFP, "MSA FP exception", regs, 0,
-                      regs_to_trapnr(regs), SIGFPE) == NOTIFY_STOP)
+                      current->thread.trap_nr, SIGFPE) == NOTIFY_STOP)
                goto out;
 
        /* Clear MSACSR.Cause before enabling interrupts */
@@ -1523,7 +1535,6 @@ asmlinkage void do_watch(struct pt_regs *regs)
 
 asmlinkage void do_mcheck(struct pt_regs *regs)
 {
-       const int field = 2 * sizeof(unsigned long);
        int multi_match = regs->cp0_status & ST0_TS;
        enum ctx_state prev_state;
        mm_segment_t old_fs = get_fs();
@@ -1532,19 +1543,8 @@ asmlinkage void do_mcheck(struct pt_regs *regs)
        show_regs(regs);
 
        if (multi_match) {
-               pr_err("Index   : %0x\n", read_c0_index());
-               pr_err("Pagemask: %0x\n", read_c0_pagemask());
-               pr_err("EntryHi : %0*lx\n", field, read_c0_entryhi());
-               pr_err("EntryLo0: %0*lx\n", field, read_c0_entrylo0());
-               pr_err("EntryLo1: %0*lx\n", field, read_c0_entrylo1());
-               pr_err("Wired   : %0x\n", read_c0_wired());
-               pr_err("Pagegrain: %0x\n", read_c0_pagegrain());
-               if (cpu_has_htw) {
-                       pr_err("PWField : %0*lx\n", field, read_c0_pwfield());
-                       pr_err("PWSize  : %0*lx\n", field, read_c0_pwsize());
-                       pr_err("PWCtl   : %0x\n", read_c0_pwctl());
-               }
-               pr_err("\n");
+               dump_tlb_regs();
+               pr_info("\n");
                dump_tlb_all();
        }
 
@@ -1651,6 +1651,7 @@ static inline void parity_protection_init(void)
        case CPU_PROAPTIV:
        case CPU_P5600:
        case CPU_QEMU_GENERIC:
+       case CPU_I6400:
                {
 #define ERRCTL_PE      0x80000000
 #define ERRCTL_L2P     0x00800000
index eb3efd137fd17cdb6e1defa163744a480ad16185..990354dd6bdedb79d77d8ec4291e14e3836dcba3 100644 (file)
@@ -891,6 +891,9 @@ static void emulate_load_store_insn(struct pt_regs *regs,
 #ifdef CONFIG_EVA
        mm_segment_t seg;
 #endif
+       union fpureg *fpr;
+       enum msa_2b_fmt df;
+       unsigned int wd;
        origpc = (unsigned long)pc;
        orig31 = regs->regs[31];
 
@@ -1202,6 +1205,75 @@ static void emulate_load_store_insn(struct pt_regs *regs,
                        break;
                return;
 
+       case msa_op:
+               if (!cpu_has_msa)
+                       goto sigill;
+
+               /*
+                * If we've reached this point then userland should have taken
+                * the MSA disabled exception & initialised vector context at
+                * some point in the past.
+                */
+               BUG_ON(!thread_msa_context_live());
+
+               df = insn.msa_mi10_format.df;
+               wd = insn.msa_mi10_format.wd;
+               fpr = &current->thread.fpu.fpr[wd];
+
+               switch (insn.msa_mi10_format.func) {
+               case msa_ld_op:
+                       if (!access_ok(VERIFY_READ, addr, sizeof(*fpr)))
+                               goto sigbus;
+
+                       /*
+                        * Disable preemption to avoid a race between copying
+                        * state from userland, migrating to another CPU and
+                        * updating the hardware vector register below.
+                        */
+                       preempt_disable();
+
+                       res = __copy_from_user_inatomic(fpr, addr,
+                                                       sizeof(*fpr));
+                       if (res)
+                               goto fault;
+
+                       /*
+                        * Update the hardware register if it is in use by the
+                        * task in this quantum, in order to avoid having to
+                        * save & restore the whole vector context.
+                        */
+                       if (test_thread_flag(TIF_USEDMSA))
+                               write_msa_wr(wd, fpr, df);
+
+                       preempt_enable();
+                       break;
+
+               case msa_st_op:
+                       if (!access_ok(VERIFY_WRITE, addr, sizeof(*fpr)))
+                               goto sigbus;
+
+                       /*
+                        * Update from the hardware register if it is in use by
+                        * the task in this quantum, in order to avoid having to
+                        * save & restore the whole vector context.
+                        */
+                       preempt_disable();
+                       if (test_thread_flag(TIF_USEDMSA))
+                               read_msa_wr(wd, fpr, df);
+                       preempt_enable();
+
+                       res = __copy_to_user_inatomic(addr, fpr, sizeof(*fpr));
+                       if (res)
+                               goto fault;
+                       break;
+
+               default:
+                       goto sigbus;
+               }
+
+               compute_return_epc(regs);
+               break;
+
 #ifndef CONFIG_CPU_MIPSR6
        /*
         * COP2 is available to implementor for application specific use.
@@ -2240,5 +2312,5 @@ static int __init debugfs_unaligned(void)
                return -ENOMEM;
        return 0;
 }
-__initcall(debugfs_unaligned);
+arch_initcall(debugfs_unaligned);
 #endif
diff --git a/arch/mips/kernel/uprobes.c b/arch/mips/kernel/uprobes.c
new file mode 100644 (file)
index 0000000..8452d93
--- /dev/null
@@ -0,0 +1,341 @@
+#include <linux/highmem.h>
+#include <linux/kdebug.h>
+#include <linux/types.h>
+#include <linux/notifier.h>
+#include <linux/sched.h>
+#include <linux/uprobes.h>
+
+#include <asm/branch.h>
+#include <asm/cpu-features.h>
+#include <asm/ptrace.h>
+#include <asm/inst.h>
+
+static inline int insn_has_delay_slot(const union mips_instruction insn)
+{
+       switch (insn.i_format.opcode) {
+       /*
+        * jr and jalr are in r_format format.
+        */
+       case spec_op:
+               switch (insn.r_format.func) {
+               case jalr_op:
+               case jr_op:
+                       return 1;
+               }
+               break;
+
+       /*
+        * This group contains:
+        * bltz_op, bgez_op, bltzl_op, bgezl_op,
+        * bltzal_op, bgezal_op, bltzall_op, bgezall_op.
+        */
+       case bcond_op:
+               switch (insn.i_format.rt) {
+               case bltz_op:
+               case bltzl_op:
+               case bgez_op:
+               case bgezl_op:
+               case bltzal_op:
+               case bltzall_op:
+               case bgezal_op:
+               case bgezall_op:
+               case bposge32_op:
+                       return 1;
+               }
+               break;
+
+       /*
+        * These are unconditional and in j_format.
+        */
+       case jal_op:
+       case j_op:
+       case beq_op:
+       case beql_op:
+       case bne_op:
+       case bnel_op:
+       case blez_op: /* not really i_format */
+       case blezl_op:
+       case bgtz_op:
+       case bgtzl_op:
+               return 1;
+
+       /*
+        * And now the FPA/cp1 branch instructions.
+        */
+       case cop1_op:
+#ifdef CONFIG_CPU_CAVIUM_OCTEON
+       case lwc2_op: /* This is bbit0 on Octeon */
+       case ldc2_op: /* This is bbit032 on Octeon */
+       case swc2_op: /* This is bbit1 on Octeon */
+       case sdc2_op: /* This is bbit132 on Octeon */
+#endif
+               return 1;
+       }
+
+       return 0;
+}
+
+/**
+ * arch_uprobe_analyze_insn - instruction analysis including validity and fixups.
+ * @mm: the probed address space.
+ * @arch_uprobe: the probepoint information.
+ * @addr: virtual address at which to install the probepoint
+ * Return 0 on success or a -ve number on error.
+ */
+int arch_uprobe_analyze_insn(struct arch_uprobe *aup,
+       struct mm_struct *mm, unsigned long addr)
+{
+       union mips_instruction inst;
+
+       /*
+        * For the time being this also blocks attempts to use uprobes with
+        * MIPS16 and microMIPS.
+        */
+       if (addr & 0x03)
+               return -EINVAL;
+
+       inst.word = aup->insn[0];
+       aup->ixol[0] = aup->insn[insn_has_delay_slot(inst)];
+       aup->ixol[1] = UPROBE_BRK_UPROBE_XOL;           /* NOP  */
+
+       return 0;
+}
+
+/**
+ * is_trap_insn - check if the instruction is a trap variant
+ * @insn: instruction to be checked.
+ * Returns true if @insn is a trap variant.
+ *
+ * This definition overrides the weak definition in kernel/events/uprobes.c.
+ * and is needed for the case where an architecture has multiple trap
+ * instructions (like PowerPC or MIPS).  We treat BREAK just like the more
+ * modern conditional trap instructions.
+ */
+bool is_trap_insn(uprobe_opcode_t *insn)
+{
+       union mips_instruction inst;
+
+       inst.word = *insn;
+
+       switch (inst.i_format.opcode) {
+       case spec_op:
+               switch (inst.r_format.func) {
+               case break_op:
+               case teq_op:
+               case tge_op:
+               case tgeu_op:
+               case tlt_op:
+               case tltu_op:
+               case tne_op:
+                       return 1;
+               }
+               break;
+
+       case bcond_op:  /* Yes, really ...  */
+               switch (inst.u_format.rt) {
+               case teqi_op:
+               case tgei_op:
+               case tgeiu_op:
+               case tlti_op:
+               case tltiu_op:
+               case tnei_op:
+                       return 1;
+               }
+               break;
+       }
+
+       return 0;
+}
+
+#define UPROBE_TRAP_NR ULONG_MAX
+
+/*
+ * arch_uprobe_pre_xol - prepare to execute out of line.
+ * @auprobe: the probepoint information.
+ * @regs: reflects the saved user state of current task.
+ */
+int arch_uprobe_pre_xol(struct arch_uprobe *aup, struct pt_regs *regs)
+{
+       struct uprobe_task *utask = current->utask;
+       union mips_instruction insn;
+
+       /*
+        * Now find the EPC where to resume after the breakpoint has been
+        * dealt with.  This may require emulation of a branch.
+        */
+       aup->resume_epc = regs->cp0_epc + 4;
+       if (insn_has_delay_slot((union mips_instruction) aup->insn[0])) {
+               unsigned long epc;
+
+               epc = regs->cp0_epc;
+               __compute_return_epc_for_insn(regs, insn);
+               aup->resume_epc = regs->cp0_epc;
+       }
+
+       utask->autask.saved_trap_nr = current->thread.trap_nr;
+       current->thread.trap_nr = UPROBE_TRAP_NR;
+       regs->cp0_epc = current->utask->xol_vaddr;
+
+       return 0;
+}
+
+int arch_uprobe_post_xol(struct arch_uprobe *aup, struct pt_regs *regs)
+{
+       struct uprobe_task *utask = current->utask;
+
+       current->thread.trap_nr = utask->autask.saved_trap_nr;
+       regs->cp0_epc = aup->resume_epc;
+
+       return 0;
+}
+
+/*
+ * If xol insn itself traps and generates a signal(Say,
+ * SIGILL/SIGSEGV/etc), then detect the case where a singlestepped
+ * instruction jumps back to its own address. It is assumed that anything
+ * like do_page_fault/do_trap/etc sets thread.trap_nr != -1.
+ *
+ * arch_uprobe_pre_xol/arch_uprobe_post_xol save/restore thread.trap_nr,
+ * arch_uprobe_xol_was_trapped() simply checks that ->trap_nr is not equal to
+ * UPROBE_TRAP_NR == -1 set by arch_uprobe_pre_xol().
+ */
+bool arch_uprobe_xol_was_trapped(struct task_struct *tsk)
+{
+       if (tsk->thread.trap_nr != UPROBE_TRAP_NR)
+               return true;
+
+       return false;
+}
+
+int arch_uprobe_exception_notify(struct notifier_block *self,
+       unsigned long val, void *data)
+{
+       struct die_args *args = data;
+       struct pt_regs *regs = args->regs;
+
+       /* regs == NULL is a kernel bug */
+       if (WARN_ON(!regs))
+               return NOTIFY_DONE;
+
+       /* We are only interested in userspace traps */
+       if (!user_mode(regs))
+               return NOTIFY_DONE;
+
+       switch (val) {
+       case DIE_BREAK:
+               if (uprobe_pre_sstep_notifier(regs))
+                       return NOTIFY_STOP;
+               break;
+       case DIE_UPROBE_XOL:
+               if (uprobe_post_sstep_notifier(regs))
+                       return NOTIFY_STOP;
+       default:
+               break;
+       }
+
+       return 0;
+}
+
+/*
+ * This function gets called when XOL instruction either gets trapped or
+ * the thread has a fatal signal. Reset the instruction pointer to its
+ * probed address for the potential restart or for post mortem analysis.
+ */
+void arch_uprobe_abort_xol(struct arch_uprobe *aup,
+       struct pt_regs *regs)
+{
+       struct uprobe_task *utask = current->utask;
+
+       instruction_pointer_set(regs, utask->vaddr);
+}
+
+unsigned long arch_uretprobe_hijack_return_addr(
+       unsigned long trampoline_vaddr, struct pt_regs *regs)
+{
+       unsigned long ra;
+
+       ra = regs->regs[31];
+
+       /* Replace the return address with the trampoline address */
+       regs->regs[31] = ra;
+
+       return ra;
+}
+
+/**
+ * set_swbp - store breakpoint at a given address.
+ * @auprobe: arch specific probepoint information.
+ * @mm: the probed process address space.
+ * @vaddr: the virtual address to insert the opcode.
+ *
+ * For mm @mm, store the breakpoint instruction at @vaddr.
+ * Return 0 (success) or a negative errno.
+ *
+ * This version overrides the weak version in kernel/events/uprobes.c.
+ * It is required to handle MIPS16 and microMIPS.
+ */
+int __weak set_swbp(struct arch_uprobe *auprobe, struct mm_struct *mm,
+       unsigned long vaddr)
+{
+       return uprobe_write_opcode(mm, vaddr, UPROBE_SWBP_INSN);
+}
+
+/**
+ * set_orig_insn - Restore the original instruction.
+ * @mm: the probed process address space.
+ * @auprobe: arch specific probepoint information.
+ * @vaddr: the virtual address to insert the opcode.
+ *
+ * For mm @mm, restore the original opcode (opcode) at @vaddr.
+ * Return 0 (success) or a negative errno.
+ *
+ * This overrides the weak version in kernel/events/uprobes.c.
+ */
+int set_orig_insn(struct arch_uprobe *auprobe, struct mm_struct *mm,
+                unsigned long vaddr)
+{
+       return uprobe_write_opcode(mm, vaddr,
+                       *(uprobe_opcode_t *)&auprobe->orig_inst[0].word);
+}
+
+void __weak arch_uprobe_copy_ixol(struct page *page, unsigned long vaddr,
+                                 void *src, unsigned long len)
+{
+       void *kaddr;
+
+       /* Initialize the slot */
+       kaddr = kmap_atomic(page);
+       memcpy(kaddr + (vaddr & ~PAGE_MASK), src, len);
+       kunmap_atomic(kaddr);
+
+       /*
+        * The MIPS version of flush_icache_range will operate safely on
+        * user space addresses and more importantly, it doesn't require a
+        * VMA argument.
+        */
+       flush_icache_range(vaddr, vaddr + len);
+}
+
+/**
+ * uprobe_get_swbp_addr - compute address of swbp given post-swbp regs
+ * @regs: Reflects the saved state of the task after it has hit a breakpoint
+ * instruction.
+ * Return the address of the breakpoint instruction.
+ *
+ * This overrides the weak version in kernel/events/uprobes.c.
+ */
+unsigned long uprobe_get_swbp_addr(struct pt_regs *regs)
+{
+       return instruction_pointer(regs);
+}
+
+/*
+ * See if the instruction can be emulated.
+ * Returns true if instruction was emulated, false otherwise.
+ *
+ * For now we always emulate so this function just returns 0.
+ */
+bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs)
+{
+       return 0;
+}
index 11da314565cc331a03ad2e5b75b834361842d831..9067b651c7a2d91e02ee6a591b8cd912c2a209cf 100644 (file)
@@ -817,6 +817,7 @@ static int vpe_open(struct inode *inode, struct file *filp)
 
 static int vpe_release(struct inode *inode, struct file *filp)
 {
+#if defined(CONFIG_MIPS_VPE_LOADER_MT) || defined(CONFIG_MIPS_VPE_LOADER_CMP)
        struct vpe *v;
        Elf_Ehdr *hdr;
        int ret = 0;
@@ -827,7 +828,7 @@ static int vpe_release(struct inode *inode, struct file *filp)
 
        hdr = (Elf_Ehdr *) v->pbuffer;
        if (memcmp(hdr->e_ident, ELFMAG, SELFMAG) == 0) {
-               if ((vpe_elfload(v) >= 0) && vpe_run) {
+               if (vpe_elfload(v) >= 0) {
                        vpe_run(v);
                } else {
                        pr_warn("VPE loader: ELF load failed.\n");
@@ -850,6 +851,10 @@ static int vpe_release(struct inode *inode, struct file *filp)
        v->plen = 0;
 
        return ret;
+#else
+       pr_warn("VPE loader: ELF load failed.\n");
+       return -ENOEXEC;
+#endif
 }
 
 static ssize_t vpe_write(struct file *file, const char __user *buffer,
index a57959e648a6beb5ec3e21db56512989a3382f78..c710d969938d74b57e7d0b31f1c8a270b546a00f 100644 (file)
@@ -270,4 +270,4 @@ static int __init lasat_register_sysctl(void)
        return 0;
 }
 
-__initcall(lasat_register_sysctl);
+arch_initcall(lasat_register_sysctl);
index 167f35634709b885d734778e85ec5896c07eba0d..92a37319efbe9a7498c6b38cd119abdd4c35b218 100644 (file)
 #include <asm/pgtable.h>
 #include <asm/tlbdebug.h>
 
+void dump_tlb_regs(void)
+{
+       const int field = 2 * sizeof(unsigned long);
+
+       pr_info("Index    : %0x\n", read_c0_index());
+       pr_info("PageMask : %0x\n", read_c0_pagemask());
+       pr_info("EntryHi  : %0*lx\n", field, read_c0_entryhi());
+       pr_info("EntryLo0 : %0*lx\n", field, read_c0_entrylo0());
+       pr_info("EntryLo1 : %0*lx\n", field, read_c0_entrylo1());
+       pr_info("Wired    : %0x\n", read_c0_wired());
+       switch (current_cpu_type()) {
+       case CPU_R10000:
+       case CPU_R12000:
+       case CPU_R14000:
+       case CPU_R16000:
+               pr_info("FrameMask: %0x\n", read_c0_framemask());
+               break;
+       }
+       if (cpu_has_small_pages || cpu_has_rixi || cpu_has_xpa)
+               pr_info("PageGrain: %0x\n", read_c0_pagegrain());
+       if (cpu_has_htw) {
+               pr_info("PWField  : %0*lx\n", field, read_c0_pwfield());
+               pr_info("PWSize   : %0*lx\n", field, read_c0_pwsize());
+               pr_info("PWCtl    : %0x\n", read_c0_pwctl());
+       }
+}
+
 static inline const char *msk2str(unsigned int mask)
 {
        switch (mask) {
@@ -87,7 +114,7 @@ static void dump_tlb(int first, int last)
                 * leave only a single G bit set after a machine check exception
                 * due to duplicate TLB entry.
                 */
-               if (!((entrylo0 | entrylo1) & MIPS_ENTRYLO_G) &&
+               if (!((entrylo0 | entrylo1) & ENTRYLO_G) &&
                    (entryhi & 0xff) != asid)
                        continue;
 
@@ -96,8 +123,8 @@ static void dump_tlb(int first, int last)
                 */
                printk("Index: %2d pgmask=%s ", i, msk2str(pagemask));
 
-               c0 = (entrylo0 & MIPS_ENTRYLO_C) >> MIPS_ENTRYLO_C_SHIFT;
-               c1 = (entrylo1 & MIPS_ENTRYLO_C) >> MIPS_ENTRYLO_C_SHIFT;
+               c0 = (entrylo0 & ENTRYLO_C) >> ENTRYLO_C_SHIFT;
+               c1 = (entrylo1 & ENTRYLO_C) >> ENTRYLO_C_SHIFT;
 
                printk("va=%0*lx asid=%02lx\n",
                       vwidth, (entryhi & ~0x1fffUL),
@@ -114,9 +141,9 @@ static void dump_tlb(int first, int last)
                               (entrylo0 & MIPS_ENTRYLO_XI) ? 1 : 0);
                printk("pa=%0*llx c=%d d=%d v=%d g=%d] [",
                       pwidth, pa, c0,
-                      (entrylo0 & MIPS_ENTRYLO_D) ? 1 : 0,
-                      (entrylo0 & MIPS_ENTRYLO_V) ? 1 : 0,
-                      (entrylo0 & MIPS_ENTRYLO_G) ? 1 : 0);
+                      (entrylo0 & ENTRYLO_D) ? 1 : 0,
+                      (entrylo0 & ENTRYLO_V) ? 1 : 0,
+                      (entrylo0 & ENTRYLO_G) ? 1 : 0);
                /* RI/XI are in awkward places, so mask them off separately */
                pa = entrylo1 & ~(MIPS_ENTRYLO_RI | MIPS_ENTRYLO_XI);
                if (xpa)
@@ -128,9 +155,9 @@ static void dump_tlb(int first, int last)
                               (entrylo1 & MIPS_ENTRYLO_XI) ? 1 : 0);
                printk("pa=%0*llx c=%d d=%d v=%d g=%d]\n",
                       pwidth, pa, c1,
-                      (entrylo1 & MIPS_ENTRYLO_D) ? 1 : 0,
-                      (entrylo1 & MIPS_ENTRYLO_V) ? 1 : 0,
-                      (entrylo1 & MIPS_ENTRYLO_G) ? 1 : 0);
+                      (entrylo1 & ENTRYLO_D) ? 1 : 0,
+                      (entrylo1 & ENTRYLO_V) ? 1 : 0,
+                      (entrylo1 & ENTRYLO_G) ? 1 : 0);
        }
        printk("\n");
 
index 8e0d3cff8ae4481b104733019fe71be0c5c640a1..cfcbb5218b5951bbfaf661f99dec5da5c710c6bf 100644 (file)
 #include <asm/pgtable.h>
 #include <asm/tlbdebug.h>
 
+extern int r3k_have_wired_reg;
+
+void dump_tlb_regs(void)
+{
+       pr_info("Index    : %0x\n", read_c0_index());
+       pr_info("EntryHi  : %0lx\n", read_c0_entryhi());
+       pr_info("EntryLo  : %0lx\n", read_c0_entrylo0());
+       if (r3k_have_wired_reg)
+               pr_info("Wired    : %0x\n", read_c0_wired());
+}
+
 static void dump_tlb(int first, int last)
 {
        int     i;
index df0f850d6a5f49195710b5acd115c2c1e62eed72..0996b025eeefb0e6aee1081bd0360e6ff0d53b29 100644 (file)
@@ -126,26 +126,34 @@ static irqreturn_t ls1x_clockevent_isr(int irq, void *devid)
        return IRQ_HANDLED;
 }
 
-static void ls1x_clockevent_set_mode(enum clock_event_mode mode,
-                                    struct clock_event_device *cd)
+static int ls1x_clockevent_set_state_periodic(struct clock_event_device *cd)
 {
        raw_spin_lock(&ls1x_timer_lock);
-       switch (mode) {
-       case CLOCK_EVT_MODE_PERIODIC:
-               ls1x_pwmtimer_set_period(ls1x_jiffies_per_tick);
-               ls1x_pwmtimer_restart();
-       case CLOCK_EVT_MODE_RESUME:
-               __raw_writel(INT_EN | CNT_EN, timer_base + PWM_CTRL);
-               break;
-       case CLOCK_EVT_MODE_ONESHOT:
-       case CLOCK_EVT_MODE_SHUTDOWN:
-               __raw_writel(__raw_readl(timer_base + PWM_CTRL) & ~CNT_EN,
-                            timer_base + PWM_CTRL);
-               break;
-       default:
-               break;
-       }
+       ls1x_pwmtimer_set_period(ls1x_jiffies_per_tick);
+       ls1x_pwmtimer_restart();
+       __raw_writel(INT_EN | CNT_EN, timer_base + PWM_CTRL);
        raw_spin_unlock(&ls1x_timer_lock);
+
+       return 0;
+}
+
+static int ls1x_clockevent_tick_resume(struct clock_event_device *cd)
+{
+       raw_spin_lock(&ls1x_timer_lock);
+       __raw_writel(INT_EN | CNT_EN, timer_base + PWM_CTRL);
+       raw_spin_unlock(&ls1x_timer_lock);
+
+       return 0;
+}
+
+static int ls1x_clockevent_set_state_shutdown(struct clock_event_device *cd)
+{
+       raw_spin_lock(&ls1x_timer_lock);
+       __raw_writel(__raw_readl(timer_base + PWM_CTRL) & ~CNT_EN,
+                    timer_base + PWM_CTRL);
+       raw_spin_unlock(&ls1x_timer_lock);
+
+       return 0;
 }
 
 static int ls1x_clockevent_set_next(unsigned long evt,
@@ -160,12 +168,15 @@ static int ls1x_clockevent_set_next(unsigned long evt,
 }
 
 static struct clock_event_device ls1x_clockevent = {
-       .name           = "ls1x-pwmtimer",
-       .features       = CLOCK_EVT_FEAT_PERIODIC,
-       .rating         = 300,
-       .irq            = LS1X_TIMER_IRQ,
-       .set_next_event = ls1x_clockevent_set_next,
-       .set_mode       = ls1x_clockevent_set_mode,
+       .name                   = "ls1x-pwmtimer",
+       .features               = CLOCK_EVT_FEAT_PERIODIC,
+       .rating                 = 300,
+       .irq                    = LS1X_TIMER_IRQ,
+       .set_next_event         = ls1x_clockevent_set_next,
+       .set_state_shutdown     = ls1x_clockevent_set_state_shutdown,
+       .set_state_periodic     = ls1x_clockevent_set_state_periodic,
+       .set_state_oneshot      = ls1x_clockevent_set_state_shutdown,
+       .tick_resume            = ls1x_clockevent_tick_resume,
 };
 
 static struct irqaction ls1x_pwmtimer_irqaction = {
index 875037063a80ecc634d74759ce3032b78261ea19..da77d412514c03db21e6577466a9c8b8e8ac158b 100644 (file)
@@ -51,40 +51,36 @@ void enable_mfgpt0_counter(void)
 }
 EXPORT_SYMBOL(enable_mfgpt0_counter);
 
-static void init_mfgpt_timer(enum clock_event_mode mode,
-                            struct clock_event_device *evt)
+static int mfgpt_timer_set_periodic(struct clock_event_device *evt)
 {
        raw_spin_lock(&mfgpt_lock);
 
-       switch (mode) {
-       case CLOCK_EVT_MODE_PERIODIC:
-               outw(COMPARE, MFGPT0_CMP2);     /* set comparator2 */
-               outw(0, MFGPT0_CNT);    /* set counter to 0 */
-               enable_mfgpt0_counter();
-               break;
-
-       case CLOCK_EVT_MODE_SHUTDOWN:
-       case CLOCK_EVT_MODE_UNUSED:
-               if (evt->mode == CLOCK_EVT_MODE_PERIODIC ||
-                   evt->mode == CLOCK_EVT_MODE_ONESHOT)
-                       disable_mfgpt0_counter();
-               break;
-
-       case CLOCK_EVT_MODE_ONESHOT:
-               /* The oneshot mode have very high deviation, Not use it! */
-               break;
-
-       case CLOCK_EVT_MODE_RESUME:
-               /* Nothing to do here */
-               break;
-       }
+       outw(COMPARE, MFGPT0_CMP2);     /* set comparator2 */
+       outw(0, MFGPT0_CNT);            /* set counter to 0 */
+       enable_mfgpt0_counter();
+
        raw_spin_unlock(&mfgpt_lock);
+       return 0;
+}
+
+static int mfgpt_timer_shutdown(struct clock_event_device *evt)
+{
+       if (clockevent_state_periodic(evt) || clockevent_state_oneshot(evt)) {
+               raw_spin_lock(&mfgpt_lock);
+               disable_mfgpt0_counter();
+               raw_spin_unlock(&mfgpt_lock);
+       }
+
+       return 0;
 }
 
 static struct clock_event_device mfgpt_clockevent = {
        .name = "mfgpt",
        .features = CLOCK_EVT_FEAT_PERIODIC,
-       .set_mode = init_mfgpt_timer,
+
+       /* The oneshot mode have very high deviation, don't use it! */
+       .set_state_shutdown = mfgpt_timer_shutdown,
+       .set_state_periodic = mfgpt_timer_set_periodic,
        .irq = CS5536_MFGPT_INTR,
 };
 
index 5c21cd3bd339ab253c8b9a956de7bd20534e00f5..bf9f1a77f0e59825fcdb6ced3ce73ca78d8c7c19 100644 (file)
@@ -78,55 +78,77 @@ static void hpet_enable_legacy_int(void)
        /* Do nothing on Loongson-3 */
 }
 
-static void hpet_set_mode(enum clock_event_mode mode,
-                               struct clock_event_device *evt)
+static int hpet_set_state_periodic(struct clock_event_device *evt)
 {
-       int cfg = 0;
+       int cfg;
 
        spin_lock(&hpet_lock);
-       switch (mode) {
-       case CLOCK_EVT_MODE_PERIODIC:
-               pr_info("set clock event to periodic mode!\n");
-               /* stop counter */
-               hpet_stop_counter();
-
-               /* enables the timer0 to generate a periodic interrupt */
-               cfg = hpet_read(HPET_T0_CFG);
-               cfg &= ~HPET_TN_LEVEL;
-               cfg |= HPET_TN_ENABLE | HPET_TN_PERIODIC |
-                               HPET_TN_SETVAL | HPET_TN_32BIT;
-               hpet_write(HPET_T0_CFG, cfg);
-
-               /* set the comparator */
-               hpet_write(HPET_T0_CMP, HPET_COMPARE_VAL);
-               udelay(1);
-               hpet_write(HPET_T0_CMP, HPET_COMPARE_VAL);
-
-               /* start counter */
-               hpet_start_counter();
-               break;
-       case CLOCK_EVT_MODE_SHUTDOWN:
-       case CLOCK_EVT_MODE_UNUSED:
-               cfg = hpet_read(HPET_T0_CFG);
-               cfg &= ~HPET_TN_ENABLE;
-               hpet_write(HPET_T0_CFG, cfg);
-               break;
-       case CLOCK_EVT_MODE_ONESHOT:
-               pr_info("set clock event to one shot mode!\n");
-               cfg = hpet_read(HPET_T0_CFG);
-               /* set timer0 type
-                * 1 : periodic interrupt
-                * 0 : non-periodic(oneshot) interrupt
-                */
-               cfg &= ~HPET_TN_PERIODIC;
-               cfg |= HPET_TN_ENABLE | HPET_TN_32BIT;
-               hpet_write(HPET_T0_CFG, cfg);
-               break;
-       case CLOCK_EVT_MODE_RESUME:
-               hpet_enable_legacy_int();
-               break;
-       }
+
+       pr_info("set clock event to periodic mode!\n");
+       /* stop counter */
+       hpet_stop_counter();
+
+       /* enables the timer0 to generate a periodic interrupt */
+       cfg = hpet_read(HPET_T0_CFG);
+       cfg &= ~HPET_TN_LEVEL;
+       cfg |= HPET_TN_ENABLE | HPET_TN_PERIODIC | HPET_TN_SETVAL |
+               HPET_TN_32BIT;
+       hpet_write(HPET_T0_CFG, cfg);
+
+       /* set the comparator */
+       hpet_write(HPET_T0_CMP, HPET_COMPARE_VAL);
+       udelay(1);
+       hpet_write(HPET_T0_CMP, HPET_COMPARE_VAL);
+
+       /* start counter */
+       hpet_start_counter();
+
+       spin_unlock(&hpet_lock);
+       return 0;
+}
+
+static int hpet_set_state_shutdown(struct clock_event_device *evt)
+{
+       int cfg;
+
+       spin_lock(&hpet_lock);
+
+       cfg = hpet_read(HPET_T0_CFG);
+       cfg &= ~HPET_TN_ENABLE;
+       hpet_write(HPET_T0_CFG, cfg);
+
        spin_unlock(&hpet_lock);
+       return 0;
+}
+
+static int hpet_set_state_oneshot(struct clock_event_device *evt)
+{
+       int cfg;
+
+       spin_lock(&hpet_lock);
+
+       pr_info("set clock event to one shot mode!\n");
+       cfg = hpet_read(HPET_T0_CFG);
+       /*
+        * set timer0 type
+        * 1 : periodic interrupt
+        * 0 : non-periodic(oneshot) interrupt
+        */
+       cfg &= ~HPET_TN_PERIODIC;
+       cfg |= HPET_TN_ENABLE | HPET_TN_32BIT;
+       hpet_write(HPET_T0_CFG, cfg);
+
+       spin_unlock(&hpet_lock);
+       return 0;
+}
+
+static int hpet_tick_resume(struct clock_event_device *evt)
+{
+       spin_lock(&hpet_lock);
+       hpet_enable_legacy_int();
+       spin_unlock(&hpet_lock);
+
+       return 0;
 }
 
 static int hpet_next_event(unsigned long delta,
@@ -206,7 +228,10 @@ void __init setup_hpet_timer(void)
        cd->name = "hpet";
        cd->rating = 320;
        cd->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
-       cd->set_mode = hpet_set_mode;
+       cd->set_state_shutdown = hpet_set_state_shutdown;
+       cd->set_state_periodic = hpet_set_state_periodic;
+       cd->set_state_oneshot = hpet_set_state_oneshot;
+       cd->tick_resume = hpet_tick_resume;
        cd->set_next_event = hpet_next_event;
        cd->irq = HPET_T0_IRQ;
        cd->cpumask = cpumask_of(cpu);
index 2e5f96275c38a649e7dd6fc3c56b2da0b332984e..a19641d3ac23cacdb327fdfaecd2b40924d0d6f5 100644 (file)
@@ -4,9 +4,9 @@
 
 obj-y  += cp1emu.o ieee754dp.o ieee754sp.o ieee754.o \
           dp_div.o dp_mul.o dp_sub.o dp_add.o dp_fsp.o dp_cmp.o dp_simple.o \
-          dp_tint.o dp_fint.o \
+          dp_tint.o dp_fint.o dp_maddf.o dp_msubf.o dp_2008class.o dp_fmin.o dp_fmax.o \
           sp_div.o sp_mul.o sp_sub.o sp_add.o sp_fdp.o sp_cmp.o sp_simple.o \
-          sp_tint.o sp_fint.o \
+          sp_tint.o sp_fint.o sp_maddf.o sp_msubf.o sp_2008class.o sp_fmin.o sp_fmax.o \
           dsemul.o
 
 lib-y  += ieee754d.o \
index 712f17a2ecf206e1b5d33a63956e62baac29cb08..32f0e19a0d7f71fef2bb693e0da7b7bbc6bc9af9 100644 (file)
@@ -1137,7 +1137,7 @@ emul:
                        break;
 
                case mfhc_op:
-                       if (!cpu_has_mips_r2)
+                       if (!cpu_has_mips_r2_r6)
                                goto sigill;
 
                        /* copregister rd -> gpr[rt] */
@@ -1148,7 +1148,7 @@ emul:
                        break;
 
                case mthc_op:
-                       if (!cpu_has_mips_r2)
+                       if (!cpu_has_mips_r2_r6)
                                goto sigill;
 
                        /* copregister rd <- gpr[rt] */
@@ -1181,6 +1181,24 @@ emul:
                        }
                        break;
 
+               case bc1eqz_op:
+               case bc1nez_op:
+                       if (!cpu_has_mips_r6 || delay_slot(xcp))
+                               return SIGILL;
+
+                       cond = likely = 0;
+                       switch (MIPSInst_RS(ir)) {
+                       case bc1eqz_op:
+                               if (get_fpr32(&current->thread.fpu.fpr[MIPSInst_RT(ir)], 0) & 0x1)
+                                   cond = 1;
+                               break;
+                       case bc1nez_op:
+                               if (!(get_fpr32(&current->thread.fpu.fpr[MIPSInst_RT(ir)], 0) & 0x1))
+                                   cond = 1;
+                               break;
+                       }
+                       goto branch_common;
+
                case bc_op:
                        if (delay_slot(xcp))
                                return SIGILL;
@@ -1207,7 +1225,7 @@ emul:
                        case bct_op:
                                break;
                        }
-
+branch_common:
                        set_delay_slot(xcp);
                        if (cond) {
                                /*
@@ -1376,6 +1394,14 @@ static const unsigned char cmptab[8] = {
        IEEE754_CLT | IEEE754_CEQ | IEEE754_CUN,        /* cmp_ule (sig) cmp_ngt */
 };
 
+static const unsigned char negative_cmptab[8] = {
+       0, /* Reserved */
+       IEEE754_CLT | IEEE754_CGT | IEEE754_CEQ,
+       IEEE754_CLT | IEEE754_CGT | IEEE754_CUN,
+       IEEE754_CLT | IEEE754_CGT,
+       /* Reserved */
+};
+
 
 /*
  * Additional MIPS4 instructions
@@ -1717,6 +1743,126 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
                        SPFROMREG(rv.s, MIPSInst_FS(ir));
                        break;
 
+               case fseleqz_op:
+                       if (!cpu_has_mips_r6)
+                               return SIGILL;
+
+                       SPFROMREG(rv.s, MIPSInst_FT(ir));
+                       if (rv.w & 0x1)
+                               rv.w = 0;
+                       else
+                               SPFROMREG(rv.s, MIPSInst_FS(ir));
+                       break;
+
+               case fselnez_op:
+                       if (!cpu_has_mips_r6)
+                               return SIGILL;
+
+                       SPFROMREG(rv.s, MIPSInst_FT(ir));
+                       if (rv.w & 0x1)
+                               SPFROMREG(rv.s, MIPSInst_FS(ir));
+                       else
+                               rv.w = 0;
+                       break;
+
+               case fmaddf_op: {
+                       union ieee754sp ft, fs, fd;
+
+                       if (!cpu_has_mips_r6)
+                               return SIGILL;
+
+                       SPFROMREG(ft, MIPSInst_FT(ir));
+                       SPFROMREG(fs, MIPSInst_FS(ir));
+                       SPFROMREG(fd, MIPSInst_FD(ir));
+                       rv.s = ieee754sp_maddf(fd, fs, ft);
+                       break;
+               }
+
+               case fmsubf_op: {
+                       union ieee754sp ft, fs, fd;
+
+                       if (!cpu_has_mips_r6)
+                               return SIGILL;
+
+                       SPFROMREG(ft, MIPSInst_FT(ir));
+                       SPFROMREG(fs, MIPSInst_FS(ir));
+                       SPFROMREG(fd, MIPSInst_FD(ir));
+                       rv.s = ieee754sp_msubf(fd, fs, ft);
+                       break;
+               }
+
+               case frint_op: {
+                       union ieee754sp fs;
+
+                       if (!cpu_has_mips_r6)
+                               return SIGILL;
+
+                       SPFROMREG(fs, MIPSInst_FS(ir));
+                       rv.l = ieee754sp_tlong(fs);
+                       rv.s = ieee754sp_flong(rv.l);
+                       goto copcsr;
+               }
+
+               case fclass_op: {
+                       union ieee754sp fs;
+
+                       if (!cpu_has_mips_r6)
+                               return SIGILL;
+
+                       SPFROMREG(fs, MIPSInst_FS(ir));
+                       rv.w = ieee754sp_2008class(fs);
+                       rfmt = w_fmt;
+                       break;
+               }
+
+               case fmin_op: {
+                       union ieee754sp fs, ft;
+
+                       if (!cpu_has_mips_r6)
+                               return SIGILL;
+
+                       SPFROMREG(ft, MIPSInst_FT(ir));
+                       SPFROMREG(fs, MIPSInst_FS(ir));
+                       rv.s = ieee754sp_fmin(fs, ft);
+                       break;
+               }
+
+               case fmina_op: {
+                       union ieee754sp fs, ft;
+
+                       if (!cpu_has_mips_r6)
+                               return SIGILL;
+
+                       SPFROMREG(ft, MIPSInst_FT(ir));
+                       SPFROMREG(fs, MIPSInst_FS(ir));
+                       rv.s = ieee754sp_fmina(fs, ft);
+                       break;
+               }
+
+               case fmax_op: {
+                       union ieee754sp fs, ft;
+
+                       if (!cpu_has_mips_r6)
+                               return SIGILL;
+
+                       SPFROMREG(ft, MIPSInst_FT(ir));
+                       SPFROMREG(fs, MIPSInst_FS(ir));
+                       rv.s = ieee754sp_fmax(fs, ft);
+                       break;
+               }
+
+               case fmaxa_op: {
+                       union ieee754sp fs, ft;
+
+                       if (!cpu_has_mips_r6)
+                               return SIGILL;
+
+                       SPFROMREG(ft, MIPSInst_FT(ir));
+                       SPFROMREG(fs, MIPSInst_FS(ir));
+                       rv.s = ieee754sp_fmaxa(fs, ft);
+                       break;
+               }
+
                case fabs_op:
                        handler.u = ieee754sp_abs;
                        goto scopuop;
@@ -1820,7 +1966,7 @@ copcsr:
                        goto copcsr;
 
                default:
-                       if (MIPSInst_FUNC(ir) >= fcmp_op) {
+                       if (!NO_R6EMU && MIPSInst_FUNC(ir) >= fcmp_op) {
                                unsigned cmpop = MIPSInst_FUNC(ir) - fcmp_op;
                                union ieee754sp fs, ft;
 
@@ -1914,6 +2060,127 @@ copcsr:
                                return 0;
                        DPFROMREG(rv.d, MIPSInst_FS(ir));
                        break;
+
+               case fseleqz_op:
+                       if (!cpu_has_mips_r6)
+                               return SIGILL;
+
+                       DPFROMREG(rv.d, MIPSInst_FT(ir));
+                       if (rv.l & 0x1)
+                               rv.l = 0;
+                       else
+                               DPFROMREG(rv.d, MIPSInst_FS(ir));
+                       break;
+
+               case fselnez_op:
+                       if (!cpu_has_mips_r6)
+                               return SIGILL;
+
+                       DPFROMREG(rv.d, MIPSInst_FT(ir));
+                       if (rv.l & 0x1)
+                               DPFROMREG(rv.d, MIPSInst_FS(ir));
+                       else
+                               rv.l = 0;
+                       break;
+
+               case fmaddf_op: {
+                       union ieee754dp ft, fs, fd;
+
+                       if (!cpu_has_mips_r6)
+                               return SIGILL;
+
+                       DPFROMREG(ft, MIPSInst_FT(ir));
+                       DPFROMREG(fs, MIPSInst_FS(ir));
+                       DPFROMREG(fd, MIPSInst_FD(ir));
+                       rv.d = ieee754dp_maddf(fd, fs, ft);
+                       break;
+               }
+
+               case fmsubf_op: {
+                       union ieee754dp ft, fs, fd;
+
+                       if (!cpu_has_mips_r6)
+                               return SIGILL;
+
+                       DPFROMREG(ft, MIPSInst_FT(ir));
+                       DPFROMREG(fs, MIPSInst_FS(ir));
+                       DPFROMREG(fd, MIPSInst_FD(ir));
+                       rv.d = ieee754dp_msubf(fd, fs, ft);
+                       break;
+               }
+
+               case frint_op: {
+                       union ieee754dp fs;
+
+                       if (!cpu_has_mips_r6)
+                               return SIGILL;
+
+                       DPFROMREG(fs, MIPSInst_FS(ir));
+                       rv.l = ieee754dp_tlong(fs);
+                       rv.d = ieee754dp_flong(rv.l);
+                       goto copcsr;
+               }
+
+               case fclass_op: {
+                       union ieee754dp fs;
+
+                       if (!cpu_has_mips_r6)
+                               return SIGILL;
+
+                       DPFROMREG(fs, MIPSInst_FS(ir));
+                       rv.w = ieee754dp_2008class(fs);
+                       rfmt = w_fmt;
+                       break;
+               }
+
+               case fmin_op: {
+                       union ieee754dp fs, ft;
+
+                       if (!cpu_has_mips_r6)
+                               return SIGILL;
+
+                       DPFROMREG(ft, MIPSInst_FT(ir));
+                       DPFROMREG(fs, MIPSInst_FS(ir));
+                       rv.d = ieee754dp_fmin(fs, ft);
+                       break;
+               }
+
+               case fmina_op: {
+                       union ieee754dp fs, ft;
+
+                       if (!cpu_has_mips_r6)
+                               return SIGILL;
+
+                       DPFROMREG(ft, MIPSInst_FT(ir));
+                       DPFROMREG(fs, MIPSInst_FS(ir));
+                       rv.d = ieee754dp_fmina(fs, ft);
+                       break;
+               }
+
+               case fmax_op: {
+                       union ieee754dp fs, ft;
+
+                       if (!cpu_has_mips_r6)
+                               return SIGILL;
+
+                       DPFROMREG(ft, MIPSInst_FT(ir));
+                       DPFROMREG(fs, MIPSInst_FS(ir));
+                       rv.d = ieee754dp_fmax(fs, ft);
+                       break;
+               }
+
+               case fmaxa_op: {
+                       union ieee754dp fs, ft;
+
+                       if (!cpu_has_mips_r6)
+                               return SIGILL;
+
+                       DPFROMREG(ft, MIPSInst_FT(ir));
+                       DPFROMREG(fs, MIPSInst_FS(ir));
+                       rv.d = ieee754dp_fmaxa(fs, ft);
+                       break;
+               }
+
                case fabs_op:
                        handler.u = ieee754dp_abs;
                        goto dcopuop;
@@ -1997,7 +2264,7 @@ dcopuop:
                        goto copcsr;
 
                default:
-                       if (MIPSInst_FUNC(ir) >= fcmp_op) {
+                       if (!NO_R6EMU && MIPSInst_FUNC(ir) >= fcmp_op) {
                                unsigned cmpop = MIPSInst_FUNC(ir) - fcmp_op;
                                union ieee754dp fs, ft;
 
@@ -2021,8 +2288,11 @@ dcopuop:
                        break;
                }
                break;
+       }
+
+       case w_fmt: {
+               union ieee754dp fs;
 
-       case w_fmt:
                switch (MIPSInst_FUNC(ir)) {
                case fcvts_op:
                        /* convert word to single precision real */
@@ -2036,10 +2306,65 @@ dcopuop:
                        rv.d = ieee754dp_fint(fs.bits);
                        rfmt = d_fmt;
                        goto copcsr;
-               default:
-                       return SIGILL;
+               default: {
+                       /* Emulating the new CMP.condn.fmt R6 instruction */
+#define CMPOP_MASK     0x7
+#define SIGN_BIT       (0x1 << 3)
+#define PREDICATE_BIT  (0x1 << 4)
+
+                       int cmpop = MIPSInst_FUNC(ir) & CMPOP_MASK;
+                       int sig = MIPSInst_FUNC(ir) & SIGN_BIT;
+                       union ieee754sp fs, ft;
+
+                       /* This is an R6 only instruction */
+                       if (!cpu_has_mips_r6 ||
+                           (MIPSInst_FUNC(ir) & 0x20))
+                               return SIGILL;
+
+                       /* fmt is w_fmt for single precision so fix it */
+                       rfmt = s_fmt;
+                       /* default to false */
+                       rv.w = 0;
+
+                       /* CMP.condn.S */
+                       SPFROMREG(fs, MIPSInst_FS(ir));
+                       SPFROMREG(ft, MIPSInst_FT(ir));
+
+                       /* positive predicates */
+                       if (!(MIPSInst_FUNC(ir) & PREDICATE_BIT)) {
+                               if (ieee754sp_cmp(fs, ft, cmptab[cmpop],
+                                                 sig))
+                                   rv.w = -1; /* true, all 1s */
+                               if ((sig) &&
+                                   ieee754_cxtest(IEEE754_INVALID_OPERATION))
+                                       rcsr = FPU_CSR_INV_X | FPU_CSR_INV_S;
+                               else
+                                       goto copcsr;
+                       } else {
+                               /* negative predicates */
+                               switch (cmpop) {
+                               case 1:
+                               case 2:
+                               case 3:
+                                       if (ieee754sp_cmp(fs, ft,
+                                                         negative_cmptab[cmpop],
+                                                         sig))
+                                               rv.w = -1; /* true, all 1s */
+                                       if (sig &&
+                                           ieee754_cxtest(IEEE754_INVALID_OPERATION))
+                                               rcsr = FPU_CSR_INV_X | FPU_CSR_INV_S;
+                                       else
+                                               goto copcsr;
+                                       break;
+                               default:
+                                       /* Reserved R6 ops */
+                                       pr_err("Reserved MIPS R6 CMP.condn.S operation\n");
+                                       return SIGILL;
+                               }
+                       }
+                       break;
+                       }
                }
-               break;
        }
 
        case l_fmt:
@@ -2060,11 +2385,60 @@ dcopuop:
                        rv.d = ieee754dp_flong(bits);
                        rfmt = d_fmt;
                        goto copcsr;
-               default:
-                       return SIGILL;
-               }
-               break;
+               default: {
+                       /* Emulating the new CMP.condn.fmt R6 instruction */
+                       int cmpop = MIPSInst_FUNC(ir) & CMPOP_MASK;
+                       int sig = MIPSInst_FUNC(ir) & SIGN_BIT;
+                       union ieee754dp fs, ft;
+
+                       if (!cpu_has_mips_r6 ||
+                           (MIPSInst_FUNC(ir) & 0x20))
+                               return SIGILL;
+
+                       /* fmt is l_fmt for double precision so fix it */
+                       rfmt = d_fmt;
+                       /* default to false */
+                       rv.l = 0;
 
+                       /* CMP.condn.D */
+                       DPFROMREG(fs, MIPSInst_FS(ir));
+                       DPFROMREG(ft, MIPSInst_FT(ir));
+
+                       /* positive predicates */
+                       if (!(MIPSInst_FUNC(ir) & PREDICATE_BIT)) {
+                               if (ieee754dp_cmp(fs, ft,
+                                                 cmptab[cmpop], sig))
+                                   rv.l = -1LL; /* true, all 1s */
+                               if (sig &&
+                                   ieee754_cxtest(IEEE754_INVALID_OPERATION))
+                                       rcsr = FPU_CSR_INV_X | FPU_CSR_INV_S;
+                               else
+                                       goto copcsr;
+                       } else {
+                               /* negative predicates */
+                               switch (cmpop) {
+                               case 1:
+                               case 2:
+                               case 3:
+                                       if (ieee754dp_cmp(fs, ft,
+                                                         negative_cmptab[cmpop],
+                                                         sig))
+                                               rv.l = -1LL; /* true, all 1s */
+                                       if (sig &&
+                                           ieee754_cxtest(IEEE754_INVALID_OPERATION))
+                                               rcsr = FPU_CSR_INV_X | FPU_CSR_INV_S;
+                                       else
+                                               goto copcsr;
+                                       break;
+                               default:
+                                       /* Reserved R6 ops */
+                                       pr_err("Reserved MIPS R6 CMP.condn.D operation\n");
+                                       return SIGILL;
+                               }
+                       }
+                       break;
+                       }
+               }
        default:
                return SIGILL;
        }
diff --git a/arch/mips/math-emu/dp_2008class.c b/arch/mips/math-emu/dp_2008class.c
new file mode 100644 (file)
index 0000000..9dc39fc
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * IEEE754 floating point arithmetic
+ * double precision: CLASS.f
+ * FPR[fd] = class(FPR[fs])
+ *
+ * MIPS floating point support
+ * Copyright (C) 2015 Imagination Technologies, Ltd.
+ * Author: Markos Chandras <markos.chandras@imgtec.com>
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License as published by the
+ *  Free Software Foundation; version 2 of the License.
+ */
+
+#include "ieee754dp.h"
+
+int ieee754dp_2008class(union ieee754dp x)
+{
+       COMPXDP;
+
+       EXPLODEXDP;
+
+       /*
+        * 10 bit mask as follows:
+        *
+        * bit0 = SNAN
+        * bit1 = QNAN
+        * bit2 = -INF
+        * bit3 = -NORM
+        * bit4 = -DNORM
+        * bit5 = -ZERO
+        * bit6 = INF
+        * bit7 = NORM
+        * bit8 = DNORM
+        * bit9 = ZERO
+        */
+
+       switch(xc) {
+       case IEEE754_CLASS_SNAN:
+               return 0x01;
+       case IEEE754_CLASS_QNAN:
+               return 0x02;
+       case IEEE754_CLASS_INF:
+               return 0x04 << (xs ? 0 : 4);
+       case IEEE754_CLASS_NORM:
+               return 0x08 << (xs ? 0 : 4);
+       case IEEE754_CLASS_DNORM:
+               return 0x10 << (xs ? 0 : 4);
+       case IEEE754_CLASS_ZERO:
+               return 0x20 << (xs ? 0 : 4);
+       default:
+               pr_err("Unknown class: %d\n", xc);
+               return 0;
+       }
+}
diff --git a/arch/mips/math-emu/dp_fmax.c b/arch/mips/math-emu/dp_fmax.c
new file mode 100644 (file)
index 0000000..fd71b8d
--- /dev/null
@@ -0,0 +1,213 @@
+/*
+ * IEEE754 floating point arithmetic
+ * double precision: MIN{,A}.f
+ * MIN : Scalar Floating-Point Minimum
+ * MINA: Scalar Floating-Point argument with Minimum Absolute Value
+ *
+ * MIN.D : FPR[fd] = minNum(FPR[fs],FPR[ft])
+ * MINA.D: FPR[fd] = maxNumMag(FPR[fs],FPR[ft])
+ *
+ * MIPS floating point support
+ * Copyright (C) 2015 Imagination Technologies, Ltd.
+ * Author: Markos Chandras <markos.chandras@imgtec.com>
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License as published by the
+ *  Free Software Foundation; version 2 of the License.
+ */
+
+#include "ieee754dp.h"
+
+union ieee754dp ieee754dp_fmax(union ieee754dp x, union ieee754dp y)
+{
+       COMPXDP;
+       COMPYDP;
+
+       EXPLODEXDP;
+       EXPLODEYDP;
+
+       FLUSHXDP;
+       FLUSHYDP;
+
+       ieee754_clearcx();
+
+       switch (CLPAIR(xc, yc)) {
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+               return ieee754dp_nanxcpt(y);
+
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
+               return ieee754dp_nanxcpt(x);
+
+       /* numbers are preferred to NaNs */
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
+               return x;
+
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
+               return y;
+
+       /*
+        * Infinity and zero handling
+        */
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
+               return xs ? y : x;
+
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
+               return ys ? x : y;
+
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
+               if (xs == ys)
+                       return x;
+               return ieee754dp_zero(1);
+
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
+               DPDNORMX;
+
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
+               DPDNORMY;
+               break;
+
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
+               DPDNORMX;
+       }
+
+       /* Finally get to do some computation */
+
+       assert(xm & DP_HIDDEN_BIT);
+       assert(ym & DP_HIDDEN_BIT);
+
+       /* Compare signs */
+       if (xs > ys)
+               return y;
+       else if (xs < ys)
+               return x;
+
+       /* Compare exponent */
+       if (xe > ye)
+               return x;
+       else if (xe < ye)
+               return y;
+
+       /* Compare mantissa */
+       if (xm <= ym)
+               return y;
+       return x;
+}
+
+union ieee754dp ieee754dp_fmaxa(union ieee754dp x, union ieee754dp y)
+{
+       COMPXDP;
+       COMPYDP;
+
+       EXPLODEXDP;
+       EXPLODEYDP;
+
+       FLUSHXDP;
+       FLUSHYDP;
+
+       ieee754_clearcx();
+
+       switch (CLPAIR(xc, yc)) {
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+               return ieee754dp_nanxcpt(y);
+
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
+               return ieee754dp_nanxcpt(x);
+
+       /* numbers are preferred to NaNs */
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
+               return x;
+
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
+               return y;
+
+       /*
+        * Infinity and zero handling
+        */
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
+               return x;
+
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
+               return y;
+
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
+               if (xs == ys)
+                       return x;
+               return ieee754dp_zero(1);
+
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
+               DPDNORMX;
+
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
+               DPDNORMY;
+               break;
+
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
+               DPDNORMX;
+       }
+
+       /* Finally get to do some computation */
+
+       assert(xm & DP_HIDDEN_BIT);
+       assert(ym & DP_HIDDEN_BIT);
+
+       /* Compare exponent */
+       if (xe > ye)
+               return x;
+       else if (xe < ye)
+               return y;
+
+       /* Compare mantissa */
+       if (xm <= ym)
+               return y;
+       return x;
+}
diff --git a/arch/mips/math-emu/dp_fmin.c b/arch/mips/math-emu/dp_fmin.c
new file mode 100644 (file)
index 0000000..c1072b0
--- /dev/null
@@ -0,0 +1,213 @@
+/*
+ * IEEE754 floating point arithmetic
+ * double precision: MIN{,A}.f
+ * MIN : Scalar Floating-Point Minimum
+ * MINA: Scalar Floating-Point argument with Minimum Absolute Value
+ *
+ * MIN.D : FPR[fd] = minNum(FPR[fs],FPR[ft])
+ * MINA.D: FPR[fd] = maxNumMag(FPR[fs],FPR[ft])
+ *
+ * MIPS floating point support
+ * Copyright (C) 2015 Imagination Technologies, Ltd.
+ * Author: Markos Chandras <markos.chandras@imgtec.com>
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License as published by the
+ *  Free Software Foundation; version 2 of the License.
+ */
+
+#include "ieee754dp.h"
+
+union ieee754dp ieee754dp_fmin(union ieee754dp x, union ieee754dp y)
+{
+       COMPXDP;
+       COMPYDP;
+
+       EXPLODEXDP;
+       EXPLODEYDP;
+
+       FLUSHXDP;
+       FLUSHYDP;
+
+       ieee754_clearcx();
+
+       switch (CLPAIR(xc, yc)) {
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+               return ieee754dp_nanxcpt(y);
+
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
+               return ieee754dp_nanxcpt(x);
+
+       /* numbers are preferred to NaNs */
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
+               return x;
+
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
+               return y;
+
+       /*
+        * Infinity and zero handling
+        */
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
+               return xs ? x : y;
+
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
+               return ys ? y : x;
+
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
+               if (xs == ys)
+                       return x;
+               return ieee754dp_zero(1);
+
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
+               DPDNORMX;
+
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
+               DPDNORMY;
+               break;
+
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
+               DPDNORMX;
+       }
+
+       /* Finally get to do some computation */
+
+       assert(xm & DP_HIDDEN_BIT);
+       assert(ym & DP_HIDDEN_BIT);
+
+       /* Compare signs */
+       if (xs > ys)
+               return x;
+       else if (xs < ys)
+               return y;
+
+       /* Compare exponent */
+       if (xe > ye)
+               return y;
+       else if (xe < ye)
+               return x;
+
+       /* Compare mantissa */
+       if (xm <= ym)
+               return x;
+       return y;
+}
+
+union ieee754dp ieee754dp_fmina(union ieee754dp x, union ieee754dp y)
+{
+       COMPXDP;
+       COMPYDP;
+
+       EXPLODEXDP;
+       EXPLODEYDP;
+
+       FLUSHXDP;
+       FLUSHYDP;
+
+       ieee754_clearcx();
+
+       switch (CLPAIR(xc, yc)) {
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+               return ieee754dp_nanxcpt(y);
+
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
+               return ieee754dp_nanxcpt(x);
+
+       /* numbers are preferred to NaNs */
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
+               return x;
+
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
+               return y;
+
+       /*
+        * Infinity and zero handling
+        */
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
+               return x;
+
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
+               return y;
+
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
+               if (xs == ys)
+                       return x;
+               return ieee754dp_zero(1);
+
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
+               DPDNORMX;
+
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
+               DPDNORMY;
+               break;
+
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
+               DPDNORMX;
+       }
+
+       /* Finally get to do some computation */
+
+       assert(xm & DP_HIDDEN_BIT);
+       assert(ym & DP_HIDDEN_BIT);
+
+       /* Compare exponent */
+       if (xe > ye)
+               return y;
+       else if (xe < ye)
+               return x;
+
+       /* Compare mantissa */
+       if (xm <= ym)
+               return x;
+       return y;
+}
diff --git a/arch/mips/math-emu/dp_maddf.c b/arch/mips/math-emu/dp_maddf.c
new file mode 100644 (file)
index 0000000..119eda9
--- /dev/null
@@ -0,0 +1,265 @@
+/*
+ * IEEE754 floating point arithmetic
+ * double precision: MADDF.f (Fused Multiply Add)
+ * MADDF.fmt: FPR[fd] = FPR[fd] + (FPR[fs] x FPR[ft])
+ *
+ * MIPS floating point support
+ * Copyright (C) 2015 Imagination Technologies, Ltd.
+ * Author: Markos Chandras <markos.chandras@imgtec.com>
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License as published by the
+ *  Free Software Foundation; version 2 of the License.
+ */
+
+#include "ieee754dp.h"
+
+union ieee754dp ieee754dp_maddf(union ieee754dp z, union ieee754dp x,
+                               union ieee754dp y)
+{
+       int re;
+       int rs;
+       u64 rm;
+       unsigned lxm;
+       unsigned hxm;
+       unsigned lym;
+       unsigned hym;
+       u64 lrm;
+       u64 hrm;
+       u64 t;
+       u64 at;
+       int s;
+
+       COMPXDP;
+       COMPYDP;
+
+       u64 zm; int ze; int zs __maybe_unused; int zc;
+
+       EXPLODEXDP;
+       EXPLODEYDP;
+       EXPLODEDP(z, zc, zs, ze, zm)
+
+       FLUSHXDP;
+       FLUSHYDP;
+       FLUSHDP(z, zc, zs, ze, zm);
+
+       ieee754_clearcx();
+
+       switch (zc) {
+       case IEEE754_CLASS_SNAN:
+               ieee754_setcx(IEEE754_INVALID_OPERATION);
+               return ieee754dp_nanxcpt(z);
+       case IEEE754_CLASS_DNORM:
+               DPDNORMx(zm, ze);
+       /* QNAN is handled separately below */
+       }
+
+       switch (CLPAIR(xc, yc)) {
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+               return ieee754dp_nanxcpt(y);
+
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
+               return ieee754dp_nanxcpt(x);
+
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
+               return y;
+
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
+               return x;
+
+
+       /*
+        * Infinity handling
+        */
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
+               if (zc == IEEE754_CLASS_QNAN)
+                       return z;
+               ieee754_setcx(IEEE754_INVALID_OPERATION);
+               return ieee754dp_indef();
+
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
+               if (zc == IEEE754_CLASS_QNAN)
+                       return z;
+               return ieee754dp_inf(xs ^ ys);
+
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
+               if (zc == IEEE754_CLASS_INF)
+                       return ieee754dp_inf(zs);
+               /* Multiplication is 0 so just return z */
+               return z;
+
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
+               DPDNORMX;
+
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
+               if (zc == IEEE754_CLASS_QNAN)
+                       return z;
+               else if (zc == IEEE754_CLASS_INF)
+                       return ieee754dp_inf(zs);
+               DPDNORMY;
+               break;
+
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
+               if (zc == IEEE754_CLASS_QNAN)
+                       return z;
+               else if (zc == IEEE754_CLASS_INF)
+                       return ieee754dp_inf(zs);
+               DPDNORMX;
+               break;
+
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
+               if (zc == IEEE754_CLASS_QNAN)
+                       return z;
+               else if (zc == IEEE754_CLASS_INF)
+                       return ieee754dp_inf(zs);
+               /* fall through to real computations */
+       }
+
+       /* Finally get to do some computation */
+
+       /*
+        * Do the multiplication bit first
+        *
+        * rm = xm * ym, re = xe + ye basically
+        *
+        * At this point xm and ym should have been normalized.
+        */
+       assert(xm & DP_HIDDEN_BIT);
+       assert(ym & DP_HIDDEN_BIT);
+
+       re = xe + ye;
+       rs = xs ^ ys;
+
+       /* shunt to top of word */
+       xm <<= 64 - (DP_FBITS + 1);
+       ym <<= 64 - (DP_FBITS + 1);
+
+       /*
+        * Multiply 32 bits xm, ym to give high 32 bits rm with stickness.
+        */
+
+       /* 32 * 32 => 64 */
+#define DPXMULT(x, y)  ((u64)(x) * (u64)y)
+
+       lxm = xm;
+       hxm = xm >> 32;
+       lym = ym;
+       hym = ym >> 32;
+
+       lrm = DPXMULT(lxm, lym);
+       hrm = DPXMULT(hxm, hym);
+
+       t = DPXMULT(lxm, hym);
+
+       at = lrm + (t << 32);
+       hrm += at < lrm;
+       lrm = at;
+
+       hrm = hrm + (t >> 32);
+
+       t = DPXMULT(hxm, lym);
+
+       at = lrm + (t << 32);
+       hrm += at < lrm;
+       lrm = at;
+
+       hrm = hrm + (t >> 32);
+
+       rm = hrm | (lrm != 0);
+
+       /*
+        * Sticky shift down to normal rounding precision.
+        */
+       if ((s64) rm < 0) {
+               rm = (rm >> (64 - (DP_FBITS + 1 + 3))) |
+                    ((rm << (DP_FBITS + 1 + 3)) != 0);
+                       re++;
+       } else {
+               rm = (rm >> (64 - (DP_FBITS + 1 + 3 + 1))) |
+                    ((rm << (DP_FBITS + 1 + 3 + 1)) != 0);
+       }
+       assert(rm & (DP_HIDDEN_BIT << 3));
+
+       /* And now the addition */
+       assert(zm & DP_HIDDEN_BIT);
+
+       /*
+        * Provide guard,round and stick bit space.
+        */
+       zm <<= 3;
+
+       if (ze > re) {
+               /*
+                * Have to shift y fraction right to align.
+                */
+               s = ze - re;
+               rm = XDPSRS(rm, s);
+               re += s;
+       } else if (re > ze) {
+               /*
+                * Have to shift x fraction right to align.
+                */
+               s = re - ze;
+               zm = XDPSRS(zm, s);
+               ze += s;
+       }
+       assert(ze == re);
+       assert(ze <= DP_EMAX);
+
+       if (zs == rs) {
+               /*
+                * Generate 28 bit result of adding two 27 bit numbers
+                * leaving result in xm, xs and xe.
+                */
+               zm = zm + rm;
+
+               if (zm >> (DP_FBITS + 1 + 3)) { /* carry out */
+                       zm = XDPSRS1(zm);
+                       ze++;
+               }
+       } else {
+               if (zm >= rm) {
+                       zm = zm - rm;
+               } else {
+                       zm = rm - zm;
+                       zs = rs;
+               }
+               if (zm == 0)
+                       return ieee754dp_zero(ieee754_csr.rm == FPU_CSR_RD);
+
+               /*
+                * Normalize to rounding precision.
+                */
+               while ((zm >> (DP_FBITS + 3)) == 0) {
+                       zm <<= 1;
+                       ze--;
+               }
+       }
+
+       return ieee754dp_format(zs, ze, zm);
+}
diff --git a/arch/mips/math-emu/dp_msubf.c b/arch/mips/math-emu/dp_msubf.c
new file mode 100644 (file)
index 0000000..1224126
--- /dev/null
@@ -0,0 +1,269 @@
+/*
+ * IEEE754 floating point arithmetic
+ * double precision: MSUB.f (Fused Multiply Subtract)
+ * MSUBF.fmt: FPR[fd] = FPR[fd] - (FPR[fs] x FPR[ft])
+ *
+ * MIPS floating point support
+ * Copyright (C) 2015 Imagination Technologies, Ltd.
+ * Author: Markos Chandras <markos.chandras@imgtec.com>
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License as published by the
+ *  Free Software Foundation; version 2 of the License.
+ */
+
+#include "ieee754dp.h"
+
+union ieee754dp ieee754dp_msubf(union ieee754dp z, union ieee754dp x,
+                               union ieee754dp y)
+{
+       int re;
+       int rs;
+       u64 rm;
+       unsigned lxm;
+       unsigned hxm;
+       unsigned lym;
+       unsigned hym;
+       u64 lrm;
+       u64 hrm;
+       u64 t;
+       u64 at;
+       int s;
+
+       COMPXDP;
+       COMPYDP;
+
+       u64 zm; int ze; int zs __maybe_unused; int zc;
+
+       EXPLODEXDP;
+       EXPLODEYDP;
+       EXPLODEDP(z, zc, zs, ze, zm)
+
+       FLUSHXDP;
+       FLUSHYDP;
+       FLUSHDP(z, zc, zs, ze, zm);
+
+       ieee754_clearcx();
+
+       switch (zc) {
+       case IEEE754_CLASS_SNAN:
+               ieee754_setcx(IEEE754_INVALID_OPERATION);
+               return ieee754dp_nanxcpt(z);
+       case IEEE754_CLASS_DNORM:
+               DPDNORMx(zm, ze);
+       /* QNAN is handled separately below */
+       }
+
+       switch (CLPAIR(xc, yc)) {
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+               return ieee754dp_nanxcpt(y);
+
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
+               return ieee754dp_nanxcpt(x);
+
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
+               return y;
+
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
+               return x;
+
+
+       /*
+        * Infinity handling
+        */
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
+               if (zc == IEEE754_CLASS_QNAN)
+                       return z;
+               ieee754_setcx(IEEE754_INVALID_OPERATION);
+               return ieee754dp_indef();
+
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
+               if (zc == IEEE754_CLASS_QNAN)
+                       return z;
+               return ieee754dp_inf(xs ^ ys);
+
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
+               if (zc == IEEE754_CLASS_INF)
+                       return ieee754dp_inf(zs);
+               /* Multiplication is 0 so just return z */
+               return z;
+
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
+               DPDNORMX;
+
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
+               if (zc == IEEE754_CLASS_QNAN)
+                       return z;
+               else if (zc == IEEE754_CLASS_INF)
+                       return ieee754dp_inf(zs);
+               DPDNORMY;
+               break;
+
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
+               if (zc == IEEE754_CLASS_QNAN)
+                       return z;
+               else if (zc == IEEE754_CLASS_INF)
+                       return ieee754dp_inf(zs);
+               DPDNORMX;
+               break;
+
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
+               if (zc == IEEE754_CLASS_QNAN)
+                       return z;
+               else if (zc == IEEE754_CLASS_INF)
+                       return ieee754dp_inf(zs);
+               /* fall through to real computations */
+       }
+
+       /* Finally get to do some computation */
+
+       /*
+        * Do the multiplication bit first
+        *
+        * rm = xm * ym, re = xe + ye basically
+        *
+        * At this point xm and ym should have been normalized.
+        */
+       assert(xm & DP_HIDDEN_BIT);
+       assert(ym & DP_HIDDEN_BIT);
+
+       re = xe + ye;
+       rs = xs ^ ys;
+
+       /* shunt to top of word */
+       xm <<= 64 - (DP_FBITS + 1);
+       ym <<= 64 - (DP_FBITS + 1);
+
+       /*
+        * Multiply 32 bits xm, ym to give high 32 bits rm with stickness.
+        */
+
+       /* 32 * 32 => 64 */
+#define DPXMULT(x, y)  ((u64)(x) * (u64)y)
+
+       lxm = xm;
+       hxm = xm >> 32;
+       lym = ym;
+       hym = ym >> 32;
+
+       lrm = DPXMULT(lxm, lym);
+       hrm = DPXMULT(hxm, hym);
+
+       t = DPXMULT(lxm, hym);
+
+       at = lrm + (t << 32);
+       hrm += at < lrm;
+       lrm = at;
+
+       hrm = hrm + (t >> 32);
+
+       t = DPXMULT(hxm, lym);
+
+       at = lrm + (t << 32);
+       hrm += at < lrm;
+       lrm = at;
+
+       hrm = hrm + (t >> 32);
+
+       rm = hrm | (lrm != 0);
+
+       /*
+        * Sticky shift down to normal rounding precision.
+        */
+       if ((s64) rm < 0) {
+               rm = (rm >> (64 - (DP_FBITS + 1 + 3))) |
+                    ((rm << (DP_FBITS + 1 + 3)) != 0);
+                       re++;
+       } else {
+               rm = (rm >> (64 - (DP_FBITS + 1 + 3 + 1))) |
+                    ((rm << (DP_FBITS + 1 + 3 + 1)) != 0);
+       }
+       assert(rm & (DP_HIDDEN_BIT << 3));
+
+       /* And now the subtraction */
+
+       /* flip sign of r and handle as add */
+       rs ^= 1;
+
+       assert(zm & DP_HIDDEN_BIT);
+
+       /*
+        * Provide guard,round and stick bit space.
+        */
+       zm <<= 3;
+
+       if (ze > re) {
+               /*
+                * Have to shift y fraction right to align.
+                */
+               s = ze - re;
+               rm = XDPSRS(rm, s);
+               re += s;
+       } else if (re > ze) {
+               /*
+                * Have to shift x fraction right to align.
+                */
+               s = re - ze;
+               zm = XDPSRS(zm, s);
+               ze += s;
+       }
+       assert(ze == re);
+       assert(ze <= DP_EMAX);
+
+       if (zs == rs) {
+               /*
+                * Generate 28 bit result of adding two 27 bit numbers
+                * leaving result in xm, xs and xe.
+                */
+               zm = zm + rm;
+
+               if (zm >> (DP_FBITS + 1 + 3)) { /* carry out */
+                       zm = XDPSRS1(zm);
+                       ze++;
+               }
+       } else {
+               if (zm >= rm) {
+                       zm = zm - rm;
+               } else {
+                       zm = rm - zm;
+                       zs = rs;
+               }
+               if (zm == 0)
+                       return ieee754dp_zero(ieee754_csr.rm == FPU_CSR_RD);
+
+               /*
+                * Normalize to rounding precision.
+                */
+               while ((zm >> (DP_FBITS + 3)) == 0) {
+                       zm <<= 1;
+                       ze--;
+               }
+       }
+
+       return ieee754dp_format(zs, ze, zm);
+}
index e0b5cc27d78b0dd906ec1248b670346116219b37..cbb36c14b155ad07dae2250550bc4090622180cd 100644 (file)
@@ -33,7 +33,6 @@ struct emuframe {
 
 int mips_dsemul(struct pt_regs *regs, mips_instruction ir, unsigned long cpc)
 {
-       extern asmlinkage void handle_dsemulret(void);
        struct emuframe __user *fr;
        int err;
 
index a5ca108ce4679aba5cd003a25542fc6705c08cb3..df94720714c73cc95736544f7b05804d607d27ca 100644 (file)
@@ -75,6 +75,16 @@ int ieee754sp_cmp(union ieee754sp x, union ieee754sp y, int cop, int sig);
 
 union ieee754sp ieee754sp_sqrt(union ieee754sp x);
 
+union ieee754sp ieee754sp_maddf(union ieee754sp z, union ieee754sp x,
+                               union ieee754sp y);
+union ieee754sp ieee754sp_msubf(union ieee754sp z, union ieee754sp x,
+                               union ieee754sp y);
+int ieee754sp_2008class(union ieee754sp x);
+union ieee754sp ieee754sp_fmin(union ieee754sp x, union ieee754sp y);
+union ieee754sp ieee754sp_fmina(union ieee754sp x, union ieee754sp y);
+union ieee754sp ieee754sp_fmax(union ieee754sp x, union ieee754sp y);
+union ieee754sp ieee754sp_fmaxa(union ieee754sp x, union ieee754sp y);
+
 /*
  * double precision (often aka double)
 */
@@ -99,6 +109,15 @@ int ieee754dp_cmp(union ieee754dp x, union ieee754dp y, int cop, int sig);
 
 union ieee754dp ieee754dp_sqrt(union ieee754dp x);
 
+union ieee754dp ieee754dp_maddf(union ieee754dp z, union ieee754dp x,
+                               union ieee754dp y);
+union ieee754dp ieee754dp_msubf(union ieee754dp z, union ieee754dp x,
+                               union ieee754dp y);
+int ieee754dp_2008class(union ieee754dp x);
+union ieee754dp ieee754dp_fmin(union ieee754dp x, union ieee754dp y);
+union ieee754dp ieee754dp_fmina(union ieee754dp x, union ieee754dp y);
+union ieee754dp ieee754dp_fmax(union ieee754dp x, union ieee754dp y);
+union ieee754dp ieee754dp_fmaxa(union ieee754dp x, union ieee754dp y);
 
 
 /* 5 types of floating point number
index 05389d5e3a933d7dbee1e728adb0b40b1f795599..6383e2c5c1adb5d527fe1023eb173f06e3776dc7 100644 (file)
@@ -65,8 +65,8 @@ static inline int ieee754_class_nan(int xc)
                        vc = IEEE754_CLASS_INF;                         \
                else if (vm & SP_MBIT(SP_FBITS-1))                      \
                        vc = IEEE754_CLASS_SNAN;                        \
-       else                                                            \
-               vc = IEEE754_CLASS_QNAN;                                \
+               else                                                    \
+                       vc = IEEE754_CLASS_QNAN;                        \
        } else if (ve == SP_EMIN-1+SP_EBIAS) {                          \
                if (vm) {                                               \
                        ve = SP_EMIN;                                   \
@@ -105,8 +105,8 @@ static inline int ieee754_class_nan(int xc)
                if (vm) {                                               \
                        ve = DP_EMIN;                                   \
                        vc = IEEE754_CLASS_DNORM;                       \
-       } else                                                          \
-               vc = IEEE754_CLASS_ZERO;                                \
+               } else                                                  \
+                       vc = IEEE754_CLASS_ZERO;                        \
        } else {                                                        \
                ve -= DP_EBIAS;                                         \
                vm |= DP_HIDDEN_BIT;                                    \
index f308e0f05fc5856e74524804d275bb298ac2d6a5..506a67a98cdf5cadf12420c17bb89ef4d4af41d9 100644 (file)
@@ -65,4 +65,4 @@ do {                                                                  \
 
        return 0;
 }
-__initcall(debugfs_fpuemu);
+arch_initcall(debugfs_fpuemu);
diff --git a/arch/mips/math-emu/sp_2008class.c b/arch/mips/math-emu/sp_2008class.c
new file mode 100644 (file)
index 0000000..ff62606
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * IEEE754 floating point arithmetic
+ * single precision: CLASS.f
+ * FPR[fd] = class(FPR[fs])
+ *
+ * MIPS floating point support
+ * Copyright (C) 2015 Imagination Technologies, Ltd.
+ * Author: Markos Chandras <markos.chandras@imgtec.com>
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License as published by the
+ *  Free Software Foundation; version 2 of the License.
+ */
+
+#include "ieee754sp.h"
+
+int ieee754sp_2008class(union ieee754sp x)
+{
+       COMPXSP;
+
+       EXPLODEXSP;
+
+       /*
+        * 10 bit mask as follows:
+        *
+        * bit0 = SNAN
+        * bit1 = QNAN
+        * bit2 = -INF
+        * bit3 = -NORM
+        * bit4 = -DNORM
+        * bit5 = -ZERO
+        * bit6 = INF
+        * bit7 = NORM
+        * bit8 = DNORM
+        * bit9 = ZERO
+        */
+
+       switch(xc) {
+       case IEEE754_CLASS_SNAN:
+               return 0x01;
+       case IEEE754_CLASS_QNAN:
+               return 0x02;
+       case IEEE754_CLASS_INF:
+               return 0x04 << (xs ? 0 : 4);
+       case IEEE754_CLASS_NORM:
+               return 0x08 << (xs ? 0 : 4);
+       case IEEE754_CLASS_DNORM:
+               return 0x10 << (xs ? 0 : 4);
+       case IEEE754_CLASS_ZERO:
+               return 0x20 << (xs ? 0 : 4);
+       default:
+               pr_err("Unknown class: %d\n", xc);
+               return 0;
+       }
+}
diff --git a/arch/mips/math-emu/sp_fmax.c b/arch/mips/math-emu/sp_fmax.c
new file mode 100644 (file)
index 0000000..4d00084
--- /dev/null
@@ -0,0 +1,213 @@
+/*
+ * IEEE754 floating point arithmetic
+ * single precision: MAX{,A}.f
+ * MAX : Scalar Floating-Point Maximum
+ * MAXA: Scalar Floating-Point argument with Maximum Absolute Value
+ *
+ * MAX.S : FPR[fd] = maxNum(FPR[fs],FPR[ft])
+ * MAXA.S: FPR[fd] = maxNumMag(FPR[fs],FPR[ft])
+ *
+ * MIPS floating point support
+ * Copyright (C) 2015 Imagination Technologies, Ltd.
+ * Author: Markos Chandras <markos.chandras@imgtec.com>
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License as published by the
+ *  Free Software Foundation; version 2 of the License.
+ */
+
+#include "ieee754sp.h"
+
+union ieee754sp ieee754sp_fmax(union ieee754sp x, union ieee754sp y)
+{
+       COMPXSP;
+       COMPYSP;
+
+       EXPLODEXSP;
+       EXPLODEYSP;
+
+       FLUSHXSP;
+       FLUSHYSP;
+
+       ieee754_clearcx();
+
+       switch (CLPAIR(xc, yc)) {
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+               return ieee754sp_nanxcpt(y);
+
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
+               return ieee754sp_nanxcpt(x);
+
+       /* numbers are preferred to NaNs */
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
+               return x;
+
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
+               return y;
+
+       /*
+        * Infinity and zero handling
+        */
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
+               return xs ? y : x;
+
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
+               return ys ? x : y;
+
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
+               if (xs == ys)
+                       return x;
+               return ieee754sp_zero(1);
+
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
+               SPDNORMX;
+
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
+               SPDNORMY;
+               break;
+
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
+               SPDNORMX;
+       }
+
+       /* Finally get to do some computation */
+
+       assert(xm & SP_HIDDEN_BIT);
+       assert(ym & SP_HIDDEN_BIT);
+
+       /* Compare signs */
+       if (xs > ys)
+               return y;
+       else if (xs < ys)
+               return x;
+
+       /* Compare exponent */
+       if (xe > ye)
+               return x;
+       else if (xe < ye)
+               return y;
+
+       /* Compare mantissa */
+       if (xm <= ym)
+               return y;
+       return x;
+}
+
+union ieee754sp ieee754sp_fmaxa(union ieee754sp x, union ieee754sp y)
+{
+       COMPXSP;
+       COMPYSP;
+
+       EXPLODEXSP;
+       EXPLODEYSP;
+
+       FLUSHXSP;
+       FLUSHYSP;
+
+       ieee754_clearcx();
+
+       switch (CLPAIR(xc, yc)) {
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+               return ieee754sp_nanxcpt(y);
+
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
+               return ieee754sp_nanxcpt(x);
+
+       /* numbers are preferred to NaNs */
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
+               return x;
+
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
+               return y;
+
+       /*
+        * Infinity and zero handling
+        */
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
+               return x;
+
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
+               return y;
+
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
+               if (xs == ys)
+                       return x;
+               return ieee754sp_zero(1);
+
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
+               SPDNORMX;
+
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
+               SPDNORMY;
+               break;
+
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
+               SPDNORMX;
+       }
+
+       /* Finally get to do some computation */
+
+       assert(xm & SP_HIDDEN_BIT);
+       assert(ym & SP_HIDDEN_BIT);
+
+       /* Compare exponent */
+       if (xe > ye)
+               return x;
+       else if (xe < ye)
+               return y;
+
+       /* Compare mantissa */
+       if (xm <= ym)
+               return y;
+       return x;
+}
diff --git a/arch/mips/math-emu/sp_fmin.c b/arch/mips/math-emu/sp_fmin.c
new file mode 100644 (file)
index 0000000..4eb1bb9
--- /dev/null
@@ -0,0 +1,213 @@
+/*
+ * IEEE754 floating point arithmetic
+ * single precision: MIN{,A}.f
+ * MIN : Scalar Floating-Point Minimum
+ * MINA: Scalar Floating-Point argument with Minimum Absolute Value
+ *
+ * MIN.S : FPR[fd] = minNum(FPR[fs],FPR[ft])
+ * MINA.S: FPR[fd] = maxNumMag(FPR[fs],FPR[ft])
+ *
+ * MIPS floating point support
+ * Copyright (C) 2015 Imagination Technologies, Ltd.
+ * Author: Markos Chandras <markos.chandras@imgtec.com>
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License as published by the
+ *  Free Software Foundation; version 2 of the License.
+ */
+
+#include "ieee754sp.h"
+
+union ieee754sp ieee754sp_fmin(union ieee754sp x, union ieee754sp y)
+{
+       COMPXSP;
+       COMPYSP;
+
+       EXPLODEXSP;
+       EXPLODEYSP;
+
+       FLUSHXSP;
+       FLUSHYSP;
+
+       ieee754_clearcx();
+
+       switch (CLPAIR(xc, yc)) {
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+               return ieee754sp_nanxcpt(y);
+
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
+               return ieee754sp_nanxcpt(x);
+
+       /* numbers are preferred to NaNs */
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
+               return x;
+
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
+               return y;
+
+       /*
+        * Infinity and zero handling
+        */
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
+               return xs ? x : y;
+
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
+               return ys ? y : x;
+
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
+               if (xs == ys)
+                       return x;
+               return ieee754sp_zero(1);
+
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
+               SPDNORMX;
+
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
+               SPDNORMY;
+               break;
+
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
+               SPDNORMX;
+       }
+
+       /* Finally get to do some computation */
+
+       assert(xm & SP_HIDDEN_BIT);
+       assert(ym & SP_HIDDEN_BIT);
+
+       /* Compare signs */
+       if (xs > ys)
+               return x;
+       else if (xs < ys)
+               return y;
+
+       /* Compare exponent */
+       if (xe > ye)
+               return y;
+       else if (xe < ye)
+               return x;
+
+       /* Compare mantissa */
+       if (xm <= ym)
+               return x;
+       return y;
+}
+
+union ieee754sp ieee754sp_fmina(union ieee754sp x, union ieee754sp y)
+{
+       COMPXSP;
+       COMPYSP;
+
+       EXPLODEXSP;
+       EXPLODEYSP;
+
+       FLUSHXSP;
+       FLUSHYSP;
+
+       ieee754_clearcx();
+
+       switch (CLPAIR(xc, yc)) {
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+               return ieee754sp_nanxcpt(y);
+
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
+               return ieee754sp_nanxcpt(x);
+
+       /* numbers are preferred to NaNs */
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
+               return x;
+
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
+               return y;
+
+       /*
+        * Infinity and zero handling
+        */
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
+               return x;
+
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
+               return y;
+
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
+               if (xs == ys)
+                       return x;
+               return ieee754sp_zero(1);
+
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
+               SPDNORMX;
+
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
+               SPDNORMY;
+               break;
+
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
+               SPDNORMX;
+       }
+
+       /* Finally get to do some computation */
+
+       assert(xm & SP_HIDDEN_BIT);
+       assert(ym & SP_HIDDEN_BIT);
+
+       /* Compare exponent */
+       if (xe > ye)
+               return y;
+       else if (xe < ye)
+               return x;
+
+       /* Compare mantissa */
+       if (xm <= ym)
+               return x;
+       return y;
+}
diff --git a/arch/mips/math-emu/sp_maddf.c b/arch/mips/math-emu/sp_maddf.c
new file mode 100644 (file)
index 0000000..dd1dd83
--- /dev/null
@@ -0,0 +1,255 @@
+/*
+ * IEEE754 floating point arithmetic
+ * single precision: MADDF.f (Fused Multiply Add)
+ * MADDF.fmt: FPR[fd] = FPR[fd] + (FPR[fs] x FPR[ft])
+ *
+ * MIPS floating point support
+ * Copyright (C) 2015 Imagination Technologies, Ltd.
+ * Author: Markos Chandras <markos.chandras@imgtec.com>
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License as published by the
+ *  Free Software Foundation; version 2 of the License.
+ */
+
+#include "ieee754sp.h"
+
+union ieee754sp ieee754sp_maddf(union ieee754sp z, union ieee754sp x,
+                               union ieee754sp y)
+{
+       int re;
+       int rs;
+       unsigned rm;
+       unsigned short lxm;
+       unsigned short hxm;
+       unsigned short lym;
+       unsigned short hym;
+       unsigned lrm;
+       unsigned hrm;
+       unsigned t;
+       unsigned at;
+       int s;
+
+       COMPXSP;
+       COMPYSP;
+       u32 zm; int ze; int zs __maybe_unused; int zc;
+
+       EXPLODEXSP;
+       EXPLODEYSP;
+       EXPLODESP(z, zc, zs, ze, zm)
+
+       FLUSHXSP;
+       FLUSHYSP;
+       FLUSHSP(z, zc, zs, ze, zm);
+
+       ieee754_clearcx();
+
+       switch (zc) {
+       case IEEE754_CLASS_SNAN:
+               ieee754_setcx(IEEE754_INVALID_OPERATION);
+               return ieee754sp_nanxcpt(z);
+       case IEEE754_CLASS_DNORM:
+               SPDNORMx(zm, ze);
+       /* QNAN is handled separately below */
+       }
+
+       switch (CLPAIR(xc, yc)) {
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+               return ieee754sp_nanxcpt(y);
+
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
+               return ieee754sp_nanxcpt(x);
+
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
+               return y;
+
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
+               return x;
+
+       /*
+        * Infinity handling
+        */
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
+               if (zc == IEEE754_CLASS_QNAN)
+                       return z;
+               ieee754_setcx(IEEE754_INVALID_OPERATION);
+               return ieee754sp_indef();
+
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
+               if (zc == IEEE754_CLASS_QNAN)
+                       return z;
+               return ieee754sp_inf(xs ^ ys);
+
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
+               if (zc == IEEE754_CLASS_INF)
+                       return ieee754sp_inf(zs);
+               /* Multiplication is 0 so just return z */
+               return z;
+
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
+               SPDNORMX;
+
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
+               if (zc == IEEE754_CLASS_QNAN)
+                       return z;
+               else if (zc == IEEE754_CLASS_INF)
+                       return ieee754sp_inf(zs);
+               SPDNORMY;
+               break;
+
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
+               if (zc == IEEE754_CLASS_QNAN)
+                       return z;
+               else if (zc == IEEE754_CLASS_INF)
+                       return ieee754sp_inf(zs);
+               SPDNORMX;
+               break;
+
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
+               if (zc == IEEE754_CLASS_QNAN)
+                       return z;
+               else if (zc == IEEE754_CLASS_INF)
+                       return ieee754sp_inf(zs);
+               /* fall through to real computations */
+       }
+
+       /* Finally get to do some computation */
+
+       /*
+        * Do the multiplication bit first
+        *
+        * rm = xm * ym, re = xe + ye basically
+        *
+        * At this point xm and ym should have been normalized.
+        */
+
+       /* rm = xm * ym, re = xe+ye basically */
+       assert(xm & SP_HIDDEN_BIT);
+       assert(ym & SP_HIDDEN_BIT);
+
+       re = xe + ye;
+       rs = xs ^ ys;
+
+       /* shunt to top of word */
+       xm <<= 32 - (SP_FBITS + 1);
+       ym <<= 32 - (SP_FBITS + 1);
+
+       /*
+        * Multiply 32 bits xm, ym to give high 32 bits rm with stickness.
+        */
+       lxm = xm & 0xffff;
+       hxm = xm >> 16;
+       lym = ym & 0xffff;
+       hym = ym >> 16;
+
+       lrm = lxm * lym;        /* 16 * 16 => 32 */
+       hrm = hxm * hym;        /* 16 * 16 => 32 */
+
+       t = lxm * hym; /* 16 * 16 => 32 */
+       at = lrm + (t << 16);
+       hrm += at < lrm;
+       lrm = at;
+       hrm = hrm + (t >> 16);
+
+       t = hxm * lym; /* 16 * 16 => 32 */
+       at = lrm + (t << 16);
+       hrm += at < lrm;
+       lrm = at;
+       hrm = hrm + (t >> 16);
+
+       rm = hrm | (lrm != 0);
+
+       /*
+        * Sticky shift down to normal rounding precision.
+        */
+       if ((int) rm < 0) {
+               rm = (rm >> (32 - (SP_FBITS + 1 + 3))) |
+                   ((rm << (SP_FBITS + 1 + 3)) != 0);
+               re++;
+       } else {
+               rm = (rm >> (32 - (SP_FBITS + 1 + 3 + 1))) |
+                    ((rm << (SP_FBITS + 1 + 3 + 1)) != 0);
+       }
+       assert(rm & (SP_HIDDEN_BIT << 3));
+
+       /* And now the addition */
+
+       assert(zm & SP_HIDDEN_BIT);
+
+       /*
+        * Provide guard,round and stick bit space.
+        */
+       zm <<= 3;
+
+       if (ze > re) {
+               /*
+                * Have to shift y fraction right to align.
+                */
+               s = ze - re;
+               SPXSRSYn(s);
+       } else if (re > ze) {
+               /*
+                * Have to shift x fraction right to align.
+                */
+               s = re - ze;
+               SPXSRSYn(s);
+       }
+       assert(ze == re);
+       assert(ze <= SP_EMAX);
+
+       if (zs == rs) {
+               /*
+                * Generate 28 bit result of adding two 27 bit numbers
+                * leaving result in zm, zs and ze.
+                */
+               zm = zm + rm;
+
+               if (zm >> (SP_FBITS + 1 + 3)) { /* carry out */
+                       SPXSRSX1();
+               }
+       } else {
+               if (zm >= rm) {
+                       zm = zm - rm;
+               } else {
+                       zm = rm - zm;
+                       zs = rs;
+               }
+               if (zm == 0)
+                       return ieee754sp_zero(ieee754_csr.rm == FPU_CSR_RD);
+
+               /*
+                * Normalize in extended single precision
+                */
+               while ((zm >> (SP_MBITS + 3)) == 0) {
+                       zm <<= 1;
+                       ze--;
+               }
+
+       }
+       return ieee754sp_format(zs, ze, zm);
+}
diff --git a/arch/mips/math-emu/sp_msubf.c b/arch/mips/math-emu/sp_msubf.c
new file mode 100644 (file)
index 0000000..81c38b9
--- /dev/null
@@ -0,0 +1,258 @@
+/*
+ * IEEE754 floating point arithmetic
+ * single precision: MSUB.f (Fused Multiply Subtract)
+ * MSUBF.fmt: FPR[fd] = FPR[fd] - (FPR[fs] x FPR[ft])
+ *
+ * MIPS floating point support
+ * Copyright (C) 2015 Imagination Technologies, Ltd.
+ * Author: Markos Chandras <markos.chandras@imgtec.com>
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License as published by the
+ *  Free Software Foundation; version 2 of the License.
+ */
+
+#include "ieee754sp.h"
+
+union ieee754sp ieee754sp_msubf(union ieee754sp z, union ieee754sp x,
+                               union ieee754sp y)
+{
+       int re;
+       int rs;
+       unsigned rm;
+       unsigned short lxm;
+       unsigned short hxm;
+       unsigned short lym;
+       unsigned short hym;
+       unsigned lrm;
+       unsigned hrm;
+       unsigned t;
+       unsigned at;
+       int s;
+
+       COMPXSP;
+       COMPYSP;
+       u32 zm; int ze; int zs __maybe_unused; int zc;
+
+       EXPLODEXSP;
+       EXPLODEYSP;
+       EXPLODESP(z, zc, zs, ze, zm)
+
+       FLUSHXSP;
+       FLUSHYSP;
+       FLUSHSP(z, zc, zs, ze, zm);
+
+       ieee754_clearcx();
+
+       switch (zc) {
+       case IEEE754_CLASS_SNAN:
+               ieee754_setcx(IEEE754_INVALID_OPERATION);
+               return ieee754sp_nanxcpt(z);
+       case IEEE754_CLASS_DNORM:
+               SPDNORMx(zm, ze);
+       /* QNAN is handled separately below */
+       }
+
+       switch (CLPAIR(xc, yc)) {
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+               return ieee754sp_nanxcpt(y);
+
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
+               return ieee754sp_nanxcpt(x);
+
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
+               return y;
+
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
+               return x;
+
+       /*
+        * Infinity handling
+        */
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
+               if (zc == IEEE754_CLASS_QNAN)
+                       return z;
+               ieee754_setcx(IEEE754_INVALID_OPERATION);
+               return ieee754sp_indef();
+
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
+               if (zc == IEEE754_CLASS_QNAN)
+                       return z;
+               return ieee754sp_inf(xs ^ ys);
+
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
+               if (zc == IEEE754_CLASS_INF)
+                       return ieee754sp_inf(zs);
+               /* Multiplication is 0 so just return z */
+               return z;
+
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
+               SPDNORMX;
+
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
+               if (zc == IEEE754_CLASS_QNAN)
+                       return z;
+               else if (zc == IEEE754_CLASS_INF)
+                       return ieee754sp_inf(zs);
+               SPDNORMY;
+               break;
+
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
+               if (zc == IEEE754_CLASS_QNAN)
+                       return z;
+               else if (zc == IEEE754_CLASS_INF)
+                       return ieee754sp_inf(zs);
+               SPDNORMX;
+               break;
+
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
+               if (zc == IEEE754_CLASS_QNAN)
+                       return z;
+               else if (zc == IEEE754_CLASS_INF)
+                       return ieee754sp_inf(zs);
+               /* fall through to real compuation */
+       }
+
+       /* Finally get to do some computation */
+
+       /*
+        * Do the multiplication bit first
+        *
+        * rm = xm * ym, re = xe + ye basically
+        *
+        * At this point xm and ym should have been normalized.
+        */
+
+       /* rm = xm * ym, re = xe+ye basically */
+       assert(xm & SP_HIDDEN_BIT);
+       assert(ym & SP_HIDDEN_BIT);
+
+       re = xe + ye;
+       rs = xs ^ ys;
+
+       /* shunt to top of word */
+       xm <<= 32 - (SP_FBITS + 1);
+       ym <<= 32 - (SP_FBITS + 1);
+
+       /*
+        * Multiply 32 bits xm, ym to give high 32 bits rm with stickness.
+        */
+       lxm = xm & 0xffff;
+       hxm = xm >> 16;
+       lym = ym & 0xffff;
+       hym = ym >> 16;
+
+       lrm = lxm * lym;        /* 16 * 16 => 32 */
+       hrm = hxm * hym;        /* 16 * 16 => 32 */
+
+       t = lxm * hym; /* 16 * 16 => 32 */
+       at = lrm + (t << 16);
+       hrm += at < lrm;
+       lrm = at;
+       hrm = hrm + (t >> 16);
+
+       t = hxm * lym; /* 16 * 16 => 32 */
+       at = lrm + (t << 16);
+       hrm += at < lrm;
+       lrm = at;
+       hrm = hrm + (t >> 16);
+
+       rm = hrm | (lrm != 0);
+
+       /*
+        * Sticky shift down to normal rounding precision.
+        */
+       if ((int) rm < 0) {
+               rm = (rm >> (32 - (SP_FBITS + 1 + 3))) |
+                   ((rm << (SP_FBITS + 1 + 3)) != 0);
+               re++;
+       } else {
+               rm = (rm >> (32 - (SP_FBITS + 1 + 3 + 1))) |
+                    ((rm << (SP_FBITS + 1 + 3 + 1)) != 0);
+       }
+       assert(rm & (SP_HIDDEN_BIT << 3));
+
+       /* And now the subtraction */
+
+       /* Flip sign of r and handle as add */
+       rs ^= 1;
+
+       assert(zm & SP_HIDDEN_BIT);
+
+       /*
+        * Provide guard,round and stick bit space.
+        */
+       zm <<= 3;
+
+       if (ze > re) {
+               /*
+                * Have to shift y fraction right to align.
+                */
+               s = ze - re;
+               SPXSRSYn(s);
+       } else if (re > ze) {
+               /*
+                * Have to shift x fraction right to align.
+                */
+               s = re - ze;
+               SPXSRSYn(s);
+       }
+       assert(ze == re);
+       assert(ze <= SP_EMAX);
+
+       if (zs == rs) {
+               /*
+                * Generate 28 bit result of adding two 27 bit numbers
+                * leaving result in zm, zs and ze.
+                */
+               zm = zm + rm;
+
+               if (zm >> (SP_FBITS + 1 + 3)) { /* carry out */
+                       SPXSRSX1(); /* shift preserving sticky */
+               }
+       } else {
+               if (zm >= rm) {
+                       zm = zm - rm;
+               } else {
+                       zm = rm - zm;
+                       zs = rs;
+               }
+               if (zm == 0)
+                       return ieee754sp_zero(ieee754_csr.rm == FPU_CSR_RD);
+
+               /*
+                * Normalize in extended single precision
+                */
+               while ((zm >> (SP_MBITS + 3)) == 0) {
+                       zm <<= 1;
+                       ze--;
+               }
+
+       }
+       return ieee754sp_format(zs, ze, zm);
+}
index fbea4432f3f23fe3d44d278f48d28fd78797d580..5d3a25e1cfaea62cf7859f3408e3d101f9bf4060 100644 (file)
@@ -1276,6 +1276,7 @@ static void probe_pcache(void)
        case CPU_PROAPTIV:
        case CPU_M5150:
        case CPU_QEMU_GENERIC:
+       case CPU_I6400:
                if (!(read_c0_config7() & MIPS_CONF7_IAR) &&
                    (c->icache.waysize > PAGE_SIZE))
                        c->icache.flags |= MIPS_CACHE_ALIASES;
index eeaf0245c3b16f89a8295f0f60172fd2ccf812b4..8f23cf08f4baa68d4d73b93b62a396867085f877 100644 (file)
@@ -194,6 +194,40 @@ static void mips_dma_free_coherent(struct device *dev, size_t size, void *vaddr,
                __free_pages(page, get_order(size));
 }
 
+static int mips_dma_mmap(struct device *dev, struct vm_area_struct *vma,
+       void *cpu_addr, dma_addr_t dma_addr, size_t size,
+       struct dma_attrs *attrs)
+{
+       unsigned long user_count = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
+       unsigned long count = PAGE_ALIGN(size) >> PAGE_SHIFT;
+       unsigned long addr = (unsigned long)cpu_addr;
+       unsigned long off = vma->vm_pgoff;
+       unsigned long pfn;
+       int ret = -ENXIO;
+
+       if (!plat_device_is_coherent(dev) && !hw_coherentio)
+               addr = CAC_ADDR(addr);
+
+       pfn = page_to_pfn(virt_to_page((void *)addr));
+
+       if (dma_get_attr(DMA_ATTR_WRITE_COMBINE, attrs))
+               vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+       else
+               vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+
+       if (dma_mmap_from_coherent(dev, vma, cpu_addr, size, &ret))
+               return ret;
+
+       if (off < count && user_count <= (count - off)) {
+               ret = remap_pfn_range(vma, vma->vm_start,
+                                     pfn + off,
+                                     user_count << PAGE_SHIFT,
+                                     vma->vm_page_prot);
+       }
+
+       return ret;
+}
+
 static inline void __dma_sync_virtual(void *addr, size_t size,
        enum dma_data_direction direction)
 {
@@ -380,6 +414,7 @@ EXPORT_SYMBOL(dma_cache_sync);
 static struct dma_map_ops mips_default_dma_map_ops = {
        .alloc = mips_dma_alloc_coherent,
        .free = mips_dma_free_coherent,
+       .mmap = mips_dma_mmap,
        .map_page = mips_dma_map_page,
        .unmap_page = mips_dma_unmap_page,
        .map_sg = mips_dma_map_sg,
index 852a41c6da4507080d611dce0b1fc206caf30556..4b88fa031891d474c715db30479218e8216aa948 100644 (file)
@@ -57,12 +57,10 @@ static void __kprobes __do_page_fault(struct pt_regs *regs, unsigned long write,
 
 #ifdef CONFIG_KPROBES
        /*
-        * This is to notify the fault handler of the kprobes.  The
-        * exception code is redundant as it is also carried in REGS,
-        * but we pass it anyhow.
+        * This is to notify the fault handler of the kprobes.
         */
        if (notify_die(DIE_PAGE_FAULT, "page fault", regs, -1,
-                      (regs->cp0_cause >> 2) & 0x1f, SIGSEGV) == NOTIFY_STOP)
+                      current->thread.trap_nr, SIGSEGV) == NOTIFY_STOP)
                return;
 #endif
 
@@ -224,6 +222,7 @@ bad_area_nosemaphore:
                        print_vma_addr(" ", regs->regs[31]);
                        pr_info("\n");
                }
+               current->thread.trap_nr = (regs->cp0_cause >> 2) & 0x1f;
                info.si_signo = SIGSEGV;
                info.si_errno = 0;
                /* info.si_code has been set above */
@@ -282,6 +281,7 @@ do_sigbus:
                       field, (unsigned long) regs->cp0_epc,
                       field, (unsigned long) regs->regs[31]);
 #endif
+       current->thread.trap_nr = (regs->cp0_cause >> 2) & 0x1f;
        tsk->thread.cp0_badvaddr = address;
        info.si_signo = SIGBUS;
        info.si_errno = 0;
index 198a3147dd7d08b78746790c628d2012a65c61ec..66d0f49c5bec4bab02d8e2e194570527d9ccd4e8 100644 (file)
@@ -37,6 +37,7 @@
 #include <asm/cpu.h>
 #include <asm/dma.h>
 #include <asm/kmap_types.h>
+#include <asm/maar.h>
 #include <asm/mmu_context.h>
 #include <asm/sections.h>
 #include <asm/pgtable.h>
@@ -333,9 +334,40 @@ static inline void mem_init_free_highmem(void)
 #endif
 }
 
-unsigned __weak platform_maar_init(unsigned num_maars)
+unsigned __weak platform_maar_init(unsigned num_pairs)
 {
-       return 0;
+       struct maar_config cfg[BOOT_MEM_MAP_MAX];
+       unsigned i, num_configured, num_cfg = 0;
+       phys_addr_t skip;
+
+       for (i = 0; i < boot_mem_map.nr_map; i++) {
+               switch (boot_mem_map.map[i].type) {
+               case BOOT_MEM_RAM:
+               case BOOT_MEM_INIT_RAM:
+                       break;
+               default:
+                       continue;
+               }
+
+               skip = 0x10000 - (boot_mem_map.map[i].addr & 0xffff);
+
+               cfg[num_cfg].lower = boot_mem_map.map[i].addr;
+               cfg[num_cfg].lower += skip;
+
+               cfg[num_cfg].upper = cfg[num_cfg].lower;
+               cfg[num_cfg].upper += boot_mem_map.map[i].size - 1;
+               cfg[num_cfg].upper -= skip;
+
+               cfg[num_cfg].attrs = MIPS_MAAR_S;
+               num_cfg++;
+       }
+
+       num_configured = maar_config(cfg, num_cfg, num_pairs);
+       if (num_configured < num_cfg)
+               pr_warn("Not enough MAAR pairs (%u) for all bootmem regions (%u)\n",
+                       num_pairs, num_cfg);
+
+       return num_configured;
 }
 
 static void maar_init(void)
index 4ceafd13870cd6945634713f04ac3f7d65ba52d2..53ea8391f9bbf9c2ddf81a114e59f52d05ad7abf 100644 (file)
@@ -14,6 +14,7 @@
 #include <asm/pgtable.h>
 #include <asm/mmu_context.h>
 #include <asm/r4kcache.h>
+#include <asm/mips-cm.h>
 
 /*
  * MIPS32/MIPS64 L2 cache handling
@@ -94,6 +95,38 @@ static inline int mips_sc_is_activated(struct cpuinfo_mips *c)
        return 1;
 }
 
+static int __init mips_sc_probe_cm3(void)
+{
+       struct cpuinfo_mips *c = &current_cpu_data;
+       unsigned long cfg = read_gcr_l2_config();
+       unsigned long sets, line_sz, assoc;
+
+       if (cfg & CM_GCR_L2_CONFIG_BYPASS_MSK)
+               return 0;
+
+       sets = cfg & CM_GCR_L2_CONFIG_SET_SIZE_MSK;
+       sets >>= CM_GCR_L2_CONFIG_SET_SIZE_SHF;
+       c->scache.sets = 64 << sets;
+
+       line_sz = cfg & CM_GCR_L2_CONFIG_LINE_SIZE_MSK;
+       line_sz >>= CM_GCR_L2_CONFIG_LINE_SIZE_SHF;
+       c->scache.linesz = 2 << line_sz;
+
+       assoc = cfg & CM_GCR_L2_CONFIG_ASSOC_MSK;
+       assoc >>= CM_GCR_L2_CONFIG_ASSOC_SHF;
+       c->scache.ways = assoc + 1;
+       c->scache.waysize = c->scache.sets * c->scache.linesz;
+       c->scache.waybit = __ffs(c->scache.waysize);
+
+       c->scache.flags &= ~MIPS_CACHE_NOT_PRESENT;
+
+       return 1;
+}
+
+void __weak platform_early_l2_init(void)
+{
+}
+
 static inline int __init mips_sc_probe(void)
 {
        struct cpuinfo_mips *c = &current_cpu_data;
@@ -103,6 +136,15 @@ static inline int __init mips_sc_probe(void)
        /* Mark as not present until probe completed */
        c->scache.flags |= MIPS_CACHE_NOT_PRESENT;
 
+       /*
+        * Do we need some platform specific probing before
+        * we configure L2?
+        */
+       platform_early_l2_init();
+
+       if (mips_cm_revision() >= CM_REV_CM3)
+               return mips_sc_probe_cm3();
+
        /* Ignore anything but MIPSxx processors */
        if (!(c->isa_level & (MIPS_CPU_ISA_M32R1 | MIPS_CPU_ISA_M32R2 |
                              MIPS_CPU_ISA_M32R6 | MIPS_CPU_ISA_M64R1 |
index 2b75b8f880ed1f50df9429d758d2b4d5cf624cd2..b4f366f7c0f57ae86a5cf601d75c81cda7ee2acd 100644 (file)
@@ -36,7 +36,7 @@ extern void build_tlb_refill_handler(void);
                "nop\n\t"               \
                ".set   pop\n\t")
 
-static int r3k_have_wired_reg;                 /* Should be in cpu_data? */
+int r3k_have_wired_reg;                        /* Should be in cpu_data? */
 
 /* TLB operations. */
 static void local_flush_tlb_from(int entry)
index cec3e187c48f4dcf6e176e14c7e85be1d1234b35..53c24784a2f7bd2e8c0ae719f1f07c9ad60dd52b 100644 (file)
@@ -303,3 +303,10 @@ mips_pci_controller:
        if (!register_vsmp_smp_ops())
                return;
 }
+
+void platform_early_l2_init(void)
+{
+       /* L2 configuration lives in the CM3 */
+       if (mips_cm_revision() >= CM_REV_CM3)
+               mips_cm_probe();
+}
index fa8f591f371361ba6fe3654617e6f44690a48a25..c6a6c7afddab41f00475bce99e53f861dc10db58 100644 (file)
@@ -382,122 +382,12 @@ void malta_be_init(void)
        /* Could change CM error mask register. */
 }
 
-
-static char *tr[8] = {
-       "mem",  "gcr",  "gic",  "mmio",
-       "0x04", "0x05", "0x06", "0x07"
-};
-
-static char *mcmd[32] = {
-       [0x00] = "0x00",
-       [0x01] = "Legacy Write",
-       [0x02] = "Legacy Read",
-       [0x03] = "0x03",
-       [0x04] = "0x04",
-       [0x05] = "0x05",
-       [0x06] = "0x06",
-       [0x07] = "0x07",
-       [0x08] = "Coherent Read Own",
-       [0x09] = "Coherent Read Share",
-       [0x0a] = "Coherent Read Discard",
-       [0x0b] = "Coherent Ready Share Always",
-       [0x0c] = "Coherent Upgrade",
-       [0x0d] = "Coherent Writeback",
-       [0x0e] = "0x0e",
-       [0x0f] = "0x0f",
-       [0x10] = "Coherent Copyback",
-       [0x11] = "Coherent Copyback Invalidate",
-       [0x12] = "Coherent Invalidate",
-       [0x13] = "Coherent Write Invalidate",
-       [0x14] = "Coherent Completion Sync",
-       [0x15] = "0x15",
-       [0x16] = "0x16",
-       [0x17] = "0x17",
-       [0x18] = "0x18",
-       [0x19] = "0x19",
-       [0x1a] = "0x1a",
-       [0x1b] = "0x1b",
-       [0x1c] = "0x1c",
-       [0x1d] = "0x1d",
-       [0x1e] = "0x1e",
-       [0x1f] = "0x1f"
-};
-
-static char *core[8] = {
-       "Invalid/OK",   "Invalid/Data",
-       "Shared/OK",    "Shared/Data",
-       "Modified/OK",  "Modified/Data",
-       "Exclusive/OK", "Exclusive/Data"
-};
-
-static char *causes[32] = {
-       "None", "GC_WR_ERR", "GC_RD_ERR", "COH_WR_ERR",
-       "COH_RD_ERR", "MMIO_WR_ERR", "MMIO_RD_ERR", "0x07",
-       "0x08", "0x09", "0x0a", "0x0b",
-       "0x0c", "0x0d", "0x0e", "0x0f",
-       "0x10", "0x11", "0x12", "0x13",
-       "0x14", "0x15", "0x16", "INTVN_WR_ERR",
-       "INTVN_RD_ERR", "0x19", "0x1a", "0x1b",
-       "0x1c", "0x1d", "0x1e", "0x1f"
-};
-
 int malta_be_handler(struct pt_regs *regs, int is_fixup)
 {
        /* This duplicates the handling in do_be which seems wrong */
        int retval = is_fixup ? MIPS_BE_FIXUP : MIPS_BE_FATAL;
 
-       if (mips_cm_present()) {
-               unsigned long cm_error = read_gcr_error_cause();
-               unsigned long cm_addr = read_gcr_error_addr();
-               unsigned long cm_other = read_gcr_error_mult();
-               unsigned long cause, ocause;
-               char buf[256];
-
-               cause = cm_error & CM_GCR_ERROR_CAUSE_ERRTYPE_MSK;
-               if (cause != 0) {
-                       cause >>= CM_GCR_ERROR_CAUSE_ERRTYPE_SHF;
-                       if (cause < 16) {
-                               unsigned long cca_bits = (cm_error >> 15) & 7;
-                               unsigned long tr_bits = (cm_error >> 12) & 7;
-                               unsigned long cmd_bits = (cm_error >> 7) & 0x1f;
-                               unsigned long stag_bits = (cm_error >> 3) & 15;
-                               unsigned long sport_bits = (cm_error >> 0) & 7;
-
-                               snprintf(buf, sizeof(buf),
-                                        "CCA=%lu TR=%s MCmd=%s STag=%lu "
-                                        "SPort=%lu\n",
-                                        cca_bits, tr[tr_bits], mcmd[cmd_bits],
-                                        stag_bits, sport_bits);
-                       } else {
-                               /* glob state & sresp together */
-                               unsigned long c3_bits = (cm_error >> 18) & 7;
-                               unsigned long c2_bits = (cm_error >> 15) & 7;
-                               unsigned long c1_bits = (cm_error >> 12) & 7;
-                               unsigned long c0_bits = (cm_error >> 9) & 7;
-                               unsigned long sc_bit = (cm_error >> 8) & 1;
-                               unsigned long cmd_bits = (cm_error >> 3) & 0x1f;
-                               unsigned long sport_bits = (cm_error >> 0) & 7;
-                               snprintf(buf, sizeof(buf),
-                                        "C3=%s C2=%s C1=%s C0=%s SC=%s "
-                                        "MCmd=%s SPort=%lu\n",
-                                        core[c3_bits], core[c2_bits],
-                                        core[c1_bits], core[c0_bits],
-                                        sc_bit ? "True" : "False",
-                                        mcmd[cmd_bits], sport_bits);
-                       }
-
-                       ocause = (cm_other & CM_GCR_ERROR_MULT_ERR2ND_MSK) >>
-                                CM_GCR_ERROR_MULT_ERR2ND_SHF;
-
-                       pr_err("CM_ERROR=%08lx %s <%s>\n", cm_error,
-                              causes[cause], buf);
-                       pr_err("CM_ADDR =%08lx\n", cm_addr);
-                       pr_err("CM_OTHER=%08lx %s\n", cm_other, causes[ocause]);
-
-                       /* reprime cause register */
-                       write_gcr_error_cause(0);
-               }
-       }
+       mips_cm_error_report();
 
        return retval;
 }
index b769657be4d4609f9e4545ac97147ca63000a363..dadeb83791828249e3af6d62ad55f1e9a2756a8a 100644 (file)
@@ -179,31 +179,6 @@ void __init prom_free_prom_memory(void)
        }
 }
 
-unsigned platform_maar_init(unsigned num_pairs)
-{
-       phys_addr_t mem_end = (physical_memsize & ~0xffffull) - 1;
-       struct maar_config cfg[] = {
-               /* DRAM preceding I/O */
-               { 0x00000000, 0x0fffffff, MIPS_MAAR_S },
-
-               /* DRAM following I/O */
-               { 0x20000000, mem_end, MIPS_MAAR_S },
-
-               /* DRAM alias in upper half of physical */
-               { 0x80000000, 0x80000000 + mem_end, MIPS_MAAR_S },
-       };
-       unsigned i, num_cfg = ARRAY_SIZE(cfg);
-
-       /* If DRAM fits before I/O, drop the region following it */
-       if (physical_memsize <= 0x10000000) {
-               num_cfg--;
-               for (i = 1; i < num_cfg; i++)
-                       cfg[i] = cfg[i + 1];
-       }
-
-       return maar_config(cfg, num_cfg, num_pairs);
-}
-
 phys_addr_t mips_cdmm_phys_base(void)
 {
        /* This address is "typically unused" */
index 5f5d18b0e94d8acdccb2b8c86ac153fd784ad6bb..3660dc67d544fbd44c4ff7188fbc0d000fcabf4e 100644 (file)
@@ -87,7 +87,7 @@ struct nlm_pic_irq {
 static void xlp_pic_enable(struct irq_data *d)
 {
        unsigned long flags;
-       struct nlm_pic_irq *pd = irq_data_get_irq_handler_data(d);
+       struct nlm_pic_irq *pd = irq_data_get_irq_chip_data(d);
 
        BUG_ON(!pd);
        spin_lock_irqsave(&pd->node->piclock, flags);
@@ -97,7 +97,7 @@ static void xlp_pic_enable(struct irq_data *d)
 
 static void xlp_pic_disable(struct irq_data *d)
 {
-       struct nlm_pic_irq *pd = irq_data_get_irq_handler_data(d);
+       struct nlm_pic_irq *pd = irq_data_get_irq_chip_data(d);
        unsigned long flags;
 
        BUG_ON(!pd);
@@ -108,7 +108,7 @@ static void xlp_pic_disable(struct irq_data *d)
 
 static void xlp_pic_mask_ack(struct irq_data *d)
 {
-       struct nlm_pic_irq *pd = irq_data_get_irq_handler_data(d);
+       struct nlm_pic_irq *pd = irq_data_get_irq_chip_data(d);
 
        clear_c0_eimr(pd->picirq);
        ack_c0_eirr(pd->picirq);
@@ -116,7 +116,7 @@ static void xlp_pic_mask_ack(struct irq_data *d)
 
 static void xlp_pic_unmask(struct irq_data *d)
 {
-       struct nlm_pic_irq *pd = irq_data_get_irq_handler_data(d);
+       struct nlm_pic_irq *pd = irq_data_get_irq_chip_data(d);
 
        BUG_ON(!pd);
 
@@ -193,7 +193,7 @@ void nlm_setup_pic_irq(int node, int picirq, int irq, int irt)
        pic_data->picirq = picirq;
        pic_data->node = nlm_get_node(node);
        irq_set_chip_and_handler(xirq, &xlp_pic, handle_level_irq);
-       irq_set_handler_data(xirq, pic_data);
+       irq_set_chip_data(xirq, pic_data);
 }
 
 void nlm_set_pic_extra_ack(int node, int irq, void (*xack)(struct irq_data *))
@@ -202,7 +202,7 @@ void nlm_set_pic_extra_ack(int node, int irq, void (*xack)(struct irq_data *))
        int xirq;
 
        xirq = nlm_irq_to_xirq(node, irq);
-       pic_data = irq_get_handler_data(xirq);
+       pic_data = irq_get_chip_data(xirq);
        if (WARN_ON(!pic_data))
                return;
        pic_data->extra_ack = xack;
index f5fff228b347b6da07d68212fb11f4ae140548c8..0136b4f9c9cde0e4cfa95c8a58d441093d3e8009 100644 (file)
@@ -82,8 +82,9 @@ void nlm_send_ipi_mask(const struct cpumask *mask, unsigned int action)
 }
 
 /* IRQ_IPI_SMP_FUNCTION Handler */
-void nlm_smp_function_ipi_handler(unsigned int irq, struct irq_desc *desc)
+void nlm_smp_function_ipi_handler(unsigned int __irq, struct irq_desc *desc)
 {
+       unsigned int irq = irq_desc_get_irq(desc);
        clear_c0_eimr(irq);
        ack_c0_eirr(irq);
        generic_smp_call_function_interrupt();
@@ -91,8 +92,9 @@ void nlm_smp_function_ipi_handler(unsigned int irq, struct irq_desc *desc)
 }
 
 /* IRQ_IPI_SMP_RESCHEDULE  handler */
-void nlm_smp_resched_ipi_handler(unsigned int irq, struct irq_desc *desc)
+void nlm_smp_resched_ipi_handler(unsigned int __irq, struct irq_desc *desc)
 {
+       unsigned int irq = irq_desc_get_irq(desc);
        clear_c0_eimr(irq);
        ack_c0_eirr(irq);
        scheduler_ipi();
index 7b066a44e6798e71447e55633ff1cb8334a2948d..c11b9c7dc7c8ea1b96842716c74969dbdfc2131f 100644 (file)
@@ -152,7 +152,7 @@ static const u8 sata_phy_config1[]  = {
        0xC9, 0xC9, 0x07, 0x07, 0x18, 0x18, 0x01, 0x01, 0x22, 0x00
 };
 
-/* SATA PHY config for register block 2 0x0x8065 .. 0x0x80A4 */
+/* SATA PHY config for register block 2 0x8065 .. 0x80A4 */
 static const u8 sata_phy_config2[]  = {
        0xAA, 0x00, 0x4C, 0xC9, 0xC9, 0x07, 0x07, 0x18,
        0x18, 0x05, 0x0C, 0x10, 0x00, 0x10, 0x00, 0xFF,
index a8f4144a0297fce376bb1965a62b8ccc8e33e155..80ec929747c37b30eb8da5749c21134b1c0b4558 100644 (file)
@@ -91,6 +91,8 @@ static int xlp9xx_irq_to_irt(int irq)
                return 134;
        case PIC_SATA_IRQ:
                return 143;
+       case PIC_NAND_IRQ:
+               return 151;
        case PIC_SPI_IRQ:
                return 152;
        case PIC_MMC_IRQ:
index 81f58958cf081bf8f307f47c1dd4a3a93e82c5cd..3c9ec3ddca845dccac627dcf13fec4a7b62ee272 100644 (file)
@@ -91,6 +91,7 @@ int __init oprofile_arch_init(struct oprofile_operations *ops)
        case CPU_INTERAPTIV:
        case CPU_PROAPTIV:
        case CPU_P5600:
+       case CPU_I6400:
        case CPU_M5150:
        case CPU_LOONGSON1:
        case CPU_SB1:
index 6a6e2cc55b8926975fb17f9f54649a0a634018c5..8f988a61b7a850526e623733a969b405f7755fce 100644 (file)
@@ -392,6 +392,10 @@ static int __init mipsxx_init(void)
                op_model_mipsxx_ops.cpu_type = "mips/P5600";
                break;
 
+       case CPU_I6400:
+               op_model_mipsxx_ops.cpu_type = "mips/I6400";
+               break;
+
        case CPU_M5150:
                op_model_mipsxx_ops.cpu_type = "mips/M5150";
                break;
index 3407495fcbe2fdca58976a49b4c0a9639691ae93..bb14335f804b4a72c21f1c5df9cf5ddb879b948f 100644 (file)
@@ -131,7 +131,7 @@ struct xlp_msi_data {
  */
 static void xlp_msi_enable(struct irq_data *d)
 {
-       struct xlp_msi_data *md = irq_data_get_irq_handler_data(d);
+       struct xlp_msi_data *md = irq_data_get_irq_chip_data(d);
        unsigned long flags;
        int vec;
 
@@ -148,7 +148,7 @@ static void xlp_msi_enable(struct irq_data *d)
 
 static void xlp_msi_disable(struct irq_data *d)
 {
-       struct xlp_msi_data *md = irq_data_get_irq_handler_data(d);
+       struct xlp_msi_data *md = irq_data_get_irq_chip_data(d);
        unsigned long flags;
        int vec;
 
@@ -165,7 +165,7 @@ static void xlp_msi_disable(struct irq_data *d)
 
 static void xlp_msi_mask_ack(struct irq_data *d)
 {
-       struct xlp_msi_data *md = irq_data_get_irq_handler_data(d);
+       struct xlp_msi_data *md = irq_data_get_irq_chip_data(d);
        int link, vec;
 
        link = nlm_irq_msilink(d->irq);
@@ -211,7 +211,7 @@ static void xlp_msix_mask_ack(struct irq_data *d)
        msixvec = nlm_irq_msixvec(d->irq);
        link = nlm_irq_msixlink(msixvec);
        pci_msi_mask_irq(d);
-       md = irq_data_get_irq_handler_data(d);
+       md = irq_data_get_irq_chip_data(d);
 
        /* Ack MSI on bridge */
        if (cpu_is_xlp9xx()) {
@@ -302,7 +302,7 @@ static int xlp_setup_msi(uint64_t lnkbase, int node, int link,
        /* Get MSI data for the link */
        lirq = PIC_PCIE_LINK_MSI_IRQ(link);
        xirq = nlm_irq_to_xirq(node, nlm_link_msiirq(link, 0));
-       md = irq_get_handler_data(xirq);
+       md = irq_get_chip_data(xirq);
        msiaddr = MSI_LINK_ADDR(node, link);
 
        spin_lock_irqsave(&md->msi_lock, flags);
@@ -409,7 +409,7 @@ static int xlp_setup_msix(uint64_t lnkbase, int node, int link,
        /* Get MSI data for the link */
        lirq = PIC_PCIE_MSIX_IRQ(link);
        xirq = nlm_irq_to_xirq(node, nlm_link_msixirq(link, 0));
-       md = irq_get_handler_data(xirq);
+       md = irq_get_chip_data(xirq);
        msixaddr = MSIX_LINK_ADDR(node, link);
 
        spin_lock_irqsave(&md->msi_lock, flags);
@@ -485,7 +485,7 @@ void __init xlp_init_node_msi_irqs(int node, int link)
        irq = nlm_irq_to_xirq(node, nlm_link_msiirq(link, 0));
        for (i = irq; i < irq + XLP_MSIVEC_PER_LINK; i++) {
                irq_set_chip_and_handler(i, &xlp_msi_chip, handle_level_irq);
-               irq_set_handler_data(i, md);
+               irq_set_chip_data(i, md);
        }
 
        for (i = 0; i < XLP_MSIXVEC_PER_LINK ; i++) {
@@ -508,7 +508,7 @@ void __init xlp_init_node_msi_irqs(int node, int link)
                /* Initialize MSI-X extended irq space for the link  */
                irq = nlm_irq_to_xirq(node, nlm_link_msixirq(link, i));
                irq_set_chip_and_handler(irq, &xlp_msix_chip, handle_level_irq);
-               irq_set_handler_data(irq, md);
+               irq_set_chip_data(irq, md);
        }
 }
 
@@ -520,7 +520,7 @@ void nlm_dispatch_msi(int node, int lirq)
 
        link = lirq - PIC_PCIE_LINK_MSI_IRQ_BASE;
        irqbase = nlm_irq_to_xirq(node, nlm_link_msiirq(link, 0));
-       md = irq_get_handler_data(irqbase);
+       md = irq_get_chip_data(irqbase);
        if (cpu_is_xlp9xx())
                status = nlm_read_reg(md->lnkbase, PCIE_9XX_MSI_STATUS) &
                                                md->msi_enabled_mask;
@@ -550,7 +550,7 @@ void nlm_dispatch_msix(int node, int lirq)
 
        link = lirq - PIC_PCIE_MSIX_IRQ_BASE;
        irqbase = nlm_irq_to_xirq(node, nlm_link_msixirq(link, 0));
-       md = irq_get_handler_data(irqbase);
+       md = irq_get_chip_data(irqbase);
        if (cpu_is_xlp9xx())
                status = nlm_read_reg(md->lnkbase, PCIE_9XX_MSIX_STATUSX(link));
        else
index 710aef5c070e839539a309b88fab97735316c501..2dc97c45685e8b2889b15814032a3e8b6b6f7cc0 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/types.h>
 
 #include <asm/addrspace.h>
-#include <asm/debug.h>
 
 #include <asm/emma/emma2rh.h>
 
 static int check_args(struct pci_bus *bus, u32 devfn, u32 * bus_num)
 {
        /* check if the bus is top-level */
-       if (bus->parent != NULL) {
+       if (bus->parent != NULL)
                *bus_num = bus->number;
-               db_assert(bus_num != NULL);
-       } else
+       else
                *bus_num = 0;
 
        if (*bus_num == 0) {
index 283157f8dc64794a3a02936ef11974538c8950eb..ad35a5e6a56c5b4ca978f702a8786b1dcd998fa3 100644 (file)
@@ -312,8 +312,8 @@ static void ar71xx_pci_irq_init(struct ar71xx_pci_controller *apc)
                irq_set_chip_data(i, apc);
        }
 
-       irq_set_handler_data(apc->irq, apc);
-       irq_set_chained_handler(apc->irq, ar71xx_pci_irq_handler);
+       irq_set_chained_handler_and_data(apc->irq, ar71xx_pci_irq_handler,
+                                        apc);
 }
 
 static void ar71xx_pci_reset(void)
index 0af362b5af9266537b51a13ed9d2f842ad890992..907d11dd921b3da9b2f540b4ae14eab897a70588 100644 (file)
@@ -321,8 +321,8 @@ static void ar724x_pci_irq_init(struct ar724x_pci_controller *apc,
                irq_set_chip_data(i, apc);
        }
 
-       irq_set_handler_data(apc->irq, apc);
-       irq_set_chained_handler(apc->irq, ar724x_pci_irq_handler);
+       irq_set_chained_handler_and_data(apc->irq, ar724x_pci_irq_handler,
+                                        apc);
 }
 
 static int ar724x_pci_probe(struct platform_device *pdev)
index c5347d99cf3a2b2583f78b86c3429caab8434d11..6a15dbd085aa8e600a59d5a0680cd9be1a3f3f60 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/of_irq.h>
 #include <linux/of_pci.h>
 
-#include <asm/gpio.h>
 #include <asm/addrspace.h>
 
 #include <lantiq_soc.h>
index 80fafe646e7411a9c8e8f8fa1e0cb75cbd7ea7b8..53c8efaf15723c882952a0bcc5572c18f7a9e049 100644 (file)
@@ -129,7 +129,7 @@ static void rt3883_pci_write_cfg32(struct rt3883_pci_controller *rpc,
        rt3883_pci_w32(rpc, val, RT3883_PCI_REG_CFGDATA);
 }
 
-static void rt3883_pci_irq_handler(unsigned int irq, struct irq_desc *desc)
+static void rt3883_pci_irq_handler(unsigned int __irq, struct irq_desc *desc)
 {
        struct rt3883_pci_controller *rpc;
        u32 pending;
@@ -145,7 +145,7 @@ static void rt3883_pci_irq_handler(unsigned int irq, struct irq_desc *desc)
        }
 
        while (pending) {
-               unsigned bit = __ffs(pending);
+               unsigned irq, bit = __ffs(pending);
 
                irq = irq_find_mapping(rpc->irq_domain, bit);
                generic_handle_irq(irq);
@@ -225,8 +225,7 @@ static int rt3883_pci_irq_init(struct device *dev,
                return -ENODEV;
        }
 
-       irq_set_handler_data(irq, rpc);
-       irq_set_chained_handler(irq, rt3883_pci_irq_handler);
+       irq_set_chained_handler_and_data(irq, rt3883_pci_irq_handler, rpc);
 
        return 0;
 }
diff --git a/arch/mips/pistachio/Kconfig b/arch/mips/pistachio/Kconfig
new file mode 100644 (file)
index 0000000..97731ea
--- /dev/null
@@ -0,0 +1,13 @@
+config PISTACHIO_GPTIMER_CLKSRC
+       bool "Enable General Purpose Timer based clocksource"
+       depends on MACH_PISTACHIO
+       select CLKSRC_PISTACHIO
+       select MIPS_EXTERNAL_TIMER
+       help
+         This option enables a clocksource driver based on a Pistachio
+         SoC General Purpose external timer.
+
+         If you want to enable the CPUFreq, you need to enable
+         this option.
+
+         If you don't want to enable CPUFreq, you can leave this disabled.
index 1207ec4dfb77021a6a114d776684ccfbe696ea00..8b9cf64630406e53552fe052ca10172370e5a88d 100644 (file)
@@ -88,7 +88,8 @@ static void unmask_cic_irq(struct irq_data *d)
        * Make sure we have IRQ affinity.  It may have changed while
        * we were processing the IRQ.
        */
-       if (!cpumask_test_cpu(smp_processor_id(), d->affinity))
+       if (!cpumask_test_cpu(smp_processor_id(),
+                             irq_data_get_affinity_mask(d)))
                return;
 #endif
 
index 24bf057a36136b61cd1f4b60df57ecc7367ac892..a8e70a9f274bdf70b0be449bee57c71c513e6fc4 100644 (file)
@@ -36,8 +36,8 @@ struct systick_device {
        int freq_scale;
 };
 
-static void systick_set_clock_mode(enum clock_event_mode mode,
-                               struct clock_event_device *evt);
+static int systick_set_oneshot(struct clock_event_device *evt);
+static int systick_shutdown(struct clock_event_device *evt);
 
 static int systick_next_event(unsigned long delta,
                                struct clock_event_device *evt)
@@ -73,11 +73,12 @@ static struct systick_device systick = {
                 * cevt-r4k uses 300, make sure systick
                 * gets used if available
                 */
-               .rating         = 310,
-               .features       = CLOCK_EVT_FEAT_ONESHOT,
-               .set_next_event = systick_next_event,
-               .set_mode       = systick_set_clock_mode,
-               .event_handler  = systick_event_handler,
+               .rating                 = 310,
+               .features               = CLOCK_EVT_FEAT_ONESHOT,
+               .set_next_event         = systick_next_event,
+               .set_state_shutdown     = systick_shutdown,
+               .set_state_oneshot      = systick_set_oneshot,
+               .event_handler          = systick_event_handler,
        },
 };
 
@@ -87,33 +88,33 @@ static struct irqaction systick_irqaction = {
        .dev_id = &systick.dev,
 };
 
-static void systick_set_clock_mode(enum clock_event_mode mode,
-                               struct clock_event_device *evt)
+static int systick_shutdown(struct clock_event_device *evt)
 {
        struct systick_device *sdev;
 
        sdev = container_of(evt, struct systick_device, dev);
 
-       switch (mode) {
-       case CLOCK_EVT_MODE_ONESHOT:
-               if (!sdev->irq_requested)
-                       setup_irq(systick.dev.irq, &systick_irqaction);
-               sdev->irq_requested = 1;
-               iowrite32(CFG_EXT_STK_EN | CFG_CNT_EN,
-                               systick.membase + SYSTICK_CONFIG);
-               break;
-
-       case CLOCK_EVT_MODE_SHUTDOWN:
-               if (sdev->irq_requested)
-                       free_irq(systick.dev.irq, &systick_irqaction);
-               sdev->irq_requested = 0;
-               iowrite32(0, systick.membase + SYSTICK_CONFIG);
-               break;
-
-       default:
-               pr_err("%s: Unhandeled mips clock_mode\n", systick.dev.name);
-               break;
-       }
+       if (sdev->irq_requested)
+               free_irq(systick.dev.irq, &systick_irqaction);
+       sdev->irq_requested = 0;
+       iowrite32(0, systick.membase + SYSTICK_CONFIG);
+
+       return 0;
+}
+
+static int systick_set_oneshot(struct clock_event_device *evt)
+{
+       struct systick_device *sdev;
+
+       sdev = container_of(evt, struct systick_device, dev);
+
+       if (!sdev->irq_requested)
+               setup_irq(systick.dev.irq, &systick_irqaction);
+       sdev->irq_requested = 1;
+       iowrite32(CFG_EXT_STK_EN | CFG_CNT_EN,
+                 systick.membase + SYSTICK_CONFIG);
+
+       return 0;
 }
 
 static void __init ralink_systick_init(struct device_node *np)
index e31e8cdcb296bfadc9c6ab2f394e089b4f48ad4b..9bd7a2de0765fc13dcd1fbffa493b47415abb22a 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/mtd/nand.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
+#include <linux/gpio.h>
 #include <linux/gpio_keys.h>
 #include <linux/input.h>
 #include <linux/serial_8250.h>
index 5aa3df8530826d7afe93c6430d2945532b37794c..650d5d39f34d902a60324cd9def8a48af228b994 100644 (file)
@@ -140,6 +140,11 @@ static int rb532_gpio_direction_output(struct gpio_chip *chip,
        return 0;
 }
 
+static int rb532_gpio_to_irq(struct gpio_chip *chip, unsigned gpio)
+{
+       return 8 + 4 * 32 + gpio;
+}
+
 static struct rb532_gpio_chip rb532_gpio_chip[] = {
        [0] = {
                .chip = {
@@ -148,6 +153,7 @@ static struct rb532_gpio_chip rb532_gpio_chip[] = {
                        .direction_output       = rb532_gpio_direction_output,
                        .get                    = rb532_gpio_get,
                        .set                    = rb532_gpio_set,
+                       .to_irq                 = rb532_gpio_to_irq,
                        .base                   = 0,
                        .ngpio                  = 32,
                },
index a6d10f607f348ce1815813d9f3c488b7620c0805..42d6cb9f956e35500d5a1b3268685447ebd5f7f2 100644 (file)
@@ -64,12 +64,6 @@ static int rt_next_event(unsigned long delta, struct clock_event_device *evt)
        return LOCAL_HUB_L(PI_RT_COUNT) >= cnt ? -ETIME : 0;
 }
 
-static void rt_set_mode(enum clock_event_mode mode,
-               struct clock_event_device *evt)
-{
-       /* Nothing to do ...  */
-}
-
 unsigned int rt_timer_irq;
 
 static DEFINE_PER_CPU(struct clock_event_device, hub_rt_clockevent);
@@ -124,7 +118,6 @@ void hub_rt_clock_event_init(void)
        cd->irq                 = irq;
        cd->cpumask             = cpumask_of(cpu);
        cd->set_next_event      = rt_next_event;
-       cd->set_mode            = rt_set_mode;
        clockevents_register_device(cd);
 }
 
index 41a1d22422112caa5b08cbc51b66ca47cf267a72..a4e55999ecb4c7744a7ac085d9dd5d2b2fe18126 100644 (file)
@@ -250,4 +250,4 @@ int __init sibyte_bus_watcher(void)
        return 0;
 }
 
-__initcall(sibyte_bus_watcher);
+device_initcall(sibyte_bus_watcher);
index cf8ec568b9dfad3eb820826cfd1ae7ddfcf096a2..fb4b3520cdc615f507eb90a08e77ba6e06a26903 100644 (file)
 #define SNI_COUNTER2_DIV       64
 #define SNI_COUNTER0_DIV       ((SNI_CLOCK_TICK_RATE / SNI_COUNTER2_DIV) / HZ)
 
-static void a20r_set_mode(enum clock_event_mode mode,
-                         struct clock_event_device *evt)
+static int a20r_set_periodic(struct clock_event_device *evt)
 {
-       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();
+       *(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();
 
-               break;
-       case CLOCK_EVT_MODE_ONESHOT:
-       case CLOCK_EVT_MODE_UNUSED:
-       case CLOCK_EVT_MODE_SHUTDOWN:
-               break;
-       case CLOCK_EVT_MODE_RESUME:
-               break;
-       }
+       *(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();
+       return 0;
 }
 
 static struct clock_event_device a20r_clockevent_device = {
-       .name           = "a20r-timer",
-       .features       = CLOCK_EVT_FEAT_PERIODIC,
+       .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,
+       .rating                 = 300,
+       .irq                    = SNI_A20R_IRQ_TIMER,
+       .set_state_periodic     = a20r_set_periodic,
 };
 
 static irqreturn_t a20r_interrupt(int irq, void *dev_id)
index 2791b8641df64c4624fc480ef5ee3a37e36c3a77..9d9962ab7d25ccfea97238f402e5dc2f65e20d98 100644 (file)
@@ -117,22 +117,6 @@ void clk_put(struct clk *clk)
 }
 EXPORT_SYMBOL(clk_put);
 
-/* GPIO support */
-
-#ifdef CONFIG_GPIOLIB
-int gpio_to_irq(unsigned gpio)
-{
-       return -EINVAL;
-}
-EXPORT_SYMBOL(gpio_to_irq);
-
-int irq_to_gpio(unsigned irq)
-{
-       return -EINVAL;
-}
-EXPORT_SYMBOL(irq_to_gpio);
-#endif
-
 #define BOARD_VEC(board)       extern struct txx9_board_vec board;
 #include <asm/txx9/boards.h>
 #undef BOARD_VEC
index 6d08446b877c9721564b271b48b7ad6dfe7fe5ec..12fe0f3bb7e9b0bf8120af19badf4ddf72903565 100644 (file)
 #include <linux/io.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
+#include <linux/gpio.h>
 
 #include <linux/libata.h>
 #include <scsi/scsi_host.h>
 
-#include <asm/gpio.h>
-
 #define DRV_NAME       "pata-rb532-cf"
 #define DRV_VERSION    "0.1.0"
 #define DRV_DESC       "PATA driver for RouterBOARD 532 Compact Flash"
index ab3bde16ecb4443a2e63d8e327fa1db730294dff..1c543effe062f8631c688088a1620454fadf160e 100644 (file)
@@ -331,6 +331,18 @@ static phys_addr_t mips_cdmm_cur_base(void)
                << MIPS_CDMMBASE_ADDR_START;
 }
 
+/**
+ * mips_cdmm_phys_base() - Choose a physical base address for CDMM region.
+ *
+ * Picking a suitable physical address at which to map the CDMM region is
+ * platform specific, so this weak function can be overridden by platform
+ * code to pick a suitable value if none is configured by the bootloader.
+ */
+phys_addr_t __weak mips_cdmm_phys_base(void)
+{
+       return 0;
+}
+
 /**
  * mips_cdmm_setup() - Ensure the CDMM bus is initialised and usable.
  * @bus:       Pointer to bus information for current CPU.
@@ -368,7 +380,7 @@ static int mips_cdmm_setup(struct mips_cdmm_bus *bus)
        if (!bus->phys)
                bus->phys = mips_cdmm_cur_base();
        /* Otherwise, ask platform code for suggestions */
-       if (!bus->phys && mips_cdmm_phys_base)
+       if (!bus->phys)
                bus->phys = mips_cdmm_phys_base();
        /* Otherwise, copy what other CPUs have done */
        if (!bus->phys)
index 4e57730e0be4e919203e21e070fb43666bb7b61d..74e002e80fd3c91919ec60f0cb37882befad5005 100644 (file)
@@ -111,6 +111,10 @@ config CLKSRC_LPC32XX
        select CLKSRC_MMIO
        select CLKSRC_OF
 
+config CLKSRC_PISTACHIO
+       bool
+       select CLKSRC_OF
+
 config CLKSRC_STM32
        bool "Clocksource for STM32 SoCs" if !ARCH_STM32
        depends on OF && ARM && (ARCH_STM32 || COMPILE_TEST)
index f228354961ca6f853a193f39b0a5fa2a63e47cd4..066337e247379dad08f05353f08645fa00bc93e1 100644 (file)
@@ -44,6 +44,7 @@ obj-$(CONFIG_FSL_FTM_TIMER)   += fsl_ftm_timer.o
 obj-$(CONFIG_VF_PIT_TIMER)     += vf_pit_timer.o
 obj-$(CONFIG_CLKSRC_QCOM)      += qcom-timer.o
 obj-$(CONFIG_MTK_TIMER)                += mtk_timer.o
+obj-$(CONFIG_CLKSRC_PISTACHIO) += time-pistachio.o
 
 obj-$(CONFIG_ARM_ARCH_TIMER)           += arm_arch_timer.o
 obj-$(CONFIG_ARM_GLOBAL_TIMER)         += arm_global_timer.o
index b81ed1a5342d90ca7481dd48c0bf928da5bcc6e7..a155bec06d18a713c89e3745013b40f4ee3aca1d 100644 (file)
@@ -79,6 +79,13 @@ static void gic_clockevent_cpu_exit(struct clock_event_device *cd)
        disable_percpu_irq(gic_timer_irq);
 }
 
+static void gic_update_frequency(void *data)
+{
+       unsigned long rate = (unsigned long)data;
+
+       clockevents_update_freq(this_cpu_ptr(&gic_clockevent_device), rate);
+}
+
 static int gic_cpu_notifier(struct notifier_block *nb, unsigned long action,
                                void *data)
 {
@@ -94,18 +101,40 @@ static int gic_cpu_notifier(struct notifier_block *nb, unsigned long action,
        return NOTIFY_OK;
 }
 
+static int gic_clk_notifier(struct notifier_block *nb, unsigned long action,
+                           void *data)
+{
+       struct clk_notifier_data *cnd = data;
+
+       if (action == POST_RATE_CHANGE)
+               on_each_cpu(gic_update_frequency, (void *)cnd->new_rate, 1);
+
+       return NOTIFY_OK;
+}
+
+
 static struct notifier_block gic_cpu_nb = {
        .notifier_call = gic_cpu_notifier,
 };
 
+static struct notifier_block gic_clk_nb = {
+       .notifier_call = gic_clk_notifier,
+};
+
 static int gic_clockevent_init(void)
 {
+       int ret;
+
        if (!cpu_has_counter || !gic_frequency)
                return -ENXIO;
 
-       setup_percpu_irq(gic_timer_irq, &gic_compare_irqaction);
+       ret = setup_percpu_irq(gic_timer_irq, &gic_compare_irqaction);
+       if (ret < 0)
+               return ret;
 
-       register_cpu_notifier(&gic_cpu_nb);
+       ret = register_cpu_notifier(&gic_cpu_nb);
+       if (ret < 0)
+               pr_warn("GIC: Unable to register CPU notifier\n");
 
        gic_clockevent_cpu_init(this_cpu_ptr(&gic_clockevent_device));
 
@@ -125,18 +154,17 @@ static struct clocksource gic_clocksource = {
 
 static void __init __gic_clocksource_init(void)
 {
+       int ret;
+
        /* Set clocksource mask. */
        gic_clocksource.mask = CLOCKSOURCE_MASK(gic_get_count_width());
 
        /* Calculate a somewhat reasonable rating value. */
        gic_clocksource.rating = 200 + gic_frequency / 10000000;
 
-       clocksource_register_hz(&gic_clocksource, gic_frequency);
-
-       gic_clockevent_init();
-
-       /* And finally start the counter */
-       gic_start_count();
+       ret = clocksource_register_hz(&gic_clocksource, gic_frequency);
+       if (ret < 0)
+               pr_warn("GIC: Unable to register clocksource\n");
 }
 
 void __init gic_clocksource_init(unsigned int frequency)
@@ -146,11 +174,16 @@ void __init gic_clocksource_init(unsigned int frequency)
                GIC_LOCAL_TO_HWIRQ(GIC_LOCAL_INT_COMPARE);
 
        __gic_clocksource_init();
+       gic_clockevent_init();
+
+       /* And finally start the counter */
+       gic_start_count();
 }
 
 static void __init gic_clocksource_of_init(struct device_node *node)
 {
        struct clk *clk;
+       int ret;
 
        if (WARN_ON(!gic_present || !node->parent ||
                    !of_device_is_compatible(node->parent, "mti,gic")))
@@ -158,8 +191,13 @@ static void __init gic_clocksource_of_init(struct device_node *node)
 
        clk = of_clk_get(node, 0);
        if (!IS_ERR(clk)) {
+               if (clk_prepare_enable(clk) < 0) {
+                       pr_err("GIC failed to enable clock\n");
+                       clk_put(clk);
+                       return;
+               }
+
                gic_frequency = clk_get_rate(clk);
-               clk_put(clk);
        } else if (of_property_read_u32(node, "clock-frequency",
                                        &gic_frequency)) {
                pr_err("GIC frequency not specified.\n");
@@ -172,6 +210,15 @@ static void __init gic_clocksource_of_init(struct device_node *node)
        }
 
        __gic_clocksource_init();
+
+       ret = gic_clockevent_init();
+       if (!ret && !IS_ERR(clk)) {
+               if (clk_notifier_register(clk, &gic_clk_nb) < 0)
+                       pr_warn("GIC: Unable to register clock notifier\n");
+       }
+
+       /* And finally start the counter */
+       gic_start_count();
 }
 CLOCKSOURCE_OF_DECLARE(mips_gic_timer, "mti,gic-timer",
                       gic_clocksource_of_init);
diff --git a/drivers/clocksource/time-pistachio.c b/drivers/clocksource/time-pistachio.c
new file mode 100644 (file)
index 0000000..18d4266
--- /dev/null
@@ -0,0 +1,217 @@
+/*
+ * Pistachio clocksource based on general-purpose timers
+ *
+ * Copyright (C) 2015 Imagination Technologies
+ *
+ * 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.
+ */
+
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+#include <linux/clk.h>
+#include <linux/clocksource.h>
+#include <linux/clockchips.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/mfd/syscon.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/sched_clock.h>
+#include <linux/time.h>
+
+/* Top level reg */
+#define CR_TIMER_CTRL_CFG              0x00
+#define TIMER_ME_GLOBAL                        BIT(0)
+#define CR_TIMER_REV                   0x10
+
+/* Timer specific registers */
+#define TIMER_CFG                      0x20
+#define TIMER_ME_LOCAL                 BIT(0)
+#define TIMER_RELOAD_VALUE             0x24
+#define TIMER_CURRENT_VALUE            0x28
+#define TIMER_CURRENT_OVERFLOW_VALUE   0x2C
+#define TIMER_IRQ_STATUS               0x30
+#define TIMER_IRQ_CLEAR                        0x34
+#define TIMER_IRQ_MASK                 0x38
+
+#define PERIP_TIMER_CONTROL            0x90
+
+/* Timer specific configuration Values */
+#define RELOAD_VALUE                   0xffffffff
+
+struct pistachio_clocksource {
+       void __iomem *base;
+       raw_spinlock_t lock;
+       struct clocksource cs;
+};
+
+static struct pistachio_clocksource pcs_gpt;
+
+#define to_pistachio_clocksource(cs)   \
+       container_of(cs, struct pistachio_clocksource, cs)
+
+static inline u32 gpt_readl(void __iomem *base, u32 offset, u32 gpt_id)
+{
+       return readl(base + 0x20 * gpt_id + offset);
+}
+
+static inline void gpt_writel(void __iomem *base, u32 value, u32 offset,
+               u32 gpt_id)
+{
+       writel(value, base + 0x20 * gpt_id + offset);
+}
+
+static cycle_t pistachio_clocksource_read_cycles(struct clocksource *cs)
+{
+       struct pistachio_clocksource *pcs = to_pistachio_clocksource(cs);
+       u32 counter, overflw;
+       unsigned long flags;
+
+       /*
+        * The counter value is only refreshed after the overflow value is read.
+        * And they must be read in strict order, hence raw spin lock added.
+        */
+
+       raw_spin_lock_irqsave(&pcs->lock, flags);
+       overflw = gpt_readl(pcs->base, TIMER_CURRENT_OVERFLOW_VALUE, 0);
+       counter = gpt_readl(pcs->base, TIMER_CURRENT_VALUE, 0);
+       raw_spin_unlock_irqrestore(&pcs->lock, flags);
+
+       return ~(cycle_t)counter;
+}
+
+static u64 notrace pistachio_read_sched_clock(void)
+{
+       return pistachio_clocksource_read_cycles(&pcs_gpt.cs);
+}
+
+static void pistachio_clksrc_set_mode(struct clocksource *cs, int timeridx,
+                       int enable)
+{
+       struct pistachio_clocksource *pcs = to_pistachio_clocksource(cs);
+       u32 val;
+
+       val = gpt_readl(pcs->base, TIMER_CFG, timeridx);
+       if (enable)
+               val |= TIMER_ME_LOCAL;
+       else
+               val &= ~TIMER_ME_LOCAL;
+
+       gpt_writel(pcs->base, val, TIMER_CFG, timeridx);
+}
+
+static void pistachio_clksrc_enable(struct clocksource *cs, int timeridx)
+{
+       struct pistachio_clocksource *pcs = to_pistachio_clocksource(cs);
+
+       /* Disable GPT local before loading reload value */
+       pistachio_clksrc_set_mode(cs, timeridx, false);
+       gpt_writel(pcs->base, RELOAD_VALUE, TIMER_RELOAD_VALUE, timeridx);
+       pistachio_clksrc_set_mode(cs, timeridx, true);
+}
+
+static void pistachio_clksrc_disable(struct clocksource *cs, int timeridx)
+{
+       /* Disable GPT local */
+       pistachio_clksrc_set_mode(cs, timeridx, false);
+}
+
+static int pistachio_clocksource_enable(struct clocksource *cs)
+{
+       pistachio_clksrc_enable(cs, 0);
+       return 0;
+}
+
+static void pistachio_clocksource_disable(struct clocksource *cs)
+{
+       pistachio_clksrc_disable(cs, 0);
+}
+
+/* Desirable clock source for pistachio platform */
+static struct pistachio_clocksource pcs_gpt = {
+       .cs =   {
+               .name           = "gptimer",
+               .rating         = 300,
+               .enable         = pistachio_clocksource_enable,
+               .disable        = pistachio_clocksource_disable,
+               .read           = pistachio_clocksource_read_cycles,
+               .mask           = CLOCKSOURCE_MASK(32),
+               .flags          = CLOCK_SOURCE_IS_CONTINUOUS |
+                                 CLOCK_SOURCE_SUSPEND_NONSTOP,
+               },
+};
+
+static void __init pistachio_clksrc_of_init(struct device_node *node)
+{
+       struct clk *sys_clk, *fast_clk;
+       struct regmap *periph_regs;
+       unsigned long rate;
+       int ret;
+
+       pcs_gpt.base = of_iomap(node, 0);
+       if (!pcs_gpt.base) {
+               pr_err("cannot iomap\n");
+               return;
+       }
+
+       periph_regs = syscon_regmap_lookup_by_phandle(node, "img,cr-periph");
+       if (IS_ERR(periph_regs)) {
+               pr_err("cannot get peripheral regmap (%lu)\n",
+                      PTR_ERR(periph_regs));
+               return;
+       }
+
+       /* Switch to using the fast counter clock */
+       ret = regmap_update_bits(periph_regs, PERIP_TIMER_CONTROL,
+                                0xf, 0x0);
+       if (ret)
+               return;
+
+       sys_clk = of_clk_get_by_name(node, "sys");
+       if (IS_ERR(sys_clk)) {
+               pr_err("clock get failed (%lu)\n", PTR_ERR(sys_clk));
+               return;
+       }
+
+       fast_clk = of_clk_get_by_name(node, "fast");
+       if (IS_ERR(fast_clk)) {
+               pr_err("clock get failed (%lu)\n", PTR_ERR(fast_clk));
+               return;
+       }
+
+       ret = clk_prepare_enable(sys_clk);
+       if (ret < 0) {
+               pr_err("failed to enable clock (%d)\n", ret);
+               return;
+       }
+
+       ret = clk_prepare_enable(fast_clk);
+       if (ret < 0) {
+               pr_err("failed to enable clock (%d)\n", ret);
+               clk_disable_unprepare(sys_clk);
+               return;
+       }
+
+       rate = clk_get_rate(fast_clk);
+
+       /* Disable irq's for clocksource usage */
+       gpt_writel(&pcs_gpt.base, 0, TIMER_IRQ_MASK, 0);
+       gpt_writel(&pcs_gpt.base, 0, TIMER_IRQ_MASK, 1);
+       gpt_writel(&pcs_gpt.base, 0, TIMER_IRQ_MASK, 2);
+       gpt_writel(&pcs_gpt.base, 0, TIMER_IRQ_MASK, 3);
+
+       /* Enable timer block */
+       writel(TIMER_ME_GLOBAL, pcs_gpt.base);
+
+       raw_spin_lock_init(&pcs_gpt.lock);
+       sched_clock_register(pistachio_read_sched_clock, 32, rate);
+       clocksource_register_hz(&pcs_gpt.cs, rate);
+}
+CLOCKSOURCE_OF_DECLARE(pistachio_gptimer, "img,pistachio-gptimer",
+                      pistachio_clksrc_of_init);
index f82cd678ce086e68da421506aceaed8d7b4f458b..2b64f6177e33cb36d9f0b965f4524f1461101576 100644 (file)
@@ -20,6 +20,7 @@ obj-$(CONFIG_GPIO_ADP5588)    += gpio-adp5588.o
 obj-$(CONFIG_GPIO_ALTERA)      += gpio-altera.o
 obj-$(CONFIG_GPIO_AMD8111)     += gpio-amd8111.o
 obj-$(CONFIG_GPIO_ARIZONA)     += gpio-arizona.o
+obj-$(CONFIG_ATH79)            += gpio-ath79.o
 obj-$(CONFIG_GPIO_BCM_KONA)    += gpio-bcm-kona.o
 obj-$(CONFIG_GPIO_BRCMSTB)     += gpio-brcmstb.o
 obj-$(CONFIG_GPIO_BT8XX)       += gpio-bt8xx.o
diff --git a/drivers/gpio/gpio-ath79.c b/drivers/gpio/gpio-ath79.c
new file mode 100644 (file)
index 0000000..03b9953
--- /dev/null
@@ -0,0 +1,204 @@
+/*
+ *  Atheros AR71XX/AR724X/AR913X GPIO API support
+ *
+ *  Copyright (C) 2010-2011 Jaiganesh Narayanan <jnarayanan@atheros.com>
+ *  Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
+ *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+ *
+ *  Parts of this file are based on Atheros' 2.6.15/2.6.31 BSP
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License version 2 as published
+ *  by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/spinlock.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/gpio.h>
+#include <linux/platform_data/gpio-ath79.h>
+#include <linux/of_device.h>
+
+#include <asm/mach-ath79/ar71xx_regs.h>
+
+static void __iomem *ath79_gpio_base;
+static u32 ath79_gpio_count;
+static DEFINE_SPINLOCK(ath79_gpio_lock);
+
+static void __ath79_gpio_set_value(unsigned gpio, int value)
+{
+       void __iomem *base = ath79_gpio_base;
+
+       if (value)
+               __raw_writel(1 << gpio, base + AR71XX_GPIO_REG_SET);
+       else
+               __raw_writel(1 << gpio, base + AR71XX_GPIO_REG_CLEAR);
+}
+
+static int __ath79_gpio_get_value(unsigned gpio)
+{
+       return (__raw_readl(ath79_gpio_base + AR71XX_GPIO_REG_IN) >> gpio) & 1;
+}
+
+static int ath79_gpio_get_value(struct gpio_chip *chip, unsigned offset)
+{
+       return __ath79_gpio_get_value(offset);
+}
+
+static void ath79_gpio_set_value(struct gpio_chip *chip,
+                                 unsigned offset, int value)
+{
+       __ath79_gpio_set_value(offset, value);
+}
+
+static int ath79_gpio_direction_input(struct gpio_chip *chip,
+                                      unsigned offset)
+{
+       void __iomem *base = ath79_gpio_base;
+       unsigned long flags;
+
+       spin_lock_irqsave(&ath79_gpio_lock, flags);
+
+       __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_OE) & ~(1 << offset),
+                    base + AR71XX_GPIO_REG_OE);
+
+       spin_unlock_irqrestore(&ath79_gpio_lock, flags);
+
+       return 0;
+}
+
+static int ath79_gpio_direction_output(struct gpio_chip *chip,
+                                       unsigned offset, int value)
+{
+       void __iomem *base = ath79_gpio_base;
+       unsigned long flags;
+
+       spin_lock_irqsave(&ath79_gpio_lock, flags);
+
+       if (value)
+               __raw_writel(1 << offset, base + AR71XX_GPIO_REG_SET);
+       else
+               __raw_writel(1 << offset, base + AR71XX_GPIO_REG_CLEAR);
+
+       __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_OE) | (1 << offset),
+                    base + AR71XX_GPIO_REG_OE);
+
+       spin_unlock_irqrestore(&ath79_gpio_lock, flags);
+
+       return 0;
+}
+
+static int ar934x_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+       void __iomem *base = ath79_gpio_base;
+       unsigned long flags;
+
+       spin_lock_irqsave(&ath79_gpio_lock, flags);
+
+       __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_OE) | (1 << offset),
+                    base + AR71XX_GPIO_REG_OE);
+
+       spin_unlock_irqrestore(&ath79_gpio_lock, flags);
+
+       return 0;
+}
+
+static int ar934x_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
+                                       int value)
+{
+       void __iomem *base = ath79_gpio_base;
+       unsigned long flags;
+
+       spin_lock_irqsave(&ath79_gpio_lock, flags);
+
+       if (value)
+               __raw_writel(1 << offset, base + AR71XX_GPIO_REG_SET);
+       else
+               __raw_writel(1 << offset, base + AR71XX_GPIO_REG_CLEAR);
+
+       __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_OE) & ~(1 << offset),
+                    base + AR71XX_GPIO_REG_OE);
+
+       spin_unlock_irqrestore(&ath79_gpio_lock, flags);
+
+       return 0;
+}
+
+static struct gpio_chip ath79_gpio_chip = {
+       .label                  = "ath79",
+       .get                    = ath79_gpio_get_value,
+       .set                    = ath79_gpio_set_value,
+       .direction_input        = ath79_gpio_direction_input,
+       .direction_output       = ath79_gpio_direction_output,
+       .base                   = 0,
+};
+
+static const struct of_device_id ath79_gpio_of_match[] = {
+       { .compatible = "qca,ar7100-gpio" },
+       { .compatible = "qca,ar9340-gpio" },
+       {},
+};
+
+static int ath79_gpio_probe(struct platform_device *pdev)
+{
+       struct ath79_gpio_platform_data *pdata = pdev->dev.platform_data;
+       struct device_node *np = pdev->dev.of_node;
+       struct resource *res;
+       bool oe_inverted;
+       int err;
+
+       if (np) {
+               err = of_property_read_u32(np, "ngpios", &ath79_gpio_count);
+               if (err) {
+                       dev_err(&pdev->dev, "ngpios property is not valid\n");
+                       return err;
+               }
+               if (ath79_gpio_count >= 32) {
+                       dev_err(&pdev->dev, "ngpios must be less than 32\n");
+                       return -EINVAL;
+               }
+               oe_inverted = of_device_is_compatible(np, "qca,ar9340-gpio");
+       } else if (pdata) {
+               ath79_gpio_count = pdata->ngpios;
+               oe_inverted = pdata->oe_inverted;
+       } else {
+               dev_err(&pdev->dev, "No DT node or platform data found\n");
+               return -EINVAL;
+       }
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       ath79_gpio_base = devm_ioremap_nocache(
+               &pdev->dev, res->start, resource_size(res));
+       if (!ath79_gpio_base)
+               return -ENOMEM;
+
+       ath79_gpio_chip.dev = &pdev->dev;
+       ath79_gpio_chip.ngpio = ath79_gpio_count;
+       if (oe_inverted) {
+               ath79_gpio_chip.direction_input = ar934x_gpio_direction_input;
+               ath79_gpio_chip.direction_output = ar934x_gpio_direction_output;
+       }
+
+       err = gpiochip_add(&ath79_gpio_chip);
+       if (err) {
+               dev_err(&pdev->dev,
+                       "cannot add AR71xx GPIO chip, error=%d", err);
+               return err;
+       }
+
+       return 0;
+}
+
+static struct platform_driver ath79_gpio_driver = {
+       .driver = {
+               .name = "ath79-gpio",
+               .of_match_table = ath79_gpio_of_match,
+       },
+       .probe = ath79_gpio_probe,
+};
+
+module_platform_driver(ath79_gpio_driver);
index e956e81cd4e6deee087cf31a652ae75f5f8462ef..62c5814c796bcfbaf7af1eb52e4777f1bae28d68 100644 (file)
@@ -7,6 +7,7 @@
 #include <linux/input-polldev.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
+#include <linux/gpio.h>
 
 #include <asm/mach-rc32434/gpio.h>
 #include <asm/mach-rc32434/rb.h>
index ff4be0515a0dc7dbb206ae0a84968f922817101e..7d4616963b5ae6bc7e4b578265f5cf0b7d243fbc 100644 (file)
@@ -42,20 +42,46 @@ static struct irq_chip gic_level_irq_controller, gic_edge_irq_controller;
 
 static void __gic_irq_dispatch(void);
 
-static inline unsigned int gic_read(unsigned int reg)
+static inline u32 gic_read32(unsigned int reg)
 {
        return __raw_readl(gic_base + reg);
 }
 
-static inline void gic_write(unsigned int reg, unsigned int val)
+static inline u64 gic_read64(unsigned int reg)
 {
-       __raw_writel(val, gic_base + reg);
+       return __raw_readq(gic_base + reg);
 }
 
-static inline void gic_update_bits(unsigned int reg, unsigned int mask,
-                                  unsigned int val)
+static inline unsigned long gic_read(unsigned int reg)
 {
-       unsigned int regval;
+       if (!mips_cm_is64)
+               return gic_read32(reg);
+       else
+               return gic_read64(reg);
+}
+
+static inline void gic_write32(unsigned int reg, u32 val)
+{
+       return __raw_writel(val, gic_base + reg);
+}
+
+static inline void gic_write64(unsigned int reg, u64 val)
+{
+       return __raw_writeq(val, gic_base + reg);
+}
+
+static inline void gic_write(unsigned int reg, unsigned long val)
+{
+       if (!mips_cm_is64)
+               return gic_write32(reg, (u32)val);
+       else
+               return gic_write64(reg, (u64)val);
+}
+
+static inline void gic_update_bits(unsigned int reg, unsigned long mask,
+                                  unsigned long val)
+{
+       unsigned long regval;
 
        regval = gic_read(reg);
        regval &= ~mask;
@@ -66,40 +92,40 @@ static inline void gic_update_bits(unsigned int reg, unsigned int mask,
 static inline void gic_reset_mask(unsigned int intr)
 {
        gic_write(GIC_REG(SHARED, GIC_SH_RMASK) + GIC_INTR_OFS(intr),
-                 1 << GIC_INTR_BIT(intr));
+                 1ul << GIC_INTR_BIT(intr));
 }
 
 static inline void gic_set_mask(unsigned int intr)
 {
        gic_write(GIC_REG(SHARED, GIC_SH_SMASK) + GIC_INTR_OFS(intr),
-                 1 << GIC_INTR_BIT(intr));
+                 1ul << GIC_INTR_BIT(intr));
 }
 
 static inline void gic_set_polarity(unsigned int intr, unsigned int pol)
 {
        gic_update_bits(GIC_REG(SHARED, GIC_SH_SET_POLARITY) +
-                       GIC_INTR_OFS(intr), 1 << GIC_INTR_BIT(intr),
-                       pol << GIC_INTR_BIT(intr));
+                       GIC_INTR_OFS(intr), 1ul << GIC_INTR_BIT(intr),
+                       (unsigned long)pol << GIC_INTR_BIT(intr));
 }
 
 static inline void gic_set_trigger(unsigned int intr, unsigned int trig)
 {
        gic_update_bits(GIC_REG(SHARED, GIC_SH_SET_TRIGGER) +
-                       GIC_INTR_OFS(intr), 1 << GIC_INTR_BIT(intr),
-                       trig << GIC_INTR_BIT(intr));
+                       GIC_INTR_OFS(intr), 1ul << GIC_INTR_BIT(intr),
+                       (unsigned long)trig << GIC_INTR_BIT(intr));
 }
 
 static inline void gic_set_dual_edge(unsigned int intr, unsigned int dual)
 {
        gic_update_bits(GIC_REG(SHARED, GIC_SH_SET_DUAL) + GIC_INTR_OFS(intr),
-                       1 << GIC_INTR_BIT(intr),
-                       dual << GIC_INTR_BIT(intr));
+                       1ul << GIC_INTR_BIT(intr),
+                       (unsigned long)dual << GIC_INTR_BIT(intr));
 }
 
 static inline void gic_map_to_pin(unsigned int intr, unsigned int pin)
 {
-       gic_write(GIC_REG(SHARED, GIC_SH_INTR_MAP_TO_PIN_BASE) +
-                 GIC_SH_MAP_TO_PIN(intr), GIC_MAP_TO_PIN_MSK | pin);
+       gic_write32(GIC_REG(SHARED, GIC_SH_INTR_MAP_TO_PIN_BASE) +
+                   GIC_SH_MAP_TO_PIN(intr), GIC_MAP_TO_PIN_MSK | pin);
 }
 
 static inline void gic_map_to_vpe(unsigned int intr, unsigned int vpe)
@@ -114,10 +140,13 @@ cycle_t gic_read_count(void)
 {
        unsigned int hi, hi2, lo;
 
+       if (mips_cm_is64)
+               return (cycle_t)gic_read(GIC_REG(SHARED, GIC_SH_COUNTER));
+
        do {
-               hi = gic_read(GIC_REG(SHARED, GIC_SH_COUNTER_63_32));
-               lo = gic_read(GIC_REG(SHARED, GIC_SH_COUNTER_31_00));
-               hi2 = gic_read(GIC_REG(SHARED, GIC_SH_COUNTER_63_32));
+               hi = gic_read32(GIC_REG(SHARED, GIC_SH_COUNTER_63_32));
+               lo = gic_read32(GIC_REG(SHARED, GIC_SH_COUNTER_31_00));
+               hi2 = gic_read32(GIC_REG(SHARED, GIC_SH_COUNTER_63_32));
        } while (hi2 != hi);
 
        return (((cycle_t) hi) << 32) + lo;
@@ -136,10 +165,14 @@ unsigned int gic_get_count_width(void)
 
 void gic_write_compare(cycle_t cnt)
 {
-       gic_write(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_HI),
-                               (int)(cnt >> 32));
-       gic_write(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_LO),
-                               (int)(cnt & 0xffffffff));
+       if (mips_cm_is64) {
+               gic_write(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE), cnt);
+       } else {
+               gic_write32(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_HI),
+                                       (int)(cnt >> 32));
+               gic_write32(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_LO),
+                                       (int)(cnt & 0xffffffff));
+       }
 }
 
 void gic_write_cpu_compare(cycle_t cnt, int cpu)
@@ -149,10 +182,15 @@ void gic_write_cpu_compare(cycle_t cnt, int cpu)
        local_irq_save(flags);
 
        gic_write(GIC_REG(VPE_LOCAL, GIC_VPE_OTHER_ADDR), cpu);
-       gic_write(GIC_REG(VPE_OTHER, GIC_VPE_COMPARE_HI),
-                               (int)(cnt >> 32));
-       gic_write(GIC_REG(VPE_OTHER, GIC_VPE_COMPARE_LO),
-                               (int)(cnt & 0xffffffff));
+
+       if (mips_cm_is64) {
+               gic_write(GIC_REG(VPE_OTHER, GIC_VPE_COMPARE), cnt);
+       } else {
+               gic_write32(GIC_REG(VPE_OTHER, GIC_VPE_COMPARE_HI),
+                                       (int)(cnt >> 32));
+               gic_write32(GIC_REG(VPE_OTHER, GIC_VPE_COMPARE_LO),
+                                       (int)(cnt & 0xffffffff));
+       }
 
        local_irq_restore(flags);
 }
@@ -161,8 +199,11 @@ cycle_t gic_read_compare(void)
 {
        unsigned int hi, lo;
 
-       hi = gic_read(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_HI));
-       lo = gic_read(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_LO));
+       if (mips_cm_is64)
+               return (cycle_t)gic_read(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE));
+
+       hi = gic_read32(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_HI));
+       lo = gic_read32(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_LO));
 
        return (((cycle_t) hi) << 32) + lo;
 }
@@ -197,7 +238,7 @@ static bool gic_local_irq_is_routable(int intr)
        if (cpu_has_veic)
                return true;
 
-       vpe_ctl = gic_read(GIC_REG(VPE_LOCAL, GIC_VPE_CTL));
+       vpe_ctl = gic_read32(GIC_REG(VPE_LOCAL, GIC_VPE_CTL));
        switch (intr) {
        case GIC_LOCAL_INT_TIMER:
                return vpe_ctl & GIC_VPE_CTL_TIMER_RTBL_MSK;
@@ -263,7 +304,7 @@ int gic_get_c0_fdc_int(void)
 
 static void gic_handle_shared_int(bool chained)
 {
-       unsigned int i, intr, virq;
+       unsigned int i, intr, virq, gic_reg_step = mips_cm_is64 ? 8 : 4;
        unsigned long *pcpu_mask;
        unsigned long pending_reg, intrmask_reg;
        DECLARE_BITMAP(pending, GIC_MAX_INTRS);
@@ -278,8 +319,8 @@ static void gic_handle_shared_int(bool chained)
        for (i = 0; i < BITS_TO_LONGS(gic_shared_intrs); i++) {
                pending[i] = gic_read(pending_reg);
                intrmask[i] = gic_read(intrmask_reg);
-               pending_reg += 0x4;
-               intrmask_reg += 0x4;
+               pending_reg += gic_reg_step;
+               intrmask_reg += gic_reg_step;
        }
 
        bitmap_and(pending, pending, intrmask, gic_shared_intrs);
@@ -429,8 +470,8 @@ static void gic_handle_local_int(bool chained)
        unsigned long pending, masked;
        unsigned int intr, virq;
 
-       pending = gic_read(GIC_REG(VPE_LOCAL, GIC_VPE_PEND));
-       masked = gic_read(GIC_REG(VPE_LOCAL, GIC_VPE_MASK));
+       pending = gic_read32(GIC_REG(VPE_LOCAL, GIC_VPE_PEND));
+       masked = gic_read32(GIC_REG(VPE_LOCAL, GIC_VPE_MASK));
 
        bitmap_and(&pending, &pending, &masked, GIC_NUM_LOCAL_INTRS);
 
@@ -453,14 +494,14 @@ static void gic_mask_local_irq(struct irq_data *d)
 {
        int intr = GIC_HWIRQ_TO_LOCAL(d->hwirq);
 
-       gic_write(GIC_REG(VPE_LOCAL, GIC_VPE_RMASK), 1 << intr);
+       gic_write32(GIC_REG(VPE_LOCAL, GIC_VPE_RMASK), 1 << intr);
 }
 
 static void gic_unmask_local_irq(struct irq_data *d)
 {
        int intr = GIC_HWIRQ_TO_LOCAL(d->hwirq);
 
-       gic_write(GIC_REG(VPE_LOCAL, GIC_VPE_SMASK), 1 << intr);
+       gic_write32(GIC_REG(VPE_LOCAL, GIC_VPE_SMASK), 1 << intr);
 }
 
 static struct irq_chip gic_local_irq_controller = {
@@ -478,7 +519,7 @@ static void gic_mask_local_irq_all_vpes(struct irq_data *d)
        spin_lock_irqsave(&gic_lock, flags);
        for (i = 0; i < gic_vpes; i++) {
                gic_write(GIC_REG(VPE_LOCAL, GIC_VPE_OTHER_ADDR), i);
-               gic_write(GIC_REG(VPE_OTHER, GIC_VPE_RMASK), 1 << intr);
+               gic_write32(GIC_REG(VPE_OTHER, GIC_VPE_RMASK), 1 << intr);
        }
        spin_unlock_irqrestore(&gic_lock, flags);
 }
@@ -492,7 +533,7 @@ static void gic_unmask_local_irq_all_vpes(struct irq_data *d)
        spin_lock_irqsave(&gic_lock, flags);
        for (i = 0; i < gic_vpes; i++) {
                gic_write(GIC_REG(VPE_LOCAL, GIC_VPE_OTHER_ADDR), i);
-               gic_write(GIC_REG(VPE_OTHER, GIC_VPE_SMASK), 1 << intr);
+               gic_write32(GIC_REG(VPE_OTHER, GIC_VPE_SMASK), 1 << intr);
        }
        spin_unlock_irqrestore(&gic_lock, flags);
 }
@@ -612,7 +653,7 @@ static void __init gic_basic_init(void)
                for (j = 0; j < GIC_NUM_LOCAL_INTRS; j++) {
                        if (!gic_local_irq_is_routable(j))
                                continue;
-                       gic_write(GIC_REG(VPE_OTHER, GIC_VPE_RMASK), 1 << j);
+                       gic_write32(GIC_REG(VPE_OTHER, GIC_VPE_RMASK), 1 << j);
                }
        }
 }
@@ -657,27 +698,32 @@ static int gic_local_irq_domain_map(struct irq_domain *d, unsigned int virq,
 
                switch (intr) {
                case GIC_LOCAL_INT_WD:
-                       gic_write(GIC_REG(VPE_OTHER, GIC_VPE_WD_MAP), val);
+                       gic_write32(GIC_REG(VPE_OTHER, GIC_VPE_WD_MAP), val);
                        break;
                case GIC_LOCAL_INT_COMPARE:
-                       gic_write(GIC_REG(VPE_OTHER, GIC_VPE_COMPARE_MAP), val);
+                       gic_write32(GIC_REG(VPE_OTHER, GIC_VPE_COMPARE_MAP),
+                                   val);
                        break;
                case GIC_LOCAL_INT_TIMER:
                        /* CONFIG_MIPS_CMP workaround (see __gic_init) */
                        val = GIC_MAP_TO_PIN_MSK | timer_cpu_pin;
-                       gic_write(GIC_REG(VPE_OTHER, GIC_VPE_TIMER_MAP), val);
+                       gic_write32(GIC_REG(VPE_OTHER, GIC_VPE_TIMER_MAP),
+                                   val);
                        break;
                case GIC_LOCAL_INT_PERFCTR:
-                       gic_write(GIC_REG(VPE_OTHER, GIC_VPE_PERFCTR_MAP), val);
+                       gic_write32(GIC_REG(VPE_OTHER, GIC_VPE_PERFCTR_MAP),
+                                   val);
                        break;
                case GIC_LOCAL_INT_SWINT0:
-                       gic_write(GIC_REG(VPE_OTHER, GIC_VPE_SWINT0_MAP), val);
+                       gic_write32(GIC_REG(VPE_OTHER, GIC_VPE_SWINT0_MAP),
+                                   val);
                        break;
                case GIC_LOCAL_INT_SWINT1:
-                       gic_write(GIC_REG(VPE_OTHER, GIC_VPE_SWINT1_MAP), val);
+                       gic_write32(GIC_REG(VPE_OTHER, GIC_VPE_SWINT1_MAP),
+                                   val);
                        break;
                case GIC_LOCAL_INT_FDC:
-                       gic_write(GIC_REG(VPE_OTHER, GIC_VPE_FDC_MAP), val);
+                       gic_write32(GIC_REG(VPE_OTHER, GIC_VPE_FDC_MAP), val);
                        break;
                default:
                        pr_err("Invalid local IRQ %d\n", intr);
@@ -782,7 +828,7 @@ static void __init __gic_init(unsigned long gic_base_addr,
                 */
                if (IS_ENABLED(CONFIG_MIPS_CMP) &&
                    gic_local_irq_is_routable(GIC_LOCAL_INT_TIMER)) {
-                       timer_cpu_pin = gic_read(GIC_REG(VPE_LOCAL,
+                       timer_cpu_pin = gic_read32(GIC_REG(VPE_LOCAL,
                                                         GIC_VPE_TIMER_MAP)) &
                                        GIC_MAP_MSK;
                        irq_set_chained_handler(MIPS_CPU_IRQ_BASE +
index dd9430043536541b577a4b90418cebb33a67baf3..cba3d9fcb46535946c2c1b67ef660f0cca9d803f 100644 (file)
@@ -41,6 +41,8 @@
 #include <linux/gpio.h>
 #include <linux/atomic.h>
 
+#include <asm/mach-ar7/ar7.h>
+
 MODULE_AUTHOR("Eugene Konev <ejka@imfi.kspu.ru>");
 MODULE_DESCRIPTION("TI AR7 ethernet driver (CPMAC)");
 MODULE_LICENSE("GPL");
index 22853d33da052532b3c0cda3aea6615ddd83a3bb..d1a33a927f6d1295f3cadaae26ea78d343ecab87 100644 (file)
@@ -70,7 +70,14 @@ static irqreturn_t cvm_oct_do_interrupt(int cpl, void *dev_id)
  */
 static inline int cvm_oct_check_rcv_error(cvmx_wqe_t *work)
 {
-       if ((work->word2.snoip.err_code == 10) && (work->len <= 64)) {
+       int port;
+
+       if (octeon_has_feature(OCTEON_FEATURE_PKND))
+               port = work->word0.pip.cn68xx.pknd;
+       else
+               port = work->word1.cn38xx.ipprt;
+
+       if ((work->word2.snoip.err_code == 10) && (work->word1.len <= 64)) {
                /*
                 * Ignore length errors on min size packets. Some
                 * equipment incorrectly pads packets to 64+4FCS
@@ -87,8 +94,8 @@ static inline int cvm_oct_check_rcv_error(cvmx_wqe_t *work)
                 * packet to determine if we can remove a non spec
                 * preamble and generate a correct packet.
                 */
-               int interface = cvmx_helper_get_interface_num(work->ipprt);
-               int index = cvmx_helper_get_interface_index_num(work->ipprt);
+               int interface = cvmx_helper_get_interface_num(port);
+               int index = cvmx_helper_get_interface_index_num(port);
                union cvmx_gmxx_rxx_frm_ctl gmxx_rxx_frm_ctl;
 
                gmxx_rxx_frm_ctl.u64 =
@@ -99,7 +106,7 @@ static inline int cvm_oct_check_rcv_error(cvmx_wqe_t *work)
                            cvmx_phys_to_ptr(work->packet_ptr.s.addr);
                        int i = 0;
 
-                       while (i < work->len - 1) {
+                       while (i < work->word1.len - 1) {
                                if (*ptr != 0x55)
                                        break;
                                ptr++;
@@ -109,18 +116,18 @@ static inline int cvm_oct_check_rcv_error(cvmx_wqe_t *work)
                        if (*ptr == 0xd5) {
                                /*
                                  printk_ratelimited("Port %d received 0xd5 preamble\n",
-                                         work->ipprt);
+                                         port);
                                 */
                                work->packet_ptr.s.addr += i + 1;
-                               work->len -= i + 5;
+                               work->word1.len -= i + 5;
                        } else if ((*ptr & 0xf) == 0xd) {
                                /*
                                  printk_ratelimited("Port %d received 0x?d preamble\n",
-                                         work->ipprt);
+                                         port);
                                 */
                                work->packet_ptr.s.addr += i;
-                               work->len -= i + 4;
-                               for (i = 0; i < work->len; i++) {
+                               work->word1.len -= i + 4;
+                               for (i = 0; i < work->word1.len; i++) {
                                        *ptr =
                                            ((*ptr & 0xf0) >> 4) |
                                            ((*(ptr + 1) & 0xf) << 4);
@@ -128,7 +135,7 @@ static inline int cvm_oct_check_rcv_error(cvmx_wqe_t *work)
                                }
                        } else {
                                printk_ratelimited("Port %d unknown preamble, packet dropped\n",
-                                                  work->ipprt);
+                                                  port);
                                /*
                                   cvmx_helper_dump_packet(work);
                                 */
@@ -138,7 +145,7 @@ static inline int cvm_oct_check_rcv_error(cvmx_wqe_t *work)
                }
        } else {
                printk_ratelimited("Port %d receive error code %d, packet dropped\n",
-                                  work->ipprt, work->word2.snoip.err_code);
+                                  port, work->word2.snoip.err_code);
                cvm_oct_free_work(work);
                return 1;
        }
@@ -172,9 +179,16 @@ static int cvm_oct_napi_poll(struct napi_struct *napi, int budget)
        }
 
        /* Only allow work for our group (and preserve priorities) */
-       old_group_mask = cvmx_read_csr(CVMX_POW_PP_GRP_MSKX(coreid));
-       cvmx_write_csr(CVMX_POW_PP_GRP_MSKX(coreid),
-                      (old_group_mask & ~0xFFFFull) | 1 << pow_receive_group);
+       if (OCTEON_IS_MODEL(OCTEON_CN68XX)) {
+               old_group_mask = cvmx_read_csr(CVMX_SSO_PPX_GRP_MSK(coreid));
+               cvmx_write_csr(CVMX_SSO_PPX_GRP_MSK(coreid),
+                               1ull << pow_receive_group);
+               cvmx_read_csr(CVMX_SSO_PPX_GRP_MSK(coreid)); /* Flush */
+       } else {
+               old_group_mask = cvmx_read_csr(CVMX_POW_PP_GRP_MSKX(coreid));
+               cvmx_write_csr(CVMX_POW_PP_GRP_MSKX(coreid),
+                       (old_group_mask & ~0xFFFFull) | 1 << pow_receive_group);
+       }
 
        if (USE_ASYNC_IOBDMA) {
                cvmx_pow_work_request_async(CVMX_SCR_SCRATCH, CVMX_POW_NO_WAIT);
@@ -186,6 +200,7 @@ static int cvm_oct_napi_poll(struct napi_struct *napi, int budget)
                struct sk_buff **pskb = NULL;
                int skb_in_hw;
                cvmx_wqe_t *work;
+               int port;
 
                if (USE_ASYNC_IOBDMA && did_work_request)
                        work = cvmx_pow_work_response_async(CVMX_SCR_SCRATCH);
@@ -195,12 +210,19 @@ static int cvm_oct_napi_poll(struct napi_struct *napi, int budget)
                prefetch(work);
                did_work_request = 0;
                if (work == NULL) {
-                       union cvmx_pow_wq_int wq_int;
+                       if (OCTEON_IS_MODEL(OCTEON_CN68XX)) {
+                               cvmx_write_csr(CVMX_SSO_WQ_IQ_DIS,
+                                              1ull << pow_receive_group);
+                               cvmx_write_csr(CVMX_SSO_WQ_INT,
+                                              1ull << pow_receive_group);
+                       } else {
+                               union cvmx_pow_wq_int wq_int;
 
-                       wq_int.u64 = 0;
-                       wq_int.s.iq_dis = 1 << pow_receive_group;
-                       wq_int.s.wq_int = 1 << pow_receive_group;
-                       cvmx_write_csr(CVMX_POW_WQ_INT, wq_int.u64);
+                               wq_int.u64 = 0;
+                               wq_int.s.iq_dis = 1 << pow_receive_group;
+                               wq_int.s.wq_int = 1 << pow_receive_group;
+                               cvmx_write_csr(CVMX_POW_WQ_INT, wq_int.u64);
+                       }
                        break;
                }
                pskb = (struct sk_buff **)(cvm_oct_get_buffer_ptr(work->packet_ptr) -
@@ -220,7 +242,13 @@ static int cvm_oct_napi_poll(struct napi_struct *napi, int budget)
                        prefetch(&skb->head);
                        prefetch(&skb->len);
                }
-               prefetch(cvm_oct_device[work->ipprt]);
+
+               if (octeon_has_feature(OCTEON_FEATURE_PKND))
+                       port = work->word0.pip.cn68xx.pknd;
+               else
+                       port = work->word1.cn38xx.ipprt;
+
+               prefetch(cvm_oct_device[port]);
 
                /* Immediately throw away all packets with receive errors */
                if (unlikely(work->word2.snoip.rcv_error)) {
@@ -237,7 +265,7 @@ static int cvm_oct_napi_poll(struct napi_struct *napi, int budget)
                        skb->data = skb->head + work->packet_ptr.s.addr -
                                cvmx_ptr_to_phys(skb->head);
                        prefetch(skb->data);
-                       skb->len = work->len;
+                       skb->len = work->word1.len;
                        skb_set_tail_pointer(skb, skb->len);
                        packet_not_copied = 1;
                } else {
@@ -245,7 +273,7 @@ static int cvm_oct_napi_poll(struct napi_struct *napi, int budget)
                         * We have to copy the packet. First allocate
                         * an skbuff for it.
                         */
-                       skb = dev_alloc_skb(work->len);
+                       skb = dev_alloc_skb(work->word1.len);
                        if (!skb) {
                                cvm_oct_free_work(work);
                                continue;
@@ -268,13 +296,14 @@ static int cvm_oct_napi_poll(struct napi_struct *napi, int budget)
                                        else
                                                ptr += 6;
                                }
-                               memcpy(skb_put(skb, work->len), ptr, work->len);
+                               memcpy(skb_put(skb, work->word1.len), ptr,
+                                      work->word1.len);
                                /* No packet buffers to free */
                        } else {
                                int segments = work->word2.s.bufs;
                                union cvmx_buf_ptr segment_ptr =
                                    work->packet_ptr;
-                               int len = work->len;
+                               int len = work->word1.len;
 
                                while (segments--) {
                                        union cvmx_buf_ptr next_ptr =
@@ -310,10 +339,9 @@ static int cvm_oct_napi_poll(struct napi_struct *napi, int budget)
                        }
                        packet_not_copied = 0;
                }
-
-               if (likely((work->ipprt < TOTAL_NUMBER_OF_PORTS) &&
-                          cvm_oct_device[work->ipprt])) {
-                       struct net_device *dev = cvm_oct_device[work->ipprt];
+               if (likely((port < TOTAL_NUMBER_OF_PORTS) &&
+                          cvm_oct_device[port])) {
+                       struct net_device *dev = cvm_oct_device[port];
                        struct octeon_ethernet *priv = netdev_priv(dev);
 
                        /*
@@ -333,7 +361,7 @@ static int cvm_oct_napi_poll(struct napi_struct *napi, int budget)
                                        skb->ip_summed = CHECKSUM_UNNECESSARY;
 
                                /* Increment RX stats for virtual ports */
-                               if (work->ipprt >= CVMX_PIP_NUM_INPUT_PORTS) {
+                               if (port >= CVMX_PIP_NUM_INPUT_PORTS) {
 #ifdef CONFIG_64BIT
                                        atomic64_add(1,
                                                     (atomic64_t *)&priv->stats.rx_packets);
@@ -368,7 +396,7 @@ static int cvm_oct_napi_poll(struct napi_struct *napi, int budget)
                         * doesn't exist.
                         */
                        printk_ratelimited("Port %d not controlled by Linux, packet dropped\n",
-                                  work->ipprt);
+                                  port);
                        dev_kfree_skb_irq(skb);
                }
                /*
@@ -390,7 +418,13 @@ static int cvm_oct_napi_poll(struct napi_struct *napi, int budget)
                }
        }
        /* Restore the original POW group mask */
-       cvmx_write_csr(CVMX_POW_PP_GRP_MSKX(coreid), old_group_mask);
+       if (OCTEON_IS_MODEL(OCTEON_CN68XX)) {
+               cvmx_write_csr(CVMX_SSO_PPX_GRP_MSK(coreid), old_group_mask);
+               cvmx_read_csr(CVMX_SSO_PPX_GRP_MSK(coreid)); /* Flush */
+       } else {
+               cvmx_write_csr(CVMX_POW_PP_GRP_MSKX(coreid), old_group_mask);
+       }
+
        if (USE_ASYNC_IOBDMA) {
                /* Restore the scratch area */
                cvmx_scratch_write64(CVMX_SCR_SCRATCH, old_scratch);
@@ -422,8 +456,6 @@ void cvm_oct_rx_initialize(void)
 {
        int i;
        struct net_device *dev_for_napi = NULL;
-       union cvmx_pow_wq_int_thrx int_thr;
-       union cvmx_pow_wq_int_pc int_pc;
 
        for (i = 0; i < TOTAL_NUMBER_OF_PORTS; i++) {
                if (cvm_oct_device[i]) {
@@ -449,15 +481,34 @@ void cvm_oct_rx_initialize(void)
 
        disable_irq_nosync(OCTEON_IRQ_WORKQ0 + pow_receive_group);
 
-       int_thr.u64 = 0;
-       int_thr.s.tc_en = 1;
-       int_thr.s.tc_thr = 1;
        /* Enable POW interrupt when our port has at least one packet */
-       cvmx_write_csr(CVMX_POW_WQ_INT_THRX(pow_receive_group), int_thr.u64);
-
-       int_pc.u64 = 0;
-       int_pc.s.pc_thr = 5;
-       cvmx_write_csr(CVMX_POW_WQ_INT_PC, int_pc.u64);
+       if (OCTEON_IS_MODEL(OCTEON_CN68XX)) {
+               union cvmx_sso_wq_int_thrx int_thr;
+               union cvmx_pow_wq_int_pc int_pc;
+
+               int_thr.u64 = 0;
+               int_thr.s.tc_en = 1;
+               int_thr.s.tc_thr = 1;
+               cvmx_write_csr(CVMX_SSO_WQ_INT_THRX(pow_receive_group),
+                              int_thr.u64);
+
+               int_pc.u64 = 0;
+               int_pc.s.pc_thr = 5;
+               cvmx_write_csr(CVMX_SSO_WQ_INT_PC, int_pc.u64);
+       } else {
+               union cvmx_pow_wq_int_thrx int_thr;
+               union cvmx_pow_wq_int_pc int_pc;
+
+               int_thr.u64 = 0;
+               int_thr.s.tc_en = 1;
+               int_thr.s.tc_thr = 1;
+               cvmx_write_csr(CVMX_POW_WQ_INT_THRX(pow_receive_group),
+                              int_thr.u64);
+
+               int_pc.u64 = 0;
+               int_pc.s.pc_thr = 5;
+               cvmx_write_csr(CVMX_POW_WQ_INT_PC, int_pc.u64);
+       }
 
        /* Schedule NAPI now. This will indirectly enable the interrupt. */
        napi_schedule(&cvm_oct_napi);
index 7c1c1b052b7d172a7ec7eb8fedc11a96af3f92c0..588354756c57e5e94608d2ffdc0cb61d76b20a9c 100644 (file)
@@ -589,13 +589,14 @@ int cvm_oct_xmit_pow(struct sk_buff *skb, struct net_device *dev)
         * Fill in some of the work queue fields. We may need to add
         * more if the software at the other end needs them.
         */
-       work->hw_chksum = skb->csum;
-       work->len = skb->len;
-       work->ipprt = priv->port;
-       work->qos = priv->port & 0x7;
-       work->grp = pow_send_group;
-       work->tag_type = CVMX_HELPER_INPUT_TAG_TYPE;
-       work->tag = pow_send_group;     /* FIXME */
+       if (!OCTEON_IS_MODEL(OCTEON_CN68XX))
+               work->word0.pip.cn38xx.hw_chksum = skb->csum;
+       work->word1.len = skb->len;
+       cvmx_wqe_set_port(work, priv->port);
+       cvmx_wqe_set_qos(work, priv->port & 0x7);
+       cvmx_wqe_set_grp(work, pow_send_group);
+       work->word1.tag_type = CVMX_HELPER_INPUT_TAG_TYPE;
+       work->word1.tag = pow_send_group;       /* FIXME */
        /* Default to zero. Sets of zero later are commented out */
        work->word2.u64 = 0;
        work->word2.s.bufs = 1;
@@ -675,8 +676,8 @@ int cvm_oct_xmit_pow(struct sk_buff *skb, struct net_device *dev)
        }
 
        /* Submit the packet to the POW */
-       cvmx_pow_work_submit(work, work->tag, work->tag_type, work->qos,
-                            work->grp);
+       cvmx_pow_work_submit(work, work->word1.tag, work->word1.tag_type,
+                            cvmx_wqe_get_qos(work), cvmx_wqe_get_grp(work));
        priv->stats.tx_packets++;
        priv->stats.tx_bytes += skb->len;
        dev_consume_skb_any(skb);
index 1ba789a7741bd2514c098ea4ffa8b828c11f6c07..45f024bc5e33f777d2a320633dff9eb55dfac64d 100644 (file)
@@ -8,6 +8,10 @@
  * published by the Free Software Foundation.
  */
 
+#include <asm/octeon/cvmx-pip.h>
+#include <asm/octeon/cvmx-helper.h>
+#include <asm/octeon/cvmx-helper-util.h>
+
 /**
  * cvm_oct_get_buffer_ptr - convert packet data address to pointer
  * @packet_ptr: Packet data hardware address
@@ -28,14 +32,12 @@ static inline void *cvm_oct_get_buffer_ptr(union cvmx_buf_ptr packet_ptr)
  */
 static inline int INTERFACE(int ipd_port)
 {
-       if (ipd_port < 32)      /* Interface 0 or 1 for RGMII,GMII,SPI, etc */
-               return ipd_port >> 4;
-       else if (ipd_port < 36) /* Interface 2 for NPI */
-               return 2;
-       else if (ipd_port < 40) /* Interface 3 for loopback */
-               return 3;
-       else if (ipd_port == 40)        /* Non existent interface for POW0 */
-               return 4;
+       int interface = cvmx_helper_get_interface_num(ipd_port);
+
+       if (interface >= 0)
+               return interface;
+       else if (ipd_port == CVMX_PIP_NUM_INPUT_PORTS)
+               return 10;
        panic("Illegal ipd_port %d passed to INTERFACE\n", ipd_port);
 }
 
@@ -47,7 +49,5 @@ static inline int INTERFACE(int ipd_port)
  */
 static inline int INDEX(int ipd_port)
 {
-       if (ipd_port < 32)
-               return ipd_port & 15;
-       return ipd_port & 3;
+       return cvmx_helper_get_interface_index_num(ipd_port);
 }
index f9dba23a375914fc3fe4807f901860300e9bfc64..fbde4191e717b972125092757656ca4b3899cce0 100644 (file)
@@ -152,7 +152,7 @@ static void cvm_oct_configure_common_hw(void)
                             num_packet_buffers);
        if (CVMX_FPA_OUTPUT_BUFFER_POOL != CVMX_FPA_PACKET_POOL)
                cvm_oct_mem_fill_fpa(CVMX_FPA_OUTPUT_BUFFER_POOL,
-                                    CVMX_FPA_OUTPUT_BUFFER_POOL_SIZE, 128);
+                                    CVMX_FPA_OUTPUT_BUFFER_POOL_SIZE, 1024);
 
 #ifdef __LITTLE_ENDIAN
        {
@@ -859,7 +859,10 @@ static int cvm_oct_remove(struct platform_device *pdev)
        int port;
 
        /* Disable POW interrupt */
-       cvmx_write_csr(CVMX_POW_WQ_INT_THRX(pow_receive_group), 0);
+       if (OCTEON_IS_MODEL(OCTEON_CN68XX))
+               cvmx_write_csr(CVMX_SSO_WQ_INT_THRX(pow_receive_group), 0);
+       else
+               cvmx_write_csr(CVMX_POW_WQ_INT_THRX(pow_receive_group), 0);
 
        cvmx_ipd_disable();
 
index 358323c83b4f340dec1a915ef923145fb972d933..a8c8cfd52a23b862561b1211fe5f4330da909723 100644 (file)
@@ -879,6 +879,11 @@ static const struct tty_operations mips_ejtag_fdc_tty_ops = {
        .chars_in_buffer        = mips_ejtag_fdc_tty_chars_in_buffer,
 };
 
+int __weak get_c0_fdc_int(void)
+{
+       return -1;
+}
+
 static int mips_ejtag_fdc_tty_probe(struct mips_cdmm_device *dev)
 {
        int ret, nport;
@@ -967,9 +972,7 @@ static int mips_ejtag_fdc_tty_probe(struct mips_cdmm_device *dev)
        wake_up_process(priv->thread);
 
        /* Look for an FDC IRQ */
-       priv->irq = -1;
-       if (get_c0_fdc_int)
-               priv->irq = get_c0_fdc_int();
+       priv->irq = get_c0_fdc_int();
 
        /* Try requesting the IRQ */
        if (priv->irq >= 0) {
index 9b1ad3734911bce05c2554a079ac715cad01addd..4e6861605050489e4ca3df78d94520993805c0ce 100644 (file)
 
 /* Shared Global Counter */
 #define GIC_SH_COUNTER_31_00_OFS       0x0010
+/* 64-bit counter register for CM3 */
+#define GIC_SH_COUNTER_OFS             GIC_SH_COUNTER_31_00_OFS
 #define GIC_SH_COUNTER_63_32_OFS       0x0014
 #define GIC_SH_REVISIONID_OFS          0x0020
 
 /* Convert an interrupt number to a byte offset/bit for multi-word registers */
-#define GIC_INTR_OFS(intr)             (((intr) / 32) * 4)
-#define GIC_INTR_BIT(intr)             ((intr) % 32)
+#define GIC_INTR_OFS(intr) ({                          \
+       unsigned bits = mips_cm_is64 ? 64 : 32;         \
+       unsigned reg_idx = (intr) / bits;               \
+       unsigned reg_width = bits / 8;                  \
+                                                       \
+       reg_idx * reg_width;                            \
+})
+#define GIC_INTR_BIT(intr)             ((intr) % (mips_cm_is64 ? 64 : 32))
 
 /* Polarity : Reset Value is always 0 */
 #define GIC_SH_SET_POLARITY_OFS                0x0100
 #define GIC_VPE_WD_COUNT0_OFS          0x0094
 #define GIC_VPE_WD_INITIAL0_OFS                0x0098
 #define GIC_VPE_COMPARE_LO_OFS         0x00a0
+/* 64-bit Compare register on CM3 */
+#define GIC_VPE_COMPARE_OFS            GIC_VPE_COMPARE_LO_OFS
 #define GIC_VPE_COMPARE_HI_OFS         0x00a4
 
 #define GIC_VPE_EIC_SHADOW_SET_BASE_OFS        0x0100