diff options
Diffstat (limited to 'arch')
39 files changed, 725 insertions, 194 deletions
diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig index 7db85ab00c52..a598641eed98 100644 --- a/arch/arc/Kconfig +++ b/arch/arc/Kconfig @@ -100,6 +100,7 @@ source "arch/arc/plat-tb10x/Kconfig" source "arch/arc/plat-axs10x/Kconfig" #New platform adds here source "arch/arc/plat-eznps/Kconfig" +source "arch/arc/plat-hsdk/Kconfig" endmenu @@ -418,7 +419,7 @@ endif # ISA_ARCV2 endmenu # "ARC CPU Configuration" config LINUX_LINK_BASE - hex "Linux Link Address" + hex "Kernel link address" default "0x80000000" help ARC700 divides the 32 bit phy address space into two equal halves @@ -431,6 +432,14 @@ config LINUX_LINK_BASE If you don't know what the above means, leave this setting alone. This needs to match memory start address specified in Device Tree +config LINUX_RAM_BASE + hex "RAM base address" + default LINUX_LINK_BASE + help + By default Linux is linked at base of RAM. However in some special + cases (such as HSDK), Linux can't be linked at start of DDR, hence + this option. + config HIGHMEM bool "High Memory Support" select ARCH_DISCONTIGMEM_ENABLE diff --git a/arch/arc/Makefile b/arch/arc/Makefile index 3a61cfcc38c0..3a4b52b7e09d 100644 --- a/arch/arc/Makefile +++ b/arch/arc/Makefile @@ -111,6 +111,7 @@ core-y += arch/arc/plat-sim/ core-$(CONFIG_ARC_PLAT_TB10X) += arch/arc/plat-tb10x/ core-$(CONFIG_ARC_PLAT_AXS10X) += arch/arc/plat-axs10x/ core-$(CONFIG_ARC_PLAT_EZNPS) += arch/arc/plat-eznps/ +core-$(CONFIG_ARC_SOC_HSDK) += arch/arc/plat-hsdk/ ifdef CONFIG_ARC_PLAT_EZNPS KBUILD_CPPFLAGS += -I$(srctree)/arch/arc/plat-eznps/include diff --git a/arch/arc/boot/dts/axc001.dtsi b/arch/arc/boot/dts/axc001.dtsi index a380ffa1a458..fdc266504ada 100644 --- a/arch/arc/boot/dts/axc001.dtsi +++ b/arch/arc/boot/dts/axc001.dtsi @@ -99,7 +99,7 @@ memory { device_type = "memory"; - /* CONFIG_KERNEL_RAM_BASE_ADDRESS needs to match low mem start */ + /* CONFIG_LINUX_RAM_BASE needs to match low mem start */ reg = <0x0 0x80000000 0x0 0x1b000000>; /* (512 - 32) MiB */ }; diff --git a/arch/arc/boot/dts/axc003.dtsi b/arch/arc/boot/dts/axc003.dtsi index cc9239ef8d08..4e6e9f57e790 100644 --- a/arch/arc/boot/dts/axc003.dtsi +++ b/arch/arc/boot/dts/axc003.dtsi @@ -24,10 +24,17 @@ ranges = <0x00000000 0x0 0xf0000000 0x10000000>; - core_clk: core_clk { + input_clk: input-clk { #clock-cells = <0>; compatible = "fixed-clock"; - clock-frequency = <90000000>; + clock-frequency = <33333333>; + }; + + core_clk: core-clk@80 { + compatible = "snps,axs10x-arc-pll-clock"; + reg = <0x80 0x10>, <0x100 0x10>; + #clock-cells = <0>; + clocks = <&input_clk>; }; core_intc: archs-intc@cpu { @@ -102,7 +109,7 @@ memory { device_type = "memory"; - /* CONFIG_KERNEL_RAM_BASE_ADDRESS needs to match low mem start */ + /* CONFIG_LINUX_RAM_BASE needs to match low mem start */ reg = <0x0 0x80000000 0x0 0x20000000 /* 512 MiB low mem */ 0x1 0xc0000000 0x0 0x40000000>; /* 1 GiB highmem */ }; diff --git a/arch/arc/boot/dts/axc003_idu.dtsi b/arch/arc/boot/dts/axc003_idu.dtsi index 4ebb2170abec..63954a8b0100 100644 --- a/arch/arc/boot/dts/axc003_idu.dtsi +++ b/arch/arc/boot/dts/axc003_idu.dtsi @@ -24,10 +24,17 @@ ranges = <0x00000000 0x0 0xf0000000 0x10000000>; - core_clk: core_clk { + input_clk: input-clk { #clock-cells = <0>; compatible = "fixed-clock"; - clock-frequency = <100000000>; + clock-frequency = <33333333>; + }; + + core_clk: core-clk@80 { + compatible = "snps,axs10x-arc-pll-clock"; + reg = <0x80 0x10>, <0x100 0x10>; + #clock-cells = <0>; + clocks = <&input_clk>; }; core_intc: archs-intc@cpu { @@ -108,7 +115,7 @@ memory { device_type = "memory"; - /* CONFIG_KERNEL_RAM_BASE_ADDRESS needs to match low mem start */ + /* CONFIG_LINUX_RAM_BASE needs to match low mem start */ reg = <0x0 0x80000000 0x0 0x20000000 /* 512 MiB low mem */ 0x1 0xc0000000 0x0 0x40000000>; /* 1 GiB highmem */ }; diff --git a/arch/arc/boot/dts/hsdk.dts b/arch/arc/boot/dts/hsdk.dts new file mode 100644 index 000000000000..229d13adbce4 --- /dev/null +++ b/arch/arc/boot/dts/hsdk.dts @@ -0,0 +1,189 @@ +/* + * Copyright (C) 2017 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 ARC HS Development Kit + */ +/dts-v1/; + +#include <dt-bindings/net/ti-dp83867.h> + +/ { + model = "snps,hsdk"; + compatible = "snps,hsdk"; + + #address-cells = <1>; + #size-cells = <1>; + + chosen { + bootargs = "earlycon=uart8250,mmio32,0xf0005000,115200n8 console=ttyS0,115200n8 debug print-fatal-signals=1"; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu@0 { + device_type = "cpu"; + compatible = "snps,archs38"; + reg = <0>; + clocks = <&core_clk>; + }; + + cpu@1 { + device_type = "cpu"; + compatible = "snps,archs38"; + reg = <1>; + clocks = <&core_clk>; + }; + + cpu@2 { + device_type = "cpu"; + compatible = "snps,archs38"; + reg = <2>; + clocks = <&core_clk>; + }; + + cpu@3 { + device_type = "cpu"; + compatible = "snps,archs38"; + reg = <3>; + clocks = <&core_clk>; + }; + }; + + core_clk: core-clk { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <500000000>; + }; + + cpu_intc: cpu-interrupt-controller { + compatible = "snps,archs-intc"; + interrupt-controller; + #interrupt-cells = <1>; + }; + + idu_intc: idu-interrupt-controller { + compatible = "snps,archs-idu-intc"; + interrupt-controller; + #interrupt-cells = <1>; + interrupt-parent = <&cpu_intc>; + }; + + arcpct: pct { + compatible = "snps,archs-pct"; + }; + + /* TIMER0 with interrupt for clockevent */ + timer { + compatible = "snps,arc-timer"; + interrupts = <16>; + interrupt-parent = <&cpu_intc>; + clocks = <&core_clk>; + }; + + /* 64-bit Global Free Running Counter */ + gfrc { + compatible = "snps,archs-timer-gfrc"; + clocks = <&core_clk>; + }; + + soc { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + interrupt-parent = <&idu_intc>; + + ranges = <0x00000000 0xf0000000 0x10000000>; + + serial: serial@5000 { + compatible = "snps,dw-apb-uart"; + reg = <0x5000 0x100>; + clock-frequency = <33330000>; + interrupts = <6>; + baud = <115200>; + reg-shift = <2>; + reg-io-width = <4>; + }; + + gmacclk: gmacclk { + compatible = "fixed-clock"; + clock-frequency = <400000000>; + #clock-cells = <0>; + }; + + mmcclk_ciu: mmcclk-ciu { + compatible = "fixed-clock"; + clock-frequency = <100000000>; + #clock-cells = <0>; + }; + + mmcclk_biu: mmcclk-biu { + compatible = "fixed-clock"; + clock-frequency = <400000000>; + #clock-cells = <0>; + }; + + ethernet@8000 { + #interrupt-cells = <1>; + compatible = "snps,dwmac"; + reg = <0x8000 0x2000>; + interrupts = <10>; + interrupt-names = "macirq"; + phy-mode = "rgmii"; + snps,pbl = <32>; + clocks = <&gmacclk>; + clock-names = "stmmaceth"; + phy-handle = <&phy0>; + + mdio { + #address-cells = <1>; + #size-cells = <0>; + compatible = "snps,dwmac-mdio"; + phy0: ethernet-phy@0 { + reg = <0>; + ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>; + ti,tx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>; + ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>; + }; + }; + }; + + ohci@60000 { + compatible = "snps,hsdk-v1.0-ohci", "generic-ohci"; + reg = <0x60000 0x100>; + interrupts = <15>; + }; + + ehci@40000 { + compatible = "snps,hsdk-v1.0-ehci", "generic-ehci"; + reg = <0x40000 0x100>; + interrupts = <15>; + }; + + mmc@a000 { + compatible = "altr,socfpga-dw-mshc"; + reg = <0xa000 0x400>; + num-slots = <1>; + fifo-depth = <16>; + card-detect-delay = <200>; + clocks = <&mmcclk_biu>, <&mmcclk_ciu>; + clock-names = "biu", "ciu"; + interrupts = <12>; + bus-width = <4>; + }; + }; + + memory@80000000 { + #address-cells = <1>; + #size-cells = <1>; + device_type = "memory"; + reg = <0x80000000 0x40000000>; /* 1 GiB */ + }; +}; diff --git a/arch/arc/boot/dts/nsim_hs.dts b/arch/arc/boot/dts/nsim_hs.dts index 3772c40c245e..8d787b251f73 100644 --- a/arch/arc/boot/dts/nsim_hs.dts +++ b/arch/arc/boot/dts/nsim_hs.dts @@ -18,7 +18,7 @@ memory { device_type = "memory"; - /* CONFIG_LINUX_LINK_BASE needs to match low mem start */ + /* CONFIG_LINUX_RAM_BASE needs to match low mem start */ reg = <0x0 0x80000000 0x0 0x20000000 /* 512 MB low mem */ 0x1 0x00000000 0x0 0x40000000>; /* 1 GB highmem */ }; diff --git a/arch/arc/configs/hsdk_defconfig b/arch/arc/configs/hsdk_defconfig new file mode 100644 index 000000000000..9a3fcf446388 --- /dev/null +++ b/arch/arc/configs/hsdk_defconfig @@ -0,0 +1,80 @@ +CONFIG_DEFAULT_HOSTNAME="ARCLinux" +CONFIG_SYSVIPC=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_MODULE_UNLOAD=y +CONFIG_ARC_SOC_HSDK=y +CONFIG_ISA_ARCV2=y +CONFIG_SMP=y +CONFIG_LINUX_LINK_BASE=0x90000000 +CONFIG_LINUX_RAM_BASE=0x80000000 +CONFIG_ARC_BUILTIN_DTB_NAME="hsdk" +CONFIG_PREEMPT=y +# CONFIG_COMPACTION is not set +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_INET=y +CONFIG_DEVTMPFS=y +# 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_STMMAC_ETH=y +CONFIG_MICREL_PHY=y +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_SERIO is not set +# CONFIG_LEGACY_PTYS 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_FB_UDL=y +CONFIG_FRAMEBUFFER_CONSOLE=y +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_IOMMU_SUPPORT is not set +CONFIG_EXT3_FS=y +CONFIG_VFAT_FS=y +CONFIG_TMPFS=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 +CONFIG_CRYPTO_ECHAINIV=y diff --git a/arch/arc/include/asm/cache.h b/arch/arc/include/asm/cache.h index 02fd1cece6ef..8486f328cc5d 100644 --- a/arch/arc/include/asm/cache.h +++ b/arch/arc/include/asm/cache.h @@ -47,7 +47,8 @@ : "r"(data), "r"(ptr)); \ }) -#define ARCH_DMA_MINALIGN L1_CACHE_BYTES +/* Largest line length for either L1 or L2 is 128 bytes */ +#define ARCH_DMA_MINALIGN 128 extern void arc_cache_init(void); extern char *arc_cache_mumbojumbo(int cpu_id, char *buf, int len); @@ -95,6 +96,8 @@ extern unsigned long perip_base, perip_end; #define ARC_REG_SLC_CTRL 0x903 #define ARC_REG_SLC_FLUSH 0x904 #define ARC_REG_SLC_INVALIDATE 0x905 +#define ARC_AUX_SLC_IVDL 0x910 +#define ARC_AUX_SLC_FLDL 0x912 #define ARC_REG_SLC_RGN_START 0x914 #define ARC_REG_SLC_RGN_START1 0x915 #define ARC_REG_SLC_RGN_END 0x916 diff --git a/arch/arc/include/asm/entry-compact.h b/arch/arc/include/asm/entry-compact.h index 14c310f2e0b1..ec36d5b6d435 100644 --- a/arch/arc/include/asm/entry-compact.h +++ b/arch/arc/include/asm/entry-compact.h @@ -192,6 +192,12 @@ PUSHAX lp_start PUSHAX erbta +#ifdef CONFIG_ARC_PLAT_EZNPS + .word CTOP_INST_SCHD_RW + PUSHAX CTOP_AUX_GPA1 + PUSHAX CTOP_AUX_EFLAGS +#endif + lr r9, [ecr] st r9, [sp, PT_event] /* EV_Trap expects r9 to have ECR */ .endm @@ -208,6 +214,12 @@ * by hardware and that is not good. *-------------------------------------------------------------*/ .macro EXCEPTION_EPILOGUE +#ifdef CONFIG_ARC_PLAT_EZNPS + .word CTOP_INST_SCHD_RW + POPAX CTOP_AUX_EFLAGS + POPAX CTOP_AUX_GPA1 +#endif + POPAX erbta POPAX lp_start POPAX lp_end @@ -265,6 +277,12 @@ PUSHAX lp_end PUSHAX lp_start PUSHAX bta_l\LVL\() + +#ifdef CONFIG_ARC_PLAT_EZNPS + .word CTOP_INST_SCHD_RW + PUSHAX CTOP_AUX_GPA1 + PUSHAX CTOP_AUX_EFLAGS +#endif .endm /*-------------------------------------------------------------- @@ -277,6 +295,12 @@ * by hardware and that is not good. *-------------------------------------------------------------*/ .macro INTERRUPT_EPILOGUE LVL +#ifdef CONFIG_ARC_PLAT_EZNPS + .word CTOP_INST_SCHD_RW + POPAX CTOP_AUX_EFLAGS + POPAX CTOP_AUX_GPA1 +#endif + POPAX bta_l\LVL\() POPAX lp_start POPAX lp_end diff --git a/arch/arc/include/asm/irqflags-arcv2.h b/arch/arc/include/asm/irqflags-arcv2.h index a64c447b0337..8a4f77ea3238 100644 --- a/arch/arc/include/asm/irqflags-arcv2.h +++ b/arch/arc/include/asm/irqflags-arcv2.h @@ -47,9 +47,6 @@ #define ISA_INIT_STATUS_BITS (STATUS_IE_MASK | STATUS_AD_MASK | \ (ARCV2_IRQ_DEF_PRIO << 1)) -/* SLEEP needs default irq priority (<=) which can interrupt the doze */ -#define ISA_SLEEP_ARG (0x10 | ARCV2_IRQ_DEF_PRIO) - #ifndef __ASSEMBLY__ /* diff --git a/arch/arc/include/asm/irqflags-compact.h b/arch/arc/include/asm/irqflags-compact.h index 4c6eed80cd8b..fcb80171fc34 100644 --- a/arch/arc/include/asm/irqflags-compact.h +++ b/arch/arc/include/asm/irqflags-compact.h @@ -43,8 +43,6 @@ #define ISA_INIT_STATUS_BITS STATUS_IE_MASK -#define ISA_SLEEP_ARG 0x3 - #ifndef __ASSEMBLY__ /****************************************************************** diff --git a/arch/arc/include/asm/page.h b/arch/arc/include/asm/page.h index 296c3426a6ad..109baa06831c 100644 --- a/arch/arc/include/asm/page.h +++ b/arch/arc/include/asm/page.h @@ -85,7 +85,7 @@ typedef pte_t * pgtable_t; */ #define virt_to_pfn(kaddr) (__pa(kaddr) >> PAGE_SHIFT) -#define ARCH_PFN_OFFSET virt_to_pfn(CONFIG_LINUX_LINK_BASE) +#define ARCH_PFN_OFFSET virt_to_pfn(CONFIG_LINUX_RAM_BASE) #ifdef CONFIG_FLATMEM #define pfn_valid(pfn) (((pfn) - ARCH_PFN_OFFSET) < max_mapnr) diff --git a/arch/arc/include/asm/processor.h b/arch/arc/include/asm/processor.h index 4104a0839214..d400a2161935 100644 --- a/arch/arc/include/asm/processor.h +++ b/arch/arc/include/asm/processor.h @@ -27,6 +27,13 @@ struct arc_fpu { }; #endif +#ifdef CONFIG_ARC_PLAT_EZNPS +struct eznps_dp { + unsigned int eflags; + unsigned int gpa1; +}; +#endif + /* Arch specific stuff which needs to be saved per task. * However these items are not so important so as to earn a place in * struct thread_info @@ -38,6 +45,9 @@ struct thread_struct { #ifdef CONFIG_ARC_FPU_SAVE_RESTORE struct arc_fpu fpu; #endif +#ifdef CONFIG_ARC_PLAT_EZNPS + struct eznps_dp dp; +#endif }; #define INIT_THREAD { \ diff --git a/arch/arc/include/asm/ptrace.h b/arch/arc/include/asm/ptrace.h index 5297faa8a378..5a8cb22724a1 100644 --- a/arch/arc/include/asm/ptrace.h +++ b/arch/arc/include/asm/ptrace.h @@ -19,6 +19,11 @@ #ifdef CONFIG_ISA_ARCOMPACT struct pt_regs { +#ifdef CONFIG_ARC_PLAT_EZNPS + unsigned long eflags; /* Extended FLAGS */ + unsigned long gpa1; /* General Purpose Aux */ +#endif + /* Real registers */ unsigned long bta; /* bta_l1, bta_l2, erbta */ diff --git a/arch/arc/include/asm/spinlock.h b/arch/arc/include/asm/spinlock.h index a325e6a36523..47efc8451b70 100644 --- a/arch/arc/include/asm/spinlock.h +++ b/arch/arc/include/asm/spinlock.h @@ -247,9 +247,15 @@ static inline void arch_spin_lock(arch_spinlock_t *lock) __asm__ __volatile__( "1: ex %0, [%1] \n" +#ifdef CONFIG_EZNPS_MTM_EXT + " .word %3 \n" +#endif " breq %0, %2, 1b \n" : "+&r" (val) : "r"(&(lock->slock)), "ir"(__ARCH_SPIN_LOCK_LOCKED__) +#ifdef CONFIG_EZNPS_MTM_EXT + , "i"(CTOP_INST_SCHD_RW) +#endif : "memory"); /* @@ -291,6 +297,12 @@ static inline void arch_spin_unlock(arch_spinlock_t *lock) */ smp_mb(); + /* + * EX is not really required here, a simple STore of 0 suffices. + * However this causes tasklist livelocks in SystemC based SMP virtual + * platforms where the systemc core scheduler uses EX as a cue for + * moving to next core. Do a git log of this file for details + */ __asm__ __volatile__( " ex %0, [%1] \n" : "+r" (val) diff --git a/arch/arc/include/asm/switch_to.h b/arch/arc/include/asm/switch_to.h index 1b171ab5fec0..f7d07feeea61 100644 --- a/arch/arc/include/asm/switch_to.h +++ b/arch/arc/include/asm/switch_to.h @@ -26,10 +26,19 @@ extern void fpu_save_restore(struct task_struct *p, struct task_struct *n); #endif /* !CONFIG_ARC_FPU_SAVE_RESTORE */ +#ifdef CONFIG_ARC_PLAT_EZNPS +extern void dp_save_restore(struct task_struct *p, struct task_struct *n); +#define ARC_EZNPS_DP_PREV(p, n) dp_save_restore(p, n) +#else +#define ARC_EZNPS_DP_PREV(p, n) + +#endif /* !CONFIG_ARC_PLAT_EZNPS */ + struct task_struct *__switch_to(struct task_struct *p, struct task_struct *n); #define switch_to(prev, next, last) \ do { \ + ARC_EZNPS_DP_PREV(prev, next); \ ARC_FPU_PREV(prev, next); \ last = __switch_to(prev, next);\ ARC_FPU_NEXT(next); \ diff --git a/arch/arc/kernel/devtree.c b/arch/arc/kernel/devtree.c index 3b67f538f142..521ef3521a1c 100644 --- a/arch/arc/kernel/devtree.c +++ b/arch/arc/kernel/devtree.c @@ -29,8 +29,9 @@ 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 = 166666666; /* Fixed 166.6MHz clk (TB10x) */ - else if (of_flat_dt_is_compatible(dt_root, "snps,arc-sdp")) - arc_base_baud = 33333333; /* Fixed 33MHz clk (AXS10x) */ + else if (of_flat_dt_is_compatible(dt_root, "snps,arc-sdp") || + of_flat_dt_is_compatible(dt_root, "snps,hsdk")) + arc_base_baud = 33333333; /* Fixed 33MHz clk (AXS10x & HSDK) */ else if (of_flat_dt_is_compatible(dt_root, "ezchip,arc-nps")) arc_base_baud = 800000000; /* Fixed 800MHz clk (NPS) */ else diff --git a/arch/arc/kernel/entry-compact.S b/arch/arc/kernel/entry-compact.S index 9211707634dc..f285dbb28066 100644 --- a/arch/arc/kernel/entry-compact.S +++ b/arch/arc/kernel/entry-compact.S @@ -25,12 +25,12 @@ * * 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 + * -Wrappers for sys_{,rt_}sigsuspend() no longer 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 + * out. Since we don't do FAKE RTIE for Priv-V, CPU exception 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. @@ -59,7 +59,7 @@ */ #include <linux/errno.h> -#include <linux/linkage.h> /* {EXTRY,EXIT} */ +#include <linux/linkage.h> /* {ENTRY,EXIT} */ #include <asm/entry.h> #include <asm/irqflags.h> @@ -80,8 +80,8 @@ .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 + * across sections (.vector to .text) we are guaranteed that 'j somewhere' + * will use the 'j limm' form of the instruction as long as somewhere is in * a section other than .vector. */ @@ -105,13 +105,13 @@ VECTOR handle_interrupt_level1 ; Other devices ; ******************** Exceptions ********************** VECTOR EV_MachineCheck ; 0x100, Fatal Machine check (0x20) -VECTOR EV_TLBMissI ; 0x108, Intruction TLB miss (0x21) +VECTOR EV_TLBMissI ; 0x108, Instruction 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) +VECTOR EV_Extension ; 0x130, Extn Instruction Excp (0x26) .rept 24 VECTOR reserved ; Reserved Exceptions @@ -199,7 +199,7 @@ END(handle_interrupt_level2) ; --------------------------------------------- ; User Mode Memory Bus Error Interrupt Handler -; (Kernel mode memory errors handled via seperate exception vectors) +; (Kernel mode memory errors handled via separate exception vectors) ; --------------------------------------------- ENTRY(mem_service) @@ -273,7 +273,7 @@ ENTRY(EV_TLBProtV) ;------ (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 + ; -Access Violation : 00_23_(00|01|02|03)_00 ; x r w r+w ; -Unaligned Access : 00_23_04_00 ; @@ -327,7 +327,7 @@ END(call_do_page_fault) .Lrestore_regs: - # Interrpts are actually disabled from this point on, but will get + # Interrupts are actually disabled from this point on, but will get # reenabled after we return from interrupt/exception. # But irq tracer needs to be told now... TRACE_ASM_IRQ_ENABLE @@ -335,7 +335,7 @@ END(call_do_page_fault) lr r10, [status32] ; Restore REG File. In case multiple Events outstanding, - ; use the same priorty as rtie: EXCPN, L2 IRQ, L1 IRQ, None + ; use the same priority as rtie: EXCPN, L2 IRQ, L1 IRQ, None ; Note that we use realtime STATUS32 (not pt_regs->status32) to ; decide that. diff --git a/arch/arc/kernel/entry.S b/arch/arc/kernel/entry.S index 1eea99beecc3..85d9ea4a0acc 100644 --- a/arch/arc/kernel/entry.S +++ b/arch/arc/kernel/entry.S @@ -92,6 +92,12 @@ ENTRY(EV_MachineCheck) lr r0, [efa] mov r1, sp + ; hardware auto-disables MMU, re-enable it to allow kernel vaddr + ; access for say stack unwinding of modules for crash dumps + lr r3, [ARC_REG_PID] + or r3, r3, MMU_ENABLE + sr r3, [ARC_REG_PID] + lsr r3, r2, 8 bmsk r3, r3, 7 brne r3, ECR_C_MCHK_DUP_TLB, 1f diff --git a/arch/arc/kernel/process.c b/arch/arc/kernel/process.c index 2a018de6d6cd..5ac3b547453f 100644 --- a/arch/arc/kernel/process.c +++ b/arch/arc/kernel/process.c @@ -79,15 +79,40 @@ done: return uval; } +#ifdef CONFIG_ISA_ARCV2 + void arch_cpu_idle(void) { - /* sleep, but enable all interrupts before committing */ + /* Re-enable interrupts <= default irq priority before commiting SLEEP */ + const unsigned int arg = 0x10 | ARCV2_IRQ_DEF_PRIO; + __asm__ __volatile__( "sleep %0 \n" : - :"I"(ISA_SLEEP_ARG)); /* can't be "r" has to be embedded const */ + :"I"(arg)); /* can't be "r" has to be embedded const */ +} + +#elif defined(CONFIG_EZNPS_MTM_EXT) /* ARC700 variant in NPS */ + +void arch_cpu_idle(void) +{ + /* only the calling HW thread needs to sleep */ + __asm__ __volatile__( + ".word %0 \n" + : + :"i"(CTOP_INST_HWSCHD_WFT_IE12)); +} + +#else /* ARC700 */ + +void arch_cpu_idle(void) +{ + /* sleep, but enable both set E1/E2 (levels of interrutps) before committing */ + __asm__ __volatile__("sleep 0x3 \n"); } +#endif + asmlinkage void ret_from_fork(void); /* @@ -209,6 +234,10 @@ void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long usp) */ regs->status32 = STATUS_U_MASK | STATUS_L_MASK | ISA_INIT_STATUS_BITS; +#ifdef CONFIG_EZNPS_MTM_EXT + regs->eflags = 0; +#endif + /* bogus seed values for debugging */ regs->lp_start = 0x10; regs->lp_end = 0x80; diff --git a/arch/arc/kernel/setup.c b/arch/arc/kernel/setup.c index 666613fde91d..c4ffb441716c 100644 --- a/arch/arc/kernel/setup.c +++ b/arch/arc/kernel/setup.c @@ -385,13 +385,13 @@ void setup_processor(void) read_arc_build_cfg_regs(); arc_init_IRQ(); - printk(arc_cpu_mumbojumbo(cpu_id, str, sizeof(str))); + pr_info("%s", arc_cpu_mumbojumbo(cpu_id, str, sizeof(str))); arc_mmu_init(); arc_cache_init(); - printk(arc_extn_mumbojumbo(cpu_id, str, sizeof(str))); - printk(arc_platform_smp_cpuinfo()); + pr_info("%s", arc_extn_mumbojumbo(cpu_id, str, sizeof(str))); + pr_info("%s", arc_platform_smp_cpuinfo()); arc_chk_core_config(); } diff --git a/arch/arc/kernel/traps.c b/arch/arc/kernel/traps.c index ff83e78d0cfb..bcd7c9fc5d0f 100644 --- a/arch/arc/kernel/traps.c +++ b/arch/arc/kernel/traps.c @@ -80,7 +80,7 @@ int name(unsigned long address, struct pt_regs *regs) \ DO_ERROR_INFO(SIGILL, "Priv Op/Disabled Extn", do_privilege_fault, ILL_PRVOPC) DO_ERROR_INFO(SIGILL, "Invalid Extn Insn", do_extension_fault, ILL_ILLOPC) DO_ERROR_INFO(SIGILL, "Illegal Insn (or Seq)", insterror_is_error, ILL_ILLOPC) -DO_ERROR_INFO(SIGBUS, "Invalid Mem Access", do_memory_error, BUS_ADRERR) +DO_ERROR_INFO(SIGBUS, "Invalid Mem Access", __weak do_memory_error, BUS_ADRERR) DO_ERROR_INFO(SIGTRAP, "Breakpoint Set", trap_is_brkpt, TRAP_BRKPT) DO_ERROR_INFO(SIGBUS, "Misaligned Access", do_misaligned_error, BUS_ADRALN) @@ -103,7 +103,7 @@ int do_misaligned_access(unsigned long address, struct pt_regs *regs, */ void do_machine_check_fault(unsigned long address, struct pt_regs *regs) { - die("Machine Check Exception", regs, address); + die("Unhandled Machine Check Exception", regs, address); } diff --git a/arch/arc/kernel/troubleshoot.c b/arch/arc/kernel/troubleshoot.c index f9caf79186d4..7e94476f3994 100644 --- a/arch/arc/kernel/troubleshoot.c +++ b/arch/arc/kernel/troubleshoot.c @@ -140,7 +140,7 @@ static void show_ecr_verbose(struct pt_regs *regs) } else if (vec == ECR_V_ITLB_MISS) { pr_cont("Insn could not be fetched\n"); } else if (vec == ECR_V_MACH_CHK) { - pr_cont("%s\n", (cause_code == 0x0) ? + pr_cont("Machine Check (%s)\n", (cause_code == 0x0) ? "Double Fault" : "Other Fatal Err"); } else if (vec == ECR_V_PROTV) { @@ -233,6 +233,9 @@ void show_kernel_fault_diag(const char *str, struct pt_regs *regs, { current->thread.fault_address = address; + /* Show fault description */ + pr_info("\n%s\n", str); + /* Caller and Callee regs */ show_regs(regs); diff --git a/arch/arc/mm/cache.c b/arch/arc/mm/cache.c index 7db283b46ebd..eee924dfffa6 100644 --- a/arch/arc/mm/cache.c +++ b/arch/arc/mm/cache.c @@ -652,7 +652,7 @@ static void __ic_line_inv_vaddr(phys_addr_t paddr, unsigned long vaddr, #endif /* CONFIG_ARC_HAS_ICACHE */ -noinline void slc_op(phys_addr_t paddr, unsigned long sz, const int op) +noinline void slc_op_rgn(phys_addr_t paddr, unsigned long sz, const int op) { #ifdef CONFIG_ISA_ARCV2 /* @@ -715,6 +715,58 @@ noinline void slc_op(phys_addr_t paddr, unsigned long sz, const int op) #endif } +noinline void slc_op_line(phys_addr_t paddr, unsigned long sz, const int op) +{ +#ifdef CONFIG_ISA_ARCV2 + /* + * SLC is shared between all cores and concurrent aux operations from + * multiple cores need to be serialized using a spinlock + * A concurrent operation can be silently ignored and/or the old/new + * operation can remain incomplete forever (lockup in SLC_CTRL_BUSY loop + * below) + */ + static DEFINE_SPINLOCK(lock); + + const unsigned long SLC_LINE_MASK = ~(l2_line_sz - 1); + unsigned int ctrl, cmd; + unsigned long flags; + int num_lines; + + spin_lock_irqsave(&lock, flags); + + 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; + + write_aux_reg(ARC_REG_SLC_CTRL, ctrl); + + cmd = op & OP_INV ? ARC_AUX_SLC_IVDL : ARC_AUX_SLC_FLDL; + + sz += paddr & ~SLC_LINE_MASK; + paddr &= SLC_LINE_MASK; + + num_lines = DIV_ROUND_UP(sz, l2_line_sz); + + while (num_lines-- > 0) { + write_aux_reg(cmd, paddr); + paddr += l2_line_sz; + } + + /* Make sure "busy" bit reports correct stataus, see STAR 9001165532 */ + read_aux_reg(ARC_REG_SLC_CTRL); + + while (read_aux_reg(ARC_REG_SLC_CTRL) & SLC_CTRL_BUSY); + + spin_unlock_irqrestore(&lock, flags); +#endif +} + +#define slc_op(paddr, sz, op) slc_op_rgn(paddr, sz, op) + noinline static void slc_entire_op(const int op) { unsigned int ctrl, r = ARC_REG_SLC_CTRL; @@ -1095,7 +1147,7 @@ SYSCALL_DEFINE3(cacheflush, uint32_t, start, uint32_t, sz, uint32_t, flags) */ noinline void __init arc_ioc_setup(void) { - unsigned int ap_sz; + unsigned int ioc_base, mem_sz; /* Flush + invalidate + disable L1 dcache */ __dc_disable(); @@ -1104,18 +1156,29 @@ noinline void __init arc_ioc_setup(void) if (read_aux_reg(ARC_REG_SLC_BCR)) slc_entire_op(OP_FLUSH_N_INV); - /* IOC Aperture start: TDB: handle non default CONFIG_LINUX_LINK_BASE */ - write_aux_reg(ARC_REG_IO_COH_AP0_BASE, 0x80000); - /* - * IOC Aperture size: - * decoded as 2 ^ (SIZE + 2) KB: so setting 0x11 implies 512M + * currently IOC Aperture covers entire DDR * TBD: fix for PGU + 1GB of low mem * TBD: fix for PAE */ - ap_sz = order_base_2(arc_get_mem_sz()/1024) - 2; - write_aux_reg(ARC_REG_IO_COH_AP0_SIZE, ap_sz); + mem_sz = arc_get_mem_sz(); + + if (!is_power_of_2(mem_sz) || mem_sz < 4096) + panic("IOC Aperture size must be power of 2 larger than 4KB"); + + /* + * IOC Aperture size decoded as 2 ^ (SIZE + 2) KB, + * so setting 0x11 implies 512MB, 0x12 implies 1GB... + */ + write_aux_reg(ARC_REG_IO_COH_AP0_SIZE, order_base_2(mem_sz >> 10) - 2); + + /* for now assume kernel base is start of IOC aperture */ + ioc_base = CONFIG_LINUX_RAM_BASE; + + if (ioc_base % mem_sz != 0) + panic("IOC Aperture start must be aligned to the size of the aperture"); + write_aux_reg(ARC_REG_IO_COH_AP0_BASE, ioc_base >> 12); write_aux_reg(ARC_REG_IO_COH_PARTIAL, 1); write_aux_reg(ARC_REG_IO_COH_ENABLE, 1); @@ -1207,7 +1270,7 @@ void __ref arc_cache_init(void) unsigned int __maybe_unused cpu = smp_processor_id(); char str[256]; - printk(arc_cache_mumbojumbo(0, str, sizeof(str))); + pr_info("%s", arc_cache_mumbojumbo(0, str, sizeof(str))); if (!cpu) arc_cache_init_master(); diff --git a/arch/arc/mm/fault.c b/arch/arc/mm/fault.c index 162c97528872..a0b7bd6d030d 100644 --- a/arch/arc/mm/fault.c +++ b/arch/arc/mm/fault.c @@ -207,7 +207,7 @@ no_context: /* Are we prepared to handle this kernel fault? * * (The kernel has valid exception-points in the source - * when it acesses user-memory. When it fails in one + * when it accesses user-memory. When it fails in one * of those points, we find it in a table and do a jump * to some fixup code that loads an appropriate error * code) diff --git a/arch/arc/mm/init.c b/arch/arc/mm/init.c index 8c9415ed6280..ba145065c579 100644 --- a/arch/arc/mm/init.c +++ b/arch/arc/mm/init.c @@ -26,7 +26,7 @@ pgd_t swapper_pg_dir[PTRS_PER_PGD] __aligned(PAGE_SIZE); char empty_zero_page[PAGE_SIZE] __aligned(PAGE_SIZE); EXPORT_SYMBOL(empty_zero_page); -static const unsigned long low_mem_start = CONFIG_LINUX_LINK_BASE; +static const unsigned long low_mem_start = CONFIG_LINUX_RAM_BASE; static unsigned long low_mem_sz; #ifdef CONFIG_HIGHMEM @@ -63,7 +63,7 @@ void __init early_init_dt_add_memory_arch(u64 base, u64 size) if (!low_mem_sz) { if (base != low_mem_start) - panic("CONFIG_LINUX_LINK_BASE != DT memory { }"); + panic("CONFIG_LINUX_RAM_BASE != DT memory { }"); low_mem_sz = size; in_use = 1; @@ -161,7 +161,7 @@ void __init setup_arch_memory(void) * We can't use the helper free_area_init(zones[]) because it uses * PAGE_OFFSET to compute the @min_low_pfn which would be wrong * when our kernel doesn't start at PAGE_OFFSET, i.e. - * PAGE_OFFSET != CONFIG_LINUX_LINK_BASE + * PAGE_OFFSET != CONFIG_LINUX_RAM_BASE */ free_area_init_node(0, /* node-id */ zones_size, /* num pages per zone */ diff --git a/arch/arc/mm/tlb.c b/arch/arc/mm/tlb.c index b181f3ee38aa..8ceefbf72fb0 100644 --- a/arch/arc/mm/tlb.c +++ b/arch/arc/mm/tlb.c @@ -821,7 +821,7 @@ void arc_mmu_init(void) char str[256]; struct cpuinfo_arc_mmu *mmu = &cpuinfo_arc700[smp_processor_id()].mmu; - printk(arc_mmu_mumbojumbo(0, str, sizeof(str))); + pr_info("%s", arc_mmu_mumbojumbo(0, str, sizeof(str))); /* * Can't be done in processor.h due to header include depenedencies @@ -908,9 +908,6 @@ void do_tlb_overlap_fault(unsigned long cause, unsigned long address, local_irq_save(flags); - /* re-enable the MMU */ - write_aux_reg(ARC_REG_PID, MMU_ENABLE | read_aux_reg(ARC_REG_PID)); - /* loop thru all sets of TLB */ for (set = 0; set < mmu->sets; set++) { diff --git a/arch/arc/mm/tlbex.S b/arch/arc/mm/tlbex.S index b30e4e36bb00..0e1e47a67c73 100644 --- a/arch/arc/mm/tlbex.S +++ b/arch/arc/mm/tlbex.S @@ -274,6 +274,13 @@ ex_saved_reg1: .macro COMMIT_ENTRY_TO_MMU #if (CONFIG_ARC_MMU_VER < 4) +#ifdef CONFIG_EZNPS_MTM_EXT + /* verify if entry for this vaddr+ASID already exists */ + sr TLBProbe, [ARC_REG_TLBCOMMAND] + lr r0, [ARC_REG_TLBINDEX] + bbit0 r0, 31, 88f +#endif + /* Get free TLB slot: Set = computed from vaddr, way = random */ sr TLBGetIndex, [ARC_REG_TLBCOMMAND] @@ -287,6 +294,8 @@ ex_saved_reg1: #else sr TLBInsertEntry, [ARC_REG_TLBCOMMAND] #endif + +88: .endm diff --git a/arch/arc/plat-axs10x/axs10x.c b/arch/arc/plat-axs10x/axs10x.c index 38ff349d7f2a..f1ac6790da5f 100644 --- a/arch/arc/plat-axs10x/axs10x.c +++ b/arch/arc/plat-axs10x/axs10x.c @@ -80,22 +80,6 @@ static void __init axs10x_enable_gpio_intc_wire(void) iowrite32(1 << MB_TO_GPIO_IRQ, (void __iomem *) GPIO_INTEN); } -static inline void __init -write_cgu_reg(uint32_t value, void __iomem *reg, void __iomem *lock_reg) -{ - unsigned int loops = 128 * 1024, ctr; - - iowrite32(value, reg); - - ctr = loops; - while (((ioread32(lock_reg) & 1) == 1) && ctr--) /* wait for unlock */ - cpu_relax(); - - ctr = loops; - while (((ioread32(lock_reg) & 1) == 0) && ctr--) /* wait for re-lock */ - cpu_relax(); -} - static void __init axs10x_print_board_ver(unsigned int creg, const char *str) { union ver { @@ -314,7 +298,6 @@ static void __init axs101_early_init(void) #ifdef CONFIG_AXS103 -#define AXC003_CGU 0xF0000000 #define AXC003_CREG 0xF0001000 #define AXC003_MST_AXI_TUNNEL 0 #define AXC003_MST_HS38 1 @@ -324,131 +307,38 @@ static void __init axs101_early_init(void) #define CREG_CPU_TUN_IO_CTRL (AXC003_CREG + 0x494) -union pll_reg { - struct { -#ifdef CONFIG_CPU_BIG_ENDIAN - unsigned int pad:17, noupd:1, bypass:1, edge:1, high:6, low:6; -#else - unsigned int low:6, high:6, edge:1, bypass:1, noupd:1, pad:17; -#endif - }; - unsigned int val; -}; - -static unsigned int __init axs103_get_freq(void) -{ - union pll_reg idiv, fbdiv, odiv; - unsigned int f = 33333333; - - idiv.val = ioread32((void __iomem *)AXC003_CGU + 0x80 + 0); - fbdiv.val = ioread32((void __iomem *)AXC003_CGU + 0x80 + 4); - odiv.val = ioread32((void __iomem *)AXC003_CGU + 0x80 + 8); - - if (idiv.bypass != 1) - f = f / (idiv.low + idiv.high); - - if (fbdiv.bypass != 1) - f = f * (fbdiv.low + fbdiv.high); - - if (odiv.bypass != 1) - f = f / (odiv.low + odiv.high); - - f = (f + 500000) / 1000000; /* Rounding */ - return f; -} - -static inline unsigned int __init encode_div(unsigned int id, int upd) -{ - union pll_reg div; - - div.val = 0; - - div.noupd = !upd; - div.bypass = id == 1 ? 1 : 0; - div.edge = (id%2 == 0) ? 0 : 1; /* 0 = rising */ - div.low = (id%2 == 0) ? id >> 1 : (id >> 1)+1; - div.high = id >> 1; - - return div.val; -} - -noinline static void __init -axs103_set_freq(unsigned int id, unsigned int fd, unsigned int od) -{ - write_cgu_reg(encode_div(id, 0), - (void __iomem *)AXC003_CGU + 0x80 + 0, - (void __iomem *)AXC003_CGU + 0x110); - - write_cgu_reg(encode_div(fd, 0), - (void __iomem *)AXC003_CGU + 0x80 + 4, - (void __iomem *)AXC003_CGU + 0x110); - - write_cgu_reg(encode_div(od, 1), - (void __iomem *)AXC003_CGU + 0x80 + 8, - (void __iomem *)AXC003_CGU + 0x110); -} - static void __init axs103_early_init(void) { - int offset = fdt_path_offset(initial_boot_params, "/cpu_card/core_clk"); - const struct fdt_property *prop = fdt_get_property(initial_boot_params, - offset, - "clock-frequency", - NULL); - u32 freq = be32_to_cpu(*(u32*)(prop->data)) / 1000000, orig = freq; - +#ifdef CONFIG_ARC_MCIP /* * AXS103 configurations for SMP/QUAD configurations share device tree - * which defaults to 90 MHz. However recent failures of Quad config + * which defaults to 100 MHz. However recent failures of Quad config * revealed P&R timing violations so clamp it down to safe 50 MHz * Instead of duplicating defconfig/DT for SMP/QUAD, add a small hack - * - * This hack is really hacky as of now. Fix it properly by getting the - * number of cores as return value of platform's early SMP callback + * of fudging the freq in DT */ -#ifdef CONFIG_ARC_MCIP unsigned int num_cores = (read_aux_reg(ARC_REG_MCIP_BCR) >> 16) & 0x3F; - if (num_cores > 2) - freq = 50; -#endif - - switch (freq) { - case 33: - axs103_set_freq(1, 1, 1); - break; - case 50: - axs103_set_freq(1, 30, 20); - break; - case 75: - axs103_set_freq(2, 45, 10); - break; - case 90: - axs103_set_freq(2, 54, 10); - break; - case 100: - axs103_set_freq(1, 30, 10); - break; - case 125: - axs103_set_freq(2, 45, 6); - break; - default: + if (num_cores > 2) { + u32 freq = 50, orig; /* - * In this case, core_frequency derived from - * DT "clock-frequency" might not match with board value. - * Hence update it to match the board value. + * TODO: use cpu node "cpu-freq" param instead of platform-specific + * "/cpu_card/core_clk" as it works only if we use fixed-clock for cpu. */ - freq = axs103_get_freq(); - break; - } - - pr_info("Freq is %dMHz\n", freq); - - /* Patching .dtb in-place with new core clock value */ - if (freq != orig ) { - freq = cpu_to_be32(freq * 1000000); - fdt_setprop_inplace(initial_boot_params, offset, - "clock-frequency", &freq, sizeof(freq)); + int off = fdt_path_offset(initial_boot_params, "/cpu_card/core_clk"); + const struct fdt_property *prop; + + prop = fdt_get_property(initial_boot_params, off, + "clock-frequency", NULL); + orig = be32_to_cpu(*(u32*)(prop->data)) / 1000000; + + /* Patching .dtb in-place with new core clock value */ + if (freq != orig ) { + freq = cpu_to_be32(freq * 1000000); + fdt_setprop_inplace(initial_boot_params, off, + "clock-frequency", &freq, sizeof(freq)); + } } +#endif /* Memory maps already config in pre-bootloader */ diff --git a/arch/arc/plat-eznps/Kconfig b/arch/arc/plat-eznps/Kconfig index 1595a38e50cd..e151e2067886 100644 --- a/arch/arc/plat-eznps/Kconfig +++ b/arch/arc/plat-eznps/Kconfig @@ -12,8 +12,8 @@ menuconfig ARC_PLAT_EZNPS help Support for EZchip development platforms, based on ARC700 cores. - We handle few flavours: - - Hardware Emulator AKA HE which is FPGA based chasis + We handle few flavors: + - Hardware Emulator AKA HE which is FPGA based chassis - Simulator based on MetaWare nSIM - NPS400 chip based on ASIC @@ -32,3 +32,25 @@ config EZNPS_MTM_EXT any of them seem like CPU from Linux point of view. All threads within same core share the execution unit of the core and HW scheduler round robin between them. + +config EZNPS_MEM_ERROR_ALIGN + bool "ARC-EZchip Memory error as an exception" + depends on EZNPS_MTM_EXT + default n + help + On the real chip of the NPS, user memory errors are handled + as a machine check exception, which is fatal, whereas on + simulator platform for NPS, is handled as a Level 2 interrupt + (just a stock ARC700) which is recoverable. This option makes + simulator behave like hardware. + +config EZNPS_SHARED_AUX_REGS + bool "ARC-EZchip Shared Auxiliary Registers Per Core" + depends on ARC_PLAT_EZNPS + default y + help + On the real chip of the NPS, auxiliary registers are shared between + all the cpus of the core, whereas on simulator platform for NPS, + each cpu has a different set of auxiliary registers. Configuration + should be unset if auxiliary registers are not shared between the cpus + of the core, so there will be a need to initialize them per cpu. diff --git a/arch/arc/plat-eznps/Makefile b/arch/arc/plat-eznps/Makefile index 21091b199df0..8d4371706b2f 100644 --- a/arch/arc/plat-eznps/Makefile +++ b/arch/arc/plat-eznps/Makefile @@ -2,6 +2,6 @@ # Makefile for the linux kernel. # -obj-y := entry.o platform.o +obj-y := entry.o platform.o ctop.o obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_EZNPS_MTM_EXT) += mtm.o diff --git a/arch/arc/plat-eznps/ctop.c b/arch/arc/plat-eznps/ctop.c new file mode 100644 index 000000000000..030bcd070a1b --- /dev/null +++ b/arch/arc/plat-eznps/ctop.c @@ -0,0 +1,32 @@ +/* + * Copyright(c) 2015 EZchip Technologies. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + */ + +#include <linux/sched.h> +#include <asm/processor.h> +#include <plat/ctop.h> + +void dp_save_restore(struct task_struct *prev, struct task_struct *next) +{ + struct eznps_dp *prev_task_dp = &prev->thread.dp; + struct eznps_dp *next_task_dp = &next->thread.dp; + + /* Here we save all Data Plane related auxiliary registers */ + prev_task_dp->eflags = read_aux_reg(CTOP_AUX_EFLAGS); + write_aux_reg(CTOP_AUX_EFLAGS, next_task_dp->eflags); + + prev_task_dp->gpa1 = read_aux_reg(CTOP_AUX_GPA1); + write_aux_reg(CTOP_AUX_GPA1, next_task_dp->gpa1); +} diff --git a/arch/arc/plat-eznps/entry.S b/arch/arc/plat-eznps/entry.S index 328261c27cda..091c92c32ab6 100644 --- a/arch/arc/plat-eznps/entry.S +++ b/arch/arc/plat-eznps/entry.S @@ -27,7 +27,7 @@ .align 1024 ; HW requierment for restart first PC ENTRY(res_service) -#ifdef CONFIG_EZNPS_MTM_EXT +#if defined(CONFIG_EZNPS_MTM_EXT) && defined(CONFIG_EZNPS_SHARED_AUX_REGS) ; There is no work for HW thread id != 0 lr r3, [CTOP_AUX_THREAD_ID] cmp r3, 0 diff --git a/arch/arc/plat-eznps/include/plat/ctop.h b/arch/arc/plat-eznps/include/plat/ctop.h index ee2e32df5e90..0c7d11022d0f 100644 --- a/arch/arc/plat-eznps/include/plat/ctop.h +++ b/arch/arc/plat-eznps/include/plat/ctop.h @@ -39,6 +39,7 @@ #define CTOP_AUX_LOGIC_CORE_ID (CTOP_AUX_BASE + 0x018) #define CTOP_AUX_MT_CTRL (CTOP_AUX_BASE + 0x020) #define CTOP_AUX_HW_COMPLY (CTOP_AUX_BASE + 0x024) +#define CTOP_AUX_DPC (CTOP_AUX_BASE + 0x02C) #define CTOP_AUX_LPC (CTOP_AUX_BASE + 0x030) #define CTOP_AUX_EFLAGS (CTOP_AUX_BASE + 0x080) #define CTOP_AUX_IACK (CTOP_AUX_BASE + 0x088) @@ -46,6 +47,7 @@ #define CTOP_AUX_UDMC (CTOP_AUX_BASE + 0x300) /* EZchip core instructions */ +#define CTOP_INST_HWSCHD_WFT_IE12 0x3E6F7344 #define CTOP_INST_HWSCHD_OFF_R4 0x3C6F00BF #define CTOP_INST_HWSCHD_RESTORE_R4 0x3E6F7103 #define CTOP_INST_SCHD_RW 0x3E6F7004 diff --git a/arch/arc/plat-eznps/mtm.c b/arch/arc/plat-eznps/mtm.c index aaaaffd3d940..2388de3d09ef 100644 --- a/arch/arc/plat-eznps/mtm.c +++ b/arch/arc/plat-eznps/mtm.c @@ -21,10 +21,22 @@ #include <plat/mtm.h> #include <plat/smp.h> -#define MT_CTRL_HS_CNT 0xFF +#define MT_HS_CNT_MIN 0x01 +#define MT_HS_CNT_MAX 0xFF #define MT_CTRL_ST_CNT 0xF #define NPS_NUM_HW_THREADS 0x10 +static int mtm_hs_ctr = MT_HS_CNT_MAX; + +#ifdef CONFIG_EZNPS_MEM_ERROR_ALIGN +int do_memory_error(unsigned long address, struct pt_regs *regs) +{ + die("Invalid Mem Access", regs, address); + + return 1; +} +#endif + static void mtm_init_nat(int cpu) { struct nps_host_reg_mtm_cfg mtm_cfg; @@ -98,6 +110,18 @@ void mtm_enable_core(unsigned int cpu) int i; struct nps_host_reg_aux_mt_ctrl mt_ctrl; struct nps_host_reg_mtm_cfg mtm_cfg; + struct nps_host_reg_aux_dpc dpc; + + /* + * Initializing dpc register in each CPU. + * Overwriting the init value of the DPC + * register so that CMEM and FMT virtual address + * spaces are accessible, and Data Plane HW + * facilities are enabled. + */ + dpc.ien = 1; + dpc.men = 1; + write_aux_reg(CTOP_AUX_DPC, dpc.value); if (NPS_CPU_TO_THREAD_NUM(cpu) != 0) return; @@ -118,9 +142,7 @@ void mtm_enable_core(unsigned int cpu) /* Enable HW schedule, stall counter, mtm */ mt_ctrl.value = 0; mt_ctrl.hsen = 1; - mt_ctrl.hs_cnt = MT_CTRL_HS_CNT; - mt_ctrl.sten = 1; - mt_ctrl.st_cnt = MT_CTRL_ST_CNT; + mt_ctrl.hs_cnt = mtm_hs_ctr; mt_ctrl.mten = 1; write_aux_reg(CTOP_AUX_MT_CTRL, mt_ctrl.value); @@ -131,3 +153,23 @@ void mtm_enable_core(unsigned int cpu) */ cpu_relax(); } + +/* Verify and set the value of the mtm hs counter */ +static int __init set_mtm_hs_ctr(char *ctr_str) +{ + long hs_ctr; + int ret; + + ret = kstrtol(ctr_str, 0, &hs_ctr); + + if (ret || hs_ctr > MT_HS_CNT_MAX || hs_ctr < MT_HS_CNT_MIN) { + pr_err("** Invalid @nps_mtm_hs_ctr [%d] needs to be [%d:%d] (incl)\n", + hs_ctr, MT_HS_CNT_MIN, MT_HS_CNT_MAX); + return -EINVAL; + } + + mtm_hs_ctr = hs_ctr; + + return 0; +} +early_param("nps_mtm_hs_ctr", set_mtm_hs_ctr); diff --git a/arch/arc/plat-hsdk/Kconfig b/arch/arc/plat-hsdk/Kconfig new file mode 100644 index 000000000000..5a6ed5afb009 --- /dev/null +++ b/arch/arc/plat-hsdk/Kconfig @@ -0,0 +1,9 @@ +# Copyright (C) 2017 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_SOC_HSDK + bool "ARC HS Development Kit SOC" diff --git a/arch/arc/plat-hsdk/Makefile b/arch/arc/plat-hsdk/Makefile new file mode 100644 index 000000000000..9a50c511a672 --- /dev/null +++ b/arch/arc/plat-hsdk/Makefile @@ -0,0 +1,9 @@ +# +# Copyright (C) 2017 Synopsys, Inc. (www.synopsys.com) +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# + +obj-y := platform.o diff --git a/arch/arc/plat-hsdk/platform.c b/arch/arc/plat-hsdk/platform.c new file mode 100644 index 000000000000..a2e7fd17e36d --- /dev/null +++ b/arch/arc/plat-hsdk/platform.c @@ -0,0 +1,66 @@ +/* + * ARC HSDK Platform support code + * + * Copyright (C) 2017 Synopsys, Inc. (www.synopsys.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/init.h> +#include <linux/smp.h> +#include <asm/arcregs.h> +#include <asm/io.h> +#include <asm/mach_desc.h> + +#define ARC_CCM_UNUSED_ADDR 0x60000000 + +static void __init hsdk_init_per_cpu(unsigned int cpu) +{ + /* + * By default ICCM is mapped to 0x7z while this area is used for + * kernel virtual mappings, so move it to currently unused area. + */ + if (cpuinfo_arc700[cpu].iccm.sz) + write_aux_reg(ARC_REG_AUX_ICCM, ARC_CCM_UNUSED_ADDR); + + /* + * By default DCCM is mapped to 0x8z while this area is used by kernel, + * so move it to currently unused area. + */ + if (cpuinfo_arc700[cpu].dccm.sz) + write_aux_reg(ARC_REG_AUX_DCCM, ARC_CCM_UNUSED_ADDR); +} + +#define ARC_PERIPHERAL_BASE 0xf0000000 +#define CREG_BASE (ARC_PERIPHERAL_BASE + 0x1000) +#define CREG_PAE (CREG_BASE + 0x180) +#define CREG_PAE_UPDATE (CREG_BASE + 0x194) + +static void __init hsdk_init_early(void) +{ + /* + * PAE remapping for DMA clients does not work due to an RTL bug, so + * CREG_PAE register must be programmed to all zeroes, otherwise it + * will cause problems with DMA to/from peripherals even if PAE40 is + * not used. + */ + + /* Default is 1, which means "PAE offset = 4GByte" */ + writel_relaxed(0, (void __iomem *) CREG_PAE); + + /* Really apply settings made above */ + writel(1, (void __iomem *) CREG_PAE_UPDATE); +} + +static const char *hsdk_compat[] __initconst = { + "snps,hsdk", + NULL, +}; + +MACHINE_START(SIMULATION, "hsdk") + .dt_compat = hsdk_compat, + .init_early = hsdk_init_early, + .init_per_cpu = hsdk_init_per_cpu, +MACHINE_END |