- 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 - Miscll updates/cleanups -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJVk0g8AAoJEGnX8d3iisJecqsQAI6gvBC4GSNYDrmgGJJK1uLQ uf6ZXQRLBtyxwa6VMvaNFe91i5XV5WvEXDuNBQX4FdYbp7Fs+Jz5VK79xFtbVEdU H6mgKcs9HBwQvrHBxl54XxxXfX7kD1kxrlV7cL4b7bXTEX0XyH5ROUj600/YP+B4 8t+XdYcfgFK0HpeFGXVP+Xmv/e+hBbzCpOjOd2ZFqEwymvSpZDc4KZ2yDvV2+Ybn JNZ421urQOrxR27njvvPvtpeN7uuJKfRYq7IuIR8+Ad72S19EDdw+DZHp2XoUMXA wgydWrrOaX2Dr2CmXHGA1C4nWEG7+Yo9I1WitjJct0tkOQyDR2OIDGmvKGBd1uoS QsihtoKBRvns+2gpXBEOmOHmF6ggpHNN0ppIwCp+AK5kX3fmxBtyUekyYmVpg8oQ xgFIuJgmiAvW7QB7xIO6SFFt18De2ifDRrKWJwVauvfW/PvUIwuUBEcbh0OHAn54 ebUUWu2ZdVNe0XCsZOAQGwYHZRWBk8Bn3bhFpNnOliRiF77e9GsKeGYeIswYFy7I 42Gp35ftEj1pLLFZ1vIsAo72N6ErmHwPOcJkaBYaTbPGPcTEO2aR6b8WOcCjsPxK DUeUV3H2HV+6V4jw/96lnsaRqsaj4TsJxEAFRR3wT1DLoRudCIDubaXTdvvDie77 RgKn4ZdxgmXD97+deBqc =KwNo -----END PGP SIGNATURE----- Merge tag 'arc-4.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/vgupta/arc 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 ...
This commit is contained in:
commit
0890a26479
106 changed files with 7059 additions and 2394 deletions
46
Documentation/devicetree/bindings/arc/archs-idu-intc.txt
Normal file
46
Documentation/devicetree/bindings/arc/archs-idu-intc.txt
Normal file
|
@ -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 */
|
||||
};
|
22
Documentation/devicetree/bindings/arc/archs-intc.txt
Normal file
22
Documentation/devicetree/bindings/arc/archs-intc.txt
Normal file
|
@ -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>;
|
||||
};
|
7
Documentation/devicetree/bindings/arc/axs101.txt
Normal file
7
Documentation/devicetree/bindings/arc/axs101.txt
Normal file
|
@ -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";
|
8
Documentation/devicetree/bindings/arc/axs103.txt
Normal file
8
Documentation/devicetree/bindings/arc/axs103.txt
Normal file
|
@ -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";
|
|
@ -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>
|
||||
|
|
159
arch/arc/Kconfig
159
arch/arc/Kconfig
|
@ -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
|
||||
|
|
|
@ -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/
|
||||
|
||||
|
|
|
@ -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))
|
||||
|
|
100
arch/arc/boot/dts/axc001.dtsi
Normal file
100
arch/arc/boot/dts/axc001.dtsi
Normal file
|
@ -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 */
|
||||
};
|
||||
};
|
102
arch/arc/boot/dts/axc003.dtsi
Normal file
102
arch/arc/boot/dts/axc003.dtsi
Normal file
|
@ -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 */
|
||||
};
|
||||
};
|
126
arch/arc/boot/dts/axc003_idu.dtsi
Normal file
126
arch/arc/boot/dts/axc003_idu.dtsi
Normal file
|
@ -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 */
|
||||
};
|
||||
};
|
21
arch/arc/boot/dts/axs101.dts
Normal file
21
arch/arc/boot/dts/axs101.dts
Normal file
|
@ -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";
|
||||
};
|
||||
};
|
24
arch/arc/boot/dts/axs103.dts
Normal file
24
arch/arc/boot/dts/axs103.dts
Normal file
|
@ -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";
|
||||
};
|
||||
};
|
24
arch/arc/boot/dts/axs103_idu.dts
Normal file
24
arch/arc/boot/dts/axs103_idu.dts
Normal file
|
@ -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";
|
||||
};
|
||||
};
|
224
arch/arc/boot/dts/axs10x_mb.dtsi
Normal file
224
arch/arc/boot/dts/axs10x_mb.dtsi
Normal file
|
@ -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>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
|
@ -10,7 +10,7 @@
|
|||
/include/ "skeleton.dtsi"
|
||||
|
||||
/ {
|
||||
compatible = "snps,arc-angel4";
|
||||
compatible = "snps,nsim";
|
||||
clock-frequency = <80000000>; /* 80 MHZ */
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
53
arch/arc/boot/dts/nsim_hs.dts
Normal file
53
arch/arc/boot/dts/nsim_hs.dts
Normal file
|
@ -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>;
|
||||
};
|
||||
};
|
||||
};
|
72
arch/arc/boot/dts/nsim_hs_idu.dts
Normal file
72
arch/arc/boot/dts/nsim_hs_idu.dts
Normal file
|
@ -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>;
|
||||
};
|
||||
};
|
||||
};
|
80
arch/arc/boot/dts/nsimosci_hs.dts
Normal file
80
arch/arc/boot/dts/nsimosci_hs.dts
Normal file
|
@ -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>;
|
||||
};
|
||||
};
|
||||
};
|
101
arch/arc/boot/dts/nsimosci_hs_idu.dts
Normal file
101
arch/arc/boot/dts/nsimosci_hs_idu.dts
Normal file
|
@ -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>;
|
||||
};
|
||||
};
|
||||
};
|
61
arch/arc/boot/dts/vdk_axc003.dtsi
Normal file
61
arch/arc/boot/dts/vdk_axc003.dtsi
Normal file
|
@ -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 */
|
||||
};
|
||||
};
|
76
arch/arc/boot/dts/vdk_axc003_idu.dtsi
Normal file
76
arch/arc/boot/dts/vdk_axc003_idu.dtsi
Normal file
|
@ -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 */
|
||||
};
|
||||
};
|
93
arch/arc/boot/dts/vdk_axs10x_mb.dtsi
Normal file
93
arch/arc/boot/dts/vdk_axs10x_mb.dtsi
Normal file
|
@ -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";
|
||||
};
|
||||
};
|
||||
};
|
21
arch/arc/boot/dts/vdk_hs38.dts
Normal file
21
arch/arc/boot/dts/vdk_hs38.dts
Normal file
|
@ -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";
|
||||
};
|
||||
};
|
21
arch/arc/boot/dts/vdk_hs38_smp.dts
Normal file
21
arch/arc/boot/dts/vdk_hs38_smp.dts
Normal file
|
@ -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";
|
||||
};
|
||||
};
|
111
arch/arc/configs/axs101_defconfig
Normal file
111
arch/arc/configs/axs101_defconfig
Normal file
|
@ -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
|
117
arch/arc/configs/axs103_defconfig
Normal file
117
arch/arc/configs/axs103_defconfig
Normal file
|
@ -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
|
118
arch/arc/configs/axs103_smp_defconfig
Normal file
118
arch/arc/configs/axs103_smp_defconfig
Normal file
|
@ -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
|
|
@ -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
|
||||
|
|
64
arch/arc/configs/nsim_hs_defconfig
Normal file
64
arch/arc/configs/nsim_hs_defconfig
Normal file
|
@ -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
|
63
arch/arc/configs/nsim_hs_smp_defconfig
Normal file
63
arch/arc/configs/nsim_hs_smp_defconfig
Normal file
|
@ -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
|
|
@ -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
|
||||
|
|
73
arch/arc/configs/nsimosci_hs_defconfig
Normal file
73
arch/arc/configs/nsimosci_hs_defconfig
Normal file
|
@ -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
|
93
arch/arc/configs/nsimosci_hs_smp_defconfig
Normal file
93
arch/arc/configs/nsimosci_hs_smp_defconfig
Normal file
|
@ -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
|
|
@ -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"
|
||||
|
|
102
arch/arc/configs/vdk_hs38_defconfig
Normal file
102
arch/arc/configs/vdk_hs38_defconfig
Normal file
|
@ -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
|
104
arch/arc/configs/vdk_hs38_smp_defconfig
Normal file
104
arch/arc/configs/vdk_hs38_smp_defconfig
Normal file
|
@ -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
|
|
@ -1,5 +1,4 @@
|
|||
generic-y += auxvec.h
|
||||
generic-y += barrier.h
|
||||
generic-y += bitsperlong.h
|
||||
generic-y += bugs.h
|
||||
generic-y += clkdev.h
|
||||
|
|
|
@ -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
|
||||
|
@ -58,6 +62,15 @@
|
|||
#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 */
|
||||
|
|
|
@ -23,13 +23,21 @@
|
|||
|
||||
#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; \
|
||||
})
|
||||
|
||||
|
|
48
arch/arc/include/asm/barrier.h
Normal file
48
arch/arc/include/asm/barrier.h
Normal file
|
@ -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
|
|
@ -18,83 +18,50 @@
|
|||
#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;
|
||||
/*
|
||||
* Hardware assisted Atomic-R-M-W
|
||||
*/
|
||||
|
||||
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;
|
||||
|
||||
__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);
|
||||
#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 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;
|
||||
}
|
||||
|
||||
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);
|
||||
#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 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);
|
||||
#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 void __change_bit(unsigned long nr, volatile unsigned long *m)
|
||||
{
|
||||
unsigned long temp;
|
||||
m += nr >> 5;
|
||||
#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)
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -22,11 +22,10 @@
|
|||
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);
|
||||
|
|
|
@ -14,23 +14,6 @@
|
|||
#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
|
||||
|
|
|
@ -15,6 +15,11 @@
|
|||
/* 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
|
||||
|
|
190
arch/arc/include/asm/entry-arcv2.h
Normal file
190
arch/arc/include/asm/entry-arcv2.h
Normal file
|
@ -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
|
307
arch/arc/include/asm/entry-compact.h
Normal file
307
arch/arc/include/asm/entry-compact.h
Normal file
|
@ -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 */
|
|
@ -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
|
||||
|
@ -143,8 +125,6 @@
|
|||
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.
|
||||
|
@ -157,12 +137,13 @@
|
|||
*-------------------------------------------------------------*/
|
||||
.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
|
||||
|
@ -209,12 +190,16 @@
|
|||
.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
|
||||
|
||||
/*--------------------------------------------------------------
|
||||
|
@ -240,117 +225,6 @@
|
|||
|
||||
.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"
|
||||
*/
|
||||
|
@ -359,222 +233,6 @@
|
|||
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
|
||||
|
||||
/*-------------------------------------------------
|
||||
|
@ -643,6 +301,4 @@
|
|||
|
||||
#endif /* CONFIG_ARC_CURR_IN_REG */
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#endif /* __ASM_ARC_ENTRY_H */
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -13,8 +13,14 @@
|
|||
#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>
|
||||
|
|
124
arch/arc/include/asm/irqflags-arcv2.h
Normal file
124
arch/arc/include/asm/irqflags-arcv2.h
Normal file
|
@ -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
|
183
arch/arc/include/asm/irqflags-compact.h
Normal file
183
arch/arc/include/asm/irqflags-compact.h
Normal file
|
@ -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
|
|
@ -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
|
||||
|
@ -9,171 +10,10 @@
|
|||
#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());
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ISA_ARCOMPACT
|
||||
#include <asm/irqflags-compact.h>
|
||||
#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
|
||||
|
||||
#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
|
||||
|
|
94
arch/arc/include/asm/mcip.h
Normal file
94
arch/arc/include/asm/mcip.h
Normal file
|
@ -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
|
|
@ -15,24 +15,41 @@
|
|||
#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
|
||||
|
@ -45,6 +62,11 @@
|
|||
#define TLBIVUTLB 0x6 /* explicitly inv uTLBs */
|
||||
#endif
|
||||
|
||||
#if (CONFIG_ARC_MMU_VER >= 4)
|
||||
#define TLBInsertEntry 0x7
|
||||
#define TLBDeleteEntry 0x8
|
||||
#endif
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
typedef struct {
|
||||
|
|
|
@ -72,8 +72,18 @@
|
|||
#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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#endif
|
||||
|
||||
#define THREAD_SIZE (PAGE_SIZE << THREAD_SIZE_ORDER)
|
||||
#define THREAD_SHIFT (PAGE_SHIFT << THREAD_SIZE_ORDER)
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
239
arch/arc/kernel/entry-arcv2.S
Normal file
239
arch/arc/kernel/entry-arcv2.S
Normal file
|
@ -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)
|
393
arch/arc/kernel/entry-compact.S
Normal file
393
arch/arc/kernel/entry-compact.S
Normal file
|
@ -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)
|
|
@ -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
|
||||
*/
|
||||
|
||||
/*------------------------------------------------------------------
|
||||
|
@ -67,206 +20,59 @@
|
|||
* 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
|
||||
;################### Special Sys Call Wrappers ##########################
|
||||
|
||||
;############################ Vector Table #################################
|
||||
ENTRY(sys_clone_wrapper)
|
||||
SAVE_CALLEE_SAVED_USER
|
||||
bl @sys_clone
|
||||
DISCARD_CALLEE_SAVED_USER
|
||||
|
||||
.macro VECTOR lbl
|
||||
#if 1 /* Just in case, build breaks */
|
||||
j \lbl
|
||||
#else
|
||||
b \lbl
|
||||
nop
|
||||
#endif
|
||||
.endm
|
||||
GET_CURR_THR_INFO_FLAGS r10
|
||||
btst r10, TIF_SYSCALL_TRACE
|
||||
bnz tracesys_exit
|
||||
|
||||
.section .vector, "ax",@progbits
|
||||
.align 4
|
||||
b ret_from_system_call
|
||||
END(sys_clone_wrapper)
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
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
|
||||
|
||||
; ********* Critical System Events **********************
|
||||
VECTOR res_service ; 0x0, Restart Vector (0x0)
|
||||
VECTOR mem_service ; 0x8, Mem exception (0x1)
|
||||
VECTOR instr_service ; 0x10, Instrn Error (0x2)
|
||||
ld r9, [sp, PT_status32]
|
||||
brne r9, 0, 1f
|
||||
|
||||
; ******************** 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)
|
||||
|
||||
; TODO-vineetg for SMP this wont work
|
||||
; free up r9 as scratchpad
|
||||
st r9, [@int2_saved_reg]
|
||||
|
||||
;Which mode (user/kernel) was the system in when intr occured
|
||||
lr r9, [status32_l2]
|
||||
|
||||
SWITCH_TO_KERNEL_STK
|
||||
SAVE_ALL_INT2
|
||||
|
||||
;------------------------------------------------------
|
||||
; 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]
|
||||
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
|
||||
; 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)
|
||||
|
||||
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)
|
||||
#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
|
||||
|
||||
; Reset to .text as this file is included in entry-<isa>.S
|
||||
.section .text, "ax",@progbits
|
||||
#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
|
||||
|
||||
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 #############################
|
||||
|
||||
; ---------------------------------------------
|
||||
|
@ -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
|
||||
b .Lrestore_regs
|
||||
|
||||
;############# 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
|
||||
##### DONT ADD CODE HERE - .Lrestore_regs actually follows in entry-<isa>.S
|
||||
|
||||
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
|
||||
|
||||
;return from level 1
|
||||
|
||||
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
|
||||
|
|
|
@ -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
|
||||
|
|
143
arch/arc/kernel/intc-arcv2.c
Normal file
143
arch/arc/kernel/intc-arcv2.c
Normal file
|
@ -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);
|
226
arch/arc/kernel/intc-compact.c
Normal file
226
arch/arc/kernel/intc-compact.c
Normal file
|
@ -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);
|
|
@ -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);
|
||||
|
|
341
arch/arc/kernel/mcip.c
Normal file
341
arch/arc/kernel/mcip.c
Normal file
|
@ -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);
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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)
|
||||
};
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 */
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
if (consumer_fn(address, arg) == -1)
|
||||
break;
|
||||
|
||||
ret = arc_unwind(&frame_info);
|
||||
|
||||
if (ret == 0) {
|
||||
frame_info.regs.r63 = frame_info.regs.r31;
|
||||
continue;
|
||||
} else {
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
|
||||
frame_info.regs.r63 = frame_info.regs.r31;
|
||||
}
|
||||
|
||||
return address; /* return the last address it saw */
|
||||
|
|
|
@ -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 */
|
||||
|
@ -59,14 +62,10 @@
|
|||
|
||||
/********** 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;
|
||||
}
|
||||
|
||||
|
@ -74,6 +73,55 @@ static cycle_t arc_counter_read(struct clocksource *cs)
|
|||
{
|
||||
unsigned long flags;
|
||||
union {
|
||||
#ifdef CONFIG_CPU_BIG_ENDIAN
|
||||
struct { u32 h, l; };
|
||||
#else
|
||||
struct { u32 l, h; };
|
||||
#endif
|
||||
cycle_t full;
|
||||
} stamp;
|
||||
|
||||
local_irq_save(flags);
|
||||
|
||||
__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);
|
||||
|
||||
local_irq_restore(flags);
|
||||
|
||||
return stamp.full;
|
||||
}
|
||||
|
||||
static struct clocksource arc_counter = {
|
||||
.name = "ARConnect GRTC",
|
||||
.rating = 400,
|
||||
.read = arc_counter_read,
|
||||
.mask = CLOCKSOURCE_MASK(64),
|
||||
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
#ifdef CONFIG_ARC_HAS_RTC
|
||||
|
||||
#define AUX_RTC_CTRL 0x103
|
||||
#define AUX_RTC_LOW 0x104
|
||||
#define AUX_RTC_HIGH 0x105
|
||||
|
||||
int arc_counter_setup(void)
|
||||
{
|
||||
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
|
||||
|
@ -82,37 +130,27 @@ static cycle_t arc_counter_read(struct clocksource *cs)
|
|||
cycle_t full;
|
||||
} stamp;
|
||||
|
||||
flags = arch_local_irq_save();
|
||||
|
||||
__asm__ __volatile(
|
||||
" .extCoreRegister tsch, 58, r, cannot_shortcut \n"
|
||||
" rtsc %0, 0 \n"
|
||||
" mov %1, 0 \n"
|
||||
: "=r" (stamp.low), "=r" (stamp.high));
|
||||
|
||||
arch_local_irq_restore(flags);
|
||||
"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 = "ARC RTSC",
|
||||
.rating = 300,
|
||||
.name = "ARCv2 RTC",
|
||||
.rating = 350,
|
||||
.read = arc_counter_read,
|
||||
.mask = CLOCKSOURCE_MASK(32),
|
||||
.mask = CLOCKSOURCE_MASK(64),
|
||||
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
|
||||
};
|
||||
|
||||
#else /* !CONFIG_ARC_HAS_RTSC */
|
||||
|
||||
static bool is_usable_as_clocksource(void)
|
||||
{
|
||||
#ifdef CONFIG_SMP
|
||||
return 0;
|
||||
#else
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
#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 *********/
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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]
|
||||
|
|
236
arch/arc/lib/memcpy-archs.S
Normal file
236
arch/arc/lib/memcpy-archs.S
Normal file
|
@ -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)
|
93
arch/arc/lib/memset-archs.S
Normal file
93
arch/arc/lib/memset-archs.S
Normal file
|
@ -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)
|
78
arch/arc/lib/strcmp-archs.S
Normal file
78
arch/arc/lib/strcmp-archs.S
Normal file
|
@ -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)
|
|
@ -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
|
||||
|
|
|
@ -1,64 +1,12 @@
|
|||
/*
|
||||
* ARC700 VIPT Cache Management
|
||||
* 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.
|
||||
*
|
||||
* 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>
|
||||
|
@ -73,9 +21,15 @@
|
|||
#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) \
|
||||
|
@ -91,6 +45,11 @@ char *arc_cache_mumbojumbo(int c, char *buf, int len)
|
|||
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;
|
||||
}
|
||||
|
||||
|
@ -101,7 +60,7 @@ char *arc_cache_mumbojumbo(int c, char *buf, int len)
|
|||
*/
|
||||
void read_decode_cache_bcr(void)
|
||||
{
|
||||
struct cpuinfo_arc_cache *p_ic, *p_dc;
|
||||
struct cpuinfo_arc_cache *p_ic, *p_dc, *p_slc;
|
||||
unsigned int cpu = smp_processor_id();
|
||||
struct bcr_cache {
|
||||
#ifdef CONFIG_CPU_BIG_ENDIAN
|
||||
|
@ -111,14 +70,29 @@ void read_decode_cache_bcr(void)
|
|||
#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;
|
||||
|
||||
BUG_ON(ibcr.config != 3);
|
||||
p_ic->assoc = 2; /* Fixed to 2w set assoc */
|
||||
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;
|
||||
|
@ -130,66 +104,40 @@ dc_chk:
|
|||
READ_BCR(ARC_REG_DC_BCR, dbcr);
|
||||
|
||||
if (!dbcr.ver)
|
||||
return;
|
||||
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 */
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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
|
||||
* Line Operation on {I,D}-Cache
|
||||
*/
|
||||
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
|
||||
|
@ -197,162 +145,7 @@ void arc_cache_init(void)
|
|||
#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
|
||||
* 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
|
||||
|
@ -393,9 +186,228 @@ static inline void __dc_line_op(unsigned long paddr, unsigned long vaddr,
|
|||
* "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 __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)
|
||||
{
|
||||
|
@ -410,7 +422,7 @@ __ic_line_inv_vaddr_local(unsigned long paddr, unsigned long vaddr,
|
|||
unsigned long flags;
|
||||
|
||||
local_irq_save(flags);
|
||||
__cache_line_loop(paddr, vaddr, sz, OP_INV_IC);
|
||||
(*_cache_line_loop_ic_fn)(paddr, vaddr, sz, OP_INV_IC);
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
|
@ -453,6 +465,53 @@ static void __ic_line_inv_vaddr(unsigned long paddr, unsigned long vaddr,
|
|||
|
||||
#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
|
||||
|
@ -493,7 +552,7 @@ void flush_dcache_page(struct page *page)
|
|||
} else if (page_mapped(page)) {
|
||||
|
||||
/* kernel reading from page with U-mapping */
|
||||
void *paddr = page_address(page);
|
||||
unsigned long paddr = (unsigned long)page_address(page);
|
||||
unsigned long vaddr = page->index << PAGE_CACHE_SHIFT;
|
||||
|
||||
if (addr_not_cache_congruent(paddr, vaddr))
|
||||
|
@ -502,22 +561,30 @@ void flush_dcache_page(struct page *page)
|
|||
}
|
||||
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);
|
||||
|
||||
|
@ -605,7 +672,7 @@ void __inv_icache_page(unsigned long paddr, unsigned long vaddr)
|
|||
* 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)
|
||||
void __flush_dcache_page(unsigned long paddr, unsigned long vaddr)
|
||||
{
|
||||
__dc_line_op(paddr, vaddr & PAGE_MASK, PAGE_SIZE, OP_FLUSH_N_INV);
|
||||
}
|
||||
|
@ -637,7 +704,7 @@ void flush_cache_page(struct vm_area_struct *vma, unsigned long u_vaddr,
|
|||
|
||||
u_vaddr &= PAGE_MASK;
|
||||
|
||||
___flush_dcache_page(paddr, u_vaddr);
|
||||
__flush_dcache_page(paddr, u_vaddr);
|
||||
|
||||
if (vma->vm_flags & VM_EXEC)
|
||||
__inv_icache_page(paddr, u_vaddr);
|
||||
|
@ -663,8 +730,8 @@ void flush_anon_page(struct vm_area_struct *vma, struct page *page,
|
|||
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);
|
||||
unsigned long kfrom = (unsigned long)page_address(from);
|
||||
unsigned long kto = (unsigned long)page_address(to);
|
||||
int clean_src_k_mappings = 0;
|
||||
|
||||
/*
|
||||
|
@ -680,7 +747,7 @@ void copy_user_highpage(struct page *to, struct page *from,
|
|||
clean_src_k_mappings = 1;
|
||||
}
|
||||
|
||||
copy_page(kto, kfrom);
|
||||
copy_page((void *)kto, (void *)kfrom);
|
||||
|
||||
/*
|
||||
* Mark DST page K-mapping as dirty for a later finalization by
|
||||
|
@ -721,3 +788,56 @@ SYSCALL_DEFINE3(cacheflush, uint32_t, start, uint32_t, sz, uint32_t, flags)
|
|||
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");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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);
|
||||
}
|
46
arch/arc/plat-axs10x/Kconfig
Normal file
46
arch/arc/plat-axs10x/Kconfig
Normal file
|
@ -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
|
9
arch/arc/plat-axs10x/Makefile
Normal file
9
arch/arc/plat-axs10x/Makefile
Normal file
|
@ -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
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue