Merge tag 'arc-4.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/vgupta/arc
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 1 Jul 2015 16:24:26 +0000 (09:24 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 1 Jul 2015 16:24:26 +0000 (09:24 -0700)
Pull ARC architecture updates from Vineet Gupta:

 - support for HS38 cores based on ARCv2 ISA

     ARCv2 is the next generation ISA from Synopsys and basis for the
     HS3{4,6,8} families of processors which retain the traditional ARC mantra of
     low power and configurability and are now more performant and feature rich.

     HS38x is a 10 stage pipeline core which supports MMU (with huge pages) and
     SMP (upto 4 cores) among other features.

     + www.synopsys.com/dw/ipdir.php?ds=arc-hs38-processor
     + http://news.synopsys.com/2014-10-14-New-DesignWare-ARC-HS38-Processor-Doubles-Performance-for-Embedded-Linux-Applications
     + http://www.embedded.com/electronics-news/4435975/Synopsys-ARC-HS38-core-gives-2X-boost-to-Linux-based-apps

 - support for ARC SDP (Software Development platform): Main Board + CPU Cards
    = AXS101: CPU Card with ARC700 in silicon @ 700 MHz
    = AXS103: CPU Card with HS38x in FPGA

 - refactoring of ARCompact port to accomodate new ARCv2 ISA

 - misc updates/cleanups

* tag 'arc-4.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/vgupta/arc: (72 commits)
  ARC: Fix build failures for ARCompact in linux-next after ARCv2 support
  ARCv2: Allow older gcc to cope with new regime of ARCv2/ARCompact support
  ARCv2: [vdk] dts files and defconfig for HS38 VDK
  ARCv2: [axs103] Support ARC SDP FPGA platform for HS38x cores
  ARC: [axs101] Prepare for AXS103
  ARCv2: [nsim*hs*] Support simulation platforms for HS38x cores
  ARCv2: All bits in place, allow ARCv2 builds
  ARCv2: SLC: Handle explcit flush for DMA ops (w/o IO-coherency)
  ARCv2: STAR 9000837815 workaround hardware exclusive transactions livelock
  ARC: Reduce bitops lines of code using macros
  ARCv2: barriers
  arch: conditionally define smp_{mb,rmb,wmb}
  ARC: add smp barriers around atomics per Documentation/atomic_ops.txt
  ARC: add compiler barrier to LLSC based cmpxchg
  ARCv2: SMP: intc: IDU 2nd level intc for dynamic IRQ distribution
  ARCv2: SMP: clocksource: Enable Global Real Time counter
  ARCv2: SMP: ARConnect debug/robustness
  ARCv2: SMP: Support ARConnect (MCIP) for Inter-Core-Interrupts et al
  ARC: make plat_smp_ops weak to allow over-rides
  ARCv2: clocksource: Introduce 64bit local RTC counter
  ...

110 files changed:
Documentation/devicetree/bindings/arc/archs-idu-intc.txt [new file with mode: 0644]
Documentation/devicetree/bindings/arc/archs-intc.txt [new file with mode: 0644]
Documentation/devicetree/bindings/arc/axs101.txt [new file with mode: 0644]
Documentation/devicetree/bindings/arc/axs103.txt [new file with mode: 0644]
MAINTAINERS
arch/arc/Kconfig
arch/arc/Makefile
arch/arc/boot/dts/Makefile
arch/arc/boot/dts/angel4.dts [deleted file]
arch/arc/boot/dts/axc001.dtsi [new file with mode: 0644]
arch/arc/boot/dts/axc003.dtsi [new file with mode: 0644]
arch/arc/boot/dts/axc003_idu.dtsi [new file with mode: 0644]
arch/arc/boot/dts/axs101.dts [new file with mode: 0644]
arch/arc/boot/dts/axs103.dts [new file with mode: 0644]
arch/arc/boot/dts/axs103_idu.dts [new file with mode: 0644]
arch/arc/boot/dts/axs10x_mb.dtsi [new file with mode: 0644]
arch/arc/boot/dts/nsim_700.dts [new file with mode: 0644]
arch/arc/boot/dts/nsim_hs.dts [new file with mode: 0644]
arch/arc/boot/dts/nsim_hs_idu.dts [new file with mode: 0644]
arch/arc/boot/dts/nsimosci_hs.dts [new file with mode: 0644]
arch/arc/boot/dts/nsimosci_hs_idu.dts [new file with mode: 0644]
arch/arc/boot/dts/vdk_axc003.dtsi [new file with mode: 0644]
arch/arc/boot/dts/vdk_axc003_idu.dtsi [new file with mode: 0644]
arch/arc/boot/dts/vdk_axs10x_mb.dtsi [new file with mode: 0644]
arch/arc/boot/dts/vdk_hs38.dts [new file with mode: 0644]
arch/arc/boot/dts/vdk_hs38_smp.dts [new file with mode: 0644]
arch/arc/configs/axs101_defconfig [new file with mode: 0644]
arch/arc/configs/axs103_defconfig [new file with mode: 0644]
arch/arc/configs/axs103_smp_defconfig [new file with mode: 0644]
arch/arc/configs/nsim_700_defconfig
arch/arc/configs/nsim_hs_defconfig [new file with mode: 0644]
arch/arc/configs/nsim_hs_smp_defconfig [new file with mode: 0644]
arch/arc/configs/nsimosci_defconfig
arch/arc/configs/nsimosci_hs_defconfig [new file with mode: 0644]
arch/arc/configs/nsimosci_hs_smp_defconfig [new file with mode: 0644]
arch/arc/configs/tb10x_defconfig
arch/arc/configs/vdk_hs38_defconfig [new file with mode: 0644]
arch/arc/configs/vdk_hs38_smp_defconfig [new file with mode: 0644]
arch/arc/include/asm/Kbuild
arch/arc/include/asm/arcregs.h
arch/arc/include/asm/atomic.h
arch/arc/include/asm/barrier.h [new file with mode: 0644]
arch/arc/include/asm/bitops.h
arch/arc/include/asm/cache.h
arch/arc/include/asm/cacheflush.h
arch/arc/include/asm/cmpxchg.h
arch/arc/include/asm/delay.h
arch/arc/include/asm/dma-mapping.h
arch/arc/include/asm/elf.h
arch/arc/include/asm/entry-arcv2.h [new file with mode: 0644]
arch/arc/include/asm/entry-compact.h [new file with mode: 0644]
arch/arc/include/asm/entry.h
arch/arc/include/asm/io.h
arch/arc/include/asm/irq.h
arch/arc/include/asm/irqflags-arcv2.h [new file with mode: 0644]
arch/arc/include/asm/irqflags-compact.h [new file with mode: 0644]
arch/arc/include/asm/irqflags.h
arch/arc/include/asm/mcip.h [new file with mode: 0644]
arch/arc/include/asm/mmu.h
arch/arc/include/asm/pgtable.h
arch/arc/include/asm/processor.h
arch/arc/include/asm/ptrace.h
arch/arc/include/asm/spinlock.h
arch/arc/include/asm/thread_info.h
arch/arc/include/asm/uaccess.h
arch/arc/include/uapi/asm/page.h
arch/arc/kernel/Makefile
arch/arc/kernel/asm-offsets.c
arch/arc/kernel/devtree.c
arch/arc/kernel/entry-arcv2.S [new file with mode: 0644]
arch/arc/kernel/entry-compact.S [new file with mode: 0644]
arch/arc/kernel/entry.S
arch/arc/kernel/head.S
arch/arc/kernel/intc-arcv2.c [new file with mode: 0644]
arch/arc/kernel/intc-compact.c [new file with mode: 0644]
arch/arc/kernel/irq.c
arch/arc/kernel/mcip.c [new file with mode: 0644]
arch/arc/kernel/perf_event.c
arch/arc/kernel/process.c
arch/arc/kernel/ptrace.c
arch/arc/kernel/setup.c
arch/arc/kernel/signal.c
arch/arc/kernel/smp.c
arch/arc/kernel/stacktrace.c
arch/arc/kernel/time.c
arch/arc/kernel/troubleshoot.c
arch/arc/lib/Makefile
arch/arc/lib/memcmp.S
arch/arc/lib/memcpy-archs.S [new file with mode: 0644]
arch/arc/lib/memset-archs.S [new file with mode: 0644]
arch/arc/lib/strcmp-archs.S [new file with mode: 0644]
arch/arc/mm/Makefile
arch/arc/mm/cache.c [new file with mode: 0644]
arch/arc/mm/cache_arc700.c [deleted file]
arch/arc/mm/dma.c
arch/arc/mm/tlb.c
arch/arc/mm/tlbex.S
arch/arc/plat-arcfpga/Kconfig [deleted file]
arch/arc/plat-arcfpga/Makefile [deleted file]
arch/arc/plat-arcfpga/include/plat/smp.h [deleted file]
arch/arc/plat-arcfpga/platform.c [deleted file]
arch/arc/plat-arcfpga/smp.c [deleted file]
arch/arc/plat-axs10x/Kconfig [new file with mode: 0644]
arch/arc/plat-axs10x/Makefile [new file with mode: 0644]
arch/arc/plat-axs10x/axs10x.c [new file with mode: 0644]
arch/arc/plat-sim/Kconfig [new file with mode: 0644]
arch/arc/plat-sim/Makefile [new file with mode: 0644]
arch/arc/plat-sim/platform.c [new file with mode: 0644]
include/asm-generic/barrier.h
scripts/sortextable.c

diff --git a/Documentation/devicetree/bindings/arc/archs-idu-intc.txt b/Documentation/devicetree/bindings/arc/archs-idu-intc.txt
new file mode 100644 (file)
index 0000000..0dcb7c7
--- /dev/null
@@ -0,0 +1,46 @@
+* ARC-HS Interrupt Distribution Unit
+
+  This optional 2nd level interrupt controller can be used in SMP configurations for
+  dynamic IRQ routing, load balancing of common/external IRQs towards core intc.
+
+Properties:
+
+- compatible: "snps,archs-idu-intc"
+- interrupt-controller: This is an interrupt controller.
+- interrupt-parent: <reference to parent core intc>
+- #interrupt-cells: Must be <2>.
+- interrupts: <...> specifies the upstream core irqs
+
+  First cell specifies the "common" IRQ from peripheral to IDU
+  Second cell specifies the irq distribution mode to cores
+     0=Round Robin; 1=cpu0, 2=cpu1, 4=cpu2, 8=cpu3
+
+  intc accessed via the special ARC AUX register interface, hence "reg" property
+  is not specified.
+
+Example:
+       core_intc: core-interrupt-controller {
+               compatible = "snps,archs-intc";
+               interrupt-controller;
+               #interrupt-cells = <1>;
+       };
+
+       idu_intc: idu-interrupt-controller {
+               compatible = "snps,archs-idu-intc";
+               interrupt-controller;
+               interrupt-parent = <&core_intc>;
+
+               /*
+                * <hwirq  distribution>
+                * distribution: 0=RR; 1=cpu0, 2=cpu1, 4=cpu2, 8=cpu3
+                */
+               #interrupt-cells = <2>;
+
+               /* upstream core irqs: downstream these are "COMMON" irq 0,1..  */
+               interrupts = <24 25 26 27 28 29 30 31>;
+       };
+
+       some_device: serial@c0fc1000 {
+               interrupt-parent = <&idu_intc>;
+               interrupts = <0 0>;     /* upstream idu IRQ #24, Round Robin */
+       };
diff --git a/Documentation/devicetree/bindings/arc/archs-intc.txt b/Documentation/devicetree/bindings/arc/archs-intc.txt
new file mode 100644 (file)
index 0000000..69f326d
--- /dev/null
@@ -0,0 +1,22 @@
+* ARC-HS incore Interrupt Controller (Provided by cores implementing ARCv2 ISA)
+
+Properties:
+
+- compatible: "snps,archs-intc"
+- interrupt-controller: This is an interrupt controller.
+- #interrupt-cells: Must be <1>.
+
+  Single Cell "interrupts" property of a device specifies the IRQ number
+  between 16 to 256
+
+  intc accessed via the special ARC AUX register interface, hence "reg" property
+  is not specified.
+
+Example:
+
+       intc: interrupt-controller {
+               compatible = "snps,archs-intc";
+               interrupt-controller;
+               #interrupt-cells = <1>;
+               interrupts = <16 17 18 19 20 21 22 23 24 25>;
+       };
diff --git a/Documentation/devicetree/bindings/arc/axs101.txt b/Documentation/devicetree/bindings/arc/axs101.txt
new file mode 100644 (file)
index 0000000..48290d5
--- /dev/null
@@ -0,0 +1,7 @@
+Synopsys DesignWare ARC Software Development Platforms Device Tree Bindings
+---------------------------------------------------------------------------
+
+SDP Main Board with an AXC001 CPU Card hoisting ARC700 core in silicon
+
+Required root node properties:
+    - compatible = "snps,axs101", "snps,arc-sdp";
diff --git a/Documentation/devicetree/bindings/arc/axs103.txt b/Documentation/devicetree/bindings/arc/axs103.txt
new file mode 100644 (file)
index 0000000..6eea862
--- /dev/null
@@ -0,0 +1,8 @@
+Synopsys DesignWare ARC Software Development Platforms Device Tree Bindings
+---------------------------------------------------------------------------
+
+SDP Main Board with an AXC003 FPGA Card which can contain various flavours of
+HS38x cores.
+
+Required root node properties:
+    - compatible = "snps,axs103", "snps,arc-sdp";
index 0e6b09150aad52720d8f98b1802e0a4005e688af..ab6fb58b3873cc4b628784cec6b2488c0cb7c850 100644 (file)
@@ -9832,6 +9832,13 @@ F:       arch/arc/
 F:     Documentation/devicetree/bindings/arc/
 F:     drivers/tty/serial/arc_uart.c
 
+SYNOPSYS ARC SDP platform support
+M:     Alexey Brodkin <abrodkin@synopsys.com>
+S:     Supported
+F:     arch/arc/plat-axs10x
+F:     arch/arc/boot/dts/ax*
+F:     Documentation/devicetree/bindings/arc/axs10*
+
 SYSTEM CONFIGURATION (SYSCON)
 M:     Lee Jones <lee.jones@linaro.org>
 M:     Arnd Bergmann <arnd@arndb.de>
index df94ac1f75b6ac517784364cdeff6781eead9a6b..e7cee0a5c56dfa80222d8286a63342b10c07bc42 100644 (file)
@@ -81,17 +81,37 @@ menu "ARC Architecture Configuration"
 
 menu "ARC Platform/SoC/Board"
 
-source "arch/arc/plat-arcfpga/Kconfig"
+source "arch/arc/plat-sim/Kconfig"
 source "arch/arc/plat-tb10x/Kconfig"
+source "arch/arc/plat-axs10x/Kconfig"
 #New platform adds here
 
 endmenu
 
+choice
+       prompt "ARC Instruction Set"
+       default ISA_ARCOMPACT
+
+config ISA_ARCOMPACT
+       bool "ARCompact ISA"
+       help
+         The original ARC ISA of ARC600/700 cores
+
+config ISA_ARCV2
+       bool "ARC ISA v2"
+       help
+         ISA for the Next Generation ARC-HS cores
+
+endchoice
+
 menu "ARC CPU Configuration"
 
 choice
        prompt "ARC Core"
-       default ARC_CPU_770
+       default ARC_CPU_770 if ISA_ARCOMPACT
+       default ARC_CPU_HS if ISA_ARCV2
+
+if ISA_ARCOMPACT
 
 config ARC_CPU_750D
        bool "ARC750D"
@@ -100,7 +120,7 @@ config ARC_CPU_750D
 
 config ARC_CPU_770
        bool "ARC770"
-       select ARC_CPU_REL_4_10
+       select ARC_HAS_SWAPE
        help
          Support for ARC770 core introduced with Rel 4.10 (Summer 2011)
          This core has a bunch of cool new features:
@@ -109,6 +129,27 @@ config ARC_CPU_770
          -Caches: New Prog Model, Region Flush
          -Insns: endian swap, load-locked/store-conditional, time-stamp-ctr
 
+endif  #ISA_ARCOMPACT
+
+config ARC_CPU_HS
+       bool "ARC-HS"
+       depends on ISA_ARCV2
+       help
+         Support for ARC HS38x Cores based on ARCv2 ISA
+         The notable features are:
+           - SMP configurations of upto 4 core with coherency
+           - Optional L2 Cache and IO-Coherency
+           - Revised Interrupt Architecture (multiple priorites, reg banks,
+               auto stack switch, auto regfile save/restore)
+           - MMUv4 (PIPT dcache, Huge Pages)
+           - Instructions for
+               * 64bit load/store: LDD, STD
+               * Hardware assisted divide/remainder: DIV, REM
+               * Function prologue/epilogue: ENTER_S, LEAVE_S
+               * IRQ enable/disable: CLRI, SETI
+               * pop count: FFS, FLS
+               * SETcc, BMSKN, XBFU...
+
 endchoice
 
 config CPU_BIG_ENDIAN
@@ -117,17 +158,13 @@ config CPU_BIG_ENDIAN
        help
          Build kernel for Big Endian Mode of ARC CPU
 
-# If a platform can't work with 0x8000_0000 based dma_addr_t
-config ARC_PLAT_NEEDS_CPU_TO_DMA
-       bool
-
 config SMP
-       bool "Symmetric Multi-Processing (Incomplete)"
+       bool "Symmetric Multi-Processing"
        default n
+       select ARC_HAS_COH_CACHES if ISA_ARCV2
+       select ARC_MCIP if ISA_ARCV2
        help
-         This enables support for systems with more than one CPU. If you have
-         a system with only one CPU, say N. If you have a system with more
-         than one CPU, say Y.
+         This enables support for systems with more than one CPU.
 
 if SMP
 
@@ -137,13 +174,20 @@ config ARC_HAS_COH_CACHES
 config ARC_HAS_REENTRANT_IRQ_LV2
        def_bool n
 
-endif
+config ARC_MCIP
+       bool "ARConnect Multicore IP (MCIP) Support "
+       depends on ISA_ARCV2
+       help
+         This IP block enables SMP in ARC-HS38 cores.
+         It provides for cross-core interrupts, multi-core debug
+         hardware semaphores, shared memory,....
 
 config NR_CPUS
        int "Maximum number of CPUs (2-4096)"
        range 2 4096
-       depends on SMP
-       default "2"
+       default "4"
+
+endif  #SMP
 
 menuconfig ARC_CACHE
        bool "Enable Cache Support"
@@ -185,7 +229,7 @@ config ARC_CACHE_PAGES
 
 config ARC_CACHE_VIPT_ALIASING
        bool "Support VIPT Aliasing D$"
-       depends on ARC_HAS_DCACHE
+       depends on ARC_HAS_DCACHE && ISA_ARCOMPACT
        default n
 
 endif  #ARC_CACHE
@@ -226,9 +270,10 @@ config ARC_HAS_HW_MPY
          Multipler. Otherwise software multipy lib is used
 
 choice
-       prompt "ARC700 MMU Version"
+       prompt "MMU Version"
        default ARC_MMU_V3 if ARC_CPU_770
        default ARC_MMU_V2 if ARC_CPU_750D
+       default ARC_MMU_V4 if ARC_CPU_HS
 
 config ARC_MMU_V1
        bool "MMU v1"
@@ -249,6 +294,10 @@ config ARC_MMU_V3
          Variable Page size (1k-16k), var JTLB size 128 x (2 or 4)
          Shared Address Spaces (SASID)
 
+config ARC_MMU_V4
+       bool "MMU v4"
+       depends on ISA_ARCV2
+
 endchoice
 
 
@@ -271,6 +320,8 @@ config ARC_PAGE_SIZE_4K
 
 endchoice
 
+if ISA_ARCOMPACT
+
 config ARC_COMPACT_IRQ_LEVELS
        bool "ARCompact IRQ Priorities: High(2)/Low(1)"
        default n
@@ -290,7 +341,7 @@ config ARC_IRQ5_LV2
 config ARC_IRQ6_LV2
        bool
 
-endif
+endif  #ARC_COMPACT_IRQ_LEVELS
 
 config ARC_FPU_SAVE_RESTORE
        bool "Enable FPU state persistence across context switch"
@@ -303,32 +354,53 @@ config ARC_FPU_SAVE_RESTORE
          based on actual usage of FPU by a task. Thus our implemn does
          this for all tasks in system.
 
+endif  #ISA_ARCOMPACT
+
 config ARC_CANT_LLSC
        def_bool n
 
-menuconfig ARC_CPU_REL_4_10
-       bool "Enable support for Rel 4.10 features"
-       default n
-       help
-         -ARC770 (and dependent features) enabled
-         -ARC750 also shares some of the new features with 770
-
 config ARC_HAS_LLSC
        bool "Insn: LLOCK/SCOND (efficient atomic ops)"
        default y
-       depends on ARC_CPU_770 && !ARC_CANT_LLSC
+       depends on !ARC_CPU_750D && !ARC_CANT_LLSC
 
 config ARC_HAS_SWAPE
        bool "Insn: SWAPE (endian-swap)"
        default y
-       depends on ARC_CPU_REL_4_10
 
-config ARC_HAS_RTSC
-       bool "Insn: RTSC (64-bit r/o cycle counter)"
+if ISA_ARCV2
+
+config ARC_HAS_LL64
+       bool "Insn: 64bit LDD/STD"
+       help
+         Enable gcc to generate 64-bit load/store instructions
+         ISA mandates even/odd registers to allow encoding of two
+         dest operands with 2 possible source operands.
        default y
-       depends on ARC_CPU_REL_4_10
+
+config ARC_HAS_RTC
+       bool "Local 64-bit r/o cycle counter"
+       default n
        depends on !SMP
 
+config ARC_HAS_GRTC
+       bool "SMP synchronized 64-bit cycle counter"
+       default y
+       depends on SMP
+
+config ARC_NUMBER_OF_INTERRUPTS
+       int "Number of interrupts"
+       range 8 240
+       default 32
+       help
+         This defines the number of interrupts on the ARCv2HS core.
+         It affects the size of vector table.
+         The initial 8 IRQs are fixed (Timer, ICI etc) and although configurable
+         in hardware, it keep things simple for Linux to assume they are always
+         present.
+
+endif  # ISA_ARCV2
+
 endmenu   # "ARC CPU Configuration"
 
 config LINUX_LINK_BASE
@@ -354,8 +426,10 @@ config ARC_CURR_IN_REG
 
 config ARC_EMUL_UNALIGNED
        bool "Emulate unaligned memory access (userspace only)"
+       default N
        select SYSCTL_ARCH_UNALIGN_NO_WARN
        select SYSCTL_ARCH_UNALIGN_ALLOW
+       depends on ISA_ARCOMPACT
        help
          This enables misaligned 16 & 32 bit memory access from user space.
          Use ONLY-IF-ABS-NECESSARY as it will be very slow and also can hide
@@ -378,9 +452,10 @@ menuconfig ARC_DBG
        bool "ARC debugging"
        default y
 
+if ARC_DBG
+
 config ARC_DW2_UNWIND
        bool "Enable DWARF specific kernel stack unwind"
-       depends on ARC_DBG
        default y
        select KALLSYMS
        help
@@ -394,18 +469,38 @@ config ARC_DW2_UNWIND
 
 config ARC_DBG_TLB_PARANOIA
        bool "Paranoia Checks in Low Level TLB Handlers"
-       depends on ARC_DBG
        default n
 
 config ARC_DBG_TLB_MISS_COUNT
        bool "Profile TLB Misses"
        default n
        select DEBUG_FS
-       depends on ARC_DBG
        help
          Counts number of I and D TLB Misses and exports them via Debugfs
          The counters can be cleared via Debugfs as well
 
+if SMP
+
+config ARC_IPI_DBG
+       bool "Debug Inter Core interrupts"
+       default n
+
+endif
+
+endif
+
+config ARC_UBOOT_SUPPORT
+       bool "Support uboot arg Handling"
+       default n
+       help
+         ARC Linux by default checks for uboot provided args as pointers to
+         external cmdline or DTB. This however breaks in absence of uboot,
+         when booting from Metaware debugger directly, as the registers are
+         not zeroed out on reset by mdb and/or ARCv2 based cores. The bogus
+         registers look like uboot args to kernel which then chokes.
+         So only enable the uboot arg checking/processing if users are sure
+         of uboot being in play.
+
 config ARC_BUILTIN_DTB_NAME
        string "Built in DTB"
        help
index db72fec0e160fc8e67fe17c5faf9c6ef54c8bcdb..6107062c01115dbea8a56e02bce254a8ba5b91af 100644 (file)
@@ -9,12 +9,14 @@
 UTS_MACHINE := arc
 
 ifeq ($(CROSS_COMPILE),)
-CROSS_COMPILE := arc-linux-uclibc-
+CROSS_COMPILE := arc-linux-
 endif
 
 KBUILD_DEFCONFIG := nsim_700_defconfig
 
-cflags-y       += -mA7 -fno-common -pipe -fno-builtin -D__linux__
+cflags-y       += -fno-common -pipe -fno-builtin -D__linux__
+cflags-$(CONFIG_ISA_ARCOMPACT) += -mA7
+cflags-$(CONFIG_ISA_ARCV2)     += -mcpu=archs
 
 ifdef CONFIG_ARC_CURR_IN_REG
 # For a global register defintion, make sure it gets passed to every file
@@ -33,7 +35,11 @@ cflags-$(atleast_gcc44)                      += -fsection-anchors
 
 cflags-$(CONFIG_ARC_HAS_LLSC)          += -mlock
 cflags-$(CONFIG_ARC_HAS_SWAPE)         += -mswape
-cflags-$(CONFIG_ARC_HAS_RTSC)          += -mrtsc
+
+ifndef CONFIG_ARC_HAS_LL64
+cflags-$(CONFIG_ISA_ARCV2)             += -mno-ll64
+endif
+
 cflags-$(CONFIG_ARC_DW2_UNWIND)                += -fasynchronous-unwind-tables
 
 # By default gcc 4.8 generates dwarf4 which kernel unwinder can't grok
@@ -81,8 +87,9 @@ core-y                += arch/arc/
 # w/o this dtb won't embed into kernel binary
 core-y         += arch/arc/boot/dts/
 
-core-$(CONFIG_ARC_PLAT_FPGA_LEGACY)    += arch/arc/plat-arcfpga/
-core-$(CONFIG_ARC_PLAT_TB10X)          += arch/arc/plat-tb10x/
+core-$(CONFIG_ARC_PLAT_SIM)    += arch/arc/plat-sim/
+core-$(CONFIG_ARC_PLAT_TB10X)  += arch/arc/plat-tb10x/
+core-$(CONFIG_ARC_PLAT_AXS10X) += arch/arc/plat-axs10x/
 
 drivers-$(CONFIG_OPROFILE)     += arch/arc/oprofile/
 
index faf240e29ec2cebc1b6f7762b0c0556de37f1a8f..b0e3f19bbd07e32cb57c91f803302603ebe429fc 100644 (file)
@@ -1,5 +1,5 @@
 # Built-in dtb
-builtindtb-y           := angel4
+builtindtb-y           := nsim_700
 
 ifneq ($(CONFIG_ARC_BUILTIN_DTB_NAME),"")
        builtindtb-y    := $(patsubst "%",%,$(CONFIG_ARC_BUILTIN_DTB_NAME))
diff --git a/arch/arc/boot/dts/angel4.dts b/arch/arc/boot/dts/angel4.dts
deleted file mode 100644 (file)
index 3b076fb..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2012 Synopsys, Inc. (www.synopsys.com)
- *
- * 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.
- */
-/dts-v1/;
-
-/include/ "skeleton.dtsi"
-
-/ {
-       compatible = "snps,arc-angel4";
-       clock-frequency = <80000000>;   /* 80 MHZ */
-       #address-cells = <1>;
-       #size-cells = <1>;
-       interrupt-parent = <&intc>;
-
-       chosen {
-               bootargs = "earlycon=arc_uart,mmio32,0xc0fc1000,115200n8 console=ttyARC0,115200n8";
-       };
-
-       aliases {
-               serial0 = &arcuart0;
-       };
-
-       fpga {
-               compatible = "simple-bus";
-               #address-cells = <1>;
-               #size-cells = <1>;
-
-               /* child and parent address space 1:1 mapped */
-               ranges;
-
-               intc: interrupt-controller {
-                       compatible = "snps,arc700-intc";
-                       interrupt-controller;
-                       #interrupt-cells = <1>;
-               };
-
-               arcuart0: serial@c0fc1000 {
-                       compatible = "snps,arc-uart";
-                       reg = <0xc0fc1000 0x100>;
-                       interrupts = <5>;
-                       clock-frequency = <80000000>;
-                       current-speed = <115200>;
-                       status = "okay";
-               };
-
-               ethernet@c0fc2000 {
-                       compatible = "snps,arc-emac";
-                       reg = <0xc0fc2000 0x3c>;
-                       interrupts = <6>;
-                       mac-address = [ 00 11 22 33 44 55 ];
-                       clock-frequency = <80000000>;
-                       max-speed = <100>;
-                       phy = <&phy0>;
-
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-                       phy0: ethernet-phy@0 {
-                               reg = <1>;
-                       };
-               };
-
-               arcpmu0: pmu {
-                       compatible = "snps,arc700-pct";
-               };
-       };
-};
diff --git a/arch/arc/boot/dts/axc001.dtsi b/arch/arc/boot/dts/axc001.dtsi
new file mode 100644 (file)
index 0000000..a5e2726
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2013-15 Synopsys, Inc. (www.synopsys.com)
+ *
+ * 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.
+ */
+
+/*
+ * Device tree for AXC001 770D/EM6/AS221 CPU card
+ * Note that this file only supports the 770D CPU
+ */
+
+/ {
+       compatible = "snps,arc";
+       clock-frequency = <750000000>;  /* 750 MHZ */
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       cpu_card {
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <1>;
+
+               ranges = <0x00000000 0xf0000000 0x10000000>;
+
+               cpu_intc: arc700-intc@cpu {
+                       compatible = "snps,arc700-intc";
+                       interrupt-controller;
+                       #interrupt-cells = <1>;
+               };
+
+               /*
+                * this GPIO block ORs all interrupts on CPU card (creg,..)
+                * to uplink only 1 IRQ to ARC core intc
+                */
+               dw-apb-gpio@0x2000 {
+                       compatible = "snps,dw-apb-gpio";
+                       reg = < 0x2000 0x80 >;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+
+                       ictl_intc: gpio-controller@0 {
+                               compatible = "snps,dw-apb-gpio-port";
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               snps,nr-gpios = <30>;
+                               reg = <0>;
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
+                               interrupt-parent = <&cpu_intc>;
+                               interrupts = <15>;
+                       };
+               };
+
+               debug_uart: dw-apb-uart@0x5000 {
+                       compatible = "snps,dw-apb-uart";
+                       reg = <0x5000 0x100>;
+                       clock-frequency = <33333000>;
+                       interrupt-parent = <&ictl_intc>;
+                       interrupts = <19 4>;
+                       baud = <115200>;
+                       reg-shift = <2>;
+                       reg-io-width = <4>;
+               };
+
+               arcpmu0: pmu {
+                       compatible = "snps,arc700-pct";
+               };
+       };
+
+       /*
+        * This INTC is actually connected to DW APB GPIO
+        * which acts as a wire between MB INTC and CPU INTC.
+        * GPIO INTC is configured in platform init code
+        * and here we mimic direct connection from MB INTC to
+        * CPU INTC, thus we set "interrupts = <7>" instead of
+        * "interrupts = <12>"
+        *
+        * This intc actually resides on MB, but we move it here to
+        * avoid duplicating the MB dtsi file given that IRQ from
+        * this intc to cpu intc are different for axs101 and axs103
+        */
+       mb_intc: dw-apb-ictl@0xe0012000 {
+               #interrupt-cells = <1>;
+               compatible = "snps,dw-apb-ictl";
+               reg = < 0xe0012000 0x200 >;
+               interrupt-controller;
+               interrupt-parent = <&cpu_intc>;
+               interrupts = < 7 >;
+       };
+
+       memory {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges = <0x00000000 0x80000000 0x40000000>;
+               device_type = "memory";
+               reg = <0x00000000 0x20000000>;  /* 512MiB */
+       };
+};
diff --git a/arch/arc/boot/dts/axc003.dtsi b/arch/arc/boot/dts/axc003.dtsi
new file mode 100644 (file)
index 0000000..15c8d62
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2014-15 Synopsys, Inc. (www.synopsys.com)
+ *
+ * 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.
+ */
+
+/*
+ * Device tree for AXC003 CPU card: HS38x UP configuration
+ */
+
+/ {
+       compatible = "snps,arc";
+       clock-frequency = <75000000>;
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       cpu_card {
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <1>;
+
+               ranges = <0x00000000 0xf0000000 0x10000000>;
+
+               cpu_intc: archs-intc@cpu {
+                       compatible = "snps,archs-intc";
+                       interrupt-controller;
+                       #interrupt-cells = <1>;
+               };
+
+               /*
+                * this GPIO block ORs all interrupts on CPU card (creg,..)
+                * to uplink only 1 IRQ to ARC core intc
+                */
+               dw-apb-gpio@0x2000 {
+                       compatible = "snps,dw-apb-gpio";
+                       reg = < 0x2000 0x80 >;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+
+                       ictl_intc: gpio-controller@0 {
+                               compatible = "snps,dw-apb-gpio-port";
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               snps,nr-gpios = <30>;
+                               reg = <0>;
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
+                               interrupt-parent = <&cpu_intc>;
+                               interrupts = <25>;
+                       };
+               };
+
+               debug_uart: dw-apb-uart@0x5000 {
+                       compatible = "snps,dw-apb-uart";
+                       reg = <0x5000 0x100>;
+                       clock-frequency = <33333000>;
+                       interrupt-parent = <&ictl_intc>;
+                       interrupts = <2 4>;
+                       baud = <115200>;
+                       reg-shift = <2>;
+                       reg-io-width = <4>;
+               };
+
+               arcpct0: pct {
+                       compatible = "snps,archs-pct";
+                       #interrupt-cells = <1>;
+                       interrupt-parent = <&cpu_intc>;
+                       interrupts = <20>;
+               };
+       };
+
+       /*
+        * This INTC is actually connected to DW APB GPIO
+        * which acts as a wire between MB INTC and CPU INTC.
+        * GPIO INTC is configured in platform init code
+        * and here we mimic direct connection from MB INTC to
+        * CPU INTC, thus we set "interrupts = <7>" instead of
+        * "interrupts = <12>"
+        *
+        * This intc actually resides on MB, but we move it here to
+        * avoid duplicating the MB dtsi file given that IRQ from
+        * this intc to cpu intc are different for axs101 and axs103
+        */
+       mb_intc: dw-apb-ictl@0xe0012000 {
+               #interrupt-cells = <1>;
+               compatible = "snps,dw-apb-ictl";
+               reg = < 0xe0012000 0x200 >;
+               interrupt-controller;
+               interrupt-parent = <&cpu_intc>;
+               interrupts = < 24 >;
+       };
+
+       memory {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges = <0x00000000 0x80000000 0x40000000>;
+               device_type = "memory";
+               reg = <0x00000000 0x20000000>;  /* 512MiB */
+       };
+};
diff --git a/arch/arc/boot/dts/axc003_idu.dtsi b/arch/arc/boot/dts/axc003_idu.dtsi
new file mode 100644 (file)
index 0000000..199d428
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2014, 2015 Synopsys, Inc. (www.synopsys.com)
+ *
+ * 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.
+ */
+
+/*
+ * Device tree for AXC003 CPU card: HS38x2 (Dual Core) with IDU intc
+ */
+
+/ {
+       compatible = "snps,arc";
+       clock-frequency = <75000000>;
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       cpu_card {
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <1>;
+
+               ranges = <0x00000000 0xf0000000 0x10000000>;
+
+               cpu_intc: archs-intc@cpu {
+                       compatible = "snps,archs-intc";
+                       interrupt-controller;
+                       #interrupt-cells = <1>;
+               };
+
+               idu_intc: idu-interrupt-controller {
+                       compatible = "snps,archs-idu-intc";
+                       interrupt-controller;
+                       interrupt-parent = <&cpu_intc>;
+
+                       /*
+                        * <hwirq  distribution>
+                        * distribution: 0=RR; 1=cpu0, 2=cpu1, 4=cpu2, 8=cpu3
+                        */
+                       #interrupt-cells = <2>;
+
+                       /*
+                        * upstream irqs to core intc - downstream these are
+                        * "COMMON" irq 0,1..
+                        */
+                       interrupts = <24 25>;
+               };
+
+               /*
+                * this GPIO block ORs all interrupts on CPU card (creg,..)
+                * to uplink only 1 IRQ to ARC core intc
+                */
+               dw-apb-gpio@0x2000 {
+                       compatible = "snps,dw-apb-gpio";
+                       reg = < 0x2000 0x80 >;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+
+                       ictl_intc: gpio-controller@0 {
+                               compatible = "snps,dw-apb-gpio-port";
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               snps,nr-gpios = <30>;
+                               reg = <0>;
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
+                               interrupt-parent = <&idu_intc>;
+
+                               /*
+                                * cmn irq 1 -> cpu irq 25
+                                * Distribute to cpu0 only
+                                */
+                               interrupts = <1 1>;
+                       };
+               };
+
+               debug_uart: dw-apb-uart@0x5000 {
+                       compatible = "snps,dw-apb-uart";
+                       reg = <0x5000 0x100>;
+                       clock-frequency = <33333000>;
+                       interrupt-parent = <&ictl_intc>;
+                       interrupts = <2 4>;
+                       baud = <115200>;
+                       reg-shift = <2>;
+                       reg-io-width = <4>;
+               };
+
+               arcpct0: pct {
+                       compatible = "snps,archs-pct";
+                       #interrupt-cells = <1>;
+                       interrupt-parent = <&cpu_intc>;
+                       interrupts = <20>;
+               };
+       };
+
+       /*
+        * This INTC is actually connected to DW APB GPIO
+        * which acts as a wire between MB INTC and CPU INTC.
+        * GPIO INTC is configured in platform init code
+        * and here we mimic direct connection from MB INTC to
+        * CPU INTC, thus we set "interrupts = <0 1>" instead of
+        * "interrupts = <12>"
+        *
+        * This intc actually resides on MB, but we move it here to
+        * avoid duplicating the MB dtsi file given that IRQ from
+        * this intc to cpu intc are different for axs101 and axs103
+        */
+       mb_intc: dw-apb-ictl@0xe0012000 {
+               #interrupt-cells = <1>;
+               compatible = "snps,dw-apb-ictl";
+               reg = < 0xe0012000 0x200 >;
+               interrupt-controller;
+               interrupt-parent = <&idu_intc>;
+               interrupts = <0 1>;     /* cmn irq 0 -> cpu irq 24
+                                          distribute to cpu0 only */
+       };
+
+       memory {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges = <0x00000000 0x80000000 0x40000000>;
+               device_type = "memory";
+               reg = <0x00000000 0x20000000>;  /* 512MiB */
+       };
+};
diff --git a/arch/arc/boot/dts/axs101.dts b/arch/arc/boot/dts/axs101.dts
new file mode 100644 (file)
index 0000000..3f9b058
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2013-15 Synopsys, Inc. (www.synopsys.com)
+ *
+ * ARC AXS101 S/W development platform
+ *
+ * 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.
+ */
+/dts-v1/;
+
+/include/ "axc001.dtsi"
+/include/ "axs10x_mb.dtsi"
+
+/ {
+       compatible = "snps,axs101", "snps,arc-sdp";
+
+       chosen {
+               bootargs = "earlycon=uart8250,mmio32,0xe0022000,115200n8 console=tty0 console=ttyS3,115200n8 consoleblank=0";
+       };
+};
diff --git a/arch/arc/boot/dts/axs103.dts b/arch/arc/boot/dts/axs103.dts
new file mode 100644 (file)
index 0000000..e6d0e31
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2014-15 Synopsys, Inc. (www.synopsys.com)
+ *
+ * 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.
+ */
+
+/*
+ * Device Tree for AXS103 SDP with AXS10X Main Board and
+ * AXC003 FPGA Card (with UP bitfile)
+ */
+/dts-v1/;
+
+/include/ "axc003.dtsi"
+/include/ "axs10x_mb.dtsi"
+
+/ {
+       compatible = "snps,axs103", "snps,arc-sdp";
+
+       chosen {
+               bootargs = "earlycon=uart8250,mmio32,0xe0022000,115200n8 console=ttyS3,115200n8 debug print-fatal-signals=1";
+       };
+};
diff --git a/arch/arc/boot/dts/axs103_idu.dts b/arch/arc/boot/dts/axs103_idu.dts
new file mode 100644 (file)
index 0000000..f999fef
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2014-15 Synopsys, Inc. (www.synopsys.com)
+ *
+ * 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.
+ */
+
+/*
+ * Device Tree for AXS103 SDP with AXS10X Main Board and
+ * AXC003 FPGA Card (with SMP bitfile)
+ */
+/dts-v1/;
+
+/include/ "axc003_idu.dtsi"
+/include/ "axs10x_mb.dtsi"
+
+/ {
+       compatible = "snps,axs103", "snps,arc-sdp";
+
+       chosen {
+               bootargs = "earlycon=uart8250,mmio32,0xe0022000,115200n8 console=ttyS3,115200n8 debug print-fatal-signals=1";
+       };
+};
diff --git a/arch/arc/boot/dts/axs10x_mb.dtsi b/arch/arc/boot/dts/axs10x_mb.dtsi
new file mode 100644 (file)
index 0000000..f3db321
--- /dev/null
@@ -0,0 +1,224 @@
+/*
+ * Support for peripherals on the AXS10x mainboard
+ *
+ * Copyright (C) 2013-15 Synopsys, Inc. (www.synopsys.com)
+ *
+ * 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.
+ */
+
+/ {
+       axs10x_mb {
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges = <0x00000000 0xe0000000 0x10000000>;
+               interrupt-parent = <&mb_intc>;
+
+               clocks {
+                       i2cclk: i2cclk {
+                               compatible = "fixed-clock";
+                               clock-frequency = <50000000>;
+                               #clock-cells = <0>;
+                       };
+
+                       apbclk: apbclk {
+                               compatible = "fixed-clock";
+                               clock-frequency = <50000000>;
+                               #clock-cells = <0>;
+                       };
+
+                       mmcclk: mmcclk {
+                               compatible = "fixed-clock";
+                               clock-frequency = <50000000>;
+                               #clock-cells = <0>;
+                       };
+               };
+
+               ethernet@0x18000 {
+                       #interrupt-cells = <1>;
+                       compatible = "snps,dwmac";
+                       reg = < 0x18000 0x2000 >;
+                       interrupts = < 4 >;
+                       interrupt-names = "macirq";
+                       phy-mode = "rgmii";
+                       snps,pbl = < 32 >;
+                       clocks = <&apbclk>;
+                       clock-names = "stmmaceth";
+               };
+
+               ehci@0x40000 {
+                       compatible = "generic-ehci";
+                       reg = < 0x40000 0x100 >;
+                       interrupts = < 8 >;
+               };
+
+               ohci@0x60000 {
+                       compatible = "generic-ohci";
+                       reg = < 0x60000 0x100 >;
+                       interrupts = < 8 >;
+               };
+
+               /*
+                * According to DW Mobile Storage databook it is required
+                * to use  "Hold Register" if card is enumerated in SDR12 or
+                * SDR25 modes.
+                *
+                * Utilization of "Hold Register" is already implemented via
+                * dw_mci_pltfm_prepare_command() which in its turn gets
+                * used through dw_mci_drv_data->prepare_command call-back.
+                * This call-back is used in Altera Socfpga platform and so
+                * we may reuse it saying that we're compatible with their
+                * "altr,socfpga-dw-mshc".
+                *
+                * Most probably "Hold Register" utilization is platform-
+                * independent requirement which means that single unified
+                * "snps,dw-mshc" should be enough for all users of DW MMC once
+                * dw_mci_pltfm_prepare_command() is used in generic platform
+                * code.
+                */
+               mmc@0x15000 {
+                       compatible = "altr,socfpga-dw-mshc";
+                       reg = < 0x15000 0x400 >;
+                       num-slots = < 1 >;
+                       fifo-depth = < 16 >;
+                       card-detect-delay = < 200 >;
+                       clocks = <&apbclk>, <&mmcclk>;
+                       clock-names = "biu", "ciu";
+                       interrupts = < 7 >;
+                       bus-width = < 4 >;
+               };
+
+               uart@0x20000 {
+                       compatible = "snps,dw-apb-uart";
+                       reg = <0x20000 0x100>;
+                       clock-frequency = <33333333>;
+                       interrupts = <17>;
+                       baud = <115200>;
+                       reg-shift = <2>;
+                       reg-io-width = <4>;
+               };
+
+               uart@0x21000 {
+                       compatible = "snps,dw-apb-uart";
+                       reg = <0x21000 0x100>;
+                       clock-frequency = <33333333>;
+                       interrupts = <18>;
+                       baud = <115200>;
+                       reg-shift = <2>;
+                       reg-io-width = <4>;
+               };
+
+               /* UART muxed with USB data port (ttyS3) */
+               uart@0x22000 {
+                       compatible = "snps,dw-apb-uart";
+                       reg = <0x22000 0x100>;
+                       clock-frequency = <33333333>;
+                       interrupts = <19>;
+                       baud = <115200>;
+                       reg-shift = <2>;
+                       reg-io-width = <4>;
+               };
+
+               i2c@0x1d000 {
+                       compatible = "snps,designware-i2c";
+                       reg = <0x1d000 0x100>;
+                       clock-frequency = <400000>;
+                       clocks = <&i2cclk>;
+                       interrupts = <14>;
+               };
+
+               i2c@0x1e000 {
+                       compatible = "snps,designware-i2c";
+                       reg = <0x1e000 0x100>;
+                       clock-frequency = <400000>;
+                       clocks = <&i2cclk>;
+                       interrupts = <15>;
+               };
+
+               i2c@0x1f000 {
+                       compatible = "snps,designware-i2c";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <0x1f000 0x100>;
+                       clock-frequency = <400000>;
+                       clocks = <&i2cclk>;
+                       interrupts = <16>;
+
+                       eeprom@0x54{
+                               compatible = "24c01";
+                               reg = <0x54>;
+                               pagesize = <0x8>;
+                       };
+
+                       eeprom@0x57{
+                               compatible = "24c04";
+                               reg = <0x57>;
+                               pagesize = <0x8>;
+                       };
+               };
+
+               gpio0:gpio@13000 {
+                       compatible = "snps,dw-apb-gpio";
+                       reg = <0x13000 0x1000>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+
+                       gpio0_banka: gpio-controller@0 {
+                               compatible = "snps,dw-apb-gpio-port";
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               snps,nr-gpios = <32>;
+                               reg = <0>;
+                       };
+
+                       gpio0_bankb: gpio-controller@1 {
+                               compatible = "snps,dw-apb-gpio-port";
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               snps,nr-gpios = <8>;
+                               reg = <1>;
+                       };
+
+                       gpio0_bankc: gpio-controller@2 {
+                               compatible = "snps,dw-apb-gpio-port";
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               snps,nr-gpios = <8>;
+                               reg = <2>;
+                       };
+               };
+
+               gpio1:gpio@14000 {
+                       compatible = "snps,dw-apb-gpio";
+                       reg = <0x14000 0x1000>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+
+                       gpio1_banka: gpio-controller@0 {
+                               compatible = "snps,dw-apb-gpio-port";
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               snps,nr-gpios = <30>;
+                               reg = <0>;
+                       };
+
+                       gpio1_bankb: gpio-controller@1 {
+                               compatible = "snps,dw-apb-gpio-port";
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               snps,nr-gpios = <10>;
+                               reg = <1>;
+                       };
+
+                       gpio1_bankc: gpio-controller@2 {
+                               compatible = "snps,dw-apb-gpio-port";
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               snps,nr-gpios = <8>;
+                               reg = <2>;
+                       };
+               };
+       };
+};
diff --git a/arch/arc/boot/dts/nsim_700.dts b/arch/arc/boot/dts/nsim_700.dts
new file mode 100644 (file)
index 0000000..105a001
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2012 Synopsys, Inc. (www.synopsys.com)
+ *
+ * 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.
+ */
+/dts-v1/;
+
+/include/ "skeleton.dtsi"
+
+/ {
+       compatible = "snps,nsim";
+       clock-frequency = <80000000>;   /* 80 MHZ */
+       #address-cells = <1>;
+       #size-cells = <1>;
+       interrupt-parent = <&intc>;
+
+       chosen {
+               bootargs = "earlycon=arc_uart,mmio32,0xc0fc1000,115200n8 console=ttyARC0,115200n8";
+       };
+
+       aliases {
+               serial0 = &arcuart0;
+       };
+
+       fpga {
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <1>;
+
+               /* child and parent address space 1:1 mapped */
+               ranges;
+
+               intc: interrupt-controller {
+                       compatible = "snps,arc700-intc";
+                       interrupt-controller;
+                       #interrupt-cells = <1>;
+               };
+
+               arcuart0: serial@c0fc1000 {
+                       compatible = "snps,arc-uart";
+                       reg = <0xc0fc1000 0x100>;
+                       interrupts = <5>;
+                       clock-frequency = <80000000>;
+                       current-speed = <115200>;
+                       status = "okay";
+               };
+
+               ethernet@c0fc2000 {
+                       compatible = "snps,arc-emac";
+                       reg = <0xc0fc2000 0x3c>;
+                       interrupts = <6>;
+                       mac-address = [ 00 11 22 33 44 55 ];
+                       clock-frequency = <80000000>;
+                       max-speed = <100>;
+                       phy = <&phy0>;
+
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       phy0: ethernet-phy@0 {
+                               reg = <1>;
+                       };
+               };
+
+               arcpmu0: pmu {
+                       compatible = "snps,arc700-pct";
+               };
+       };
+};
diff --git a/arch/arc/boot/dts/nsim_hs.dts b/arch/arc/boot/dts/nsim_hs.dts
new file mode 100644 (file)
index 0000000..911f069
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2014-15 Synopsys, Inc. (www.synopsys.com)
+ *
+ * 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.
+ */
+/dts-v1/;
+
+/include/ "skeleton.dtsi"
+
+/ {
+       compatible = "snps,nsim_hs";
+       interrupt-parent = <&core_intc>;
+
+       chosen {
+               bootargs = "earlycon=arc_uart,mmio32,0xc0fc1000,115200n8 console=ttyARC0,115200n8";
+       };
+
+       aliases {
+               serial0 = &arcuart0;
+       };
+
+       fpga {
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <1>;
+
+               /* child and parent address space 1:1 mapped */
+               ranges;
+
+               core_intc: core-interrupt-controller {
+                       compatible = "snps,archs-intc";
+                       interrupt-controller;
+                       #interrupt-cells = <1>;
+               };
+
+               arcuart0: serial@c0fc1000 {
+                       compatible = "snps,arc-uart";
+                       reg = <0xc0fc1000 0x100>;
+                       interrupts = <24>;
+                       clock-frequency = <80000000>;
+                       current-speed = <115200>;
+                       status = "okay";
+               };
+
+               arcpct0: pct {
+                       compatible = "snps,archs-pct";
+                       #interrupt-cells = <1>;
+                       interrupts = <20>;
+               };
+       };
+};
diff --git a/arch/arc/boot/dts/nsim_hs_idu.dts b/arch/arc/boot/dts/nsim_hs_idu.dts
new file mode 100644 (file)
index 0000000..46ab319
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2014-15 Synopsys, Inc. (www.synopsys.com)
+ *
+ * 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.
+ */
+/dts-v1/;
+
+/include/ "skeleton.dtsi"
+
+/ {
+       compatible = "snps,nsim_hs";
+       interrupt-parent = <&core_intc>;
+
+       chosen {
+               bootargs = "earlycon=arc_uart,mmio32,0xc0fc1000,115200n8 console=ttyARC0,115200n8";
+       };
+
+       aliases {
+               serial0 = &arcuart0;
+       };
+
+       fpga {
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <1>;
+
+               /* child and parent address space 1:1 mapped */
+               ranges;
+
+               core_intc: core-interrupt-controller {
+                       compatible = "snps,archs-intc";
+                       interrupt-controller;
+                       #interrupt-cells = <1>;
+               };
+
+               idu_intc: idu-interrupt-controller {
+                       compatible = "snps,archs-idu-intc";
+                       interrupt-controller;
+                       interrupt-parent = <&core_intc>;
+
+                       /*
+                        * <hwirq  distribution>
+                        * distribution: 0=RR; 1=cpu0, 2=cpu1, 4=cpu2, 8=cpu3
+                        */
+                       #interrupt-cells = <2>;
+
+                       /*
+                        * upstream irqs to core intc - downstream these are
+                        * "COMMON" irq 0,1..
+                        */
+                       interrupts = <24 25 26 27 28 29 30 31>;
+               };
+
+               arcuart0: serial@c0fc1000 {
+                       compatible = "snps,arc-uart";
+                       reg = <0xc0fc1000 0x100>;
+                       interrupt-parent = <&idu_intc>;
+                       interrupts = <0 0>;
+                       clock-frequency = <80000000>;
+                       current-speed = <115200>;
+                       status = "okay";
+               };
+
+               arcpct0: pct {
+                       compatible = "snps,archs-pct";
+                       #interrupt-cells = <1>;
+                       interrupts = <20>;
+               };
+       };
+};
diff --git a/arch/arc/boot/dts/nsimosci_hs.dts b/arch/arc/boot/dts/nsimosci_hs.dts
new file mode 100644 (file)
index 0000000..d64a96f
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2014-15 Synopsys, Inc. (www.synopsys.com)
+ *
+ * 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.
+ */
+/dts-v1/;
+
+/include/ "skeleton.dtsi"
+
+/ {
+       compatible = "snps,nsimosci_hs";
+       clock-frequency = <20000000>;   /* 20 MHZ */
+       #address-cells = <1>;
+       #size-cells = <1>;
+       interrupt-parent = <&core_intc>;
+
+       chosen {
+               /* this is for console on PGU */
+               /* bootargs = "console=tty0 consoleblank=0"; */
+               /* this is for console on serial */
+               bootargs = "earlycon=uart8250,mmio32,0xf0000000,115200n8 console=tty0 console=ttyS0,115200n8 consoleblank=0 debug";
+       };
+
+       aliases {
+               serial0 = &uart0;
+       };
+
+       fpga {
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <1>;
+
+               /* child and parent address space 1:1 mapped */
+               ranges;
+
+               core_intc: core-interrupt-controller {
+                       compatible = "snps,archs-intc";
+                       interrupt-controller;
+                       #interrupt-cells = <1>;
+               };
+
+               uart0: serial@f0000000 {
+                       compatible = "ns8250";
+                       reg = <0xf0000000 0x2000>;
+                       interrupts = <24>;
+                       clock-frequency = <3686400>;
+                       baud = <115200>;
+                       reg-shift = <2>;
+                       reg-io-width = <4>;
+                       no-loopback-test = <1>;
+               };
+
+               pgu0: pgu@f9000000 {
+                       compatible = "snps,arcpgufb";
+                       reg = <0xf9000000 0x400>;
+               };
+
+               ps2: ps2@f9001000 {
+                       compatible = "snps,arc_ps2";
+                       reg = <0xf9000400 0x14>;
+                       interrupts = <27>;
+                       interrupt-names = "arc_ps2_irq";
+               };
+
+               eth0: ethernet@f0003000 {
+                       compatible = "snps,oscilan";
+                       reg = <0xf0003000 0x44>;
+                       interrupts = <25>, <26>;
+                       interrupt-names = "rx", "tx";
+               };
+
+               arcpct0: pct {
+                       compatible = "snps,archs-pct";
+                       #interrupt-cells = <1>;
+                       interrupts = <20>;
+               };
+       };
+};
diff --git a/arch/arc/boot/dts/nsimosci_hs_idu.dts b/arch/arc/boot/dts/nsimosci_hs_idu.dts
new file mode 100644 (file)
index 0000000..f6bf0ca
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2014-15 Synopsys, Inc. (www.synopsys.com)
+ *
+ * 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.
+ */
+/dts-v1/;
+
+/include/ "skeleton.dtsi"
+
+/ {
+       compatible = "snps,nsimosci_hs";
+       clock-frequency = <5000000>;    /* 5 MHZ */
+       #address-cells = <1>;
+       #size-cells = <1>;
+       interrupt-parent = <&core_intc>;
+
+       chosen {
+               /* this is for console on serial */
+               bootargs = "earlycon=uart8250,mmio32,0xf0000000,115200n8 console=tty0 console=ttyS0,115200n8 consoleblan=0 debug";
+       };
+
+       aliases {
+               serial0 = &uart0;
+       };
+
+       fpga {
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <1>;
+
+               /* child and parent address space 1:1 mapped */
+               ranges;
+
+               core_intc: core-interrupt-controller {
+                       compatible = "snps,archs-intc";
+                       interrupt-controller;
+                       #interrupt-cells = <1>;
+/*                     interrupts = <16 17 18 19 20 21 22 23 24 25>; */
+               };
+
+               idu_intc: idu-interrupt-controller {
+                       compatible = "snps,archs-idu-intc";
+                       interrupt-controller;
+                       interrupt-parent = <&core_intc>;
+
+                       /*
+                        * <hwirq  distribution>
+                        * distribution: 0=RR; 1=cpu0, 2=cpu1, 4=cpu2, 8=cpu3
+                        */
+                       #interrupt-cells = <2>;
+
+                       /*
+                        * upstream irqs to core intc - downstream these are
+                        * "COMMON" irq 0,1..
+                        */
+                       interrupts = <24 25 26 27 28 29 30 31>;
+               };
+
+               uart0: serial@f0000000 {
+                       compatible = "ns8250";
+                       reg = <0xf0000000 0x2000>;
+                       interrupt-parent = <&idu_intc>;
+                       interrupts = <0 0>; /* cmn irq 0 -> cpu irq 24
+                                               RR distribute to all cpus */
+                       clock-frequency = <3686400>;
+                       baud = <115200>;
+                       reg-shift = <2>;
+                       reg-io-width = <4>;
+                       no-loopback-test = <1>;
+               };
+
+               pgu0: pgu@f9000000 {
+                       compatible = "snps,arcpgufb";
+                       reg = <0xf9000000 0x400>;
+               };
+
+               ps2: ps2@f9001000 {
+                       compatible = "snps,arc_ps2";
+                       reg = <0xf9000400 0x14>;
+                       interrupts = <3 0>;
+                       interrupt-parent = <&idu_intc>;
+                       interrupt-names = "arc_ps2_irq";
+               };
+
+               eth0: ethernet@f0003000 {
+                       compatible = "snps,oscilan";
+                       reg = <0xf0003000 0x44>;
+                       interrupt-parent = <&idu_intc>;
+                       interrupts = <1 2>, <2 2>;
+                       interrupt-names = "rx", "tx";
+               };
+
+               arcpct0: pct {
+                       compatible = "snps,archs-pct";
+                       #interrupt-cells = <1>;
+                       interrupts = <20>;
+               };
+       };
+};
diff --git a/arch/arc/boot/dts/vdk_axc003.dtsi b/arch/arc/boot/dts/vdk_axc003.dtsi
new file mode 100644 (file)
index 0000000..9393fd9
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2013, 2014 Synopsys, Inc. (www.synopsys.com)
+ *
+ * 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.
+ */
+
+/*
+ * Device tree for AXC003 CPU card: HS38x UP configuration (VDK version)
+ */
+
+/ {
+       compatible = "snps,arc";
+       clock-frequency = <50000000>;
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       cpu_card {
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <1>;
+
+               ranges = <0x00000000 0xf0000000 0x10000000>;
+
+               cpu_intc: archs-intc@cpu {
+                       compatible = "snps,archs-intc";
+                       interrupt-controller;
+                       #interrupt-cells = <1>;
+               };
+
+               debug_uart: dw-apb-uart@0x5000 {
+                       compatible = "snps,dw-apb-uart";
+                       reg = <0x5000 0x100>;
+                       clock-frequency = <2403200>;
+                       interrupt-parent = <&cpu_intc>;
+                       interrupts = <19>;
+                       baud = <115200>;
+                       reg-shift = <2>;
+                       reg-io-width = <4>;
+               };
+
+       };
+
+       mb_intc: dw-apb-ictl@0xe0012000 {
+               #interrupt-cells = <1>;
+               compatible = "snps,dw-apb-ictl";
+               reg = < 0xe0012000 0x200 >;
+               interrupt-controller;
+               interrupt-parent = <&cpu_intc>;
+               interrupts = < 18 >;
+       };
+
+       memory {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges = <0x00000000 0x80000000 0x40000000>;
+               device_type = "memory";
+               reg = <0x00000000 0x20000000>;  /* 512MiB */
+       };
+};
diff --git a/arch/arc/boot/dts/vdk_axc003_idu.dtsi b/arch/arc/boot/dts/vdk_axc003_idu.dtsi
new file mode 100644 (file)
index 0000000..9bee8ed
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2014, 2015 Synopsys, Inc. (www.synopsys.com)
+ *
+ * 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.
+ */
+
+/*
+ * Device tree for AXC003 CPU card:
+ * HS38x2 (Dual Core) with IDU intc (VDK version)
+ */
+
+/ {
+       compatible = "snps,arc";
+       clock-frequency = <50000000>;
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       cpu_card {
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <1>;
+
+               ranges = <0x00000000 0xf0000000 0x10000000>;
+
+               cpu_intc: archs-intc@cpu {
+                       compatible = "snps,archs-intc";
+                       interrupt-controller;
+                       #interrupt-cells = <1>;
+               };
+
+               idu_intc: idu-interrupt-controller {
+                       compatible = "snps,archs-idu-intc";
+                       interrupt-controller;
+                       interrupt-parent = <&cpu_intc>;
+
+                       /*
+                        * <hwirq  distribution>
+                        * distribution: 0=RR; 1=cpu0, 2=cpu1, 4=cpu2, 8=cpu3
+                        */
+                       #interrupt-cells = <2>;
+
+                       interrupts = <24 25 26 27>;
+               };
+
+               debug_uart: dw-apb-uart@0x5000 {
+                       compatible = "snps,dw-apb-uart";
+                       reg = <0x5000 0x100>;
+                       clock-frequency = <2403200>;
+                       interrupt-parent = <&idu_intc>;
+                       interrupts = <2 0>;
+                       baud = <115200>;
+                       reg-shift = <2>;
+                       reg-io-width = <4>;
+               };
+
+       };
+
+       mb_intc: dw-apb-ictl@0xe0012000 {
+               #interrupt-cells = <1>;
+               compatible = "snps,dw-apb-ictl";
+               reg = < 0xe0012000 0x200 >;
+               interrupt-controller;
+               interrupt-parent = <&idu_intc>;
+               interrupts = < 0 0 >;
+       };
+
+       memory {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges = <0x00000000 0x80000000 0x40000000>;
+               device_type = "memory";
+               reg = <0x00000000 0x20000000>;  /* 512MiB */
+       };
+};
diff --git a/arch/arc/boot/dts/vdk_axs10x_mb.dtsi b/arch/arc/boot/dts/vdk_axs10x_mb.dtsi
new file mode 100644 (file)
index 0000000..45cd665
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * Support for peripherals on the AXS10x mainboard (VDK version)
+ *
+ * Copyright (C) 2013-15 Synopsys, Inc. (www.synopsys.com)
+ *
+ * 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.
+ */
+
+/ {
+       axs10x_mb_vdk {
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges = <0x00000000 0xe0000000 0x10000000>;
+               interrupt-parent = <&mb_intc>;
+
+               clocks {
+                       apbclk: apbclk {
+                               compatible = "fixed-clock";
+                               clock-frequency = <50000000>;
+                               #clock-cells = <0>;
+                       };
+
+               };
+
+               ethernet@0x18000 {
+                       #interrupt-cells = <1>;
+                       compatible = "snps,dwmac";
+                       reg = < 0x18000 0x2000 >;
+                       interrupts = < 4 >;
+                       interrupt-names = "macirq";
+                       phy-mode = "rgmii";
+                       snps,phy-addr = < 0 >;  // VDK model phy address is 0
+                       snps,pbl = < 32 >;
+                       clocks = <&apbclk>;
+                       clock-names = "stmmaceth";
+               };
+
+               ehci@0x40000 {
+                       compatible = "generic-ehci";
+                       reg = < 0x40000 0x100 >;
+                       interrupts = < 8 >;
+               };
+
+               uart@0x20000 {
+                       compatible = "snps,dw-apb-uart";
+                       reg = <0x20000 0x100>;
+                       clock-frequency = <2403200>;
+                       interrupts = <17>;
+                       baud = <115200>;
+                       reg-shift = <2>;
+                       reg-io-width = <4>;
+               };
+
+               uart@0x21000 {
+                       compatible = "snps,dw-apb-uart";
+                       reg = <0x21000 0x100>;
+                       clock-frequency = <2403200>;
+                       interrupts = <18>;
+                       baud = <115200>;
+                       reg-shift = <2>;
+                       reg-io-width = <4>;
+               };
+
+               uart@0x22000 {
+                       compatible = "snps,dw-apb-uart";
+                       reg = <0x22000 0x100>;
+                       clock-frequency = <2403200>;
+                       interrupts = <19>;
+                       baud = <115200>;
+                       reg-shift = <2>;
+                       reg-io-width = <4>;
+               };
+
+/* PGU output directly sent to virtual LCD screen; hdmi controller not modelled */
+               pgu@0x17000 {
+                       compatible = "snps,arcpgufb";
+                       reg = <0x17000 0x400>;
+                       clock-frequency = <51000000>; /* PGU'clock is initated in init function */
+                       /* interrupts = <5>;   PGU interrupts not used, this vector is used for ps2 below */
+               };
+
+/* VDK has additional ps2 keyboard/mouse interface integrated in LCD screen model */
+               ps2: ps2@e0017400 {
+                       compatible = "snps,arc_ps2";
+                       reg = <0x17400 0x14>;
+                       interrupts = <5>;
+                       interrupt-names = "arc_ps2_irq";
+               };
+       };
+};
diff --git a/arch/arc/boot/dts/vdk_hs38.dts b/arch/arc/boot/dts/vdk_hs38.dts
new file mode 100644 (file)
index 0000000..5d803dd
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2013 Synopsys, Inc. (www.synopsys.com)
+ *
+ * ARC HS38 Virtual Development Kit (VDK)
+ *
+ * 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.
+ */
+/dts-v1/;
+
+/include/ "vdk_axc003.dtsi"
+/include/ "vdk_axs10x_mb.dtsi"
+
+/ {
+       compatible = "snps,axs103";
+
+       chosen {
+               bootargs = "earlycon=uart8250,mmio32,0xe0022000,115200n8 console=tty0 console=ttyS3,115200n8 consoleblank=0";
+       };
+};
diff --git a/arch/arc/boot/dts/vdk_hs38_smp.dts b/arch/arc/boot/dts/vdk_hs38_smp.dts
new file mode 100644 (file)
index 0000000..031a5bc
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2013 Synopsys, Inc. (www.synopsys.com)
+ *
+ * ARC HS38 Virtual Development Kit, SMP version (VDK)
+ *
+ * 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.
+ */
+/dts-v1/;
+
+/include/ "vdk_axc003_idu.dtsi"
+/include/ "vdk_axs10x_mb.dtsi"
+
+/ {
+       compatible = "snps,axs103";
+
+       chosen {
+               bootargs = "earlycon=uart8250,mmio32,0xe0022000,115200n8 console=tty0 console=ttyS3,115200n8 consoleblank=0";
+       };
+};
diff --git a/arch/arc/configs/axs101_defconfig b/arch/arc/configs/axs101_defconfig
new file mode 100644 (file)
index 0000000..562dac6
--- /dev/null
@@ -0,0 +1,111 @@
+CONFIG_CROSS_COMPILE="arc-linux-uclibc-"
+CONFIG_DEFAULT_HOSTNAME="ARCLinux"
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+# CONFIG_CROSS_MEMORY_ATTACH is not set
+CONFIG_NO_HZ_IDLE=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_PID_NS is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE="../arc_initramfs/"
+CONFIG_EMBEDDED=y
+CONFIG_PERF_EVENTS=y
+# CONFIG_VM_EVENT_COUNTERS is not set
+# CONFIG_SLUB_DEBUG is not set
+# CONFIG_COMPAT_BRK is not set
+CONFIG_MODULES=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_ARC_PLAT_AXS10X=y
+CONFIG_AXS101=y
+CONFIG_ARC_CACHE_LINE_SHIFT=5
+CONFIG_ARC_BUILTIN_DTB_NAME="axs101"
+CONFIG_PREEMPT=y
+# CONFIG_COMPACTION is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_IPV6 is not set
+# CONFIG_STANDALONE is not set
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+# CONFIG_FIRMWARE_IN_KERNEL is not set
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_NETDEVICES=y
+# CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+CONFIG_STMMAC_ETH=y
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+CONFIG_NATIONAL_PHY=y
+# CONFIG_USB_NET_DRIVERS is not set
+CONFIG_INPUT_EVDEV=y
+CONFIG_MOUSE_PS2_TOUCHKIT=y
+CONFIG_MOUSE_SERIAL=y
+CONFIG_MOUSE_SYNAPTICS_USB=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_DW=y
+CONFIG_SERIAL_OF_PLATFORM=y
+# CONFIG_HW_RANDOM is not set
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_DESIGNWARE_PLATFORM=y
+# CONFIG_HWMON is not set
+CONFIG_FB=y
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+# CONFIG_LOGO_LINUX_CLUT224 is not set
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_HCD_PLATFORM=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_HCD_PLATFORM=y
+CONFIG_USB_STORAGE=y
+CONFIG_MMC=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_DW=y
+CONFIG_MMC_DW_IDMAC=y
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT4_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_NTFS_FS=y
+CONFIG_TMPFS=y
+CONFIG_JFFS2_FS=y
+CONFIG_NFS_FS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_STRIP_ASM_SYMS=y
+CONFIG_LOCKUP_DETECTOR=y
+CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=10
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_DEBUG_PREEMPT is not set
+# CONFIG_FTRACE is not set
diff --git a/arch/arc/configs/axs103_defconfig b/arch/arc/configs/axs103_defconfig
new file mode 100644 (file)
index 0000000..83a6d8d
--- /dev/null
@@ -0,0 +1,117 @@
+CONFIG_CROSS_COMPILE="arc-linux-uclibc-"
+CONFIG_DEFAULT_HOSTNAME="ARCLinux"
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+# CONFIG_CROSS_MEMORY_ATTACH is not set
+CONFIG_NO_HZ_IDLE=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_PID_NS is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE="../../arc_initramfs_hs/"
+CONFIG_EMBEDDED=y
+CONFIG_PERF_EVENTS=y
+# CONFIG_VM_EVENT_COUNTERS is not set
+# CONFIG_SLUB_DEBUG is not set
+# CONFIG_COMPAT_BRK is not set
+CONFIG_MODULES=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_ARC_PLAT_AXS10X=y
+CONFIG_AXS103=y
+CONFIG_ISA_ARCV2=y
+CONFIG_ARC_BUILTIN_DTB_NAME="axs103"
+CONFIG_PREEMPT=y
+# CONFIG_COMPACTION is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_IPV6 is not set
+# CONFIG_STANDALONE is not set
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+# CONFIG_FIRMWARE_IN_KERNEL is not set
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_AXS=y
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_NETDEVICES=y
+# CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+CONFIG_STMMAC_ETH=y
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+CONFIG_NATIONAL_PHY=y
+# CONFIG_USB_NET_DRIVERS is not set
+CONFIG_INPUT_EVDEV=y
+CONFIG_MOUSE_PS2_TOUCHKIT=y
+CONFIG_MOUSE_SERIAL=y
+CONFIG_MOUSE_SYNAPTICS_USB=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_DW=y
+CONFIG_SERIAL_OF_PLATFORM=y
+# CONFIG_HW_RANDOM is not set
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_DESIGNWARE_PLATFORM=y
+# CONFIG_HWMON is not set
+CONFIG_FB=y
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+# CONFIG_LOGO_LINUX_CLUT224 is not set
+CONFIG_USB=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_HCD_PLATFORM=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_HCD_PLATFORM=y
+CONFIG_USB_STORAGE=y
+CONFIG_MMC=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_DW=y
+CONFIG_MMC_DW_IDMAC=y
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT4_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_NTFS_FS=y
+CONFIG_TMPFS=y
+CONFIG_JFFS2_FS=y
+CONFIG_NFS_FS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_STRIP_ASM_SYMS=y
+CONFIG_LOCKUP_DETECTOR=y
+CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=10
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_DEBUG_PREEMPT is not set
+# CONFIG_FTRACE is not set
diff --git a/arch/arc/configs/axs103_smp_defconfig b/arch/arc/configs/axs103_smp_defconfig
new file mode 100644 (file)
index 0000000..f1e1c84
--- /dev/null
@@ -0,0 +1,118 @@
+CONFIG_CROSS_COMPILE="arc-linux-uclibc-"
+CONFIG_DEFAULT_HOSTNAME="ARCLinux"
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+# CONFIG_CROSS_MEMORY_ATTACH is not set
+CONFIG_NO_HZ_IDLE=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_PID_NS is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE="../../arc_initramfs_hs/"
+CONFIG_EMBEDDED=y
+CONFIG_PERF_EVENTS=y
+# CONFIG_VM_EVENT_COUNTERS is not set
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLAB=y
+CONFIG_MODULES=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_ARC_PLAT_AXS10X=y
+CONFIG_AXS103=y
+CONFIG_ISA_ARCV2=y
+CONFIG_SMP=y
+CONFIG_ARC_BUILTIN_DTB_NAME="axs103_idu"
+CONFIG_PREEMPT=y
+# CONFIG_COMPACTION is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_IPV6 is not set
+# CONFIG_STANDALONE is not set
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+# CONFIG_FIRMWARE_IN_KERNEL is not set
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_AXS=y
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_NETDEVICES=y
+# CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+CONFIG_STMMAC_ETH=y
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+CONFIG_NATIONAL_PHY=y
+# CONFIG_USB_NET_DRIVERS is not set
+CONFIG_INPUT_EVDEV=y
+CONFIG_MOUSE_PS2_TOUCHKIT=y
+CONFIG_MOUSE_SERIAL=y
+CONFIG_MOUSE_SYNAPTICS_USB=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_DW=y
+CONFIG_SERIAL_OF_PLATFORM=y
+# CONFIG_HW_RANDOM is not set
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_DESIGNWARE_PLATFORM=y
+# CONFIG_HWMON is not set
+CONFIG_FB=y
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+# CONFIG_LOGO_LINUX_CLUT224 is not set
+CONFIG_USB=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_HCD_PLATFORM=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_HCD_PLATFORM=y
+CONFIG_USB_STORAGE=y
+CONFIG_MMC=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_DW=y
+CONFIG_MMC_DW_IDMAC=y
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT4_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_NTFS_FS=y
+CONFIG_TMPFS=y
+CONFIG_JFFS2_FS=y
+CONFIG_NFS_FS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_STRIP_ASM_SYMS=y
+CONFIG_LOCKUP_DETECTOR=y
+CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=10
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_DEBUG_PREEMPT is not set
+# CONFIG_FTRACE is not set
index ef4d3bc7b6c05fdaa414c3c0312bfb829ab769e9..138f9d8879570a8b329415d9238c710fa6e5b032 100644 (file)
@@ -1,4 +1,4 @@
-CONFIG_CROSS_COMPILE="arc-linux-uclibc-"
+CONFIG_CROSS_COMPILE="arc-linux-"
 # CONFIG_LOCALVERSION_AUTO is not set
 CONFIG_DEFAULT_HOSTNAME="ARCLinux"
 # CONFIG_SWAP is not set
@@ -22,9 +22,8 @@ CONFIG_MODULES=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_IOSCHED_DEADLINE is not set
 # CONFIG_IOSCHED_CFQ is not set
-CONFIG_ARC_PLAT_FPGA_LEGACY=y
-# CONFIG_ARC_HAS_RTSC is not set
-CONFIG_ARC_BUILTIN_DTB_NAME="angel4"
+CONFIG_ARC_PLAT_SIM=y
+CONFIG_ARC_BUILTIN_DTB_NAME="nsim_700"
 CONFIG_PREEMPT=y
 # CONFIG_COMPACTION is not set
 # CONFIG_CROSS_MEMORY_ATTACH is not set
diff --git a/arch/arc/configs/nsim_hs_defconfig b/arch/arc/configs/nsim_hs_defconfig
new file mode 100644 (file)
index 0000000..f761a7c
--- /dev/null
@@ -0,0 +1,64 @@
+CONFIG_CROSS_COMPILE="arc-linux-uclibc-"
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_DEFAULT_HOSTNAME="ARCLinux"
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+# CONFIG_CROSS_MEMORY_ATTACH is not set
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_PID_NS is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE="../arc_initramfs_hs/"
+CONFIG_KALLSYMS_ALL=y
+CONFIG_EMBEDDED=y
+# CONFIG_SLUB_DEBUG is not set
+# CONFIG_COMPAT_BRK is not set
+CONFIG_KPROBES=y
+CONFIG_MODULES=y
+# CONFIG_LBDAF is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_ARC_PLAT_SIM=y
+CONFIG_ISA_ARCV2=y
+CONFIG_ARC_BUILTIN_DTB_NAME="nsim_hs"
+CONFIG_PREEMPT=y
+# CONFIG_COMPACTION is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_UNIX_DIAG=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+# CONFIG_IPV6 is not set
+# CONFIG_STANDALONE is not set
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+# CONFIG_FIRMWARE_IN_KERNEL is not set
+# CONFIG_BLK_DEV is not set
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_SERIO is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_ARC=y
+CONFIG_SERIAL_ARC_CONSOLE=y
+# CONFIG_HW_RANDOM is not set
+# CONFIG_HWMON is not set
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_HID is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_TMPFS=y
+# CONFIG_MISC_FILESYSTEMS is not set
+CONFIG_NFS_FS=y
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+# CONFIG_DEBUG_PREEMPT is not set
+CONFIG_XZ_DEC=y
diff --git a/arch/arc/configs/nsim_hs_smp_defconfig b/arch/arc/configs/nsim_hs_smp_defconfig
new file mode 100644 (file)
index 0000000..dc6f74f
--- /dev/null
@@ -0,0 +1,63 @@
+CONFIG_CROSS_COMPILE="arc-linux-uclibc-"
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_DEFAULT_HOSTNAME="ARCLinux"
+# CONFIG_SWAP is not set
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_PID_NS is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE="../arc_initramfs_hs/"
+CONFIG_KALLSYMS_ALL=y
+CONFIG_EMBEDDED=y
+# CONFIG_SLUB_DEBUG is not set
+# CONFIG_COMPAT_BRK is not set
+CONFIG_KPROBES=y
+CONFIG_MODULES=y
+# CONFIG_LBDAF is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_ARC_PLAT_SIM=y
+CONFIG_ARC_BOARD_ML509=y
+CONFIG_ISA_ARCV2=y
+CONFIG_SMP=y
+CONFIG_ARC_BUILTIN_DTB_NAME="nsim_hs_idu"
+CONFIG_PREEMPT=y
+# CONFIG_COMPACTION is not set
+# CONFIG_CROSS_MEMORY_ATTACH is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_UNIX_DIAG=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+# CONFIG_IPV6 is not set
+# CONFIG_STANDALONE is not set
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+# CONFIG_FIRMWARE_IN_KERNEL is not set
+# CONFIG_BLK_DEV is not set
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_SERIO is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_ARC=y
+CONFIG_SERIAL_ARC_CONSOLE=y
+# CONFIG_HW_RANDOM is not set
+# CONFIG_HWMON is not set
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_HID is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_TMPFS=y
+# CONFIG_MISC_FILESYSTEMS is not set
+CONFIG_NFS_FS=y
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_XZ_DEC=y
index d2ac4e56ba1dd6955c43044aa0ec8da7e062c785..31e1d95764ff91dc10fe80d936a5613e6f713cc4 100644 (file)
@@ -1,4 +1,4 @@
-CONFIG_CROSS_COMPILE="arc-linux-uclibc-"
+CONFIG_CROSS_COMPILE="arc-linux-"
 # CONFIG_LOCALVERSION_AUTO is not set
 CONFIG_DEFAULT_HOSTNAME="ARCLinux"
 # CONFIG_SWAP is not set
@@ -23,8 +23,7 @@ CONFIG_MODULES=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_IOSCHED_DEADLINE is not set
 # CONFIG_IOSCHED_CFQ is not set
-CONFIG_ARC_PLAT_FPGA_LEGACY=y
-# CONFIG_ARC_HAS_RTSC is not set
+CONFIG_ARC_PLAT_SIM=y
 CONFIG_ARC_BUILTIN_DTB_NAME="nsimosci"
 # CONFIG_COMPACTION is not set
 CONFIG_NET=y
diff --git a/arch/arc/configs/nsimosci_hs_defconfig b/arch/arc/configs/nsimosci_hs_defconfig
new file mode 100644 (file)
index 0000000..3fef0a2
--- /dev/null
@@ -0,0 +1,73 @@
+CONFIG_CROSS_COMPILE="arc-linux-uclibc-"
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_DEFAULT_HOSTNAME="ARCLinux"
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+# CONFIG_CROSS_MEMORY_ATTACH is not set
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_PID_NS is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE="../arc_initramfs_hs/"
+CONFIG_KALLSYMS_ALL=y
+CONFIG_EMBEDDED=y
+# CONFIG_SLUB_DEBUG is not set
+# CONFIG_COMPAT_BRK is not set
+CONFIG_KPROBES=y
+CONFIG_MODULES=y
+# CONFIG_LBDAF is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_ARC_PLAT_SIM=y
+CONFIG_ISA_ARCV2=y
+CONFIG_ARC_BUILTIN_DTB_NAME="nsimosci_hs"
+# CONFIG_COMPACTION is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_UNIX_DIAG=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+# CONFIG_IPV6 is not set
+# CONFIG_STANDALONE is not set
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+# CONFIG_FIRMWARE_IN_KERNEL is not set
+# CONFIG_BLK_DEV is not set
+CONFIG_NETDEVICES=y
+CONFIG_NET_OSCI_LAN=y
+CONFIG_INPUT_EVDEV=y
+# CONFIG_MOUSE_PS2_ALPS is not set
+# CONFIG_MOUSE_PS2_LOGIPS2PP is not set
+# CONFIG_MOUSE_PS2_SYNAPTICS is not set
+# CONFIG_MOUSE_PS2_TRACKPOINT is not set
+CONFIG_MOUSE_PS2_TOUCHKIT=y
+# CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIO_ARC_PS2=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=1
+CONFIG_SERIAL_8250_RUNTIME_UARTS=1
+CONFIG_SERIAL_OF_PLATFORM=y
+# CONFIG_HW_RANDOM is not set
+# CONFIG_HWMON is not set
+CONFIG_FB=y
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_LOGO=y
+# CONFIG_HID is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_TMPFS=y
+# CONFIG_MISC_FILESYSTEMS is not set
+CONFIG_NFS_FS=y
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
diff --git a/arch/arc/configs/nsimosci_hs_smp_defconfig b/arch/arc/configs/nsimosci_hs_smp_defconfig
new file mode 100644 (file)
index 0000000..5178483
--- /dev/null
@@ -0,0 +1,93 @@
+CONFIG_CROSS_COMPILE="arc-linux-uclibc-"
+CONFIG_DEFAULT_HOSTNAME="ARCLinux"
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+# CONFIG_UTS_NS is not set
+# CONFIG_PID_NS is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE="../arc_initramfs_hs/"
+# CONFIG_COMPAT_BRK is not set
+CONFIG_KPROBES=y
+CONFIG_MODULES=y
+# CONFIG_LBDAF is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_ARC_PLAT_SIM=y
+CONFIG_ARC_BOARD_ML509=y
+CONFIG_ISA_ARCV2=y
+CONFIG_SMP=y
+CONFIG_ARC_HAS_LL64=y
+# CONFIG_ARC_HAS_RTSC is not set
+CONFIG_ARC_BUILTIN_DTB_NAME="nsimosci_hs_idu"
+CONFIG_PREEMPT=y
+# CONFIG_COMPACTION is not set
+# CONFIG_CROSS_MEMORY_ATTACH is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_PACKET_DIAG=y
+CONFIG_UNIX=y
+CONFIG_UNIX_DIAG=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_IPV6 is not set
+# CONFIG_WIRELESS is not set
+# CONFIG_STANDALONE is not set
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+# CONFIG_FIRMWARE_IN_KERNEL is not set
+# CONFIG_BLK_DEV is not set
+CONFIG_NETDEVICES=y
+# CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+CONFIG_NET_OSCI_LAN=y
+# CONFIG_WLAN is not set
+CONFIG_INPUT_EVDEV=y
+CONFIG_MOUSE_PS2_TOUCHKIT=y
+# CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIO_ARC_PS2=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=1
+CONFIG_SERIAL_8250_RUNTIME_UARTS=1
+CONFIG_SERIAL_8250_DW=y
+CONFIG_SERIAL_OF_PLATFORM=y
+# CONFIG_HW_RANDOM is not set
+# CONFIG_HWMON is not set
+CONFIG_FB=y
+CONFIG_ARCPGU_RGB888=y
+CONFIG_ARCPGU_DISPTYPE=0
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_LOGO=y
+# CONFIG_HID is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_TMPFS=y
+# CONFIG_MISC_FILESYSTEMS is not set
+CONFIG_NFS_FS=y
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_FTRACE=y
index 6be6492442d640d3aba09b42239650995aa6e5be..3b4dc9cebcf15234f3d42a4efd2e40b9c5bd4150 100644 (file)
@@ -1,4 +1,4 @@
-CONFIG_CROSS_COMPILE="arc-linux-uclibc-"
+CONFIG_CROSS_COMPILE="arc-linux-"
 # CONFIG_LOCALVERSION_AUTO is not set
 CONFIG_DEFAULT_HOSTNAME="tb10x"
 CONFIG_SYSVIPC=y
@@ -26,7 +26,6 @@ CONFIG_MODULE_UNLOAD=y
 # CONFIG_BLOCK is not set
 CONFIG_ARC_PLAT_TB10X=y
 CONFIG_ARC_CACHE_LINE_SHIFT=5
-# CONFIG_ARC_HAS_RTSC is not set
 CONFIG_ARC_STACK_NONEXEC=y
 CONFIG_HZ=250
 CONFIG_ARC_BUILTIN_DTB_NAME="abilis_tb100_dvk"
diff --git a/arch/arc/configs/vdk_hs38_defconfig b/arch/arc/configs/vdk_hs38_defconfig
new file mode 100644 (file)
index 0000000..ef35ef3
--- /dev/null
@@ -0,0 +1,102 @@
+CONFIG_CROSS_COMPILE="arc-linux-uclibc-"
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_DEFAULT_HOSTNAME="ARCLinux"
+# CONFIG_CROSS_MEMORY_ATTACH is not set
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_EMBEDDED=y
+CONFIG_PERF_EVENTS=y
+# CONFIG_VM_EVENT_COUNTERS is not set
+# CONFIG_SLUB_DEBUG is not set
+# CONFIG_COMPAT_BRK is not set
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_ARC_PLAT_AXS10X=y
+CONFIG_AXS103=y
+CONFIG_ISA_ARCV2=y
+CONFIG_ARC_UBOOT_SUPPORT=y
+CONFIG_ARC_BUILTIN_DTB_NAME="vdk_hs38"
+CONFIG_PREEMPT=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+# CONFIG_IPV6 is not set
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_STANDALONE is not set
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+# CONFIG_FIRMWARE_IN_KERNEL is not set
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_SLRAM=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_NETDEVICES=y
+# CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+CONFIG_STMMAC_ETH=y
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+CONFIG_NATIONAL_PHY=y
+CONFIG_MOUSE_PS2_TOUCHKIT=y
+CONFIG_SERIO_ARC_PS2=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_DW=y
+CONFIG_SERIAL_OF_PLATFORM=y
+# CONFIG_HW_RANDOM is not set
+# CONFIG_HWMON is not set
+CONFIG_FB=y
+CONFIG_ARCPGU_RGB888=y
+CONFIG_ARCPGU_DISPTYPE=0
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+# CONFIG_LOGO_LINUX_CLUT224 is not set
+CONFIG_USB=y
+CONFIG_USB_EHCI_HCD=y
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+CONFIG_USB_EHCI_HCD_PLATFORM=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_HCD_PLATFORM=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_SERIAL=y
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT4_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_NTFS_FS=y
+CONFIG_TMPFS=y
+CONFIG_JFFS2_FS=y
+CONFIG_NFS_FS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_STRIP_ASM_SYMS=y
+CONFIG_DEBUG_SHIRQ=y
+CONFIG_LOCKUP_DETECTOR=y
+CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=10
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_DEBUG_PREEMPT is not set
+# CONFIG_FTRACE is not set
diff --git a/arch/arc/configs/vdk_hs38_smp_defconfig b/arch/arc/configs/vdk_hs38_smp_defconfig
new file mode 100644 (file)
index 0000000..634509e
--- /dev/null
@@ -0,0 +1,104 @@
+CONFIG_CROSS_COMPILE="arc-linux-uclibc-"
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_DEFAULT_HOSTNAME="ARCLinux"
+# CONFIG_CROSS_MEMORY_ATTACH is not set
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_EMBEDDED=y
+CONFIG_PERF_EVENTS=y
+# CONFIG_VM_EVENT_COUNTERS is not set
+# CONFIG_SLUB_DEBUG is not set
+# CONFIG_COMPAT_BRK is not set
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_ARC_PLAT_AXS10X=y
+CONFIG_AXS103=y
+CONFIG_ISA_ARCV2=y
+CONFIG_SMP=y
+# CONFIG_ARC_HAS_GRTC is not set
+CONFIG_ARC_UBOOT_SUPPORT=y
+CONFIG_ARC_BUILTIN_DTB_NAME="vdk_hs38_smp"
+CONFIG_PREEMPT=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+# CONFIG_IPV6 is not set
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_STANDALONE is not set
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+# CONFIG_FIRMWARE_IN_KERNEL is not set
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_SLRAM=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_NETDEVICES=y
+# CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+CONFIG_STMMAC_ETH=y
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+CONFIG_NATIONAL_PHY=y
+CONFIG_MOUSE_PS2_TOUCHKIT=y
+CONFIG_SERIO_ARC_PS2=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_DW=y
+CONFIG_SERIAL_OF_PLATFORM=y
+# CONFIG_HW_RANDOM is not set
+# CONFIG_HWMON is not set
+CONFIG_FB=y
+CONFIG_ARCPGU_RGB888=y
+CONFIG_ARCPGU_DISPTYPE=0
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+# CONFIG_LOGO_LINUX_CLUT224 is not set
+CONFIG_USB=y
+CONFIG_USB_EHCI_HCD=y
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+CONFIG_USB_EHCI_HCD_PLATFORM=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_HCD_PLATFORM=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_SERIAL=y
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT4_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_NTFS_FS=y
+CONFIG_TMPFS=y
+CONFIG_JFFS2_FS=y
+CONFIG_NFS_FS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_STRIP_ASM_SYMS=y
+CONFIG_DEBUG_SHIRQ=y
+CONFIG_LOCKUP_DETECTOR=y
+CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=10
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_DEBUG_PREEMPT is not set
+# CONFIG_FTRACE is not set
index 769b312c1abb5406c34f52a2db5201a490be8a0b..1a80cc91a03ba323f8418dfb705098a00f031671 100644 (file)
@@ -1,5 +1,4 @@
 generic-y += auxvec.h
-generic-y += barrier.h
 generic-y += bitsperlong.h
 generic-y += bugs.h
 generic-y += clkdev.h
index e2b1b1211b0d4ddbb527ed7239eaf05759dfae27..070f58827a5c12c2e19469ff4280f7c69e0f36a3 100644 (file)
@@ -16,6 +16,8 @@
 #define ARC_REG_PERIBASE_BCR   0x69
 #define ARC_REG_FP_BCR         0x6B    /* ARCompact: Single-Precision FPU */
 #define ARC_REG_DPFP_BCR       0x6C    /* ARCompact: Dbl Precision FPU */
+#define ARC_REG_FP_V2_BCR      0xc8    /* ARCv2 FPU */
+#define ARC_REG_SLC_BCR                0xce
 #define ARC_REG_DCCM_BCR       0x74    /* DCCM Present + SZ */
 #define ARC_REG_TIMERS_BCR     0x75
 #define ARC_REG_AP_BCR         0x76
@@ -31,6 +33,7 @@
 #define ARC_REG_BPU_BCR                0xc0
 #define ARC_REG_ISA_CFG_BCR    0xc1
 #define ARC_REG_RTT_BCR                0xF2
+#define ARC_REG_IRQ_BCR                0xF3
 #define ARC_REG_SMART_BCR      0xFF
 
 /* status32 Bits Positions */
@@ -51,6 +54,7 @@
  * [15: 8] = Exception Cause Code
  * [ 7: 0] = Exception Parameters (for certain types only)
  */
+#ifdef CONFIG_ISA_ARCOMPACT
 #define ECR_V_MEM_ERR                  0x01
 #define ECR_V_INSN_ERR                 0x02
 #define ECR_V_MACH_CHK                 0x20
 #define ECR_V_DTLB_MISS                        0x22
 #define ECR_V_PROTV                    0x23
 #define ECR_V_TRAP                     0x25
+#else
+#define ECR_V_MEM_ERR                  0x01
+#define ECR_V_INSN_ERR                 0x02
+#define ECR_V_MACH_CHK                 0x03
+#define ECR_V_ITLB_MISS                        0x04
+#define ECR_V_DTLB_MISS                        0x05
+#define ECR_V_PROTV                    0x06
+#define ECR_V_TRAP                     0x09
+#endif
 
 /* DTLB Miss and Protection Violation Cause Codes */
 
@@ -76,9 +89,6 @@
 #define ECR_C_BIT_DTLB_LD_MISS         8
 #define ECR_C_BIT_DTLB_ST_MISS         9
 
-/* Dummy ECR values for Interrupts */
-#define event_IRQ1             0x0031abcd
-#define event_IRQ2             0x0032abcd
 
 /* Auxiliary registers */
 #define AUX_IDENTITY           4
@@ -204,9 +214,11 @@ struct bcr_identity {
 
 struct bcr_isa {
 #ifdef CONFIG_CPU_BIG_ENDIAN
-       unsigned int pad1:23, atomic1:1, ver:8;
+       unsigned int div_rem:4, pad2:4, ldd:1, unalign:1, atomic:1, be:1,
+                    pad1:11, atomic1:1, ver:8;
 #else
-       unsigned int ver:8, atomic1:1, pad1:23;
+       unsigned int ver:8, atomic1:1, pad1:11, be:1, atomic:1, unalign:1,
+                    ldd:1, pad2:4, div_rem:4;
 #endif
 };
 
@@ -269,11 +281,19 @@ struct bcr_fp_arcompact {
 #endif
 };
 
+struct bcr_fp_arcv2 {
+#ifdef CONFIG_CPU_BIG_ENDIAN
+       unsigned int pad2:15, dp:1, pad1:7, sp:1, ver:8;
+#else
+       unsigned int ver:8, sp:1, pad1:7, dp:1, pad2:15;
+#endif
+};
+
 struct bcr_timer {
 #ifdef CONFIG_CPU_BIG_ENDIAN
-       unsigned int pad2:15, rtsc:1, pad1:6, t1:1, t0:1, ver:8;
+       unsigned int pad2:15, rtsc:1, pad1:5, rtc:1, t1:1, t0:1, ver:8;
 #else
-       unsigned int ver:8, t0:1, t1:1, pad1:6, rtsc:1, pad2:15;
+       unsigned int ver:8, t0:1, t1:1, rtc:1, pad1:5, rtsc:1, pad2:15;
 #endif
 };
 
@@ -285,6 +305,14 @@ struct bcr_bpu_arcompact {
 #endif
 };
 
+struct bcr_bpu_arcv2 {
+#ifdef CONFIG_CPU_BIG_ENDIAN
+       unsigned int pad:6, fbe:2, tqe:2, ts:4, ft:1, rse:2, pte:3, bce:3, ver:8;
+#else
+       unsigned int ver:8, bce:3, pte:3, rse:2, ft:1, ts:4, tqe:2, fbe:2, pad:6;
+#endif
+};
+
 struct bcr_generic {
 #ifdef CONFIG_CPU_BIG_ENDIAN
        unsigned int pad:24, ver:8;
@@ -299,11 +327,12 @@ struct bcr_generic {
  */
 
 struct cpuinfo_arc_mmu {
-       unsigned int ver, pg_sz, sets, ways, u_dtlb, u_itlb, num_tlb;
+       unsigned int ver:4, pg_sz_k:8, s_pg_sz_m:8, u_dtlb:6, u_itlb:6;
+       unsigned int num_tlb:16, sets:12, ways:4;
 };
 
 struct cpuinfo_arc_cache {
-       unsigned int sz_k:8, line_len:8, assoc:4, ver:4, alias:1, vipt:1, pad:6;
+       unsigned int sz_k:14, line_len:8, assoc:4, ver:4, alias:1, vipt:1;
 };
 
 struct cpuinfo_arc_bpu {
@@ -315,14 +344,13 @@ struct cpuinfo_arc_ccm {
 };
 
 struct cpuinfo_arc {
-       struct cpuinfo_arc_cache icache, dcache;
+       struct cpuinfo_arc_cache icache, dcache, slc;
        struct cpuinfo_arc_mmu mmu;
        struct cpuinfo_arc_bpu bpu;
        struct bcr_identity core;
        struct bcr_isa isa;
        struct bcr_timer timers;
        unsigned int vec_base;
-       unsigned int uncached_base;
        struct cpuinfo_arc_ccm iccm, dccm;
        struct {
                unsigned int swap:1, norm:1, minmax:1, barrel:1, crc:1, pad1:3,
@@ -336,6 +364,22 @@ struct cpuinfo_arc {
 
 extern struct cpuinfo_arc cpuinfo_arc700[];
 
+static inline int is_isa_arcv2(void)
+{
+       return IS_ENABLED(CONFIG_ISA_ARCV2);
+}
+
+static inline int is_isa_arcompact(void)
+{
+       return IS_ENABLED(CONFIG_ISA_ARCOMPACT);
+}
+
+#if defined(CONFIG_ISA_ARCOMPACT) && !defined(_CPU_DEFAULT_A7)
+#error "Toolchain not configured for ARCompact builds"
+#elif defined(CONFIG_ISA_ARCV2) && !defined(_CPU_DEFAULT_HS)
+#error "Toolchain not configured for ARCv2 builds"
+#endif
+
 #endif /* __ASEMBLY__ */
 
 #endif /* _ASM_ARC_ARCREGS_H */
index 9917a45fc430d042a4f59006abf84ceedad1bca7..03484cb4d16d2eb4fada0095ee427726c23bd2e1 100644 (file)
 
 #define atomic_set(v, i) (((v)->counter) = (i))
 
+#ifdef CONFIG_ISA_ARCV2
+#define PREFETCHW      "       prefetchw   [%1]        \n"
+#else
+#define PREFETCHW
+#endif
+
 #define ATOMIC_OP(op, c_op, asm_op)                                    \
 static inline void atomic_##op(int i, atomic_t *v)                     \
 {                                                                      \
        unsigned int temp;                                              \
                                                                        \
        __asm__ __volatile__(                                           \
-       "1:     llock   %0, [%1]        \n"                             \
+       "1:                             \n"                             \
+       PREFETCHW                                                       \
+       "       llock   %0, [%1]        \n"                             \
        "       " #asm_op " %0, %0, %2  \n"                             \
        "       scond   %0, [%1]        \n"                             \
        "       bnz     1b              \n"                             \
@@ -43,8 +51,16 @@ static inline int atomic_##op##_return(int i, atomic_t *v)           \
 {                                                                      \
        unsigned int temp;                                              \
                                                                        \
+       /*                                                              \
+        * Explicit full memory barrier needed before/after as          \
+        * LLOCK/SCOND thmeselves don't provide any such semantics      \
+        */                                                             \
+       smp_mb();                                                       \
+                                                                       \
        __asm__ __volatile__(                                           \
-       "1:     llock   %0, [%1]        \n"                             \
+       "1:                             \n"                             \
+       PREFETCHW                                                       \
+       "       llock   %0, [%1]        \n"                             \
        "       " #asm_op " %0, %0, %2  \n"                             \
        "       scond   %0, [%1]        \n"                             \
        "       bnz     1b              \n"                             \
@@ -52,6 +68,8 @@ static inline int atomic_##op##_return(int i, atomic_t *v)            \
        : "r"(&v->counter), "ir"(i)                                     \
        : "cc");                                                        \
                                                                        \
+       smp_mb();                                                       \
+                                                                       \
        return temp;                                                    \
 }
 
@@ -105,6 +123,9 @@ static inline int atomic_##op##_return(int i, atomic_t *v)          \
        unsigned long flags;                                            \
        unsigned long temp;                                             \
                                                                        \
+       /*                                                              \
+        * spin lock/unlock provides the needed smp_mb() before/after   \
+        */                                                             \
        atomic_ops_lock(flags);                                         \
        temp = v->counter;                                              \
        temp c_op i;                                                    \
@@ -142,9 +163,19 @@ ATOMIC_OP(and, &=, and)
 #define __atomic_add_unless(v, a, u)                                   \
 ({                                                                     \
        int c, old;                                                     \
+                                                                       \
+       /*                                                              \
+        * Explicit full memory barrier needed before/after as          \
+        * LLOCK/SCOND thmeselves don't provide any such semantics      \
+        */                                                             \
+       smp_mb();                                                       \
+                                                                       \
        c = atomic_read(v);                                             \
        while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c)\
                c = old;                                                \
+                                                                       \
+       smp_mb();                                                       \
+                                                                       \
        c;                                                              \
 })
 
diff --git a/arch/arc/include/asm/barrier.h b/arch/arc/include/asm/barrier.h
new file mode 100644 (file)
index 0000000..a720998
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2014-15 Synopsys, Inc. (www.synopsys.com)
+ *
+ * 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_BARRIER_H
+#define __ASM_BARRIER_H
+
+#ifdef CONFIG_ISA_ARCV2
+
+/*
+ * ARCv2 based HS38 cores are in-order issue, but still weakly ordered
+ * due to micro-arch buffering/queuing of load/store, cache hit vs. miss ...
+ *
+ * Explicit barrier provided by DMB instruction
+ *  - Operand supports fine grained load/store/load+store semantics
+ *  - Ensures that selected memory operation issued before it will complete
+ *    before any subsequent memory operation of same type
+ *  - DMB guarantees SMP as well as local barrier semantics
+ *    (asm-generic/barrier.h ensures sane smp_*mb if not defined here, i.e.
+ *    UP: barrier(), SMP: smp_*mb == *mb)
+ *  - DSYNC provides DMB+completion_of_cache_bpu_maintenance_ops hence not needed
+ *    in the general case. Plus it only provides full barrier.
+ */
+
+#define mb()   asm volatile("dmb 3\n" : : : "memory")
+#define rmb()  asm volatile("dmb 1\n" : : : "memory")
+#define wmb()  asm volatile("dmb 2\n" : : : "memory")
+
+#endif
+
+#ifdef CONFIG_ISA_ARCOMPACT
+
+/*
+ * ARCompact based cores (ARC700) only have SYNC instruction which is super
+ * heavy weight as it flushes the pipeline as well.
+ * There are no real SMP implementations of such cores.
+ */
+
+#define mb()   asm volatile("sync\n" : : : "memory")
+#endif
+
+#include <asm-generic/barrier.h>
+
+#endif
index 4051e9525939fd9050b06b048bec8e1a47307d7b..99fe118d3730bc050263e5be7dd3423ab659d46c 100644 (file)
 #include <linux/types.h>
 #include <linux/compiler.h>
 #include <asm/barrier.h>
+#ifndef CONFIG_ARC_HAS_LLSC
+#include <asm/smp.h>
+#endif
 
-/*
- * Hardware assisted read-modify-write using ARC700 LLOCK/SCOND insns.
- * The Kconfig glue ensures that in SMP, this is only set if the container
- * SoC/platform has cross-core coherent LLOCK/SCOND
- */
 #if defined(CONFIG_ARC_HAS_LLSC)
 
-static inline void set_bit(unsigned long nr, volatile unsigned long *m)
-{
-       unsigned int temp;
-
-       m += nr >> 5;
-
-       /*
-        * ARC ISA micro-optimization:
-        *
-        * Instructions dealing with bitpos only consider lower 5 bits (0-31)
-        * e.g (x << 33) is handled like (x << 1) by ASL instruction
-        *  (mem pointer still needs adjustment to point to next word)
-        *
-        * Hence the masking to clamp @nr arg can be elided in general.
-        *
-        * However if @nr is a constant (above assumed it in a register),
-        * and greater than 31, gcc can optimize away (x << 33) to 0,
-        * as overflow, given the 32-bit ISA. Thus masking needs to be done
-        * for constant @nr, but no code is generated due to const prop.
-        */
-       if (__builtin_constant_p(nr))
-               nr &= 0x1f;
-
-       __asm__ __volatile__(
-       "1:     llock   %0, [%1]        \n"
-       "       bset    %0, %0, %2      \n"
-       "       scond   %0, [%1]        \n"
-       "       bnz     1b      \n"
-       : "=&r"(temp)
-       : "r"(m), "ir"(nr)
-       : "cc");
-}
-
-static inline void clear_bit(unsigned long nr, volatile unsigned long *m)
-{
-       unsigned int temp;
-
-       m += nr >> 5;
-
-       if (__builtin_constant_p(nr))
-               nr &= 0x1f;
-
-       __asm__ __volatile__(
-       "1:     llock   %0, [%1]        \n"
-       "       bclr    %0, %0, %2      \n"
-       "       scond   %0, [%1]        \n"
-       "       bnz     1b      \n"
-       : "=&r"(temp)
-       : "r"(m), "ir"(nr)
-       : "cc");
-}
-
-static inline void change_bit(unsigned long nr, volatile unsigned long *m)
-{
-       unsigned int temp;
-
-       m += nr >> 5;
-
-       if (__builtin_constant_p(nr))
-               nr &= 0x1f;
+/*
+ * Hardware assisted Atomic-R-M-W
+ */
 
-       __asm__ __volatile__(
-       "1:     llock   %0, [%1]        \n"
-       "       bxor    %0, %0, %2      \n"
-       "       scond   %0, [%1]        \n"
-       "       bnz     1b              \n"
-       : "=&r"(temp)
-       : "r"(m), "ir"(nr)
-       : "cc");
+#define BIT_OP(op, c_op, asm_op)                                       \
+static inline void op##_bit(unsigned long nr, volatile unsigned long *m)\
+{                                                                      \
+       unsigned int temp;                                              \
+                                                                       \
+       m += nr >> 5;                                                   \
+                                                                       \
+       /*                                                              \
+        * ARC ISA micro-optimization:                                  \
+        *                                                              \
+        * Instructions dealing with bitpos only consider lower 5 bits  \
+        * e.g (x << 33) is handled like (x << 1) by ASL instruction    \
+        *  (mem pointer still needs adjustment to point to next word)  \
+        *                                                              \
+        * Hence the masking to clamp @nr arg can be elided in general. \
+        *                                                              \
+        * However if @nr is a constant (above assumed in a register),  \
+        * and greater than 31, gcc can optimize away (x << 33) to 0,   \
+        * as overflow, given the 32-bit ISA. Thus masking needs to be  \
+        * done for const @nr, but no code is generated due to gcc      \
+        * const prop.                                                  \
+        */                                                             \
+       if (__builtin_constant_p(nr))                                   \
+               nr &= 0x1f;                                             \
+                                                                       \
+       __asm__ __volatile__(                                           \
+       "1:     llock       %0, [%1]            \n"                     \
+       "       " #asm_op " %0, %0, %2  \n"                             \
+       "       scond       %0, [%1]            \n"                     \
+       "       bnz         1b                  \n"                     \
+       : "=&r"(temp)   /* Early clobber, to prevent reg reuse */       \
+       : "r"(m),       /* Not "m": llock only supports reg direct addr mode */ \
+         "ir"(nr)                                                      \
+       : "cc");                                                        \
 }
 
 /*
@@ -108,75 +75,38 @@ static inline void change_bit(unsigned long nr, volatile unsigned long *m)
  * Since ARC lacks a equivalent h/w primitive, the bit is set unconditionally
  * and the old value of bit is returned
  */
-static inline int test_and_set_bit(unsigned long nr, volatile unsigned long *m)
-{
-       unsigned long old, temp;
-
-       m += nr >> 5;
-
-       if (__builtin_constant_p(nr))
-               nr &= 0x1f;
-
-       __asm__ __volatile__(
-       "1:     llock   %0, [%2]        \n"
-       "       bset    %1, %0, %3      \n"
-       "       scond   %1, [%2]        \n"
-       "       bnz     1b              \n"
-       : "=&r"(old), "=&r"(temp)
-       : "r"(m), "ir"(nr)
-       : "cc");
-
-       return (old & (1 << nr)) != 0;
-}
-
-static inline int
-test_and_clear_bit(unsigned long nr, volatile unsigned long *m)
-{
-       unsigned int old, temp;
-
-       m += nr >> 5;
-
-       if (__builtin_constant_p(nr))
-               nr &= 0x1f;
-
-       __asm__ __volatile__(
-       "1:     llock   %0, [%2]        \n"
-       "       bclr    %1, %0, %3      \n"
-       "       scond   %1, [%2]        \n"
-       "       bnz     1b              \n"
-       : "=&r"(old), "=&r"(temp)
-       : "r"(m), "ir"(nr)
-       : "cc");
-
-       return (old & (1 << nr)) != 0;
-}
-
-static inline int
-test_and_change_bit(unsigned long nr, volatile unsigned long *m)
-{
-       unsigned int old, temp;
-
-       m += nr >> 5;
-
-       if (__builtin_constant_p(nr))
-               nr &= 0x1f;
-
-       __asm__ __volatile__(
-       "1:     llock   %0, [%2]        \n"
-       "       bxor    %1, %0, %3      \n"
-       "       scond   %1, [%2]        \n"
-       "       bnz     1b              \n"
-       : "=&r"(old), "=&r"(temp)
-       : "r"(m), "ir"(nr)
-       : "cc");
-
-       return (old & (1 << nr)) != 0;
+#define TEST_N_BIT_OP(op, c_op, asm_op)                                        \
+static inline int test_and_##op##_bit(unsigned long nr, volatile unsigned long *m)\
+{                                                                      \
+       unsigned long old, temp;                                        \
+                                                                       \
+       m += nr >> 5;                                                   \
+                                                                       \
+       if (__builtin_constant_p(nr))                                   \
+               nr &= 0x1f;                                             \
+                                                                       \
+       /*                                                              \
+        * Explicit full memory barrier needed before/after as          \
+        * LLOCK/SCOND themselves don't provide any such smenatic       \
+        */                                                             \
+       smp_mb();                                                       \
+                                                                       \
+       __asm__ __volatile__(                                           \
+       "1:     llock       %0, [%2]    \n"                             \
+       "       " #asm_op " %1, %0, %3  \n"                             \
+       "       scond       %1, [%2]    \n"                             \
+       "       bnz         1b          \n"                             \
+       : "=&r"(old), "=&r"(temp)                                       \
+       : "r"(m), "ir"(nr)                                              \
+       : "cc");                                                        \
+                                                                       \
+       smp_mb();                                                       \
+                                                                       \
+       return (old & (1 << nr)) != 0;                                  \
 }
 
 #else  /* !CONFIG_ARC_HAS_LLSC */
 
-#include <asm/smp.h>
-
 /*
  * Non hardware assisted Atomic-R-M-W
  * Locking would change to irq-disabling only (UP) and spinlocks (SMP)
@@ -193,108 +123,43 @@ test_and_change_bit(unsigned long nr, volatile unsigned long *m)
  *             at compile time)
  */
 
-static inline void set_bit(unsigned long nr, volatile unsigned long *m)
-{
-       unsigned long temp, flags;
-       m += nr >> 5;
-
-       if (__builtin_constant_p(nr))
-               nr &= 0x1f;
-
-       bitops_lock(flags);
-
-       temp = *m;
-       *m = temp | (1UL << nr);
-
-       bitops_unlock(flags);
-}
-
-static inline void clear_bit(unsigned long nr, volatile unsigned long *m)
-{
-       unsigned long temp, flags;
-       m += nr >> 5;
-
-       if (__builtin_constant_p(nr))
-               nr &= 0x1f;
-
-       bitops_lock(flags);
-
-       temp = *m;
-       *m = temp & ~(1UL << nr);
-
-       bitops_unlock(flags);
-}
-
-static inline void change_bit(unsigned long nr, volatile unsigned long *m)
-{
-       unsigned long temp, flags;
-       m += nr >> 5;
-
-       if (__builtin_constant_p(nr))
-               nr &= 0x1f;
-
-       bitops_lock(flags);
-
-       temp = *m;
-       *m = temp ^ (1UL << nr);
-
-       bitops_unlock(flags);
-}
-
-static inline int test_and_set_bit(unsigned long nr, volatile unsigned long *m)
-{
-       unsigned long old, flags;
-       m += nr >> 5;
-
-       if (__builtin_constant_p(nr))
-               nr &= 0x1f;
-
-       bitops_lock(flags);
-
-       old = *m;
-       *m = old | (1 << nr);
-
-       bitops_unlock(flags);
-
-       return (old & (1 << nr)) != 0;
-}
-
-static inline int
-test_and_clear_bit(unsigned long nr, volatile unsigned long *m)
-{
-       unsigned long old, flags;
-       m += nr >> 5;
-
-       if (__builtin_constant_p(nr))
-               nr &= 0x1f;
-
-       bitops_lock(flags);
-
-       old = *m;
-       *m = old & ~(1 << nr);
-
-       bitops_unlock(flags);
-
-       return (old & (1 << nr)) != 0;
+#define BIT_OP(op, c_op, asm_op)                                       \
+static inline void op##_bit(unsigned long nr, volatile unsigned long *m)\
+{                                                                      \
+       unsigned long temp, flags;                                      \
+       m += nr >> 5;                                                   \
+                                                                       \
+       if (__builtin_constant_p(nr))                                   \
+               nr &= 0x1f;                                             \
+                                                                       \
+       /*                                                              \
+        * spin lock/unlock provide the needed smp_mb() before/after    \
+        */                                                             \
+       bitops_lock(flags);                                             \
+                                                                       \
+       temp = *m;                                                      \
+       *m = temp c_op (1UL << nr);                                     \
+                                                                       \
+       bitops_unlock(flags);                                           \
 }
 
-static inline int
-test_and_change_bit(unsigned long nr, volatile unsigned long *m)
-{
-       unsigned long old, flags;
-       m += nr >> 5;
-
-       if (__builtin_constant_p(nr))
-               nr &= 0x1f;
-
-       bitops_lock(flags);
-
-       old = *m;
-       *m = old ^ (1 << nr);
-
-       bitops_unlock(flags);
-
-       return (old & (1 << nr)) != 0;
+#define TEST_N_BIT_OP(op, c_op, asm_op)                                        \
+static inline int test_and_##op##_bit(unsigned long nr, volatile unsigned long *m)\
+{                                                                      \
+       unsigned long old, flags;                                       \
+       m += nr >> 5;                                                   \
+                                                                       \
+       if (__builtin_constant_p(nr))                                   \
+               nr &= 0x1f;                                             \
+                                                                       \
+       bitops_lock(flags);                                             \
+                                                                       \
+       old = *m;                                                       \
+       *m = old c_op (1 << nr);                                        \
+                                                                       \
+       bitops_unlock(flags);                                           \
+                                                                       \
+       return (old & (1 << nr)) != 0;                                  \
 }
 
 #endif /* CONFIG_ARC_HAS_LLSC */
@@ -303,86 +168,51 @@ test_and_change_bit(unsigned long nr, volatile unsigned long *m)
  * Non atomic variants
  **************************************/
 
-static inline void __set_bit(unsigned long nr, volatile unsigned long *m)
-{
-       unsigned long temp;
-       m += nr >> 5;
-
-       if (__builtin_constant_p(nr))
-               nr &= 0x1f;
-
-       temp = *m;
-       *m = temp | (1UL << nr);
-}
-
-static inline void __clear_bit(unsigned long nr, volatile unsigned long *m)
-{
-       unsigned long temp;
-       m += nr >> 5;
-
-       if (__builtin_constant_p(nr))
-               nr &= 0x1f;
-
-       temp = *m;
-       *m = temp & ~(1UL << nr);
-}
-
-static inline void __change_bit(unsigned long nr, volatile unsigned long *m)
-{
-       unsigned long temp;
-       m += nr >> 5;
-
-       if (__builtin_constant_p(nr))
-               nr &= 0x1f;
-
-       temp = *m;
-       *m = temp ^ (1UL << nr);
-}
-
-static inline int
-__test_and_set_bit(unsigned long nr, volatile unsigned long *m)
-{
-       unsigned long old;
-       m += nr >> 5;
-
-       if (__builtin_constant_p(nr))
-               nr &= 0x1f;
-
-       old = *m;
-       *m = old | (1 << nr);
-
-       return (old & (1 << nr)) != 0;
+#define __BIT_OP(op, c_op, asm_op)                                     \
+static inline void __##op##_bit(unsigned long nr, volatile unsigned long *m)   \
+{                                                                      \
+       unsigned long temp;                                             \
+       m += nr >> 5;                                                   \
+                                                                       \
+       if (__builtin_constant_p(nr))                                   \
+               nr &= 0x1f;                                             \
+                                                                       \
+       temp = *m;                                                      \
+       *m = temp c_op (1UL << nr);                                     \
 }
 
-static inline int
-__test_and_clear_bit(unsigned long nr, volatile unsigned long *m)
-{
-       unsigned long old;
-       m += nr >> 5;
-
-       if (__builtin_constant_p(nr))
-               nr &= 0x1f;
-
-       old = *m;
-       *m = old & ~(1 << nr);
-
-       return (old & (1 << nr)) != 0;
+#define __TEST_N_BIT_OP(op, c_op, asm_op)                              \
+static inline int __test_and_##op##_bit(unsigned long nr, volatile unsigned long *m)\
+{                                                                      \
+       unsigned long old;                                              \
+       m += nr >> 5;                                                   \
+                                                                       \
+       if (__builtin_constant_p(nr))                                   \
+               nr &= 0x1f;                                             \
+                                                                       \
+       old = *m;                                                       \
+       *m = old c_op (1 << nr);                                        \
+                                                                       \
+       return (old & (1 << nr)) != 0;                                  \
 }
 
-static inline int
-__test_and_change_bit(unsigned long nr, volatile unsigned long *m)
-{
-       unsigned long old;
-       m += nr >> 5;
-
-       if (__builtin_constant_p(nr))
-               nr &= 0x1f;
-
-       old = *m;
-       *m = old ^ (1 << nr);
-
-       return (old & (1 << nr)) != 0;
-}
+#define BIT_OPS(op, c_op, asm_op)                                      \
+                                                                       \
+       /* set_bit(), clear_bit(), change_bit() */                      \
+       BIT_OP(op, c_op, asm_op)                                        \
+                                                                       \
+       /* test_and_set_bit(), test_and_clear_bit(), test_and_change_bit() */\
+       TEST_N_BIT_OP(op, c_op, asm_op)                                 \
+                                                                       \
+       /* __set_bit(), __clear_bit(), __change_bit() */                \
+       __BIT_OP(op, c_op, asm_op)                                      \
+                                                                       \
+       /* __test_and_set_bit(), __test_and_clear_bit(), __test_and_change_bit() */\
+       __TEST_N_BIT_OP(op, c_op, asm_op)
+
+BIT_OPS(set, |, bset)
+BIT_OPS(clear, & ~, bclr)
+BIT_OPS(change, ^, bxor)
 
 /*
  * This routine doesn't need to be atomic.
@@ -402,6 +232,8 @@ test_bit(unsigned int nr, const volatile unsigned long *addr)
        return ((mask & *addr) != 0);
 }
 
+#ifdef CONFIG_ISA_ARCOMPACT
+
 /*
  * Count the number of zeros, starting from MSB
  * Helper for fls( ) friends
@@ -494,6 +326,75 @@ static inline __attribute__ ((const)) int __ffs(unsigned long word)
        return ffs(word) - 1;
 }
 
+#else  /* CONFIG_ISA_ARCV2 */
+
+/*
+ * fls = Find Last Set in word
+ * @result: [1-32]
+ * fls(1) = 1, fls(0x80000000) = 32, fls(0) = 0
+ */
+static inline __attribute__ ((const)) int fls(unsigned long x)
+{
+       int n;
+
+       asm volatile(
+       "       fls.f   %0, %1          \n"  /* 0:31; 0(Z) if src 0 */
+       "       add.nz  %0, %0, 1       \n"  /* 0:31 -> 1:32 */
+       : "=r"(n)       /* Early clobber not needed */
+       : "r"(x)
+       : "cc");
+
+       return n;
+}
+
+/*
+ * __fls: Similar to fls, but zero based (0-31). Also 0 if no bit set
+ */
+static inline __attribute__ ((const)) int __fls(unsigned long x)
+{
+       /* FLS insn has exactly same semantics as the API */
+       return  __builtin_arc_fls(x);
+}
+
+/*
+ * ffs = Find First Set in word (LSB to MSB)
+ * @result: [1-32], 0 if all 0's
+ */
+static inline __attribute__ ((const)) int ffs(unsigned long x)
+{
+       int n;
+
+       asm volatile(
+       "       ffs.f   %0, %1          \n"  /* 0:31; 31(Z) if src 0 */
+       "       add.nz  %0, %0, 1       \n"  /* 0:31 -> 1:32 */
+       "       mov.z   %0, 0           \n"  /* 31(Z)-> 0 */
+       : "=r"(n)       /* Early clobber not needed */
+       : "r"(x)
+       : "cc");
+
+       return n;
+}
+
+/*
+ * __ffs: Similar to ffs, but zero based (0-31)
+ */
+static inline __attribute__ ((const)) int __ffs(unsigned long x)
+{
+       int n;
+
+       asm volatile(
+       "       ffs.f   %0, %1          \n"  /* 0:31; 31(Z) if src 0 */
+       "       mov.z   %0, 0           \n"  /* 31(Z)-> 0 */
+       : "=r"(n)
+       : "r"(x)
+       : "cc");
+
+       return n;
+
+}
+
+#endif /* CONFIG_ISA_ARCOMPACT */
+
 /*
  * ffz = Find First Zero in word.
  * @return:[0-31], 32 if all 1's
index 7861255da32d64aa62e03d6fa881f84d9abf3b2f..d67345d3e2d444b1d357c004cbb1e33508d93060 100644 (file)
@@ -60,7 +60,7 @@ extern void read_decode_cache_bcr(void);
 #define ARC_REG_IC_IVIC                0x10
 #define ARC_REG_IC_CTRL                0x11
 #define ARC_REG_IC_IVIL                0x19
-#if defined(CONFIG_ARC_MMU_V3)
+#if defined(CONFIG_ARC_MMU_V3) || defined(CONFIG_ARC_MMU_V4)
 #define ARC_REG_IC_PTAG                0x1E
 #endif
 
@@ -74,12 +74,24 @@ extern void read_decode_cache_bcr(void);
 #define ARC_REG_DC_IVDL                0x4A
 #define ARC_REG_DC_FLSH                0x4B
 #define ARC_REG_DC_FLDL                0x4C
-#if defined(CONFIG_ARC_MMU_V3)
 #define ARC_REG_DC_PTAG                0x5C
-#endif
 
 /* Bit val in DC_CTRL */
 #define DC_CTRL_INV_MODE_FLUSH  0x40
 #define DC_CTRL_FLUSH_STATUS    0x100
 
+/*System-level cache (L2 cache) related Auxiliary registers */
+#define ARC_REG_SLC_CFG                0x901
+#define ARC_REG_SLC_CTRL       0x903
+#define ARC_REG_SLC_FLUSH      0x904
+#define ARC_REG_SLC_INVALIDATE 0x905
+#define ARC_REG_SLC_RGN_START  0x914
+#define ARC_REG_SLC_RGN_END    0x916
+
+/* Bit val in SLC_CONTROL */
+#define SLC_CTRL_IM            0x040
+#define SLC_CTRL_DISABLE       0x001
+#define SLC_CTRL_BUSY          0x100
+#define SLC_CTRL_RGN_OP_INV    0x200
+
 #endif /* _ASM_CACHE_H */
index 6abc4972bc93bbba015c3ebe92ea40926c7413a8..0992d3dbcc65f66e4e97925703ec9dc113a7b9a4 100644 (file)
@@ -34,9 +34,7 @@ void flush_cache_all(void);
 void flush_icache_range(unsigned long start, unsigned long end);
 void __sync_icache_dcache(unsigned long paddr, unsigned long vaddr, int len);
 void __inv_icache_page(unsigned long paddr, unsigned long vaddr);
-void ___flush_dcache_page(unsigned long paddr, unsigned long vaddr);
-#define __flush_dcache_page(p, v)      \
-               ___flush_dcache_page((unsigned long)p, (unsigned long)v)
+void __flush_dcache_page(unsigned long paddr, unsigned long vaddr);
 
 #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1
 
index 03cd6894855d614237851515d1cafb6d2a56908b..44fd531f4d7b93a9df7bff6dec976af5e571506c 100644 (file)
@@ -10,6 +10,8 @@
 #define __ASM_ARC_CMPXCHG_H
 
 #include <linux/types.h>
+
+#include <asm/barrier.h>
 #include <asm/smp.h>
 
 #ifdef CONFIG_ARC_HAS_LLSC
@@ -19,16 +21,25 @@ __cmpxchg(volatile void *ptr, unsigned long expected, unsigned long new)
 {
        unsigned long prev;
 
+       /*
+        * Explicit full memory barrier needed before/after as
+        * LLOCK/SCOND thmeselves don't provide any such semantics
+        */
+       smp_mb();
+
        __asm__ __volatile__(
        "1:     llock   %0, [%1]        \n"
        "       brne    %0, %2, 2f      \n"
        "       scond   %3, [%1]        \n"
        "       bnz     1b              \n"
        "2:                             \n"
-       : "=&r"(prev)
-       : "r"(ptr), "ir"(expected),
-         "r"(new) /* can't be "ir". scond can't take limm for "b" */
-       : "cc");
+       : "=&r"(prev)   /* Early clobber, to prevent reg reuse */
+       : "r"(ptr),     /* Not "m": llock only supports reg direct addr mode */
+         "ir"(expected),
+         "r"(new)      /* can't be "ir". scond can't take LIMM for "b" */
+       : "cc", "memory"); /* so that gcc knows memory is being written here */
+
+       smp_mb();
 
        return prev;
 }
@@ -42,6 +53,9 @@ __cmpxchg(volatile void *ptr, unsigned long expected, unsigned long new)
        int prev;
        volatile unsigned long *p = ptr;
 
+       /*
+        * spin lock/unlock provide the needed smp_mb() before/after
+        */
        atomic_ops_lock(flags);
        prev = *p;
        if (prev == expected)
@@ -77,12 +91,16 @@ static inline unsigned long __xchg(unsigned long val, volatile void *ptr,
 
        switch (size) {
        case 4:
+               smp_mb();
+
                __asm__ __volatile__(
                "       ex  %0, [%1]    \n"
                : "+r"(val)
                : "r"(ptr)
                : "memory");
 
+               smp_mb();
+
                return val;
        }
        return __xchg_bad_pointer();
index 43de302569815073bb4d4f23cb98b60a5e0c0552..08e7e2a16ac176a597ceb21c3b0f399b6ad98ea6 100644 (file)
 static inline void __delay(unsigned long loops)
 {
        __asm__ __volatile__(
-       "1:     sub.f %0, %0, 1 \n"
-       "       jpnz 1b         \n"
-       : "+r"(loops)
-       :
-       : "cc");
+       "       lp  1f  \n"
+       "       nop     \n"
+       "1:             \n"
+       : "+l"(loops));
 }
 
 extern void __bad_udelay(void);
index 45b8e0cea1764d2b9e4a0b0d1f27b787eb845870..fd6cdb56d4fd7e2956cee9a88fb6e6c7520c8c26 100644 (file)
 #include <asm-generic/dma-coherent.h>
 #include <asm/cacheflush.h>
 
-#ifndef CONFIG_ARC_PLAT_NEEDS_CPU_TO_DMA
-/*
- * dma_map_* API take cpu addresses, which is kernel logical address in the
- * untranslated address space (0x8000_0000) based. The dma address (bus addr)
- * ideally needs to be 0x0000_0000 based hence these glue routines.
- * However given that intermediate bus bridges can ignore the high bit, we can
- * do with these routines being no-ops.
- * If a platform/device comes up which sriclty requires 0 based bus addr
- * (e.g. AHB-PCI bridge on Angel4 board), then it can provide it's own versions
- */
-#define plat_dma_addr_to_kernel(dev, addr) ((unsigned long)(addr))
-#define plat_kernel_addr_to_dma(dev, ptr) ((dma_addr_t)(ptr))
-
-#else
-#include <plat/dma_addr.h>
-#endif
-
 void *dma_alloc_noncoherent(struct device *dev, size_t size,
                            dma_addr_t *dma_handle, gfp_t gfp);
 
@@ -94,7 +77,7 @@ dma_map_single(struct device *dev, void *cpu_addr, size_t size,
               enum dma_data_direction dir)
 {
        _dma_cache_sync((unsigned long)cpu_addr, size, dir);
-       return plat_kernel_addr_to_dma(dev, cpu_addr);
+       return (dma_addr_t)cpu_addr;
 }
 
 static inline void
@@ -147,16 +130,14 @@ static inline void
 dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle,
                        size_t size, enum dma_data_direction dir)
 {
-       _dma_cache_sync(plat_dma_addr_to_kernel(dev, dma_handle), size,
-                       DMA_FROM_DEVICE);
+       _dma_cache_sync(dma_handle, size, DMA_FROM_DEVICE);
 }
 
 static inline void
 dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle,
                           size_t size, enum dma_data_direction dir)
 {
-       _dma_cache_sync(plat_dma_addr_to_kernel(dev, dma_handle), size,
-                       DMA_TO_DEVICE);
+       _dma_cache_sync(dma_handle, size, DMA_TO_DEVICE);
 }
 
 static inline void
@@ -164,8 +145,7 @@ dma_sync_single_range_for_cpu(struct device *dev, dma_addr_t dma_handle,
                              unsigned long offset, size_t size,
                              enum dma_data_direction direction)
 {
-       _dma_cache_sync(plat_dma_addr_to_kernel(dev, dma_handle) + offset,
-                       size, DMA_FROM_DEVICE);
+       _dma_cache_sync(dma_handle + offset, size, DMA_FROM_DEVICE);
 }
 
 static inline void
@@ -173,8 +153,7 @@ dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle,
                                 unsigned long offset, size_t size,
                                 enum dma_data_direction direction)
 {
-       _dma_cache_sync(plat_dma_addr_to_kernel(dev, dma_handle) + offset,
-                       size, DMA_TO_DEVICE);
+       _dma_cache_sync(dma_handle + offset, size, DMA_TO_DEVICE);
 }
 
 static inline void
index a262828576839d9d48e5e2be18ae65b9fad815e5..51a99e25fe338251b23fe00bf2b1849b6a7252a2 100644 (file)
 /* These ELF defines belong to uapi but libc elf.h already defines them */
 #define EM_ARCOMPACT           93
 
+#define EM_ARCV2               195     /* ARCv2 Cores */
+
+#define EM_ARC_INUSE           (IS_ENABLED(CONFIG_ISA_ARCOMPACT) ? \
+                                       EM_ARCOMPACT : EM_ARCV2)
+
 /* ARC Relocations (kernel Modules only) */
 #define  R_ARC_32              0x4
 #define  R_ARC_32_ME           0x1B
diff --git a/arch/arc/include/asm/entry-arcv2.h b/arch/arc/include/asm/entry-arcv2.h
new file mode 100644 (file)
index 0000000..b5ff87e
--- /dev/null
@@ -0,0 +1,190 @@
+
+#ifndef __ASM_ARC_ENTRY_ARCV2_H
+#define __ASM_ARC_ENTRY_ARCV2_H
+
+#include <asm/asm-offsets.h>
+#include <asm/irqflags-arcv2.h>
+#include <asm/thread_info.h>   /* For THREAD_SIZE */
+
+/*------------------------------------------------------------------------*/
+.macro INTERRUPT_PROLOGUE      called_from
+
+       ; Before jumping to Interrupt Vector, hardware micro-ops did following:
+       ;   1. SP auto-switched to kernel mode stack
+       ;   2. STATUS32.Z flag set to U mode at time of interrupt (U:1, K:0)
+       ;   3. Auto saved: r0-r11, blink, LPE,LPS,LPC, JLI,LDI,EI, PC, STAT32
+       ;
+       ; Now manually save: r12, sp, fp, gp, r25
+
+       PUSH    r12
+
+       ; Saving pt_regs->sp correctly requires some extra work due to the way
+       ; Auto stack switch works
+       ;  - U mode: retrieve it from AUX_USER_SP
+       ;  - K mode: add the offset from current SP where H/w starts auto push
+       ;
+       ; Utilize the fact that Z bit is set if Intr taken in U mode
+       mov.nz  r9, sp
+       add.nz  r9, r9, SZ_PT_REGS - PT_sp - 4
+       bnz     1f
+
+       lr      r9, [AUX_USER_SP]
+1:
+       PUSH    r9      ; SP
+
+       PUSH    fp
+       PUSH    gp
+
+#ifdef CONFIG_ARC_CURR_IN_REG
+       PUSH    r25                     ; user_r25
+       GET_CURR_TASK_ON_CPU    r25
+#else
+       sub     sp, sp, 4
+#endif
+
+.ifnc \called_from, exception
+       sub     sp, sp, 12      ; BTA/ECR/orig_r0 placeholder per pt_regs
+.endif
+
+.endm
+
+/*------------------------------------------------------------------------*/
+.macro INTERRUPT_EPILOGUE      called_from
+
+.ifnc \called_from, exception
+       add     sp, sp, 12      ; skip BTA/ECR/orig_r0 placeholderss
+.endif
+
+#ifdef CONFIG_ARC_CURR_IN_REG
+       POP     r25
+#else
+       add     sp, sp, 4
+#endif
+
+       POP     gp
+       POP     fp
+
+       ; Don't touch AUX_USER_SP if returning to K mode (Z bit set)
+       ; (Z bit set on K mode is inverse of INTERRUPT_PROLOGUE)
+       add.z   sp, sp, 4
+       bz      1f
+
+       POPAX   AUX_USER_SP
+1:
+       POP     r12
+
+.endm
+
+/*------------------------------------------------------------------------*/
+.macro EXCEPTION_PROLOGUE
+
+       ; Before jumping to Exception Vector, hardware micro-ops did following:
+       ;   1. SP auto-switched to kernel mode stack
+       ;   2. STATUS32.Z flag set to U mode at time of interrupt (U:1,K:0)
+       ;
+       ; Now manually save the complete reg file
+
+       PUSH    r9              ; freeup a register: slot of erstatus
+
+       PUSHAX  eret
+       sub     sp, sp, 12      ; skip JLI, LDI, EI
+       PUSH    lp_count
+       PUSHAX  lp_start
+       PUSHAX  lp_end
+       PUSH    blink
+
+       PUSH    r11
+       PUSH    r10
+
+       ld.as   r9,  [sp, 10]   ; load stashed r9 (status32 stack slot)
+       lr      r10, [erstatus]
+       st.as   r10, [sp, 10]   ; save status32 at it's right stack slot
+
+       PUSH    r9
+       PUSH    r8
+       PUSH    r7
+       PUSH    r6
+       PUSH    r5
+       PUSH    r4
+       PUSH    r3
+       PUSH    r2
+       PUSH    r1
+       PUSH    r0
+
+       ; -- for interrupts, regs above are auto-saved by h/w in that order --
+       ; Now do what ISR prologue does (manually save r12, sp, fp, gp, r25)
+       ;
+       ; Set Z flag if this was from U mode (expected by INTERRUPT_PROLOGUE)
+       ; Although H/w exception micro-ops do set Z flag for U mode (just like
+       ; for interrupts), it could get clobbered in case we soft land here from
+       ; a TLB Miss exception handler (tlbex.S)
+
+       and     r10, r10, STATUS_U_MASK
+       xor.f   0, r10, STATUS_U_MASK
+
+       INTERRUPT_PROLOGUE  exception
+
+       PUSHAX  erbta
+       PUSHAX  ecr             ; r9 contains ECR, expected by EV_Trap
+
+       PUSH    r0              ; orig_r0
+.endm
+
+/*------------------------------------------------------------------------*/
+.macro EXCEPTION_EPILOGUE
+
+       ; Assumes r0 has PT_status32
+       btst   r0, STATUS_U_BIT ; Z flag set if K, used in INTERRUPT_EPILOGUE
+
+       add     sp, sp, 8       ; orig_r0/ECR don't need restoring
+       POPAX   erbta
+
+       INTERRUPT_EPILOGUE  exception
+
+       POP     r0
+       POP     r1
+       POP     r2
+       POP     r3
+       POP     r4
+       POP     r5
+       POP     r6
+       POP     r7
+       POP     r8
+       POP     r9
+       POP     r10
+       POP     r11
+
+       POP     blink
+       POPAX   lp_end
+       POPAX   lp_start
+
+       POP     r9
+       mov     lp_count, r9
+
+       add     sp, sp, 12      ; skip JLI, LDI, EI
+       POPAX   eret
+       POPAX   erstatus
+
+       ld.as   r9, [sp, -12]   ; reload r9 which got clobbered
+.endm
+
+.macro FAKE_RET_FROM_EXCPN
+       lr      r9, [status32]
+       bic     r9, r9, (STATUS_U_MASK|STATUS_DE_MASK|STATUS_AE_MASK)
+       or      r9, r9, (STATUS_L_MASK|STATUS_IE_MASK)
+       kflag   r9
+.endm
+
+/* Get thread_info of "current" tsk */
+.macro GET_CURR_THR_INFO_FROM_SP  reg
+       bmskn \reg, sp, THREAD_SHIFT - 1
+.endm
+
+/* Get CPU-ID of this core */
+.macro  GET_CPU_ID  reg
+       lr  \reg, [identity]
+       xbfu \reg, \reg, 0xE8   /* 00111    01000 */
+                               /* M = 8-1  N = 8 */
+.endm
+
+#endif
diff --git a/arch/arc/include/asm/entry-compact.h b/arch/arc/include/asm/entry-compact.h
new file mode 100644 (file)
index 0000000..415443c
--- /dev/null
@@ -0,0 +1,307 @@
+/*
+ * Copyright (C) 2014-15 Synopsys, Inc. (www.synopsys.com)
+ * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
+ *
+ * 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.
+ *
+ * Vineetg: March 2009 (Supporting 2 levels of Interrupts)
+ *  Stack switching code can no longer reliably rely on the fact that
+ *  if we are NOT in user mode, stack is switched to kernel mode.
+ *  e.g. L2 IRQ interrupted a L1 ISR which had not yet completed
+ *  it's prologue including stack switching from user mode
+ *
+ * Vineetg: Aug 28th 2008: Bug #94984
+ *  -Zero Overhead Loop Context shd be cleared when entering IRQ/EXcp/Trap
+ *   Normally CPU does this automatically, however when doing FAKE rtie,
+ *   we also need to explicitly do this. The problem in macros
+ *   FAKE_RET_FROM_EXCPN and FAKE_RET_FROM_EXCPN_LOCK_IRQ was that this bit
+ *   was being "CLEARED" rather then "SET". Actually "SET" clears ZOL context
+ *
+ * Vineetg: May 5th 2008
+ *  -Modified CALLEE_REG save/restore macros to handle the fact that
+ *      r25 contains the kernel current task ptr
+ *  - Defined Stack Switching Macro to be reused in all intr/excp hdlrs
+ *  - Shaved off 11 instructions from RESTORE_ALL_INT1 by using the
+ *      address Write back load ld.ab instead of seperate ld/add instn
+ *
+ * Amit Bhor, Sameer Dhavale: Codito Technologies 2004
+ */
+
+#ifndef __ASM_ARC_ENTRY_COMPACT_H
+#define __ASM_ARC_ENTRY_COMPACT_H
+
+#include <asm/asm-offsets.h>
+#include <asm/irqflags-compact.h>
+#include <asm/thread_info.h>   /* For THREAD_SIZE */
+
+/*--------------------------------------------------------------
+ * Switch to Kernel Mode stack if SP points to User Mode stack
+ *
+ * Entry   : r9 contains pre-IRQ/exception/trap status32
+ * Exit    : SP set to K mode stack
+ *           SP at the time of entry (K/U) saved @ pt_regs->sp
+ * Clobbers: r9
+ *-------------------------------------------------------------*/
+
+.macro SWITCH_TO_KERNEL_STK
+
+       /* User Mode when this happened ? Yes: Proceed to switch stack */
+       bbit1   r9, STATUS_U_BIT, 88f
+
+       /* OK we were already in kernel mode when this event happened, thus can
+        * assume SP is kernel mode SP. _NO_ need to do any stack switching
+        */
+
+#ifdef CONFIG_ARC_COMPACT_IRQ_LEVELS
+       /* However....
+        * If Level 2 Interrupts enabled, we may end up with a corner case:
+        * 1. User Task executing
+        * 2. L1 IRQ taken, ISR starts (CPU auto-switched to KERNEL mode)
+        * 3. But before it could switch SP from USER to KERNEL stack
+        *      a L2 IRQ "Interrupts" L1
+        * Thay way although L2 IRQ happened in Kernel mode, stack is still
+        * not switched.
+        * To handle this, we may need to switch stack even if in kernel mode
+        * provided SP has values in range of USER mode stack ( < 0x7000_0000 )
+        */
+       brlo sp, VMALLOC_START, 88f
+
+       /* TODO: vineetg:
+        * We need to be a bit more cautious here. What if a kernel bug in
+        * L1 ISR, caused SP to go whaco (some small value which looks like
+        * USER stk) and then we take L2 ISR.
+        * Above brlo alone would treat it as a valid L1-L2 sceanrio
+        * instead of shouting alound
+        * The only feasible way is to make sure this L2 happened in
+        * L1 prelogue ONLY i.e. ilink2 is less than a pre-set marker in
+        * L1 ISR before it switches stack
+        */
+
+#endif
+
+    /*------Intr/Ecxp happened in kernel mode, SP already setup ------ */
+       /* save it nevertheless @ pt_regs->sp for uniformity */
+
+       b.d     66f
+       st      sp, [sp, PT_sp - SZ_PT_REGS]
+
+88: /*------Intr/Ecxp happened in user mode, "switch" stack ------ */
+
+       GET_CURR_TASK_ON_CPU   r9
+
+       /* With current tsk in r9, get it's kernel mode stack base */
+       GET_TSK_STACK_BASE  r9, r9
+
+       /* save U mode SP @ pt_regs->sp */
+       st      sp, [r9, PT_sp - SZ_PT_REGS]
+
+       /* final SP switch */
+       mov     sp, r9
+66:
+.endm
+
+/*------------------------------------------------------------
+ * "FAKE" a rtie to return from CPU Exception context
+ * This is to re-enable Exceptions within exception
+ * Look at EV_ProtV to see how this is actually used
+ *-------------------------------------------------------------*/
+
+.macro FAKE_RET_FROM_EXCPN
+
+       ld  r9, [sp, PT_status32]
+       bic r9, r9, (STATUS_U_MASK|STATUS_DE_MASK)
+       bset  r9, r9, STATUS_L_BIT
+       sr  r9, [erstatus]
+       mov r9, 55f
+       sr  r9, [eret]
+
+       rtie
+55:
+.endm
+
+/*--------------------------------------------------------------
+ * For early Exception/ISR Prologue, a core reg is temporarily needed to
+ * code the rest of prolog (stack switching). This is done by stashing
+ * it to memory (non-SMP case) or SCRATCH0 Aux Reg (SMP).
+ *
+ * Before saving the full regfile - this reg is restored back, only
+ * to be saved again on kernel mode stack, as part of pt_regs.
+ *-------------------------------------------------------------*/
+.macro PROLOG_FREEUP_REG       reg, mem
+#ifdef CONFIG_SMP
+       sr  \reg, [ARC_REG_SCRATCH_DATA0]
+#else
+       st  \reg, [\mem]
+#endif
+.endm
+
+.macro PROLOG_RESTORE_REG      reg, mem
+#ifdef CONFIG_SMP
+       lr  \reg, [ARC_REG_SCRATCH_DATA0]
+#else
+       ld  \reg, [\mem]
+#endif
+.endm
+
+/*--------------------------------------------------------------
+ * Exception Entry prologue
+ * -Switches stack to K mode (if not already)
+ * -Saves the register file
+ *
+ * After this it is safe to call the "C" handlers
+ *-------------------------------------------------------------*/
+.macro EXCEPTION_PROLOGUE
+
+       /* Need at least 1 reg to code the early exception prologue */
+       PROLOG_FREEUP_REG r9, @ex_saved_reg1
+
+       /* U/K mode at time of exception (stack not switched if already K) */
+       lr  r9, [erstatus]
+
+       /* ARC700 doesn't provide auto-stack switching */
+       SWITCH_TO_KERNEL_STK
+
+#ifdef CONFIG_ARC_CURR_IN_REG
+       /* Treat r25 as scratch reg (save on stack) and load with "current" */
+       PUSH    r25
+       GET_CURR_TASK_ON_CPU   r25
+#else
+       sub     sp, sp, 4
+#endif
+
+       st.a    r0, [sp, -8]    /* orig_r0 needed for syscall (skip ECR slot) */
+       sub     sp, sp, 4       /* skip pt_regs->sp, already saved above */
+
+       /* Restore r9 used to code the early prologue */
+       PROLOG_RESTORE_REG  r9, @ex_saved_reg1
+
+       /* now we are ready to save the regfile */
+       SAVE_R0_TO_R12
+       PUSH    gp
+       PUSH    fp
+       PUSH    blink
+       PUSHAX  eret
+       PUSHAX  erstatus
+       PUSH    lp_count
+       PUSHAX  lp_end
+       PUSHAX  lp_start
+       PUSHAX  erbta
+
+       lr      r9, [ecr]
+       st      r9, [sp, PT_event]    /* EV_Trap expects r9 to have ECR */
+.endm
+
+/*--------------------------------------------------------------
+ * Restore all registers used by system call or Exceptions
+ * SP should always be pointing to the next free stack element
+ * when entering this macro.
+ *
+ * NOTE:
+ *
+ * It is recommended that lp_count/ilink1/ilink2 not be used as a dest reg
+ * for memory load operations. If used in that way interrupts are deffered
+ * by hardware and that is not good.
+ *-------------------------------------------------------------*/
+.macro EXCEPTION_EPILOGUE
+       POPAX   erbta
+       POPAX   lp_start
+       POPAX   lp_end
+
+       POP     r9
+       mov     lp_count, r9    ;LD to lp_count is not allowed
+
+       POPAX   erstatus
+       POPAX   eret
+       POP     blink
+       POP     fp
+       POP     gp
+       RESTORE_R12_TO_R0
+
+       ld  sp, [sp] /* restore original sp */
+       /* orig_r0, ECR, user_r25 skipped automatically */
+.endm
+
+/* Dummy ECR values for Interrupts */
+#define event_IRQ1             0x0031abcd
+#define event_IRQ2             0x0032abcd
+
+.macro INTERRUPT_PROLOGUE  LVL
+
+       /* free up r9 as scratchpad */
+       PROLOG_FREEUP_REG r9, @int\LVL\()_saved_reg
+
+       /* Which mode (user/kernel) was the system in when intr occured */
+       lr  r9, [status32_l\LVL\()]
+
+       SWITCH_TO_KERNEL_STK
+
+#ifdef CONFIG_ARC_CURR_IN_REG
+       /* Treat r25 as scratch reg (save on stack) and load with "current" */
+       PUSH    r25
+       GET_CURR_TASK_ON_CPU   r25
+#else
+       sub     sp, sp, 4
+#endif
+
+       PUSH    0x003\LVL\()abcd    /* Dummy ECR */
+       sub     sp, sp, 8           /* skip orig_r0 (not needed)
+                                      skip pt_regs->sp, already saved above */
+
+       /* Restore r9 used to code the early prologue */
+       PROLOG_RESTORE_REG  r9, @int\LVL\()_saved_reg
+
+       SAVE_R0_TO_R12
+       PUSH    gp
+       PUSH    fp
+       PUSH    blink
+       PUSH    ilink\LVL\()
+       PUSHAX  status32_l\LVL\()
+       PUSH    lp_count
+       PUSHAX  lp_end
+       PUSHAX  lp_start
+       PUSHAX  bta_l\LVL\()
+.endm
+
+/*--------------------------------------------------------------
+ * Restore all registers used by interrupt handlers.
+ *
+ * NOTE:
+ *
+ * It is recommended that lp_count/ilink1/ilink2 not be used as a dest reg
+ * for memory load operations. If used in that way interrupts are deffered
+ * by hardware and that is not good.
+ *-------------------------------------------------------------*/
+.macro INTERRUPT_EPILOGUE  LVL
+       POPAX   bta_l\LVL\()
+       POPAX   lp_start
+       POPAX   lp_end
+
+       POP     r9
+       mov     lp_count, r9    ;LD to lp_count is not allowed
+
+       POPAX   status32_l\LVL\()
+       POP     ilink\LVL\()
+       POP     blink
+       POP     fp
+       POP     gp
+       RESTORE_R12_TO_R0
+
+       ld  sp, [sp] /* restore original sp */
+       /* orig_r0, ECR, user_r25 skipped automatically */
+.endm
+
+/* Get thread_info of "current" tsk */
+.macro GET_CURR_THR_INFO_FROM_SP  reg
+       bic \reg, sp, (THREAD_SIZE - 1)
+.endm
+
+/* Get CPU-ID of this core */
+.macro  GET_CPU_ID  reg
+       lr  \reg, [identity]
+       lsr \reg, \reg, 8
+       bmsk \reg, \reg, 7
+.endm
+
+#endif  /* __ASM_ARC_ENTRY_COMPACT_H */
index 884081099f800fd6b4ba133bc1f1746084845c49..ad7860c5ce153c731264f770067e653b70568fd5 100644 (file)
@@ -1,45 +1,27 @@
 /*
+ * Copyright (C) 2014-15 Synopsys, Inc. (www.synopsys.com)
  * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
  *
  * 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.
- *
- * Vineetg: March 2009 (Supporting 2 levels of Interrupts)
- *  Stack switching code can no longer reliably rely on the fact that
- *  if we are NOT in user mode, stack is switched to kernel mode.
- *  e.g. L2 IRQ interrupted a L1 ISR which had not yet completed
- *  it's prologue including stack switching from user mode
- *
- * Vineetg: Aug 28th 2008: Bug #94984
- *  -Zero Overhead Loop Context shd be cleared when entering IRQ/EXcp/Trap
- *   Normally CPU does this automatically, however when doing FAKE rtie,
- *   we also need to explicitly do this. The problem in macros
- *   FAKE_RET_FROM_EXCPN and FAKE_RET_FROM_EXCPN_LOCK_IRQ was that this bit
- *   was being "CLEARED" rather then "SET". Actually "SET" clears ZOL context
- *
- * Vineetg: May 5th 2008
- *  -Modified CALLEE_REG save/restore macros to handle the fact that
- *      r25 contains the kernel current task ptr
- *  - Defined Stack Switching Macro to be reused in all intr/excp hdlrs
- *  - Shaved off 11 instructions from RESTORE_ALL_INT1 by using the
- *      address Write back load ld.ab instead of seperate ld/add instn
- *
- * Amit Bhor, Sameer Dhavale: Codito Technologies 2004
  */
 
 #ifndef __ASM_ARC_ENTRY_H
 #define __ASM_ARC_ENTRY_H
 
-#ifdef __ASSEMBLY__
 #include <asm/unistd.h>                /* For NR_syscalls defination */
-#include <asm/asm-offsets.h>
 #include <asm/arcregs.h>
 #include <asm/ptrace.h>
 #include <asm/processor.h>     /* For VMALLOC_START */
-#include <asm/thread_info.h>   /* For THREAD_SIZE */
 #include <asm/mmu.h>
 
+#ifdef CONFIG_ISA_ARCOMPACT
+#include <asm/entry-compact.h> /* ISA specific bits */
+#else
+#include <asm/entry-arcv2.h>
+#endif
+
 /* Note on the LD/ST addr modes with addr reg wback
  *
  * LD.a same as LD.aw
        POP     r13
 .endm
 
-#define OFF_USER_R25_FROM_R24  (SZ_CALLEE_REGS + SZ_PT_REGS - 8)/4
-
 /*--------------------------------------------------------------
  * Collect User Mode callee regs as struct callee_regs - needed by
  * fork/do_signal/unaligned-access-emulation.
  *-------------------------------------------------------------*/
 .macro SAVE_CALLEE_SAVED_USER
 
+       mov     r12, sp         ; save SP as ref to pt_regs
        SAVE_R13_TO_R24
 
 #ifdef CONFIG_ARC_CURR_IN_REG
-       ; Retrieve orig r25 and save it on stack
-       ld.as   r12, [sp, OFF_USER_R25_FROM_R24]
-       st.a    r12, [sp, -4]
+       ; Retrieve orig r25 and save it with rest of callee_regs
+       ld.as   r12, [r12, PT_user_r25]
+       PUSH    r12
 #else
        PUSH    r25
 #endif
 .macro RESTORE_CALLEE_SAVED_USER
 
 #ifdef CONFIG_ARC_CURR_IN_REG
-       ld.ab   r12, [sp, 4]
-       st.as   r12, [sp, OFF_USER_R25_FROM_R24]
+       POP     r12
 #else
        POP     r25
 #endif
        RESTORE_R24_TO_R13
+
+       ; SP is back to start of pt_regs
+#ifdef CONFIG_ARC_CURR_IN_REG
+       st.as   r12, [sp, PT_user_r25]
+#endif
 .endm
 
 /*--------------------------------------------------------------
 
 .endm
 
-/*--------------------------------------------------------------
- * Switch to Kernel Mode stack if SP points to User Mode stack
- *
- * Entry   : r9 contains pre-IRQ/exception/trap status32
- * Exit    : SP is set to kernel mode stack pointer
- *           If CURR_IN_REG, r25 set to "current" task pointer
- * Clobbers: r9
- *-------------------------------------------------------------*/
-
-.macro SWITCH_TO_KERNEL_STK
-
-       /* User Mode when this happened ? Yes: Proceed to switch stack */
-       bbit1   r9, STATUS_U_BIT, 88f
-
-       /* OK we were already in kernel mode when this event happened, thus can
-        * assume SP is kernel mode SP. _NO_ need to do any stack switching
-        */
-
-#ifdef CONFIG_ARC_COMPACT_IRQ_LEVELS
-       /* However....
-        * If Level 2 Interrupts enabled, we may end up with a corner case:
-        * 1. User Task executing
-        * 2. L1 IRQ taken, ISR starts (CPU auto-switched to KERNEL mode)
-        * 3. But before it could switch SP from USER to KERNEL stack
-        *      a L2 IRQ "Interrupts" L1
-        * Thay way although L2 IRQ happened in Kernel mode, stack is still
-        * not switched.
-        * To handle this, we may need to switch stack even if in kernel mode
-        * provided SP has values in range of USER mode stack ( < 0x7000_0000 )
-        */
-       brlo sp, VMALLOC_START, 88f
-
-       /* TODO: vineetg:
-        * We need to be a bit more cautious here. What if a kernel bug in
-        * L1 ISR, caused SP to go whaco (some small value which looks like
-        * USER stk) and then we take L2 ISR.
-        * Above brlo alone would treat it as a valid L1-L2 sceanrio
-        * instead of shouting alound
-        * The only feasible way is to make sure this L2 happened in
-        * L1 prelogue ONLY i.e. ilink2 is less than a pre-set marker in
-        * L1 ISR before it switches stack
-        */
-
-#endif
-
-       /* Save Pre Intr/Exception KERNEL MODE SP on kernel stack
-        * safe-keeping not really needed, but it keeps the epilogue code
-        * (SP restore) simpler/uniform.
-        */
-       b.d     66f
-       mov     r9, sp
-
-88: /*------Intr/Ecxp happened in user mode, "switch" stack ------ */
-
-       GET_CURR_TASK_ON_CPU   r9
-
-       /* With current tsk in r9, get it's kernel mode stack base */
-       GET_TSK_STACK_BASE  r9, r9
-
-66:
-#ifdef CONFIG_ARC_CURR_IN_REG
-       /*
-        * Treat r25 as scratch reg, save it on stack first
-        * Load it with current task pointer
-        */
-       st      r25, [r9, -4]
-       GET_CURR_TASK_ON_CPU   r25
-#endif
-
-       /* Save Pre Intr/Exception User SP on kernel stack */
-       st.a    sp, [r9, -16]   ; Make room for orig_r0, ECR, user_r25
-
-       /* CAUTION:
-        * SP should be set at the very end when we are done with everything
-        * In case of 2 levels of interrupt we depend on value of SP to assume
-        * that everything else is done (loading r25 etc)
-        */
-
-       /* set SP to point to kernel mode stack */
-       mov sp, r9
-
-       /* ----- Stack Switched to kernel Mode, Now save REG FILE ----- */
-
-.endm
-
-/*------------------------------------------------------------
- * "FAKE" a rtie to return from CPU Exception context
- * This is to re-enable Exceptions within exception
- * Look at EV_ProtV to see how this is actually used
- *-------------------------------------------------------------*/
-
-.macro FAKE_RET_FROM_EXCPN  reg
-
-       ld  \reg, [sp, PT_status32]
-       bic  \reg, \reg, (STATUS_U_MASK|STATUS_DE_MASK)
-       bset \reg, \reg, STATUS_L_BIT
-       sr  \reg, [erstatus]
-       mov \reg, 55f
-       sr  \reg, [eret]
-
-       rtie
-55:
-.endm
-
-/*
- * @reg [OUT] &thread_info of "current"
- */
-.macro GET_CURR_THR_INFO_FROM_SP  reg
-       bic \reg, sp, (THREAD_SIZE - 1)
-.endm
-
 /*
  * @reg [OUT] thread_info->flags of "current"
  */
        ld  \reg, [\reg, THREAD_INFO_FLAGS]
 .endm
 
-/*--------------------------------------------------------------
- * For early Exception Prologue, a core reg is temporarily needed to
- * code the rest of prolog (stack switching). This is done by stashing
- * it to memory (non-SMP case) or SCRATCH0 Aux Reg (SMP).
- *
- * Before saving the full regfile - this reg is restored back, only
- * to be saved again on kernel mode stack, as part of pt_regs.
- *-------------------------------------------------------------*/
-.macro EXCPN_PROLOG_FREEUP_REG reg
-#ifdef CONFIG_SMP
-       sr  \reg, [ARC_REG_SCRATCH_DATA0]
-#else
-       st  \reg, [@ex_saved_reg1]
-#endif
-.endm
-
-.macro EXCPN_PROLOG_RESTORE_REG        reg
-#ifdef CONFIG_SMP
-       lr  \reg, [ARC_REG_SCRATCH_DATA0]
-#else
-       ld  \reg, [@ex_saved_reg1]
-#endif
-.endm
-
-/*--------------------------------------------------------------
- * Exception Entry prologue
- * -Switches stack to K mode (if not already)
- * -Saves the register file
- *
- * After this it is safe to call the "C" handlers
- *-------------------------------------------------------------*/
-.macro EXCEPTION_PROLOGUE
-
-       /* Need at least 1 reg to code the early exception prologue */
-       EXCPN_PROLOG_FREEUP_REG r9
-
-       /* U/K mode at time of exception (stack not switched if already K) */
-       lr  r9, [erstatus]
-
-       /* ARC700 doesn't provide auto-stack switching */
-       SWITCH_TO_KERNEL_STK
-
-       /* save the regfile */
-       SAVE_ALL_SYS
-.endm
-
-/*--------------------------------------------------------------
- * Save all registers used by Exceptions (TLB Miss, Prot-V, Mem err etc)
- * Requires SP to be already switched to kernel mode Stack
- * sp points to the next free element on the stack at exit of this macro.
- * Registers are pushed / popped in the order defined in struct ptregs
- * in asm/ptrace.h
- * Note that syscalls are implemented via TRAP which is also a exception
- * from CPU's point of view
- *-------------------------------------------------------------*/
-.macro SAVE_ALL_SYS
-
-       lr      r9, [ecr]
-       st      r9, [sp, 8]    /* ECR */
-       st      r0, [sp, 4]    /* orig_r0, needed only for sys calls */
-
-       /* Restore r9 used to code the early prologue */
-       EXCPN_PROLOG_RESTORE_REG  r9
-
-       SAVE_R0_TO_R12
-       PUSH    gp
-       PUSH    fp
-       PUSH    blink
-       PUSHAX  eret
-       PUSHAX  erstatus
-       PUSH    lp_count
-       PUSHAX  lp_end
-       PUSHAX  lp_start
-       PUSHAX  erbta
-.endm
-
-/*--------------------------------------------------------------
- * Restore all registers used by system call or Exceptions
- * SP should always be pointing to the next free stack element
- * when entering this macro.
- *
- * NOTE:
- *
- * It is recommended that lp_count/ilink1/ilink2 not be used as a dest reg
- * for memory load operations. If used in that way interrupts are deffered
- * by hardware and that is not good.
- *-------------------------------------------------------------*/
-.macro RESTORE_ALL_SYS
-       POPAX   erbta
-       POPAX   lp_start
-       POPAX   lp_end
-
-       POP     r9
-       mov     lp_count, r9    ;LD to lp_count is not allowed
-
-       POPAX   erstatus
-       POPAX   eret
-       POP     blink
-       POP     fp
-       POP     gp
-       RESTORE_R12_TO_R0
-
-       ld  sp, [sp] /* restore original sp */
-       /* orig_r0, ECR, user_r25 skipped automatically */
-.endm
-
-
-/*--------------------------------------------------------------
- * Save all registers used by interrupt handlers.
- *-------------------------------------------------------------*/
-.macro SAVE_ALL_INT1
-
-       /* restore original r9 to be saved as part of reg-file */
-#ifdef CONFIG_SMP
-       lr  r9, [ARC_REG_SCRATCH_DATA0]
-#else
-       ld  r9, [@int1_saved_reg]
-#endif
-
-       /* now we are ready to save the remaining context :) */
-       st      event_IRQ1, [sp, 8]    /* Dummy ECR */
-       st      0, [sp, 4]    /* orig_r0 , N/A for IRQ */
-
-       SAVE_R0_TO_R12
-       PUSH    gp
-       PUSH    fp
-       PUSH    blink
-       PUSH    ilink1
-       PUSHAX  status32_l1
-       PUSH    lp_count
-       PUSHAX  lp_end
-       PUSHAX  lp_start
-       PUSHAX  bta_l1
-.endm
-
-.macro SAVE_ALL_INT2
-
-       /* TODO-vineetg: SMP we can't use global nor can we use
-       *   SCRATCH0 as we do for int1 because while int1 is using
-       *   it, int2 can come
-       */
-       /* retsore original r9 , saved in sys_saved_r9 */
-       ld  r9, [@int2_saved_reg]
-
-       /* now we are ready to save the remaining context :) */
-       st      event_IRQ2, [sp, 8]    /* Dummy ECR */
-       st      0, [sp, 4]    /* orig_r0 , N/A for IRQ */
-
-       SAVE_R0_TO_R12
-       PUSH    gp
-       PUSH    fp
-       PUSH    blink
-       PUSH    ilink2
-       PUSHAX  status32_l2
-       PUSH    lp_count
-       PUSHAX  lp_end
-       PUSHAX  lp_start
-       PUSHAX  bta_l2
-.endm
-
-/*--------------------------------------------------------------
- * Restore all registers used by interrupt handlers.
- *
- * NOTE:
- *
- * It is recommended that lp_count/ilink1/ilink2 not be used as a dest reg
- * for memory load operations. If used in that way interrupts are deffered
- * by hardware and that is not good.
- *-------------------------------------------------------------*/
-
-.macro RESTORE_ALL_INT1
-       POPAX   bta_l1
-       POPAX   lp_start
-       POPAX   lp_end
-
-       POP     r9
-       mov     lp_count, r9    ;LD to lp_count is not allowed
-
-       POPAX   status32_l1
-       POP     ilink1
-       POP     blink
-       POP     fp
-       POP     gp
-       RESTORE_R12_TO_R0
-
-       ld  sp, [sp] /* restore original sp */
-       /* orig_r0, ECR, user_r25 skipped automatically */
-.endm
-
-.macro RESTORE_ALL_INT2
-       POPAX   bta_l2
-       POPAX   lp_start
-       POPAX   lp_end
-
-       POP     r9
-       mov     lp_count, r9    ;LD to lp_count is not allowed
-
-       POPAX   status32_l2
-       POP     ilink2
-       POP     blink
-       POP     fp
-       POP     gp
-       RESTORE_R12_TO_R0
-
-       ld  sp, [sp] /* restore original sp */
-       /* orig_r0, ECR, user_r25 skipped automatically */
-.endm
-
-
-/* Get CPU-ID of this core */
-.macro  GET_CPU_ID  reg
-       lr  \reg, [identity]
-       lsr \reg, \reg, 8
-       bmsk \reg, \reg, 7
-.endm
-
 #ifdef CONFIG_SMP
 
 /*-------------------------------------------------
 
 #endif /* CONFIG_ARC_CURR_IN_REG */
 
-#endif  /* __ASSEMBLY__ */
-
 #endif  /* __ASM_ARC_ENTRY_H */
index 7cc4ced5dbf4e4894c6b7d594a9810df74ab26d0..694ece8a024372bef7fd24b3ccb1e9dc323b4afe 100644 (file)
@@ -99,9 +99,45 @@ static inline void __raw_writel(u32 w, volatile void __iomem *addr)
 
 }
 
-#define readb_relaxed readb
-#define readw_relaxed readw
-#define readl_relaxed readl
+#ifdef CONFIG_ISA_ARCV2
+#include <asm/barrier.h>
+#define __iormb()              rmb()
+#define __iowmb()              wmb()
+#else
+#define __iormb()              do { } while (0)
+#define __iowmb()              do { } while (0)
+#endif
+
+/*
+ * MMIO can also get buffered/optimized in micro-arch, so barriers needed
+ * Based on ARM model for the typical use case
+ *
+ *     <ST [DMA buffer]>
+ *     <writel MMIO "go" reg>
+ *  or:
+ *     <readl MMIO "status" reg>
+ *     <LD [DMA buffer]>
+ *
+ * http://lkml.kernel.org/r/20150622133656.GG1583@arm.com
+ */
+#define readb(c)               ({ u8  __v = readb_relaxed(c); __iormb(); __v; })
+#define readw(c)               ({ u16 __v = readw_relaxed(c); __iormb(); __v; })
+#define readl(c)               ({ u32 __v = readl_relaxed(c); __iormb(); __v; })
+
+#define writeb(v,c)            ({ __iowmb(); writeb_relaxed(v,c); })
+#define writew(v,c)            ({ __iowmb(); writew_relaxed(v,c); })
+#define writel(v,c)            ({ __iowmb(); writel_relaxed(v,c); })
+
+/*
+ * Relaxed API for drivers which can handle any ordering themselves
+ */
+#define readb_relaxed(c)       __raw_readb(c)
+#define readw_relaxed(c)       __raw_readw(c)
+#define readl_relaxed(c)       __raw_readl(c)
+
+#define writeb_relaxed(v,c)    __raw_writeb(v,c)
+#define writew_relaxed(v,c)    __raw_writew(v,c)
+#define writel_relaxed(v,c)    __raw_writel(v,c)
 
 #include <asm-generic/io.h>
 
index f38652fb2ed772566b0a47cf51a01183a329004c..bc51036373261c6068292830adae89a80b5d0c9c 100644 (file)
 #define NR_IRQS                128 /* allow some CPU external IRQ handling */
 
 /* Platform Independent IRQs */
+#ifdef CONFIG_ISA_ARCOMPACT
 #define TIMER0_IRQ      3
 #define TIMER1_IRQ      4
+#else
+#define TIMER0_IRQ      16
+#define TIMER1_IRQ      17
+#define IPI_IRQ         19
+#endif
 
 #include <linux/interrupt.h>
 #include <asm-generic/irq.h>
diff --git a/arch/arc/include/asm/irqflags-arcv2.h b/arch/arc/include/asm/irqflags-arcv2.h
new file mode 100644 (file)
index 0000000..ad481c2
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2014-15 Synopsys, Inc. (www.synopsys.com)
+ *
+ * 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_IRQFLAGS_ARCV2_H
+#define __ASM_IRQFLAGS_ARCV2_H
+
+#include <asm/arcregs.h>
+
+/* status32 Bits */
+#define STATUS_AD_BIT  19   /* Disable Align chk: core supports non-aligned */
+#define STATUS_IE_BIT  31
+
+#define STATUS_AD_MASK         (1<<STATUS_AD_BIT)
+#define STATUS_IE_MASK         (1<<STATUS_IE_BIT)
+
+#define AUX_USER_SP            0x00D
+#define AUX_IRQ_CTRL           0x00E
+#define AUX_IRQ_ACT            0x043   /* Active Intr across all levels */
+#define AUX_IRQ_LVL_PEND       0x200   /* Pending Intr across all levels */
+#define AUX_IRQ_PRIORITY       0x206
+#define ICAUSE                 0x40a
+#define AUX_IRQ_SELECT         0x40b
+#define AUX_IRQ_ENABLE         0x40c
+
+/* Was Intr taken in User Mode */
+#define AUX_IRQ_ACT_BIT_U      31
+
+/* 0 is highest level, but taken by FIRQs, if present in design */
+#define ARCV2_IRQ_DEF_PRIO             0
+
+/* seed value for status register */
+#define ISA_INIT_STATUS_BITS   (STATUS_IE_MASK | STATUS_AD_MASK | \
+                                       (ARCV2_IRQ_DEF_PRIO << 1))
+
+#ifndef __ASSEMBLY__
+
+/*
+ * Save IRQ state and disable IRQs
+ */
+static inline long arch_local_irq_save(void)
+{
+       unsigned long flags;
+
+       __asm__ __volatile__("  clri %0 \n" : "=r" (flags) : : "memory");
+
+       return flags;
+}
+
+/*
+ * restore saved IRQ state
+ */
+static inline void arch_local_irq_restore(unsigned long flags)
+{
+       __asm__ __volatile__("  seti %0 \n" : : "r" (flags) : "memory");
+}
+
+/*
+ * Unconditionally Enable IRQs
+ */
+static inline void arch_local_irq_enable(void)
+{
+       unsigned int irqact = read_aux_reg(AUX_IRQ_ACT);
+
+       if (irqact & 0xffff)
+               write_aux_reg(AUX_IRQ_ACT, irqact & ~0xffff);
+
+       __asm__ __volatile__("  seti    \n" : : : "memory");
+}
+
+/*
+ * Unconditionally Disable IRQs
+ */
+static inline void arch_local_irq_disable(void)
+{
+       __asm__ __volatile__("  clri    \n" : : : "memory");
+}
+
+/*
+ * save IRQ state
+ */
+static inline long arch_local_save_flags(void)
+{
+       unsigned long temp;
+
+       __asm__ __volatile__(
+       "       lr  %0, [status32]      \n"
+       : "=&r"(temp)
+       :
+       : "memory");
+
+       return temp;
+}
+
+/*
+ * Query IRQ state
+ */
+static inline int arch_irqs_disabled_flags(unsigned long flags)
+{
+       return !(flags & (STATUS_IE_MASK));
+}
+
+static inline int arch_irqs_disabled(void)
+{
+       return arch_irqs_disabled_flags(arch_local_save_flags());
+}
+
+#else
+
+.macro IRQ_DISABLE  scratch
+       clri
+.endm
+
+.macro IRQ_ENABLE  scratch
+       seti
+.endm
+
+#endif /* __ASSEMBLY__ */
+
+#endif
diff --git a/arch/arc/include/asm/irqflags-compact.h b/arch/arc/include/asm/irqflags-compact.h
new file mode 100644 (file)
index 0000000..aa80557
--- /dev/null
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2014-15 Synopsys, Inc. (www.synopsys.com)
+ * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
+ *
+ * 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_IRQFLAGS_ARCOMPACT_H
+#define __ASM_IRQFLAGS_ARCOMPACT_H
+
+/* vineetg: March 2010 : local_irq_save( ) optimisation
+ *  -Remove explicit mov of current status32 into reg, that is not needed
+ *  -Use BIC  insn instead of INVERTED + AND
+ *  -Conditionally disable interrupts (if they are not enabled, don't disable)
+*/
+
+#include <asm/arcregs.h>
+
+/* status32 Reg bits related to Interrupt Handling */
+#define STATUS_E1_BIT          1       /* Int 1 enable */
+#define STATUS_E2_BIT          2       /* Int 2 enable */
+#define STATUS_A1_BIT          3       /* Int 1 active */
+#define STATUS_A2_BIT          4       /* Int 2 active */
+
+#define STATUS_E1_MASK         (1<<STATUS_E1_BIT)
+#define STATUS_E2_MASK         (1<<STATUS_E2_BIT)
+#define STATUS_A1_MASK         (1<<STATUS_A1_BIT)
+#define STATUS_A2_MASK         (1<<STATUS_A2_BIT)
+#define STATUS_IE_MASK         (STATUS_E1_MASK | STATUS_E2_MASK)
+
+/* Other Interrupt Handling related Aux regs */
+#define AUX_IRQ_LEV            0x200   /* IRQ Priority: L1 or L2 */
+#define AUX_IRQ_HINT           0x201   /* For generating Soft Interrupts */
+#define AUX_IRQ_LV12           0x43    /* interrupt level register */
+
+#define AUX_IENABLE            0x40c
+#define AUX_ITRIGGER           0x40d
+#define AUX_IPULSE             0x415
+
+#define ISA_INIT_STATUS_BITS   STATUS_IE_MASK
+
+#ifndef __ASSEMBLY__
+
+/******************************************************************
+ * IRQ Control Macros
+ *
+ * All of them have "memory" clobber (compiler barrier) which is needed to
+ * ensure that LD/ST requiring irq safetly (R-M-W when LLSC is not available)
+ * are redone after IRQs are re-enabled (and gcc doesn't reuse stale register)
+ *
+ * Noted at the time of Abilis Timer List corruption
+ *     Orig Bug + Rejected solution    : https://lkml.org/lkml/2013/3/29/67
+ *     Reasoning                       : https://lkml.org/lkml/2013/4/8/15
+ *
+ ******************************************************************/
+
+/*
+ * Save IRQ state and disable IRQs
+ */
+static inline long arch_local_irq_save(void)
+{
+       unsigned long temp, flags;
+
+       __asm__ __volatile__(
+       "       lr  %1, [status32]      \n"
+       "       bic %0, %1, %2          \n"
+       "       and.f 0, %1, %2 \n"
+       "       flag.nz %0              \n"
+       : "=r"(temp), "=r"(flags)
+       : "n"((STATUS_E1_MASK | STATUS_E2_MASK))
+       : "memory", "cc");
+
+       return flags;
+}
+
+/*
+ * restore saved IRQ state
+ */
+static inline void arch_local_irq_restore(unsigned long flags)
+{
+
+       __asm__ __volatile__(
+       "       flag %0                 \n"
+       :
+       : "r"(flags)
+       : "memory");
+}
+
+/*
+ * Unconditionally Enable IRQs
+ */
+extern void arch_local_irq_enable(void);
+
+/*
+ * Unconditionally Disable IRQs
+ */
+static inline void arch_local_irq_disable(void)
+{
+       unsigned long temp;
+
+       __asm__ __volatile__(
+       "       lr  %0, [status32]      \n"
+       "       and %0, %0, %1          \n"
+       "       flag %0                 \n"
+       : "=&r"(temp)
+       : "n"(~(STATUS_E1_MASK | STATUS_E2_MASK))
+       : "memory");
+}
+
+/*
+ * save IRQ state
+ */
+static inline long arch_local_save_flags(void)
+{
+       unsigned long temp;
+
+       __asm__ __volatile__(
+       "       lr  %0, [status32]      \n"
+       : "=&r"(temp)
+       :
+       : "memory");
+
+       return temp;
+}
+
+/*
+ * Query IRQ state
+ */
+static inline int arch_irqs_disabled_flags(unsigned long flags)
+{
+       return !(flags & (STATUS_E1_MASK
+#ifdef CONFIG_ARC_COMPACT_IRQ_LEVELS
+                       | STATUS_E2_MASK
+#endif
+               ));
+}
+
+static inline int arch_irqs_disabled(void)
+{
+       return arch_irqs_disabled_flags(arch_local_save_flags());
+}
+
+#else
+
+#ifdef CONFIG_TRACE_IRQFLAGS
+
+.macro TRACE_ASM_IRQ_DISABLE
+       bl      trace_hardirqs_off
+.endm
+
+.macro TRACE_ASM_IRQ_ENABLE
+       bl      trace_hardirqs_on
+.endm
+
+#else
+
+.macro TRACE_ASM_IRQ_DISABLE
+.endm
+
+.macro TRACE_ASM_IRQ_ENABLE
+.endm
+
+#endif
+
+.macro IRQ_DISABLE  scratch
+       lr      \scratch, [status32]
+       bic     \scratch, \scratch, (STATUS_E1_MASK | STATUS_E2_MASK)
+       flag    \scratch
+       TRACE_ASM_IRQ_DISABLE
+.endm
+
+.macro IRQ_ENABLE  scratch
+       lr      \scratch, [status32]
+       or      \scratch, \scratch, (STATUS_E1_MASK | STATUS_E2_MASK)
+       flag    \scratch
+       TRACE_ASM_IRQ_ENABLE
+.endm
+
+#endif /* __ASSEMBLY__ */
+
+#endif
index 27ecc6975a5845dee5960197bded8edeff261cbc..59bc6a64f75da77c9cf1972ba35625d74651d51e 100644 (file)
@@ -1,4 +1,5 @@
 /*
+ * Copyright (C) 2014-15 Synopsys, Inc. (www.synopsys.com)
  * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
  *
  * This program is free software; you can redistribute it and/or modify
 #ifndef __ASM_ARC_IRQFLAGS_H
 #define __ASM_ARC_IRQFLAGS_H
 
-/* vineetg: March 2010 : local_irq_save( ) optimisation
- *  -Remove explicit mov of current status32 into reg, that is not needed
- *  -Use BIC  insn instead of INVERTED + AND
- *  -Conditionally disable interrupts (if they are not enabled, don't disable)
-*/
-
-#include <asm/arcregs.h>
-
-/* status32 Reg bits related to Interrupt Handling */
-#define STATUS_E1_BIT          1       /* Int 1 enable */
-#define STATUS_E2_BIT          2       /* Int 2 enable */
-#define STATUS_A1_BIT          3       /* Int 1 active */
-#define STATUS_A2_BIT          4       /* Int 2 active */
-
-#define STATUS_E1_MASK         (1<<STATUS_E1_BIT)
-#define STATUS_E2_MASK         (1<<STATUS_E2_BIT)
-#define STATUS_A1_MASK         (1<<STATUS_A1_BIT)
-#define STATUS_A2_MASK         (1<<STATUS_A2_BIT)
-
-/* Other Interrupt Handling related Aux regs */
-#define AUX_IRQ_LEV            0x200   /* IRQ Priority: L1 or L2 */
-#define AUX_IRQ_HINT           0x201   /* For generating Soft Interrupts */
-#define AUX_IRQ_LV12           0x43    /* interrupt level register */
-
-#define AUX_IENABLE            0x40c
-#define AUX_ITRIGGER           0x40d
-#define AUX_IPULSE             0x415
-
-#ifndef __ASSEMBLY__
-
-/******************************************************************
- * IRQ Control Macros
- *
- * All of them have "memory" clobber (compiler barrier) which is needed to
- * ensure that LD/ST requiring irq safetly (R-M-W when LLSC is not available)
- * are redone after IRQs are re-enabled (and gcc doesn't reuse stale register)
- *
- * Noted at the time of Abilis Timer List corruption
- *     Orig Bug + Rejected solution    : https://lkml.org/lkml/2013/3/29/67
- *     Reasoning                       : https://lkml.org/lkml/2013/4/8/15
- *
- ******************************************************************/
-
-/*
- * Save IRQ state and disable IRQs
- */
-static inline long arch_local_irq_save(void)
-{
-       unsigned long temp, flags;
-
-       __asm__ __volatile__(
-       "       lr  %1, [status32]      \n"
-       "       bic %0, %1, %2          \n"
-       "       and.f 0, %1, %2 \n"
-       "       flag.nz %0              \n"
-       : "=r"(temp), "=r"(flags)
-       : "n"((STATUS_E1_MASK | STATUS_E2_MASK))
-       : "memory", "cc");
-
-       return flags;
-}
-
-/*
- * restore saved IRQ state
- */
-static inline void arch_local_irq_restore(unsigned long flags)
-{
-
-       __asm__ __volatile__(
-       "       flag %0                 \n"
-       :
-       : "r"(flags)
-       : "memory");
-}
-
-/*
- * Unconditionally Enable IRQs
- */
-extern void arch_local_irq_enable(void);
-
-/*
- * Unconditionally Disable IRQs
- */
-static inline void arch_local_irq_disable(void)
-{
-       unsigned long temp;
-
-       __asm__ __volatile__(
-       "       lr  %0, [status32]      \n"
-       "       and %0, %0, %1          \n"
-       "       flag %0                 \n"
-       : "=&r"(temp)
-       : "n"(~(STATUS_E1_MASK | STATUS_E2_MASK))
-       : "memory");
-}
-
-/*
- * save IRQ state
- */
-static inline long arch_local_save_flags(void)
-{
-       unsigned long temp;
-
-       __asm__ __volatile__(
-       "       lr  %0, [status32]      \n"
-       : "=&r"(temp)
-       :
-       : "memory");
-
-       return temp;
-}
-
-/*
- * Query IRQ state
- */
-static inline int arch_irqs_disabled_flags(unsigned long flags)
-{
-       return !(flags & (STATUS_E1_MASK
-#ifdef CONFIG_ARC_COMPACT_IRQ_LEVELS
-                       | STATUS_E2_MASK
-#endif
-               ));
-}
-
-static inline int arch_irqs_disabled(void)
-{
-       return arch_irqs_disabled_flags(arch_local_save_flags());
-}
-
-#else
-
-#ifdef CONFIG_TRACE_IRQFLAGS
-
-.macro TRACE_ASM_IRQ_DISABLE
-       bl      trace_hardirqs_off
-.endm
-
-.macro TRACE_ASM_IRQ_ENABLE
-       bl      trace_hardirqs_on
-.endm
-
+#ifdef CONFIG_ISA_ARCOMPACT
+#include <asm/irqflags-compact.h>
 #else
-
-.macro TRACE_ASM_IRQ_DISABLE
-.endm
-
-.macro TRACE_ASM_IRQ_ENABLE
-.endm
-
+#include <asm/irqflags-arcv2.h>
 #endif
 
-.macro IRQ_DISABLE  scratch
-       lr      \scratch, [status32]
-       bic     \scratch, \scratch, (STATUS_E1_MASK | STATUS_E2_MASK)
-       flag    \scratch
-       TRACE_ASM_IRQ_DISABLE
-.endm
-
-.macro IRQ_ENABLE  scratch
-       lr      \scratch, [status32]
-       or      \scratch, \scratch, (STATUS_E1_MASK | STATUS_E2_MASK)
-       flag    \scratch
-       TRACE_ASM_IRQ_ENABLE
-.endm
-
-#endif /* __ASSEMBLY__ */
-
 #endif
diff --git a/arch/arc/include/asm/mcip.h b/arch/arc/include/asm/mcip.h
new file mode 100644 (file)
index 0000000..52c11f0
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * ARConnect IP Support (Multi core enabler: Cross core IPI, RTC ...)
+ *
+ * Copyright (C) 2014-15 Synopsys, Inc. (www.synopsys.com)
+ *
+ * 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_MCIP_H
+#define __ASM_MCIP_H
+
+#ifdef CONFIG_ISA_ARCV2
+
+#include <asm/arcregs.h>
+
+#define ARC_REG_MCIP_BCR       0x0d0
+#define ARC_REG_MCIP_CMD       0x600
+#define ARC_REG_MCIP_WDATA     0x601
+#define ARC_REG_MCIP_READBACK  0x602
+
+struct mcip_cmd {
+#ifdef CONFIG_CPU_BIG_ENDIAN
+       unsigned int pad:8, param:16, cmd:8;
+#else
+       unsigned int cmd:8, param:16, pad:8;
+#endif
+
+#define CMD_INTRPT_GENERATE_IRQ                0x01
+#define CMD_INTRPT_GENERATE_ACK                0x02
+#define CMD_INTRPT_READ_STATUS         0x03
+#define CMD_INTRPT_CHECK_SOURCE                0x04
+
+/* Semaphore Commands */
+#define CMD_SEMA_CLAIM_AND_READ                0x11
+#define CMD_SEMA_RELEASE               0x12
+
+#define CMD_DEBUG_SET_MASK             0x34
+#define CMD_DEBUG_SET_SELECT           0x36
+
+#define CMD_GRTC_READ_LO               0x42
+#define CMD_GRTC_READ_HI               0x43
+
+#define CMD_IDU_ENABLE                 0x71
+#define CMD_IDU_DISABLE                        0x72
+#define CMD_IDU_SET_MODE               0x74
+#define CMD_IDU_SET_DEST               0x76
+#define CMD_IDU_SET_MASK               0x7C
+
+#define IDU_M_TRIG_LEVEL               0x0
+#define IDU_M_TRIG_EDGE                        0x1
+
+#define IDU_M_DISTRI_RR                        0x0
+#define IDU_M_DISTRI_DEST              0x2
+};
+
+/*
+ * MCIP programming model
+ *
+ * - Simple commands write {cmd:8,param:16} to MCIP_CMD aux reg
+ *   (param could be irq, common_irq, core_id ...)
+ * - More involved commands setup MCIP_WDATA with cmd specific data
+ *   before invoking the simple command
+ */
+static inline void __mcip_cmd(unsigned int cmd, unsigned int param)
+{
+       struct mcip_cmd buf;
+
+       buf.pad = 0;
+       buf.cmd = cmd;
+       buf.param = param;
+
+       WRITE_AUX(ARC_REG_MCIP_CMD, buf);
+}
+
+/*
+ * Setup additional data for a cmd
+ * Callers need to lock to ensure atomicity
+ */
+static inline void __mcip_cmd_data(unsigned int cmd, unsigned int param,
+                                  unsigned int data)
+{
+       write_aux_reg(ARC_REG_MCIP_WDATA, data);
+
+       __mcip_cmd(cmd, param);
+}
+
+extern void mcip_init_early_smp(void);
+extern void mcip_init_smp(unsigned int cpu);
+
+#endif
+
+#endif
index 8c84ae98c33767937ce52f33c8cab6daddabe278..0f9c3eb5327e4494f4a310e62e194c4457c08bea 100644 (file)
 #define CONFIG_ARC_MMU_VER 2
 #elif defined(CONFIG_ARC_MMU_V3)
 #define CONFIG_ARC_MMU_VER 3
+#elif defined(CONFIG_ARC_MMU_V4)
+#define CONFIG_ARC_MMU_VER 4
 #endif
 
 /* MMU Management regs */
 #define ARC_REG_MMU_BCR                0x06f
+#if (CONFIG_ARC_MMU_VER < 4)
 #define ARC_REG_TLBPD0         0x405
 #define ARC_REG_TLBPD1         0x406
 #define ARC_REG_TLBINDEX       0x407
 #define ARC_REG_TLBCOMMAND     0x408
 #define ARC_REG_PID            0x409
 #define ARC_REG_SCRATCH_DATA0  0x418
+#else
+#define ARC_REG_TLBPD0         0x460
+#define ARC_REG_TLBPD1         0x461
+#define ARC_REG_TLBINDEX       0x464
+#define ARC_REG_TLBCOMMAND     0x465
+#define ARC_REG_PID            0x468
+#define ARC_REG_SCRATCH_DATA0  0x46c
+#endif
 
 /* Bits in MMU PID register */
-#define MMU_ENABLE             (1 << 31)       /* Enable MMU for process */
+#define __TLB_ENABLE           (1 << 31)
+#define __PROG_ENABLE          (1 << 30)
+#define MMU_ENABLE             (__TLB_ENABLE | __PROG_ENABLE)
 
 /* Error code if probe fails */
 #define TLB_LKUP_ERR           0x80000000
 
+#if (CONFIG_ARC_MMU_VER < 4)
 #define TLB_DUP_ERR    (TLB_LKUP_ERR | 0x00000001)
+#else
+#define TLB_DUP_ERR    (TLB_LKUP_ERR | 0x40000000)
+#endif
 
 /* TLB Commands */
 #define TLBWrite    0x1
 #define TLBIVUTLB   0x6                /* explicitly inv uTLBs */
 #endif
 
+#if (CONFIG_ARC_MMU_VER >= 4)
+#define TLBInsertEntry 0x7
+#define TLBDeleteEntry 0x8
+#endif
+
 #ifndef __ASSEMBLY__
 
 typedef struct {
index 9615fe1701c60af212b1d20e0d626120956462e1..1281718802f7c8e4d3f71bdf50b3affd57fd66d6 100644 (file)
 #define _PAGE_READ          (1<<3)     /* Page has user read perm (H) */
 #define _PAGE_ACCESSED      (1<<4)     /* Page is accessed (S) */
 #define _PAGE_MODIFIED      (1<<5)     /* Page modified (dirty) (S) */
+
+#if (CONFIG_ARC_MMU_VER >= 4)
+#define _PAGE_WTHRU         (1<<7)     /* Page cache mode write-thru (H) */
+#endif
+
 #define _PAGE_GLOBAL        (1<<8)     /* Page is global (H) */
 #define _PAGE_PRESENT       (1<<9)     /* TLB entry is valid (H) */
+
+#if (CONFIG_ARC_MMU_VER >= 4)
+#define _PAGE_SZ            (1<<10)    /* Page Size indicator (H) */
+#endif
+
 #define _PAGE_SHARED_CODE   (1<<11)    /* Shared Code page with cmn vaddr
                                           usable for shared TLB entries (H) */
 #endif
index 52312cb5dbe21490b48e21343ab8f82b7eecfc0e..ee682d8e0213c5c6c2fac2d70f39dff23b15854a 100644 (file)
@@ -77,7 +77,7 @@ struct task_struct;
  */
 #define TSK_K_ESP(tsk)         (tsk->thread.ksp)
 
-#define TSK_K_REG(tsk, off)    (*((unsigned int *)(TSK_K_ESP(tsk) + \
+#define TSK_K_REG(tsk, off)    (*((unsigned long *)(TSK_K_ESP(tsk) + \
                                        sizeof(struct callee_regs) + off)))
 
 #define TSK_K_BLINK(tsk)       TSK_K_REG(tsk, 4)
@@ -100,29 +100,26 @@ extern unsigned int get_wchan(struct task_struct *p);
 
 #endif /* !__ASSEMBLY__ */
 
-/* Kernels Virtual memory area.
- * Unlike other architectures(MIPS, sh, cris ) ARC 700 does not have a
- * "kernel translated" region (like KSEG2 in MIPS). So we use a upper part
- * of the translated bottom 2GB for kernel virtual memory and protect
- * these pages from user accesses by disabling Ru, Eu and Wu.
+/*
+ * System Memory Map on ARC
+ *
+ * ---------------------------- (lower 2G, Translated) -------------------------
+ * 0x0000_0000         0x5FFF_FFFF     (user vaddr: TASK_SIZE)
+ * 0x6000_0000         0x6FFF_FFFF     (reserved gutter between U/K)
+ * 0x7000_0000         0x7FFF_FFFF     (kvaddr: vmalloc/modules/pkmap..)
+ *
+ * PAGE_OFFSET ---------------- (Upper 2G, Untranslated) -----------------------
+ * 0x8000_0000         0xBFFF_FFFF     (kernel direct mapped)
+ * 0xC000_0000         0xFFFF_FFFF     (peripheral uncached space)
+ * -----------------------------------------------------------------------------
  */
-#define VMALLOC_SIZE   (0x10000000)    /* 256M */
-#define VMALLOC_START  (PAGE_OFFSET - VMALLOC_SIZE)
-#define VMALLOC_END    (PAGE_OFFSET)
+#define VMALLOC_START  0x70000000
+#define VMALLOC_SIZE   (PAGE_OFFSET - VMALLOC_START)
+#define VMALLOC_END    (VMALLOC_START + VMALLOC_SIZE)
 
-/* Most of the architectures seem to be keeping some kind of padding between
- * userspace TASK_SIZE and PAGE_OFFSET. i.e TASK_SIZE != PAGE_OFFSET.
- */
 #define USER_KERNEL_GUTTER    0x10000000
 
-/* User address space:
- * On ARC700, CPU allows the entire lower half of 32 bit address space to be
- * translated. Thus potentially 2G (0:0x7FFF_FFFF) could be User vaddr space.
- * However we steal 256M for kernel addr (0x7000_0000:0x7FFF_FFFF) and another
- * 256M (0x6000_0000:0x6FFF_FFFF) is gutter between user/kernel spaces
- * Thus total User vaddr space is (0:0x5FFF_FFFF)
- */
-#define TASK_SIZE      (PAGE_OFFSET - VMALLOC_SIZE - USER_KERNEL_GUTTER)
+#define TASK_SIZE      (VMALLOC_START - USER_KERNEL_GUTTER)
 
 #define STACK_TOP       TASK_SIZE
 #define STACK_TOP_MAX   STACK_TOP
index 1bfeec2c0558c2f6f91142105bee0c6ff70c7a75..91755972b9a25222c37a36e6b76dfd758cdbe771 100644 (file)
@@ -16,6 +16,7 @@
 
 /* THE pt_regs: Defines how regs are saved during entry into kernel */
 
+#ifdef CONFIG_ISA_ARCOMPACT
 struct pt_regs {
 
        /* Real registers */
@@ -56,6 +57,48 @@ struct pt_regs {
 
        long user_r25;
 };
+#else
+
+struct pt_regs {
+
+       long orig_r0;
+
+       union {
+               struct {
+#ifdef CONFIG_CPU_BIG_ENDIAN
+                       unsigned long state:8, ecr_vec:8,
+                                     ecr_cause:8, ecr_param:8;
+#else
+                       unsigned long ecr_param:8, ecr_cause:8,
+                                     ecr_vec:8, state:8;
+#endif
+               };
+               unsigned long event;
+       };
+
+       long bta;       /* bta_l1, bta_l2, erbta */
+
+       long user_r25;
+
+       long r26;       /* gp */
+       long fp;
+       long sp;        /* user/kernel sp depending on where we came from  */
+
+       long r12;
+
+       /*------- Below list auto saved by h/w -----------*/
+       long r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11;
+
+       long blink;
+       long lp_end, lp_start, lp_count;
+
+       long ei, ldi, jli;
+
+       long ret;
+       long status32;
+};
+
+#endif
 
 /* Callee saved registers - need to be saved only when you are scheduled out */
 
index b6a8c2dfbe6e42cd51def893784f0780bc67264e..e1651df6a93d5bc8ab0af3a833c7c6ffd23acacc 100644 (file)
@@ -22,24 +22,46 @@ static inline void arch_spin_lock(arch_spinlock_t *lock)
 {
        unsigned int tmp = __ARCH_SPIN_LOCK_LOCKED__;
 
+       /*
+        * This smp_mb() is technically superfluous, we only need the one
+        * after the lock for providing the ACQUIRE semantics.
+        * However doing the "right" thing was regressing hackbench
+        * so keeping this, pending further investigation
+        */
+       smp_mb();
+
        __asm__ __volatile__(
        "1:     ex  %0, [%1]            \n"
        "       breq  %0, %2, 1b        \n"
        : "+&r" (tmp)
        : "r"(&(lock->slock)), "ir"(__ARCH_SPIN_LOCK_LOCKED__)
        : "memory");
+
+       /*
+        * ACQUIRE barrier to ensure load/store after taking the lock
+        * don't "bleed-up" out of the critical section (leak-in is allowed)
+        * http://www.spinics.net/lists/kernel/msg2010409.html
+        *
+        * ARCv2 only has load-load, store-store and all-all barrier
+        * thus need the full all-all barrier
+        */
+       smp_mb();
 }
 
 static inline int arch_spin_trylock(arch_spinlock_t *lock)
 {
        unsigned int tmp = __ARCH_SPIN_LOCK_LOCKED__;
 
+       smp_mb();
+
        __asm__ __volatile__(
        "1:     ex  %0, [%1]            \n"
        : "+r" (tmp)
        : "r"(&(lock->slock))
        : "memory");
 
+       smp_mb();
+
        return (tmp == __ARCH_SPIN_LOCK_UNLOCKED__);
 }
 
@@ -47,12 +69,22 @@ static inline void arch_spin_unlock(arch_spinlock_t *lock)
 {
        unsigned int tmp = __ARCH_SPIN_LOCK_UNLOCKED__;
 
+       /*
+        * RELEASE barrier: given the instructions avail on ARCv2, full barrier
+        * is the only option
+        */
+       smp_mb();
+
        __asm__ __volatile__(
        "       ex  %0, [%1]            \n"
        : "+r" (tmp)
        : "r"(&(lock->slock))
        : "memory");
 
+       /*
+        * superfluous, but keeping for now - see pairing version in
+        * arch_spin_lock above
+        */
        smp_mb();
 }
 
index aca0d5a45c7b84c2bdc0f95da1549ad7d3f1af68..3af67455659af49d9f9d53b67ac26024cf3b77b9 100644 (file)
@@ -25,6 +25,7 @@
 #endif
 
 #define THREAD_SIZE     (PAGE_SIZE << THREAD_SIZE_ORDER)
+#define THREAD_SHIFT   (PAGE_SHIFT << THREAD_SIZE_ORDER)
 
 #ifndef __ASSEMBLY__
 
index 30c9baffa96f1f3a5cab5d6ec6fe83b9f4e86318..d1da6032b715a7fea35d71fcedeeeb8cdfe590e4 100644 (file)
@@ -659,31 +659,30 @@ static inline unsigned long __arc_clear_user(void __user *to, unsigned long n)
 static inline long
 __arc_strncpy_from_user(char *dst, const char __user *src, long count)
 {
-       long res = count;
+       long res = 0;
        char val;
-       unsigned int hw_count;
 
        if (count == 0)
                return 0;
 
        __asm__ __volatile__(
-       "       lp 2f           \n"
+       "       lp      3f                      \n"
        "1:     ldb.ab  %3, [%2, 1]             \n"
-       "       breq.d  %3, 0, 2f               \n"
+       "       breq.d  %3, 0, 3f               \n"
        "       stb.ab  %3, [%1, 1]             \n"
-       "2:     sub %0, %6, %4                  \n"
-       "3:     ;nop                            \n"
+       "       add     %0, %0, 1       # Num of NON NULL bytes copied  \n"
+       "3:                                                             \n"
        "       .section .fixup, \"ax\"         \n"
        "       .align 4                        \n"
-       "4:     mov %0, %5                      \n"
+       "4:     mov %0, %4              # sets @res as -EFAULT  \n"
        "       j   3b                          \n"
        "       .previous                       \n"
        "       .section __ex_table, \"a\"      \n"
        "       .align 4                        \n"
        "       .word   1b, 4b                  \n"
        "       .previous                       \n"
-       : "=r"(res), "+r"(dst), "+r"(src), "=&r"(val), "=l"(hw_count)
-       : "g"(-EFAULT), "ir"(count), "4"(count) /* this "4" seeds lp_count */
+       : "+r"(res), "+r"(dst), "+r"(src), "=r"(val)
+       : "g"(-EFAULT), "l"(count)
        : "memory");
 
        return res;
index e5d41e08240c561f4299d2b3ce6c6e30d7d3a236..9d129a2a1351951465b22fd020f568abe1843b7a 100644 (file)
@@ -30,7 +30,7 @@
 #define PAGE_OFFSET    (0x80000000)
 #else
 #define PAGE_SIZE      (1UL << PAGE_SHIFT)     /* Default 8K */
-#define PAGE_OFFSET    (0x80000000UL)  /* Kernel starts at 2G onwards */
+#define PAGE_OFFSET    (0x80000000UL)          /* Kernel starts at 2G onwards */
 #endif
 
 #define PAGE_MASK      (~(PAGE_SIZE-1))
index 113f2033da9f096a45588a40b00193c8305cf693..e7f3625a19b51dc5f117e13fc71b2930bbb4b52d 100644 (file)
@@ -8,12 +8,14 @@
 # Pass UTS_MACHINE for user_regset definition
 CFLAGS_ptrace.o                += -DUTS_MACHINE='"$(UTS_MACHINE)"'
 
-obj-y  := arcksyms.o setup.o irq.o time.o reset.o ptrace.o entry.o process.o
+obj-y  := arcksyms.o setup.o irq.o time.o reset.o ptrace.o process.o devtree.o
 obj-y  += signal.o traps.o sys.o troubleshoot.o stacktrace.o disasm.o clk.o
-obj-y  += devtree.o
+obj-$(CONFIG_ISA_ARCOMPACT)            += entry-compact.o intc-compact.o
+obj-$(CONFIG_ISA_ARCV2)                        += entry-arcv2.o intc-arcv2.o
 
 obj-$(CONFIG_MODULES)                  += arcksyms.o module.o
 obj-$(CONFIG_SMP)                      += smp.o
+obj-$(CONFIG_ARC_MCIP)                 += mcip.o
 obj-$(CONFIG_ARC_DW2_UNWIND)           += unwind.o
 obj-$(CONFIG_KPROBES)                  += kprobes.o
 obj-$(CONFIG_ARC_EMUL_UNALIGNED)       += unaligned.o
index 6c3aa0edb9b5bc1914d006b2a22b766f71adba9c..ecaf34e9235c20dba4729d79321bef0d3b462a37 100644 (file)
@@ -37,6 +37,8 @@ int main(void)
 
        DEFINE(TASK_ACT_MM, offsetof(struct task_struct, active_mm));
        DEFINE(TASK_TGID, offsetof(struct task_struct, tgid));
+       DEFINE(TASK_PID, offsetof(struct task_struct, pid));
+       DEFINE(TASK_COMM, offsetof(struct task_struct, comm));
 
        DEFINE(MM_CTXT, offsetof(struct mm_struct, context));
        DEFINE(MM_PGD, offsetof(struct mm_struct, pgd));
@@ -56,8 +58,11 @@ int main(void)
        DEFINE(PT_r5, offsetof(struct pt_regs, r5));
        DEFINE(PT_r6, offsetof(struct pt_regs, r6));
        DEFINE(PT_r7, offsetof(struct pt_regs, r7));
+       DEFINE(PT_ret, offsetof(struct pt_regs, ret));
 
        DEFINE(SZ_CALLEE_REGS, sizeof(struct callee_regs));
        DEFINE(SZ_PT_REGS, sizeof(struct pt_regs));
+       DEFINE(PT_user_r25, offsetof(struct pt_regs, user_r25));
+
        return 0;
 }
index e32b54abff51fdc6b16894ce466fd16d2063bd7f..7e844fd8213fda0c0e41f6dc436c8a348f2afd52 100644 (file)
@@ -32,6 +32,8 @@ static void __init arc_set_early_base_baud(unsigned long dt_root)
 
        if (of_flat_dt_is_compatible(dt_root, "abilis,arc-tb10x"))
                arc_base_baud = core_clk/3;
+       else if (of_flat_dt_is_compatible(dt_root, "snps,arc-sdp"))
+               arc_base_baud = 33333333;       /* Fixed 33MHz clk (AXS10x) */
        else
                arc_base_baud = core_clk;
 }
diff --git a/arch/arc/kernel/entry-arcv2.S b/arch/arc/kernel/entry-arcv2.S
new file mode 100644 (file)
index 0000000..bd7105d
--- /dev/null
@@ -0,0 +1,239 @@
+/*
+ * ARCv2 ISA based core Low Level Intr/Traps/Exceptions(non-TLB) Handling
+ *
+ * Copyright (C) 2013 Synopsys, Inc. (www.synopsys.com)
+ *
+ * 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/linkage.h>   /* ARC_{EXTRY,EXIT} */
+#include <asm/entry.h>       /* SAVE_ALL_{INT1,INT2,TRAP...} */
+#include <asm/errno.h>
+#include <asm/arcregs.h>
+#include <asm/irqflags.h>
+
+       .cpu HS
+
+#define VECTOR .word
+
+;############################ Vector Table #################################
+
+       .section .vector,"a",@progbits
+       .align 4
+
+# Initial 16 slots are Exception Vectors
+VECTOR stext                   ; Restart Vector (jump to entry point)
+VECTOR mem_service             ; Mem exception
+VECTOR instr_service           ; Instrn Error
+VECTOR EV_MachineCheck         ; Fatal Machine check
+VECTOR EV_TLBMissI             ; Intruction TLB miss
+VECTOR EV_TLBMissD             ; Data TLB miss
+VECTOR EV_TLBProtV             ; Protection Violation
+VECTOR EV_PrivilegeV           ; Privilege Violation
+VECTOR EV_SWI                  ; Software Breakpoint
+VECTOR EV_Trap                 ; Trap exception
+VECTOR EV_Extension            ; Extn Instruction Exception
+VECTOR EV_DivZero              ; Divide by Zero
+VECTOR EV_DCError              ; Data Cache Error
+VECTOR EV_Misaligned           ; Misaligned Data Access
+VECTOR reserved                ; Reserved slots
+VECTOR reserved                ; Reserved slots
+
+# Begin Interrupt Vectors
+VECTOR handle_interrupt        ; (16) Timer0
+VECTOR handle_interrupt        ; unused (Timer1)
+VECTOR handle_interrupt        ; unused (WDT)
+VECTOR handle_interrupt        ; (19) ICI (inter core interrupt)
+VECTOR handle_interrupt
+VECTOR handle_interrupt
+VECTOR handle_interrupt
+VECTOR handle_interrupt        ; (23) End of fixed IRQs
+
+.rept CONFIG_ARC_NUMBER_OF_INTERRUPTS - 8
+       VECTOR  handle_interrupt
+.endr
+
+       .section .text, "ax",@progbits
+
+res_service:           ; processor restart
+       flag    0x1     ; not implemented
+       nop
+       nop
+
+reserved:              ; processor restart
+       rtie            ; jump to processor initializations
+
+;##################### Interrupt Handling ##############################
+
+ENTRY(handle_interrupt)
+
+       INTERRUPT_PROLOGUE  irq
+
+       clri            ; To make status32.IE agree with CPU internal state
+
+       lr  r0, [ICAUSE]
+
+       mov   blink, ret_from_exception
+
+       b.d  arch_do_IRQ
+       mov r1, sp
+
+END(handle_interrupt)
+
+;################### Non TLB Exception Handling #############################
+
+ENTRY(EV_SWI)
+       flag 1
+END(EV_SWI)
+
+ENTRY(EV_DivZero)
+       flag 1
+END(EV_DivZero)
+
+ENTRY(EV_DCError)
+       flag 1
+END(EV_DCError)
+
+ENTRY(EV_Misaligned)
+
+       EXCEPTION_PROLOGUE
+
+       lr  r0, [efa]   ; Faulting Data address
+       mov r1, sp
+
+       FAKE_RET_FROM_EXCPN
+
+       SAVE_CALLEE_SAVED_USER
+       mov r2, sp              ; callee_regs
+
+       bl  do_misaligned_access
+
+       ; TBD: optimize - do this only if a callee reg was involved
+       ; either a dst of emulated LD/ST or src with address-writeback
+       RESTORE_CALLEE_SAVED_USER
+
+       b   ret_from_exception
+END(EV_Misaligned)
+
+; ---------------------------------------------
+; Protection Violation Exception Handler
+; ---------------------------------------------
+
+ENTRY(EV_TLBProtV)
+
+       EXCEPTION_PROLOGUE
+
+       lr  r0, [efa]   ; Faulting Data address
+       mov r1, sp      ; pt_regs
+
+       FAKE_RET_FROM_EXCPN
+
+       mov blink, ret_from_exception
+       b   do_page_fault
+
+END(EV_TLBProtV)
+
+; From Linux standpoint Slow Path I/D TLB Miss is same a ProtV as they
+; need to call do_page_fault().
+; ECR in pt_regs provides whether access was R/W/X
+
+.global        call_do_page_fault
+.set call_do_page_fault, EV_TLBProtV
+
+;############# Common Handlers for ARCompact and ARCv2 ##############
+
+#include "entry.S"
+
+;############# Return from Intr/Excp/Trap (ARCv2 ISA Specifics) ##############
+;
+; Restore the saved sys context (common exit-path for EXCPN/IRQ/Trap)
+; IRQ shd definitely not happen between now and rtie
+; All 2 entry points to here already disable interrupts
+
+.Lrestore_regs:
+
+       ld      r0, [sp, PT_status32]   ; U/K mode at time of entry
+       lr      r10, [AUX_IRQ_ACT]
+
+       bmsk    r11, r10, 15    ; AUX_IRQ_ACT.ACTIVE
+       breq    r11, 0, .Lexcept_ret    ; No intr active, ret from Exception
+
+;####### Return from Intr #######
+
+debug_marker_l1:
+       bbit1.nt r0, STATUS_DE_BIT, .Lintr_ret_to_delay_slot
+
+.Lisr_ret_fast_path:
+       ; Handle special case #1: (Entry via Exception, Return via IRQ)
+       ;
+       ; Exception in U mode, preempted in kernel, Intr taken (K mode), orig
+       ; task now returning to U mode (riding the Intr)
+       ; AUX_IRQ_ACTIVE won't have U bit set (since intr in K mode), hence SP
+       ; won't be switched to correct U mode value (from AUX_SP)
+       ; So force AUX_IRQ_ACT.U for such a case
+
+       btst    r0, STATUS_U_BIT                ; Z flag set if K (Z clear for U)
+       bset.nz r11, r11, AUX_IRQ_ACT_BIT_U     ; NZ means U
+       sr      r11, [AUX_IRQ_ACT]
+
+       INTERRUPT_EPILOGUE  irq
+       rtie
+
+;####### Return from Exception / pure kernel mode #######
+
+.Lexcept_ret:  ; Expects r0 has PT_status32
+
+debug_marker_syscall:
+       EXCEPTION_EPILOGUE
+       rtie
+
+;####### Return from Intr to insn in delay slot #######
+
+; Handle special case #2: (Entry via Exception in Delay Slot, Return via IRQ)
+;
+; Intr returning to a Delay Slot (DS) insn
+; (since IRQ NOT allowed in DS in ARCv2, this can only happen if orig
+; entry was via Exception in DS which got preempted in kernel).
+;
+; IRQ RTIE won't reliably restore DE bit and/or BTA, needs handling
+.Lintr_ret_to_delay_slot:
+debug_marker_ds:
+
+       ld      r2, [@intr_to_DE_cnt]
+       add     r2, r2, 1
+       st      r2, [@intr_to_DE_cnt]
+
+       ld      r2, [sp, PT_ret]
+       ld      r3, [sp, PT_status32]
+
+       bic     r0, r3, STATUS_U_MASK|STATUS_DE_MASK|STATUS_IE_MASK|STATUS_L_MASK
+       st      r0, [sp, PT_status32]
+
+       mov     r1, .Lintr_ret_to_delay_slot_2
+       st      r1, [sp, PT_ret]
+
+       st      r2, [sp, 0]
+       st      r3, [sp, 4]
+
+       b       .Lisr_ret_fast_path
+
+.Lintr_ret_to_delay_slot_2:
+       sub     sp, sp, SZ_PT_REGS
+       st      r9, [sp, -4]
+
+       ld      r9, [sp, 0]
+       sr      r9, [eret]
+
+       ld      r9, [sp, 4]
+       sr      r9, [erstatus]
+
+       ld      r9, [sp, 8]
+       sr      r9, [erbta]
+
+       ld      r9, [sp, -4]
+       add     sp, sp, SZ_PT_REGS
+       rtie
+
+END(ret_from_exception)
diff --git a/arch/arc/kernel/entry-compact.S b/arch/arc/kernel/entry-compact.S
new file mode 100644 (file)
index 0000000..15d457b
--- /dev/null
@@ -0,0 +1,393 @@
+/*
+ * Low Level Interrupts/Traps/Exceptions(non-TLB) Handling for ARCompact ISA
+ *
+ * Copyright (C) 2014-15 Synopsys, Inc. (www.synopsys.com)
+ * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
+ *
+ * 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.
+ *
+ * vineetg: May 2011
+ *  -Userspace unaligned access emulation
+ *
+ * vineetg: Feb 2011 (ptrace low level code fixes)
+ *  -traced syscall return code (r0) was not saved into pt_regs for restoring
+ *   into user reg-file when traded task rets to user space.
+ *  -syscalls needing arch-wrappers (mainly for passing sp as pt_regs)
+ *   were not invoking post-syscall trace hook (jumping directly into
+ *   ret_from_system_call)
+ *
+ * vineetg: Nov 2010:
+ *  -Vector table jumps (@8 bytes) converted into branches (@4 bytes)
+ *  -To maintain the slot size of 8 bytes/vector, added nop, which is
+ *   not executed at runtime.
+ *
+ * vineetg: Nov 2009 (Everything needed for TIF_RESTORE_SIGMASK)
+ *  -do_signal()invoked upon TIF_RESTORE_SIGMASK as well
+ *  -Wrappers for sys_{,rt_}sigsuspend() nolonger needed as they don't
+ *   need ptregs anymore
+ *
+ * Vineetg: Oct 2009
+ *  -In a rare scenario, Process gets a Priv-V exception and gets scheduled
+ *   out. Since we don't do FAKE RTIE for Priv-V, CPU excpetion state remains
+ *   active (AE bit enabled).  This causes a double fault for a subseq valid
+ *   exception. Thus FAKE RTIE needed in low level Priv-Violation handler.
+ *   Instr Error could also cause similar scenario, so same there as well.
+ *
+ * Vineetg: March 2009 (Supporting 2 levels of Interrupts)
+ *
+ * Vineetg: Aug 28th 2008: Bug #94984
+ *  -Zero Overhead Loop Context shd be cleared when entering IRQ/EXcp/Trap
+ *   Normally CPU does this automatically, however when doing FAKE rtie,
+ *   we need to explicitly do this. The problem in macros
+ *   FAKE_RET_FROM_EXCPN and FAKE_RET_FROM_EXCPN_LOCK_IRQ was that this bit
+ *   was being "CLEARED" rather then "SET". Since it is Loop INHIBIT Bit,
+ *   setting it and not clearing it clears ZOL context
+ *
+ * Vineetg: May 16th, 2008
+ *  - r25 now contains the Current Task when in kernel
+ *
+ * Vineetg: Dec 22, 2007
+ *    Minor Surgery of Low Level ISR to make it SMP safe
+ *    - MMU_SCRATCH0 Reg used for freeing up r9 in Level 1 ISR
+ *    - _current_task is made an array of NR_CPUS
+ *    - Access of _current_task wrapped inside a macro so that if hardware
+ *       team agrees for a dedicated reg, no other code is touched
+ *
+ * Amit Bhor, Rahul Trivedi, Kanika Nema, Sameer Dhavale : Codito Tech 2004
+ */
+
+#include <linux/errno.h>
+#include <linux/linkage.h>     /* {EXTRY,EXIT} */
+#include <asm/entry.h>
+#include <asm/irqflags.h>
+
+       .cpu A7
+
+;############################ Vector Table #################################
+
+.macro VECTOR  lbl
+#if 1   /* Just in case, build breaks */
+       j   \lbl
+#else
+       b   \lbl
+       nop
+#endif
+.endm
+
+       .section .vector, "ax",@progbits
+       .align 4
+
+/* Each entry in the vector table must occupy 2 words. Since it is a jump
+ * across sections (.vector to .text) we are gauranteed that 'j somewhere'
+ * will use the 'j limm' form of the intrsuction as long as somewhere is in
+ * a section other than .vector.
+ */
+
+; ********* Critical System Events **********************
+VECTOR   res_service             ; 0x0, Restart Vector  (0x0)
+VECTOR   mem_service             ; 0x8, Mem exception   (0x1)
+VECTOR   instr_service           ; 0x10, Instrn Error   (0x2)
+
+; ******************** Device ISRs **********************
+#ifdef CONFIG_ARC_IRQ3_LV2
+VECTOR   handle_interrupt_level2
+#else
+VECTOR   handle_interrupt_level1
+#endif
+
+VECTOR   handle_interrupt_level1
+
+#ifdef CONFIG_ARC_IRQ5_LV2
+VECTOR   handle_interrupt_level2
+#else
+VECTOR   handle_interrupt_level1
+#endif
+
+#ifdef CONFIG_ARC_IRQ6_LV2
+VECTOR   handle_interrupt_level2
+#else
+VECTOR   handle_interrupt_level1
+#endif
+
+.rept   25
+VECTOR   handle_interrupt_level1 ; Other devices
+.endr
+
+/* FOR ARC600: timer = 0x3, uart = 0x8, emac = 0x10 */
+
+; ******************** Exceptions **********************
+VECTOR   EV_MachineCheck         ; 0x100, Fatal Machine check   (0x20)
+VECTOR   EV_TLBMissI             ; 0x108, Intruction TLB miss   (0x21)
+VECTOR   EV_TLBMissD             ; 0x110, Data TLB miss         (0x22)
+VECTOR   EV_TLBProtV             ; 0x118, Protection Violation  (0x23)
+                                ;         or Misaligned Access
+VECTOR   EV_PrivilegeV           ; 0x120, Privilege Violation   (0x24)
+VECTOR   EV_Trap                 ; 0x128, Trap exception        (0x25)
+VECTOR   EV_Extension            ; 0x130, Extn Intruction Excp  (0x26)
+
+.rept   24
+VECTOR   reserved                ; Reserved Exceptions
+.endr
+
+
+;##################### Scratch Mem for IRQ stack switching #############
+
+ARCFP_DATA int1_saved_reg
+       .align 32
+       .type   int1_saved_reg, @object
+       .size   int1_saved_reg, 4
+int1_saved_reg:
+       .zero 4
+
+/* Each Interrupt level needs its own scratch */
+#ifdef CONFIG_ARC_COMPACT_IRQ_LEVELS
+
+ARCFP_DATA int2_saved_reg
+       .type   int2_saved_reg, @object
+       .size   int2_saved_reg, 4
+int2_saved_reg:
+       .zero 4
+
+#endif
+
+; ---------------------------------------------
+       .section .text, "ax",@progbits
+
+res_service:           ; processor restart
+       flag    0x1     ; not implemented
+       nop
+       nop
+
+reserved:              ; processor restart
+       rtie            ; jump to processor initializations
+
+;##################### Interrupt Handling ##############################
+
+#ifdef CONFIG_ARC_COMPACT_IRQ_LEVELS
+; ---------------------------------------------
+;  Level 2 ISR: Can interrupt a Level 1 ISR
+; ---------------------------------------------
+ENTRY(handle_interrupt_level2)
+
+       INTERRUPT_PROLOGUE 2
+
+       ;------------------------------------------------------
+       ; if L2 IRQ interrupted a L1 ISR, disable preemption
+       ;------------------------------------------------------
+
+       ld r9, [sp, PT_status32]        ; get statu32_l2 (saved in pt_regs)
+       bbit0 r9, STATUS_A1_BIT, 1f     ; L1 not active when L2 IRQ, so normal
+
+       ; A1 is set in status32_l2
+       ; bump thread_info->preempt_count (Disable preemption)
+       GET_CURR_THR_INFO_FROM_SP   r10
+       ld      r9, [r10, THREAD_INFO_PREEMPT_COUNT]
+       add     r9, r9, 1
+       st      r9, [r10, THREAD_INFO_PREEMPT_COUNT]
+
+1:
+       ;------------------------------------------------------
+       ; setup params for Linux common ISR and invoke it
+       ;------------------------------------------------------
+       lr  r0, [icause2]
+       and r0, r0, 0x1f
+
+       bl.d  @arch_do_IRQ
+       mov r1, sp
+
+       mov r8,0x2
+       sr r8, [AUX_IRQ_LV12]       ; clear bit in Sticky Status Reg
+
+       b   ret_from_exception
+
+END(handle_interrupt_level2)
+
+#endif
+
+; ---------------------------------------------
+;  Level 1 ISR
+; ---------------------------------------------
+ENTRY(handle_interrupt_level1)
+
+       INTERRUPT_PROLOGUE 1
+
+       lr  r0, [icause1]
+       and r0, r0, 0x1f
+
+#ifdef CONFIG_TRACE_IRQFLAGS
+       ; icause1 needs to be read early, before calling tracing, which
+       ; can clobber scratch regs, hence use of stack to stash it
+       push r0
+       TRACE_ASM_IRQ_DISABLE
+       pop  r0
+#endif
+
+       bl.d  @arch_do_IRQ
+       mov r1, sp
+
+       mov r8,0x1
+       sr r8, [AUX_IRQ_LV12]       ; clear bit in Sticky Status Reg
+
+       b   ret_from_exception
+END(handle_interrupt_level1)
+
+;################### Non TLB Exception Handling #############################
+
+; ---------------------------------------------
+; Protection Violation Exception Handler
+; ---------------------------------------------
+
+ENTRY(EV_TLBProtV)
+
+       EXCEPTION_PROLOGUE
+
+       lr  r2, [ecr]
+       lr  r0, [efa]   ; Faulting Data address (not part of pt_regs saved above)
+
+       ; Exception auto-disables further Intr/exceptions.
+       ; Re-enable them by pretending to return from exception
+       ; (so rest of handler executes in pure K mode)
+
+       FAKE_RET_FROM_EXCPN
+
+       mov   r1, sp    ; Handle to pt_regs
+
+       ;------ (5) Type of Protection Violation? ----------
+       ;
+       ; ProtV Hardware Exception is triggered for Access Faults of 2 types
+       ;   -Access Violaton    : 00_23_(00|01|02|03)_00
+       ;                                x  r  w  r+w
+       ;   -Unaligned Access   : 00_23_04_00
+       ;
+       bbit1 r2, ECR_C_BIT_PROTV_MISALIG_DATA, 4f
+
+       ;========= (6a) Access Violation Processing ========
+       bl  do_page_fault
+       b   ret_from_exception
+
+       ;========== (6b) Non aligned access ============
+4:
+
+       SAVE_CALLEE_SAVED_USER
+       mov r2, sp              ; callee_regs
+
+       bl  do_misaligned_access
+
+       ; TBD: optimize - do this only if a callee reg was involved
+       ; either a dst of emulated LD/ST or src with address-writeback
+       RESTORE_CALLEE_SAVED_USER
+
+       b   ret_from_exception
+
+END(EV_TLBProtV)
+
+; Wrapper for Linux page fault handler called from EV_TLBMiss*
+; Very similar to ProtV handler case (6a) above, but avoids the extra checks
+; for Misaligned access
+;
+ENTRY(call_do_page_fault)
+
+       EXCEPTION_PROLOGUE
+       lr  r0, [efa]   ; Faulting Data address
+       mov   r1, sp
+       FAKE_RET_FROM_EXCPN
+
+       mov blink, ret_from_exception
+       b  do_page_fault
+
+END(call_do_page_fault)
+
+;############# Common Handlers for ARCompact and ARCv2 ##############
+
+#include "entry.S"
+
+;############# Return from Intr/Excp/Trap (ARC Specifics) ##############
+;
+; Restore the saved sys context (common exit-path for EXCPN/IRQ/Trap)
+; IRQ shd definitely not happen between now and rtie
+; All 2 entry points to here already disable interrupts
+
+.Lrestore_regs:
+
+       TRACE_ASM_IRQ_ENABLE
+
+       lr      r10, [status32]
+
+       ; Restore REG File. In case multiple Events outstanding,
+       ; use the same priorty as rtie: EXCPN, L2 IRQ, L1 IRQ, None
+       ; Note that we use realtime STATUS32 (not pt_regs->status32) to
+       ; decide that.
+
+       ; if Returning from Exception
+       btst   r10, STATUS_AE_BIT
+       bnz    .Lexcep_ret
+
+       ; Not Exception so maybe Interrupts (Level 1 or 2)
+
+#ifdef CONFIG_ARC_COMPACT_IRQ_LEVELS
+
+       ; Level 2 interrupt return Path - from hardware standpoint
+       bbit0  r10, STATUS_A2_BIT, not_level2_interrupt
+
+       ;------------------------------------------------------------------
+       ; However the context returning might not have taken L2 intr itself
+       ; e.g. Task'A' user-code -> L2 intr -> schedule -> 'B' user-code ret
+       ; Special considerations needed for the context which took L2 intr
+
+       ld   r9, [sp, PT_event]        ; Ensure this is L2 intr context
+       brne r9, event_IRQ2, 149f
+
+       ;------------------------------------------------------------------
+       ; if L2 IRQ interrupted an L1 ISR,  we'd disabled preemption earlier
+       ; so that sched doesn't move to new task, causing L1 to be delayed
+       ; undeterministically. Now that we've achieved that, let's reset
+       ; things to what they were, before returning from L2 context
+       ;----------------------------------------------------------------
+
+       ld r9, [sp, PT_status32]       ; get statu32_l2 (saved in pt_regs)
+       bbit0 r9, STATUS_A1_BIT, 149f  ; L1 not active when L2 IRQ, so normal
+
+       ; decrement thread_info->preempt_count (re-enable preemption)
+       GET_CURR_THR_INFO_FROM_SP   r10
+       ld      r9, [r10, THREAD_INFO_PREEMPT_COUNT]
+
+       ; paranoid check, given A1 was active when A2 happened, preempt count
+       ; must not be 0 because we would have incremented it.
+       ; If this does happen we simply HALT as it means a BUG !!!
+       cmp     r9, 0
+       bnz     2f
+       flag 1
+
+2:
+       sub     r9, r9, 1
+       st      r9, [r10, THREAD_INFO_PREEMPT_COUNT]
+
+149:
+       ;return from level 2
+       INTERRUPT_EPILOGUE 2
+debug_marker_l2:
+       rtie
+
+not_level2_interrupt:
+
+#endif
+
+       bbit0  r10, STATUS_A1_BIT, .Lpure_k_mode_ret
+
+       ;return from level 1
+       INTERRUPT_EPILOGUE 1
+debug_marker_l1:
+       rtie
+
+.Lexcep_ret:
+.Lpure_k_mode_ret:
+
+       ;this case is for syscalls or Exceptions or pure kernel mode
+
+       EXCEPTION_EPILOGUE
+debug_marker_syscall:
+       rtie
+
+END(ret_from_exception)
index d868289c5a26f74e780ee2e59ff6174987d68d68..f7a82fd4d6018b29c4e4297af9b839ca1a154fab 100644 (file)
@@ -1,60 +1,13 @@
 /*
- * Low Level Interrupts/Traps/Exceptions(non-TLB) Handling for ARC
+ * Common Low Level Interrupts/Traps/Exceptions(non-TLB) Handling for ARC
+ * (included from entry-<isa>.S
  *
+ * Copyright (C) 2014-15 Synopsys, Inc. (www.synopsys.com)
  * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
  *
  * 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.
- *
- * vineetg: May 2011
- *  -Userspace unaligned access emulation
- *
- * vineetg: Feb 2011 (ptrace low level code fixes)
- *  -traced syscall return code (r0) was not saved into pt_regs for restoring
- *   into user reg-file when traded task rets to user space.
- *  -syscalls needing arch-wrappers (mainly for passing sp as pt_regs)
- *   were not invoking post-syscall trace hook (jumping directly into
- *   ret_from_system_call)
- *
- * vineetg: Nov 2010:
- *  -Vector table jumps (@8 bytes) converted into branches (@4 bytes)
- *  -To maintain the slot size of 8 bytes/vector, added nop, which is
- *   not executed at runtime.
- *
- * vineetg: Nov 2009 (Everything needed for TIF_RESTORE_SIGMASK)
- *  -do_signal()invoked upon TIF_RESTORE_SIGMASK as well
- *  -Wrappers for sys_{,rt_}sigsuspend() nolonger needed as they don't
- *   need ptregs anymore
- *
- * Vineetg: Oct 2009
- *  -In a rare scenario, Process gets a Priv-V exception and gets scheduled
- *   out. Since we don't do FAKE RTIE for Priv-V, CPU excpetion state remains
- *   active (AE bit enabled).  This causes a double fault for a subseq valid
- *   exception. Thus FAKE RTIE needed in low level Priv-Violation handler.
- *   Instr Error could also cause similar scenario, so same there as well.
- *
- * Vineetg: March 2009 (Supporting 2 levels of Interrupts)
- *
- * Vineetg: Aug 28th 2008: Bug #94984
- *  -Zero Overhead Loop Context shd be cleared when entering IRQ/EXcp/Trap
- *   Normally CPU does this automatically, however when doing FAKE rtie,
- *   we need to explicitly do this. The problem in macros
- *   FAKE_RET_FROM_EXCPN and FAKE_RET_FROM_EXCPN_LOCK_IRQ was that this bit
- *   was being "CLEARED" rather then "SET". Since it is Loop INHIBIT Bit,
- *   setting it and not clearing it clears ZOL context
- *
- * Vineetg: May 16th, 2008
- *  - r25 now contains the Current Task when in kernel
- *
- * Vineetg: Dec 22, 2007
- *    Minor Surgery of Low Level ISR to make it SMP safe
- *    - MMU_SCRATCH0 Reg used for freeing up r9 in Level 1 ISR
- *    - _current_task is made an array of NR_CPUS
- *    - Access of _current_task wrapped inside a macro so that if hardware
- *       team agrees for a dedicated reg, no other code is touched
- *
- * Amit Bhor, Rahul Trivedi, Kanika Nema, Sameer Dhavale : Codito Tech 2004
  */
 
 /*------------------------------------------------------------------
  *  Global Pointer (gp)                 r26
  *  Frame Pointer (fp)                  r27
  *  Stack Pointer (sp)                  r28
- *  Interrupt link register (ilink1)    r29
- *  Interrupt link register (ilink2)    r30
  *  Branch link register (blink)        r31
  *------------------------------------------------------------------
  */
 
-       .cpu A7
-
-;############################ Vector Table #################################
-
-.macro VECTOR  lbl
-#if 1   /* Just in case, build breaks */
-       j   \lbl
-#else
-       b   \lbl
-       nop
-#endif
-.endm
-
-       .section .vector, "ax",@progbits
-       .align 4
-
-/* Each entry in the vector table must occupy 2 words. Since it is a jump
- * across sections (.vector to .text) we are gauranteed that 'j somewhere'
- * will use the 'j limm' form of the intrsuction as long as somewhere is in
- * a section other than .vector.
- */
-
-; ********* Critical System Events **********************
-VECTOR   res_service             ; 0x0, Restart Vector  (0x0)
-VECTOR   mem_service             ; 0x8, Mem exception   (0x1)
-VECTOR   instr_service           ; 0x10, Instrn Error   (0x2)
-
-; ******************** Device ISRs **********************
-#ifdef CONFIG_ARC_IRQ3_LV2
-VECTOR   handle_interrupt_level2
-#else
-VECTOR   handle_interrupt_level1
-#endif
-
-VECTOR   handle_interrupt_level1
-
-#ifdef CONFIG_ARC_IRQ5_LV2
-VECTOR   handle_interrupt_level2
-#else
-VECTOR   handle_interrupt_level1
-#endif
-
-#ifdef CONFIG_ARC_IRQ6_LV2
-VECTOR   handle_interrupt_level2
-#else
-VECTOR   handle_interrupt_level1
-#endif
-
-.rept   25
-VECTOR   handle_interrupt_level1 ; Other devices
-.endr
-
-/* FOR ARC600: timer = 0x3, uart = 0x8, emac = 0x10 */
-
-; ******************** Exceptions **********************
-VECTOR   EV_MachineCheck         ; 0x100, Fatal Machine check   (0x20)
-VECTOR   EV_TLBMissI             ; 0x108, Intruction TLB miss   (0x21)
-VECTOR   EV_TLBMissD             ; 0x110, Data TLB miss         (0x22)
-VECTOR   EV_TLBProtV             ; 0x118, Protection Violation  (0x23)
-                                ;         or Misaligned Access
-VECTOR   EV_PrivilegeV           ; 0x120, Privilege Violation   (0x24)
-VECTOR   EV_Trap                 ; 0x128, Trap exception        (0x25)
-VECTOR   EV_Extension            ; 0x130, Extn Intruction Excp  (0x26)
-
-.rept   24
-VECTOR   reserved                ; Reserved Exceptions
-.endr
-
-#include <linux/linkage.h>   /* {EXTRY,EXIT} */
-#include <asm/entry.h>       /* SAVE_ALL_{INT1,INT2,SYS...} */
-#include <asm/errno.h>
-#include <asm/arcregs.h>
-#include <asm/irqflags.h>
-
-;##################### Scratch Mem for IRQ stack switching #############
-
-ARCFP_DATA int1_saved_reg
-       .align 32
-       .type   int1_saved_reg, @object
-       .size   int1_saved_reg, 4
-int1_saved_reg:
-       .zero 4
-
-/* Each Interrupt level needs its own scratch */
-#ifdef CONFIG_ARC_COMPACT_IRQ_LEVELS
-
-ARCFP_DATA int2_saved_reg
-       .type   int2_saved_reg, @object
-       .size   int2_saved_reg, 4
-int2_saved_reg:
-       .zero 4
-
-#endif
-
-; ---------------------------------------------
-       .section .text, "ax",@progbits
-
-res_service:           ; processor restart
-       flag    0x1     ; not implemented
-       nop
-       nop
-
-reserved:              ; processor restart
-       rtie            ; jump to processor initializations
-
-;##################### Interrupt Handling ##############################
-
-#ifdef CONFIG_ARC_COMPACT_IRQ_LEVELS
-; ---------------------------------------------
-;  Level 2 ISR: Can interrupt a Level 1 ISR
-; ---------------------------------------------
-ENTRY(handle_interrupt_level2)
+;################### Special Sys Call Wrappers ##########################
 
-       ; TODO-vineetg for SMP this wont work
-       ; free up r9 as scratchpad
-       st  r9, [@int2_saved_reg]
+ENTRY(sys_clone_wrapper)
+       SAVE_CALLEE_SAVED_USER
+       bl  @sys_clone
+       DISCARD_CALLEE_SAVED_USER
 
-       ;Which mode (user/kernel) was the system in when intr occured
-       lr  r9, [status32_l2]
+       GET_CURR_THR_INFO_FLAGS   r10
+       btst r10, TIF_SYSCALL_TRACE
+       bnz  tracesys_exit
 
-       SWITCH_TO_KERNEL_STK
-       SAVE_ALL_INT2
+       b ret_from_system_call
+END(sys_clone_wrapper)
 
-       ;------------------------------------------------------
-       ; if L2 IRQ interrupted a L1 ISR, disable preemption
-       ;------------------------------------------------------
+ENTRY(ret_from_fork)
+       ; when the forked child comes here from the __switch_to function
+       ; r0 has the last task pointer.
+       ; put last task in scheduler queue
+       bl   @schedule_tail
 
-       ld r9, [sp, PT_status32]        ; get statu32_l2 (saved in pt_regs)
-       bbit0 r9, STATUS_A1_BIT, 1f     ; L1 not active when L2 IRQ, so normal
+       ld   r9, [sp, PT_status32]
+       brne r9, 0, 1f
 
-       ; A1 is set in status32_l2
-       ; bump thread_info->preempt_count (Disable preemption)
-       GET_CURR_THR_INFO_FROM_SP   r10
-       ld      r9, [r10, THREAD_INFO_PREEMPT_COUNT]
-       add     r9, r9, 1
-       st      r9, [r10, THREAD_INFO_PREEMPT_COUNT]
+       jl.d [r14]              ; kernel thread entry point
+       mov  r0, r13            ; (see PF_KTHREAD block in copy_thread)
 
 1:
-       ;------------------------------------------------------
-       ; setup params for Linux common ISR and invoke it
-       ;------------------------------------------------------
-       lr  r0, [icause2]
-       and r0, r0, 0x1f
-
-       bl.d  @arch_do_IRQ
-       mov r1, sp
-
-       mov r8,0x2
-       sr r8, [AUX_IRQ_LV12]       ; clear bit in Sticky Status Reg
-
-       b   ret_from_exception
-
-END(handle_interrupt_level2)
-
-#endif
-
-; ---------------------------------------------
-;  Level 1 ISR
-; ---------------------------------------------
-ENTRY(handle_interrupt_level1)
-
-       /* free up r9 as scratchpad */
-#ifdef CONFIG_SMP
-       sr  r9, [ARC_REG_SCRATCH_DATA0]
-#else
-       st   r9, [@int1_saved_reg]
-#endif
-
-       ;Which mode (user/kernel) was the system in when intr occured
-       lr  r9, [status32_l1]
-
-       SWITCH_TO_KERNEL_STK
-       SAVE_ALL_INT1
+       ; Return to user space
+       ; 1. Any forked task (Reach here via BRne above)
+       ; 2. First ever init task (Reach here via return from JL above)
+       ;    This is the historic "kernel_execve" use-case, to return to init
+       ;    user mode, in a round about way since that is always done from
+       ;    a kernel thread which is executed via JL above but always returns
+       ;    out whenever kernel_execve (now inline do_fork()) is involved
+       b    ret_from_exception
+END(ret_from_fork)
 
-       lr  r0, [icause1]
-       and r0, r0, 0x1f
+#ifdef CONFIG_ARC_DW2_UNWIND
+; Workaround for bug 94179 (STAR ):
+; Despite -fasynchronous-unwind-tables, linker is not making dwarf2 unwinder
+; section (.debug_frame) as loadable. So we force it here.
+; This also fixes STAR 9000487933 where the prev-workaround (objcopy --setflag)
+; would not work after a clean build due to kernel build system dependencies.
+.section .debug_frame, "wa",@progbits
 
-#ifdef CONFIG_TRACE_IRQFLAGS
-       ; icause1 needs to be read early, before calling tracing, which
-       ; can clobber scratch regs, hence use of stack to stash it
-       push r0
-       TRACE_ASM_IRQ_DISABLE
-       pop  r0
+; Reset to .text as this file is included in entry-<isa>.S
+.section .text, "ax",@progbits
 #endif
 
-       bl.d  @arch_do_IRQ
-       mov r1, sp
-
-       mov r8,0x1
-       sr r8, [AUX_IRQ_LV12]       ; clear bit in Sticky Status Reg
-
-       b   ret_from_exception
-END(handle_interrupt_level1)
-
 ;################### Non TLB Exception Handling #############################
 
 ; ---------------------------------------------
@@ -280,7 +86,7 @@ ENTRY(instr_service)
        lr  r0, [efa]
        mov r1, sp
 
-       FAKE_RET_FROM_EXCPN r9
+       FAKE_RET_FROM_EXCPN
 
        bl  do_insterror_or_kprobe
        b   ret_from_exception
@@ -297,7 +103,7 @@ ENTRY(mem_service)
        lr  r0, [efa]
        mov r1, sp
 
-       FAKE_RET_FROM_EXCPN r9
+       FAKE_RET_FROM_EXCPN
 
        bl  do_memory_error
        b   ret_from_exception
@@ -333,60 +139,6 @@ ENTRY(EV_MachineCheck)
 
 END(EV_MachineCheck)
 
-; ---------------------------------------------
-; Protection Violation Exception Handler
-; ---------------------------------------------
-
-ENTRY(EV_TLBProtV)
-
-       EXCEPTION_PROLOGUE
-
-       ;---------(3) Save some more regs-----------------
-       ;  vineetg: Mar 6th: Random Seg Fault issue #1
-       ;  ecr and efa were not saved in case an Intr sneaks in
-       ;  after fake rtie
-
-       lr  r2, [ecr]
-       lr  r0, [efa]   ; Faulting Data address
-
-       ; --------(4) Return from CPU Exception Mode ---------
-       ;  Fake a rtie, but rtie to next label
-       ;  That way, subsequently, do_page_fault ( ) executes in pure kernel
-       ;  mode with further Exceptions enabled
-
-       FAKE_RET_FROM_EXCPN r9
-
-       mov   r1, sp
-
-       ;------ (5) Type of Protection Violation? ----------
-       ;
-       ; ProtV Hardware Exception is triggered for Access Faults of 2 types
-       ;   -Access Violaton    : 00_23_(00|01|02|03)_00
-       ;                                x  r  w  r+w
-       ;   -Unaligned Access   : 00_23_04_00
-       ;
-       bbit1 r2, ECR_C_BIT_PROTV_MISALIG_DATA, 4f
-
-       ;========= (6a) Access Violation Processing ========
-       bl  do_page_fault
-       b   ret_from_exception
-
-       ;========== (6b) Non aligned access ============
-4:
-
-       SAVE_CALLEE_SAVED_USER
-       mov r2, sp              ; callee_regs
-
-       bl  do_misaligned_access
-
-       ; TBD: optimize - do this only if a callee reg was involved
-       ; either a dst of emulated LD/ST or src with address-writeback
-       RESTORE_CALLEE_SAVED_USER
-
-       b   ret_from_exception
-
-END(EV_TLBProtV)
-
 ; ---------------------------------------------
 ; Privilege Violation Exception Handler
 ; ---------------------------------------------
@@ -397,7 +149,7 @@ ENTRY(EV_PrivilegeV)
        lr  r0, [efa]
        mov r1, sp
 
-       FAKE_RET_FROM_EXCPN r9
+       FAKE_RET_FROM_EXCPN
 
        bl  do_privilege_fault
        b   ret_from_exception
@@ -413,14 +165,17 @@ ENTRY(EV_Extension)
        lr  r0, [efa]
        mov r1, sp
 
-       FAKE_RET_FROM_EXCPN r9
+       FAKE_RET_FROM_EXCPN
 
        bl  do_extension_fault
        b   ret_from_exception
 END(EV_Extension)
 
-;######################### System Call Tracing #########################
+;################ Trap Handling (Syscall, Breakpoint) ##################
 
+; ---------------------------------------------
+; syscall Tracing
+; ---------------------------------------------
 tracesys:
        ; save EFA in case tracer wants the PC of traced task
        ; using ERET won't work since next-PC has already committed
@@ -463,10 +218,9 @@ tracesys_exit:
        b   ret_from_exception ; NOT ret_from_system_call at is saves r0 which
        ; we'd done before calling post hook above
 
-;################### Break Point TRAP ##########################
-
-       ; ======= (5b) Trap is due to Break-Point =========
-
+; ---------------------------------------------
+; Breakpoint TRAP
+; ---------------------------------------------
 trap_with_param:
 
        ; stop_pc info by gdb needs this info
@@ -475,7 +229,7 @@ trap_with_param:
 
        ; Now that we have read EFA, it is safe to do "fake" rtie
        ;   and get out of CPU exception mode
-       FAKE_RET_FROM_EXCPN r11
+       FAKE_RET_FROM_EXCPN
 
        ; Save callee regs in case gdb wants to have a look
        ; SP will grow up by size of CALLEE Reg-File
@@ -494,37 +248,33 @@ trap_with_param:
 
        b   ret_from_exception
 
-;##################### Trap Handling ##############################
-;
-; EV_Trap caused by TRAP_S and TRAP0 instructions.
-;------------------------------------------------------------------
-;   (1) System Calls
-;       :parameters in r0-r7.
-;       :r8 has the system call number
-;   (2) Break Points
-;------------------------------------------------------------------
+; ---------------------------------------------
+; syscall TRAP
+; ABI: (r0-r7) upto 8 args, (r8) syscall number
+; ---------------------------------------------
 
 ENTRY(EV_Trap)
 
        EXCEPTION_PROLOGUE
 
-       ;------- (4) What caused the Trap --------------
-       lr     r12, [ecr]
-       bmsk.f 0, r12, 7
+       ;============ TRAP 1   :breakpoints
+       ; Check ECR for trap with arg (PROLOGUE ensures r9 has ECR)
+       bmsk.f 0, r9, 7
        bnz    trap_with_param
 
-       ; ======= (5a) Trap is due to System Call ========
+       ;============ TRAP  (no param): syscall top level
 
-       ; Before doing anything, return from CPU Exception Mode
-       FAKE_RET_FROM_EXCPN r11
+       ; First return from Exception to pure K mode (Exception/IRQs renabled)
+       FAKE_RET_FROM_EXCPN
 
-       ; If syscall tracing ongoing, invoke pre-pos-hooks
+       ; If syscall tracing ongoing, invoke pre-post-hooks
        GET_CURR_THR_INFO_FLAGS   r10
        btst r10, TIF_SYSCALL_TRACE
        bnz tracesys  ; this never comes back
 
-       ;============ This is normal System Call case ==========
-       ; Sys-call num shd not exceed the total system calls avail
+       ;============ Normal syscall case
+
+       ; syscall num shd not exceed the total system calls avail
        cmp     r8,  NR_syscalls
        mov.hi  r0, -ENOSYS
        bhi     ret_from_system_call
@@ -565,7 +315,7 @@ resume_user_mode_begin:
        ; Fast Path return to user mode if no pending work
        GET_CURR_THR_INFO_FLAGS   r9
        and.f  0,  r9, _TIF_WORK_MASK
-       bz     restore_regs
+       bz     .Lrestore_regs
 
        ; --- (Slow Path #1) task preemption ---
        bbit0  r9, TIF_NEED_RESCHED, .Lchk_pend_signals
@@ -624,11 +374,11 @@ resume_kernel_mode:
        ; Can't preempt if preemption disabled
        GET_CURR_THR_INFO_FROM_SP   r10
        ld  r8, [r10, THREAD_INFO_PREEMPT_COUNT]
-       brne  r8, 0, restore_regs
+       brne  r8, 0, .Lrestore_regs
 
        ; check if this task's NEED_RESCHED flag set
        ld  r9, [r10, THREAD_INFO_FLAGS]
-       bbit0  r9, TIF_NEED_RESCHED, restore_regs
+       bbit0  r9, TIF_NEED_RESCHED, .Lrestore_regs
 
        ; Invoke PREEMPTION
        bl      preempt_schedule_irq
@@ -636,142 +386,7 @@ resume_kernel_mode:
        ; preempt_schedule_irq() always returns with IRQ disabled
 #endif
 
-       ; fall through
-
-;############# Return from Intr/Excp/Trap (ARC Specifics) ##############
-;
-; Restore the saved sys context (common exit-path for EXCPN/IRQ/Trap)
-; IRQ shd definitely not happen between now and rtie
-; All 2 entry points to here already disable interrupts
-
-restore_regs :
-
-       TRACE_ASM_IRQ_ENABLE
-
-       lr      r10, [status32]
-
-       ; Restore REG File. In case multiple Events outstanding,
-       ; use the same priorty as rtie: EXCPN, L2 IRQ, L1 IRQ, None
-       ; Note that we use realtime STATUS32 (not pt_regs->status32) to
-       ; decide that.
-
-       ; if Returning from Exception
-       bbit0  r10, STATUS_AE_BIT, not_exception
-       RESTORE_ALL_SYS
-       rtie
-
-       ; Not Exception so maybe Interrupts (Level 1 or 2)
-
-not_exception:
-
-#ifdef CONFIG_ARC_COMPACT_IRQ_LEVELS
-
-       ; Level 2 interrupt return Path - from hardware standpoint
-       bbit0  r10, STATUS_A2_BIT, not_level2_interrupt
-
-       ;------------------------------------------------------------------
-       ; However the context returning might not have taken L2 intr itself
-       ; e.g. Task'A' user-code -> L2 intr -> schedule -> 'B' user-code ret
-       ; Special considerations needed for the context which took L2 intr
-
-       ld   r9, [sp, PT_event]        ; Ensure this is L2 intr context
-       brne r9, event_IRQ2, 149f
-
-       ;------------------------------------------------------------------
-       ; if L2 IRQ interrupted an L1 ISR,  we'd disabled preemption earlier
-       ; so that sched doesn't move to new task, causing L1 to be delayed
-       ; undeterministically. Now that we've achieved that, let's reset
-       ; things to what they were, before returning from L2 context
-       ;----------------------------------------------------------------
-
-       ld r9, [sp, PT_status32]       ; get statu32_l2 (saved in pt_regs)
-       bbit0 r9, STATUS_A1_BIT, 149f  ; L1 not active when L2 IRQ, so normal
-
-       ; decrement thread_info->preempt_count (re-enable preemption)
-       GET_CURR_THR_INFO_FROM_SP   r10
-       ld      r9, [r10, THREAD_INFO_PREEMPT_COUNT]
-
-       ; paranoid check, given A1 was active when A2 happened, preempt count
-       ; must not be 0 because we would have incremented it.
-       ; If this does happen we simply HALT as it means a BUG !!!
-       cmp     r9, 0
-       bnz     2f
-       flag 1
-
-2:
-       sub     r9, r9, 1
-       st      r9, [r10, THREAD_INFO_PREEMPT_COUNT]
-
-149:
-       ;return from level 2
-       RESTORE_ALL_INT2
-debug_marker_l2:
-       rtie
-
-not_level2_interrupt:
-
-#endif
-
-       bbit0  r10, STATUS_A1_BIT, not_level1_interrupt
+       b       .Lrestore_regs
 
-       ;return from level 1
+##### DONT ADD CODE HERE - .Lrestore_regs actually follows in entry-<isa>.S
 
-       RESTORE_ALL_INT1
-debug_marker_l1:
-       rtie
-
-not_level1_interrupt:
-
-       ;this case is for syscalls or Exceptions (with fake rtie)
-
-       RESTORE_ALL_SYS
-debug_marker_syscall:
-       rtie
-
-END(ret_from_exception)
-
-ENTRY(ret_from_fork)
-       ; when the forked child comes here from the __switch_to function
-       ; r0 has the last task pointer.
-       ; put last task in scheduler queue
-       bl   @schedule_tail
-
-       ld   r9, [sp, PT_status32]
-       brne r9, 0, 1f
-
-       jl.d [r14]              ; kernel thread entry point
-       mov  r0, r13            ; (see PF_KTHREAD block in copy_thread)
-
-1:
-       ; Return to user space
-       ; 1. Any forked task (Reach here via BRne above)
-       ; 2. First ever init task (Reach here via return from JL above)
-       ;    This is the historic "kernel_execve" use-case, to return to init
-       ;    user mode, in a round about way since that is always done from
-       ;    a kernel thread which is executed via JL above but always returns
-       ;    out whenever kernel_execve (now inline do_fork()) is involved
-       b    ret_from_exception
-END(ret_from_fork)
-
-;################### Special Sys Call Wrappers ##########################
-
-ENTRY(sys_clone_wrapper)
-       SAVE_CALLEE_SAVED_USER
-       bl  @sys_clone
-       DISCARD_CALLEE_SAVED_USER
-
-       GET_CURR_THR_INFO_FLAGS   r10
-       btst r10, TIF_SYSCALL_TRACE
-       bnz  tracesys_exit
-
-       b ret_from_system_call
-END(sys_clone_wrapper)
-
-#ifdef CONFIG_ARC_DW2_UNWIND
-; Workaround for bug 94179 (STAR ):
-; Despite -fasynchronous-unwind-tables, linker is not making dwarf2 unwinder
-; section (.debug_frame) as loadable. So we force it here.
-; This also fixes STAR 9000487933 where the prev-workaround (objcopy --setflag)
-; would not work after a clean build due to kernel build system dependencies.
-.section .debug_frame, "wa",@progbits
-#endif
index b0e8666fdccc755ac11763a3bf0b6594f4ed628a..812f95e6ae6946d56550cbd80a0baaa8a6e94cc0 100644 (file)
@@ -49,8 +49,6 @@
 1:
 .endm
 
-       .cpu A7
-
        .section .init.text, "ax",@progbits
        .type stext, @function
        .globl stext
@@ -83,6 +81,7 @@ stext:
        st.ab   0, [r5, 4]
 1:
 
+#ifdef CONFIG_ARC_UBOOT_SUPPORT
        ; Uboot - kernel ABI
        ;    r0 = [0] No uboot interaction, [1] cmdline in r2, [2] DTB in r2
        ;    r1 = magic number (board identity, unused as of now
@@ -90,6 +89,7 @@ stext:
        ; These are handled later in setup_arch()
        st      r0, [@uboot_tag]
        st      r2, [@uboot_arg]
+#endif
 
        ; setup "current" tsk and optionally cache it in dedicated r25
        mov     r9, @init_task
diff --git a/arch/arc/kernel/intc-arcv2.c b/arch/arc/kernel/intc-arcv2.c
new file mode 100644 (file)
index 0000000..6208c63
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2014 Synopsys, Inc. (www.synopsys.com)
+ *
+ * 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/interrupt.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/irqdomain.h>
+#include <linux/irqchip.h>
+#include "../../drivers/irqchip/irqchip.h"
+#include <asm/irq.h>
+
+/*
+ * Early Hardware specific Interrupt setup
+ * -Called very early (start_kernel -> setup_arch -> setup_processor)
+ * -Platform Independent (must for any ARC Core)
+ * -Needed for each CPU (hence not foldable into init_IRQ)
+ */
+void arc_init_IRQ(void)
+{
+       unsigned int tmp;
+
+       struct aux_irq_ctrl {
+#ifdef CONFIG_CPU_BIG_ENDIAN
+               unsigned int res3:18, save_idx_regs:1, res2:1,
+                            save_u_to_u:1, save_lp_regs:1, save_blink:1,
+                            res:4, save_nr_gpr_pairs:5;
+#else
+               unsigned int save_nr_gpr_pairs:5, res:4,
+                            save_blink:1, save_lp_regs:1, save_u_to_u:1,
+                            res2:1, save_idx_regs:1, res3:18;
+#endif
+       } ictrl;
+
+       *(unsigned int *)&ictrl = 0;
+
+       ictrl.save_nr_gpr_pairs = 6;    /* r0 to r11 (r12 saved manually) */
+       ictrl.save_blink = 1;
+       ictrl.save_lp_regs = 1;         /* LP_COUNT, LP_START, LP_END */
+       ictrl.save_u_to_u = 0;          /* user ctxt saved on kernel stack */
+       ictrl.save_idx_regs = 1;        /* JLI, LDI, EI */
+
+       WRITE_AUX(AUX_IRQ_CTRL, ictrl);
+
+       /* setup status32, don't enable intr yet as kernel doesn't want */
+       tmp = read_aux_reg(0xa);
+       tmp |= ISA_INIT_STATUS_BITS;
+       tmp &= ~STATUS_IE_MASK;
+       asm volatile("flag %0   \n"::"r"(tmp));
+
+       /*
+        * ARCv2 core intc provides multiple interrupt priorities (upto 16).
+        * Typical builds though have only two levels (0-high, 1-low)
+        * Linux by default uses lower prio 1 for most irqs, reserving 0 for
+        * NMI style interrupts in future (say perf)
+        *
+        * Read the intc BCR to confirm that Linux default priority is avail
+        * in h/w
+        *
+        * Note:
+        *  IRQ_BCR[27..24] contains N-1 (for N priority levels) and prio level
+        *  is 0 based.
+        */
+       tmp = (read_aux_reg(ARC_REG_IRQ_BCR) >> 24 ) & 0xF;
+       if (ARCV2_IRQ_DEF_PRIO > tmp)
+               panic("Linux default irq prio incorrect\n");
+}
+
+static void arcv2_irq_mask(struct irq_data *data)
+{
+       write_aux_reg(AUX_IRQ_SELECT, data->irq);
+       write_aux_reg(AUX_IRQ_ENABLE, 0);
+}
+
+static void arcv2_irq_unmask(struct irq_data *data)
+{
+       write_aux_reg(AUX_IRQ_SELECT, data->irq);
+       write_aux_reg(AUX_IRQ_ENABLE, 1);
+}
+
+void arcv2_irq_enable(struct irq_data *data)
+{
+       /* set default priority */
+       write_aux_reg(AUX_IRQ_SELECT, data->irq);
+       write_aux_reg(AUX_IRQ_PRIORITY, ARCV2_IRQ_DEF_PRIO);
+
+       /*
+        * hw auto enables (linux unmask) all by default
+        * So no need to do IRQ_ENABLE here
+        * XXX: However OSCI LAN need it
+        */
+       write_aux_reg(AUX_IRQ_ENABLE, 1);
+}
+
+static struct irq_chip arcv2_irq_chip = {
+       .name           = "ARCv2 core Intc",
+       .irq_mask       = arcv2_irq_mask,
+       .irq_unmask     = arcv2_irq_unmask,
+       .irq_enable     = arcv2_irq_enable
+};
+
+static int arcv2_irq_map(struct irq_domain *d, unsigned int irq,
+                        irq_hw_number_t hw)
+{
+       if (irq == TIMER0_IRQ || irq == IPI_IRQ)
+               irq_set_chip_and_handler(irq, &arcv2_irq_chip, handle_percpu_irq);
+       else
+               irq_set_chip_and_handler(irq, &arcv2_irq_chip, handle_level_irq);
+
+       return 0;
+}
+
+static const struct irq_domain_ops arcv2_irq_ops = {
+       .xlate = irq_domain_xlate_onecell,
+       .map = arcv2_irq_map,
+};
+
+static struct irq_domain *root_domain;
+
+static int __init
+init_onchip_IRQ(struct device_node *intc, struct device_node *parent)
+{
+       if (parent)
+               panic("DeviceTree incore intc not a root irq controller\n");
+
+       root_domain = irq_domain_add_legacy(intc, NR_CPU_IRQS, 0, 0,
+                                           &arcv2_irq_ops, NULL);
+
+       if (!root_domain)
+               panic("root irq domain not avail\n");
+
+       /* with this we don't need to export root_domain */
+       irq_set_default_host(root_domain);
+
+       return 0;
+}
+
+IRQCHIP_DECLARE(arc_intc, "snps,archs-intc", init_onchip_IRQ);
diff --git a/arch/arc/kernel/intc-compact.c b/arch/arc/kernel/intc-compact.c
new file mode 100644 (file)
index 0000000..fcdddb6
--- /dev/null
@@ -0,0 +1,226 @@
+/*
+ * Copyright (C) 2011-12 Synopsys, Inc. (www.synopsys.com)
+ *
+ * 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/interrupt.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/irqdomain.h>
+#include <linux/irqchip.h>
+#include "../../drivers/irqchip/irqchip.h"
+#include <asm/irq.h>
+
+/*
+ * Early Hardware specific Interrupt setup
+ * -Platform independent, needed for each CPU (not foldable into init_IRQ)
+ * -Called very early (start_kernel -> setup_arch -> setup_processor)
+ *
+ * what it does ?
+ * -Optionally, setup the High priority Interrupts as Level 2 IRQs
+ */
+void arc_init_IRQ(void)
+{
+       int level_mask = 0;
+
+       /* setup any high priority Interrupts (Level2 in ARCompact jargon) */
+       level_mask |= IS_ENABLED(CONFIG_ARC_IRQ3_LV2) << 3;
+       level_mask |= IS_ENABLED(CONFIG_ARC_IRQ5_LV2) << 5;
+       level_mask |= IS_ENABLED(CONFIG_ARC_IRQ6_LV2) << 6;
+
+       /*
+        * Write to register, even if no LV2 IRQs configured to reset it
+        * in case bootloader had mucked with it
+        */
+       write_aux_reg(AUX_IRQ_LEV, level_mask);
+
+       if (level_mask)
+               pr_info("Level-2 interrupts bitset %x\n", level_mask);
+}
+
+/*
+ * ARC700 core includes a simple on-chip intc supporting
+ * -per IRQ enable/disable
+ * -2 levels of interrupts (high/low)
+ * -all interrupts being level triggered
+ *
+ * To reduce platform code, we assume all IRQs directly hooked-up into intc.
+ * Platforms with external intc, hence cascaded IRQs, are free to over-ride
+ * below, per IRQ.
+ */
+
+static void arc_irq_mask(struct irq_data *data)
+{
+       unsigned int ienb;
+
+       ienb = read_aux_reg(AUX_IENABLE);
+       ienb &= ~(1 << data->irq);
+       write_aux_reg(AUX_IENABLE, ienb);
+}
+
+static void arc_irq_unmask(struct irq_data *data)
+{
+       unsigned int ienb;
+
+       ienb = read_aux_reg(AUX_IENABLE);
+       ienb |= (1 << data->irq);
+       write_aux_reg(AUX_IENABLE, ienb);
+}
+
+static struct irq_chip onchip_intc = {
+       .name           = "ARC In-core Intc",
+       .irq_mask       = arc_irq_mask,
+       .irq_unmask     = arc_irq_unmask,
+};
+
+static int arc_intc_domain_map(struct irq_domain *d, unsigned int irq,
+                              irq_hw_number_t hw)
+{
+       /*
+        * XXX: the IPI IRQ needs to be handled like TIMER too. However ARC core
+        *      code doesn't own it (like TIMER0). ISS IDU / ezchip define it
+        *      in platform header which can't be included here as it goes
+        *      against multi-platform image philisophy
+        */
+       if (irq == TIMER0_IRQ)
+               irq_set_chip_and_handler(irq, &onchip_intc, handle_percpu_irq);
+       else
+               irq_set_chip_and_handler(irq, &onchip_intc, handle_level_irq);
+
+       return 0;
+}
+
+static const struct irq_domain_ops arc_intc_domain_ops = {
+       .xlate = irq_domain_xlate_onecell,
+       .map = arc_intc_domain_map,
+};
+
+static struct irq_domain *root_domain;
+
+static int __init
+init_onchip_IRQ(struct device_node *intc, struct device_node *parent)
+{
+       if (parent)
+               panic("DeviceTree incore intc not a root irq controller\n");
+
+       root_domain = irq_domain_add_legacy(intc, NR_CPU_IRQS, 0, 0,
+                                           &arc_intc_domain_ops, NULL);
+
+       if (!root_domain)
+               panic("root irq domain not avail\n");
+
+       /* with this we don't need to export root_domain */
+       irq_set_default_host(root_domain);
+
+       return 0;
+}
+
+IRQCHIP_DECLARE(arc_intc, "snps,arc700-intc", init_onchip_IRQ);
+
+/*
+ * arch_local_irq_enable - Enable interrupts.
+ *
+ * 1. Explicitly called to re-enable interrupts
+ * 2. Implicitly called from spin_unlock_irq, write_unlock_irq etc
+ *    which maybe in hard ISR itself
+ *
+ * Semantics of this function change depending on where it is called from:
+ *
+ * -If called from hard-ISR, it must not invert interrupt priorities
+ *  e.g. suppose TIMER is high priority (Level 2) IRQ
+ *    Time hard-ISR, timer_interrupt( ) calls spin_unlock_irq several times.
+ *    Here local_irq_enable( ) shd not re-enable lower priority interrupts
+ * -If called from soft-ISR, it must re-enable all interrupts
+ *    soft ISR are low prioity jobs which can be very slow, thus all IRQs
+ *    must be enabled while they run.
+ *    Now hardware context wise we may still be in L2 ISR (not done rtie)
+ *    still we must re-enable both L1 and L2 IRQs
+ *  Another twist is prev scenario with flow being
+ *     L1 ISR ==> interrupted by L2 ISR  ==> L2 soft ISR
+ *     here we must not re-enable Ll as prev Ll Interrupt's h/w context will get
+ *     over-written (this is deficiency in ARC700 Interrupt mechanism)
+ */
+
+#ifdef CONFIG_ARC_COMPACT_IRQ_LEVELS   /* Complex version for 2 IRQ levels */
+
+void arch_local_irq_enable(void)
+{
+
+       unsigned long flags = arch_local_save_flags();
+
+       /* Allow both L1 and L2 at the onset */
+       flags |= (STATUS_E1_MASK | STATUS_E2_MASK);
+
+       /* Called from hard ISR (between irq_enter and irq_exit) */
+       if (in_irq()) {
+
+               /* If in L2 ISR, don't re-enable any further IRQs as this can
+                * cause IRQ priorities to get upside down. e.g. it could allow
+                * L1 be taken while in L2 hard ISR which is wrong not only in
+                * theory, it can also cause the dreaded L1-L2-L1 scenario
+                */
+               if (flags & STATUS_A2_MASK)
+                       flags &= ~(STATUS_E1_MASK | STATUS_E2_MASK);
+
+               /* Even if in L1 ISR, allowe Higher prio L2 IRQs */
+               else if (flags & STATUS_A1_MASK)
+                       flags &= ~(STATUS_E1_MASK);
+       }
+
+       /* called from soft IRQ, ideally we want to re-enable all levels */
+
+       else if (in_softirq()) {
+
+               /* However if this is case of L1 interrupted by L2,
+                * re-enabling both may cause whaco L1-L2-L1 scenario
+                * because ARC700 allows level 1 to interrupt an active L2 ISR
+                * Thus we disable both
+                * However some code, executing in soft ISR wants some IRQs
+                * to be enabled so we re-enable L2 only
+                *
+                * How do we determine L1 intr by L2
+                *  -A2 is set (means in L2 ISR)
+                *  -E1 is set in this ISR's pt_regs->status32 which is
+                *      saved copy of status32_l2 when l2 ISR happened
+                */
+               struct pt_regs *pt = get_irq_regs();
+
+               if ((flags & STATUS_A2_MASK) && pt &&
+                   (pt->status32 & STATUS_A1_MASK)) {
+                       /*flags &= ~(STATUS_E1_MASK | STATUS_E2_MASK); */
+                       flags &= ~(STATUS_E1_MASK);
+               }
+       }
+
+       arch_local_irq_restore(flags);
+}
+
+#else /* ! CONFIG_ARC_COMPACT_IRQ_LEVELS */
+
+/*
+ * Simpler version for only 1 level of interrupt
+ * Here we only Worry about Level 1 Bits
+ */
+void arch_local_irq_enable(void)
+{
+       unsigned long flags;
+
+       /*
+        * ARC IDE Drivers tries to re-enable interrupts from hard-isr
+        * context which is simply wrong
+        */
+       if (in_irq()) {
+               WARN_ONCE(1, "IRQ enabled from hard-isr");
+               return;
+       }
+
+       flags = arch_local_save_flags();
+       flags |= (STATUS_E1_MASK | STATUS_E2_MASK);
+       arch_local_irq_restore(flags);
+}
+#endif
+EXPORT_SYMBOL(arch_local_irq_enable);
index 620ec2fe32a94f855c6e3db0a04fa25c41d5d1c2..2989a7bcf8a863709734d7f5343bb16c789089f2 100644 (file)
@@ -8,115 +8,9 @@
  */
 
 #include <linux/interrupt.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/irqdomain.h>
 #include <linux/irqchip.h>
-#include "../../drivers/irqchip/irqchip.h"
-#include <asm/sections.h>
-#include <asm/irq.h>
 #include <asm/mach_desc.h>
 
-/*
- * Early Hardware specific Interrupt setup
- * -Platform independent, needed for each CPU (not foldable into init_IRQ)
- * -Called very early (start_kernel -> setup_arch -> setup_processor)
- *
- * what it does ?
- * -Optionally, setup the High priority Interrupts as Level 2 IRQs
- */
-void arc_init_IRQ(void)
-{
-       int level_mask = 0;
-
-       /* setup any high priority Interrupts (Level2 in ARCompact jargon) */
-       level_mask |= IS_ENABLED(CONFIG_ARC_IRQ3_LV2) << 3;
-       level_mask |= IS_ENABLED(CONFIG_ARC_IRQ5_LV2) << 5;
-       level_mask |= IS_ENABLED(CONFIG_ARC_IRQ6_LV2) << 6;
-
-       /*
-        * Write to register, even if no LV2 IRQs configured to reset it
-        * in case bootloader had mucked with it
-        */
-       write_aux_reg(AUX_IRQ_LEV, level_mask);
-
-       if (level_mask)
-               pr_info("Level-2 interrupts bitset %x\n", level_mask);
-}
-
-/*
- * ARC700 core includes a simple on-chip intc supporting
- * -per IRQ enable/disable
- * -2 levels of interrupts (high/low)
- * -all interrupts being level triggered
- *
- * To reduce platform code, we assume all IRQs directly hooked-up into intc.
- * Platforms with external intc, hence cascaded IRQs, are free to over-ride
- * below, per IRQ.
- */
-
-static void arc_irq_mask(struct irq_data *data)
-{
-       unsigned int ienb;
-
-       ienb = read_aux_reg(AUX_IENABLE);
-       ienb &= ~(1 << data->irq);
-       write_aux_reg(AUX_IENABLE, ienb);
-}
-
-static void arc_irq_unmask(struct irq_data *data)
-{
-       unsigned int ienb;
-
-       ienb = read_aux_reg(AUX_IENABLE);
-       ienb |= (1 << data->irq);
-       write_aux_reg(AUX_IENABLE, ienb);
-}
-
-static struct irq_chip onchip_intc = {
-       .name           = "ARC In-core Intc",
-       .irq_mask       = arc_irq_mask,
-       .irq_unmask     = arc_irq_unmask,
-};
-
-static int arc_intc_domain_map(struct irq_domain *d, unsigned int irq,
-                               irq_hw_number_t hw)
-{
-       if (irq == TIMER0_IRQ)
-               irq_set_chip_and_handler(irq, &onchip_intc, handle_percpu_irq);
-       else
-               irq_set_chip_and_handler(irq, &onchip_intc, handle_level_irq);
-
-       return 0;
-}
-
-static const struct irq_domain_ops arc_intc_domain_ops = {
-       .xlate = irq_domain_xlate_onecell,
-       .map = arc_intc_domain_map,
-};
-
-static struct irq_domain *root_domain;
-
-static int __init
-init_onchip_IRQ(struct device_node *intc, struct device_node *parent)
-{
-       if (parent)
-               panic("DeviceTree incore intc not a root irq controller\n");
-
-       root_domain = irq_domain_add_legacy(intc, NR_CPU_IRQS, 0, 0,
-                                           &arc_intc_domain_ops, NULL);
-
-       if (!root_domain)
-               panic("root irq domain not avail\n");
-
-       /* with this we don't need to export root_domain */
-       irq_set_default_host(root_domain);
-
-       return 0;
-}
-
-IRQCHIP_DECLARE(arc_intc, "snps,arc700-intc", init_onchip_IRQ);
-
 /*
  * Late Interrupt system init called from start_kernel for Boot CPU only
  *
@@ -178,107 +72,3 @@ void arc_request_percpu_irq(int irq, int cpu,
 
        enable_percpu_irq(irq, 0);
 }
-
-/*
- * arch_local_irq_enable - Enable interrupts.
- *
- * 1. Explicitly called to re-enable interrupts
- * 2. Implicitly called from spin_unlock_irq, write_unlock_irq etc
- *    which maybe in hard ISR itself
- *
- * Semantics of this function change depending on where it is called from:
- *
- * -If called from hard-ISR, it must not invert interrupt priorities
- *  e.g. suppose TIMER is high priority (Level 2) IRQ
- *    Time hard-ISR, timer_interrupt( ) calls spin_unlock_irq several times.
- *    Here local_irq_enable( ) shd not re-enable lower priority interrupts
- * -If called from soft-ISR, it must re-enable all interrupts
- *    soft ISR are low prioity jobs which can be very slow, thus all IRQs
- *    must be enabled while they run.
- *    Now hardware context wise we may still be in L2 ISR (not done rtie)
- *    still we must re-enable both L1 and L2 IRQs
- *  Another twist is prev scenario with flow being
- *     L1 ISR ==> interrupted by L2 ISR  ==> L2 soft ISR
- *     here we must not re-enable Ll as prev Ll Interrupt's h/w context will get
- *     over-written (this is deficiency in ARC700 Interrupt mechanism)
- */
-
-#ifdef CONFIG_ARC_COMPACT_IRQ_LEVELS   /* Complex version for 2 IRQ levels */
-
-void arch_local_irq_enable(void)
-{
-
-       unsigned long flags;
-       flags = arch_local_save_flags();
-
-       /* Allow both L1 and L2 at the onset */
-       flags |= (STATUS_E1_MASK | STATUS_E2_MASK);
-
-       /* Called from hard ISR (between irq_enter and irq_exit) */
-       if (in_irq()) {
-
-               /* If in L2 ISR, don't re-enable any further IRQs as this can
-                * cause IRQ priorities to get upside down. e.g. it could allow
-                * L1 be taken while in L2 hard ISR which is wrong not only in
-                * theory, it can also cause the dreaded L1-L2-L1 scenario
-                */
-               if (flags & STATUS_A2_MASK)
-                       flags &= ~(STATUS_E1_MASK | STATUS_E2_MASK);
-
-               /* Even if in L1 ISR, allowe Higher prio L2 IRQs */
-               else if (flags & STATUS_A1_MASK)
-                       flags &= ~(STATUS_E1_MASK);
-       }
-
-       /* called from soft IRQ, ideally we want to re-enable all levels */
-
-       else if (in_softirq()) {
-
-               /* However if this is case of L1 interrupted by L2,
-                * re-enabling both may cause whaco L1-L2-L1 scenario
-                * because ARC700 allows level 1 to interrupt an active L2 ISR
-                * Thus we disable both
-                * However some code, executing in soft ISR wants some IRQs
-                * to be enabled so we re-enable L2 only
-                *
-                * How do we determine L1 intr by L2
-                *  -A2 is set (means in L2 ISR)
-                *  -E1 is set in this ISR's pt_regs->status32 which is
-                *      saved copy of status32_l2 when l2 ISR happened
-                */
-               struct pt_regs *pt = get_irq_regs();
-               if ((flags & STATUS_A2_MASK) && pt &&
-                   (pt->status32 & STATUS_A1_MASK)) {
-                       /*flags &= ~(STATUS_E1_MASK | STATUS_E2_MASK); */
-                       flags &= ~(STATUS_E1_MASK);
-               }
-       }
-
-       arch_local_irq_restore(flags);
-}
-
-#else /* ! CONFIG_ARC_COMPACT_IRQ_LEVELS */
-
-/*
- * Simpler version for only 1 level of interrupt
- * Here we only Worry about Level 1 Bits
- */
-void arch_local_irq_enable(void)
-{
-       unsigned long flags;
-
-       /*
-        * ARC IDE Drivers tries to re-enable interrupts from hard-isr
-        * context which is simply wrong
-        */
-       if (in_irq()) {
-               WARN_ONCE(1, "IRQ enabled from hard-isr");
-               return;
-       }
-
-       flags = arch_local_save_flags();
-       flags |= (STATUS_E1_MASK | STATUS_E2_MASK);
-       arch_local_irq_restore(flags);
-}
-#endif
-EXPORT_SYMBOL(arch_local_irq_enable);
diff --git a/arch/arc/kernel/mcip.c b/arch/arc/kernel/mcip.c
new file mode 100644 (file)
index 0000000..30284e8
--- /dev/null
@@ -0,0 +1,341 @@
+/*
+ * ARC ARConnect (MultiCore IP) support (formerly known as MCIP)
+ *
+ * Copyright (C) 2013 Synopsys, Inc. (www.synopsys.com)
+ *
+ * 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/smp.h>
+#include <linux/irq.h>
+#include <linux/spinlock.h>
+#include <asm/mcip.h>
+
+static char smp_cpuinfo_buf[128];
+static int idu_detected;
+
+static DEFINE_RAW_SPINLOCK(mcip_lock);
+
+/*
+ * Any SMP specific init any CPU does when it comes up.
+ * Here we setup the CPU to enable Inter-Processor-Interrupts
+ * Called for each CPU
+ * -Master      : init_IRQ()
+ * -Other(s)    : start_kernel_secondary()
+ */
+void mcip_init_smp(unsigned int cpu)
+{
+       smp_ipi_irq_setup(cpu, IPI_IRQ);
+}
+
+static void mcip_ipi_send(int cpu)
+{
+       unsigned long flags;
+       int ipi_was_pending;
+
+       /*
+        * NOTE: We must spin here if the other cpu hasn't yet
+        * serviced a previous message. This can burn lots
+        * of time, but we MUST follows this protocol or
+        * ipi messages can be lost!!!
+        * Also, we must release the lock in this loop because
+        * the other side may get to this same loop and not
+        * be able to ack -- thus causing deadlock.
+        */
+
+       do {
+               raw_spin_lock_irqsave(&mcip_lock, flags);
+               __mcip_cmd(CMD_INTRPT_READ_STATUS, cpu);
+               ipi_was_pending = read_aux_reg(ARC_REG_MCIP_READBACK);
+               if (ipi_was_pending == 0)
+                       break; /* break out but keep lock */
+               raw_spin_unlock_irqrestore(&mcip_lock, flags);
+       } while (1);
+
+       __mcip_cmd(CMD_INTRPT_GENERATE_IRQ, cpu);
+       raw_spin_unlock_irqrestore(&mcip_lock, flags);
+
+#ifdef CONFIG_ARC_IPI_DBG
+       if (ipi_was_pending)
+               pr_info("IPI ACK delayed from cpu %d\n", cpu);
+#endif
+}
+
+static void mcip_ipi_clear(int irq)
+{
+       unsigned int cpu, c;
+       unsigned long flags;
+       unsigned int __maybe_unused copy;
+
+       raw_spin_lock_irqsave(&mcip_lock, flags);
+
+       /* Who sent the IPI */
+       __mcip_cmd(CMD_INTRPT_CHECK_SOURCE, 0);
+
+       copy = cpu = read_aux_reg(ARC_REG_MCIP_READBACK);       /* 1,2,4,8... */
+
+       /*
+        * In rare case, multiple concurrent IPIs sent to same target can
+        * possibly be coalesced by MCIP into 1 asserted IRQ, so @cpus can be
+        * "vectored" (multiple bits sets) as opposed to typical single bit
+        */
+       do {
+               c = __ffs(cpu);                 /* 0,1,2,3 */
+               __mcip_cmd(CMD_INTRPT_GENERATE_ACK, c);
+               cpu &= ~(1U << c);
+       } while (cpu);
+
+       raw_spin_unlock_irqrestore(&mcip_lock, flags);
+
+#ifdef CONFIG_ARC_IPI_DBG
+       if (c != __ffs(copy))
+               pr_info("IPIs from %x coalesced to %x\n",
+                       copy, raw_smp_processor_id());
+#endif
+}
+
+volatile int wake_flag;
+
+static void mcip_wakeup_cpu(int cpu, unsigned long pc)
+{
+       BUG_ON(cpu == 0);
+       wake_flag = cpu;
+}
+
+void arc_platform_smp_wait_to_boot(int cpu)
+{
+       while (wake_flag != cpu)
+               ;
+
+       wake_flag = 0;
+       __asm__ __volatile__("j @first_lines_of_secondary       \n");
+}
+
+struct plat_smp_ops plat_smp_ops = {
+       .info           = smp_cpuinfo_buf,
+       .cpu_kick       = mcip_wakeup_cpu,
+       .ipi_send       = mcip_ipi_send,
+       .ipi_clear      = mcip_ipi_clear,
+};
+
+void mcip_init_early_smp(void)
+{
+#define IS_AVAIL1(var, str)    ((var) ? str : "")
+
+       struct mcip_bcr {
+#ifdef CONFIG_CPU_BIG_ENDIAN
+               unsigned int pad3:8,
+                            idu:1, llm:1, num_cores:6,
+                            iocoh:1,  grtc:1, dbg:1, pad2:1,
+                            msg:1, sem:1, ipi:1, pad:1,
+                            ver:8;
+#else
+               unsigned int ver:8,
+                            pad:1, ipi:1, sem:1, msg:1,
+                            pad2:1, dbg:1, grtc:1, iocoh:1,
+                            num_cores:6, llm:1, idu:1,
+                            pad3:8;
+#endif
+       } mp;
+
+       READ_BCR(ARC_REG_MCIP_BCR, mp);
+
+       sprintf(smp_cpuinfo_buf,
+               "Extn [SMP]\t: ARConnect (v%d): %d cores with %s%s%s%s\n",
+               mp.ver, mp.num_cores,
+               IS_AVAIL1(mp.ipi, "IPI "),
+               IS_AVAIL1(mp.idu, "IDU "),
+               IS_AVAIL1(mp.dbg, "DEBUG "),
+               IS_AVAIL1(mp.grtc, "GRTC"));
+
+       idu_detected = mp.idu;
+
+       if (mp.dbg) {
+               __mcip_cmd_data(CMD_DEBUG_SET_SELECT, 0, 0xf);
+               __mcip_cmd_data(CMD_DEBUG_SET_MASK, 0xf, 0xf);
+       }
+
+       if (IS_ENABLED(CONFIG_ARC_HAS_GRTC) && !mp.grtc)
+               panic("kernel trying to use non-existent GRTC\n");
+}
+
+/***************************************************************************
+ * ARCv2 Interrupt Distribution Unit (IDU)
+ *
+ * Connects external "COMMON" IRQs to core intc, providing:
+ *  -dynamic routing (IRQ affinity)
+ *  -load balancing (Round Robin interrupt distribution)
+ *  -1:N distribution
+ *
+ * It physically resides in the MCIP hw block
+ */
+
+#include <linux/irqchip.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include "../../drivers/irqchip/irqchip.h"
+
+/*
+ * Set the DEST for @cmn_irq to @cpu_mask (1 bit per core)
+ */
+static void idu_set_dest(unsigned int cmn_irq, unsigned int cpu_mask)
+{
+       __mcip_cmd_data(CMD_IDU_SET_DEST, cmn_irq, cpu_mask);
+}
+
+static void idu_set_mode(unsigned int cmn_irq, unsigned int lvl,
+                          unsigned int distr)
+{
+       union {
+               unsigned int word;
+               struct {
+                       unsigned int distr:2, pad:2, lvl:1, pad2:27;
+               };
+       } data;
+
+       data.distr = distr;
+       data.lvl = lvl;
+       __mcip_cmd_data(CMD_IDU_SET_MODE, cmn_irq, data.word);
+}
+
+static void idu_irq_mask(struct irq_data *data)
+{
+       unsigned long flags;
+
+       raw_spin_lock_irqsave(&mcip_lock, flags);
+       __mcip_cmd_data(CMD_IDU_SET_MASK, data->hwirq, 1);
+       raw_spin_unlock_irqrestore(&mcip_lock, flags);
+}
+
+static void idu_irq_unmask(struct irq_data *data)
+{
+       unsigned long flags;
+
+       raw_spin_lock_irqsave(&mcip_lock, flags);
+       __mcip_cmd_data(CMD_IDU_SET_MASK, data->hwirq, 0);
+       raw_spin_unlock_irqrestore(&mcip_lock, flags);
+}
+
+static int
+idu_irq_set_affinity(struct irq_data *d, const struct cpumask *cpumask, bool f)
+{
+       return IRQ_SET_MASK_OK;
+}
+
+static struct irq_chip idu_irq_chip = {
+       .name                   = "MCIP IDU Intc",
+       .irq_mask               = idu_irq_mask,
+       .irq_unmask             = idu_irq_unmask,
+#ifdef CONFIG_SMP
+       .irq_set_affinity       = idu_irq_set_affinity,
+#endif
+
+};
+
+static int idu_first_irq;
+
+static void idu_cascade_isr(unsigned int core_irq, struct irq_desc *desc)
+{
+       struct irq_domain *domain = irq_desc_get_handler_data(desc);
+       unsigned int idu_irq;
+
+       idu_irq = core_irq - idu_first_irq;
+       generic_handle_irq(irq_find_mapping(domain, idu_irq));
+}
+
+static int idu_irq_map(struct irq_domain *d, unsigned int virq, irq_hw_number_t hwirq)
+{
+       irq_set_chip_and_handler(virq, &idu_irq_chip, handle_level_irq);
+       irq_set_status_flags(virq, IRQ_MOVE_PCNTXT);
+
+       return 0;
+}
+
+static int idu_irq_xlate(struct irq_domain *d, struct device_node *n,
+                        const u32 *intspec, unsigned int intsize,
+                        irq_hw_number_t *out_hwirq, unsigned int *out_type)
+{
+       irq_hw_number_t hwirq = *out_hwirq = intspec[0];
+       int distri = intspec[1];
+       unsigned long flags;
+
+       *out_type = IRQ_TYPE_NONE;
+
+       /* XXX: validate distribution scheme again online cpu mask */
+       if (distri == 0) {
+               /* 0 - Round Robin to all cpus, otherwise 1 bit per core */
+               raw_spin_lock_irqsave(&mcip_lock, flags);
+               idu_set_dest(hwirq, BIT(num_online_cpus()) - 1);
+               idu_set_mode(hwirq, IDU_M_TRIG_LEVEL, IDU_M_DISTRI_RR);
+               raw_spin_unlock_irqrestore(&mcip_lock, flags);
+       } else {
+               /*
+                * DEST based distribution for Level Triggered intr can only
+                * have 1 CPU, so generalize it to always contain 1 cpu
+                */
+               int cpu = ffs(distri);
+
+               if (cpu != fls(distri))
+                       pr_warn("IDU irq %lx distri mode set to cpu %x\n",
+                               hwirq, cpu);
+
+               raw_spin_lock_irqsave(&mcip_lock, flags);
+               idu_set_dest(hwirq, cpu);
+               idu_set_mode(hwirq, IDU_M_TRIG_LEVEL, IDU_M_DISTRI_DEST);
+               raw_spin_unlock_irqrestore(&mcip_lock, flags);
+       }
+
+       return 0;
+}
+
+static const struct irq_domain_ops idu_irq_ops = {
+       .xlate  = idu_irq_xlate,
+       .map    = idu_irq_map,
+};
+
+/*
+ * [16, 23]: Statically assigned always private-per-core (Timers, WDT, IPI)
+ * [24, 23+C]: If C > 0 then "C" common IRQs
+ * [24+C, N]: Not statically assigned, private-per-core
+ */
+
+
+static int __init
+idu_of_init(struct device_node *intc, struct device_node *parent)
+{
+       struct irq_domain *domain;
+       /* Read IDU BCR to confirm nr_irqs */
+       int nr_irqs = of_irq_count(intc);
+       int i, irq;
+
+       if (!idu_detected)
+               panic("IDU not detected, but DeviceTree using it");
+
+       pr_info("MCIP: IDU referenced from Devicetree %d irqs\n", nr_irqs);
+
+       domain = irq_domain_add_linear(intc, nr_irqs, &idu_irq_ops, NULL);
+
+       /* Parent interrupts (core-intc) are already mapped */
+
+       for (i = 0; i < nr_irqs; i++) {
+               /*
+                * Return parent uplink IRQs (towards core intc) 24,25,.....
+                * this step has been done before already
+                * however we need it to get the parent virq and set IDU handler
+                * as first level isr
+                */
+               irq = irq_of_parse_and_map(intc, i);
+               if (!i)
+                       idu_first_irq = irq;
+
+               irq_set_handler_data(irq, domain);
+               irq_set_chained_handler(irq, idu_cascade_isr);
+       }
+
+       __mcip_cmd(CMD_IDU_ENABLE, 0);
+
+       return 0;
+}
+IRQCHIP_DECLARE(arcv2_idu_intc, "snps,archs-idu-intc", idu_of_init);
index fd2ec50102f201254b1e5e51b4bbc7fa93fba95a..1287388c258ace8ef57f1030a46acb65f0fbb87e 100644 (file)
@@ -266,10 +266,9 @@ static int arc_pmu_add(struct perf_event *event, int flags)
 
 static int arc_pmu_device_probe(struct platform_device *pdev)
 {
-       struct arc_pmu *arc_pmu;
        struct arc_reg_pct_build pct_bcr;
        struct arc_reg_cc_build cc_bcr;
-       int i, j, ret;
+       int i, j;
 
        union cc_name {
                struct {
@@ -336,9 +335,7 @@ static int arc_pmu_device_probe(struct platform_device *pdev)
        /* ARC 700 PMU does not support sampling events */
        arc_pmu->pmu.capabilities |= PERF_PMU_CAP_NO_INTERRUPT;
 
-       ret = perf_pmu_register(&arc_pmu->pmu, pdev->name, PERF_TYPE_RAW);
-
-       return ret;
+       return perf_pmu_register(&arc_pmu->pmu, pdev->name, PERF_TYPE_RAW);
 }
 
 #ifdef CONFIG_OF
index e095c557afdddc3aefce744c97d5d7bb20a6f2e6..44092456776f8e9cd929b36e5083fbc4074dac9b 100644 (file)
@@ -44,7 +44,11 @@ SYSCALL_DEFINE0(arc_gettls)
 void arch_cpu_idle(void)
 {
        /* sleep, but enable all interrupts before committing */
-       __asm__("sleep 0x3");
+       if (is_isa_arcompact()) {
+               __asm__("sleep 0x3");
+       } else {
+               __asm__("sleep 0x10");
+       }
 }
 
 asmlinkage void ret_from_fork(void);
@@ -166,8 +170,7 @@ void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long usp)
         * [L] ZOL loop inhibited to begin with - cleared by a LP insn
         * Interrupts enabled
         */
-       regs->status32 = STATUS_U_MASK | STATUS_L_MASK |
-                        STATUS_E1_MASK | STATUS_E2_MASK;
+       regs->status32 = STATUS_U_MASK | STATUS_L_MASK | ISA_INIT_STATUS_BITS;
 
        /* bogus seed values for debugging */
        regs->lp_start = 0x10;
@@ -197,8 +200,11 @@ int elf_check_arch(const struct elf32_hdr *x)
 {
        unsigned int eflags;
 
-       if (x->e_machine != EM_ARCOMPACT)
+       if (x->e_machine != EM_ARC_INUSE) {
+               pr_err("ELF not built for %s ISA\n",
+                       is_isa_arcompact() ? "ARCompact":"ARCv2");
                return 0;
+       }
 
        eflags = x->e_flags;
        if ((eflags & EF_ARC_OSABI_MSK) < EF_ARC_OSABI_CURRENT) {
index 13b3ffb27a384f8c214bfe110943ba020b0c297f..4442204fe238e656886384c5133d4af85492dabb 100644 (file)
@@ -47,10 +47,47 @@ static int genregs_get(struct task_struct *target,
                        offsetof(struct user_regs_struct, LOC) + 4);
 
        REG_O_ZERO(pad);
-       REG_O_CHUNK(scratch, callee, ptregs);
+       REG_O_ONE(scratch.bta, &ptregs->bta);
+       REG_O_ONE(scratch.lp_start, &ptregs->lp_start);
+       REG_O_ONE(scratch.lp_end, &ptregs->lp_end);
+       REG_O_ONE(scratch.lp_count, &ptregs->lp_count);
+       REG_O_ONE(scratch.status32, &ptregs->status32);
+       REG_O_ONE(scratch.ret, &ptregs->ret);
+       REG_O_ONE(scratch.blink, &ptregs->blink);
+       REG_O_ONE(scratch.fp, &ptregs->fp);
+       REG_O_ONE(scratch.gp, &ptregs->r26);
+       REG_O_ONE(scratch.r12, &ptregs->r12);
+       REG_O_ONE(scratch.r11, &ptregs->r11);
+       REG_O_ONE(scratch.r10, &ptregs->r10);
+       REG_O_ONE(scratch.r9, &ptregs->r9);
+       REG_O_ONE(scratch.r8, &ptregs->r8);
+       REG_O_ONE(scratch.r7, &ptregs->r7);
+       REG_O_ONE(scratch.r6, &ptregs->r6);
+       REG_O_ONE(scratch.r5, &ptregs->r5);
+       REG_O_ONE(scratch.r4, &ptregs->r4);
+       REG_O_ONE(scratch.r3, &ptregs->r3);
+       REG_O_ONE(scratch.r2, &ptregs->r2);
+       REG_O_ONE(scratch.r1, &ptregs->r1);
+       REG_O_ONE(scratch.r0, &ptregs->r0);
+       REG_O_ONE(scratch.sp, &ptregs->sp);
+
        REG_O_ZERO(pad2);
-       REG_O_CHUNK(callee, efa, cregs);
-       REG_O_CHUNK(efa, stop_pc, &target->thread.fault_address);
+
+       REG_O_ONE(callee.r25, &cregs->r25);
+       REG_O_ONE(callee.r24, &cregs->r24);
+       REG_O_ONE(callee.r23, &cregs->r23);
+       REG_O_ONE(callee.r22, &cregs->r22);
+       REG_O_ONE(callee.r21, &cregs->r21);
+       REG_O_ONE(callee.r20, &cregs->r20);
+       REG_O_ONE(callee.r19, &cregs->r19);
+       REG_O_ONE(callee.r18, &cregs->r18);
+       REG_O_ONE(callee.r17, &cregs->r17);
+       REG_O_ONE(callee.r16, &cregs->r16);
+       REG_O_ONE(callee.r15, &cregs->r15);
+       REG_O_ONE(callee.r14, &cregs->r14);
+       REG_O_ONE(callee.r13, &cregs->r13);
+
+       REG_O_ONE(efa, &target->thread.fault_address);
 
        if (!ret) {
                if (in_brkpt_trap(ptregs)) {
@@ -97,12 +134,51 @@ static int genregs_set(struct task_struct *target,
                        offsetof(struct user_regs_struct, LOC) + 4);
 
        REG_IGNORE_ONE(pad);
-       /* TBD: disallow updates to STATUS32 etc*/
-       REG_IN_CHUNK(scratch, pad2, ptregs);    /* pt_regs[bta..sp] */
+
+       REG_IN_ONE(scratch.bta, &ptregs->bta);
+       REG_IN_ONE(scratch.lp_start, &ptregs->lp_start);
+       REG_IN_ONE(scratch.lp_end, &ptregs->lp_end);
+       REG_IN_ONE(scratch.lp_count, &ptregs->lp_count);
+
+       REG_IGNORE_ONE(scratch.status32);
+
+       REG_IN_ONE(scratch.ret, &ptregs->ret);
+       REG_IN_ONE(scratch.blink, &ptregs->blink);
+       REG_IN_ONE(scratch.fp, &ptregs->fp);
+       REG_IN_ONE(scratch.gp, &ptregs->r26);
+       REG_IN_ONE(scratch.r12, &ptregs->r12);
+       REG_IN_ONE(scratch.r11, &ptregs->r11);
+       REG_IN_ONE(scratch.r10, &ptregs->r10);
+       REG_IN_ONE(scratch.r9, &ptregs->r9);
+       REG_IN_ONE(scratch.r8, &ptregs->r8);
+       REG_IN_ONE(scratch.r7, &ptregs->r7);
+       REG_IN_ONE(scratch.r6, &ptregs->r6);
+       REG_IN_ONE(scratch.r5, &ptregs->r5);
+       REG_IN_ONE(scratch.r4, &ptregs->r4);
+       REG_IN_ONE(scratch.r3, &ptregs->r3);
+       REG_IN_ONE(scratch.r2, &ptregs->r2);
+       REG_IN_ONE(scratch.r1, &ptregs->r1);
+       REG_IN_ONE(scratch.r0, &ptregs->r0);
+       REG_IN_ONE(scratch.sp, &ptregs->sp);
+
        REG_IGNORE_ONE(pad2);
-       REG_IN_CHUNK(callee, efa, cregs);       /* callee_regs[r25..r13] */
+
+       REG_IN_ONE(callee.r25, &cregs->r25);
+       REG_IN_ONE(callee.r24, &cregs->r24);
+       REG_IN_ONE(callee.r23, &cregs->r23);
+       REG_IN_ONE(callee.r22, &cregs->r22);
+       REG_IN_ONE(callee.r21, &cregs->r21);
+       REG_IN_ONE(callee.r20, &cregs->r20);
+       REG_IN_ONE(callee.r19, &cregs->r19);
+       REG_IN_ONE(callee.r18, &cregs->r18);
+       REG_IN_ONE(callee.r17, &cregs->r17);
+       REG_IN_ONE(callee.r16, &cregs->r16);
+       REG_IN_ONE(callee.r15, &cregs->r15);
+       REG_IN_ONE(callee.r14, &cregs->r14);
+       REG_IN_ONE(callee.r13, &cregs->r13);
+
        REG_IGNORE_ONE(efa);                    /* efa update invalid */
-       REG_IGNORE_ONE(stop_pc);                        /* PC updated via @ret */
+       REG_IGNORE_ONE(stop_pc);                /* PC updated via @ret */
 
        return ret;
 }
@@ -124,7 +200,7 @@ static const struct user_regset arc_regsets[] = {
 
 static const struct user_regset_view user_arc_view = {
        .name           = UTS_MACHINE,
-       .e_machine      = EM_ARCOMPACT,
+       .e_machine      = EM_ARC_INUSE,
        .regsets        = arc_regsets,
        .n              = ARRAY_SIZE(arc_regsets)
 };
index 1d167c6df8caae8a48d59b2aa08539e9f20b51d6..a3d186211ed367bcf852718682a62f24b555f3de 100644 (file)
@@ -30,6 +30,8 @@
 
 #define FIX_PTR(x)  __asm__ __volatile__(";" : "+r"(x))
 
+unsigned int intr_to_DE_cnt;
+
 /* Part of U-boot ABI: see head.S */
 int __initdata uboot_tag;
 char __initdata *uboot_arg;
@@ -54,7 +56,7 @@ static void read_arc_build_cfg_regs(void)
        cpu->vec_base = read_aux_reg(AUX_INTR_VEC_BASE);
 
        READ_BCR(ARC_REG_D_UNCACH_BCR, uncached_space);
-       cpu->uncached_base = uncached_space.start << 24;
+       BUG_ON((uncached_space.start << 24) != ARC_UNCACHED_ADDR_SPACE);
 
        READ_BCR(ARC_REG_MUL_BCR, cpu->extn_mpy);
 
@@ -96,7 +98,7 @@ static void read_arc_build_cfg_regs(void)
        read_decode_mmu_bcr();
        read_decode_cache_bcr();
 
-       {
+       if (is_isa_arcompact()) {
                struct bcr_fp_arcompact sp, dp;
                struct bcr_bpu_arcompact bpu;
 
@@ -112,6 +114,19 @@ static void read_arc_build_cfg_regs(void)
                        cpu->bpu.num_cache = 256 << (bpu.ent - 1);
                        cpu->bpu.num_pred = 256 << (bpu.ent - 1);
                }
+       } else {
+               struct bcr_fp_arcv2 spdp;
+               struct bcr_bpu_arcv2 bpu;
+
+               READ_BCR(ARC_REG_FP_V2_BCR, spdp);
+               cpu->extn.fpu_sp = spdp.sp ? 1 : 0;
+               cpu->extn.fpu_dp = spdp.dp ? 1 : 0;
+
+               READ_BCR(ARC_REG_BPU_BCR, bpu);
+               cpu->bpu.ver = bpu.ver;
+               cpu->bpu.full = bpu.ft;
+               cpu->bpu.num_cache = 256 << bpu.bce;
+               cpu->bpu.num_pred = 2048 << bpu.pte;
        }
 
        READ_BCR(ARC_REG_AP_BCR, bcr);
@@ -131,6 +146,7 @@ static const struct cpuinfo_data arc_cpu_tbl[] = {
        { {0x30, "ARC 700"      }, 0x33},
        { {0x34, "ARC 700 R4.10"}, 0x34},
        { {0x35, "ARC 700 R4.11"}, 0x35},
+       { {0x50, "ARC HS38"     }, 0x51},
        { {0x00, NULL           } }
 };
 
@@ -149,13 +165,17 @@ static char *arc_cpu_mumbojumbo(int cpu_id, char *buf, int len)
 
        FIX_PTR(cpu);
 
-       {
+       if (is_isa_arcompact()) {
                isa_nm = "ARCompact";
                be = IS_ENABLED(CONFIG_CPU_BIG_ENDIAN);
 
                atomic = cpu->isa.atomic1;
                if (!cpu->isa.ver)      /* ISA BCR absent, use Kconfig info */
                        atomic = IS_ENABLED(CONFIG_ARC_HAS_LLSC);
+       } else {
+               isa_nm = "ARCv2";
+               be = cpu->isa.be;
+               atomic = cpu->isa.atomic;
        }
 
        n += scnprintf(buf + n, len - n,
@@ -183,16 +203,34 @@ static char *arc_cpu_mumbojumbo(int cpu_id, char *buf, int len)
        n += scnprintf(buf + n, len - n, "Timers\t\t: %s%s%s%s\nISA Extn\t: ",
                       IS_AVAIL1(cpu->timers.t0, "Timer0 "),
                       IS_AVAIL1(cpu->timers.t1, "Timer1 "),
-                      IS_AVAIL2(cpu->timers.rtsc, "64-bit RTSC ", CONFIG_ARC_HAS_RTSC));
+                      IS_AVAIL2(cpu->timers.rtc, "64-bit RTC ",
+                                CONFIG_ARC_HAS_RTC));
 
-       n += i = scnprintf(buf + n, len - n, "%s%s",
-                          IS_AVAIL2(atomic, "atomic ", CONFIG_ARC_HAS_LLSC));
+       n += i = scnprintf(buf + n, len - n, "%s%s%s%s%s",
+                          IS_AVAIL2(atomic, "atomic ", CONFIG_ARC_HAS_LLSC),
+                          IS_AVAIL2(cpu->isa.ldd, "ll64 ", CONFIG_ARC_HAS_LL64),
+                          IS_AVAIL1(cpu->isa.unalign, "unalign (not used)"));
 
        if (i)
                n += scnprintf(buf + n, len - n, "\n\t\t: ");
 
+       if (cpu->extn_mpy.ver) {
+               if (cpu->extn_mpy.ver <= 0x2) { /* ARCompact */
+                       n += scnprintf(buf + n, len - n, "mpy ");
+               } else {
+                       int opt = 2;    /* stock MPY/MPYH */
+
+                       if (cpu->extn_mpy.dsp)  /* OPT 7-9 */
+                               opt = cpu->extn_mpy.dsp + 6;
+
+                       n += scnprintf(buf + n, len - n, "mpy[opt %d] ", opt);
+               }
+               n += scnprintf(buf + n, len - n, "%s",
+                              IS_USED(CONFIG_ARC_HAS_HW_MPY));
+       }
+
        n += scnprintf(buf + n, len - n, "%s%s%s%s%s%s%s%s\n",
-                      IS_AVAIL1(cpu->extn_mpy.ver, "mpy "),
+                      IS_AVAIL1(cpu->isa.div_rem, "div_rem "),
                       IS_AVAIL1(cpu->extn.norm, "norm "),
                       IS_AVAIL1(cpu->extn.barrel, "barrel-shift "),
                       IS_AVAIL1(cpu->extn.swap, "swap "),
@@ -219,7 +257,7 @@ static char *arc_extn_mumbojumbo(int cpu_id, char *buf, int len)
 
        n += scnprintf(buf + n, len - n,
                       "Vector Table\t: %#x\nUncached Base\t: %#x\n",
-                      cpu->vec_base, cpu->uncached_base);
+                      cpu->vec_base, ARC_UNCACHED_ADDR_SPACE);
 
        if (cpu->extn.fpu_sp || cpu->extn.fpu_dp)
                n += scnprintf(buf + n, len - n, "FPU\t\t: %s%s\n",
@@ -254,8 +292,8 @@ static void arc_chk_core_config(void)
        if (!cpu->timers.t1)
                panic("Timer1 is not present!\n");
 
-       if (IS_ENABLED(CONFIG_ARC_HAS_RTSC) && !cpu->timers.rtsc)
-               panic("RTSC is not present\n");
+       if (IS_ENABLED(CONFIG_ARC_HAS_RTC) && !cpu->timers.rtc)
+               panic("RTC is not present\n");
 
 #ifdef CONFIG_ARC_HAS_DCCM
        /*
@@ -323,13 +361,16 @@ static inline int is_kernel(unsigned long addr)
 
 void __init setup_arch(char **cmdline_p)
 {
+#ifdef CONFIG_ARC_UBOOT_SUPPORT
        /* make sure that uboot passed pointer to cmdline/dtb is valid */
        if (uboot_tag && is_kernel((unsigned long)uboot_arg))
                panic("Invalid uboot arg\n");
 
        /* See if u-boot passed an external Device Tree blob */
        machine_desc = setup_machine_fdt(uboot_arg);    /* uboot_tag == 2 */
-       if (!machine_desc) {
+       if (!machine_desc)
+#endif
+       {
                /* No, so try the embedded one */
                machine_desc = setup_machine_fdt(__dtb_start);
                if (!machine_desc)
index 2251fb4bbfd76c4e8ab67477302d1e215017e73d..004b7f0bc76cc58c6988547df1bb8705cd36004d 100644 (file)
@@ -67,7 +67,33 @@ stash_usr_regs(struct rt_sigframe __user *sf, struct pt_regs *regs,
               sigset_t *set)
 {
        int err;
-       err = __copy_to_user(&(sf->uc.uc_mcontext.regs.scratch), regs,
+       struct user_regs_struct uregs;
+
+       uregs.scratch.bta       = regs->bta;
+       uregs.scratch.lp_start  = regs->lp_start;
+       uregs.scratch.lp_end    = regs->lp_end;
+       uregs.scratch.lp_count  = regs->lp_count;
+       uregs.scratch.status32  = regs->status32;
+       uregs.scratch.ret       = regs->ret;
+       uregs.scratch.blink     = regs->blink;
+       uregs.scratch.fp        = regs->fp;
+       uregs.scratch.gp        = regs->r26;
+       uregs.scratch.r12       = regs->r12;
+       uregs.scratch.r11       = regs->r11;
+       uregs.scratch.r10       = regs->r10;
+       uregs.scratch.r9        = regs->r9;
+       uregs.scratch.r8        = regs->r8;
+       uregs.scratch.r7        = regs->r7;
+       uregs.scratch.r6        = regs->r6;
+       uregs.scratch.r5        = regs->r5;
+       uregs.scratch.r4        = regs->r4;
+       uregs.scratch.r3        = regs->r3;
+       uregs.scratch.r2        = regs->r2;
+       uregs.scratch.r1        = regs->r1;
+       uregs.scratch.r0        = regs->r0;
+       uregs.scratch.sp        = regs->sp;
+
+       err = __copy_to_user(&(sf->uc.uc_mcontext.regs.scratch), &uregs.scratch,
                             sizeof(sf->uc.uc_mcontext.regs.scratch));
        err |= __copy_to_user(&sf->uc.uc_sigmask, set, sizeof(sigset_t));
 
@@ -78,14 +104,40 @@ static int restore_usr_regs(struct pt_regs *regs, struct rt_sigframe __user *sf)
 {
        sigset_t set;
        int err;
+       struct user_regs_struct uregs;
 
        err = __copy_from_user(&set, &sf->uc.uc_sigmask, sizeof(set));
        if (!err)
                set_current_blocked(&set);
 
-       err |= __copy_from_user(regs, &(sf->uc.uc_mcontext.regs.scratch),
+       err |= __copy_from_user(&uregs.scratch,
+                               &(sf->uc.uc_mcontext.regs.scratch),
                                sizeof(sf->uc.uc_mcontext.regs.scratch));
 
+       regs->bta       = uregs.scratch.bta;
+       regs->lp_start  = uregs.scratch.lp_start;
+       regs->lp_end    = uregs.scratch.lp_end;
+       regs->lp_count  = uregs.scratch.lp_count;
+       regs->status32  = uregs.scratch.status32;
+       regs->ret       = uregs.scratch.ret;
+       regs->blink     = uregs.scratch.blink;
+       regs->fp        = uregs.scratch.fp;
+       regs->r26       = uregs.scratch.gp;
+       regs->r12       = uregs.scratch.r12;
+       regs->r11       = uregs.scratch.r11;
+       regs->r10       = uregs.scratch.r10;
+       regs->r9        = uregs.scratch.r9;
+       regs->r8        = uregs.scratch.r8;
+       regs->r7        = uregs.scratch.r7;
+       regs->r6        = uregs.scratch.r6;
+       regs->r5        = uregs.scratch.r5;
+       regs->r4        = uregs.scratch.r4;
+       regs->r3        = uregs.scratch.r3;
+       regs->r2        = uregs.scratch.r2;
+       regs->r1        = uregs.scratch.r1;
+       regs->r0        = uregs.scratch.r0;
+       regs->sp        = uregs.scratch.sp;
+
        return err;
 }
 
@@ -284,7 +336,7 @@ static void arc_restart_syscall(struct k_sigaction *ka, struct pt_regs *regs)
                 * their orig user space value when we ret from kernel
                 */
                regs->r0 = regs->orig_r0;
-               regs->ret -= 4;
+               regs->ret -= is_isa_arcv2() ? 2 : 4;
                break;
        }
 }
@@ -325,10 +377,10 @@ void do_signal(struct pt_regs *regs)
                if (regs->r0 == -ERESTARTNOHAND ||
                    regs->r0 == -ERESTARTSYS || regs->r0 == -ERESTARTNOINTR) {
                        regs->r0 = regs->orig_r0;
-                       regs->ret -= 4;
+                       regs->ret -= is_isa_arcv2() ? 2 : 4;
                } else if (regs->r0 == -ERESTART_RESTARTBLOCK) {
                        regs->r8 = __NR_restart_syscall;
-                       regs->ret -= 4;
+                       regs->ret -= is_isa_arcv2() ? 2 : 4;
                }
                syscall_wont_restart(regs);     /* No more restarts */
        }
index 6a400b1b0b62e07b9e0d7b14d549e8a57652d681..be13d12420bad642c5141a58fdc82d5798204b59 100644 (file)
@@ -31,7 +31,7 @@ arch_spinlock_t smp_atomic_ops_lock = __ARCH_SPIN_LOCK_UNLOCKED;
 arch_spinlock_t smp_bitops_lock = __ARCH_SPIN_LOCK_UNLOCKED;
 #endif
 
-struct plat_smp_ops  plat_smp_ops;
+struct plat_smp_ops  __weak plat_smp_ops;
 
 /* XXX: per cpu ? Only needed once in early seconday boot */
 struct task_struct *secondary_idle_tsk;
@@ -182,7 +182,7 @@ int __cpu_up(unsigned int cpu, struct task_struct *idle)
 /*
  * not supported here
  */
-int __init setup_profiling_timer(unsigned int multiplier)
+int setup_profiling_timer(unsigned int multiplier)
 {
        return -EINVAL;
 }
@@ -278,8 +278,10 @@ static void ipi_cpu_stop(void)
        machine_halt();
 }
 
-static inline void __do_IPI(unsigned long msg)
+static inline int __do_IPI(unsigned long msg)
 {
+       int rc = 0;
+
        switch (msg) {
        case IPI_RESCHEDULE:
                scheduler_ipi();
@@ -294,8 +296,10 @@ static inline void __do_IPI(unsigned long msg)
                break;
 
        default:
-               pr_warn("IPI with unexpected msg %ld\n", msg);
+               rc = 1;
        }
+
+       return rc;
 }
 
 /*
@@ -305,6 +309,7 @@ static inline void __do_IPI(unsigned long msg)
 irqreturn_t do_IPI(int irq, void *dev_id)
 {
        unsigned long pending;
+       unsigned long __maybe_unused copy;
 
        pr_debug("IPI [%ld] received on cpu %d\n",
                 *this_cpu_ptr(&ipi_data), smp_processor_id());
@@ -316,11 +321,18 @@ irqreturn_t do_IPI(int irq, void *dev_id)
         * "dequeue" the msg corresponding to this IPI (and possibly other
         * piggybacked msg from elided IPIs: see ipi_send_msg_one() above)
         */
-       pending = xchg(this_cpu_ptr(&ipi_data), 0);
+       copy = pending = xchg(this_cpu_ptr(&ipi_data), 0);
 
        do {
                unsigned long msg = __ffs(pending);
-               __do_IPI(msg);
+               int rc;
+
+               rc = __do_IPI(msg);
+#ifdef CONFIG_ARC_IPI_DBG
+               /* IPI received but no valid @msg */
+               if (rc)
+                       pr_info("IPI with bogus msg %ld in %ld\n", msg, copy);
+#endif
                pending &= ~(1U << msg);
        } while (pending);
 
index 92320d6f737cf5149d0968f5da3cd73a47af9848..001de4ce711eae2b095451a52f68e77db3d81ef4 100644 (file)
@@ -122,19 +122,17 @@ arc_unwind_core(struct task_struct *tsk, struct pt_regs *regs,
        while (1) {
                address = UNW_PC(&frame_info);
 
-               if (address && __kernel_text_address(address)) {
-                       if (consumer_fn(address, arg) == -1)
-                               break;
-               }
+               if (!address || !__kernel_text_address(address))
+                       break;
 
-               ret = arc_unwind(&frame_info);
+               if (consumer_fn(address, arg) == -1)
+                       break;
 
-               if (ret == 0) {
-                       frame_info.regs.r63 = frame_info.regs.r31;
-                       continue;
-               } else {
+               ret = arc_unwind(&frame_info);
+               if (ret)
                        break;
-               }
+
+               frame_info.regs.r63 = frame_info.regs.r31;
        }
 
        return address;         /* return the last address it saw */
index dbe74f418019bf7e498ed95bcdc08149a752ff51..3364d2bbc515471bba6478b8b34a417251ffde56 100644 (file)
@@ -26,6 +26,7 @@
  * while TIMER1 for free running (clocksource)
  *
  * Newer ARC700 cores have 64bit clk fetching RTSC insn, preferred over TIMER1
+ * which however is currently broken
  */
 
 #include <linux/spinlock.h>
@@ -44,6 +45,8 @@
 #include <asm/clk.h>
 #include <asm/mach_desc.h>
 
+#include <asm/mcip.h>
+
 /* Timer related Aux registers */
 #define ARC_REG_TIMER0_LIMIT   0x23    /* timer 0 limit */
 #define ARC_REG_TIMER0_CTRL    0x22    /* timer 0 control */
 
 /********** Clock Source Device *********/
 
-#ifdef CONFIG_ARC_HAS_RTSC
+#ifdef CONFIG_ARC_HAS_GRTC
 
-int arc_counter_setup(void)
+static int arc_counter_setup(void)
 {
-       /*
-        * For SMP this needs to be 0. However Kconfig glue doesn't
-        * enable this option for SMP configs
-        */
        return 1;
 }
 
@@ -75,45 +74,84 @@ static cycle_t arc_counter_read(struct clocksource *cs)
        unsigned long flags;
        union {
 #ifdef CONFIG_CPU_BIG_ENDIAN
-               struct { u32 high, low; };
+               struct { u32 h, l; };
 #else
-               struct { u32 low, high; };
+               struct { u32 lh; };
 #endif
                cycle_t  full;
        } stamp;
 
-       flags = arch_local_irq_save();
+       local_irq_save(flags);
 
-       __asm__ __volatile(
-       "       .extCoreRegister tsch, 58,  r, cannot_shortcut  \n"
-       "       rtsc %0, 0      \n"
-       "       mov  %1, 0      \n"
-       : "=r" (stamp.low), "=r" (stamp.high));
+       __mcip_cmd(CMD_GRTC_READ_LO, 0);
+       stamp.l = read_aux_reg(ARC_REG_MCIP_READBACK);
+
+       __mcip_cmd(CMD_GRTC_READ_HI, 0);
+       stamp.h = read_aux_reg(ARC_REG_MCIP_READBACK);
 
-       arch_local_irq_restore(flags);
+       local_irq_restore(flags);
 
        return stamp.full;
 }
 
 static struct clocksource arc_counter = {
-       .name   = "ARC RTSC",
-       .rating = 300,
+       .name   = "ARConnect GRTC",
+       .rating = 400,
        .read   = arc_counter_read,
-       .mask   = CLOCKSOURCE_MASK(32),
+       .mask   = CLOCKSOURCE_MASK(64),
        .flags  = CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
-#else /* !CONFIG_ARC_HAS_RTSC */
+#else
+
+#ifdef CONFIG_ARC_HAS_RTC
+
+#define AUX_RTC_CTRL   0x103
+#define AUX_RTC_LOW    0x104
+#define AUX_RTC_HIGH   0x105
 
-static bool is_usable_as_clocksource(void)
+int arc_counter_setup(void)
 {
-#ifdef CONFIG_SMP
-       return 0;
+       write_aux_reg(AUX_RTC_CTRL, 1);
+
+       /* Not usable in SMP */
+       return !IS_ENABLED(CONFIG_SMP);
+}
+
+static cycle_t arc_counter_read(struct clocksource *cs)
+{
+       unsigned long status;
+       union {
+#ifdef CONFIG_CPU_BIG_ENDIAN
+               struct { u32 high, low; };
 #else
-       return 1;
+               struct { u32 low, high; };
 #endif
+               cycle_t  full;
+       } stamp;
+
+
+       __asm__ __volatile(
+       "1:                                             \n"
+       "       lr              %0, [AUX_RTC_LOW]       \n"
+       "       lr              %1, [AUX_RTC_HIGH]      \n"
+       "       lr              %2, [AUX_RTC_CTRL]      \n"
+       "       bbit0.nt        %2, 31, 1b              \n"
+       : "=r" (stamp.low), "=r" (stamp.high), "=r" (status));
+
+       return stamp.full;
 }
 
+static struct clocksource arc_counter = {
+       .name   = "ARCv2 RTC",
+       .rating = 350,
+       .read   = arc_counter_read,
+       .mask   = CLOCKSOURCE_MASK(64),
+       .flags  = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+#else /* !CONFIG_ARC_HAS_RTC */
+
 /*
  * set 32bit TIMER1 to keep counting monotonically and wraparound
  */
@@ -123,7 +161,8 @@ int arc_counter_setup(void)
        write_aux_reg(ARC_REG_TIMER1_CNT, 0);
        write_aux_reg(ARC_REG_TIMER1_CTRL, TIMER_CTRL_NH);
 
-       return is_usable_as_clocksource();
+       /* Not usable in SMP */
+       return !IS_ENABLED(CONFIG_SMP);
 }
 
 static cycle_t arc_counter_read(struct clocksource *cs)
@@ -139,6 +178,7 @@ static struct clocksource arc_counter = {
        .flags  = CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
+#endif
 #endif
 
 /********** Clock Event Device *********/
index e00a01879025ea4d55be8d404b80cf2d2e53c22b..e0cf998932123fae4df27f8c98712f57551d8849 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/proc_fs.h>
 #include <linux/file.h>
 #include <asm/arcregs.h>
+#include <asm/irqflags.h>
 
 /*
  * Common routine to print scratch regs (r0-r12) or callee regs (r13-r25)
@@ -34,7 +35,10 @@ static noinline void print_reg_file(long *reg_rev, int start_num)
                        n += scnprintf(buf + n, len - n, "\n");
 
                /* because pt_regs has regs reversed: r12..r0, r25..r13 */
-               reg_rev--;
+               if (is_isa_arcv2() && start_num == 0)
+                       reg_rev++;
+               else
+                       reg_rev--;
        }
 
        if (start_num != 0)
@@ -152,6 +156,15 @@ static void show_ecr_verbose(struct pt_regs *regs)
                                ((cause_code == 0x02) ? "Write" : "EX"));
        } else if (vec == ECR_V_INSN_ERR) {
                pr_cont("Illegal Insn\n");
+#ifdef CONFIG_ISA_ARCV2
+       } else if (vec == ECR_V_MEM_ERR) {
+               if (cause_code == 0x00)
+                       pr_cont("Bus Error from Insn Mem\n");
+               else if (cause_code == 0x10)
+                       pr_cont("Bus Error from Data Mem\n");
+               else
+                       pr_cont("Bus Error, check PRM\n");
+#endif
        } else {
                pr_cont("Check Programmer's Manual\n");
        }
@@ -185,12 +198,20 @@ void show_regs(struct pt_regs *regs)
 
        pr_info("[STAT32]: 0x%08lx", regs->status32);
 
-#define STS_BIT(r, bit)        r->status32 & STATUS_##bit##_MASK ? #bit : ""
-       if (!user_mode(regs))
-               pr_cont(" : %2s %2s %2s %2s %2s\n",
-                       STS_BIT(regs, AE), STS_BIT(regs, A2), STS_BIT(regs, A1),
-                       STS_BIT(regs, E2), STS_BIT(regs, E1));
+#define STS_BIT(r, bit)        r->status32 & STATUS_##bit##_MASK ? #bit" " : ""
 
+#ifdef CONFIG_ISA_ARCOMPACT
+       pr_cont(" : %2s%2s%2s%2s%2s%2s%2s\n",
+                       (regs->status32 & STATUS_U_MASK) ? "U " : "K ",
+                       STS_BIT(regs, DE), STS_BIT(regs, AE),
+                       STS_BIT(regs, A2), STS_BIT(regs, A1),
+                       STS_BIT(regs, E2), STS_BIT(regs, E1));
+#else
+       pr_cont(" : %2s%2s%2s%2s\n",
+                       STS_BIT(regs, IE),
+                       (regs->status32 & STATUS_U_MASK) ? "U " : "K ",
+                       STS_BIT(regs, DE), STS_BIT(regs, AE));
+#endif
        pr_info("BTA: 0x%08lx\t SP: 0x%08lx\t FP: 0x%08lx\n",
                regs->bta, regs->sp, regs->fp);
        pr_info("LPS: 0x%08lx\tLPE: 0x%08lx\tLPC: 0x%08lx\n",
index db46e200baba298cb7d1af1c59f0e26128755395..b1656d15609750910512c9e00799c8d736f665b2 100644 (file)
@@ -5,5 +5,7 @@
 # it under the terms of the GNU General Public License version 2 as
 # published by the Free Software Foundation.
 
-lib-y  := strchr-700.o strcmp.o strcpy-700.o strlen.o
-lib-y  += memcmp.o memcpy-700.o memset.o
+lib-y  := strchr-700.o strcpy-700.o strlen.o memcmp.o
+
+lib-$(CONFIG_ISA_ARCOMPACT)    += memcpy-700.o memset.o strcmp.o
+lib-$(CONFIG_ISA_ARCV2)                += memcpy-archs.o memset-archs.o strcmp-archs.o
index 978bf8314dfb47397b9732235428a5f74fce0447..a4015e7d9ab7aa6862b41ab6138b7d64c715693e 100644 (file)
@@ -24,14 +24,32 @@ ENTRY(memcmp)
        ld      r4,[r0,0]
        ld      r5,[r1,0]
        lsr.f   lp_count,r3,3
+#ifdef CONFIG_ISA_ARCV2
+       /* In ARCv2 a branch can't be the last instruction in a zero overhead
+        * loop.
+        * So we move the branch to the start of the loop, duplicate it
+        * after the end, and set up r12 so that the branch isn't taken
+        *  initially.
+        */
+       mov_s   r12,WORD2
+       lpne    .Loop_end
+       brne    WORD2,r12,.Lodd
+       ld      WORD2,[r0,4]
+#else
        lpne    .Loop_end
        ld_s    WORD2,[r0,4]
+#endif
        ld_s    r12,[r1,4]
        brne    r4,r5,.Leven
        ld.a    r4,[r0,8]
        ld.a    r5,[r1,8]
+#ifdef CONFIG_ISA_ARCV2
+.Loop_end:
+       brne    WORD2,r12,.Lodd
+#else
        brne    WORD2,r12,.Lodd
 .Loop_end:
+#endif
        asl_s   SHIFT,SHIFT,3
        bhs_s   .Last_cmp
        brne    r4,r5,.Leven
@@ -89,7 +107,6 @@ ENTRY(memcmp)
        bset.cs r0,r0,31
 .Lodd:
        cmp_s   WORD2,r12
-
        mov_s   r0,1
        j_s.d   [blink]
        bset.cs r0,r0,31
@@ -100,14 +117,25 @@ ENTRY(memcmp)
        ldb     r4,[r0,0]
        ldb     r5,[r1,0]
        lsr.f   lp_count,r3
+#ifdef CONFIG_ISA_ARCV2
+       mov     r12,r3
        lpne    .Lbyte_end
+       brne    r3,r12,.Lbyte_odd
+#else
+       lpne    .Lbyte_end
+#endif
        ldb_s   r3,[r0,1]
        ldb     r12,[r1,1]
        brne    r4,r5,.Lbyte_even
        ldb.a   r4,[r0,2]
        ldb.a   r5,[r1,2]
+#ifdef CONFIG_ISA_ARCV2
+.Lbyte_end:
+       brne    r3,r12,.Lbyte_odd
+#else
        brne    r3,r12,.Lbyte_odd
 .Lbyte_end:
+#endif
        bcc     .Lbyte_even
        brne    r4,r5,.Lbyte_even
        ldb_s   r3,[r0,1]
diff --git a/arch/arc/lib/memcpy-archs.S b/arch/arc/lib/memcpy-archs.S
new file mode 100644 (file)
index 0000000..1b2b3ac
--- /dev/null
@@ -0,0 +1,236 @@
+/*
+ * Copyright (C) 2014-15 Synopsys, Inc. (www.synopsys.com)
+ *
+ * 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/linkage.h>
+
+#ifdef __LITTLE_ENDIAN__
+# define SHIFT_1(RX,RY,IMM)    asl     RX, RY, IMM     ; <<
+# define SHIFT_2(RX,RY,IMM)    lsr     RX, RY, IMM     ; >>
+# define MERGE_1(RX,RY,IMM)    asl     RX, RY, IMM
+# define MERGE_2(RX,RY,IMM)
+# define EXTRACT_1(RX,RY,IMM)  and     RX, RY, 0xFFFF
+# define EXTRACT_2(RX,RY,IMM)  lsr     RX, RY, IMM
+#else
+# define SHIFT_1(RX,RY,IMM)    lsr     RX, RY, IMM     ; >>
+# define SHIFT_2(RX,RY,IMM)    asl     RX, RY, IMM     ; <<
+# define MERGE_1(RX,RY,IMM)    asl     RX, RY, IMM     ; <<
+# define MERGE_2(RX,RY,IMM)    asl     RX, RY, IMM     ; <<
+# define EXTRACT_1(RX,RY,IMM)  lsr     RX, RY, IMM
+# define EXTRACT_2(RX,RY,IMM)  lsr     RX, RY, 0x08
+#endif
+
+#ifdef CONFIG_ARC_HAS_LL64
+# define PREFETCH_READ(RX)     prefetch    [RX, 56]
+# define PREFETCH_WRITE(RX)    prefetchw   [RX, 64]
+# define LOADX(DST,RX)         ldd.ab  DST, [RX, 8]
+# define STOREX(SRC,RX)                std.ab  SRC, [RX, 8]
+# define ZOLSHFT               5
+# define ZOLAND                        0x1F
+#else
+# define PREFETCH_READ(RX)     prefetch    [RX, 28]
+# define PREFETCH_WRITE(RX)    prefetchw   [RX, 32]
+# define LOADX(DST,RX)         ld.ab   DST, [RX, 4]
+# define STOREX(SRC,RX)                st.ab   SRC, [RX, 4]
+# define ZOLSHFT               4
+# define ZOLAND                        0xF
+#endif
+
+ENTRY(memcpy)
+       prefetch [r1]           ; Prefetch the read location
+       prefetchw [r0]          ; Prefetch the write location
+       mov.f   0, r2
+;;; if size is zero
+       jz.d    [blink]
+       mov     r3, r0          ; don;t clobber ret val
+
+;;; if size <= 8
+       cmp     r2, 8
+       bls.d   @smallchunk
+       mov.f   lp_count, r2
+
+       and.f   r4, r0, 0x03
+       rsub    lp_count, r4, 4
+       lpnz    @aligndestination
+       ;; LOOP BEGIN
+       ldb.ab  r5, [r1,1]
+       sub     r2, r2, 1
+       stb.ab  r5, [r3,1]
+aligndestination:
+
+;;; Check the alignment of the source
+       and.f   r4, r1, 0x03
+       bnz.d   @sourceunaligned
+
+;;; CASE 0: Both source and destination are 32bit aligned
+;;; Convert len to Dwords, unfold x4
+       lsr.f   lp_count, r2, ZOLSHFT
+       lpnz    @copy32_64bytes
+       ;; LOOP START
+       LOADX (r6, r1)
+       PREFETCH_READ (r1)
+       PREFETCH_WRITE (r3)
+       LOADX (r8, r1)
+       LOADX (r10, r1)
+       LOADX (r4, r1)
+       STOREX (r6, r3)
+       STOREX (r8, r3)
+       STOREX (r10, r3)
+       STOREX (r4, r3)
+copy32_64bytes:
+
+       and.f   lp_count, r2, ZOLAND ;Last remaining 31 bytes
+smallchunk:
+       lpnz    @copyremainingbytes
+       ;; LOOP START
+       ldb.ab  r5, [r1,1]
+       stb.ab  r5, [r3,1]
+copyremainingbytes:
+
+       j       [blink]
+;;; END CASE 0
+
+sourceunaligned:
+       cmp     r4, 2
+       beq.d   @unalignedOffby2
+       sub     r2, r2, 1
+
+       bhi.d   @unalignedOffby3
+       ldb.ab  r5, [r1, 1]
+
+;;; CASE 1: The source is unaligned, off by 1
+       ;; Hence I need to read 1 byte for a 16bit alignment
+       ;; and 2bytes to reach 32bit alignment
+       ldh.ab  r6, [r1, 2]
+       sub     r2, r2, 2
+       ;; Convert to words, unfold x2
+       lsr.f   lp_count, r2, 3
+       MERGE_1 (r6, r6, 8)
+       MERGE_2 (r5, r5, 24)
+       or      r5, r5, r6
+
+       ;; Both src and dst are aligned
+       lpnz    @copy8bytes_1
+       ;; LOOP START
+       ld.ab   r6, [r1, 4]
+       prefetch [r1, 28]       ;Prefetch the next read location
+       ld.ab   r8, [r1,4]
+       prefetchw [r3, 32]      ;Prefetch the next write location
+
+       SHIFT_1 (r7, r6, 24)
+       or      r7, r7, r5
+       SHIFT_2 (r5, r6, 8)
+
+       SHIFT_1 (r9, r8, 24)
+       or      r9, r9, r5
+       SHIFT_2 (r5, r8, 8)
+
+       st.ab   r7, [r3, 4]
+       st.ab   r9, [r3, 4]
+copy8bytes_1:
+
+       ;; Write back the remaining 16bits
+       EXTRACT_1 (r6, r5, 16)
+       sth.ab  r6, [r3, 2]
+       ;; Write back the remaining 8bits
+       EXTRACT_2 (r5, r5, 16)
+       stb.ab  r5, [r3, 1]
+
+       and.f   lp_count, r2, 0x07 ;Last 8bytes
+       lpnz    @copybytewise_1
+       ;; LOOP START
+       ldb.ab  r6, [r1,1]
+       stb.ab  r6, [r3,1]
+copybytewise_1:
+       j       [blink]
+
+unalignedOffby2:
+;;; CASE 2: The source is unaligned, off by 2
+       ldh.ab  r5, [r1, 2]
+       sub     r2, r2, 1
+
+       ;; Both src and dst are aligned
+       ;; Convert to words, unfold x2
+       lsr.f   lp_count, r2, 3
+#ifdef __BIG_ENDIAN__
+       asl.nz  r5, r5, 16
+#endif
+       lpnz    @copy8bytes_2
+       ;; LOOP START
+       ld.ab   r6, [r1, 4]
+       prefetch [r1, 28]       ;Prefetch the next read location
+       ld.ab   r8, [r1,4]
+       prefetchw [r3, 32]      ;Prefetch the next write location
+
+       SHIFT_1 (r7, r6, 16)
+       or      r7, r7, r5
+       SHIFT_2 (r5, r6, 16)
+
+       SHIFT_1 (r9, r8, 16)
+       or      r9, r9, r5
+       SHIFT_2 (r5, r8, 16)
+
+       st.ab   r7, [r3, 4]
+       st.ab   r9, [r3, 4]
+copy8bytes_2:
+
+#ifdef __BIG_ENDIAN__
+       lsr.nz  r5, r5, 16
+#endif
+       sth.ab  r5, [r3, 2]
+
+       and.f   lp_count, r2, 0x07 ;Last 8bytes
+       lpnz    @copybytewise_2
+       ;; LOOP START
+       ldb.ab  r6, [r1,1]
+       stb.ab  r6, [r3,1]
+copybytewise_2:
+       j       [blink]
+
+unalignedOffby3:
+;;; CASE 3: The source is unaligned, off by 3
+;;; Hence, I need to read 1byte for achieve the 32bit alignment
+
+       ;; Both src and dst are aligned
+       ;; Convert to words, unfold x2
+       lsr.f   lp_count, r2, 3
+#ifdef __BIG_ENDIAN__
+       asl.ne  r5, r5, 24
+#endif
+       lpnz    @copy8bytes_3
+       ;; LOOP START
+       ld.ab   r6, [r1, 4]
+       prefetch [r1, 28]       ;Prefetch the next read location
+       ld.ab   r8, [r1,4]
+       prefetch [r3, 32]       ;Prefetch the next write location
+
+       SHIFT_1 (r7, r6, 8)
+       or      r7, r7, r5
+       SHIFT_2 (r5, r6, 24)
+
+       SHIFT_1 (r9, r8, 8)
+       or      r9, r9, r5
+       SHIFT_2 (r5, r8, 24)
+
+       st.ab   r7, [r3, 4]
+       st.ab   r9, [r3, 4]
+copy8bytes_3:
+
+#ifdef __BIG_ENDIAN__
+       lsr.nz  r5, r5, 24
+#endif
+       stb.ab  r5, [r3, 1]
+
+       and.f   lp_count, r2, 0x07 ;Last 8bytes
+       lpnz    @copybytewise_3
+       ;; LOOP START
+       ldb.ab  r6, [r1,1]
+       stb.ab  r6, [r3,1]
+copybytewise_3:
+       j       [blink]
+
+END(memcpy)
diff --git a/arch/arc/lib/memset-archs.S b/arch/arc/lib/memset-archs.S
new file mode 100644 (file)
index 0000000..92d573c
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2014-15 Synopsys, Inc. (www.synopsys.com)
+ *
+ * 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/linkage.h>
+
+#undef PREALLOC_NOT_AVAIL
+
+#ifdef PREALLOC_NOT_AVAIL
+#define PREWRITE(A,B)  prefetchw [(A),(B)]
+#else
+#define PREWRITE(A,B)  prealloc [(A),(B)]
+#endif
+
+ENTRY(memset)
+       prefetchw [r0]          ; Prefetch the write location
+       mov.f   0, r2
+;;; if size is zero
+       jz.d    [blink]
+       mov     r3, r0          ; don't clobber ret val
+
+;;; if length < 8
+       brls.d.nt       r2, 8, .Lsmallchunk
+       mov.f   lp_count,r2
+
+       and.f   r4, r0, 0x03
+       rsub    lp_count, r4, 4
+       lpnz    @.Laligndestination
+       ;; LOOP BEGIN
+       stb.ab  r1, [r3,1]
+       sub     r2, r2, 1
+.Laligndestination:
+
+;;; Destination is aligned
+       and     r1, r1, 0xFF
+       asl     r4, r1, 8
+       or      r4, r4, r1
+       asl     r5, r4, 16
+       or      r5, r5, r4
+       mov     r4, r5
+
+       sub3    lp_count, r2, 8
+       cmp     r2, 64
+       bmsk.hi r2, r2, 5
+       mov.ls  lp_count, 0
+       add3.hi r2, r2, 8
+
+;;; Convert len to Dwords, unfold x8
+       lsr.f   lp_count, lp_count, 6
+       lpnz    @.Lset64bytes
+       ;; LOOP START
+       PREWRITE(r3, 64)        ;Prefetch the next write location
+       std.ab  r4, [r3, 8]
+       std.ab  r4, [r3, 8]
+       std.ab  r4, [r3, 8]
+       std.ab  r4, [r3, 8]
+       std.ab  r4, [r3, 8]
+       std.ab  r4, [r3, 8]
+       std.ab  r4, [r3, 8]
+       std.ab  r4, [r3, 8]
+.Lset64bytes:
+
+       lsr.f   lp_count, r2, 5 ;Last remaining  max 124 bytes
+       lpnz    .Lset32bytes
+       ;; LOOP START
+       prefetchw   [r3, 32]    ;Prefetch the next write location
+       std.ab  r4, [r3, 8]
+       std.ab  r4, [r3, 8]
+       std.ab  r4, [r3, 8]
+       std.ab  r4, [r3, 8]
+.Lset32bytes:
+
+       and.f   lp_count, r2, 0x1F ;Last remaining 31 bytes
+.Lsmallchunk:
+       lpnz    .Lcopy3bytes
+       ;; LOOP START
+       stb.ab  r1, [r3, 1]
+.Lcopy3bytes:
+
+       j       [blink]
+
+END(memset)
+
+ENTRY(memzero)
+    ; adjust bzero args to memset args
+    mov r2, r1
+    b.d  memset    ;tail call so need to tinker with blink
+    mov r1, 0
+END(memzero)
diff --git a/arch/arc/lib/strcmp-archs.S b/arch/arc/lib/strcmp-archs.S
new file mode 100644 (file)
index 0000000..4f338ee
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2014-15 Synopsys, Inc. (www.synopsys.com)
+ *
+ * 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/linkage.h>
+
+ENTRY(strcmp)
+       or      r2, r0, r1
+       bmsk_s  r2, r2, 1
+       brne    r2, 0, @.Lcharloop
+
+;;; s1 and s2 are word aligned
+       ld.ab   r2, [r0, 4]
+
+       mov_s   r12, 0x01010101
+       ror     r11, r12
+       .align  4
+.LwordLoop:
+       ld.ab   r3, [r1, 4]
+       ;; Detect NULL char in str1
+       sub     r4, r2, r12
+       ld.ab   r5, [r0, 4]
+       bic     r4, r4, r2
+       and     r4, r4, r11
+       brne.d.nt       r4, 0, .LfoundNULL
+       ;; Check if the read locations are the same
+       cmp     r2, r3
+       beq.d   .LwordLoop
+       mov.eq  r2, r5
+
+       ;; A match is found, spot it out
+#ifdef __LITTLE_ENDIAN__
+       swape   r3, r3
+       mov_s   r0, 1
+       swape   r2, r2
+#else
+       mov_s   r0, 1
+#endif
+       cmp_s   r2, r3
+       j_s.d   [blink]
+       bset.lo r0, r0, 31
+
+       .align 4
+.LfoundNULL:
+#ifdef __BIG_ENDIAN__
+       swape   r4, r4
+       swape   r2, r2
+       swape   r3, r3
+#endif
+       ;; Find null byte
+       ffs     r0, r4
+       bmsk    r2, r2, r0
+       bmsk    r3, r3, r0
+       swape   r2, r2
+       swape   r3, r3
+       ;; make the return value
+       sub.f   r0, r2, r3
+       mov.hi  r0, 1
+       j_s.d   [blink]
+       bset.lo r0, r0, 31
+
+       .align 4
+.Lcharloop:
+       ldb.ab  r2, [r0, 1]
+       ldb.ab  r3, [r1, 1]
+       nop
+       breq    r2, 0, .Lcmpend
+       breq    r2, r3, .Lcharloop
+
+       .align 4
+.Lcmpend:
+       j_s.d   [blink]
+       sub     r0, r2, r3
+END(strcmp)
index ac95cc239c1e47d3d2f5a133b1d66936c6af0b91..7beb941556c3f73567b8174b6dc1cd15c2ef2d49 100644 (file)
@@ -7,4 +7,4 @@
 #
 
 obj-y  := extable.o ioremap.o dma.o fault.o init.o
-obj-y  += tlb.o tlbex.o cache_arc700.o mmap.o
+obj-y  += tlb.o tlbex.o cache.o mmap.o
diff --git a/arch/arc/mm/cache.c b/arch/arc/mm/cache.c
new file mode 100644 (file)
index 0000000..b29d62e
--- /dev/null
@@ -0,0 +1,843 @@
+/*
+ * ARC Cache Management
+ *
+ * Copyright (C) 2014-15 Synopsys, Inc. (www.synopsys.com)
+ * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
+ *
+ * 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/module.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/cache.h>
+#include <linux/mmu_context.h>
+#include <linux/syscalls.h>
+#include <linux/uaccess.h>
+#include <linux/pagemap.h>
+#include <asm/cacheflush.h>
+#include <asm/cachectl.h>
+#include <asm/setup.h>
+
+static int l2_line_sz;
+
+void (*_cache_line_loop_ic_fn)(unsigned long paddr, unsigned long vaddr,
+                              unsigned long sz, const int cacheop);
+
+char *arc_cache_mumbojumbo(int c, char *buf, int len)
+{
+       int n = 0;
+       struct cpuinfo_arc_cache *p;
+
+#define PR_CACHE(p, cfg, str)                                          \
+       if (!(p)->ver)                                                  \
+               n += scnprintf(buf + n, len - n, str"\t\t: N/A\n");     \
+       else                                                            \
+               n += scnprintf(buf + n, len - n,                        \
+                       str"\t\t: %uK, %dway/set, %uB Line, %s%s%s\n",  \
+                       (p)->sz_k, (p)->assoc, (p)->line_len,           \
+                       (p)->vipt ? "VIPT" : "PIPT",                    \
+                       (p)->alias ? " aliasing" : "",                  \
+                       IS_ENABLED(cfg) ? "" : " (not used)");
+
+       PR_CACHE(&cpuinfo_arc700[c].icache, CONFIG_ARC_HAS_ICACHE, "I-Cache");
+       PR_CACHE(&cpuinfo_arc700[c].dcache, CONFIG_ARC_HAS_DCACHE, "D-Cache");
+
+       p = &cpuinfo_arc700[c].slc;
+       if (p->ver)
+               n += scnprintf(buf + n, len - n,
+                       "SLC\t\t: %uK, %uB Line\n", p->sz_k, p->line_len);
+
+       return buf;
+}
+
+/*
+ * Read the Cache Build Confuration Registers, Decode them and save into
+ * the cpuinfo structure for later use.
+ * No Validation done here, simply read/convert the BCRs
+ */
+void read_decode_cache_bcr(void)
+{
+       struct cpuinfo_arc_cache *p_ic, *p_dc, *p_slc;
+       unsigned int cpu = smp_processor_id();
+       struct bcr_cache {
+#ifdef CONFIG_CPU_BIG_ENDIAN
+               unsigned int pad:12, line_len:4, sz:4, config:4, ver:8;
+#else
+               unsigned int ver:8, config:4, sz:4, line_len:4, pad:12;
+#endif
+       } ibcr, dbcr;
+
+       struct bcr_generic sbcr;
+
+       struct bcr_slc_cfg {
+#ifdef CONFIG_CPU_BIG_ENDIAN
+               unsigned int pad:24, way:2, lsz:2, sz:4;
+#else
+               unsigned int sz:4, lsz:2, way:2, pad:24;
+#endif
+       } slc_cfg;
+
+       p_ic = &cpuinfo_arc700[cpu].icache;
+       READ_BCR(ARC_REG_IC_BCR, ibcr);
+
+       if (!ibcr.ver)
+               goto dc_chk;
+
+       if (ibcr.ver <= 3) {
+               BUG_ON(ibcr.config != 3);
+               p_ic->assoc = 2;                /* Fixed to 2w set assoc */
+       } else if (ibcr.ver >= 4) {
+               p_ic->assoc = 1 << ibcr.config; /* 1,2,4,8 */
+       }
+
+       p_ic->line_len = 8 << ibcr.line_len;
+       p_ic->sz_k = 1 << (ibcr.sz - 1);
+       p_ic->ver = ibcr.ver;
+       p_ic->vipt = 1;
+       p_ic->alias = p_ic->sz_k/p_ic->assoc/TO_KB(PAGE_SIZE) > 1;
+
+dc_chk:
+       p_dc = &cpuinfo_arc700[cpu].dcache;
+       READ_BCR(ARC_REG_DC_BCR, dbcr);
+
+       if (!dbcr.ver)
+               goto slc_chk;
+
+       if (dbcr.ver <= 3) {
+               BUG_ON(dbcr.config != 2);
+               p_dc->assoc = 4;                /* Fixed to 4w set assoc */
+               p_dc->vipt = 1;
+               p_dc->alias = p_dc->sz_k/p_dc->assoc/TO_KB(PAGE_SIZE) > 1;
+       } else if (dbcr.ver >= 4) {
+               p_dc->assoc = 1 << dbcr.config; /* 1,2,4,8 */
+               p_dc->vipt = 0;
+               p_dc->alias = 0;                /* PIPT so can't VIPT alias */
+       }
+
+       p_dc->line_len = 16 << dbcr.line_len;
+       p_dc->sz_k = 1 << (dbcr.sz - 1);
+       p_dc->ver = dbcr.ver;
+
+slc_chk:
+       if (!is_isa_arcv2())
+               return;
+
+       p_slc = &cpuinfo_arc700[cpu].slc;
+       READ_BCR(ARC_REG_SLC_BCR, sbcr);
+       if (sbcr.ver) {
+               READ_BCR(ARC_REG_SLC_CFG, slc_cfg);
+               p_slc->ver = sbcr.ver;
+               p_slc->sz_k = 128 << slc_cfg.sz;
+               l2_line_sz = p_slc->line_len = (slc_cfg.lsz == 0) ? 128 : 64;
+       }
+}
+
+/*
+ * Line Operation on {I,D}-Cache
+ */
+
+#define OP_INV         0x1
+#define OP_FLUSH       0x2
+#define OP_FLUSH_N_INV 0x3
+#define OP_INV_IC      0x4
+
+/*
+ *             I-Cache Aliasing in ARC700 VIPT caches (MMU v1-v3)
+ *
+ * ARC VIPT I-cache uses vaddr to index into cache and paddr to match the tag.
+ * The orig Cache Management Module "CDU" only required paddr to invalidate a
+ * certain line since it sufficed as index in Non-Aliasing VIPT cache-geometry.
+ * Infact for distinct V1,V2,P: all of {V1-P},{V2-P},{P-P} would end up fetching
+ * the exact same line.
+ *
+ * However for larger Caches (way-size > page-size) - i.e. in Aliasing config,
+ * paddr alone could not be used to correctly index the cache.
+ *
+ * ------------------
+ * MMU v1/v2 (Fixed Page Size 8k)
+ * ------------------
+ * The solution was to provide CDU with these additonal vaddr bits. These
+ * would be bits [x:13], x would depend on cache-geometry, 13 comes from
+ * standard page size of 8k.
+ * H/w folks chose [17:13] to be a future safe range, and moreso these 5 bits
+ * of vaddr could easily be "stuffed" in the paddr as bits [4:0] since the
+ * orig 5 bits of paddr were anyways ignored by CDU line ops, as they
+ * represent the offset within cache-line. The adv of using this "clumsy"
+ * interface for additional info was no new reg was needed in CDU programming
+ * model.
+ *
+ * 17:13 represented the max num of bits passable, actual bits needed were
+ * fewer, based on the num-of-aliases possible.
+ * -for 2 alias possibility, only bit 13 needed (32K cache)
+ * -for 4 alias possibility, bits 14:13 needed (64K cache)
+ *
+ * ------------------
+ * MMU v3
+ * ------------------
+ * This ver of MMU supports variable page sizes (1k-16k): although Linux will
+ * only support 8k (default), 16k and 4k.
+ * However from hardware perspective, smaller page sizes aggrevate aliasing
+ * meaning more vaddr bits needed to disambiguate the cache-line-op ;
+ * the existing scheme of piggybacking won't work for certain configurations.
+ * Two new registers IC_PTAG and DC_PTAG inttoduced.
+ * "tag" bits are provided in PTAG, index bits in existing IVIL/IVDL/FLDL regs
+ */
+
+static inline
+void __cache_line_loop_v2(unsigned long paddr, unsigned long vaddr,
+                         unsigned long sz, const int op)
+{
+       unsigned int aux_cmd;
+       int num_lines;
+       const int full_page = __builtin_constant_p(sz) && sz == PAGE_SIZE;
+
+       if (op == OP_INV_IC) {
+               aux_cmd = ARC_REG_IC_IVIL;
+       } else {
+               /* d$ cmd: INV (discard or wback-n-discard) OR FLUSH (wback) */
+               aux_cmd = op & OP_INV ? ARC_REG_DC_IVDL : ARC_REG_DC_FLDL;
+       }
+
+       /* Ensure we properly floor/ceil the non-line aligned/sized requests
+        * and have @paddr - aligned to cache line and integral @num_lines.
+        * This however can be avoided for page sized since:
+        *  -@paddr will be cache-line aligned already (being page aligned)
+        *  -@sz will be integral multiple of line size (being page sized).
+        */
+       if (!full_page) {
+               sz += paddr & ~CACHE_LINE_MASK;
+               paddr &= CACHE_LINE_MASK;
+               vaddr &= CACHE_LINE_MASK;
+       }
+
+       num_lines = DIV_ROUND_UP(sz, L1_CACHE_BYTES);
+
+       /* MMUv2 and before: paddr contains stuffed vaddrs bits */
+       paddr |= (vaddr >> PAGE_SHIFT) & 0x1F;
+
+       while (num_lines-- > 0) {
+               write_aux_reg(aux_cmd, paddr);
+               paddr += L1_CACHE_BYTES;
+       }
+}
+
+static inline
+void __cache_line_loop_v3(unsigned long paddr, unsigned long vaddr,
+                         unsigned long sz, const int op)
+{
+       unsigned int aux_cmd, aux_tag;
+       int num_lines;
+       const int full_page = __builtin_constant_p(sz) && sz == PAGE_SIZE;
+
+       if (op == OP_INV_IC) {
+               aux_cmd = ARC_REG_IC_IVIL;
+               aux_tag = ARC_REG_IC_PTAG;
+       } else {
+               aux_cmd = op & OP_INV ? ARC_REG_DC_IVDL : ARC_REG_DC_FLDL;
+               aux_tag = ARC_REG_DC_PTAG;
+       }
+
+       /* Ensure we properly floor/ceil the non-line aligned/sized requests
+        * and have @paddr - aligned to cache line and integral @num_lines.
+        * This however can be avoided for page sized since:
+        *  -@paddr will be cache-line aligned already (being page aligned)
+        *  -@sz will be integral multiple of line size (being page sized).
+        */
+       if (!full_page) {
+               sz += paddr & ~CACHE_LINE_MASK;
+               paddr &= CACHE_LINE_MASK;
+               vaddr &= CACHE_LINE_MASK;
+       }
+       num_lines = DIV_ROUND_UP(sz, L1_CACHE_BYTES);
+
+       /*
+        * MMUv3, cache ops require paddr in PTAG reg
+        * if V-P const for loop, PTAG can be written once outside loop
+        */
+       if (full_page)
+               write_aux_reg(aux_tag, paddr);
+
+       while (num_lines-- > 0) {
+               if (!full_page) {
+                       write_aux_reg(aux_tag, paddr);
+                       paddr += L1_CACHE_BYTES;
+               }
+
+               write_aux_reg(aux_cmd, vaddr);
+               vaddr += L1_CACHE_BYTES;
+       }
+}
+
+/*
+ * In HS38x (MMU v4), although icache is VIPT, only paddr is needed for cache
+ * maintenance ops (in IVIL reg), as long as icache doesn't alias.
+ *
+ * For Aliasing icache, vaddr is also needed (in IVIL), while paddr is
+ * specified in PTAG (similar to MMU v3)
+ */
+static inline
+void __cache_line_loop_v4(unsigned long paddr, unsigned long vaddr,
+                         unsigned long sz, const int cacheop)
+{
+       unsigned int aux_cmd;
+       int num_lines;
+       const int full_page_op = __builtin_constant_p(sz) && sz == PAGE_SIZE;
+
+       if (cacheop == OP_INV_IC) {
+               aux_cmd = ARC_REG_IC_IVIL;
+       } else {
+               /* d$ cmd: INV (discard or wback-n-discard) OR FLUSH (wback) */
+               aux_cmd = cacheop & OP_INV ? ARC_REG_DC_IVDL : ARC_REG_DC_FLDL;
+       }
+
+       /* Ensure we properly floor/ceil the non-line aligned/sized requests
+        * and have @paddr - aligned to cache line and integral @num_lines.
+        * This however can be avoided for page sized since:
+        *  -@paddr will be cache-line aligned already (being page aligned)
+        *  -@sz will be integral multiple of line size (being page sized).
+        */
+       if (!full_page_op) {
+               sz += paddr & ~CACHE_LINE_MASK;
+               paddr &= CACHE_LINE_MASK;
+       }
+
+       num_lines = DIV_ROUND_UP(sz, L1_CACHE_BYTES);
+
+       while (num_lines-- > 0) {
+               write_aux_reg(aux_cmd, paddr);
+               paddr += L1_CACHE_BYTES;
+       }
+}
+
+#if (CONFIG_ARC_MMU_VER < 3)
+#define __cache_line_loop      __cache_line_loop_v2
+#elif (CONFIG_ARC_MMU_VER == 3)
+#define __cache_line_loop      __cache_line_loop_v3
+#elif (CONFIG_ARC_MMU_VER > 3)
+#define __cache_line_loop      __cache_line_loop_v4
+#endif
+
+#ifdef CONFIG_ARC_HAS_DCACHE
+
+/***************************************************************
+ * Machine specific helpers for Entire D-Cache or Per Line ops
+ */
+
+static inline void __before_dc_op(const int op)
+{
+       if (op == OP_FLUSH_N_INV) {
+               /* Dcache provides 2 cmd: FLUSH or INV
+                * INV inturn has sub-modes: DISCARD or FLUSH-BEFORE
+                * flush-n-inv is achieved by INV cmd but with IM=1
+                * So toggle INV sub-mode depending on op request and default
+                */
+               const unsigned int ctl = ARC_REG_DC_CTRL;
+               write_aux_reg(ctl, read_aux_reg(ctl) | DC_CTRL_INV_MODE_FLUSH);
+       }
+}
+
+static inline void __after_dc_op(const int op)
+{
+       if (op & OP_FLUSH) {
+               const unsigned int ctl = ARC_REG_DC_CTRL;
+               unsigned int reg;
+
+               /* flush / flush-n-inv both wait */
+               while ((reg = read_aux_reg(ctl)) & DC_CTRL_FLUSH_STATUS)
+                       ;
+
+               /* Switch back to default Invalidate mode */
+               if (op == OP_FLUSH_N_INV)
+                       write_aux_reg(ctl, reg & ~DC_CTRL_INV_MODE_FLUSH);
+       }
+}
+
+/*
+ * Operation on Entire D-Cache
+ * @op = {OP_INV, OP_FLUSH, OP_FLUSH_N_INV}
+ * Note that constant propagation ensures all the checks are gone
+ * in generated code
+ */
+static inline void __dc_entire_op(const int op)
+{
+       int aux;
+
+       __before_dc_op(op);
+
+       if (op & OP_INV)        /* Inv or flush-n-inv use same cmd reg */
+               aux = ARC_REG_DC_IVDC;
+       else
+               aux = ARC_REG_DC_FLSH;
+
+       write_aux_reg(aux, 0x1);
+
+       __after_dc_op(op);
+}
+
+/* For kernel mappings cache operation: index is same as paddr */
+#define __dc_line_op_k(p, sz, op)      __dc_line_op(p, p, sz, op)
+
+/*
+ * D-Cache Line ops: Per Line INV (discard or wback+discard) or FLUSH (wback)
+ */
+static inline void __dc_line_op(unsigned long paddr, unsigned long vaddr,
+                               unsigned long sz, const int op)
+{
+       unsigned long flags;
+
+       local_irq_save(flags);
+
+       __before_dc_op(op);
+
+       __cache_line_loop(paddr, vaddr, sz, op);
+
+       __after_dc_op(op);
+
+       local_irq_restore(flags);
+}
+
+#else
+
+#define __dc_entire_op(op)
+#define __dc_line_op(paddr, vaddr, sz, op)
+#define __dc_line_op_k(paddr, sz, op)
+
+#endif /* CONFIG_ARC_HAS_DCACHE */
+
+#ifdef CONFIG_ARC_HAS_ICACHE
+
+static inline void __ic_entire_inv(void)
+{
+       write_aux_reg(ARC_REG_IC_IVIC, 1);
+       read_aux_reg(ARC_REG_IC_CTRL);  /* blocks */
+}
+
+static inline void
+__ic_line_inv_vaddr_local(unsigned long paddr, unsigned long vaddr,
+                         unsigned long sz)
+{
+       unsigned long flags;
+
+       local_irq_save(flags);
+       (*_cache_line_loop_ic_fn)(paddr, vaddr, sz, OP_INV_IC);
+       local_irq_restore(flags);
+}
+
+#ifndef CONFIG_SMP
+
+#define __ic_line_inv_vaddr(p, v, s)   __ic_line_inv_vaddr_local(p, v, s)
+
+#else
+
+struct ic_inv_args {
+       unsigned long paddr, vaddr;
+       int sz;
+};
+
+static void __ic_line_inv_vaddr_helper(void *info)
+{
+        struct ic_inv_args *ic_inv = info;
+
+        __ic_line_inv_vaddr_local(ic_inv->paddr, ic_inv->vaddr, ic_inv->sz);
+}
+
+static void __ic_line_inv_vaddr(unsigned long paddr, unsigned long vaddr,
+                               unsigned long sz)
+{
+       struct ic_inv_args ic_inv = {
+               .paddr = paddr,
+               .vaddr = vaddr,
+               .sz    = sz
+       };
+
+       on_each_cpu(__ic_line_inv_vaddr_helper, &ic_inv, 1);
+}
+
+#endif /* CONFIG_SMP */
+
+#else  /* !CONFIG_ARC_HAS_ICACHE */
+
+#define __ic_entire_inv()
+#define __ic_line_inv_vaddr(pstart, vstart, sz)
+
+#endif /* CONFIG_ARC_HAS_ICACHE */
+
+noinline void slc_op(unsigned long paddr, unsigned long sz, const int op)
+{
+#ifdef CONFIG_ISA_ARCV2
+       unsigned long flags;
+       unsigned int ctrl;
+
+       local_irq_save(flags);
+
+       /*
+        * The Region Flush operation is specified by CTRL.RGN_OP[11..9]
+        *  - b'000 (default) is Flush,
+        *  - b'001 is Invalidate if CTRL.IM == 0
+        *  - b'001 is Flush-n-Invalidate if CTRL.IM == 1
+        */
+       ctrl = read_aux_reg(ARC_REG_SLC_CTRL);
+
+       /* Don't rely on default value of IM bit */
+       if (!(op & OP_FLUSH))           /* i.e. OP_INV */
+               ctrl &= ~SLC_CTRL_IM;   /* clear IM: Disable flush before Inv */
+       else
+               ctrl |= SLC_CTRL_IM;
+
+       if (op & OP_INV)
+               ctrl |= SLC_CTRL_RGN_OP_INV;    /* Inv or flush-n-inv */
+       else
+               ctrl &= ~SLC_CTRL_RGN_OP_INV;
+
+       write_aux_reg(ARC_REG_SLC_CTRL, ctrl);
+
+       /*
+        * Lower bits are ignored, no need to clip
+        * END needs to be setup before START (latter triggers the operation)
+        * END can't be same as START, so add (l2_line_sz - 1) to sz
+        */
+       write_aux_reg(ARC_REG_SLC_RGN_END, (paddr + sz + l2_line_sz - 1));
+       write_aux_reg(ARC_REG_SLC_RGN_START, paddr);
+
+       while (read_aux_reg(ARC_REG_SLC_CTRL) & SLC_CTRL_BUSY);
+
+       local_irq_restore(flags);
+#endif
+}
+
+static inline int need_slc_flush(void)
+{
+       return is_isa_arcv2() && l2_line_sz;
+}
+
+/***********************************************************
+ * Exported APIs
+ */
+
+/*
+ * Handle cache congruency of kernel and userspace mappings of page when kernel
+ * writes-to/reads-from
+ *
+ * The idea is to defer flushing of kernel mapping after a WRITE, possible if:
+ *  -dcache is NOT aliasing, hence any U/K-mappings of page are congruent
+ *  -U-mapping doesn't exist yet for page (finalised in update_mmu_cache)
+ *  -In SMP, if hardware caches are coherent
+ *
+ * There's a corollary case, where kernel READs from a userspace mapped page.
+ * If the U-mapping is not congruent to to K-mapping, former needs flushing.
+ */
+void flush_dcache_page(struct page *page)
+{
+       struct address_space *mapping;
+
+       if (!cache_is_vipt_aliasing()) {
+               clear_bit(PG_dc_clean, &page->flags);
+               return;
+       }
+
+       /* don't handle anon pages here */
+       mapping = page_mapping(page);
+       if (!mapping)
+               return;
+
+       /*
+        * pagecache page, file not yet mapped to userspace
+        * Make a note that K-mapping is dirty
+        */
+       if (!mapping_mapped(mapping)) {
+               clear_bit(PG_dc_clean, &page->flags);
+       } else if (page_mapped(page)) {
+
+               /* kernel reading from page with U-mapping */
+               unsigned long paddr = (unsigned long)page_address(page);
+               unsigned long vaddr = page->index << PAGE_CACHE_SHIFT;
+
+               if (addr_not_cache_congruent(paddr, vaddr))
+                       __flush_dcache_page(paddr, vaddr);
+       }
+}
+EXPORT_SYMBOL(flush_dcache_page);
+
+void dma_cache_wback_inv(unsigned long start, unsigned long sz)
+{
+       __dc_line_op_k(start, sz, OP_FLUSH_N_INV);
+
+       if (need_slc_flush())
+               slc_op(start, sz, OP_FLUSH_N_INV);
+}
+EXPORT_SYMBOL(dma_cache_wback_inv);
+
+void dma_cache_inv(unsigned long start, unsigned long sz)
+{
+       __dc_line_op_k(start, sz, OP_INV);
+
+       if (need_slc_flush())
+               slc_op(start, sz, OP_INV);
+}
+EXPORT_SYMBOL(dma_cache_inv);
+
+void dma_cache_wback(unsigned long start, unsigned long sz)
+{
+       __dc_line_op_k(start, sz, OP_FLUSH);
+
+       if (need_slc_flush())
+               slc_op(start, sz, OP_FLUSH);
+}
+EXPORT_SYMBOL(dma_cache_wback);
+
+/*
+ * This is API for making I/D Caches consistent when modifying
+ * kernel code (loadable modules, kprobes, kgdb...)
+ * This is called on insmod, with kernel virtual address for CODE of
+ * the module. ARC cache maintenance ops require PHY address thus we
+ * need to convert vmalloc addr to PHY addr
+ */
+void flush_icache_range(unsigned long kstart, unsigned long kend)
+{
+       unsigned int tot_sz;
+
+       WARN(kstart < TASK_SIZE, "%s() can't handle user vaddr", __func__);
+
+       /* Shortcut for bigger flush ranges.
+        * Here we don't care if this was kernel virtual or phy addr
+        */
+       tot_sz = kend - kstart;
+       if (tot_sz > PAGE_SIZE) {
+               flush_cache_all();
+               return;
+       }
+
+       /* Case: Kernel Phy addr (0x8000_0000 onwards) */
+       if (likely(kstart > PAGE_OFFSET)) {
+               /*
+                * The 2nd arg despite being paddr will be used to index icache
+                * This is OK since no alternate virtual mappings will exist
+                * given the callers for this case: kprobe/kgdb in built-in
+                * kernel code only.
+                */
+               __sync_icache_dcache(kstart, kstart, kend - kstart);
+               return;
+       }
+
+       /*
+        * Case: Kernel Vaddr (0x7000_0000 to 0x7fff_ffff)
+        * (1) ARC Cache Maintenance ops only take Phy addr, hence special
+        *     handling of kernel vaddr.
+        *
+        * (2) Despite @tot_sz being < PAGE_SIZE (bigger cases handled already),
+        *     it still needs to handle  a 2 page scenario, where the range
+        *     straddles across 2 virtual pages and hence need for loop
+        */
+       while (tot_sz > 0) {
+               unsigned int off, sz;
+               unsigned long phy, pfn;
+
+               off = kstart % PAGE_SIZE;
+               pfn = vmalloc_to_pfn((void *)kstart);
+               phy = (pfn << PAGE_SHIFT) + off;
+               sz = min_t(unsigned int, tot_sz, PAGE_SIZE - off);
+               __sync_icache_dcache(phy, kstart, sz);
+               kstart += sz;
+               tot_sz -= sz;
+       }
+}
+EXPORT_SYMBOL(flush_icache_range);
+
+/*
+ * General purpose helper to make I and D cache lines consistent.
+ * @paddr is phy addr of region
+ * @vaddr is typically user vaddr (breakpoint) or kernel vaddr (vmalloc)
+ *    However in one instance, when called by kprobe (for a breakpt in
+ *    builtin kernel code) @vaddr will be paddr only, meaning CDU operation will
+ *    use a paddr to index the cache (despite VIPT). This is fine since since a
+ *    builtin kernel page will not have any virtual mappings.
+ *    kprobe on loadable module will be kernel vaddr.
+ */
+void __sync_icache_dcache(unsigned long paddr, unsigned long vaddr, int len)
+{
+       __dc_line_op(paddr, vaddr, len, OP_FLUSH_N_INV);
+       __ic_line_inv_vaddr(paddr, vaddr, len);
+}
+
+/* wrapper to compile time eliminate alignment checks in flush loop */
+void __inv_icache_page(unsigned long paddr, unsigned long vaddr)
+{
+       __ic_line_inv_vaddr(paddr, vaddr, PAGE_SIZE);
+}
+
+/*
+ * wrapper to clearout kernel or userspace mappings of a page
+ * For kernel mappings @vaddr == @paddr
+ */
+void __flush_dcache_page(unsigned long paddr, unsigned long vaddr)
+{
+       __dc_line_op(paddr, vaddr & PAGE_MASK, PAGE_SIZE, OP_FLUSH_N_INV);
+}
+
+noinline void flush_cache_all(void)
+{
+       unsigned long flags;
+
+       local_irq_save(flags);
+
+       __ic_entire_inv();
+       __dc_entire_op(OP_FLUSH_N_INV);
+
+       local_irq_restore(flags);
+
+}
+
+#ifdef CONFIG_ARC_CACHE_VIPT_ALIASING
+
+void flush_cache_mm(struct mm_struct *mm)
+{
+       flush_cache_all();
+}
+
+void flush_cache_page(struct vm_area_struct *vma, unsigned long u_vaddr,
+                     unsigned long pfn)
+{
+       unsigned int paddr = pfn << PAGE_SHIFT;
+
+       u_vaddr &= PAGE_MASK;
+
+       __flush_dcache_page(paddr, u_vaddr);
+
+       if (vma->vm_flags & VM_EXEC)
+               __inv_icache_page(paddr, u_vaddr);
+}
+
+void flush_cache_range(struct vm_area_struct *vma, unsigned long start,
+                      unsigned long end)
+{
+       flush_cache_all();
+}
+
+void flush_anon_page(struct vm_area_struct *vma, struct page *page,
+                    unsigned long u_vaddr)
+{
+       /* TBD: do we really need to clear the kernel mapping */
+       __flush_dcache_page(page_address(page), u_vaddr);
+       __flush_dcache_page(page_address(page), page_address(page));
+
+}
+
+#endif
+
+void copy_user_highpage(struct page *to, struct page *from,
+       unsigned long u_vaddr, struct vm_area_struct *vma)
+{
+       unsigned long kfrom = (unsigned long)page_address(from);
+       unsigned long kto = (unsigned long)page_address(to);
+       int clean_src_k_mappings = 0;
+
+       /*
+        * If SRC page was already mapped in userspace AND it's U-mapping is
+        * not congruent with K-mapping, sync former to physical page so that
+        * K-mapping in memcpy below, sees the right data
+        *
+        * Note that while @u_vaddr refers to DST page's userspace vaddr, it is
+        * equally valid for SRC page as well
+        */
+       if (page_mapped(from) && addr_not_cache_congruent(kfrom, u_vaddr)) {
+               __flush_dcache_page(kfrom, u_vaddr);
+               clean_src_k_mappings = 1;
+       }
+
+       copy_page((void *)kto, (void *)kfrom);
+
+       /*
+        * Mark DST page K-mapping as dirty for a later finalization by
+        * update_mmu_cache(). Although the finalization could have been done
+        * here as well (given that both vaddr/paddr are available).
+        * But update_mmu_cache() already has code to do that for other
+        * non copied user pages (e.g. read faults which wire in pagecache page
+        * directly).
+        */
+       clear_bit(PG_dc_clean, &to->flags);
+
+       /*
+        * if SRC was already usermapped and non-congruent to kernel mapping
+        * sync the kernel mapping back to physical page
+        */
+       if (clean_src_k_mappings) {
+               __flush_dcache_page(kfrom, kfrom);
+               set_bit(PG_dc_clean, &from->flags);
+       } else {
+               clear_bit(PG_dc_clean, &from->flags);
+       }
+}
+
+void clear_user_page(void *to, unsigned long u_vaddr, struct page *page)
+{
+       clear_page(to);
+       clear_bit(PG_dc_clean, &page->flags);
+}
+
+
+/**********************************************************************
+ * Explicit Cache flush request from user space via syscall
+ * Needed for JITs which generate code on the fly
+ */
+SYSCALL_DEFINE3(cacheflush, uint32_t, start, uint32_t, sz, uint32_t, flags)
+{
+       /* TBD: optimize this */
+       flush_cache_all();
+       return 0;
+}
+
+void arc_cache_init(void)
+{
+       unsigned int __maybe_unused cpu = smp_processor_id();
+       char str[256];
+
+       printk(arc_cache_mumbojumbo(0, str, sizeof(str)));
+
+       if (IS_ENABLED(CONFIG_ARC_HAS_ICACHE)) {
+               struct cpuinfo_arc_cache *ic = &cpuinfo_arc700[cpu].icache;
+
+               if (!ic->ver)
+                       panic("cache support enabled but non-existent cache\n");
+
+               if (ic->line_len != L1_CACHE_BYTES)
+                       panic("ICache line [%d] != kernel Config [%d]",
+                             ic->line_len, L1_CACHE_BYTES);
+
+               if (ic->ver != CONFIG_ARC_MMU_VER)
+                       panic("Cache ver [%d] doesn't match MMU ver [%d]\n",
+                             ic->ver, CONFIG_ARC_MMU_VER);
+
+               /*
+                * In MMU v4 (HS38x) the alising icache config uses IVIL/PTAG
+                * pair to provide vaddr/paddr respectively, just as in MMU v3
+                */
+               if (is_isa_arcv2() && ic->alias)
+                       _cache_line_loop_ic_fn = __cache_line_loop_v3;
+               else
+                       _cache_line_loop_ic_fn = __cache_line_loop;
+       }
+
+       if (IS_ENABLED(CONFIG_ARC_HAS_DCACHE)) {
+               struct cpuinfo_arc_cache *dc = &cpuinfo_arc700[cpu].dcache;
+
+               if (!dc->ver)
+                       panic("cache support enabled but non-existent cache\n");
+
+               if (dc->line_len != L1_CACHE_BYTES)
+                       panic("DCache line [%d] != kernel Config [%d]",
+                             dc->line_len, L1_CACHE_BYTES);
+
+               /* check for D-Cache aliasing on ARCompact: ARCv2 has PIPT */
+               if (is_isa_arcompact()) {
+                       int handled = IS_ENABLED(CONFIG_ARC_CACHE_VIPT_ALIASING);
+
+                       if (dc->alias && !handled)
+                               panic("Enable CONFIG_ARC_CACHE_VIPT_ALIASING\n");
+                       else if (!dc->alias && handled)
+                               panic("Disable CONFIG_ARC_CACHE_VIPT_ALIASING\n");
+               }
+       }
+}
diff --git a/arch/arc/mm/cache_arc700.c b/arch/arc/mm/cache_arc700.c
deleted file mode 100644 (file)
index 12b2100..0000000
+++ /dev/null
@@ -1,723 +0,0 @@
-/*
- * ARC700 VIPT Cache Management
- *
- * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
- *
- * 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.
- *
- *  vineetg: May 2011: for Non-aliasing VIPT D-cache following can be NOPs
- *   -flush_cache_dup_mm (fork)
- *   -likewise for flush_cache_mm (exit/execve)
- *   -likewise for flush_cache_range,flush_cache_page (munmap, exit, COW-break)
- *
- * vineetg: Apr 2011
- *  -Now that MMU can support larger pg sz (16K), the determiniation of
- *   aliasing shd not be based on assumption of 8k pg
- *
- * vineetg: Mar 2011
- *  -optimised version of flush_icache_range( ) for making I/D coherent
- *   when vaddr is available (agnostic of num of aliases)
- *
- * vineetg: Mar 2011
- *  -Added documentation about I-cache aliasing on ARC700 and the way it
- *   was handled up until MMU V2.
- *  -Spotted a three year old bug when killing the 4 aliases, which needs
- *   bottom 2 bits, so we need to do paddr | {0x00, 0x01, 0x02, 0x03}
- *                        instead of paddr | {0x00, 0x01, 0x10, 0x11}
- *   (Rajesh you owe me one now)
- *
- * vineetg: Dec 2010
- *  -Off-by-one error when computing num_of_lines to flush
- *   This broke signal handling with bionic which uses synthetic sigret stub
- *
- * vineetg: Mar 2010
- *  -GCC can't generate ZOL for core cache flush loops.
- *   Conv them into iterations based as opposed to while (start < end) types
- *
- * Vineetg: July 2009
- *  -In I-cache flush routine we used to chk for aliasing for every line INV.
- *   Instead now we setup routines per cache geometry and invoke them
- *   via function pointers.
- *
- * Vineetg: Jan 2009
- *  -Cache Line flush routines used to flush an extra line beyond end addr
- *   because check was while (end >= start) instead of (end > start)
- *     =Some call sites had to work around by doing -1, -4 etc to end param
- *     =Some callers didnt care. This was spec bad in case of INV routines
- *      which would discard valid data (cause of the horrible ext2 bug
- *      in ARC IDE driver)
- *
- * vineetg: June 11th 2008: Fixed flush_icache_range( )
- *  -Since ARC700 caches are not coherent (I$ doesnt snoop D$) both need
- *   to be flushed, which it was not doing.
- *  -load_module( ) passes vmalloc addr (Kernel Virtual Addr) to the API,
- *   however ARC cache maintenance OPs require PHY addr. Thus need to do
- *   vmalloc_to_phy.
- *  -Also added optimisation there, that for range > PAGE SIZE we flush the
- *   entire cache in one shot rather than line by line. For e.g. a module
- *   with Code sz 600k, old code flushed 600k worth of cache (line-by-line),
- *   while cache is only 16 or 32k.
- */
-
-#include <linux/module.h>
-#include <linux/mm.h>
-#include <linux/sched.h>
-#include <linux/cache.h>
-#include <linux/mmu_context.h>
-#include <linux/syscalls.h>
-#include <linux/uaccess.h>
-#include <linux/pagemap.h>
-#include <asm/cacheflush.h>
-#include <asm/cachectl.h>
-#include <asm/setup.h>
-
-char *arc_cache_mumbojumbo(int c, char *buf, int len)
-{
-       int n = 0;
-
-#define PR_CACHE(p, cfg, str)                                          \
-       if (!(p)->ver)                                                  \
-               n += scnprintf(buf + n, len - n, str"\t\t: N/A\n");     \
-       else                                                            \
-               n += scnprintf(buf + n, len - n,                        \
-                       str"\t\t: %uK, %dway/set, %uB Line, %s%s%s\n",  \
-                       (p)->sz_k, (p)->assoc, (p)->line_len,           \
-                       (p)->vipt ? "VIPT" : "PIPT",                    \
-                       (p)->alias ? " aliasing" : "",                  \
-                       IS_ENABLED(cfg) ? "" : " (not used)");
-
-       PR_CACHE(&cpuinfo_arc700[c].icache, CONFIG_ARC_HAS_ICACHE, "I-Cache");
-       PR_CACHE(&cpuinfo_arc700[c].dcache, CONFIG_ARC_HAS_DCACHE, "D-Cache");
-
-       return buf;
-}
-
-/*
- * Read the Cache Build Confuration Registers, Decode them and save into
- * the cpuinfo structure for later use.
- * No Validation done here, simply read/convert the BCRs
- */
-void read_decode_cache_bcr(void)
-{
-       struct cpuinfo_arc_cache *p_ic, *p_dc;
-       unsigned int cpu = smp_processor_id();
-       struct bcr_cache {
-#ifdef CONFIG_CPU_BIG_ENDIAN
-               unsigned int pad:12, line_len:4, sz:4, config:4, ver:8;
-#else
-               unsigned int ver:8, config:4, sz:4, line_len:4, pad:12;
-#endif
-       } ibcr, dbcr;
-
-       p_ic = &cpuinfo_arc700[cpu].icache;
-       READ_BCR(ARC_REG_IC_BCR, ibcr);
-
-       if (!ibcr.ver)
-               goto dc_chk;
-
-       BUG_ON(ibcr.config != 3);
-       p_ic->assoc = 2;                /* Fixed to 2w set assoc */
-       p_ic->line_len = 8 << ibcr.line_len;
-       p_ic->sz_k = 1 << (ibcr.sz - 1);
-       p_ic->ver = ibcr.ver;
-       p_ic->vipt = 1;
-       p_ic->alias = p_ic->sz_k/p_ic->assoc/TO_KB(PAGE_SIZE) > 1;
-
-dc_chk:
-       p_dc = &cpuinfo_arc700[cpu].dcache;
-       READ_BCR(ARC_REG_DC_BCR, dbcr);
-
-       if (!dbcr.ver)
-               return;
-
-       BUG_ON(dbcr.config != 2);
-       p_dc->assoc = 4;                /* Fixed to 4w set assoc */
-       p_dc->line_len = 16 << dbcr.line_len;
-       p_dc->sz_k = 1 << (dbcr.sz - 1);
-       p_dc->ver = dbcr.ver;
-       p_dc->vipt = 1;
-       p_dc->alias = p_dc->sz_k/p_dc->assoc/TO_KB(PAGE_SIZE) > 1;
-}
-
-/*
- * 1. Validate the Cache Geomtery (compile time config matches hardware)
- * 2. If I-cache suffers from aliasing, setup work arounds (difft flush rtn)
- *    (aliasing D-cache configurations are not supported YET)
- * 3. Enable the Caches, setup default flush mode for D-Cache
- * 3. Calculate the SHMLBA used by user space
- */
-void arc_cache_init(void)
-{
-       unsigned int __maybe_unused cpu = smp_processor_id();
-       char str[256];
-
-       printk(arc_cache_mumbojumbo(0, str, sizeof(str)));
-
-       if (IS_ENABLED(CONFIG_ARC_HAS_ICACHE)) {
-               struct cpuinfo_arc_cache *ic = &cpuinfo_arc700[cpu].icache;
-
-               if (!ic->ver)
-                       panic("cache support enabled but non-existent cache\n");
-
-               if (ic->line_len != L1_CACHE_BYTES)
-                       panic("ICache line [%d] != kernel Config [%d]",
-                             ic->line_len, L1_CACHE_BYTES);
-
-               if (ic->ver != CONFIG_ARC_MMU_VER)
-                       panic("Cache ver [%d] doesn't match MMU ver [%d]\n",
-                             ic->ver, CONFIG_ARC_MMU_VER);
-       }
-
-       if (IS_ENABLED(CONFIG_ARC_HAS_DCACHE)) {
-               struct cpuinfo_arc_cache *dc = &cpuinfo_arc700[cpu].dcache;
-               int handled;
-
-               if (!dc->ver)
-                       panic("cache support enabled but non-existent cache\n");
-
-               if (dc->line_len != L1_CACHE_BYTES)
-                       panic("DCache line [%d] != kernel Config [%d]",
-                             dc->line_len, L1_CACHE_BYTES);
-
-               /* check for D-Cache aliasing */
-               handled = IS_ENABLED(CONFIG_ARC_CACHE_VIPT_ALIASING);
-
-               if (dc->alias && !handled)
-                       panic("Enable CONFIG_ARC_CACHE_VIPT_ALIASING\n");
-               else if (!dc->alias && handled)
-                       panic("Don't need CONFIG_ARC_CACHE_VIPT_ALIASING\n");
-       }
-}
-
-#define OP_INV         0x1
-#define OP_FLUSH       0x2
-#define OP_FLUSH_N_INV 0x3
-#define OP_INV_IC      0x4
-
-/*
- * Common Helper for Line Operations on {I,D}-Cache
- */
-static inline void __cache_line_loop(unsigned long paddr, unsigned long vaddr,
-                                    unsigned long sz, const int cacheop)
-{
-       unsigned int aux_cmd, aux_tag;
-       int num_lines;
-       const int full_page_op = __builtin_constant_p(sz) && sz == PAGE_SIZE;
-
-       if (cacheop == OP_INV_IC) {
-               aux_cmd = ARC_REG_IC_IVIL;
-#if (CONFIG_ARC_MMU_VER > 2)
-               aux_tag = ARC_REG_IC_PTAG;
-#endif
-       }
-       else {
-               /* d$ cmd: INV (discard or wback-n-discard) OR FLUSH (wback) */
-               aux_cmd = cacheop & OP_INV ? ARC_REG_DC_IVDL : ARC_REG_DC_FLDL;
-#if (CONFIG_ARC_MMU_VER > 2)
-               aux_tag = ARC_REG_DC_PTAG;
-#endif
-       }
-
-       /* Ensure we properly floor/ceil the non-line aligned/sized requests
-        * and have @paddr - aligned to cache line and integral @num_lines.
-        * This however can be avoided for page sized since:
-        *  -@paddr will be cache-line aligned already (being page aligned)
-        *  -@sz will be integral multiple of line size (being page sized).
-        */
-       if (!full_page_op) {
-               sz += paddr & ~CACHE_LINE_MASK;
-               paddr &= CACHE_LINE_MASK;
-               vaddr &= CACHE_LINE_MASK;
-       }
-
-       num_lines = DIV_ROUND_UP(sz, L1_CACHE_BYTES);
-
-#if (CONFIG_ARC_MMU_VER <= 2)
-       /* MMUv2 and before: paddr contains stuffed vaddrs bits */
-       paddr |= (vaddr >> PAGE_SHIFT) & 0x1F;
-#else
-       /* if V-P const for loop, PTAG can be written once outside loop */
-       if (full_page_op)
-               write_aux_reg(aux_tag, paddr);
-#endif
-
-       while (num_lines-- > 0) {
-#if (CONFIG_ARC_MMU_VER > 2)
-               /* MMUv3, cache ops require paddr seperately */
-               if (!full_page_op) {
-                       write_aux_reg(aux_tag, paddr);
-                       paddr += L1_CACHE_BYTES;
-               }
-
-               write_aux_reg(aux_cmd, vaddr);
-               vaddr += L1_CACHE_BYTES;
-#else
-               write_aux_reg(aux_cmd, paddr);
-               paddr += L1_CACHE_BYTES;
-#endif
-       }
-}
-
-#ifdef CONFIG_ARC_HAS_DCACHE
-
-/***************************************************************
- * Machine specific helpers for Entire D-Cache or Per Line ops
- */
-
-static inline unsigned int __before_dc_op(const int op)
-{
-       unsigned int reg = reg;
-
-       if (op == OP_FLUSH_N_INV) {
-               /* Dcache provides 2 cmd: FLUSH or INV
-                * INV inturn has sub-modes: DISCARD or FLUSH-BEFORE
-                * flush-n-inv is achieved by INV cmd but with IM=1
-                * So toggle INV sub-mode depending on op request and default
-                */
-               reg = read_aux_reg(ARC_REG_DC_CTRL);
-               write_aux_reg(ARC_REG_DC_CTRL, reg | DC_CTRL_INV_MODE_FLUSH)
-                       ;
-       }
-
-       return reg;
-}
-
-static inline void __after_dc_op(const int op, unsigned int reg)
-{
-       if (op & OP_FLUSH)      /* flush / flush-n-inv both wait */
-               while (read_aux_reg(ARC_REG_DC_CTRL) & DC_CTRL_FLUSH_STATUS);
-
-       /* Switch back to default Invalidate mode */
-       if (op == OP_FLUSH_N_INV)
-               write_aux_reg(ARC_REG_DC_CTRL, reg & ~DC_CTRL_INV_MODE_FLUSH);
-}
-
-/*
- * Operation on Entire D-Cache
- * @cacheop = {OP_INV, OP_FLUSH, OP_FLUSH_N_INV}
- * Note that constant propagation ensures all the checks are gone
- * in generated code
- */
-static inline void __dc_entire_op(const int cacheop)
-{
-       unsigned int ctrl_reg;
-       int aux;
-
-       ctrl_reg = __before_dc_op(cacheop);
-
-       if (cacheop & OP_INV)   /* Inv or flush-n-inv use same cmd reg */
-               aux = ARC_REG_DC_IVDC;
-       else
-               aux = ARC_REG_DC_FLSH;
-
-       write_aux_reg(aux, 0x1);
-
-       __after_dc_op(cacheop, ctrl_reg);
-}
-
-/* For kernel mappings cache operation: index is same as paddr */
-#define __dc_line_op_k(p, sz, op)      __dc_line_op(p, p, sz, op)
-
-/*
- * D-Cache : Per Line INV (discard or wback+discard) or FLUSH (wback)
- */
-static inline void __dc_line_op(unsigned long paddr, unsigned long vaddr,
-                               unsigned long sz, const int cacheop)
-{
-       unsigned long flags;
-       unsigned int ctrl_reg;
-
-       local_irq_save(flags);
-
-       ctrl_reg = __before_dc_op(cacheop);
-
-       __cache_line_loop(paddr, vaddr, sz, cacheop);
-
-       __after_dc_op(cacheop, ctrl_reg);
-
-       local_irq_restore(flags);
-}
-
-#else
-
-#define __dc_entire_op(cacheop)
-#define __dc_line_op(paddr, vaddr, sz, cacheop)
-#define __dc_line_op_k(paddr, sz, cacheop)
-
-#endif /* CONFIG_ARC_HAS_DCACHE */
-
-
-#ifdef CONFIG_ARC_HAS_ICACHE
-
-/*
- *             I-Cache Aliasing in ARC700 VIPT caches
- *
- * ARC VIPT I-cache uses vaddr to index into cache and paddr to match the tag.
- * The orig Cache Management Module "CDU" only required paddr to invalidate a
- * certain line since it sufficed as index in Non-Aliasing VIPT cache-geometry.
- * Infact for distinct V1,V2,P: all of {V1-P},{V2-P},{P-P} would end up fetching
- * the exact same line.
- *
- * However for larger Caches (way-size > page-size) - i.e. in Aliasing config,
- * paddr alone could not be used to correctly index the cache.
- *
- * ------------------
- * MMU v1/v2 (Fixed Page Size 8k)
- * ------------------
- * The solution was to provide CDU with these additonal vaddr bits. These
- * would be bits [x:13], x would depend on cache-geometry, 13 comes from
- * standard page size of 8k.
- * H/w folks chose [17:13] to be a future safe range, and moreso these 5 bits
- * of vaddr could easily be "stuffed" in the paddr as bits [4:0] since the
- * orig 5 bits of paddr were anyways ignored by CDU line ops, as they
- * represent the offset within cache-line. The adv of using this "clumsy"
- * interface for additional info was no new reg was needed in CDU programming
- * model.
- *
- * 17:13 represented the max num of bits passable, actual bits needed were
- * fewer, based on the num-of-aliases possible.
- * -for 2 alias possibility, only bit 13 needed (32K cache)
- * -for 4 alias possibility, bits 14:13 needed (64K cache)
- *
- * ------------------
- * MMU v3
- * ------------------
- * This ver of MMU supports variable page sizes (1k-16k): although Linux will
- * only support 8k (default), 16k and 4k.
- * However from hardware perspective, smaller page sizes aggrevate aliasing
- * meaning more vaddr bits needed to disambiguate the cache-line-op ;
- * the existing scheme of piggybacking won't work for certain configurations.
- * Two new registers IC_PTAG and DC_PTAG inttoduced.
- * "tag" bits are provided in PTAG, index bits in existing IVIL/IVDL/FLDL regs
- */
-
-/***********************************************************
- * Machine specific helper for per line I-Cache invalidate.
- */
-
-static inline void __ic_entire_inv(void)
-{
-       write_aux_reg(ARC_REG_IC_IVIC, 1);
-       read_aux_reg(ARC_REG_IC_CTRL);  /* blocks */
-}
-
-static inline void
-__ic_line_inv_vaddr_local(unsigned long paddr, unsigned long vaddr,
-                         unsigned long sz)
-{
-       unsigned long flags;
-
-       local_irq_save(flags);
-       __cache_line_loop(paddr, vaddr, sz, OP_INV_IC);
-       local_irq_restore(flags);
-}
-
-#ifndef CONFIG_SMP
-
-#define __ic_line_inv_vaddr(p, v, s)   __ic_line_inv_vaddr_local(p, v, s)
-
-#else
-
-struct ic_inv_args {
-       unsigned long paddr, vaddr;
-       int sz;
-};
-
-static void __ic_line_inv_vaddr_helper(void *info)
-{
-        struct ic_inv_args *ic_inv = info;
-
-        __ic_line_inv_vaddr_local(ic_inv->paddr, ic_inv->vaddr, ic_inv->sz);
-}
-
-static void __ic_line_inv_vaddr(unsigned long paddr, unsigned long vaddr,
-                               unsigned long sz)
-{
-       struct ic_inv_args ic_inv = {
-               .paddr = paddr,
-               .vaddr = vaddr,
-               .sz    = sz
-       };
-
-       on_each_cpu(__ic_line_inv_vaddr_helper, &ic_inv, 1);
-}
-
-#endif /* CONFIG_SMP */
-
-#else  /* !CONFIG_ARC_HAS_ICACHE */
-
-#define __ic_entire_inv()
-#define __ic_line_inv_vaddr(pstart, vstart, sz)
-
-#endif /* CONFIG_ARC_HAS_ICACHE */
-
-
-/***********************************************************
- * Exported APIs
- */
-
-/*
- * Handle cache congruency of kernel and userspace mappings of page when kernel
- * writes-to/reads-from
- *
- * The idea is to defer flushing of kernel mapping after a WRITE, possible if:
- *  -dcache is NOT aliasing, hence any U/K-mappings of page are congruent
- *  -U-mapping doesn't exist yet for page (finalised in update_mmu_cache)
- *  -In SMP, if hardware caches are coherent
- *
- * There's a corollary case, where kernel READs from a userspace mapped page.
- * If the U-mapping is not congruent to to K-mapping, former needs flushing.
- */
-void flush_dcache_page(struct page *page)
-{
-       struct address_space *mapping;
-
-       if (!cache_is_vipt_aliasing()) {
-               clear_bit(PG_dc_clean, &page->flags);
-               return;
-       }
-
-       /* don't handle anon pages here */
-       mapping = page_mapping(page);
-       if (!mapping)
-               return;
-
-       /*
-        * pagecache page, file not yet mapped to userspace
-        * Make a note that K-mapping is dirty
-        */
-       if (!mapping_mapped(mapping)) {
-               clear_bit(PG_dc_clean, &page->flags);
-       } else if (page_mapped(page)) {
-
-               /* kernel reading from page with U-mapping */
-               void *paddr = page_address(page);
-               unsigned long vaddr = page->index << PAGE_CACHE_SHIFT;
-
-               if (addr_not_cache_congruent(paddr, vaddr))
-                       __flush_dcache_page(paddr, vaddr);
-       }
-}
-EXPORT_SYMBOL(flush_dcache_page);
-
-
-void dma_cache_wback_inv(unsigned long start, unsigned long sz)
-{
-       __dc_line_op_k(start, sz, OP_FLUSH_N_INV);
-}
-EXPORT_SYMBOL(dma_cache_wback_inv);
-
-void dma_cache_inv(unsigned long start, unsigned long sz)
-{
-       __dc_line_op_k(start, sz, OP_INV);
-}
-EXPORT_SYMBOL(dma_cache_inv);
-
-void dma_cache_wback(unsigned long start, unsigned long sz)
-{
-       __dc_line_op_k(start, sz, OP_FLUSH);
-}
-EXPORT_SYMBOL(dma_cache_wback);
-
-/*
- * This is API for making I/D Caches consistent when modifying
- * kernel code (loadable modules, kprobes, kgdb...)
- * This is called on insmod, with kernel virtual address for CODE of
- * the module. ARC cache maintenance ops require PHY address thus we
- * need to convert vmalloc addr to PHY addr
- */
-void flush_icache_range(unsigned long kstart, unsigned long kend)
-{
-       unsigned int tot_sz;
-
-       WARN(kstart < TASK_SIZE, "%s() can't handle user vaddr", __func__);
-
-       /* Shortcut for bigger flush ranges.
-        * Here we don't care if this was kernel virtual or phy addr
-        */
-       tot_sz = kend - kstart;
-       if (tot_sz > PAGE_SIZE) {
-               flush_cache_all();
-               return;
-       }
-
-       /* Case: Kernel Phy addr (0x8000_0000 onwards) */
-       if (likely(kstart > PAGE_OFFSET)) {
-               /*
-                * The 2nd arg despite being paddr will be used to index icache
-                * This is OK since no alternate virtual mappings will exist
-                * given the callers for this case: kprobe/kgdb in built-in
-                * kernel code only.
-                */
-               __sync_icache_dcache(kstart, kstart, kend - kstart);
-               return;
-       }
-
-       /*
-        * Case: Kernel Vaddr (0x7000_0000 to 0x7fff_ffff)
-        * (1) ARC Cache Maintenance ops only take Phy addr, hence special
-        *     handling of kernel vaddr.
-        *
-        * (2) Despite @tot_sz being < PAGE_SIZE (bigger cases handled already),
-        *     it still needs to handle  a 2 page scenario, where the range
-        *     straddles across 2 virtual pages and hence need for loop
-        */
-       while (tot_sz > 0) {
-               unsigned int off, sz;
-               unsigned long phy, pfn;
-
-               off = kstart % PAGE_SIZE;
-               pfn = vmalloc_to_pfn((void *)kstart);
-               phy = (pfn << PAGE_SHIFT) + off;
-               sz = min_t(unsigned int, tot_sz, PAGE_SIZE - off);
-               __sync_icache_dcache(phy, kstart, sz);
-               kstart += sz;
-               tot_sz -= sz;
-       }
-}
-EXPORT_SYMBOL(flush_icache_range);
-
-/*
- * General purpose helper to make I and D cache lines consistent.
- * @paddr is phy addr of region
- * @vaddr is typically user vaddr (breakpoint) or kernel vaddr (vmalloc)
- *    However in one instance, when called by kprobe (for a breakpt in
- *    builtin kernel code) @vaddr will be paddr only, meaning CDU operation will
- *    use a paddr to index the cache (despite VIPT). This is fine since since a
- *    builtin kernel page will not have any virtual mappings.
- *    kprobe on loadable module will be kernel vaddr.
- */
-void __sync_icache_dcache(unsigned long paddr, unsigned long vaddr, int len)
-{
-       __dc_line_op(paddr, vaddr, len, OP_FLUSH_N_INV);
-       __ic_line_inv_vaddr(paddr, vaddr, len);
-}
-
-/* wrapper to compile time eliminate alignment checks in flush loop */
-void __inv_icache_page(unsigned long paddr, unsigned long vaddr)
-{
-       __ic_line_inv_vaddr(paddr, vaddr, PAGE_SIZE);
-}
-
-/*
- * wrapper to clearout kernel or userspace mappings of a page
- * For kernel mappings @vaddr == @paddr
- */
-void ___flush_dcache_page(unsigned long paddr, unsigned long vaddr)
-{
-       __dc_line_op(paddr, vaddr & PAGE_MASK, PAGE_SIZE, OP_FLUSH_N_INV);
-}
-
-noinline void flush_cache_all(void)
-{
-       unsigned long flags;
-
-       local_irq_save(flags);
-
-       __ic_entire_inv();
-       __dc_entire_op(OP_FLUSH_N_INV);
-
-       local_irq_restore(flags);
-
-}
-
-#ifdef CONFIG_ARC_CACHE_VIPT_ALIASING
-
-void flush_cache_mm(struct mm_struct *mm)
-{
-       flush_cache_all();
-}
-
-void flush_cache_page(struct vm_area_struct *vma, unsigned long u_vaddr,
-                     unsigned long pfn)
-{
-       unsigned int paddr = pfn << PAGE_SHIFT;
-
-       u_vaddr &= PAGE_MASK;
-
-       ___flush_dcache_page(paddr, u_vaddr);
-
-       if (vma->vm_flags & VM_EXEC)
-               __inv_icache_page(paddr, u_vaddr);
-}
-
-void flush_cache_range(struct vm_area_struct *vma, unsigned long start,
-                      unsigned long end)
-{
-       flush_cache_all();
-}
-
-void flush_anon_page(struct vm_area_struct *vma, struct page *page,
-                    unsigned long u_vaddr)
-{
-       /* TBD: do we really need to clear the kernel mapping */
-       __flush_dcache_page(page_address(page), u_vaddr);
-       __flush_dcache_page(page_address(page), page_address(page));
-
-}
-
-#endif
-
-void copy_user_highpage(struct page *to, struct page *from,
-       unsigned long u_vaddr, struct vm_area_struct *vma)
-{
-       void *kfrom = page_address(from);
-       void *kto = page_address(to);
-       int clean_src_k_mappings = 0;
-
-       /*
-        * If SRC page was already mapped in userspace AND it's U-mapping is
-        * not congruent with K-mapping, sync former to physical page so that
-        * K-mapping in memcpy below, sees the right data
-        *
-        * Note that while @u_vaddr refers to DST page's userspace vaddr, it is
-        * equally valid for SRC page as well
-        */
-       if (page_mapped(from) && addr_not_cache_congruent(kfrom, u_vaddr)) {
-               __flush_dcache_page(kfrom, u_vaddr);
-               clean_src_k_mappings = 1;
-       }
-
-       copy_page(kto, kfrom);
-
-       /*
-        * Mark DST page K-mapping as dirty for a later finalization by
-        * update_mmu_cache(). Although the finalization could have been done
-        * here as well (given that both vaddr/paddr are available).
-        * But update_mmu_cache() already has code to do that for other
-        * non copied user pages (e.g. read faults which wire in pagecache page
-        * directly).
-        */
-       clear_bit(PG_dc_clean, &to->flags);
-
-       /*
-        * if SRC was already usermapped and non-congruent to kernel mapping
-        * sync the kernel mapping back to physical page
-        */
-       if (clean_src_k_mappings) {
-               __flush_dcache_page(kfrom, kfrom);
-               set_bit(PG_dc_clean, &from->flags);
-       } else {
-               clear_bit(PG_dc_clean, &from->flags);
-       }
-}
-
-void clear_user_page(void *to, unsigned long u_vaddr, struct page *page)
-{
-       clear_page(to);
-       clear_bit(PG_dc_clean, &page->flags);
-}
-
-
-/**********************************************************************
- * Explicit Cache flush request from user space via syscall
- * Needed for JITs which generate code on the fly
- */
-SYSCALL_DEFINE3(cacheflush, uint32_t, start, uint32_t, sz, uint32_t, flags)
-{
-       /* TBD: optimize this */
-       flush_cache_all();
-       return 0;
-}
index 12cc6485b2185c4eae5399adbda4598da619a1dd..74a637a1cfc48b2c5d4f0047a0b25bc51d238e16 100644 (file)
@@ -14,8 +14,6 @@
  * Cache bit off in the TLB entry.
  *
  * The default DMA address == Phy address which is 0x8000_0000 based.
- * A platform/device can make it zero based, by over-riding
- * plat_{dma,kernel}_addr_to_{kernel,dma}
  */
 
 #include <linux/dma-mapping.h>
@@ -37,7 +35,7 @@ void *dma_alloc_noncoherent(struct device *dev, size_t size,
                return NULL;
 
        /* This is bus address, platform dependent */
-       *dma_handle = plat_kernel_addr_to_dma(dev, paddr);
+       *dma_handle = (dma_addr_t)paddr;
 
        return paddr;
 }
@@ -46,8 +44,7 @@ EXPORT_SYMBOL(dma_alloc_noncoherent);
 void dma_free_noncoherent(struct device *dev, size_t size, void *vaddr,
                          dma_addr_t dma_handle)
 {
-       free_pages_exact((void *)plat_dma_addr_to_kernel(dev, dma_handle),
-                        size);
+       free_pages_exact((void *)dma_handle, size);
 }
 EXPORT_SYMBOL(dma_free_noncoherent);
 
@@ -67,7 +64,19 @@ void *dma_alloc_coherent(struct device *dev, size_t size,
                memset(kvaddr, 0, size);
 
        /* This is bus address, platform dependent */
-       *dma_handle = plat_kernel_addr_to_dma(dev, paddr);
+       *dma_handle = (dma_addr_t)paddr;
+
+       /*
+        * Evict any existing L1 and/or L2 lines for the backing page
+        * in case it was used earlier as a normal "cached" page.
+        * Yeah this bit us - STAR 9000898266
+        *
+        * Although core does call flush_cache_vmap(), it gets kvaddr hence
+        * can't be used to efficiently flush L1 and/or L2 which need paddr
+        * Currently flush_cache_vmap nukes the L1 cache completely which
+        * will be optimized as a separate commit
+        */
+       dma_cache_wback_inv((unsigned long)paddr, size);
 
        return kvaddr;
 }
@@ -78,8 +87,7 @@ void dma_free_coherent(struct device *dev, size_t size, void *kvaddr,
 {
        iounmap((void __force __iomem *)kvaddr);
 
-       free_pages_exact((void *)plat_dma_addr_to_kernel(dev, dma_handle),
-                        size);
+       free_pages_exact((void *)dma_handle, size);
 }
 EXPORT_SYMBOL(dma_free_coherent);
 
index 7f47d2a56f44374e00939e6742ed6717c452c58a..2c7ce8bb74758c127673582426f214a0ee0d0af7 100644 (file)
@@ -113,6 +113,8 @@ static inline void __tlb_entry_erase(void)
        write_aux_reg(ARC_REG_TLBCOMMAND, TLBWrite);
 }
 
+#if (CONFIG_ARC_MMU_VER < 4)
+
 static inline unsigned int tlb_entry_lkup(unsigned long vaddr_n_asid)
 {
        unsigned int idx;
@@ -210,6 +212,28 @@ static void tlb_entry_insert(unsigned int pd0, unsigned int pd1)
        write_aux_reg(ARC_REG_TLBCOMMAND, TLBWrite);
 }
 
+#else  /* CONFIG_ARC_MMU_VER >= 4) */
+
+static void utlb_invalidate(void)
+{
+       /* No need since uTLB is always in sync with JTLB */
+}
+
+static void tlb_entry_erase(unsigned int vaddr_n_asid)
+{
+       write_aux_reg(ARC_REG_TLBPD0, vaddr_n_asid | _PAGE_PRESENT);
+       write_aux_reg(ARC_REG_TLBCOMMAND, TLBDeleteEntry);
+}
+
+static void tlb_entry_insert(unsigned int pd0, unsigned int pd1)
+{
+       write_aux_reg(ARC_REG_TLBPD0, pd0);
+       write_aux_reg(ARC_REG_TLBPD1, pd1);
+       write_aux_reg(ARC_REG_TLBCOMMAND, TLBInsertEntry);
+}
+
+#endif
+
 /*
  * Un-conditionally (without lookup) erase the entire MMU contents
  */
@@ -582,23 +606,42 @@ void read_decode_mmu_bcr(void)
 #endif
        } *mmu3;
 
+       struct bcr_mmu_4 {
+#ifdef CONFIG_CPU_BIG_ENDIAN
+       unsigned int ver:8, sasid:1, sz1:4, sz0:4, res:2, pae:1,
+                    n_ways:2, n_entry:2, n_super:2, u_itlb:3, u_dtlb:3;
+#else
+       /*           DTLB      ITLB      JES        JE         JA      */
+       unsigned int u_dtlb:3, u_itlb:3, n_super:2, n_entry:2, n_ways:2,
+                    pae:1, res:2, sz0:4, sz1:4, sasid:1, ver:8;
+#endif
+       } *mmu4;
+
        tmp = read_aux_reg(ARC_REG_MMU_BCR);
        mmu->ver = (tmp >> 24);
 
        if (mmu->ver <= 2) {
                mmu2 = (struct bcr_mmu_1_2 *)&tmp;
-               mmu->pg_sz = PAGE_SIZE;
+               mmu->pg_sz_k = TO_KB(PAGE_SIZE);
                mmu->sets = 1 << mmu2->sets;
                mmu->ways = 1 << mmu2->ways;
                mmu->u_dtlb = mmu2->u_dtlb;
                mmu->u_itlb = mmu2->u_itlb;
-       } else {
+       } else if (mmu->ver == 3) {
                mmu3 = (struct bcr_mmu_3 *)&tmp;
-               mmu->pg_sz = 512 << mmu3->pg_sz;
+               mmu->pg_sz_k = 1 << (mmu3->pg_sz - 1);
                mmu->sets = 1 << mmu3->sets;
                mmu->ways = 1 << mmu3->ways;
                mmu->u_dtlb = mmu3->u_dtlb;
                mmu->u_itlb = mmu3->u_itlb;
+       } else {
+               mmu4 = (struct bcr_mmu_4 *)&tmp;
+               mmu->pg_sz_k = 1 << (mmu4->sz0 - 1);
+               mmu->s_pg_sz_m = 1 << (mmu4->sz1 - 11);
+               mmu->sets = 64 << mmu4->n_entry;
+               mmu->ways = mmu4->n_ways * 2;
+               mmu->u_dtlb = mmu4->u_dtlb * 4;
+               mmu->u_itlb = mmu4->u_itlb * 4;
        }
 
        mmu->num_tlb = mmu->sets * mmu->ways;
@@ -608,10 +651,15 @@ char *arc_mmu_mumbojumbo(int cpu_id, char *buf, int len)
 {
        int n = 0;
        struct cpuinfo_arc_mmu *p_mmu = &cpuinfo_arc700[cpu_id].mmu;
+       char super_pg[64] = "";
+
+       if (p_mmu->s_pg_sz_m)
+               scnprintf(super_pg, 64, "%dM Super Page%s, ",
+                         p_mmu->s_pg_sz_m, " (not used)");
 
        n += scnprintf(buf + n, len - n,
-                     "MMU [v%x]\t: %dk PAGE, JTLB %d (%dx%d), uDTLB %d, uITLB %d %s\n",
-                      p_mmu->ver, TO_KB(p_mmu->pg_sz),
+                     "MMU [v%x]\t: %dk PAGE, %sJTLB %d (%dx%d), uDTLB %d, uITLB %d %s\n",
+                      p_mmu->ver, p_mmu->pg_sz_k, super_pg,
                       p_mmu->num_tlb, p_mmu->sets, p_mmu->ways,
                       p_mmu->u_dtlb, p_mmu->u_itlb,
                       IS_ENABLED(CONFIG_ARC_MMU_SASID) ? ",SASID" : "");
@@ -639,7 +687,7 @@ void arc_mmu_init(void)
                      mmu->ver, CONFIG_ARC_MMU_VER);
        }
 
-       if (mmu->pg_sz != PAGE_SIZE)
+       if (mmu->pg_sz_k != TO_KB(PAGE_SIZE))
                panic("MMU pg size != PAGE_SIZE (%luk)\n", TO_KB(PAGE_SIZE));
 
        /* Enable the MMU */
index d572f1c2c72470e4b8f321787a8499e02da518e0..f6f4c3cb505d1341a8c24b1172a6a89f71e6fc26 100644 (file)
@@ -35,8 +35,6 @@
  * Rahul Trivedi, Amit Bhor: Codito Technologies 2004
  */
 
-       .cpu A7
-
 #include <linux/linkage.h>
 #include <asm/entry.h>
 #include <asm/mmu.h>
@@ -46,6 +44,7 @@
 #include <asm/processor.h>
 #include <asm/tlb-mmu1.h>
 
+#ifdef CONFIG_ISA_ARCOMPACT
 ;-----------------------------------------------------------------
 ; ARC700 Exception Handling doesn't auto-switch stack and it only provides
 ; ONE scratch AUX reg "ARC_REG_SCRATCH_DATA0"
@@ -123,6 +122,24 @@ ex_saved_reg1:
 #endif
 .endm
 
+#else  /* ARCv2 */
+
+.macro TLBMISS_FREEUP_REGS
+       PUSH  r0
+       PUSH  r1
+       PUSH  r2
+       PUSH  r3
+.endm
+
+.macro TLBMISS_RESTORE_REGS
+       POP   r3
+       POP   r2
+       POP   r1
+       POP   r0
+.endm
+
+#endif
+
 ;============================================================================
 ;  Troubleshooting Stuff
 ;============================================================================
@@ -241,6 +258,7 @@ ex_saved_reg1:
 ; Commit the TLB entry into MMU
 
 .macro COMMIT_ENTRY_TO_MMU
+#if (CONFIG_ARC_MMU_VER < 4)
 
        /* Get free TLB slot: Set = computed from vaddr, way = random */
        sr  TLBGetIndex, [ARC_REG_TLBCOMMAND]
@@ -251,6 +269,10 @@ ex_saved_reg1:
 #else
        sr TLBWrite, [ARC_REG_TLBCOMMAND]
 #endif
+
+#else
+       sr TLBInsertEntry, [ARC_REG_TLBCOMMAND]
+#endif
 .endm
 
 
@@ -291,6 +313,7 @@ ENTRY(EV_TLBMissI)
        CONV_PTE_TO_TLB
        COMMIT_ENTRY_TO_MMU
        TLBMISS_RESTORE_REGS
+EV_TLBMissI_fast_ret:  ; additional label for VDK OS-kit instrumentation
        rtie
 
 END(EV_TLBMissI)
@@ -356,6 +379,7 @@ ENTRY(EV_TLBMissD)
 
        COMMIT_ENTRY_TO_MMU
        TLBMISS_RESTORE_REGS
+EV_TLBMissD_fast_ret:  ; additional label for VDK OS-kit instrumentation
        rtie
 
 ;-------- Common routine to call Linux Page Fault Handler -----------
@@ -366,19 +390,5 @@ do_slow_path_pf:
 
        ; Slow path TLB Miss handled as a regular ARC Exception
        ; (stack switching / save the complete reg-file).
-       EXCEPTION_PROLOGUE
-
-       ; ------- setup args for Linux Page fault Hanlder ---------
-       mov_s r1, sp
-       lr    r0, [efa]
-
-       ; We don't want exceptions to be disabled while the fault is handled.
-       ; Now that we have saved the context we return from exception hence
-       ; exceptions get re-enable
-
-       FAKE_RET_FROM_EXCPN  r9
-
-       bl  do_page_fault
-       b   ret_from_exception
-
+       b  call_do_page_fault
 END(EV_TLBMissD)
diff --git a/arch/arc/plat-arcfpga/Kconfig b/arch/arc/plat-arcfpga/Kconfig
deleted file mode 100644 (file)
index 217593a..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-#
-# Copyright (C) 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
-#
-# 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.
-#
-
-menuconfig ARC_PLAT_FPGA_LEGACY
-       bool "\"Legacy\" ARC FPGA dev Boards"
-       select ARC_HAS_COH_CACHES if SMP
-       help
-         Support for ARC development boards, provided by Synopsys.
-         These are based on FPGA or ISS. e.g.
-         - ARCAngel4
-         - ML509
-         - MetaWare ISS
-
-if ARC_PLAT_FPGA_LEGACY
-
-config ISS_SMP_EXTN
-       bool "ARC SMP Extensions (ISS Models only)"
-       default n
-       depends on SMP
-       help
-         SMP Extensions to ARC700, in a "simulation only" Model, supported in
-         ARC ISS (Instruction Set Simulator).
-         The SMP extensions include:
-         -IDU (Interrupt Distribution Unit)
-         -XTL (To enable CPU start/stop/set-PC for another CPU)
-         It doesn't provide coherent Caches and/or Atomic Ops (LLOCK/SCOND)
-
-endif
diff --git a/arch/arc/plat-arcfpga/Makefile b/arch/arc/plat-arcfpga/Makefile
deleted file mode 100644 (file)
index 66fd0ec..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-#
-# Copyright (C) 2011-2012 Synopsys, Inc. (www.synopsys.com)
-#
-# 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.
-#
-
-KBUILD_CFLAGS  += -Iarch/arc/plat-arcfpga/include
-
-obj-y := platform.o
-obj-$(CONFIG_ISS_SMP_EXTN)             += smp.o
diff --git a/arch/arc/plat-arcfpga/include/plat/smp.h b/arch/arc/plat-arcfpga/include/plat/smp.h
deleted file mode 100644 (file)
index c09eb4c..0000000
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
- *
- * 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.
- *
- *  Rajeshwar Ranga: Interrupt Distribution Unit API's
- */
-
-#ifndef __PLAT_ARCFPGA_SMP_H
-#define __PLAT_ARCFPGA_SMP_H
-
-#ifdef CONFIG_SMP
-
-#include <linux/types.h>
-#include <asm/arcregs.h>
-
-#define ARC_AUX_IDU_REG_CMD            0x2000
-#define ARC_AUX_IDU_REG_PARAM          0x2001
-
-#define ARC_AUX_XTL_REG_CMD            0x2002
-#define ARC_AUX_XTL_REG_PARAM          0x2003
-
-#define ARC_REG_MP_BCR                 0x2021
-
-#define ARC_XTL_CMD_WRITE_PC           0x04
-#define ARC_XTL_CMD_CLEAR_HALT         0x02
-
-/*
- * Build Configuration Register which identifies the sub-components
- */
-struct bcr_mp {
-#ifdef CONFIG_CPU_BIG_ENDIAN
-       unsigned int mp_arch:16, pad:5, sdu:1, idu:1, scu:1, ver:8;
-#else
-       unsigned int ver:8, scu:1, idu:1, sdu:1, pad:5, mp_arch:16;
-#endif
-};
-
-/* IDU supports 256 common interrupts */
-#define NR_IDU_IRQS                    256
-
-/*
- * The Aux Regs layout is same bit-by-bit in both BE/LE modes.
- * However when casted as a bitfield encoded "C" struct, gcc treats it as
- * memory, generating different code for BE/LE, requiring strcture adj (see
- * include/asm/arcregs.h)
- *
- * However when manually "carving" the value for a Aux, no special handling
- * of BE is needed because of the property discribed above
- */
-#define IDU_SET_COMMAND(irq, cmd)                      \
-do {                                                   \
-       uint32_t __val;                                 \
-       __val = (((irq & 0xFF) << 8) | (cmd & 0xFF));   \
-       write_aux_reg(ARC_AUX_IDU_REG_CMD, __val);      \
-} while (0)
-
-#define IDU_SET_PARAM(par)  write_aux_reg(ARC_AUX_IDU_REG_PARAM, par)
-#define IDU_GET_PARAM()     read_aux_reg(ARC_AUX_IDU_REG_PARAM)
-
-/* IDU Commands */
-#define IDU_DISABLE                    0x00
-#define IDU_ENABLE                     0x01
-#define IDU_IRQ_CLEAR                  0x02
-#define IDU_IRQ_ASSERT                 0x03
-#define IDU_IRQ_WMODE                  0x04
-#define IDU_IRQ_STATUS                 0x05
-#define IDU_IRQ_ACK                    0x06
-#define IDU_IRQ_PEND                   0x07
-#define IDU_IRQ_RMODE                  0x08
-#define IDU_IRQ_WBITMASK               0x09
-#define IDU_IRQ_RBITMASK               0x0A
-
-#define idu_enable()           IDU_SET_COMMAND(0, IDU_ENABLE)
-#define idu_disable()          IDU_SET_COMMAND(0, IDU_DISABLE)
-
-#define idu_irq_assert(irq)    IDU_SET_COMMAND((irq), IDU_IRQ_ASSERT)
-#define idu_irq_clear(irq)     IDU_SET_COMMAND((irq), IDU_IRQ_CLEAR)
-
-/* IDU Interrupt Mode - Destination Encoding */
-#define IDU_IRQ_MOD_DISABLE            0x00
-#define IDU_IRQ_MOD_ROUND_RECP         0x01
-#define IDU_IRQ_MOD_TCPU_FIRSTRECP     0x02
-#define IDU_IRQ_MOD_TCPU_ALLRECP       0x03
-
-/* IDU Interrupt Mode  - Triggering Mode */
-#define IDU_IRQ_MODE_LEVEL_TRIG                0x00
-#define IDU_IRQ_MODE_PULSE_TRIG                0x01
-
-#define IDU_IRQ_MODE_PARAM(dest_mode, trig_mode)   \
-       (((trig_mode & 0x01) << 15) | (dest_mode & 0xFF))
-
-struct idu_irq_config {
-       uint8_t irq;
-       uint8_t dest_mode;
-       uint8_t trig_mode;
-};
-
-struct idu_irq_status {
-       uint8_t irq;
-       bool enabled;
-       bool status;
-       bool ack;
-       bool pend;
-       uint8_t next_rr;
-};
-
-extern void idu_irq_set_tgtcpu(uint8_t irq, uint32_t mask);
-extern void idu_irq_set_mode(uint8_t irq, uint8_t dest_mode, uint8_t trig_mode);
-
-extern void iss_model_init_smp(unsigned int cpu);
-extern void iss_model_init_early_smp(void);
-
-#endif /* CONFIG_SMP */
-
-#endif
diff --git a/arch/arc/plat-arcfpga/platform.c b/arch/arc/plat-arcfpga/platform.c
deleted file mode 100644 (file)
index afc8825..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * ARC FPGA Platform support code
- *
- * Copyright (C) 2012 Synopsys, Inc. (www.synopsys.com)
- *
- * 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/init.h>
-#include <asm/mach_desc.h>
-#include <plat/smp.h>
-
-/*----------------------- Machine Descriptions ------------------------------
- *
- * Machine description is simply a set of platform/board specific callbacks
- * This is not directly related to DeviceTree based dynamic device creation,
- * however as part of early device tree scan, we also select the right
- * callback set, by matching the DT compatible name.
- */
-
-static const char *legacy_fpga_compat[] __initconst = {
-       "snps,arc-angel4",
-       "snps,arc-ml509",
-       NULL,
-};
-
-MACHINE_START(LEGACY_FPGA, "legacy_fpga")
-       .dt_compat      = legacy_fpga_compat,
-#ifdef CONFIG_ISS_SMP_EXTN
-       .init_early     = iss_model_init_early_smp,
-       .init_smp       = iss_model_init_smp,
-#endif
-MACHINE_END
-
-static const char *simulation_compat[] __initconst = {
-       "snps,nsim",
-       "snps,nsimosci",
-       NULL,
-};
-
-MACHINE_START(SIMULATION, "simulation")
-       .dt_compat      = simulation_compat,
-MACHINE_END
diff --git a/arch/arc/plat-arcfpga/smp.c b/arch/arc/plat-arcfpga/smp.c
deleted file mode 100644 (file)
index 64797ba..0000000
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * ARC700 Simulation-only Extensions for SMP
- *
- * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
- *
- * 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.
- *
- *  Vineet Gupta    - 2012 : split off arch common and plat specific SMP
- *  Rajeshwar Ranga - 2007 : Interrupt Distribution Unit API's
- */
-
-#include <linux/smp.h>
-#include <linux/irq.h>
-#include <plat/smp.h>
-
-#define IDU_INTERRUPT_0 16
-
-static char smp_cpuinfo_buf[128];
-
-/*
- *-------------------------------------------------------------------
- * Platform specific callbacks expected by arch SMP code
- *-------------------------------------------------------------------
- */
-
-/*
- * Master kick starting another CPU
- */
-static void iss_model_smp_wakeup_cpu(int cpu, unsigned long pc)
-{
-       /* setup the start PC */
-       write_aux_reg(ARC_AUX_XTL_REG_PARAM, pc);
-
-       /* Trigger WRITE_PC cmd for this cpu */
-       write_aux_reg(ARC_AUX_XTL_REG_CMD,
-                       (ARC_XTL_CMD_WRITE_PC | (cpu << 8)));
-
-       /* Take the cpu out of Halt */
-       write_aux_reg(ARC_AUX_XTL_REG_CMD,
-                       (ARC_XTL_CMD_CLEAR_HALT | (cpu << 8)));
-
-}
-
-static inline int get_hw_config_num_irq(void)
-{
-       uint32_t val = read_aux_reg(ARC_REG_VECBASE_BCR);
-
-       switch (val & 0x03) {
-       case 0:
-               return 16;
-       case 1:
-               return 32;
-       case 2:
-               return 8;
-       default:
-               return 0;
-       }
-
-       return 0;
-}
-
-/*
- * Any SMP specific init any CPU does when it comes up.
- * Here we setup the CPU to enable Inter-Processor-Interrupts
- * Called for each CPU
- * -Master      : init_IRQ()
- * -Other(s)    : start_kernel_secondary()
- */
-void iss_model_init_smp(unsigned int cpu)
-{
-       /* Check if CPU is configured for more than 16 interrupts */
-       if (NR_IRQS <= 16 || get_hw_config_num_irq() <= 16)
-               panic("[arcfpga] IRQ system can't support IDU IPI\n");
-
-       idu_disable();
-
-       /****************************************************************
-        * IDU provides a set of Common IRQs, each of which can be dynamically
-        * attached to (1|many|all) CPUs.
-        * The Common IRQs [0-15] are mapped as CPU pvt [16-31]
-        *
-        * Here we use a simple 1:1 mapping:
-        * A CPU 'x' is wired to Common IRQ 'x'.
-        * So an IDU ASSERT on IRQ 'x' will trigger Interupt on CPU 'x', which
-        * makes up for our simple IPI plumbing.
-        *
-        * TBD: Have a dedicated multicast IRQ for sending IPIs to all CPUs
-        *      w/o having to do one-at-a-time
-        ******************************************************************/
-
-       /*
-        * Claim an IRQ which would trigger IPI on this CPU.
-        * In IDU parlance it involves setting up a cpu bitmask for the IRQ
-        * The bitmap here contains only 1 CPU (self).
-        */
-       idu_irq_set_tgtcpu(cpu, 0x1 << cpu);
-
-       /* Set the IRQ destination to use the bitmask above */
-       idu_irq_set_mode(cpu, 7, /* XXX: IDU_IRQ_MOD_TCPU_ALLRECP: ISS bug */
-                        IDU_IRQ_MODE_PULSE_TRIG);
-
-       idu_enable();
-
-       /* Attach the arch-common IPI ISR to our IDU IRQ */
-       smp_ipi_irq_setup(cpu, IDU_INTERRUPT_0 + cpu);
-}
-
-static void iss_model_ipi_send(int cpu)
-{
-       idu_irq_assert(cpu);
-}
-
-static void iss_model_ipi_clear(int irq)
-{
-       idu_irq_clear(IDU_INTERRUPT_0 + smp_processor_id());
-}
-
-void iss_model_init_early_smp(void)
-{
-#define IS_AVAIL1(var, str)    ((var) ? str : "")
-
-       struct bcr_mp mp;
-
-       READ_BCR(ARC_REG_MP_BCR, mp);
-
-       sprintf(smp_cpuinfo_buf, "Extn [ISS-SMP]: v%d, arch(%d) %s %s %s\n",
-               mp.ver, mp.mp_arch, IS_AVAIL1(mp.scu, "SCU"),
-               IS_AVAIL1(mp.idu, "IDU"), IS_AVAIL1(mp.sdu, "SDU"));
-
-       plat_smp_ops.info = smp_cpuinfo_buf;
-
-       plat_smp_ops.cpu_kick = iss_model_smp_wakeup_cpu;
-       plat_smp_ops.ipi_send = iss_model_ipi_send;
-       plat_smp_ops.ipi_clear = iss_model_ipi_clear;
-}
-
-/*
- *-------------------------------------------------------------------
- * Low level Platform IPI Providers
- *-------------------------------------------------------------------
- */
-
-/* Set the Mode for the Common IRQ */
-void idu_irq_set_mode(uint8_t irq, uint8_t dest_mode, uint8_t trig_mode)
-{
-       uint32_t par = IDU_IRQ_MODE_PARAM(dest_mode, trig_mode);
-
-       IDU_SET_PARAM(par);
-       IDU_SET_COMMAND(irq, IDU_IRQ_WMODE);
-}
-
-/* Set the target cpu Bitmask for Common IRQ */
-void idu_irq_set_tgtcpu(uint8_t irq, uint32_t mask)
-{
-       IDU_SET_PARAM(mask);
-       IDU_SET_COMMAND(irq, IDU_IRQ_WBITMASK);
-}
-
-/* Get the Interrupt Acknowledged status for IRQ (as CPU Bitmask) */
-bool idu_irq_get_ack(uint8_t irq)
-{
-       uint32_t val;
-
-       IDU_SET_COMMAND(irq, IDU_IRQ_ACK);
-       val = IDU_GET_PARAM();
-
-       return val & (1 << irq);
-}
-
-/*
- * Get the Interrupt Pending status for IRQ (as CPU Bitmask)
- * -Pending means CPU has not yet noticed the IRQ (e.g. disabled)
- * -After Interrupt has been taken, the IPI expcitily needs to be
- *  cleared, to be acknowledged.
- */
-bool idu_irq_get_pend(uint8_t irq)
-{
-       uint32_t val;
-
-       IDU_SET_COMMAND(irq, IDU_IRQ_PEND);
-       val = IDU_GET_PARAM();
-
-       return val & (1 << irq);
-}
diff --git a/arch/arc/plat-axs10x/Kconfig b/arch/arc/plat-axs10x/Kconfig
new file mode 100644 (file)
index 0000000..d475f9d
--- /dev/null
@@ -0,0 +1,46 @@
+#
+# Copyright (C) 2013-15 Synopsys, Inc. (www.synopsys.com)
+#
+# 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.
+#
+
+menuconfig ARC_PLAT_AXS10X
+       bool "Synopsys ARC AXS10x Software Development Platforms"
+       select DW_APB_ICTL
+       select GPIO_DWAPB
+       select OF_GPIO
+       select GENERIC_IRQ_CHIP
+       select ARCH_REQUIRE_GPIOLIB
+       help
+         Support for the ARC AXS10x Software Development Platforms.
+
+         The AXS10x Platforms consist of a mainboard with peripherals,
+         on which several daughter cards can be placed. The daughter cards
+         typically contain a CPU and memory.
+
+if ARC_PLAT_AXS10X
+
+config AXS101
+       depends on ISA_ARCOMPACT
+       bool "AXS101 with AXC001 CPU Card (ARC 770D/EM6/AS221)"
+       help
+         This adds support for the 770D/EM6/AS221 CPU Card. Only the ARC
+         770D is supported in Linux.
+
+         The AXS101 Platform consists of an AXS10x mainboard with
+         this daughtercard. Please use the axs101.dts device tree
+         with this configuration.
+
+config AXS103
+       bool "AXS103 with AXC003 CPU Card (ARC HS38x)"
+       depends on ISA_ARCV2
+       help
+         This adds support for the HS38x CPU Card.
+
+         The AXS103 Platform consists of an AXS10x mainboard with
+         this daughtercard. Please use the axs103.dts device tree
+         with this configuration.
+
+endif
diff --git a/arch/arc/plat-axs10x/Makefile b/arch/arc/plat-axs10x/Makefile
new file mode 100644 (file)
index 0000000..d4748f2
--- /dev/null
@@ -0,0 +1,9 @@
+#
+# Copyright (C) 2013-15 Synopsys, Inc. (www.synopsys.com)
+#
+# 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.
+#
+
+obj-$(CONFIG_ARC_PLAT_AXS10X) += axs10x.o
diff --git a/arch/arc/plat-axs10x/axs10x.c b/arch/arc/plat-axs10x/axs10x.c
new file mode 100644 (file)
index 0000000..99f7da5
--- /dev/null
@@ -0,0 +1,484 @@
+/*
+ * AXS101/AXS103 Software Development Platform
+ *
+ * Copyright (C) 2013-15 Synopsys, Inc. (www.synopsys.com)
+ *
+ * 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.
+ *
+ * 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.
+ *
+ */
+
+#include <linux/of_platform.h>
+
+#include <asm/asm-offsets.h>
+#include <asm/clk.h>
+#include <asm/io.h>
+#include <asm/mach_desc.h>
+#include <asm/mcip.h>
+
+#define AXS_MB_CGU             0xE0010000
+#define AXS_MB_CREG            0xE0011000
+
+#define CREG_MB_IRQ_MUX                (AXS_MB_CREG + 0x214)
+#define CREG_MB_SW_RESET       (AXS_MB_CREG + 0x220)
+#define CREG_MB_VER            (AXS_MB_CREG + 0x230)
+#define CREG_MB_CONFIG         (AXS_MB_CREG + 0x234)
+
+#define AXC001_CREG            0xF0001000
+#define AXC001_GPIO_INTC       0xF0003000
+
+static void __init axs10x_enable_gpio_intc_wire(void)
+{
+       /*
+        * Peripherals on CPU Card and Mother Board are wired to cpu intc via
+        * intermediate DW APB GPIO blocks (mainly for debouncing)
+        *
+        *         ---------------------
+        *        |  snps,arc700-intc |
+        *        ---------------------
+        *          | #7          | #15
+        * -------------------   -------------------
+        * | snps,dw-apb-gpio |  | snps,dw-apb-gpio |
+        * -------------------   -------------------
+        *        |                         |
+        *        |                 [ Debug UART on cpu card ]
+        *        |
+        * ------------------------
+        * | snps,dw-apb-intc (MB)|
+        * ------------------------
+        *  |      |       |      |
+        * [eth] [uart]        [... other perip on Main Board]
+        *
+        * Current implementation of "irq-dw-apb-ictl" driver doesn't work well
+        * with stacked INTCs. In particular problem happens if its master INTC
+        * not yet instantiated. See discussion here -
+        * https://lkml.org/lkml/2015/3/4/755
+        *
+        * So setup the first gpio block as a passive pass thru and hide it from
+        * DT hardware topology - connect MB intc directly to cpu intc
+        * The GPIO "wire" needs to be init nevertheless (here)
+        *
+        * One side adv is that peripheral interrupt handling avoids one nested
+        * intc ISR hop
+        */
+#define GPIO_INTEN             (AXC001_GPIO_INTC + 0x30)
+#define GPIO_INTMASK           (AXC001_GPIO_INTC + 0x34)
+#define GPIO_INTTYPE_LEVEL     (AXC001_GPIO_INTC + 0x38)
+#define GPIO_INT_POLARITY      (AXC001_GPIO_INTC + 0x3c)
+#define MB_TO_GPIO_IRQ         12
+
+       iowrite32(~(1 << MB_TO_GPIO_IRQ), (void __iomem *) GPIO_INTMASK);
+       iowrite32(0, (void __iomem *) GPIO_INTTYPE_LEVEL);
+       iowrite32(~0, (void __iomem *) GPIO_INT_POLARITY);
+       iowrite32(1 << MB_TO_GPIO_IRQ, (void __iomem *) GPIO_INTEN);
+}
+
+static inline void __init
+write_cgu_reg(uint32_t value, void __iomem *reg, void __iomem *lock_reg)
+{
+       unsigned int loops = 128 * 1024, ctr;
+
+       iowrite32(value, reg);
+
+       ctr = loops;
+       while (((ioread32(lock_reg) & 1) == 1) && ctr--) /* wait for unlock */
+               cpu_relax();
+
+       ctr = loops;
+       while (((ioread32(lock_reg) & 1) == 0) && ctr--) /* wait for re-lock */
+               cpu_relax();
+}
+
+static void __init axs10x_print_board_ver(unsigned int creg, const char *str)
+{
+       union ver {
+               struct {
+#ifdef CONFIG_CPU_BIG_ENDIAN
+                       unsigned int pad:11, y:12, m:4, d:5;
+#else
+                       unsigned int d:5, m:4, y:12, pad:11;
+#endif
+               };
+               unsigned int val;
+       } board;
+
+       board.val = ioread32((void __iomem *)creg);
+       pr_info("AXS: %s FPGA Date: %u-%u-%u\n", str, board.d, board.m,
+               board.y);
+}
+
+static void __init axs10x_early_init(void)
+{
+       int mb_rev;
+       char mb[32];
+
+       /* Determine motherboard version */
+       if (ioread32((void __iomem *) CREG_MB_CONFIG) & (1 << 28))
+               mb_rev = 3;     /* HT-3 (rev3.0) */
+       else
+               mb_rev = 2;     /* HT-2 (rev2.0) */
+
+       axs10x_enable_gpio_intc_wire();
+
+       scnprintf(mb, 32, "MainBoard v%d", mb_rev);
+       axs10x_print_board_ver(CREG_MB_VER, mb);
+}
+
+#ifdef CONFIG_AXS101
+
+#define CREG_CPU_ADDR_770      (AXC001_CREG + 0x20)
+#define CREG_CPU_ADDR_TUNN     (AXC001_CREG + 0x60)
+#define CREG_CPU_ADDR_770_UPD  (AXC001_CREG + 0x34)
+#define CREG_CPU_ADDR_TUNN_UPD (AXC001_CREG + 0x74)
+
+#define CREG_CPU_ARC770_IRQ_MUX        (AXC001_CREG + 0x114)
+#define CREG_CPU_GPIO_UART_MUX (AXC001_CREG + 0x120)
+
+/*
+ * Set up System Memory Map for ARC cpu / peripherals controllers
+ *
+ * Each AXI master has a 4GB memory map specified as 16 apertures of 256MB, each
+ * of which maps to a corresponding 256MB aperture in Target slave memory map.
+ *
+ * e.g. ARC cpu AXI Master's aperture 8 (0x8000_0000) is mapped to aperture 0
+ * (0x0000_0000) of DDR Port 0 (slave #1)
+ *
+ * Access from cpu to MB controllers such as GMAC is setup using AXI Tunnel:
+ * which has master/slaves on both ends.
+ * e.g. aperture 14 (0xE000_0000) of ARC cpu is mapped to aperture 14
+ * (0xE000_0000) of CPU Card AXI Tunnel slave (slave #3) which is mapped to
+ * MB AXI Tunnel Master, which also has a mem map setup
+ *
+ * In the reverse direction, MB AXI Masters (e.g. GMAC) mem map is setup
+ * to map to MB AXI Tunnel slave which connects to CPU Card AXI Tunnel Master
+ */
+struct aperture {
+       unsigned int slave_sel:4, slave_off:4, pad:24;
+};
+
+/* CPU Card target slaves */
+#define AXC001_SLV_NONE                        0
+#define AXC001_SLV_DDR_PORT0           1
+#define AXC001_SLV_SRAM                        2
+#define AXC001_SLV_AXI_TUNNEL          3
+#define AXC001_SLV_AXI2APB             6
+#define AXC001_SLV_DDR_PORT1           7
+
+/* MB AXI Target slaves */
+#define AXS_MB_SLV_NONE                        0
+#define AXS_MB_SLV_AXI_TUNNEL_CPU      1
+#define AXS_MB_SLV_AXI_TUNNEL_HAPS     2
+#define AXS_MB_SLV_SRAM                        3
+#define AXS_MB_SLV_CONTROL             4
+
+/* MB AXI masters */
+#define AXS_MB_MST_TUNNEL_CPU          0
+#define AXS_MB_MST_USB_OHCI            10
+
+/*
+ * memmap for ARC core on CPU Card
+ */
+static const struct aperture axc001_memmap[16] = {
+       {AXC001_SLV_AXI_TUNNEL,         0x0},
+       {AXC001_SLV_AXI_TUNNEL,         0x1},
+       {AXC001_SLV_SRAM,               0x0}, /* 0x2000_0000: Local SRAM */
+       {AXC001_SLV_NONE,               0x0},
+       {AXC001_SLV_NONE,               0x0},
+       {AXC001_SLV_NONE,               0x0},
+       {AXC001_SLV_NONE,               0x0},
+       {AXC001_SLV_NONE,               0x0},
+       {AXC001_SLV_DDR_PORT0,          0x0}, /* 0x8000_0000: DDR   0..256M */
+       {AXC001_SLV_DDR_PORT0,          0x1}, /* 0x9000_0000: DDR 256..512M */
+       {AXC001_SLV_DDR_PORT0,          0x2},
+       {AXC001_SLV_DDR_PORT0,          0x3},
+       {AXC001_SLV_NONE,               0x0},
+       {AXC001_SLV_AXI_TUNNEL,         0xD},
+       {AXC001_SLV_AXI_TUNNEL,         0xE}, /* MB: CREG, CGU... */
+       {AXC001_SLV_AXI2APB,            0x0}, /* CPU Card local CREG, CGU... */
+};
+
+/*
+ * memmap for CPU Card AXI Tunnel Master (for access by MB controllers)
+ * GMAC (MB) -> MB AXI Tunnel slave -> CPU Card AXI Tunnel Master -> DDR
+ */
+static const struct aperture axc001_axi_tunnel_memmap[16] = {
+       {AXC001_SLV_AXI_TUNNEL,         0x0},
+       {AXC001_SLV_AXI_TUNNEL,         0x1},
+       {AXC001_SLV_SRAM,               0x0},
+       {AXC001_SLV_NONE,               0x0},
+       {AXC001_SLV_NONE,               0x0},
+       {AXC001_SLV_NONE,               0x0},
+       {AXC001_SLV_NONE,               0x0},
+       {AXC001_SLV_NONE,               0x0},
+       {AXC001_SLV_DDR_PORT1,          0x0},
+       {AXC001_SLV_DDR_PORT1,          0x1},
+       {AXC001_SLV_DDR_PORT1,          0x2},
+       {AXC001_SLV_DDR_PORT1,          0x3},
+       {AXC001_SLV_NONE,               0x0},
+       {AXC001_SLV_AXI_TUNNEL,         0xD},
+       {AXC001_SLV_AXI_TUNNEL,         0xE},
+       {AXC001_SLV_AXI2APB,            0x0},
+};
+
+/*
+ * memmap for MB AXI Masters
+ * Same mem map for all perip controllers as well as MB AXI Tunnel Master
+ */
+static const struct aperture axs_mb_memmap[16] = {
+       {AXS_MB_SLV_SRAM,               0x0},
+       {AXS_MB_SLV_SRAM,               0x0},
+       {AXS_MB_SLV_NONE,               0x0},
+       {AXS_MB_SLV_NONE,               0x0},
+       {AXS_MB_SLV_NONE,               0x0},
+       {AXS_MB_SLV_NONE,               0x0},
+       {AXS_MB_SLV_NONE,               0x0},
+       {AXS_MB_SLV_NONE,               0x0},
+       {AXS_MB_SLV_AXI_TUNNEL_CPU,     0x8},   /* DDR on CPU Card */
+       {AXS_MB_SLV_AXI_TUNNEL_CPU,     0x9},   /* DDR on CPU Card */
+       {AXS_MB_SLV_AXI_TUNNEL_CPU,     0xA},
+       {AXS_MB_SLV_AXI_TUNNEL_CPU,     0xB},
+       {AXS_MB_SLV_NONE,               0x0},
+       {AXS_MB_SLV_AXI_TUNNEL_HAPS,    0xD},
+       {AXS_MB_SLV_CONTROL,            0x0},   /* MB Local CREG, CGU... */
+       {AXS_MB_SLV_AXI_TUNNEL_CPU,     0xF},
+};
+
+static noinline void __init
+axs101_set_memmap(void __iomem *base, const struct aperture map[16])
+{
+       unsigned int slave_select, slave_offset;
+       int i;
+
+       slave_select = slave_offset = 0;
+       for (i = 0; i < 8; i++) {
+               slave_select |= map[i].slave_sel << (i << 2);
+               slave_offset |= map[i].slave_off << (i << 2);
+       }
+
+       iowrite32(slave_select, base + 0x0);    /* SLV0 */
+       iowrite32(slave_offset, base + 0x8);    /* OFFSET0 */
+
+       slave_select = slave_offset = 0;
+       for (i = 0; i < 8; i++) {
+               slave_select |= map[i+8].slave_sel << (i << 2);
+               slave_offset |= map[i+8].slave_off << (i << 2);
+       }
+
+       iowrite32(slave_select, base + 0x4);    /* SLV1 */
+       iowrite32(slave_offset, base + 0xC);    /* OFFSET1 */
+}
+
+static void __init axs101_early_init(void)
+{
+       int i;
+
+       /* ARC 770D memory view */
+       axs101_set_memmap((void __iomem *) CREG_CPU_ADDR_770, axc001_memmap);
+       iowrite32(1, (void __iomem *) CREG_CPU_ADDR_770_UPD);
+
+       /* AXI tunnel memory map (incoming traffic from MB into CPU Card */
+       axs101_set_memmap((void __iomem *) CREG_CPU_ADDR_TUNN,
+                             axc001_axi_tunnel_memmap);
+       iowrite32(1, (void __iomem *) CREG_CPU_ADDR_TUNN_UPD);
+
+       /* MB peripherals memory map */
+       for (i = AXS_MB_MST_TUNNEL_CPU; i <= AXS_MB_MST_USB_OHCI; i++)
+               axs101_set_memmap((void __iomem *) AXS_MB_CREG + (i << 4),
+                                     axs_mb_memmap);
+
+       iowrite32(0x3ff, (void __iomem *) AXS_MB_CREG + 0x100); /* Update */
+
+       /* GPIO pins 18 and 19 are used as UART rx and tx, respectively. */
+       iowrite32(0x01, (void __iomem *) CREG_CPU_GPIO_UART_MUX);
+
+       /* Set up the MB interrupt system: mux interrupts to GPIO7) */
+       iowrite32(0x01, (void __iomem *) CREG_MB_IRQ_MUX);
+
+       /* reset ethernet and ULPI interfaces */
+       iowrite32(0x18, (void __iomem *) CREG_MB_SW_RESET);
+
+       /* map GPIO 14:10 to ARC 9:5 (IRQ mux change for MB v2 onwards) */
+       iowrite32(0x52, (void __iomem *) CREG_CPU_ARC770_IRQ_MUX);
+
+       axs10x_early_init();
+}
+
+#endif /* CONFIG_AXS101 */
+
+#ifdef CONFIG_AXS103
+
+#define AXC003_CGU     0xF0000000
+#define AXC003_CREG    0xF0001000
+#define AXC003_MST_AXI_TUNNEL  0
+#define AXC003_MST_HS38                1
+
+#define CREG_CPU_AXI_M0_IRQ_MUX        (AXC003_CREG + 0x440)
+#define CREG_CPU_GPIO_UART_MUX (AXC003_CREG + 0x480)
+#define CREG_CPU_TUN_IO_CTRL   (AXC003_CREG + 0x494)
+
+
+union pll_reg {
+       struct {
+#ifdef CONFIG_CPU_BIG_ENDIAN
+               unsigned int pad:17, noupd:1, bypass:1, edge:1, high:6, low:6;
+#else
+               unsigned int low:6, high:6, edge:1, bypass:1, noupd:1, pad:17;
+#endif
+       };
+       unsigned int val;
+};
+
+static unsigned int __init axs103_get_freq(void)
+{
+       union pll_reg idiv, fbdiv, odiv;
+       unsigned int f = 33333333;
+
+       idiv.val = ioread32((void __iomem *)AXC003_CGU + 0x80 + 0);
+       fbdiv.val = ioread32((void __iomem *)AXC003_CGU + 0x80 + 4);
+       odiv.val = ioread32((void __iomem *)AXC003_CGU + 0x80 + 8);
+
+       if (idiv.bypass != 1)
+               f = f / (idiv.low + idiv.high);
+
+       if (fbdiv.bypass != 1)
+               f = f * (fbdiv.low + fbdiv.high);
+
+       if (odiv.bypass != 1)
+               f = f / (odiv.low + odiv.high);
+
+       f = (f + 500000) / 1000000; /* Rounding */
+       return f;
+}
+
+static inline unsigned int __init encode_div(unsigned int id, int upd)
+{
+       union pll_reg div;
+
+       div.val = 0;
+
+       div.noupd = !upd;
+       div.bypass = id == 1 ? 1 : 0;
+       div.edge = (id%2 == 0) ? 0 : 1;  /* 0 = rising */
+       div.low = (id%2 == 0) ? id >> 1 : (id >> 1)+1;
+       div.high = id >> 1;
+
+       return div.val;
+}
+
+noinline static void __init
+axs103_set_freq(unsigned int id, unsigned int fd, unsigned int od)
+{
+       write_cgu_reg(encode_div(id, 0),
+                     (void __iomem *)AXC003_CGU + 0x80 + 0,
+                     (void __iomem *)AXC003_CGU + 0x110);
+
+       write_cgu_reg(encode_div(fd, 0),
+                     (void __iomem *)AXC003_CGU + 0x80 + 4,
+                     (void __iomem *)AXC003_CGU + 0x110);
+
+       write_cgu_reg(encode_div(od, 1),
+                     (void __iomem *)AXC003_CGU + 0x80 + 8,
+                     (void __iomem *)AXC003_CGU + 0x110);
+}
+
+static void __init axs103_early_init(void)
+{
+       switch (arc_get_core_freq()/1000000) {
+       case 33:
+               axs103_set_freq(1, 1, 1);
+               break;
+       case 50:
+               axs103_set_freq(1, 30, 20);
+               break;
+       case 75:
+               axs103_set_freq(2, 45, 10);
+               break;
+       case 90:
+               axs103_set_freq(2, 54, 10);
+               break;
+       case 100:
+               axs103_set_freq(1, 30, 10);
+               break;
+       case 125:
+               axs103_set_freq(2, 45,  6);
+               break;
+       default:
+               /*
+                * In this case, core_frequency derived from
+                * DT "clock-frequency" might not match with board value.
+                * Hence update it to match the board value.
+                */
+               arc_set_core_freq(axs103_get_freq() * 1000000);
+               break;
+       }
+
+       pr_info("Freq is %dMHz\n", axs103_get_freq());
+
+       /* Memory maps already config in pre-bootloader */
+
+       /* set GPIO mux to UART */
+       iowrite32(0x01, (void __iomem *) CREG_CPU_GPIO_UART_MUX);
+
+       iowrite32((0x00100000U | 0x000C0000U | 0x00003322U),
+                 (void __iomem *) CREG_CPU_TUN_IO_CTRL);
+
+       /* Set up the AXS_MB interrupt system.*/
+       iowrite32(12, (void __iomem *) (CREG_CPU_AXI_M0_IRQ_MUX
+                                        + (AXC003_MST_HS38 << 2)));
+
+       /* connect ICTL - Main Board with GPIO line */
+       iowrite32(0x01, (void __iomem *) CREG_MB_IRQ_MUX);
+
+       axs10x_print_board_ver(AXC003_CREG + 4088, "AXC003 CPU Card");
+
+       axs10x_early_init();
+
+#ifdef CONFIG_ARC_MCIP
+       /* No Hardware init, but filling the smp ops callbacks */
+       mcip_init_early_smp();
+#endif
+}
+#endif
+
+#ifdef CONFIG_AXS101
+
+static const char *axs101_compat[] __initconst = {
+       "snps,axs101",
+       NULL,
+};
+
+MACHINE_START(AXS101, "axs101")
+       .dt_compat      = axs101_compat,
+       .init_early     = axs101_early_init,
+MACHINE_END
+
+#endif /* CONFIG_AXS101 */
+
+#ifdef CONFIG_AXS103
+
+static const char *axs103_compat[] __initconst = {
+       "snps,axs103",
+       NULL,
+};
+
+MACHINE_START(AXS103, "axs103")
+       .dt_compat      = axs103_compat,
+       .init_early     = axs103_early_init,
+#ifdef CONFIG_ARC_MCIP
+       .init_smp       = mcip_init_smp,
+#endif
+MACHINE_END
+
+/*
+ * For the VDK OS-kit, to get the offset to pid and command fields
+ */
+char coware_swa_pid_offset[TASK_PID];
+char coware_swa_comm_offset[TASK_COMM];
+
+#endif /* CONFIG_AXS103 */
diff --git a/arch/arc/plat-sim/Kconfig b/arch/arc/plat-sim/Kconfig
new file mode 100644 (file)
index 0000000..18e39fc
--- /dev/null
@@ -0,0 +1,14 @@
+#
+# Copyright (C) 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
+#
+# 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.
+#
+
+menuconfig ARC_PLAT_SIM
+       bool "ARC nSIM based simulation virtual platforms"
+       select ARC_HAS_COH_CACHES if SMP
+       help
+         Support for nSIM based ARC simulation platforms
+         This includes the standalone nSIM (uart only) vs. System C OSCI VP
diff --git a/arch/arc/plat-sim/Makefile b/arch/arc/plat-sim/Makefile
new file mode 100644 (file)
index 0000000..00b1a95
--- /dev/null
@@ -0,0 +1,9 @@
+#
+# Copyright (C) 2011-2012 Synopsys, Inc. (www.synopsys.com)
+#
+# 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.
+#
+
+obj-y := platform.o
diff --git a/arch/arc/plat-sim/platform.c b/arch/arc/plat-sim/platform.c
new file mode 100644 (file)
index 0000000..d9e35b4
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * ARC simulation Platform support code
+ *
+ * Copyright (C) 2012 Synopsys, Inc. (www.synopsys.com)
+ *
+ * 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/init.h>
+#include <asm/mach_desc.h>
+#include <asm/mcip.h>
+
+/*----------------------- Machine Descriptions ------------------------------
+ *
+ * Machine description is simply a set of platform/board specific callbacks
+ * This is not directly related to DeviceTree based dynamic device creation,
+ * however as part of early device tree scan, we also select the right
+ * callback set, by matching the DT compatible name.
+ */
+
+static const char *simulation_compat[] __initconst = {
+       "snps,nsim",
+       "snps,nsim_hs",
+       "snps,nsimosci",
+       "snps,nsimosci_hs",
+       NULL,
+};
+
+MACHINE_START(SIMULATION, "simulation")
+       .dt_compat      = simulation_compat,
+#ifdef CONFIG_ARC_MCIP
+       .init_early     = mcip_init_early_smp,
+       .init_smp       = mcip_init_smp,
+#endif
+MACHINE_END
index e6a83d712ef6772ac7265e914837da7806e21441..55e3abc2d027270b0e6e1c554b9f376d3cd355f1 100644 (file)
 #endif
 
 #ifdef CONFIG_SMP
+
+#ifndef smp_mb
 #define smp_mb()       mb()
+#endif
+
+#ifndef smp_rmb
 #define smp_rmb()      rmb()
+#endif
+
+#ifndef smp_wmb
 #define smp_wmb()      wmb()
+#endif
+
+#ifndef smp_read_barrier_depends
 #define smp_read_barrier_depends()     read_barrier_depends()
-#else
+#endif
+
+#else  /* !CONFIG_SMP */
+
+#ifndef smp_mb
 #define smp_mb()       barrier()
+#endif
+
+#ifndef smp_rmb
 #define smp_rmb()      barrier()
+#endif
+
+#ifndef smp_wmb
 #define smp_wmb()      barrier()
+#endif
+
+#ifndef smp_read_barrier_depends
 #define smp_read_barrier_depends()     do { } while (0)
 #endif
 
+#endif /* CONFIG_SMP */
+
 #ifndef smp_store_mb
 #define smp_store_mb(var, value)  do { WRITE_ONCE(var, value); mb(); } while (0)
 #endif
index 1052d4834a44f502bda4f4f1ebe1202ace1608f5..c2423d913b46bd0e659ea4d4c057a3af6119c2d4 100644 (file)
 #define EM_MICROBLAZE  189
 #endif
 
+#ifndef EM_ARCV2
+#define EM_ARCV2       195
+#endif
+
 static int fd_map;     /* File descriptor for file being modified. */
 static int mmap_failed; /* Boolean flag. */
 static void *ehdr_curr; /* current ElfXX_Ehdr *  for resource cleanup */
@@ -281,6 +285,7 @@ do_file(char const *const fname)
                custom_sort = sort_relative_table;
                break;
        case EM_ARCOMPACT:
+       case EM_ARCV2:
        case EM_ARM:
        case EM_AARCH64:
        case EM_MICROBLAZE: