Commit ee89252b authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'arc-4.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/vgupta/arc

Pull ARC updates from Vineet Gupta:

 - Support for HSDK board hosting a Quad core HS38x4 based SoC running
   @1GHz (and some prerrquisite changes such as ability to scoot the
   kernel code/data from start of memory map etc)

 - Quite a few updates for EZChip (Mellanox) platform

 - Fixes to fault/exception printing

* tag 'arc-4.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/vgupta/arc: (26 commits)
  ARC: Re-enable MMU upon Machine Check exception
  ARC: Show fault information passed to show_kernel_fault_diag()
  ARC: [plat-hsdk] initial port for HSDK board
  ARC: mm: Decouple RAM base address from kernel link address
  ARCv2: IOC: Tighten up the contraints (specifically base / size alignment)
  ARC: [plat-axs103] refactor the DT fudging code
  ARC: [plat-axs103] use clk driver #2: Add core pll node to DT to manage cpu clk
  ARC: [plat-axs103] use clk driver #1: Get rid of platform specific cpu clk setting
  ARCv2: SLC: provide a line based flush routine for debugging
  ARC: Hardcode ARCH_DMA_MINALIGN to max line length we may have
  ARC: [plat-eznps] handle extra aux regs #2: kernel/entry exit
  ARC: [plat-eznps] handle extra aux regs #1: save/restore on context switch
  ARC: [plat-eznps] avoid toggling of DPC register
  ARC: [plat-eznps] Update the init sequence of aux regs per cpu.
  ARC: [plat-eznps] new command line argument for HW scheduler at MTM
  ARC: set boot print log level to PR_INFO
  ARC: [plat-eznps] Handle user memory error same in simulation and silicon
  ARC: [plat-eznps] use schd.wft instruction instead of sleep at idle task
  ARC: create cpu specific version of arch_cpu_idle()
  ARC: [plat-eznps] spinlock aware for MTM
  ...
