From ddf720f86efe38cb3ef88b2eaad9ea8ad7c6f798 Mon Sep 17 00:00:00 2001 From: Liav Rehana Date: Sun, 28 May 2017 09:52:00 +0300 Subject: [PATCH 01/26] ARC: typo fix in mm/fault.c Signed-off-by: Liav Rehana Signed-off-by: Noam Camus Reviewed-by: Alexey Brodkin Signed-off-by: Vineet Gupta --- arch/arc/mm/fault.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 @@ void do_page_fault(unsigned long address, struct pt_regs *regs) /* 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) From 94055304690acfa256c39e36d0eb80294d1a7d65 Mon Sep 17 00:00:00 2001 From: Liav Rehana Date: Sun, 28 May 2017 09:52:01 +0300 Subject: [PATCH 02/26] ARC: typos fix in kernel/entry-compact.S Signed-off-by: Liav Rehana Signed-off-by: Noam Camus Reviewed-by: Alexey Brodkin Signed-off-by: Vineet Gupta --- arch/arc/kernel/entry-compact.S | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) 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 -#include /* {EXTRY,EXIT} */ +#include /* {ENTRY,EXIT} */ #include #include @@ -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. From 9e9395525b8e948ae0630368c87b0b3ede5fab7a Mon Sep 17 00:00:00 2001 From: Noam Camus Date: Sun, 28 May 2017 09:52:02 +0300 Subject: [PATCH 03/26] ARC: [plat-eznps] typo fix at Kconfig Signed-off-by: Noam Camus Reviewed-by: Alexey Brodkin Signed-off-by: Vineet Gupta --- arch/arc/plat-eznps/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arc/plat-eznps/Kconfig b/arch/arc/plat-eznps/Kconfig index 1595a38e50cd..feaa47141cdb 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 From 30b7af252e8fef6bf2fc311ca654c40bd0552220 Mon Sep 17 00:00:00 2001 From: Noam Camus Date: Sun, 28 May 2017 09:52:03 +0300 Subject: [PATCH 04/26] ARC: [plat-eznps] Fix TLB Errata Due to a HW bug in NPS400 we get from time to time false TLB miss. Workaround this by validating each miss. Signed-off-by: Noam Camus Signed-off-by: Vineet Gupta --- arch/arc/mm/tlbex.S | 9 +++++++++ 1 file changed, 9 insertions(+) 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 From ab1e8660c1bb2aa6ca3fbbc7e97cc2a5ffe1599b Mon Sep 17 00:00:00 2001 From: Noam Camus Date: Sun, 28 May 2017 09:52:04 +0300 Subject: [PATCH 05/26] ARC: [plat-eznps] disabled stall counter due to a HW bug This counter represents threshold for consecutive stall which would trigger HW threads scheduling. However when enabled, low threshhold values cause performance degradation and in the worst case even livelock. So disable it by resorting to HW reset value Signed-off-by: Noam Camus Reviewed-by: Alexey Brodkin Signed-off-by: Vineet Gupta [vgupta: fixed changelog] --- arch/arc/plat-eznps/mtm.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/arc/plat-eznps/mtm.c b/arch/arc/plat-eznps/mtm.c index aaaaffd3d940..e0cb36b03d2e 100644 --- a/arch/arc/plat-eznps/mtm.c +++ b/arch/arc/plat-eznps/mtm.c @@ -119,8 +119,6 @@ void mtm_enable_core(unsigned int cpu) 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.mten = 1; write_aux_reg(CTOP_AUX_MT_CTRL, mt_ctrl.value); From c2bdac146b4f12d3f0065b865d5d36529c2cbfaa Mon Sep 17 00:00:00 2001 From: Vineet Gupta Date: Sat, 17 Oct 2015 15:29:59 +0530 Subject: [PATCH 06/26] ARC: spinlock: Document the EX based spin_unlock Signed-off-by: Vineet Gupta --- arch/arc/include/asm/spinlock.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arc/include/asm/spinlock.h b/arch/arc/include/asm/spinlock.h index 233d5ffe6ec7..968c730ef114 100644 --- a/arch/arc/include/asm/spinlock.h +++ b/arch/arc/include/asm/spinlock.h @@ -296,6 +296,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) From 1112c3b2ce5281a7118606648bb8cc010b2499ca Mon Sep 17 00:00:00 2001 From: Noam Camus Date: Sun, 28 May 2017 09:52:05 +0300 Subject: [PATCH 07/26] ARC: [plat-eznps] spinlock aware for MTM This way when we execute "ex" during trying to hold lock we can switch to other HW thread and utilize the core intead of just spinning on a lock. We noticed about 10% improvement of execution time with hackbench test. Signed-off-by: Noam Camus Signed-off-by: Vineet Gupta --- arch/arc/include/asm/spinlock.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arc/include/asm/spinlock.h b/arch/arc/include/asm/spinlock.h index 968c730ef114..193c9eb5a803 100644 --- a/arch/arc/include/asm/spinlock.h +++ b/arch/arc/include/asm/spinlock.h @@ -252,9 +252,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"); /* From 64f42cec84deb32fdaf24649481c72fcd7800dc1 Mon Sep 17 00:00:00 2001 From: Vineet Gupta Date: Fri, 2 Jun 2017 11:49:10 -0700 Subject: [PATCH 08/26] ARC: create cpu specific version of arch_cpu_idle() This paves way for creating a 3rd variant needed for NPS ARC700 without littering ifdey'ery all over the place Signed-off-by: Vineet Gupta --- arch/arc/include/asm/irqflags-arcv2.h | 3 --- arch/arc/include/asm/irqflags-compact.h | 2 -- arch/arc/kernel/process.c | 18 ++++++++++++++++-- 3 files changed, 16 insertions(+), 7 deletions(-) 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/kernel/process.c b/arch/arc/kernel/process.c index 2a018de6d6cd..fd5b2190a957 100644 --- a/arch/arc/kernel/process.c +++ b/arch/arc/kernel/process.c @@ -79,15 +79,29 @@ SYSCALL_DEFINE3(arc_usr_cmpxchg, int *, uaddr, int, expected, int, new) 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 */ } +#else + +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); /* From 644fa02b392e25d7592951da2b2b64b4d533d1be Mon Sep 17 00:00:00 2001 From: Noam Camus Date: Sun, 28 May 2017 09:52:06 +0300 Subject: [PATCH 09/26] ARC: [plat-eznps] use schd.wft instruction instead of sleep at idle task When HW threads are active we want CPU to enter idle state only for the calling HW thread and not to put on sleep all HW threads sharing this core. For this need the NPS400 got dedicated instruction so only calling thread is entring sleep and all other are still awake and can execute instructions. Signed-off-by: Noam Camus Signed-off-by: Vineet Gupta [vgupta: reworked patch to not use inline ifdef but a new function itself] --- arch/arc/kernel/process.c | 13 ++++++++++++- arch/arc/plat-eznps/include/plat/ctop.h | 1 + 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/arch/arc/kernel/process.c b/arch/arc/kernel/process.c index fd5b2190a957..5c631a111240 100644 --- a/arch/arc/kernel/process.c +++ b/arch/arc/kernel/process.c @@ -92,7 +92,18 @@ void arch_cpu_idle(void) :"I"(arg)); /* can't be "r" has to be embedded const */ } -#else +#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) { diff --git a/arch/arc/plat-eznps/include/plat/ctop.h b/arch/arc/plat-eznps/include/plat/ctop.h index ee2e32df5e90..7729d3d18300 100644 --- a/arch/arc/plat-eznps/include/plat/ctop.h +++ b/arch/arc/plat-eznps/include/plat/ctop.h @@ -46,6 +46,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 From 983394959f5edff6b39bcd10317badaaf33efa99 Mon Sep 17 00:00:00 2001 From: Noam Camus Date: Tue, 13 Jun 2017 17:03:45 +0300 Subject: [PATCH 10/26] ARC: [plat-eznps] Handle user memory error same in simulation and silicon On ARC700 (and nSIM), user mode memory error triggers an L2 interrupt which is handled gracefully by kernel (or it tries to despite this being imprecise, and error could get charged to kernel itself). The offending task is killed and kernel moves on. NPS hardware however raises a Machine Check exception for same error which is NOT recoverable by kernel. This patch aligns kernel handling for nSIM case, to same as hardware by overriding the default user space bus error handler. Signed-off-by: Noam Camus Signed-off-by: Elad Kanfi [vgupta: rewrote changelog] Signed-off-by: Vineet Gupta --- arch/arc/kernel/traps.c | 2 +- arch/arc/plat-eznps/Kconfig | 11 +++++++++++ arch/arc/plat-eznps/mtm.c | 9 +++++++++ 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/arch/arc/kernel/traps.c b/arch/arc/kernel/traps.c index ff83e78d0cfb..62675b94fccd 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) diff --git a/arch/arc/plat-eznps/Kconfig b/arch/arc/plat-eznps/Kconfig index feaa47141cdb..b36afb1feaba 100644 --- a/arch/arc/plat-eznps/Kconfig +++ b/arch/arc/plat-eznps/Kconfig @@ -32,3 +32,14 @@ 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. diff --git a/arch/arc/plat-eznps/mtm.c b/arch/arc/plat-eznps/mtm.c index e0cb36b03d2e..dcbf8f6ebf74 100644 --- a/arch/arc/plat-eznps/mtm.c +++ b/arch/arc/plat-eznps/mtm.c @@ -25,6 +25,15 @@ #define MT_CTRL_ST_CNT 0xF #define NPS_NUM_HW_THREADS 0x10 +#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; From 18ee4becb5a9f52d0808347279bece447ef5a217 Mon Sep 17 00:00:00 2001 From: Noam Camus Date: Thu, 15 Jun 2017 11:43:51 +0300 Subject: [PATCH 11/26] ARC: set boot print log level to PR_INFO Some of the boot printing code had printk() w/o explicit log level. This patch introduces consistency allowing platforms to switch to less verbose console logging using cmdline. NPS400 with 4K CPUs needs to avoid the cpu info printing for faster bootup. Signed-off-by: Noam Camus Signed-off-by: Vineet Gupta --- arch/arc/kernel/setup.c | 6 +++--- arch/arc/mm/cache.c | 2 +- arch/arc/mm/tlb.c | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) 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/mm/cache.c b/arch/arc/mm/cache.c index 7db283b46ebd..7754efb69d9b 100644 --- a/arch/arc/mm/cache.c +++ b/arch/arc/mm/cache.c @@ -1207,7 +1207,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/tlb.c b/arch/arc/mm/tlb.c index b181f3ee38aa..edc59a0a9c9b 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 From 35b55ef2b8f5aeedf349a1fe2ad8b11d5974f3f1 Mon Sep 17 00:00:00 2001 From: Noam Camus Date: Thu, 15 Jun 2017 11:43:57 +0300 Subject: [PATCH 12/26] ARC: [plat-eznps] new command line argument for HW scheduler at MTM We add ability for all cores at NPS SoC to control the number of cycles HW thread can execute before it is replace with another eligible HW thread within the same core. The replacement is done by the HW scheduler. Signed-off-by: Noam Camus Signed-off-by: Vineet Gupta [vgupta: simplified handlign of out of range argument value] --- .../admin-guide/kernel-parameters.txt | 9 +++++++ arch/arc/plat-eznps/mtm.c | 27 +++++++++++++++++-- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index d9c171ce4190..1c0a995c4856 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -2750,6 +2750,15 @@ If the dependencies are under your control, you can 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 purges which is reported from either PAL_VM_SUMMARY or SAL PALO. diff --git a/arch/arc/plat-eznps/mtm.c b/arch/arc/plat-eznps/mtm.c index dcbf8f6ebf74..8a13f0ac49fb 100644 --- a/arch/arc/plat-eznps/mtm.c +++ b/arch/arc/plat-eznps/mtm.c @@ -21,10 +21,13 @@ #include #include -#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) { @@ -127,7 +130,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.hs_cnt = mtm_hs_ctr; mt_ctrl.mten = 1; write_aux_reg(CTOP_AUX_MT_CTRL, mt_ctrl.value); @@ -138,3 +141,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); From abd8926bff32df82d0fb8322b9fe382774f630b5 Mon Sep 17 00:00:00 2001 From: Liav Rehana Date: Thu, 15 Jun 2017 11:43:58 +0300 Subject: [PATCH 13/26] ARC: [plat-eznps] Update the init sequence of aux regs per cpu. This commit add new configuration that enables us to distinguish between building the kernel for platforms that have a different set of auxiliary registers for each cpu and platforms that have a shared set of auxiliary registers across every thread in each core. On platforms that implement a different set of auxiliary registers disabling this configuration insures that we initialize registers on every cpu and not just for the first thread of the core. Example for non shared registers is working with EZsim (non silicon) Signed-off-by: Liav Rehana Signed-off-by: Noam Camus Signed-off-by: Vineet Gupta --- arch/arc/plat-eznps/Kconfig | 11 +++++++++++ arch/arc/plat-eznps/entry.S | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/arch/arc/plat-eznps/Kconfig b/arch/arc/plat-eznps/Kconfig index b36afb1feaba..e151e2067886 100644 --- a/arch/arc/plat-eznps/Kconfig +++ b/arch/arc/plat-eznps/Kconfig @@ -43,3 +43,14 @@ config EZNPS_MEM_ERROR_ALIGN 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/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 From 3f9cd874dcc8705b53c03431f0ae46c94e572349 Mon Sep 17 00:00:00 2001 From: Elad Kanfi Date: Thu, 15 Jun 2017 11:44:01 +0300 Subject: [PATCH 14/26] ARC: [plat-eznps] avoid toggling of DPC register HW bug description: in case of HW thread context switch the dpc configuration of the exiting thread is dragged one cycle into the next thread. In order to avoid the consequences of this bug, the DPC register is set to an initial value, and not changed afterwards. Signed-off-by: Elad Kanfi Signed-off-by: Noam Camus Signed-off-by: Vineet Gupta --- arch/arc/plat-eznps/include/plat/ctop.h | 1 + arch/arc/plat-eznps/mtm.c | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/arch/arc/plat-eznps/include/plat/ctop.h b/arch/arc/plat-eznps/include/plat/ctop.h index 7729d3d18300..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) diff --git a/arch/arc/plat-eznps/mtm.c b/arch/arc/plat-eznps/mtm.c index 8a13f0ac49fb..2388de3d09ef 100644 --- a/arch/arc/plat-eznps/mtm.c +++ b/arch/arc/plat-eznps/mtm.c @@ -110,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; From 5b2189ab6ee0717babac912f779dcd440e942173 Mon Sep 17 00:00:00 2001 From: Noam Camus Date: Thu, 15 Jun 2017 11:43:59 +0300 Subject: [PATCH 15/26] ARC: [plat-eznps] handle extra aux regs #1: save/restore on context switch save EFLAGS, and GPA1 auxiliary registers during context switch, since they may be changed by the new task in kernel mode, while using atomic ops e.g. cmpxchg. Signed-off-by: Noam Camus Signed-off-by: Vineet Gupta --- arch/arc/include/asm/processor.h | 10 ++++++++++ arch/arc/include/asm/switch_to.h | 9 +++++++++ arch/arc/plat-eznps/Makefile | 2 +- arch/arc/plat-eznps/ctop.c | 32 ++++++++++++++++++++++++++++++++ 4 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 arch/arc/plat-eznps/ctop.c 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/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/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 +#include +#include + +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); +} From 28923f6b74060b183207a373ddae4ce4948cabea Mon Sep 17 00:00:00 2001 From: Liav Rehana Date: Thu, 15 Jun 2017 11:44:00 +0300 Subject: [PATCH 16/26] ARC: [plat-eznps] handle extra aux regs #2: kernel/entry exit Preserve eflags and gpa1 aux during entry/exit into kernel as these could be modified by kernel mode These registers used by compare exchange instructions. - GPA1 is used for compare value, - EFLAGS got bit reflects atomic operation response. EFLAGS is zeroed for each new user task so it won't get its parent value. Signed-off-by: Liav Rehana Signed-off-by: Noam Camus Signed-off-by: Vineet Gupta --- arch/arc/include/asm/entry-compact.h | 24 ++++++++++++++++++++++++ arch/arc/include/asm/ptrace.h | 5 +++++ arch/arc/kernel/process.c | 4 ++++ 3 files changed, 33 insertions(+) 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/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/kernel/process.c b/arch/arc/kernel/process.c index 5c631a111240..5ac3b547453f 100644 --- a/arch/arc/kernel/process.c +++ b/arch/arc/kernel/process.c @@ -234,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; From 9f82e90a6668e522c7fd0e0322c52d86f29b624d Mon Sep 17 00:00:00 2001 From: Alexey Brodkin Date: Tue, 18 Jul 2017 17:31:24 +0300 Subject: [PATCH 17/26] ARC: Hardcode ARCH_DMA_MINALIGN to max line length we may have Current implementation relies on L1 line length which might easily be smaller than L2 line (which is usually the case BTW). Imagine this typical case: L2 line is 128 bytes while L1 line is 64-bytes. Now we want to allocate small buffer and later use it for DMA (consider IOC is not available). kmalloc() allocates small KMALLOC_MIN_SIZE-sized, KMALLOC_MIN_SIZE-aligned That way if buffer happens to be aligned to L1 line and not L2 line we'll be flushing and invalidating extra portions of data from L2 which will cause cache coherency issues. And since KMALLOC_MIN_SIZE is bound to ARCH_DMA_MINALIGN the fix could be simple - set ARCH_DMA_MINALIGN to the largest cache line we may ever get. As of today neither L1 of ARC700 and ARC HS38 nor SLC might not be longer than 128 bytes. Signed-off-by: Alexey Brodkin Signed-off-by: Vineet Gupta --- arch/arc/include/asm/cache.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arc/include/asm/cache.h b/arch/arc/include/asm/cache.h index 02fd1cece6ef..6349af790c65 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); From ae0b63d97d8efc377cc5b161abccc6e3586b206f Mon Sep 17 00:00:00 2001 From: Vineet Gupta Date: Tue, 1 Aug 2017 10:23:27 +0530 Subject: [PATCH 18/26] ARCv2: SLC: provide a line based flush routine for debugging Signed-off-by: Vineet Gupta --- arch/arc/include/asm/cache.h | 2 ++ arch/arc/mm/cache.c | 54 +++++++++++++++++++++++++++++++++++- 2 files changed, 55 insertions(+), 1 deletion(-) diff --git a/arch/arc/include/asm/cache.h b/arch/arc/include/asm/cache.h index 6349af790c65..8486f328cc5d 100644 --- a/arch/arc/include/asm/cache.h +++ b/arch/arc/include/asm/cache.h @@ -96,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/mm/cache.c b/arch/arc/mm/cache.c index 7754efb69d9b..ad498e58a1fe 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; From 9926c29f746d178400543e2056cee4d437e697f3 Mon Sep 17 00:00:00 2001 From: Eugeniy Paltsev Date: Mon, 14 Aug 2017 19:12:10 +0300 Subject: [PATCH 19/26] ARC: [plat-axs103] use clk driver #1: Get rid of platform specific cpu clk setting historically axs103 platform code used to set the cpu clk by writing to PLL registers directly. however the axs10x clk driver is now upstream so no need to do this amymore. Driver is selected automatically when CONFIG_ARC_PLAT_AXS10X is set Signed-off-by: Eugeniy Paltsev Signed-off-by: Vineet Gupta [vgupta: deleted more code not needed anymore] --- arch/arc/plat-axs10x/axs10x.c | 118 ++-------------------------------- 1 file changed, 5 insertions(+), 113 deletions(-) diff --git a/arch/arc/plat-axs10x/axs10x.c b/arch/arc/plat-axs10x/axs10x.c index 38ff349d7f2a..6c0cb084e636 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,72 +307,12 @@ 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) { + /* + * 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. + */ int offset = fdt_path_offset(initial_boot_params, "/cpu_card/core_clk"); const struct fdt_property *prop = fdt_get_property(initial_boot_params, offset, @@ -399,7 +322,7 @@ static void __init axs103_early_init(void) /* * 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 * @@ -412,37 +335,6 @@ static void __init axs103_early_init(void) 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: - /* - * In this case, core_frequency derived from - * DT "clock-frequency" might not match with board value. - * Hence update it to match the board value. - */ - 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); From f6a09bace0bb9587985b48ed652f2b292f8de0de Mon Sep 17 00:00:00 2001 From: Eugeniy Paltsev Date: Mon, 14 Aug 2017 19:12:11 +0300 Subject: [PATCH 20/26] ARC: [plat-axs103] use clk driver #2: Add core pll node to DT to manage cpu clk Add core pll node (core_clk) to manage cpu frequency. core_clk represents pll itself. input_clk represents clock signal source (basically xtal) which comes to pll input. Signed-off-by: Eugeniy Paltsev Signed-off-by: Vineet Gupta --- arch/arc/boot/dts/axc003.dtsi | 11 +++++++++-- arch/arc/boot/dts/axc003_idu.dtsi | 11 +++++++++-- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/arch/arc/boot/dts/axc003.dtsi b/arch/arc/boot/dts/axc003.dtsi index cc9239ef8d08..dca7e39409be 100644 --- a/arch/arc/boot/dts/axc003.dtsi +++ b/arch/arc/boot/dts/axc003.dtsi @@ -24,10 +24,17 @@ cpu_card { 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 { diff --git a/arch/arc/boot/dts/axc003_idu.dtsi b/arch/arc/boot/dts/axc003_idu.dtsi index 4ebb2170abec..5b56beffc1c5 100644 --- a/arch/arc/boot/dts/axc003_idu.dtsi +++ b/arch/arc/boot/dts/axc003_idu.dtsi @@ -24,10 +24,17 @@ cpu_card { 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 { From 0fa400cb8a90753044bbcb5810fa1a59d96d5ea1 Mon Sep 17 00:00:00 2001 From: Vineet Gupta Date: Tue, 22 Aug 2017 14:37:22 -0700 Subject: [PATCH 21/26] ARC: [plat-axs103] refactor the DT fudging code with clk frequency setting code gone by prev commits, we can elide the unconditonal DT parsing to the specific case of quad core config where we possibly need to fudge the DT value. Signed-off-by: Vineet Gupta --- arch/arc/plat-axs10x/axs10x.c | 44 +++++++++++++++++------------------ 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/arch/arc/plat-axs10x/axs10x.c b/arch/arc/plat-axs10x/axs10x.c index 6c0cb084e636..f1ac6790da5f 100644 --- a/arch/arc/plat-axs10x/axs10x.c +++ b/arch/arc/plat-axs10x/axs10x.c @@ -309,38 +309,36 @@ static void __init axs101_early_init(void) static void __init axs103_early_init(void) { - /* - * 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. - */ - 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 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 + if (num_cores > 2) { + u32 freq = 50, orig; + /* + * 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. + */ + int off = fdt_path_offset(initial_boot_params, "/cpu_card/core_clk"); + const struct fdt_property *prop; - /* 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)); + 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 */ From bee91c3a3ce63daf64bb53ae60e6a2fb2961d3d7 Mon Sep 17 00:00:00 2001 From: Eugeniy Paltsev Date: Tue, 15 Aug 2017 21:13:53 +0300 Subject: [PATCH 22/26] ARCv2: IOC: Tighten up the contraints (specifically base / size alignment) [Needed for HSDK] - Currently IOC base is hardcoded to 0x8000_0000 which is default value of LINUX_LINK_BASE, but may not always be the case - IOC programming model imposes the constraint that IOC aperture size needs to be aligned to IOC base address, which we were not checking so far. Signed-off-by: Eugeniy Paltsev Signed-off-by: Vineet Gupta [vgupta: reworked the changelog] --- arch/arc/mm/cache.c | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/arch/arc/mm/cache.c b/arch/arc/mm/cache.c index ad498e58a1fe..d68d36c15909 100644 --- a/arch/arc/mm/cache.c +++ b/arch/arc/mm/cache.c @@ -1147,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(); @@ -1156,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_LINK_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); From 9ed68785f7f2b001a6911d64fbd10cfc6fa49b27 Mon Sep 17 00:00:00 2001 From: Eugeniy Paltsev Date: Tue, 15 Aug 2017 21:13:54 +0300 Subject: [PATCH 23/26] ARC: mm: Decouple RAM base address from kernel link address [Needed for HSDK] Currently the first page of system (hence RAM base) is assumed to be @ CONFIG_LINUX_LINK_BASE, where kernel itself is linked. However is case of HSDK platform, for reasons explained in that patch, this is not true. kernel needs to be linked @ 0x9000_0000 while DDR is still wired at 0x8000_0000. To properly account for this 256M of RAM, we need to introduce a new option and base page frame accountiing off of it. Signed-off-by: Eugeniy Paltsev Signed-off-by: Vineet Gupta [vgupta: renamed CONFIG_KERNEL_RAM_BASE_ADDRESS => CONFIG_LINUX_RAM_BASE : simplified changelog] --- arch/arc/Kconfig | 10 +++++++++- arch/arc/boot/dts/axc001.dtsi | 2 +- arch/arc/boot/dts/axc003.dtsi | 2 +- arch/arc/boot/dts/axc003_idu.dtsi | 2 +- arch/arc/boot/dts/nsim_hs.dts | 2 +- arch/arc/include/asm/page.h | 2 +- arch/arc/mm/cache.c | 2 +- arch/arc/mm/init.c | 6 +++--- 8 files changed, 18 insertions(+), 10 deletions(-) diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig index 7db85ab00c52..65b7549e17db 100644 --- a/arch/arc/Kconfig +++ b/arch/arc/Kconfig @@ -418,7 +418,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 +431,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/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 @@ mb_intc: dw-apb-ictl@0xe0012000 { 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 dca7e39409be..4e6e9f57e790 100644 --- a/arch/arc/boot/dts/axc003.dtsi +++ b/arch/arc/boot/dts/axc003.dtsi @@ -109,7 +109,7 @@ mb_intc: dw-apb-ictl@0xe0012000 { 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 5b56beffc1c5..63954a8b0100 100644 --- a/arch/arc/boot/dts/axc003_idu.dtsi +++ b/arch/arc/boot/dts/axc003_idu.dtsi @@ -115,7 +115,7 @@ mb_intc: dw-apb-ictl@0xe0012000 { 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/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/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/mm/cache.c b/arch/arc/mm/cache.c index d68d36c15909..eee924dfffa6 100644 --- a/arch/arc/mm/cache.c +++ b/arch/arc/mm/cache.c @@ -1173,7 +1173,7 @@ noinline void __init arc_ioc_setup(void) 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_LINK_BASE; + 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"); 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 */ From a518d63777a4e94e4b2dd86501604ec49ffe86b2 Mon Sep 17 00:00:00 2001 From: Alexey Brodkin Date: Tue, 15 Aug 2017 21:13:55 +0300 Subject: [PATCH 24/26] ARC: [plat-hsdk] initial port for HSDK board This initial port adds support of ARC HS Development Kit board with some basic features such serial port, USB, SD/MMC and Ethernet. Essentially we run Linux kernel on all 4 cores (i.e. utilize SMP) and heavily use IO Coherency for speeding-up DMA-aware peripherals. Note as opposed to other ARC boards we link Linux kernel to 0x9000_0000 intentionally because cores 1 and 3 configured with DCCM situated at our more usual link base 0x8000_0000. We still can use memory region starting at 0x8000_0000 as we reallocate DCCM in our platform code. Note that 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. Acked-by: Rob Herring Signed-off-by: Alexey Brodkin Signed-off-by: Eugeniy Paltsev Signed-off-by: Vineet Gupta --- .../devicetree/bindings/arc/hsdk.txt | 7 + arch/arc/Kconfig | 1 + arch/arc/Makefile | 1 + arch/arc/boot/dts/hsdk.dts | 189 ++++++++++++++++++ arch/arc/configs/hsdk_defconfig | 80 ++++++++ arch/arc/kernel/devtree.c | 5 +- arch/arc/plat-hsdk/Kconfig | 9 + arch/arc/plat-hsdk/Makefile | 9 + arch/arc/plat-hsdk/platform.c | 66 ++++++ 9 files changed, 365 insertions(+), 2 deletions(-) create mode 100644 Documentation/devicetree/bindings/arc/hsdk.txt create mode 100644 arch/arc/boot/dts/hsdk.dts create mode 100644 arch/arc/configs/hsdk_defconfig create mode 100644 arch/arc/plat-hsdk/Kconfig create mode 100644 arch/arc/plat-hsdk/Makefile create mode 100644 arch/arc/plat-hsdk/platform.c diff --git a/Documentation/devicetree/bindings/arc/hsdk.txt b/Documentation/devicetree/bindings/arc/hsdk.txt new file mode 100644 index 000000000000..be50654bbf61 --- /dev/null +++ b/Documentation/devicetree/bindings/arc/hsdk.txt @@ -0,0 +1,7 @@ +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"; diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig index 65b7549e17db..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 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/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 + +/ { + 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 = ; + ti,tx-internal-delay = ; + ti,fifo-depth = ; + }; + }; + }; + + 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/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/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/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 +#include +#include +#include +#include + +#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 From aa7e3a5e8b63628c7fc131effc163ade08ced41b Mon Sep 17 00:00:00 2001 From: Jose Abreu Date: Tue, 29 Aug 2017 10:14:20 +0100 Subject: [PATCH 25/26] ARC: Show fault information passed to show_kernel_fault_diag() Currently we pass a string argument to show_kernel_fault_diag() which describes the reason for the fault. This is not being used so just add a pr_info() which outputs the fault information. With this change we get from: | | Path: /bin/busybox | CPU: 0 PID: 92 Comm: modprobe Not tainted 4.12.0-rc6 #30 | task: 9a254780 task.stack: 9a212000 | | [ECR ]: 0x00200400 => Other Fatal Err | to: | | Unhandled Machine Check Exception | Path: /bin/busybox | CPU: 0 PID: 92 Comm: modprobe Not tainted 4.12.0-rc6 #37 | task: 9a240780 task.stack: 9a226000 | |[ECR ]: 0x00200400 => Machine Check (Other Fatal Err) | Which can help debugging. Cc: Alexey Brodkin Signed-off-by: Jose Abreu Signed-off-by: Vineet Gupta --- arch/arc/kernel/traps.c | 2 +- arch/arc/kernel/troubleshoot.c | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/arch/arc/kernel/traps.c b/arch/arc/kernel/traps.c index 62675b94fccd..bcd7c9fc5d0f 100644 --- a/arch/arc/kernel/traps.c +++ b/arch/arc/kernel/traps.c @@ -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); From 1ee55a8f7f6b7ca4c0c59e0b4b4e3584a085c2d3 Mon Sep 17 00:00:00 2001 From: Jose Abreu Date: Fri, 1 Sep 2017 17:00:23 +0100 Subject: [PATCH 26/26] ARC: Re-enable MMU upon Machine Check exception I recently came upon a scenario where I would get a double fault machine check exception tiriggered by a kernel module. However the ensuing crash stacktrace (ksym lookup) was not working correctly. Turns out that machine check auto-disables MMU while modules are allocated in kernel vaddr spapce. This patch re-enables the MMU before start printing the stacktrace making stacktracing of modules work upon a fatal exception. Cc: stable@kernel.org Signed-off-by: Jose Abreu Reviewed-by: Alexey Brodkin Signed-off-by: Vineet Gupta [vgupta: moved code into low level handler to avoid in 2 places] --- arch/arc/kernel/entry.S | 6 ++++++ arch/arc/mm/tlb.c | 3 --- 2 files changed, 6 insertions(+), 3 deletions(-) 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/mm/tlb.c b/arch/arc/mm/tlb.c index edc59a0a9c9b..8ceefbf72fb0 100644 --- a/arch/arc/mm/tlb.c +++ b/arch/arc/mm/tlb.c @@ -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++) {