parents 0d519f2d 1ee55a8f
...@@ -2764,6 +2764,15 @@ ...@@ -2764,6 +2764,15 @@
If the dependencies are under your control, you can If the dependencies are under your control, you can
turn on cpu0_hotplug. turn on cpu0_hotplug.
nps_mtm_hs_ctr= [KNL,ARC]
This parameter sets the maximum duration, in
cycles, each HW thread of the CTOP can run
without interruptions, before HW switches it.
The actual maximum duration is 16 times this
parameter's value.
Format: integer between 1 and 255
Default: 255
nptcg= [IA-64] Override max number of concurrent global TLB nptcg= [IA-64] Override max number of concurrent global TLB
purges which is reported from either PAL_VM_SUMMARY or purges which is reported from either PAL_VM_SUMMARY or
SAL PALO. SAL PALO.
......
Synopsys DesignWare ARC HS Development Kit Device Tree Bindings
---------------------------------------------------------------------------
ARC HSDK Board with quad-core ARC HS38x4 in silicon.
Required root node properties:
- compatible = "snps,hsdk";
...@@ -100,6 +100,7 @@ source "arch/arc/plat-tb10x/Kconfig" ...@@ -100,6 +100,7 @@ source "arch/arc/plat-tb10x/Kconfig"
source "arch/arc/plat-axs10x/Kconfig" source "arch/arc/plat-axs10x/Kconfig"
#New platform adds here #New platform adds here
source "arch/arc/plat-eznps/Kconfig" source "arch/arc/plat-eznps/Kconfig"
source "arch/arc/plat-hsdk/Kconfig"
endmenu endmenu
...@@ -418,7 +419,7 @@ endif # ISA_ARCV2 ...@@ -418,7 +419,7 @@ endif # ISA_ARCV2
endmenu # "ARC CPU Configuration" endmenu # "ARC CPU Configuration"
config LINUX_LINK_BASE config LINUX_LINK_BASE
hex "Linux Link Address" hex "Kernel link address"
default "0x80000000" default "0x80000000"
help help
ARC700 divides the 32 bit phy address space into two equal halves ARC700 divides the 32 bit phy address space into two equal halves
...@@ -431,6 +432,14 @@ config LINUX_LINK_BASE ...@@ -431,6 +432,14 @@ config LINUX_LINK_BASE
If you don't know what the above means, leave this setting alone. If you don't know what the above means, leave this setting alone.
This needs to match memory start address specified in Device Tree 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 config HIGHMEM
bool "High Memory Support" bool "High Memory Support"
select ARCH_DISCONTIGMEM_ENABLE select ARCH_DISCONTIGMEM_ENABLE
......
...@@ -111,6 +111,7 @@ core-y += arch/arc/plat-sim/ ...@@ -111,6 +111,7 @@ core-y += arch/arc/plat-sim/
core-$(CONFIG_ARC_PLAT_TB10X) += arch/arc/plat-tb10x/ core-$(CONFIG_ARC_PLAT_TB10X) += arch/arc/plat-tb10x/
core-$(CONFIG_ARC_PLAT_AXS10X) += arch/arc/plat-axs10x/ core-$(CONFIG_ARC_PLAT_AXS10X) += arch/arc/plat-axs10x/
core-$(CONFIG_ARC_PLAT_EZNPS) += arch/arc/plat-eznps/ core-$(CONFIG_ARC_PLAT_EZNPS) += arch/arc/plat-eznps/
core-$(CONFIG_ARC_SOC_HSDK) += arch/arc/plat-hsdk/
ifdef CONFIG_ARC_PLAT_EZNPS ifdef CONFIG_ARC_PLAT_EZNPS
KBUILD_CPPFLAGS += -I$(srctree)/arch/arc/plat-eznps/include KBUILD_CPPFLAGS += -I$(srctree)/arch/arc/plat-eznps/include
......
...@@ -99,7 +99,7 @@ mb_intc: dw-apb-ictl@0xe0012000 { ...@@ -99,7 +99,7 @@ mb_intc: dw-apb-ictl@0xe0012000 {
memory { memory {
device_type = "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 */ reg = <0x0 0x80000000 0x0 0x1b000000>; /* (512 - 32) MiB */
}; };
......
...@@ -24,10 +24,17 @@ cpu_card { ...@@ -24,10 +24,17 @@ cpu_card {
ranges = <0x00000000 0x0 0xf0000000 0x10000000>; ranges = <0x00000000 0x0 0xf0000000 0x10000000>;
core_clk: core_clk { input_clk: input-clk {
#clock-cells = <0>; #clock-cells = <0>;
compatible = "fixed-clock"; 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 { core_intc: archs-intc@cpu {
...@@ -102,7 +109,7 @@ mb_intc: dw-apb-ictl@0xe0012000 { ...@@ -102,7 +109,7 @@ mb_intc: dw-apb-ictl@0xe0012000 {
memory { memory {
device_type = "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 */ reg = <0x0 0x80000000 0x0 0x20000000 /* 512 MiB low mem */
0x1 0xc0000000 0x0 0x40000000>; /* 1 GiB highmem */ 0x1 0xc0000000 0x0 0x40000000>; /* 1 GiB highmem */
}; };
......
...@@ -24,10 +24,17 @@ cpu_card { ...@@ -24,10 +24,17 @@ cpu_card {
ranges = <0x00000000 0x0 0xf0000000 0x10000000>; ranges = <0x00000000 0x0 0xf0000000 0x10000000>;
core_clk: core_clk { input_clk: input-clk {
#clock-cells = <0>; #clock-cells = <0>;
compatible = "fixed-clock"; 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 { core_intc: archs-intc@cpu {
...@@ -108,7 +115,7 @@ mb_intc: dw-apb-ictl@0xe0012000 { ...@@ -108,7 +115,7 @@ mb_intc: dw-apb-ictl@0xe0012000 {
memory { memory {
device_type = "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 */ reg = <0x0 0x80000000 0x0 0x20000000 /* 512 MiB low mem */
0x1 0xc0000000 0x0 0x40000000>; /* 1 GiB highmem */ 0x1 0xc0000000 0x0 0x40000000>; /* 1 GiB highmem */
}; };
......
/*
* 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 */
};
};
...@@ -18,7 +18,7 @@ / { ...@@ -18,7 +18,7 @@ / {
memory { memory {
device_type = "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 */ reg = <0x0 0x80000000 0x0 0x20000000 /* 512 MB low mem */
0x1 0x00000000 0x0 0x40000000>; /* 1 GB highmem */ 0x1 0x00000000 0x0 0x40000000>; /* 1 GB highmem */
}; };
......
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
...@@ -47,7 +47,8 @@ ...@@ -47,7 +47,8 @@
: "r"(data), "r"(ptr)); \ : "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 void arc_cache_init(void);
extern char *arc_cache_mumbojumbo(int cpu_id, char *buf, int len); extern char *arc_cache_mumbojumbo(int cpu_id, char *buf, int len);
...@@ -95,6 +96,8 @@ extern unsigned long perip_base, perip_end; ...@@ -95,6 +96,8 @@ extern unsigned long perip_base, perip_end;
#define ARC_REG_SLC_CTRL 0x903 #define ARC_REG_SLC_CTRL 0x903
#define ARC_REG_SLC_FLUSH 0x904 #define ARC_REG_SLC_FLUSH 0x904
#define ARC_REG_SLC_INVALIDATE 0x905 #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_START 0x914
#define ARC_REG_SLC_RGN_START1 0x915 #define ARC_REG_SLC_RGN_START1 0x915
#define ARC_REG_SLC_RGN_END 0x916 #define ARC_REG_SLC_RGN_END 0x916
......
...@@ -192,6 +192,12 @@ ...@@ -192,6 +192,12 @@
PUSHAX lp_start PUSHAX lp_start
PUSHAX erbta PUSHAX erbta
#ifdef CONFIG_ARC_PLAT_EZNPS
.word CTOP_INST_SCHD_RW
PUSHAX CTOP_AUX_GPA1
PUSHAX CTOP_AUX_EFLAGS
#endif
lr r9, [ecr] lr r9, [ecr]
st r9, [sp, PT_event] /* EV_Trap expects r9 to have ECR */ st r9, [sp, PT_event] /* EV_Trap expects r9 to have ECR */
.endm .endm
...@@ -208,6 +214,12 @@ ...@@ -208,6 +214,12 @@
* by hardware and that is not good. * by hardware and that is not good.
*-------------------------------------------------------------*/ *-------------------------------------------------------------*/
.macro EXCEPTION_EPILOGUE .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 erbta
POPAX lp_start POPAX lp_start
POPAX lp_end POPAX lp_end
...@@ -265,6 +277,12 @@ ...@@ -265,6 +277,12 @@
PUSHAX lp_end PUSHAX lp_end
PUSHAX lp_start PUSHAX lp_start
PUSHAX bta_l\LVL\() PUSHAX bta_l\LVL\()
#ifdef CONFIG_ARC_PLAT_EZNPS
.word CTOP_INST_SCHD_RW
PUSHAX CTOP_AUX_GPA1
PUSHAX CTOP_AUX_EFLAGS
#endif
.endm .endm
/*-------------------------------------------------------------- /*--------------------------------------------------------------
...@@ -277,6 +295,12 @@ ...@@ -277,6 +295,12 @@
* by hardware and that is not good. * by hardware and that is not good.
*-------------------------------------------------------------*/ *-------------------------------------------------------------*/
.macro INTERRUPT_EPILOGUE LVL .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 bta_l\LVL\()
POPAX lp_start POPAX lp_start
POPAX lp_end POPAX lp_end
......
...@@ -47,9 +47,6 @@ ...@@ -47,9 +47,6 @@
#define ISA_INIT_STATUS_BITS (STATUS_IE_MASK | STATUS_AD_MASK | \ #define ISA_INIT_STATUS_BITS (STATUS_IE_MASK | STATUS_AD_MASK | \
(ARCV2_IRQ_DEF_PRIO << 1)) (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__ #ifndef __ASSEMBLY__
/* /*
......
...@@ -43,8 +43,6 @@ ...@@ -43,8 +43,6 @@
#define ISA_INIT_STATUS_BITS STATUS_IE_MASK #define ISA_INIT_STATUS_BITS STATUS_IE_MASK
#define ISA_SLEEP_ARG 0x3
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
/****************************************************************** /******************************************************************
......
...@@ -85,7 +85,7 @@ typedef pte_t * pgtable_t; ...@@ -85,7 +85,7 @@ typedef pte_t * pgtable_t;
*/ */
#define virt_to_pfn(kaddr) (__pa(kaddr) >> PAGE_SHIFT) #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 #ifdef CONFIG_FLATMEM
#define pfn_valid(pfn) (((pfn) - ARCH_PFN_OFFSET) < max_mapnr) #define pfn_valid(pfn) (((pfn) - ARCH_PFN_OFFSET) < max_mapnr)
......
...@@ -27,6 +27,13 @@ struct arc_fpu { ...@@ -27,6 +27,13 @@ struct arc_fpu {
}; };
#endif #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. /* Arch specific stuff which needs to be saved per task.
* However these items are not so important so as to earn a place in * However these items are not so important so as to earn a place in
* struct thread_info * struct thread_info
...@@ -38,6 +45,9 @@ struct thread_struct { ...@@ -38,6 +45,9 @@ struct thread_struct {
#ifdef CONFIG_ARC_FPU_SAVE_RESTORE #ifdef CONFIG_ARC_FPU_SAVE_RESTORE
struct arc_fpu fpu; struct arc_fpu fpu;
#endif #endif
#ifdef CONFIG_ARC_PLAT_EZNPS
struct eznps_dp dp;
#endif
}; };
#define INIT_THREAD { \ #define INIT_THREAD { \
......
...@@ -19,6 +19,11 @@ ...@@ -19,6 +19,11 @@
#ifdef CONFIG_ISA_ARCOMPACT #ifdef CONFIG_ISA_ARCOMPACT
struct pt_regs { struct pt_regs {
#ifdef CONFIG_ARC_PLAT_EZNPS
unsigned long eflags; /* Extended FLAGS */
unsigned long gpa1; /* General Purpose Aux */
#endif
/* Real registers */ /* Real registers */
unsigned long bta; /* bta_l1, bta_l2, erbta */ unsigned long bta; /* bta_l1, bta_l2, erbta */
......
...@@ -247,9 +247,15 @@ static inline void arch_spin_lock(arch_spinlock_t *lock) ...@@ -247,9 +247,15 @@ static inline void arch_spin_lock(arch_spinlock_t *lock)
__asm__ __volatile__( __asm__ __volatile__(
"1: ex %0, [%1] \n" "1: ex %0, [%1] \n"
#ifdef CONFIG_EZNPS_MTM_EXT
" .word %3 \n"
#endif
" breq %0, %2, 1b \n" " breq %0, %2, 1b \n"
: "+&r" (val) : "+&r" (val)
: "r"(&(lock->slock)), "ir"(__ARCH_SPIN_LOCK_LOCKED__) : "r"(&(lock->slock)), "ir"(__ARCH_SPIN_LOCK_LOCKED__)
#ifdef CONFIG_EZNPS_MTM_EXT
, "i"(CTOP_INST_SCHD_RW)
#endif
: "memory"); : "memory");
/* /*
...@@ -291,6 +297,12 @@ static inline void arch_spin_unlock(arch_spinlock_t *lock) ...@@ -291,6 +297,12 @@ static inline void arch_spin_unlock(arch_spinlock_t *lock)
*/ */
smp_mb(); 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__( __asm__ __volatile__(
" ex %0, [%1] \n" " ex %0, [%1] \n"
: "+r" (val) : "+r" (val)
......
...@@ -26,10 +26,19 @@ extern void fpu_save_restore(struct task_struct *p, struct task_struct *n); ...@@ -26,10 +26,19 @@ extern void fpu_save_restore(struct task_struct *p, struct task_struct *n);
#endif /* !CONFIG_ARC_FPU_SAVE_RESTORE */ #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); struct task_struct *__switch_to(struct task_struct *p, struct task_struct *n);
#define switch_to(prev, next, last) \ #define switch_to(prev, next, last) \
do { \ do { \
ARC_EZNPS_DP_PREV(prev, next); \
ARC_FPU_PREV(prev, next); \ ARC_FPU_PREV(prev, next); \
last = __switch_to(prev, next);\ last = __switch_to(prev, next);\
ARC_FPU_NEXT(next); \ ARC_FPU_NEXT(next); \
......
...@@ -29,8 +29,9 @@ static void __init arc_set_early_base_baud(unsigned long dt_root) ...@@ -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")) if (of_flat_dt_is_compatible(dt_root, "abilis,arc-tb10x"))
arc_base_baud = 166666666; /* Fixed 166.6MHz clk (TB10x) */ arc_base_baud = 166666666; /* Fixed 166.6MHz clk (TB10x) */
else if (of_flat_dt_is_compatible(dt_root, "snps,arc-sdp")) else if (of_flat_dt_is_compatible(dt_root, "snps,arc-sdp") ||
arc_base_baud = 33333333; /* Fixed 33MHz clk (AXS10x) */ 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")) else if (of_flat_dt_is_compatible(dt_root, "ezchip,arc-nps"))
arc_base_baud = 800000000; /* Fixed 800MHz clk (NPS) */ arc_base_baud = 800000000; /* Fixed 800MHz clk (NPS) */
else else
......
...@@ -25,12 +25,12 @@ ...@@ -25,12 +25,12 @@
* *
* vineetg: Nov 2009 (Everything needed for TIF_RESTORE_SIGMASK) * vineetg: Nov 2009 (Everything needed for TIF_RESTORE_SIGMASK)
* -do_signal()invoked upon TIF_RESTORE_SIGMASK as well * -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 * need ptregs anymore
* *
* Vineetg: Oct 2009 * Vineetg: Oct 2009
* -In a rare scenario, Process gets a Priv-V exception and gets scheduled * -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 * active (AE bit enabled). This causes a double fault for a subseq valid
* exception. Thus FAKE RTIE needed in low level Priv-Violation handler. * exception. Thus FAKE RTIE needed in low level Priv-Violation handler.
* Instr Error could also cause similar scenario, so same there as well. * Instr Error could also cause similar scenario, so same there as well.
...@@ -59,7 +59,7 @@ ...@@ -59,7 +59,7 @@
*/ */
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/linkage.h> /* {EXTRY,EXIT} */ #include <linux/linkage.h> /* {ENTRY,EXIT} */
#include <asm/entry.h> #include <asm/entry.h>
#include <asm/irqflags.h> #include <asm/irqflags.h>
...@@ -80,8 +80,8 @@ ...@@ -80,8 +80,8 @@
.align 4 .align 4
/* Each entry in the vector table must occupy 2 words. Since it is a jump /* 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' * across sections (.vector to .text) we are guaranteed that 'j somewhere'
* will use the 'j limm' form of the intrsuction as long as somewhere is in * will use the 'j limm' form of the instruction as long as somewhere is in
* a section other than .vector. * a section other than .vector.
*/ */
...@@ -105,13 +105,13 @@ VECTOR handle_interrupt_level1 ; Other devices ...@@ -105,13 +105,13 @@ VECTOR handle_interrupt_level1 ; Other devices
; ******************** Exceptions ********************** ; ******************** Exceptions **********************
VECTOR EV_MachineCheck ; 0x100, Fatal Machine check (0x20) 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_TLBMissD ; 0x110, Data TLB miss (0x22)
VECTOR EV_TLBProtV ; 0x118, Protection Violation (0x23) VECTOR EV_TLBProtV ; 0x118, Protection Violation (0x23)
; or Misaligned Access ; or Misaligned Access
VECTOR EV_PrivilegeV ; 0x120, Privilege Violation (0x24) VECTOR EV_PrivilegeV ; 0x120, Privilege Violation (0x24)
VECTOR EV_Trap ; 0x128, Trap exception (0x25) 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 .rept 24
VECTOR reserved ; Reserved Exceptions VECTOR reserved ; Reserved Exceptions
...@@ -199,7 +199,7 @@ END(handle_interrupt_level2) ...@@ -199,7 +199,7 @@ END(handle_interrupt_level2)
; --------------------------------------------- ; ---------------------------------------------
; User Mode Memory Bus Error Interrupt Handler ; 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) ENTRY(mem_service)
...@@ -273,7 +273,7 @@ ENTRY(EV_TLBProtV) ...@@ -273,7 +273,7 @@ ENTRY(EV_TLBProtV)
;------ (5) Type of Protection Violation? ---------- ;------ (5) Type of Protection Violation? ----------
; ;
; ProtV Hardware Exception is triggered for Access Faults of 2 types ; 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 ; x r w r+w
; -Unaligned Access : 00_23_04_00 ; -Unaligned Access : 00_23_04_00
; ;
...@@ -327,7 +327,7 @@ END(call_do_page_fault) ...@@ -327,7 +327,7 @@ END(call_do_page_fault)
.Lrestore_regs: .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. # reenabled after we return from interrupt/exception.
# But irq tracer needs to be told now... # But irq tracer needs to be told now...
TRACE_ASM_IRQ_ENABLE TRACE_ASM_IRQ_ENABLE
...@@ -335,7 +335,7 @@ END(call_do_page_fault) ...@@ -335,7 +335,7 @@ END(call_do_page_fault)
lr r10, [status32] lr r10, [status32]
; Restore REG File. In case multiple Events outstanding, ; 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 ; Note that we use realtime STATUS32 (not pt_regs->status32) to
; decide that. ; decide that.
......
...@@ -92,6 +92,12 @@ ENTRY(EV_MachineCheck) ...@@ -92,6 +92,12 @@ ENTRY(EV_MachineCheck)
lr r0, [efa] lr r0, [efa]
mov r1, sp 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 lsr r3, r2, 8
bmsk r3, r3, 7 bmsk r3, r3, 7
brne r3, ECR_C_MCHK_DUP_TLB, 1f brne r3, ECR_C_MCHK_DUP_TLB, 1f
......
...@@ -79,15 +79,40 @@ SYSCALL_DEFINE3(arc_usr_cmpxchg, int *, uaddr, int, expected, int, new) ...@@ -79,15 +79,40 @@ SYSCALL_DEFINE3(arc_usr_cmpxchg, int *, uaddr, int, expected, int, new)
return uval; return uval;
} }
#ifdef CONFIG_ISA_ARCV2
void arch_cpu_idle(void) 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__( __asm__ __volatile__(
"sleep %0 \n" "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); asmlinkage void ret_from_fork(void);
/* /*
...@@ -209,6 +234,10 @@ void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long usp) ...@@ -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; 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 */ /* bogus seed values for debugging */
regs->lp_start = 0x10; regs->lp_start = 0x10;
regs->lp_end = 0x80; regs->lp_end = 0x80;
......
...@@ -385,13 +385,13 @@ void setup_processor(void) ...@@ -385,13 +385,13 @@ void setup_processor(void)
read_arc_build_cfg_regs(); read_arc_build_cfg_regs();
arc_init_IRQ(); 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_mmu_init();
arc_cache_init(); arc_cache_init();
printk(arc_extn_mumbojumbo(cpu_id, str, sizeof(str))); pr_info("%s", arc_extn_mumbojumbo(cpu_id, str, sizeof(str)));
printk(arc_platform_smp_cpuinfo()); pr_info("%s", arc_platform_smp_cpuinfo());
arc_chk_core_config(); arc_chk_core_config();
} }
......
...@@ -80,7 +80,7 @@ int name(unsigned long address, struct pt_regs *regs) \ ...@@ -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, "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, "Invalid Extn Insn", do_extension_fault, ILL_ILLOPC)
DO_ERROR_INFO(SIGILL, "Illegal Insn (or Seq)", insterror_is_error, 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(SIGTRAP, "Breakpoint Set", trap_is_brkpt, TRAP_BRKPT)
DO_ERROR_INFO(SIGBUS, "Misaligned Access", do_misaligned_error, BUS_ADRALN) 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, ...@@ -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) 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);
} }
......
...@@ -140,7 +140,7 @@ static void show_ecr_verbose(struct pt_regs *regs) ...@@ -140,7 +140,7 @@ static void show_ecr_verbose(struct pt_regs *regs)
} else if (vec == ECR_V_ITLB_MISS) { } else if (vec == ECR_V_ITLB_MISS) {
pr_cont("Insn could not be fetched\n"); pr_cont("Insn could not be fetched\n");
} else if (vec == ECR_V_MACH_CHK) { } 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"); "Double Fault" : "Other Fatal Err");
} else if (vec == ECR_V_PROTV) { } else if (vec == ECR_V_PROTV) {
...@@ -233,6 +233,9 @@ void show_kernel_fault_diag(const char *str, struct pt_regs *regs, ...@@ -233,6 +233,9 @@ void show_kernel_fault_diag(const char *str, struct pt_regs *regs,
{ {
current->thread.fault_address = address; current->thread.fault_address = address;
/* Show fault description */
pr_info("\n%s\n", str);
/* Caller and Callee regs */ /* Caller and Callee regs */
show_regs(regs); show_regs(regs);
......
...@@ -652,7 +652,7 @@ static void __ic_line_inv_vaddr(phys_addr_t paddr, unsigned long vaddr, ...@@ -652,7 +652,7 @@ static void __ic_line_inv_vaddr(phys_addr_t paddr, unsigned long vaddr,
#endif /* CONFIG_ARC_HAS_ICACHE */ #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 #ifdef CONFIG_ISA_ARCV2
/* /*
...@@ -715,6 +715,58 @@ noinline void slc_op(phys_addr_t paddr, unsigned long sz, const int op) ...@@ -715,6 +715,58 @@ noinline void slc_op(phys_addr_t paddr, unsigned long sz, const int op)
#endif #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) noinline static void slc_entire_op(const int op)
{ {
unsigned int ctrl, r = ARC_REG_SLC_CTRL; unsigned int ctrl, r = ARC_REG_SLC_CTRL;
...@@ -1095,7 +1147,7 @@ SYSCALL_DEFINE3(cacheflush, uint32_t, start, uint32_t, sz, uint32_t, flags) ...@@ -1095,7 +1147,7 @@ SYSCALL_DEFINE3(cacheflush, uint32_t, start, uint32_t, sz, uint32_t, flags)
*/ */
noinline void __init arc_ioc_setup(void) noinline void __init arc_ioc_setup(void)
{ {
unsigned int ap_sz; unsigned int ioc_base, mem_sz;
/* Flush + invalidate + disable L1 dcache */ /* Flush + invalidate + disable L1 dcache */
__dc_disable(); __dc_disable();
...@@ -1104,18 +1156,29 @@ noinline void __init arc_ioc_setup(void) ...@@ -1104,18 +1156,29 @@ noinline void __init arc_ioc_setup(void)
if (read_aux_reg(ARC_REG_SLC_BCR)) if (read_aux_reg(ARC_REG_SLC_BCR))
slc_entire_op(OP_FLUSH_N_INV); 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: * currently IOC Aperture covers entire DDR
* decoded as 2 ^ (SIZE + 2) KB: so setting 0x11 implies 512M
* TBD: fix for PGU + 1GB of low mem * TBD: fix for PGU + 1GB of low mem
* TBD: fix for PAE * TBD: fix for PAE
*/ */
ap_sz = order_base_2(arc_get_mem_sz()/1024) - 2; mem_sz = arc_get_mem_sz();
write_aux_reg(ARC_REG_IO_COH_AP0_SIZE, ap_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_PARTIAL, 1);
write_aux_reg(ARC_REG_IO_COH_ENABLE, 1); write_aux_reg(ARC_REG_IO_COH_ENABLE, 1);
...@@ -1207,7 +1270,7 @@ void __ref arc_cache_init(void) ...@@ -1207,7 +1270,7 @@ void __ref arc_cache_init(void)
unsigned int __maybe_unused cpu = smp_processor_id(); unsigned int __maybe_unused cpu = smp_processor_id();
char str[256]; char str[256];
printk(arc_cache_mumbojumbo(0, str, sizeof(str))); pr_info("%s", arc_cache_mumbojumbo(0, str, sizeof(str)));
if (!cpu) if (!cpu)
arc_cache_init_master(); arc_cache_init_master();
......
...@@ -207,7 +207,7 @@ void do_page_fault(unsigned long address, struct pt_regs *regs) ...@@ -207,7 +207,7 @@ void do_page_fault(unsigned long address, struct pt_regs *regs)
/* Are we prepared to handle this kernel fault? /* Are we prepared to handle this kernel fault?
* *
* (The kernel has valid exception-points in the source * (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 * of those points, we find it in a table and do a jump
* to some fixup code that loads an appropriate error * to some fixup code that loads an appropriate error
* code) * code)
......
...@@ -26,7 +26,7 @@ pgd_t swapper_pg_dir[PTRS_PER_PGD] __aligned(PAGE_SIZE); ...@@ -26,7 +26,7 @@ pgd_t swapper_pg_dir[PTRS_PER_PGD] __aligned(PAGE_SIZE);
char empty_zero_page[PAGE_SIZE] __aligned(PAGE_SIZE); char empty_zero_page[PAGE_SIZE] __aligned(PAGE_SIZE);
EXPORT_SYMBOL(empty_zero_page); 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; static unsigned long low_mem_sz;
#ifdef CONFIG_HIGHMEM #ifdef CONFIG_HIGHMEM
...@@ -63,7 +63,7 @@ void __init early_init_dt_add_memory_arch(u64 base, u64 size) ...@@ -63,7 +63,7 @@ void __init early_init_dt_add_memory_arch(u64 base, u64 size)
if (!low_mem_sz) { if (!low_mem_sz) {
if (base != low_mem_start) if (base != low_mem_start)
panic("CONFIG_LINUX_LINK_BASE != DT memory { }"); panic("CONFIG_LINUX_RAM_BASE != DT memory { }");
low_mem_sz = size; low_mem_sz = size;
in_use = 1; in_use = 1;
...@@ -161,7 +161,7 @@ void __init setup_arch_memory(void) ...@@ -161,7 +161,7 @@ void __init setup_arch_memory(void)
* We can't use the helper free_area_init(zones[]) because it uses * 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 * PAGE_OFFSET to compute the @min_low_pfn which would be wrong
* when our kernel doesn't start at PAGE_OFFSET, i.e. * 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 */ free_area_init_node(0, /* node-id */
zones_size, /* num pages per zone */ zones_size, /* num pages per zone */
......
...@@ -821,7 +821,7 @@ void arc_mmu_init(void) ...@@ -821,7 +821,7 @@ void arc_mmu_init(void)
char str[256]; char str[256];
struct cpuinfo_arc_mmu *mmu = &cpuinfo_arc700[smp_processor_id()].mmu; 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 * 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, ...@@ -908,9 +908,6 @@ void do_tlb_overlap_fault(unsigned long cause, unsigned long address,
local_irq_save(flags); 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 */ /* loop thru all sets of TLB */
for (set = 0; set < mmu->sets; set++) { for (set = 0; set < mmu->sets; set++) {
......
...@@ -274,6 +274,13 @@ ex_saved_reg1: ...@@ -274,6 +274,13 @@ ex_saved_reg1:
.macro COMMIT_ENTRY_TO_MMU .macro COMMIT_ENTRY_TO_MMU
#if (CONFIG_ARC_MMU_VER < 4) #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 */ /* Get free TLB slot: Set = computed from vaddr, way = random */
sr TLBGetIndex, [ARC_REG_TLBCOMMAND] sr TLBGetIndex, [ARC_REG_TLBCOMMAND]
...@@ -287,6 +294,8 @@ ex_saved_reg1: ...@@ -287,6 +294,8 @@ ex_saved_reg1:
#else #else
sr TLBInsertEntry, [ARC_REG_TLBCOMMAND] sr TLBInsertEntry, [ARC_REG_TLBCOMMAND]
#endif #endif
88:
.endm .endm
......
...@@ -80,22 +80,6 @@ static void __init axs10x_enable_gpio_intc_wire(void) ...@@ -80,22 +80,6 @@ static void __init axs10x_enable_gpio_intc_wire(void)
iowrite32(1 << MB_TO_GPIO_IRQ, (void __iomem *) GPIO_INTEN); 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) static void __init axs10x_print_board_ver(unsigned int creg, const char *str)
{ {
union ver { union ver {
...@@ -314,7 +298,6 @@ static void __init axs101_early_init(void) ...@@ -314,7 +298,6 @@ static void __init axs101_early_init(void)
#ifdef CONFIG_AXS103 #ifdef CONFIG_AXS103
#define AXC003_CGU 0xF0000000
#define AXC003_CREG 0xF0001000 #define AXC003_CREG 0xF0001000
#define AXC003_MST_AXI_TUNNEL 0 #define AXC003_MST_AXI_TUNNEL 0
#define AXC003_MST_HS38 1 #define AXC003_MST_HS38 1
...@@ -324,131 +307,38 @@ static void __init axs101_early_init(void) ...@@ -324,131 +307,38 @@ static void __init axs101_early_init(void)
#define CREG_CPU_TUN_IO_CTRL (AXC003_CREG + 0x494) #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) static void __init axs103_early_init(void)
{ {
int offset = fdt_path_offset(initial_boot_params, "/cpu_card/core_clk"); #ifdef CONFIG_ARC_MCIP
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;
/* /*
* AXS103 configurations for SMP/QUAD configurations share device tree * 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 * 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 * Instead of duplicating defconfig/DT for SMP/QUAD, add a small hack
* * of fudging the freq in DT
* 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
*/ */
#ifdef CONFIG_ARC_MCIP
unsigned int num_cores = (read_aux_reg(ARC_REG_MCIP_BCR) >> 16) & 0x3F; unsigned int num_cores = (read_aux_reg(ARC_REG_MCIP_BCR) >> 16) & 0x3F;
if (num_cores > 2) if (num_cores > 2) {
freq = 50; u32 freq = 50, orig;
#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:
/* /*
* In this case, core_frequency derived from * TODO: use cpu node "cpu-freq" param instead of platform-specific
* DT "clock-frequency" might not match with board value. * "/cpu_card/core_clk" as it works only if we use fixed-clock for cpu.
* Hence update it to match the board value.
*/ */
freq = axs103_get_freq(); int off = fdt_path_offset(initial_boot_params, "/cpu_card/core_clk");
break; const struct fdt_property *prop;
}
prop = fdt_get_property(initial_boot_params, off,
pr_info("Freq is %dMHz\n", freq); "clock-frequency", NULL);
orig = be32_to_cpu(*(u32*)(prop->data)) / 1000000;
/* Patching .dtb in-place with new core clock value */
if (freq != orig ) { /* Patching .dtb in-place with new core clock value */
freq = cpu_to_be32(freq * 1000000); if (freq != orig ) {
fdt_setprop_inplace(initial_boot_params, offset, freq = cpu_to_be32(freq * 1000000);
"clock-frequency", &freq, sizeof(freq)); fdt_setprop_inplace(initial_boot_params, off,
"clock-frequency", &freq, sizeof(freq));
}
} }
#endif
/* Memory maps already config in pre-bootloader */ /* Memory maps already config in pre-bootloader */
......
...@@ -12,8 +12,8 @@ menuconfig ARC_PLAT_EZNPS ...@@ -12,8 +12,8 @@ menuconfig ARC_PLAT_EZNPS
help help
Support for EZchip development platforms, Support for EZchip development platforms,
based on ARC700 cores. based on ARC700 cores.
We handle few flavours: We handle few flavors:
- Hardware Emulator AKA HE which is FPGA based chasis - Hardware Emulator AKA HE which is FPGA based chassis
- Simulator based on MetaWare nSIM - Simulator based on MetaWare nSIM
- NPS400 chip based on ASIC - NPS400 chip based on ASIC
...@@ -32,3 +32,25 @@ config EZNPS_MTM_EXT ...@@ -32,3 +32,25 @@ config EZNPS_MTM_EXT
any of them seem like CPU from Linux point of view. any of them seem like CPU from Linux point of view.
All threads within same core share the execution unit of the All threads within same core share the execution unit of the
core and HW scheduler round robin between them. 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.
...@@ -2,6 +2,6 @@ ...@@ -2,6 +2,6 @@
# Makefile for the linux kernel. # 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_SMP) += smp.o
obj-$(CONFIG_EZNPS_MTM_EXT) += mtm.o obj-$(CONFIG_EZNPS_MTM_EXT) += mtm.o
/*
* 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);
}
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
.align 1024 ; HW requierment for restart first PC .align 1024 ; HW requierment for restart first PC
ENTRY(res_service) 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 ; There is no work for HW thread id != 0
lr r3, [CTOP_AUX_THREAD_ID] lr r3, [CTOP_AUX_THREAD_ID]
cmp r3, 0 cmp r3, 0
......
...@@ -39,6 +39,7 @@ ...@@ -39,6 +39,7 @@
#define CTOP_AUX_LOGIC_CORE_ID (CTOP_AUX_BASE + 0x018) #define CTOP_AUX_LOGIC_CORE_ID (CTOP_AUX_BASE + 0x018)
#define CTOP_AUX_MT_CTRL (CTOP_AUX_BASE + 0x020) #define CTOP_AUX_MT_CTRL (CTOP_AUX_BASE + 0x020)
#define CTOP_AUX_HW_COMPLY (CTOP_AUX_BASE + 0x024) #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_LPC (CTOP_AUX_BASE + 0x030)
#define CTOP_AUX_EFLAGS (CTOP_AUX_BASE + 0x080) #define CTOP_AUX_EFLAGS (CTOP_AUX_BASE + 0x080)
#define CTOP_AUX_IACK (CTOP_AUX_BASE + 0x088) #define CTOP_AUX_IACK (CTOP_AUX_BASE + 0x088)
...@@ -46,6 +47,7 @@ ...@@ -46,6 +47,7 @@
#define CTOP_AUX_UDMC (CTOP_AUX_BASE + 0x300) #define CTOP_AUX_UDMC (CTOP_AUX_BASE + 0x300)
/* EZchip core instructions */ /* EZchip core instructions */
#define CTOP_INST_HWSCHD_WFT_IE12 0x3E6F7344
#define CTOP_INST_HWSCHD_OFF_R4 0x3C6F00BF #define CTOP_INST_HWSCHD_OFF_R4 0x3C6F00BF
#define CTOP_INST_HWSCHD_RESTORE_R4 0x3E6F7103 #define CTOP_INST_HWSCHD_RESTORE_R4 0x3E6F7103
#define CTOP_INST_SCHD_RW 0x3E6F7004 #define CTOP_INST_SCHD_RW 0x3E6F7004
......
...@@ -21,10 +21,22 @@ ...@@ -21,10 +21,22 @@
#include <plat/mtm.h> #include <plat/mtm.h>
#include <plat/smp.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 MT_CTRL_ST_CNT 0xF
#define NPS_NUM_HW_THREADS 0x10 #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) static void mtm_init_nat(int cpu)
{ {
struct nps_host_reg_mtm_cfg mtm_cfg; struct nps_host_reg_mtm_cfg mtm_cfg;
...@@ -98,6 +110,18 @@ void mtm_enable_core(unsigned int cpu) ...@@ -98,6 +110,18 @@ void mtm_enable_core(unsigned int cpu)
int i; int i;
struct nps_host_reg_aux_mt_ctrl mt_ctrl; struct nps_host_reg_aux_mt_ctrl mt_ctrl;
struct nps_host_reg_mtm_cfg mtm_cfg; 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) if (NPS_CPU_TO_THREAD_NUM(cpu) != 0)
return; return;
...@@ -118,9 +142,7 @@ void mtm_enable_core(unsigned int cpu) ...@@ -118,9 +142,7 @@ void mtm_enable_core(unsigned int cpu)
/* Enable HW schedule, stall counter, mtm */ /* Enable HW schedule, stall counter, mtm */
mt_ctrl.value = 0; mt_ctrl.value = 0;
mt_ctrl.hsen = 1; mt_ctrl.hsen = 1;
mt_ctrl.hs_cnt = MT_CTRL_HS_CNT; mt_ctrl.hs_cnt = mtm_hs_ctr;
mt_ctrl.sten = 1;
mt_ctrl.st_cnt = MT_CTRL_ST_CNT;
mt_ctrl.mten = 1; mt_ctrl.mten = 1;
write_aux_reg(CTOP_AUX_MT_CTRL, mt_ctrl.value); write_aux_reg(CTOP_AUX_MT_CTRL, mt_ctrl.value);
...@@ -131,3 +153,23 @@ void mtm_enable_core(unsigned int cpu) ...@@ -131,3 +153,23 @@ void mtm_enable_core(unsigned int cpu)
*/ */
cpu_relax(); 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);
# 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"
#
# 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
/*
* 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
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment